codexuse-cli 2.5.5 → 2.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +83 -217
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../lib/profile-manager.ts","../../../lib/auto-roll-settings.ts","../../../lib/app-state.ts","../../../lib/chat-scrollback.ts","../../../lib/commit-message-prompt.ts","../../../lib/codex-settings.ts","../../../lib/logger.ts","../../../lib/license-service.ts","../../../lib/license-secret.ts","../../../lib/offer-config.ts","../../../lib/cloud-sync-service.ts","../../../lib/cloud-sync-types.ts","../../../lib/type-guards.ts","../../../lib/cloud-sync-client.ts","../../../lib/codex-config.ts","../../../lib/codex-config-metadata.ts","../../../lib/codex-cli.ts","../../../lib/errors.ts","../../../lib/license-guard.ts","../src/codex-cli.ts","../../../lib/codex-rpc.ts","../../../lib/rate-limit-notifier.ts","../../../lib/storage-migration-v1.ts","../../../lib/legacy-localstorage-keys.ts","../src/daemon.ts","../../../lib/codex-app-server.ts","../../../lib/apps-list-rpc.ts","../../../lib/cli-env.ts","../../../lib/workspace-parity-store.ts","../../../lib/git/git-service.ts","../../../lib/git/git-cli.ts","../../../electron/telegram-bridge.ts","../../../lib/retryable-turn-error.ts","../src/index.ts"],"sourcesContent":["import { promises as fs } from 'fs';\nimport path from 'path';\nimport { join } from 'path';\nimport { parse, stringify } from '@iarna/toml';\nimport {\n Profile,\n ProfileData,\n ActiveAuth,\n ProfileMetadata,\n OrganizationInfo,\n SubscriptionInfo,\n TokenAlert,\n TokenIssue,\n TokenStatus,\n} from './types';\nimport type { CloudSyncProfileRecord } from './cloud-sync-types';\nimport { getLastProfileName, persistLastProfileName } from './codex-settings';\nimport { getAppState, getUserDataDir, updateAppState, type ProfileRecordState } from './app-state';\nimport { logError, logWarn } from './logger';\n\nconst TOKEN_EXPIRING_SOON_WINDOW_MS = 15 * 60 * 1000;\nexport const REFRESH_TOKEN_REDEEMED_SNIPPET = 'refresh token was already used';\nexport const REFRESH_TOKEN_REDEEMED_REASON =\n 'Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.';\nconst AUTH_BACKUP_MISSING_MARKER = '__codexuse_missing_auth__';\nconst DEFAULT_WORKSPACE_ID = '__default__';\nlet globalAuthSwapLock: Promise<void> = Promise.resolve();\n\nexport function detectRefreshTokenRedeemedMessage(output: string | Buffer | null | undefined): string | null {\n if (!output) {\n return null;\n }\n\n const text = output.toString();\n if (!text) {\n return null;\n }\n\n const normalized = text\n .toLowerCase()\n .replace(/\\s+/g, ' ');\n if (!normalized.includes(REFRESH_TOKEN_REDEEMED_SNIPPET)) {\n return null;\n }\n\n const trimmed = text.trim();\n return trimmed.length > 0 ? trimmed : REFRESH_TOKEN_REDEEMED_REASON;\n}\n\ntype ProfileRecord = {\n name: string;\n displayName: string | null;\n data: ProfileData;\n metadata?: ProfileMetadata;\n accountId: string | null;\n workspaceId: string | null;\n workspaceName: string | null;\n email: string | null;\n authMethod: string | null;\n createdAt: string | null;\n updatedAt: string | null;\n};\n\nexport class ProfileManager {\n private codexDir: string;\n private profileHomesRoot: string;\n private activeAuth: string;\n private activeAuthBackup: string;\n private lastActiveAuthErrorSignature: string | null;\n constructor() {\n const homeDir = process.env.HOME || process.env.USERPROFILE || '';\n this.codexDir = join(homeDir, '.codex');\n this.profileHomesRoot = join(getUserDataDir(), 'profile-homes');\n this.activeAuth = join(this.codexDir, 'auth.json');\n this.activeAuthBackup = `${this.activeAuth}.swap`;\n this.lastActiveAuthErrorSignature = null;\n }\n\n private computeExpiryIso(data: ProfileData | null | undefined): string | undefined {\n if (!data) {\n return undefined;\n }\n if (typeof data.expired === 'string' && data.expired.trim()) {\n const parsed = Date.parse(data.expired);\n if (!Number.isNaN(parsed)) {\n return new Date(parsed).toISOString();\n }\n }\n const expiresIn = typeof data.expires_in === 'number' && Number.isFinite(data.expires_in)\n ? data.expires_in\n : undefined;\n const issuedMs =\n typeof data.timestamp === 'number' && Number.isFinite(data.timestamp)\n ? data.timestamp\n : undefined;\n const issuedAt = issuedMs ? issuedMs : undefined;\n const baseMs = issuedAt ?? Date.now();\n if (expiresIn && expiresIn > 0) {\n return new Date(baseMs + expiresIn * 1000).toISOString();\n }\n return undefined;\n }\n\n private normalizeProfileName(name: string): string {\n if (typeof name !== 'string') {\n throw new Error('Profile name is required');\n }\n\n const trimmed = name.trim();\n if (!trimmed) {\n throw new Error('Profile name must not be empty.');\n }\n\n if (trimmed === '.' || trimmed === '..') {\n throw new Error(`Profile name '${name}' is not allowed.`);\n }\n\n if (/[\\\\/]/.test(trimmed)) {\n throw new Error(\"Profile name cannot contain path separators.\");\n }\n\n if (trimmed.includes('\\0')) {\n throw new Error('Profile name contains invalid characters.');\n }\n\n return trimmed;\n }\n\n private isNotFoundError(error: unknown): boolean {\n return Boolean(\n error &&\n typeof error === 'object' &&\n 'code' in error &&\n (error as NodeJS.ErrnoException).code === 'ENOENT',\n );\n }\n\n private async readPreferredProfileName(): Promise<string | null> {\n try {\n return await getLastProfileName();\n } catch (error) {\n logWarn('Failed to read preferred profile name:', error);\n return null;\n }\n }\n\n private async persistPreferredProfileName(name: string | null): Promise<void> {\n try {\n await persistLastProfileName(name);\n } catch (error) {\n logWarn('Failed to persist preferred profile name:', error);\n }\n }\n\n private toStateRecord(record: ProfileRecord): ProfileRecordState {\n return {\n name: record.name,\n displayName: record.displayName ?? null,\n data: record.data,\n metadata: record.metadata,\n accountId: record.accountId ?? null,\n workspaceId: record.workspaceId ?? null,\n workspaceName: record.workspaceName ?? null,\n email: record.email ?? null,\n authMethod: record.authMethod ?? null,\n createdAt: record.createdAt ?? null,\n updatedAt: record.updatedAt ?? null,\n };\n }\n\n private fromStateRecord(profileName: string, raw: ProfileRecordState): ProfileRecord | null {\n if (!raw || typeof raw !== 'object') {\n return null;\n }\n\n const dataRaw = raw.data;\n if (!dataRaw || typeof dataRaw !== 'object') {\n return null;\n }\n\n return {\n name: profileName,\n displayName: typeof raw.displayName === 'string' ? raw.displayName : null,\n data: dataRaw as ProfileData,\n metadata: raw.metadata,\n accountId: typeof raw.accountId === 'string' ? raw.accountId : null,\n workspaceId: typeof raw.workspaceId === 'string' ? raw.workspaceId : null,\n workspaceName: typeof raw.workspaceName === 'string' ? raw.workspaceName : null,\n email: typeof raw.email === 'string' ? raw.email : null,\n authMethod: typeof raw.authMethod === 'string' ? raw.authMethod : null,\n createdAt: typeof raw.createdAt === 'string' ? raw.createdAt : null,\n updatedAt: typeof raw.updatedAt === 'string' ? raw.updatedAt : null,\n };\n }\n\n private async readProfilesStateMap(): Promise<Record<string, ProfileRecordState>> {\n const state = await getAppState();\n return { ...(state.profilesByName ?? {}) };\n }\n\n private async writeProfilesStateMap(nextMap: Record<string, ProfileRecordState>): Promise<void> {\n await updateAppState((state) => ({\n ...state,\n profilesByName: nextMap,\n }), { mode: 'replace' });\n }\n\n private async readProfileRecord(profileName: string): Promise<ProfileRecord | null> {\n const map = await this.readProfilesStateMap();\n const raw = map[profileName];\n if (!raw) {\n return null;\n }\n return this.fromStateRecord(profileName, raw);\n }\n\n private async listProfileRecords(): Promise<ProfileRecord[]> {\n const map = await this.readProfilesStateMap();\n const records: ProfileRecord[] = [];\n for (const [profileName, raw] of Object.entries(map)) {\n const record = this.fromStateRecord(profileName, raw);\n if (record) {\n records.push(record);\n }\n }\n return records;\n }\n\n private async writeProfileRecord(record: ProfileRecord): Promise<void> {\n const map = await this.readProfilesStateMap();\n map[record.name] = this.toStateRecord(record);\n await this.writeProfilesStateMap(map);\n }\n\n private async deleteProfileRecord(name: string): Promise<void> {\n const map = await this.readProfilesStateMap();\n if (!Object.prototype.hasOwnProperty.call(map, name)) {\n return;\n }\n delete map[name];\n await this.writeProfilesStateMap(map);\n }\n\n private resolveAuthMethod(data: ProfileData | null | undefined): string {\n const raw = typeof data?.auth_method === 'string' ? data.auth_method.trim().toLowerCase() : '';\n return raw || 'codex-cli';\n }\n\n private async readActiveAuthFile(): Promise<ActiveAuth | null> {\n try {\n const raw = await fs.readFile(this.activeAuth, 'utf8');\n const trimmed = raw.trim();\n if (!trimmed) {\n return null;\n }\n return JSON.parse(trimmed) as ActiveAuth;\n } catch (error) {\n if (this.isNotFoundError(error)) {\n return null;\n }\n const message = error instanceof Error ? error.message : 'unknown error';\n const signature = typeof message === 'string' ? `${message}:${this.activeAuth}` : this.activeAuth;\n if (this.lastActiveAuthErrorSignature !== signature) {\n logWarn('Failed to read active auth file:', error);\n this.lastActiveAuthErrorSignature = signature;\n }\n return null;\n }\n }\n\n private async getActiveAuthAccountId(): Promise<string | undefined> {\n const activeAuth = await this.readActiveAuthFile();\n if (!activeAuth) {\n return undefined;\n }\n return this.getAccountIdFromData(activeAuth);\n }\n\n /**\n * Decode a JWT payload into an object without validating the signature.\n */\n private decodeJwtPayload(token?: string | null): Record<string, unknown> | null {\n if (!token || typeof token !== 'string') {\n return null;\n }\n\n const segments = token.split('.');\n if (segments.length < 2) {\n return null;\n }\n\n try {\n const payload = Buffer.from(segments[1], 'base64url').toString('utf8');\n return JSON.parse(payload);\n } catch {\n return null;\n }\n }\n\n private toIsoStringFromSeconds(seconds?: number): string | undefined {\n if (typeof seconds !== 'number' || Number.isNaN(seconds)) {\n return undefined;\n }\n\n try {\n return new Date(seconds * 1000).toISOString();\n } catch {\n return undefined;\n }\n }\n\n private normalizeEmailCandidate(value: unknown): string | undefined {\n if (typeof value !== 'string') {\n return undefined;\n }\n\n const trimmed = value.trim();\n if (!trimmed || trimmed.includes(' ')) {\n return undefined;\n }\n\n const atIndex = trimmed.indexOf('@');\n if (atIndex <= 0 || atIndex === trimmed.length - 1) {\n return undefined;\n }\n\n const domain = trimmed.slice(atIndex + 1);\n if (!domain || !domain.includes('.')) {\n return undefined;\n }\n\n return trimmed;\n }\n\n private pickFirstEmail(candidates: Array<string | undefined>): string | undefined {\n for (const candidate of candidates) {\n const normalized = this.normalizeEmailCandidate(candidate);\n if (normalized) {\n return normalized;\n }\n }\n return undefined;\n }\n\n private findEmailInObject(value: unknown, seen = new Set<unknown>()): string | undefined {\n if (!value || typeof value !== 'object') {\n return undefined;\n }\n\n if (seen.has(value)) {\n return undefined;\n }\n seen.add(value);\n\n if (Array.isArray(value)) {\n for (const entry of value) {\n const nested = this.findEmailInObject(entry, seen);\n if (nested) {\n return nested;\n }\n }\n return undefined;\n }\n\n for (const [key, entry] of Object.entries(value as Record<string, unknown>)) {\n if (typeof entry === 'string') {\n const normalized = this.normalizeEmailCandidate(entry);\n const lowerKey = key.toLowerCase();\n const keyHintsAtEmail =\n lowerKey.includes('email') ||\n lowerKey.includes('contact') ||\n lowerKey.includes('username') ||\n lowerKey.includes('login');\n\n if (normalized && (keyHintsAtEmail || entry.includes('@'))) {\n return normalized;\n }\n }\n\n if (entry && typeof entry === 'object') {\n const nested = this.findEmailInObject(entry, seen);\n if (nested) {\n return nested;\n }\n }\n }\n\n return undefined;\n }\n\n private resolveProfileEmail(data: ProfileData, metadata?: ProfileMetadata): string | undefined {\n const direct = this.normalizeEmailCandidate(data.email);\n if (direct) {\n return direct;\n }\n\n if (metadata?.email) {\n return metadata.email;\n }\n\n return this.findEmailInObject(data);\n }\n\n private evaluateTokenStatus(data: ProfileData, metadata?: ProfileMetadata): TokenStatus {\n const expiresAt = metadata?.tokenExpiresAt ?? this.computeExpiryIso(data);\n const parsedExpiry = expiresAt ? Date.parse(expiresAt) : Number.NaN;\n const hasExpiry = !Number.isNaN(parsedExpiry);\n const tokenAlert = data.tokenAlert;\n\n if (!data || typeof data !== 'object' || Object.keys(data).length === 0) {\n return {\n state: 'missing',\n reason: 'No authentication data saved for this profile.',\n expiresAt,\n issue: 'auth-missing',\n requiresUserAction: true,\n };\n }\n\n if (tokenAlert?.issue) {\n const reason = typeof tokenAlert.reason === 'string' && tokenAlert.reason.trim().length > 0\n ? tokenAlert.reason.trim()\n : tokenAlert.issue === 'refresh-redeemed'\n ? REFRESH_TOKEN_REDEEMED_REASON\n : 'Authentication needs attention. Re-login this profile.';\n const issue = (tokenAlert.issue as TokenIssue) ?? 'auth-missing';\n return {\n state: 'invalid',\n reason,\n expiresAt,\n issue,\n requiresUserAction: true,\n };\n }\n\n if (!data.access_token) {\n return {\n state: 'missing',\n reason: 'Access token is missing. Re-authenticate with Codex CLI.',\n expiresAt,\n issue: 'access-missing',\n requiresUserAction: true,\n };\n }\n\n if (!this.decodeJwtPayload(data.access_token)) {\n return {\n state: 'invalid',\n reason: 'Access token is corrupted or not a valid JWT.',\n expiresAt,\n issue: 'access-invalid',\n requiresUserAction: true,\n };\n }\n\n const refreshToken = typeof data.refresh_token === 'string' ? data.refresh_token.trim() : '';\n if (!refreshToken) {\n return {\n state: 'missing',\n reason: 'Refresh token is missing. Run Codex login again.',\n expiresAt,\n issue: 'refresh-missing',\n requiresUserAction: true,\n };\n }\n\n if (hasExpiry) {\n const diff = parsedExpiry - Date.now();\n if (diff <= 0) {\n return {\n state: 'expiring',\n reason: 'Access token expired.',\n expiresAt,\n accessTokenExpired: true,\n issue: 'access-expired',\n requiresUserAction: false,\n };\n }\n\n if (diff <= TOKEN_EXPIRING_SOON_WINDOW_MS) {\n return {\n state: 'expiring',\n reason: 'Access token expires soon.',\n expiresAt,\n issue: 'access-expiring',\n requiresUserAction: false,\n };\n }\n }\n\n return {\n state: 'ok',\n expiresAt,\n requiresUserAction: false,\n };\n }\n\n private extractProfileMetadata(data: ProfileData): ProfileMetadata | undefined {\n const idPayload = this.decodeJwtPayload(data.id_token) as Record<string, unknown> | null;\n const accessPayload = this.decodeJwtPayload(data.access_token) as Record<string, unknown> | null;\n\n if (!idPayload && !accessPayload) {\n return undefined;\n }\n\n const authInfo = (idPayload?.['https://api.openai.com/auth'] ??\n accessPayload?.['https://api.openai.com/auth']) as Record<string, unknown> | undefined;\n\n const profileInfo = accessPayload?.['https://api.openai.com/profile'] as Record<string, unknown> | undefined;\n\n const getNumber = (obj: Record<string, unknown> | null | undefined, key: string): number | undefined =>\n typeof obj?.[key] === 'number' ? (obj[key] as number) : undefined;\n\n const getString = (obj: Record<string, unknown> | undefined | null, key: string): string | undefined =>\n typeof obj?.[key] === 'string' ? (obj[key] as string) : undefined;\n\n const exp = getNumber(idPayload, 'exp') ?? getNumber(accessPayload, 'exp');\n const iat = getNumber(idPayload, 'iat') ?? getNumber(accessPayload, 'iat');\n const authTime = getNumber(idPayload, 'auth_time') ?? getNumber(accessPayload, 'auth_time');\n\n const organizationsRaw = Array.isArray(authInfo?.['organizations'])\n ? (authInfo?.['organizations'] as unknown[])\n : undefined;\n\n const organizations = organizationsRaw\n ? organizationsRaw\n .map((org): OrganizationInfo => {\n const record = org as Record<string, unknown> | undefined;\n return {\n id: getString(record, 'id'),\n title: getString(record, 'title'),\n role: getString(record, 'role'),\n isDefault: typeof record?.['is_default'] === 'boolean' ? (record?.['is_default'] as boolean) : undefined,\n };\n })\n .filter(\n org =>\n org.id ||\n org.title ||\n org.role ||\n typeof org.isDefault === 'boolean'\n )\n : undefined;\n\n const groups = Array.isArray(authInfo?.['groups'])\n ? (authInfo?.['groups'] as unknown[]).filter((group): group is string => typeof group === 'string')\n : undefined;\n\n const emailVerified =\n typeof profileInfo?.['email_verified'] === 'boolean'\n ? (profileInfo?.['email_verified'] as boolean)\n : typeof idPayload?.['email_verified'] === 'boolean'\n ? (idPayload?.['email_verified'] as boolean)\n : typeof accessPayload?.['email_verified'] === 'boolean'\n ? (accessPayload?.['email_verified'] as boolean)\n : undefined;\n\n const email =\n this.pickFirstEmail([\n getString(profileInfo, 'email'),\n getString(profileInfo, 'email_address'),\n getString(profileInfo, 'primary_email'),\n getString(profileInfo, 'default_email'),\n getString(profileInfo, 'contact_email'),\n ]) ??\n this.findEmailInObject(profileInfo) ??\n this.pickFirstEmail([\n getString(authInfo, 'user_email'),\n getString(authInfo, 'email'),\n getString(authInfo, 'userEmail'),\n getString(authInfo, 'chatgpt_user_email'),\n ]) ??\n this.findEmailInObject(authInfo) ??\n this.pickFirstEmail([\n getString(idPayload, 'email'),\n getString(idPayload, 'preferred_username'),\n getString(idPayload, 'username'),\n ]) ??\n this.findEmailInObject(idPayload) ??\n this.pickFirstEmail([\n getString(accessPayload, 'email'),\n ]) ??\n this.findEmailInObject(accessPayload);\n\n const subscription: SubscriptionInfo | undefined = authInfo\n ? {\n activeStart: getString(authInfo, 'chatgpt_subscription_active_start'),\n activeUntil: getString(authInfo, 'chatgpt_subscription_active_until'),\n lastChecked: getString(authInfo, 'chatgpt_subscription_last_checked'),\n }\n : undefined;\n\n const planType = getString(authInfo, 'chatgpt_plan_type');\n const chatgptUserId = getString(authInfo, 'chatgpt_user_id');\n const chatgptAccountUserId = getString(authInfo, 'chatgpt_account_user_id');\n const userId =\n getString(authInfo, 'user_id') ??\n chatgptAccountUserId ??\n getString(idPayload ?? undefined, 'sub') ??\n getString(accessPayload ?? undefined, 'sub');\n\n const metadata: ProfileMetadata = {\n email,\n planType,\n subscription,\n organizations,\n groups,\n userId,\n chatgptUserId,\n emailVerified,\n tokenExpiresAt: this.toIsoStringFromSeconds(exp),\n tokenIssuedAt: this.toIsoStringFromSeconds(iat),\n tokenAuthTime: this.toIsoStringFromSeconds(authTime),\n };\n\n const hasMeaningfulData =\n Boolean(metadata.planType) ||\n Boolean(\n metadata.subscription &&\n (metadata.subscription.activeStart ||\n metadata.subscription.activeUntil ||\n metadata.subscription.lastChecked)\n ) ||\n Boolean(metadata.organizations && metadata.organizations.length > 0) ||\n Boolean(metadata.groups && metadata.groups.length > 0) ||\n Boolean(metadata.userId) ||\n Boolean(metadata.chatgptUserId) ||\n Boolean(metadata.email) ||\n typeof metadata.emailVerified === 'boolean' ||\n Boolean(metadata.tokenExpiresAt) ||\n Boolean(metadata.tokenIssuedAt) ||\n Boolean(metadata.tokenAuthTime);\n\n return hasMeaningfulData ? metadata : undefined;\n }\n\n /**\n * Initialize the profile manager and create necessary directories\n */\n async initialize(): Promise<void> {\n this.profileHomesRoot = join(getUserDataDir(), 'profile-homes');\n\n try {\n await fs.mkdir(this.codexDir, { recursive: true });\n } catch (error) {\n logError('Failed to ensure Codex directory exists:', error);\n throw new Error('Failed to initialize profile manager');\n }\n try {\n await fs.mkdir(this.profileHomesRoot, { recursive: true });\n } catch (error) {\n logError('Failed to ensure profile homes directory exists:', error);\n throw new Error('Failed to initialize profile manager');\n }\n\n await this.recoverActiveAuthBackup();\n }\n\n private enqueueAuthSwap<T>(task: () => Promise<T>): Promise<T> {\n const run = globalAuthSwapLock.then(task, task);\n globalAuthSwapLock = run.then(\n () => undefined,\n () => undefined,\n );\n return run;\n }\n\n private async recoverActiveAuthBackup(): Promise<void> {\n let backup: string;\n try {\n backup = await fs.readFile(this.activeAuthBackup, 'utf8');\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn('Failed to inspect active auth backup:', error);\n }\n return;\n }\n\n try {\n if (backup === AUTH_BACKUP_MISSING_MARKER) {\n await fs.rm(this.activeAuth, { force: true });\n } else {\n try {\n await this.writeAtomic(this.activeAuth, backup);\n } catch (error) {\n logWarn('Failed to restore active auth from backup, falling back to direct write:', error);\n try {\n await fs.writeFile(this.activeAuth, backup, 'utf8');\n } catch (fallbackError) {\n logWarn('Direct write failed while restoring active auth backup:', fallbackError);\n }\n }\n }\n } catch (error) {\n logWarn('Failed to restore active auth from backup:', error);\n }\n\n try {\n await fs.rm(this.activeAuthBackup, { force: true });\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn('Failed to remove active auth backup:', error);\n }\n }\n }\n\n private async writeAtomic(filePath: string, contents: string): Promise<void> {\n const tempPath = `${filePath}.tmp`;\n const dir = path.dirname(filePath);\n await fs.mkdir(dir, { recursive: true });\n\n await fs.writeFile(tempPath, contents, 'utf8');\n try {\n await fs.rename(tempPath, filePath);\n } catch (error) {\n // Fall back to writing directly if rename fails for any reason.\n try {\n await fs.writeFile(filePath, contents, 'utf8');\n } catch (writeError) {\n // Surface the original error context to aid debugging.\n const original = error instanceof Error ? error.message : String(error);\n const fallback = writeError instanceof Error ? writeError.message : String(writeError);\n throw new Error(`Atomic write failed (rename: ${original}; direct write: ${fallback})`);\n }\n }\n // Best-effort cleanup of temp file if it still exists.\n try {\n await fs.rm(tempPath, { force: true });\n } catch {\n // ignore cleanup failures\n }\n }\n\n /**\n * Extract account_id from auth data (supports both formats)\n */\n private getAccountIdFromData(data: ProfileData | ActiveAuth): string | undefined {\n if ('account_id' in data && typeof data.account_id === 'string' && data.account_id.trim()) {\n return data.account_id.trim();\n }\n\n if ('tokens' in data && data.tokens && typeof data.tokens === 'object') {\n const accountId = (data.tokens as { account_id?: unknown }).account_id;\n if (typeof accountId === 'string' && accountId.trim()) {\n return accountId.trim();\n }\n }\n\n const projectId =\n 'project_id' in data && typeof (data as ProfileData).project_id === 'string'\n ? (data as ProfileData).project_id?.trim()\n : undefined;\n if (projectId) {\n return projectId;\n }\n\n const email =\n 'email' in data && typeof (data as ProfileData).email === 'string'\n ? (data as ProfileData).email?.trim()\n : undefined;\n return email || undefined;\n }\n\n private resolveWorkspaceIdentity(data: ProfileData | ActiveAuth, metadata?: ProfileMetadata): { id: string; name?: string } {\n const directId =\n 'workspace_id' in data && typeof data.workspace_id === 'string'\n ? data.workspace_id.trim()\n : undefined;\n const directName =\n 'workspace_name' in data && typeof data.workspace_name === 'string'\n ? data.workspace_name.trim()\n : undefined;\n\n if (directId) {\n return { id: directId, name: directName };\n }\n\n const organizations = metadata?.organizations;\n if (organizations && organizations.length > 0) {\n const preferred = organizations.find(org => org.isDefault) ?? organizations[0];\n if (preferred?.id) {\n return { id: preferred.id, name: preferred.title ?? directName };\n }\n }\n\n return { id: DEFAULT_WORKSPACE_ID, name: directName };\n }\n\n private async getProfileRowByName(name: string): Promise<ProfileRecord | undefined> {\n const normalized = this.normalizeProfileName(name);\n const record = await this.readProfileRecord(normalized);\n return record ?? undefined;\n }\n\n private async getProfileRowByAccountId(\n accountId: string,\n options?: { authMethod?: string | null; preferAuthMethod?: string | null },\n ): Promise<ProfileRecord | undefined> {\n const records = await this.listProfileRecords();\n const matches = records.filter(record => {\n const storedAccountId = record.accountId ?? this.getAccountIdFromData(record.data);\n return storedAccountId === accountId;\n });\n\n if (matches.length === 0) {\n return undefined;\n }\n\n const mustMatch = typeof options?.authMethod === 'string' ? options.authMethod.trim().toLowerCase() : null;\n if (mustMatch) {\n return matches.find(record => this.resolveAuthMethod(record.data) === mustMatch);\n }\n\n const prefer = typeof options?.preferAuthMethod === 'string' ? options.preferAuthMethod.trim().toLowerCase() : null;\n if (prefer) {\n return matches.find(record => this.resolveAuthMethod(record.data) === prefer) ?? matches[0];\n }\n\n return matches[0];\n }\n\n private async getProfileRowByAccountAndWorkspace(\n accountId: string,\n workspaceId: string,\n options?: { authMethod?: string | null; preferAuthMethod?: string | null },\n ): Promise<ProfileRecord | undefined> {\n const workspaceKey = workspaceId && workspaceId.trim().length > 0 ? workspaceId.trim() : DEFAULT_WORKSPACE_ID;\n const records = await this.listProfileRecords();\n const matches = records.filter(record => {\n const storedAccountId = record.accountId ?? this.getAccountIdFromData(record.data);\n if (storedAccountId !== accountId) {\n return false;\n }\n const storedWorkspace = record.workspaceId ?? record.data.workspace_id ?? DEFAULT_WORKSPACE_ID;\n return (storedWorkspace && storedWorkspace.trim() ? storedWorkspace.trim() : DEFAULT_WORKSPACE_ID) === workspaceKey;\n });\n\n if (matches.length === 0) {\n return undefined;\n }\n\n const mustMatch = typeof options?.authMethod === 'string' ? options.authMethod.trim().toLowerCase() : null;\n if (mustMatch) {\n return matches.find(record => this.resolveAuthMethod(record.data) === mustMatch);\n }\n\n const prefer = typeof options?.preferAuthMethod === 'string' ? options.preferAuthMethod.trim().toLowerCase() : null;\n if (prefer) {\n return matches.find(record => this.resolveAuthMethod(record.data) === prefer) ?? matches[0];\n }\n\n return matches[0];\n }\n\n private async persistProfileRecord(\n name: string,\n data: ProfileData,\n metadata?: ProfileMetadata,\n options?: { displayName?: string | null },\n ): Promise<void> {\n const resolvedName = this.normalizeProfileName(name);\n const existingRecord = await this.readProfileRecord(resolvedName);\n if (typeof data.auth_method === 'string') {\n data.auth_method = data.auth_method.trim().toLowerCase();\n }\n if (!data.auth_method) {\n data.auth_method = 'codex-cli';\n }\n const resolvedMetadata = metadata ?? this.extractProfileMetadata(data) ?? existingRecord?.metadata;\n const workspace = this.resolveWorkspaceIdentity(data, resolvedMetadata);\n const workspaceId = workspace.id || DEFAULT_WORKSPACE_ID;\n const workspaceName = workspace.name ?? null;\n if (!data.workspace_id) {\n data.workspace_id = workspaceId;\n }\n if (!data.workspace_name && workspaceName) {\n data.workspace_name = workspaceName;\n }\n\n const now = new Date().toISOString();\n const accountId = this.getAccountIdFromData(data) ?? null;\n const resolvedEmail = this.resolveProfileEmail(data, resolvedMetadata) ?? data.email ?? null;\n if (resolvedEmail) {\n data.email = resolvedEmail;\n }\n const createdAt = data.created_at ?? existingRecord?.createdAt ?? now;\n data.created_at = createdAt;\n const updatedAt = data.updated_at ?? now;\n data.updated_at = updatedAt;\n\n const displayName =\n typeof options?.displayName === 'string' && options.displayName.trim().length > 0\n ? options.displayName.trim()\n : existingRecord?.displayName ?? resolvedName;\n\n const record: ProfileRecord = {\n name: resolvedName,\n displayName,\n data,\n metadata: resolvedMetadata,\n accountId,\n workspaceId: data.workspace_id ?? workspaceId,\n workspaceName: data.workspace_name ?? workspaceName,\n email: resolvedEmail ?? null,\n authMethod: typeof data.auth_method === 'string' ? data.auth_method : null,\n createdAt,\n updatedAt,\n };\n\n await fs.mkdir(this.getProfileHomePath(resolvedName), { recursive: true });\n await this.writeProfileRecord(record);\n }\n\n private buildProfileFromRow(row: ProfileRecord): Profile {\n const profile = this.buildProfileFromData(row.name, row.data, {\n displayName: row.displayName ?? undefined,\n email: row.email ?? undefined,\n createdAt: row.createdAt ?? undefined,\n authMethod: row.authMethod ?? undefined,\n accountId: row.accountId ?? undefined,\n workspaceId: row.workspaceId ?? undefined,\n workspaceName: row.workspaceName ?? undefined,\n metadata: row.metadata,\n });\n\n return profile;\n }\n\n private buildProfileFromData(\n name: string,\n data: ProfileData,\n fallback?: {\n displayName?: string;\n email?: string;\n createdAt?: string;\n authMethod?: string;\n accountId?: string;\n projectId?: string;\n workspaceId?: string;\n workspaceName?: string;\n metadata?: ProfileMetadata;\n },\n ): Profile {\n const metadata = fallback?.metadata ?? this.extractProfileMetadata(data);\n const workspace = this.resolveWorkspaceIdentity(data, metadata);\n const workspaceId = workspace.id || fallback?.workspaceId || DEFAULT_WORKSPACE_ID;\n const workspaceName = workspace.name ?? fallback?.workspaceName ?? undefined;\n const email = this.resolveProfileEmail(data, metadata) ?? fallback?.email ?? undefined;\n const tokenStatus = this.evaluateTokenStatus(data, metadata);\n const accountId = this.getAccountIdFromData(data) ?? fallback?.accountId;\n const projectId =\n typeof data.project_id === 'string' && data.project_id.trim().length > 0\n ? data.project_id.trim()\n : fallback?.projectId;\n\n return {\n name,\n displayName: fallback?.displayName ?? name,\n isValid: Boolean(data && Object.keys(data).length > 0),\n accountId,\n projectId,\n workspaceId,\n workspaceName,\n email,\n createdAt: data.created_at ?? fallback?.createdAt ?? undefined,\n authMethod: typeof data.auth_method === 'string'\n ? data.auth_method.trim().toLowerCase()\n : fallback?.authMethod ?? undefined,\n metadata,\n tokenStatus,\n };\n }\n\n private parseTimestamp(value?: string | null): number | null {\n if (typeof value !== 'string' || value.trim() === '') {\n return null;\n }\n\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? null : parsed;\n }\n\n private compareProfilesForPreference(a: Profile, b: Profile): number {\n if (Boolean(a.isValid) !== Boolean(b.isValid)) {\n return a.isValid ? -1 : 1;\n }\n\n const aTimestamp = this.parseTimestamp(a.createdAt ?? null);\n const bTimestamp = this.parseTimestamp(b.createdAt ?? null);\n\n if (aTimestamp !== null || bTimestamp !== null) {\n if (aTimestamp !== null && bTimestamp !== null) {\n if (aTimestamp > bTimestamp) {\n return -1;\n }\n if (aTimestamp < bTimestamp) {\n return 1;\n }\n } else if (aTimestamp !== null) {\n return -1;\n } else {\n return 1;\n }\n }\n\n return a.name.localeCompare(b.name);\n }\n\n private selectPreferredProfile(profiles: Profile[]): Profile {\n if (profiles.length <= 1) {\n return profiles[0];\n }\n\n return profiles\n .slice()\n .sort((a, b) => this.compareProfilesForPreference(a, b))[0];\n }\n\n /**\n * Convert profile data to Codex's expected format\n */\n private convertToCodexFormat(data: ProfileData): ActiveAuth {\n // Check if data is already in Codex format\n if ('tokens' in data) {\n return data as ActiveAuth;\n }\n\n // Convert flat structure to nested Codex format.\n // Keep existing refresh metadata if present; never forge it.\n const lastRefresh = typeof data.last_refresh === 'string' ? data.last_refresh.trim() : '';\n let normalizedLastRefresh = lastRefresh.length > 0 ? lastRefresh : undefined;\n if (!normalizedLastRefresh) {\n const accessPayload = this.decodeJwtPayload(data.access_token);\n const tokenIssuedAt = typeof accessPayload?.iat === 'number'\n ? this.toIsoStringFromSeconds(accessPayload.iat)\n : undefined;\n if (tokenIssuedAt) {\n normalizedLastRefresh = tokenIssuedAt;\n }\n }\n if (!normalizedLastRefresh) {\n const createdAt = typeof data.created_at === 'string' ? data.created_at.trim() : '';\n if (createdAt) {\n normalizedLastRefresh = createdAt;\n }\n }\n const codexAuth: ActiveAuth = {\n OPENAI_API_KEY: null,\n tokens: {\n id_token: data.id_token,\n access_token: data.access_token,\n refresh_token: data.refresh_token,\n account_id: data.account_id,\n ...(normalizedLastRefresh ? { last_refresh: normalizedLastRefresh } : {}),\n },\n };\n if (normalizedLastRefresh) {\n codexAuth.last_refresh = normalizedLastRefresh;\n }\n return codexAuth;\n }\n\n /**\n * Normalize Codex auth data to flat profile format\n */\n private normalizeProfileData(data: ActiveAuth): ProfileData {\n // If data is already in flat format, return as-is\n if ('id_token' in data) {\n return data as ProfileData;\n }\n\n // Convert nested Codex format to flat\n const tokens = data.tokens || {};\n const profile: ProfileData = {\n id_token: tokens.id_token,\n access_token: tokens.access_token,\n refresh_token: tokens.refresh_token,\n account_id: tokens.account_id,\n };\n const tokenLastRefresh = typeof tokens.last_refresh === 'string' ? tokens.last_refresh.trim() : '';\n const rootLastRefresh = typeof data.last_refresh === 'string' ? data.last_refresh.trim() : '';\n const normalizedLastRefresh = tokenLastRefresh || rootLastRefresh;\n if (normalizedLastRefresh) {\n profile.last_refresh = normalizedLastRefresh;\n }\n\n if (data.email) {\n profile.email = data.email;\n }\n\n return profile;\n }\n\n private mergeProfileRecords(existing: ProfileData, incoming: ProfileData): {\n profile: ProfileData;\n metadata?: ProfileMetadata;\n } {\n const merged: ProfileData = {\n ...existing,\n ...incoming,\n created_at: existing.created_at ?? incoming.created_at ?? new Date().toISOString(),\n };\n\n if (typeof merged.auth_method === 'string') {\n merged.auth_method = merged.auth_method.trim().toLowerCase();\n }\n if (!merged.auth_method) {\n merged.auth_method = 'codex-cli';\n }\n\n const metadata = this.extractProfileMetadata(merged);\n const resolvedEmail = this.resolveProfileEmail(merged, metadata);\n\n if (resolvedEmail) {\n merged.email = resolvedEmail;\n }\n\n const workspace = this.resolveWorkspaceIdentity(merged, metadata);\n if (!merged.workspace_id) {\n merged.workspace_id = workspace.id || existing.workspace_id || DEFAULT_WORKSPACE_ID;\n }\n if (!merged.workspace_name) {\n merged.workspace_name = workspace.name ?? existing.workspace_name;\n }\n\n if (this.hasTokenChanges(existing, incoming)) {\n delete merged.tokenAlert;\n }\n\n return { profile: merged, metadata };\n }\n\n private hasTokenChanges(existing: ProfileData, incoming: ProfileData): boolean {\n const tokenKeys: Array<keyof ProfileData> = [\n 'id_token',\n 'access_token',\n 'refresh_token',\n 'last_refresh',\n 'account_id',\n 'workspace_id',\n ];\n\n return tokenKeys.some(key => {\n const nextValue = incoming[key];\n if (typeof nextValue !== 'string' || nextValue.length === 0) {\n return false;\n }\n return nextValue !== existing[key];\n });\n }\n\n async flagAuthIssue(\n name: string,\n issue: TokenIssue,\n reason?: string,\n options?: { observedAt?: string },\n ): Promise<void> {\n await this.initialize();\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n logWarn(`Cannot flag auth issue '${issue}' for missing profile '${profileName}'.`);\n return;\n }\n\n const observedAt = options?.observedAt ? Date.parse(options.observedAt) : null;\n const updatedAt = record.updatedAt ? Date.parse(record.updatedAt) : null;\n if (observedAt !== null && updatedAt !== null && observedAt <= updatedAt) {\n return;\n }\n\n const data: ProfileData = record.data;\n\n const trimmedReason = typeof reason === 'string' && reason.trim().length > 0 ? reason.trim() : undefined;\n const normalized = trimmedReason?.toLowerCase() ?? '';\n const storedReason = issue === 'refresh-redeemed'\n ? (normalized.includes(REFRESH_TOKEN_REDEEMED_SNIPPET)\n ? REFRESH_TOKEN_REDEEMED_REASON\n : trimmedReason ?? REFRESH_TOKEN_REDEEMED_REASON)\n : trimmedReason;\n const alert: TokenAlert = {\n issue,\n reason: storedReason,\n recordedAt: new Date().toISOString(),\n };\n\n data.tokenAlert = alert;\n\n try {\n const metadata = this.extractProfileMetadata(data);\n await this.persistProfileRecord(profileName, data, metadata);\n } catch (error) {\n logError(`Failed to persist token alert for profile '${profileName}':`, error);\n }\n }\n\n async flagRefreshTokenRedeemed(name: string, reason?: string, options?: { observedAt?: string }): Promise<void> {\n await this.flagAuthIssue(name, 'refresh-redeemed', reason, options);\n }\n\n private async syncProfileTokensFromActiveAuth(\n profileName: string,\n baselineProfile: ProfileData,\n authPath?: string,\n ): Promise<void> {\n const targetPath = authPath ?? this.activeAuth;\n try {\n const authRaw = await fs.readFile(targetPath, 'utf8');\n await this.syncProfileTokensFromAuthContent(profileName, baselineProfile, authRaw);\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to read Codex auth for '${profileName}' while syncing tokens:`, error);\n }\n }\n }\n\n private async syncProfileTokensFromAuthContent(\n profileName: string,\n baselineProfile: ProfileData,\n authContent: string,\n ): Promise<void> {\n let activeAuth: ActiveAuth;\n try {\n activeAuth = JSON.parse(authContent) as ActiveAuth;\n } catch (error) {\n logWarn(`Failed to parse Codex auth while syncing tokens for '${profileName}':`, error);\n return;\n }\n\n const normalized = this.normalizeProfileData(activeAuth);\n const metadata = this.extractProfileMetadata(normalized);\n const workspace = this.resolveWorkspaceIdentity(normalized, metadata);\n normalized.workspace_id = normalized.workspace_id ?? workspace.id ?? DEFAULT_WORKSPACE_ID;\n if (workspace.name) {\n normalized.workspace_name = normalized.workspace_name ?? workspace.name;\n }\n const hasTokens =\n typeof normalized.id_token === 'string' ||\n typeof normalized.access_token === 'string' ||\n typeof normalized.refresh_token === 'string';\n\n if (!hasTokens) {\n return;\n }\n\n let existing = baselineProfile;\n const latestRow = await this.getProfileRowByName(profileName);\n if (latestRow) {\n existing = latestRow.data;\n }\n\n const existingAccountId = this.getAccountIdFromData(existing);\n const newAccountId = this.getAccountIdFromData(normalized);\n\n if (existingAccountId && newAccountId && existingAccountId !== newAccountId) {\n logWarn(\n `Skipped syncing tokens for profile '${profileName}' because Codex auth switched to account '${newAccountId}'.`,\n );\n return;\n }\n\n if (!this.hasTokenChanges(existing, normalized)) {\n return;\n }\n\n const { profile: merged, metadata: mergedMetadata } = this.mergeProfileRecords(existing, normalized);\n\n try {\n await this.persistProfileRecord(profileName, merged, mergedMetadata);\n } catch (error) {\n logError(`Failed to persist refreshed tokens for profile '${profileName}':`, error);\n }\n }\n\n private async copyCodexConfig(targetCodexHome: string): Promise<void> {\n const candidates = ['config.toml', 'config.json', 'config.yaml', 'config.yml'];\n for (const file of candidates) {\n const source = join(this.codexDir, file);\n const destination = join(targetCodexHome, file);\n try {\n await fs.copyFile(source, destination);\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to copy Codex config '${file}' to profile home:`, error);\n }\n }\n }\n }\n\n private getProfileHomePath(profileName: string): string {\n return join(this.profileHomesRoot, profileName);\n }\n\n private ensureTrailingNewline(content: string): string {\n return content.endsWith('\\n') ? content : `${content}\\n`;\n }\n\n private async sanitizeProfileConfig(profileHome: string): Promise<void> {\n const configPath = join(profileHome, 'config.toml');\n let raw: string;\n try {\n raw = await fs.readFile(configPath, 'utf8');\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to read config for profile home '${profileHome}':`, error);\n }\n return;\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = parse(raw) as Record<string, unknown>;\n } catch (error) {\n logWarn(`Failed to parse config.toml for profile home '${profileHome}':`, error);\n return;\n }\n\n if (!Object.prototype.hasOwnProperty.call(parsed, 'model_reasoning_effort')) {\n return;\n }\n\n delete parsed['model_reasoning_effort'];\n const sanitized = this.ensureTrailingNewline(stringify(parsed as Record<string, unknown>));\n try {\n await fs.writeFile(configPath, sanitized, 'utf8');\n } catch (error) {\n logWarn(`Failed to write sanitized config.toml for profile home '${profileHome}':`, error);\n }\n }\n\n private async prepareProfileHome(profileName: string, authData: ActiveAuth): Promise<string> {\n const profileHome = this.getProfileHomePath(profileName);\n await fs.mkdir(profileHome, { recursive: true });\n const authPath = join(profileHome, 'auth.json');\n await this.writeAtomic(authPath, JSON.stringify(authData, null, 2));\n await this.copyCodexConfig(profileHome);\n await this.sanitizeProfileConfig(profileHome);\n return profileHome;\n }\n\n /**\n * List all available profiles\n */\n async profileExists(name: string): Promise<boolean> {\n await this.initialize();\n const profileName = this.normalizeProfileName(name);\n return Boolean(await this.getProfileRowByName(profileName));\n }\n\n async listProfiles(): Promise<Profile[]> {\n await this.initialize();\n try {\n const records = await this.listProfileRecords();\n return records\n .map(record => this.buildProfileFromRow(record))\n .filter(profile => !profile.authMethod || profile.authMethod === 'codex-cli')\n .sort((a, b) => {\n const aLabel = a.displayName ?? a.name;\n const bLabel = b.displayName ?? b.name;\n const base = aLabel.localeCompare(bLabel);\n return base !== 0 ? base : a.name.localeCompare(b.name);\n });\n } catch (error) {\n logError('Error reading profiles from disk:', error);\n return [];\n }\n }\n\n /**\n * Create a new profile by running codex login\n */\n async createProfile(name: string): Promise<Profile | null> {\n await this.initialize();\n\n const profileName = this.normalizeProfileName(name);\n if (await this.getProfileRowByName(profileName)) {\n throw new Error(`Profile '${profileName}' already exists!`);\n }\n\n let authData: ActiveAuth;\n try {\n const authRaw = await fs.readFile(this.activeAuth, 'utf8');\n authData = JSON.parse(authRaw) as ActiveAuth;\n } catch (error) {\n logError('Error creating profile:', error);\n throw new Error('Failed to create profile. Make sure Codex CLI is installed and you are logged in.');\n }\n\n const normalizedProfile = this.normalizeProfileData(authData);\n normalizedProfile.created_at = normalizedProfile.created_at ?? new Date().toISOString();\n if (typeof normalizedProfile.auth_method === 'string') {\n normalizedProfile.auth_method = normalizedProfile.auth_method.trim().toLowerCase();\n }\n normalizedProfile.auth_method = normalizedProfile.auth_method ?? 'codex-cli';\n\n const metadata = this.extractProfileMetadata(normalizedProfile);\n const workspace = this.resolveWorkspaceIdentity(normalizedProfile, metadata);\n normalizedProfile.workspace_id = normalizedProfile.workspace_id ?? workspace.id ?? DEFAULT_WORKSPACE_ID;\n if (workspace.name) {\n normalizedProfile.workspace_name = normalizedProfile.workspace_name ?? workspace.name;\n }\n\n const accountId = this.getAccountIdFromData(normalizedProfile);\n if (accountId) {\n const requestedWorkspace = normalizedProfile.workspace_id ?? DEFAULT_WORKSPACE_ID;\n const duplicate = await this.getProfileRowByAccountAndWorkspace(accountId, requestedWorkspace, { authMethod: 'codex-cli' });\n if (duplicate) {\n normalizedProfile.workspace_id = `${requestedWorkspace}:${profileName}`;\n normalizedProfile.workspace_name = normalizedProfile.workspace_name ?? profileName;\n }\n }\n\n const resolvedEmail = this.resolveProfileEmail(normalizedProfile, metadata);\n if (resolvedEmail) {\n normalizedProfile.email = resolvedEmail;\n }\n\n try {\n await this.persistProfileRecord(profileName, normalizedProfile, metadata);\n const stored = await this.getProfileRowByName(profileName);\n return stored ? this.buildProfileFromRow(stored) : null;\n } catch (error) {\n logError('Error creating profile:', error);\n throw new Error('Failed to create profile. Make sure Codex CLI is installed and you are logged in.');\n }\n }\n\n /**\n * Switch to a different profile\n */\n async switchToProfile(name: string): Promise<boolean> {\n await this.initialize();\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n throw new Error(`Profile '${profileName}' not found!`);\n }\n\n try {\n const profileData = record.data;\n const codexFormat = this.convertToCodexFormat(profileData);\n await this.writeAtomic(this.activeAuth, JSON.stringify(codexFormat, null, 2));\n await this.persistPreferredProfileName(profileName);\n return true;\n } catch (error) {\n logError('Error switching profile:', error);\n throw new Error('Failed to switch profile');\n }\n }\n\n async refreshProfileAuth(name: string): Promise<Profile> {\n await this.initialize();\n\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n throw new Error(`Profile '${profileName}' not found!`);\n }\n\n const existing: ProfileData = record.data;\n let activeAuth: ActiveAuth;\n try {\n const authContent = await fs.readFile(this.activeAuth, 'utf8');\n activeAuth = JSON.parse(authContent) as ActiveAuth;\n } catch (error) {\n if (this.isNotFoundError(error)) {\n throw new Error('Codex CLI did not produce an auth file. Complete the login before refreshing this profile.');\n }\n logError('Failed to read Codex auth file during refresh:', error);\n throw new Error('Failed to read Codex auth file. Complete the login and try again.');\n }\n\n const normalized = this.normalizeProfileData(activeAuth);\n const existingAccountId = this.getAccountIdFromData(existing);\n const newAccountId = this.getAccountIdFromData(normalized);\n const normalizedMetadata = this.extractProfileMetadata(normalized);\n const normalizedWorkspace = this.resolveWorkspaceIdentity(normalized, normalizedMetadata);\n normalized.workspace_id = normalized.workspace_id ?? normalizedWorkspace.id ?? DEFAULT_WORKSPACE_ID;\n if (normalizedWorkspace.name) {\n normalized.workspace_name = normalized.workspace_name ?? normalizedWorkspace.name;\n }\n\n if (existingAccountId && newAccountId && existingAccountId !== newAccountId) {\n throw new Error(\n `Active Codex login is for account '${newAccountId}', but profile '${profileName}' is tied to '${existingAccountId}'. Create a new profile for the new account instead.`,\n );\n }\n\n if (existingAccountId && normalized.workspace_id) {\n const currentWorkspace = this.resolveWorkspaceIdentity(existing, this.extractProfileMetadata(existing));\n const targetWorkspaceId = normalized.workspace_id;\n const currentWorkspaceId = currentWorkspace.id ?? DEFAULT_WORKSPACE_ID;\n if (targetWorkspaceId !== currentWorkspaceId) {\n const duplicate = await this.getProfileRowByAccountAndWorkspace(existingAccountId, targetWorkspaceId, {\n authMethod: this.resolveAuthMethod(existing),\n });\n if (duplicate && duplicate.name !== profileName) {\n throw new Error(\n `Account is already saved as profile '${duplicate.name}'. Switch to or delete that profile before creating another.`,\n );\n }\n }\n }\n\n const { profile: merged, metadata } = this.mergeProfileRecords(existing, normalized);\n delete merged.tokenAlert;\n\n await this.persistProfileRecord(profileName, merged, metadata);\n const updated = await this.getProfileRowByName(profileName);\n if (!updated) {\n throw new Error('Failed to persist refreshed profile data.');\n }\n\n const profile = this.buildProfileFromRow(updated);\n if (metadata) {\n profile.metadata = metadata;\n profile.tokenStatus = this.evaluateTokenStatus(merged, metadata);\n }\n return profile;\n }\n\n /**\n * Execute an action with a profile's auth injected.\n * Creates an isolated CODEX_HOME with the profile's auth/config, invokes the action\n * with env overrides, then syncs any refreshed tokens back to the profile.\n */\n async runWithProfileAuth<T>(\n name: string,\n action: (env: NodeJS.ProcessEnv) => Promise<T>,\n ): Promise<T> {\n return this.enqueueAuthSwap(async () => {\n await this.initialize();\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n throw new Error(`Profile '${profileName}' not found!`);\n }\n\n let profileData: ProfileData = record.data;\n // If the user's active Codex auth is for the same account and has fresher tokens,\n // sync it into this profile before running actions (prevents avoidable re-logins).\n await this.syncProfileTokensFromActiveAuth(profileName, profileData);\n const updatedRecord = await this.getProfileRowByName(profileName);\n if (updatedRecord) {\n profileData = updatedRecord.data;\n }\n const profileHome = this.getProfileHomePath(profileName);\n await fs.mkdir(profileHome, { recursive: true });\n\n if (profileData.auth_method && profileData.auth_method !== 'codex-cli') {\n throw new Error('Unsupported auth method. Codex CLI profiles only.');\n }\n const codexFormat = this.convertToCodexFormat(profileData);\n await this.prepareProfileHome(profileName, codexFormat);\n const authPath = path.join(profileHome, 'auth.json');\n\n const envOverrides: NodeJS.ProcessEnv = {\n ...process.env,\n HOME: profileHome,\n USERPROFILE: profileHome,\n CODEX_HOME: profileHome,\n };\n\n try {\n return await action(envOverrides);\n } finally {\n let finalAuthContent: string | null = null;\n try {\n finalAuthContent = await fs.readFile(authPath, 'utf8');\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to read isolated auth for '${profileName}' after action:`, error);\n }\n }\n\n try {\n if (finalAuthContent) {\n await this.syncProfileTokensFromAuthContent(profileName, profileData, finalAuthContent);\n } else {\n await this.syncProfileTokensFromActiveAuth(profileName, profileData, authPath);\n }\n } catch (error) {\n logWarn(`Failed to sync refreshed tokens for profile '${profileName}':`, error);\n }\n }\n });\n }\n\n /**\n * Rename a profile\n */\n async renameProfile(oldName: string, newName: string): Promise<boolean> {\n await this.initialize();\n const sourceName = this.normalizeProfileName(oldName);\n const targetName = this.normalizeProfileName(newName);\n\n const existing = await this.getProfileRowByName(sourceName);\n if (!existing) {\n throw new Error(`Profile '${sourceName}' not found!`);\n }\n\n if (await this.getProfileRowByName(targetName)) {\n throw new Error(`Profile '${targetName}' already exists!`);\n }\n\n const preferred = await this.readPreferredProfileName();\n if (preferred && preferred === sourceName) {\n await this.persistPreferredProfileName(targetName);\n }\n\n const oldHome = this.getProfileHomePath(sourceName);\n const newHome = this.getProfileHomePath(targetName);\n try {\n await fs.mkdir(this.profileHomesRoot, { recursive: true });\n await fs.rename(oldHome, newHome);\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to move profile home from '${sourceName}' to '${targetName}':`, error);\n }\n }\n\n try {\n const updatedRecord: ProfileRecord = {\n ...existing,\n name: targetName,\n };\n await this.writeProfileRecord(updatedRecord);\n await this.deleteProfileRecord(sourceName);\n } catch (error) {\n logWarn(`Failed to rewrite profile record after renaming '${sourceName}' to '${targetName}':`, error);\n }\n\n return true;\n }\n\n async updateProfileDisplayName(name: string, displayName: string): Promise<boolean> {\n await this.initialize();\n\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n throw new Error(`Profile '${profileName}' not found!`);\n }\n\n const trimmed = typeof displayName === 'string' ? displayName.trim() : '';\n if (!trimmed) {\n throw new Error('Profile name must not be empty.');\n }\n\n const now = new Date().toISOString();\n record.displayName = trimmed;\n record.updatedAt = now;\n (record.data as ProfileData & { updated_at?: string }).updated_at = now;\n\n await this.writeProfileRecord(record);\n return true;\n }\n\n /**\n * Delete a profile\n */\n async deleteProfile(name: string): Promise<boolean> {\n await this.initialize();\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n throw new Error(`Profile '${profileName}' not found!`);\n }\n const preferred = await this.readPreferredProfileName();\n if (preferred && preferred === profileName) {\n await this.persistPreferredProfileName(null);\n }\n try {\n await fs.rm(this.getProfileHomePath(profileName), { recursive: true, force: true });\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to remove profile home for '${profileName}':`, error);\n }\n }\n await this.deleteProfileRecord(profileName);\n return true;\n }\n\n /**\n * Delete every profile that does not appear in the allow-list.\n * Used to enforce plan limits when local storage was tampered with.\n */\n async deleteProfilesNotIn(allowedNames: Iterable<string>): Promise<string[]> {\n await this.initialize();\n const normalized = new Set<string>();\n for (const name of allowedNames) {\n try {\n normalized.add(this.normalizeProfileName(name));\n } catch {\n // Skip invalid names so we only retain well-formed entries.\n }\n }\n\n const records = await this.listProfileRecords();\n const deleteCandidates = records\n .map(record => {\n try {\n return this.normalizeProfileName(record.name);\n } catch {\n return null;\n }\n })\n .filter((name): name is string => Boolean(name) && !normalized.has(name));\n\n if (deleteCandidates.length === 0) {\n return [];\n }\n\n const removed: string[] = [];\n for (const name of deleteCandidates) {\n try {\n await fs.rm(this.getProfileHomePath(name), { recursive: true, force: true });\n await this.deleteProfileRecord(name);\n removed.push(name);\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to remove profile '${name}' during plan enforcement:`, error);\n }\n }\n }\n const preferred = await this.readPreferredProfileName();\n if (preferred && removed.includes(preferred)) {\n await this.persistPreferredProfileName(null);\n }\n return removed;\n }\n\n /**\n * Check if the current auth matches a profile (for smart detection)\n */\n async getCurrentProfile(): Promise<{ name: string | null; trusted: boolean }> {\n await this.initialize();\n const preferredName = await this.readPreferredProfileName();\n if (preferredName) {\n try {\n const normalizedPreferred = this.normalizeProfileName(preferredName);\n const preferredRecord = await this.getProfileRowByName(normalizedPreferred);\n if (preferredRecord) {\n return { name: normalizedPreferred, trusted: true };\n }\n } catch {\n // fall through to active auth detection\n }\n }\n const activeAuth = await this.readActiveAuthFile();\n\n if (activeAuth) {\n const normalizedAuth = this.normalizeProfileData(activeAuth);\n const authMetadata = this.extractProfileMetadata(normalizedAuth);\n const workspace = this.resolveWorkspaceIdentity(normalizedAuth, authMetadata);\n const activeAccountId = this.getAccountIdFromData(normalizedAuth);\n\n if (activeAccountId) {\n const scoped = await this.getProfileRowByAccountAndWorkspace(activeAccountId, workspace.id ?? DEFAULT_WORKSPACE_ID, {\n preferAuthMethod: 'codex-cli',\n });\n if (scoped) {\n const normalized = this.normalizeProfileName(scoped.name);\n await this.persistPreferredProfileName(normalized);\n return { name: normalized, trusted: true };\n }\n\n const matching = await this.getProfileRowByAccountId(activeAccountId, { preferAuthMethod: 'codex-cli' });\n if (matching) {\n const normalized = this.normalizeProfileName(matching.name);\n await this.persistPreferredProfileName(normalized);\n return { name: normalized, trusted: true };\n }\n }\n }\n\n const preferred = await this.readPreferredProfileName();\n if (preferred) {\n try {\n const normalized = this.normalizeProfileName(preferred);\n const exists = await this.getProfileRowByName(normalized);\n if (exists) {\n return { name: normalized, trusted: true };\n }\n } catch {\n await this.persistPreferredProfileName(null);\n return { name: null, trusted: false };\n }\n await this.persistPreferredProfileName(null);\n }\n\n return { name: null, trusted: false };\n }\n\n /**\n * Export a profile to a portable format.\n * Sensitive tokens are included but should be handled securely.\n */\n async exportProfile(name: string): Promise<{\n name: string;\n displayName: string | null;\n email: string | null;\n accountId: string | null;\n workspaceId: string | null;\n workspaceName: string | null;\n authMethod: string | null;\n createdAt: string | null;\n metadata: ProfileMetadata | undefined;\n exportedAt: string;\n }> {\n await this.initialize();\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n throw new Error(`Profile '${profileName}' not found!`);\n }\n\n return {\n name: record.name,\n displayName: record.displayName,\n email: record.email,\n accountId: record.accountId,\n workspaceId: record.workspaceId,\n workspaceName: record.workspaceName,\n authMethod: record.authMethod,\n createdAt: record.createdAt,\n metadata: record.metadata,\n exportedAt: new Date().toISOString(),\n };\n }\n\n /**\n * Export profiles for cloud sync (includes token-bearing auth data).\n */\n async exportProfilesForCloudSync(): Promise<CloudSyncProfileRecord[]> {\n await this.initialize();\n const records = await this.listProfileRecords();\n return records.map(record => ({\n name: record.name,\n displayName: record.displayName,\n data: record.data,\n metadata: record.metadata,\n accountId: record.accountId,\n workspaceId: record.workspaceId,\n workspaceName: record.workspaceName,\n email: record.email,\n authMethod: record.authMethod,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n }));\n }\n\n /**\n * Replace local profiles with a full snapshot from cloud sync.\n */\n async replaceProfilesFromCloudSync(records: CloudSyncProfileRecord[]): Promise<{ imported: number; removed: number }> {\n await this.initialize();\n const now = new Date().toISOString();\n const normalized = new Map<string, ProfileRecord>();\n const existingMap = await this.readProfilesStateMap();\n const existingNames = new Set(Object.keys(existingMap));\n\n for (const candidate of records ?? []) {\n try {\n const name = this.normalizeProfileName(candidate?.name ?? '');\n const data =\n candidate && typeof candidate.data === 'object' && candidate.data !== null\n ? (candidate.data as ProfileData)\n : null;\n if (!data) {\n continue;\n }\n\n const metadata =\n candidate.metadata && typeof candidate.metadata === 'object'\n ? candidate.metadata\n : undefined;\n\n const record: ProfileRecord = {\n name,\n displayName: typeof candidate.displayName === 'string' ? candidate.displayName : null,\n data,\n metadata,\n accountId: typeof candidate.accountId === 'string' ? candidate.accountId : null,\n workspaceId: typeof candidate.workspaceId === 'string' ? candidate.workspaceId : null,\n workspaceName: typeof candidate.workspaceName === 'string' ? candidate.workspaceName : null,\n email: typeof candidate.email === 'string' ? candidate.email : null,\n authMethod: typeof candidate.authMethod === 'string' ? candidate.authMethod : this.resolveAuthMethod(data),\n createdAt: typeof candidate.createdAt === 'string' ? candidate.createdAt : now,\n updatedAt: typeof candidate.updatedAt === 'string' ? candidate.updatedAt : now,\n };\n\n normalized.set(name, record);\n } catch {\n // Ignore malformed record entries.\n }\n }\n\n const nextMap: Record<string, ProfileRecordState> = {};\n for (const record of normalized.values()) {\n nextMap[record.name] = this.toStateRecord(record);\n }\n await this.writeProfilesStateMap(nextMap);\n\n let removed = 0;\n\n for (const name of existingNames) {\n if (normalized.has(name)) {\n continue;\n }\n try {\n await fs.rm(this.getProfileHomePath(name), { recursive: true, force: true });\n removed += 1;\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to remove profile '${name}' during cloud sync replace:`, error);\n }\n }\n }\n\n const preferred = await this.readPreferredProfileName();\n if (preferred) {\n try {\n const normalizedPreferred = this.normalizeProfileName(preferred);\n if (!normalized.has(normalizedPreferred)) {\n await this.persistPreferredProfileName(null);\n }\n } catch {\n await this.persistPreferredProfileName(null);\n }\n }\n\n return {\n imported: normalized.size,\n removed,\n };\n }\n}\n","export interface AutoRollSettings {\n enabled: boolean;\n warningThreshold: number;\n switchThreshold: number;\n}\n\nexport const DEFAULT_AUTO_ROLL_ENABLED = false;\nexport const DEFAULT_AUTO_ROLL_WARNING_THRESHOLD = 85;\nexport const DEFAULT_AUTO_ROLL_SWITCH_THRESHOLD = 95;\nexport const AUTO_ROLL_WARNING_MIN = 50;\nconst AUTO_ROLL_WARNING_MAX = 99;\nconst AUTO_ROLL_SWITCH_MAX = 100;\n\nfunction clampNumber(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nfunction resolveFiniteNumber(value: number, fallback: number): number {\n return Number.isFinite(value) ? value : fallback;\n}\n\nexport function sanitizeAutoRollWarningThreshold(value: number): number {\n const numeric = resolveFiniteNumber(value, DEFAULT_AUTO_ROLL_WARNING_THRESHOLD);\n return clampNumber(numeric, AUTO_ROLL_WARNING_MIN, AUTO_ROLL_WARNING_MAX);\n}\n\nexport function sanitizeAutoRollSwitchThreshold(\n value: number,\n warningThreshold: number,\n): number {\n const sanitizedWarning = sanitizeAutoRollWarningThreshold(warningThreshold);\n const numeric = resolveFiniteNumber(value, DEFAULT_AUTO_ROLL_SWITCH_THRESHOLD);\n return clampNumber(numeric, sanitizedWarning + 1, AUTO_ROLL_SWITCH_MAX);\n}\n\nexport function sanitizeAutoRollThresholds(\n warningThreshold: number,\n switchThreshold: number,\n): Pick<AutoRollSettings, \"warningThreshold\" | \"switchThreshold\"> {\n const sanitizedWarning = sanitizeAutoRollWarningThreshold(warningThreshold);\n const sanitizedSwitch = sanitizeAutoRollSwitchThreshold(switchThreshold, sanitizedWarning);\n return {\n warningThreshold: sanitizedWarning,\n switchThreshold: sanitizedSwitch,\n };\n}\n\n/**\n * Normalize partial auto-roll settings into a safe shape with bounds.\n * Ensures switch threshold is always above warning and both live within [50, 100].\n */\nexport function normalizeAutoRollSettings(\n raw?: Partial<AutoRollSettings> | null,\n): AutoRollSettings {\n const enabled = typeof raw?.enabled === 'boolean' ? raw.enabled : DEFAULT_AUTO_ROLL_ENABLED;\n const rawWarning = resolveFiniteNumber(\n typeof raw?.warningThreshold === 'number' ? raw.warningThreshold : NaN,\n DEFAULT_AUTO_ROLL_WARNING_THRESHOLD,\n );\n const rawSwitch = resolveFiniteNumber(\n typeof raw?.switchThreshold === 'number' ? raw.switchThreshold : NaN,\n DEFAULT_AUTO_ROLL_SWITCH_THRESHOLD,\n );\n\n // First clamp warning to valid range, then ensure switch is above it\n const { warningThreshold: normalizedWarning, switchThreshold: normalizedSwitch } = sanitizeAutoRollThresholds(\n rawWarning,\n rawSwitch,\n );\n\n return {\n enabled,\n warningThreshold: normalizedWarning,\n switchThreshold: normalizedSwitch,\n };\n}\n","import { promises as fs } from \"node:fs\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport type { ProfileData, ProfileMetadata } from \"./types\";\nimport {\n CHAT_SCROLLBACK_DEFAULT,\n normalizeChatHistoryScrollbackItems,\n} from \"./chat-scrollback\";\nimport {\n DEFAULT_COMMIT_MESSAGE_PROMPT,\n normalizeCommitMessagePrompt,\n} from \"./commit-message-prompt\";\n\nconst APP_STATE_FILE = \"app-state.json\";\nconst APP_NAME = \"codexuse-desktop\";\n\nexport type LicenseStatusCode = \"inactive\" | \"active\" | \"grace\" | \"error\";\nexport type ReasoningEffort = \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"none\";\n\nexport type ProfileRecordState = {\n name: string;\n displayName: string | null;\n data: ProfileData;\n metadata?: ProfileMetadata;\n accountId: string | null;\n workspaceId: string | null;\n workspaceName: string | null;\n email: string | null;\n authMethod: string | null;\n createdAt: string | null;\n updatedAt: string | null;\n};\n\nexport type SkillsInstallState = {\n id: string;\n repo?: string | null;\n repoPath?: string | null;\n sourceLabel?: string | null;\n sourceType?: \"official\" | \"community\" | \"local\";\n viewUrl?: string | null;\n createdAt?: string | null;\n};\n\nexport type SyncState = {\n lastPushAt: string | null;\n lastPullAt: string | null;\n lastError: string | null;\n remoteUpdatedAt: string | null;\n};\n\nexport type TelemetryState = {\n installId: string | null;\n enabled: boolean;\n lastFlushAt: string | null;\n lastError: string | null;\n};\n\nexport type AppState = {\n schemaVersion: 1;\n autoRoll: {\n enabled: boolean;\n warningThreshold: number;\n switchThreshold: number;\n };\n app: {\n lastAppVersion: string | null;\n pendingUpdateVersion: string | null;\n lastProfileName: string | null;\n };\n license: {\n licenseKey: string | null;\n purchaseEmail: string | null;\n lastVerifiedAt: string | null;\n nextCheckAt: string | null;\n lastVerificationError: string | null;\n status: LicenseStatusCode;\n signature: string | null;\n };\n providers: {\n selectedProviderId: string;\n defaultModel: string | null;\n defaultReasoningEffort: ReasoningEffort;\n list: Array<{\n id: string;\n name: string;\n models: string[];\n apiKey?: string;\n baseUrl?: string;\n }>;\n overridesByPath: Record<string, { selectedModel?: string | null; reasoningEffort?: ReasoningEffort }>;\n };\n sandbox: {\n defaultMode: string;\n defaultApprovalPolicy: string;\n overridesByPath: Record<string, { mode?: string; approvalPolicy?: string }>;\n };\n preferences: {\n excludeFolders: string[];\n enableTaskCompleteBeep: boolean;\n preventSleepDuringTasks: boolean;\n chatHistoryScrollbackItems: number | null;\n systemNotificationsEnabled: boolean;\n subagentSystemNotificationsEnabled: boolean;\n folderHistory: Array<{ path: string; name: string; lastVisited: number }>;\n pinnedPaths: string[];\n };\n runtimeSettings: Record<string, unknown>;\n workspaceSettingsByPath: Record<\n string,\n {\n systemPrompt?: string;\n runScript?: string;\n buildScript?: string;\n openIdeCommand?: string;\n }\n >;\n conversationCategoriesByCwd: Record<string, Array<{ id: string; name: string }>>;\n conversationCategoryAssignmentsByCwd: Record<string, Record<string, string>>;\n git: {\n commitMessagePrompt: string;\n commitMessageModelId: string | null;\n };\n agents: {\n multiAgentEnabled: boolean;\n maxThreads: number;\n maxDepth: number;\n };\n skills: {\n sources: Array<{\n id: string;\n repo: string;\n label: string;\n branch?: string | null;\n url?: string | null;\n official?: boolean;\n compatibilityNote?: string | null;\n priority?: number;\n }>;\n installsBySlug: Record<string, SkillsInstallState>;\n };\n sync: SyncState;\n telemetry: TelemetryState;\n profilesByName: Record<string, ProfileRecordState>;\n migration: {\n status: \"pending\" | \"pending_local_storage\" | \"complete\";\n startedAt: string | null;\n completedAt: string | null;\n localStorageImportedAt: string | null;\n lastError?: string | null;\n };\n};\n\nexport type AppStatePatch = DeepPartial<AppState>;\nexport type AppStateUpdateMode = \"replace\" | \"patch\";\nexport type AppStateUpdateOptions = {\n allowBeforeMigrationComplete?: boolean;\n mode?: AppStateUpdateMode;\n};\ntype AppStateUpdateTransform = (current: AppState) => AppState | AppStatePatch;\n\ntype DeepPartial<T> = {\n [K in keyof T]?: T[K] extends Array<infer U>\n ? U[]\n : T[K] extends object\n ? DeepPartial<T[K]>\n : T[K];\n};\n\nlet configuredUserDataDir: string | null = null;\nlet appStateCache: AppState | null = null;\nlet writeLock: Promise<void> = Promise.resolve();\nconst writeLockContext = new AsyncLocalStorage<boolean>();\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction clone<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nfunction resolveDefaultUserDataDir(): string {\n const home = process.env.HOME || process.env.USERPROFILE || os.homedir();\n if (!home) {\n throw new Error(\"Unable to resolve home directory for app state.\");\n }\n\n if (process.platform === \"darwin\") {\n return path.join(home, \"Library\", \"Application Support\", APP_NAME);\n }\n if (process.platform === \"win32\") {\n const appData = process.env.APPDATA;\n if (appData) {\n return path.join(appData, APP_NAME);\n }\n return path.join(home, \"AppData\", \"Roaming\", APP_NAME);\n }\n return path.join(home, \".config\", APP_NAME);\n}\n\nexport function getUserDataDir(): string {\n return configuredUserDataDir ?? resolveDefaultUserDataDir();\n}\n\nfunction resolveAppStatePath(): string {\n return path.join(getUserDataDir(), APP_STATE_FILE);\n}\n\nfunction createDefaultAppState(): AppState {\n return {\n schemaVersion: 1,\n autoRoll: {\n enabled: false,\n warningThreshold: 85,\n switchThreshold: 95,\n },\n app: {\n lastAppVersion: null,\n pendingUpdateVersion: null,\n lastProfileName: null,\n },\n license: {\n licenseKey: null,\n purchaseEmail: null,\n lastVerifiedAt: null,\n nextCheckAt: null,\n lastVerificationError: null,\n status: \"inactive\",\n signature: null,\n },\n providers: {\n selectedProviderId: \"openai\",\n defaultModel: null,\n defaultReasoningEffort: \"medium\",\n list: [],\n overridesByPath: {},\n },\n sandbox: {\n defaultMode: \"chat\",\n defaultApprovalPolicy: \"on-failure\",\n overridesByPath: {},\n },\n preferences: {\n excludeFolders: [],\n enableTaskCompleteBeep: true,\n preventSleepDuringTasks: true,\n chatHistoryScrollbackItems: CHAT_SCROLLBACK_DEFAULT,\n systemNotificationsEnabled: true,\n subagentSystemNotificationsEnabled: true,\n folderHistory: [],\n pinnedPaths: [],\n },\n runtimeSettings: {},\n workspaceSettingsByPath: {},\n conversationCategoriesByCwd: {},\n conversationCategoryAssignmentsByCwd: {},\n git: {\n commitMessagePrompt: DEFAULT_COMMIT_MESSAGE_PROMPT,\n commitMessageModelId: null,\n },\n agents: {\n multiAgentEnabled: false,\n maxThreads: 6,\n maxDepth: 1,\n },\n skills: {\n sources: [],\n installsBySlug: {},\n },\n sync: {\n lastPushAt: null,\n lastPullAt: null,\n lastError: null,\n remoteUpdatedAt: null,\n },\n telemetry: {\n installId: null,\n enabled: true,\n lastFlushAt: null,\n lastError: null,\n },\n profilesByName: {},\n migration: {\n status: \"pending\",\n startedAt: null,\n completedAt: null,\n localStorageImportedAt: null,\n lastError: null,\n },\n };\n}\n\nfunction asString(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction normalizeAppState(raw: unknown): AppState {\n const defaults = createDefaultAppState();\n if (!isRecord(raw)) {\n return defaults;\n }\n\n const next = deepMerge(defaults, raw as AppStatePatch);\n const merged = clone(next);\n\n merged.schemaVersion = 1;\n if (typeof merged.autoRoll.enabled !== \"boolean\") {\n merged.autoRoll.enabled = false;\n }\n if (!Number.isFinite(merged.autoRoll.warningThreshold)) {\n merged.autoRoll.warningThreshold = 85;\n }\n if (!Number.isFinite(merged.autoRoll.switchThreshold)) {\n merged.autoRoll.switchThreshold = 95;\n }\n if (merged.autoRoll.warningThreshold < 50 || merged.autoRoll.warningThreshold > 99) {\n merged.autoRoll.warningThreshold = 85;\n }\n if (merged.autoRoll.switchThreshold <= merged.autoRoll.warningThreshold || merged.autoRoll.switchThreshold > 100) {\n merged.autoRoll.switchThreshold = Math.min(100, Math.max(merged.autoRoll.warningThreshold + 1, 95));\n }\n merged.app.lastAppVersion = asString(merged.app.lastAppVersion);\n merged.app.pendingUpdateVersion = asString(merged.app.pendingUpdateVersion);\n merged.app.lastProfileName = asString(merged.app.lastProfileName);\n {\n const allowedAppKeys = new Set(Object.keys(defaults.app));\n for (const key of Object.keys(merged.app as Record<string, unknown>)) {\n if (!allowedAppKeys.has(key)) {\n delete (merged.app as Record<string, unknown>)[key];\n }\n }\n }\n\n merged.license.licenseKey = asString(merged.license.licenseKey);\n merged.license.purchaseEmail = asString(merged.license.purchaseEmail);\n merged.license.lastVerifiedAt = asString(merged.license.lastVerifiedAt);\n merged.license.nextCheckAt = asString(merged.license.nextCheckAt);\n merged.license.lastVerificationError = asString(merged.license.lastVerificationError);\n merged.license.signature = asString(merged.license.signature);\n if (![\"inactive\", \"active\", \"grace\", \"error\"].includes(merged.license.status)) {\n merged.license.status = \"inactive\";\n }\n\n if (!Array.isArray(merged.providers.list)) {\n merged.providers.list = [];\n }\n merged.providers.selectedProviderId = asString(merged.providers.selectedProviderId) ?? \"openai\";\n merged.providers.defaultModel = asString(merged.providers.defaultModel);\n if (![\"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"none\"].includes(merged.providers.defaultReasoningEffort)) {\n merged.providers.defaultReasoningEffort = \"medium\";\n }\n\n if (!isRecord(merged.providers.overridesByPath)) {\n merged.providers.overridesByPath = {};\n }\n if (!isRecord(merged.sandbox.overridesByPath)) {\n merged.sandbox.overridesByPath = {};\n }\n\n if (!Array.isArray(merged.preferences.excludeFolders)) {\n merged.preferences.excludeFolders = [];\n }\n if (typeof merged.preferences.enableTaskCompleteBeep !== \"boolean\") {\n merged.preferences.enableTaskCompleteBeep = true;\n }\n if (typeof merged.preferences.preventSleepDuringTasks !== \"boolean\") {\n merged.preferences.preventSleepDuringTasks = true;\n }\n merged.preferences.chatHistoryScrollbackItems = normalizeChatHistoryScrollbackItems(\n merged.preferences.chatHistoryScrollbackItems,\n );\n if (typeof merged.preferences.systemNotificationsEnabled !== \"boolean\") {\n merged.preferences.systemNotificationsEnabled = true;\n }\n if (typeof merged.preferences.subagentSystemNotificationsEnabled !== \"boolean\") {\n merged.preferences.subagentSystemNotificationsEnabled = true;\n }\n if (!Array.isArray(merged.preferences.folderHistory)) {\n merged.preferences.folderHistory = [];\n }\n if (!Array.isArray(merged.preferences.pinnedPaths)) {\n merged.preferences.pinnedPaths = [];\n }\n {\n const allowedPreferenceKeys = new Set(Object.keys(defaults.preferences));\n for (const key of Object.keys(merged.preferences as Record<string, unknown>)) {\n if (!allowedPreferenceKeys.has(key)) {\n delete (merged.preferences as Record<string, unknown>)[key];\n }\n }\n }\n\n if (!isRecord(merged.runtimeSettings)) {\n merged.runtimeSettings = {};\n }\n\n const legacyProjectSettingsByPath = isRecord(\n (raw as Record<string, unknown>).projectSettingsByPath,\n )\n ? ((raw as Record<string, unknown>)\n .projectSettingsByPath as AppState[\"workspaceSettingsByPath\"])\n : null;\n if (!isRecord(merged.workspaceSettingsByPath)) {\n merged.workspaceSettingsByPath = {};\n }\n if (legacyProjectSettingsByPath) {\n merged.workspaceSettingsByPath = {\n ...legacyProjectSettingsByPath,\n ...merged.workspaceSettingsByPath,\n };\n }\n delete (merged as Record<string, unknown>).projectSettingsByPath;\n if (!isRecord(merged.conversationCategoriesByCwd)) {\n merged.conversationCategoriesByCwd = {};\n }\n if (!isRecord(merged.conversationCategoryAssignmentsByCwd)) {\n merged.conversationCategoryAssignmentsByCwd = {};\n }\n if (!isRecord(merged.git)) {\n merged.git = clone(defaults.git);\n }\n merged.git.commitMessagePrompt =\n normalizeCommitMessagePrompt(merged.git.commitMessagePrompt) ??\n DEFAULT_COMMIT_MESSAGE_PROMPT;\n merged.git.commitMessageModelId = asString(merged.git.commitMessageModelId);\n\n if (!isRecord(merged.agents)) {\n merged.agents = clone(defaults.agents);\n }\n if (typeof merged.agents.multiAgentEnabled !== \"boolean\") {\n merged.agents.multiAgentEnabled = defaults.agents.multiAgentEnabled;\n }\n if (!Number.isFinite(merged.agents.maxThreads)) {\n merged.agents.maxThreads = defaults.agents.maxThreads;\n }\n merged.agents.maxThreads = Math.max(1, Math.min(12, Math.round(merged.agents.maxThreads)));\n if (!Number.isFinite(merged.agents.maxDepth)) {\n merged.agents.maxDepth = defaults.agents.maxDepth;\n }\n merged.agents.maxDepth = Math.max(1, Math.min(4, Math.round(merged.agents.maxDepth)));\n\n if (!isRecord(merged.skills)) {\n merged.skills = clone(defaults.skills);\n }\n if (!Array.isArray(merged.skills.sources)) {\n merged.skills.sources = [];\n }\n if (!isRecord(merged.skills.installsBySlug)) {\n merged.skills.installsBySlug = {};\n }\n\n if (!isRecord(merged.sync)) {\n merged.sync = clone(defaults.sync);\n }\n merged.sync.lastPushAt = asString(merged.sync.lastPushAt);\n merged.sync.lastPullAt = asString(merged.sync.lastPullAt);\n merged.sync.lastError = asString(merged.sync.lastError);\n merged.sync.remoteUpdatedAt = asString(merged.sync.remoteUpdatedAt);\n\n if (!isRecord(merged.telemetry)) {\n merged.telemetry = clone(defaults.telemetry);\n }\n merged.telemetry.installId = asString(merged.telemetry.installId);\n if (typeof merged.telemetry.enabled !== \"boolean\") {\n merged.telemetry.enabled = true;\n }\n merged.telemetry.lastFlushAt = asString(merged.telemetry.lastFlushAt);\n merged.telemetry.lastError = asString(merged.telemetry.lastError);\n\n if (!isRecord(merged.profilesByName)) {\n merged.profilesByName = {};\n }\n\n if (!isRecord(merged.migration)) {\n merged.migration = clone(defaults.migration);\n }\n if (![\"pending\", \"pending_local_storage\", \"complete\"].includes(merged.migration.status)) {\n merged.migration.status = \"pending\";\n }\n merged.migration.startedAt = asString(merged.migration.startedAt);\n merged.migration.completedAt = asString(merged.migration.completedAt);\n merged.migration.localStorageImportedAt = asString(merged.migration.localStorageImportedAt);\n merged.migration.lastError = asString(merged.migration.lastError);\n\n return merged;\n}\n\nfunction deepMerge<T>(base: T, patch: DeepPartial<T>): T {\n if (!isRecord(base) || !isRecord(patch)) {\n return clone((patch as T) ?? base);\n }\n\n const next: Record<string, unknown> = { ...(base as Record<string, unknown>) };\n for (const [key, patchValue] of Object.entries(patch)) {\n if (patchValue === undefined) {\n continue;\n }\n\n const currentValue = next[key];\n if (Array.isArray(patchValue)) {\n next[key] = clone(patchValue);\n continue;\n }\n\n if (isRecord(currentValue) && isRecord(patchValue)) {\n next[key] = deepMerge(currentValue, patchValue as DeepPartial<typeof currentValue>);\n continue;\n }\n\n next[key] = clone(patchValue);\n }\n\n return next as T;\n}\n\nasync function writeAtomic(filePath: string, contents: string): Promise<void> {\n const dir = path.dirname(filePath);\n const base = path.basename(filePath);\n const token = `${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}`;\n const tempPath = path.join(dir, `${base}.${token}.tmp`);\n\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(tempPath, contents, \"utf8\");\n try {\n await fs.rename(tempPath, filePath);\n } finally {\n await fs.rm(tempPath, { force: true }).catch(() => undefined);\n }\n}\n\nasync function writeAppStateToDisk(state: AppState): Promise<void> {\n const filePath = resolveAppStatePath();\n await writeAtomic(filePath, `${JSON.stringify(state, null, 2)}\\n`);\n}\n\nasync function readAppStateFromDisk(): Promise<AppState | null> {\n const filePath = resolveAppStatePath();\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n return normalizeAppState(JSON.parse(raw) as unknown);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n}\n\nasync function ensureInitialized(): Promise<AppState> {\n if (appStateCache) {\n return appStateCache;\n }\n\n const filePath = resolveAppStatePath();\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n\n const loaded = await readAppStateFromDisk();\n const normalized = loaded ?? normalizeAppState(null);\n appStateCache = normalized;\n\n if (loaded === null) {\n await writeAppStateToDisk(normalized);\n }\n\n return appStateCache;\n}\n\nasync function withWriteLock<T>(task: () => Promise<T>): Promise<T> {\n if (writeLockContext.getStore()) {\n return task();\n }\n\n const previous = writeLock;\n let release: (() => void) | undefined;\n writeLock = new Promise<void>(resolve => {\n release = resolve;\n });\n\n await previous;\n try {\n return await writeLockContext.run(true, task);\n } finally {\n if (release) {\n release();\n }\n }\n}\n\nexport async function initializeAppState(userDataDir: string): Promise<AppState> {\n configuredUserDataDir = userDataDir;\n const state = await ensureInitialized();\n return clone(state);\n}\n\nexport async function getAppState(): Promise<AppState> {\n const state = await ensureInitialized();\n return clone(state);\n}\n\nexport async function updateAppState(\n transform: AppStateUpdateTransform,\n options: AppStateUpdateOptions = {},\n): Promise<AppState> {\n const mode = options.mode ?? \"patch\";\n const allowBeforeMigrationComplete = options.allowBeforeMigrationComplete === true;\n\n return withWriteLock(async () => {\n const current = (await readAppStateFromDisk()) ?? (await ensureInitialized());\n appStateCache = current;\n if (!allowBeforeMigrationComplete && current.migration.status !== \"complete\") {\n throw new Error(\"Storage migration is not complete yet.\");\n }\n\n const transformed = transform(clone(current));\n const nextState = mode === \"replace\"\n ? normalizeAppState(transformed)\n : normalizeAppState(deepMerge(current, transformed as AppStatePatch));\n await writeAppStateToDisk(nextState);\n appStateCache = nextState;\n return clone(nextState);\n });\n}\n\nexport async function patchAppState(patch: AppStatePatch): Promise<AppState> {\n return updateAppState(() => patch, {\n mode: \"patch\",\n allowBeforeMigrationComplete: false,\n });\n}\n","export const CHAT_SCROLLBACK_DEFAULT = 200;\nexport const CHAT_SCROLLBACK_MIN = 50;\nexport const CHAT_SCROLLBACK_MAX = 5000;\nexport const CHAT_SCROLLBACK_PRESETS = [200, 500, 1000, 2000, 5000] as const;\n\nexport function clampChatScrollbackItems(value: number): number {\n if (!Number.isFinite(value)) {\n return CHAT_SCROLLBACK_DEFAULT;\n }\n const rounded = Math.round(value);\n return Math.max(CHAT_SCROLLBACK_MIN, Math.min(CHAT_SCROLLBACK_MAX, rounded));\n}\n\nexport function isChatScrollbackPreset(value: number): boolean {\n return (CHAT_SCROLLBACK_PRESETS as readonly number[]).includes(value);\n}\n\nexport function normalizeChatHistoryScrollbackItems(value: unknown): number | null {\n if (value === null) {\n return null;\n }\n\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return clampChatScrollbackItems(value);\n }\n\n if (typeof value === \"string\") {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) {\n return clampChatScrollbackItems(parsed);\n }\n }\n\n return CHAT_SCROLLBACK_DEFAULT;\n}\n\n","export const DEFAULT_COMMIT_MESSAGE_PROMPT = `Generate a concise git commit message for the following changes. Follow conventional commit format (e.g., feat:, fix:, refactor:, docs:, etc.). Keep the summary line under 72 characters. Only output the commit message, nothing else.\n\nChanges:\n{diff}`;\n\nconst DIFF_PLACEHOLDER = \"{diff}\";\n\nfunction normalizeLineEndings(value: string): string {\n return value.replace(/\\r\\n/g, \"\\n\");\n}\n\nexport function normalizeCommitMessagePrompt(value: string | null | undefined): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const normalized = normalizeLineEndings(value).trim();\n return normalized.length > 0 ? normalized : null;\n}\n\nexport function buildCommitMessagePrompt(\n diff: string,\n template?: string | null,\n): string {\n const normalizedDiff = normalizeLineEndings(diff).trim();\n if (!normalizedDiff) {\n return \"\";\n }\n\n const normalizedTemplate = normalizeCommitMessagePrompt(template);\n const base = normalizedTemplate ?? DEFAULT_COMMIT_MESSAGE_PROMPT;\n\n if (base.includes(DIFF_PLACEHOLDER)) {\n return base.split(DIFF_PLACEHOLDER).join(normalizedDiff);\n }\n\n return `${base}\\n\\nChanges:\\n${normalizedDiff}`;\n}\n\n","import { normalizeAutoRollSettings, type AutoRollSettings } from \"./auto-roll-settings\";\nimport { getAppState, patchAppState, type AppState } from \"./app-state\";\n\ntype LicenseStatusCode = \"inactive\" | \"active\" | \"grace\" | \"error\";\n\ninterface StoredLicense {\n licenseKey?: string | null;\n purchaseEmail?: string | null;\n lastVerifiedAt?: string | null;\n nextCheckAt?: string | null;\n lastVerificationError?: string | null;\n status?: LicenseStatusCode;\n signature?: string | null;\n}\n\ninterface CodexSettings {\n license?: StoredLicense | null;\n lastProfileName?: string | null;\n autoRoll?: AutoRollSettings | null;\n lastAppVersion?: string | null;\n pendingUpdateVersion?: string | null;\n}\n\nfunction toCodexSettings(state: AppState): CodexSettings {\n const license = state.license.licenseKey\n ? {\n licenseKey: state.license.licenseKey,\n purchaseEmail: state.license.purchaseEmail,\n lastVerifiedAt: state.license.lastVerifiedAt,\n nextCheckAt: state.license.nextCheckAt,\n lastVerificationError: state.license.lastVerificationError,\n status: state.license.status,\n signature: state.license.signature,\n }\n : null;\n\n const autoRoll = normalizeAutoRollSettings(state.autoRoll);\n\n return {\n ...(license ? { license } : {}),\n ...(state.app.lastProfileName ? { lastProfileName: state.app.lastProfileName } : {}),\n ...(autoRoll ? { autoRoll } : {}),\n ...(state.app.lastAppVersion ? { lastAppVersion: state.app.lastAppVersion } : {}),\n ...(state.app.pendingUpdateVersion ? { pendingUpdateVersion: state.app.pendingUpdateVersion } : {}),\n };\n}\n\nfunction asString(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction parseStoredLicense(raw?: unknown): StoredLicense | null {\n if (!isRecord(raw)) {\n return null;\n }\n\n const statusCandidate = asString(raw.status);\n const status = [\"inactive\", \"active\", \"grace\", \"error\"].includes(statusCandidate ?? \"\")\n ? (statusCandidate as LicenseStatusCode)\n : undefined;\n\n const license: StoredLicense = {\n licenseKey: asString(raw.licenseKey ?? raw.license_key),\n purchaseEmail: asString(raw.purchaseEmail ?? raw.purchase_email),\n lastVerifiedAt: asString(raw.lastVerifiedAt ?? raw.last_verified_at),\n nextCheckAt: asString(raw.nextCheckAt ?? raw.next_check_at),\n lastVerificationError: asString(raw.lastVerificationError ?? raw.last_verification_error),\n status,\n signature: asString(raw.signature),\n };\n\n const hasValue = Boolean(\n license.licenseKey ||\n license.purchaseEmail ||\n license.lastVerifiedAt ||\n license.nextCheckAt ||\n license.lastVerificationError ||\n license.status,\n );\n\n return hasValue ? license : null;\n}\n\nfunction parseAutoRoll(raw: unknown): AutoRollSettings | null {\n if (!raw) {\n return null;\n }\n try {\n return normalizeAutoRollSettings(raw as Partial<AutoRollSettings>);\n } catch {\n return null;\n }\n}\n\nexport async function getCodexSettings(): Promise<CodexSettings> {\n const state = await getAppState();\n return toCodexSettings(state);\n}\n\nexport async function setCodexSettings(settings: CodexSettings): Promise<void> {\n const autoRoll = parseAutoRoll(settings.autoRoll);\n const license = parseStoredLicense(settings.license);\n await patchAppState({\n app: {\n lastProfileName: asString(settings.lastProfileName),\n lastAppVersion: asString(settings.lastAppVersion),\n pendingUpdateVersion: asString(settings.pendingUpdateVersion),\n },\n autoRoll: autoRoll\n ? {\n enabled: autoRoll.enabled,\n warningThreshold: autoRoll.warningThreshold,\n switchThreshold: autoRoll.switchThreshold,\n }\n : undefined,\n license: license\n ? {\n licenseKey: license.licenseKey ?? null,\n purchaseEmail: license.purchaseEmail ?? null,\n lastVerifiedAt: license.lastVerifiedAt ?? null,\n nextCheckAt: license.nextCheckAt ?? null,\n lastVerificationError: license.lastVerificationError ?? null,\n status: license.status ?? \"inactive\",\n signature: license.signature ?? null,\n }\n : {\n licenseKey: null,\n purchaseEmail: null,\n lastVerifiedAt: null,\n nextCheckAt: null,\n lastVerificationError: null,\n status: \"inactive\",\n signature: null,\n },\n });\n}\n\nexport async function getLastProfileName(): Promise<string | null> {\n const state = await getAppState();\n return asString(state.app.lastProfileName);\n}\n\nexport async function persistLastProfileName(profileName: string | null): Promise<void> {\n await patchAppState({\n app: {\n lastProfileName: asString(profileName),\n },\n });\n}\n\nexport async function getStoredLicense(): Promise<StoredLicense | null> {\n const state = await getAppState();\n return parseStoredLicense(state.license);\n}\n\nexport async function persistLicense(license: StoredLicense | null): Promise<void> {\n const parsed = parseStoredLicense(license);\n await patchAppState({\n license: parsed\n ? {\n licenseKey: parsed.licenseKey ?? null,\n purchaseEmail: parsed.purchaseEmail ?? null,\n lastVerifiedAt: parsed.lastVerifiedAt ?? null,\n nextCheckAt: parsed.nextCheckAt ?? null,\n lastVerificationError: parsed.lastVerificationError ?? null,\n status: parsed.status ?? \"inactive\",\n signature: parsed.signature ?? null,\n }\n : {\n licenseKey: null,\n purchaseEmail: null,\n lastVerifiedAt: null,\n nextCheckAt: null,\n lastVerificationError: null,\n status: \"inactive\",\n signature: null,\n },\n });\n}\n\nexport async function getStoredAutoRollSettings(): Promise<AutoRollSettings | null> {\n const state = await getAppState();\n return normalizeAutoRollSettings(state.autoRoll);\n}\n\nexport async function persistAutoRollSettings(settings: AutoRollSettings | null): Promise<void> {\n const normalized = normalizeAutoRollSettings(settings ?? undefined);\n await patchAppState({\n autoRoll: {\n enabled: normalized.enabled,\n warningThreshold: normalized.warningThreshold,\n switchThreshold: normalized.switchThreshold,\n },\n });\n}\n\nexport async function getStoredAppVersion(): Promise<string | null> {\n const state = await getAppState();\n return asString(state.app.lastAppVersion);\n}\n\nexport async function persistAppVersion(version: string | null): Promise<void> {\n await patchAppState({\n app: {\n lastAppVersion: asString(version),\n },\n });\n}\n\nexport async function getPendingUpdateVersion(): Promise<string | null> {\n const state = await getAppState();\n return asString(state.app.pendingUpdateVersion);\n}\n\nexport async function persistPendingUpdateVersion(version: string | null): Promise<void> {\n await patchAppState({\n app: {\n pendingUpdateVersion: asString(version),\n },\n });\n}\n\nexport async function readCodexSettingsJsonRaw(): Promise<Record<string, unknown>> {\n const state = await getAppState();\n return {\n lastProfileName: state.app.lastProfileName,\n lastAppVersion: state.app.lastAppVersion,\n pendingUpdateVersion: state.app.pendingUpdateVersion,\n autoRoll: state.autoRoll,\n license: state.license,\n providers: state.providers.list,\n selectedProviderId: state.providers.selectedProviderId,\n defaultModel: state.providers.defaultModel,\n defaultReasoningEffort: state.providers.defaultReasoningEffort,\n selectionsByCwd: state.providers.overridesByPath,\n mode: state.sandbox.defaultMode,\n approvalPolicy: state.sandbox.defaultApprovalPolicy,\n sandboxSelectionsByCwd: state.sandbox.overridesByPath,\n excludeFolders: state.preferences.excludeFolders,\n enableTaskCompleteBeep: state.preferences.enableTaskCompleteBeep,\n preventSleepDuringTasks: state.preferences.preventSleepDuringTasks,\n systemNotificationsEnabled: state.preferences.systemNotificationsEnabled,\n subagentSystemNotificationsEnabled:\n state.preferences.subagentSystemNotificationsEnabled,\n folderHistory: state.preferences.folderHistory,\n pinnedPaths: state.preferences.pinnedPaths,\n workspaceSettingsByPath: state.workspaceSettingsByPath,\n // Legacy compatibility for older consumers.\n projectSettingsByPath: state.workspaceSettingsByPath,\n categoriesByCwd: state.conversationCategoriesByCwd,\n conversationCategoryByCwd: state.conversationCategoryAssignmentsByCwd,\n git: state.git,\n agents: state.agents,\n sync: state.sync,\n };\n}\n\nexport async function writeCodexSettingsJsonRaw(payload: Record<string, unknown> | null | undefined): Promise<void> {\n if (!isRecord(payload)) {\n return;\n }\n\n const autoRoll = parseAutoRoll(payload.autoRoll ?? payload.auto_roll);\n const license = parseStoredLicense(payload.license);\n\n await patchAppState({\n app: {\n lastProfileName: asString(payload.lastProfileName ?? payload.last_profile_name),\n lastAppVersion: asString(payload.lastAppVersion ?? payload.last_app_version),\n pendingUpdateVersion: asString(payload.pendingUpdateVersion ?? payload.pending_update_version),\n },\n autoRoll: autoRoll\n ? {\n enabled: autoRoll.enabled,\n warningThreshold: autoRoll.warningThreshold,\n switchThreshold: autoRoll.switchThreshold,\n }\n : undefined,\n license: license\n ? {\n licenseKey: license.licenseKey ?? null,\n purchaseEmail: license.purchaseEmail ?? null,\n lastVerifiedAt: license.lastVerifiedAt ?? null,\n nextCheckAt: license.nextCheckAt ?? null,\n lastVerificationError: license.lastVerificationError ?? null,\n status: license.status ?? \"inactive\",\n signature: license.signature ?? null,\n }\n : undefined,\n providers: {\n list: Array.isArray(payload.providers)\n ? (payload.providers as AppState[\"providers\"][\"list\"])\n : undefined,\n selectedProviderId: asString(payload.selectedProviderId) ?? undefined,\n defaultModel: asString(payload.defaultModel ?? payload.selectedModel),\n defaultReasoningEffort:\n typeof payload.defaultReasoningEffort === \"string\"\n ? (payload.defaultReasoningEffort as AppState[\"providers\"][\"defaultReasoningEffort\"])\n : typeof payload.reasoningEffort === \"string\"\n ? (payload.reasoningEffort as AppState[\"providers\"][\"defaultReasoningEffort\"])\n : undefined,\n overridesByPath:\n isRecord(payload.selectionsByCwd) ? (payload.selectionsByCwd as AppState[\"providers\"][\"overridesByPath\"]) : undefined,\n },\n sandbox: {\n defaultMode: asString(payload.mode ?? payload.defaultMode) ?? undefined,\n defaultApprovalPolicy:\n asString(payload.approvalPolicy ?? payload.defaultApprovalPolicy) ?? undefined,\n overridesByPath:\n isRecord(payload.sandboxSelectionsByCwd)\n ? (payload.sandboxSelectionsByCwd as AppState[\"sandbox\"][\"overridesByPath\"])\n : undefined,\n },\n preferences: {\n excludeFolders: Array.isArray(payload.excludeFolders)\n ? (payload.excludeFolders as string[])\n : undefined,\n enableTaskCompleteBeep:\n typeof payload.enableTaskCompleteBeep === \"boolean\"\n ? payload.enableTaskCompleteBeep\n : undefined,\n preventSleepDuringTasks:\n typeof payload.preventSleepDuringTasks === \"boolean\"\n ? payload.preventSleepDuringTasks\n : undefined,\n systemNotificationsEnabled:\n typeof payload.systemNotificationsEnabled === \"boolean\"\n ? payload.systemNotificationsEnabled\n : undefined,\n subagentSystemNotificationsEnabled:\n typeof payload.subagentSystemNotificationsEnabled === \"boolean\"\n ? payload.subagentSystemNotificationsEnabled\n : undefined,\n folderHistory: Array.isArray(payload.folderHistory)\n ? (payload.folderHistory as AppState[\"preferences\"][\"folderHistory\"])\n : undefined,\n pinnedPaths: Array.isArray(payload.pinnedPaths)\n ? (payload.pinnedPaths as string[])\n : undefined,\n },\n workspaceSettingsByPath: isRecord(payload.workspaceSettingsByPath)\n ? (payload.workspaceSettingsByPath as AppState[\"workspaceSettingsByPath\"])\n : isRecord(payload.projectSettingsByPath)\n ? (payload.projectSettingsByPath as AppState[\"workspaceSettingsByPath\"])\n : undefined,\n conversationCategoriesByCwd: isRecord(payload.categoriesByCwd)\n ? (payload.categoriesByCwd as AppState[\"conversationCategoriesByCwd\"])\n : undefined,\n conversationCategoryAssignmentsByCwd: isRecord(payload.conversationCategoryByCwd)\n ? (payload.conversationCategoryByCwd as AppState[\"conversationCategoryAssignmentsByCwd\"])\n : undefined,\n git: isRecord(payload.git)\n ? (payload.git as AppState[\"git\"])\n : undefined,\n agents: isRecord(payload.agents)\n ? (payload.agents as AppState[\"agents\"])\n : undefined,\n sync: isRecord(payload.sync) ? (payload.sync as AppState[\"sync\"]) : undefined,\n });\n}\n\nexport type { StoredLicense, LicenseStatusCode };\nexport type { AutoRollSettings } from \"./auto-roll-settings\";\n","const isTestEnv =\n process.env.NODE_ENV === 'test' ||\n process.env.VITEST === 'true' ||\n process.env.VITEST === '1';\n\nfunction isMocked(fn: unknown): boolean {\n return Boolean(fn && typeof fn === 'function' && 'mock' in (fn as Record<string, unknown>));\n}\n\nexport function logWarn(...args: Parameters<typeof console.warn>): void {\n if (isTestEnv && !isMocked(console.warn)) {\n return;\n }\n console.warn(...args);\n}\n\nexport function logError(...args: Parameters<typeof console.error>): void {\n if (isTestEnv && !isMocked(console.error)) {\n return;\n }\n console.error(...args);\n}\n\nexport function logInfo(...args: Parameters<typeof console.warn>): void {\n if (isTestEnv && !isMocked(console.warn)) {\n return;\n }\n console.warn(...args);\n}\n","import crypto from 'node:crypto';\nimport { persistLicense, getStoredLicense, type StoredLicense } from './codex-settings';\nimport { getLicenseSecret } from './license-secret';\nimport { getActiveOffer, buildCheckoutUrl } from './offer-config';\n\nconst offer = getActiveOffer();\nconst PRODUCT_PERMALINK = offer.productPermalink;\nconst PRODUCT_ID = '3_CcyVEXt2FOMiEpPx8xzw==';\nconst PRODUCT_URL = buildCheckoutUrl(offer);\nconst LICENSE_PRICE_DISPLAY = offer.isActive ? offer.salePriceDisplay : offer.basePriceDisplay;\nconst BASE_PRICE_DISPLAY = offer.basePriceDisplay;\nconst PROMO_CODE = offer.couponCode;\nconst PROMO_PERCENT = offer.discountPercent;\nconst PROMO_ACTIVE = offer.isActive;\nconst LICENSE_MAX_USES = 5;\nconst FREE_PROFILE_LIMIT = 2;\nconst LICENSE_REFRESH_INTERVAL_MS = 5 * 60 * 1000;\nconst MAX_NEXT_CHECK_MS = 60 * 60 * 1000;\nconst GRACE_MAX_AGE_MS = 3 * 60 * 60 * 1000;\n\ntype LicenseTier = 'free' | 'pro';\ntype LicenseState = 'inactive' | 'active' | 'grace' | 'verifying' | 'error';\n\ninterface LicenseStatus {\n tier: LicenseTier;\n state: LicenseState;\n isPro: boolean;\n profileLimit: number | null;\n profilesRemaining: number | null;\n purchaseEmail: string | null;\n maskedLicenseKey: string | null;\n lastVerifiedAt: string | null;\n nextCheckAt: string | null;\n message: string | null;\n error: string | null;\n productPermalink: string;\n productUrl: string;\n productId: string;\n priceDisplay: string;\n basePriceDisplay: string;\n promoCode: string | null;\n promoPercent: number | null;\n maxDevices: number;\n}\n\ninterface GumroadLicenseResponse {\n success: boolean;\n message?: string;\n uses?: number;\n purchase?: {\n id: string;\n email: string;\n product_id?: string;\n product_permalink?: string;\n refunded?: boolean;\n chargebacked?: boolean;\n subscription_cancelled?: boolean;\n subscription_failed?: boolean;\n license_disabled?: boolean;\n variants?: string;\n };\n license_disabled?: boolean;\n}\n\ntype VerificationMode = 'activation' | 'refresh';\n\nclass LicenseError extends Error {\n readonly code: 'network' | 'invalid' | 'revoked';\n\n constructor(message: string, code: 'network' | 'invalid' | 'revoked') {\n super(message);\n this.name = 'LicenseError';\n this.code = code;\n }\n}\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction maskLicenseKey(key: string | null | undefined): string | null {\n if (!key || typeof key !== 'string') {\n return null;\n }\n\n const trimmed = key.trim();\n if (trimmed.length <= 4) {\n return '••••';\n }\n\n const visible = trimmed.slice(-4);\n return `••••${visible}`;\n}\n\nfunction resolveProfilesRemaining(limit: number | null, currentProfiles: number): number | null {\n if (typeof limit !== 'number') {\n return null;\n }\n return Math.max(0, limit - currentProfiles);\n}\n\nfunction determineTierFromStored(stored: StoredLicense | null): LicenseTier {\n if (!stored || !stored.licenseKey) {\n return 'free';\n }\n\n if (stored.status === 'inactive') {\n return 'free';\n }\n\n return 'pro';\n}\n\nfunction licenseSignaturePayload(license: StoredLicense): string {\n const payload = {\n licenseKey: license.licenseKey ?? null,\n purchaseEmail: license.purchaseEmail ?? null,\n lastVerifiedAt: license.lastVerifiedAt ?? null,\n nextCheckAt: license.nextCheckAt ?? null,\n lastVerificationError: license.lastVerificationError ?? null,\n status: license.status ?? null,\n };\n return JSON.stringify(payload);\n}\n\nfunction signLicense(license: StoredLicense, secret: string): string {\n return crypto.createHmac('sha256', secret).update(licenseSignaturePayload(license)).digest('hex');\n}\n\nfunction withSignature(license: StoredLicense, secret: string): StoredLicense {\n return {\n ...license,\n signature: signLicense(license, secret),\n };\n}\n\nfunction isSignatureValid(license: StoredLicense, secret: string): boolean {\n if (!license.signature) {\n return false;\n }\n const expected = signLicense(license, secret);\n return expected === license.signature;\n}\n\nasync function requestGumroadVerify(licenseKey: string, mode: VerificationMode): Promise<GumroadLicenseResponse> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 10_000);\n\n try {\n const body = new URLSearchParams({\n product_permalink: PRODUCT_PERMALINK,\n product_id: PRODUCT_ID,\n license_key: licenseKey,\n increment_uses_count: mode === 'activation' ? 'true' : 'false',\n });\n\n const response = await fetch('https://api.gumroad.com/v2/licenses/verify', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => null);\n const message = errorText\n ? `License verification failed (${response.status}): ${errorText}`\n : `License verification failed (${response.status}).`;\n throw new LicenseError(message, 'network');\n }\n\n const json = (await response.json()) as GumroadLicenseResponse;\n return json;\n } catch (error) {\n if (error instanceof LicenseError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n throw new LicenseError('License verification timed out.', 'network');\n }\n\n throw new LicenseError(\n error instanceof Error ? error.message : 'Unable to reach Gumroad for license verification.',\n 'network',\n );\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction normalizeVerificationResult(response: GumroadLicenseResponse): { email: string | null } {\n if (!response.success) {\n const message = response.message ?? 'License key is invalid.';\n throw new LicenseError(message, 'invalid');\n }\n\n if (!response.purchase) {\n throw new LicenseError('License verification response was incomplete.', 'network');\n }\n\n if (response.purchase.chargebacked || response.purchase.refunded || response.license_disabled) {\n throw new LicenseError('This license has been revoked or refunded.', 'revoked');\n }\n\n if (response.purchase.subscription_cancelled || response.purchase.subscription_failed) {\n throw new LicenseError('This license subscription is no longer active.', 'revoked');\n }\n\n const email = response.purchase.email ?? null;\n return { email };\n}\n\nfunction ensureWithinUseLimit(response: GumroadLicenseResponse): void {\n if (!response.success) {\n return;\n }\n\n if (typeof response.uses !== 'number') {\n return;\n }\n\n if (response.uses > LICENSE_MAX_USES) {\n throw new LicenseError(\n `This license has reached the activation limit (${LICENSE_MAX_USES}). Contact support to move it to another device.`,\n 'invalid',\n );\n }\n}\n\nfunction toLicenseStatus(stored: StoredLicense | null, overrides: Partial<LicenseStatus> = {}): LicenseStatus {\n const tier = determineTierFromStored(stored);\n const isPro = tier === 'pro';\n\n const state: LicenseState =\n stored && stored.status\n ? stored.status\n : isPro\n ? 'active'\n : 'inactive';\n\n const base: LicenseStatus = {\n tier,\n state,\n isPro,\n profileLimit: isPro ? null : FREE_PROFILE_LIMIT,\n profilesRemaining: null,\n purchaseEmail: stored?.purchaseEmail ?? null,\n maskedLicenseKey: maskLicenseKey(stored?.licenseKey),\n lastVerifiedAt: stored?.lastVerifiedAt ?? null,\n nextCheckAt: stored?.nextCheckAt ?? null,\n message: null,\n error: stored?.lastVerificationError ?? null,\n productUrl: PRODUCT_URL,\n productId: PRODUCT_ID,\n productPermalink: PRODUCT_PERMALINK,\n priceDisplay: LICENSE_PRICE_DISPLAY,\n basePriceDisplay: BASE_PRICE_DISPLAY,\n promoCode: PROMO_ACTIVE ? PROMO_CODE : null,\n promoPercent: PROMO_ACTIVE ? PROMO_PERCENT : null,\n maxDevices: LICENSE_MAX_USES,\n };\n\n return { ...base, ...overrides };\n}\n\nfunction parseTimestamp(value: string | null | undefined): number | null {\n if (typeof value !== 'string' || value.trim() === '') {\n return null;\n }\n\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? null : parsed;\n}\n\nclass LicenseService {\n private cache: LicenseStatus | null = null;\n private refreshPromise: Promise<void> | null = null;\n private verificationPromise: Promise<LicenseStatus> | null = null;\n\n async getCachedStatus(): Promise<LicenseStatus> {\n return this.getStatus();\n }\n\n async getStatus(options: { forceRefresh?: boolean } = {}): Promise<LicenseStatus> {\n const forceRefresh = Boolean(options.forceRefresh);\n const secret = await getLicenseSecret();\n const stored = await getStoredLicense();\n\n if (!stored?.licenseKey) {\n const status = toLicenseStatus(null);\n this.cache = status;\n return status;\n }\n\n const now = Date.now();\n const nextCheckTs = parseTimestamp(stored.nextCheckAt);\n const lastVerifiedTs = parseTimestamp(stored.lastVerifiedAt);\n const graceStale =\n (stored.status === 'grace' || stored.status === 'error') &&\n (lastVerifiedTs === null || lastVerifiedTs + GRACE_MAX_AGE_MS < now);\n\n let workingStored: StoredLicense = { ...stored };\n const signatureValid = isSignatureValid(workingStored, secret);\n\n let cappedNextCheckTs = nextCheckTs;\n\n if (nextCheckTs !== null && nextCheckTs > now + MAX_NEXT_CHECK_MS) {\n cappedNextCheckTs = now;\n const updated = {\n ...workingStored,\n nextCheckAt: new Date(cappedNextCheckTs).toISOString(),\n };\n const signed = withSignature(updated, secret);\n workingStored = signed;\n await persistLicense(signed);\n }\n\n const tampered = Boolean(workingStored.licenseKey) && !signatureValid;\n\n const cached = tampered\n ? toLicenseStatus(null, {\n state: 'verifying',\n message: 'License data changed, rechecking.',\n error: 'Untrusted license data.',\n })\n : toLicenseStatus(workingStored);\n this.cache = cached;\n\n const shouldRefresh =\n forceRefresh || graceStale || tampered || cappedNextCheckTs === null || cappedNextCheckTs <= now;\n\n if (!shouldRefresh) {\n return cached;\n }\n\n if (this.verificationPromise && !forceRefresh) {\n return this.verificationPromise;\n }\n\n const verify = async (): Promise<LicenseStatus> => {\n try {\n const result = await requestGumroadVerify(workingStored.licenseKey!, 'refresh');\n ensureWithinUseLimit(result);\n const normalized = normalizeVerificationResult(result);\n const updated: StoredLicense = {\n licenseKey: workingStored.licenseKey,\n purchaseEmail: normalized.email,\n lastVerifiedAt: nowIso(),\n nextCheckAt: new Date(Date.now() + LICENSE_REFRESH_INTERVAL_MS).toISOString(),\n status: 'active',\n lastVerificationError: null,\n };\n\n const signed = withSignature(updated, secret);\n\n await persistLicense(signed);\n const status = toLicenseStatus(signed);\n this.cache = status;\n return status;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'License verification failed.';\n\n if (error instanceof LicenseError && error.code === 'network') {\n const fallbackStored: StoredLicense = withSignature(\n {\n ...workingStored,\n status: tampered ? 'inactive' : workingStored.status === 'inactive' ? 'inactive' : 'grace',\n lastVerificationError: message,\n nextCheckAt: new Date(Date.now() + LICENSE_REFRESH_INTERVAL_MS).toISOString(),\n },\n secret,\n );\n await persistLicense(fallbackStored);\n const fallback = toLicenseStatus(fallbackStored, {\n state: fallbackStored.status ?? 'grace',\n error: message,\n });\n this.cache = fallback;\n return fallback;\n }\n\n const fallbackStored: StoredLicense = withSignature({\n licenseKey: workingStored.licenseKey,\n purchaseEmail: workingStored.purchaseEmail ?? null,\n lastVerifiedAt: workingStored.lastVerifiedAt ?? null,\n nextCheckAt: null,\n status: 'inactive',\n lastVerificationError: message,\n }, secret);\n await persistLicense(fallbackStored);\n const fallback = toLicenseStatus(fallbackStored, { error: message });\n this.cache = fallback;\n return fallback;\n }\n };\n\n this.verificationPromise = verify();\n try {\n return await this.verificationPromise;\n } finally {\n this.verificationPromise = null;\n }\n }\n\n async activate(licenseKey: string): Promise<LicenseStatus> {\n const trimmed = licenseKey.trim();\n if (!trimmed) {\n throw new Error('License key is required.');\n }\n\n const secret = await getLicenseSecret();\n const digest = crypto.createHash('sha256').update(trimmed).digest('hex');\n\n const result = await requestGumroadVerify(trimmed, 'activation');\n ensureWithinUseLimit(result);\n const normalized = normalizeVerificationResult(result);\n const stored: StoredLicense = {\n licenseKey: trimmed,\n purchaseEmail: normalized.email,\n lastVerifiedAt: nowIso(),\n nextCheckAt: new Date(Date.now() + LICENSE_REFRESH_INTERVAL_MS).toISOString(),\n status: 'active',\n lastVerificationError: null,\n };\n\n const signed = withSignature(stored, secret);\n\n await persistLicense(signed);\n const status = toLicenseStatus(signed, {\n message: `License verified (${digest.slice(0, 8)}).`,\n });\n this.cache = status;\n return status;\n }\n\n applyProfileCount(status: LicenseStatus, profileCount: number): LicenseStatus {\n const profilesRemaining = resolveProfilesRemaining(status.profileLimit, profileCount);\n return {\n ...status,\n profilesRemaining,\n };\n }\n\n refreshStatusInBackground(options: { force?: boolean } = {}): void {\n if (this.refreshPromise) {\n return;\n }\n\n const forceRefresh = Boolean(options.force);\n this.refreshPromise = (async () => {\n try {\n await this.getStatus({ forceRefresh });\n } catch (error) {\n console.warn('Background license refresh failed:', error);\n } finally {\n this.refreshPromise = null;\n }\n })();\n }\n}\n\nexport const licenseService = new LicenseService();\nexport type { LicenseStatus, LicenseTier, LicenseState };\nexport { FREE_PROFILE_LIMIT, LICENSE_PRICE_DISPLAY, PRODUCT_PERMALINK, PRODUCT_URL, PRODUCT_ID };\n\nfunction isExplicitInvalidation(message: string | null | undefined): boolean {\n if (!message) {\n return false;\n }\n const normalized = message.toLowerCase();\n return (\n normalized.includes('revoked') ||\n normalized.includes('refunded') ||\n normalized.includes('invalid') ||\n normalized.includes('no longer active')\n );\n}\n\n/**\n * Determines when it is safe to enforce profile limits (e.g., pruning).\n * We skip enforcement when the license state is uncertain (grace/error/verifying)\n * and only enforce limits for true free/unlicensed states or explicit revocations.\n */\nexport function shouldEnforceProfileLimit(status: LicenseStatus): boolean {\n if (status.isPro) {\n return false;\n }\n\n if (status.state === 'grace' || status.state === 'verifying' || status.state === 'error') {\n return false;\n }\n\n if (isExplicitInvalidation(status.error)) {\n return true;\n }\n\n return status.state === 'inactive';\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { getUserDataDir } from './app-state';\n\nconst SECRET_FILE = 'license.secret';\n\nfunction resolveSecretPath(): string {\n return path.join(getUserDataDir(), SECRET_FILE);\n}\n\nasync function generateSecret(): Promise<string> {\n return crypto.randomBytes(32).toString('hex');\n}\n\nasync function readSecretIfExists(secretPath: string): Promise<string | null> {\n try {\n const existing = await fs.readFile(secretPath, 'utf8');\n const trimmed = existing.trim();\n if (trimmed.length > 0) {\n return trimmed;\n }\n return null;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n throw error;\n }\n}\n\nasync function writeSecret(secretPath: string, secret: string): Promise<void> {\n await fs.mkdir(path.dirname(secretPath), { recursive: true });\n await fs.writeFile(secretPath, `${secret}\\n`, { mode: 0o600 });\n await fs.chmod(secretPath, 0o600).catch(() => undefined);\n}\n\nexport async function getLicenseSecret(): Promise<string> {\n const secretPath = resolveSecretPath();\n const existing = await readSecretIfExists(secretPath);\n if (existing) {\n return existing;\n }\n\n const secret = await generateSecret();\n await writeSecret(secretPath, secret);\n return secret;\n}\n","/**\n * Single source of truth for pricing, promo codes, and checkout URLs.\n * Every surface (license-service, landing page, upgrade modal, JSON-LD)\n * should derive its pricing/promo data from this file.\n */\n\nexport interface OfferConfig {\n basePriceUsd: number;\n basePriceDisplay: string;\n couponCode: string | null;\n discountPercent: number;\n salePriceUsd: number;\n salePriceDisplay: string;\n isActive: boolean;\n campaign: string | null;\n productPermalink: string;\n checkoutBaseUrl: string;\n}\n\nexport function getActiveOffer(): OfferConfig {\n const basePriceUsd = 39;\n const discountPercent = 50;\n const salePriceUsd = basePriceUsd * (100 - discountPercent) / 100;\n\n return {\n basePriceUsd,\n basePriceDisplay: `$${basePriceUsd}`,\n couponCode: \"SPRING50\",\n discountPercent,\n salePriceUsd,\n salePriceDisplay: `$${salePriceUsd.toFixed(2)}`,\n isActive: true,\n campaign: \"spring-2026\",\n productPermalink: \"codex-use\",\n checkoutBaseUrl: \"https://hweihwang.gumroad.com/l/codex-use\",\n };\n}\n\nexport function buildCheckoutUrl(\n offer: OfferConfig,\n utm?: { source: string; medium: string; campaign?: string },\n): string {\n const base = offer.checkoutBaseUrl;\n const withCoupon = offer.isActive && offer.couponCode\n ? `${base}/${offer.couponCode}`\n : base;\n\n if (!utm) {\n return withCoupon;\n }\n\n const params = new URLSearchParams();\n params.set(\"utm_source\", utm.source);\n params.set(\"utm_medium\", utm.medium);\n if (utm.campaign) {\n params.set(\"utm_campaign\", utm.campaign);\n } else if (offer.campaign) {\n params.set(\"utm_campaign\", offer.campaign);\n }\n\n return `${withCoupon}?${params.toString()}`;\n}\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport {\n CLOUD_SYNC_SCHEMA_VERSION,\n type CloudSyncProfileRecord,\n type CloudSyncSnapshot,\n} from \"./cloud-sync-types\";\nimport {\n CloudSyncClientError,\n fetchRemoteSnapshotMeta,\n fetchRemoteSnapshot,\n pushRemoteSnapshot,\n} from \"./cloud-sync-client\";\nimport { ProfileManager } from \"./profile-manager\";\nimport { getCodexConfigSnapshot, saveCodexConfigContent } from \"./codex-config\";\nimport {\n getStoredLicense,\n readCodexSettingsJsonRaw,\n writeCodexSettingsJsonRaw,\n} from \"./codex-settings\";\nimport { getAppState, getUserDataDir, patchAppState } from \"./app-state\";\nimport { licenseService } from \"./license-service\";\nimport { logInfo, logWarn } from \"./logger\";\nimport { formatUserFacingError } from \"./errors\";\nimport type { CloudSyncRunResultPayload, CloudSyncStatusPayload } from \"./ipc-types\";\nimport { isRecord } from \"./type-guards\";\n\nconst SYNC_BACKUP_DIR = \"sync-backups\";\nconst PRE_PULL_BACKUP_PREFIX = \"pre-pull-\";\nconst PRE_PULL_BACKUP_SUFFIX = \".json\";\nconst PRE_PULL_BACKUP_KEEP_COUNT = 3;\nconst SYNC_SIZE_WARN_BYTES = 1 * 1024 * 1024;\nconst SYNC_SIZE_MAX_BYTES = 5 * 1024 * 1024;\nconst MB_DIVISOR = 1024 * 1024;\n\ninterface CloudSyncStateFile {\n lastPushAt?: string;\n lastPullAt?: string;\n lastError?: string;\n remoteUpdatedAt?: string;\n}\n\ntype Eligibility = {\n canSync: boolean;\n reason: string | null;\n licenseKey: string | null;\n licenseState: string | null;\n};\n\ntype BuildLocalSnapshotOptions = {\n enforcePushGuards?: boolean;\n};\n\nfunction mapProfilesFromAppState(raw: unknown): CloudSyncProfileRecord[] {\n if (!isRecord(raw)) {\n return [];\n }\n\n const profiles: CloudSyncProfileRecord[] = [];\n\n for (const [name, value] of Object.entries(raw)) {\n if (!isRecord(value)) {\n continue;\n }\n\n const data = isRecord(value.data) ? value.data : null;\n if (!data) {\n continue;\n }\n\n const normalizedName = typeof name === \"string\" ? name.trim() : \"\";\n if (!normalizedName) {\n continue;\n }\n\n profiles.push({\n name: normalizedName,\n displayName: typeof value.displayName === \"string\" ? value.displayName : null,\n data,\n metadata: isRecord(value.metadata) ? value.metadata : undefined,\n accountId: typeof value.accountId === \"string\" ? value.accountId : null,\n workspaceId: typeof value.workspaceId === \"string\" ? value.workspaceId : null,\n workspaceName: typeof value.workspaceName === \"string\" ? value.workspaceName : null,\n email: typeof value.email === \"string\" ? value.email : null,\n authMethod: typeof value.authMethod === \"string\" ? value.authMethod : null,\n createdAt: typeof value.createdAt === \"string\" ? value.createdAt : null,\n updatedAt: typeof value.updatedAt === \"string\" ? value.updatedAt : null,\n });\n }\n\n return profiles;\n}\n\nfunction summarizeSnapshot(snapshot: CloudSyncSnapshot): {\n profiles: number;\n configBytes: number;\n settingsKeys: number;\n} {\n const configBytes =\n typeof snapshot.configTomlContent === \"string\" ? snapshot.configTomlContent.length : 0;\n const settingsKeys =\n isRecord(snapshot.settingsJson) ? Object.keys(snapshot.settingsJson).length : 0;\n\n return {\n profiles: snapshot.profiles.length,\n configBytes,\n settingsKeys,\n };\n}\n\nasync function readState(): Promise<CloudSyncStateFile> {\n const state = await getAppState();\n return {\n lastPushAt: state.sync.lastPushAt ?? undefined,\n lastPullAt: state.sync.lastPullAt ?? undefined,\n lastError: state.sync.lastError ?? undefined,\n remoteUpdatedAt: state.sync.remoteUpdatedAt ?? undefined,\n };\n}\n\nasync function writeState(patch: Partial<CloudSyncStateFile>): Promise<void> {\n await patchAppState({\n sync: {\n ...(typeof patch.lastPushAt === \"string\" ? { lastPushAt: patch.lastPushAt } : {}),\n ...(typeof patch.lastPullAt === \"string\" ? { lastPullAt: patch.lastPullAt } : {}),\n ...(typeof patch.lastError === \"string\" ? { lastError: patch.lastError } : patch.lastError === undefined ? { lastError: null } : {}),\n ...(typeof patch.remoteUpdatedAt === \"string\"\n ? { remoteUpdatedAt: patch.remoteUpdatedAt }\n : {}),\n },\n });\n}\n\nasync function resolveEligibility(): Promise<Eligibility> {\n const stored = await getStoredLicense();\n const licenseKey = typeof stored?.licenseKey === \"string\" ? stored.licenseKey.trim() : \"\";\n\n if (!licenseKey) {\n return {\n canSync: false,\n reason: \"License key is required for cloud sync.\",\n licenseKey: null,\n licenseState: null,\n };\n }\n\n const status = await licenseService.getStatus();\n const active = status.state === \"active\" || status.state === \"grace\";\n if (!active) {\n return {\n canSync: false,\n reason: \"Cloud sync requires an active Pro license.\",\n licenseKey,\n licenseState: status.state,\n };\n }\n\n return {\n canSync: true,\n reason: null,\n licenseKey,\n licenseState: status.state,\n };\n}\n\nfunction formatMegabytes(bytes: number): string {\n return (bytes / MB_DIVISOR).toFixed(2);\n}\n\nfunction resolveSyncBackupsDir(): string {\n return path.join(getUserDataDir(), SYNC_BACKUP_DIR);\n}\n\nfunction toSafeIsoForFileName(iso: string): string {\n return iso.replace(/:/g, \"-\");\n}\n\nasync function pruneOldPrePullBackups(backupsDir: string): Promise<void> {\n const entries = await fs.readdir(backupsDir, { withFileTypes: true });\n const files = entries\n .filter(\n (entry) =>\n entry.isFile() &&\n entry.name.startsWith(PRE_PULL_BACKUP_PREFIX) &&\n entry.name.endsWith(PRE_PULL_BACKUP_SUFFIX),\n )\n .map((entry) => entry.name)\n .sort((a, b) => b.localeCompare(a));\n\n if (files.length <= PRE_PULL_BACKUP_KEEP_COUNT) {\n return;\n }\n\n for (const stale of files.slice(PRE_PULL_BACKUP_KEEP_COUNT)) {\n await fs.rm(path.join(backupsDir, stale), { force: true });\n }\n}\n\nasync function createPrePullBackup(profileManager: ProfileManager): Promise<string> {\n const snapshot = await buildLocalSnapshot(profileManager, {\n enforcePushGuards: false,\n });\n const backupsDir = resolveSyncBackupsDir();\n await fs.mkdir(backupsDir, { recursive: true });\n\n const timestamp = toSafeIsoForFileName(new Date().toISOString());\n const backupPath = path.join(\n backupsDir,\n `${PRE_PULL_BACKUP_PREFIX}${timestamp}${PRE_PULL_BACKUP_SUFFIX}`,\n );\n await fs.writeFile(backupPath, `${JSON.stringify(snapshot, null, 2)}\\n`, \"utf8\");\n await pruneOldPrePullBackups(backupsDir);\n\n logInfo(\"[cloud-sync] created pre-pull backup\", { backupPath });\n return backupPath;\n}\n\nasync function buildLocalSnapshot(\n profileManager: ProfileManager,\n options: BuildLocalSnapshotOptions = {},\n): Promise<CloudSyncSnapshot> {\n const enforcePushGuards = options.enforcePushGuards !== false;\n const profilesFromManager = await profileManager.exportProfilesForCloudSync();\n const state = await getAppState();\n const profilesFromState = mapProfilesFromAppState(state.profilesByName);\n const profiles = profilesFromManager.length > 0 ? profilesFromManager : profilesFromState;\n const config = await getCodexConfigSnapshot();\n const settingsJson = await readCodexSettingsJsonRaw();\n\n const hasProfiles = profiles.length > 0;\n const hasConfig = typeof config.content === \"string\" && config.content.trim().length > 0;\n const hasSettings = isRecord(settingsJson) && Object.keys(settingsJson).length > 0;\n\n if (enforcePushGuards && !hasProfiles && !hasConfig && !hasSettings) {\n throw new Error(\"Refusing to push an empty cloud sync snapshot.\");\n }\n\n const snapshot: CloudSyncSnapshot = {\n schemaVersion: CLOUD_SYNC_SCHEMA_VERSION,\n updatedAt: new Date().toISOString(),\n profiles,\n configTomlContent: config.exists ? config.content : null,\n settingsJson,\n };\n\n if (!enforcePushGuards) {\n return snapshot;\n }\n\n return snapshot;\n}\n\nasync function applyRemoteSnapshot(profileManager: ProfileManager, snapshot: CloudSyncSnapshot): Promise<void> {\n await profileManager.replaceProfilesFromCloudSync(snapshot.profiles ?? []);\n\n if (typeof snapshot.configTomlContent === \"string\") {\n await saveCodexConfigContent(snapshot.configTomlContent);\n }\n\n if (snapshot.settingsJson && isRecord(snapshot.settingsJson)) {\n await writeCodexSettingsJsonRaw(snapshot.settingsJson);\n } else {\n await writeCodexSettingsJsonRaw({});\n }\n}\n\nfunction toRunError(mode: \"push\" | \"pull\", error: unknown): CloudSyncRunResultPayload {\n const message = formatUserFacingError(error, {\n fallback: `Cloud sync ${mode} failed.`,\n });\n\n return {\n mode,\n status: \"error\",\n message,\n localUpdatedAt: null,\n remoteUpdatedAt: null,\n };\n}\n\nexport async function getCloudSyncStatus(): Promise<CloudSyncStatusPayload> {\n const eligibility = await resolveEligibility();\n const state = await readState();\n\n let remoteUpdatedAt: string | null = state.remoteUpdatedAt ?? null;\n if (eligibility.canSync && eligibility.licenseKey) {\n try {\n remoteUpdatedAt = await fetchRemoteSnapshotMeta(eligibility.licenseKey);\n } catch (error) {\n if (error instanceof CloudSyncClientError && error.status === 404) {\n try {\n const remote = await fetchRemoteSnapshot(eligibility.licenseKey);\n remoteUpdatedAt = remote?.updatedAt ?? null;\n } catch {\n // Keep status lightweight when remote endpoint is unavailable.\n }\n }\n // Keep status lightweight when remote endpoint is unavailable.\n }\n }\n\n return {\n canSync: eligibility.canSync,\n reason: eligibility.reason,\n licenseState: eligibility.licenseState,\n hasLicenseKey: Boolean(eligibility.licenseKey),\n lastPushAt: state.lastPushAt ?? null,\n lastPullAt: state.lastPullAt ?? null,\n lastError: state.lastError ?? null,\n remoteUpdatedAt,\n };\n}\n\nexport async function pushCloudSync(): Promise<CloudSyncRunResultPayload> {\n const eligibility = await resolveEligibility();\n if (!eligibility.canSync || !eligibility.licenseKey) {\n return {\n mode: \"push\",\n status: \"skipped\",\n message: eligibility.reason ?? \"Cloud sync unavailable.\",\n localUpdatedAt: null,\n remoteUpdatedAt: null,\n };\n }\n\n const profileManager = new ProfileManager();\n\n try {\n await profileManager.initialize();\n const localSnapshot = await buildLocalSnapshot(profileManager, { enforcePushGuards: true });\n const serializedSnapshot = JSON.stringify(localSnapshot);\n const snapshotBytes = Buffer.byteLength(serializedSnapshot, \"utf8\");\n if (snapshotBytes > SYNC_SIZE_WARN_BYTES) {\n logWarn(\"[cloud-sync] push snapshot is large\", {\n bytes: snapshotBytes,\n megabytes: formatMegabytes(snapshotBytes),\n });\n }\n if (snapshotBytes > SYNC_SIZE_MAX_BYTES) {\n throw new Error(\n `Snapshot too large to sync (${formatMegabytes(snapshotBytes)} MB). Reduce profiles or config size.`,\n );\n }\n if (process.env.NODE_ENV !== \"production\") {\n logInfo(\"[cloud-sync] push snapshot summary\", summarizeSnapshot(localSnapshot));\n }\n const remote = await pushRemoteSnapshot(eligibility.licenseKey, localSnapshot, {\n serializedSnapshot,\n });\n\n await writeState({\n lastPushAt: new Date().toISOString(),\n remoteUpdatedAt: remote.snapshot.updatedAt,\n lastError: undefined,\n });\n\n if (remote.status === \"stale\") {\n return {\n mode: \"push\",\n status: \"stale\",\n message: \"Remote cloud snapshot is newer. Pull first.\",\n localUpdatedAt: localSnapshot.updatedAt,\n remoteUpdatedAt: remote.snapshot.updatedAt,\n };\n }\n\n return {\n mode: \"push\",\n status: \"applied\",\n message: \"Cloud sync push completed.\",\n localUpdatedAt: localSnapshot.updatedAt,\n remoteUpdatedAt: remote.snapshot.updatedAt,\n };\n } catch (error) {\n const result = toRunError(\"push\", error);\n const lastError = error instanceof CloudSyncClientError ? error.message : result.message;\n await writeState({ lastError });\n return result;\n }\n}\n\nexport async function pullCloudSync(): Promise<CloudSyncRunResultPayload> {\n const eligibility = await resolveEligibility();\n if (!eligibility.canSync || !eligibility.licenseKey) {\n return {\n mode: \"pull\",\n status: \"skipped\",\n message: eligibility.reason ?? \"Cloud sync unavailable.\",\n localUpdatedAt: null,\n remoteUpdatedAt: null,\n };\n }\n\n const profileManager = new ProfileManager();\n\n try {\n await profileManager.initialize();\n const remote = await fetchRemoteSnapshot(eligibility.licenseKey);\n\n if (!remote) {\n return {\n mode: \"pull\",\n status: \"skipped\",\n message: \"No cloud snapshot found.\",\n localUpdatedAt: null,\n remoteUpdatedAt: null,\n };\n }\n\n let backupWarningSuffix = \"\";\n try {\n await createPrePullBackup(profileManager);\n } catch (backupError) {\n logWarn(\"[cloud-sync] pre-pull backup failed; continuing pull\", backupError);\n const reason = formatUserFacingError(backupError, { fallback: \"unknown error\" });\n backupWarningSuffix = ` Warning: pre-pull backup failed (${reason}).`;\n }\n await applyRemoteSnapshot(profileManager, remote);\n await writeState({\n lastPullAt: new Date().toISOString(),\n remoteUpdatedAt: remote.updatedAt,\n lastError: undefined,\n });\n\n return {\n mode: \"pull\",\n status: \"applied\",\n message: `Cloud sync pull completed.${backupWarningSuffix}`,\n localUpdatedAt: remote.updatedAt,\n remoteUpdatedAt: remote.updatedAt,\n };\n } catch (error) {\n const result = toRunError(\"pull\", error);\n const lastError = error instanceof CloudSyncClientError ? error.message : result.message;\n await writeState({ lastError });\n return result;\n }\n}\n","import type { ProfileData, ProfileMetadata } from \"./types\";\n\nexport const CLOUD_SYNC_SCHEMA_VERSION = 1 as const;\n\nexport interface CloudSyncProfileRecord {\n name: string;\n displayName: string | null;\n data: ProfileData;\n metadata?: ProfileMetadata;\n accountId: string | null;\n workspaceId: string | null;\n workspaceName: string | null;\n email: string | null;\n authMethod: string | null;\n createdAt: string | null;\n updatedAt: string | null;\n}\n\nexport interface CloudSyncSnapshot {\n schemaVersion: typeof CLOUD_SYNC_SCHEMA_VERSION;\n updatedAt: string;\n profiles: CloudSyncProfileRecord[];\n configTomlContent: string | null;\n settingsJson: Record<string, unknown> | null;\n}\n\nexport interface CloudSyncGetResponse {\n snapshot: CloudSyncSnapshot | null;\n}\n\nexport interface CloudSyncMetaResponse {\n updatedAt: string | null;\n}\n\nexport type CloudSyncPutStatus = \"applied\" | \"stale\";\n\nexport interface CloudSyncPutResponse {\n status: CloudSyncPutStatus;\n snapshot: CloudSyncSnapshot;\n}\n","export function isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function toIsoOrNull(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? null : new Date(parsed).toISOString();\n}\n","import {\n CLOUD_SYNC_SCHEMA_VERSION,\n type CloudSyncGetResponse,\n type CloudSyncMetaResponse,\n type CloudSyncPutResponse,\n type CloudSyncSnapshot,\n} from \"./cloud-sync-types\";\nimport { isRecord, toIsoOrNull } from \"./type-guards\";\n\nconst DEFAULT_CLOUD_SYNC_API_BASE_URL = \"https://api.codexuse.com\";\nconst CLOUD_SYNC_TIMEOUT_MS = 15_000;\n\nexport class CloudSyncClientError extends Error {\n readonly status: number | null;\n\n constructor(message: string, status: number | null = null) {\n super(message);\n this.name = \"CloudSyncClientError\";\n this.status = status;\n }\n}\n\nfunction normalizeBaseUrl(value: string): string {\n const trimmed = value.trim();\n return trimmed.endsWith(\"/\") ? trimmed.slice(0, -1) : trimmed;\n}\n\nexport function getCloudSyncApiBaseUrl(): string {\n const fromEnv = typeof process.env.CODEXUSE_API_BASE_URL === \"string\"\n ? process.env.CODEXUSE_API_BASE_URL\n : \"\";\n\n if (fromEnv.trim().length === 0) {\n return DEFAULT_CLOUD_SYNC_API_BASE_URL;\n }\n\n return normalizeBaseUrl(fromEnv);\n}\n\nfunction buildSyncUrl(pathname: string): string {\n const baseUrl = getCloudSyncApiBaseUrl();\n const normalizedPath = pathname.startsWith(\"/\") ? pathname : `/${pathname}`;\n return `${baseUrl}${normalizedPath}`;\n}\n\nfunction normalizeSnapshot(value: unknown): CloudSyncSnapshot | null {\n if (!isRecord(value)) {\n return null;\n }\n\n // Tolerate malformed legacy payloads where snapshot is nested one level:\n // { snapshot: { ...actualSnapshot } }\n if (isRecord(value.snapshot)) {\n const nested = normalizeSnapshot(value.snapshot);\n if (nested) {\n return nested;\n }\n }\n\n const updatedAt = toIsoOrNull(value.updatedAt);\n if (!updatedAt) {\n return null;\n }\n\n const schemaVersion = Number(value.schemaVersion);\n if (!Number.isFinite(schemaVersion) || schemaVersion !== CLOUD_SYNC_SCHEMA_VERSION) {\n return null;\n }\n\n const rawProfiles = Array.isArray(value.profiles) ? value.profiles : [];\n const profiles = rawProfiles\n .map((entry) => (isRecord(entry) ? entry : null))\n .filter((entry): entry is Record<string, unknown> => Boolean(entry))\n .map((entry) => {\n const data = isRecord(entry.data) ? entry.data : {};\n const metadata = isRecord(entry.metadata) ? entry.metadata : undefined;\n return {\n name: typeof entry.name === \"string\" ? entry.name : \"\",\n displayName: typeof entry.displayName === \"string\" ? entry.displayName : null,\n data,\n metadata,\n accountId: typeof entry.accountId === \"string\" ? entry.accountId : null,\n workspaceId: typeof entry.workspaceId === \"string\" ? entry.workspaceId : null,\n workspaceName: typeof entry.workspaceName === \"string\" ? entry.workspaceName : null,\n email: typeof entry.email === \"string\" ? entry.email : null,\n authMethod: typeof entry.authMethod === \"string\" ? entry.authMethod : null,\n createdAt: typeof entry.createdAt === \"string\" ? entry.createdAt : null,\n updatedAt: typeof entry.updatedAt === \"string\" ? entry.updatedAt : null,\n };\n })\n .filter((entry) => entry.name.trim().length > 0);\n\n const rawSettings = value.settingsJson;\n const settingsJson = isRecord(rawSettings) ? rawSettings : null;\n\n return {\n schemaVersion: CLOUD_SYNC_SCHEMA_VERSION,\n updatedAt,\n profiles,\n configTomlContent: typeof value.configTomlContent === \"string\" ? value.configTomlContent : null,\n settingsJson,\n };\n}\n\nasync function requestJson<T>(\n method: \"GET\" | \"PUT\",\n pathname: string,\n licenseKey: string,\n body?: unknown,\n rawBody?: string,\n): Promise<T> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), CLOUD_SYNC_TIMEOUT_MS);\n\n try {\n const response = await fetch(buildSyncUrl(pathname), {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-codexuse-license-key\": licenseKey,\n },\n body: typeof rawBody === \"string\"\n ? rawBody\n : body === undefined\n ? undefined\n : JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const message = await response.text().catch(() => \"\");\n throw new CloudSyncClientError(\n message || `Cloud sync request failed (${response.status}).`,\n response.status,\n );\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof CloudSyncClientError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new CloudSyncClientError(\"Cloud sync request timed out.\");\n }\n\n throw new CloudSyncClientError(\n error instanceof Error ? error.message : \"Cloud sync request failed.\",\n );\n } finally {\n clearTimeout(timeout);\n }\n}\n\nexport async function fetchRemoteSnapshot(licenseKey: string): Promise<CloudSyncSnapshot | null> {\n const response = await requestJson<CloudSyncGetResponse>(\"GET\", \"/v1/sync/snapshot\", licenseKey);\n return normalizeSnapshot(response.snapshot);\n}\n\nexport async function fetchRemoteSnapshotMeta(licenseKey: string): Promise<string | null> {\n const response = await requestJson<CloudSyncMetaResponse>(\n \"GET\",\n \"/v1/sync/snapshot/meta\",\n licenseKey,\n );\n return toIsoOrNull(response.updatedAt);\n}\n\nexport async function pushRemoteSnapshot(\n licenseKey: string,\n snapshot: CloudSyncSnapshot,\n options?: { serializedSnapshot?: string },\n): Promise<CloudSyncPutResponse> {\n const serializedSnapshot = typeof options?.serializedSnapshot === \"string\"\n ? options.serializedSnapshot\n : JSON.stringify(snapshot);\n const response = await requestJson<CloudSyncPutResponse>(\n \"PUT\",\n \"/v1/sync/snapshot\",\n licenseKey,\n undefined,\n `{\"snapshot\":${serializedSnapshot}}`,\n );\n\n const normalized = normalizeSnapshot(response.snapshot);\n if (!normalized) {\n throw new CloudSyncClientError(\"Cloud sync server returned an invalid snapshot payload.\");\n }\n\n const status = response.status === \"stale\" ? \"stale\" : \"applied\";\n return {\n status,\n snapshot: normalized,\n };\n}\n","import { mkdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parse, stringify } from \"@iarna/toml\";\nimport {\n getCodexConfigMetadata,\n type CodexConfigMetadata,\n type CodexFeatureStage,\n} from \"./codex-config-metadata\";\nimport { formatUserFacingError } from \"./errors\";\n\ntype RawConfig = Record<string, unknown>;\n\nexport type CodexDiagnosticCategory = \"feature\" | \"security\" | \"risk\" | \"config\";\nexport type CodexDiagnosticSeverity = \"info\" | \"warning\" | \"risk\";\n\nexport interface CodexConfigDiagnostic {\n id: string;\n category: CodexDiagnosticCategory;\n severity: CodexDiagnosticSeverity;\n title: string;\n message: string;\n fixId: string | null;\n fixLabel: string | null;\n}\n\nexport interface CodexConfigFeaturesSummary {\n unifiedExec: boolean | null;\n shellSnapshot: boolean | null;\n values: Record<string, boolean | null>;\n}\n\nexport interface CodexConfigToolsSummary {\n webSearch: boolean | null;\n viewImage: boolean | null;\n}\n\nexport interface CodexConfigNoticeSummary {\n hideFullAccessWarning: boolean | null;\n hideGpt51MigrationPrompt: boolean | null;\n hideLegacyGpt51CodexMaxMigrationPrompt: boolean | null;\n hideRateLimitModelNudge: boolean | null;\n modelMigrations: Record<string, string> | null;\n}\n\nexport interface CodexConfigSettingsSummary {\n model: string | null;\n reviewModel: string | null;\n modelReasoningEffort: string | null;\n modelReasoningSummary: string | null;\n modelVerbosity: string | null;\n approvalPolicy: string | null;\n sandboxMode: string | null;\n webSearch: string | null;\n personality: string | null;\n toolOutputTokenLimit: number | null;\n modelAutoCompactTokenLimit: number | null;\n modelContextWindow: number | null;\n features: CodexConfigFeaturesSummary;\n tools: CodexConfigToolsSummary;\n notice: CodexConfigNoticeSummary;\n}\n\nexport interface CodexConfigSnapshotPayload {\n path: string;\n exists: boolean;\n content: string;\n settings: CodexConfigSettingsSummary;\n mcpServers: McpServerConfig[];\n rmcpClientEnabled: boolean;\n parseError: string | null;\n isYoloPreset: boolean;\n updatedAt: number | null;\n metadata: CodexConfigMetadata;\n diagnostics: CodexConfigDiagnostic[];\n}\n\nexport interface CodexFeatureUpdateMap {\n [featureName: string]: boolean | null | undefined;\n unifiedExec?: boolean | null;\n shellSnapshot?: boolean | null;\n}\n\nexport interface CodexConfigUpdatePayload {\n model?: string | null;\n reviewModel?: string | null;\n modelReasoningEffort?: string | null;\n modelReasoningSummary?: string | null;\n modelVerbosity?: string | null;\n approvalPolicy?: string | null;\n sandboxMode?: string | null;\n webSearch?: string | null;\n personality?: string | null;\n toolOutputTokenLimit?: number | null;\n modelAutoCompactTokenLimit?: number | null;\n modelContextWindow?: number | null;\n features?: CodexFeatureUpdateMap;\n tools?: {\n webSearch?: boolean | null;\n viewImage?: boolean | null;\n };\n notice?: {\n hideFullAccessWarning?: boolean | null;\n hideGpt51MigrationPrompt?: boolean | null;\n hideLegacyGpt51CodexMaxMigrationPrompt?: boolean | null;\n hideRateLimitModelNudge?: boolean | null;\n modelMigrations?: Record<string, string> | null;\n };\n applyFixes?: string[] | null;\n}\n\nexport interface McpServerConfig {\n name: string;\n transport: \"stdio\" | \"http\" | \"sse\";\n enabled: boolean;\n command?: string | null;\n args?: string[] | null;\n cwd?: string | null;\n env?: Record<string, string> | null;\n envVars?: string[] | null;\n url?: string | null;\n bearerTokenEnvVar?: string | null;\n httpHeaders?: Record<string, string> | null;\n envHttpHeaders?: Record<string, string> | null;\n startupTimeoutSec?: number | null;\n toolTimeoutSec?: number | null;\n enabledTools?: string[] | null;\n disabledTools?: string[] | null;\n}\n\ntype ParsedResult = {\n data: RawConfig | null;\n error: string | null;\n};\n\nconst DEFAULT_CONFIG_TEMPLATE = [\n \"# ~/.codex/config.toml (managed by CodexUse)\",\n \"# Safe defaults with prompts and sandboxed access.\",\n \"# To enable full access, opt into the YOLO preset from settings.\",\n \"\",\n 'model = \"gpt-5.3-codex\"',\n 'review_model = \"gpt-5.3-codex\"',\n 'model_reasoning_effort = \"medium\"',\n 'model_reasoning_summary = \"auto\"',\n 'model_verbosity = \"medium\"',\n 'approval_policy = \"on-request\"',\n 'sandbox_mode = \"read-only\"',\n 'web_search = \"cached\"',\n \"\",\n].join(\"\\n\");\n\nconst SUPPORTED_REASONING_EFFORT = new Set([\"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"none\"]);\nconst CLI_SUPPORTED_REASONING_EFFORT = new Set([\"minimal\", \"low\", \"medium\", \"high\", \"none\"]);\n\nconst KNOWN_APPROVAL_POLICIES = new Set([\"untrusted\", \"on-failure\", \"on-request\", \"never\"]);\nconst KNOWN_SANDBOX_MODES = new Set([\"read-only\", \"workspace-write\", \"danger-full-access\"]);\n\nconst YOLO_PRESET: CodexConfigUpdatePayload = {\n model: \"gpt-5.3-codex\",\n reviewModel: \"gpt-5.3-codex\",\n modelReasoningEffort: \"xhigh\",\n modelReasoningSummary: \"detailed\",\n modelVerbosity: \"high\",\n approvalPolicy: \"never\",\n sandboxMode: \"danger-full-access\",\n webSearch: \"live\",\n personality: \"pragmatic\",\n toolOutputTokenLimit: 25_000,\n modelAutoCompactTokenLimit: 233_000,\n features: {\n unifiedExec: true,\n shellSnapshot: true,\n },\n notice: {\n hideFullAccessWarning: true,\n hideGpt51MigrationPrompt: true,\n hideRateLimitModelNudge: true,\n },\n};\n\nfunction resolveHomeDir(): string {\n const homeDir = process.env.HOME || process.env.USERPROFILE;\n if (!homeDir) {\n throw new Error(\"Unable to determine home directory for Codex config.\");\n }\n return homeDir;\n}\n\nfunction getConfigPath(): string {\n const homeDir = resolveHomeDir();\n return path.join(homeDir, \".codex\", \"config.toml\");\n}\n\nasync function ensureConfigDirExists(filePath: string): Promise<void> {\n const dir = path.dirname(filePath);\n await mkdir(dir, { recursive: true });\n}\n\nfunction normalizeLineEndings(content: string): string {\n return content.replace(/\\r\\n/g, \"\\n\");\n}\n\nfunction ensureTrailingNewline(content: string): string {\n return content.endsWith(\"\\n\") ? content : `${content}\\n`;\n}\n\nfunction tryParseToml(content: string): ParsedResult {\n try {\n const parsed = parse(content) as RawConfig;\n return { data: parsed ?? {}, error: null };\n } catch (error) {\n const maybe = error as Partial<{ line: number; column: number; col: number }>;\n const line = typeof maybe?.line === \"number\" ? maybe.line : null;\n const column = typeof maybe?.column === \"number\" ? maybe.column : typeof maybe?.col === \"number\" ? maybe.col : null;\n const location = line !== null ? `line ${line}${column !== null ? `, column ${column}` : \"\"}` : null;\n\n const friendly = formatUserFacingError(error, {\n fallback: \"Invalid config.toml syntax. Fix it and try again.\",\n maxLength: 180,\n });\n const message = location ? `${friendly} (near ${location}).` : friendly;\n return { data: null, error: message };\n }\n}\n\nfunction toStringOrNull(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction toBooleanOrNull(value: unknown): boolean | null {\n if (typeof value === \"boolean\") {\n return value;\n }\n return null;\n}\n\nfunction toNumberOrNull(value: unknown): number | null {\n if (typeof value !== \"number\") {\n return null;\n }\n return Number.isFinite(value) ? value : null;\n}\n\nfunction toStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value\n .map(entry => (typeof entry === \"string\" ? entry.trim() : \"\"))\n .filter(entry => entry.length > 0);\n}\n\nfunction toStringRecord(value: unknown): Record<string, string> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return {};\n }\n\n const result: Record<string, string> = {};\n for (const [key, raw] of Object.entries(value)) {\n if (typeof raw !== \"string\") {\n continue;\n }\n const normalizedKey = key.trim();\n const normalizedValue = raw.trim();\n if (!normalizedKey || !normalizedValue) {\n continue;\n }\n result[normalizedKey] = normalizedValue;\n }\n return result;\n}\n\nfunction buildSettingsSummary(data: RawConfig | null): CodexConfigSettingsSummary {\n const noticeCandidate = data && typeof data[\"notice\"] === \"object\" && data[\"notice\"] !== null\n ? (data[\"notice\"] as RawConfig)\n : null;\n\n const featuresCandidate =\n data && typeof data[\"features\"] === \"object\" && data[\"features\"] !== null && !Array.isArray(data[\"features\"])\n ? (data[\"features\"] as RawConfig)\n : null;\n\n const toolsCandidate =\n data && typeof data[\"tools\"] === \"object\" && data[\"tools\"] !== null && !Array.isArray(data[\"tools\"])\n ? (data[\"tools\"] as RawConfig)\n : null;\n\n const featureValues: Record<string, boolean | null> = {};\n if (featuresCandidate) {\n for (const [key, value] of Object.entries(featuresCandidate)) {\n featureValues[key] = toBooleanOrNull(value);\n }\n }\n\n const modelMigrationsRaw = noticeCandidate ? toStringRecord(noticeCandidate[\"model_migrations\"]) : {};\n\n return {\n model: data ? toStringOrNull(data[\"model\"]) : null,\n reviewModel: data ? toStringOrNull(data[\"review_model\"]) : null,\n modelReasoningEffort: data ? toStringOrNull(data[\"model_reasoning_effort\"]) : null,\n modelReasoningSummary: data ? toStringOrNull(data[\"model_reasoning_summary\"]) : null,\n modelVerbosity: data ? toStringOrNull(data[\"model_verbosity\"]) : null,\n approvalPolicy: data ? toStringOrNull(data[\"approval_policy\"]) : null,\n sandboxMode: data ? toStringOrNull(data[\"sandbox_mode\"]) : null,\n webSearch: data ? toStringOrNull(data[\"web_search\"]) : null,\n personality: data ? toStringOrNull(data[\"personality\"]) : null,\n toolOutputTokenLimit: data ? toNumberOrNull(data[\"tool_output_token_limit\"]) : null,\n modelAutoCompactTokenLimit: data ? toNumberOrNull(data[\"model_auto_compact_token_limit\"]) : null,\n modelContextWindow: data ? toNumberOrNull(data[\"model_context_window\"]) : null,\n features: {\n unifiedExec: featuresCandidate ? toBooleanOrNull(featuresCandidate[\"unified_exec\"]) : null,\n shellSnapshot: featuresCandidate ? toBooleanOrNull(featuresCandidate[\"shell_snapshot\"]) : null,\n values: featureValues,\n },\n tools: {\n webSearch: toolsCandidate ? toBooleanOrNull(toolsCandidate[\"web_search\"]) : null,\n viewImage: toolsCandidate ? toBooleanOrNull(toolsCandidate[\"view_image\"]) : null,\n },\n notice: {\n hideFullAccessWarning: noticeCandidate ? toBooleanOrNull(noticeCandidate[\"hide_full_access_warning\"]) : null,\n hideGpt51MigrationPrompt: noticeCandidate ? toBooleanOrNull(noticeCandidate[\"hide_gpt5_1_migration_prompt\"]) : null,\n hideLegacyGpt51CodexMaxMigrationPrompt: noticeCandidate\n ? toBooleanOrNull(noticeCandidate[\"hide_gpt-5.1-codex-max_migration_prompt\"])\n : null,\n hideRateLimitModelNudge: noticeCandidate ? toBooleanOrNull(noticeCandidate[\"hide_rate_limit_model_nudge\"]) : null,\n modelMigrations: Object.keys(modelMigrationsRaw).length > 0 ? modelMigrationsRaw : null,\n },\n };\n}\n\nfunction getUnsupportedReasoningEffort(\n data: RawConfig | null,\n allowed: Set<string> = SUPPORTED_REASONING_EFFORT,\n): string | null {\n if (!data || !Object.prototype.hasOwnProperty.call(data, \"model_reasoning_effort\")) {\n return null;\n }\n\n const raw = data[\"model_reasoning_effort\"];\n if (typeof raw !== \"string\") {\n return String(raw ?? \"\");\n }\n\n const value = raw.trim();\n if (!value) {\n return null;\n }\n\n return allowed.has(value) ? null : value;\n}\n\nfunction parseRmcpClientEnabled(data: RawConfig | null): boolean {\n const rawFeatures =\n data && typeof data[\"features\"] === \"object\" && data[\"features\"] !== null && !Array.isArray(data[\"features\"])\n ? (data[\"features\"] as RawConfig)\n : null;\n\n if (rawFeatures && typeof rawFeatures[\"rmcp_client\"] === \"boolean\") {\n return rawFeatures[\"rmcp_client\"] as boolean;\n }\n\n if (data && typeof data[\"experimental_use_rmcp_client\"] === \"boolean\") {\n return data[\"experimental_use_rmcp_client\"] as boolean;\n }\n\n return false;\n}\n\nfunction parseMcpServer(name: string, rawValue: unknown): McpServerConfig | null {\n if (typeof rawValue !== \"object\" || rawValue === null || Array.isArray(rawValue)) {\n return null;\n }\n const raw = rawValue as RawConfig;\n const typeValue = toStringOrNull(raw[\"type\"]);\n const command = toStringOrNull(raw[\"command\"]);\n const args = toStringArray(raw[\"args\"]);\n const env = toStringRecord(raw[\"env\"]);\n const envVars = toStringArray(raw[\"env_vars\"]);\n const cwd = toStringOrNull(raw[\"cwd\"]);\n const url = toStringOrNull(raw[\"url\"]);\n const bearerTokenEnvVar = toStringOrNull(raw[\"bearer_token_env_var\"]);\n const httpHeaders = toStringRecord(raw[\"http_headers\"]);\n const envHttpHeaders = toStringRecord(raw[\"env_http_headers\"]);\n const startupTimeoutSec = toNumberOrNull(raw[\"startup_timeout_sec\"]);\n const toolTimeoutSec = toNumberOrNull(raw[\"tool_timeout_sec\"]);\n const enabledTools = toStringArray(raw[\"enabled_tools\"]);\n const disabledTools = toStringArray(raw[\"disabled_tools\"]);\n const enabled = typeof raw[\"enabled\"] === \"boolean\" ? raw[\"enabled\"] : true;\n const transport: \"stdio\" | \"http\" | \"sse\" =\n typeValue === \"stdio\" || typeValue === \"http\" || typeValue === \"sse\"\n ? typeValue\n : url\n ? \"http\"\n : \"stdio\";\n\n return {\n name,\n transport,\n enabled,\n command,\n args: args.length > 0 ? args : null,\n cwd,\n env: Object.keys(env).length > 0 ? env : null,\n envVars: envVars.length > 0 ? envVars : null,\n url,\n bearerTokenEnvVar,\n httpHeaders: Object.keys(httpHeaders).length > 0 ? httpHeaders : null,\n envHttpHeaders: Object.keys(envHttpHeaders).length > 0 ? envHttpHeaders : null,\n startupTimeoutSec,\n toolTimeoutSec,\n enabledTools: enabledTools.length > 0 ? enabledTools : null,\n disabledTools: disabledTools.length > 0 ? disabledTools : null,\n };\n}\n\nfunction buildMcpServersList(data: RawConfig | null): McpServerConfig[] {\n const rawServers = data?.[\"mcp_servers\"];\n if (typeof rawServers !== \"object\" || rawServers === null || Array.isArray(rawServers)) {\n return [];\n }\n\n const servers: McpServerConfig[] = [];\n for (const [name, rawValue] of Object.entries(rawServers)) {\n const parsed = parseMcpServer(name, rawValue);\n if (parsed) {\n servers.push(parsed);\n }\n }\n return servers;\n}\n\nfunction getFeatureStage(metadata: CodexConfigMetadata, featureKey: string): CodexFeatureStage {\n const found = metadata.featureCatalog.find(entry => entry.key === featureKey);\n return found?.stage ?? \"unknown\";\n}\n\nfunction looksLikeSecretValue(value: string): boolean {\n const normalized = value.trim();\n if (normalized.length < 12) {\n return false;\n }\n if (/\\s/.test(normalized)) {\n return false;\n }\n if (!/^[A-Za-z0-9._:-]+$/.test(normalized)) {\n return false;\n }\n const hasLetters = /[A-Za-z]/.test(normalized);\n const hasNumbers = /\\d/.test(normalized);\n return hasLetters && hasNumbers;\n}\n\nfunction buildConfigDiagnostics(\n data: RawConfig | null,\n summary: CodexConfigSettingsSummary,\n mcpServers: McpServerConfig[],\n metadata: CodexConfigMetadata,\n): CodexConfigDiagnostic[] {\n const diagnostics: CodexConfigDiagnostic[] = [];\n\n const featureTable =\n data && typeof data[\"features\"] === \"object\" && data[\"features\"] !== null && !Array.isArray(data[\"features\"])\n ? (data[\"features\"] as RawConfig)\n : null;\n\n const knownTopLevelKeys = new Set(metadata.schemaTopLevelKeys);\n if (data) {\n for (const key of Object.keys(data)) {\n if (knownTopLevelKeys.has(key)) {\n continue;\n }\n diagnostics.push({\n id: `unknown-top-level:${key}`,\n category: \"config\",\n severity: \"warning\",\n title: `Unknown config key: ${key}`,\n message: `This top-level key is not in the known Codex schema and may be ignored by Codex CLI.`,\n fixId: null,\n fixLabel: null,\n });\n }\n }\n\n if (featureTable) {\n const knownFeatureKeys = new Set(metadata.schemaFeatureKeys);\n for (const [featureKey] of Object.entries(featureTable)) {\n if (!knownFeatureKeys.has(featureKey)) {\n diagnostics.push({\n id: `unknown-feature:${featureKey}`,\n category: \"feature\",\n severity: \"warning\",\n title: `Unknown feature flag: features.${featureKey}`,\n message: \"This feature is not recognized in the current schema. Keeping it is non-destructive, but it may do nothing.\",\n fixId: `remove-feature:${featureKey}`,\n fixLabel: \"Remove flag\",\n });\n continue;\n }\n\n const stage = getFeatureStage(metadata, featureKey);\n if (stage === \"deprecated\") {\n diagnostics.push({\n id: `deprecated-feature:${featureKey}`,\n category: \"feature\",\n severity: \"warning\",\n title: `Deprecated feature flag: features.${featureKey}`,\n message: \"Codex marks this feature as deprecated. Prefer removing it.\",\n fixId: `remove-feature:${featureKey}`,\n fixLabel: \"Remove deprecated flag\",\n });\n }\n }\n }\n\n for (const server of mcpServers) {\n if (server.transport === \"stdio\" && server.args) {\n for (let index = 0; index < server.args.length; index += 1) {\n const value = server.args[index] ?? \"\";\n if (/(api[-_]?key|token|secret)\\s*=\\s*/i.test(value)) {\n diagnostics.push({\n id: `mcp-secret-arg:${server.name}:${index}`,\n category: \"security\",\n severity: \"warning\",\n title: `Potential secret in MCP args (${server.name})`,\n message: \"Argument text appears to contain a literal token/API key. Move secrets to environment variables.\",\n fixId: null,\n fixLabel: null,\n });\n }\n }\n }\n\n if (server.httpHeaders) {\n for (const [header, headerValue] of Object.entries(server.httpHeaders)) {\n if (!looksLikeSecretValue(headerValue)) {\n continue;\n }\n diagnostics.push({\n id: `mcp-secret-header:${server.name}:${header}`,\n category: \"security\",\n severity: \"warning\",\n title: `Potential secret in MCP header (${server.name})`,\n message: `HTTP header '${header}' appears to contain a literal secret. Prefer env_http_headers or bearer_token_env_var.`,\n fixId: null,\n fixLabel: null,\n });\n }\n }\n }\n\n if (summary.approvalPolicy === \"never\" && summary.sandboxMode === \"danger-full-access\") {\n diagnostics.push({\n id: \"risk:yolo-combo\",\n category: \"risk\",\n severity: \"risk\",\n title: \"High-risk execution mode enabled\",\n message: \"approval_policy=never + sandbox_mode=danger-full-access removes approval and sandbox guardrails.\",\n fixId: null,\n fixLabel: null,\n });\n }\n\n return diagnostics;\n}\n\nfunction isYoloApplied(summary: CodexConfigSettingsSummary): boolean {\n return (\n summary.model === YOLO_PRESET.model &&\n summary.reviewModel === YOLO_PRESET.reviewModel &&\n summary.modelReasoningEffort === YOLO_PRESET.modelReasoningEffort &&\n summary.modelReasoningSummary === YOLO_PRESET.modelReasoningSummary &&\n summary.modelVerbosity === YOLO_PRESET.modelVerbosity &&\n summary.approvalPolicy === YOLO_PRESET.approvalPolicy &&\n summary.sandboxMode === YOLO_PRESET.sandboxMode &&\n summary.webSearch === YOLO_PRESET.webSearch &&\n summary.personality === YOLO_PRESET.personality &&\n summary.toolOutputTokenLimit === YOLO_PRESET.toolOutputTokenLimit &&\n summary.modelAutoCompactTokenLimit === YOLO_PRESET.modelAutoCompactTokenLimit &&\n summary.features.unifiedExec === true &&\n summary.features.shellSnapshot === true &&\n summary.notice.hideFullAccessWarning === true &&\n summary.notice.hideGpt51MigrationPrompt === true &&\n summary.notice.hideRateLimitModelNudge === true\n );\n}\n\nasync function readConfigContent(): Promise<{ exists: boolean; content: string }> {\n const configPath = getConfigPath();\n try {\n const content = await readFile(configPath, \"utf8\");\n return {\n exists: true,\n content: normalizeLineEndings(content),\n };\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return {\n exists: false,\n content: DEFAULT_CONFIG_TEMPLATE,\n };\n }\n throw error;\n }\n}\n\nasync function writeConfigContent(content: string): Promise<void> {\n const configPath = getConfigPath();\n await ensureConfigDirExists(configPath);\n const normalized = ensureTrailingNewline(normalizeLineEndings(content));\n await writeFile(configPath, normalized, \"utf8\");\n}\n\nasync function getUpdatedAt(configPath: string, exists: boolean): Promise<number | null> {\n if (!exists) {\n return null;\n }\n\n try {\n const stats = await stat(configPath);\n return stats.mtimeMs;\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n}\n\nasync function buildSnapshot(content: string, exists: boolean): Promise<CodexConfigSnapshotPayload> {\n const configPath = getConfigPath();\n const parsed = tryParseToml(content);\n const summary = buildSettingsSummary(parsed.data);\n const updatedAt = await getUpdatedAt(configPath, exists);\n const mcpServers = buildMcpServersList(parsed.data);\n const rmcpClientEnabled = parseRmcpClientEnabled(parsed.data);\n const metadata = await getCodexConfigMetadata();\n const diagnostics = parsed.error\n ? []\n : buildConfigDiagnostics(parsed.data, summary, mcpServers, metadata);\n\n return {\n path: configPath,\n exists,\n content,\n settings: summary,\n mcpServers,\n rmcpClientEnabled,\n parseError: parsed.error,\n isYoloPreset: parsed.error ? false : isYoloApplied(summary),\n updatedAt,\n metadata,\n diagnostics,\n };\n}\n\nfunction sanitizeString(value: string | null | undefined): string | null {\n if (value === null || value === undefined) {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction sanitizeNumber(value: number | null | undefined): number | null {\n if (value === undefined || value === null) {\n return null;\n }\n if (!Number.isFinite(value)) {\n throw new Error(\"Numeric value must be finite.\");\n }\n return value;\n}\n\nfunction normalizeStringArrayInput(values?: string[] | null): string[] | null {\n if (!values) {\n return null;\n }\n const normalized = values\n .map(value => sanitizeString(value))\n .filter((value): value is string => Boolean(value));\n return normalized.length > 0 ? normalized : null;\n}\n\nfunction normalizeStringRecordInput(record?: Record<string, string> | null): Record<string, string> | null {\n if (!record) {\n return null;\n }\n const normalized: Record<string, string> = {};\n for (const [key, value] of Object.entries(record)) {\n const normalizedKey = sanitizeString(key);\n const normalizedValue = sanitizeString(value);\n if (normalizedKey && normalizedValue) {\n normalized[normalizedKey] = normalizedValue;\n }\n }\n return Object.keys(normalized).length > 0 ? normalized : null;\n}\n\nfunction applySuggestedFixes(current: RawConfig, fixIds?: string[] | null): RawConfig {\n if (!fixIds || fixIds.length === 0) {\n return current;\n }\n\n let next: RawConfig = { ...current };\n\n for (const fixId of fixIds) {\n if (!fixId.startsWith(\"remove-feature:\")) {\n continue;\n }\n\n const featureKey = fixId.slice(\"remove-feature:\".length).trim();\n if (!featureKey) {\n continue;\n }\n\n const rawFeatures =\n typeof next[\"features\"] === \"object\" && next[\"features\"] !== null && !Array.isArray(next[\"features\"])\n ? { ...(next[\"features\"] as RawConfig) }\n : {};\n\n if (!Object.prototype.hasOwnProperty.call(rawFeatures, featureKey)) {\n continue;\n }\n\n delete rawFeatures[featureKey];\n if (Object.keys(rawFeatures).length === 0) {\n delete next[\"features\"];\n } else {\n next[\"features\"] = rawFeatures;\n }\n }\n\n return next;\n}\n\nfunction applyUpdatesToConfig(current: RawConfig, updates: CodexConfigUpdatePayload): RawConfig {\n const next: RawConfig = { ...current };\n\n const applyStringField = (key: string, candidate?: string | null) => {\n if (candidate === undefined) {\n return;\n }\n const normalized = sanitizeString(candidate);\n if (!normalized) {\n delete next[key];\n } else {\n next[key] = normalized;\n }\n };\n\n const applyNumberField = (key: string, candidate?: number | null) => {\n if (candidate === undefined) {\n return;\n }\n const normalized = sanitizeNumber(candidate);\n if (normalized === null) {\n delete next[key];\n } else {\n next[key] = normalized;\n }\n };\n\n applyStringField(\"model\", updates.model);\n applyStringField(\"review_model\", updates.reviewModel);\n applyStringField(\"model_reasoning_effort\", updates.modelReasoningEffort);\n applyStringField(\"model_reasoning_summary\", updates.modelReasoningSummary);\n applyStringField(\"model_verbosity\", updates.modelVerbosity);\n applyStringField(\"approval_policy\", updates.approvalPolicy);\n applyStringField(\"sandbox_mode\", updates.sandboxMode);\n applyStringField(\"web_search\", updates.webSearch);\n applyStringField(\"personality\", updates.personality);\n\n applyNumberField(\"tool_output_token_limit\", updates.toolOutputTokenLimit);\n applyNumberField(\"model_auto_compact_token_limit\", updates.modelAutoCompactTokenLimit);\n applyNumberField(\"model_context_window\", updates.modelContextWindow);\n\n if (updates.features) {\n const rawFeatures =\n typeof next[\"features\"] === \"object\" && next[\"features\"] !== null && !Array.isArray(next[\"features\"])\n ? { ...(next[\"features\"] as RawConfig) }\n : {};\n\n const applyFeatureField = (key: string, candidate: boolean | null | undefined) => {\n if (candidate === undefined) {\n return;\n }\n if (candidate === null) {\n delete rawFeatures[key];\n return;\n }\n rawFeatures[key] = candidate;\n };\n\n for (const [rawKey, candidate] of Object.entries(updates.features)) {\n const key = rawKey === \"unifiedExec\"\n ? \"unified_exec\"\n : rawKey === \"shellSnapshot\"\n ? \"shell_snapshot\"\n : rawKey;\n applyFeatureField(key, candidate);\n }\n\n if (Object.keys(rawFeatures).length === 0) {\n delete next[\"features\"];\n } else {\n next[\"features\"] = rawFeatures;\n }\n }\n\n if (updates.tools) {\n const rawTools =\n typeof next[\"tools\"] === \"object\" && next[\"tools\"] !== null && !Array.isArray(next[\"tools\"])\n ? { ...(next[\"tools\"] as RawConfig) }\n : {};\n\n const applyToolField = (key: string, candidate?: boolean | null) => {\n if (candidate === undefined) {\n return;\n }\n if (candidate === null) {\n delete rawTools[key];\n } else {\n rawTools[key] = candidate;\n }\n };\n\n applyToolField(\"web_search\", updates.tools.webSearch);\n applyToolField(\"view_image\", updates.tools.viewImage);\n\n if (Object.keys(rawTools).length === 0) {\n delete next[\"tools\"];\n } else {\n next[\"tools\"] = rawTools;\n }\n }\n\n if (updates.notice) {\n const rawNotice = next[\"notice\"];\n const currentNotice =\n rawNotice && typeof rawNotice === \"object\" && rawNotice !== null\n ? { ...(rawNotice as RawConfig) }\n : {};\n\n const applyBooleanField = (key: string, candidate?: boolean | null) => {\n if (candidate === undefined) {\n return;\n }\n if (candidate === null) {\n delete currentNotice[key];\n } else {\n currentNotice[key] = candidate;\n }\n };\n\n const applyRecordField = (key: string, candidate?: Record<string, string> | null) => {\n if (candidate === undefined) {\n return;\n }\n const normalized = normalizeStringRecordInput(candidate);\n if (!normalized) {\n delete currentNotice[key];\n } else {\n currentNotice[key] = normalized;\n }\n };\n\n applyBooleanField(\"hide_full_access_warning\", updates.notice.hideFullAccessWarning);\n applyBooleanField(\"hide_gpt5_1_migration_prompt\", updates.notice.hideGpt51MigrationPrompt);\n applyBooleanField(\n \"hide_gpt-5.1-codex-max_migration_prompt\",\n updates.notice.hideLegacyGpt51CodexMaxMigrationPrompt,\n );\n applyBooleanField(\"hide_rate_limit_model_nudge\", updates.notice.hideRateLimitModelNudge);\n applyRecordField(\"model_migrations\", updates.notice.modelMigrations);\n\n if (Object.keys(currentNotice).length === 0) {\n delete next[\"notice\"];\n } else {\n next[\"notice\"] = currentNotice;\n }\n }\n\n return applySuggestedFixes(next, updates.applyFixes);\n}\n\nfunction validateMcpServerName(name: string): string {\n const normalized = sanitizeString(name);\n if (!normalized) {\n throw new Error(\"MCP server name is required.\");\n }\n if (!/^[A-Za-z0-9._-]+$/.test(normalized)) {\n throw new Error(\"MCP server name must use letters, numbers, periods, underscores, or hyphens.\");\n }\n return normalized;\n}\n\nfunction applyMcpServerUpsert(\n current: RawConfig,\n server: McpServerConfig,\n rmcpClientEnabled?: boolean | null,\n): RawConfig {\n const name = validateMcpServerName(server.name);\n const next: RawConfig = { ...current };\n const rawServers =\n typeof next[\"mcp_servers\"] === \"object\" && next[\"mcp_servers\"] !== null && !Array.isArray(next[\"mcp_servers\"])\n ? { ...(next[\"mcp_servers\"] as RawConfig) }\n : {};\n\n const base =\n typeof rawServers[name] === \"object\" && rawServers[name] !== null && !Array.isArray(rawServers[name])\n ? { ...(rawServers[name] as RawConfig) }\n : {};\n\n const updated: RawConfig = { ...base };\n\n const setStringField = (key: string, value: string | null | undefined) => {\n const normalized = sanitizeString(value ?? null);\n if (!normalized) {\n delete updated[key];\n return;\n }\n updated[key] = normalized;\n };\n\n const setStringArrayField = (key: string, values: string[] | null | undefined) => {\n const normalized = normalizeStringArrayInput(values);\n if (!normalized) {\n delete updated[key];\n return;\n }\n updated[key] = normalized;\n };\n\n const setRecordField = (key: string, values: Record<string, string> | null | undefined) => {\n const normalized = normalizeStringRecordInput(values);\n if (!normalized) {\n delete updated[key];\n return;\n }\n updated[key] = normalized;\n };\n\n const setNumberField = (key: string, value: number | null | undefined) => {\n if (value === null || value === undefined) {\n delete updated[key];\n return;\n }\n if (!Number.isFinite(value)) {\n throw new Error(`Invalid numeric value for ${key}.`);\n }\n updated[key] = value;\n };\n\n updated[\"enabled\"] = Boolean(server.enabled);\n updated[\"type\"] = server.transport;\n setNumberField(\"startup_timeout_sec\", server.startupTimeoutSec);\n setNumberField(\"tool_timeout_sec\", server.toolTimeoutSec);\n setStringArrayField(\"enabled_tools\", server.enabledTools);\n setStringArrayField(\"disabled_tools\", server.disabledTools);\n\n if (server.transport !== \"stdio\") {\n setStringField(\"url\", server.url);\n if (!sanitizeString(server.url)) {\n throw new Error(\"HTTP/SSE MCP server requires a URL.\");\n }\n setStringField(\"bearer_token_env_var\", server.bearerTokenEnvVar);\n setRecordField(\"http_headers\", server.httpHeaders);\n setRecordField(\"env_http_headers\", server.envHttpHeaders);\n delete updated[\"command\"];\n delete updated[\"args\"];\n delete updated[\"env\"];\n delete updated[\"env_vars\"];\n delete updated[\"cwd\"];\n } else {\n setStringField(\"command\", server.command);\n if (!sanitizeString(server.command)) {\n throw new Error(\"STDIO MCP server requires a command.\");\n }\n setStringArrayField(\"args\", server.args);\n setRecordField(\"env\", server.env);\n setStringArrayField(\"env_vars\", server.envVars);\n setStringField(\"cwd\", server.cwd);\n delete updated[\"url\"];\n delete updated[\"bearer_token_env_var\"];\n delete updated[\"http_headers\"];\n delete updated[\"env_http_headers\"];\n }\n\n rawServers[name] = updated;\n if (Object.keys(rawServers).length > 0) {\n next[\"mcp_servers\"] = rawServers;\n } else {\n delete next[\"mcp_servers\"];\n }\n\n const rmcpEnabledValue = rmcpClientEnabled ?? parseRmcpClientEnabled(next);\n return applyRmcpClientFlag(next, rmcpEnabledValue);\n}\n\nfunction applyMcpServerRemoval(current: RawConfig, serverName: string): RawConfig {\n const name = validateMcpServerName(serverName);\n const next: RawConfig = { ...current };\n const rawServers =\n typeof next[\"mcp_servers\"] === \"object\" && next[\"mcp_servers\"] !== null && !Array.isArray(next[\"mcp_servers\"])\n ? { ...(next[\"mcp_servers\"] as RawConfig) }\n : {};\n\n if (!Object.prototype.hasOwnProperty.call(rawServers, name)) {\n return next;\n }\n\n delete rawServers[name];\n if (Object.keys(rawServers).length > 0) {\n next[\"mcp_servers\"] = rawServers;\n } else {\n delete next[\"mcp_servers\"];\n }\n return next;\n}\n\nfunction applyRmcpClientFlag(current: RawConfig, enabled: boolean): RawConfig {\n const next: RawConfig = { ...current };\n const rawFeatures =\n typeof next[\"features\"] === \"object\" && next[\"features\"] !== null && !Array.isArray(next[\"features\"])\n ? { ...(next[\"features\"] as RawConfig) }\n : {};\n\n if (enabled) {\n rawFeatures[\"rmcp_client\"] = true;\n } else {\n delete rawFeatures[\"rmcp_client\"];\n }\n\n if (Object.keys(rawFeatures).length > 0) {\n next[\"features\"] = rawFeatures;\n } else {\n delete next[\"features\"];\n }\n\n delete next[\"experimental_use_rmcp_client\"];\n return next;\n}\n\nasync function readParsedConfigOrThrow(): Promise<RawConfig> {\n const { content } = await readConfigContent();\n const parsed = tryParseToml(content);\n\n if (!parsed.data) {\n throw new Error(parsed.error ?? \"config.toml contains invalid TOML syntax.\");\n }\n\n return parsed.data;\n}\n\nexport async function getCodexConfigSnapshot(): Promise<CodexConfigSnapshotPayload> {\n const { content, exists } = await readConfigContent();\n return buildSnapshot(content, exists);\n}\n\nexport async function saveCodexConfigContent(content: string): Promise<CodexConfigSnapshotPayload> {\n const normalized = ensureTrailingNewline(normalizeLineEndings(content));\n const parsed = tryParseToml(normalized);\n if (!parsed.data) {\n throw new Error(parsed.error ?? \"config.toml contains invalid TOML syntax.\");\n }\n await writeConfigContent(normalized);\n return buildSnapshot(normalized, true);\n}\n\nexport async function updateCodexConfigValues(\n updates: CodexConfigUpdatePayload,\n): Promise<CodexConfigSnapshotPayload> {\n const parsed = await readParsedConfigOrThrow();\n const updated = applyUpdatesToConfig(parsed, updates);\n const serialized = ensureTrailingNewline(stringify(updated as Record<string, any>));\n await writeConfigContent(serialized);\n return buildSnapshot(serialized, true);\n}\n\nexport async function applyYoloOpinionatedMode(): Promise<CodexConfigSnapshotPayload> {\n return updateCodexConfigValues(YOLO_PRESET);\n}\n\nexport async function upsertMcpServer(\n server: McpServerConfig,\n options?: { rmcpClientEnabled?: boolean | null },\n): Promise<CodexConfigSnapshotPayload> {\n const parsed = await readParsedConfigOrThrow();\n const updated = applyMcpServerUpsert(parsed, server, options?.rmcpClientEnabled);\n const serialized = ensureTrailingNewline(stringify(updated as Record<string, any>));\n await writeConfigContent(serialized);\n return buildSnapshot(serialized, true);\n}\n\nexport async function removeMcpServer(serverName: string): Promise<CodexConfigSnapshotPayload> {\n const parsed = await readParsedConfigOrThrow();\n const updated = applyMcpServerRemoval(parsed, serverName);\n const serialized = ensureTrailingNewline(stringify(updated as Record<string, any>));\n await writeConfigContent(serialized);\n return buildSnapshot(serialized, true);\n}\n\nexport async function setRmcpClient(enabled: boolean): Promise<CodexConfigSnapshotPayload> {\n const parsed = await readParsedConfigOrThrow();\n const updated = applyRmcpClientFlag(parsed, enabled);\n const serialized = ensureTrailingNewline(stringify(updated as Record<string, any>));\n await writeConfigContent(serialized);\n return buildSnapshot(serialized, true);\n}\n\nexport async function sanitizeCodexConfigForCli(): Promise<(() => Promise<void>) | null> {\n const { content } = await readConfigContent();\n const parsed = tryParseToml(content);\n\n if (!parsed.data) {\n throw new Error(parsed.error ?? \"config.toml contains invalid TOML syntax.\");\n }\n\n const unsupportedReasoning = getUnsupportedReasoningEffort(parsed.data, CLI_SUPPORTED_REASONING_EFFORT);\n if (!unsupportedReasoning) {\n return null;\n }\n\n const sanitized = { ...(parsed.data as RawConfig) };\n delete sanitized[\"model_reasoning_effort\"];\n const sanitizedContent = ensureTrailingNewline(stringify(sanitized as Record<string, any>));\n await writeConfigContent(sanitizedContent);\n\n let restored = false;\n return async () => {\n if (restored) {\n return;\n }\n restored = true;\n const originalContent = ensureTrailingNewline(normalizeLineEndings(content));\n await writeConfigContent(originalContent);\n };\n}\n\nexport type { McpServerConfig };\n\nexport function isKnownApprovalPolicy(value: string | null): value is \"untrusted\" | \"on-failure\" | \"on-request\" | \"never\" {\n return Boolean(value && KNOWN_APPROVAL_POLICIES.has(value));\n}\n\nexport function isKnownSandboxMode(value: string | null): value is \"read-only\" | \"workspace-write\" | \"danger-full-access\" {\n return Boolean(value && KNOWN_SANDBOX_MODES.has(value));\n}\n","import { spawn } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { requireCodexCli } from \"./codex-cli\";\n\nexport type CodexFeatureStage = \"stable\" | \"experimental\" | \"under development\" | \"deprecated\" | \"unknown\";\n\nexport interface CodexFeatureCatalogEntry {\n key: string;\n stage: CodexFeatureStage;\n enabled: boolean | null;\n}\n\nexport interface CodexConfigMetadata {\n schemaTopLevelKeys: string[];\n schemaFeatureKeys: string[];\n featureCatalog: CodexFeatureCatalogEntry[];\n codexVersion: string | null;\n fetchedAt: number;\n}\n\nconst CONFIG_SCHEMA_URL = \"https://raw.githubusercontent.com/openai/codex/main/codex-rs/core/config.schema.json\";\nconst METADATA_CACHE_TTL_MS = 60_000;\n\nconst FALLBACK_SCHEMA_TOP_LEVEL_KEYS = [\n \"agents\",\n \"analytics\",\n \"approval_policy\",\n \"apps\",\n \"chatgpt_base_url\",\n \"check_for_update_on_startup\",\n \"cli_auth_credentials_store\",\n \"compact_prompt\",\n \"developer_instructions\",\n \"disable_paste_burst\",\n \"experimental_compact_prompt_file\",\n \"experimental_use_freeform_apply_patch\",\n \"experimental_use_unified_exec_tool\",\n \"features\",\n \"feedback\",\n \"file_opener\",\n \"forced_chatgpt_workspace_id\",\n \"forced_login_method\",\n \"ghost_snapshot\",\n \"hide_agent_reasoning\",\n \"history\",\n \"instructions\",\n \"log_dir\",\n \"mcp_oauth_callback_port\",\n \"mcp_oauth_credentials_store\",\n \"mcp_servers\",\n \"model\",\n \"model_auto_compact_token_limit\",\n \"model_context_window\",\n \"model_instructions_file\",\n \"model_provider\",\n \"model_providers\",\n \"model_reasoning_effort\",\n \"model_reasoning_summary\",\n \"model_supports_reasoning_summaries\",\n \"model_verbosity\",\n \"notice\",\n \"notify\",\n \"oss_provider\",\n \"otel\",\n \"personality\",\n \"profile\",\n \"profiles\",\n \"project_doc_fallback_filenames\",\n \"project_doc_max_bytes\",\n \"project_root_markers\",\n \"projects\",\n \"review_model\",\n \"sandbox_mode\",\n \"sandbox_workspace_write\",\n \"shell_environment_policy\",\n \"show_raw_agent_reasoning\",\n \"skills\",\n \"suppress_unstable_features_warning\",\n \"tool_output_token_limit\",\n \"tools\",\n \"tui\",\n \"web_search\",\n \"windows_wsl_setup_acknowledged\",\n];\n\nconst FALLBACK_FEATURE_KEYS = [\n \"apply_patch_freeform\",\n \"apps\",\n \"child_agents_md\",\n \"collab\",\n \"collaboration_modes\",\n \"connectors\",\n \"elevated_windows_sandbox\",\n \"enable_experimental_windows_sandbox\",\n \"enable_request_compression\",\n \"experimental_use_freeform_apply_patch\",\n \"experimental_use_unified_exec_tool\",\n \"experimental_windows_sandbox\",\n \"include_apply_patch_tool\",\n \"memory_tool\",\n \"personality\",\n \"powershell_utf8\",\n \"remote_models\",\n \"request_rule\",\n \"responses_websockets\",\n \"responses_websockets_v2\",\n \"runtime_metrics\",\n \"search_tool\",\n \"shell_snapshot\",\n \"shell_tool\",\n \"skill_env_var_dependency_prompt\",\n \"skill_mcp_dependency_install\",\n \"sqlite\",\n \"steer\",\n \"undo\",\n \"unified_exec\",\n \"use_linux_sandbox_bwrap\",\n \"web_search\",\n \"web_search_cached\",\n \"web_search_request\",\n];\n\nlet metadataCache: CodexConfigMetadata | null = null;\nlet metadataCacheAt = 0;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort((a, b) => a.localeCompare(b));\n}\n\nasync function runCommand(\n command: string,\n args: string[],\n timeoutMs = 3_000,\n): Promise<{ stdout: string; exitCode: number | null }> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: process.env,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", chunk => {\n stdout += chunk.toString();\n });\n\n child.stderr?.on(\"data\", chunk => {\n stderr += chunk.toString();\n });\n\n const timeout = setTimeout(() => {\n child.kill();\n reject(new Error(`Command timed out: ${command} ${args.join(\" \")}`));\n }, timeoutMs);\n\n child.on(\"error\", error => {\n clearTimeout(timeout);\n reject(error);\n });\n\n child.on(\"close\", code => {\n clearTimeout(timeout);\n if (code !== 0 && !stdout.trim() && stderr.trim()) {\n resolve({ stdout: stderr, exitCode: code });\n return;\n }\n resolve({ stdout, exitCode: code });\n });\n });\n}\n\nasync function runCodexCommand(args: string[]): Promise<{ stdout: string; exitCode: number | null }> {\n const codexPath = await requireCodexCli();\n const isJsLauncher = codexPath.endsWith(\".js\");\n const command = isJsLauncher ? process.execPath : codexPath;\n const commandArgs = isJsLauncher ? [codexPath, ...args] : args;\n return runCommand(command, commandArgs);\n}\n\nfunction parseFeatureCatalog(output: string): CodexFeatureCatalogEntry[] {\n const entries: CodexFeatureCatalogEntry[] = [];\n const lines = output.split(/\\r?\\n/).map(line => line.trim()).filter(Boolean);\n\n for (const line of lines) {\n const match = line.match(/^(\\S+)\\s+(stable|experimental|deprecated|under development)\\s+(true|false)$/i);\n if (!match) {\n continue;\n }\n const [, key, stageRaw, enabledRaw] = match;\n const stage = stageRaw.toLowerCase() as Exclude<CodexFeatureStage, \"unknown\">;\n entries.push({\n key,\n stage,\n enabled: enabledRaw === \"true\",\n });\n }\n\n return entries.sort((a, b) => a.key.localeCompare(b.key));\n}\n\nfunction parseSchemaKeys(schemaRaw: string): { topLevelKeys: string[]; featureKeys: string[] } {\n const parsed = JSON.parse(schemaRaw) as unknown;\n if (!isRecord(parsed)) {\n return {\n topLevelKeys: FALLBACK_SCHEMA_TOP_LEVEL_KEYS,\n featureKeys: FALLBACK_FEATURE_KEYS,\n };\n }\n\n const properties = isRecord(parsed.properties) ? parsed.properties : {};\n const topLevelKeys = uniqueSorted(Object.keys(properties));\n\n const features = isRecord(properties.features) ? properties.features : {};\n const featureProperties = isRecord(features.properties) ? features.properties : {};\n const featureKeys = uniqueSorted(Object.keys(featureProperties));\n\n return {\n topLevelKeys: topLevelKeys.length > 0 ? topLevelKeys : FALLBACK_SCHEMA_TOP_LEVEL_KEYS,\n featureKeys: featureKeys.length > 0 ? featureKeys : FALLBACK_FEATURE_KEYS,\n };\n}\n\nasync function readSchemaFromLocal(): Promise<string | null> {\n const candidates = [\n process.env.CODEX_CONFIG_SCHEMA_PATH,\n path.join(process.cwd(), \"codex-rs\", \"core\", \"config.schema.json\"),\n path.join(process.cwd(), \"node_modules\", \"@openai\", \"codex\", \"codex-rs\", \"core\", \"config.schema.json\"),\n ].filter((candidate): candidate is string => Boolean(candidate));\n\n for (const candidate of candidates) {\n try {\n return await readFile(candidate, \"utf8\");\n } catch {\n // Continue to next candidate.\n }\n }\n\n return null;\n}\n\nasync function readSchemaFromRemote(): Promise<string | null> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 2_500);\n\n try {\n const response = await fetch(CONFIG_SCHEMA_URL, {\n signal: controller.signal,\n headers: {\n \"User-Agent\": \"codexuse-desktop\",\n },\n });\n\n if (!response.ok) {\n return null;\n }\n\n return await response.text();\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nasync function readSchemaKeys(): Promise<{ topLevelKeys: string[]; featureKeys: string[] }> {\n const local = await readSchemaFromLocal();\n if (local) {\n try {\n return parseSchemaKeys(local);\n } catch {\n // Fallback to remote/fallback sets.\n }\n }\n\n const remote = await readSchemaFromRemote();\n if (remote) {\n try {\n return parseSchemaKeys(remote);\n } catch {\n // Fallback below.\n }\n }\n\n return {\n topLevelKeys: FALLBACK_SCHEMA_TOP_LEVEL_KEYS,\n featureKeys: FALLBACK_FEATURE_KEYS,\n };\n}\n\nasync function readCodexVersion(): Promise<string | null> {\n try {\n const { stdout } = await runCodexCommand([\"--version\"]);\n const value = stdout.trim();\n return value.length > 0 ? value : null;\n } catch {\n return null;\n }\n}\n\nasync function readFeatureCatalog(): Promise<CodexFeatureCatalogEntry[]> {\n try {\n const { stdout } = await runCodexCommand([\"features\", \"list\"]);\n return parseFeatureCatalog(stdout);\n } catch {\n return [];\n }\n}\n\nexport async function getCodexConfigMetadata(forceRefresh = false): Promise<CodexConfigMetadata> {\n const now = Date.now();\n if (!forceRefresh && metadataCache && (now - metadataCacheAt) < METADATA_CACHE_TTL_MS) {\n return metadataCache;\n }\n\n const [schemaKeys, featureCatalog, codexVersion] = await Promise.all([\n readSchemaKeys(),\n readFeatureCatalog(),\n readCodexVersion(),\n ]);\n\n const catalogMap = new Map<string, CodexFeatureCatalogEntry>();\n for (const entry of featureCatalog) {\n catalogMap.set(entry.key, entry);\n }\n\n for (const featureKey of schemaKeys.featureKeys) {\n if (!catalogMap.has(featureKey)) {\n catalogMap.set(featureKey, {\n key: featureKey,\n stage: \"unknown\",\n enabled: null,\n });\n }\n }\n\n const mergedFeatureCatalog = Array.from(catalogMap.values()).sort((a, b) => a.key.localeCompare(b.key));\n\n const metadata: CodexConfigMetadata = {\n schemaTopLevelKeys: uniqueSorted(schemaKeys.topLevelKeys),\n schemaFeatureKeys: uniqueSorted(schemaKeys.featureKeys),\n featureCatalog: mergedFeatureCatalog,\n codexVersion,\n fetchedAt: now,\n };\n\n metadataCache = metadata;\n metadataCacheAt = now;\n return metadata;\n}\n","import { readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { CodexCliInfoPayload, CodexCliStatusPayload } from \"./ipc-types\";\nimport type { CodexCliChannel } from \"./codex-cli-channel\";\n\ntype MutableStatus = CodexCliStatusPayload;\nconst STABLE_CHANNEL: CodexCliChannel = \"stable\";\nconst ENV_HINTS = [\"CODEX_BINARY\", \"CODEX_CLI_PATH\", \"CODEX_PATH\"] as const;\n\nlet cachedStatus: MutableStatus | null = null;\n\nfunction fileExists(candidate: string | undefined | null): string | null {\n if (!candidate) {\n return null;\n }\n\n const normalized = path.resolve(candidate);\n\n try {\n const stats = statSync(normalized);\n if (stats.isFile()) {\n return normalized;\n }\n } catch {\n // ignore missing paths\n }\n\n return null;\n}\n\nfunction resolveBundledCodexBinary(): string | null {\n const candidates: string[] = [];\n const processWithResources = process as NodeJS.Process & { resourcesPath?: string };\n const resourcesPath = processWithResources.resourcesPath;\n const packageSegments = [\"@openai\", \"codex\"];\n\n if (resourcesPath) {\n candidates.push(\n path.join(resourcesPath, \"app.asar.unpacked\", \"node_modules\", ...packageSegments, \"bin\", \"codex.js\"),\n );\n candidates.push(\n path.join(resourcesPath, \"app.asar.unpacked\", \"node_modules\", ...packageSegments, \"bin\", \"codex\"),\n );\n }\n\n const projectRoot = process.cwd();\n candidates.push(path.join(projectRoot, \"node_modules\", ...packageSegments, \"bin\", \"codex.js\"));\n candidates.push(path.join(projectRoot, \"node_modules\", ...packageSegments, \"bin\", \"codex\"));\n\n for (const candidate of candidates) {\n const resolved = fileExists(candidate);\n if (resolved) {\n return resolved;\n }\n }\n\n return null;\n}\n\nfunction isElectronRuntime(): boolean {\n return typeof process.versions?.electron === \"string\" && process.versions.electron.length > 0;\n}\n\nfunction resolveCodexFromEnv(): string | null {\n for (const key of ENV_HINTS) {\n const value = process.env[key];\n if (!value) {\n continue;\n }\n const resolved = fileExists(value);\n if (resolved) {\n return resolved;\n }\n }\n return null;\n}\n\nfunction resolveCodexFromNodeModules(): string | null {\n const packageSegments = [\"@openai\", \"codex\", \"bin\"];\n const fileNames = [\"codex.js\", \"codex\"];\n\n let current = path.resolve(__dirname);\n let last = \"\";\n while (current !== last) {\n for (const fileName of fileNames) {\n const candidate = fileExists(\n path.join(current, \"node_modules\", ...packageSegments, fileName),\n );\n if (candidate) {\n return candidate;\n }\n }\n last = current;\n current = path.dirname(current);\n }\n return null;\n}\n\nfunction resolveCodexFromPath(): string | null {\n const pathValue = process.env.PATH ?? \"\";\n if (!pathValue) {\n return null;\n }\n const entries = pathValue\n .split(path.delimiter)\n .map(entry => entry.trim())\n .filter(Boolean);\n const names = process.platform === \"win32\"\n ? [\"codex.exe\", \"codex.cmd\", \"codex.bat\", \"codex\"]\n : [\"codex\"];\n\n for (const entry of entries) {\n for (const name of names) {\n const candidate = fileExists(path.join(entry, name));\n if (candidate) {\n return candidate;\n }\n }\n }\n return null;\n}\n\nfunction resolvePackageJsonPath(cliPath: string): string | null {\n const normalized = path.resolve(cliPath);\n const binDir = path.dirname(normalized);\n const packageDir = path.basename(binDir) === \"bin\" ? path.dirname(binDir) : path.dirname(normalized);\n const pkgPath = path.join(packageDir, \"package.json\");\n return fileExists(pkgPath);\n}\n\nfunction readCodexCliVersion(cliPath: string): string | null {\n const packageJsonPath = resolvePackageJsonPath(cliPath);\n if (!packageJsonPath) {\n return null;\n }\n try {\n const raw = readFileSync(packageJsonPath, \"utf8\");\n const parsed = JSON.parse(raw) as { version?: unknown };\n if (typeof parsed?.version !== \"string\") {\n return null;\n }\n const normalized = parsed.version.trim();\n return normalized.length > 0 ? normalized : null;\n } catch {\n return null;\n }\n}\n\nfunction buildUnavailableStatus(reason?: string): MutableStatus {\n return {\n available: false,\n path: null,\n reason: reason ?? \"Codex CLI not found. Install @openai/codex or set CODEX_BINARY.\",\n source: null,\n channel: STABLE_CHANNEL,\n };\n}\n\nfunction evaluateBundledOnlyStatus(): MutableStatus {\n const resolvedPath = resolveBundledCodexBinary();\n if (resolvedPath) {\n return {\n available: true,\n path: resolvedPath,\n reason: null,\n source: \"bundled\",\n channel: STABLE_CHANNEL,\n };\n }\n\n return buildUnavailableStatus(\"Bundled Codex CLI is missing. Reinstall CodexUse.\");\n}\n\nfunction evaluateExternalStatus(): MutableStatus {\n const envPath = resolveCodexFromEnv();\n if (envPath) {\n return {\n available: true,\n path: envPath,\n reason: null,\n source: \"env\",\n channel: STABLE_CHANNEL,\n };\n }\n\n const nodeModulesPath = resolveCodexFromNodeModules();\n if (nodeModulesPath) {\n return {\n available: true,\n path: nodeModulesPath,\n reason: null,\n source: \"node_modules\",\n channel: STABLE_CHANNEL,\n };\n }\n\n const pathResolved = resolveCodexFromPath();\n if (pathResolved) {\n return {\n available: true,\n path: pathResolved,\n reason: null,\n source: \"path\",\n channel: STABLE_CHANNEL,\n };\n }\n\n return buildUnavailableStatus();\n}\n\nfunction evaluateCodexCliStatus(): MutableStatus {\n const bundledStatus = evaluateBundledOnlyStatus();\n if (bundledStatus.available) {\n return bundledStatus;\n }\n\n const externalStatus = evaluateExternalStatus();\n if (externalStatus.available) {\n return externalStatus;\n }\n\n // In Electron, keep a bundled-first failure reason when all fallbacks miss.\n if (isElectronRuntime()) {\n return bundledStatus;\n }\n\n return externalStatus;\n}\n\nexport async function refreshCodexStatus(): Promise<CodexCliStatusPayload> {\n cachedStatus = evaluateCodexCliStatus();\n return { ...cachedStatus };\n}\n\nexport async function getCodexCliStatus(): Promise<CodexCliStatusPayload> {\n if (!cachedStatus) {\n return refreshCodexStatus();\n }\n return { ...cachedStatus };\n}\n\nexport async function getCodexCliInfo(): Promise<CodexCliInfoPayload> {\n const status = await getCodexCliStatus();\n const version =\n status.available && status.path\n ? readCodexCliVersion(status.path)\n : null;\n return { ...status, version };\n}\n\nexport class CodexCliMissingError extends Error {\n readonly status: CodexCliStatusPayload;\n\n constructor(status: CodexCliStatusPayload, message?: string) {\n super(message ?? status.reason ?? \"Codex CLI is not available\");\n Object.setPrototypeOf(this, new.target.prototype);\n this.name = \"CodexCliMissingError\";\n this.status = { ...status };\n }\n}\n\nexport async function requireCodexCli(): Promise<string> {\n const status = await refreshCodexStatus();\n if (!status.available || !status.path) {\n throw new CodexCliMissingError(status);\n }\n return status.path;\n}\n","/* eslint-disable-next-line no-control-regex */\nconst ANSI_PATTERN = /\\u001B\\[[0-9;]*m/g;\n\nfunction stripAnsi(value: string): string {\n return value.replace(ANSI_PATTERN, \"\");\n}\n\nfunction normalizeWhitespace(value: string): string {\n return value.replace(/\\s+/g, \" \").trim();\n}\n\nexport function compactErrorText(value: string, maxLength = 220): string {\n if (!value) {\n return \"\";\n }\n const cleaned = normalizeWhitespace(stripAnsi(String(value)));\n if (!cleaned) {\n return \"\";\n }\n if (cleaned.length <= maxLength) {\n return cleaned;\n }\n return `${cleaned.slice(0, maxLength).trimEnd()}…`;\n}\n\nexport function formatUserFacingError(\n error: unknown,\n options: {\n fallback?: string;\n notFoundFallback?: string;\n maxLength?: number;\n } = {},\n): string {\n const fallback = options.fallback ?? \"Something went wrong. Please try again.\";\n if (error === null || typeof error === \"undefined\") {\n return fallback;\n }\n\n const rawMessage =\n typeof error === \"string\"\n ? error\n : error instanceof Error\n ? error.message\n : String(error);\n\n let cleaned = normalizeWhitespace(stripAnsi(rawMessage));\n if (!cleaned) {\n return fallback;\n }\n\n // Strip Electron IPC error prefix\n if (cleaned.startsWith(\"Error invoking remote method\")) {\n cleaned = cleaned.replace(/^Error invoking remote method '[^']+': Error: /, \"\");\n }\n\n const lower = cleaned.toLowerCase();\n\n if (options.notFoundFallback && (lower.includes(\"enoent\") || lower.includes(\"not found\"))) {\n return options.notFoundFallback;\n }\n\n if (lower.includes(\"rate limit\") || lower.includes(\"quota exceeded\") || lower.includes(\"too many requests\") || lower.includes(\"429\")) {\n cleaned = \"Rate limit exceeded. Please wait a moment or upgrade your plan.\";\n } else if (lower.includes(\"timeout\") || lower.includes(\"timed out\")) {\n cleaned = \"Request timed out. Check your connection and try again.\";\n } else if (\n lower.includes(\"network\") ||\n lower.includes(\"econn\") ||\n lower.includes(\"networkerror\") ||\n lower.includes(\"connection\")\n ) {\n cleaned = \"Network issue. Check your connection and retry.\";\n } else if (lower.includes(\"permission\") || lower.includes(\"eacces\")) {\n cleaned = \"Permission denied. Restart CodexUse and retry.\";\n } else if (lower.includes(\"openai codex\") && lower.includes(\"workdir:\")) {\n // If it's just the CLI banner, it's likely a generic failure or the actual error is buried.\n // We'll try to find a more specific error message within it, or default to a generic one.\n if (lower.includes(\"error:\")) {\n // Try to extract the part after \"error:\"\n const parts = cleaned.split(/error:/i);\n if (parts.length > 1) {\n cleaned = parts[parts.length - 1].trim();\n }\n } else {\n cleaned = \"Codex CLI failed to respond. Please try again.\";\n }\n }\n\n const maxLength = typeof options.maxLength === \"number\" ? options.maxLength : 220;\n if (cleaned.length > maxLength) {\n cleaned = `${cleaned.slice(0, maxLength).trimEnd()}…`;\n }\n\n return cleaned;\n}\n","import { licenseService, shouldEnforceProfileLimit } from \"./license-service\";\nimport { ProfileManager } from \"./profile-manager\";\n\nexport const PROJECT_LIMIT_MESSAGE =\n \"CodexUse Free supports up to 2 projects. Upgrade to CodexUse Pro for unlimited projects.\";\n\nexport async function assertProfileCreationAllowed(\n profileManager?: ProfileManager,\n): Promise<void> {\n const manager = profileManager ?? new ProfileManager();\n await manager.initialize();\n\n const license = await licenseService.getStatus();\n const profiles = await manager.listProfiles();\n const licenseWithCounts = licenseService.applyProfileCount(license, profiles.length);\n\n if (\n typeof licenseWithCounts.profileLimit === \"number\" &&\n licenseWithCounts.profilesRemaining !== null &&\n licenseWithCounts.profilesRemaining <= 0\n ) {\n throw new Error(\"CodexUse Free supports up to 2 profiles. Upgrade to CodexUse Pro for unlimited profiles.\");\n }\n}\n\ntype WorkspaceLike = {\n kind?: string | null;\n};\n\nfunction countMainProjects(workspaces: WorkspaceLike[]): number {\n return workspaces.filter((workspace) => (workspace.kind ?? \"main\") !== \"worktree\").length;\n}\n\nexport async function assertProjectCreationAllowed(\n workspaces: WorkspaceLike[],\n): Promise<void> {\n const license = await licenseService.getStatus();\n if (!shouldEnforceProfileLimit(license)) {\n return;\n }\n\n const mainProjectCount = countMainProjects(workspaces);\n if (mainProjectCount >= 2) {\n throw new Error(PROJECT_LIMIT_MESSAGE);\n }\n}\n","import { spawn } from \"node:child_process\";\nimport { statSync } from \"node:fs\";\nimport path from \"node:path\";\n\nconst ENV_HINTS = [\"CODEX_BINARY\", \"CODEX_CLI_PATH\", \"CODEX_PATH\"] as const;\n\nexport type CodexLoginMode = \"browser\" | \"device\";\n\nfunction fileExists(candidate: string | null | undefined): string | null {\n if (!candidate) return null;\n const resolved = path.resolve(candidate);\n try {\n const stat = statSync(resolved);\n if (stat.isFile()) return resolved;\n } catch {\n return null;\n }\n return null;\n}\n\nfunction resolveFromEnv(): string | null {\n for (const key of ENV_HINTS) {\n const value = process.env[key];\n if (!value) continue;\n const resolved = fileExists(value);\n if (resolved) return resolved;\n }\n return null;\n}\n\nfunction resolveFromPath(): string | null {\n const pathValue = process.env.PATH ?? \"\";\n const entries = pathValue.split(path.delimiter).filter(Boolean);\n const names = process.platform === \"win32\"\n ? [\"codex.exe\", \"codex.cmd\", \"codex.bat\", \"codex\"]\n : [\"codex\"];\n\n for (const entry of entries) {\n for (const name of names) {\n const candidate = fileExists(path.join(entry, name));\n if (candidate) return candidate;\n }\n }\n\n return null;\n}\n\nexport function resolveCodexBinary(): string | null {\n return (\n resolveFromEnv() ||\n resolveFromPath()\n );\n}\n\nexport function requireCodexBinary(context?: string): string {\n const resolved = resolveCodexBinary();\n if (resolved) return resolved;\n const hint = \"Install Codex CLI (npm i -g @openai/codex) or set CODEX_BINARY.\";\n const message = context ? `${context} ${hint}` : hint;\n throw new Error(message);\n}\n\nfunction buildCodexCommand(codexPath: string, args: string[]): { command: string; args: string[]; shell: boolean } {\n const normalized = codexPath.toLowerCase();\n const isJs = normalized.endsWith(\".js\");\n if (isJs) {\n return { command: process.execPath, args: [codexPath, ...args], shell: false };\n }\n\n const useShell = process.platform === \"win32\";\n return { command: codexPath, args, shell: useShell };\n}\n\nfunction isHeadless(): boolean {\n if (process.env.CODEXUSE_HEADLESS === \"1\") return true;\n if (process.env.CI) return true;\n if (process.env.SSH_CONNECTION || process.env.SSH_TTY) return true;\n if (process.platform === \"linux\") {\n if (!process.env.DISPLAY && !process.env.WAYLAND_DISPLAY) return true;\n }\n return false;\n}\n\nexport function resolveLoginMode(preferred?: CodexLoginMode | null): CodexLoginMode {\n if (preferred === \"browser\" || preferred === \"device\") {\n return preferred;\n }\n const envMode = process.env.CODEXUSE_LOGIN_MODE;\n if (envMode === \"browser\" || envMode === \"device\") {\n return envMode;\n }\n return isHeadless() ? \"device\" : \"browser\";\n}\n\nexport async function runCodexLogin(mode?: CodexLoginMode | null): Promise<void> {\n const codexPath = requireCodexBinary(\"Codex CLI is required to login.\");\n const resolvedMode = resolveLoginMode(mode ?? null);\n const loginArgs = resolvedMode === \"device\"\n ? [\"login\", \"--device-auth\"]\n : [\"login\"];\n const { command, args, shell } = buildCodexCommand(codexPath, loginArgs);\n\n const child = spawn(command, args, {\n stdio: \"inherit\",\n env: process.env,\n shell,\n });\n\n const exitCode = await new Promise<number>((resolve) => {\n child.on(\"close\", (code) => resolve(code ?? 0));\n });\n\n if (exitCode !== 0) {\n throw new Error(`Codex CLI login failed (exit code ${exitCode}).`);\n }\n}\n","import { spawn } from \"node:child_process\";\nimport readline from \"node:readline\";\nimport { promises as fs } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { requireCodexCli } from \"./codex-cli\";\nimport { logWarn } from \"./logger\";\nimport type { RateLimitSnapshot, RateLimitWindow } from \"./types\";\n\ntype RpcError = {\n code?: number;\n message?: string;\n data?: unknown;\n};\n\ntype RpcMessage = {\n id?: number | string | null;\n method?: string;\n result?: unknown;\n error?: RpcError;\n};\n\ntype RpcRateLimitWindow = {\n usedPercent?: number;\n windowDurationMins?: number;\n resetsAt?: number;\n};\n\ntype RpcRateLimitSnapshot = {\n primary?: RpcRateLimitWindow | null;\n secondary?: RpcRateLimitWindow | null;\n};\n\nconst RPC_TIMEOUT_MS = 10_000;\nconst MAX_STDERR_CAPTURE_CHARS = 32_768;\nconst REFRESH_TOKEN_REDEEMED_SNIPPET = \"refresh token was already used\";\n\ntype AuthRecord = {\n last_refresh?: unknown;\n access_token?: unknown;\n tokens?: {\n last_refresh?: unknown;\n access_token?: unknown;\n };\n};\n\nfunction parseTimestamp(value: unknown): number | null {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n return null;\n }\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? null : parsed;\n}\n\nfunction decodeJwtPayload(token: unknown): Record<string, unknown> | null {\n if (typeof token !== \"string\" || token.trim().length === 0) {\n return null;\n }\n\n const segments = token.split(\".\");\n if (segments.length < 2) {\n return null;\n }\n\n try {\n const payloadRaw = Buffer.from(segments[1], \"base64url\").toString(\"utf8\");\n const payload = JSON.parse(payloadRaw);\n return payload && typeof payload === \"object\" ? (payload as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\nfunction extractJwtIssuedAtMs(token: unknown): number | null {\n const payload = decodeJwtPayload(token);\n if (!payload) {\n return null;\n }\n\n const issuedAt = payload[\"iat\"];\n if (typeof issuedAt !== \"number\" || !Number.isFinite(issuedAt)) {\n return null;\n }\n\n return issuedAt * 1000;\n}\n\nfunction parseAuthRecord(content: string): AuthRecord | null {\n try {\n const parsed = JSON.parse(content);\n return parsed && typeof parsed === \"object\" ? (parsed as AuthRecord) : null;\n } catch {\n return null;\n }\n}\n\nfunction extractAuthRecencyMs(content: string): number | null {\n const parsed = parseAuthRecord(content);\n if (!parsed) {\n return null;\n }\n\n const rootLastRefresh = parseTimestamp(parsed.last_refresh);\n const nestedLastRefresh = parseTimestamp(parsed.tokens?.last_refresh);\n const rootAccessIssuedAt = extractJwtIssuedAtMs(parsed.access_token);\n const nestedAccessIssuedAt = extractJwtIssuedAtMs(parsed.tokens?.access_token);\n const candidates = [rootLastRefresh, nestedLastRefresh, rootAccessIssuedAt, nestedAccessIssuedAt]\n .filter((value): value is number => typeof value === \"number\" && Number.isFinite(value));\n\n if (candidates.length === 0) {\n return null;\n }\n\n return Math.max(...candidates);\n}\n\nfunction shouldWriteBackAuth(\n initialSourceAuth: string | null,\n currentSourceAuth: string | null,\n updatedAuth: string,\n): boolean {\n if (updatedAuth.trim().length === 0) {\n return false;\n }\n\n if (!currentSourceAuth) {\n return true;\n }\n\n if (currentSourceAuth === updatedAuth) {\n return false;\n }\n\n if (currentSourceAuth === initialSourceAuth) {\n return true;\n }\n\n const currentRecency = extractAuthRecencyMs(currentSourceAuth);\n const updatedRecency = extractAuthRecencyMs(updatedAuth);\n\n if (typeof updatedRecency === \"number\" && typeof currentRecency === \"number\") {\n return updatedRecency > currentRecency;\n }\n\n if (typeof updatedRecency === \"number\" && typeof currentRecency !== \"number\") {\n return true;\n }\n\n return false;\n}\n\nfunction inferRefreshFailureHint(stderrOutput: string): string | null {\n if (!stderrOutput) {\n return null;\n }\n\n const normalized = stderrOutput.toLowerCase();\n if (normalized.includes(REFRESH_TOKEN_REDEEMED_SNIPPET)) {\n return REFRESH_TOKEN_REDEEMED_SNIPPET;\n }\n\n return null;\n}\n\nasync function sendPayload(\n child: ReturnType<typeof spawn>,\n payload: Record<string, unknown>,\n): Promise<void> {\n child.stdin?.write(JSON.stringify(payload));\n child.stdin?.write(\"\\n\");\n}\n\nfunction isRpcResponseForRequest(message: RpcMessage, requestId: number): boolean {\n if (message.id !== requestId) {\n return false;\n }\n return (\n Object.prototype.hasOwnProperty.call(message, \"result\") ||\n Object.prototype.hasOwnProperty.call(message, \"error\")\n );\n}\n\nexport async function readRpcResponseById(\n rl: readline.Interface,\n requestId: number,\n timeoutMs: number,\n): Promise<RpcMessage> {\n return new Promise<RpcMessage>((resolve, reject) => {\n const timer = setTimeout(() => {\n cleanup();\n reject(new Error(\"codex RPC timed out\"));\n }, Math.max(1, timeoutMs));\n\n const cleanup = () => {\n clearTimeout(timer);\n rl.off(\"line\", onLine);\n rl.off(\"close\", onClose);\n };\n\n const onClose = () => {\n cleanup();\n reject(new Error(\"codex RPC stream closed before response\"));\n };\n\n const onLine = (line: string) => {\n let parsed: RpcMessage;\n try {\n parsed = JSON.parse(line) as RpcMessage;\n } catch {\n cleanup();\n reject(new Error(\"codex RPC returned malformed JSON\"));\n return;\n }\n\n if (!isRpcResponseForRequest(parsed, requestId)) {\n return;\n }\n\n cleanup();\n resolve(parsed);\n };\n\n rl.on(\"line\", onLine);\n rl.on(\"close\", onClose);\n });\n}\n\nfunction formatRpcError(method: string, error: RpcError): string {\n const codeText = typeof error.code === \"number\" ? ` (code ${error.code})` : \"\";\n const message =\n typeof error.message === \"string\" && error.message.trim().length > 0\n ? error.message.trim()\n : \"Unknown RPC error\";\n return `${method} failed${codeText}: ${message}`;\n}\n\nfunction toWindow(rpc?: RpcRateLimitWindow | null): RateLimitWindow | undefined {\n if (!rpc) return undefined;\n const usedPercent =\n typeof rpc.usedPercent === \"number\" && Number.isFinite(rpc.usedPercent)\n ? rpc.usedPercent\n : undefined;\n const windowMinutes =\n typeof rpc.windowDurationMins === \"number\" && Number.isFinite(rpc.windowDurationMins)\n ? rpc.windowDurationMins\n : undefined;\n\n let resetsAt: string | undefined;\n let resetsInSeconds: number | undefined;\n if (typeof rpc.resetsAt === \"number\" && Number.isFinite(rpc.resetsAt)) {\n const ms = rpc.resetsAt > 10_000_000_000 ? rpc.resetsAt : rpc.resetsAt * 1000;\n resetsAt = new Date(ms).toISOString();\n resetsInSeconds = Math.max(0, Math.round((ms - Date.now()) / 1000));\n }\n\n if (\n typeof usedPercent === \"undefined\" &&\n typeof windowMinutes === \"undefined\" &&\n typeof resetsAt === \"undefined\"\n ) {\n return undefined;\n }\n\n const window: RateLimitWindow = {};\n if (typeof usedPercent === \"number\") {\n window.usedPercent = usedPercent;\n }\n if (typeof windowMinutes === \"number\") {\n window.windowMinutes = windowMinutes;\n }\n if (typeof resetsAt === \"string\") {\n window.resetsAt = resetsAt;\n }\n if (typeof resetsInSeconds === \"number\") {\n window.resetsInSeconds = resetsInSeconds;\n }\n return window;\n}\n\nexport function parseRateLimitSnapshotFromRpcMessage(\n message: RpcMessage,\n): RateLimitSnapshot | null {\n if (message.error) {\n throw new Error(formatRpcError(\"account/rateLimits/read\", message.error));\n }\n\n const result = message.result as { rateLimits?: RpcRateLimitSnapshot } | undefined;\n const limits = result?.rateLimits;\n const primary = toWindow(limits?.primary ?? null);\n const secondary = toWindow(limits?.secondary ?? null);\n\n if (!primary && !secondary) {\n return null;\n }\n\n const snapshot: RateLimitSnapshot = {\n lastUpdated: new Date().toISOString(),\n source: \"codex-rpc\",\n };\n if (primary) {\n snapshot.primary = primary;\n }\n if (secondary) {\n snapshot.secondary = secondary;\n }\n return snapshot;\n}\n\nexport async function fetchRateLimitsViaRpc(\n envOverride?: NodeJS.ProcessEnv,\n options: { authPath?: string; codexPath?: string } = {},\n): Promise<RateLimitSnapshot | null> {\n const binaryPath = options.codexPath ?? await requireCodexCli();\n const tempHome = await fs.mkdtemp(path.join(os.tmpdir(), \"codex-rpc-\"));\n const tempAuthPath = path.join(tempHome, \"auth.json\");\n let initialSourceAuth: string | null = null;\n\n const sourceAuthPath =\n options.authPath ??\n (envOverride?.CODEX_HOME\n ? path.join(envOverride.CODEX_HOME, \"auth.json\")\n : path.join(\n envOverride?.HOME ?? process.env.HOME ?? process.env.USERPROFILE ?? os.homedir(),\n \".codex\",\n \"auth.json\",\n ));\n\n try {\n initialSourceAuth = await fs.readFile(sourceAuthPath, \"utf8\").catch(() => null);\n if (!initialSourceAuth) {\n return null;\n }\n await fs.writeFile(tempAuthPath, initialSourceAuth, \"utf8\");\n } catch {\n await fs.rm(tempHome, { recursive: true, force: true }).catch(() => {});\n return null;\n }\n\n const child = spawn(process.execPath, [binaryPath, \"-s\", \"read-only\", \"-a\", \"untrusted\", \"app-server\"], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: {\n ...process.env,\n ...(envOverride ?? {}),\n HOME: tempHome,\n USERPROFILE: tempHome,\n CODEX_HOME: tempHome,\n CODEX_TELEMETRY_LABEL: \"codex-rpc\",\n ELECTRON_RUN_AS_NODE: \"1\",\n },\n });\n\n const rl = readline.createInterface({\n input: child.stdout!,\n crlfDelay: Infinity,\n });\n let stderrOutput = \"\";\n child.stderr?.on(\"data\", chunk => {\n if (stderrOutput.length >= MAX_STDERR_CAPTURE_CHARS) {\n return;\n }\n const text = chunk.toString(\"utf8\");\n const remaining = MAX_STDERR_CAPTURE_CHARS - stderrOutput.length;\n stderrOutput += text.slice(0, Math.max(0, remaining));\n });\n\n try {\n await sendPayload(child, {\n id: 1,\n method: \"initialize\",\n params: { clientInfo: { name: \"codexuse\", version: \"0.0.0\" } },\n });\n const initializeResponse = await readRpcResponseById(rl, 1, RPC_TIMEOUT_MS);\n if (initializeResponse.error) {\n throw new Error(formatRpcError(\"initialize\", initializeResponse.error));\n }\n\n await sendPayload(child, { method: \"initialized\", params: {} });\n\n await sendPayload(child, { id: 2, method: \"account/rateLimits/read\", params: {} });\n const message = await readRpcResponseById(rl, 2, RPC_TIMEOUT_MS);\n if (message.error) {\n const base = formatRpcError(\"account/rateLimits/read\", message.error);\n const hint = inferRefreshFailureHint(stderrOutput);\n if (hint && !base.toLowerCase().includes(hint)) {\n throw new Error(`${base}; ${hint}`);\n }\n throw new Error(base);\n }\n\n return parseRateLimitSnapshotFromRpcMessage(message);\n } finally {\n child.kill();\n rl.close();\n try {\n const updatedAuth = await fs.readFile(tempAuthPath, \"utf8\");\n if (updatedAuth.trim().length > 0) {\n const currentSourceAuth = await fs.readFile(sourceAuthPath, \"utf8\").catch(() => null);\n if (shouldWriteBackAuth(initialSourceAuth, currentSourceAuth, updatedAuth)) {\n await fs.writeFile(sourceAuthPath, updatedAuth, \"utf8\");\n } else if (\n currentSourceAuth &&\n currentSourceAuth !== updatedAuth &&\n currentSourceAuth !== initialSourceAuth\n ) {\n logWarn(\"Skipped stale auth sync-back after rate-limit probe; source auth changed in flight.\", {\n sourceAuthPath,\n currentRecencyMs: extractAuthRecencyMs(currentSourceAuth),\n updatedRecencyMs: extractAuthRecencyMs(updatedAuth),\n });\n }\n }\n } catch {\n // Best effort: if auth sync-back fails, keep existing source auth.\n }\n await fs.rm(tempHome, { recursive: true, force: true }).catch(() => {});\n }\n}\n","import type { RateLimitSnapshot } from \"@/lib/types\";\n\ntype Notify = (payload: { title: string; body: string }) => void;\n\ninterface RateLimitNotifierOptions {\n notify: Notify;\n now?: () => number;\n approachThresholdPercent?: number;\n approachCooldownMs?: number;\n resetCooldownMs?: number;\n exhaustedThresholdPercent?: number;\n recoveryThresholdPercent?: number;\n}\n\nconst DEFAULT_APPROACH_THRESHOLD = 95;\nconst DEFAULT_APPROACH_COOLDOWN_MS = 30 * 60 * 1000; // 30 minutes\nconst DEFAULT_RESET_COOLDOWN_MS = 5 * 60 * 1000; // 5 minutes\nconst DEFAULT_EXHAUSTED_THRESHOLD = 98;\nconst DEFAULT_RECOVERY_THRESHOLD = 50;\nconst APPROACH_RENOTIFY_FLOOR_MS = 2 * 60 * 1000; // Prevents back-to-back alerts when windows jitter\nconst RESET_WINDOW_BUCKET_MS = 5 * 60 * 1000;\n\ninterface RateLimitState {\n lastSnapshot: RateLimitSnapshot | null;\n lastApproachWindow: string | null;\n lastApproachAt: number | null;\n lastResetAt: number | null;\n exhaustedWindow: string | null;\n}\n\nfunction pickResetsAt(snapshot: RateLimitSnapshot | null | undefined): string | null {\n if (!snapshot) {\n return null;\n }\n\n return snapshot.primary?.resetsAt ?? snapshot.secondary?.resetsAt ?? null;\n}\n\nexport function maxUsedPercent(snapshot: RateLimitSnapshot | null | undefined): number | null {\n if (!snapshot) {\n return null;\n }\n\n const candidates = [\n snapshot.primary?.usedPercent,\n snapshot.secondary?.usedPercent,\n ].filter((value): value is number => typeof value === \"number\" && Number.isFinite(value));\n\n if (candidates.length === 0) {\n return null;\n }\n\n return Math.max(...candidates);\n}\n\nfunction normalizeResetWindowKey(resetsAt: string | null | undefined): string | null {\n if (!resetsAt) {\n return null;\n }\n\n const parsed = Date.parse(resetsAt);\n if (Number.isNaN(parsed)) {\n return resetsAt;\n }\n\n const bucket = Math.floor(parsed / RESET_WINDOW_BUCKET_MS);\n return `reset-${bucket}`;\n}\n\nfunction formatResetWindow(snapshot: RateLimitSnapshot | null | undefined): string | null {\n const resetsInSeconds = snapshot?.primary?.resetsInSeconds ?? snapshot?.secondary?.resetsInSeconds ?? null;\n if (typeof resetsInSeconds !== \"number\" || Number.isNaN(resetsInSeconds)) {\n return null;\n }\n\n const minutes = Math.max(0, Math.round(resetsInSeconds / 60));\n if (minutes >= 120) {\n const hours = Math.round(minutes / 60);\n return `${hours}h`;\n }\n\n return `${minutes}m`;\n}\n\nexport class RateLimitNotifier {\n private readonly notify: Notify;\n private readonly now: () => number;\n private readonly approachThreshold: number;\n private readonly approachCooldownMs: number;\n private readonly resetCooldownMs: number;\n private readonly exhaustedThreshold: number;\n private readonly recoveryThreshold: number;\n\n private readonly states = new Map<string, RateLimitState>();\n\n constructor(options: RateLimitNotifierOptions) {\n this.notify = options.notify;\n this.now = options.now ?? (() => Date.now());\n this.approachThreshold = options.approachThresholdPercent ?? DEFAULT_APPROACH_THRESHOLD;\n this.approachCooldownMs = options.approachCooldownMs ?? DEFAULT_APPROACH_COOLDOWN_MS;\n this.resetCooldownMs = options.resetCooldownMs ?? DEFAULT_RESET_COOLDOWN_MS;\n this.exhaustedThreshold = options.exhaustedThresholdPercent ?? DEFAULT_EXHAUSTED_THRESHOLD;\n this.recoveryThreshold = options.recoveryThresholdPercent ?? DEFAULT_RECOVERY_THRESHOLD;\n }\n\n handleSnapshot(accountId: string, profileName: string, snapshot: RateLimitSnapshot | null | undefined): void {\n if (!accountId || !profileName) {\n return;\n }\n\n const state = this.states.get(accountId) ?? {\n lastSnapshot: null,\n lastApproachAt: null,\n lastApproachWindow: null,\n lastResetAt: null,\n exhaustedWindow: null,\n };\n\n const previousUsage = maxUsedPercent(state.lastSnapshot);\n const currentUsage = maxUsedPercent(snapshot);\n const previousWindow = pickResetsAt(state.lastSnapshot);\n const currentWindow = pickResetsAt(snapshot);\n const normalizedPreviousWindow = normalizeResetWindowKey(previousWindow);\n const normalizedCurrentWindow = normalizeResetWindowKey(currentWindow);\n const now = this.now();\n\n const wasExhausted =\n typeof previousUsage === \"number\" && previousUsage >= this.exhaustedThreshold;\n const currentWindowKey =\n normalizedCurrentWindow ??\n normalizedPreviousWindow ??\n currentWindow ??\n previousWindow ??\n \"unknown\";\n\n if (wasExhausted) {\n state.exhaustedWindow = normalizedPreviousWindow ?? state.exhaustedWindow ?? currentWindowKey;\n }\n\n // Reset notifications disabled - they're just noise. Nobody waits around for limits to reset.\n // Clear exhausted state silently so we can re-notify on next approach.\n if (this.shouldNotifyReset(state, currentUsage, currentWindowKey, previousWindow, now)) {\n state.lastResetAt = now;\n state.exhaustedWindow = null;\n state.lastApproachWindow = null;\n state.lastApproachAt = null;\n }\n\n if (\n typeof currentUsage === \"number\" &&\n currentUsage >= this.approachThreshold &&\n this.canNotifyApproach(state, currentWindowKey, now)\n ) {\n const windowText = formatResetWindow(snapshot);\n const body = windowText\n ? `${currentUsage}% used. Resets in ${windowText}.`\n : `${currentUsage}% used.`;\n this.notify({\n title: `${profileName} is nearing its limit`,\n body,\n });\n state.lastApproachWindow = currentWindowKey;\n state.lastApproachAt = now;\n }\n\n if (typeof currentUsage === \"number\" && currentUsage >= this.exhaustedThreshold) {\n state.exhaustedWindow = currentWindowKey;\n }\n\n state.lastSnapshot = snapshot ?? null;\n this.states.set(accountId, state);\n }\n\n private canNotifyApproach(state: RateLimitState, windowKey: string, now: number): boolean {\n if (!windowKey) {\n return false;\n }\n\n if (typeof state.lastApproachAt === \"number\" && now - state.lastApproachAt < APPROACH_RENOTIFY_FLOOR_MS) {\n return false;\n }\n\n if (state.lastApproachWindow !== windowKey) {\n return true;\n }\n\n if (typeof state.lastApproachAt !== \"number\") {\n return true;\n }\n\n return now - state.lastApproachAt >= this.approachCooldownMs;\n }\n\n private shouldNotifyReset(\n state: RateLimitState,\n currentUsage: number | null,\n currentWindowKey: string,\n previousWindow: string | null,\n now: number,\n ): boolean {\n if (!state.exhaustedWindow) {\n return false;\n }\n\n const windowChanged =\n Boolean(currentWindowKey) && currentWindowKey !== state.exhaustedWindow;\n const usageRecovered =\n typeof currentUsage === \"number\" && currentUsage <= this.recoveryThreshold && Boolean(previousWindow);\n\n if (!windowChanged && !usageRecovered) {\n return false;\n }\n\n if (typeof state.lastResetAt === \"number\" && now - state.lastResetAt < this.resetCooldownMs) {\n return false;\n }\n\n return true;\n }\n}\n","import { promises as fs, type Dirent } from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { normalizeAutoRollSettings, type AutoRollSettings } from \"./auto-roll-settings\";\nimport {\n getAppState,\n getUserDataDir,\n updateAppState,\n type AppState,\n type AppStatePatch,\n type ProfileRecordState,\n type SkillsInstallState,\n} from \"./app-state\";\nimport { LEGACY_LOCALSTORAGE_KEYS, type LegacyLocalStorageKey } from \"./legacy-localstorage-keys\";\nimport type { ProfileData, ProfileMetadata } from \"./types\";\nimport { logWarn } from \"./logger\";\n\nconst SQLITE_STORAGE_DIR = \".f86eb5e712267207\";\nconst LEGACY_SETTINGS_FILE = \"settings.json\";\nconst LEGACY_SETTINGS_BACKUP_FILE = \"settings.json.bak\";\nconst LEGACY_SYNC_STATE_FILE = \"sync-state.json\";\nconst LEGACY_PROFILE_HOMES_DIR = \"profile-homes\";\nconst LEGACY_SKILLS_DIR = \"skills\";\nconst LEGACY_SKILL_CACHE_DIR = \"skill-cache\";\nconst LEGACY_SKILLS_REPOS_FILE = \"repos.json\";\nconst LEGACY_SKILL_MANIFEST = \".codexuse-skill.json\";\nconst LEGACY_LICENSE_SECRET_FILE = \"license.secret\";\n\ntype LegacyLocalStorageMergeResult = {\n patch: AppStatePatch;\n consumedKeys: string[];\n skippedKeys: string[];\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asString(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction resolveHomeDir(): string {\n const home = process.env.HOME || process.env.USERPROFILE || os.homedir();\n if (!home) {\n throw new Error(\"HOME is not set.\");\n }\n return home;\n}\n\nfunction resolveCodexDir(): string {\n return path.join(resolveHomeDir(), \".codex\");\n}\n\nfunction resolveLegacyPath(...segments: string[]): string {\n return path.join(resolveCodexDir(), ...segments);\n}\n\nasync function readJsonFile(filePath: string): Promise<unknown> {\n const raw = await fs.readFile(filePath, \"utf8\");\n return JSON.parse(raw) as unknown;\n}\n\nasync function readJsonFileIfExists(filePath: string): Promise<unknown | null> {\n try {\n return await readJsonFile(filePath);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n}\n\nasync function copyDirectoryManual(source: string, destination: string): Promise<void> {\n await fs.mkdir(destination, { recursive: true });\n const entries = await fs.readdir(source, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = path.join(source, entry.name);\n const destPath = path.join(destination, entry.name);\n\n if (entry.isSymbolicLink()) {\n const linkTarget = await fs.readlink(srcPath);\n await fs.symlink(linkTarget, destPath).catch(error => {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n });\n continue;\n }\n\n if (entry.isDirectory()) {\n await copyDirectoryManual(srcPath, destPath);\n continue;\n }\n\n if (entry.isFile()) {\n await fs.copyFile(srcPath, destPath);\n }\n }\n}\n\nasync function copyDirIfExists(source: string, destination: string): Promise<void> {\n let stats: Awaited<ReturnType<typeof fs.stat>> | null = null;\n try {\n stats = await fs.stat(source);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return;\n }\n throw error;\n }\n\n if (!stats.isDirectory()) {\n return;\n }\n\n // Retry-safe migration: clear partial destination from prior failed runs.\n await fs.rm(destination, { recursive: true, force: true });\n await fs.mkdir(path.dirname(destination), { recursive: true });\n try {\n await fs.cp(source, destination, {\n recursive: true,\n errorOnExist: false,\n force: true,\n dereference: false,\n verbatimSymlinks: true,\n });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ERR_FS_CP_EINVAL\") {\n await copyDirectoryManual(source, destination);\n return;\n }\n throw error;\n }\n}\n\nasync function copyFileIfExists(\n source: string,\n destination: string,\n options?: { mode?: number },\n): Promise<void> {\n try {\n const sourceStat = await fs.stat(source);\n if (!sourceStat.isFile()) {\n return;\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return;\n }\n throw error;\n }\n\n try {\n const destinationStat = await fs.stat(destination);\n if (destinationStat.isFile()) {\n return;\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n\n await fs.mkdir(path.dirname(destination), { recursive: true });\n await fs.copyFile(source, destination);\n if (typeof options?.mode === \"number\") {\n await fs.chmod(destination, options.mode).catch(() => undefined);\n }\n}\n\nasync function cleanupCopiedSkillsMetadata(skillsDir: string): Promise<void> {\n await removeIfExists(path.join(skillsDir, LEGACY_SKILLS_REPOS_FILE));\n\n let entries: Dirent[] = [];\n try {\n entries = await fs.readdir(skillsDir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) {\n continue;\n }\n await removeIfExists(path.join(skillsDir, entry.name, LEGACY_SKILL_MANIFEST));\n }\n}\n\nasync function migrateLegacyDirectoriesToUserData(): Promise<void> {\n const userDataDir = getUserDataDir();\n const legacyCodexDir = resolveCodexDir();\n\n await copyDirIfExists(\n path.join(legacyCodexDir, LEGACY_PROFILE_HOMES_DIR),\n path.join(userDataDir, LEGACY_PROFILE_HOMES_DIR),\n );\n await copyDirIfExists(\n path.join(legacyCodexDir, LEGACY_SKILLS_DIR),\n path.join(userDataDir, LEGACY_SKILLS_DIR),\n );\n await copyDirIfExists(\n path.join(legacyCodexDir, LEGACY_SKILL_CACHE_DIR),\n path.join(userDataDir, LEGACY_SKILL_CACHE_DIR),\n );\n await copyFileIfExists(\n path.join(legacyCodexDir, LEGACY_LICENSE_SECRET_FILE),\n path.join(userDataDir, LEGACY_LICENSE_SECRET_FILE),\n { mode: 0o600 },\n );\n\n await cleanupCopiedSkillsMetadata(path.join(userDataDir, LEGACY_SKILLS_DIR));\n}\n\nfunction pickAutoRoll(raw: unknown): AutoRollSettings | null {\n if (!raw) {\n return null;\n }\n try {\n return normalizeAutoRollSettings(raw as Partial<AutoRollSettings>);\n } catch {\n return null;\n }\n}\n\nfunction parseLegacyLicense(raw: unknown): AppState[\"license\"] {\n if (!isRecord(raw)) {\n return {\n licenseKey: null,\n purchaseEmail: null,\n lastVerifiedAt: null,\n nextCheckAt: null,\n lastVerificationError: null,\n status: \"inactive\",\n signature: null,\n };\n }\n\n const statusCandidate = asString(raw.status);\n const status = [\"inactive\", \"active\", \"grace\", \"error\"].includes(statusCandidate ?? \"\")\n ? (statusCandidate as AppState[\"license\"][\"status\"])\n : \"inactive\";\n\n return {\n licenseKey: asString(raw.licenseKey ?? raw.license_key),\n purchaseEmail: asString(raw.purchaseEmail ?? raw.purchase_email),\n lastVerifiedAt: asString(raw.lastVerifiedAt ?? raw.last_verified_at),\n nextCheckAt: asString(raw.nextCheckAt ?? raw.next_check_at),\n lastVerificationError: asString(raw.lastVerificationError ?? raw.last_verification_error),\n status,\n signature: asString(raw.signature),\n };\n}\n\nfunction parseLegacyProfileRecord(name: string, raw: unknown): ProfileRecordState | null {\n if (!isRecord(raw)) {\n return null;\n }\n\n const dataRaw = raw.data;\n let data: ProfileData | null = null;\n if (isRecord(dataRaw)) {\n data = dataRaw as ProfileData;\n } else if (typeof dataRaw === \"string\") {\n try {\n data = JSON.parse(dataRaw) as ProfileData;\n } catch {\n data = null;\n }\n }\n\n if (!data) {\n return null;\n }\n\n return {\n name,\n displayName: asString(raw.displayName ?? raw.display_name) ?? name,\n data,\n metadata: isRecord(raw.metadata) ? (raw.metadata as ProfileMetadata) : undefined,\n accountId: asString(raw.accountId ?? raw.account_id),\n workspaceId: asString(raw.workspaceId ?? raw.workspace_id),\n workspaceName: asString(raw.workspaceName ?? raw.workspace_name),\n email: asString(raw.email),\n authMethod: asString(raw.authMethod ?? raw.auth_method),\n createdAt: asString(raw.createdAt ?? raw.created_at),\n updatedAt: asString(raw.updatedAt ?? raw.updated_at),\n };\n}\n\nasync function loadLegacySettingsPatch(): Promise<AppStatePatch> {\n const filePath = resolveLegacyPath(LEGACY_SETTINGS_FILE);\n const raw = await readJsonFileIfExists(filePath);\n if (!isRecord(raw)) {\n return {};\n }\n\n const autoRoll = pickAutoRoll(raw.autoRoll ?? raw.auto_roll);\n const license = parseLegacyLicense(raw.license ?? raw.license_data ?? raw.license_state);\n\n return {\n app: {\n lastAppVersion: asString(raw.lastAppVersion ?? raw.last_app_version),\n pendingUpdateVersion: asString(raw.pendingUpdateVersion ?? raw.pending_update_version),\n lastProfileName: asString(raw.lastProfileName ?? raw.last_profile_name),\n },\n license,\n autoRoll: autoRoll\n ? {\n enabled: autoRoll.enabled,\n warningThreshold: autoRoll.warningThreshold,\n switchThreshold: autoRoll.switchThreshold,\n }\n : undefined,\n };\n}\n\nasync function loadLegacySyncPatch(): Promise<AppStatePatch> {\n const filePath = resolveLegacyPath(LEGACY_SYNC_STATE_FILE);\n const raw = await readJsonFileIfExists(filePath);\n if (!isRecord(raw)) {\n return {};\n }\n\n return {\n sync: {\n lastPushAt: asString(raw.lastPushAt),\n lastPullAt: asString(raw.lastPullAt),\n lastError: asString(raw.lastError),\n remoteUpdatedAt: asString(raw.remoteUpdatedAt),\n },\n };\n}\n\nasync function loadLegacyProfilesPatch(): Promise<AppStatePatch> {\n const root = resolveLegacyPath(LEGACY_PROFILE_HOMES_DIR);\n let entries: Dirent[] = [];\n try {\n entries = await fs.readdir(root, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return {};\n }\n throw error;\n }\n\n const profilesByName: Record<string, ProfileRecordState> = {};\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) {\n continue;\n }\n const profileFile = path.join(root, entry.name, \"profile.json\");\n const raw = await readJsonFileIfExists(profileFile);\n if (!raw) {\n continue;\n }\n\n const parsed = parseLegacyProfileRecord(entry.name, raw);\n if (!parsed) {\n continue;\n }\n\n profilesByName[entry.name] = parsed;\n }\n\n if (Object.keys(profilesByName).length === 0) {\n return {};\n }\n\n return { profilesByName };\n}\n\nfunction parseSkillInstallMetadata(raw: unknown): SkillsInstallState | null {\n if (!isRecord(raw)) {\n return null;\n }\n\n const id = asString(raw.id);\n if (!id) {\n return null;\n }\n\n return {\n id,\n repo: asString(raw.repo),\n repoPath: asString(raw.repoPath),\n sourceLabel: asString(raw.sourceLabel),\n sourceType:\n raw.sourceType === \"official\" || raw.sourceType === \"community\" || raw.sourceType === \"local\"\n ? raw.sourceType\n : undefined,\n viewUrl: asString(raw.viewUrl),\n createdAt: asString(raw.createdAt),\n };\n}\n\nasync function loadLegacySkillsPatch(): Promise<AppStatePatch> {\n const skillsRoot = resolveLegacyPath(LEGACY_SKILLS_DIR);\n const reposPath = path.join(skillsRoot, LEGACY_SKILLS_REPOS_FILE);\n const reposRaw = await readJsonFileIfExists(reposPath);\n\n const installsBySlug: Record<string, SkillsInstallState> = {};\n let dirEntries: Array<Dirent> = [];\n\n try {\n dirEntries = await fs.readdir(skillsRoot, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n\n for (const entry of dirEntries) {\n if (!entry.isDirectory()) {\n continue;\n }\n if (entry.name.startsWith(\".\")) {\n continue;\n }\n const manifestPath = path.join(skillsRoot, entry.name, LEGACY_SKILL_MANIFEST);\n const manifestRaw = await readJsonFileIfExists(manifestPath);\n const parsed = parseSkillInstallMetadata(manifestRaw);\n if (!parsed) {\n continue;\n }\n installsBySlug[entry.name] = parsed;\n }\n\n const sources = isRecord(reposRaw) && Array.isArray(reposRaw.sources)\n ? (reposRaw.sources as AppState[\"skills\"][\"sources\"])\n : [];\n\n if (sources.length === 0 && Object.keys(installsBySlug).length === 0) {\n return {};\n }\n\n return {\n skills: {\n sources,\n installsBySlug,\n },\n };\n}\n\nfunction mergeLegacyLocalStoragePatch(payload: Record<string, unknown>): LegacyLocalStorageMergeResult {\n const patch: AppStatePatch = {};\n const consumedKeys = new Set<string>();\n const skippedKeys = new Set<string>();\n const legacyPayloadKeys = new Set<LegacyLocalStorageKey>(\n Object.keys(payload).filter((key): key is LegacyLocalStorageKey =>\n (LEGACY_LOCALSTORAGE_KEYS as readonly string[]).includes(key),\n ),\n );\n const hasKey = (key: LegacyLocalStorageKey) => legacyPayloadKeys.has(key);\n const markSkippedIfPresent = (key: LegacyLocalStorageKey, consumed: boolean) => {\n if (!hasKey(key)) {\n return;\n }\n if (consumed) {\n consumedKeys.add(key);\n } else {\n skippedKeys.add(key);\n }\n };\n\n const settingsStorage = payload[\"settings-storage\"];\n if (isRecord(settingsStorage)) {\n const nextExcludeFolders = Array.isArray(settingsStorage.excludeFolders)\n ? (settingsStorage.excludeFolders.filter(item => typeof item === \"string\") as string[])\n : undefined;\n const nextBeep =\n typeof settingsStorage.enableTaskCompleteBeep === \"boolean\"\n ? settingsStorage.enableTaskCompleteBeep\n : undefined;\n const nextSleep =\n typeof settingsStorage.preventSleepDuringTasks === \"boolean\"\n ? settingsStorage.preventSleepDuringTasks\n : undefined;\n patch.preferences = {\n excludeFolders: nextExcludeFolders,\n enableTaskCompleteBeep: nextBeep,\n preventSleepDuringTasks: nextSleep,\n };\n markSkippedIfPresent(\n \"settings-storage\",\n nextExcludeFolders !== undefined || nextBeep !== undefined || nextSleep !== undefined,\n );\n } else {\n markSkippedIfPresent(\"settings-storage\", false);\n }\n\n const provider = payload.provider;\n if (isRecord(provider)) {\n const list = Array.isArray(provider.providers)\n ? (provider.providers\n .filter(isRecord)\n .map(item => ({\n id: asString(item.id) ?? \"\",\n name: asString(item.name) ?? \"\",\n models: Array.isArray(item.models)\n ? (item.models.filter(model => typeof model === \"string\") as string[])\n : [],\n apiKey: asString(item.apiKey) ?? undefined,\n baseUrl: asString(item.baseUrl) ?? undefined,\n }))\n .filter(item => item.id && item.name) as AppState[\"providers\"][\"list\"])\n : undefined;\n\n const overridesByPath = isRecord(provider.selectionsByCwd)\n ? (provider.selectionsByCwd as AppState[\"providers\"][\"overridesByPath\"])\n : undefined;\n\n patch.providers = {\n list,\n selectedProviderId: asString(provider.selectedProviderId) ?? undefined,\n defaultModel: asString(provider.defaultModel ?? provider.selectedModel),\n defaultReasoningEffort:\n typeof provider.defaultReasoningEffort === \"string\"\n ? (provider.defaultReasoningEffort as AppState[\"providers\"][\"defaultReasoningEffort\"])\n : typeof provider.reasoningEffort === \"string\"\n ? (provider.reasoningEffort as AppState[\"providers\"][\"defaultReasoningEffort\"])\n : undefined,\n overridesByPath,\n };\n markSkippedIfPresent(\n \"provider\",\n list !== undefined ||\n asString(provider.selectedProviderId) !== null ||\n asString(provider.defaultModel ?? provider.selectedModel) !== null ||\n typeof provider.defaultReasoningEffort === \"string\" ||\n typeof provider.reasoningEffort === \"string\" ||\n overridesByPath !== undefined,\n );\n } else {\n markSkippedIfPresent(\"provider\", false);\n }\n\n const sandbox = payload[\"sandbox-storage\"];\n if (isRecord(sandbox)) {\n const defaultMode = asString(sandbox.defaultMode ?? sandbox.mode) ?? undefined;\n const defaultApprovalPolicy =\n asString(sandbox.defaultApprovalPolicy ?? sandbox.approvalPolicy) ?? undefined;\n const overridesByPath = isRecord(sandbox.selectionsByCwd)\n ? (sandbox.selectionsByCwd as AppState[\"sandbox\"][\"overridesByPath\"])\n : undefined;\n patch.sandbox = {\n defaultMode,\n defaultApprovalPolicy,\n overridesByPath,\n };\n markSkippedIfPresent(\n \"sandbox-storage\",\n defaultMode !== undefined || defaultApprovalPolicy !== undefined || overridesByPath !== undefined,\n );\n } else {\n markSkippedIfPresent(\"sandbox-storage\", false);\n }\n\n const projectSettings = payload[\"project-settings-storage\"];\n if (isRecord(projectSettings) && isRecord(projectSettings.settingsByPath)) {\n patch.workspaceSettingsByPath = projectSettings.settingsByPath as AppState[\"workspaceSettingsByPath\"];\n markSkippedIfPresent(\"project-settings-storage\", true);\n } else {\n markSkippedIfPresent(\"project-settings-storage\", false);\n }\n\n const folder = payload[\"folder-storage\"];\n if (isRecord(folder)) {\n const folderHistory = Array.isArray(folder.folderHistory)\n ? (folder.folderHistory.filter(isRecord) as AppState[\"preferences\"][\"folderHistory\"])\n : undefined;\n const pinnedPaths = Array.isArray(folder.pinnedPaths)\n ? (folder.pinnedPaths.filter(item => typeof item === \"string\") as string[])\n : undefined;\n patch.preferences = {\n ...(patch.preferences ?? {}),\n folderHistory,\n pinnedPaths,\n };\n markSkippedIfPresent(\"folder-storage\", folderHistory !== undefined || pinnedPaths !== undefined);\n } else {\n markSkippedIfPresent(\"folder-storage\", false);\n }\n\n const categories = payload[\"conversation-categories-storage\"];\n let consumedCategories = false;\n if (isRecord(categories)) {\n if (isRecord(categories.categoriesByCwd)) {\n patch.conversationCategoriesByCwd =\n categories.categoriesByCwd as AppState[\"conversationCategoriesByCwd\"];\n consumedCategories = true;\n }\n if (isRecord(categories.conversationCategoryByCwd)) {\n patch.conversationCategoryAssignmentsByCwd =\n categories.conversationCategoryByCwd as AppState[\"conversationCategoryAssignmentsByCwd\"];\n consumedCategories = true;\n }\n }\n markSkippedIfPresent(\"conversation-categories-storage\", consumedCategories);\n\n const legacyAutoRoll = payload[\"codex:auto-roll-settings\"];\n const autoRoll = pickAutoRoll(legacyAutoRoll);\n if (autoRoll) {\n patch.autoRoll = {\n enabled: autoRoll.enabled,\n warningThreshold: autoRoll.warningThreshold,\n switchThreshold: autoRoll.switchThreshold,\n };\n markSkippedIfPresent(\"codex:auto-roll-settings\", true);\n } else {\n markSkippedIfPresent(\"codex:auto-roll-settings\", false);\n }\n\n return {\n patch,\n consumedKeys: Array.from(consumedKeys),\n skippedKeys: Array.from(skippedKeys),\n };\n}\n\nasync function removeIfExists(target: string): Promise<void> {\n await fs.rm(target, { recursive: true, force: true });\n}\n\nasync function cleanupLegacyCanonicalSources(): Promise<void> {\n const homeDir = resolveHomeDir();\n\n await removeIfExists(path.join(homeDir, SQLITE_STORAGE_DIR));\n await removeIfExists(resolveLegacyPath(LEGACY_SETTINGS_FILE));\n await removeIfExists(resolveLegacyPath(LEGACY_SETTINGS_BACKUP_FILE));\n await removeIfExists(resolveLegacyPath(LEGACY_SYNC_STATE_FILE));\n await removeIfExists(resolveLegacyPath(LEGACY_LICENSE_SECRET_FILE));\n await removeIfExists(resolveLegacyPath(LEGACY_SKILLS_DIR, LEGACY_SKILLS_REPOS_FILE));\n\n const profileHomesRoot = resolveLegacyPath(LEGACY_PROFILE_HOMES_DIR);\n try {\n const profileHomes = await fs.readdir(profileHomesRoot, { withFileTypes: true });\n for (const profileHome of profileHomes) {\n if (!profileHome.isDirectory()) {\n continue;\n }\n const profileDir = path.join(profileHomesRoot, profileHome.name);\n let files: string[] = [];\n try {\n files = await fs.readdir(profileDir);\n } catch {\n continue;\n }\n for (const file of files) {\n if (!file.startsWith(\"profile.json\")) {\n continue;\n }\n await removeIfExists(path.join(profileDir, file));\n }\n }\n } catch (error) {\n // cleanup is best-effort; log for diagnostics without failing migration\n logWarn(\"Failed cleaning legacy profile metadata:\", {\n profileHomesRoot,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n\n const skillsRoot = resolveLegacyPath(LEGACY_SKILLS_DIR);\n try {\n const skillDirs = await fs.readdir(skillsRoot, { withFileTypes: true });\n for (const entry of skillDirs) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) {\n continue;\n }\n await removeIfExists(path.join(skillsRoot, entry.name, LEGACY_SKILL_MANIFEST));\n }\n } catch (error) {\n // cleanup is best-effort; log for diagnostics without failing migration\n logWarn(\"Failed cleaning legacy skills metadata:\", {\n skillsRoot,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n}\n\nexport async function runStorageMigrationV1(): Promise<AppState> {\n const current = await getAppState();\n if (current.migration.status === \"complete\" || current.migration.status === \"pending_local_storage\") {\n return current;\n }\n\n const startedAt = new Date().toISOString();\n\n try {\n await migrateLegacyDirectoriesToUserData();\n const patches = await Promise.all([\n loadLegacySettingsPatch(),\n loadLegacySyncPatch(),\n loadLegacyProfilesPatch(),\n loadLegacySkillsPatch(),\n ]);\n\n const mergedPatch: AppStatePatch = patches.reduce((acc, patch) => {\n return {\n ...acc,\n ...patch,\n app: { ...(acc.app ?? {}), ...(patch.app ?? {}) },\n license: { ...(acc.license ?? {}), ...(patch.license ?? {}) },\n autoRoll: { ...(acc.autoRoll ?? {}), ...(patch.autoRoll ?? {}) },\n providers: { ...(acc.providers ?? {}), ...(patch.providers ?? {}) },\n sandbox: { ...(acc.sandbox ?? {}), ...(patch.sandbox ?? {}) },\n preferences: { ...(acc.preferences ?? {}), ...(patch.preferences ?? {}) },\n sync: { ...(acc.sync ?? {}), ...(patch.sync ?? {}) },\n profilesByName: { ...(acc.profilesByName ?? {}), ...(patch.profilesByName ?? {}) },\n workspaceSettingsByPath: {\n ...(acc.workspaceSettingsByPath ?? {}),\n ...(patch.workspaceSettingsByPath ?? {}),\n },\n conversationCategoriesByCwd: {\n ...(acc.conversationCategoriesByCwd ?? {}),\n ...(patch.conversationCategoriesByCwd ?? {}),\n },\n conversationCategoryAssignmentsByCwd: {\n ...(acc.conversationCategoryAssignmentsByCwd ?? {}),\n ...(patch.conversationCategoryAssignmentsByCwd ?? {}),\n },\n skills: {\n ...(acc.skills ?? {}),\n ...(patch.skills ?? {}),\n sources: patch.skills?.sources ?? acc.skills?.sources,\n installsBySlug: {\n ...(acc.skills?.installsBySlug ?? {}),\n ...(patch.skills?.installsBySlug ?? {}),\n },\n },\n };\n }, {} as AppStatePatch);\n\n return await updateAppState((state) => ({\n ...state,\n ...mergedPatch,\n app: { ...state.app, ...(mergedPatch.app ?? {}) },\n license: { ...state.license, ...(mergedPatch.license ?? {}) },\n autoRoll: { ...state.autoRoll, ...(mergedPatch.autoRoll ?? {}) },\n providers: {\n ...state.providers,\n ...(mergedPatch.providers ?? {}),\n overridesByPath: {\n ...state.providers.overridesByPath,\n ...(mergedPatch.providers?.overridesByPath ?? {}),\n },\n },\n sandbox: {\n ...state.sandbox,\n ...(mergedPatch.sandbox ?? {}),\n overridesByPath: {\n ...state.sandbox.overridesByPath,\n ...(mergedPatch.sandbox?.overridesByPath ?? {}),\n },\n },\n preferences: { ...state.preferences, ...(mergedPatch.preferences ?? {}) },\n sync: { ...state.sync, ...(mergedPatch.sync ?? {}) },\n profilesByName: {\n ...state.profilesByName,\n ...(mergedPatch.profilesByName ?? {}),\n },\n workspaceSettingsByPath: {\n ...state.workspaceSettingsByPath,\n ...(mergedPatch.workspaceSettingsByPath ?? {}),\n },\n conversationCategoriesByCwd: {\n ...state.conversationCategoriesByCwd,\n ...(mergedPatch.conversationCategoriesByCwd ?? {}),\n },\n conversationCategoryAssignmentsByCwd: {\n ...state.conversationCategoryAssignmentsByCwd,\n ...(mergedPatch.conversationCategoryAssignmentsByCwd ?? {}),\n },\n skills: {\n ...state.skills,\n ...(mergedPatch.skills ?? {}),\n installsBySlug: {\n ...state.skills.installsBySlug,\n ...(mergedPatch.skills?.installsBySlug ?? {}),\n },\n },\n migration: {\n ...state.migration,\n status: \"pending_local_storage\",\n startedAt: state.migration.startedAt ?? startedAt,\n completedAt: null,\n localStorageImportedAt: null,\n lastError: null,\n },\n }), {\n mode: \"replace\",\n allowBeforeMigrationComplete: true,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n await updateAppState((state) => ({\n ...state,\n migration: {\n ...state.migration,\n status: \"pending\",\n startedAt: state.migration.startedAt ?? startedAt,\n lastError: message,\n },\n }), {\n mode: \"replace\",\n allowBeforeMigrationComplete: true,\n });\n throw error;\n }\n}\n\nexport async function importLegacyLocalStorageOnce(\n payload: Record<string, unknown>,\n): Promise<{ completed: boolean; importedKeys: string[]; skippedKeys?: string[] }> {\n const current = await getAppState();\n if (current.migration.status === \"complete\") {\n return { completed: true, importedKeys: [], skippedKeys: [] };\n }\n\n if (current.migration.status !== \"pending_local_storage\") {\n return { completed: false, importedKeys: [], skippedKeys: [] };\n }\n\n if (!payload || !isRecord(payload)) {\n return { completed: false, importedKeys: [], skippedKeys: [] };\n }\n\n const { patch, consumedKeys, skippedKeys } = mergeLegacyLocalStoragePatch(payload);\n\n const completedAt = new Date().toISOString();\n const next = await updateAppState((state) => {\n if (state.migration.status !== \"pending_local_storage\") {\n return state;\n }\n\n return {\n ...state,\n ...patch,\n app: { ...state.app, ...(patch.app ?? {}) },\n autoRoll: { ...state.autoRoll, ...(patch.autoRoll ?? {}) },\n license: { ...state.license, ...(patch.license ?? {}) },\n providers: {\n ...state.providers,\n ...(patch.providers ?? {}),\n overridesByPath: {\n ...state.providers.overridesByPath,\n ...(patch.providers?.overridesByPath ?? {}),\n },\n },\n sandbox: {\n ...state.sandbox,\n ...(patch.sandbox ?? {}),\n overridesByPath: {\n ...state.sandbox.overridesByPath,\n ...(patch.sandbox?.overridesByPath ?? {}),\n },\n },\n preferences: { ...state.preferences, ...(patch.preferences ?? {}) },\n workspaceSettingsByPath: {\n ...state.workspaceSettingsByPath,\n ...(patch.workspaceSettingsByPath ?? {}),\n },\n conversationCategoriesByCwd: {\n ...state.conversationCategoriesByCwd,\n ...(patch.conversationCategoriesByCwd ?? {}),\n },\n conversationCategoryAssignmentsByCwd: {\n ...state.conversationCategoryAssignmentsByCwd,\n ...(patch.conversationCategoryAssignmentsByCwd ?? {}),\n },\n migration: {\n ...state.migration,\n status: \"complete\",\n completedAt,\n localStorageImportedAt: completedAt,\n lastError: null,\n },\n };\n }, {\n mode: \"replace\",\n allowBeforeMigrationComplete: true,\n });\n\n if (next.migration.status !== \"complete\") {\n return { completed: false, importedKeys: [], skippedKeys: [] };\n }\n\n await cleanupLegacyCanonicalSources();\n return { completed: true, importedKeys: consumedKeys, skippedKeys };\n}\n","export const LEGACY_LOCALSTORAGE_KEYS = [\n \"settings-storage\",\n \"provider\",\n \"sandbox-storage\",\n \"project-settings-storage\",\n \"folder-storage\",\n \"conversation-categories-storage\",\n \"codex:auto-roll-settings\",\n] as const;\n\nexport const ORPHAN_LOCALSTORAGE_KEYS = [\n \"token-count-storage\",\n \"codexia-chat-input-store\",\n \"codex\",\n] as const;\n\nexport type LegacyLocalStorageKey = (typeof LEGACY_LOCALSTORAGE_KEYS)[number];\n","import path from \"node:path\";\nimport { CodexAppServer } from \"../../../lib/codex-app-server\";\nimport { licenseService } from \"../../../lib/license-service\";\nimport { assertProjectCreationAllowed } from \"../../../lib/license-guard\";\nimport {\n addParityWorkspace,\n connectParityWorkspace,\n getParityWorkspaceById,\n listParityWorkspaces,\n type WorkspaceInfo as ProjectInfo,\n} from \"../../../lib/workspace-parity-store\";\nimport { createTelegramBridge } from \"../../../electron/telegram-bridge\";\n\ntype DaemonStartOptions = {\n telegramBotToken: string;\n projectPath: string | null;\n version: string;\n};\n\nfunction hasFlag(args: string[], flag: string): boolean {\n return args.includes(flag);\n}\n\nfunction stripFlags(args: string[]): string[] {\n return args.filter(arg => !arg.startsWith(\"-\"));\n}\n\nfunction parseStringFlag(flags: string[], name: string): string | null {\n const explicit = flags.find(flag => flag.startsWith(`${name}=`));\n if (!explicit) {\n return null;\n }\n const value = explicit.slice(`${name}=`.length).trim();\n return value.length > 0 ? value : \"\";\n}\n\nfunction printDaemonHelp(version: string): void {\n console.log(`CodexUse CLI v${version}\n\nUsage:\n codexuse daemon start --telegram-bot-token=<token> [--project-path=/abs/path]\n\nEnvironment:\n CODEXUSE_TELEGRAM_BOT_TOKEN Telegram bot token fallback\n\nNotes:\n - Runs Codex app-server + Telegram bridge in headless mode (no desktop app).\n - --project-path auto-registers that path and makes it the default project for new chats.\n - Use on VPS/Linux with a process manager (systemd, pm2, supervisord).\n - Stop with Ctrl+C or SIGTERM.\n`);\n}\n\nasync function ensureProjectRegistered(projectPath: string): Promise<ProjectInfo> {\n const resolvedPath = path.resolve(projectPath);\n const projects = await listParityWorkspaces();\n const existing = projects.find(entry => path.resolve(entry.path) === resolvedPath) ?? null;\n if (!existing) {\n await assertProjectCreationAllowed(projects);\n const added = await addParityWorkspace(resolvedPath);\n console.log(`Added project: ${added.name} (${added.path})`);\n return added;\n }\n if (!existing.connected) {\n const connected = await connectParityWorkspace(existing.id);\n console.log(`Connected project: ${connected.name} (${connected.path})`);\n return connected;\n }\n return existing;\n}\n\nasync function resolveProEnabled(): Promise<boolean> {\n const cached = await licenseService.getCachedStatus().catch(() => null);\n if (cached?.isPro) {\n return true;\n }\n const refreshed = await licenseService.getStatus().catch(() => cached);\n return Boolean(refreshed?.isPro);\n}\n\nfunction parseProcessExitPayload(payload: unknown): string {\n if (!payload || typeof payload !== \"object\") {\n return \"\";\n }\n const record = payload as Record<string, unknown>;\n const code = typeof record.code === \"number\" ? record.code : null;\n const signal = typeof record.signal === \"string\" ? record.signal : null;\n if (code !== null && signal) {\n return `code=${code}, signal=${signal}`;\n }\n if (code !== null) {\n return `code=${code}`;\n }\n if (signal) {\n return `signal=${signal}`;\n }\n return \"\";\n}\n\nasync function runDaemonStart(options: DaemonStartOptions): Promise<void> {\n if (!options.telegramBotToken) {\n throw new Error(\n \"Telegram bot token is required. Pass --telegram-bot-token=<token> or set CODEXUSE_TELEGRAM_BOT_TOKEN.\",\n );\n }\n\n let preferredProject: ProjectInfo | null = null;\n if (options.projectPath) {\n preferredProject = await ensureProjectRegistered(options.projectPath);\n }\n\n const appServer = new CodexAppServer();\n await appServer.initialize({\n name: \"codexuse-cli-daemon\",\n title: \"CodexUse CLI Daemon\",\n version: options.version,\n });\n\n const bridge = createTelegramBridge({\n getAppServer: () => appServer,\n listProjects: () => listParityWorkspaces(),\n getProjectById: (id: string) => getParityWorkspaceById(id),\n isProEnabled: () => resolveProEnabled(),\n getDefaultProjectId: () => preferredProject?.id ?? null,\n });\n\n await bridge.applyRuntimeSettings({\n telegramBridgeEnabled: true,\n telegramBotToken: options.telegramBotToken,\n });\n\n const status = bridge.getStatus();\n if (!status.running) {\n await bridge.dispose().catch(() => undefined);\n await appServer.stop().catch(() => undefined);\n throw new Error(status.lastError || \"Telegram bridge failed to start.\");\n }\n\n const botLabel = status.botUsername ? `@${status.botUsername}` : \"(unknown)\";\n const projects = await listParityWorkspaces().catch(() => [] as ProjectInfo[]);\n console.log(`Daemon started. Telegram bot: ${botLabel}`);\n console.log(`Streaming mode: ${status.streamMode}`);\n if (preferredProject) {\n console.log(`Default project: ${preferredProject.name} [${preferredProject.id}]`);\n }\n console.log(`Projects available: ${projects.length}`);\n console.log(\"Running until SIGINT/SIGTERM...\");\n\n let stopping = false;\n let resolveWait: (() => void) | null = null;\n\n const stop = async (reason: string, exitCode: number) => {\n if (stopping) {\n return;\n }\n stopping = true;\n process.exitCode = exitCode;\n console.log(`Stopping daemon (${reason})...`);\n await bridge.dispose().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(`Failed to stop Telegram bridge cleanly: ${message}`);\n });\n await appServer.stop().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(`Failed to stop app-server cleanly: ${message}`);\n });\n resolveWait?.();\n };\n\n const onSigInt = () => {\n void stop(\"SIGINT\", 0);\n };\n const onSigTerm = () => {\n void stop(\"SIGTERM\", 0);\n };\n const onProcessExited = (payload: unknown) => {\n const suffix = parseProcessExitPayload(payload);\n const detail = suffix ? ` (${suffix})` : \"\";\n console.error(`Codex app-server exited unexpectedly${detail}.`);\n void stop(\"app-server-exited\", 1);\n };\n\n process.once(\"SIGINT\", onSigInt);\n process.once(\"SIGTERM\", onSigTerm);\n appServer.once(\"codex:process-exited\", onProcessExited);\n\n try {\n await new Promise<void>((resolve) => {\n resolveWait = resolve;\n });\n } finally {\n process.off(\"SIGINT\", onSigInt);\n process.off(\"SIGTERM\", onSigTerm);\n appServer.off(\"codex:process-exited\", onProcessExited);\n }\n}\n\nexport async function handleDaemonCommand(args: string[], version: string): Promise<void> {\n const flags = args.filter(arg => arg.startsWith(\"-\"));\n const params = stripFlags(args);\n const sub = params[0];\n\n if (!sub || hasFlag(flags, \"--help\") || hasFlag(flags, \"-h\")) {\n printDaemonHelp(version);\n return;\n }\n\n switch (sub) {\n case \"start\":\n {\n const tokenFlag =\n parseStringFlag(flags, \"--telegram-bot-token\")\n ?? parseStringFlag(flags, \"--bot-token\");\n const tokenEnv = process.env.CODEXUSE_TELEGRAM_BOT_TOKEN?.trim() || null;\n const telegramBotToken = (tokenFlag && tokenFlag.trim()) || tokenEnv || \"\";\n const projectPath =\n parseStringFlag(flags, \"--project-path\")\n ?? parseStringFlag(flags, \"--project\")\n ?? null;\n\n await runDaemonStart({\n telegramBotToken,\n projectPath,\n version,\n });\n return;\n }\n default:\n printDaemonHelp(version);\n return;\n }\n}\n","import { spawn, spawnSync, type ChildProcessWithoutNullStreams } from \"node:child_process\";\nimport { EventEmitter } from \"node:events\";\nimport readline from \"node:readline\";\nimport path from \"node:path\";\nimport { requireCodexCli } from \"./codex-cli\";\nimport {\n buildAppsListPayload,\n isAppsListMethod,\n isAppsListThreadNotFoundError,\n isMethodUnavailableError,\n type AppsListParams,\n} from \"./apps-list-rpc\";\nimport { buildCliEnv } from \"./cli-env\";\nimport { logError, logInfo, logWarn } from \"./logger\";\n\ntype JsonRpcId = number | string;\n\ntype JsonRpcRequest = {\n id: JsonRpcId;\n method: string;\n params?: unknown;\n};\n\ntype JsonRpcNotification = {\n method: string;\n params?: unknown;\n};\n\ntype JsonRpcError = {\n code: number;\n message: string;\n data?: unknown;\n};\n\ntype JsonRpcResponse = {\n id: JsonRpcId;\n result?: unknown;\n error?: JsonRpcError;\n};\n\ntype PendingRequest = {\n method: string;\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n};\n\ntype PendingRequestKind = \"exec\" | \"patch\" | \"approval\" | \"user_input\";\n\ntype PendingServerRequest = {\n id: JsonRpcId;\n kind: PendingRequestKind;\n method: string;\n};\n\nexport type CodexReviewDecision = \"approved\" | \"approved_for_session\" | \"denied\" | \"abort\";\n\nexport type CodexAppServerEventName =\n | \"codex:event\"\n | \"codex:notification\"\n | \"codex:auth-status\"\n | \"codex:login-complete\"\n | \"codex:exec-command-request\"\n | \"codex:apply-patch-request\"\n | \"codex:server-request\"\n | \"codex:backend-error\"\n | \"codex:process-exited\";\n\nexport interface CodexClientInfo {\n name: string;\n title?: string;\n version?: string;\n}\n\nexport interface CodexEventPayload {\n method: string;\n params?: unknown;\n}\n\nexport interface CodexNotificationPayload {\n method: string;\n params?: unknown;\n}\n\nexport interface CodexExecCommandRequestPayload {\n requestToken: string;\n params: Record<string, unknown>;\n}\n\nexport interface CodexApplyPatchRequestPayload {\n requestToken: string;\n params: Record<string, unknown>;\n}\n\nexport interface CodexServerRequestPayload {\n requestId: JsonRpcId;\n method: string;\n params: Record<string, unknown>;\n}\n\nexport interface CodexBackendErrorPayload {\n code: number;\n message: string;\n data?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\" && !Array.isArray(value));\n}\n\nfunction requestIdToToken(id: JsonRpcId): string {\n return typeof id === \"string\" ? id : String(id);\n}\n\nfunction isAlreadyInitializedError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const message = (error as { message?: unknown }).message;\n return typeof message === \"string\" && message.toLowerCase().includes(\"already initialized\");\n}\n\nfunction isThreadNotFoundError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const message = (error as { message?: unknown }).message;\n if (typeof message !== \"string\") return false;\n const lower = message.toLowerCase();\n return lower.includes(\"thread not found\") || lower.includes(\"rollout\");\n}\n\nfunction isMethodPayloadUnsupportedError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n const code = (error as { code?: unknown }).code;\n if (typeof code !== \"number\" || code !== -32600) {\n return false;\n }\n const message = (error as { message?: unknown }).message;\n if (typeof message !== \"string\") {\n return false;\n }\n const normalized = message.toLowerCase();\n return (\n normalized.includes(\"invalid request\")\n || normalized.includes(\"missing field\")\n || normalized.includes(\"unknown field\")\n );\n}\n\nfunction asString(value: unknown): string {\n return typeof value === \"string\" ? value : value != null ? String(value) : \"\";\n}\n\nfunction isInlineImageValue(value: string): boolean {\n const normalized = value.trim().toLowerCase();\n return (\n normalized.startsWith(\"data:\")\n || normalized.startsWith(\"http://\")\n || normalized.startsWith(\"https://\")\n );\n}\n\nfunction normalizeSendUserMessageItem(\n value: unknown,\n): Record<string, unknown> | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const type = asString(value.type).trim();\n if (!type) {\n return null;\n }\n\n const data = isRecord(value.data) ? value.data : {};\n\n if (type === \"text\") {\n const text = asString(data.text ?? value.text);\n if (!text.trim()) {\n return null;\n }\n return { type: \"text\", data: { text } };\n }\n\n if (type === \"image\") {\n const imageUrl = asString(\n data.image_url\n ?? data.imageUrl\n ?? data.url\n ?? value.image_url\n ?? value.imageUrl\n ?? value.url,\n ).trim();\n if (!imageUrl) {\n return null;\n }\n return { type: \"image\", data: { image_url: imageUrl } };\n }\n\n if (type === \"localImage\") {\n const path = asString(data.path ?? value.path).trim();\n if (!path) {\n return null;\n }\n return { type: \"localImage\", data: { path } };\n }\n\n return value;\n}\n\nfunction buildSendUserMessageItemsFromLegacyParams(\n params: Record<string, unknown>,\n): Record<string, unknown>[] | null {\n const items: Record<string, unknown>[] = [];\n\n const text = asString(params.text);\n if (text.trim()) {\n items.push({\n type: \"text\",\n data: { text },\n });\n }\n\n if (Array.isArray(params.images)) {\n for (const candidate of params.images) {\n const image = asString(candidate).trim();\n if (!image) {\n continue;\n }\n if (isInlineImageValue(image)) {\n items.push({\n type: \"image\",\n data: { image_url: image },\n });\n continue;\n }\n items.push({\n type: \"localImage\",\n data: { path: image },\n });\n }\n }\n\n if (items.length === 0) {\n return null;\n }\n return items;\n}\n\nfunction normalizeSendUserMessageParams(\n params: Record<string, unknown>,\n): Record<string, unknown> {\n const normalized: Record<string, unknown> = { ...params };\n const conversationId = asString(\n params.conversationId\n ?? params.conversation_id\n ?? params.threadId\n ?? params.thread_id\n ?? \"\",\n ).trim();\n if (conversationId && !asString(params.conversationId).trim()) {\n normalized.conversationId = conversationId;\n }\n\n const items = Array.isArray(params.items)\n ? params.items\n .map((item) => normalizeSendUserMessageItem(item))\n .filter((item): item is Record<string, unknown> => item !== null)\n : null;\n if (items && items.length > 0) {\n normalized.items = items;\n return normalized;\n }\n\n const legacyItems = buildSendUserMessageItemsFromLegacyParams(params);\n if (legacyItems) {\n normalized.items = legacyItems;\n }\n return normalized;\n}\n\nfunction normalizeTurnInputParams(\n params: Record<string, unknown>,\n): Record<string, unknown> {\n const normalized: Record<string, unknown> = { ...params };\n const threadId = asString(\n params.threadId\n ?? params.thread_id\n ?? params.conversationId\n ?? params.conversation_id\n ?? \"\",\n ).trim();\n if (threadId && !asString(params.threadId).trim()) {\n normalized.threadId = threadId;\n }\n\n const expectedTurnId = asString(\n params.expectedTurnId\n ?? params.expected_turn_id\n ?? params.turnId\n ?? params.turn_id\n ?? \"\",\n ).trim();\n if (expectedTurnId && !asString(params.expectedTurnId).trim()) {\n normalized.expectedTurnId = expectedTurnId;\n }\n const turnId = asString(params.turnId ?? params.turn_id ?? expectedTurnId).trim();\n if (turnId && !asString(params.turnId).trim()) {\n normalized.turnId = turnId;\n }\n\n const providedInput = Array.isArray(params.input)\n ? params.input.filter((entry) => isRecord(entry))\n : [];\n if (providedInput.length > 0) {\n normalized.input = providedInput;\n return normalized;\n }\n\n const input: Record<string, unknown>[] = [];\n const text = asString(params.text);\n if (text.trim()) {\n input.push({ type: \"text\", text });\n }\n if (Array.isArray(params.images)) {\n for (const candidate of params.images) {\n const image = asString(candidate).trim();\n if (!image || isInlineImageValue(image)) {\n continue;\n }\n input.push({\n type: \"localImage\",\n path: image,\n });\n }\n }\n if (input.length > 0) {\n normalized.input = input;\n }\n return normalized;\n}\n\nfunction pickMethodKind(method: string, params: unknown): PendingRequestKind | null {\n const normalized = method.toLowerCase();\n if (normalized.includes(\"requestapproval\")) return \"approval\";\n if (normalized.includes(\"requestuserinput\")) return \"user_input\";\n if (isRecord(params)) {\n if (\"file_changes\" in params || \"fileChanges\" in params || \"grant_root\" in params || \"grantRoot\" in params) {\n return \"patch\";\n }\n if (\"command\" in params || \"parsed_cmd\" in params || \"parsedCmd\" in params || \"cwd\" in params) {\n return \"exec\";\n }\n }\n if (normalized.includes(\"apply\") && normalized.includes(\"patch\")) return \"patch\";\n if (normalized.includes(\"file\") && normalized.includes(\"change\")) return \"patch\";\n if (normalized.includes(\"exec\") || normalized.includes(\"command\")) return \"exec\";\n return null;\n}\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 45_000;\nconst THREAD_LIST_REQUEST_TIMEOUT_MS = 180_000;\nconst MAX_PARSE_BUFFER_CHARS = 2_000_000;\nconst DEFAULT_THREAD_LIVE_WORKSPACE_ID = \"__default__\";\nconst REQUEST_TIMEOUT_WARNING_COOLDOWN_MS = 30_000;\n\nfunction isLikelyRecoverableJsonParseError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n const message = error.message.toLowerCase();\n return (\n message.includes(\"unterminated string\") ||\n message.includes(\"unexpected end of json input\") ||\n message.includes(\"bad control character\")\n );\n}\n\nfunction isIgnorableAppsListTransportStderr(message: string): boolean {\n const normalized = message.toLowerCase();\n if (!normalized.includes(\"backend-api/wham/apps\")) {\n return false;\n }\n return (\n normalized.includes(\"worker quit with fatal\") &&\n normalized.includes(\"transport channel closed\")\n );\n}\n\nfunction isIgnorableMissingSkillsSymlinkStderr(message: string): boolean {\n const normalized = message.toLowerCase();\n return (\n normalized.includes(\"codex_core::skills::loader\") &&\n normalized.includes(\"failed to stat skills entry\") &&\n normalized.includes(\"(symlink)\") &&\n normalized.includes(\"no such file or directory\")\n );\n}\n\nfunction isRequestTimeoutErrorMessage(value: unknown): boolean {\n if (typeof value !== \"string\") {\n return false;\n }\n return value.toLowerCase().includes(\"request timed out\");\n}\n\nfunction getRequestTimeoutMs(method: string): number {\n if (method === \"thread/list\") {\n return THREAD_LIST_REQUEST_TIMEOUT_MS;\n }\n return DEFAULT_REQUEST_TIMEOUT_MS;\n}\n\nfunction normalizeThreadLiveWorkspaceId(value: unknown): string {\n const workspaceId = asString(value).trim();\n return workspaceId || DEFAULT_THREAD_LIVE_WORKSPACE_ID;\n}\n\nfunction resolveThreadLiveWorkspacePayloadId(workspaceId: string): string | null {\n return workspaceId === DEFAULT_THREAD_LIVE_WORKSPACE_ID ? null : workspaceId;\n}\n\nfunction threadLiveKey(workspaceId: string, threadId: string): string {\n return `${workspaceId}:${threadId}`;\n}\n\nfunction buildThreadRealtimePayloads(\n threadId: string,\n workspaceId: string | null,\n): Record<string, unknown>[] {\n const payloads: Record<string, unknown>[] = [];\n const seen = new Set<string>();\n const pushPayload = (payload: Record<string, unknown>) => {\n const signature = JSON.stringify(payload);\n if (seen.has(signature)) {\n return;\n }\n seen.add(signature);\n payloads.push(payload);\n };\n\n pushPayload({ threadId });\n pushPayload({ conversationId: threadId });\n pushPayload({ threadId, conversationId: threadId });\n\n if (!workspaceId) {\n return payloads;\n }\n\n pushPayload({ threadId, workspaceId });\n pushPayload({ conversationId: threadId, workspaceId });\n pushPayload({ threadId, conversationId: threadId, workspaceId });\n pushPayload({ threadId, workspace_id: workspaceId });\n pushPayload({ conversationId: threadId, workspace_id: workspaceId });\n pushPayload({ threadId, conversationId: threadId, workspace_id: workspaceId });\n return payloads;\n}\n\nfunction escapeInvalidJsonStringChars(input: string): string {\n let output = \"\";\n let inString = false;\n let escaped = false;\n\n for (let i = 0; i < input.length; i += 1) {\n const char = input[i];\n\n if (escaped) {\n output += char;\n escaped = false;\n continue;\n }\n if (char === \"\\\\\") {\n output += char;\n escaped = true;\n continue;\n }\n if (char === \"\\\"\") {\n output += char;\n inString = !inString;\n continue;\n }\n if (inString) {\n if (char === \"\\n\") {\n output += \"\\\\n\";\n continue;\n }\n if (char === \"\\r\") {\n output += \"\\\\r\";\n continue;\n }\n if (char === \"\\t\") {\n output += \"\\\\t\";\n continue;\n }\n const code = char.charCodeAt(0);\n if (code >= 0 && code < 0x20) {\n output += `\\\\u${code.toString(16).padStart(4, \"0\")}`;\n continue;\n }\n }\n\n output += char;\n }\n\n return output;\n}\n\nlet cachedRuntimeBinary: string | null = null;\n\nfunction resolveRuntimeBinary(env?: NodeJS.ProcessEnv): string {\n const override =\n env?.CODEX_NODE_RUNTIME?.trim() ||\n env?.CODEX_NODE_BIN?.trim() ||\n env?.CODEX_NODE?.trim() ||\n process.env.CODEX_NODE_RUNTIME?.trim() ||\n process.env.CODEX_NODE_BIN?.trim() ||\n process.env.CODEX_NODE?.trim() ||\n null;\n if (override) {\n return override;\n }\n\n if (cachedRuntimeBinary) {\n return cachedRuntimeBinary;\n }\n\n const runtimeEnv: NodeJS.ProcessEnv = { ...process.env, ...env };\n const homeDir = runtimeEnv.HOME ?? runtimeEnv.USERPROFILE ?? \"\";\n const pathHints = (runtimeEnv.CODEX_PATH_HINTS ?? process.env.CODEX_PATH_HINTS ?? \"\")\n .split(path.delimiter)\n .map(entry => entry.trim())\n .filter(Boolean);\n const extraPathEntries = [\n \"/usr/local/bin\",\n \"/opt/homebrew/bin\",\n path.join(homeDir, \".local\", \"bin\"),\n path.join(homeDir, \".fnm\", \"aliases\", \"default\", \"bin\"),\n path.join(homeDir, \".fnm\", \"current\", \"bin\"),\n ...pathHints,\n ].filter(Boolean);\n const currentPath = runtimeEnv.PATH ?? \"\";\n runtimeEnv.PATH = Array.from(\n new Set([...extraPathEntries, ...currentPath.split(path.delimiter).filter(Boolean)]),\n ).join(path.delimiter);\n\n const candidates = Array.from(\n new Set(\n [\n runtimeEnv.CODEX_NODE_RUNTIME?.trim(),\n runtimeEnv.CODEX_NODE_BIN?.trim(),\n runtimeEnv.CODEX_NODE?.trim(),\n \"/opt/homebrew/bin/node\",\n \"/usr/local/bin/node\",\n \"node\",\n ].filter(Boolean),\n ),\n );\n\n for (const candidate of candidates) {\n const probe = spawnSync(candidate, [\"-v\"], { env: runtimeEnv, stdio: \"ignore\" });\n if (!probe.error && probe.status === 0) {\n cachedRuntimeBinary = candidate;\n return candidate;\n }\n }\n\n cachedRuntimeBinary = process.execPath;\n return process.execPath;\n}\n\nexport class CodexAppServer extends EventEmitter {\n private child: ChildProcessWithoutNullStreams | null = null;\n private reader: readline.Interface | null = null;\n private nextRequestId = 1;\n private pendingRequests = new Map<string, PendingRequest>();\n private pendingServerRequests = new Map<string, PendingServerRequest>();\n private timeoutRecoveryPromise: Promise<void> | null = null;\n private lastTimeoutWarningAtByMethod = new Map<string, number>();\n private startPromise: Promise<void> | null = null;\n private initializePromise: Promise<unknown> | null = null;\n private initializeResponse: unknown | null = null;\n private parseLineBuffer: string | null = null;\n private threadLiveSubscriptionIdByKey = new Map<string, string>();\n private threadLiveModeByKey = new Map<string, \"realtime\" | \"listener\">();\n\n constructor() {\n super();\n this.setMaxListeners(50);\n }\n\n async start(): Promise<void> {\n if (this.child) {\n return;\n }\n if (!this.startPromise) {\n this.startPromise = this.spawnProcess().finally(() => {\n this.startPromise = null;\n });\n }\n await this.startPromise;\n }\n\n async stop(): Promise<void> {\n if (this.reader) {\n this.reader.close();\n this.reader = null;\n }\n if (this.child) {\n const child = this.child;\n this.child = null;\n try {\n child.kill();\n } catch {\n // ignore kill errors\n }\n }\n this.initializePromise = null;\n this.initializeResponse = null;\n this.parseLineBuffer = null;\n this.threadLiveSubscriptionIdByKey.clear();\n this.threadLiveModeByKey.clear();\n this.clearPendingRequests(new Error(\"codex app-server stopped\"));\n }\n\n isRunning(): boolean {\n return Boolean(this.child && !this.child.killed);\n }\n\n async initialize(clientInfo?: CodexClientInfo): Promise<unknown> {\n if (this.initializeResponse) {\n return this.initializeResponse;\n }\n if (!this.initializePromise) {\n this.initializePromise = (async () => {\n await this.start();\n const payload: Record<string, unknown> = {\n clientInfo: clientInfo ?? {\n name: \"codexuse\",\n title: \"CodexUse\",\n version: \"0.0.0\",\n },\n };\n try {\n const response = await this.request(\"initialize\", payload);\n await this.notify(\"initialized\", {});\n this.initializeResponse = response;\n return response;\n } catch (error) {\n if (isAlreadyInitializedError(error)) {\n this.initializeResponse = this.initializeResponse ?? {};\n return this.initializeResponse;\n }\n throw error;\n }\n })().finally(() => {\n this.initializePromise = null;\n });\n }\n return this.initializePromise;\n }\n\n async getAccount(refreshToken = false): Promise<unknown> {\n return this.request(\"account/read\", { refreshToken });\n }\n\n async getAccountRateLimits(): Promise<unknown> {\n return this.request(\"account/rateLimits/read\");\n }\n\n async loginAccount(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"account/login/start\", params);\n }\n\n async cancelLoginAccount(loginId: string): Promise<unknown> {\n return this.request(\"account/login/cancel\", { loginId });\n }\n\n async logoutAccount(): Promise<unknown> {\n return this.request(\"account/logout\");\n }\n\n async newConversation(params: Record<string, unknown>, overrides?: Record<string, unknown> | null): Promise<unknown> {\n const merged = overrides ? { ...params, ...overrides } : params;\n return this.request(\"newConversation\", merged);\n }\n\n async resumeConversation(params: Record<string, unknown>, overrides?: Record<string, unknown> | null): Promise<unknown> {\n const merged = overrides ? { ...params, ...overrides } : params;\n return this.request(\"resumeConversation\", merged);\n }\n\n private async addConversationListenerWithResumeFallback(\n threadId: string,\n workspaceId: string | null = null,\n ): Promise<Record<string, unknown> | null> {\n const listenerParams: Record<string, unknown> = {\n conversationId: threadId,\n };\n const resolvedWorkspaceId = workspaceId ? workspaceId.trim() : \"\";\n if (resolvedWorkspaceId) {\n listenerParams.workspaceId = resolvedWorkspaceId;\n listenerParams.workspace_id = resolvedWorkspaceId;\n }\n try {\n const response = await this.request(\"addConversationListener\", listenerParams);\n return isRecord(response) ? response : null;\n } catch (error) {\n if (!isThreadNotFoundError(error)) {\n throw error;\n }\n await this.threadResume(\n resolvedWorkspaceId\n ? { threadId, workspaceId: resolvedWorkspaceId, workspace_id: resolvedWorkspaceId }\n : { threadId },\n );\n const response = await this.request(\"addConversationListener\", listenerParams);\n return isRecord(response) ? response : null;\n }\n }\n\n private async removeConversationListenerBySubscriptionId(\n subscriptionId: string,\n ): Promise<void> {\n if (!subscriptionId) {\n return;\n }\n await this.request(\"removeConversationListener\", { subscriptionId });\n }\n\n private trackThreadLiveSubscriptionId(\n key: string,\n subscriptionId: string | null,\n ): void {\n if (!subscriptionId) {\n return;\n }\n const previousSubscriptionId =\n this.threadLiveSubscriptionIdByKey.get(key) ?? null;\n this.threadLiveSubscriptionIdByKey.set(key, subscriptionId);\n if (previousSubscriptionId && previousSubscriptionId !== subscriptionId) {\n void this.removeConversationListenerBySubscriptionId(\n previousSubscriptionId,\n ).catch(() => {\n // Ignore stale listener cleanup errors.\n });\n }\n }\n\n private async startThreadRealtime(\n threadId: string,\n workspaceId: string | null = null,\n ): Promise<Record<string, unknown> | null> {\n const payloads = buildThreadRealtimePayloads(threadId, workspaceId);\n let resumed = false;\n for (let index = 0; index < payloads.length; index += 1) {\n const payload = payloads[index];\n try {\n const response = await this.request(\"thread/realtime/start\", payload);\n return isRecord(response) ? response : {};\n } catch (error) {\n if (isMethodUnavailableError(error, \"thread/realtime/start\")) {\n return null;\n }\n if (isMethodPayloadUnsupportedError(error)) {\n continue;\n }\n if (!isThreadNotFoundError(error)) {\n throw error;\n }\n if (resumed) {\n continue;\n }\n resumed = true;\n await this.threadResume({ threadId });\n // Retry from the first payload after a successful resume.\n index = -1;\n }\n }\n return null;\n }\n\n private async stopThreadRealtime(\n threadId: string,\n workspaceId: string | null = null,\n ): Promise<boolean> {\n const payloads = buildThreadRealtimePayloads(threadId, workspaceId);\n for (const payload of payloads) {\n try {\n await this.request(\"thread/realtime/stop\", payload);\n return true;\n } catch (error) {\n if (isMethodUnavailableError(error, \"thread/realtime/stop\")) {\n return false;\n }\n if (isMethodPayloadUnsupportedError(error)) {\n continue;\n }\n if (isThreadNotFoundError(error)) {\n return true;\n }\n throw error;\n }\n }\n return false;\n }\n\n async addConversationListener(params: Record<string, unknown>): Promise<unknown> {\n const conversationId = asString(\n params.conversationId ?? params.threadId ?? params.thread_id ?? \"\",\n ).trim();\n const workspaceId = asString(\n params.workspaceId ?? params.workspace_id ?? \"\",\n ).trim();\n if (!conversationId) {\n return this.request(\"addConversationListener\", params);\n }\n return this.addConversationListenerWithResumeFallback(\n conversationId,\n workspaceId || null,\n );\n }\n\n async removeConversationListener(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"removeConversationListener\", params);\n }\n\n async threadLiveSubscribe(params: Record<string, unknown>): Promise<unknown> {\n const workspaceId = normalizeThreadLiveWorkspaceId(\n params.workspaceId ?? params.workspace_id,\n );\n const workspaceIdForPayload = resolveThreadLiveWorkspacePayloadId(workspaceId);\n const threadId = asString(\n params.threadId ?? params.thread_id ?? params.conversationId,\n ).trim();\n if (!threadId) {\n return {};\n }\n\n const key = threadLiveKey(workspaceId, threadId);\n const realtimeResponse = await this.startThreadRealtime(\n threadId,\n workspaceIdForPayload,\n );\n if (realtimeResponse) {\n const previousSubscriptionId =\n this.threadLiveSubscriptionIdByKey.get(key) ?? null;\n this.threadLiveSubscriptionIdByKey.delete(key);\n this.threadLiveModeByKey.set(key, \"realtime\");\n if (previousSubscriptionId) {\n void this.removeConversationListenerBySubscriptionId(\n previousSubscriptionId,\n ).catch(() => {\n // Best-effort cleanup when switching listener modes.\n });\n }\n return realtimeResponse;\n }\n const response = await this.addConversationListenerWithResumeFallback(\n threadId,\n workspaceIdForPayload,\n );\n this.threadLiveModeByKey.set(key, \"listener\");\n this.trackThreadLiveSubscriptionId(\n key,\n asString(response?.subscriptionId ?? \"\").trim() || null,\n );\n return response ?? {};\n }\n\n async threadLiveUnsubscribe(\n params: Record<string, unknown>,\n ): Promise<unknown> {\n const workspaceId = normalizeThreadLiveWorkspaceId(\n params.workspaceId ?? params.workspace_id,\n );\n const workspaceIdForPayload = resolveThreadLiveWorkspacePayloadId(workspaceId);\n const threadId = asString(\n params.threadId ?? params.thread_id ?? params.conversationId,\n ).trim();\n if (!threadId) {\n return {};\n }\n\n const key = threadLiveKey(workspaceId, threadId);\n const mode = this.threadLiveModeByKey.get(key) ?? null;\n this.threadLiveModeByKey.delete(key);\n const subscriptionId = this.threadLiveSubscriptionIdByKey.get(key) ?? null;\n this.threadLiveSubscriptionIdByKey.delete(key);\n\n if (mode === \"realtime\") {\n const stoppedRealtime = await this.stopThreadRealtime(\n threadId,\n workspaceIdForPayload,\n );\n if (stoppedRealtime) {\n return {};\n }\n }\n if (subscriptionId) {\n await this.removeConversationListenerBySubscriptionId(subscriptionId);\n return {};\n }\n if (mode !== \"listener\") {\n const stoppedRealtime = await this.stopThreadRealtime(\n threadId,\n workspaceIdForPayload,\n );\n if (stoppedRealtime) {\n return {};\n }\n }\n return this.removeConversationListener(\n workspaceIdForPayload\n ? {\n conversationId: threadId,\n workspaceId: workspaceIdForPayload,\n workspace_id: workspaceIdForPayload,\n }\n : { conversationId: threadId },\n );\n }\n\n async sendUserMessage(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"sendUserMessage\", normalizeSendUserMessageParams(params));\n }\n\n async threadStart(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"thread/start\", params);\n }\n\n async threadResume(params: Record<string, unknown>): Promise<unknown> {\n const sanitized = { ...params };\n delete sanitized.rolloutPath;\n delete sanitized.rollout_path;\n return this.request(\"thread/resume\", sanitized);\n }\n\n async turnStart(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"turn/start\", normalizeTurnInputParams(params));\n }\n\n async steerTurn(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"turn/steer\", normalizeTurnInputParams(params));\n }\n\n async interruptTurn(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"turn/interrupt\", params);\n }\n\n async turnSteer(params: Record<string, unknown>): Promise<unknown> {\n return this.steerTurn(params);\n }\n\n async turnInterrupt(params: Record<string, unknown>): Promise<unknown> {\n return this.interruptTurn(params);\n }\n\n async interruptConversation(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"interruptConversation\", params);\n }\n\n async archiveConversation(conversationId: string): Promise<void> {\n try {\n await this.request(\"thread/archive\", { threadId: conversationId });\n return;\n } catch {\n // fall through to legacy endpoint\n }\n try {\n await this.request(\"archiveConversation\", { conversationId });\n } catch {\n // ignore archive failures\n }\n }\n\n async listConversations(params: {\n cursor?: string | null;\n limit?: number;\n cwd?: string | null;\n sortKey?: \"created_at\" | \"updated_at\" | null;\n searchQuery?: string | null;\n sourceKinds?: string[] | null;\n archived?: boolean | null;\n modelProviders?: string[] | null;\n }): Promise<unknown> {\n return this.request(\"thread/list\", {\n cursor: params.cursor ?? null,\n limit: params.limit ?? 20,\n cwd: params.cwd ?? null,\n sortKey: params.sortKey ?? null,\n searchQuery: params.searchQuery ?? null,\n sourceKinds: params.sourceKinds ?? null,\n archived: params.archived ?? null,\n modelProviders: params.modelProviders ?? null,\n });\n }\n\n async listSkillsCore(params?: {\n cwd?: string | null;\n forceReload?: boolean;\n }): Promise<unknown> {\n const cwd = typeof params?.cwd === \"string\" ? params.cwd.trim() : \"\";\n return this.request(\"skills/list\", {\n cwds: cwd ? [cwd] : [],\n forceReload: Boolean(params?.forceReload),\n });\n }\n\n async listApps(params?: AppsListParams): Promise<unknown> {\n const payload = buildAppsListPayload(params);\n const methods = [\"app/list\", \"apps/list\", \"apps_list\"] as const;\n for (let index = 0; index < methods.length; index += 1) {\n const method = methods[index];\n try {\n return await this.request(method, payload);\n } catch (error) {\n const hasLegacyFallback = index < methods.length - 1;\n if (hasLegacyFallback && isMethodUnavailableError(error, method)) {\n continue;\n }\n if (isAppsListThreadNotFoundError(error)) {\n return { data: [] };\n }\n throw error;\n }\n }\n throw new Error(\"Apps list is unavailable from the connected Codex backend.\");\n }\n\n async setSkillEnabledCore(params: { path: string; enabled: boolean }): Promise<unknown> {\n const skillPath = typeof params.path === \"string\" ? params.path.trim() : \"\";\n if (!skillPath) {\n throw new Error(\"Skill path is required.\");\n }\n return this.request(\"skills/config/write\", {\n path: skillPath,\n enabled: Boolean(params.enabled),\n });\n }\n\n async readThread(params: { threadId: string; includeTurns?: boolean | null }): Promise<unknown> {\n return this.request(\"thread/read\", {\n threadId: params.threadId,\n includeTurns: Boolean(params.includeTurns),\n });\n }\n\n async setThreadName(threadId: string, name: string): Promise<unknown> {\n return this.request(\"thread/name/set\", { threadId, name });\n }\n\n async startReview(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"review/start\", params);\n }\n\n async startCompact(params: Record<string, unknown>): Promise<unknown> {\n try {\n return await this.request(\"thread/compact/start\", params);\n } catch {\n try {\n return await this.request(\"thread/compact\", params);\n } catch {\n return this.request(\"compactThread\", params);\n }\n }\n }\n\n async respondExecCommandRequest(requestToken: string, decision: CodexReviewDecision): Promise<void> {\n await this.respondReviewDecision(requestToken, \"exec\", decision);\n }\n\n async respondApplyPatchRequest(requestToken: string, decision: CodexReviewDecision): Promise<void> {\n await this.respondReviewDecision(requestToken, \"patch\", decision);\n }\n\n async respondToServerRequest(requestId: JsonRpcId, result: Record<string, unknown>): Promise<void> {\n const token = requestIdToToken(requestId);\n const pending = this.pendingServerRequests.get(token);\n if (!pending) {\n throw new Error(`Unknown server request: ${requestId}`);\n }\n this.pendingServerRequests.delete(token);\n await this.sendResponse(pending.id, result ?? {});\n }\n\n private async spawnProcess(): Promise<void> {\n const codexPath = await requireCodexCli();\n const env = buildCliEnv(codexPath, { ELECTRON_RUN_AS_NODE: \"1\" });\n const runtimeBin = resolveRuntimeBinary(env);\n const child = spawn(runtimeBin, [codexPath, \"app-server\"], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env,\n });\n this.child = child;\n this.initializeResponse = null;\n this.initializePromise = null;\n this.parseLineBuffer = null;\n\n child.on(\"exit\", (code, signal) => {\n logWarn(\"[app-server] exited\", { code, signal });\n this.child = null;\n this.initializeResponse = null;\n this.initializePromise = null;\n this.threadLiveSubscriptionIdByKey.clear();\n this.threadLiveModeByKey.clear();\n this.clearPendingRequests(new Error(\"codex app-server exited\"));\n this.emit(\"codex:process-exited\", {});\n });\n child.on(\"error\", error => {\n logError(\"[app-server] process error\", error);\n this.threadLiveSubscriptionIdByKey.clear();\n this.threadLiveModeByKey.clear();\n this.emit(\"codex:process-exited\", {});\n });\n\n if (child.stderr) {\n child.stderr.on(\"data\", chunk => {\n const lines = chunk.toString().split(/\\r?\\n/);\n for (const line of lines) {\n const message = line.trim();\n if (!message) continue;\n // Filter out known harmless errors from the Rust backend's state db reconciliation.\n // These occur when the db has thread entries for session files that no longer exist.\n const normalized = message.toLowerCase();\n if (normalized.includes(\"state db missing rollout path for thread\")) {\n continue;\n }\n // The app-server may emit this during recorder initialization; it's noisy/non-actionable in UI logs.\n if (\n normalized.includes(\"rollout::recorder\") &&\n normalized.includes(\"falling back on rollout system\")\n ) {\n continue;\n }\n if (isIgnorableAppsListTransportStderr(message)) {\n continue;\n }\n if (isIgnorableMissingSkillsSymlinkStderr(message)) {\n continue;\n }\n logWarn(\"[app-server] stderr\", message);\n }\n });\n }\n\n if (!child.stdout) {\n throw new Error(\"codex app-server missing stdout\");\n }\n\n this.reader = readline.createInterface({\n input: child.stdout,\n crlfDelay: Infinity,\n });\n\n this.reader.on(\"line\", line => {\n this.handleIncomingLine(line);\n });\n\n logInfo(\"[app-server] started\");\n }\n\n private handleIncomingLine(line: string): void {\n if (this.parseLineBuffer !== null) {\n const merged = `${this.parseLineBuffer}\\n${line}`;\n const handled = this.tryHandleMessage(merged);\n if (handled) {\n this.parseLineBuffer = null;\n return;\n }\n if (merged.length < MAX_PARSE_BUFFER_CHARS) {\n this.parseLineBuffer = merged;\n return;\n }\n this.logParseFailure(\n merged,\n new Error(\"Buffered JSON message exceeded max size while recovering malformed output.\"),\n );\n this.parseLineBuffer = null;\n return;\n }\n\n if (!line.trim()) {\n return;\n }\n\n const handled = this.tryHandleMessage(line);\n if (handled) {\n return;\n }\n\n if (line.trimStart().startsWith(\"{\")) {\n this.parseLineBuffer = line;\n }\n }\n\n private tryHandleMessage(line: string): boolean {\n let parsed: unknown;\n let parseError: unknown = null;\n try {\n parsed = JSON.parse(line) as unknown;\n } catch (error) {\n parseError = error;\n const repaired = escapeInvalidJsonStringChars(line);\n if (repaired !== line) {\n try {\n parsed = JSON.parse(repaired) as unknown;\n parseError = null;\n } catch (repairError) {\n parseError = repairError;\n }\n }\n }\n\n if (parseError) {\n if (isLikelyRecoverableJsonParseError(parseError)) {\n return false;\n }\n this.logParseFailure(line, parseError);\n return true;\n }\n if (!isRecord(parsed)) {\n logWarn(\"[app-server] unexpected JSON message\", parsed);\n return true;\n }\n\n const hasId = \"id\" in parsed;\n const hasMethod = typeof parsed.method === \"string\";\n const hasResult = \"result\" in parsed;\n const hasError = \"error\" in parsed;\n\n if (hasMethod && hasId) {\n this.handleServerRequest(parsed as JsonRpcRequest);\n return true;\n }\n\n if (hasMethod) {\n this.handleNotification(parsed as JsonRpcNotification);\n return true;\n }\n\n if (hasId && (hasResult || hasError)) {\n this.handleResponse(parsed as JsonRpcResponse);\n return true;\n }\n\n logWarn(\"[app-server] unknown message shape\", parsed);\n return true;\n }\n\n private logParseFailure(line: string, error: unknown): void {\n const message = error instanceof Error ? error.message : String(error);\n logWarn(\"[app-server] failed to parse JSON\", {\n error: message,\n length: line.length,\n startsWithJsonObject: line.trimStart().startsWith(\"{\"),\n });\n }\n\n private handleResponse(response: JsonRpcResponse): void {\n const token = requestIdToToken(response.id);\n const pending = this.pendingRequests.get(token);\n if (!pending) {\n logWarn(\"[app-server] response with no pending request\", response.id);\n return;\n }\n this.pendingRequests.delete(token);\n\n if (response.error) {\n const error = new Error(response.error.message || \"codex app-server error\");\n (error as Error & { code?: number; data?: unknown }).code = response.error.code;\n (error as Error & { code?: number; data?: unknown }).data = response.error.data;\n const suppressBackendErrorEvent =\n isAppsListMethod(pending.method) ||\n (pending.method === \"addConversationListener\" && isThreadNotFoundError(error)) ||\n (pending.method === \"thread/resume\" && isThreadNotFoundError(error));\n if (!suppressBackendErrorEvent) {\n this.emit(\"codex:backend-error\", {\n code: response.error.code,\n message: response.error.message,\n data: response.error.data,\n } satisfies CodexBackendErrorPayload);\n }\n pending.reject(error);\n return;\n }\n\n pending.resolve(response.result);\n }\n\n private handleNotification(notification: JsonRpcNotification): void {\n const { method, params } = notification;\n if (method.startsWith(\"codex/event/\")) {\n this.emit(\"codex:event\", { method, params } satisfies CodexEventPayload);\n return;\n }\n\n const normalized = method.toLowerCase();\n if (normalized.includes(\"auth\") && normalized.includes(\"status\")) {\n this.emit(\"codex:auth-status\", params ?? {});\n return;\n }\n if (normalized.includes(\"login\") && normalized.includes(\"complete\")) {\n this.emit(\"codex:login-complete\", params ?? {});\n return;\n }\n\n this.emit(\"codex:notification\", { method, params } satisfies CodexNotificationPayload);\n }\n\n private handleServerRequest(request: JsonRpcRequest): void {\n const kind = pickMethodKind(request.method, request.params);\n if (!kind) {\n void this.sendError(request.id, {\n code: -32601,\n message: `Unsupported request: ${request.method}`,\n });\n return;\n }\n\n const token = requestIdToToken(request.id);\n this.pendingServerRequests.set(token, { id: request.id, kind, method: request.method });\n\n const params = isRecord(request.params) ? request.params : {};\n if (kind === \"exec\") {\n this.emit(\"codex:exec-command-request\", {\n requestToken: token,\n params,\n } satisfies CodexExecCommandRequestPayload);\n } else if (kind === \"patch\") {\n this.emit(\"codex:apply-patch-request\", {\n requestToken: token,\n params,\n } satisfies CodexApplyPatchRequestPayload);\n } else {\n this.emit(\"codex:server-request\", {\n requestId: request.id,\n method: request.method,\n params,\n } satisfies CodexServerRequestPayload);\n }\n }\n\n private async respondReviewDecision(\n requestToken: string,\n kind: PendingRequestKind,\n decision: CodexReviewDecision,\n ): Promise<void> {\n const pending = this.pendingServerRequests.get(requestToken);\n if (!pending) {\n throw new Error(`Unknown approval request: ${requestToken}`);\n }\n if (pending.kind !== kind) {\n throw new Error(`Mismatched approval request type for ${requestToken}`);\n }\n this.pendingServerRequests.delete(requestToken);\n await this.sendResponse(pending.id, { decision });\n }\n\n private async request(method: string, params?: unknown): Promise<unknown> {\n // Skip initialization check for the initialize method itself to avoid recursive deadlock\n if (method !== \"initialize\") {\n await this.initialize();\n } else {\n await this.start();\n }\n const id = this.nextRequestId++;\n const token = requestIdToToken(id);\n const timeoutMs = getRequestTimeoutMs(method);\n const payload: JsonRpcRequest = params ? { id, method, params } : { id, method };\n const result = new Promise<unknown>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const pending = this.pendingRequests.get(token);\n if (!pending) {\n return;\n }\n this.pendingRequests.delete(token);\n const timeoutError = new Error(\n `codex app-server request timed out after ${timeoutMs}ms (${method})`,\n );\n pending.reject(timeoutError);\n this.maybeRecoverFromTimeout(method, timeoutError);\n }, timeoutMs);\n\n this.pendingRequests.set(token, {\n method,\n resolve: (value) => {\n clearTimeout(timeout);\n resolve(value);\n },\n reject: (error) => {\n clearTimeout(timeout);\n reject(error);\n },\n });\n });\n await this.writeMessage(payload);\n return result;\n }\n\n private async notify(method: string, params?: unknown): Promise<void> {\n await this.start();\n const payload: JsonRpcNotification = params ? { method, params } : { method };\n await this.writeMessage(payload);\n }\n\n private async sendResponse(id: JsonRpcId, result: unknown): Promise<void> {\n await this.writeMessage({ id, result });\n }\n\n private async sendError(id: JsonRpcId, error: JsonRpcError): Promise<void> {\n await this.writeMessage({ id, error });\n }\n\n private async writeMessage(message: Record<string, unknown>): Promise<void> {\n if (!this.child || !this.child.stdin) {\n throw new Error(\"codex app-server is not running\");\n }\n const payload = JSON.stringify({ jsonrpc: \"2.0\", ...message });\n this.child.stdin.write(`${payload}\\n`);\n }\n\n private clearPendingRequests(error: Error): void {\n for (const pending of this.pendingRequests.values()) {\n pending.reject(error);\n }\n this.pendingRequests.clear();\n this.pendingServerRequests.clear();\n this.threadLiveSubscriptionIdByKey.clear();\n this.threadLiveModeByKey.clear();\n }\n\n private maybeRecoverFromTimeout(method: string, error: unknown): void {\n const message = error instanceof Error ? error.message : String(error ?? \"\");\n if (!isRequestTimeoutErrorMessage(message)) {\n return;\n }\n // Runtime methods may time out transiently (network/auth/backend contention).\n // Hard-recycling the app-server here causes request-failure storms and severe UI jank.\n // Keep automatic recycle only for initialize-timeouts.\n if (method !== \"initialize\") {\n const now = Date.now();\n const lastWarning = this.lastTimeoutWarningAtByMethod.get(method) ?? 0;\n if (now - lastWarning >= REQUEST_TIMEOUT_WARNING_COOLDOWN_MS) {\n this.lastTimeoutWarningAtByMethod.set(method, now);\n logWarn(\"[app-server] request timed out (keeping process alive)\", { method });\n }\n return;\n }\n if (this.timeoutRecoveryPromise) {\n return;\n }\n this.timeoutRecoveryPromise = (async () => {\n logWarn(\"[app-server] recycling after request timeout\", { method });\n try {\n await this.stop();\n } catch (stopError) {\n logWarn(\"[app-server] failed to recycle after timeout\", stopError);\n }\n })().finally(() => {\n this.timeoutRecoveryPromise = null;\n });\n }\n}\n","export type AppsListParams = {\n workspaceId?: string | null;\n threadId?: string | null;\n cursor?: string | null;\n limit?: number | null;\n};\n\nconst APPS_LIST_METHODS = new Set([\"app/list\", \"apps/list\", \"apps_list\"]);\n\nexport function isAppsListMethod(method: string): boolean {\n return APPS_LIST_METHODS.has(method);\n}\n\nexport function buildAppsListPayload(params?: AppsListParams): {\n threadId: string | null;\n cursor: string | null;\n limit: number | null;\n} {\n return {\n threadId: params?.threadId ?? null,\n cursor: params?.cursor ?? null,\n limit: params?.limit ?? null,\n };\n}\n\nexport function isMethodUnavailableError(error: unknown, method: string): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n const code = typeof (error as { code?: unknown }).code === \"number\"\n ? ((error as { code: number }).code)\n : null;\n if (code !== -32601 && code !== -32600) {\n return false;\n }\n const message = typeof (error as { message?: unknown }).message === \"string\"\n ? ((error as { message: string }).message).toLowerCase()\n : \"\";\n if (!message) {\n return false;\n }\n const normalizedMethod = method.toLowerCase();\n if (message.includes(\"method not found\") || message.includes(\"unknown method\")) {\n return true;\n }\n return message.includes(\"unknown variant\") && message.includes(normalizedMethod);\n}\n\nexport function isAppsListSoftFailure(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n const message = typeof (error as { message?: unknown }).message === \"string\"\n ? ((error as { message: string }).message).toLowerCase()\n : \"\";\n if (!message) {\n return false;\n }\n const mentionsAppsFailure = message.includes(\"failed to list apps\");\n if (!mentionsAppsFailure) {\n return false;\n }\n const hasTransportFailure =\n message.includes(\"failed to send request\") ||\n message.includes(\"transport channel closed\") ||\n message.includes(\"connection closed via error\") ||\n message.includes(\"reqwest::error\");\n if (hasTransportFailure) {\n return true;\n }\n const has403 =\n message.includes(\"status 403\") ||\n message.includes(\"403 forbidden\") ||\n message.includes(\"forbidden\");\n const hasConnectorDirectory = message.includes(\"connectors/directory/list\");\n const hasChallengeMarkers =\n message.includes(\"just a moment\") ||\n message.includes(\"cdn-cgi/challenge-platform\") ||\n message.includes(\"_cf_chl_opt\");\n const hasHtmlPayload = message.includes(\"<!doctype html\") || message.includes(\"<html\");\n return has403 && (hasConnectorDirectory || hasChallengeMarkers || hasHtmlPayload);\n}\n\nexport function isAppsListThreadNotFoundError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n const message = typeof (error as { message?: unknown }).message === \"string\"\n ? ((error as { message: string }).message).toLowerCase()\n : \"\";\n if (!message) {\n return false;\n }\n const mentionsThread = message.includes(\"thread\");\n const mentionsNotFound =\n message.includes(\"not found\") || message.includes(\"unknown thread\");\n return mentionsThread && mentionsNotFound;\n}\n","import path from \"path\";\n\nexport function buildCliEnv(codexPath: string, overrides: Partial<NodeJS.ProcessEnv> = {}): NodeJS.ProcessEnv {\n const env = { ...process.env, ...overrides };\n const currentPath = env.PATH ?? \"\";\n const codexDir = path.dirname(codexPath);\n const homeDir = process.env.HOME ?? \"\";\n const extraPathHints = (process.env.CODEX_PATH_HINTS ?? \"\")\n .split(path.delimiter)\n .map(entry => entry.trim())\n .filter(Boolean);\n const extras = [\n codexDir,\n \"/usr/local/bin\",\n \"/opt/homebrew/bin\",\n path.join(homeDir, \".local\", \"bin\"),\n path.join(homeDir, \".fnm\", \"aliases\", \"default\", \"bin\"),\n path.join(homeDir, \".fnm\", \"current\", \"bin\"),\n ...extraPathHints,\n ].filter(Boolean);\n\n const segments = [\n ...extras,\n ...currentPath.split(path.delimiter).filter(Boolean),\n ];\n\n env.PATH = Array.from(new Set(segments)).join(path.delimiter);\n return env;\n}\n","import path from \"node:path\";\nimport fs from \"node:fs/promises\";\nimport { randomUUID } from \"node:crypto\";\nimport { getAppState, getUserDataDir } from \"./app-state\";\nimport { cloneRepositoryFromUrl } from \"./git\";\nimport { FREE_PROFILE_LIMIT, licenseService, shouldEnforceProfileLimit } from \"./license-service\";\n\nconst STORE_FILE = \"workspace-parity.json\";\nconst LEGACY_STORE_FILE = \"workspace-parity.json\";\nconst PROFILE_ROOT_DIR = \"profiles\";\nconst PROFILE_PARITY_DIR = \"parity\";\nconst LEGACY_MIGRATION_MARKER_FILE = \"workspace-parity-profile-migration.json\";\n\nexport type WorkspaceSettings = {\n sidebarCollapsed: boolean;\n sortOrder?: number | null;\n groupId?: string | null;\n cloneSourceWorkspaceId?: string | null;\n gitRoot?: string | null;\n launchScript?: string | null;\n launchScripts?:\n | Array<{\n id: string;\n script: string;\n icon: string;\n label?: string | null;\n }>\n | null;\n worktreeSetupScript?: string | null;\n};\n\nexport type WorkspaceKind = \"main\" | \"worktree\";\n\nexport type WorkspaceInfo = {\n id: string;\n name: string;\n path: string;\n connected: boolean;\n kind?: WorkspaceKind;\n parentId?: string | null;\n worktree?: { branch: string } | null;\n settings: WorkspaceSettings;\n};\n\ntype WorkspaceStore = {\n version: 1;\n workspaces: WorkspaceInfo[];\n};\n\ntype LegacyMigrationMarker = {\n version: 1;\n migratedToProfileKey: string;\n migratedAt: string;\n};\n\ntype ActiveProfileContext = {\n profileName: string | null;\n profileKey: string;\n profileRootDir: string;\n parityStoreDir: string;\n};\n\nfunction defaultSettings(): WorkspaceSettings {\n return {\n sidebarCollapsed: false,\n sortOrder: null,\n groupId: null,\n cloneSourceWorkspaceId: null,\n gitRoot: null,\n launchScript: null,\n launchScripts: null,\n worktreeSetupScript: null,\n };\n}\n\nfunction defaultStore(): WorkspaceStore {\n return {\n version: 1,\n workspaces: [],\n };\n}\n\nfunction normalizeProfileName(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction toProfileStorageKey(profileName: string | null): string {\n const normalized = (profileName ?? \"default\")\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return normalized || \"default\";\n}\n\nasync function getActiveProfileContext(): Promise<ActiveProfileContext> {\n let profileName: string | null = null;\n try {\n const state = await getAppState();\n profileName = normalizeProfileName(state.app.lastProfileName);\n } catch {\n profileName = null;\n }\n const profileKey = toProfileStorageKey(profileName);\n const profileRootDir = path.join(getUserDataDir(), PROFILE_ROOT_DIR, profileKey);\n return {\n profileName,\n profileKey,\n profileRootDir,\n parityStoreDir: path.join(profileRootDir, PROFILE_PARITY_DIR),\n };\n}\n\nfunction toWorkspaceName(inputPath: string): string {\n const normalized = inputPath.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n const parts = normalized.split(\"/\").filter(Boolean);\n return parts[parts.length - 1] ?? inputPath;\n}\n\nasync function ensureStoreDir(): Promise<string> {\n const context = await getActiveProfileContext();\n const dir = context.parityStoreDir;\n await fs.mkdir(dir, { recursive: true });\n return dir;\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction legacyStorePath(): string {\n return path.join(getUserDataDir(), LEGACY_STORE_FILE);\n}\n\nfunction legacyMigrationMarkerPath(): string {\n return path.join(getUserDataDir(), LEGACY_MIGRATION_MARKER_FILE);\n}\n\nasync function readLegacyMigrationMarker(): Promise<LegacyMigrationMarker | null> {\n try {\n const raw = await fs.readFile(legacyMigrationMarkerPath(), \"utf8\");\n const parsed = JSON.parse(raw) as LegacyMigrationMarker;\n if (\n parsed &&\n parsed.version === 1 &&\n typeof parsed.migratedToProfileKey === \"string\" &&\n parsed.migratedToProfileKey.trim()\n ) {\n return parsed;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nasync function writeLegacyMigrationMarker(profileKey: string): Promise<void> {\n const marker: LegacyMigrationMarker = {\n version: 1,\n migratedToProfileKey: profileKey,\n migratedAt: new Date().toISOString(),\n };\n const markerPath = legacyMigrationMarkerPath();\n await fs.mkdir(path.dirname(markerPath), { recursive: true });\n await fs.writeFile(markerPath, JSON.stringify(marker, null, 2), \"utf8\");\n}\n\nasync function migrateLegacyStoreIfNeeded(scopedStorePath: string): Promise<void> {\n if (await fileExists(scopedStorePath)) {\n return;\n }\n\n const context = await getActiveProfileContext();\n const legacyPath = legacyStorePath();\n if (!(await fileExists(legacyPath))) {\n return;\n }\n\n const marker = await readLegacyMigrationMarker();\n if (\n marker &&\n marker.migratedToProfileKey &&\n marker.migratedToProfileKey !== context.profileKey\n ) {\n return;\n }\n\n await fs.mkdir(path.dirname(scopedStorePath), { recursive: true });\n await fs.copyFile(legacyPath, scopedStorePath);\n await writeLegacyMigrationMarker(context.profileKey);\n}\n\nasync function storePath(): Promise<string> {\n const dir = await ensureStoreDir();\n const scopedPath = path.join(dir, STORE_FILE);\n await migrateLegacyStoreIfNeeded(scopedPath);\n return scopedPath;\n}\n\nfunction sanitizeWorkspace(entry: Partial<WorkspaceInfo>): WorkspaceInfo | null {\n if (!entry || typeof entry !== \"object\") {\n return null;\n }\n const id = typeof entry.id === \"string\" && entry.id.trim() ? entry.id.trim() : null;\n const workspacePath = typeof entry.path === \"string\" && entry.path.trim() ? path.resolve(entry.path) : null;\n if (!id || !workspacePath) {\n return null;\n }\n const name =\n typeof entry.name === \"string\" && entry.name.trim()\n ? entry.name.trim()\n : toWorkspaceName(workspacePath);\n const branch =\n entry.worktree && typeof entry.worktree === \"object\" && typeof entry.worktree.branch === \"string\"\n ? entry.worktree.branch.trim() || \"main\"\n : \"main\";\n\n return {\n id,\n name,\n path: workspacePath,\n connected: Boolean(entry.connected),\n kind: entry.kind === \"worktree\" ? \"worktree\" : \"main\",\n parentId: typeof entry.parentId === \"string\" && entry.parentId.trim() ? entry.parentId.trim() : null,\n worktree: entry.kind === \"worktree\" ? { branch } : null,\n settings: {\n ...defaultSettings(),\n ...(entry.settings ?? {}),\n },\n };\n}\n\nasync function readStore(): Promise<WorkspaceStore> {\n const filePath = await storePath();\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n const parsed = JSON.parse(raw) as WorkspaceStore;\n const source = Array.isArray(parsed?.workspaces) ? parsed.workspaces : [];\n const workspaces = source\n .map((entry) => sanitizeWorkspace(entry))\n .filter((entry): entry is WorkspaceInfo => Boolean(entry));\n return {\n version: 1,\n workspaces,\n };\n } catch {\n return defaultStore();\n }\n}\n\nasync function writeStore(store: WorkspaceStore): Promise<void> {\n const filePath = await storePath();\n await fs.writeFile(filePath, JSON.stringify(store, null, 2), \"utf8\");\n}\n\nfunction dedupeByPath(workspaces: WorkspaceInfo[]): WorkspaceInfo[] {\n const seen = new Set<string>();\n const ordered: WorkspaceInfo[] = [];\n for (const workspace of workspaces) {\n const key = workspace.path.toLowerCase();\n if (seen.has(key)) {\n continue;\n }\n seen.add(key);\n ordered.push(workspace);\n }\n return ordered;\n}\n\nasync function upsertStore(mutator: (store: WorkspaceStore) => WorkspaceStore): Promise<WorkspaceStore> {\n const current = await readStore();\n const next = mutator(current);\n await writeStore(next);\n return next;\n}\n\nfunction isMainWorkspace(workspace: WorkspaceInfo): boolean {\n return (workspace.kind ?? \"main\") !== \"worktree\";\n}\n\nfunction pruneToFreeProjectLimit(workspaces: WorkspaceInfo[]): WorkspaceInfo[] {\n const mainWorkspaces = workspaces.filter((workspace) => isMainWorkspace(workspace));\n if (mainWorkspaces.length <= FREE_PROFILE_LIMIT) {\n return workspaces;\n }\n\n const keptMainIds = new Set(mainWorkspaces.slice(0, FREE_PROFILE_LIMIT).map((workspace) => workspace.id));\n return workspaces.filter((workspace) => {\n if (isMainWorkspace(workspace)) {\n return keptMainIds.has(workspace.id);\n }\n return typeof workspace.parentId === \"string\" && keptMainIds.has(workspace.parentId);\n });\n}\n\nasync function enforceFreeProjectLimitIfNeeded(workspaces: WorkspaceInfo[]): Promise<WorkspaceInfo[]> {\n const license = await licenseService.getStatus().catch(() => null);\n if (!license || !shouldEnforceProfileLimit(license)) {\n return workspaces;\n }\n\n const pruned = pruneToFreeProjectLimit(workspaces);\n if (pruned.length === workspaces.length) {\n return workspaces;\n }\n\n await writeStore({\n version: 1,\n workspaces: pruned,\n });\n return pruned;\n}\n\nfunction parseRepoName(gitUrl: string): string {\n const cleaned = gitUrl.trim().replace(/\\/+$/, \"\").replace(/\\.git$/, \"\");\n const parts = cleaned.split(/[/:]/).filter(Boolean);\n return parts[parts.length - 1] ?? \"workspace\";\n}\n\nexport async function listParityWorkspaces(): Promise<WorkspaceInfo[]> {\n const store = await readStore();\n const deduped = dedupeByPath(store.workspaces);\n return enforceFreeProjectLimitIfNeeded(deduped);\n}\n\nexport async function getParityWorkspaceById(id: string): Promise<WorkspaceInfo | null> {\n const workspaces = await listParityWorkspaces();\n return workspaces.find((entry) => entry.id === id) ?? null;\n}\n\nexport async function addParityWorkspace(targetPath: string): Promise<WorkspaceInfo> {\n const resolved = path.resolve(targetPath);\n const name = toWorkspaceName(resolved);\n await fs.mkdir(resolved, { recursive: true });\n\n const nextWorkspace: WorkspaceInfo = {\n id: randomUUID(),\n name,\n path: resolved,\n connected: true,\n kind: \"main\",\n parentId: null,\n worktree: null,\n settings: defaultSettings(),\n };\n\n await upsertStore((store) => ({\n version: 1,\n workspaces: dedupeByPath([nextWorkspace, ...store.workspaces]),\n }));\n\n return nextWorkspace;\n}\n\nexport async function addParityWorkspaceFromGitUrl(options: {\n url: string;\n targetParentPath?: string | null;\n name?: string | null;\n}): Promise<WorkspaceInfo> {\n const repoName = options.name?.trim() || parseRepoName(options.url);\n const context = await getActiveProfileContext();\n const parentPath =\n options.targetParentPath?.trim() || path.join(context.profileRootDir, \"workspaces\");\n\n const resolvedParent = path.resolve(parentPath);\n await fs.mkdir(resolvedParent, { recursive: true });\n\n const cloneResult = await cloneRepositoryFromUrl({\n url: options.url,\n destinationPath: resolvedParent,\n targetFolderName: repoName,\n });\n\n return addParityWorkspace(cloneResult.path);\n}\n\nexport async function addParityClone(options: {\n parentId: string;\n branch: string;\n name?: string | null;\n copyAgentsMd?: boolean;\n targetParentPath?: string | null;\n}): Promise<WorkspaceInfo> {\n const parent = await getParityWorkspaceById(options.parentId);\n if (!parent) {\n throw new Error(`Parent workspace '${options.parentId}' not found.`);\n }\n const branch = options.branch?.trim() || \"main\";\n const cloneName = options.name?.trim() || `${parent.name}-${branch}`;\n const cloneParentPath =\n typeof options.targetParentPath === \"string\" &&\n options.targetParentPath.trim().length > 0\n ? options.targetParentPath.trim()\n : path.dirname(parent.path);\n const clonePath = path.resolve(cloneParentPath, cloneName);\n await fs.mkdir(clonePath, { recursive: true });\n\n const workspace: WorkspaceInfo = {\n id: randomUUID(),\n name: cloneName,\n path: clonePath,\n connected: true,\n kind: \"worktree\",\n parentId: parent.id,\n worktree: { branch },\n settings: {\n ...defaultSettings(),\n cloneSourceWorkspaceId: parent.id,\n },\n };\n\n await upsertStore((store) => ({\n version: 1,\n workspaces: dedupeByPath([workspace, ...store.workspaces]),\n }));\n\n return workspace;\n}\n\nexport async function addParityWorktree(options: {\n parentId: string;\n branch: string;\n name?: string | null;\n copyAgentsMd?: boolean;\n targetParentPath?: string | null;\n}): Promise<WorkspaceInfo> {\n return addParityClone(options);\n}\n\nexport async function updateParityWorkspaceSettings(\n id: string,\n settings: Partial<WorkspaceSettings>,\n): Promise<WorkspaceInfo> {\n let updated: WorkspaceInfo | null = null;\n await upsertStore((store) => {\n const next = store.workspaces.map((entry) => {\n if (entry.id !== id) {\n return entry;\n }\n updated = {\n ...entry,\n settings: {\n ...entry.settings,\n ...settings,\n },\n };\n return updated;\n });\n return {\n version: 1,\n workspaces: next,\n };\n });\n\n if (!updated) {\n throw new Error(`Workspace '${id}' not found.`);\n }\n return updated;\n}\n\nexport async function removeParityWorkspace(id: string): Promise<void> {\n await upsertStore((store) => ({\n version: 1,\n workspaces: store.workspaces.filter((entry) => entry.id !== id && entry.parentId !== id),\n }));\n}\n\nexport async function removeParityWorktree(id: string): Promise<void> {\n await upsertStore((store) => ({\n version: 1,\n workspaces: store.workspaces.filter((entry) => entry.id !== id),\n }));\n}\n\nexport async function renameParityWorktree(id: string, branch: string): Promise<WorkspaceInfo> {\n const normalizedBranch = branch.trim();\n if (!normalizedBranch) {\n throw new Error(\"Branch name is required.\");\n }\n\n let updated: WorkspaceInfo | null = null;\n await upsertStore((store) => {\n const next = store.workspaces.map((entry) => {\n if (entry.id !== id) {\n return entry;\n }\n updated = {\n ...entry,\n name: normalizedBranch,\n worktree: {\n branch: normalizedBranch,\n },\n };\n return updated;\n });\n return {\n version: 1,\n workspaces: next,\n };\n });\n\n if (!updated) {\n throw new Error(`Workspace '${id}' not found.`);\n }\n return updated;\n}\n\nexport async function renameParityWorktreeUpstream(\n id: string,\n oldBranch: string,\n newBranch: string,\n): Promise<WorkspaceInfo> {\n void oldBranch;\n return renameParityWorktree(id, newBranch);\n}\n\nexport async function connectParityWorkspace(id: string): Promise<WorkspaceInfo> {\n let updated: WorkspaceInfo | null = null;\n await upsertStore((store) => {\n const next = store.workspaces.map((entry) => {\n if (entry.id !== id) {\n return entry;\n }\n updated = {\n ...entry,\n connected: true,\n };\n return updated;\n });\n return {\n version: 1,\n workspaces: next,\n };\n });\n\n if (!updated) {\n throw new Error(`Workspace '${id}' not found.`);\n }\n return updated;\n}\n","/**\n * Git Service\n *\n * Core git operations using native git CLI (CodexMonitor approach).\n * CLI is used first, isomorphic-git is fallback for edge cases.\n */\n\nimport git from \"isomorphic-git\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type {\n GitFileChange,\n GitFileStatus,\n GitRepoStatus,\n GitCommitOptions,\n GitCommitResult,\n GitAuthor,\n GitHubPullRequest,\n GitHubPullRequestComment,\n GitHubPullRequestDiff,\n GitCloneFromUrlOptions,\n GitCloneFromUrlResult,\n GitInitRepoResult,\n GitCreateGitHubRepoResult,\n GitPushCurrentBranchResult,\n} from \"./git-types\";\nimport * as cli from \"./git-cli\";\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Check if a directory is a git repository (CLI first)\n */\nexport async function isGitRepo(dir: string): Promise<boolean> {\n // Try CLI first\n const cliResult = await cli.isGitRepoCli(dir);\n if (cliResult) {\n return true;\n }\n // Fallback to isomorphic-git\n try {\n await git.findRoot({ fs, filepath: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the root directory of a git repo (CLI first)\n */\nexport async function getRepoRoot(dir: string): Promise<string | null> {\n // Try CLI first\n const cliResult = await cli.getRepoRootCli(dir);\n if (cliResult) {\n return cliResult;\n }\n // Fallback to isomorphic-git\n try {\n return await git.findRoot({ fs, filepath: dir });\n } catch {\n return null;\n }\n}\n\n/**\n * Get the current branch name (CLI first)\n */\nexport async function getCurrentBranch(dir: string): Promise<string | null> {\n // Try CLI first\n const cliResult = await cli.getCurrentBranchCli(dir);\n if (cliResult) {\n return cliResult;\n }\n // Fallback to isomorphic-git\n try {\n return (await git.currentBranch({ fs, dir, fullname: false })) ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Convert isomorphic-git status matrix to our file status\n * Status matrix format: [HEAD, WORKDIR, STAGE]\n * Values: 0 = absent, 1 = identical to HEAD, 2 = different from HEAD\n */\nfunction parseFileStatus(row: [string, number, number, number]): GitFileChange | null {\n const [filepath, head, workdir, stage] = row;\n\n // Skip unchanged files\n if (head === 1 && workdir === 1 && stage === 1) {\n return null;\n }\n\n let status: GitFileStatus = \"unchanged\";\n let staged = false;\n\n // Determine status based on the matrix\n if (head === 0 && workdir === 2 && stage === 0) {\n // New file, not staged (untracked)\n status = \"untracked\";\n } else if (head === 0 && workdir === 2 && stage === 2) {\n // New file, staged\n status = \"new\";\n staged = true;\n } else if (head === 0 && stage === 2) {\n // New file, staged\n status = \"new\";\n staged = true;\n } else if (head === 1 && workdir === 2 && stage === 1) {\n // Modified, not staged\n status = \"modified\";\n } else if (head === 1 && workdir === 2 && stage === 2) {\n // Modified, staged\n status = \"modified\";\n staged = true;\n } else if (head === 1 && stage === 2) {\n // Modified and staged\n status = \"modified\";\n staged = true;\n } else if (head === 1 && workdir === 0) {\n // Deleted\n status = \"deleted\";\n staged = stage === 0;\n } else if (head === 1 && workdir === 2 && stage === 3) {\n // Modified with staged and unstaged changes\n status = \"modified\";\n staged = true;\n }\n\n if (status === \"unchanged\") {\n return null;\n }\n\n return { filepath, status, staged };\n}\n\n/**\n * Calculate how many commits the local branch is ahead/behind the remote.\n * Uses the configured upstream or falls back to origin/<branch>.\n */\nasync function getAheadBehind(\n dir: string,\n branch: string | null\n): Promise<{ ahead: number; behind: number }> {\n if (!branch) {\n return { ahead: 0, behind: 0 };\n }\n\n try {\n // Try to find the remote tracking branch\n const remotes = await git.listRemotes({ fs, dir });\n if (remotes.length === 0) {\n return { ahead: 0, behind: 0 };\n }\n\n // Use 'origin' as default remote, or first available\n const remoteName = remotes.find((r) => r.remote === \"origin\")?.remote ?? remotes[0]?.remote;\n if (!remoteName) {\n return { ahead: 0, behind: 0 };\n }\n\n const remoteRef = `refs/remotes/${remoteName}/${branch}`;\n\n // Check if remote ref exists\n let remoteOid: string;\n try {\n remoteOid = await git.resolveRef({ fs, dir, ref: remoteRef });\n } catch {\n // Remote branch doesn't exist (e.g., new branch not pushed yet)\n // Count all local commits as \"ahead\"\n try {\n const localCommits = await git.log({ fs, dir, depth: 1000 });\n return { ahead: localCommits.length, behind: 0 };\n } catch {\n return { ahead: 0, behind: 0 };\n }\n }\n\n // Get local HEAD\n let localOid: string;\n try {\n localOid = await git.resolveRef({ fs, dir, ref: \"HEAD\" });\n } catch {\n return { ahead: 0, behind: 0 };\n }\n\n if (localOid === remoteOid) {\n return { ahead: 0, behind: 0 };\n }\n\n // Find merge base (common ancestor)\n const mergeBase = await git.findMergeBase({\n fs,\n dir,\n oids: [localOid, remoteOid],\n });\n\n if (!mergeBase || mergeBase.length === 0) {\n // No common ancestor - diverged completely\n return { ahead: 0, behind: 0 };\n }\n\n const baseOid = mergeBase[0];\n\n // Count commits from base to local (ahead)\n let ahead = 0;\n try {\n const localCommits = await git.log({ fs, dir, ref: localOid, depth: 1000 });\n for (const commit of localCommits) {\n if (commit.oid === baseOid) break;\n ahead++;\n }\n } catch {\n ahead = 0;\n }\n\n // Count commits from base to remote (behind)\n let behind = 0;\n try {\n const remoteCommits = await git.log({ fs, dir, ref: remoteOid, depth: 1000 });\n for (const commit of remoteCommits) {\n if (commit.oid === baseOid) break;\n behind++;\n }\n } catch {\n behind = 0;\n }\n\n return { ahead, behind };\n } catch (error) {\n console.error(\"Failed to calculate ahead/behind:\", error);\n return { ahead: 0, behind: 0 };\n }\n}\n\n/**\n * Get the status of all files in a git repository\n */\nexport async function getStatus(dir: string): Promise<GitRepoStatus> {\n // Check if it's a repo\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return {\n isRepo: false,\n branch: null,\n changes: [],\n hasChanges: false,\n ahead: 0,\n behind: 0,\n };\n }\n\n // Get branch\n const branch = await getCurrentBranch(repoRoot);\n\n // Try CLI first (CodexMonitor approach) - more reliable than isomorphic-git\n const cliStatus = await cli.getStatusCli(repoRoot);\n if (cliStatus) {\n return cliStatus;\n }\n\n // Fallback to isomorphic-git if CLI fails\n try {\n const statusMatrix = await git.statusMatrix({ fs, dir: repoRoot });\n\n const changes: GitFileChange[] = [];\n for (const row of statusMatrix) {\n const change = parseFileStatus(row as [string, number, number, number]);\n if (change) {\n changes.push(change);\n }\n }\n\n changes.sort((a, b) => {\n if (a.staged !== b.staged) {\n return a.staged ? -1 : 1;\n }\n return a.filepath.localeCompare(b.filepath);\n });\n\n const { ahead, behind } = await getAheadBehind(repoRoot, branch);\n\n return {\n isRepo: true,\n branch,\n changes,\n hasChanges: changes.length > 0,\n ahead,\n behind,\n };\n } catch (error) {\n console.error(\"Failed to read git status via isomorphic-git:\", error);\n\n return {\n isRepo: true,\n branch,\n changes: [],\n hasChanges: false,\n ahead: 0,\n behind: 0,\n };\n }\n}\n\n/**\n * Stage files for commit (CLI first)\n */\nexport async function stageFiles(dir: string, files: string[]): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository\");\n }\n\n // Try CLI first\n const cliResult = await cli.stageFilesCli(repoRoot, files);\n if (cliResult) {\n return;\n }\n\n // Fallback to isomorphic-git\n for (const filepath of files) {\n await git.add({ fs, dir: repoRoot, filepath });\n }\n}\n\n/**\n * Stage all changed files (CLI first)\n */\nexport async function stageAll(dir: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository\");\n }\n\n // Try CLI first\n const cliResult = await cli.stageAllCli(repoRoot);\n if (cliResult) {\n return;\n }\n\n // Fallback to isomorphic-git\n const status = await getStatus(repoRoot);\n\n for (const change of status.changes) {\n if (change.status === \"deleted\") {\n await git.remove({ fs, dir: repoRoot, filepath: change.filepath });\n } else {\n await git.add({ fs, dir: repoRoot, filepath: change.filepath });\n }\n }\n}\n\n/**\n * Create a commit (CLI first)\n */\nexport async function commit(options: GitCommitOptions): Promise<GitCommitResult> {\n const { dir, message, author, files } = options;\n\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return {\n sha: \"\",\n success: false,\n error: \"Not a git repository\",\n };\n }\n\n try {\n // Stage files if specified, otherwise stage all\n if (files && files.length > 0) {\n await stageFiles(repoRoot, files);\n } else {\n await stageAll(repoRoot);\n }\n\n // Try CLI first\n const cliResult = await cli.commitCli(repoRoot, message, author);\n if (cliResult.success) {\n return cliResult;\n }\n\n // Fallback to isomorphic-git\n const sha = await git.commit({\n fs,\n dir: repoRoot,\n message,\n author: {\n name: author.name,\n email: author.email,\n },\n });\n\n return {\n sha,\n success: true,\n };\n } catch (error) {\n return {\n sha: \"\",\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Get recent commits (CLI first)\n */\nexport async function getRecentCommits(\n dir: string,\n limit: number = 10\n): Promise<Array<{ sha: string; message: string; author: string; date: Date }>> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return [];\n }\n\n // Try CLI first\n const cliResult = await cli.getLogSummaryCli(repoRoot, limit);\n if (cliResult.length > 0) {\n return cliResult.map((c) => ({\n sha: c.sha,\n message: c.message,\n author: c.author,\n date: new Date(c.date),\n }));\n }\n\n // Fallback to isomorphic-git\n try {\n const commits = await git.log({ fs, dir: repoRoot, depth: limit });\n return commits.map((c) => ({\n sha: c.oid,\n message: c.commit.message,\n author: c.commit.author.name,\n date: new Date(c.commit.author.timestamp * 1000),\n }));\n } catch {\n return [];\n }\n}\n\n/**\n * Get default author from git config\n */\nexport async function getDefaultAuthor(dir: string): Promise<GitAuthor | null> {\n const cwd = await resolveGitCommandCwd(dir);\n\n const scopedName = await readGitConfigValue(cwd, [\"config\", \"--get\", \"user.name\"]);\n const scopedEmail = await readGitConfigValue(cwd, [\"config\", \"--get\", \"user.email\"]);\n\n let name = scopedName;\n let email = scopedEmail;\n\n if (!name || !email) {\n const globalName = await readGitConfigValue(cwd, [\"config\", \"--global\", \"--get\", \"user.name\"]);\n const globalEmail = await readGitConfigValue(cwd, [\"config\", \"--global\", \"--get\", \"user.email\"]);\n name = name ?? globalName;\n email = email ?? globalEmail;\n }\n\n if (!name || !email) {\n return null;\n }\n\n return { name, email };\n}\n\n/**\n * Simple line-by-line diff result\n */\nexport interface DiffLine {\n type: \"add\" | \"remove\" | \"context\";\n content: string;\n oldLineNumber?: number;\n newLineNumber?: number;\n}\n\nexport interface FileDiff {\n filepath: string;\n status: GitFileStatus;\n lines: DiffLine[];\n oldContent: string | null;\n newContent: string | null;\n isBinary: boolean;\n}\n\n/**\n * Check if content appears to be binary\n */\nfunction isBinaryContent(content: string): boolean {\n // Check for null bytes which indicate binary content\n return content.includes(\"\\0\");\n}\n\n/**\n * Simple diff algorithm - computes line-by-line changes\n */\nfunction computeLineDiff(oldContent: string, newContent: string): DiffLine[] {\n const oldLines = oldContent.split(\"\\n\");\n const newLines = newContent.split(\"\\n\");\n const result: DiffLine[] = [];\n\n // Use a simple LCS-based diff\n const lcs = computeLCS(oldLines, newLines);\n\n let oldIdx = 0;\n let newIdx = 0;\n let oldLineNum = 1;\n let newLineNum = 1;\n\n for (const [commonOldIdx, commonNewIdx] of lcs) {\n // Add removed lines before the common line\n while (oldIdx < commonOldIdx) {\n result.push({\n type: \"remove\",\n content: oldLines[oldIdx],\n oldLineNumber: oldLineNum++,\n });\n oldIdx++;\n }\n\n // Add inserted lines before the common line\n while (newIdx < commonNewIdx) {\n result.push({\n type: \"add\",\n content: newLines[newIdx],\n newLineNumber: newLineNum++,\n });\n newIdx++;\n }\n\n // Add the common line as context\n result.push({\n type: \"context\",\n content: oldLines[oldIdx],\n oldLineNumber: oldLineNum++,\n newLineNumber: newLineNum++,\n });\n oldIdx++;\n newIdx++;\n }\n\n // Add remaining removed lines\n while (oldIdx < oldLines.length) {\n result.push({\n type: \"remove\",\n content: oldLines[oldIdx],\n oldLineNumber: oldLineNum++,\n });\n oldIdx++;\n }\n\n // Add remaining inserted lines\n while (newIdx < newLines.length) {\n result.push({\n type: \"add\",\n content: newLines[newIdx],\n newLineNumber: newLineNum++,\n });\n newIdx++;\n }\n\n return result;\n}\n\n/**\n * Compute Longest Common Subsequence indices\n */\nfunction computeLCS(a: string[], b: string[]): [number, number][] {\n const m = a.length;\n const n = b.length;\n\n // Build LCS table\n const dp: number[][] = Array(m + 1)\n .fill(null)\n .map(() => Array(n + 1).fill(0));\n\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n if (a[i - 1] === b[j - 1]) {\n dp[i][j] = dp[i - 1][j - 1] + 1;\n } else {\n dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);\n }\n }\n }\n\n // Backtrack to find the actual LCS\n const result: [number, number][] = [];\n let i = m;\n let j = n;\n\n while (i > 0 && j > 0) {\n if (a[i - 1] === b[j - 1]) {\n result.unshift([i - 1, j - 1]);\n i--;\n j--;\n } else if (dp[i - 1][j] > dp[i][j - 1]) {\n i--;\n } else {\n j--;\n }\n }\n\n return result;\n}\n\n/**\n * Get the diff for a specific file\n */\nexport async function getFileDiff(dir: string, filepath: string): Promise<FileDiff | null> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return null;\n }\n\n try {\n // Get the file status first\n const status = await getStatus(repoRoot);\n const fileChange = status.changes.find((c) => c.filepath === filepath);\n\n if (!fileChange) {\n return null;\n }\n\n const fullPath = path.join(repoRoot, filepath);\n let oldContent: string | null = null;\n let newContent: string | null = null;\n\n // Get the HEAD version of the file\n if (fileChange.status !== \"new\" && fileChange.status !== \"untracked\") {\n try {\n const headCommit = await git.resolveRef({ fs, dir: repoRoot, ref: \"HEAD\" });\n const { blob } = await git.readBlob({\n fs,\n dir: repoRoot,\n oid: headCommit,\n filepath,\n });\n oldContent = new TextDecoder().decode(blob);\n } catch {\n // File doesn't exist in HEAD (new file)\n oldContent = null;\n }\n }\n\n // Get the working directory version\n if (fileChange.status !== \"deleted\") {\n try {\n newContent = await fs.promises.readFile(fullPath, \"utf-8\");\n } catch {\n newContent = null;\n }\n }\n\n // Check for binary content\n const isBinary =\n (oldContent !== null && isBinaryContent(oldContent)) ||\n (newContent !== null && isBinaryContent(newContent));\n\n if (isBinary) {\n return {\n filepath,\n status: fileChange.status,\n lines: [],\n oldContent: null,\n newContent: null,\n isBinary: true,\n };\n }\n\n // Compute the diff\n const lines = computeLineDiff(oldContent ?? \"\", newContent ?? \"\");\n\n return {\n filepath,\n status: fileChange.status,\n lines,\n oldContent,\n newContent,\n isBinary: false,\n };\n } catch (error) {\n console.error(\"Failed to get file diff:\", error);\n return null;\n }\n}\n\n/**\n * Discard changes for specific files (CLI first)\n * - For modified/deleted files: Restore content from HEAD\n * - For new/untracked files: Delete from disk\n */\nexport async function discardChanges(dir: string, filepaths: string[]): Promise<boolean> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) return false;\n\n // Try CLI first\n const cliResult = await cli.discardChangesCli(repoRoot, filepaths);\n if (cliResult) {\n return true;\n }\n\n // Fallback to isomorphic-git\n try {\n // Get HEAD commit\n const commits = await git.log({ fs, dir: repoRoot, depth: 1 });\n if (commits.length === 0) {\n // No commits yet, just delete all files\n for (const filepath of filepaths) {\n const fullPath = path.join(repoRoot, filepath);\n if (fs.existsSync(fullPath)) {\n await fs.promises.unlink(fullPath);\n }\n }\n return true;\n }\n\n const headCommit = commits[0].oid;\n\n for (const filepath of filepaths) {\n const fullPath = path.join(repoRoot, filepath);\n\n try {\n // Try to read file from HEAD commit\n const { blob } = await git.readBlob({\n fs,\n dir: repoRoot,\n oid: headCommit,\n filepath,\n });\n\n // File exists in HEAD - restore it\n await fs.promises.writeFile(fullPath, blob);\n\n // Also remove from staging area by resetting the index entry\n await git.resetIndex({ fs, dir: repoRoot, filepath });\n } catch {\n // File doesn't exist in HEAD (untracked/new) - delete it\n if (fs.existsSync(fullPath)) {\n await fs.promises.unlink(fullPath);\n }\n\n // If it was staged as new, remove from index\n try {\n await git.remove({ fs, dir: repoRoot, filepath });\n } catch {\n // Ignore if already not in index\n }\n }\n }\n return true;\n } catch (error) {\n console.error(\"Failed to discard changes:\", error);\n return false;\n }\n}\n\nfunction parseGitHubRepo(remoteUrl: string): string | null {\n if (!remoteUrl) {\n return null;\n }\n const trimmed = remoteUrl.trim();\n const scpMatch = /^git@github\\.com:([^/]+\\/[^/]+?)(?:\\.git)?$/i.exec(trimmed);\n if (scpMatch?.[1]) {\n return scpMatch[1];\n }\n\n try {\n const parsed = new URL(trimmed);\n if (parsed.hostname.toLowerCase() !== \"github.com\") {\n return null;\n }\n const pathname = parsed.pathname.replace(/^\\/+|\\/+$/g, \"\");\n if (!pathname) {\n return null;\n }\n return pathname.replace(/\\.git$/i, \"\");\n } catch {\n return null;\n }\n}\n\nasync function getGitHubRepoName(dir: string): Promise<{ repoRoot: string; repoName: string }> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n const remotes = await git.listRemotes({ fs, dir: repoRoot });\n if (!remotes.length) {\n throw new Error(\"No git remote configured.\");\n }\n const preferred = remotes.find((remote) => remote.remote === \"origin\") ?? remotes[0];\n const repoName = parseGitHubRepo(preferred.url ?? \"\");\n if (!repoName) {\n throw new Error(\"Remote is not a GitHub repository.\");\n }\n return { repoRoot, repoName };\n}\n\nfunction commandFailureDetail(\n stdout: string | Buffer | undefined,\n stderr: string | Buffer | undefined,\n fallback: string,\n): string {\n const stderrText = typeof stderr === \"string\" ? stderr : stderr?.toString(\"utf8\") ?? \"\";\n const stdoutText = typeof stdout === \"string\" ? stdout : stdout?.toString(\"utf8\") ?? \"\";\n const detail = (stderrText.trim() || stdoutText.trim());\n return detail || fallback;\n}\n\nasync function runGhCommand(\n repoRoot: string,\n args: string[],\n): Promise<{ stdout: string; stderr: string }> {\n try {\n const { stdout, stderr } = await execFileAsync(\"gh\", args, {\n cwd: repoRoot,\n maxBuffer: 25 * 1024 * 1024,\n });\n return { stdout: String(stdout ?? \"\"), stderr: String(stderr ?? \"\") };\n } catch (error) {\n const record = error as {\n stdout?: string | Buffer;\n stderr?: string | Buffer;\n message?: string;\n };\n const detail = commandFailureDetail(\n record.stdout,\n record.stderr,\n record.message ?? \"GitHub CLI command failed.\",\n );\n throw new Error(detail);\n }\n}\n\nasync function runGitCommand(\n cwd: string,\n args: string[],\n): Promise<{ stdout: string; stderr: string }> {\n try {\n const { stdout, stderr } = await execFileAsync(\"git\", args, {\n cwd,\n maxBuffer: 50 * 1024 * 1024,\n });\n return { stdout: String(stdout ?? \"\"), stderr: String(stderr ?? \"\") };\n } catch (error) {\n const record = error as {\n stdout?: string | Buffer;\n stderr?: string | Buffer;\n message?: string;\n };\n const detail = commandFailureDetail(\n record.stdout,\n record.stderr,\n record.message ?? \"Git command failed.\",\n );\n throw new Error(detail);\n }\n}\n\nasync function resolveGitCommandCwd(value: string): Promise<string> {\n const trimmed = value.trim();\n const fallback = process.cwd();\n if (!trimmed) {\n return fallback;\n }\n const resolved = path.resolve(trimmed);\n try {\n const stats = await fs.promises.stat(resolved);\n if (stats.isDirectory()) {\n return resolved;\n }\n return path.dirname(resolved);\n } catch {\n return fallback;\n }\n}\n\nasync function readGitConfigValue(cwd: string, args: string[]): Promise<string | null> {\n try {\n const { stdout } = await runGitCommand(cwd, args);\n const value = stdout.trim();\n return value.length > 0 ? value : null;\n } catch {\n return null;\n }\n}\n\nfunction defaultRepoNameFromUrl(url: string): string | null {\n const trimmed = url.trim().replace(/\\/+$/, \"\");\n if (!trimmed) {\n return null;\n }\n const tail = trimmed.split(\"/\").pop()?.trim() ?? \"\";\n if (!tail) {\n return null;\n }\n const withoutGit = tail.replace(/\\.git$/i, \"\");\n return withoutGit.trim() ? withoutGit.trim() : null;\n}\n\nfunction validateTargetFolderName(value: string): string {\n const trimmed = value.trim();\n if (!trimmed) {\n throw new Error(\"Target folder name is required.\");\n }\n if (trimmed.includes(\"/\") || trimmed.includes(\"\\\\\")) {\n throw new Error(\"Target folder name must not include path separators.\");\n }\n if (trimmed === \".\" || trimmed === \"..\") {\n throw new Error(\"Target folder name is invalid.\");\n }\n return trimmed;\n}\n\nfunction validateBranchName(name: string): string {\n const trimmed = name.trim();\n if (!trimmed) {\n throw new Error(\"Branch name is required.\");\n }\n if (/\\s/.test(trimmed)) {\n throw new Error(\"Branch name cannot contain whitespace.\");\n }\n if (trimmed.startsWith(\"/\") || trimmed.endsWith(\"/\")) {\n throw new Error(\"Branch name cannot start or end with '/'.\");\n }\n if (trimmed.includes(\"..\") || trimmed.includes(\"@{\") || trimmed.includes(\"//\")) {\n throw new Error(\"Branch name is invalid.\");\n }\n if (/[~^:?*[\\]\\\\]/.test(trimmed) || trimmed.endsWith(\".\")) {\n throw new Error(\"Branch name contains invalid characters.\");\n }\n return trimmed;\n}\n\nfunction validateRepoName(value: string): string {\n const trimmed = value.trim();\n if (!trimmed) {\n throw new Error(\"Repository name is required.\");\n }\n if (/\\s/.test(trimmed)) {\n throw new Error(\"Repository name cannot contain spaces.\");\n }\n if (trimmed.startsWith(\"/\") || trimmed.endsWith(\"/\")) {\n throw new Error(\"Repository name cannot start or end with '/'.\");\n }\n if (trimmed.includes(\"//\")) {\n throw new Error(\"Repository name is invalid.\");\n }\n return trimmed\n .replace(/^https?:\\/\\/github\\.com\\//i, \"\")\n .replace(/^git@github\\.com:/i, \"\")\n .replace(/\\.git$/i, \"\")\n .replace(/\\/+$/, \"\");\n}\n\nfunction parsePullRequestDiff(diffText: string): GitHubPullRequestDiff[] {\n const entries: GitHubPullRequestDiff[] = [];\n let currentLines: string[] = [];\n let currentOldPath: string | null = null;\n let currentNewPath: string | null = null;\n let currentStatus: string | null = null;\n\n const finalizeCurrent = () => {\n if (!currentLines.length) {\n return;\n }\n const diff = currentLines.join(\"\\n\");\n if (!diff.trim()) {\n return;\n }\n const status = currentStatus ?? \"M\";\n const resolvedPath =\n status === \"D\" ? currentOldPath : currentNewPath ?? currentOldPath;\n if (!resolvedPath) {\n return;\n }\n entries.push({\n path: resolvedPath.replace(/\\\\/g, \"/\"),\n status,\n diff,\n });\n };\n\n diffText.split(/\\r?\\n/).forEach((line) => {\n if (line.startsWith(\"diff --git \")) {\n finalizeCurrent();\n currentLines = [line];\n currentOldPath = null;\n currentNewPath = null;\n currentStatus = null;\n\n const rest = line.slice(\"diff --git \".length).trim();\n const [rawOldPath = \"\", rawNewPath = \"\"] = rest.split(/\\s+/);\n const oldPath = rawOldPath.replace(/^a\\//, \"\");\n const newPath = rawNewPath.replace(/^b\\//, \"\");\n currentOldPath = oldPath || null;\n currentNewPath = newPath || null;\n return;\n }\n\n if (line.startsWith(\"new file mode \")) {\n currentStatus = \"A\";\n } else if (line.startsWith(\"deleted file mode \")) {\n currentStatus = \"D\";\n } else if (line.startsWith(\"rename from \")) {\n currentStatus = \"R\";\n const renamedFrom = line.slice(\"rename from \".length).trim();\n if (renamedFrom) {\n currentOldPath = renamedFrom;\n }\n } else if (line.startsWith(\"rename to \")) {\n currentStatus = \"R\";\n const renamedTo = line.slice(\"rename to \".length).trim();\n if (renamedTo) {\n currentNewPath = renamedTo;\n }\n }\n\n currentLines.push(line);\n });\n\n finalizeCurrent();\n return entries;\n}\n\nexport async function getGitHubPullRequest(\n dir: string,\n prNumber: number,\n): Promise<GitHubPullRequest> {\n if (!Number.isFinite(prNumber) || prNumber <= 0) {\n throw new Error(\"Invalid pull request number.\");\n }\n const { repoRoot, repoName } = await getGitHubRepoName(dir);\n const { stdout } = await runGhCommand(repoRoot, [\n \"pr\",\n \"view\",\n String(prNumber),\n \"--repo\",\n repoName,\n \"--json\",\n \"number,title,url,updatedAt,createdAt,body,headRefName,baseRefName,isDraft,author\",\n ]);\n const parsed = JSON.parse(stdout) as GitHubPullRequest;\n return parsed;\n}\n\nexport async function getGitHubPullRequestDiff(\n dir: string,\n prNumber: number,\n): Promise<GitHubPullRequestDiff[]> {\n if (!Number.isFinite(prNumber) || prNumber <= 0) {\n throw new Error(\"Invalid pull request number.\");\n }\n const { repoRoot, repoName } = await getGitHubRepoName(dir);\n const { stdout } = await runGhCommand(repoRoot, [\n \"pr\",\n \"diff\",\n String(prNumber),\n \"--repo\",\n repoName,\n \"--color\",\n \"never\",\n ]);\n return parsePullRequestDiff(stdout);\n}\n\nexport async function getGitHubPullRequestComments(\n dir: string,\n prNumber: number,\n): Promise<GitHubPullRequestComment[]> {\n if (!Number.isFinite(prNumber) || prNumber <= 0) {\n throw new Error(\"Invalid pull request number.\");\n }\n const { repoRoot, repoName } = await getGitHubRepoName(dir);\n const { stdout } = await runGhCommand(repoRoot, [\n \"api\",\n `/repos/${repoName}/issues/${prNumber}/comments?per_page=30`,\n ]);\n const parsed = JSON.parse(stdout) as Array<Record<string, unknown>>;\n return parsed.map((comment) => ({\n id:\n typeof comment.id === \"number\" || typeof comment.id === \"string\"\n ? comment.id\n : \"\",\n body: typeof comment.body === \"string\" ? comment.body : \"\",\n createdAt:\n typeof comment.created_at === \"string\" ? comment.created_at : \"\",\n url: typeof comment.html_url === \"string\" ? comment.html_url : \"\",\n author:\n comment.user && typeof comment.user === \"object\"\n ? {\n login:\n typeof (comment.user as Record<string, unknown>).login === \"string\"\n ? String((comment.user as Record<string, unknown>).login)\n : \"unknown\",\n }\n : null,\n }));\n}\n\nexport async function checkoutGitHubPullRequest(\n dir: string,\n prNumber: number,\n): Promise<{ branch: string | null }> {\n if (!Number.isFinite(prNumber) || prNumber <= 0) {\n throw new Error(\"Invalid pull request number.\");\n }\n const { repoRoot } = await getGitHubRepoName(dir);\n await runGhCommand(repoRoot, [\"pr\", \"checkout\", String(prNumber)]);\n const branch = await getCurrentBranch(repoRoot);\n return { branch };\n}\n\nasync function countEffectiveDirEntries(root: string): Promise<number> {\n const entries = await fs.promises.readdir(root);\n let count = 0;\n for (const entry of entries) {\n if (entry === \".git\" || entry === \".DS_Store\" || entry === \"Thumbs.db\") {\n continue;\n }\n count += 1;\n }\n return count;\n}\n\nexport async function cloneRepositoryFromUrl(\n options: GitCloneFromUrlOptions,\n): Promise<GitCloneFromUrlResult> {\n const url = options.url?.trim() ?? \"\";\n if (!url) {\n throw new Error(\"Remote Git URL is required.\");\n }\n\n const destinationPath = options.destinationPath?.trim() ?? \"\";\n if (!destinationPath) {\n throw new Error(\"Destination folder is required.\");\n }\n\n const destination = path.resolve(destinationPath);\n let destinationStats: fs.Stats;\n try {\n destinationStats = await fs.promises.stat(destination);\n } catch {\n throw new Error(\"Destination folder must exist.\");\n }\n if (!destinationStats.isDirectory()) {\n throw new Error(\"Destination folder must be a directory.\");\n }\n\n const rawFolderName =\n options.targetFolderName?.trim() || defaultRepoNameFromUrl(url);\n if (!rawFolderName) {\n throw new Error(\"Could not determine target folder name.\");\n }\n const folderName = validateTargetFolderName(rawFolderName);\n const clonePath = path.join(destination, folderName);\n\n const cloneExists = await fs.promises\n .stat(clonePath)\n .then((value) => value.isDirectory())\n .catch(() => false);\n if (cloneExists) {\n const entryCount = await countEffectiveDirEntries(clonePath);\n if (entryCount > 0) {\n throw new Error(\"Destination path already exists and is not empty.\");\n }\n }\n\n try {\n await runGitCommand(destination, [\"clone\", url, clonePath]);\n } catch (error) {\n await fs.promises.rm(clonePath, { recursive: true, force: true }).catch(() => undefined);\n throw error;\n }\n\n return {\n path: clonePath,\n name: path.basename(clonePath),\n };\n}\n\nexport async function initGitRepository(\n dir: string,\n branch: string,\n force = false,\n): Promise<GitInitRepoResult> {\n const workspacePath = path.resolve(dir.trim());\n const normalizedBranch = validateBranchName(branch);\n\n let stats: fs.Stats;\n try {\n stats = await fs.promises.stat(workspacePath);\n } catch {\n throw new Error(\"Workspace path does not exist.\");\n }\n if (!stats.isDirectory()) {\n throw new Error(\"Workspace path must be a directory.\");\n }\n\n const existingRoot = await getRepoRoot(workspacePath);\n if (existingRoot) {\n return { status: \"already_initialized\" };\n }\n\n const entryCount = await countEffectiveDirEntries(workspacePath);\n if (entryCount > 0 && !force) {\n return { status: \"needs_confirmation\", entryCount };\n }\n\n await runGitCommand(workspacePath, [\"init\", \"-b\", normalizedBranch]);\n\n let commitError: string | null = null;\n if (entryCount > 0) {\n await runGitCommand(workspacePath, [\"add\", \"--all\"]);\n try {\n await runGitCommand(workspacePath, [\"commit\", \"-m\", \"chore: initial commit\"]);\n } catch (error) {\n commitError = error instanceof Error ? error.message : String(error);\n }\n }\n\n return {\n status: \"initialized\",\n commitError,\n };\n}\n\nfunction isRepoAlreadyExistsMessage(message: string): boolean {\n const lower = message.toLowerCase();\n return (\n lower.includes(\"already exists\")\n || lower.includes(\"name already exists\")\n || lower.includes(\"has already been taken\")\n );\n}\n\nexport async function createGitHubRepo(\n dir: string,\n repo: string,\n visibility: \"private\" | \"public\",\n branch: string,\n): Promise<GitCreateGitHubRepoResult> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n\n const repoName = validateRepoName(repo);\n const normalizedBranch = validateBranchName(branch);\n const visibilityFlag = visibility === \"public\" ? \"--public\" : \"--private\";\n\n const remotes = await git.listRemotes({ fs, dir: repoRoot });\n const originExists = remotes.some((entry) => entry.remote === \"origin\");\n\n try {\n if (originExists) {\n await runGhCommand(repoRoot, [\"repo\", \"create\", repoName, visibilityFlag]);\n } else {\n await runGhCommand(repoRoot, [\n \"repo\",\n \"create\",\n repoName,\n visibilityFlag,\n \"--source=.\",\n \"--remote=origin\",\n ]);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (!isRepoAlreadyExistsMessage(message)) {\n throw error;\n }\n }\n\n let pushError: string | null = null;\n let defaultBranchError: string | null = null;\n\n const hasHeadCommit = await runGitCommand(repoRoot, [\"rev-parse\", \"--verify\", \"HEAD\"])\n .then(() => true)\n .catch(() => false);\n\n if (hasHeadCommit) {\n try {\n await runGitCommand(repoRoot, [\"push\", \"-u\", \"origin\", normalizedBranch]);\n } catch (error) {\n pushError = error instanceof Error ? error.message : String(error);\n }\n } else {\n pushError = \"No commits yet. Create a commit before publishing.\";\n }\n\n try {\n await runGhCommand(repoRoot, [\"repo\", \"edit\", repoName, \"--default-branch\", normalizedBranch]);\n } catch (error) {\n defaultBranchError = error instanceof Error ? error.message : String(error);\n }\n\n const remoteUrl = await runGitCommand(repoRoot, [\"remote\", \"get-url\", \"origin\"])\n .then((result) => result.stdout.trim() || null)\n .catch(() => null);\n\n return {\n status: pushError || defaultBranchError ? \"partial\" : \"ok\",\n pushError,\n defaultBranchError,\n remoteUrl,\n };\n}\n\nexport async function pushCurrentBranch(\n dir: string,\n branch?: string,\n): Promise<GitPushCurrentBranchResult> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n\n const branchName = branch?.trim()\n ? validateBranchName(branch)\n : await getCurrentBranch(repoRoot);\n if (!branchName) {\n throw new Error(\"Detached HEAD. Checkout a branch before pushing.\");\n }\n\n const remotes = await git.listRemotes({ fs, dir: repoRoot });\n const remoteName = remotes.find((entry) => entry.remote === \"origin\")?.remote ?? remotes[0]?.remote;\n if (!remoteName) {\n throw new Error(\"No git remote configured. Add a remote and push again.\");\n }\n\n const hasHeadCommit = await runGitCommand(repoRoot, [\"rev-parse\", \"--verify\", \"HEAD\"])\n .then(() => true)\n .catch(() => false);\n if (!hasHeadCommit) {\n throw new Error(\"No commits yet. Create a commit before pushing.\");\n }\n\n const { stdout, stderr } = await runGitCommand(repoRoot, [\"push\", \"-u\", remoteName, branchName]);\n const output = `${stdout}\\n${stderr}`;\n const remoteUrl = await runGitCommand(repoRoot, [\"remote\", \"get-url\", remoteName])\n .then((result) => result.stdout.trim() || null)\n .catch(() => null);\n\n return {\n status: /everything up[\\s-]*to[\\s-]*date/i.test(output) ? \"up_to_date\" : \"ok\",\n branch: branchName,\n remote: remoteName,\n remoteBranch: branchName,\n remoteUrl,\n };\n}\n\nconst MAX_COMMIT_DIFF_CHARS = 30_000;\n\nfunction trimCommitDiff(value: string): string {\n const normalized = value.trim();\n if (normalized.length <= MAX_COMMIT_DIFF_CHARS) {\n return normalized;\n }\n const truncated = normalized.slice(0, MAX_COMMIT_DIFF_CHARS);\n return `${truncated}\\n\\n[diff truncated]`;\n}\n\nexport async function getCommitMessageDiff(dir: string): Promise<string> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n\n const stagedRaw = await runGitCommand(repoRoot, [\"diff\", \"--cached\", \"--no-color\", \"--\"]).then((value) => value.stdout);\n const staged = stagedRaw.trim();\n\n if (staged) {\n return trimCommitDiff(staged);\n }\n\n throw new Error(\"No staged changes found to summarize.\");\n}\n\nconst IMAGE_EXTENSIONS = new Set([\n \".png\",\n \".jpg\",\n \".jpeg\",\n \".gif\",\n \".webp\",\n \".bmp\",\n \".svg\",\n \".tif\",\n \".tiff\",\n \".ico\",\n \".avif\",\n \".heic\",\n]);\n\nfunction isImagePath(targetPath: string): boolean {\n const extension = path.extname(targetPath).toLowerCase();\n return IMAGE_EXTENSIONS.has(extension);\n}\n\nfunction toDiffString(lines: DiffLine[]): string {\n return lines\n .map((line) => {\n if (line.type === \"add\") {\n return `+${line.content}`;\n }\n if (line.type === \"remove\") {\n return `-${line.content}`;\n }\n return ` ${line.content}`;\n })\n .join(\"\\n\");\n}\n\ntype FlatGitDiff = {\n path: string;\n status: string;\n diff: string;\n oldLines?: string[];\n newLines?: string[];\n isBinary?: boolean;\n isImage?: boolean;\n oldImageData?: string | null;\n newImageData?: string | null;\n oldImageMime?: string | null;\n newImageMime?: string | null;\n};\n\ntype FlatGitLogEntry = {\n sha: string;\n summary: string;\n author: string;\n timestamp: number;\n};\n\nexport type GitLogSummary = {\n total: number;\n entries: FlatGitLogEntry[];\n ahead: number;\n behind: number;\n aheadEntries: FlatGitLogEntry[];\n behindEntries: FlatGitLogEntry[];\n upstream: string | null;\n};\n\nfunction parseLogEntries(stdout: string): FlatGitLogEntry[] {\n return stdout\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => {\n const [sha = \"\", summary = \"\", author = \"\", timestampRaw = \"0\"] =\n line.split(\"\\x1f\");\n const timestampSeconds = Number(timestampRaw);\n const timestamp = Number.isFinite(timestampSeconds)\n ? Math.max(0, Math.trunc(timestampSeconds * 1000))\n : 0;\n return {\n sha,\n summary,\n author,\n timestamp,\n };\n })\n .filter((entry) => entry.sha.length > 0);\n}\n\nexport async function listGitRoots(dir: string, depth = 2): Promise<string[]> {\n const start = path.resolve(dir);\n const queue: Array<{ current: string; remaining: number }> = [\n { current: start, remaining: Math.max(0, Math.trunc(depth)) },\n ];\n const visited = new Set<string>();\n const results: string[] = [];\n\n while (queue.length > 0) {\n const next = queue.shift();\n if (!next) continue;\n if (visited.has(next.current)) continue;\n visited.add(next.current);\n\n const gitPath = path.join(next.current, \".git\");\n const hasGit = await fs.promises\n .stat(gitPath)\n .then((stats) => stats.isDirectory() || stats.isFile())\n .catch(() => false);\n if (hasGit) {\n results.push(next.current);\n continue;\n }\n\n if (next.remaining <= 0) {\n continue;\n }\n\n const children = await fs.promises\n .readdir(next.current, { withFileTypes: true })\n .catch(() => [] as fs.Dirent[]);\n for (const child of children) {\n if (!child.isDirectory()) continue;\n if (child.name === \".git\" || child.name === \"node_modules\") continue;\n if (child.name.startsWith(\".\")) continue;\n queue.push({\n current: path.join(next.current, child.name),\n remaining: next.remaining - 1,\n });\n }\n }\n\n return results.sort((a, b) => a.localeCompare(b));\n}\n\nexport async function listBranches(\n dir: string,\n): Promise<Array<{ name: string; lastCommit: number }>> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return [];\n }\n const { stdout } = await runGitCommand(repoRoot, [\n \"for-each-ref\",\n \"--sort=-committerdate\",\n \"--format=%(refname:short)\\t%(committerdate:unix)\",\n \"refs/heads\",\n ]);\n return stdout\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => {\n const [name = \"\", timestampRaw = \"0\"] = line.split(\"\\t\");\n const timestampSeconds = Number(timestampRaw);\n return {\n name,\n lastCommit: Number.isFinite(timestampSeconds)\n ? Math.max(0, Math.trunc(timestampSeconds * 1000))\n : 0,\n };\n })\n .filter((entry) => entry.name.length > 0);\n}\n\nexport async function checkoutBranch(dir: string, name: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n const branch = validateBranchName(name);\n await runGitCommand(repoRoot, [\"checkout\", branch]);\n}\n\nexport async function createBranch(dir: string, name: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n const branch = validateBranchName(name);\n await runGitCommand(repoRoot, [\"checkout\", \"-b\", branch]);\n}\n\nexport async function getRemoteUrl(dir: string): Promise<string | null> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return null;\n }\n try {\n const { stdout } = await runGitCommand(repoRoot, [\n \"remote\",\n \"get-url\",\n \"origin\",\n ]);\n const value = stdout.trim();\n return value || null;\n } catch {\n return null;\n }\n}\n\nexport async function getGitLogSummary(\n dir: string,\n limit = 40,\n): Promise<GitLogSummary> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return {\n total: 0,\n entries: [],\n ahead: 0,\n behind: 0,\n aheadEntries: [],\n behindEntries: [],\n upstream: null,\n };\n }\n\n const logLimit = Number.isFinite(limit) && limit > 0 ? Math.floor(limit) : 40;\n const format = \"%H%x1f%s%x1f%an%x1f%at\";\n const [entriesResult, upstreamResult] = await Promise.all([\n runGitCommand(repoRoot, [\"log\", `--pretty=format:${format}`, `-n${logLimit}`]).catch(\n () => ({ stdout: \"\", stderr: \"\" }),\n ),\n runGitCommand(repoRoot, [\n \"rev-parse\",\n \"--abbrev-ref\",\n \"--symbolic-full-name\",\n \"@{upstream}\",\n ]).catch(() => ({ stdout: \"\", stderr: \"\" }),\n ),\n ]);\n\n const entries = parseLogEntries(entriesResult.stdout);\n const upstream = upstreamResult.stdout.trim() || null;\n let aheadEntries: FlatGitLogEntry[] = [];\n let behindEntries: FlatGitLogEntry[] = [];\n\n if (upstream) {\n const [aheadResult, behindResult] = await Promise.all([\n runGitCommand(repoRoot, [\n \"log\",\n `--pretty=format:${format}`,\n `${upstream}..HEAD`,\n ]).catch(() => ({ stdout: \"\", stderr: \"\" }),\n ),\n runGitCommand(repoRoot, [\n \"log\",\n `--pretty=format:${format}`,\n `HEAD..${upstream}`,\n ]).catch(() => ({ stdout: \"\", stderr: \"\" }),\n ),\n ]);\n aheadEntries = parseLogEntries(aheadResult.stdout);\n behindEntries = parseLogEntries(behindResult.stdout);\n }\n\n return {\n total: entries.length,\n entries,\n ahead: aheadEntries.length,\n behind: behindEntries.length,\n aheadEntries,\n behindEntries,\n upstream,\n };\n}\n\nexport async function getDiffs(dir: string): Promise<FlatGitDiff[]> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return [];\n }\n const status = await getStatus(repoRoot);\n const results: FlatGitDiff[] = [];\n for (const change of status.changes) {\n const fileDiff = await getFileDiff(repoRoot, change.filepath);\n if (!fileDiff) {\n continue;\n }\n const image = isImagePath(change.filepath);\n results.push({\n path: change.filepath,\n status: change.status,\n diff: fileDiff.isBinary ? \"\" : toDiffString(fileDiff.lines),\n oldLines: fileDiff.oldContent?.split(\"\\n\"),\n newLines: fileDiff.newContent?.split(\"\\n\"),\n isBinary: fileDiff.isBinary,\n isImage: image,\n oldImageData: null,\n newImageData: null,\n oldImageMime: null,\n newImageMime: null,\n });\n }\n return results;\n}\n\nexport async function getCommitDiff(\n dir: string,\n sha: string,\n): Promise<FlatGitDiff[]> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return [];\n }\n const normalizedSha = sha.trim();\n if (!normalizedSha) {\n throw new Error(\"Commit SHA is required.\");\n }\n const { stdout } = await runGitCommand(repoRoot, [\n \"show\",\n \"--format=\",\n \"--no-color\",\n \"--binary\",\n normalizedSha,\n ]);\n return parsePullRequestDiff(stdout).map((entry) => ({\n path: entry.path,\n status: entry.status,\n diff: entry.diff,\n }));\n}\n\nexport async function stageFile(dir: string, filepath: string): Promise<void> {\n const normalized = filepath.trim();\n if (!normalized) {\n throw new Error(\"File path is required.\");\n }\n await stageFiles(dir, [normalized]);\n}\n\nexport async function unstageFile(dir: string, filepath: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n const normalized = filepath.trim();\n if (!normalized) {\n throw new Error(\"File path is required.\");\n }\n try {\n await runGitCommand(repoRoot, [\"restore\", \"--staged\", \"--\", normalized]);\n } catch {\n await runGitCommand(repoRoot, [\"reset\", \"HEAD\", \"--\", normalized]);\n }\n}\n\nexport async function revertFile(dir: string, filepath: string): Promise<void> {\n const normalized = filepath.trim();\n if (!normalized) {\n throw new Error(\"File path is required.\");\n }\n const success = await discardChanges(dir, [normalized]);\n if (!success) {\n throw new Error(`Failed to revert '${normalized}'.`);\n }\n}\n\nexport async function revertAll(dir: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n const status = await getStatus(repoRoot);\n if (status.changes.length === 0) {\n return;\n }\n const success = await discardChanges(\n repoRoot,\n status.changes.map((change) => change.filepath),\n );\n if (!success) {\n throw new Error(\"Failed to revert all changes.\");\n }\n}\n\nexport async function pull(dir: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n await runGitCommand(repoRoot, [\"pull\", \"--ff-only\"]);\n}\n\nexport async function fetch(dir: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n await runGitCommand(repoRoot, [\"fetch\", \"--all\", \"--prune\"]);\n}\n\nfunction isMissingTrackingBranchError(message: string): boolean {\n const normalized = message.toLowerCase();\n return (\n normalized.includes(\"no tracking information\") ||\n normalized.includes(\"no upstream configured\")\n );\n}\n\nexport async function sync(dir: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n await fetch(repoRoot);\n try {\n await pull(repoRoot);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (!isMissingTrackingBranchError(message)) {\n throw error;\n }\n }\n await pushCurrentBranch(repoRoot);\n}\n\nexport async function getGitHubIssues(\n dir: string,\n): Promise<{ total: number; issues: Array<{ number: number; title: string; url: string; updatedAt: string }> }> {\n const { repoRoot, repoName } = await getGitHubRepoName(dir);\n const { stdout } = await runGhCommand(repoRoot, [\n \"api\",\n `/repos/${repoName}/issues?state=open&per_page=30`,\n ]);\n const parsed = JSON.parse(stdout) as Array<Record<string, unknown>>;\n const issues = parsed\n .filter((entry) => !(\"pull_request\" in entry))\n .map((entry) => ({\n number: Number(entry.number ?? 0),\n title: String(entry.title ?? \"\"),\n url: String(entry.html_url ?? entry.url ?? \"\"),\n updatedAt: String(entry.updated_at ?? \"\"),\n }))\n .filter((entry) => Number.isFinite(entry.number) && entry.number > 0);\n return {\n total: issues.length,\n issues,\n };\n}\n\nexport async function getGitHubPullRequests(\n dir: string,\n): Promise<{ total: number; pullRequests: GitHubPullRequest[] }> {\n const { repoRoot, repoName } = await getGitHubRepoName(dir);\n const { stdout } = await runGhCommand(repoRoot, [\n \"pr\",\n \"list\",\n \"--repo\",\n repoName,\n \"--state\",\n \"open\",\n \"--limit\",\n \"30\",\n \"--json\",\n \"number,title,url,updatedAt,createdAt,body,headRefName,baseRefName,isDraft,author\",\n ]);\n const pullRequests = JSON.parse(stdout) as GitHubPullRequest[];\n return {\n total: pullRequests.length,\n pullRequests,\n };\n}\n","/**\n * Git CLI Operations\n *\n * All git operations using native git CLI (CodexMonitor approach).\n * CLI is used first, isomorphic-git is only fallback.\n */\n\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type {\n GitFileChange,\n GitFileStatus,\n GitRepoStatus,\n GitAuthor,\n} from \"./git-types\";\n\nconst execFileAsync = promisify(execFile);\nconst MAX_BUFFER_BYTES = 10 * 1024 * 1024;\n\n/**\n * Check if a directory is a git repository (CLI version)\n */\nexport async function isGitRepoCli(dir: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"rev-parse\", \"--git-dir\"], {\n cwd: dir,\n encoding: \"utf8\",\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the root directory of a git repo (CLI version)\n */\nexport async function getRepoRootCli(dir: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"rev-parse\", \"--show-toplevel\"],\n { cwd: dir, encoding: \"utf8\" }\n );\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the current branch name (CLI version)\n */\nexport async function getCurrentBranchCli(dir: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"],\n { cwd: dir, encoding: \"utf8\" }\n );\n const branch = stdout.trim();\n return branch === \"HEAD\" ? null : branch;\n } catch {\n return null;\n }\n}\n\nfunction parseBranchLine(line: string): {\n branch: string | null;\n ahead: number;\n behind: number;\n} {\n const trimmed = line.trim();\n let branch: string | null = null;\n\n if (trimmed.startsWith(\"No commits yet on \")) {\n branch = trimmed.slice(\"No commits yet on \".length).trim();\n } else if (trimmed.startsWith(\"Initial commit on \")) {\n branch = trimmed.slice(\"Initial commit on \".length).trim();\n } else if (trimmed.startsWith(\"HEAD\")) {\n branch = null;\n } else {\n branch = trimmed.split(\"...\")[0]?.trim() ?? null;\n }\n\n const aheadMatch = trimmed.match(/ahead (\\d+)/);\n const behindMatch = trimmed.match(/behind (\\d+)/);\n\n return {\n branch,\n ahead: aheadMatch ? Number(aheadMatch[1]) : 0,\n behind: behindMatch ? Number(behindMatch[1]) : 0,\n };\n}\n\nfunction mapStatusFromXY(xy: string): { status: GitFileStatus; staged: boolean } | null {\n if (xy.length < 2 || xy === \"??\") {\n return null;\n }\n\n const x = xy[0];\n const y = xy[1];\n\n if (x === \" \" && y === \" \") {\n return null;\n }\n\n let status: GitFileStatus = \"modified\";\n\n if (x === \"D\" || y === \"D\") {\n status = \"deleted\";\n } else if (x === \"A\" || y === \"A\") {\n status = \"new\";\n } else if (\n x === \"M\" ||\n y === \"M\" ||\n x === \"R\" ||\n y === \"R\" ||\n x === \"C\" ||\n y === \"C\" ||\n x === \"U\" ||\n y === \"U\"\n ) {\n status = \"modified\";\n } else {\n return null;\n }\n\n const staged = x !== \" \" && x !== \"?\";\n\n return { status, staged };\n}\n\n/**\n * Get git status (CLI version)\n */\nexport async function getStatusCli(dir: string): Promise<GitRepoStatus | null> {\n const repoRoot = await getRepoRootCli(dir);\n if (!repoRoot) {\n return { isRepo: false, branch: null, changes: [], hasChanges: false, ahead: 0, behind: 0 };\n }\n\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"-c\", \"core.quotepath=false\", \"status\", \"--porcelain=1\", \"--branch\", \"-z\"],\n {\n cwd: repoRoot,\n encoding: \"utf8\",\n maxBuffer: MAX_BUFFER_BYTES,\n }\n );\n\n const records = stdout.split(\"\\0\");\n let branch: string | null = null;\n let ahead = 0;\n let behind = 0;\n const changes: GitFileChange[] = [];\n\n for (let i = 0; i < records.length; i++) {\n const record = records[i];\n if (!record) {\n continue;\n }\n\n if (record.startsWith(\"## \")) {\n const parsed = parseBranchLine(record.slice(3));\n branch = parsed.branch;\n ahead = parsed.ahead;\n behind = parsed.behind;\n continue;\n }\n\n if (record.length < 3) {\n continue;\n }\n\n const xy = record.slice(0, 2);\n let filepath = record.slice(3);\n\n if (!filepath) {\n continue;\n }\n\n if (xy === \"??\") {\n changes.push({ filepath, status: \"untracked\", staged: false });\n continue;\n }\n\n if (xy.includes(\"R\") || xy.includes(\"C\")) {\n const renamed = records[i + 1];\n if (renamed) {\n filepath = renamed;\n i += 1;\n }\n }\n\n const parsed = mapStatusFromXY(xy);\n if (!parsed) {\n continue;\n }\n\n changes.push({ filepath, status: parsed.status, staged: parsed.staged });\n }\n\n changes.sort((a, b) => {\n if (a.staged !== b.staged) {\n return a.staged ? -1 : 1;\n }\n return a.filepath.localeCompare(b.filepath);\n });\n\n return {\n isRepo: true,\n branch,\n changes,\n hasChanges: changes.length > 0,\n ahead,\n behind,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Stage files (CLI version)\n */\nexport async function stageFilesCli(dir: string, files: string[]): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"add\", \"--\", ...files], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Stage all changes (CLI version)\n */\nexport async function stageAllCli(dir: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"add\", \"-A\"], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Unstage files (CLI version)\n */\nexport async function unstageFilesCli(dir: string, files: string[]): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"reset\", \"HEAD\", \"--\", ...files], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Unstage all (CLI version)\n */\nexport async function unstageAllCli(dir: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"reset\", \"HEAD\"], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Create a commit (CLI version)\n */\nexport async function commitCli(\n dir: string,\n message: string,\n author?: { name: string; email: string }\n): Promise<{ sha: string; success: boolean; error?: string }> {\n try {\n const env: Record<string, string> = {};\n if (author) {\n env.GIT_AUTHOR_NAME = author.name;\n env.GIT_AUTHOR_EMAIL = author.email;\n }\n\n await execFileAsync(\"git\", [\"commit\", \"-m\", message], {\n cwd: dir,\n env: { ...process.env, ...env },\n });\n\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"HEAD\"], {\n cwd: dir,\n encoding: \"utf8\",\n });\n\n return { sha: stdout.trim(), success: true };\n } catch (error) {\n return {\n sha: \"\",\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Get default author (CLI version)\n */\nexport async function getDefaultAuthorCli(dir: string): Promise<GitAuthor | null> {\n try {\n const [{ stdout: name }, { stdout: email }] = await Promise.all([\n execFileAsync(\"git\", [\"config\", \"user.name\"], { cwd: dir, encoding: \"utf8\" }),\n execFileAsync(\"git\", [\"config\", \"user.email\"], { cwd: dir, encoding: \"utf8\" }),\n ]);\n\n const nameStr = name.trim();\n const emailStr = email.trim();\n\n if (!nameStr || !emailStr) {\n return null;\n }\n\n return { name: nameStr, email: emailStr };\n } catch {\n return null;\n }\n}\n\n/**\n * List remotes (CLI version)\n */\nexport async function listRemotesCli(\n dir: string\n): Promise<{ remote: string; url: string }[]> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"remote\", \"-v\"], {\n cwd: dir,\n encoding: \"utf8\",\n });\n\n const remotes: { remote: string; url: string }[] = [];\n const seen = new Set<string>();\n\n for (const line of stdout.split(\"\\n\")) {\n const match = line.match(/^(\\S+)\\s+(\\S+)\\s+\\(fetch\\)$/);\n if (match) {\n const [, name, url] = match;\n if (!seen.has(name)) {\n seen.add(name);\n remotes.push({ remote: name, url });\n }\n }\n }\n\n return remotes;\n } catch {\n return [];\n }\n}\n\n/**\n * Get remote URL (CLI version)\n */\nexport async function getRemoteUrlCli(dir: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"config\", \"--get\", \"remote.origin.url\"],\n { cwd: dir, encoding: \"utf8\" }\n );\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Pull (CLI version)\n */\nexport async function pullCli(dir: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"pull\"], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Fetch (CLI version)\n */\nexport async function fetchCli(dir: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"fetch\"], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Push (CLI version)\n */\nexport async function pushCli(dir: string, branch?: string): Promise<boolean> {\n try {\n const args = branch ? [\"push\", \"origin\", branch] : [\"push\"];\n await execFileAsync(\"git\", args, { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Checkout branch (CLI version)\n */\nexport async function checkoutBranchCli(dir: string, name: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"checkout\", name], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Create branch (CLI version)\n */\nexport async function createBranchCli(dir: string, name: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"checkout\", \"-b\", name], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * List branches (CLI version)\n */\nexport async function listBranchesCli(dir: string): Promise<string[]> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"branch\", \"-a\", \"--format=%(refname:short)\"],\n { cwd: dir, encoding: \"utf8\" }\n );\n\n return stdout\n .split(\"\\n\")\n .map((b) => b.trim())\n .filter((b) => b && !b.startsWith(\"HEAD\"));\n } catch {\n return [];\n }\n}\n\n/**\n * Get file diff (CLI version)\n */\nexport async function getFileDiffCli(\n dir: string,\n filepath: string\n): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\", \"HEAD\", \"--\", filepath],\n { cwd: dir, encoding: \"utf8\", maxBuffer: MAX_BUFFER_BYTES }\n );\n return stdout;\n } catch {\n return null;\n }\n}\n\n/**\n * Get diff for unstaged files (CLI version)\n */\nexport async function getUnstagedDiffCli(dir: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\"],\n { cwd: dir, encoding: \"utf8\", maxBuffer: MAX_BUFFER_BYTES }\n );\n return stdout;\n } catch {\n return null;\n }\n}\n\n/**\n * Get diff for staged files (CLI version)\n */\nexport async function getStagedDiffCli(dir: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\", \"--cached\"],\n { cwd: dir, encoding: \"utf8\", maxBuffer: MAX_BUFFER_BYTES }\n );\n return stdout;\n } catch {\n return null;\n }\n}\n\n/**\n * Discard changes (CLI version)\n */\nexport async function discardChangesCli(\n dir: string,\n filepaths: string[]\n): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"checkout\", \"--\", ...filepaths], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get log summary (CLI version)\n */\nexport async function getLogSummaryCli(\n dir: string,\n limit = 40\n): Promise<\n {\n sha: string;\n message: string;\n author: string;\n date: string;\n }[]\n> {\n try {\n const format = \"%H%x00%s%x00%an%x00%ai%x00--SEP--\";\n const { stdout } = await execFileAsync(\n \"git\",\n [\"log\", `--max-count=${limit}`, `--pretty=format:${format}`],\n { cwd: dir, encoding: \"utf8\" }\n );\n\n return stdout\n .split(\"--SEP--\")\n .map((entry) => {\n const [sha, message, author, date] = entry.trim().split(\"\\x00\");\n if (!sha) return null;\n return { sha: sha.trim(), message: message || \"\", author: author || \"\", date: date || \"\" };\n })\n .filter((e): e is NonNullable<typeof e> => e !== null);\n } catch {\n return [];\n }\n}\n\n/**\n * Get ahead/behind (CLI version)\n */\nexport async function getAheadBehindCli(\n dir: string,\n branch: string | null\n): Promise<{ ahead: number; behind: number }> {\n if (!branch) {\n return { ahead: 0, behind: 0 };\n }\n\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"rev-list\", \"--left-right\", \"--count\", `${branch}...@{u}`],\n { cwd: dir, encoding: \"utf8\" }\n );\n\n const match = stdout.trim().match(/(\\d+)\\s+(\\d+)/);\n if (match) {\n return { ahead: Number(match[1]), behind: Number(match[2]) };\n }\n } catch {\n // No upstream\n }\n\n return { ahead: 0, behind: 0 };\n}\n\n/**\n * Init repository (CLI version)\n */\nexport async function initRepoCli(\n dir: string,\n branch = \"main\"\n): Promise<{ success: boolean; error?: string }> {\n try {\n await execFileAsync(\"git\", [\"init\", \"-b\", branch], { cwd: dir });\n return { success: true };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Clone repository (CLI version)\n */\nexport async function cloneRepoCli(\n url: string,\n dir: string\n): Promise<{ success: boolean; error?: string }> {\n try {\n await execFileAsync(\"git\", [\"clone\", url, dir], { maxBuffer: MAX_BUFFER_BYTES });\n return { success: true };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type {\n CodexAppServer,\n CodexApplyPatchRequestPayload,\n CodexEventPayload,\n CodexExecCommandRequestPayload,\n CodexNotificationPayload,\n CodexServerRequestPayload,\n} from \"../lib/codex-app-server\";\nimport type { WorkspaceInfo as ProjectInfo } from \"../lib/workspace-parity-store\";\nimport { isRetryableTurnErrorPayload } from \"../lib/retryable-turn-error\";\nimport { logInfo, logWarn } from \"../lib/logger\";\nimport { getUserDataDir } from \"../lib/app-state\";\n\ntype JsonRecord = Record<string, unknown>;\n\ntype TelegramBridgeOptions = {\n getAppServer: () => CodexAppServer | null;\n listProjects: () => Promise<ProjectInfo[]>;\n getProjectById: (id: string) => Promise<ProjectInfo | null>;\n isProEnabled: () => Promise<boolean>;\n getDefaultProjectId?: () => Promise<string | null> | string | null;\n};\n\ntype TelegramBridgeSettings = {\n enabled: boolean;\n token: string | null;\n};\n\ntype TelegramBridgeStreamMode = \"draft\" | \"message\" | \"none\";\n\nexport type TelegramBridgeStatus = {\n state: \"stopped\" | \"running\" | \"error\";\n running: boolean;\n botUsername: string | null;\n allowedChats: number;\n activeChats: number;\n streamMode: TelegramBridgeStreamMode;\n lastError: string | null;\n startedAtMs: number | null;\n};\n\ntype TelegramTokenTestResult = {\n ok: boolean;\n username: string | null;\n error: string | null;\n};\n\ntype TelegramApiResponse<T> = {\n ok: boolean;\n result?: T;\n description?: string;\n error_code?: number;\n parameters?: {\n retry_after?: number;\n };\n};\n\ntype TelegramUpdate = {\n update_id?: number;\n message?: JsonRecord;\n callback_query?: JsonRecord;\n my_chat_member?: JsonRecord;\n};\n\ntype ChatSession = {\n chatId: string;\n projectId: string | null;\n threadId: string | null;\n listenerSubscriptionId: string | null;\n activeTurnId: string | null;\n processing: boolean;\n finalizeInFlight: boolean;\n lastProjectOrder: string[];\n lastThreadOrder: string[];\n completedTextCandidate: string | null;\n recentFinalizedTurnIds: string[];\n recentFinalSignatures: Array<{ signature: string; at: number }>;\n recentIncomingMessageIds: number[];\n streamFlushPromise: Promise<void> | null;\n streamFlushPending: boolean;\n lastDeliveredFinalText: string | null;\n lastDeliveredFinalAtMs: number;\n typingTimer: NodeJS.Timeout | null;\n stream: {\n draftId: string;\n buffer: string;\n lastSent: string;\n flushTimer: NodeJS.Timeout | null;\n messageId: number | null;\n } | null;\n};\n\ntype PendingApprovalAction = {\n id: string;\n kind: \"exec\" | \"patch\";\n chatId: string;\n requestToken: string;\n createdAtMs: number;\n};\n\ntype PendingUserInput = {\n chatId: string;\n requestId: string | number;\n method: string;\n params: JsonRecord;\n createdAtMs: number;\n};\n\nconst TELEGRAM_API_BASE = \"https://api.telegram.org\";\nconst TELEGRAM_POLL_TIMEOUT_SECONDS = 30;\nconst TELEGRAM_API_TIMEOUT_MS = 40_000;\nconst TELEGRAM_STREAM_FLUSH_MS = 300;\nconst TELEGRAM_MAX_MESSAGE_LENGTH = 4096;\nconst TELEGRAM_PENDING_TTL_MS = 30 * 60 * 1000;\nconst TELEGRAM_RETRY_LIMIT_MS = 30_000;\nconst TELEGRAM_MIN_SEND_INTERVAL_MS = 500;\nconst TELEGRAM_FINAL_TEXT_DEDUPE_MS = 2_500;\nconst TELEGRAM_RECENT_FINALIZED_TURNS_MAX = 24;\nconst TELEGRAM_FINAL_SIGNATURE_DEDUPE_MS = 20_000;\nconst TELEGRAM_RECENT_FINAL_SIGNATURES_MAX = 40;\nconst TELEGRAM_RECENT_INCOMING_MESSAGES_MAX = 32;\nconst TELEGRAM_TYPING_HEARTBEAT_MS = 4_000;\nconst TELEGRAM_BRIDGE_LOCK_FILE_PREFIX = \"telegram-bridge\";\n\nfunction asRecord(value: unknown): JsonRecord {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as JsonRecord)\n : {};\n}\n\nfunction asString(value: unknown): string {\n return typeof value === \"string\" ? value : value != null ? String(value) : \"\";\n}\n\nfunction asTrimmedString(value: unknown): string {\n return asString(value).trim();\n}\n\nfunction asNumber(value: unknown): number | null {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n if (typeof value === \"string\" && value.trim()) {\n const parsed = Number(value.trim());\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n return null;\n}\n\nfunction normalizeChatId(value: unknown): string | null {\n const trimmed = asTrimmedString(value);\n if (!trimmed) {\n return null;\n }\n if (!/^-?[0-9]+$/.test(trimmed)) {\n return null;\n }\n return trimmed;\n}\n\nfunction extractThreadId(value: unknown): string {\n const params = asRecord(value);\n const turn = asRecord(params.turn);\n const thread = asRecord(params.thread);\n const item = asRecord(params.item);\n const msg = asRecord(params.msg);\n const msgItem = asRecord(msg.item);\n return asTrimmedString(\n params.threadId ??\n params.thread_id ??\n params.conversationId ??\n params.conversation_id ??\n turn.threadId ??\n turn.thread_id ??\n thread.id ??\n thread.threadId ??\n thread.thread_id ??\n item.threadId ??\n item.thread_id ??\n item.conversationId ??\n item.conversation_id ??\n msg.threadId ??\n msg.thread_id ??\n msg.conversationId ??\n msg.conversation_id ??\n msgItem.threadId ??\n msgItem.thread_id ??\n msgItem.conversationId ??\n msgItem.conversation_id ??\n \"\",\n );\n}\n\nfunction extractTurnId(value: unknown): string {\n const params = asRecord(value);\n const turn = asRecord(params.turn);\n const msg = asRecord(params.msg);\n const msgTurn = asRecord(msg.turn);\n return asTrimmedString(\n turn.id ??\n turn.turnId ??\n turn.turn_id ??\n params.turnId ??\n params.turn_id ??\n msg.turnId ??\n msg.turn_id ??\n msgTurn.id ??\n msgTurn.turnId ??\n msgTurn.turn_id ??\n \"\",\n );\n}\n\nfunction extractText(value: unknown, depth = 0): string {\n if (typeof value === \"string\") {\n return value;\n }\n if (depth > 4 || value == null) {\n return \"\";\n }\n if (Array.isArray(value)) {\n return value.map((entry) => extractText(entry, depth + 1)).join(\"\");\n }\n if (typeof value !== \"object\") {\n return \"\";\n }\n const record = value as JsonRecord;\n return (\n extractText(record.text, depth + 1) ||\n extractText(record.delta, depth + 1) ||\n extractText(record.message, depth + 1) ||\n extractText(record.content, depth + 1) ||\n extractText(record.value, depth + 1)\n );\n}\n\nfunction extractDeltaFromNotification(params: JsonRecord): string {\n const msg = asRecord(params.msg);\n return (\n asString(params.delta) ||\n extractText(params.delta) ||\n extractText(msg.delta ?? msg.message ?? msg.content ?? msg.value)\n );\n}\n\nfunction looksLikeAssistantItem(item: JsonRecord): boolean {\n const itemType = asTrimmedString(item.type).toLowerCase();\n if (\n itemType === \"agentmessage\" ||\n itemType === \"agent_message\" ||\n itemType === \"assistantmessage\" ||\n itemType === \"assistant_message\"\n ) {\n return true;\n }\n const itemRole = asTrimmedString(\n item.role ?? item.authorRole ?? item.author_role ?? item.senderRole ?? item.sender_role,\n ).toLowerCase();\n if (itemRole === \"assistant\" || itemRole === \"agent\") {\n return true;\n }\n const itemId = asTrimmedString(item.id);\n return itemId.startsWith(\"msg_\");\n}\n\nfunction extractAssistantTextFromItemCompleted(params: JsonRecord): string {\n const item = asRecord(params.item);\n if (!looksLikeAssistantItem(item)) {\n return \"\";\n }\n return asString(item.text) || extractText(item.content) || extractText(params.msg) || \"\";\n}\n\nfunction extractCommandText(params: JsonRecord): string {\n const command = params.command;\n if (typeof command === \"string\") {\n return command.trim();\n }\n if (Array.isArray(command)) {\n const parts = command.map((entry) => asString(entry).trim()).filter(Boolean);\n if (parts.length > 0) {\n return parts.join(\" \");\n }\n }\n const parsed = asRecord(params.parsed_cmd ?? params.parsedCmd);\n const parsedText = asTrimmedString(parsed.text ?? parsed.command);\n if (parsedText) {\n return parsedText;\n }\n return asTrimmedString(params.cmd ?? \"\");\n}\n\nfunction summarizePatchRequest(params: JsonRecord): string {\n const fileChanges = params.file_changes ?? params.fileChanges;\n if (Array.isArray(fileChanges)) {\n const count = fileChanges.length;\n return `${count} file ${count === 1 ? \"change\" : \"changes\"}`;\n }\n const summary = extractText(params);\n return summary.trim() || \"Apply patch request\";\n}\n\nfunction splitMessage(text: string, maxLength = TELEGRAM_MAX_MESSAGE_LENGTH): string[] {\n const normalized = text.trim();\n if (!normalized) {\n return [];\n }\n if (normalized.length <= maxLength) {\n return [normalized];\n }\n const parts: string[] = [];\n let index = 0;\n while (index < normalized.length) {\n const remaining = normalized.slice(index);\n if (remaining.length <= maxLength) {\n parts.push(remaining);\n break;\n }\n let cut = maxLength;\n const newlineCut = remaining.lastIndexOf(\"\\n\", maxLength);\n if (newlineCut >= Math.floor(maxLength * 0.5)) {\n cut = newlineCut;\n }\n const chunk = remaining.slice(0, cut).trim();\n parts.push(chunk || remaining.slice(0, maxLength));\n index += cut;\n }\n return parts;\n}\n\nfunction mergeStreamDeltaBuffer(current: string, incoming: string): string {\n if (!incoming) {\n return current;\n }\n if (!current) {\n return incoming;\n }\n if (current.endsWith(incoming)) {\n return current;\n }\n if (incoming.startsWith(current)) {\n return incoming;\n }\n\n // Some event sources send cumulative text while others send token deltas.\n // Merge on suffix/prefix overlap so we do not duplicate content in Telegram output.\n const maxProbe = Math.min(current.length, incoming.length, 2_048);\n for (let size = maxProbe; size > 0; size -= 1) {\n if (current.slice(-size) === incoming.slice(0, size)) {\n return current + incoming.slice(size);\n }\n }\n return current + incoming;\n}\n\nfunction nowMs(): number {\n return Date.now();\n}\n\nexport class TelegramBridge {\n private readonly options: TelegramBridgeOptions;\n private settings: TelegramBridgeSettings = {\n enabled: false,\n token: null,\n };\n\n private status: TelegramBridgeStatus = {\n state: \"stopped\",\n running: false,\n botUsername: null,\n allowedChats: 0,\n activeChats: 0,\n streamMode: \"message\",\n lastError: null,\n startedAtMs: null,\n };\n\n private running = false;\n private pollAbortController: AbortController | null = null;\n private pollLoopPromise: Promise<void> | null = null;\n private updateOffset: number | null = null;\n private draftStreamingEnabled = false;\n private messageStreamingEnabled = true;\n\n private sessionsByChatId = new Map<string, ChatSession>();\n private chatIdByThreadId = new Map<string, string>();\n private pendingApprovalById = new Map<string, PendingApprovalAction>();\n private pendingUserInputByRequestId = new Map<string, PendingUserInput>();\n\n private appServerListenersBound = false;\n\n private readonly recentDeltaBySignature = new Map<string, number>();\n private readonly lastSendAtByChatId = new Map<string, number>();\n private runtimeLockPath: string | null = null;\n\n private readonly handleCodexNotification = (payload: CodexNotificationPayload) => {\n this.handleNotification(payload).catch((error) => {\n logWarn(\"[telegram-bridge] notification handling failed\", error);\n });\n };\n\n private readonly handleCodexEvent = (payload: CodexEventPayload) => {\n this.handleEvent(payload).catch((error) => {\n logWarn(\"[telegram-bridge] event handling failed\", error);\n });\n };\n\n private readonly handleExecApprovalRequest = (payload: CodexExecCommandRequestPayload) => {\n this.handleApprovalRequest(\"exec\", payload.requestToken, payload.params).catch((error) => {\n logWarn(\"[telegram-bridge] exec approval handling failed\", error);\n });\n };\n\n private readonly handlePatchApprovalRequest = (payload: CodexApplyPatchRequestPayload) => {\n this.handleApprovalRequest(\"patch\", payload.requestToken, payload.params).catch((error) => {\n logWarn(\"[telegram-bridge] patch approval handling failed\", error);\n });\n };\n\n private readonly handleServerRequest = (payload: CodexServerRequestPayload) => {\n this.handleUserInputRequest(payload).catch((error) => {\n logWarn(\"[telegram-bridge] user-input request handling failed\", error);\n });\n };\n\n constructor(options: TelegramBridgeOptions) {\n this.options = options;\n }\n\n private getCurrentStreamMode(): TelegramBridgeStreamMode {\n if (this.messageStreamingEnabled) {\n return \"message\";\n }\n if (this.draftStreamingEnabled) {\n return \"draft\";\n }\n return \"none\";\n }\n\n public getStatus(): TelegramBridgeStatus {\n return {\n ...this.status,\n allowedChats: 0,\n activeChats: this.sessionsByChatId.size,\n streamMode: this.getCurrentStreamMode(),\n };\n }\n\n public async testToken(tokenInput?: string | null): Promise<TelegramTokenTestResult> {\n const token = asTrimmedString(tokenInput) || this.settings.token || \"\";\n if (!token) {\n return {\n ok: false,\n username: null,\n error: \"Telegram bot token is required.\",\n };\n }\n try {\n const response = await this.callTelegramApi<{ username?: unknown }>(\n token,\n \"getMe\",\n {},\n { retry429: false },\n );\n const username = asTrimmedString(asRecord(response).username);\n return {\n ok: true,\n username: username || null,\n error: null,\n };\n } catch (error) {\n return {\n ok: false,\n username: null,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n public async applyRuntimeSettings(settings: JsonRecord): Promise<void> {\n const next = this.extractSettings(settings);\n const tokenChanged = next.token !== this.settings.token;\n const enabledChanged = next.enabled !== this.settings.enabled;\n this.settings = next;\n this.status.allowedChats = 0;\n if (tokenChanged) {\n this.status.botUsername = null;\n this.draftStreamingEnabled = false;\n this.messageStreamingEnabled = true;\n this.status.streamMode = this.getCurrentStreamMode();\n }\n const shouldRestart = tokenChanged || enabledChanged;\n await this.syncRuntimeState({ shouldRestart });\n }\n\n public async dispose(): Promise<void> {\n await this.stop(\"Bridge disposed.\");\n }\n\n public async stop(reason?: string): Promise<void> {\n if (!this.running && !this.pollLoopPromise) {\n await this.releaseRuntimeLock();\n this.status.state = \"stopped\";\n this.status.running = false;\n this.status.startedAtMs = null;\n if (reason) {\n this.status.lastError = null;\n }\n return;\n }\n\n this.running = false;\n this.status.running = false;\n this.status.state = \"stopped\";\n this.status.startedAtMs = null;\n\n if (this.pollAbortController) {\n this.pollAbortController.abort();\n this.pollAbortController = null;\n }\n\n if (this.pollLoopPromise) {\n try {\n await this.pollLoopPromise;\n } catch {\n // Ignore poll loop termination errors during shutdown.\n }\n this.pollLoopPromise = null;\n }\n\n this.detachAppServerListeners();\n await this.detachAllConversationListeners();\n this.clearSessionState();\n await this.releaseRuntimeLock();\n\n if (reason) {\n logInfo(\"[telegram-bridge] stopped\", reason);\n }\n }\n\n private extractSettings(raw: JsonRecord): TelegramBridgeSettings {\n return {\n enabled: raw.telegramBridgeEnabled === true,\n token: (() => {\n const token = asTrimmedString(raw.telegramBotToken);\n return token || null;\n })(),\n };\n }\n\n private async syncRuntimeState(options: { shouldRestart: boolean }): Promise<void> {\n const shouldRun =\n this.settings.enabled &&\n Boolean(this.settings.token);\n\n if (!shouldRun) {\n await this.stop(\"Disabled or incomplete Telegram settings.\");\n this.status.state = \"stopped\";\n this.status.lastError = null;\n return;\n }\n\n const isPro = await this.options.isProEnabled().catch((error) => {\n logWarn(\"[telegram-bridge] failed to verify Pro status\", error);\n return false;\n });\n\n if (!isPro) {\n await this.stop(\"Telegram bridge requires Pro.\");\n this.status.state = \"error\";\n this.status.lastError = \"Telegram mobile access requires Pro.\";\n return;\n }\n\n if (this.running && options.shouldRestart) {\n await this.stop(\"Restarting Telegram bridge after settings change.\");\n }\n\n if (this.running) {\n return;\n }\n\n await this.start();\n }\n\n private async start(): Promise<void> {\n const token = this.settings.token;\n if (!token) {\n this.status.state = \"error\";\n this.status.lastError = \"Telegram bot token is missing.\";\n return;\n }\n\n const me = await this.testToken(token);\n if (!me.ok) {\n this.status.state = \"error\";\n this.status.lastError = me.error;\n this.status.botUsername = null;\n return;\n }\n\n try {\n await this.acquireRuntimeLock(token);\n } catch (error) {\n this.status.state = \"error\";\n this.status.lastError = error instanceof Error ? error.message : String(error);\n return;\n }\n\n this.status.botUsername = me.username;\n this.status.lastError = null;\n this.status.state = \"running\";\n this.status.running = true;\n this.status.startedAtMs = nowMs();\n this.running = true;\n\n this.attachAppServerListeners();\n\n this.pollAbortController = new AbortController();\n this.pollLoopPromise = this.runPolling(this.pollAbortController.signal).finally(() => {\n this.pollLoopPromise = null;\n });\n\n logInfo(\"[telegram-bridge] started\", {\n allowedChats: \"all-private-chats\",\n botUsername: this.status.botUsername,\n });\n }\n\n private async runPolling(signal: AbortSignal): Promise<void> {\n const token = this.settings.token;\n if (!token) {\n return;\n }\n\n // Ensure polling mode is enabled in case webhook was configured externally.\n await this.callTelegramApi(token, \"deleteWebhook\", { drop_pending_updates: false }).catch(\n (error) => {\n logWarn(\"[telegram-bridge] deleteWebhook failed\", error);\n },\n );\n\n let backoffMs = 1_000;\n\n while (!signal.aborted && this.running) {\n try {\n this.prunePendingActions();\n const updates = await this.callTelegramApi<TelegramUpdate[]>(\n token,\n \"getUpdates\",\n {\n offset: this.updateOffset,\n timeout: TELEGRAM_POLL_TIMEOUT_SECONDS,\n allowed_updates: [\"message\", \"callback_query\", \"my_chat_member\"],\n },\n {\n signal,\n retry429: true,\n },\n );\n\n const list = Array.isArray(updates) ? updates : [];\n for (const update of list) {\n const updateId = asNumber(update.update_id);\n if (updateId !== null) {\n this.updateOffset = updateId + 1;\n }\n await this.handleUpdate(update);\n }\n\n backoffMs = 1_000;\n } catch (error) {\n if (signal.aborted || !this.running) {\n break;\n }\n const message = error instanceof Error ? error.message : String(error);\n this.status.state = \"error\";\n this.status.lastError = message;\n logWarn(\"[telegram-bridge] polling error\", message);\n await this.sleep(Math.min(backoffMs, TELEGRAM_RETRY_LIMIT_MS));\n backoffMs = Math.min(backoffMs * 2, TELEGRAM_RETRY_LIMIT_MS);\n }\n }\n\n if (!signal.aborted && this.running) {\n this.status.state = \"error\";\n this.status.lastError = \"Telegram polling stopped unexpectedly.\";\n }\n }\n\n private async handleUpdate(update: TelegramUpdate): Promise<void> {\n const record = asRecord(update);\n if (record.callback_query) {\n await this.handleCallbackQuery(asRecord(record.callback_query));\n return;\n }\n if (record.message) {\n await this.handleMessage(asRecord(record.message));\n return;\n }\n if (record.my_chat_member) {\n this.handleMembershipUpdate(asRecord(record.my_chat_member));\n return;\n }\n }\n\n private handleMembershipUpdate(payload: JsonRecord): void {\n const chat = asRecord(payload.chat);\n const chatId = normalizeChatId(chat.id);\n if (!chatId) {\n return;\n }\n const newMember = asRecord(payload.new_chat_member);\n const status = asTrimmedString(newMember.status).toLowerCase();\n if (status === \"kicked\" || status === \"left\") {\n void this.resetSession(chatId);\n }\n }\n\n private async handleMessage(message: JsonRecord): Promise<void> {\n const chat = asRecord(message.chat);\n const chatId = normalizeChatId(chat.id);\n if (!chatId) {\n return;\n }\n const session = this.getOrCreateSession(chatId);\n const messageId = asNumber(message.message_id ?? message.messageId);\n if (messageId !== null && this.isDuplicateIncomingMessage(session, messageId)) {\n return;\n }\n\n const chatType = asTrimmedString(chat.type).toLowerCase();\n if (chatType && chatType !== \"private\") {\n await this.sendSimpleMessage(chatId, \"Private chats only. Use me in a direct chat.\");\n return;\n }\n\n const text = asTrimmedString(message.text);\n if (!text) {\n return;\n }\n\n const parsedCommand = this.parseCommand(text);\n if (parsedCommand) {\n const handled = await this.handleCommand(chatId, parsedCommand.command, parsedCommand.args);\n if (handled) {\n return;\n }\n }\n\n await this.handlePromptText(chatId, text);\n }\n\n private async handleCallbackQuery(callbackQuery: JsonRecord): Promise<void> {\n const callbackId = asTrimmedString(callbackQuery.id);\n const message = asRecord(callbackQuery.message);\n const chat = asRecord(message.chat);\n const chatId = normalizeChatId(chat.id);\n const data = asTrimmedString(callbackQuery.data);\n\n if (!callbackId || !chatId || !data) {\n return;\n }\n\n const approvalMatch = /^cu:ap:([a-z0-9]+):(approved|approved_for_session|denied|abort)$/i.exec(\n data,\n );\n if (approvalMatch) {\n const actionId = approvalMatch[1];\n const decision = approvalMatch[2] as \"approved\" | \"approved_for_session\" | \"denied\" | \"abort\";\n const action = this.pendingApprovalById.get(actionId);\n if (!action || action.chatId !== chatId) {\n await this.answerCallbackQuery(callbackId, \"Action expired.\");\n return;\n }\n\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.answerCallbackQuery(callbackId, \"Backend unavailable.\");\n return;\n }\n\n try {\n if (action.kind === \"exec\") {\n await appServer.respondExecCommandRequest(action.requestToken, decision);\n } else {\n await appServer.respondApplyPatchRequest(action.requestToken, decision);\n }\n this.pendingApprovalById.delete(actionId);\n await this.answerCallbackQuery(callbackId, `Recorded: ${decision}`);\n await this.sendSimpleMessage(chatId, `Approval decision sent: ${decision}.`);\n } catch (error) {\n await this.answerCallbackQuery(callbackId, \"Failed to submit decision.\");\n await this.sendSimpleMessage(\n chatId,\n `Failed to submit approval decision: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n return;\n }\n\n await this.answerCallbackQuery(callbackId, \"Unknown action.\");\n }\n\n private parseCommand(text: string): { command: string; args: string } | null {\n const trimmed = text.trim();\n if (!trimmed.startsWith(\"/\")) {\n return null;\n }\n const [head, ...rest] = trimmed.split(/\\s+/g);\n const commandWithSlash = head.slice(1);\n const command = commandWithSlash.split(\"@\")[0]?.trim().toLowerCase();\n if (!command) {\n return null;\n }\n return {\n command,\n args: rest.join(\" \").trim(),\n };\n }\n\n private async handleCommand(chatId: string, command: string, args: string): Promise<boolean> {\n switch (command) {\n case \"start\":\n case \"help\": {\n await this.sendHelp(chatId);\n return true;\n }\n case \"status\": {\n await this.sendStatus(chatId);\n return true;\n }\n case \"projects\":\n case \"workspaces\": {\n await this.sendProjects(chatId);\n return true;\n }\n case \"project\":\n case \"workspace\": {\n await this.selectProject(chatId, args);\n return true;\n }\n case \"new\": {\n await this.createNewThread(chatId);\n return true;\n }\n case \"threads\": {\n await this.listThreads(chatId);\n return true;\n }\n case \"thread\": {\n await this.selectThread(chatId, args);\n return true;\n }\n case \"interrupt\": {\n await this.interruptTurn(chatId);\n return true;\n }\n case \"input\": {\n await this.submitUserInput(chatId, args);\n return true;\n }\n default:\n return false;\n }\n }\n\n private async sendHelp(chatId: string): Promise<void> {\n const lines = [\n \"CodexUse Telegram bridge is connected.\",\n \"\",\n \"Commands:\",\n \"/status - Show current status\",\n \"/projects - List available projects\",\n \"/project <index|id> - Select active project\",\n \"/new - Start a new thread in active project\",\n \"/threads - List recent threads in active project\",\n \"/thread <index|id> - Switch active thread\",\n \"/interrupt - Interrupt active turn\",\n \"/input <request-id> qid=answer;... - Reply to request-user-input\",\n \"\",\n \"Send any normal text message to run it in the active thread.\",\n ];\n await this.sendSimpleMessage(chatId, lines.join(\"\\n\"));\n }\n\n private async sendStatus(chatId: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n const status = this.getStatus();\n const lines = [\n `Bridge: ${status.state}`,\n `Streaming mode: ${status.streamMode}`,\n \"Allowed chats: all private chats\",\n `Bot: ${status.botUsername ? `@${status.botUsername}` : \"(unknown)\"}`,\n `Active project: ${session.projectId ?? \"(not selected)\"}`,\n `Active thread: ${session.threadId ?? \"(none)\"}`,\n `Processing: ${session.processing ? \"yes\" : \"no\"}`,\n ];\n if (status.lastError) {\n lines.push(`Last error: ${status.lastError}`);\n }\n await this.sendSimpleMessage(chatId, lines.join(\"\\n\"));\n }\n\n private async sendProjects(chatId: string): Promise<void> {\n const projects = await this.options.listProjects();\n const session = this.getOrCreateSession(chatId);\n if (projects.length === 0) {\n await this.sendSimpleMessage(chatId, \"No projects found in this desktop app.\");\n return;\n }\n session.lastProjectOrder = projects.map((entry) => entry.id);\n const lines = [\"Projects:\"];\n projects.forEach((project, index) => {\n const isActive = project.id === session.projectId;\n lines.push(\n `${index + 1}. ${project.name}${isActive ? \" (active)\" : \"\"} [${project.id}]`,\n );\n });\n await this.sendSimpleMessage(chatId, lines.join(\"\\n\"));\n }\n\n private async selectProject(chatId: string, args: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n const projects = await this.options.listProjects();\n if (projects.length === 0) {\n await this.sendSimpleMessage(chatId, \"No projects available.\");\n return;\n }\n\n const selected = this.resolveProjectSelection(args, projects, session.lastProjectOrder);\n if (!selected) {\n await this.sendSimpleMessage(\n chatId,\n \"Project not found. Use /projects, then /project <index|id>.\",\n );\n return;\n }\n\n if (session.projectId !== selected.id) {\n await this.detachConversationListener(session);\n session.projectId = selected.id;\n session.threadId = null;\n session.activeTurnId = null;\n session.processing = false;\n session.completedTextCandidate = null;\n this.resetStream(session);\n }\n\n await this.sendSimpleMessage(chatId, `Active project set to: ${selected.name}.`);\n }\n\n private resolveProjectSelection(\n args: string,\n projects: ProjectInfo[],\n order: string[],\n ): ProjectInfo | null {\n const input = args.trim();\n if (!input) {\n return null;\n }\n\n const numeric = Number(input);\n if (Number.isInteger(numeric) && numeric >= 1) {\n if (order.length > 0 && numeric <= order.length) {\n const id = order[numeric - 1];\n return projects.find((entry) => entry.id === id) ?? null;\n }\n if (numeric <= projects.length) {\n return projects[numeric - 1] ?? null;\n }\n }\n\n return projects.find((entry) => entry.id === input) ?? null;\n }\n\n private async createNewThread(chatId: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n const project = await this.ensureSessionProject(session, chatId);\n if (!project) {\n return;\n }\n\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return;\n }\n\n try {\n const response = await appServer.threadStart({\n workspaceId: project.id,\n workspace_id: project.id,\n cwd: project.path,\n });\n const threadId = this.extractThreadIdFromResponse(response);\n if (!threadId) {\n await this.sendSimpleMessage(chatId, \"Thread started, but thread id was missing.\");\n return;\n }\n session.threadId = threadId;\n session.activeTurnId = null;\n session.processing = false;\n session.completedTextCandidate = null;\n this.resetStream(session);\n await this.attachConversationListener(session, project.id, threadId);\n await this.sendSimpleMessage(chatId, `Started new thread: ${threadId}`);\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to start a new thread: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private async listThreads(chatId: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n const project = await this.ensureSessionProject(session, chatId);\n if (!project) {\n return;\n }\n\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return;\n }\n\n try {\n const response = await appServer.listConversations({\n cwd: project.path,\n limit: 20,\n sortKey: \"updated_at\",\n archived: false,\n });\n const threads = this.extractThreadList(response);\n if (threads.length === 0) {\n await this.sendSimpleMessage(chatId, \"No threads found for this project.\");\n return;\n }\n session.lastThreadOrder = threads.map((entry) => entry.id);\n const lines = [\"Threads:\"];\n threads.forEach((thread, index) => {\n const isActive = thread.id === session.threadId;\n const title = thread.title || \"(untitled)\";\n lines.push(`${index + 1}. ${title}${isActive ? \" (active)\" : \"\"} [${thread.id}]`);\n });\n await this.sendSimpleMessage(chatId, lines.join(\"\\n\"));\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to list threads: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private async selectThread(chatId: string, args: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n const project = await this.ensureSessionProject(session, chatId);\n if (!project) {\n return;\n }\n\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return;\n }\n\n const input = args.trim();\n if (!input) {\n await this.sendSimpleMessage(chatId, \"Usage: /thread <index|id>\");\n return;\n }\n\n let threadId = \"\";\n const numeric = Number(input);\n if (Number.isInteger(numeric) && numeric >= 1) {\n if (session.lastThreadOrder.length > 0 && numeric <= session.lastThreadOrder.length) {\n threadId = session.lastThreadOrder[numeric - 1] ?? \"\";\n }\n }\n if (!threadId) {\n threadId = input;\n }\n\n try {\n await appServer.threadResume({\n workspaceId: project.id,\n workspace_id: project.id,\n threadId,\n });\n session.threadId = threadId;\n session.activeTurnId = null;\n session.processing = false;\n session.completedTextCandidate = null;\n this.resetStream(session);\n await this.attachConversationListener(session, project.id, threadId);\n await this.sendSimpleMessage(chatId, `Active thread set to: ${threadId}`);\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to switch thread: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private async interruptTurn(chatId: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n const project = await this.ensureSessionProject(session, chatId);\n if (!project || !session.threadId) {\n await this.sendSimpleMessage(chatId, \"No active thread to interrupt.\");\n return;\n }\n\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return;\n }\n\n const turnId = session.activeTurnId || \"pending\";\n try {\n await appServer.interruptTurn({\n workspaceId: project.id,\n workspace_id: project.id,\n threadId: session.threadId,\n turnId,\n });\n session.processing = false;\n session.activeTurnId = null;\n this.resetStream(session);\n await this.sendSimpleMessage(chatId, \"Interrupt requested.\");\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to interrupt turn: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private async submitUserInput(chatId: string, args: string): Promise<void> {\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return;\n }\n\n const trimmed = args.trim();\n if (!trimmed) {\n await this.sendSimpleMessage(\n chatId,\n \"Usage: /input <request-id> qid=answer; qid2=answer\",\n );\n return;\n }\n\n const [requestTokenPart, ...restParts] = trimmed.split(/\\s+/g);\n let requestIdToken = requestTokenPart.trim();\n let bodyText = restParts.join(\" \").trim();\n\n if (!requestIdToken || requestIdToken.includes(\"=\")) {\n const pendingForChat = Array.from(this.pendingUserInputByRequestId.values()).filter(\n (entry) => entry.chatId === chatId,\n );\n if (pendingForChat.length !== 1) {\n await this.sendSimpleMessage(\n chatId,\n \"Request id is required. Use /input <request-id> qid=answer;...\",\n );\n return;\n }\n requestIdToken = String(pendingForChat[0].requestId);\n bodyText = trimmed;\n }\n\n const pending = this.pendingUserInputByRequestId.get(requestIdToken);\n if (!pending || pending.chatId !== chatId) {\n await this.sendSimpleMessage(chatId, \"Unknown or expired request id.\");\n return;\n }\n\n const answers = this.parseUserInputAnswers(bodyText, pending.params);\n if (!answers) {\n await this.sendSimpleMessage(\n chatId,\n \"Could not parse answers. Format: /input <request-id> qid=answer; qid2=answer\",\n );\n return;\n }\n\n try {\n await appServer.respondToServerRequest(pending.requestId, {\n answers,\n });\n this.pendingUserInputByRequestId.delete(requestIdToken);\n await this.sendSimpleMessage(chatId, \"Input submitted.\");\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to submit input: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private parseUserInputAnswers(\n bodyText: string,\n params: JsonRecord,\n ): Record<string, { answers: string[] }> | null {\n const questionsRaw = Array.isArray(params.questions) ? params.questions : [];\n const questions = questionsRaw\n .map((entry) => asRecord(entry))\n .filter((entry) => asTrimmedString(entry.id));\n\n const questionIds = new Set(questions.map((entry) => asTrimmedString(entry.id)));\n const answers: Record<string, { answers: string[] }> = {};\n\n const segments = bodyText\n .split(\";\")\n .map((segment) => segment.trim())\n .filter(Boolean);\n\n if (segments.length === 0) {\n if (questions.length === 1 && bodyText.trim()) {\n const id = asTrimmedString(questions[0].id);\n answers[id] = { answers: [bodyText.trim()] };\n return answers;\n }\n return null;\n }\n\n for (const segment of segments) {\n const eqIndex = segment.indexOf(\"=\");\n if (eqIndex <= 0) {\n if (questions.length === 1) {\n const id = asTrimmedString(questions[0].id);\n answers[id] = { answers: [segment.trim()] };\n continue;\n }\n return null;\n }\n const key = segment.slice(0, eqIndex).trim();\n const value = segment.slice(eqIndex + 1).trim();\n if (!key || !value || !questionIds.has(key)) {\n return null;\n }\n const splitValues = value\n .split(\",\")\n .map((entry) => entry.trim())\n .filter(Boolean);\n answers[key] = {\n answers: splitValues.length > 0 ? splitValues : [value],\n };\n }\n\n return Object.keys(answers).length > 0 ? answers : null;\n }\n\n private async handlePromptText(chatId: string, text: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n if (session.processing) {\n await this.sendSimpleMessage(\n chatId,\n \"A response is already in progress. Wait for completion or use /interrupt.\",\n );\n return;\n }\n\n const project = await this.ensureSessionProject(session, chatId);\n if (!project) {\n return;\n }\n\n const threadId = session.threadId || (await this.startThreadForSession(chatId, session, project));\n if (!threadId) {\n return;\n }\n\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return;\n }\n\n try {\n session.completedTextCandidate = null;\n this.resetStream(session);\n const response = await appServer.sendUserMessage({\n workspaceId: project.id,\n workspace_id: project.id,\n threadId,\n thread_id: threadId,\n conversationId: threadId,\n conversation_id: threadId,\n text,\n });\n\n const turnId = this.extractTurnIdFromResponse(response);\n session.processing = true;\n session.activeTurnId = turnId || null;\n this.ensureTypingIndicator(session);\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to send message: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private async startThreadForSession(\n chatId: string,\n session: ChatSession,\n project: ProjectInfo,\n ): Promise<string | null> {\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return null;\n }\n\n try {\n const response = await appServer.threadStart({\n workspaceId: project.id,\n workspace_id: project.id,\n cwd: project.path,\n });\n const threadId = this.extractThreadIdFromResponse(response);\n if (!threadId) {\n await this.sendSimpleMessage(chatId, \"Could not create thread (missing thread id).\");\n return null;\n }\n session.threadId = threadId;\n await this.attachConversationListener(session, project.id, threadId);\n return threadId;\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to create thread: ${error instanceof Error ? error.message : String(error)}`,\n );\n return null;\n }\n }\n\n private async ensureSessionProject(\n session: ChatSession,\n chatId: string,\n ): Promise<ProjectInfo | null> {\n if (session.projectId) {\n const existing = await this.options.getProjectById(session.projectId);\n if (existing) {\n return existing;\n }\n session.projectId = null;\n session.threadId = null;\n }\n\n const defaultProjectId = await this.resolveDefaultProjectId();\n if (defaultProjectId) {\n const preferred = await this.options.getProjectById(defaultProjectId).catch(() => null);\n if (preferred) {\n session.projectId = preferred.id;\n return preferred;\n }\n }\n\n const projects = await this.options.listProjects();\n if (projects.length === 0) {\n await this.sendSimpleMessage(chatId, \"No projects found. Add a project in desktop settings first.\");\n return null;\n }\n\n const connected = projects.find((entry) => entry.connected);\n const selected = connected ?? projects[0];\n session.projectId = selected.id;\n session.lastProjectOrder = projects.map((entry) => entry.id);\n return selected;\n }\n\n private async resolveDefaultProjectId(): Promise<string | null> {\n const resolver = this.options.getDefaultProjectId;\n if (!resolver) {\n return null;\n }\n try {\n const value = await resolver();\n const normalized = asTrimmedString(value);\n return normalized || null;\n } catch {\n return null;\n }\n }\n\n private extractThreadIdFromResponse(value: unknown): string {\n const record = asRecord(value);\n const result = asRecord(record.result);\n const thread = asRecord(result.thread ?? record.thread);\n return asTrimmedString(\n thread.id ??\n thread.threadId ??\n thread.thread_id ??\n result.threadId ??\n result.thread_id ??\n record.threadId ??\n record.thread_id ??\n result.conversationId ??\n result.conversation_id ??\n \"\",\n );\n }\n\n private extractTurnIdFromResponse(value: unknown): string {\n const record = asRecord(value);\n const result = asRecord(record.result);\n const turn = asRecord(result.turn ?? record.turn);\n return asTrimmedString(\n turn.id ??\n turn.turnId ??\n turn.turn_id ??\n result.turnId ??\n result.turn_id ??\n record.turnId ??\n record.turn_id ??\n \"\",\n );\n }\n\n private extractThreadList(value: unknown): Array<{ id: string; title: string }> {\n const root = asRecord(value);\n const primary = Array.isArray(value)\n ? (value as unknown[])\n : (Array.isArray(root.data)\n ? root.data\n : Array.isArray(root.threads)\n ? root.threads\n : Array.isArray(root.items)\n ? root.items\n : []);\n const result: Array<{ id: string; title: string }> = [];\n for (const entry of primary) {\n const thread = asRecord(entry);\n const id = asTrimmedString(\n thread.id ??\n thread.threadId ??\n thread.thread_id ??\n thread.conversationId ??\n thread.conversation_id ??\n \"\",\n );\n if (!id) {\n continue;\n }\n const title =\n asTrimmedString(\n thread.name ?? thread.title ?? thread.preview ?? thread.summary ?? thread.path ?? \"\",\n ) || \"(untitled)\";\n result.push({ id, title });\n }\n return result;\n }\n\n private getOrCreateSession(chatId: string): ChatSession {\n const existing = this.sessionsByChatId.get(chatId);\n if (existing) {\n return existing;\n }\n const session: ChatSession = {\n chatId,\n projectId: null,\n threadId: null,\n listenerSubscriptionId: null,\n activeTurnId: null,\n processing: false,\n finalizeInFlight: false,\n lastProjectOrder: [],\n lastThreadOrder: [],\n completedTextCandidate: null,\n recentFinalizedTurnIds: [],\n recentFinalSignatures: [],\n recentIncomingMessageIds: [],\n streamFlushPromise: null,\n streamFlushPending: false,\n lastDeliveredFinalText: null,\n lastDeliveredFinalAtMs: 0,\n typingTimer: null,\n stream: null,\n };\n this.sessionsByChatId.set(chatId, session);\n this.status.activeChats = this.sessionsByChatId.size;\n return session;\n }\n\n private async resetSession(chatId: string): Promise<void> {\n const session = this.sessionsByChatId.get(chatId);\n if (!session) {\n return;\n }\n await this.detachConversationListener(session);\n this.stopTypingIndicator(session);\n if (session.threadId) {\n this.chatIdByThreadId.delete(session.threadId);\n }\n this.sessionsByChatId.delete(chatId);\n this.status.activeChats = this.sessionsByChatId.size;\n }\n\n private async attachConversationListener(\n session: ChatSession,\n projectId: string,\n threadId: string,\n ): Promise<void> {\n const appServer = this.options.getAppServer();\n if (!appServer) {\n return;\n }\n\n await this.detachConversationListener(session);\n\n try {\n const response = await appServer.addConversationListener({\n conversationId: threadId,\n workspaceId: projectId,\n workspace_id: projectId,\n });\n const responseRecord = asRecord(response);\n const subscriptionId = asTrimmedString(responseRecord.subscriptionId);\n session.listenerSubscriptionId = subscriptionId || null;\n session.threadId = threadId;\n this.chatIdByThreadId.set(threadId, session.chatId);\n } catch (error) {\n logWarn(\"[telegram-bridge] failed to attach conversation listener\", error);\n }\n }\n\n private async detachConversationListener(session: ChatSession): Promise<void> {\n const appServer = this.options.getAppServer();\n if (!appServer) {\n session.listenerSubscriptionId = null;\n return;\n }\n\n const subscriptionId = session.listenerSubscriptionId;\n session.listenerSubscriptionId = null;\n if (!subscriptionId) {\n return;\n }\n\n try {\n await appServer.removeConversationListener({\n subscriptionId,\n });\n } catch (error) {\n logWarn(\"[telegram-bridge] failed to remove conversation listener\", error);\n }\n }\n\n private async detachAllConversationListeners(): Promise<void> {\n const sessions = Array.from(this.sessionsByChatId.values());\n await Promise.all(sessions.map((session) => this.detachConversationListener(session)));\n }\n\n private clearSessionState(): void {\n for (const session of this.sessionsByChatId.values()) {\n this.resetStream(session);\n }\n this.sessionsByChatId.clear();\n this.chatIdByThreadId.clear();\n this.pendingApprovalById.clear();\n this.pendingUserInputByRequestId.clear();\n this.recentDeltaBySignature.clear();\n this.lastSendAtByChatId.clear();\n this.status.activeChats = 0;\n }\n\n private attachAppServerListeners(): void {\n if (this.appServerListenersBound) {\n return;\n }\n const appServer = this.options.getAppServer();\n if (!appServer) {\n this.status.state = \"error\";\n this.status.lastError = \"Codex app-server is unavailable.\";\n return;\n }\n\n appServer.on(\"codex:notification\", this.handleCodexNotification);\n appServer.on(\"codex:event\", this.handleCodexEvent);\n appServer.on(\"codex:exec-command-request\", this.handleExecApprovalRequest);\n appServer.on(\"codex:apply-patch-request\", this.handlePatchApprovalRequest);\n appServer.on(\"codex:server-request\", this.handleServerRequest);\n this.appServerListenersBound = true;\n }\n\n private detachAppServerListeners(): void {\n if (!this.appServerListenersBound) {\n return;\n }\n const appServer = this.options.getAppServer();\n if (!appServer) {\n this.appServerListenersBound = false;\n return;\n }\n\n appServer.off(\"codex:notification\", this.handleCodexNotification);\n appServer.off(\"codex:event\", this.handleCodexEvent);\n appServer.off(\"codex:exec-command-request\", this.handleExecApprovalRequest);\n appServer.off(\"codex:apply-patch-request\", this.handlePatchApprovalRequest);\n appServer.off(\"codex:server-request\", this.handleServerRequest);\n this.appServerListenersBound = false;\n }\n\n private async handleNotification(payload: CodexNotificationPayload): Promise<void> {\n if (!this.running) {\n return;\n }\n const method = asTrimmedString(payload.method);\n if (!method) {\n return;\n }\n const params = asRecord(payload.params);\n const threadId = extractThreadId(params);\n if (!threadId) {\n return;\n }\n const session = this.resolveSessionByThreadId(threadId);\n if (!session) {\n return;\n }\n\n if (method === \"turn/started\") {\n const turnId = extractTurnId(params);\n session.processing = true;\n if (turnId) {\n session.activeTurnId = turnId;\n }\n this.ensureTypingIndicator(session);\n return;\n }\n\n if (method === \"item/agentMessage/delta\") {\n const delta = extractDeltaFromNotification(params);\n if (!delta) {\n return;\n }\n if (this.isDuplicateDelta(`${threadId}|${delta}`)) {\n return;\n }\n this.appendAssistantDelta(session, delta);\n return;\n }\n\n if (method === \"item/completed\") {\n const text = extractAssistantTextFromItemCompleted(params);\n if (text.trim()) {\n session.completedTextCandidate = text;\n }\n return;\n }\n\n if (method === \"turn/completed\") {\n await this.finalizeTurn(session);\n return;\n }\n\n if (method === \"error\") {\n if (!isRetryableTurnErrorPayload(params)) {\n const errorMessage =\n asTrimmedString(asRecord(params.error).message) ||\n asTrimmedString(params.message) ||\n \"Turn failed.\";\n await this.sendSimpleMessage(session.chatId, `Turn error: ${errorMessage}`);\n }\n await this.finalizeTurn(session);\n return;\n }\n }\n\n private async handleEvent(payload: CodexEventPayload): Promise<void> {\n if (!this.running) {\n return;\n }\n const method = asTrimmedString(payload.method);\n if (!method.startsWith(\"codex/event/\")) {\n return;\n }\n const params = asRecord(payload.params);\n const threadId = extractThreadId(params);\n if (!threadId) {\n return;\n }\n const session = this.resolveSessionByThreadId(threadId);\n if (!session) {\n return;\n }\n\n const msg = asRecord(params.msg);\n const msgType = asTrimmedString(msg.type).toLowerCase();\n\n if (msgType === \"agent_message_delta\" || msgType === \"agent_message_content_delta\") {\n const delta = extractText(msg.delta ?? msg.message ?? msg.content ?? msg.value);\n if (!delta) {\n return;\n }\n if (this.isDuplicateDelta(`${threadId}|${delta}`)) {\n return;\n }\n this.appendAssistantDelta(session, delta);\n return;\n }\n\n if (msgType === \"agent_message\") {\n const text = extractText(msg.message ?? msg.content ?? msg.text ?? msg.value);\n if (text.trim()) {\n session.completedTextCandidate = text;\n }\n return;\n }\n\n if (msgType === \"task_started\") {\n session.processing = true;\n const turnId = extractTurnId(params);\n if (turnId) {\n session.activeTurnId = turnId;\n }\n this.ensureTypingIndicator(session);\n return;\n }\n\n if (msgType === \"task_complete\" || msgType === \"turn_aborted\") {\n await this.finalizeTurn(session);\n return;\n }\n\n if (msgType === \"error\" || msgType === \"stream_error\") {\n if (!isRetryableTurnErrorPayload(msg)) {\n const errorMessage =\n asTrimmedString(msg.message) || asTrimmedString(msg.error) || \"Turn failed.\";\n await this.sendSimpleMessage(session.chatId, `Turn error: ${errorMessage}`);\n }\n await this.finalizeTurn(session);\n }\n }\n\n private resolveSessionByThreadId(threadId: string): ChatSession | null {\n const chatId = this.chatIdByThreadId.get(threadId);\n if (!chatId) {\n return null;\n }\n const session = this.sessionsByChatId.get(chatId);\n if (!session || session.threadId !== threadId) {\n return null;\n }\n return session;\n }\n\n private appendAssistantDelta(session: ChatSession, delta: string): void {\n if (!session.stream) {\n session.stream = {\n draftId: randomUUID().slice(0, 12),\n buffer: \"\",\n lastSent: \"\",\n flushTimer: null,\n messageId: null,\n };\n }\n const nextBuffer = mergeStreamDeltaBuffer(session.stream.buffer, delta);\n if (nextBuffer === session.stream.buffer) {\n return;\n }\n session.stream.buffer = nextBuffer;\n session.processing = true;\n this.ensureTypingIndicator(session);\n this.scheduleDraftFlush(session, false);\n }\n\n private scheduleDraftFlush(session: ChatSession, force: boolean): void {\n if (!session.stream) {\n return;\n }\n\n if (force) {\n if (session.stream.flushTimer) {\n clearTimeout(session.stream.flushTimer);\n session.stream.flushTimer = null;\n }\n if (session.streamFlushPromise) {\n session.streamFlushPending = true;\n return;\n }\n void this.flushDraft(session, true);\n return;\n }\n\n if (session.streamFlushPromise) {\n session.streamFlushPending = true;\n return;\n }\n\n if (session.stream.flushTimer) {\n return;\n }\n\n session.stream.flushTimer = setTimeout(() => {\n if (session.stream) {\n session.stream.flushTimer = null;\n }\n void this.flushDraft(session, false);\n }, TELEGRAM_STREAM_FLUSH_MS);\n }\n\n private async flushDraft(session: ChatSession, force: boolean): Promise<void> {\n if (!this.running) {\n return;\n }\n\n if (session.streamFlushPromise) {\n if (force) {\n session.streamFlushPending = true;\n }\n return;\n }\n\n const currentStream = session.stream;\n if (!currentStream) {\n return;\n }\n\n const draftId = currentStream.draftId;\n const rawText = currentStream.buffer;\n if (!rawText.trim()) {\n return;\n }\n\n const draftText =\n rawText.length <= TELEGRAM_MAX_MESSAGE_LENGTH\n ? rawText\n : rawText.slice(rawText.length - TELEGRAM_MAX_MESSAGE_LENGTH);\n\n if (!force && draftText === currentStream.lastSent) {\n return;\n }\n\n const runFlush = async () => {\n if (this.draftStreamingEnabled) {\n try {\n await this.sendDraftMessage(session.chatId, draftText, draftId);\n const activeStream = this.getStreamByDraftId(session, draftId);\n if (activeStream) {\n activeStream.lastSent = draftText;\n }\n this.status.streamMode = this.getCurrentStreamMode();\n return;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (this.isDraftStreamingUnsupportedError(message)) {\n this.draftStreamingEnabled = false;\n this.status.streamMode = this.getCurrentStreamMode();\n logWarn(\n \"[telegram-bridge] sendMessageDraft unavailable, falling back to message edit streaming\",\n message,\n );\n } else {\n logWarn(\"[telegram-bridge] failed to flush draft\", message);\n return;\n }\n }\n }\n\n if (!this.messageStreamingEnabled) {\n return;\n }\n\n try {\n await this.sendOrEditStreamMessage(session, draftText, draftId);\n const activeStream = this.getStreamByDraftId(session, draftId);\n if (activeStream) {\n activeStream.lastSent = draftText;\n }\n this.status.streamMode = this.getCurrentStreamMode();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (this.isMessageStreamingUnsupportedError(message)) {\n this.messageStreamingEnabled = false;\n this.status.streamMode = this.getCurrentStreamMode();\n logWarn(\"[telegram-bridge] edit streaming unavailable, disabling streaming\", message);\n return;\n }\n logWarn(\"[telegram-bridge] failed to flush message-edit stream\", message);\n }\n };\n\n const flushPromise = runFlush();\n session.streamFlushPromise = flushPromise;\n try {\n await flushPromise;\n } finally {\n if (session.streamFlushPromise === flushPromise) {\n session.streamFlushPromise = null;\n }\n if (session.streamFlushPending && this.running && session.stream) {\n session.streamFlushPending = false;\n void this.flushDraft(session, false);\n }\n }\n }\n\n private async finalizeTurn(session: ChatSession): Promise<void> {\n if (session.finalizeInFlight) {\n return;\n }\n if (!session.processing && !session.stream?.buffer && !session.completedTextCandidate) {\n return;\n }\n\n session.finalizeInFlight = true;\n try {\n await this.flushDraft(session, true);\n if (session.streamFlushPromise) {\n await session.streamFlushPromise.catch(() => undefined);\n }\n if (session.streamFlushPending && session.stream) {\n session.streamFlushPending = false;\n await this.flushDraft(session, true);\n if (session.streamFlushPromise) {\n await session.streamFlushPromise.catch(() => undefined);\n }\n }\n\n const finalText = (session.completedTextCandidate ?? session.stream?.buffer ?? \"\").trim();\n const turnId = session.activeTurnId;\n const alreadyFinalizedTurn = turnId\n ? session.recentFinalizedTurnIds.includes(turnId)\n : false;\n const now = nowMs();\n const duplicateByRecentText =\n finalText.length > 0 &&\n session.lastDeliveredFinalText === finalText &&\n now - session.lastDeliveredFinalAtMs <= TELEGRAM_FINAL_TEXT_DEDUPE_MS;\n const duplicateByFinalSignature = this.isDuplicateFinalSignature(session, finalText, now);\n\n if (finalText && !alreadyFinalizedTurn && !duplicateByRecentText && !duplicateByFinalSignature) {\n const chunks = splitMessage(finalText, TELEGRAM_MAX_MESSAGE_LENGTH);\n let chunkStartIndex = 0;\n const streamMessageId = session.stream?.messageId ?? null;\n if (streamMessageId !== null && chunks.length > 0) {\n const reused = await this.tryFinalizeStreamMessage(session.chatId, streamMessageId, chunks[0]);\n if (!reused) {\n await this.sendSimpleMessage(session.chatId, chunks[0]);\n }\n chunkStartIndex = 1;\n }\n for (let index = chunkStartIndex; index < chunks.length; index += 1) {\n await this.sendSimpleMessage(session.chatId, chunks[index]);\n }\n session.lastDeliveredFinalText = finalText;\n session.lastDeliveredFinalAtMs = now;\n this.recordFinalSignature(session, finalText, now);\n if (turnId) {\n session.recentFinalizedTurnIds.push(turnId);\n if (session.recentFinalizedTurnIds.length > TELEGRAM_RECENT_FINALIZED_TURNS_MAX) {\n session.recentFinalizedTurnIds.splice(\n 0,\n session.recentFinalizedTurnIds.length - TELEGRAM_RECENT_FINALIZED_TURNS_MAX,\n );\n }\n }\n }\n } finally {\n session.processing = false;\n session.activeTurnId = null;\n session.completedTextCandidate = null;\n this.resetStream(session);\n session.finalizeInFlight = false;\n }\n }\n\n private resetStream(session: ChatSession): void {\n this.stopTypingIndicator(session);\n if (session.stream?.flushTimer) {\n clearTimeout(session.stream.flushTimer);\n }\n session.streamFlushPending = false;\n session.streamFlushPromise = null;\n session.stream = null;\n }\n\n private ensureTypingIndicator(session: ChatSession): void {\n if (!this.running || !session.processing) {\n return;\n }\n if (session.typingTimer) {\n return;\n }\n void this.sendTypingAction(session.chatId);\n session.typingTimer = setInterval(() => {\n if (!this.running || !session.processing) {\n this.stopTypingIndicator(session);\n return;\n }\n void this.sendTypingAction(session.chatId);\n }, TELEGRAM_TYPING_HEARTBEAT_MS);\n }\n\n private stopTypingIndicator(session: ChatSession): void {\n if (session.typingTimer) {\n clearInterval(session.typingTimer);\n session.typingTimer = null;\n }\n }\n\n private isDraftStreamingUnsupportedError(message: string): boolean {\n const lower = message.toLowerCase();\n return (\n lower.includes(\"sendmessagedraft\") ||\n lower.includes(\"method not found\") ||\n lower.includes(\"there is no method\") ||\n lower.includes(\"text must be non-empty\") ||\n lower.includes(\"random_id_invalid\") ||\n lower.includes(\"random id invalid\") ||\n lower.includes(\"not found\")\n );\n }\n\n private isMessageStreamingUnsupportedError(message: string): boolean {\n const lower = message.toLowerCase();\n return (\n lower.includes(\"editmessagetext\") &&\n (lower.includes(\"method not found\") || lower.includes(\"there is no method\"))\n );\n }\n\n private async sendOrEditStreamMessage(\n session: ChatSession,\n text: string,\n draftId: string,\n ): Promise<void> {\n const stream = this.getStreamByDraftId(session, draftId);\n if (!stream) {\n return;\n }\n const existingMessageId = stream.messageId;\n if (existingMessageId !== null) {\n const edited = await this.tryEditMessageText(session.chatId, existingMessageId, text);\n if (edited) {\n return;\n }\n const activeStream = this.getStreamByDraftId(session, draftId);\n if (activeStream) {\n activeStream.messageId = null;\n }\n }\n\n const sent = await this.sendSimpleMessage(session.chatId, text);\n const messageId = this.extractTelegramMessageId(sent);\n if (messageId !== null) {\n const activeStream = this.getStreamByDraftId(session, draftId);\n if (activeStream) {\n activeStream.messageId = messageId;\n }\n }\n }\n\n private getStreamByDraftId(\n session: ChatSession,\n draftId: string,\n ): ChatSession[\"stream\"] {\n const stream = session.stream;\n if (!stream || stream.draftId !== draftId) {\n return null;\n }\n return stream;\n }\n\n private async tryFinalizeStreamMessage(\n chatId: string,\n messageId: number,\n text: string,\n ): Promise<boolean> {\n return this.tryEditMessageText(chatId, messageId, text);\n }\n\n private async tryEditMessageText(\n chatId: string,\n messageId: number,\n text: string,\n ): Promise<boolean> {\n try {\n await this.editMessageText(chatId, messageId, text);\n return true;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const lower = message.toLowerCase();\n if (lower.includes(\"message is not modified\")) {\n return true;\n }\n if (\n lower.includes(\"message to edit not found\") ||\n lower.includes(\"message can't be edited\") ||\n lower.includes(\"message cant be edited\")\n ) {\n return false;\n }\n throw error;\n }\n }\n\n private isDuplicateIncomingMessage(session: ChatSession, messageId: number): boolean {\n if (session.recentIncomingMessageIds.includes(messageId)) {\n return true;\n }\n session.recentIncomingMessageIds.push(messageId);\n if (session.recentIncomingMessageIds.length > TELEGRAM_RECENT_INCOMING_MESSAGES_MAX) {\n session.recentIncomingMessageIds.splice(\n 0,\n session.recentIncomingMessageIds.length - TELEGRAM_RECENT_INCOMING_MESSAGES_MAX,\n );\n }\n return false;\n }\n\n private buildFinalSignature(session: ChatSession, finalText: string): string {\n const normalized = finalText.trim();\n if (!normalized) {\n return \"\";\n }\n const threadKey = session.threadId ?? \"no-thread\";\n const digest = createHash(\"sha1\").update(normalized).digest(\"hex\");\n return `${threadKey}|${digest}`;\n }\n\n private isDuplicateFinalSignature(\n session: ChatSession,\n finalText: string,\n now: number,\n ): boolean {\n const signature = this.buildFinalSignature(session, finalText);\n if (!signature) {\n return false;\n }\n\n let duplicated = false;\n const kept: Array<{ signature: string; at: number }> = [];\n for (const entry of session.recentFinalSignatures) {\n if (now - entry.at > TELEGRAM_FINAL_SIGNATURE_DEDUPE_MS) {\n continue;\n }\n if (entry.signature === signature) {\n duplicated = true;\n }\n kept.push(entry);\n }\n session.recentFinalSignatures = kept;\n return duplicated;\n }\n\n private recordFinalSignature(session: ChatSession, finalText: string, now: number): void {\n const signature = this.buildFinalSignature(session, finalText);\n if (!signature) {\n return;\n }\n\n const kept = session.recentFinalSignatures.filter(\n (entry) =>\n entry.signature !== signature && now - entry.at <= TELEGRAM_FINAL_SIGNATURE_DEDUPE_MS,\n );\n kept.push({ signature, at: now });\n if (kept.length > TELEGRAM_RECENT_FINAL_SIGNATURES_MAX) {\n kept.splice(0, kept.length - TELEGRAM_RECENT_FINAL_SIGNATURES_MAX);\n }\n session.recentFinalSignatures = kept;\n }\n\n private isDuplicateDelta(signature: string): boolean {\n const now = nowMs();\n const previous = this.recentDeltaBySignature.get(signature) ?? 0;\n this.recentDeltaBySignature.set(signature, now);\n if (this.recentDeltaBySignature.size > 2_048) {\n for (const [key, at] of this.recentDeltaBySignature) {\n if (now - at > 5_000) {\n this.recentDeltaBySignature.delete(key);\n }\n }\n }\n return previous > 0 && now - previous <= 500;\n }\n\n private async handleApprovalRequest(\n kind: \"exec\" | \"patch\",\n requestToken: string,\n params: JsonRecord,\n ): Promise<void> {\n if (!this.running) {\n return;\n }\n\n const chatId = this.resolveChatIdForRequest(params);\n if (!chatId) {\n return;\n }\n\n const actionId = randomUUID().replace(/-/g, \"\").slice(0, 10);\n this.pendingApprovalById.set(actionId, {\n id: actionId,\n kind,\n chatId,\n requestToken,\n createdAtMs: nowMs(),\n });\n\n const threadId = extractThreadId(params);\n const title = kind === \"exec\" ? \"Command approval required\" : \"Patch approval required\";\n const detail = kind === \"exec\" ? extractCommandText(params) : summarizePatchRequest(params);\n const lines = [title];\n if (threadId) {\n lines.push(`Thread: ${threadId}`);\n }\n if (detail) {\n lines.push(`Detail: ${detail}`);\n }\n\n await this.sendSimpleMessage(chatId, lines.join(\"\\n\"), {\n reply_markup: {\n inline_keyboard: [\n [\n { text: \"Approve\", callback_data: `cu:ap:${actionId}:approved` },\n { text: \"Approve session\", callback_data: `cu:ap:${actionId}:approved_for_session` },\n ],\n [\n { text: \"Deny\", callback_data: `cu:ap:${actionId}:denied` },\n { text: \"Abort\", callback_data: `cu:ap:${actionId}:abort` },\n ],\n ],\n },\n });\n }\n\n private async handleUserInputRequest(payload: CodexServerRequestPayload): Promise<void> {\n if (!this.running) {\n return;\n }\n const method = asTrimmedString(payload.method).toLowerCase();\n if (!method.includes(\"requestuserinput\")) {\n return;\n }\n\n const params = asRecord(payload.params);\n const chatId = this.resolveChatIdForRequest(params);\n if (!chatId) {\n return;\n }\n\n const token = String(payload.requestId);\n this.pendingUserInputByRequestId.set(token, {\n chatId,\n requestId: payload.requestId,\n method: payload.method,\n params,\n createdAtMs: nowMs(),\n });\n\n const questions = Array.isArray(params.questions)\n ? params.questions.map((entry) => asRecord(entry)).filter((entry) => asTrimmedString(entry.id))\n : [];\n\n const lines = [\n \"Input required.\",\n `Request ID: ${token}`,\n \"Reply with: /input <request-id> qid=answer; qid2=answer\",\n ];\n\n if (questions.length > 0) {\n lines.push(\"\");\n for (const question of questions) {\n const qid = asTrimmedString(question.id);\n const qtext = asTrimmedString(question.question) || asTrimmedString(question.header) || \"Question\";\n lines.push(`${qid}: ${qtext}`);\n const options = Array.isArray(question.options)\n ? question.options.map((entry) => asRecord(entry)).map((entry) => asTrimmedString(entry.label)).filter(Boolean)\n : [];\n if (options.length > 0) {\n lines.push(`Options: ${options.join(\", \")}`);\n }\n }\n }\n\n await this.sendSimpleMessage(chatId, lines.join(\"\\n\"));\n }\n\n private resolveChatIdForRequest(params: JsonRecord): string | null {\n const threadId = extractThreadId(params);\n if (threadId) {\n const mapped = this.chatIdByThreadId.get(threadId);\n if (mapped) {\n return mapped;\n }\n }\n const sessions = Array.from(this.sessionsByChatId.values());\n if (sessions.length === 1) {\n return sessions[0].chatId;\n }\n return null;\n }\n\n private prunePendingActions(): void {\n const threshold = nowMs() - TELEGRAM_PENDING_TTL_MS;\n for (const [id, entry] of this.pendingApprovalById) {\n if (entry.createdAtMs < threshold) {\n this.pendingApprovalById.delete(id);\n }\n }\n for (const [requestId, entry] of this.pendingUserInputByRequestId) {\n if (entry.createdAtMs < threshold) {\n this.pendingUserInputByRequestId.delete(requestId);\n }\n }\n }\n\n private async answerCallbackQuery(callbackQueryId: string, text?: string): Promise<void> {\n const token = this.settings.token;\n if (!token) {\n return;\n }\n await this.callTelegramApi(\n token,\n \"answerCallbackQuery\",\n {\n callback_query_id: callbackQueryId,\n text: text || undefined,\n },\n {\n retry429: false,\n },\n ).catch(() => undefined);\n }\n\n private async sendTypingAction(chatId: string): Promise<void> {\n const token = this.settings.token;\n if (!token) {\n return;\n }\n await this.callTelegramApi(\n token,\n \"sendChatAction\",\n {\n chat_id: chatId,\n action: \"typing\",\n },\n {\n retry429: false,\n },\n ).catch(() => undefined);\n }\n\n private async sendDraftMessage(chatId: string, text: string, draftId: string): Promise<void> {\n const token = this.settings.token;\n if (!token) {\n return;\n }\n await this.sendWithRateLimit(chatId);\n await this.callTelegramApi(\n token,\n \"sendMessageDraft\",\n {\n chat_id: chatId,\n text,\n message_text: text,\n draft_id: draftId,\n },\n {\n retry429: true,\n },\n );\n }\n\n private async sendSimpleMessage(\n chatId: string,\n text: string,\n extra?: Record<string, unknown>,\n ): Promise<JsonRecord | null> {\n const token = this.settings.token;\n if (!token) {\n return null;\n }\n const payload: Record<string, unknown> = {\n chat_id: chatId,\n text,\n ...extra,\n };\n await this.sendWithRateLimit(chatId);\n const result = await this.callTelegramApi<JsonRecord>(token, \"sendMessage\", payload, {\n retry429: true,\n });\n return asRecord(result);\n }\n\n private async editMessageText(chatId: string, messageId: number, text: string): Promise<void> {\n const token = this.settings.token;\n if (!token) {\n return;\n }\n await this.sendWithRateLimit(chatId);\n await this.callTelegramApi(\n token,\n \"editMessageText\",\n {\n chat_id: chatId,\n message_id: messageId,\n text,\n },\n {\n retry429: true,\n },\n );\n }\n\n private extractTelegramMessageId(value: unknown): number | null {\n const record = asRecord(value);\n return asNumber(record.message_id ?? record.messageId);\n }\n\n private async sendWithRateLimit(chatId: string): Promise<void> {\n const lastSend = this.lastSendAtByChatId.get(chatId) ?? 0;\n const now = nowMs();\n const waitMs = TELEGRAM_MIN_SEND_INTERVAL_MS - (now - lastSend);\n if (waitMs > 0) {\n await this.sleep(waitMs);\n }\n this.lastSendAtByChatId.set(chatId, nowMs());\n }\n\n private async callTelegramApi<T>(\n token: string,\n method: string,\n payload: Record<string, unknown>,\n options?: { signal?: AbortSignal; retry429?: boolean },\n ): Promise<T> {\n const url = `${TELEGRAM_API_BASE}/bot${token}/${method}`;\n\n const execute = async (): Promise<TelegramApiResponse<T>> => {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, TELEGRAM_API_TIMEOUT_MS);\n\n const signal = options?.signal;\n let externalAbortListener: (() => void) | null = null;\n if (signal) {\n if (signal.aborted) {\n clearTimeout(timeoutId);\n controller.abort();\n } else {\n externalAbortListener = () => controller.abort();\n signal.addEventListener(\"abort\", externalAbortListener, { once: true });\n }\n }\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n const json = (await response.json()) as TelegramApiResponse<T>;\n return json;\n } finally {\n clearTimeout(timeoutId);\n if (signal && externalAbortListener) {\n signal.removeEventListener(\"abort\", externalAbortListener);\n }\n }\n };\n\n const response = await execute();\n if (response.ok) {\n return response.result as T;\n }\n\n const retryAfterSeconds = response.parameters?.retry_after;\n if (\n options?.retry429 &&\n response.error_code === 429 &&\n typeof retryAfterSeconds === \"number\" &&\n retryAfterSeconds > 0\n ) {\n await this.sleep(retryAfterSeconds * 1000);\n const retried = await execute();\n if (retried.ok) {\n return retried.result as T;\n }\n throw new Error(retried.description || `${method} failed (code ${retried.error_code ?? \"unknown\"})`);\n }\n\n throw new Error(response.description || `${method} failed (code ${response.error_code ?? \"unknown\"})`);\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, Math.max(0, Math.floor(ms)));\n });\n }\n\n private buildRuntimeLockPath(token: string): string {\n const tokenHash = createHash(\"sha1\").update(token).digest(\"hex\").slice(0, 16);\n return path.join(getUserDataDir(), `${TELEGRAM_BRIDGE_LOCK_FILE_PREFIX}-${tokenHash}.lock`);\n }\n\n private async acquireRuntimeLock(token: string): Promise<void> {\n if (this.runtimeLockPath) {\n return;\n }\n const lockPath = this.buildRuntimeLockPath(token);\n await fs.mkdir(path.dirname(lockPath), { recursive: true });\n\n const payload = JSON.stringify(\n {\n pid: process.pid,\n startedAt: new Date().toISOString(),\n },\n null,\n 2,\n );\n\n try {\n await fs.writeFile(lockPath, payload, { encoding: \"utf8\", flag: \"wx\" });\n this.runtimeLockPath = lockPath;\n return;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") {\n throw error;\n }\n }\n\n const existingPid = await this.readLockPid(lockPath);\n if (existingPid && existingPid !== process.pid && this.isProcessAlive(existingPid)) {\n throw new Error(\n `Telegram bridge already running in another process (pid ${existingPid}). Stop the other instance to avoid duplicate replies.`,\n );\n }\n\n await fs.unlink(lockPath).catch(() => undefined);\n await fs.writeFile(lockPath, payload, { encoding: \"utf8\", flag: \"wx\" });\n this.runtimeLockPath = lockPath;\n }\n\n private async releaseRuntimeLock(): Promise<void> {\n const lockPath = this.runtimeLockPath;\n this.runtimeLockPath = null;\n if (!lockPath) {\n return;\n }\n await fs.unlink(lockPath).catch(() => undefined);\n }\n\n private async readLockPid(lockPath: string): Promise<number | null> {\n try {\n const raw = await fs.readFile(lockPath, \"utf8\");\n const parsed = JSON.parse(raw) as { pid?: unknown };\n const pid = asNumber(parsed.pid);\n if (pid === null || pid <= 0) {\n return null;\n }\n return Math.trunc(pid);\n } catch {\n return null;\n }\n }\n\n private isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n return code === \"EPERM\";\n }\n }\n}\n\nexport function createTelegramBridge(options: TelegramBridgeOptions): TelegramBridge {\n return new TelegramBridge(options);\n}\n","type JsonRecord = Record<string, unknown>;\n\nconst RETRY_FLAG_KEYS = [\n \"willRetry\",\n \"will_retry\",\n \"retryable\",\n \"retryable_error\",\n \"shouldRetry\",\n \"should_retry\",\n \"retry\",\n] as const;\n\nconst RETRY_PROGRESS_MESSAGE_RE =\n /(?:reconnecting|retrying)(?:\\.\\.\\.)?(?:\\s+\\d+\\s*\\/\\s*\\d+)?/i;\n\nfunction asRecord(value: unknown): JsonRecord {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as JsonRecord)\n : {};\n}\n\nfunction asString(value: unknown): string {\n return typeof value === \"string\" ? value : value != null ? String(value) : \"\";\n}\n\nfunction parseBooleanLike(value: unknown): boolean | null {\n if (typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"number\") {\n if (value === 1) {\n return true;\n }\n if (value === 0) {\n return false;\n }\n return null;\n }\n if (typeof value === \"string\") {\n const normalized = value.trim().toLowerCase();\n if (!normalized) {\n return null;\n }\n if (normalized === \"true\" || normalized === \"1\") {\n return true;\n }\n if (normalized === \"false\" || normalized === \"0\") {\n return false;\n }\n }\n return null;\n}\n\nfunction extractRetryFlag(payload: unknown): boolean | null {\n const root = asRecord(payload);\n const nestedCandidates = [\n root,\n asRecord(root.error),\n asRecord(root.details),\n asRecord(root.data),\n asRecord(root.meta),\n ];\n\n for (const candidate of nestedCandidates) {\n for (const key of RETRY_FLAG_KEYS) {\n const parsed = parseBooleanLike(candidate[key]);\n if (parsed !== null) {\n return parsed;\n }\n }\n }\n\n return null;\n}\n\nfunction isRetryProgressMessage(message: string): boolean {\n const trimmed = message.trim();\n if (!trimmed) {\n return false;\n }\n return RETRY_PROGRESS_MESSAGE_RE.test(trimmed);\n}\n\nfunction extractErrorMessageCandidates(payload: unknown): string[] {\n const root = asRecord(payload);\n const error = asRecord(root.error);\n\n return [\n asString(root.message),\n asString(root.detail),\n asString(root.reason),\n asString(root.error),\n asString(error.message),\n asString(error.detail),\n asString(error.reason),\n asString(error.error),\n ]\n .map(value => value.trim())\n .filter(Boolean);\n}\n\nexport function isRetryableTurnErrorPayload(payload: unknown): boolean {\n const retryFlag = extractRetryFlag(payload);\n if (retryFlag !== null) {\n return retryFlag;\n }\n return extractErrorMessageCandidates(payload).some(isRetryProgressMessage);\n}\n","import { ProfileManager } from \"../../../lib/profile-manager\";\nimport { licenseService } from \"../../../lib/license-service\";\nimport { getCloudSyncStatus, pullCloudSync, pushCloudSync } from \"../../../lib/cloud-sync-service\";\nimport { assertProfileCreationAllowed } from \"../../../lib/license-guard\";\nimport { runCodexLogin, resolveCodexBinary, resolveLoginMode, type CodexLoginMode } from \"./codex-cli\";\nimport { fetchRateLimitsViaRpc } from \"../../../lib/codex-rpc\";\nimport { maxUsedPercent } from \"../../../lib/rate-limit-notifier\";\nimport { getAppState, getUserDataDir, initializeAppState } from \"../../../lib/app-state\";\nimport { importLegacyLocalStorageOnce, runStorageMigrationV1 } from \"../../../lib/storage-migration-v1\";\nimport { getStoredAutoRollSettings } from \"../../../lib/codex-settings\";\nimport { handleDaemonCommand } from \"./daemon\";\nimport type { OrganizationInfo, Profile, RateLimitSnapshot, RateLimitWindow } from \"../../../lib/types\";\n\ndeclare const __CODEXUSE_CLI_VERSION__: string;\n\nconst VERSION = typeof __CODEXUSE_CLI_VERSION__ === \"string\"\n ? __CODEXUSE_CLI_VERSION__\n : \"0.0.0\";\nlet cliStorageReadyPromise: Promise<void> | null = null;\n\nasync function ensureCliStorageReady(): Promise<void> {\n if (cliStorageReadyPromise) {\n return cliStorageReadyPromise;\n }\n\n cliStorageReadyPromise = (async () => {\n await initializeAppState(getUserDataDir());\n const migrated = await runStorageMigrationV1();\n if (migrated.migration.status === \"pending_local_storage\") {\n await importLegacyLocalStorageOnce({});\n }\n\n const state = await getAppState();\n if (state.migration.status !== \"complete\") {\n throw new Error(\n `Storage migration is not complete (status: ${state.migration.status}). CLI cannot continue until migration succeeds.`,\n );\n }\n })().catch((error) => {\n cliStorageReadyPromise = null;\n throw error;\n });\n\n return cliStorageReadyPromise;\n}\n\nfunction printHelp(): void {\n console.log(`CodexUse CLI v${VERSION}\n\nUsage:\n codexuse profile list [--no-usage] [--compact]\n codexuse profile current\n codexuse profile add <name> [--skip-login] [--device-auth] [--login=browser|device]\n codexuse profile refresh <name> [--skip-login] [--device-auth] [--login=browser|device]\n codexuse profile switch <name>\n codexuse profile autoroll [--threshold=50-100] [--dry-run] [--watch] [--interval=seconds]\n codexuse profile delete <name>\n codexuse profile rename <old> <new>\n\n codexuse license status [--refresh]\n codexuse license activate <license-key>\n\n codexuse sync status\n codexuse sync pull\n codexuse sync push\n\n codexuse daemon start --telegram-bot-token=<token> [--project-path=/abs/path]\n\nFlags:\n -h, --help Show help\n -v, --version Show version\n --no-usage Skip rate-limit usage fetch\n --compact Names only\n --device-auth Use device auth for Codex login\n --login=MODE Login mode: browser | device\n --threshold=NN Auto-roll switch threshold percent (50-100)\n --watch Keep checking and auto-switch when threshold is reached\n --interval=SEC Watch interval in seconds (default: 30)\n --dry-run Print planned switch without changing active profile\n --telegram-bot-token=TOKEN Telegram bot token for daemon mode\n --project-path=PATH Optional path to auto-register and set as default project in daemon mode\n`);\n}\n\nfunction hasFlag(args: string[], flag: string): boolean {\n return args.includes(flag);\n}\n\nfunction stripFlags(args: string[]): string[] {\n return args.filter(arg => !arg.startsWith(\"-\"));\n}\n\nfunction parseLoginMode(flags: string[]): CodexLoginMode | null {\n if (flags.includes(\"--device-auth\")) return \"device\";\n const explicit = flags.find(flag => flag.startsWith(\"--login=\"));\n if (!explicit) return null;\n const value = explicit.split(\"=\")[1];\n if (value === \"browser\" || value === \"device\") {\n return value;\n }\n return null;\n}\n\nconst DEFAULT_AUTOROLL_INTERVAL_SECONDS = 30;\nconst DEFAULT_AUTOROLL_THRESHOLD = 95;\n\nfunction parseNumericFlag(flags: string[], name: string): number | null {\n const explicit = flags.find(flag => flag.startsWith(`${name}=`));\n if (!explicit) {\n return null;\n }\n const raw = explicit.slice(`${name}=`.length);\n const value = Number.parseFloat(raw);\n return Number.isFinite(value) ? value : Number.NaN;\n}\n\nfunction parseIntegerFlag(flags: string[], name: string): number | null {\n const explicit = flags.find(flag => flag.startsWith(`${name}=`));\n if (!explicit) {\n return null;\n }\n const raw = explicit.slice(`${name}=`.length);\n const value = Number.parseInt(raw, 10);\n return Number.isFinite(value) ? value : Number.NaN;\n}\n\nfunction formatProfileLabel(name: string, displayName?: string | null): string {\n if (displayName && displayName.trim() && displayName !== name) {\n return `${displayName} (${name})`;\n }\n return name;\n}\n\nfunction toTitleCase(value: string): string {\n return value.replace(/\\w\\S*/g, word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());\n}\n\nfunction formatShortDate(value?: string | null): string | null {\n if (!value) return null;\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return null;\n if (typeof Intl !== \"undefined\" && Intl.DateTimeFormat) {\n return new Intl.DateTimeFormat(undefined, { month: \"short\", day: \"numeric\" }).format(date);\n }\n return date.toLocaleDateString();\n}\n\nfunction formatRelativeTime(value?: string | null): string | null {\n if (!value) return null;\n const parsed = Date.parse(value);\n if (Number.isNaN(parsed)) return null;\n const diffMs = parsed - Date.now();\n const absMs = Math.abs(diffMs);\n if (absMs < 60_000) {\n return null;\n }\n const minutes = Math.round(absMs / 60_000);\n if (minutes < 60) {\n return diffMs >= 0 ? `in ${minutes}m` : `${minutes}m ago`;\n }\n const hours = Math.round(minutes / 60);\n if (hours < 24) {\n return diffMs >= 0 ? `in ${hours}h` : `${hours}h ago`;\n }\n const days = Math.round(hours / 24);\n return diffMs >= 0 ? `in ${days}d` : `${days}d ago`;\n}\n\nfunction formatOrganizations(organizations?: OrganizationInfo[]): string | null {\n if (!organizations || !Array.isArray(organizations) || organizations.length === 0) {\n return null;\n }\n const parts = organizations\n .map(org => {\n if (!org) return null;\n const name = org.title || org.id;\n if (!name) return null;\n return org.role ? `${name} (${org.role})` : name;\n })\n .filter((value): value is string => Boolean(value));\n return parts.length > 0 ? parts.join(\", \") : null;\n}\n\nfunction formatWindowLabel(windowMinutes?: number): string | null {\n if (typeof windowMinutes !== \"number\" || Number.isNaN(windowMinutes)) {\n return null;\n }\n if (windowMinutes >= 2880) {\n const days = windowMinutes / 1440;\n const rounded = Math.round(days * 10) / 10;\n const display = Number.isInteger(rounded) ? rounded.toFixed(0) : rounded.toFixed(1);\n return `${display.replace(/\\.0$/, \"\")}d window`;\n }\n if (windowMinutes >= 60) {\n const hours = windowMinutes / 60;\n const rounded = Math.round(hours * 10) / 10;\n const display = Number.isInteger(rounded) ? rounded.toFixed(0) : rounded.toFixed(1);\n return `${display.replace(/\\.0$/, \"\")}h window`;\n }\n const minutes = Math.round(windowMinutes);\n return `${minutes}m window`;\n}\n\nfunction formatDurationFromSeconds(seconds?: number | null): string | null {\n if (typeof seconds !== \"number\" || Number.isNaN(seconds)) {\n return null;\n }\n if (seconds <= 0) {\n return \"now\";\n }\n const minutes = Math.floor(seconds / 60);\n if (minutes === 0) {\n return `${Math.max(1, Math.round(seconds))}s`;\n }\n if (minutes < 60) {\n return `${minutes}m`;\n }\n const hours = Math.floor(minutes / 60);\n const remainingMinutes = minutes % 60;\n if (hours < 24) {\n return remainingMinutes ? `${hours}h ${remainingMinutes}m` : `${hours}h`;\n }\n const days = Math.floor(hours / 24);\n const remainingHours = hours % 24;\n return remainingHours ? `${days}d ${remainingHours}h` : `${days}d`;\n}\n\nfunction formatResetText(window: RateLimitWindow): string | null {\n if (window.resetsAt) {\n return formatRelativeTime(window.resetsAt) ?? window.resetsAt;\n }\n const durationText = formatDurationFromSeconds(window.resetsInSeconds);\n if (!durationText) return null;\n if (durationText === \"now\") return \"now\";\n return `in ${durationText}`;\n}\n\ntype RateLimitRow = {\n label: string;\n used: string;\n reset: string | null;\n};\n\nfunction formatWindowUsage(window: RateLimitWindow): RateLimitRow | null {\n const label = formatWindowLabel(window.windowMinutes) ?? \"window\";\n const usedPercent =\n typeof window.usedPercent === \"number\" && Number.isFinite(window.usedPercent)\n ? `${Math.round(Math.max(0, Math.min(100, window.usedPercent)))}%`\n : \"n/a\";\n const resetText = formatResetText(window);\n return {\n label,\n used: usedPercent,\n reset: resetText ? `reset ${resetText}` : null,\n };\n}\n\ntype UsageInfo = {\n summary: string;\n rows: RateLimitRow[] | null;\n usageSummary: RateLimitUsageSummary;\n};\n\ntype RateLimitUsageKey = \"primary\" | \"secondary\";\n\ntype RateLimitUsageSummary = {\n windowKey: RateLimitUsageKey;\n usagePercent: number;\n hasUsage: boolean;\n resetsInSeconds: number | null;\n windowMinutes: number | null;\n};\n\nconst EMPTY_USAGE_SUMMARY: RateLimitUsageSummary = {\n windowKey: \"primary\",\n usagePercent: 0,\n hasUsage: false,\n resetsInSeconds: null,\n windowMinutes: null,\n};\n\nfunction toFiniteNumberOrNull(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction summarizeRateLimitSnapshot(snapshot: RateLimitSnapshot | null | undefined): RateLimitUsageSummary {\n if (!snapshot) {\n return { ...EMPTY_USAGE_SUMMARY };\n }\n\n const entries: Array<{ key: RateLimitUsageKey; window: RateLimitWindow | undefined }> = [\n { key: \"primary\", window: snapshot.primary },\n { key: \"secondary\", window: snapshot.secondary },\n ];\n\n let summary: RateLimitUsageSummary = { ...EMPTY_USAGE_SUMMARY };\n let initialized = false;\n\n for (const entry of entries) {\n if (!entry.window) {\n continue;\n }\n\n const usageValueRaw = toFiniteNumberOrNull(entry.window.usedPercent);\n const usageValue = usageValueRaw === null ? 0 : Math.max(0, Math.min(100, usageValueRaw));\n const hasUsage = usageValueRaw !== null;\n const resetsInSeconds = toFiniteNumberOrNull(entry.window.resetsInSeconds);\n const windowMinutes = toFiniteNumberOrNull(entry.window.windowMinutes);\n\n if (!initialized) {\n initialized = true;\n summary = {\n windowKey: entry.key,\n usagePercent: usageValue,\n hasUsage,\n resetsInSeconds,\n windowMinutes,\n };\n continue;\n }\n\n if (hasUsage && summary.hasUsage && usageValue > summary.usagePercent) {\n summary = {\n windowKey: entry.key,\n usagePercent: usageValue,\n hasUsage,\n resetsInSeconds,\n windowMinutes,\n };\n continue;\n }\n\n if (!hasUsage && !summary.hasUsage && summary.resetsInSeconds !== null) {\n if (resetsInSeconds !== null && resetsInSeconds < summary.resetsInSeconds) {\n summary = {\n windowKey: entry.key,\n usagePercent: usageValue,\n hasUsage,\n resetsInSeconds,\n windowMinutes,\n };\n }\n continue;\n }\n\n if (!hasUsage && !summary.hasUsage && summary.resetsInSeconds === null && resetsInSeconds !== null) {\n summary = {\n windowKey: entry.key,\n usagePercent: usageValue,\n hasUsage,\n resetsInSeconds,\n windowMinutes,\n };\n continue;\n }\n\n if (hasUsage && !summary.hasUsage) {\n summary = {\n windowKey: entry.key,\n usagePercent: usageValue,\n hasUsage,\n resetsInSeconds,\n windowMinutes,\n };\n }\n }\n\n return summary;\n}\n\nfunction fallbackUsage(profile: Profile): UsageInfo {\n const usageSummary = summarizeRateLimitSnapshot(profile.rateLimit ?? null);\n if (!profile.isValid) {\n return { summary: \"invalid\", rows: null, usageSummary };\n }\n if (profile.tokenStatus?.requiresUserAction) {\n return { summary: \"auth required\", rows: null, usageSummary };\n }\n return { summary: \"n/a\", rows: null, usageSummary };\n}\n\nasync function resolveProfileUsage(\n manager: ProfileManager,\n profile: Profile,\n codexPath: string,\n): Promise<UsageInfo> {\n if (!profile.isValid || profile.tokenStatus?.requiresUserAction) {\n return fallbackUsage(profile);\n }\n\n try {\n const snapshot = await manager.runWithProfileAuth(profile.name, (env) =>\n fetchRateLimitsViaRpc(env, { codexPath }),\n );\n if (!snapshot) {\n const usageSummary = summarizeRateLimitSnapshot(profile.rateLimit ?? null);\n return { summary: \"n/a\", rows: null, usageSummary };\n }\n const rows: RateLimitRow[] = [];\n if (snapshot.primary) {\n const row = formatWindowUsage(snapshot.primary);\n if (row) rows.push(row);\n }\n if (snapshot.secondary) {\n const row = formatWindowUsage(snapshot.secondary);\n if (row) rows.push(row);\n }\n const maxPercent = maxUsedPercent(snapshot);\n const summary = typeof maxPercent === \"number\"\n ? `${Math.round(maxPercent)}%`\n : \"n/a\";\n return { summary, rows: rows.length > 0 ? rows : null, usageSummary: summarizeRateLimitSnapshot(snapshot) };\n } catch {\n return fallbackUsage(profile);\n }\n}\n\ntype AutoRollCandidate = {\n profile: Profile;\n usageSummary: RateLimitUsageSummary;\n};\n\nfunction compareAutoRollCandidates(a: AutoRollCandidate, b: AutoRollCandidate): number {\n if (a.usageSummary.usagePercent !== b.usageSummary.usagePercent) {\n return a.usageSummary.usagePercent - b.usageSummary.usagePercent;\n }\n const aReset = a.usageSummary.resetsInSeconds ?? Number.POSITIVE_INFINITY;\n const bReset = b.usageSummary.resetsInSeconds ?? Number.POSITIVE_INFINITY;\n if (aReset !== bReset) {\n return aReset - bReset;\n }\n return a.profile.name.localeCompare(b.profile.name);\n}\n\nfunction computeAutoRollCandidate(\n profiles: Profile[],\n usageMap: Map<string, UsageInfo>,\n currentProfileName: string,\n currentSummary: RateLimitUsageSummary,\n switchThreshold: number,\n): AutoRollCandidate | null {\n const candidates = profiles\n .filter(profile => profile.name !== currentProfileName && profile.isValid && !profile.tokenStatus?.requiresUserAction)\n .map(profile => ({\n profile,\n usageSummary: usageMap.get(profile.name)?.usageSummary ?? summarizeRateLimitSnapshot(profile.rateLimit ?? null),\n }));\n\n if (candidates.length === 0) {\n return null;\n }\n\n const belowThreshold = candidates\n .filter(candidate => candidate.usageSummary.hasUsage && candidate.usageSummary.usagePercent < switchThreshold)\n .sort(compareAutoRollCandidates);\n let selected = belowThreshold[0] ?? null;\n\n if (!selected) {\n selected = candidates\n .filter(candidate => candidate.usageSummary.hasUsage)\n .sort(compareAutoRollCandidates)[0] ?? null;\n }\n\n if (!selected) {\n selected = candidates\n .filter(candidate => !candidate.usageSummary.hasUsage)\n .sort((a, b) => {\n const aReset = a.usageSummary.resetsInSeconds ?? Number.POSITIVE_INFINITY;\n const bReset = b.usageSummary.resetsInSeconds ?? Number.POSITIVE_INFINITY;\n if (aReset !== bReset) {\n return aReset - bReset;\n }\n return a.profile.name.localeCompare(b.profile.name);\n })[0] ?? null;\n }\n\n if (!selected) {\n return null;\n }\n\n if (selected.usageSummary.hasUsage && currentSummary.hasUsage) {\n if (selected.usageSummary.usagePercent > currentSummary.usagePercent) {\n return null;\n }\n if (selected.usageSummary.usagePercent === currentSummary.usagePercent) {\n const selectedReset = selected.usageSummary.resetsInSeconds ?? Number.POSITIVE_INFINITY;\n const currentReset = currentSummary.resetsInSeconds ?? Number.POSITIVE_INFINITY;\n if (selectedReset >= currentReset) {\n return null;\n }\n }\n }\n\n return selected;\n}\n\nfunction formatPlan(profile: Profile): string {\n const metadata = profile.metadata;\n if (!metadata) {\n return \"No plan details\";\n }\n const parts: string[] = [];\n if (metadata.planType) {\n parts.push(toTitleCase(metadata.planType));\n }\n const until = metadata.subscription?.activeUntil;\n if (until) {\n const formatted = formatShortDate(until);\n if (formatted) {\n parts.push(`Until ${formatted}`);\n }\n }\n return parts.join(\" · \") || \"No plan details\";\n}\n\nfunction formatAuth(profile: Profile): string {\n const metadata = profile.metadata;\n const relative = formatRelativeTime(metadata?.tokenAuthTime);\n if (relative) return relative;\n if (metadata?.tokenAuthTime) return metadata.tokenAuthTime;\n return \"Not authenticated yet\";\n}\n\nfunction printProfileDetails(profile: Profile, usage?: UsageInfo | null): void {\n const email = profile.email ?? \"Unknown\";\n const plan = formatPlan(profile);\n const orgs = formatOrganizations(profile.metadata?.organizations) ?? \"No organizations\";\n const auth = formatAuth(profile);\n const workspace = profile.workspaceName ?? profile.workspaceId ?? null;\n\n const entries: Array<{ label: string; value: string }> = [\n { label: \"email\", value: email },\n { label: \"plan\", value: plan },\n { label: \"orgs\", value: orgs },\n { label: \"auth\", value: auth },\n ];\n if (workspace) {\n entries.push({ label: \"workspace\", value: workspace });\n }\n const pad = Math.max(...entries.map(entry => entry.label.length));\n for (const entry of entries) {\n console.log(` ${entry.label.padEnd(pad)} : ${entry.value}`);\n }\n\n if (usage) {\n if (usage.rows && usage.rows.length > 0) {\n const labelPad = Math.max(...usage.rows.map(row => row.label.length));\n const usedPad = Math.max(...usage.rows.map(row => row.used.length));\n console.log(` rate limits:`);\n for (const row of usage.rows) {\n const resetText = row.reset ? ` ${row.reset}` : \"\";\n console.log(` ${row.label.padEnd(labelPad)} ${row.used.padStart(usedPad)}${resetText}`);\n }\n return;\n }\n console.log(` rate limits: ${usage.summary}`);\n }\n}\n\nasync function mapWithConcurrency<T, R>(\n items: T[],\n limit: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = new Array(items.length);\n const workerCount = Math.max(1, Math.min(limit, items.length));\n let nextIndex = 0;\n\n const workers = Array.from({ length: workerCount }, async () => {\n while (true) {\n const current = nextIndex++;\n if (current >= items.length) {\n return;\n }\n results[current] = await fn(items[current], current);\n }\n });\n\n await Promise.all(workers);\n return results;\n}\n\nfunction parseAutoRollThreshold(flags: string[], fallbackThreshold: number): number {\n const explicitThreshold = parseNumericFlag(flags, \"--threshold\");\n if (explicitThreshold === null) {\n return fallbackThreshold;\n }\n if (Number.isNaN(explicitThreshold)) {\n throw new Error(\"Invalid --threshold value. Use --threshold=50-100.\");\n }\n if (explicitThreshold < 50 || explicitThreshold > 100) {\n throw new Error(\"Invalid --threshold value. Use a number between 50 and 100.\");\n }\n return Math.round(explicitThreshold);\n}\n\nfunction parseAutoRollIntervalSeconds(flags: string[]): number {\n const explicitInterval = parseIntegerFlag(flags, \"--interval\");\n if (explicitInterval === null) {\n return DEFAULT_AUTOROLL_INTERVAL_SECONDS;\n }\n if (Number.isNaN(explicitInterval) || explicitInterval <= 0) {\n throw new Error(\"Invalid --interval value. Use --interval=<seconds> with a positive integer.\");\n }\n return explicitInterval;\n}\n\nasync function collectUsageMap(\n manager: ProfileManager,\n profiles: Profile[],\n codexPath: string,\n): Promise<Map<string, UsageInfo>> {\n const usageMap = new Map<string, UsageInfo>();\n const limitEnv = Number.parseInt(process.env.CODEXUSE_CLI_USAGE_CONCURRENCY ?? \"3\", 10);\n const limit = Number.isFinite(limitEnv) && limitEnv > 0 ? limitEnv : 3;\n const results = await mapWithConcurrency(profiles, limit, (profile) =>\n resolveProfileUsage(manager, profile, codexPath),\n );\n for (const [index, profile] of profiles.entries()) {\n usageMap.set(profile.name, results[index]);\n }\n return usageMap;\n}\n\nasync function runAutoRollPass(\n manager: ProfileManager,\n options: {\n threshold: number;\n dryRun: boolean;\n },\n): Promise<{ switched: boolean; message: string; source: string | null; target: string | null }> {\n const profiles = await manager.listProfiles();\n if (!profiles.length) {\n return { switched: false, message: \"No profiles found.\", source: null, target: null };\n }\n\n const current = await manager.getCurrentProfile();\n if (!current.name) {\n return { switched: false, message: \"No active profile.\", source: null, target: null };\n }\n\n const codexPath = resolveCodexBinary();\n if (!codexPath) {\n throw new Error(\"Codex CLI binary not found on PATH. Auto-roll requires codex for live rate limits.\");\n }\n\n const usageMap = await collectUsageMap(manager, profiles, codexPath);\n const currentProfile = profiles.find(profile => profile.name === current.name);\n if (!currentProfile) {\n return {\n switched: false,\n message: `Current profile '${current.name}' is missing from saved profiles.`,\n source: current.name,\n target: null,\n };\n }\n\n const currentUsage = usageMap.get(current.name)?.usageSummary ?? summarizeRateLimitSnapshot(currentProfile.rateLimit ?? null);\n if (!currentUsage.hasUsage) {\n return {\n switched: false,\n message: `No live rate-limit usage for '${current.name}'. Skipping auto-roll.`,\n source: current.name,\n target: null,\n };\n }\n\n if (currentUsage.usagePercent < options.threshold) {\n return {\n switched: false,\n message: `'${current.name}' at ${Math.round(currentUsage.usagePercent)}%, below threshold ${options.threshold}%.`,\n source: current.name,\n target: null,\n };\n }\n\n const candidate = computeAutoRollCandidate(\n profiles,\n usageMap,\n current.name,\n currentUsage,\n options.threshold,\n );\n if (!candidate) {\n return {\n switched: false,\n message: `No eligible profile to switch from '${current.name}' at ${Math.round(currentUsage.usagePercent)}%.`,\n source: current.name,\n target: null,\n };\n }\n\n const candidateUsage = candidate.usageSummary.hasUsage ? `${Math.round(candidate.usageSummary.usagePercent)}%` : \"n/a\";\n if (options.dryRun) {\n return {\n switched: false,\n message: `[dry-run] Would switch '${current.name}' (${Math.round(currentUsage.usagePercent)}%) -> '${candidate.profile.name}' (${candidateUsage}).`,\n source: current.name,\n target: candidate.profile.name,\n };\n }\n\n await manager.switchToProfile(candidate.profile.name);\n return {\n switched: true,\n message: `Auto-rolled '${current.name}' (${Math.round(currentUsage.usagePercent)}%) -> '${candidate.profile.name}' (${candidateUsage}).`,\n source: current.name,\n target: candidate.profile.name,\n };\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nasync function handleProfile(args: string[]): Promise<void> {\n const flags = args.filter(arg => arg.startsWith(\"-\"));\n const params = stripFlags(args);\n const sub = params[0];\n\n if (!sub || hasFlag(flags, \"--help\") || hasFlag(flags, \"-h\")) {\n printHelp();\n return;\n }\n\n const manager = new ProfileManager();\n\n switch (sub) {\n case \"list\": {\n const profiles = await manager.listProfiles();\n const current = await manager.getCurrentProfile();\n if (!profiles.length) {\n console.log(\"No profiles found.\");\n return;\n }\n const compact = hasFlag(flags, \"--compact\");\n const withUsage = !hasFlag(flags, \"--no-usage\");\n let usageMap: Map<string, UsageInfo> | null = null;\n if (withUsage) {\n const codexPath = resolveCodexBinary();\n if (!codexPath) {\n usageMap = new Map();\n for (const profile of profiles) {\n usageMap.set(profile.name, {\n summary: \"codex cli missing\",\n rows: null,\n usageSummary: summarizeRateLimitSnapshot(profile.rateLimit ?? null),\n });\n }\n } else {\n usageMap = await collectUsageMap(manager, profiles, codexPath);\n }\n }\n for (const [index, profile] of profiles.entries()) {\n const marker = current.name === profile.name ? \"*\" : \" \";\n const label = formatProfileLabel(profile.name, profile.displayName);\n if (index > 0) {\n console.log(\"\");\n }\n const activeLabel = current.name === profile.name ? \" (active)\" : \"\";\n console.log(`${marker} ${label}${activeLabel}`);\n if (compact) continue;\n const usage = usageMap?.get(profile.name) ?? null;\n printProfileDetails(profile, usage);\n }\n return;\n }\n case \"current\": {\n const current = await manager.getCurrentProfile();\n if (!current.name) {\n console.log(\"No active profile.\");\n return;\n }\n console.log(current.name);\n return;\n }\n case \"add\": {\n const name = params[1];\n if (!name) {\n throw new Error(\"Profile name is required.\");\n }\n await assertProfileCreationAllowed(manager);\n if (!hasFlag(flags, \"--skip-login\")) {\n const loginMode = resolveLoginMode(parseLoginMode(flags));\n await runCodexLogin(loginMode);\n }\n const profile = await manager.createProfile(name);\n const label = profile ? formatProfileLabel(profile.name, profile.displayName) : name;\n console.log(`Profile created: ${label}`);\n return;\n }\n case \"refresh\": {\n const name = params[1];\n if (!name) {\n throw new Error(\"Profile name is required.\");\n }\n if (!hasFlag(flags, \"--skip-login\")) {\n const loginMode = resolveLoginMode(parseLoginMode(flags));\n await runCodexLogin(loginMode);\n }\n const profile = await manager.refreshProfileAuth(name);\n const label = formatProfileLabel(profile.name, profile.displayName);\n console.log(`Profile refreshed: ${label}`);\n return;\n }\n case \"switch\": {\n const name = params[1];\n if (!name) {\n throw new Error(\"Profile name is required.\");\n }\n await manager.switchToProfile(name);\n console.log(`Switched to profile: ${name}`);\n return;\n }\n case \"autoroll\":\n case \"auto-roll\": {\n const watch = hasFlag(flags, \"--watch\");\n const dryRun = hasFlag(flags, \"--dry-run\");\n const settings = await getStoredAutoRollSettings().catch(() => null);\n const fallbackThreshold =\n typeof settings?.switchThreshold === \"number\" && Number.isFinite(settings.switchThreshold)\n ? Math.round(settings.switchThreshold)\n : DEFAULT_AUTOROLL_THRESHOLD;\n const threshold = parseAutoRollThreshold(flags, fallbackThreshold);\n const intervalSeconds = parseAutoRollIntervalSeconds(flags);\n\n if (watch) {\n console.log(`Auto-roll watch: threshold ${threshold}% | interval ${intervalSeconds}s${dryRun ? \" | dry-run\" : \"\"}`);\n let stop = false;\n process.on(\"SIGINT\", () => {\n stop = true;\n });\n process.on(\"SIGTERM\", () => {\n stop = true;\n });\n\n while (!stop) {\n const result = await runAutoRollPass(manager, { threshold, dryRun });\n console.log(result.message);\n if (stop) {\n break;\n }\n await delay(intervalSeconds * 1000);\n }\n console.log(\"Auto-roll watch stopped.\");\n return;\n }\n\n const result = await runAutoRollPass(manager, { threshold, dryRun });\n console.log(result.message);\n return;\n }\n case \"delete\": {\n const name = params[1];\n if (!name) {\n throw new Error(\"Profile name is required.\");\n }\n await manager.deleteProfile(name);\n console.log(`Profile deleted: ${name}`);\n return;\n }\n case \"rename\": {\n const from = params[1];\n const to = params[2];\n if (!from || !to) {\n throw new Error(\"Old and new profile names are required.\");\n }\n await manager.renameProfile(from, to);\n console.log(`Profile renamed: ${from} -> ${to}`);\n return;\n }\n default:\n printHelp();\n return;\n }\n}\n\nasync function handleLicense(args: string[]): Promise<void> {\n const flags = args.filter(arg => arg.startsWith(\"-\"));\n const params = stripFlags(args);\n const sub = params[0];\n\n if (!sub || hasFlag(flags, \"--help\") || hasFlag(flags, \"-h\")) {\n printHelp();\n return;\n }\n\n switch (sub) {\n case \"status\": {\n const forceRefresh = hasFlag(flags, \"--refresh\");\n const status = await licenseService.getStatus({ forceRefresh });\n console.log(`Tier: ${status.tier}`);\n console.log(`State: ${status.state}`);\n if (status.profileLimit !== null) {\n console.log(`Profile limit: ${status.profileLimit}`);\n }\n if (status.profilesRemaining !== null) {\n console.log(`Profiles remaining: ${status.profilesRemaining}`);\n }\n if (status.purchaseEmail) {\n console.log(`Email: ${status.purchaseEmail}`);\n }\n if (status.maskedLicenseKey) {\n console.log(`License: ${status.maskedLicenseKey}`);\n }\n if (status.message) {\n console.log(`Message: ${status.message}`);\n }\n if (status.error) {\n console.log(`Error: ${status.error}`);\n }\n return;\n }\n case \"activate\": {\n const key = params[1];\n if (!key) {\n throw new Error(\"License key is required.\");\n }\n const status = await licenseService.activate(key);\n console.log(status.message ?? \"License activated.\");\n return;\n }\n default:\n printHelp();\n return;\n }\n}\n\nfunction printSyncResult(result: Awaited<ReturnType<typeof pushCloudSync>>): void {\n console.log(result.message);\n if (result.localUpdatedAt) {\n console.log(`Local snapshot: ${result.localUpdatedAt}`);\n }\n if (result.remoteUpdatedAt) {\n console.log(`Remote snapshot: ${result.remoteUpdatedAt}`);\n }\n}\n\nasync function handleSync(args: string[]): Promise<void> {\n const flags = args.filter(arg => arg.startsWith(\"-\"));\n const params = stripFlags(args);\n const sub = params[0];\n\n if (!sub || hasFlag(flags, \"--help\") || hasFlag(flags, \"-h\")) {\n printHelp();\n return;\n }\n\n switch (sub) {\n case \"status\": {\n const status = await getCloudSyncStatus();\n console.log(`Endpoint: ${status.endpoint}`);\n console.log(`Can sync: ${status.canSync ? \"yes\" : \"no\"}`);\n console.log(`Has key: ${status.hasLicenseKey ? \"yes\" : \"no\"}`);\n if (status.licenseState) {\n console.log(`License state: ${status.licenseState}`);\n }\n if (status.reason) {\n console.log(`Reason: ${status.reason}`);\n }\n if (status.remoteUpdatedAt) {\n console.log(`Remote snapshot: ${status.remoteUpdatedAt}`);\n }\n if (status.lastPushAt) {\n console.log(`Last push: ${status.lastPushAt}`);\n }\n if (status.lastPullAt) {\n console.log(`Last pull: ${status.lastPullAt}`);\n }\n if (status.lastError) {\n console.log(`Last error: ${status.lastError}`);\n }\n return;\n }\n case \"pull\": {\n const result = await pullCloudSync();\n printSyncResult(result);\n if (result.status === \"error\") {\n process.exitCode = 1;\n }\n return;\n }\n case \"push\": {\n const result = await pushCloudSync();\n printSyncResult(result);\n if (result.status === \"error\") {\n process.exitCode = 1;\n }\n return;\n }\n default:\n printHelp();\n return;\n }\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n\n if (args.length === 0) {\n printHelp();\n return;\n }\n\n if (args[0]?.startsWith(\"-\") && (hasFlag(args, \"--help\") || hasFlag(args, \"-h\"))) {\n printHelp();\n return;\n }\n\n if (args[0]?.startsWith(\"-\") && (hasFlag(args, \"--version\") || hasFlag(args, \"-v\"))) {\n console.log(VERSION);\n return;\n }\n\n const command = args[0];\n const rest = args.slice(1);\n\n switch (command) {\n case \"profile\":\n await ensureCliStorageReady();\n await handleProfile(rest);\n return;\n case \"license\":\n await ensureCliStorageReady();\n await handleLicense(rest);\n return;\n case \"sync\":\n await ensureCliStorageReady();\n await handleSync(rest);\n return;\n case \"daemon\":\n await ensureCliStorageReady();\n await handleDaemonCommand(rest, VERSION);\n return;\n default:\n printHelp();\n return;\n }\n}\n\nmain().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n process.exitCode = 1;\n});\n"],"mappings":"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","names":["import_path","os","path","fs","asString","isRecord","asString","isRecord","asString","fs","path","import_node_crypto","import_node_fs","import_node_path","path","crypto","fs","offer","crypto","fallbackStored","fallback","import_node_fs","import_node_path","isRecord","isRecord","import_promises","import_node_path","import_toml","import_node_path","import_node_fs","import_node_path","path","isRecord","path","path","normalizeLineEndings","normalizeLineEndings","normalizeLineEndings","isRecord","path","fs","import_node_child_process","import_node_fs","import_node_path","ENV_HINTS","fileExists","path","stat","import_node_child_process","import_node_fs","import_node_os","import_node_path","REFRESH_TOKEN_REDEEMED_SNIPPET","parseTimestamp","fs","path","os","readline","import_node_fs","import_node_path","import_node_os","isRecord","asString","resolveHomeDir","os","path","fs","import_node_path","import_node_child_process","import_node_readline","import_node_path","import_path","path","isRecord","asString","path","readline","handled","import_node_path","import_promises","import_node_crypto","import_node_fs","import_node_path","import_node_child_process","import_node_util","import_node_child_process","execFileAsync","path","fs","fileExists","path","fs","import_node_crypto","import_promises","import_node_path","asString","asRecord","asString","response","path","fs","path","hasFlag","stripFlags","result"]}
|
|
1
|
+
{"version":3,"sources":["../../../lib/profile-manager.ts","../../../lib/auto-roll-settings.ts","../../../lib/app-state.ts","../../../lib/chat-scrollback.ts","../../../lib/commit-message-prompt.ts","../../../lib/codex-settings.ts","../../../lib/logger.ts","../../../lib/license-service.ts","../../../lib/license-secret.ts","../../../lib/offer-config.ts","../../../lib/cloud-sync-service.ts","../../../lib/cloud-sync-types.ts","../../../lib/type-guards.ts","../../../lib/cloud-sync-client.ts","../../../lib/codex-config.ts","../../../lib/codex-config-metadata.ts","../../../lib/codex-cli.ts","../../../lib/errors.ts","../../../lib/license-guard.ts","../src/codex-cli.ts","../../../lib/codex-rpc.ts","../../../lib/rate-limit-notifier.ts","../../../lib/storage-migration-v1.ts","../../../lib/legacy-localstorage-keys.ts","../src/daemon.ts","../../../lib/codex-app-server.ts","../../../lib/apps-list-rpc.ts","../../../lib/cli-env.ts","../../../lib/workspace-parity-store.ts","../../../lib/git/git-service.ts","../../../lib/git/git-cli.ts","../../../electron/telegram-bridge.ts","../../../lib/retryable-turn-error.ts","../src/index.ts"],"sourcesContent":["import { promises as fs } from 'fs';\nimport path from 'path';\nimport { join } from 'path';\nimport { parse, stringify } from '@iarna/toml';\nimport {\n Profile,\n ProfileData,\n ActiveAuth,\n ProfileMetadata,\n OrganizationInfo,\n SubscriptionInfo,\n TokenAlert,\n TokenIssue,\n TokenStatus,\n} from './types';\nimport type { CloudSyncProfileRecord } from './cloud-sync-types';\nimport { getLastProfileName, persistLastProfileName } from './codex-settings';\nimport { getAppState, getUserDataDir, updateAppState, type ProfileRecordState } from './app-state';\nimport { logError, logWarn } from './logger';\n\nconst TOKEN_EXPIRING_SOON_WINDOW_MS = 15 * 60 * 1000;\nexport const REFRESH_TOKEN_REDEEMED_SNIPPET = 'refresh token was already used';\nexport const REFRESH_TOKEN_REDEEMED_REASON =\n 'Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.';\nconst AUTH_BACKUP_MISSING_MARKER = '__codexuse_missing_auth__';\nconst DEFAULT_WORKSPACE_ID = '__default__';\nlet globalAuthSwapLock: Promise<void> = Promise.resolve();\n\nexport function detectRefreshTokenRedeemedMessage(output: string | Buffer | null | undefined): string | null {\n if (!output) {\n return null;\n }\n\n const text = output.toString();\n if (!text) {\n return null;\n }\n\n const normalized = text\n .toLowerCase()\n .replace(/\\s+/g, ' ');\n if (!normalized.includes(REFRESH_TOKEN_REDEEMED_SNIPPET)) {\n return null;\n }\n\n const trimmed = text.trim();\n return trimmed.length > 0 ? trimmed : REFRESH_TOKEN_REDEEMED_REASON;\n}\n\ntype ProfileRecord = {\n name: string;\n displayName: string | null;\n data: ProfileData;\n metadata?: ProfileMetadata;\n accountId: string | null;\n workspaceId: string | null;\n workspaceName: string | null;\n email: string | null;\n authMethod: string | null;\n createdAt: string | null;\n updatedAt: string | null;\n};\n\nexport class ProfileManager {\n private codexDir: string;\n private profileHomesRoot: string;\n private activeAuth: string;\n private activeAuthBackup: string;\n private lastActiveAuthErrorSignature: string | null;\n constructor() {\n const homeDir = process.env.HOME || process.env.USERPROFILE || '';\n this.codexDir = join(homeDir, '.codex');\n this.profileHomesRoot = join(getUserDataDir(), 'profile-homes');\n this.activeAuth = join(this.codexDir, 'auth.json');\n this.activeAuthBackup = `${this.activeAuth}.swap`;\n this.lastActiveAuthErrorSignature = null;\n }\n\n private computeExpiryIso(data: ProfileData | null | undefined): string | undefined {\n if (!data) {\n return undefined;\n }\n if (typeof data.expired === 'string' && data.expired.trim()) {\n const parsed = Date.parse(data.expired);\n if (!Number.isNaN(parsed)) {\n return new Date(parsed).toISOString();\n }\n }\n const expiresIn = typeof data.expires_in === 'number' && Number.isFinite(data.expires_in)\n ? data.expires_in\n : undefined;\n const issuedMs =\n typeof data.timestamp === 'number' && Number.isFinite(data.timestamp)\n ? data.timestamp\n : undefined;\n const issuedAt = issuedMs ? issuedMs : undefined;\n const baseMs = issuedAt ?? Date.now();\n if (expiresIn && expiresIn > 0) {\n return new Date(baseMs + expiresIn * 1000).toISOString();\n }\n return undefined;\n }\n\n private normalizeProfileName(name: string): string {\n if (typeof name !== 'string') {\n throw new Error('Profile name is required');\n }\n\n const trimmed = name.trim();\n if (!trimmed) {\n throw new Error('Profile name must not be empty.');\n }\n\n if (trimmed === '.' || trimmed === '..') {\n throw new Error(`Profile name '${name}' is not allowed.`);\n }\n\n if (/[\\\\/]/.test(trimmed)) {\n throw new Error(\"Profile name cannot contain path separators.\");\n }\n\n if (trimmed.includes('\\0')) {\n throw new Error('Profile name contains invalid characters.');\n }\n\n return trimmed;\n }\n\n private isNotFoundError(error: unknown): boolean {\n return Boolean(\n error &&\n typeof error === 'object' &&\n 'code' in error &&\n (error as NodeJS.ErrnoException).code === 'ENOENT',\n );\n }\n\n private async readPreferredProfileName(): Promise<string | null> {\n try {\n return await getLastProfileName();\n } catch (error) {\n logWarn('Failed to read preferred profile name:', error);\n return null;\n }\n }\n\n private async persistPreferredProfileName(name: string | null): Promise<void> {\n try {\n await persistLastProfileName(name);\n } catch (error) {\n logWarn('Failed to persist preferred profile name:', error);\n }\n }\n\n private toStateRecord(record: ProfileRecord): ProfileRecordState {\n return {\n name: record.name,\n displayName: record.displayName ?? null,\n data: record.data,\n metadata: record.metadata,\n accountId: record.accountId ?? null,\n workspaceId: record.workspaceId ?? null,\n workspaceName: record.workspaceName ?? null,\n email: record.email ?? null,\n authMethod: record.authMethod ?? null,\n createdAt: record.createdAt ?? null,\n updatedAt: record.updatedAt ?? null,\n };\n }\n\n private fromStateRecord(profileName: string, raw: ProfileRecordState): ProfileRecord | null {\n if (!raw || typeof raw !== 'object') {\n return null;\n }\n\n const dataRaw = raw.data;\n if (!dataRaw || typeof dataRaw !== 'object') {\n return null;\n }\n\n return {\n name: profileName,\n displayName: typeof raw.displayName === 'string' ? raw.displayName : null,\n data: dataRaw as ProfileData,\n metadata: raw.metadata,\n accountId: typeof raw.accountId === 'string' ? raw.accountId : null,\n workspaceId: typeof raw.workspaceId === 'string' ? raw.workspaceId : null,\n workspaceName: typeof raw.workspaceName === 'string' ? raw.workspaceName : null,\n email: typeof raw.email === 'string' ? raw.email : null,\n authMethod: typeof raw.authMethod === 'string' ? raw.authMethod : null,\n createdAt: typeof raw.createdAt === 'string' ? raw.createdAt : null,\n updatedAt: typeof raw.updatedAt === 'string' ? raw.updatedAt : null,\n };\n }\n\n private async readProfilesStateMap(): Promise<Record<string, ProfileRecordState>> {\n const state = await getAppState();\n return { ...(state.profilesByName ?? {}) };\n }\n\n private async writeProfilesStateMap(nextMap: Record<string, ProfileRecordState>): Promise<void> {\n await updateAppState((state) => ({\n ...state,\n profilesByName: nextMap,\n }), { mode: 'replace' });\n }\n\n private async readProfileRecord(profileName: string): Promise<ProfileRecord | null> {\n const map = await this.readProfilesStateMap();\n const raw = map[profileName];\n if (!raw) {\n return null;\n }\n return this.fromStateRecord(profileName, raw);\n }\n\n private async listProfileRecords(): Promise<ProfileRecord[]> {\n const map = await this.readProfilesStateMap();\n const records: ProfileRecord[] = [];\n for (const [profileName, raw] of Object.entries(map)) {\n const record = this.fromStateRecord(profileName, raw);\n if (record) {\n records.push(record);\n }\n }\n return records;\n }\n\n private async writeProfileRecord(record: ProfileRecord): Promise<void> {\n const map = await this.readProfilesStateMap();\n map[record.name] = this.toStateRecord(record);\n await this.writeProfilesStateMap(map);\n }\n\n private async deleteProfileRecord(name: string): Promise<void> {\n const map = await this.readProfilesStateMap();\n if (!Object.prototype.hasOwnProperty.call(map, name)) {\n return;\n }\n delete map[name];\n await this.writeProfilesStateMap(map);\n }\n\n private resolveAuthMethod(data: ProfileData | null | undefined): string {\n const raw = typeof data?.auth_method === 'string' ? data.auth_method.trim().toLowerCase() : '';\n return raw || 'codex-cli';\n }\n\n private async readActiveAuthFile(): Promise<ActiveAuth | null> {\n try {\n const raw = await fs.readFile(this.activeAuth, 'utf8');\n const trimmed = raw.trim();\n if (!trimmed) {\n return null;\n }\n return JSON.parse(trimmed) as ActiveAuth;\n } catch (error) {\n if (this.isNotFoundError(error)) {\n return null;\n }\n const message = error instanceof Error ? error.message : 'unknown error';\n const signature = typeof message === 'string' ? `${message}:${this.activeAuth}` : this.activeAuth;\n if (this.lastActiveAuthErrorSignature !== signature) {\n logWarn('Failed to read active auth file:', error);\n this.lastActiveAuthErrorSignature = signature;\n }\n return null;\n }\n }\n\n private async getActiveAuthAccountId(): Promise<string | undefined> {\n const activeAuth = await this.readActiveAuthFile();\n if (!activeAuth) {\n return undefined;\n }\n return this.getAccountIdFromData(activeAuth);\n }\n\n /**\n * Decode a JWT payload into an object without validating the signature.\n */\n private decodeJwtPayload(token?: string | null): Record<string, unknown> | null {\n if (!token || typeof token !== 'string') {\n return null;\n }\n\n const segments = token.split('.');\n if (segments.length < 2) {\n return null;\n }\n\n try {\n const payload = Buffer.from(segments[1], 'base64url').toString('utf8');\n return JSON.parse(payload);\n } catch {\n return null;\n }\n }\n\n private toIsoStringFromSeconds(seconds?: number): string | undefined {\n if (typeof seconds !== 'number' || Number.isNaN(seconds)) {\n return undefined;\n }\n\n try {\n return new Date(seconds * 1000).toISOString();\n } catch {\n return undefined;\n }\n }\n\n private normalizeEmailCandidate(value: unknown): string | undefined {\n if (typeof value !== 'string') {\n return undefined;\n }\n\n const trimmed = value.trim();\n if (!trimmed || trimmed.includes(' ')) {\n return undefined;\n }\n\n const atIndex = trimmed.indexOf('@');\n if (atIndex <= 0 || atIndex === trimmed.length - 1) {\n return undefined;\n }\n\n const domain = trimmed.slice(atIndex + 1);\n if (!domain || !domain.includes('.')) {\n return undefined;\n }\n\n return trimmed;\n }\n\n private pickFirstEmail(candidates: Array<string | undefined>): string | undefined {\n for (const candidate of candidates) {\n const normalized = this.normalizeEmailCandidate(candidate);\n if (normalized) {\n return normalized;\n }\n }\n return undefined;\n }\n\n private findEmailInObject(value: unknown, seen = new Set<unknown>()): string | undefined {\n if (!value || typeof value !== 'object') {\n return undefined;\n }\n\n if (seen.has(value)) {\n return undefined;\n }\n seen.add(value);\n\n if (Array.isArray(value)) {\n for (const entry of value) {\n const nested = this.findEmailInObject(entry, seen);\n if (nested) {\n return nested;\n }\n }\n return undefined;\n }\n\n for (const [key, entry] of Object.entries(value as Record<string, unknown>)) {\n if (typeof entry === 'string') {\n const normalized = this.normalizeEmailCandidate(entry);\n const lowerKey = key.toLowerCase();\n const keyHintsAtEmail =\n lowerKey.includes('email') ||\n lowerKey.includes('contact') ||\n lowerKey.includes('username') ||\n lowerKey.includes('login');\n\n if (normalized && (keyHintsAtEmail || entry.includes('@'))) {\n return normalized;\n }\n }\n\n if (entry && typeof entry === 'object') {\n const nested = this.findEmailInObject(entry, seen);\n if (nested) {\n return nested;\n }\n }\n }\n\n return undefined;\n }\n\n private resolveProfileEmail(data: ProfileData, metadata?: ProfileMetadata): string | undefined {\n const direct = this.normalizeEmailCandidate(data.email);\n if (direct) {\n return direct;\n }\n\n if (metadata?.email) {\n return metadata.email;\n }\n\n return this.findEmailInObject(data);\n }\n\n private evaluateTokenStatus(data: ProfileData, metadata?: ProfileMetadata): TokenStatus {\n const expiresAt = metadata?.tokenExpiresAt ?? this.computeExpiryIso(data);\n const parsedExpiry = expiresAt ? Date.parse(expiresAt) : Number.NaN;\n const hasExpiry = !Number.isNaN(parsedExpiry);\n const tokenAlert = data.tokenAlert;\n\n if (!data || typeof data !== 'object' || Object.keys(data).length === 0) {\n return {\n state: 'missing',\n reason: 'No authentication data saved for this profile.',\n expiresAt,\n issue: 'auth-missing',\n requiresUserAction: true,\n };\n }\n\n if (tokenAlert?.issue) {\n const reason = typeof tokenAlert.reason === 'string' && tokenAlert.reason.trim().length > 0\n ? tokenAlert.reason.trim()\n : tokenAlert.issue === 'refresh-redeemed'\n ? REFRESH_TOKEN_REDEEMED_REASON\n : 'Authentication needs attention. Re-login this profile.';\n const issue = (tokenAlert.issue as TokenIssue) ?? 'auth-missing';\n return {\n state: 'invalid',\n reason,\n expiresAt,\n issue,\n requiresUserAction: true,\n };\n }\n\n if (!data.access_token) {\n return {\n state: 'missing',\n reason: 'Access token is missing. Re-authenticate with Codex CLI.',\n expiresAt,\n issue: 'access-missing',\n requiresUserAction: true,\n };\n }\n\n if (!this.decodeJwtPayload(data.access_token)) {\n return {\n state: 'invalid',\n reason: 'Access token is corrupted or not a valid JWT.',\n expiresAt,\n issue: 'access-invalid',\n requiresUserAction: true,\n };\n }\n\n const refreshToken = typeof data.refresh_token === 'string' ? data.refresh_token.trim() : '';\n if (!refreshToken) {\n return {\n state: 'missing',\n reason: 'Refresh token is missing. Run Codex login again.',\n expiresAt,\n issue: 'refresh-missing',\n requiresUserAction: true,\n };\n }\n\n if (hasExpiry) {\n const diff = parsedExpiry - Date.now();\n if (diff <= 0) {\n return {\n state: 'expiring',\n reason: 'Access token expired.',\n expiresAt,\n accessTokenExpired: true,\n issue: 'access-expired',\n requiresUserAction: false,\n };\n }\n\n if (diff <= TOKEN_EXPIRING_SOON_WINDOW_MS) {\n return {\n state: 'expiring',\n reason: 'Access token expires soon.',\n expiresAt,\n issue: 'access-expiring',\n requiresUserAction: false,\n };\n }\n }\n\n return {\n state: 'ok',\n expiresAt,\n requiresUserAction: false,\n };\n }\n\n private extractProfileMetadata(data: ProfileData): ProfileMetadata | undefined {\n const idPayload = this.decodeJwtPayload(data.id_token) as Record<string, unknown> | null;\n const accessPayload = this.decodeJwtPayload(data.access_token) as Record<string, unknown> | null;\n\n if (!idPayload && !accessPayload) {\n return undefined;\n }\n\n const authInfo = (idPayload?.['https://api.openai.com/auth'] ??\n accessPayload?.['https://api.openai.com/auth']) as Record<string, unknown> | undefined;\n\n const profileInfo = accessPayload?.['https://api.openai.com/profile'] as Record<string, unknown> | undefined;\n\n const getNumber = (obj: Record<string, unknown> | null | undefined, key: string): number | undefined =>\n typeof obj?.[key] === 'number' ? (obj[key] as number) : undefined;\n\n const getString = (obj: Record<string, unknown> | undefined | null, key: string): string | undefined =>\n typeof obj?.[key] === 'string' ? (obj[key] as string) : undefined;\n\n const exp = getNumber(idPayload, 'exp') ?? getNumber(accessPayload, 'exp');\n const iat = getNumber(idPayload, 'iat') ?? getNumber(accessPayload, 'iat');\n const authTime = getNumber(idPayload, 'auth_time') ?? getNumber(accessPayload, 'auth_time');\n\n const organizationsRaw = Array.isArray(authInfo?.['organizations'])\n ? (authInfo?.['organizations'] as unknown[])\n : undefined;\n\n const organizations = organizationsRaw\n ? organizationsRaw\n .map((org): OrganizationInfo => {\n const record = org as Record<string, unknown> | undefined;\n return {\n id: getString(record, 'id'),\n title: getString(record, 'title'),\n role: getString(record, 'role'),\n isDefault: typeof record?.['is_default'] === 'boolean' ? (record?.['is_default'] as boolean) : undefined,\n };\n })\n .filter(\n org =>\n org.id ||\n org.title ||\n org.role ||\n typeof org.isDefault === 'boolean'\n )\n : undefined;\n\n const groups = Array.isArray(authInfo?.['groups'])\n ? (authInfo?.['groups'] as unknown[]).filter((group): group is string => typeof group === 'string')\n : undefined;\n\n const emailVerified =\n typeof profileInfo?.['email_verified'] === 'boolean'\n ? (profileInfo?.['email_verified'] as boolean)\n : typeof idPayload?.['email_verified'] === 'boolean'\n ? (idPayload?.['email_verified'] as boolean)\n : typeof accessPayload?.['email_verified'] === 'boolean'\n ? (accessPayload?.['email_verified'] as boolean)\n : undefined;\n\n const email =\n this.pickFirstEmail([\n getString(profileInfo, 'email'),\n getString(profileInfo, 'email_address'),\n getString(profileInfo, 'primary_email'),\n getString(profileInfo, 'default_email'),\n getString(profileInfo, 'contact_email'),\n ]) ??\n this.findEmailInObject(profileInfo) ??\n this.pickFirstEmail([\n getString(authInfo, 'user_email'),\n getString(authInfo, 'email'),\n getString(authInfo, 'userEmail'),\n getString(authInfo, 'chatgpt_user_email'),\n ]) ??\n this.findEmailInObject(authInfo) ??\n this.pickFirstEmail([\n getString(idPayload, 'email'),\n getString(idPayload, 'preferred_username'),\n getString(idPayload, 'username'),\n ]) ??\n this.findEmailInObject(idPayload) ??\n this.pickFirstEmail([\n getString(accessPayload, 'email'),\n ]) ??\n this.findEmailInObject(accessPayload);\n\n const subscription: SubscriptionInfo | undefined = authInfo\n ? {\n activeStart: getString(authInfo, 'chatgpt_subscription_active_start'),\n activeUntil: getString(authInfo, 'chatgpt_subscription_active_until'),\n lastChecked: getString(authInfo, 'chatgpt_subscription_last_checked'),\n }\n : undefined;\n\n const planType = getString(authInfo, 'chatgpt_plan_type');\n const chatgptUserId = getString(authInfo, 'chatgpt_user_id');\n const chatgptAccountUserId = getString(authInfo, 'chatgpt_account_user_id');\n const userId =\n getString(authInfo, 'user_id') ??\n chatgptAccountUserId ??\n getString(idPayload ?? undefined, 'sub') ??\n getString(accessPayload ?? undefined, 'sub');\n\n const metadata: ProfileMetadata = {\n email,\n planType,\n subscription,\n organizations,\n groups,\n userId,\n chatgptUserId,\n emailVerified,\n tokenExpiresAt: this.toIsoStringFromSeconds(exp),\n tokenIssuedAt: this.toIsoStringFromSeconds(iat),\n tokenAuthTime: this.toIsoStringFromSeconds(authTime),\n };\n\n const hasMeaningfulData =\n Boolean(metadata.planType) ||\n Boolean(\n metadata.subscription &&\n (metadata.subscription.activeStart ||\n metadata.subscription.activeUntil ||\n metadata.subscription.lastChecked)\n ) ||\n Boolean(metadata.organizations && metadata.organizations.length > 0) ||\n Boolean(metadata.groups && metadata.groups.length > 0) ||\n Boolean(metadata.userId) ||\n Boolean(metadata.chatgptUserId) ||\n Boolean(metadata.email) ||\n typeof metadata.emailVerified === 'boolean' ||\n Boolean(metadata.tokenExpiresAt) ||\n Boolean(metadata.tokenIssuedAt) ||\n Boolean(metadata.tokenAuthTime);\n\n return hasMeaningfulData ? metadata : undefined;\n }\n\n /**\n * Initialize the profile manager and create necessary directories\n */\n async initialize(): Promise<void> {\n this.profileHomesRoot = join(getUserDataDir(), 'profile-homes');\n\n try {\n await fs.mkdir(this.codexDir, { recursive: true });\n } catch (error) {\n logError('Failed to ensure Codex directory exists:', error);\n throw new Error('Failed to initialize profile manager');\n }\n try {\n await fs.mkdir(this.profileHomesRoot, { recursive: true });\n } catch (error) {\n logError('Failed to ensure profile homes directory exists:', error);\n throw new Error('Failed to initialize profile manager');\n }\n\n await this.recoverActiveAuthBackup();\n }\n\n private enqueueAuthSwap<T>(task: () => Promise<T>): Promise<T> {\n const run = globalAuthSwapLock.then(task, task);\n globalAuthSwapLock = run.then(\n () => undefined,\n () => undefined,\n );\n return run;\n }\n\n private async recoverActiveAuthBackup(): Promise<void> {\n let backup: string;\n try {\n backup = await fs.readFile(this.activeAuthBackup, 'utf8');\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn('Failed to inspect active auth backup:', error);\n }\n return;\n }\n\n try {\n if (backup === AUTH_BACKUP_MISSING_MARKER) {\n await fs.rm(this.activeAuth, { force: true });\n } else {\n try {\n await this.writeAtomic(this.activeAuth, backup);\n } catch (error) {\n logWarn('Failed to restore active auth from backup, falling back to direct write:', error);\n try {\n await fs.writeFile(this.activeAuth, backup, 'utf8');\n } catch (fallbackError) {\n logWarn('Direct write failed while restoring active auth backup:', fallbackError);\n }\n }\n }\n } catch (error) {\n logWarn('Failed to restore active auth from backup:', error);\n }\n\n try {\n await fs.rm(this.activeAuthBackup, { force: true });\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn('Failed to remove active auth backup:', error);\n }\n }\n }\n\n private async writeAtomic(filePath: string, contents: string): Promise<void> {\n const tempPath = `${filePath}.tmp`;\n const dir = path.dirname(filePath);\n await fs.mkdir(dir, { recursive: true });\n\n await fs.writeFile(tempPath, contents, 'utf8');\n try {\n await fs.rename(tempPath, filePath);\n } catch (error) {\n // Fall back to writing directly if rename fails for any reason.\n try {\n await fs.writeFile(filePath, contents, 'utf8');\n } catch (writeError) {\n // Surface the original error context to aid debugging.\n const original = error instanceof Error ? error.message : String(error);\n const fallback = writeError instanceof Error ? writeError.message : String(writeError);\n throw new Error(`Atomic write failed (rename: ${original}; direct write: ${fallback})`);\n }\n }\n // Best-effort cleanup of temp file if it still exists.\n try {\n await fs.rm(tempPath, { force: true });\n } catch {\n // ignore cleanup failures\n }\n }\n\n /**\n * Extract account_id from auth data (supports both formats)\n */\n private getAccountIdFromData(data: ProfileData | ActiveAuth): string | undefined {\n if ('account_id' in data && typeof data.account_id === 'string' && data.account_id.trim()) {\n return data.account_id.trim();\n }\n\n if ('tokens' in data && data.tokens && typeof data.tokens === 'object') {\n const accountId = (data.tokens as { account_id?: unknown }).account_id;\n if (typeof accountId === 'string' && accountId.trim()) {\n return accountId.trim();\n }\n }\n\n const projectId =\n 'project_id' in data && typeof (data as ProfileData).project_id === 'string'\n ? (data as ProfileData).project_id?.trim()\n : undefined;\n if (projectId) {\n return projectId;\n }\n\n const email =\n 'email' in data && typeof (data as ProfileData).email === 'string'\n ? (data as ProfileData).email?.trim()\n : undefined;\n return email || undefined;\n }\n\n private resolveWorkspaceIdentity(data: ProfileData | ActiveAuth, metadata?: ProfileMetadata): { id: string; name?: string } {\n const directId =\n 'workspace_id' in data && typeof data.workspace_id === 'string'\n ? data.workspace_id.trim()\n : undefined;\n const directName =\n 'workspace_name' in data && typeof data.workspace_name === 'string'\n ? data.workspace_name.trim()\n : undefined;\n\n if (directId) {\n return { id: directId, name: directName };\n }\n\n const organizations = metadata?.organizations;\n if (organizations && organizations.length > 0) {\n const preferred = organizations.find(org => org.isDefault) ?? organizations[0];\n if (preferred?.id) {\n return { id: preferred.id, name: preferred.title ?? directName };\n }\n }\n\n return { id: DEFAULT_WORKSPACE_ID, name: directName };\n }\n\n private async getProfileRowByName(name: string): Promise<ProfileRecord | undefined> {\n const normalized = this.normalizeProfileName(name);\n const record = await this.readProfileRecord(normalized);\n return record ?? undefined;\n }\n\n private async getProfileRowByAccountId(\n accountId: string,\n options?: { authMethod?: string | null; preferAuthMethod?: string | null },\n ): Promise<ProfileRecord | undefined> {\n const records = await this.listProfileRecords();\n const matches = records.filter(record => {\n const storedAccountId = record.accountId ?? this.getAccountIdFromData(record.data);\n return storedAccountId === accountId;\n });\n\n if (matches.length === 0) {\n return undefined;\n }\n\n const mustMatch = typeof options?.authMethod === 'string' ? options.authMethod.trim().toLowerCase() : null;\n if (mustMatch) {\n return matches.find(record => this.resolveAuthMethod(record.data) === mustMatch);\n }\n\n const prefer = typeof options?.preferAuthMethod === 'string' ? options.preferAuthMethod.trim().toLowerCase() : null;\n if (prefer) {\n return matches.find(record => this.resolveAuthMethod(record.data) === prefer) ?? matches[0];\n }\n\n return matches[0];\n }\n\n private async getProfileRowByAccountAndWorkspace(\n accountId: string,\n workspaceId: string,\n options?: { authMethod?: string | null; preferAuthMethod?: string | null },\n ): Promise<ProfileRecord | undefined> {\n const workspaceKey = workspaceId && workspaceId.trim().length > 0 ? workspaceId.trim() : DEFAULT_WORKSPACE_ID;\n const records = await this.listProfileRecords();\n const matches = records.filter(record => {\n const storedAccountId = record.accountId ?? this.getAccountIdFromData(record.data);\n if (storedAccountId !== accountId) {\n return false;\n }\n const storedWorkspace = record.workspaceId ?? record.data.workspace_id ?? DEFAULT_WORKSPACE_ID;\n return (storedWorkspace && storedWorkspace.trim() ? storedWorkspace.trim() : DEFAULT_WORKSPACE_ID) === workspaceKey;\n });\n\n if (matches.length === 0) {\n return undefined;\n }\n\n const mustMatch = typeof options?.authMethod === 'string' ? options.authMethod.trim().toLowerCase() : null;\n if (mustMatch) {\n return matches.find(record => this.resolveAuthMethod(record.data) === mustMatch);\n }\n\n const prefer = typeof options?.preferAuthMethod === 'string' ? options.preferAuthMethod.trim().toLowerCase() : null;\n if (prefer) {\n return matches.find(record => this.resolveAuthMethod(record.data) === prefer) ?? matches[0];\n }\n\n return matches[0];\n }\n\n private async persistProfileRecord(\n name: string,\n data: ProfileData,\n metadata?: ProfileMetadata,\n options?: { displayName?: string | null },\n ): Promise<void> {\n const resolvedName = this.normalizeProfileName(name);\n const existingRecord = await this.readProfileRecord(resolvedName);\n if (typeof data.auth_method === 'string') {\n data.auth_method = data.auth_method.trim().toLowerCase();\n }\n if (!data.auth_method) {\n data.auth_method = 'codex-cli';\n }\n const resolvedMetadata = metadata ?? this.extractProfileMetadata(data) ?? existingRecord?.metadata;\n const workspace = this.resolveWorkspaceIdentity(data, resolvedMetadata);\n const workspaceId = workspace.id || DEFAULT_WORKSPACE_ID;\n const workspaceName = workspace.name ?? null;\n if (!data.workspace_id) {\n data.workspace_id = workspaceId;\n }\n if (!data.workspace_name && workspaceName) {\n data.workspace_name = workspaceName;\n }\n\n const now = new Date().toISOString();\n const accountId = this.getAccountIdFromData(data) ?? null;\n const resolvedEmail = this.resolveProfileEmail(data, resolvedMetadata) ?? data.email ?? null;\n if (resolvedEmail) {\n data.email = resolvedEmail;\n }\n const createdAt = data.created_at ?? existingRecord?.createdAt ?? now;\n data.created_at = createdAt;\n const updatedAt = data.updated_at ?? now;\n data.updated_at = updatedAt;\n\n const displayName =\n typeof options?.displayName === 'string' && options.displayName.trim().length > 0\n ? options.displayName.trim()\n : existingRecord?.displayName ?? resolvedName;\n\n const record: ProfileRecord = {\n name: resolvedName,\n displayName,\n data,\n metadata: resolvedMetadata,\n accountId,\n workspaceId: data.workspace_id ?? workspaceId,\n workspaceName: data.workspace_name ?? workspaceName,\n email: resolvedEmail ?? null,\n authMethod: typeof data.auth_method === 'string' ? data.auth_method : null,\n createdAt,\n updatedAt,\n };\n\n await fs.mkdir(this.getProfileHomePath(resolvedName), { recursive: true });\n await this.writeProfileRecord(record);\n }\n\n private buildProfileFromRow(row: ProfileRecord): Profile {\n const profile = this.buildProfileFromData(row.name, row.data, {\n displayName: row.displayName ?? undefined,\n email: row.email ?? undefined,\n createdAt: row.createdAt ?? undefined,\n authMethod: row.authMethod ?? undefined,\n accountId: row.accountId ?? undefined,\n workspaceId: row.workspaceId ?? undefined,\n workspaceName: row.workspaceName ?? undefined,\n metadata: row.metadata,\n });\n\n return profile;\n }\n\n private buildProfileFromData(\n name: string,\n data: ProfileData,\n fallback?: {\n displayName?: string;\n email?: string;\n createdAt?: string;\n authMethod?: string;\n accountId?: string;\n projectId?: string;\n workspaceId?: string;\n workspaceName?: string;\n metadata?: ProfileMetadata;\n },\n ): Profile {\n const metadata = fallback?.metadata ?? this.extractProfileMetadata(data);\n const workspace = this.resolveWorkspaceIdentity(data, metadata);\n const workspaceId = workspace.id || fallback?.workspaceId || DEFAULT_WORKSPACE_ID;\n const workspaceName = workspace.name ?? fallback?.workspaceName ?? undefined;\n const email = this.resolveProfileEmail(data, metadata) ?? fallback?.email ?? undefined;\n const tokenStatus = this.evaluateTokenStatus(data, metadata);\n const accountId = this.getAccountIdFromData(data) ?? fallback?.accountId;\n const projectId =\n typeof data.project_id === 'string' && data.project_id.trim().length > 0\n ? data.project_id.trim()\n : fallback?.projectId;\n\n return {\n name,\n displayName: fallback?.displayName ?? name,\n isValid: Boolean(data && Object.keys(data).length > 0),\n accountId,\n projectId,\n workspaceId,\n workspaceName,\n email,\n createdAt: data.created_at ?? fallback?.createdAt ?? undefined,\n authMethod: typeof data.auth_method === 'string'\n ? data.auth_method.trim().toLowerCase()\n : fallback?.authMethod ?? undefined,\n metadata,\n tokenStatus,\n };\n }\n\n private parseTimestamp(value?: string | null): number | null {\n if (typeof value !== 'string' || value.trim() === '') {\n return null;\n }\n\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? null : parsed;\n }\n\n private compareProfilesForPreference(a: Profile, b: Profile): number {\n if (Boolean(a.isValid) !== Boolean(b.isValid)) {\n return a.isValid ? -1 : 1;\n }\n\n const aTimestamp = this.parseTimestamp(a.createdAt ?? null);\n const bTimestamp = this.parseTimestamp(b.createdAt ?? null);\n\n if (aTimestamp !== null || bTimestamp !== null) {\n if (aTimestamp !== null && bTimestamp !== null) {\n if (aTimestamp > bTimestamp) {\n return -1;\n }\n if (aTimestamp < bTimestamp) {\n return 1;\n }\n } else if (aTimestamp !== null) {\n return -1;\n } else {\n return 1;\n }\n }\n\n return a.name.localeCompare(b.name);\n }\n\n private selectPreferredProfile(profiles: Profile[]): Profile {\n if (profiles.length <= 1) {\n return profiles[0];\n }\n\n return profiles\n .slice()\n .sort((a, b) => this.compareProfilesForPreference(a, b))[0];\n }\n\n /**\n * Convert profile data to Codex's expected format\n */\n private convertToCodexFormat(data: ProfileData): ActiveAuth {\n // Check if data is already in Codex format\n if ('tokens' in data) {\n return data as ActiveAuth;\n }\n\n // Convert flat structure to nested Codex format.\n // Keep existing refresh metadata if present; never forge it.\n const lastRefresh = typeof data.last_refresh === 'string' ? data.last_refresh.trim() : '';\n let normalizedLastRefresh = lastRefresh.length > 0 ? lastRefresh : undefined;\n if (!normalizedLastRefresh) {\n const accessPayload = this.decodeJwtPayload(data.access_token);\n const tokenIssuedAt = typeof accessPayload?.iat === 'number'\n ? this.toIsoStringFromSeconds(accessPayload.iat)\n : undefined;\n if (tokenIssuedAt) {\n normalizedLastRefresh = tokenIssuedAt;\n }\n }\n if (!normalizedLastRefresh) {\n const createdAt = typeof data.created_at === 'string' ? data.created_at.trim() : '';\n if (createdAt) {\n normalizedLastRefresh = createdAt;\n }\n }\n const codexAuth: ActiveAuth = {\n OPENAI_API_KEY: null,\n tokens: {\n id_token: data.id_token,\n access_token: data.access_token,\n refresh_token: data.refresh_token,\n account_id: data.account_id,\n ...(normalizedLastRefresh ? { last_refresh: normalizedLastRefresh } : {}),\n },\n };\n if (normalizedLastRefresh) {\n codexAuth.last_refresh = normalizedLastRefresh;\n }\n return codexAuth;\n }\n\n /**\n * Normalize Codex auth data to flat profile format\n */\n private normalizeProfileData(data: ActiveAuth): ProfileData {\n // If data is already in flat format, return as-is\n if ('id_token' in data) {\n return data as ProfileData;\n }\n\n // Convert nested Codex format to flat\n const tokens = data.tokens || {};\n const profile: ProfileData = {\n id_token: tokens.id_token,\n access_token: tokens.access_token,\n refresh_token: tokens.refresh_token,\n account_id: tokens.account_id,\n };\n const tokenLastRefresh = typeof tokens.last_refresh === 'string' ? tokens.last_refresh.trim() : '';\n const rootLastRefresh = typeof data.last_refresh === 'string' ? data.last_refresh.trim() : '';\n const normalizedLastRefresh = tokenLastRefresh || rootLastRefresh;\n if (normalizedLastRefresh) {\n profile.last_refresh = normalizedLastRefresh;\n }\n\n if (data.email) {\n profile.email = data.email;\n }\n\n return profile;\n }\n\n private mergeProfileRecords(existing: ProfileData, incoming: ProfileData): {\n profile: ProfileData;\n metadata?: ProfileMetadata;\n } {\n const merged: ProfileData = {\n ...existing,\n ...incoming,\n created_at: existing.created_at ?? incoming.created_at ?? new Date().toISOString(),\n };\n\n if (typeof merged.auth_method === 'string') {\n merged.auth_method = merged.auth_method.trim().toLowerCase();\n }\n if (!merged.auth_method) {\n merged.auth_method = 'codex-cli';\n }\n\n const metadata = this.extractProfileMetadata(merged);\n const resolvedEmail = this.resolveProfileEmail(merged, metadata);\n\n if (resolvedEmail) {\n merged.email = resolvedEmail;\n }\n\n const workspace = this.resolveWorkspaceIdentity(merged, metadata);\n if (!merged.workspace_id) {\n merged.workspace_id = workspace.id || existing.workspace_id || DEFAULT_WORKSPACE_ID;\n }\n if (!merged.workspace_name) {\n merged.workspace_name = workspace.name ?? existing.workspace_name;\n }\n\n if (this.hasTokenChanges(existing, incoming)) {\n delete merged.tokenAlert;\n }\n\n return { profile: merged, metadata };\n }\n\n private hasTokenChanges(existing: ProfileData, incoming: ProfileData): boolean {\n const tokenKeys: Array<keyof ProfileData> = [\n 'id_token',\n 'access_token',\n 'refresh_token',\n 'last_refresh',\n 'account_id',\n 'workspace_id',\n ];\n\n return tokenKeys.some(key => {\n const nextValue = incoming[key];\n if (typeof nextValue !== 'string' || nextValue.length === 0) {\n return false;\n }\n return nextValue !== existing[key];\n });\n }\n\n async flagAuthIssue(\n name: string,\n issue: TokenIssue,\n reason?: string,\n options?: { observedAt?: string },\n ): Promise<void> {\n await this.initialize();\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n logWarn(`Cannot flag auth issue '${issue}' for missing profile '${profileName}'.`);\n return;\n }\n\n const observedAt = options?.observedAt ? Date.parse(options.observedAt) : null;\n const updatedAt = record.updatedAt ? Date.parse(record.updatedAt) : null;\n if (observedAt !== null && updatedAt !== null && observedAt <= updatedAt) {\n return;\n }\n\n const data: ProfileData = record.data;\n\n const trimmedReason = typeof reason === 'string' && reason.trim().length > 0 ? reason.trim() : undefined;\n const normalized = trimmedReason?.toLowerCase() ?? '';\n const storedReason = issue === 'refresh-redeemed'\n ? (normalized.includes(REFRESH_TOKEN_REDEEMED_SNIPPET)\n ? REFRESH_TOKEN_REDEEMED_REASON\n : trimmedReason ?? REFRESH_TOKEN_REDEEMED_REASON)\n : trimmedReason;\n const alert: TokenAlert = {\n issue,\n reason: storedReason,\n recordedAt: new Date().toISOString(),\n };\n\n data.tokenAlert = alert;\n\n try {\n const metadata = this.extractProfileMetadata(data);\n await this.persistProfileRecord(profileName, data, metadata);\n } catch (error) {\n logError(`Failed to persist token alert for profile '${profileName}':`, error);\n }\n }\n\n async flagRefreshTokenRedeemed(name: string, reason?: string, options?: { observedAt?: string }): Promise<void> {\n await this.flagAuthIssue(name, 'refresh-redeemed', reason, options);\n }\n\n private async syncProfileTokensFromActiveAuth(\n profileName: string,\n baselineProfile: ProfileData,\n authPath?: string,\n ): Promise<void> {\n const targetPath = authPath ?? this.activeAuth;\n try {\n const authRaw = await fs.readFile(targetPath, 'utf8');\n await this.syncProfileTokensFromAuthContent(profileName, baselineProfile, authRaw);\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to read Codex auth for '${profileName}' while syncing tokens:`, error);\n }\n }\n }\n\n private async syncProfileTokensFromAuthContent(\n profileName: string,\n baselineProfile: ProfileData,\n authContent: string,\n ): Promise<void> {\n let activeAuth: ActiveAuth;\n try {\n activeAuth = JSON.parse(authContent) as ActiveAuth;\n } catch (error) {\n logWarn(`Failed to parse Codex auth while syncing tokens for '${profileName}':`, error);\n return;\n }\n\n const normalized = this.normalizeProfileData(activeAuth);\n const metadata = this.extractProfileMetadata(normalized);\n const workspace = this.resolveWorkspaceIdentity(normalized, metadata);\n normalized.workspace_id = normalized.workspace_id ?? workspace.id ?? DEFAULT_WORKSPACE_ID;\n if (workspace.name) {\n normalized.workspace_name = normalized.workspace_name ?? workspace.name;\n }\n const hasTokens =\n typeof normalized.id_token === 'string' ||\n typeof normalized.access_token === 'string' ||\n typeof normalized.refresh_token === 'string';\n\n if (!hasTokens) {\n return;\n }\n\n let existing = baselineProfile;\n const latestRow = await this.getProfileRowByName(profileName);\n if (latestRow) {\n existing = latestRow.data;\n }\n\n const existingAccountId = this.getAccountIdFromData(existing);\n const newAccountId = this.getAccountIdFromData(normalized);\n\n if (existingAccountId && newAccountId && existingAccountId !== newAccountId) {\n logWarn(\n `Skipped syncing tokens for profile '${profileName}' because Codex auth switched to account '${newAccountId}'.`,\n );\n return;\n }\n\n if (!this.hasTokenChanges(existing, normalized)) {\n return;\n }\n\n const { profile: merged, metadata: mergedMetadata } = this.mergeProfileRecords(existing, normalized);\n\n try {\n await this.persistProfileRecord(profileName, merged, mergedMetadata);\n } catch (error) {\n logError(`Failed to persist refreshed tokens for profile '${profileName}':`, error);\n }\n }\n\n private async copyCodexConfig(targetCodexHome: string): Promise<void> {\n const candidates = ['config.toml', 'config.json', 'config.yaml', 'config.yml'];\n for (const file of candidates) {\n const source = join(this.codexDir, file);\n const destination = join(targetCodexHome, file);\n try {\n await fs.copyFile(source, destination);\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to copy Codex config '${file}' to profile home:`, error);\n }\n }\n }\n }\n\n private getProfileHomePath(profileName: string): string {\n return join(this.profileHomesRoot, profileName);\n }\n\n private ensureTrailingNewline(content: string): string {\n return content.endsWith('\\n') ? content : `${content}\\n`;\n }\n\n private async sanitizeProfileConfig(profileHome: string): Promise<void> {\n const configPath = join(profileHome, 'config.toml');\n let raw: string;\n try {\n raw = await fs.readFile(configPath, 'utf8');\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to read config for profile home '${profileHome}':`, error);\n }\n return;\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = parse(raw) as Record<string, unknown>;\n } catch (error) {\n logWarn(`Failed to parse config.toml for profile home '${profileHome}':`, error);\n return;\n }\n\n if (!Object.prototype.hasOwnProperty.call(parsed, 'model_reasoning_effort')) {\n return;\n }\n\n delete parsed['model_reasoning_effort'];\n const sanitized = this.ensureTrailingNewline(stringify(parsed as Record<string, unknown>));\n try {\n await fs.writeFile(configPath, sanitized, 'utf8');\n } catch (error) {\n logWarn(`Failed to write sanitized config.toml for profile home '${profileHome}':`, error);\n }\n }\n\n private async prepareProfileHome(profileName: string, authData: ActiveAuth): Promise<string> {\n const profileHome = this.getProfileHomePath(profileName);\n await fs.mkdir(profileHome, { recursive: true });\n const authPath = join(profileHome, 'auth.json');\n await this.writeAtomic(authPath, JSON.stringify(authData, null, 2));\n await this.copyCodexConfig(profileHome);\n await this.sanitizeProfileConfig(profileHome);\n return profileHome;\n }\n\n /**\n * List all available profiles\n */\n async profileExists(name: string): Promise<boolean> {\n await this.initialize();\n const profileName = this.normalizeProfileName(name);\n return Boolean(await this.getProfileRowByName(profileName));\n }\n\n async listProfiles(): Promise<Profile[]> {\n await this.initialize();\n try {\n const records = await this.listProfileRecords();\n return records\n .map(record => this.buildProfileFromRow(record))\n .filter(profile => !profile.authMethod || profile.authMethod === 'codex-cli')\n .sort((a, b) => {\n const aLabel = a.displayName ?? a.name;\n const bLabel = b.displayName ?? b.name;\n const base = aLabel.localeCompare(bLabel);\n return base !== 0 ? base : a.name.localeCompare(b.name);\n });\n } catch (error) {\n logError('Error reading profiles from disk:', error);\n return [];\n }\n }\n\n /**\n * Create a new profile by running codex login\n */\n async createProfile(name: string): Promise<Profile | null> {\n await this.initialize();\n\n const profileName = this.normalizeProfileName(name);\n if (await this.getProfileRowByName(profileName)) {\n throw new Error(`Profile '${profileName}' already exists!`);\n }\n\n let authData: ActiveAuth;\n try {\n const authRaw = await fs.readFile(this.activeAuth, 'utf8');\n authData = JSON.parse(authRaw) as ActiveAuth;\n } catch (error) {\n logError('Error creating profile:', error);\n throw new Error('Failed to create profile. Make sure Codex CLI is installed and you are logged in.');\n }\n\n const normalizedProfile = this.normalizeProfileData(authData);\n normalizedProfile.created_at = normalizedProfile.created_at ?? new Date().toISOString();\n if (typeof normalizedProfile.auth_method === 'string') {\n normalizedProfile.auth_method = normalizedProfile.auth_method.trim().toLowerCase();\n }\n normalizedProfile.auth_method = normalizedProfile.auth_method ?? 'codex-cli';\n\n const metadata = this.extractProfileMetadata(normalizedProfile);\n const workspace = this.resolveWorkspaceIdentity(normalizedProfile, metadata);\n normalizedProfile.workspace_id = normalizedProfile.workspace_id ?? workspace.id ?? DEFAULT_WORKSPACE_ID;\n if (workspace.name) {\n normalizedProfile.workspace_name = normalizedProfile.workspace_name ?? workspace.name;\n }\n\n const accountId = this.getAccountIdFromData(normalizedProfile);\n if (accountId) {\n const requestedWorkspace = normalizedProfile.workspace_id ?? DEFAULT_WORKSPACE_ID;\n const duplicate = await this.getProfileRowByAccountAndWorkspace(accountId, requestedWorkspace, { authMethod: 'codex-cli' });\n if (duplicate) {\n normalizedProfile.workspace_id = `${requestedWorkspace}:${profileName}`;\n normalizedProfile.workspace_name = normalizedProfile.workspace_name ?? profileName;\n }\n }\n\n const resolvedEmail = this.resolveProfileEmail(normalizedProfile, metadata);\n if (resolvedEmail) {\n normalizedProfile.email = resolvedEmail;\n }\n\n try {\n await this.persistProfileRecord(profileName, normalizedProfile, metadata);\n const stored = await this.getProfileRowByName(profileName);\n return stored ? this.buildProfileFromRow(stored) : null;\n } catch (error) {\n logError('Error creating profile:', error);\n throw new Error('Failed to create profile. Make sure Codex CLI is installed and you are logged in.');\n }\n }\n\n /**\n * Switch to a different profile\n */\n async switchToProfile(name: string): Promise<boolean> {\n await this.initialize();\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n throw new Error(`Profile '${profileName}' not found!`);\n }\n\n try {\n const profileData = record.data;\n const codexFormat = this.convertToCodexFormat(profileData);\n await this.writeAtomic(this.activeAuth, JSON.stringify(codexFormat, null, 2));\n await this.persistPreferredProfileName(profileName);\n return true;\n } catch (error) {\n logError('Error switching profile:', error);\n throw new Error('Failed to switch profile');\n }\n }\n\n async refreshProfileAuth(name: string): Promise<Profile> {\n await this.initialize();\n\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n throw new Error(`Profile '${profileName}' not found!`);\n }\n\n const existing: ProfileData = record.data;\n let activeAuth: ActiveAuth;\n try {\n const authContent = await fs.readFile(this.activeAuth, 'utf8');\n activeAuth = JSON.parse(authContent) as ActiveAuth;\n } catch (error) {\n if (this.isNotFoundError(error)) {\n throw new Error('Codex CLI did not produce an auth file. Complete the login before refreshing this profile.');\n }\n logError('Failed to read Codex auth file during refresh:', error);\n throw new Error('Failed to read Codex auth file. Complete the login and try again.');\n }\n\n const normalized = this.normalizeProfileData(activeAuth);\n const existingAccountId = this.getAccountIdFromData(existing);\n const newAccountId = this.getAccountIdFromData(normalized);\n const normalizedMetadata = this.extractProfileMetadata(normalized);\n const normalizedWorkspace = this.resolveWorkspaceIdentity(normalized, normalizedMetadata);\n normalized.workspace_id = normalized.workspace_id ?? normalizedWorkspace.id ?? DEFAULT_WORKSPACE_ID;\n if (normalizedWorkspace.name) {\n normalized.workspace_name = normalized.workspace_name ?? normalizedWorkspace.name;\n }\n\n if (existingAccountId && newAccountId && existingAccountId !== newAccountId) {\n throw new Error(\n `Active Codex login is for account '${newAccountId}', but profile '${profileName}' is tied to '${existingAccountId}'. Create a new profile for the new account instead.`,\n );\n }\n\n if (existingAccountId && normalized.workspace_id) {\n const currentWorkspace = this.resolveWorkspaceIdentity(existing, this.extractProfileMetadata(existing));\n const targetWorkspaceId = normalized.workspace_id;\n const currentWorkspaceId = currentWorkspace.id ?? DEFAULT_WORKSPACE_ID;\n if (targetWorkspaceId !== currentWorkspaceId) {\n const duplicate = await this.getProfileRowByAccountAndWorkspace(existingAccountId, targetWorkspaceId, {\n authMethod: this.resolveAuthMethod(existing),\n });\n if (duplicate && duplicate.name !== profileName) {\n throw new Error(\n `Account is already saved as profile '${duplicate.name}'. Switch to or delete that profile before creating another.`,\n );\n }\n }\n }\n\n const { profile: merged, metadata } = this.mergeProfileRecords(existing, normalized);\n delete merged.tokenAlert;\n\n await this.persistProfileRecord(profileName, merged, metadata);\n const updated = await this.getProfileRowByName(profileName);\n if (!updated) {\n throw new Error('Failed to persist refreshed profile data.');\n }\n\n const profile = this.buildProfileFromRow(updated);\n if (metadata) {\n profile.metadata = metadata;\n profile.tokenStatus = this.evaluateTokenStatus(merged, metadata);\n }\n return profile;\n }\n\n /**\n * Execute an action with a profile's auth injected.\n * Creates an isolated CODEX_HOME with the profile's auth/config, invokes the action\n * with env overrides, then syncs any refreshed tokens back to the profile.\n */\n async runWithProfileAuth<T>(\n name: string,\n action: (env: NodeJS.ProcessEnv) => Promise<T>,\n ): Promise<T> {\n return this.enqueueAuthSwap(async () => {\n await this.initialize();\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n throw new Error(`Profile '${profileName}' not found!`);\n }\n\n let profileData: ProfileData = record.data;\n // If the user's active Codex auth is for the same account and has fresher tokens,\n // sync it into this profile before running actions (prevents avoidable re-logins).\n await this.syncProfileTokensFromActiveAuth(profileName, profileData);\n const updatedRecord = await this.getProfileRowByName(profileName);\n if (updatedRecord) {\n profileData = updatedRecord.data;\n }\n const profileHome = this.getProfileHomePath(profileName);\n await fs.mkdir(profileHome, { recursive: true });\n\n if (profileData.auth_method && profileData.auth_method !== 'codex-cli') {\n throw new Error('Unsupported auth method. Codex CLI profiles only.');\n }\n const codexFormat = this.convertToCodexFormat(profileData);\n await this.prepareProfileHome(profileName, codexFormat);\n const authPath = path.join(profileHome, 'auth.json');\n\n const envOverrides: NodeJS.ProcessEnv = {\n ...process.env,\n HOME: profileHome,\n USERPROFILE: profileHome,\n CODEX_HOME: profileHome,\n };\n\n try {\n return await action(envOverrides);\n } finally {\n let finalAuthContent: string | null = null;\n try {\n finalAuthContent = await fs.readFile(authPath, 'utf8');\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to read isolated auth for '${profileName}' after action:`, error);\n }\n }\n\n try {\n if (finalAuthContent) {\n await this.syncProfileTokensFromAuthContent(profileName, profileData, finalAuthContent);\n } else {\n await this.syncProfileTokensFromActiveAuth(profileName, profileData, authPath);\n }\n } catch (error) {\n logWarn(`Failed to sync refreshed tokens for profile '${profileName}':`, error);\n }\n }\n });\n }\n\n /**\n * Rename a profile\n */\n async renameProfile(oldName: string, newName: string): Promise<boolean> {\n await this.initialize();\n const sourceName = this.normalizeProfileName(oldName);\n const targetName = this.normalizeProfileName(newName);\n\n const existing = await this.getProfileRowByName(sourceName);\n if (!existing) {\n throw new Error(`Profile '${sourceName}' not found!`);\n }\n\n if (await this.getProfileRowByName(targetName)) {\n throw new Error(`Profile '${targetName}' already exists!`);\n }\n\n const preferred = await this.readPreferredProfileName();\n if (preferred && preferred === sourceName) {\n await this.persistPreferredProfileName(targetName);\n }\n\n const oldHome = this.getProfileHomePath(sourceName);\n const newHome = this.getProfileHomePath(targetName);\n try {\n await fs.mkdir(this.profileHomesRoot, { recursive: true });\n await fs.rename(oldHome, newHome);\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to move profile home from '${sourceName}' to '${targetName}':`, error);\n }\n }\n\n try {\n const updatedRecord: ProfileRecord = {\n ...existing,\n name: targetName,\n };\n await this.writeProfileRecord(updatedRecord);\n await this.deleteProfileRecord(sourceName);\n } catch (error) {\n logWarn(`Failed to rewrite profile record after renaming '${sourceName}' to '${targetName}':`, error);\n }\n\n return true;\n }\n\n async updateProfileDisplayName(name: string, displayName: string): Promise<boolean> {\n await this.initialize();\n\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n throw new Error(`Profile '${profileName}' not found!`);\n }\n\n const trimmed = typeof displayName === 'string' ? displayName.trim() : '';\n if (!trimmed) {\n throw new Error('Profile name must not be empty.');\n }\n\n const now = new Date().toISOString();\n record.displayName = trimmed;\n record.updatedAt = now;\n (record.data as ProfileData & { updated_at?: string }).updated_at = now;\n\n await this.writeProfileRecord(record);\n return true;\n }\n\n /**\n * Delete a profile\n */\n async deleteProfile(name: string): Promise<boolean> {\n await this.initialize();\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n throw new Error(`Profile '${profileName}' not found!`);\n }\n const preferred = await this.readPreferredProfileName();\n if (preferred && preferred === profileName) {\n await this.persistPreferredProfileName(null);\n }\n try {\n await fs.rm(this.getProfileHomePath(profileName), { recursive: true, force: true });\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to remove profile home for '${profileName}':`, error);\n }\n }\n await this.deleteProfileRecord(profileName);\n return true;\n }\n\n /**\n * Delete every profile that does not appear in the allow-list.\n * Used to enforce plan limits when local storage was tampered with.\n */\n async deleteProfilesNotIn(allowedNames: Iterable<string>): Promise<string[]> {\n await this.initialize();\n const normalized = new Set<string>();\n for (const name of allowedNames) {\n try {\n normalized.add(this.normalizeProfileName(name));\n } catch {\n // Skip invalid names so we only retain well-formed entries.\n }\n }\n\n const records = await this.listProfileRecords();\n const deleteCandidates = records\n .map(record => {\n try {\n return this.normalizeProfileName(record.name);\n } catch {\n return null;\n }\n })\n .filter((name): name is string => Boolean(name) && !normalized.has(name));\n\n if (deleteCandidates.length === 0) {\n return [];\n }\n\n const removed: string[] = [];\n for (const name of deleteCandidates) {\n try {\n await fs.rm(this.getProfileHomePath(name), { recursive: true, force: true });\n await this.deleteProfileRecord(name);\n removed.push(name);\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to remove profile '${name}' during plan enforcement:`, error);\n }\n }\n }\n const preferred = await this.readPreferredProfileName();\n if (preferred && removed.includes(preferred)) {\n await this.persistPreferredProfileName(null);\n }\n return removed;\n }\n\n /**\n * Check if the current auth matches a profile (for smart detection)\n */\n async getCurrentProfile(): Promise<{ name: string | null; trusted: boolean }> {\n await this.initialize();\n const preferredName = await this.readPreferredProfileName();\n if (preferredName) {\n try {\n const normalizedPreferred = this.normalizeProfileName(preferredName);\n const preferredRecord = await this.getProfileRowByName(normalizedPreferred);\n if (preferredRecord) {\n return { name: normalizedPreferred, trusted: true };\n }\n } catch {\n // fall through to active auth detection\n }\n }\n const activeAuth = await this.readActiveAuthFile();\n\n if (activeAuth) {\n const normalizedAuth = this.normalizeProfileData(activeAuth);\n const authMetadata = this.extractProfileMetadata(normalizedAuth);\n const workspace = this.resolveWorkspaceIdentity(normalizedAuth, authMetadata);\n const activeAccountId = this.getAccountIdFromData(normalizedAuth);\n\n if (activeAccountId) {\n const scoped = await this.getProfileRowByAccountAndWorkspace(activeAccountId, workspace.id ?? DEFAULT_WORKSPACE_ID, {\n preferAuthMethod: 'codex-cli',\n });\n if (scoped) {\n const normalized = this.normalizeProfileName(scoped.name);\n await this.persistPreferredProfileName(normalized);\n return { name: normalized, trusted: true };\n }\n\n const matching = await this.getProfileRowByAccountId(activeAccountId, { preferAuthMethod: 'codex-cli' });\n if (matching) {\n const normalized = this.normalizeProfileName(matching.name);\n await this.persistPreferredProfileName(normalized);\n return { name: normalized, trusted: true };\n }\n }\n }\n\n const preferred = await this.readPreferredProfileName();\n if (preferred) {\n try {\n const normalized = this.normalizeProfileName(preferred);\n const exists = await this.getProfileRowByName(normalized);\n if (exists) {\n return { name: normalized, trusted: true };\n }\n } catch {\n await this.persistPreferredProfileName(null);\n return { name: null, trusted: false };\n }\n await this.persistPreferredProfileName(null);\n }\n\n return { name: null, trusted: false };\n }\n\n /**\n * Export a profile to a portable format.\n * Sensitive tokens are included but should be handled securely.\n */\n async exportProfile(name: string): Promise<{\n name: string;\n displayName: string | null;\n email: string | null;\n accountId: string | null;\n workspaceId: string | null;\n workspaceName: string | null;\n authMethod: string | null;\n createdAt: string | null;\n metadata: ProfileMetadata | undefined;\n exportedAt: string;\n }> {\n await this.initialize();\n const profileName = this.normalizeProfileName(name);\n const record = await this.getProfileRowByName(profileName);\n if (!record) {\n throw new Error(`Profile '${profileName}' not found!`);\n }\n\n return {\n name: record.name,\n displayName: record.displayName,\n email: record.email,\n accountId: record.accountId,\n workspaceId: record.workspaceId,\n workspaceName: record.workspaceName,\n authMethod: record.authMethod,\n createdAt: record.createdAt,\n metadata: record.metadata,\n exportedAt: new Date().toISOString(),\n };\n }\n\n /**\n * Export profiles for cloud sync (includes token-bearing auth data).\n */\n async exportProfilesForCloudSync(): Promise<CloudSyncProfileRecord[]> {\n await this.initialize();\n const records = await this.listProfileRecords();\n return records.map(record => ({\n name: record.name,\n displayName: record.displayName,\n data: record.data,\n metadata: record.metadata,\n accountId: record.accountId,\n workspaceId: record.workspaceId,\n workspaceName: record.workspaceName,\n email: record.email,\n authMethod: record.authMethod,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n }));\n }\n\n /**\n * Replace local profiles with a full snapshot from cloud sync.\n */\n async replaceProfilesFromCloudSync(records: CloudSyncProfileRecord[]): Promise<{ imported: number; removed: number }> {\n await this.initialize();\n const now = new Date().toISOString();\n const normalized = new Map<string, ProfileRecord>();\n const existingMap = await this.readProfilesStateMap();\n const existingNames = new Set(Object.keys(existingMap));\n\n for (const candidate of records ?? []) {\n try {\n const name = this.normalizeProfileName(candidate?.name ?? '');\n const data =\n candidate && typeof candidate.data === 'object' && candidate.data !== null\n ? (candidate.data as ProfileData)\n : null;\n if (!data) {\n continue;\n }\n\n const metadata =\n candidate.metadata && typeof candidate.metadata === 'object'\n ? candidate.metadata\n : undefined;\n\n const record: ProfileRecord = {\n name,\n displayName: typeof candidate.displayName === 'string' ? candidate.displayName : null,\n data,\n metadata,\n accountId: typeof candidate.accountId === 'string' ? candidate.accountId : null,\n workspaceId: typeof candidate.workspaceId === 'string' ? candidate.workspaceId : null,\n workspaceName: typeof candidate.workspaceName === 'string' ? candidate.workspaceName : null,\n email: typeof candidate.email === 'string' ? candidate.email : null,\n authMethod: typeof candidate.authMethod === 'string' ? candidate.authMethod : this.resolveAuthMethod(data),\n createdAt: typeof candidate.createdAt === 'string' ? candidate.createdAt : now,\n updatedAt: typeof candidate.updatedAt === 'string' ? candidate.updatedAt : now,\n };\n\n normalized.set(name, record);\n } catch {\n // Ignore malformed record entries.\n }\n }\n\n const nextMap: Record<string, ProfileRecordState> = {};\n for (const record of normalized.values()) {\n nextMap[record.name] = this.toStateRecord(record);\n }\n await this.writeProfilesStateMap(nextMap);\n\n let removed = 0;\n\n for (const name of existingNames) {\n if (normalized.has(name)) {\n continue;\n }\n try {\n await fs.rm(this.getProfileHomePath(name), { recursive: true, force: true });\n removed += 1;\n } catch (error) {\n if (!this.isNotFoundError(error)) {\n logWarn(`Failed to remove profile '${name}' during cloud sync replace:`, error);\n }\n }\n }\n\n const preferred = await this.readPreferredProfileName();\n if (preferred) {\n try {\n const normalizedPreferred = this.normalizeProfileName(preferred);\n if (!normalized.has(normalizedPreferred)) {\n await this.persistPreferredProfileName(null);\n }\n } catch {\n await this.persistPreferredProfileName(null);\n }\n }\n\n return {\n imported: normalized.size,\n removed,\n };\n }\n}\n","export interface AutoRollSettings {\n enabled: boolean;\n warningThreshold: number;\n switchThreshold: number;\n}\n\nexport const DEFAULT_AUTO_ROLL_ENABLED = false;\nexport const DEFAULT_AUTO_ROLL_WARNING_THRESHOLD = 85;\nexport const DEFAULT_AUTO_ROLL_SWITCH_THRESHOLD = 95;\nexport const AUTO_ROLL_WARNING_MIN = 50;\nconst AUTO_ROLL_WARNING_MAX = 99;\nconst AUTO_ROLL_SWITCH_MAX = 100;\n\nfunction clampNumber(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nfunction resolveFiniteNumber(value: number, fallback: number): number {\n return Number.isFinite(value) ? value : fallback;\n}\n\nexport function sanitizeAutoRollWarningThreshold(value: number): number {\n const numeric = resolveFiniteNumber(value, DEFAULT_AUTO_ROLL_WARNING_THRESHOLD);\n return clampNumber(numeric, AUTO_ROLL_WARNING_MIN, AUTO_ROLL_WARNING_MAX);\n}\n\nexport function sanitizeAutoRollSwitchThreshold(\n value: number,\n warningThreshold: number,\n): number {\n const sanitizedWarning = sanitizeAutoRollWarningThreshold(warningThreshold);\n const numeric = resolveFiniteNumber(value, DEFAULT_AUTO_ROLL_SWITCH_THRESHOLD);\n return clampNumber(numeric, sanitizedWarning + 1, AUTO_ROLL_SWITCH_MAX);\n}\n\nexport function sanitizeAutoRollThresholds(\n warningThreshold: number,\n switchThreshold: number,\n): Pick<AutoRollSettings, \"warningThreshold\" | \"switchThreshold\"> {\n const sanitizedWarning = sanitizeAutoRollWarningThreshold(warningThreshold);\n const sanitizedSwitch = sanitizeAutoRollSwitchThreshold(switchThreshold, sanitizedWarning);\n return {\n warningThreshold: sanitizedWarning,\n switchThreshold: sanitizedSwitch,\n };\n}\n\n/**\n * Normalize partial auto-roll settings into a safe shape with bounds.\n * Ensures switch threshold is always above warning and both live within [50, 100].\n */\nexport function normalizeAutoRollSettings(\n raw?: Partial<AutoRollSettings> | null,\n): AutoRollSettings {\n const enabled = typeof raw?.enabled === 'boolean' ? raw.enabled : DEFAULT_AUTO_ROLL_ENABLED;\n const rawWarning = resolveFiniteNumber(\n typeof raw?.warningThreshold === 'number' ? raw.warningThreshold : NaN,\n DEFAULT_AUTO_ROLL_WARNING_THRESHOLD,\n );\n const rawSwitch = resolveFiniteNumber(\n typeof raw?.switchThreshold === 'number' ? raw.switchThreshold : NaN,\n DEFAULT_AUTO_ROLL_SWITCH_THRESHOLD,\n );\n\n // First clamp warning to valid range, then ensure switch is above it\n const { warningThreshold: normalizedWarning, switchThreshold: normalizedSwitch } = sanitizeAutoRollThresholds(\n rawWarning,\n rawSwitch,\n );\n\n return {\n enabled,\n warningThreshold: normalizedWarning,\n switchThreshold: normalizedSwitch,\n };\n}\n","import { promises as fs } from \"node:fs\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport type { ProfileData, ProfileMetadata } from \"./types\";\nimport {\n CHAT_SCROLLBACK_DEFAULT,\n normalizeChatHistoryScrollbackItems,\n} from \"./chat-scrollback\";\nimport {\n DEFAULT_COMMIT_MESSAGE_PROMPT,\n normalizeCommitMessagePrompt,\n} from \"./commit-message-prompt\";\n\nconst APP_STATE_FILE = \"app-state.json\";\nconst APP_NAME = \"codexuse-desktop\";\n\nexport type LicenseStatusCode = \"inactive\" | \"active\" | \"grace\" | \"error\";\nexport type ReasoningEffort = \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"none\";\n\nexport type ProfileRecordState = {\n name: string;\n displayName: string | null;\n data: ProfileData;\n metadata?: ProfileMetadata;\n accountId: string | null;\n workspaceId: string | null;\n workspaceName: string | null;\n email: string | null;\n authMethod: string | null;\n createdAt: string | null;\n updatedAt: string | null;\n};\n\nexport type SkillsInstallState = {\n id: string;\n repo?: string | null;\n repoPath?: string | null;\n sourceLabel?: string | null;\n sourceType?: \"official\" | \"community\" | \"local\";\n viewUrl?: string | null;\n createdAt?: string | null;\n};\n\nexport type SyncState = {\n lastPushAt: string | null;\n lastPullAt: string | null;\n lastError: string | null;\n remoteUpdatedAt: string | null;\n};\n\nexport type TelemetryState = {\n installId: string | null;\n enabled: boolean;\n lastFlushAt: string | null;\n lastError: string | null;\n};\n\nexport type AppState = {\n schemaVersion: 1;\n autoRoll: {\n enabled: boolean;\n warningThreshold: number;\n switchThreshold: number;\n };\n app: {\n lastAppVersion: string | null;\n pendingUpdateVersion: string | null;\n lastProfileName: string | null;\n };\n license: {\n licenseKey: string | null;\n purchaseEmail: string | null;\n lastVerifiedAt: string | null;\n nextCheckAt: string | null;\n lastVerificationError: string | null;\n status: LicenseStatusCode;\n signature: string | null;\n };\n providers: {\n selectedProviderId: string;\n defaultModel: string | null;\n defaultReasoningEffort: ReasoningEffort;\n list: Array<{\n id: string;\n name: string;\n models: string[];\n apiKey?: string;\n baseUrl?: string;\n }>;\n overridesByPath: Record<string, { selectedModel?: string | null; reasoningEffort?: ReasoningEffort }>;\n };\n sandbox: {\n defaultMode: string;\n defaultApprovalPolicy: string;\n overridesByPath: Record<string, { mode?: string; approvalPolicy?: string }>;\n };\n preferences: {\n excludeFolders: string[];\n enableTaskCompleteBeep: boolean;\n preventSleepDuringTasks: boolean;\n chatHistoryScrollbackItems: number | null;\n systemNotificationsEnabled: boolean;\n subagentSystemNotificationsEnabled: boolean;\n folderHistory: Array<{ path: string; name: string; lastVisited: number }>;\n pinnedPaths: string[];\n };\n runtimeSettings: Record<string, unknown>;\n workspaceSettingsByPath: Record<\n string,\n {\n systemPrompt?: string;\n runScript?: string;\n buildScript?: string;\n openIdeCommand?: string;\n }\n >;\n conversationCategoriesByCwd: Record<string, Array<{ id: string; name: string }>>;\n conversationCategoryAssignmentsByCwd: Record<string, Record<string, string>>;\n git: {\n commitMessagePrompt: string;\n commitMessageModelId: string | null;\n };\n agents: {\n multiAgentEnabled: boolean;\n maxThreads: number;\n maxDepth: number;\n };\n skills: {\n sources: Array<{\n id: string;\n repo: string;\n label: string;\n branch?: string | null;\n url?: string | null;\n official?: boolean;\n compatibilityNote?: string | null;\n priority?: number;\n }>;\n installsBySlug: Record<string, SkillsInstallState>;\n };\n sync: SyncState;\n telemetry: TelemetryState;\n profilesByName: Record<string, ProfileRecordState>;\n migration: {\n status: \"pending\" | \"pending_local_storage\" | \"complete\";\n startedAt: string | null;\n completedAt: string | null;\n localStorageImportedAt: string | null;\n lastError?: string | null;\n };\n};\n\nexport type AppStatePatch = DeepPartial<AppState>;\nexport type AppStateUpdateMode = \"replace\" | \"patch\";\nexport type AppStateUpdateOptions = {\n allowBeforeMigrationComplete?: boolean;\n mode?: AppStateUpdateMode;\n};\ntype AppStateUpdateTransform = (current: AppState) => AppState | AppStatePatch;\n\ntype DeepPartial<T> = {\n [K in keyof T]?: T[K] extends Array<infer U>\n ? U[]\n : T[K] extends object\n ? DeepPartial<T[K]>\n : T[K];\n};\n\nlet configuredUserDataDir: string | null = null;\nlet appStateCache: AppState | null = null;\nlet writeLock: Promise<void> = Promise.resolve();\nconst writeLockContext = new AsyncLocalStorage<boolean>();\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction clone<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nfunction resolveDefaultUserDataDir(): string {\n const home = process.env.HOME || process.env.USERPROFILE || os.homedir();\n if (!home) {\n throw new Error(\"Unable to resolve home directory for app state.\");\n }\n\n if (process.platform === \"darwin\") {\n return path.join(home, \"Library\", \"Application Support\", APP_NAME);\n }\n if (process.platform === \"win32\") {\n const appData = process.env.APPDATA;\n if (appData) {\n return path.join(appData, APP_NAME);\n }\n return path.join(home, \"AppData\", \"Roaming\", APP_NAME);\n }\n return path.join(home, \".config\", APP_NAME);\n}\n\nexport function getUserDataDir(): string {\n return configuredUserDataDir ?? resolveDefaultUserDataDir();\n}\n\nfunction resolveAppStatePath(): string {\n return path.join(getUserDataDir(), APP_STATE_FILE);\n}\n\nfunction createDefaultAppState(): AppState {\n return {\n schemaVersion: 1,\n autoRoll: {\n enabled: false,\n warningThreshold: 85,\n switchThreshold: 95,\n },\n app: {\n lastAppVersion: null,\n pendingUpdateVersion: null,\n lastProfileName: null,\n },\n license: {\n licenseKey: null,\n purchaseEmail: null,\n lastVerifiedAt: null,\n nextCheckAt: null,\n lastVerificationError: null,\n status: \"inactive\",\n signature: null,\n },\n providers: {\n selectedProviderId: \"openai\",\n defaultModel: null,\n defaultReasoningEffort: \"medium\",\n list: [],\n overridesByPath: {},\n },\n sandbox: {\n defaultMode: \"chat\",\n defaultApprovalPolicy: \"on-failure\",\n overridesByPath: {},\n },\n preferences: {\n excludeFolders: [],\n enableTaskCompleteBeep: true,\n preventSleepDuringTasks: true,\n chatHistoryScrollbackItems: CHAT_SCROLLBACK_DEFAULT,\n systemNotificationsEnabled: true,\n subagentSystemNotificationsEnabled: true,\n folderHistory: [],\n pinnedPaths: [],\n },\n runtimeSettings: {},\n workspaceSettingsByPath: {},\n conversationCategoriesByCwd: {},\n conversationCategoryAssignmentsByCwd: {},\n git: {\n commitMessagePrompt: DEFAULT_COMMIT_MESSAGE_PROMPT,\n commitMessageModelId: null,\n },\n agents: {\n multiAgentEnabled: false,\n maxThreads: 6,\n maxDepth: 1,\n },\n skills: {\n sources: [],\n installsBySlug: {},\n },\n sync: {\n lastPushAt: null,\n lastPullAt: null,\n lastError: null,\n remoteUpdatedAt: null,\n },\n telemetry: {\n installId: null,\n enabled: true,\n lastFlushAt: null,\n lastError: null,\n },\n profilesByName: {},\n migration: {\n status: \"pending\",\n startedAt: null,\n completedAt: null,\n localStorageImportedAt: null,\n lastError: null,\n },\n };\n}\n\nfunction asString(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction normalizeAppState(raw: unknown): AppState {\n const defaults = createDefaultAppState();\n if (!isRecord(raw)) {\n return defaults;\n }\n\n const next = deepMerge(defaults, raw as AppStatePatch);\n const merged = clone(next);\n\n merged.schemaVersion = 1;\n if (typeof merged.autoRoll.enabled !== \"boolean\") {\n merged.autoRoll.enabled = false;\n }\n if (!Number.isFinite(merged.autoRoll.warningThreshold)) {\n merged.autoRoll.warningThreshold = 85;\n }\n if (!Number.isFinite(merged.autoRoll.switchThreshold)) {\n merged.autoRoll.switchThreshold = 95;\n }\n if (merged.autoRoll.warningThreshold < 50 || merged.autoRoll.warningThreshold > 99) {\n merged.autoRoll.warningThreshold = 85;\n }\n if (merged.autoRoll.switchThreshold <= merged.autoRoll.warningThreshold || merged.autoRoll.switchThreshold > 100) {\n merged.autoRoll.switchThreshold = Math.min(100, Math.max(merged.autoRoll.warningThreshold + 1, 95));\n }\n merged.app.lastAppVersion = asString(merged.app.lastAppVersion);\n merged.app.pendingUpdateVersion = asString(merged.app.pendingUpdateVersion);\n merged.app.lastProfileName = asString(merged.app.lastProfileName);\n {\n const allowedAppKeys = new Set(Object.keys(defaults.app));\n for (const key of Object.keys(merged.app as Record<string, unknown>)) {\n if (!allowedAppKeys.has(key)) {\n delete (merged.app as Record<string, unknown>)[key];\n }\n }\n }\n\n merged.license.licenseKey = asString(merged.license.licenseKey);\n merged.license.purchaseEmail = asString(merged.license.purchaseEmail);\n merged.license.lastVerifiedAt = asString(merged.license.lastVerifiedAt);\n merged.license.nextCheckAt = asString(merged.license.nextCheckAt);\n merged.license.lastVerificationError = asString(merged.license.lastVerificationError);\n merged.license.signature = asString(merged.license.signature);\n if (![\"inactive\", \"active\", \"grace\", \"error\"].includes(merged.license.status)) {\n merged.license.status = \"inactive\";\n }\n\n if (!Array.isArray(merged.providers.list)) {\n merged.providers.list = [];\n }\n merged.providers.selectedProviderId = asString(merged.providers.selectedProviderId) ?? \"openai\";\n merged.providers.defaultModel = asString(merged.providers.defaultModel);\n if (![\"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"none\"].includes(merged.providers.defaultReasoningEffort)) {\n merged.providers.defaultReasoningEffort = \"medium\";\n }\n\n if (!isRecord(merged.providers.overridesByPath)) {\n merged.providers.overridesByPath = {};\n }\n if (!isRecord(merged.sandbox.overridesByPath)) {\n merged.sandbox.overridesByPath = {};\n }\n\n if (!Array.isArray(merged.preferences.excludeFolders)) {\n merged.preferences.excludeFolders = [];\n }\n if (typeof merged.preferences.enableTaskCompleteBeep !== \"boolean\") {\n merged.preferences.enableTaskCompleteBeep = true;\n }\n if (typeof merged.preferences.preventSleepDuringTasks !== \"boolean\") {\n merged.preferences.preventSleepDuringTasks = true;\n }\n merged.preferences.chatHistoryScrollbackItems = normalizeChatHistoryScrollbackItems(\n merged.preferences.chatHistoryScrollbackItems,\n );\n if (typeof merged.preferences.systemNotificationsEnabled !== \"boolean\") {\n merged.preferences.systemNotificationsEnabled = true;\n }\n if (typeof merged.preferences.subagentSystemNotificationsEnabled !== \"boolean\") {\n merged.preferences.subagentSystemNotificationsEnabled = true;\n }\n if (!Array.isArray(merged.preferences.folderHistory)) {\n merged.preferences.folderHistory = [];\n }\n if (!Array.isArray(merged.preferences.pinnedPaths)) {\n merged.preferences.pinnedPaths = [];\n }\n {\n const allowedPreferenceKeys = new Set(Object.keys(defaults.preferences));\n for (const key of Object.keys(merged.preferences as Record<string, unknown>)) {\n if (!allowedPreferenceKeys.has(key)) {\n delete (merged.preferences as Record<string, unknown>)[key];\n }\n }\n }\n\n if (!isRecord(merged.runtimeSettings)) {\n merged.runtimeSettings = {};\n }\n\n const legacyProjectSettingsByPath = isRecord(\n (raw as Record<string, unknown>).projectSettingsByPath,\n )\n ? ((raw as Record<string, unknown>)\n .projectSettingsByPath as AppState[\"workspaceSettingsByPath\"])\n : null;\n if (!isRecord(merged.workspaceSettingsByPath)) {\n merged.workspaceSettingsByPath = {};\n }\n if (legacyProjectSettingsByPath) {\n merged.workspaceSettingsByPath = {\n ...legacyProjectSettingsByPath,\n ...merged.workspaceSettingsByPath,\n };\n }\n delete (merged as Record<string, unknown>).projectSettingsByPath;\n if (!isRecord(merged.conversationCategoriesByCwd)) {\n merged.conversationCategoriesByCwd = {};\n }\n if (!isRecord(merged.conversationCategoryAssignmentsByCwd)) {\n merged.conversationCategoryAssignmentsByCwd = {};\n }\n if (!isRecord(merged.git)) {\n merged.git = clone(defaults.git);\n }\n merged.git.commitMessagePrompt =\n normalizeCommitMessagePrompt(merged.git.commitMessagePrompt) ??\n DEFAULT_COMMIT_MESSAGE_PROMPT;\n merged.git.commitMessageModelId = asString(merged.git.commitMessageModelId);\n\n if (!isRecord(merged.agents)) {\n merged.agents = clone(defaults.agents);\n }\n if (typeof merged.agents.multiAgentEnabled !== \"boolean\") {\n merged.agents.multiAgentEnabled = defaults.agents.multiAgentEnabled;\n }\n if (!Number.isFinite(merged.agents.maxThreads)) {\n merged.agents.maxThreads = defaults.agents.maxThreads;\n }\n merged.agents.maxThreads = Math.max(1, Math.min(12, Math.round(merged.agents.maxThreads)));\n if (!Number.isFinite(merged.agents.maxDepth)) {\n merged.agents.maxDepth = defaults.agents.maxDepth;\n }\n merged.agents.maxDepth = Math.max(1, Math.min(4, Math.round(merged.agents.maxDepth)));\n\n if (!isRecord(merged.skills)) {\n merged.skills = clone(defaults.skills);\n }\n if (!Array.isArray(merged.skills.sources)) {\n merged.skills.sources = [];\n }\n if (!isRecord(merged.skills.installsBySlug)) {\n merged.skills.installsBySlug = {};\n }\n\n if (!isRecord(merged.sync)) {\n merged.sync = clone(defaults.sync);\n }\n merged.sync.lastPushAt = asString(merged.sync.lastPushAt);\n merged.sync.lastPullAt = asString(merged.sync.lastPullAt);\n merged.sync.lastError = asString(merged.sync.lastError);\n merged.sync.remoteUpdatedAt = asString(merged.sync.remoteUpdatedAt);\n\n if (!isRecord(merged.telemetry)) {\n merged.telemetry = clone(defaults.telemetry);\n }\n merged.telemetry.installId = asString(merged.telemetry.installId);\n if (typeof merged.telemetry.enabled !== \"boolean\") {\n merged.telemetry.enabled = true;\n }\n merged.telemetry.lastFlushAt = asString(merged.telemetry.lastFlushAt);\n merged.telemetry.lastError = asString(merged.telemetry.lastError);\n\n if (!isRecord(merged.profilesByName)) {\n merged.profilesByName = {};\n }\n\n if (!isRecord(merged.migration)) {\n merged.migration = clone(defaults.migration);\n }\n if (![\"pending\", \"pending_local_storage\", \"complete\"].includes(merged.migration.status)) {\n merged.migration.status = \"pending\";\n }\n merged.migration.startedAt = asString(merged.migration.startedAt);\n merged.migration.completedAt = asString(merged.migration.completedAt);\n merged.migration.localStorageImportedAt = asString(merged.migration.localStorageImportedAt);\n merged.migration.lastError = asString(merged.migration.lastError);\n\n return merged;\n}\n\nfunction deepMerge<T>(base: T, patch: DeepPartial<T>): T {\n if (!isRecord(base) || !isRecord(patch)) {\n return clone((patch as T) ?? base);\n }\n\n const next: Record<string, unknown> = { ...(base as Record<string, unknown>) };\n for (const [key, patchValue] of Object.entries(patch)) {\n if (patchValue === undefined) {\n continue;\n }\n\n const currentValue = next[key];\n if (Array.isArray(patchValue)) {\n next[key] = clone(patchValue);\n continue;\n }\n\n if (isRecord(currentValue) && isRecord(patchValue)) {\n next[key] = deepMerge(currentValue, patchValue as DeepPartial<typeof currentValue>);\n continue;\n }\n\n next[key] = clone(patchValue);\n }\n\n return next as T;\n}\n\nasync function writeAtomic(filePath: string, contents: string): Promise<void> {\n const dir = path.dirname(filePath);\n const base = path.basename(filePath);\n const token = `${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}`;\n const tempPath = path.join(dir, `${base}.${token}.tmp`);\n\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(tempPath, contents, \"utf8\");\n try {\n await fs.rename(tempPath, filePath);\n } finally {\n await fs.rm(tempPath, { force: true }).catch(() => undefined);\n }\n}\n\nasync function writeAppStateToDisk(state: AppState): Promise<void> {\n const filePath = resolveAppStatePath();\n await writeAtomic(filePath, `${JSON.stringify(state, null, 2)}\\n`);\n}\n\nasync function readAppStateFromDisk(): Promise<AppState | null> {\n const filePath = resolveAppStatePath();\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n return normalizeAppState(JSON.parse(raw) as unknown);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n}\n\nasync function ensureInitialized(): Promise<AppState> {\n if (appStateCache) {\n return appStateCache;\n }\n\n const filePath = resolveAppStatePath();\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n\n const loaded = await readAppStateFromDisk();\n const normalized = loaded ?? normalizeAppState(null);\n appStateCache = normalized;\n\n if (loaded === null) {\n await writeAppStateToDisk(normalized);\n }\n\n return appStateCache;\n}\n\nasync function withWriteLock<T>(task: () => Promise<T>): Promise<T> {\n if (writeLockContext.getStore()) {\n return task();\n }\n\n const previous = writeLock;\n let release: (() => void) | undefined;\n writeLock = new Promise<void>(resolve => {\n release = resolve;\n });\n\n await previous;\n try {\n return await writeLockContext.run(true, task);\n } finally {\n if (release) {\n release();\n }\n }\n}\n\nexport async function initializeAppState(userDataDir: string): Promise<AppState> {\n configuredUserDataDir = userDataDir;\n const state = await ensureInitialized();\n return clone(state);\n}\n\nexport async function getAppState(): Promise<AppState> {\n const state = await ensureInitialized();\n return clone(state);\n}\n\nexport async function updateAppState(\n transform: AppStateUpdateTransform,\n options: AppStateUpdateOptions = {},\n): Promise<AppState> {\n const mode = options.mode ?? \"patch\";\n const allowBeforeMigrationComplete = options.allowBeforeMigrationComplete === true;\n\n return withWriteLock(async () => {\n const current = (await readAppStateFromDisk()) ?? (await ensureInitialized());\n appStateCache = current;\n if (!allowBeforeMigrationComplete && current.migration.status !== \"complete\") {\n throw new Error(\"Storage migration is not complete yet.\");\n }\n\n const transformed = transform(clone(current));\n const nextState = mode === \"replace\"\n ? normalizeAppState(transformed)\n : normalizeAppState(deepMerge(current, transformed as AppStatePatch));\n await writeAppStateToDisk(nextState);\n appStateCache = nextState;\n return clone(nextState);\n });\n}\n\nexport async function patchAppState(patch: AppStatePatch): Promise<AppState> {\n return updateAppState(() => patch, {\n mode: \"patch\",\n allowBeforeMigrationComplete: false,\n });\n}\n","export const CHAT_SCROLLBACK_DEFAULT = 200;\nexport const CHAT_SCROLLBACK_MIN = 50;\nexport const CHAT_SCROLLBACK_MAX = 5000;\nexport const CHAT_SCROLLBACK_PRESETS = [200, 500, 1000, 2000, 5000] as const;\n\nexport function clampChatScrollbackItems(value: number): number {\n if (!Number.isFinite(value)) {\n return CHAT_SCROLLBACK_DEFAULT;\n }\n const rounded = Math.round(value);\n return Math.max(CHAT_SCROLLBACK_MIN, Math.min(CHAT_SCROLLBACK_MAX, rounded));\n}\n\nexport function isChatScrollbackPreset(value: number): boolean {\n return (CHAT_SCROLLBACK_PRESETS as readonly number[]).includes(value);\n}\n\nexport function normalizeChatHistoryScrollbackItems(value: unknown): number | null {\n if (value === null) {\n return null;\n }\n\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return clampChatScrollbackItems(value);\n }\n\n if (typeof value === \"string\") {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) {\n return clampChatScrollbackItems(parsed);\n }\n }\n\n return CHAT_SCROLLBACK_DEFAULT;\n}\n\n","export const DEFAULT_COMMIT_MESSAGE_PROMPT = `Generate a concise git commit message for the following changes. Follow conventional commit format (e.g., feat:, fix:, refactor:, docs:, etc.). Keep the summary line under 72 characters. Only output the commit message, nothing else.\n\nChanges:\n{diff}`;\n\nconst DIFF_PLACEHOLDER = \"{diff}\";\n\nfunction normalizeLineEndings(value: string): string {\n return value.replace(/\\r\\n/g, \"\\n\");\n}\n\nexport function normalizeCommitMessagePrompt(value: string | null | undefined): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const normalized = normalizeLineEndings(value).trim();\n return normalized.length > 0 ? normalized : null;\n}\n\nexport function buildCommitMessagePrompt(\n diff: string,\n template?: string | null,\n): string {\n const normalizedDiff = normalizeLineEndings(diff).trim();\n if (!normalizedDiff) {\n return \"\";\n }\n\n const normalizedTemplate = normalizeCommitMessagePrompt(template);\n const base = normalizedTemplate ?? DEFAULT_COMMIT_MESSAGE_PROMPT;\n\n if (base.includes(DIFF_PLACEHOLDER)) {\n return base.split(DIFF_PLACEHOLDER).join(normalizedDiff);\n }\n\n return `${base}\\n\\nChanges:\\n${normalizedDiff}`;\n}\n\n","import { normalizeAutoRollSettings, type AutoRollSettings } from \"./auto-roll-settings\";\nimport { getAppState, patchAppState, type AppState } from \"./app-state\";\n\ntype LicenseStatusCode = \"inactive\" | \"active\" | \"grace\" | \"error\";\n\ninterface StoredLicense {\n licenseKey?: string | null;\n purchaseEmail?: string | null;\n lastVerifiedAt?: string | null;\n nextCheckAt?: string | null;\n lastVerificationError?: string | null;\n status?: LicenseStatusCode;\n signature?: string | null;\n}\n\ninterface CodexSettings {\n license?: StoredLicense | null;\n lastProfileName?: string | null;\n autoRoll?: AutoRollSettings | null;\n lastAppVersion?: string | null;\n pendingUpdateVersion?: string | null;\n}\n\nfunction toCodexSettings(state: AppState): CodexSettings {\n const license = state.license.licenseKey\n ? {\n licenseKey: state.license.licenseKey,\n purchaseEmail: state.license.purchaseEmail,\n lastVerifiedAt: state.license.lastVerifiedAt,\n nextCheckAt: state.license.nextCheckAt,\n lastVerificationError: state.license.lastVerificationError,\n status: state.license.status,\n signature: state.license.signature,\n }\n : null;\n\n const autoRoll = normalizeAutoRollSettings(state.autoRoll);\n\n return {\n ...(license ? { license } : {}),\n ...(state.app.lastProfileName ? { lastProfileName: state.app.lastProfileName } : {}),\n ...(autoRoll ? { autoRoll } : {}),\n ...(state.app.lastAppVersion ? { lastAppVersion: state.app.lastAppVersion } : {}),\n ...(state.app.pendingUpdateVersion ? { pendingUpdateVersion: state.app.pendingUpdateVersion } : {}),\n };\n}\n\nfunction asString(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction parseStoredLicense(raw?: unknown): StoredLicense | null {\n if (!isRecord(raw)) {\n return null;\n }\n\n const statusCandidate = asString(raw.status);\n const status = [\"inactive\", \"active\", \"grace\", \"error\"].includes(statusCandidate ?? \"\")\n ? (statusCandidate as LicenseStatusCode)\n : undefined;\n\n const license: StoredLicense = {\n licenseKey: asString(raw.licenseKey ?? raw.license_key),\n purchaseEmail: asString(raw.purchaseEmail ?? raw.purchase_email),\n lastVerifiedAt: asString(raw.lastVerifiedAt ?? raw.last_verified_at),\n nextCheckAt: asString(raw.nextCheckAt ?? raw.next_check_at),\n lastVerificationError: asString(raw.lastVerificationError ?? raw.last_verification_error),\n status,\n signature: asString(raw.signature),\n };\n\n const hasValue = Boolean(\n license.licenseKey ||\n license.purchaseEmail ||\n license.lastVerifiedAt ||\n license.nextCheckAt ||\n license.lastVerificationError ||\n license.status,\n );\n\n return hasValue ? license : null;\n}\n\nfunction parseAutoRoll(raw: unknown): AutoRollSettings | null {\n if (!raw) {\n return null;\n }\n try {\n return normalizeAutoRollSettings(raw as Partial<AutoRollSettings>);\n } catch {\n return null;\n }\n}\n\nexport async function getCodexSettings(): Promise<CodexSettings> {\n const state = await getAppState();\n return toCodexSettings(state);\n}\n\nexport async function setCodexSettings(settings: CodexSettings): Promise<void> {\n const autoRoll = parseAutoRoll(settings.autoRoll);\n const license = parseStoredLicense(settings.license);\n await patchAppState({\n app: {\n lastProfileName: asString(settings.lastProfileName),\n lastAppVersion: asString(settings.lastAppVersion),\n pendingUpdateVersion: asString(settings.pendingUpdateVersion),\n },\n autoRoll: autoRoll\n ? {\n enabled: autoRoll.enabled,\n warningThreshold: autoRoll.warningThreshold,\n switchThreshold: autoRoll.switchThreshold,\n }\n : undefined,\n license: license\n ? {\n licenseKey: license.licenseKey ?? null,\n purchaseEmail: license.purchaseEmail ?? null,\n lastVerifiedAt: license.lastVerifiedAt ?? null,\n nextCheckAt: license.nextCheckAt ?? null,\n lastVerificationError: license.lastVerificationError ?? null,\n status: license.status ?? \"inactive\",\n signature: license.signature ?? null,\n }\n : {\n licenseKey: null,\n purchaseEmail: null,\n lastVerifiedAt: null,\n nextCheckAt: null,\n lastVerificationError: null,\n status: \"inactive\",\n signature: null,\n },\n });\n}\n\nexport async function getLastProfileName(): Promise<string | null> {\n const state = await getAppState();\n return asString(state.app.lastProfileName);\n}\n\nexport async function persistLastProfileName(profileName: string | null): Promise<void> {\n await patchAppState({\n app: {\n lastProfileName: asString(profileName),\n },\n });\n}\n\nexport async function getStoredLicense(): Promise<StoredLicense | null> {\n const state = await getAppState();\n return parseStoredLicense(state.license);\n}\n\nexport async function persistLicense(license: StoredLicense | null): Promise<void> {\n const parsed = parseStoredLicense(license);\n await patchAppState({\n license: parsed\n ? {\n licenseKey: parsed.licenseKey ?? null,\n purchaseEmail: parsed.purchaseEmail ?? null,\n lastVerifiedAt: parsed.lastVerifiedAt ?? null,\n nextCheckAt: parsed.nextCheckAt ?? null,\n lastVerificationError: parsed.lastVerificationError ?? null,\n status: parsed.status ?? \"inactive\",\n signature: parsed.signature ?? null,\n }\n : {\n licenseKey: null,\n purchaseEmail: null,\n lastVerifiedAt: null,\n nextCheckAt: null,\n lastVerificationError: null,\n status: \"inactive\",\n signature: null,\n },\n });\n}\n\nexport async function getStoredAutoRollSettings(): Promise<AutoRollSettings | null> {\n const state = await getAppState();\n return normalizeAutoRollSettings(state.autoRoll);\n}\n\nexport async function persistAutoRollSettings(settings: AutoRollSettings | null): Promise<void> {\n const normalized = normalizeAutoRollSettings(settings ?? undefined);\n await patchAppState({\n autoRoll: {\n enabled: normalized.enabled,\n warningThreshold: normalized.warningThreshold,\n switchThreshold: normalized.switchThreshold,\n },\n });\n}\n\nexport async function getStoredAppVersion(): Promise<string | null> {\n const state = await getAppState();\n return asString(state.app.lastAppVersion);\n}\n\nexport async function persistAppVersion(version: string | null): Promise<void> {\n await patchAppState({\n app: {\n lastAppVersion: asString(version),\n },\n });\n}\n\nexport async function getPendingUpdateVersion(): Promise<string | null> {\n const state = await getAppState();\n return asString(state.app.pendingUpdateVersion);\n}\n\nexport async function persistPendingUpdateVersion(version: string | null): Promise<void> {\n await patchAppState({\n app: {\n pendingUpdateVersion: asString(version),\n },\n });\n}\n\nexport async function readCodexSettingsJsonRaw(): Promise<Record<string, unknown>> {\n const state = await getAppState();\n return {\n lastProfileName: state.app.lastProfileName,\n lastAppVersion: state.app.lastAppVersion,\n pendingUpdateVersion: state.app.pendingUpdateVersion,\n autoRoll: state.autoRoll,\n license: state.license,\n providers: state.providers.list,\n selectedProviderId: state.providers.selectedProviderId,\n defaultModel: state.providers.defaultModel,\n defaultReasoningEffort: state.providers.defaultReasoningEffort,\n selectionsByCwd: state.providers.overridesByPath,\n mode: state.sandbox.defaultMode,\n approvalPolicy: state.sandbox.defaultApprovalPolicy,\n sandboxSelectionsByCwd: state.sandbox.overridesByPath,\n excludeFolders: state.preferences.excludeFolders,\n enableTaskCompleteBeep: state.preferences.enableTaskCompleteBeep,\n preventSleepDuringTasks: state.preferences.preventSleepDuringTasks,\n systemNotificationsEnabled: state.preferences.systemNotificationsEnabled,\n subagentSystemNotificationsEnabled:\n state.preferences.subagentSystemNotificationsEnabled,\n folderHistory: state.preferences.folderHistory,\n pinnedPaths: state.preferences.pinnedPaths,\n workspaceSettingsByPath: state.workspaceSettingsByPath,\n // Legacy compatibility for older consumers.\n projectSettingsByPath: state.workspaceSettingsByPath,\n categoriesByCwd: state.conversationCategoriesByCwd,\n conversationCategoryByCwd: state.conversationCategoryAssignmentsByCwd,\n git: state.git,\n agents: state.agents,\n sync: state.sync,\n };\n}\n\nexport async function writeCodexSettingsJsonRaw(payload: Record<string, unknown> | null | undefined): Promise<void> {\n if (!isRecord(payload)) {\n return;\n }\n\n const autoRoll = parseAutoRoll(payload.autoRoll ?? payload.auto_roll);\n const license = parseStoredLicense(payload.license);\n\n await patchAppState({\n app: {\n lastProfileName: asString(payload.lastProfileName ?? payload.last_profile_name),\n lastAppVersion: asString(payload.lastAppVersion ?? payload.last_app_version),\n pendingUpdateVersion: asString(payload.pendingUpdateVersion ?? payload.pending_update_version),\n },\n autoRoll: autoRoll\n ? {\n enabled: autoRoll.enabled,\n warningThreshold: autoRoll.warningThreshold,\n switchThreshold: autoRoll.switchThreshold,\n }\n : undefined,\n license: license\n ? {\n licenseKey: license.licenseKey ?? null,\n purchaseEmail: license.purchaseEmail ?? null,\n lastVerifiedAt: license.lastVerifiedAt ?? null,\n nextCheckAt: license.nextCheckAt ?? null,\n lastVerificationError: license.lastVerificationError ?? null,\n status: license.status ?? \"inactive\",\n signature: license.signature ?? null,\n }\n : undefined,\n providers: {\n list: Array.isArray(payload.providers)\n ? (payload.providers as AppState[\"providers\"][\"list\"])\n : undefined,\n selectedProviderId: asString(payload.selectedProviderId) ?? undefined,\n defaultModel: asString(payload.defaultModel ?? payload.selectedModel),\n defaultReasoningEffort:\n typeof payload.defaultReasoningEffort === \"string\"\n ? (payload.defaultReasoningEffort as AppState[\"providers\"][\"defaultReasoningEffort\"])\n : typeof payload.reasoningEffort === \"string\"\n ? (payload.reasoningEffort as AppState[\"providers\"][\"defaultReasoningEffort\"])\n : undefined,\n overridesByPath:\n isRecord(payload.selectionsByCwd) ? (payload.selectionsByCwd as AppState[\"providers\"][\"overridesByPath\"]) : undefined,\n },\n sandbox: {\n defaultMode: asString(payload.mode ?? payload.defaultMode) ?? undefined,\n defaultApprovalPolicy:\n asString(payload.approvalPolicy ?? payload.defaultApprovalPolicy) ?? undefined,\n overridesByPath:\n isRecord(payload.sandboxSelectionsByCwd)\n ? (payload.sandboxSelectionsByCwd as AppState[\"sandbox\"][\"overridesByPath\"])\n : undefined,\n },\n preferences: {\n excludeFolders: Array.isArray(payload.excludeFolders)\n ? (payload.excludeFolders as string[])\n : undefined,\n enableTaskCompleteBeep:\n typeof payload.enableTaskCompleteBeep === \"boolean\"\n ? payload.enableTaskCompleteBeep\n : undefined,\n preventSleepDuringTasks:\n typeof payload.preventSleepDuringTasks === \"boolean\"\n ? payload.preventSleepDuringTasks\n : undefined,\n systemNotificationsEnabled:\n typeof payload.systemNotificationsEnabled === \"boolean\"\n ? payload.systemNotificationsEnabled\n : undefined,\n subagentSystemNotificationsEnabled:\n typeof payload.subagentSystemNotificationsEnabled === \"boolean\"\n ? payload.subagentSystemNotificationsEnabled\n : undefined,\n folderHistory: Array.isArray(payload.folderHistory)\n ? (payload.folderHistory as AppState[\"preferences\"][\"folderHistory\"])\n : undefined,\n pinnedPaths: Array.isArray(payload.pinnedPaths)\n ? (payload.pinnedPaths as string[])\n : undefined,\n },\n workspaceSettingsByPath: isRecord(payload.workspaceSettingsByPath)\n ? (payload.workspaceSettingsByPath as AppState[\"workspaceSettingsByPath\"])\n : isRecord(payload.projectSettingsByPath)\n ? (payload.projectSettingsByPath as AppState[\"workspaceSettingsByPath\"])\n : undefined,\n conversationCategoriesByCwd: isRecord(payload.categoriesByCwd)\n ? (payload.categoriesByCwd as AppState[\"conversationCategoriesByCwd\"])\n : undefined,\n conversationCategoryAssignmentsByCwd: isRecord(payload.conversationCategoryByCwd)\n ? (payload.conversationCategoryByCwd as AppState[\"conversationCategoryAssignmentsByCwd\"])\n : undefined,\n git: isRecord(payload.git)\n ? (payload.git as AppState[\"git\"])\n : undefined,\n agents: isRecord(payload.agents)\n ? (payload.agents as AppState[\"agents\"])\n : undefined,\n sync: isRecord(payload.sync) ? (payload.sync as AppState[\"sync\"]) : undefined,\n });\n}\n\nexport type { StoredLicense, LicenseStatusCode };\nexport type { AutoRollSettings } from \"./auto-roll-settings\";\n","const isTestEnv =\n process.env.NODE_ENV === 'test' ||\n process.env.VITEST === 'true' ||\n process.env.VITEST === '1';\n\nfunction isMocked(fn: unknown): boolean {\n return Boolean(fn && typeof fn === 'function' && 'mock' in (fn as Record<string, unknown>));\n}\n\nexport function logWarn(...args: Parameters<typeof console.warn>): void {\n if (isTestEnv && !isMocked(console.warn)) {\n return;\n }\n console.warn(...args);\n}\n\nexport function logError(...args: Parameters<typeof console.error>): void {\n if (isTestEnv && !isMocked(console.error)) {\n return;\n }\n console.error(...args);\n}\n\nexport function logInfo(...args: Parameters<typeof console.warn>): void {\n if (isTestEnv && !isMocked(console.warn)) {\n return;\n }\n console.warn(...args);\n}\n","import crypto from 'node:crypto';\nimport { persistLicense, getStoredLicense, type StoredLicense } from './codex-settings';\nimport { getLicenseSecret } from './license-secret';\nimport { getActiveOffer, buildCheckoutUrl } from './offer-config';\n\nconst offer = getActiveOffer();\nconst PRODUCT_PERMALINK = offer.productPermalink;\nconst PRODUCT_ID = '3_CcyVEXt2FOMiEpPx8xzw==';\nconst PRODUCT_URL = buildCheckoutUrl(offer);\nconst LICENSE_PRICE_DISPLAY = offer.isActive ? offer.salePriceDisplay : offer.basePriceDisplay;\nconst BASE_PRICE_DISPLAY = offer.basePriceDisplay;\nconst PROMO_CODE = offer.couponCode;\nconst PROMO_PERCENT = offer.discountPercent;\nconst PROMO_ACTIVE = offer.isActive;\nconst LICENSE_MAX_USES = 5;\nconst FREE_PROFILE_LIMIT = 2;\nconst LICENSE_REFRESH_INTERVAL_MS = 5 * 60 * 1000;\nconst MAX_NEXT_CHECK_MS = 60 * 60 * 1000;\nconst GRACE_MAX_AGE_MS = 3 * 60 * 60 * 1000;\n\ntype LicenseTier = 'free' | 'pro';\ntype LicenseState = 'inactive' | 'active' | 'grace' | 'verifying' | 'error';\n\ninterface LicenseStatus {\n tier: LicenseTier;\n state: LicenseState;\n isPro: boolean;\n profileLimit: number | null;\n profilesRemaining: number | null;\n purchaseEmail: string | null;\n maskedLicenseKey: string | null;\n lastVerifiedAt: string | null;\n nextCheckAt: string | null;\n message: string | null;\n error: string | null;\n productPermalink: string;\n productUrl: string;\n productId: string;\n priceDisplay: string;\n basePriceDisplay: string;\n promoCode: string | null;\n promoPercent: number | null;\n maxDevices: number;\n}\n\ninterface GumroadLicenseResponse {\n success: boolean;\n message?: string;\n uses?: number;\n purchase?: {\n id: string;\n email: string;\n product_id?: string;\n product_permalink?: string;\n refunded?: boolean;\n chargebacked?: boolean;\n subscription_cancelled?: boolean;\n subscription_failed?: boolean;\n license_disabled?: boolean;\n variants?: string;\n };\n license_disabled?: boolean;\n}\n\ntype VerificationMode = 'activation' | 'refresh';\n\nclass LicenseError extends Error {\n readonly code: 'network' | 'invalid' | 'revoked';\n\n constructor(message: string, code: 'network' | 'invalid' | 'revoked') {\n super(message);\n this.name = 'LicenseError';\n this.code = code;\n }\n}\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction maskLicenseKey(key: string | null | undefined): string | null {\n if (!key || typeof key !== 'string') {\n return null;\n }\n\n const trimmed = key.trim();\n if (trimmed.length <= 4) {\n return '••••';\n }\n\n const visible = trimmed.slice(-4);\n return `••••${visible}`;\n}\n\nfunction resolveProfilesRemaining(limit: number | null, currentProfiles: number): number | null {\n if (typeof limit !== 'number') {\n return null;\n }\n return Math.max(0, limit - currentProfiles);\n}\n\nfunction determineTierFromStored(stored: StoredLicense | null): LicenseTier {\n if (!stored || !stored.licenseKey) {\n return 'free';\n }\n\n if (stored.status === 'inactive') {\n return 'free';\n }\n\n return 'pro';\n}\n\nfunction licenseSignaturePayload(license: StoredLicense): string {\n const payload = {\n licenseKey: license.licenseKey ?? null,\n purchaseEmail: license.purchaseEmail ?? null,\n lastVerifiedAt: license.lastVerifiedAt ?? null,\n nextCheckAt: license.nextCheckAt ?? null,\n lastVerificationError: license.lastVerificationError ?? null,\n status: license.status ?? null,\n };\n return JSON.stringify(payload);\n}\n\nfunction signLicense(license: StoredLicense, secret: string): string {\n return crypto.createHmac('sha256', secret).update(licenseSignaturePayload(license)).digest('hex');\n}\n\nfunction withSignature(license: StoredLicense, secret: string): StoredLicense {\n return {\n ...license,\n signature: signLicense(license, secret),\n };\n}\n\nfunction isSignatureValid(license: StoredLicense, secret: string): boolean {\n if (!license.signature) {\n return false;\n }\n const expected = signLicense(license, secret);\n return expected === license.signature;\n}\n\nasync function requestGumroadVerify(licenseKey: string, mode: VerificationMode): Promise<GumroadLicenseResponse> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 10_000);\n\n try {\n const body = new URLSearchParams({\n product_permalink: PRODUCT_PERMALINK,\n product_id: PRODUCT_ID,\n license_key: licenseKey,\n increment_uses_count: mode === 'activation' ? 'true' : 'false',\n });\n\n const response = await fetch('https://api.gumroad.com/v2/licenses/verify', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => null);\n const message = errorText\n ? `License verification failed (${response.status}): ${errorText}`\n : `License verification failed (${response.status}).`;\n throw new LicenseError(message, 'network');\n }\n\n const json = (await response.json()) as GumroadLicenseResponse;\n return json;\n } catch (error) {\n if (error instanceof LicenseError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n throw new LicenseError('License verification timed out.', 'network');\n }\n\n throw new LicenseError(\n error instanceof Error ? error.message : 'Unable to reach Gumroad for license verification.',\n 'network',\n );\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction normalizeVerificationResult(response: GumroadLicenseResponse): { email: string | null } {\n if (!response.success) {\n const message = response.message ?? 'License key is invalid.';\n throw new LicenseError(message, 'invalid');\n }\n\n if (!response.purchase) {\n throw new LicenseError('License verification response was incomplete.', 'network');\n }\n\n if (response.purchase.chargebacked || response.purchase.refunded || response.license_disabled) {\n throw new LicenseError('This license has been revoked or refunded.', 'revoked');\n }\n\n if (response.purchase.subscription_cancelled || response.purchase.subscription_failed) {\n throw new LicenseError('This license subscription is no longer active.', 'revoked');\n }\n\n const email = response.purchase.email ?? null;\n return { email };\n}\n\nfunction ensureWithinUseLimit(response: GumroadLicenseResponse): void {\n if (!response.success) {\n return;\n }\n\n if (typeof response.uses !== 'number') {\n return;\n }\n\n if (response.uses > LICENSE_MAX_USES) {\n throw new LicenseError(\n `This license has reached the activation limit (${LICENSE_MAX_USES}). Contact support to move it to another device.`,\n 'invalid',\n );\n }\n}\n\nfunction toLicenseStatus(stored: StoredLicense | null, overrides: Partial<LicenseStatus> = {}): LicenseStatus {\n const tier = determineTierFromStored(stored);\n const isPro = tier === 'pro';\n\n const state: LicenseState =\n stored && stored.status\n ? stored.status\n : isPro\n ? 'active'\n : 'inactive';\n\n const base: LicenseStatus = {\n tier,\n state,\n isPro,\n profileLimit: isPro ? null : FREE_PROFILE_LIMIT,\n profilesRemaining: null,\n purchaseEmail: stored?.purchaseEmail ?? null,\n maskedLicenseKey: maskLicenseKey(stored?.licenseKey),\n lastVerifiedAt: stored?.lastVerifiedAt ?? null,\n nextCheckAt: stored?.nextCheckAt ?? null,\n message: null,\n error: stored?.lastVerificationError ?? null,\n productUrl: PRODUCT_URL,\n productId: PRODUCT_ID,\n productPermalink: PRODUCT_PERMALINK,\n priceDisplay: LICENSE_PRICE_DISPLAY,\n basePriceDisplay: BASE_PRICE_DISPLAY,\n promoCode: PROMO_ACTIVE ? PROMO_CODE : null,\n promoPercent: PROMO_ACTIVE ? PROMO_PERCENT : null,\n maxDevices: LICENSE_MAX_USES,\n };\n\n return { ...base, ...overrides };\n}\n\nfunction parseTimestamp(value: string | null | undefined): number | null {\n if (typeof value !== 'string' || value.trim() === '') {\n return null;\n }\n\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? null : parsed;\n}\n\nclass LicenseService {\n private cache: LicenseStatus | null = null;\n private refreshPromise: Promise<void> | null = null;\n private verificationPromise: Promise<LicenseStatus> | null = null;\n\n async getCachedStatus(): Promise<LicenseStatus> {\n return this.getStatus();\n }\n\n async getStatus(options: { forceRefresh?: boolean } = {}): Promise<LicenseStatus> {\n const forceRefresh = Boolean(options.forceRefresh);\n const secret = await getLicenseSecret();\n const stored = await getStoredLicense();\n\n if (!stored?.licenseKey) {\n const status = toLicenseStatus(null);\n this.cache = status;\n return status;\n }\n\n const now = Date.now();\n const nextCheckTs = parseTimestamp(stored.nextCheckAt);\n const lastVerifiedTs = parseTimestamp(stored.lastVerifiedAt);\n const graceStale =\n (stored.status === 'grace' || stored.status === 'error') &&\n (lastVerifiedTs === null || lastVerifiedTs + GRACE_MAX_AGE_MS < now);\n\n let workingStored: StoredLicense = { ...stored };\n const signatureValid = isSignatureValid(workingStored, secret);\n\n let cappedNextCheckTs = nextCheckTs;\n\n if (nextCheckTs !== null && nextCheckTs > now + MAX_NEXT_CHECK_MS) {\n cappedNextCheckTs = now;\n const updated = {\n ...workingStored,\n nextCheckAt: new Date(cappedNextCheckTs).toISOString(),\n };\n const signed = withSignature(updated, secret);\n workingStored = signed;\n await persistLicense(signed);\n }\n\n const tampered = Boolean(workingStored.licenseKey) && !signatureValid;\n\n const cached = tampered\n ? toLicenseStatus(null, {\n state: 'verifying',\n message: 'License data changed, rechecking.',\n error: 'Untrusted license data.',\n })\n : toLicenseStatus(workingStored);\n this.cache = cached;\n\n const shouldRefresh =\n forceRefresh || graceStale || tampered || cappedNextCheckTs === null || cappedNextCheckTs <= now;\n\n if (!shouldRefresh) {\n return cached;\n }\n\n if (this.verificationPromise && !forceRefresh) {\n return this.verificationPromise;\n }\n\n const verify = async (): Promise<LicenseStatus> => {\n try {\n const result = await requestGumroadVerify(workingStored.licenseKey!, 'refresh');\n ensureWithinUseLimit(result);\n const normalized = normalizeVerificationResult(result);\n const updated: StoredLicense = {\n licenseKey: workingStored.licenseKey,\n purchaseEmail: normalized.email,\n lastVerifiedAt: nowIso(),\n nextCheckAt: new Date(Date.now() + LICENSE_REFRESH_INTERVAL_MS).toISOString(),\n status: 'active',\n lastVerificationError: null,\n };\n\n const signed = withSignature(updated, secret);\n\n await persistLicense(signed);\n const status = toLicenseStatus(signed);\n this.cache = status;\n return status;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'License verification failed.';\n\n if (error instanceof LicenseError && error.code === 'network') {\n const fallbackStored: StoredLicense = withSignature(\n {\n ...workingStored,\n status: tampered ? 'inactive' : workingStored.status === 'inactive' ? 'inactive' : 'grace',\n lastVerificationError: message,\n nextCheckAt: new Date(Date.now() + LICENSE_REFRESH_INTERVAL_MS).toISOString(),\n },\n secret,\n );\n await persistLicense(fallbackStored);\n const fallback = toLicenseStatus(fallbackStored, {\n state: fallbackStored.status ?? 'grace',\n error: message,\n });\n this.cache = fallback;\n return fallback;\n }\n\n const fallbackStored: StoredLicense = withSignature({\n licenseKey: workingStored.licenseKey,\n purchaseEmail: workingStored.purchaseEmail ?? null,\n lastVerifiedAt: workingStored.lastVerifiedAt ?? null,\n nextCheckAt: null,\n status: 'inactive',\n lastVerificationError: message,\n }, secret);\n await persistLicense(fallbackStored);\n const fallback = toLicenseStatus(fallbackStored, { error: message });\n this.cache = fallback;\n return fallback;\n }\n };\n\n this.verificationPromise = verify();\n try {\n return await this.verificationPromise;\n } finally {\n this.verificationPromise = null;\n }\n }\n\n async activate(licenseKey: string): Promise<LicenseStatus> {\n const trimmed = licenseKey.trim();\n if (!trimmed) {\n throw new Error('License key is required.');\n }\n\n const secret = await getLicenseSecret();\n const digest = crypto.createHash('sha256').update(trimmed).digest('hex');\n\n const result = await requestGumroadVerify(trimmed, 'activation');\n ensureWithinUseLimit(result);\n const normalized = normalizeVerificationResult(result);\n const stored: StoredLicense = {\n licenseKey: trimmed,\n purchaseEmail: normalized.email,\n lastVerifiedAt: nowIso(),\n nextCheckAt: new Date(Date.now() + LICENSE_REFRESH_INTERVAL_MS).toISOString(),\n status: 'active',\n lastVerificationError: null,\n };\n\n const signed = withSignature(stored, secret);\n\n await persistLicense(signed);\n const status = toLicenseStatus(signed, {\n message: `License verified (${digest.slice(0, 8)}).`,\n });\n this.cache = status;\n return status;\n }\n\n applyProfileCount(status: LicenseStatus, profileCount: number): LicenseStatus {\n const profilesRemaining = resolveProfilesRemaining(status.profileLimit, profileCount);\n return {\n ...status,\n profilesRemaining,\n };\n }\n\n refreshStatusInBackground(options: { force?: boolean } = {}): void {\n if (this.refreshPromise) {\n return;\n }\n\n const forceRefresh = Boolean(options.force);\n this.refreshPromise = (async () => {\n try {\n await this.getStatus({ forceRefresh });\n } catch (error) {\n console.warn('Background license refresh failed:', error);\n } finally {\n this.refreshPromise = null;\n }\n })();\n }\n}\n\nexport const licenseService = new LicenseService();\nexport type { LicenseStatus, LicenseTier, LicenseState };\nexport { FREE_PROFILE_LIMIT, LICENSE_PRICE_DISPLAY, PRODUCT_PERMALINK, PRODUCT_URL, PRODUCT_ID };\n\nfunction isExplicitInvalidation(message: string | null | undefined): boolean {\n if (!message) {\n return false;\n }\n const normalized = message.toLowerCase();\n return (\n normalized.includes('revoked') ||\n normalized.includes('refunded') ||\n normalized.includes('invalid') ||\n normalized.includes('no longer active')\n );\n}\n\n/**\n * Determines when it is safe to enforce profile limits (e.g., pruning).\n * We skip enforcement when the license state is uncertain (grace/error/verifying)\n * and only enforce limits for true free/unlicensed states or explicit revocations.\n */\nexport function shouldEnforceProfileLimit(status: LicenseStatus): boolean {\n if (status.isPro) {\n return false;\n }\n\n if (status.state === 'grace' || status.state === 'verifying' || status.state === 'error') {\n return false;\n }\n\n if (isExplicitInvalidation(status.error)) {\n return true;\n }\n\n return status.state === 'inactive';\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { getUserDataDir } from './app-state';\n\nconst SECRET_FILE = 'license.secret';\n\nfunction resolveSecretPath(): string {\n return path.join(getUserDataDir(), SECRET_FILE);\n}\n\nasync function generateSecret(): Promise<string> {\n return crypto.randomBytes(32).toString('hex');\n}\n\nasync function readSecretIfExists(secretPath: string): Promise<string | null> {\n try {\n const existing = await fs.readFile(secretPath, 'utf8');\n const trimmed = existing.trim();\n if (trimmed.length > 0) {\n return trimmed;\n }\n return null;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n throw error;\n }\n}\n\nasync function writeSecret(secretPath: string, secret: string): Promise<void> {\n await fs.mkdir(path.dirname(secretPath), { recursive: true });\n await fs.writeFile(secretPath, `${secret}\\n`, { mode: 0o600 });\n await fs.chmod(secretPath, 0o600).catch(() => undefined);\n}\n\nexport async function getLicenseSecret(): Promise<string> {\n const secretPath = resolveSecretPath();\n const existing = await readSecretIfExists(secretPath);\n if (existing) {\n return existing;\n }\n\n const secret = await generateSecret();\n await writeSecret(secretPath, secret);\n return secret;\n}\n","/**\n * Single source of truth for pricing, promo codes, and checkout URLs.\n * Every surface (license-service, landing page, upgrade modal, JSON-LD)\n * should derive its pricing/promo data from this file.\n */\n\nexport interface OfferConfig {\n basePriceUsd: number;\n basePriceDisplay: string;\n couponCode: string | null;\n discountPercent: number;\n salePriceUsd: number;\n salePriceDisplay: string;\n isActive: boolean;\n campaign: string | null;\n productPermalink: string;\n checkoutBaseUrl: string;\n}\n\nexport function getActiveOffer(): OfferConfig {\n const basePriceUsd = 39;\n const discountPercent = 50;\n const salePriceUsd = basePriceUsd * (100 - discountPercent) / 100;\n\n return {\n basePriceUsd,\n basePriceDisplay: `$${basePriceUsd}`,\n couponCode: \"SPRING50\",\n discountPercent,\n salePriceUsd,\n salePriceDisplay: `$${salePriceUsd.toFixed(2)}`,\n isActive: true,\n campaign: \"spring-2026\",\n productPermalink: \"codex-use\",\n checkoutBaseUrl: \"https://hweihwang.gumroad.com/l/codex-use\",\n };\n}\n\nexport function buildCheckoutUrl(\n offer: OfferConfig,\n utm?: { source: string; medium: string; campaign?: string },\n): string {\n const base = offer.checkoutBaseUrl;\n const withCoupon = offer.isActive && offer.couponCode\n ? `${base}/${offer.couponCode}`\n : base;\n\n if (!utm) {\n return withCoupon;\n }\n\n const params = new URLSearchParams();\n params.set(\"utm_source\", utm.source);\n params.set(\"utm_medium\", utm.medium);\n if (utm.campaign) {\n params.set(\"utm_campaign\", utm.campaign);\n } else if (offer.campaign) {\n params.set(\"utm_campaign\", offer.campaign);\n }\n\n return `${withCoupon}?${params.toString()}`;\n}\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport {\n CLOUD_SYNC_SCHEMA_VERSION,\n type CloudSyncProfileRecord,\n type CloudSyncSnapshot,\n} from \"./cloud-sync-types\";\nimport {\n CloudSyncClientError,\n fetchRemoteSnapshotMeta,\n fetchRemoteSnapshot,\n pushRemoteSnapshot,\n} from \"./cloud-sync-client\";\nimport { ProfileManager } from \"./profile-manager\";\nimport { getCodexConfigSnapshot, saveCodexConfigContent } from \"./codex-config\";\nimport {\n getStoredLicense,\n readCodexSettingsJsonRaw,\n writeCodexSettingsJsonRaw,\n} from \"./codex-settings\";\nimport { getAppState, getUserDataDir, patchAppState } from \"./app-state\";\nimport { licenseService } from \"./license-service\";\nimport { logInfo, logWarn } from \"./logger\";\nimport { formatUserFacingError } from \"./errors\";\nimport type { CloudSyncRunResultPayload, CloudSyncStatusPayload } from \"./ipc-types\";\nimport { isRecord } from \"./type-guards\";\n\nconst SYNC_BACKUP_DIR = \"sync-backups\";\nconst PRE_PULL_BACKUP_PREFIX = \"pre-pull-\";\nconst PRE_PULL_BACKUP_SUFFIX = \".json\";\nconst PRE_PULL_BACKUP_KEEP_COUNT = 3;\nconst SYNC_SIZE_WARN_BYTES = 1 * 1024 * 1024;\nconst SYNC_SIZE_MAX_BYTES = 5 * 1024 * 1024;\nconst MB_DIVISOR = 1024 * 1024;\n\ninterface CloudSyncStateFile {\n lastPushAt?: string;\n lastPullAt?: string;\n lastError?: string;\n remoteUpdatedAt?: string;\n}\n\ntype Eligibility = {\n canSync: boolean;\n reason: string | null;\n licenseKey: string | null;\n licenseState: string | null;\n};\n\ntype BuildLocalSnapshotOptions = {\n enforcePushGuards?: boolean;\n};\n\nfunction mapProfilesFromAppState(raw: unknown): CloudSyncProfileRecord[] {\n if (!isRecord(raw)) {\n return [];\n }\n\n const profiles: CloudSyncProfileRecord[] = [];\n\n for (const [name, value] of Object.entries(raw)) {\n if (!isRecord(value)) {\n continue;\n }\n\n const data = isRecord(value.data) ? value.data : null;\n if (!data) {\n continue;\n }\n\n const normalizedName = typeof name === \"string\" ? name.trim() : \"\";\n if (!normalizedName) {\n continue;\n }\n\n profiles.push({\n name: normalizedName,\n displayName: typeof value.displayName === \"string\" ? value.displayName : null,\n data,\n metadata: isRecord(value.metadata) ? value.metadata : undefined,\n accountId: typeof value.accountId === \"string\" ? value.accountId : null,\n workspaceId: typeof value.workspaceId === \"string\" ? value.workspaceId : null,\n workspaceName: typeof value.workspaceName === \"string\" ? value.workspaceName : null,\n email: typeof value.email === \"string\" ? value.email : null,\n authMethod: typeof value.authMethod === \"string\" ? value.authMethod : null,\n createdAt: typeof value.createdAt === \"string\" ? value.createdAt : null,\n updatedAt: typeof value.updatedAt === \"string\" ? value.updatedAt : null,\n });\n }\n\n return profiles;\n}\n\nfunction summarizeSnapshot(snapshot: CloudSyncSnapshot): {\n profiles: number;\n configBytes: number;\n settingsKeys: number;\n} {\n const configBytes =\n typeof snapshot.configTomlContent === \"string\" ? snapshot.configTomlContent.length : 0;\n const settingsKeys =\n isRecord(snapshot.settingsJson) ? Object.keys(snapshot.settingsJson).length : 0;\n\n return {\n profiles: snapshot.profiles.length,\n configBytes,\n settingsKeys,\n };\n}\n\nasync function readState(): Promise<CloudSyncStateFile> {\n const state = await getAppState();\n return {\n lastPushAt: state.sync.lastPushAt ?? undefined,\n lastPullAt: state.sync.lastPullAt ?? undefined,\n lastError: state.sync.lastError ?? undefined,\n remoteUpdatedAt: state.sync.remoteUpdatedAt ?? undefined,\n };\n}\n\nasync function writeState(patch: Partial<CloudSyncStateFile>): Promise<void> {\n await patchAppState({\n sync: {\n ...(typeof patch.lastPushAt === \"string\" ? { lastPushAt: patch.lastPushAt } : {}),\n ...(typeof patch.lastPullAt === \"string\" ? { lastPullAt: patch.lastPullAt } : {}),\n ...(typeof patch.lastError === \"string\" ? { lastError: patch.lastError } : patch.lastError === undefined ? { lastError: null } : {}),\n ...(typeof patch.remoteUpdatedAt === \"string\"\n ? { remoteUpdatedAt: patch.remoteUpdatedAt }\n : {}),\n },\n });\n}\n\nasync function resolveEligibility(): Promise<Eligibility> {\n const stored = await getStoredLicense();\n const licenseKey = typeof stored?.licenseKey === \"string\" ? stored.licenseKey.trim() : \"\";\n\n if (!licenseKey) {\n return {\n canSync: false,\n reason: \"License key is required for cloud sync.\",\n licenseKey: null,\n licenseState: null,\n };\n }\n\n const status = await licenseService.getStatus();\n const active = status.state === \"active\" || status.state === \"grace\";\n if (!active) {\n return {\n canSync: false,\n reason: \"Cloud sync requires an active Pro license.\",\n licenseKey,\n licenseState: status.state,\n };\n }\n\n return {\n canSync: true,\n reason: null,\n licenseKey,\n licenseState: status.state,\n };\n}\n\nfunction formatMegabytes(bytes: number): string {\n return (bytes / MB_DIVISOR).toFixed(2);\n}\n\nfunction resolveSyncBackupsDir(): string {\n return path.join(getUserDataDir(), SYNC_BACKUP_DIR);\n}\n\nfunction toSafeIsoForFileName(iso: string): string {\n return iso.replace(/:/g, \"-\");\n}\n\nasync function pruneOldPrePullBackups(backupsDir: string): Promise<void> {\n const entries = await fs.readdir(backupsDir, { withFileTypes: true });\n const files = entries\n .filter(\n (entry) =>\n entry.isFile() &&\n entry.name.startsWith(PRE_PULL_BACKUP_PREFIX) &&\n entry.name.endsWith(PRE_PULL_BACKUP_SUFFIX),\n )\n .map((entry) => entry.name)\n .sort((a, b) => b.localeCompare(a));\n\n if (files.length <= PRE_PULL_BACKUP_KEEP_COUNT) {\n return;\n }\n\n for (const stale of files.slice(PRE_PULL_BACKUP_KEEP_COUNT)) {\n await fs.rm(path.join(backupsDir, stale), { force: true });\n }\n}\n\nasync function createPrePullBackup(profileManager: ProfileManager): Promise<string> {\n const snapshot = await buildLocalSnapshot(profileManager, {\n enforcePushGuards: false,\n });\n const backupsDir = resolveSyncBackupsDir();\n await fs.mkdir(backupsDir, { recursive: true });\n\n const timestamp = toSafeIsoForFileName(new Date().toISOString());\n const backupPath = path.join(\n backupsDir,\n `${PRE_PULL_BACKUP_PREFIX}${timestamp}${PRE_PULL_BACKUP_SUFFIX}`,\n );\n await fs.writeFile(backupPath, `${JSON.stringify(snapshot, null, 2)}\\n`, \"utf8\");\n await pruneOldPrePullBackups(backupsDir);\n\n logInfo(\"[cloud-sync] created pre-pull backup\", { backupPath });\n return backupPath;\n}\n\nasync function buildLocalSnapshot(\n profileManager: ProfileManager,\n options: BuildLocalSnapshotOptions = {},\n): Promise<CloudSyncSnapshot> {\n const enforcePushGuards = options.enforcePushGuards !== false;\n const profilesFromManager = await profileManager.exportProfilesForCloudSync();\n const state = await getAppState();\n const profilesFromState = mapProfilesFromAppState(state.profilesByName);\n const profiles = profilesFromManager.length > 0 ? profilesFromManager : profilesFromState;\n const config = await getCodexConfigSnapshot();\n const settingsJson = await readCodexSettingsJsonRaw();\n\n const hasProfiles = profiles.length > 0;\n const hasConfig = typeof config.content === \"string\" && config.content.trim().length > 0;\n const hasSettings = isRecord(settingsJson) && Object.keys(settingsJson).length > 0;\n\n if (enforcePushGuards && !hasProfiles && !hasConfig && !hasSettings) {\n throw new Error(\"Refusing to push an empty cloud sync snapshot.\");\n }\n\n const snapshot: CloudSyncSnapshot = {\n schemaVersion: CLOUD_SYNC_SCHEMA_VERSION,\n updatedAt: new Date().toISOString(),\n profiles,\n configTomlContent: config.exists ? config.content : null,\n settingsJson,\n };\n\n if (!enforcePushGuards) {\n return snapshot;\n }\n\n return snapshot;\n}\n\nasync function applyRemoteSnapshot(profileManager: ProfileManager, snapshot: CloudSyncSnapshot): Promise<void> {\n await profileManager.replaceProfilesFromCloudSync(snapshot.profiles ?? []);\n\n if (typeof snapshot.configTomlContent === \"string\") {\n await saveCodexConfigContent(snapshot.configTomlContent);\n }\n\n if (snapshot.settingsJson && isRecord(snapshot.settingsJson)) {\n await writeCodexSettingsJsonRaw(snapshot.settingsJson);\n } else {\n await writeCodexSettingsJsonRaw({});\n }\n}\n\nfunction toRunError(mode: \"push\" | \"pull\", error: unknown): CloudSyncRunResultPayload {\n const message = formatUserFacingError(error, {\n fallback: `Cloud sync ${mode} failed.`,\n });\n\n return {\n mode,\n status: \"error\",\n message,\n localUpdatedAt: null,\n remoteUpdatedAt: null,\n };\n}\n\nexport async function getCloudSyncStatus(): Promise<CloudSyncStatusPayload> {\n const eligibility = await resolveEligibility();\n const state = await readState();\n\n let remoteUpdatedAt: string | null = state.remoteUpdatedAt ?? null;\n if (eligibility.canSync && eligibility.licenseKey) {\n try {\n remoteUpdatedAt = await fetchRemoteSnapshotMeta(eligibility.licenseKey);\n } catch (error) {\n if (error instanceof CloudSyncClientError && error.status === 404) {\n try {\n const remote = await fetchRemoteSnapshot(eligibility.licenseKey);\n remoteUpdatedAt = remote?.updatedAt ?? null;\n } catch {\n // Keep status lightweight when remote endpoint is unavailable.\n }\n }\n // Keep status lightweight when remote endpoint is unavailable.\n }\n }\n\n return {\n canSync: eligibility.canSync,\n reason: eligibility.reason,\n licenseState: eligibility.licenseState,\n hasLicenseKey: Boolean(eligibility.licenseKey),\n lastPushAt: state.lastPushAt ?? null,\n lastPullAt: state.lastPullAt ?? null,\n lastError: state.lastError ?? null,\n remoteUpdatedAt,\n };\n}\n\nexport async function pushCloudSync(): Promise<CloudSyncRunResultPayload> {\n const eligibility = await resolveEligibility();\n if (!eligibility.canSync || !eligibility.licenseKey) {\n return {\n mode: \"push\",\n status: \"skipped\",\n message: eligibility.reason ?? \"Cloud sync unavailable.\",\n localUpdatedAt: null,\n remoteUpdatedAt: null,\n };\n }\n\n const profileManager = new ProfileManager();\n\n try {\n await profileManager.initialize();\n const localSnapshot = await buildLocalSnapshot(profileManager, { enforcePushGuards: true });\n const serializedSnapshot = JSON.stringify(localSnapshot);\n const snapshotBytes = Buffer.byteLength(serializedSnapshot, \"utf8\");\n if (snapshotBytes > SYNC_SIZE_WARN_BYTES) {\n logWarn(\"[cloud-sync] push snapshot is large\", {\n bytes: snapshotBytes,\n megabytes: formatMegabytes(snapshotBytes),\n });\n }\n if (snapshotBytes > SYNC_SIZE_MAX_BYTES) {\n throw new Error(\n `Snapshot too large to sync (${formatMegabytes(snapshotBytes)} MB). Reduce profiles or config size.`,\n );\n }\n if (process.env.NODE_ENV !== \"production\") {\n logInfo(\"[cloud-sync] push snapshot summary\", summarizeSnapshot(localSnapshot));\n }\n const remote = await pushRemoteSnapshot(eligibility.licenseKey, localSnapshot, {\n serializedSnapshot,\n });\n\n await writeState({\n lastPushAt: new Date().toISOString(),\n remoteUpdatedAt: remote.snapshot.updatedAt,\n lastError: undefined,\n });\n\n if (remote.status === \"stale\") {\n return {\n mode: \"push\",\n status: \"stale\",\n message: \"Remote cloud snapshot is newer. Pull first.\",\n localUpdatedAt: localSnapshot.updatedAt,\n remoteUpdatedAt: remote.snapshot.updatedAt,\n };\n }\n\n return {\n mode: \"push\",\n status: \"applied\",\n message: \"Cloud sync push completed.\",\n localUpdatedAt: localSnapshot.updatedAt,\n remoteUpdatedAt: remote.snapshot.updatedAt,\n };\n } catch (error) {\n const result = toRunError(\"push\", error);\n const lastError = error instanceof CloudSyncClientError ? error.message : result.message;\n await writeState({ lastError });\n return result;\n }\n}\n\nexport async function pullCloudSync(): Promise<CloudSyncRunResultPayload> {\n const eligibility = await resolveEligibility();\n if (!eligibility.canSync || !eligibility.licenseKey) {\n return {\n mode: \"pull\",\n status: \"skipped\",\n message: eligibility.reason ?? \"Cloud sync unavailable.\",\n localUpdatedAt: null,\n remoteUpdatedAt: null,\n };\n }\n\n const profileManager = new ProfileManager();\n\n try {\n await profileManager.initialize();\n const remote = await fetchRemoteSnapshot(eligibility.licenseKey);\n\n if (!remote) {\n return {\n mode: \"pull\",\n status: \"skipped\",\n message: \"No cloud snapshot found.\",\n localUpdatedAt: null,\n remoteUpdatedAt: null,\n };\n }\n\n let backupWarningSuffix = \"\";\n try {\n await createPrePullBackup(profileManager);\n } catch (backupError) {\n logWarn(\"[cloud-sync] pre-pull backup failed; continuing pull\", backupError);\n const reason = formatUserFacingError(backupError, { fallback: \"unknown error\" });\n backupWarningSuffix = ` Warning: pre-pull backup failed (${reason}).`;\n }\n await applyRemoteSnapshot(profileManager, remote);\n await writeState({\n lastPullAt: new Date().toISOString(),\n remoteUpdatedAt: remote.updatedAt,\n lastError: undefined,\n });\n\n return {\n mode: \"pull\",\n status: \"applied\",\n message: `Cloud sync pull completed.${backupWarningSuffix}`,\n localUpdatedAt: remote.updatedAt,\n remoteUpdatedAt: remote.updatedAt,\n };\n } catch (error) {\n const result = toRunError(\"pull\", error);\n const lastError = error instanceof CloudSyncClientError ? error.message : result.message;\n await writeState({ lastError });\n return result;\n }\n}\n","import type { ProfileData, ProfileMetadata } from \"./types\";\n\nexport const CLOUD_SYNC_SCHEMA_VERSION = 1 as const;\n\nexport interface CloudSyncProfileRecord {\n name: string;\n displayName: string | null;\n data: ProfileData;\n metadata?: ProfileMetadata;\n accountId: string | null;\n workspaceId: string | null;\n workspaceName: string | null;\n email: string | null;\n authMethod: string | null;\n createdAt: string | null;\n updatedAt: string | null;\n}\n\nexport interface CloudSyncSnapshot {\n schemaVersion: typeof CLOUD_SYNC_SCHEMA_VERSION;\n updatedAt: string;\n profiles: CloudSyncProfileRecord[];\n configTomlContent: string | null;\n settingsJson: Record<string, unknown> | null;\n}\n\nexport interface CloudSyncGetResponse {\n snapshot: CloudSyncSnapshot | null;\n}\n\nexport interface CloudSyncMetaResponse {\n updatedAt: string | null;\n}\n\nexport type CloudSyncPutStatus = \"applied\" | \"stale\";\n\nexport interface CloudSyncPutResponse {\n status: CloudSyncPutStatus;\n snapshot: CloudSyncSnapshot;\n}\n","export function isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function toIsoOrNull(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? null : new Date(parsed).toISOString();\n}\n","import {\n CLOUD_SYNC_SCHEMA_VERSION,\n type CloudSyncGetResponse,\n type CloudSyncMetaResponse,\n type CloudSyncPutResponse,\n type CloudSyncSnapshot,\n} from \"./cloud-sync-types\";\nimport { isRecord, toIsoOrNull } from \"./type-guards\";\n\nconst DEFAULT_CLOUD_SYNC_API_BASE_URL = \"https://api.codexuse.com\";\nconst CLOUD_SYNC_TIMEOUT_MS = 15_000;\n\nexport class CloudSyncClientError extends Error {\n readonly status: number | null;\n\n constructor(message: string, status: number | null = null) {\n super(message);\n this.name = \"CloudSyncClientError\";\n this.status = status;\n }\n}\n\nfunction normalizeBaseUrl(value: string): string {\n const trimmed = value.trim();\n return trimmed.endsWith(\"/\") ? trimmed.slice(0, -1) : trimmed;\n}\n\nexport function getCloudSyncApiBaseUrl(): string {\n const fromEnv = typeof process.env.CODEXUSE_API_BASE_URL === \"string\"\n ? process.env.CODEXUSE_API_BASE_URL\n : \"\";\n\n if (fromEnv.trim().length === 0) {\n return DEFAULT_CLOUD_SYNC_API_BASE_URL;\n }\n\n return normalizeBaseUrl(fromEnv);\n}\n\nfunction buildSyncUrl(pathname: string): string {\n const baseUrl = getCloudSyncApiBaseUrl();\n const normalizedPath = pathname.startsWith(\"/\") ? pathname : `/${pathname}`;\n return `${baseUrl}${normalizedPath}`;\n}\n\nfunction normalizeSnapshot(value: unknown): CloudSyncSnapshot | null {\n if (!isRecord(value)) {\n return null;\n }\n\n // Tolerate malformed legacy payloads where snapshot is nested one level:\n // { snapshot: { ...actualSnapshot } }\n if (isRecord(value.snapshot)) {\n const nested = normalizeSnapshot(value.snapshot);\n if (nested) {\n return nested;\n }\n }\n\n const updatedAt = toIsoOrNull(value.updatedAt);\n if (!updatedAt) {\n return null;\n }\n\n const schemaVersion = Number(value.schemaVersion);\n if (!Number.isFinite(schemaVersion) || schemaVersion !== CLOUD_SYNC_SCHEMA_VERSION) {\n return null;\n }\n\n const rawProfiles = Array.isArray(value.profiles) ? value.profiles : [];\n const profiles = rawProfiles\n .map((entry) => (isRecord(entry) ? entry : null))\n .filter((entry): entry is Record<string, unknown> => Boolean(entry))\n .map((entry) => {\n const data = isRecord(entry.data) ? entry.data : {};\n const metadata = isRecord(entry.metadata) ? entry.metadata : undefined;\n return {\n name: typeof entry.name === \"string\" ? entry.name : \"\",\n displayName: typeof entry.displayName === \"string\" ? entry.displayName : null,\n data,\n metadata,\n accountId: typeof entry.accountId === \"string\" ? entry.accountId : null,\n workspaceId: typeof entry.workspaceId === \"string\" ? entry.workspaceId : null,\n workspaceName: typeof entry.workspaceName === \"string\" ? entry.workspaceName : null,\n email: typeof entry.email === \"string\" ? entry.email : null,\n authMethod: typeof entry.authMethod === \"string\" ? entry.authMethod : null,\n createdAt: typeof entry.createdAt === \"string\" ? entry.createdAt : null,\n updatedAt: typeof entry.updatedAt === \"string\" ? entry.updatedAt : null,\n };\n })\n .filter((entry) => entry.name.trim().length > 0);\n\n const rawSettings = value.settingsJson;\n const settingsJson = isRecord(rawSettings) ? rawSettings : null;\n\n return {\n schemaVersion: CLOUD_SYNC_SCHEMA_VERSION,\n updatedAt,\n profiles,\n configTomlContent: typeof value.configTomlContent === \"string\" ? value.configTomlContent : null,\n settingsJson,\n };\n}\n\nasync function requestJson<T>(\n method: \"GET\" | \"PUT\",\n pathname: string,\n licenseKey: string,\n body?: unknown,\n rawBody?: string,\n): Promise<T> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), CLOUD_SYNC_TIMEOUT_MS);\n\n try {\n const response = await fetch(buildSyncUrl(pathname), {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-codexuse-license-key\": licenseKey,\n },\n body: typeof rawBody === \"string\"\n ? rawBody\n : body === undefined\n ? undefined\n : JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const message = await response.text().catch(() => \"\");\n throw new CloudSyncClientError(\n message || `Cloud sync request failed (${response.status}).`,\n response.status,\n );\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof CloudSyncClientError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new CloudSyncClientError(\"Cloud sync request timed out.\");\n }\n\n throw new CloudSyncClientError(\n error instanceof Error ? error.message : \"Cloud sync request failed.\",\n );\n } finally {\n clearTimeout(timeout);\n }\n}\n\nexport async function fetchRemoteSnapshot(licenseKey: string): Promise<CloudSyncSnapshot | null> {\n const response = await requestJson<CloudSyncGetResponse>(\"GET\", \"/v1/sync/snapshot\", licenseKey);\n return normalizeSnapshot(response.snapshot);\n}\n\nexport async function fetchRemoteSnapshotMeta(licenseKey: string): Promise<string | null> {\n const response = await requestJson<CloudSyncMetaResponse>(\n \"GET\",\n \"/v1/sync/snapshot/meta\",\n licenseKey,\n );\n return toIsoOrNull(response.updatedAt);\n}\n\nexport async function pushRemoteSnapshot(\n licenseKey: string,\n snapshot: CloudSyncSnapshot,\n options?: { serializedSnapshot?: string },\n): Promise<CloudSyncPutResponse> {\n const serializedSnapshot = typeof options?.serializedSnapshot === \"string\"\n ? options.serializedSnapshot\n : JSON.stringify(snapshot);\n const response = await requestJson<CloudSyncPutResponse>(\n \"PUT\",\n \"/v1/sync/snapshot\",\n licenseKey,\n undefined,\n `{\"snapshot\":${serializedSnapshot}}`,\n );\n\n const normalized = normalizeSnapshot(response.snapshot);\n if (!normalized) {\n throw new CloudSyncClientError(\"Cloud sync server returned an invalid snapshot payload.\");\n }\n\n const status = response.status === \"stale\" ? \"stale\" : \"applied\";\n return {\n status,\n snapshot: normalized,\n };\n}\n","import { mkdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parse, stringify } from \"@iarna/toml\";\nimport {\n getCodexConfigMetadata,\n type CodexConfigMetadata,\n type CodexFeatureStage,\n} from \"./codex-config-metadata\";\nimport { formatUserFacingError } from \"./errors\";\n\ntype RawConfig = Record<string, unknown>;\n\nexport type CodexDiagnosticCategory = \"feature\" | \"security\" | \"risk\" | \"config\";\nexport type CodexDiagnosticSeverity = \"info\" | \"warning\" | \"risk\";\n\nexport interface CodexConfigDiagnostic {\n id: string;\n category: CodexDiagnosticCategory;\n severity: CodexDiagnosticSeverity;\n title: string;\n message: string;\n fixId: string | null;\n fixLabel: string | null;\n}\n\nexport interface CodexConfigFeaturesSummary {\n unifiedExec: boolean | null;\n shellSnapshot: boolean | null;\n values: Record<string, boolean | null>;\n}\n\nexport interface CodexConfigToolsSummary {\n webSearch: boolean | null;\n viewImage: boolean | null;\n}\n\nexport interface CodexConfigNoticeSummary {\n hideFullAccessWarning: boolean | null;\n hideGpt51MigrationPrompt: boolean | null;\n hideLegacyGpt51CodexMaxMigrationPrompt: boolean | null;\n hideRateLimitModelNudge: boolean | null;\n modelMigrations: Record<string, string> | null;\n}\n\nexport interface CodexConfigSettingsSummary {\n model: string | null;\n reviewModel: string | null;\n modelReasoningEffort: string | null;\n modelReasoningSummary: string | null;\n modelVerbosity: string | null;\n approvalPolicy: string | null;\n sandboxMode: string | null;\n webSearch: string | null;\n personality: string | null;\n toolOutputTokenLimit: number | null;\n modelAutoCompactTokenLimit: number | null;\n modelContextWindow: number | null;\n features: CodexConfigFeaturesSummary;\n tools: CodexConfigToolsSummary;\n notice: CodexConfigNoticeSummary;\n}\n\nexport interface CodexConfigSnapshotPayload {\n path: string;\n exists: boolean;\n content: string;\n settings: CodexConfigSettingsSummary;\n mcpServers: McpServerConfig[];\n rmcpClientEnabled: boolean;\n parseError: string | null;\n isYoloPreset: boolean;\n updatedAt: number | null;\n metadata: CodexConfigMetadata;\n diagnostics: CodexConfigDiagnostic[];\n}\n\nexport interface CodexFeatureUpdateMap {\n [featureName: string]: boolean | null | undefined;\n unifiedExec?: boolean | null;\n shellSnapshot?: boolean | null;\n}\n\nexport interface CodexConfigUpdatePayload {\n model?: string | null;\n reviewModel?: string | null;\n modelReasoningEffort?: string | null;\n modelReasoningSummary?: string | null;\n modelVerbosity?: string | null;\n approvalPolicy?: string | null;\n sandboxMode?: string | null;\n webSearch?: string | null;\n personality?: string | null;\n toolOutputTokenLimit?: number | null;\n modelAutoCompactTokenLimit?: number | null;\n modelContextWindow?: number | null;\n features?: CodexFeatureUpdateMap;\n tools?: {\n webSearch?: boolean | null;\n viewImage?: boolean | null;\n };\n notice?: {\n hideFullAccessWarning?: boolean | null;\n hideGpt51MigrationPrompt?: boolean | null;\n hideLegacyGpt51CodexMaxMigrationPrompt?: boolean | null;\n hideRateLimitModelNudge?: boolean | null;\n modelMigrations?: Record<string, string> | null;\n };\n applyFixes?: string[] | null;\n}\n\nexport interface McpServerConfig {\n name: string;\n transport: \"stdio\" | \"http\" | \"sse\";\n enabled: boolean;\n command?: string | null;\n args?: string[] | null;\n cwd?: string | null;\n env?: Record<string, string> | null;\n envVars?: string[] | null;\n url?: string | null;\n bearerTokenEnvVar?: string | null;\n httpHeaders?: Record<string, string> | null;\n envHttpHeaders?: Record<string, string> | null;\n startupTimeoutSec?: number | null;\n toolTimeoutSec?: number | null;\n enabledTools?: string[] | null;\n disabledTools?: string[] | null;\n}\n\ntype ParsedResult = {\n data: RawConfig | null;\n error: string | null;\n};\n\nconst DEFAULT_CONFIG_TEMPLATE = [\n \"# ~/.codex/config.toml (managed by CodexUse)\",\n \"# Safe defaults with prompts and sandboxed access.\",\n \"# To enable full access, opt into the YOLO preset from settings.\",\n \"\",\n 'model = \"gpt-5.3-codex\"',\n 'review_model = \"gpt-5.3-codex\"',\n 'model_reasoning_effort = \"medium\"',\n 'model_reasoning_summary = \"auto\"',\n 'model_verbosity = \"medium\"',\n 'approval_policy = \"on-request\"',\n 'sandbox_mode = \"read-only\"',\n 'web_search = \"cached\"',\n \"\",\n].join(\"\\n\");\n\nconst SUPPORTED_REASONING_EFFORT = new Set([\"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"none\"]);\nconst CLI_SUPPORTED_REASONING_EFFORT = new Set([\"minimal\", \"low\", \"medium\", \"high\", \"none\"]);\n\nconst KNOWN_APPROVAL_POLICIES = new Set([\"untrusted\", \"on-failure\", \"on-request\", \"never\"]);\nconst KNOWN_SANDBOX_MODES = new Set([\"read-only\", \"workspace-write\", \"danger-full-access\"]);\n\nconst YOLO_PRESET: CodexConfigUpdatePayload = {\n model: \"gpt-5.3-codex\",\n reviewModel: \"gpt-5.3-codex\",\n modelReasoningEffort: \"xhigh\",\n modelReasoningSummary: \"detailed\",\n modelVerbosity: \"high\",\n approvalPolicy: \"never\",\n sandboxMode: \"danger-full-access\",\n webSearch: \"live\",\n personality: \"pragmatic\",\n toolOutputTokenLimit: 25_000,\n modelAutoCompactTokenLimit: 233_000,\n features: {\n unifiedExec: true,\n shellSnapshot: true,\n },\n notice: {\n hideFullAccessWarning: true,\n hideGpt51MigrationPrompt: true,\n hideRateLimitModelNudge: true,\n },\n};\n\nfunction resolveHomeDir(): string {\n const homeDir = process.env.HOME || process.env.USERPROFILE;\n if (!homeDir) {\n throw new Error(\"Unable to determine home directory for Codex config.\");\n }\n return homeDir;\n}\n\nfunction getConfigPath(): string {\n const homeDir = resolveHomeDir();\n return path.join(homeDir, \".codex\", \"config.toml\");\n}\n\nasync function ensureConfigDirExists(filePath: string): Promise<void> {\n const dir = path.dirname(filePath);\n await mkdir(dir, { recursive: true });\n}\n\nfunction normalizeLineEndings(content: string): string {\n return content.replace(/\\r\\n/g, \"\\n\");\n}\n\nfunction ensureTrailingNewline(content: string): string {\n return content.endsWith(\"\\n\") ? content : `${content}\\n`;\n}\n\nfunction tryParseToml(content: string): ParsedResult {\n try {\n const parsed = parse(content) as RawConfig;\n return { data: parsed ?? {}, error: null };\n } catch (error) {\n const maybe = error as Partial<{ line: number; column: number; col: number }>;\n const line = typeof maybe?.line === \"number\" ? maybe.line : null;\n const column = typeof maybe?.column === \"number\" ? maybe.column : typeof maybe?.col === \"number\" ? maybe.col : null;\n const location = line !== null ? `line ${line}${column !== null ? `, column ${column}` : \"\"}` : null;\n\n const friendly = formatUserFacingError(error, {\n fallback: \"Invalid config.toml syntax. Fix it and try again.\",\n maxLength: 180,\n });\n const message = location ? `${friendly} (near ${location}).` : friendly;\n return { data: null, error: message };\n }\n}\n\nfunction toStringOrNull(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction toBooleanOrNull(value: unknown): boolean | null {\n if (typeof value === \"boolean\") {\n return value;\n }\n return null;\n}\n\nfunction toNumberOrNull(value: unknown): number | null {\n if (typeof value !== \"number\") {\n return null;\n }\n return Number.isFinite(value) ? value : null;\n}\n\nfunction toStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value\n .map(entry => (typeof entry === \"string\" ? entry.trim() : \"\"))\n .filter(entry => entry.length > 0);\n}\n\nfunction toStringRecord(value: unknown): Record<string, string> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return {};\n }\n\n const result: Record<string, string> = {};\n for (const [key, raw] of Object.entries(value)) {\n if (typeof raw !== \"string\") {\n continue;\n }\n const normalizedKey = key.trim();\n const normalizedValue = raw.trim();\n if (!normalizedKey || !normalizedValue) {\n continue;\n }\n result[normalizedKey] = normalizedValue;\n }\n return result;\n}\n\nfunction buildSettingsSummary(data: RawConfig | null): CodexConfigSettingsSummary {\n const noticeCandidate = data && typeof data[\"notice\"] === \"object\" && data[\"notice\"] !== null\n ? (data[\"notice\"] as RawConfig)\n : null;\n\n const featuresCandidate =\n data && typeof data[\"features\"] === \"object\" && data[\"features\"] !== null && !Array.isArray(data[\"features\"])\n ? (data[\"features\"] as RawConfig)\n : null;\n\n const toolsCandidate =\n data && typeof data[\"tools\"] === \"object\" && data[\"tools\"] !== null && !Array.isArray(data[\"tools\"])\n ? (data[\"tools\"] as RawConfig)\n : null;\n\n const featureValues: Record<string, boolean | null> = {};\n if (featuresCandidate) {\n for (const [key, value] of Object.entries(featuresCandidate)) {\n featureValues[key] = toBooleanOrNull(value);\n }\n }\n\n const modelMigrationsRaw = noticeCandidate ? toStringRecord(noticeCandidate[\"model_migrations\"]) : {};\n\n return {\n model: data ? toStringOrNull(data[\"model\"]) : null,\n reviewModel: data ? toStringOrNull(data[\"review_model\"]) : null,\n modelReasoningEffort: data ? toStringOrNull(data[\"model_reasoning_effort\"]) : null,\n modelReasoningSummary: data ? toStringOrNull(data[\"model_reasoning_summary\"]) : null,\n modelVerbosity: data ? toStringOrNull(data[\"model_verbosity\"]) : null,\n approvalPolicy: data ? toStringOrNull(data[\"approval_policy\"]) : null,\n sandboxMode: data ? toStringOrNull(data[\"sandbox_mode\"]) : null,\n webSearch: data ? toStringOrNull(data[\"web_search\"]) : null,\n personality: data ? toStringOrNull(data[\"personality\"]) : null,\n toolOutputTokenLimit: data ? toNumberOrNull(data[\"tool_output_token_limit\"]) : null,\n modelAutoCompactTokenLimit: data ? toNumberOrNull(data[\"model_auto_compact_token_limit\"]) : null,\n modelContextWindow: data ? toNumberOrNull(data[\"model_context_window\"]) : null,\n features: {\n unifiedExec: featuresCandidate ? toBooleanOrNull(featuresCandidate[\"unified_exec\"]) : null,\n shellSnapshot: featuresCandidate ? toBooleanOrNull(featuresCandidate[\"shell_snapshot\"]) : null,\n values: featureValues,\n },\n tools: {\n webSearch: toolsCandidate ? toBooleanOrNull(toolsCandidate[\"web_search\"]) : null,\n viewImage: toolsCandidate ? toBooleanOrNull(toolsCandidate[\"view_image\"]) : null,\n },\n notice: {\n hideFullAccessWarning: noticeCandidate ? toBooleanOrNull(noticeCandidate[\"hide_full_access_warning\"]) : null,\n hideGpt51MigrationPrompt: noticeCandidate ? toBooleanOrNull(noticeCandidate[\"hide_gpt5_1_migration_prompt\"]) : null,\n hideLegacyGpt51CodexMaxMigrationPrompt: noticeCandidate\n ? toBooleanOrNull(noticeCandidate[\"hide_gpt-5.1-codex-max_migration_prompt\"])\n : null,\n hideRateLimitModelNudge: noticeCandidate ? toBooleanOrNull(noticeCandidate[\"hide_rate_limit_model_nudge\"]) : null,\n modelMigrations: Object.keys(modelMigrationsRaw).length > 0 ? modelMigrationsRaw : null,\n },\n };\n}\n\nfunction getUnsupportedReasoningEffort(\n data: RawConfig | null,\n allowed: Set<string> = SUPPORTED_REASONING_EFFORT,\n): string | null {\n if (!data || !Object.prototype.hasOwnProperty.call(data, \"model_reasoning_effort\")) {\n return null;\n }\n\n const raw = data[\"model_reasoning_effort\"];\n if (typeof raw !== \"string\") {\n return String(raw ?? \"\");\n }\n\n const value = raw.trim();\n if (!value) {\n return null;\n }\n\n return allowed.has(value) ? null : value;\n}\n\nfunction parseRmcpClientEnabled(data: RawConfig | null): boolean {\n const rawFeatures =\n data && typeof data[\"features\"] === \"object\" && data[\"features\"] !== null && !Array.isArray(data[\"features\"])\n ? (data[\"features\"] as RawConfig)\n : null;\n\n if (rawFeatures && typeof rawFeatures[\"rmcp_client\"] === \"boolean\") {\n return rawFeatures[\"rmcp_client\"] as boolean;\n }\n\n if (data && typeof data[\"experimental_use_rmcp_client\"] === \"boolean\") {\n return data[\"experimental_use_rmcp_client\"] as boolean;\n }\n\n return false;\n}\n\nfunction parseMcpServer(name: string, rawValue: unknown): McpServerConfig | null {\n if (typeof rawValue !== \"object\" || rawValue === null || Array.isArray(rawValue)) {\n return null;\n }\n const raw = rawValue as RawConfig;\n const typeValue = toStringOrNull(raw[\"type\"]);\n const command = toStringOrNull(raw[\"command\"]);\n const args = toStringArray(raw[\"args\"]);\n const env = toStringRecord(raw[\"env\"]);\n const envVars = toStringArray(raw[\"env_vars\"]);\n const cwd = toStringOrNull(raw[\"cwd\"]);\n const url = toStringOrNull(raw[\"url\"]);\n const bearerTokenEnvVar = toStringOrNull(raw[\"bearer_token_env_var\"]);\n const httpHeaders = toStringRecord(raw[\"http_headers\"]);\n const envHttpHeaders = toStringRecord(raw[\"env_http_headers\"]);\n const startupTimeoutSec = toNumberOrNull(raw[\"startup_timeout_sec\"]);\n const toolTimeoutSec = toNumberOrNull(raw[\"tool_timeout_sec\"]);\n const enabledTools = toStringArray(raw[\"enabled_tools\"]);\n const disabledTools = toStringArray(raw[\"disabled_tools\"]);\n const enabled = typeof raw[\"enabled\"] === \"boolean\" ? raw[\"enabled\"] : true;\n const transport: \"stdio\" | \"http\" | \"sse\" =\n typeValue === \"stdio\" || typeValue === \"http\" || typeValue === \"sse\"\n ? typeValue\n : url\n ? \"http\"\n : \"stdio\";\n\n return {\n name,\n transport,\n enabled,\n command,\n args: args.length > 0 ? args : null,\n cwd,\n env: Object.keys(env).length > 0 ? env : null,\n envVars: envVars.length > 0 ? envVars : null,\n url,\n bearerTokenEnvVar,\n httpHeaders: Object.keys(httpHeaders).length > 0 ? httpHeaders : null,\n envHttpHeaders: Object.keys(envHttpHeaders).length > 0 ? envHttpHeaders : null,\n startupTimeoutSec,\n toolTimeoutSec,\n enabledTools: enabledTools.length > 0 ? enabledTools : null,\n disabledTools: disabledTools.length > 0 ? disabledTools : null,\n };\n}\n\nfunction buildMcpServersList(data: RawConfig | null): McpServerConfig[] {\n const rawServers = data?.[\"mcp_servers\"];\n if (typeof rawServers !== \"object\" || rawServers === null || Array.isArray(rawServers)) {\n return [];\n }\n\n const servers: McpServerConfig[] = [];\n for (const [name, rawValue] of Object.entries(rawServers)) {\n const parsed = parseMcpServer(name, rawValue);\n if (parsed) {\n servers.push(parsed);\n }\n }\n return servers;\n}\n\nfunction getFeatureStage(metadata: CodexConfigMetadata, featureKey: string): CodexFeatureStage {\n const found = metadata.featureCatalog.find(entry => entry.key === featureKey);\n return found?.stage ?? \"unknown\";\n}\n\nfunction looksLikeSecretValue(value: string): boolean {\n const normalized = value.trim();\n if (normalized.length < 12) {\n return false;\n }\n if (/\\s/.test(normalized)) {\n return false;\n }\n if (!/^[A-Za-z0-9._:-]+$/.test(normalized)) {\n return false;\n }\n const hasLetters = /[A-Za-z]/.test(normalized);\n const hasNumbers = /\\d/.test(normalized);\n return hasLetters && hasNumbers;\n}\n\nfunction buildConfigDiagnostics(\n data: RawConfig | null,\n summary: CodexConfigSettingsSummary,\n mcpServers: McpServerConfig[],\n metadata: CodexConfigMetadata,\n): CodexConfigDiagnostic[] {\n const diagnostics: CodexConfigDiagnostic[] = [];\n\n const featureTable =\n data && typeof data[\"features\"] === \"object\" && data[\"features\"] !== null && !Array.isArray(data[\"features\"])\n ? (data[\"features\"] as RawConfig)\n : null;\n\n const knownTopLevelKeys = new Set(metadata.schemaTopLevelKeys);\n if (data) {\n for (const key of Object.keys(data)) {\n if (knownTopLevelKeys.has(key)) {\n continue;\n }\n diagnostics.push({\n id: `unknown-top-level:${key}`,\n category: \"config\",\n severity: \"warning\",\n title: `Unknown config key: ${key}`,\n message: `This top-level key is not in the known Codex schema and may be ignored by Codex CLI.`,\n fixId: null,\n fixLabel: null,\n });\n }\n }\n\n if (featureTable) {\n const knownFeatureKeys = new Set(metadata.schemaFeatureKeys);\n for (const [featureKey] of Object.entries(featureTable)) {\n if (!knownFeatureKeys.has(featureKey)) {\n diagnostics.push({\n id: `unknown-feature:${featureKey}`,\n category: \"feature\",\n severity: \"warning\",\n title: `Unknown feature flag: features.${featureKey}`,\n message: \"This feature is not recognized in the current schema. Keeping it is non-destructive, but it may do nothing.\",\n fixId: `remove-feature:${featureKey}`,\n fixLabel: \"Remove flag\",\n });\n continue;\n }\n\n const stage = getFeatureStage(metadata, featureKey);\n if (stage === \"deprecated\") {\n diagnostics.push({\n id: `deprecated-feature:${featureKey}`,\n category: \"feature\",\n severity: \"warning\",\n title: `Deprecated feature flag: features.${featureKey}`,\n message: \"Codex marks this feature as deprecated. Prefer removing it.\",\n fixId: `remove-feature:${featureKey}`,\n fixLabel: \"Remove deprecated flag\",\n });\n }\n }\n }\n\n for (const server of mcpServers) {\n if (server.transport === \"stdio\" && server.args) {\n for (let index = 0; index < server.args.length; index += 1) {\n const value = server.args[index] ?? \"\";\n if (/(api[-_]?key|token|secret)\\s*=\\s*/i.test(value)) {\n diagnostics.push({\n id: `mcp-secret-arg:${server.name}:${index}`,\n category: \"security\",\n severity: \"warning\",\n title: `Potential secret in MCP args (${server.name})`,\n message: \"Argument text appears to contain a literal token/API key. Move secrets to environment variables.\",\n fixId: null,\n fixLabel: null,\n });\n }\n }\n }\n\n if (server.httpHeaders) {\n for (const [header, headerValue] of Object.entries(server.httpHeaders)) {\n if (!looksLikeSecretValue(headerValue)) {\n continue;\n }\n diagnostics.push({\n id: `mcp-secret-header:${server.name}:${header}`,\n category: \"security\",\n severity: \"warning\",\n title: `Potential secret in MCP header (${server.name})`,\n message: `HTTP header '${header}' appears to contain a literal secret. Prefer env_http_headers or bearer_token_env_var.`,\n fixId: null,\n fixLabel: null,\n });\n }\n }\n }\n\n if (summary.approvalPolicy === \"never\" && summary.sandboxMode === \"danger-full-access\") {\n diagnostics.push({\n id: \"risk:yolo-combo\",\n category: \"risk\",\n severity: \"risk\",\n title: \"High-risk execution mode enabled\",\n message: \"approval_policy=never + sandbox_mode=danger-full-access removes approval and sandbox guardrails.\",\n fixId: null,\n fixLabel: null,\n });\n }\n\n return diagnostics;\n}\n\nfunction isYoloApplied(summary: CodexConfigSettingsSummary): boolean {\n return (\n summary.model === YOLO_PRESET.model &&\n summary.reviewModel === YOLO_PRESET.reviewModel &&\n summary.modelReasoningEffort === YOLO_PRESET.modelReasoningEffort &&\n summary.modelReasoningSummary === YOLO_PRESET.modelReasoningSummary &&\n summary.modelVerbosity === YOLO_PRESET.modelVerbosity &&\n summary.approvalPolicy === YOLO_PRESET.approvalPolicy &&\n summary.sandboxMode === YOLO_PRESET.sandboxMode &&\n summary.webSearch === YOLO_PRESET.webSearch &&\n summary.personality === YOLO_PRESET.personality &&\n summary.toolOutputTokenLimit === YOLO_PRESET.toolOutputTokenLimit &&\n summary.modelAutoCompactTokenLimit === YOLO_PRESET.modelAutoCompactTokenLimit &&\n summary.features.unifiedExec === true &&\n summary.features.shellSnapshot === true &&\n summary.notice.hideFullAccessWarning === true &&\n summary.notice.hideGpt51MigrationPrompt === true &&\n summary.notice.hideRateLimitModelNudge === true\n );\n}\n\nasync function readConfigContent(): Promise<{ exists: boolean; content: string }> {\n const configPath = getConfigPath();\n try {\n const content = await readFile(configPath, \"utf8\");\n return {\n exists: true,\n content: normalizeLineEndings(content),\n };\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return {\n exists: false,\n content: DEFAULT_CONFIG_TEMPLATE,\n };\n }\n throw error;\n }\n}\n\nasync function writeConfigContent(content: string): Promise<void> {\n const configPath = getConfigPath();\n await ensureConfigDirExists(configPath);\n const normalized = ensureTrailingNewline(normalizeLineEndings(content));\n await writeFile(configPath, normalized, \"utf8\");\n}\n\nasync function getUpdatedAt(configPath: string, exists: boolean): Promise<number | null> {\n if (!exists) {\n return null;\n }\n\n try {\n const stats = await stat(configPath);\n return stats.mtimeMs;\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n}\n\nasync function buildSnapshot(content: string, exists: boolean): Promise<CodexConfigSnapshotPayload> {\n const configPath = getConfigPath();\n const parsed = tryParseToml(content);\n const summary = buildSettingsSummary(parsed.data);\n const updatedAt = await getUpdatedAt(configPath, exists);\n const mcpServers = buildMcpServersList(parsed.data);\n const rmcpClientEnabled = parseRmcpClientEnabled(parsed.data);\n const metadata = await getCodexConfigMetadata();\n const diagnostics = parsed.error\n ? []\n : buildConfigDiagnostics(parsed.data, summary, mcpServers, metadata);\n\n return {\n path: configPath,\n exists,\n content,\n settings: summary,\n mcpServers,\n rmcpClientEnabled,\n parseError: parsed.error,\n isYoloPreset: parsed.error ? false : isYoloApplied(summary),\n updatedAt,\n metadata,\n diagnostics,\n };\n}\n\nfunction sanitizeString(value: string | null | undefined): string | null {\n if (value === null || value === undefined) {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction sanitizeNumber(value: number | null | undefined): number | null {\n if (value === undefined || value === null) {\n return null;\n }\n if (!Number.isFinite(value)) {\n throw new Error(\"Numeric value must be finite.\");\n }\n return value;\n}\n\nfunction normalizeStringArrayInput(values?: string[] | null): string[] | null {\n if (!values) {\n return null;\n }\n const normalized = values\n .map(value => sanitizeString(value))\n .filter((value): value is string => Boolean(value));\n return normalized.length > 0 ? normalized : null;\n}\n\nfunction normalizeStringRecordInput(record?: Record<string, string> | null): Record<string, string> | null {\n if (!record) {\n return null;\n }\n const normalized: Record<string, string> = {};\n for (const [key, value] of Object.entries(record)) {\n const normalizedKey = sanitizeString(key);\n const normalizedValue = sanitizeString(value);\n if (normalizedKey && normalizedValue) {\n normalized[normalizedKey] = normalizedValue;\n }\n }\n return Object.keys(normalized).length > 0 ? normalized : null;\n}\n\nfunction applySuggestedFixes(current: RawConfig, fixIds?: string[] | null): RawConfig {\n if (!fixIds || fixIds.length === 0) {\n return current;\n }\n\n let next: RawConfig = { ...current };\n\n for (const fixId of fixIds) {\n if (!fixId.startsWith(\"remove-feature:\")) {\n continue;\n }\n\n const featureKey = fixId.slice(\"remove-feature:\".length).trim();\n if (!featureKey) {\n continue;\n }\n\n const rawFeatures =\n typeof next[\"features\"] === \"object\" && next[\"features\"] !== null && !Array.isArray(next[\"features\"])\n ? { ...(next[\"features\"] as RawConfig) }\n : {};\n\n if (!Object.prototype.hasOwnProperty.call(rawFeatures, featureKey)) {\n continue;\n }\n\n delete rawFeatures[featureKey];\n if (Object.keys(rawFeatures).length === 0) {\n delete next[\"features\"];\n } else {\n next[\"features\"] = rawFeatures;\n }\n }\n\n return next;\n}\n\nfunction applyUpdatesToConfig(current: RawConfig, updates: CodexConfigUpdatePayload): RawConfig {\n const next: RawConfig = { ...current };\n\n const applyStringField = (key: string, candidate?: string | null) => {\n if (candidate === undefined) {\n return;\n }\n const normalized = sanitizeString(candidate);\n if (!normalized) {\n delete next[key];\n } else {\n next[key] = normalized;\n }\n };\n\n const applyNumberField = (key: string, candidate?: number | null) => {\n if (candidate === undefined) {\n return;\n }\n const normalized = sanitizeNumber(candidate);\n if (normalized === null) {\n delete next[key];\n } else {\n next[key] = normalized;\n }\n };\n\n applyStringField(\"model\", updates.model);\n applyStringField(\"review_model\", updates.reviewModel);\n applyStringField(\"model_reasoning_effort\", updates.modelReasoningEffort);\n applyStringField(\"model_reasoning_summary\", updates.modelReasoningSummary);\n applyStringField(\"model_verbosity\", updates.modelVerbosity);\n applyStringField(\"approval_policy\", updates.approvalPolicy);\n applyStringField(\"sandbox_mode\", updates.sandboxMode);\n applyStringField(\"web_search\", updates.webSearch);\n applyStringField(\"personality\", updates.personality);\n\n applyNumberField(\"tool_output_token_limit\", updates.toolOutputTokenLimit);\n applyNumberField(\"model_auto_compact_token_limit\", updates.modelAutoCompactTokenLimit);\n applyNumberField(\"model_context_window\", updates.modelContextWindow);\n\n if (updates.features) {\n const rawFeatures =\n typeof next[\"features\"] === \"object\" && next[\"features\"] !== null && !Array.isArray(next[\"features\"])\n ? { ...(next[\"features\"] as RawConfig) }\n : {};\n\n const applyFeatureField = (key: string, candidate: boolean | null | undefined) => {\n if (candidate === undefined) {\n return;\n }\n if (candidate === null) {\n delete rawFeatures[key];\n return;\n }\n rawFeatures[key] = candidate;\n };\n\n for (const [rawKey, candidate] of Object.entries(updates.features)) {\n const key = rawKey === \"unifiedExec\"\n ? \"unified_exec\"\n : rawKey === \"shellSnapshot\"\n ? \"shell_snapshot\"\n : rawKey;\n applyFeatureField(key, candidate);\n }\n\n if (Object.keys(rawFeatures).length === 0) {\n delete next[\"features\"];\n } else {\n next[\"features\"] = rawFeatures;\n }\n }\n\n if (updates.tools) {\n const rawTools =\n typeof next[\"tools\"] === \"object\" && next[\"tools\"] !== null && !Array.isArray(next[\"tools\"])\n ? { ...(next[\"tools\"] as RawConfig) }\n : {};\n\n const applyToolField = (key: string, candidate?: boolean | null) => {\n if (candidate === undefined) {\n return;\n }\n if (candidate === null) {\n delete rawTools[key];\n } else {\n rawTools[key] = candidate;\n }\n };\n\n applyToolField(\"web_search\", updates.tools.webSearch);\n applyToolField(\"view_image\", updates.tools.viewImage);\n\n if (Object.keys(rawTools).length === 0) {\n delete next[\"tools\"];\n } else {\n next[\"tools\"] = rawTools;\n }\n }\n\n if (updates.notice) {\n const rawNotice = next[\"notice\"];\n const currentNotice =\n rawNotice && typeof rawNotice === \"object\" && rawNotice !== null\n ? { ...(rawNotice as RawConfig) }\n : {};\n\n const applyBooleanField = (key: string, candidate?: boolean | null) => {\n if (candidate === undefined) {\n return;\n }\n if (candidate === null) {\n delete currentNotice[key];\n } else {\n currentNotice[key] = candidate;\n }\n };\n\n const applyRecordField = (key: string, candidate?: Record<string, string> | null) => {\n if (candidate === undefined) {\n return;\n }\n const normalized = normalizeStringRecordInput(candidate);\n if (!normalized) {\n delete currentNotice[key];\n } else {\n currentNotice[key] = normalized;\n }\n };\n\n applyBooleanField(\"hide_full_access_warning\", updates.notice.hideFullAccessWarning);\n applyBooleanField(\"hide_gpt5_1_migration_prompt\", updates.notice.hideGpt51MigrationPrompt);\n applyBooleanField(\n \"hide_gpt-5.1-codex-max_migration_prompt\",\n updates.notice.hideLegacyGpt51CodexMaxMigrationPrompt,\n );\n applyBooleanField(\"hide_rate_limit_model_nudge\", updates.notice.hideRateLimitModelNudge);\n applyRecordField(\"model_migrations\", updates.notice.modelMigrations);\n\n if (Object.keys(currentNotice).length === 0) {\n delete next[\"notice\"];\n } else {\n next[\"notice\"] = currentNotice;\n }\n }\n\n return applySuggestedFixes(next, updates.applyFixes);\n}\n\nfunction validateMcpServerName(name: string): string {\n const normalized = sanitizeString(name);\n if (!normalized) {\n throw new Error(\"MCP server name is required.\");\n }\n if (!/^[A-Za-z0-9._-]+$/.test(normalized)) {\n throw new Error(\"MCP server name must use letters, numbers, periods, underscores, or hyphens.\");\n }\n return normalized;\n}\n\nfunction applyMcpServerUpsert(\n current: RawConfig,\n server: McpServerConfig,\n rmcpClientEnabled?: boolean | null,\n): RawConfig {\n const name = validateMcpServerName(server.name);\n const next: RawConfig = { ...current };\n const rawServers =\n typeof next[\"mcp_servers\"] === \"object\" && next[\"mcp_servers\"] !== null && !Array.isArray(next[\"mcp_servers\"])\n ? { ...(next[\"mcp_servers\"] as RawConfig) }\n : {};\n\n const base =\n typeof rawServers[name] === \"object\" && rawServers[name] !== null && !Array.isArray(rawServers[name])\n ? { ...(rawServers[name] as RawConfig) }\n : {};\n\n const updated: RawConfig = { ...base };\n\n const setStringField = (key: string, value: string | null | undefined) => {\n const normalized = sanitizeString(value ?? null);\n if (!normalized) {\n delete updated[key];\n return;\n }\n updated[key] = normalized;\n };\n\n const setStringArrayField = (key: string, values: string[] | null | undefined) => {\n const normalized = normalizeStringArrayInput(values);\n if (!normalized) {\n delete updated[key];\n return;\n }\n updated[key] = normalized;\n };\n\n const setRecordField = (key: string, values: Record<string, string> | null | undefined) => {\n const normalized = normalizeStringRecordInput(values);\n if (!normalized) {\n delete updated[key];\n return;\n }\n updated[key] = normalized;\n };\n\n const setNumberField = (key: string, value: number | null | undefined) => {\n if (value === null || value === undefined) {\n delete updated[key];\n return;\n }\n if (!Number.isFinite(value)) {\n throw new Error(`Invalid numeric value for ${key}.`);\n }\n updated[key] = value;\n };\n\n updated[\"enabled\"] = Boolean(server.enabled);\n updated[\"type\"] = server.transport;\n setNumberField(\"startup_timeout_sec\", server.startupTimeoutSec);\n setNumberField(\"tool_timeout_sec\", server.toolTimeoutSec);\n setStringArrayField(\"enabled_tools\", server.enabledTools);\n setStringArrayField(\"disabled_tools\", server.disabledTools);\n\n if (server.transport !== \"stdio\") {\n setStringField(\"url\", server.url);\n if (!sanitizeString(server.url)) {\n throw new Error(\"HTTP/SSE MCP server requires a URL.\");\n }\n setStringField(\"bearer_token_env_var\", server.bearerTokenEnvVar);\n setRecordField(\"http_headers\", server.httpHeaders);\n setRecordField(\"env_http_headers\", server.envHttpHeaders);\n delete updated[\"command\"];\n delete updated[\"args\"];\n delete updated[\"env\"];\n delete updated[\"env_vars\"];\n delete updated[\"cwd\"];\n } else {\n setStringField(\"command\", server.command);\n if (!sanitizeString(server.command)) {\n throw new Error(\"STDIO MCP server requires a command.\");\n }\n setStringArrayField(\"args\", server.args);\n setRecordField(\"env\", server.env);\n setStringArrayField(\"env_vars\", server.envVars);\n setStringField(\"cwd\", server.cwd);\n delete updated[\"url\"];\n delete updated[\"bearer_token_env_var\"];\n delete updated[\"http_headers\"];\n delete updated[\"env_http_headers\"];\n }\n\n rawServers[name] = updated;\n if (Object.keys(rawServers).length > 0) {\n next[\"mcp_servers\"] = rawServers;\n } else {\n delete next[\"mcp_servers\"];\n }\n\n const rmcpEnabledValue = rmcpClientEnabled ?? parseRmcpClientEnabled(next);\n return applyRmcpClientFlag(next, rmcpEnabledValue);\n}\n\nfunction applyMcpServerRemoval(current: RawConfig, serverName: string): RawConfig {\n const name = validateMcpServerName(serverName);\n const next: RawConfig = { ...current };\n const rawServers =\n typeof next[\"mcp_servers\"] === \"object\" && next[\"mcp_servers\"] !== null && !Array.isArray(next[\"mcp_servers\"])\n ? { ...(next[\"mcp_servers\"] as RawConfig) }\n : {};\n\n if (!Object.prototype.hasOwnProperty.call(rawServers, name)) {\n return next;\n }\n\n delete rawServers[name];\n if (Object.keys(rawServers).length > 0) {\n next[\"mcp_servers\"] = rawServers;\n } else {\n delete next[\"mcp_servers\"];\n }\n return next;\n}\n\nfunction applyRmcpClientFlag(current: RawConfig, enabled: boolean): RawConfig {\n const next: RawConfig = { ...current };\n const rawFeatures =\n typeof next[\"features\"] === \"object\" && next[\"features\"] !== null && !Array.isArray(next[\"features\"])\n ? { ...(next[\"features\"] as RawConfig) }\n : {};\n\n if (enabled) {\n rawFeatures[\"rmcp_client\"] = true;\n } else {\n delete rawFeatures[\"rmcp_client\"];\n }\n\n if (Object.keys(rawFeatures).length > 0) {\n next[\"features\"] = rawFeatures;\n } else {\n delete next[\"features\"];\n }\n\n delete next[\"experimental_use_rmcp_client\"];\n return next;\n}\n\nasync function readParsedConfigOrThrow(): Promise<RawConfig> {\n const { content } = await readConfigContent();\n const parsed = tryParseToml(content);\n\n if (!parsed.data) {\n throw new Error(parsed.error ?? \"config.toml contains invalid TOML syntax.\");\n }\n\n return parsed.data;\n}\n\nexport async function getCodexConfigSnapshot(): Promise<CodexConfigSnapshotPayload> {\n const { content, exists } = await readConfigContent();\n return buildSnapshot(content, exists);\n}\n\nexport async function saveCodexConfigContent(content: string): Promise<CodexConfigSnapshotPayload> {\n const normalized = ensureTrailingNewline(normalizeLineEndings(content));\n const parsed = tryParseToml(normalized);\n if (!parsed.data) {\n throw new Error(parsed.error ?? \"config.toml contains invalid TOML syntax.\");\n }\n await writeConfigContent(normalized);\n return buildSnapshot(normalized, true);\n}\n\nexport async function updateCodexConfigValues(\n updates: CodexConfigUpdatePayload,\n): Promise<CodexConfigSnapshotPayload> {\n const parsed = await readParsedConfigOrThrow();\n const updated = applyUpdatesToConfig(parsed, updates);\n const serialized = ensureTrailingNewline(stringify(updated as Record<string, any>));\n await writeConfigContent(serialized);\n return buildSnapshot(serialized, true);\n}\n\nexport async function applyYoloOpinionatedMode(): Promise<CodexConfigSnapshotPayload> {\n return updateCodexConfigValues(YOLO_PRESET);\n}\n\nexport async function upsertMcpServer(\n server: McpServerConfig,\n options?: { rmcpClientEnabled?: boolean | null },\n): Promise<CodexConfigSnapshotPayload> {\n const parsed = await readParsedConfigOrThrow();\n const updated = applyMcpServerUpsert(parsed, server, options?.rmcpClientEnabled);\n const serialized = ensureTrailingNewline(stringify(updated as Record<string, any>));\n await writeConfigContent(serialized);\n return buildSnapshot(serialized, true);\n}\n\nexport async function removeMcpServer(serverName: string): Promise<CodexConfigSnapshotPayload> {\n const parsed = await readParsedConfigOrThrow();\n const updated = applyMcpServerRemoval(parsed, serverName);\n const serialized = ensureTrailingNewline(stringify(updated as Record<string, any>));\n await writeConfigContent(serialized);\n return buildSnapshot(serialized, true);\n}\n\nexport async function setRmcpClient(enabled: boolean): Promise<CodexConfigSnapshotPayload> {\n const parsed = await readParsedConfigOrThrow();\n const updated = applyRmcpClientFlag(parsed, enabled);\n const serialized = ensureTrailingNewline(stringify(updated as Record<string, any>));\n await writeConfigContent(serialized);\n return buildSnapshot(serialized, true);\n}\n\nexport async function sanitizeCodexConfigForCli(): Promise<(() => Promise<void>) | null> {\n const { content } = await readConfigContent();\n const parsed = tryParseToml(content);\n\n if (!parsed.data) {\n throw new Error(parsed.error ?? \"config.toml contains invalid TOML syntax.\");\n }\n\n const unsupportedReasoning = getUnsupportedReasoningEffort(parsed.data, CLI_SUPPORTED_REASONING_EFFORT);\n if (!unsupportedReasoning) {\n return null;\n }\n\n const sanitized = { ...(parsed.data as RawConfig) };\n delete sanitized[\"model_reasoning_effort\"];\n const sanitizedContent = ensureTrailingNewline(stringify(sanitized as Record<string, any>));\n await writeConfigContent(sanitizedContent);\n\n let restored = false;\n return async () => {\n if (restored) {\n return;\n }\n restored = true;\n const originalContent = ensureTrailingNewline(normalizeLineEndings(content));\n await writeConfigContent(originalContent);\n };\n}\n\nexport type { McpServerConfig };\n\nexport function isKnownApprovalPolicy(value: string | null): value is \"untrusted\" | \"on-failure\" | \"on-request\" | \"never\" {\n return Boolean(value && KNOWN_APPROVAL_POLICIES.has(value));\n}\n\nexport function isKnownSandboxMode(value: string | null): value is \"read-only\" | \"workspace-write\" | \"danger-full-access\" {\n return Boolean(value && KNOWN_SANDBOX_MODES.has(value));\n}\n","import { spawn } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { requireCodexCli } from \"./codex-cli\";\n\nexport type CodexFeatureStage = \"stable\" | \"experimental\" | \"under development\" | \"deprecated\" | \"unknown\";\n\nexport interface CodexFeatureCatalogEntry {\n key: string;\n stage: CodexFeatureStage;\n enabled: boolean | null;\n}\n\nexport interface CodexConfigMetadata {\n schemaTopLevelKeys: string[];\n schemaFeatureKeys: string[];\n featureCatalog: CodexFeatureCatalogEntry[];\n codexVersion: string | null;\n fetchedAt: number;\n}\n\nconst CONFIG_SCHEMA_URL = \"https://raw.githubusercontent.com/openai/codex/main/codex-rs/core/config.schema.json\";\nconst METADATA_CACHE_TTL_MS = 60_000;\n\nconst FALLBACK_SCHEMA_TOP_LEVEL_KEYS = [\n \"agents\",\n \"analytics\",\n \"approval_policy\",\n \"apps\",\n \"chatgpt_base_url\",\n \"check_for_update_on_startup\",\n \"cli_auth_credentials_store\",\n \"compact_prompt\",\n \"developer_instructions\",\n \"disable_paste_burst\",\n \"experimental_compact_prompt_file\",\n \"experimental_use_freeform_apply_patch\",\n \"experimental_use_unified_exec_tool\",\n \"features\",\n \"feedback\",\n \"file_opener\",\n \"forced_chatgpt_workspace_id\",\n \"forced_login_method\",\n \"ghost_snapshot\",\n \"hide_agent_reasoning\",\n \"history\",\n \"instructions\",\n \"log_dir\",\n \"mcp_oauth_callback_port\",\n \"mcp_oauth_credentials_store\",\n \"mcp_servers\",\n \"model\",\n \"model_auto_compact_token_limit\",\n \"model_context_window\",\n \"model_instructions_file\",\n \"model_provider\",\n \"model_providers\",\n \"model_reasoning_effort\",\n \"model_reasoning_summary\",\n \"model_supports_reasoning_summaries\",\n \"model_verbosity\",\n \"notice\",\n \"notify\",\n \"oss_provider\",\n \"otel\",\n \"personality\",\n \"profile\",\n \"profiles\",\n \"project_doc_fallback_filenames\",\n \"project_doc_max_bytes\",\n \"project_root_markers\",\n \"projects\",\n \"review_model\",\n \"sandbox_mode\",\n \"sandbox_workspace_write\",\n \"shell_environment_policy\",\n \"show_raw_agent_reasoning\",\n \"skills\",\n \"suppress_unstable_features_warning\",\n \"tool_output_token_limit\",\n \"tools\",\n \"tui\",\n \"web_search\",\n \"windows_wsl_setup_acknowledged\",\n];\n\nconst FALLBACK_FEATURE_KEYS = [\n \"apply_patch_freeform\",\n \"apps\",\n \"child_agents_md\",\n \"collab\",\n \"collaboration_modes\",\n \"connectors\",\n \"elevated_windows_sandbox\",\n \"enable_experimental_windows_sandbox\",\n \"enable_request_compression\",\n \"experimental_use_freeform_apply_patch\",\n \"experimental_use_unified_exec_tool\",\n \"experimental_windows_sandbox\",\n \"include_apply_patch_tool\",\n \"memory_tool\",\n \"personality\",\n \"powershell_utf8\",\n \"remote_models\",\n \"request_rule\",\n \"responses_websockets\",\n \"responses_websockets_v2\",\n \"runtime_metrics\",\n \"search_tool\",\n \"shell_snapshot\",\n \"shell_tool\",\n \"skill_env_var_dependency_prompt\",\n \"skill_mcp_dependency_install\",\n \"sqlite\",\n \"steer\",\n \"undo\",\n \"unified_exec\",\n \"use_linux_sandbox_bwrap\",\n \"web_search\",\n \"web_search_cached\",\n \"web_search_request\",\n];\n\nlet metadataCache: CodexConfigMetadata | null = null;\nlet metadataCacheAt = 0;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort((a, b) => a.localeCompare(b));\n}\n\nasync function runCommand(\n command: string,\n args: string[],\n timeoutMs = 3_000,\n): Promise<{ stdout: string; exitCode: number | null }> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: process.env,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", chunk => {\n stdout += chunk.toString();\n });\n\n child.stderr?.on(\"data\", chunk => {\n stderr += chunk.toString();\n });\n\n const timeout = setTimeout(() => {\n child.kill();\n reject(new Error(`Command timed out: ${command} ${args.join(\" \")}`));\n }, timeoutMs);\n\n child.on(\"error\", error => {\n clearTimeout(timeout);\n reject(error);\n });\n\n child.on(\"close\", code => {\n clearTimeout(timeout);\n if (code !== 0 && !stdout.trim() && stderr.trim()) {\n resolve({ stdout: stderr, exitCode: code });\n return;\n }\n resolve({ stdout, exitCode: code });\n });\n });\n}\n\nasync function runCodexCommand(args: string[]): Promise<{ stdout: string; exitCode: number | null }> {\n const codexPath = await requireCodexCli();\n const isJsLauncher = codexPath.endsWith(\".js\");\n const command = isJsLauncher ? process.execPath : codexPath;\n const commandArgs = isJsLauncher ? [codexPath, ...args] : args;\n return runCommand(command, commandArgs);\n}\n\nfunction parseFeatureCatalog(output: string): CodexFeatureCatalogEntry[] {\n const entries: CodexFeatureCatalogEntry[] = [];\n const lines = output.split(/\\r?\\n/).map(line => line.trim()).filter(Boolean);\n\n for (const line of lines) {\n const match = line.match(/^(\\S+)\\s+(stable|experimental|deprecated|under development)\\s+(true|false)$/i);\n if (!match) {\n continue;\n }\n const [, key, stageRaw, enabledRaw] = match;\n const stage = stageRaw.toLowerCase() as Exclude<CodexFeatureStage, \"unknown\">;\n entries.push({\n key,\n stage,\n enabled: enabledRaw === \"true\",\n });\n }\n\n return entries.sort((a, b) => a.key.localeCompare(b.key));\n}\n\nfunction parseSchemaKeys(schemaRaw: string): { topLevelKeys: string[]; featureKeys: string[] } {\n const parsed = JSON.parse(schemaRaw) as unknown;\n if (!isRecord(parsed)) {\n return {\n topLevelKeys: FALLBACK_SCHEMA_TOP_LEVEL_KEYS,\n featureKeys: FALLBACK_FEATURE_KEYS,\n };\n }\n\n const properties = isRecord(parsed.properties) ? parsed.properties : {};\n const topLevelKeys = uniqueSorted(Object.keys(properties));\n\n const features = isRecord(properties.features) ? properties.features : {};\n const featureProperties = isRecord(features.properties) ? features.properties : {};\n const featureKeys = uniqueSorted(Object.keys(featureProperties));\n\n return {\n topLevelKeys: topLevelKeys.length > 0 ? topLevelKeys : FALLBACK_SCHEMA_TOP_LEVEL_KEYS,\n featureKeys: featureKeys.length > 0 ? featureKeys : FALLBACK_FEATURE_KEYS,\n };\n}\n\nasync function readSchemaFromLocal(): Promise<string | null> {\n const candidates = [\n process.env.CODEX_CONFIG_SCHEMA_PATH,\n path.join(process.cwd(), \"codex-rs\", \"core\", \"config.schema.json\"),\n path.join(process.cwd(), \"node_modules\", \"@openai\", \"codex\", \"codex-rs\", \"core\", \"config.schema.json\"),\n ].filter((candidate): candidate is string => Boolean(candidate));\n\n for (const candidate of candidates) {\n try {\n return await readFile(candidate, \"utf8\");\n } catch {\n // Continue to next candidate.\n }\n }\n\n return null;\n}\n\nasync function readSchemaFromRemote(): Promise<string | null> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 2_500);\n\n try {\n const response = await fetch(CONFIG_SCHEMA_URL, {\n signal: controller.signal,\n headers: {\n \"User-Agent\": \"codexuse-desktop\",\n },\n });\n\n if (!response.ok) {\n return null;\n }\n\n return await response.text();\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nasync function readSchemaKeys(): Promise<{ topLevelKeys: string[]; featureKeys: string[] }> {\n const local = await readSchemaFromLocal();\n if (local) {\n try {\n return parseSchemaKeys(local);\n } catch {\n // Fallback to remote/fallback sets.\n }\n }\n\n const remote = await readSchemaFromRemote();\n if (remote) {\n try {\n return parseSchemaKeys(remote);\n } catch {\n // Fallback below.\n }\n }\n\n return {\n topLevelKeys: FALLBACK_SCHEMA_TOP_LEVEL_KEYS,\n featureKeys: FALLBACK_FEATURE_KEYS,\n };\n}\n\nasync function readCodexVersion(): Promise<string | null> {\n try {\n const { stdout } = await runCodexCommand([\"--version\"]);\n const value = stdout.trim();\n return value.length > 0 ? value : null;\n } catch {\n return null;\n }\n}\n\nasync function readFeatureCatalog(): Promise<CodexFeatureCatalogEntry[]> {\n try {\n const { stdout } = await runCodexCommand([\"features\", \"list\"]);\n return parseFeatureCatalog(stdout);\n } catch {\n return [];\n }\n}\n\nexport async function getCodexConfigMetadata(forceRefresh = false): Promise<CodexConfigMetadata> {\n const now = Date.now();\n if (!forceRefresh && metadataCache && (now - metadataCacheAt) < METADATA_CACHE_TTL_MS) {\n return metadataCache;\n }\n\n const [schemaKeys, featureCatalog, codexVersion] = await Promise.all([\n readSchemaKeys(),\n readFeatureCatalog(),\n readCodexVersion(),\n ]);\n\n const catalogMap = new Map<string, CodexFeatureCatalogEntry>();\n for (const entry of featureCatalog) {\n catalogMap.set(entry.key, entry);\n }\n\n for (const featureKey of schemaKeys.featureKeys) {\n if (!catalogMap.has(featureKey)) {\n catalogMap.set(featureKey, {\n key: featureKey,\n stage: \"unknown\",\n enabled: null,\n });\n }\n }\n\n const mergedFeatureCatalog = Array.from(catalogMap.values()).sort((a, b) => a.key.localeCompare(b.key));\n\n const metadata: CodexConfigMetadata = {\n schemaTopLevelKeys: uniqueSorted(schemaKeys.topLevelKeys),\n schemaFeatureKeys: uniqueSorted(schemaKeys.featureKeys),\n featureCatalog: mergedFeatureCatalog,\n codexVersion,\n fetchedAt: now,\n };\n\n metadataCache = metadata;\n metadataCacheAt = now;\n return metadata;\n}\n","import { readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { CodexCliInfoPayload, CodexCliStatusPayload } from \"./ipc-types\";\nimport type { CodexCliChannel } from \"./codex-cli-channel\";\n\ntype MutableStatus = CodexCliStatusPayload;\nconst STABLE_CHANNEL: CodexCliChannel = \"stable\";\nconst ENV_HINTS = [\"CODEX_BINARY\", \"CODEX_CLI_PATH\", \"CODEX_PATH\"] as const;\n\nlet cachedStatus: MutableStatus | null = null;\n\nfunction fileExists(candidate: string | undefined | null): string | null {\n if (!candidate) {\n return null;\n }\n\n const normalized = path.resolve(candidate);\n\n try {\n const stats = statSync(normalized);\n if (stats.isFile()) {\n return normalized;\n }\n } catch {\n // ignore missing paths\n }\n\n return null;\n}\n\nfunction resolveBundledCodexBinary(): string | null {\n const candidates: string[] = [];\n const processWithResources = process as NodeJS.Process & { resourcesPath?: string };\n const resourcesPath = processWithResources.resourcesPath;\n const packageSegments = [\"@openai\", \"codex\"];\n\n if (resourcesPath) {\n candidates.push(\n path.join(resourcesPath, \"app.asar.unpacked\", \"node_modules\", ...packageSegments, \"bin\", \"codex.js\"),\n );\n candidates.push(\n path.join(resourcesPath, \"app.asar.unpacked\", \"node_modules\", ...packageSegments, \"bin\", \"codex\"),\n );\n }\n\n const projectRoot = process.cwd();\n candidates.push(path.join(projectRoot, \"node_modules\", ...packageSegments, \"bin\", \"codex.js\"));\n candidates.push(path.join(projectRoot, \"node_modules\", ...packageSegments, \"bin\", \"codex\"));\n\n for (const candidate of candidates) {\n const resolved = fileExists(candidate);\n if (resolved) {\n return resolved;\n }\n }\n\n return null;\n}\n\nfunction isElectronRuntime(): boolean {\n return typeof process.versions?.electron === \"string\" && process.versions.electron.length > 0;\n}\n\nfunction resolveCodexFromEnv(): string | null {\n for (const key of ENV_HINTS) {\n const value = process.env[key];\n if (!value) {\n continue;\n }\n const resolved = fileExists(value);\n if (resolved) {\n return resolved;\n }\n }\n return null;\n}\n\nfunction resolveCodexFromNodeModules(): string | null {\n const packageSegments = [\"@openai\", \"codex\", \"bin\"];\n const fileNames = [\"codex.js\", \"codex\"];\n\n let current = path.resolve(__dirname);\n let last = \"\";\n while (current !== last) {\n for (const fileName of fileNames) {\n const candidate = fileExists(\n path.join(current, \"node_modules\", ...packageSegments, fileName),\n );\n if (candidate) {\n return candidate;\n }\n }\n last = current;\n current = path.dirname(current);\n }\n return null;\n}\n\nfunction resolveCodexFromPath(): string | null {\n const pathValue = process.env.PATH ?? \"\";\n if (!pathValue) {\n return null;\n }\n const entries = pathValue\n .split(path.delimiter)\n .map(entry => entry.trim())\n .filter(Boolean);\n const names = process.platform === \"win32\"\n ? [\"codex.exe\", \"codex.cmd\", \"codex.bat\", \"codex\"]\n : [\"codex\"];\n\n for (const entry of entries) {\n for (const name of names) {\n const candidate = fileExists(path.join(entry, name));\n if (candidate) {\n return candidate;\n }\n }\n }\n return null;\n}\n\nfunction resolvePackageJsonPath(cliPath: string): string | null {\n const normalized = path.resolve(cliPath);\n const binDir = path.dirname(normalized);\n const packageDir = path.basename(binDir) === \"bin\" ? path.dirname(binDir) : path.dirname(normalized);\n const pkgPath = path.join(packageDir, \"package.json\");\n return fileExists(pkgPath);\n}\n\nfunction readCodexCliVersion(cliPath: string): string | null {\n const packageJsonPath = resolvePackageJsonPath(cliPath);\n if (!packageJsonPath) {\n return null;\n }\n try {\n const raw = readFileSync(packageJsonPath, \"utf8\");\n const parsed = JSON.parse(raw) as { version?: unknown };\n if (typeof parsed?.version !== \"string\") {\n return null;\n }\n const normalized = parsed.version.trim();\n return normalized.length > 0 ? normalized : null;\n } catch {\n return null;\n }\n}\n\nfunction buildUnavailableStatus(reason?: string): MutableStatus {\n return {\n available: false,\n path: null,\n reason: reason ?? \"Codex CLI not found. Install @openai/codex or set CODEX_BINARY.\",\n source: null,\n channel: STABLE_CHANNEL,\n };\n}\n\nfunction evaluateBundledOnlyStatus(): MutableStatus {\n const resolvedPath = resolveBundledCodexBinary();\n if (resolvedPath) {\n return {\n available: true,\n path: resolvedPath,\n reason: null,\n source: \"bundled\",\n channel: STABLE_CHANNEL,\n };\n }\n\n return buildUnavailableStatus(\"Bundled Codex CLI is missing. Reinstall CodexUse.\");\n}\n\nfunction evaluateExternalStatus(): MutableStatus {\n const envPath = resolveCodexFromEnv();\n if (envPath) {\n return {\n available: true,\n path: envPath,\n reason: null,\n source: \"env\",\n channel: STABLE_CHANNEL,\n };\n }\n\n const nodeModulesPath = resolveCodexFromNodeModules();\n if (nodeModulesPath) {\n return {\n available: true,\n path: nodeModulesPath,\n reason: null,\n source: \"node_modules\",\n channel: STABLE_CHANNEL,\n };\n }\n\n const pathResolved = resolveCodexFromPath();\n if (pathResolved) {\n return {\n available: true,\n path: pathResolved,\n reason: null,\n source: \"path\",\n channel: STABLE_CHANNEL,\n };\n }\n\n return buildUnavailableStatus();\n}\n\nfunction evaluateCodexCliStatus(): MutableStatus {\n const bundledStatus = evaluateBundledOnlyStatus();\n if (bundledStatus.available) {\n return bundledStatus;\n }\n\n const externalStatus = evaluateExternalStatus();\n if (externalStatus.available) {\n return externalStatus;\n }\n\n // In Electron, keep a bundled-first failure reason when all fallbacks miss.\n if (isElectronRuntime()) {\n return bundledStatus;\n }\n\n return externalStatus;\n}\n\nexport async function refreshCodexStatus(): Promise<CodexCliStatusPayload> {\n cachedStatus = evaluateCodexCliStatus();\n return { ...cachedStatus };\n}\n\nexport async function getCodexCliStatus(): Promise<CodexCliStatusPayload> {\n if (!cachedStatus) {\n return refreshCodexStatus();\n }\n return { ...cachedStatus };\n}\n\nexport async function getCodexCliInfo(): Promise<CodexCliInfoPayload> {\n const status = await getCodexCliStatus();\n const version =\n status.available && status.path\n ? readCodexCliVersion(status.path)\n : null;\n return { ...status, version };\n}\n\nexport class CodexCliMissingError extends Error {\n readonly status: CodexCliStatusPayload;\n\n constructor(status: CodexCliStatusPayload, message?: string) {\n super(message ?? status.reason ?? \"Codex CLI is not available\");\n Object.setPrototypeOf(this, new.target.prototype);\n this.name = \"CodexCliMissingError\";\n this.status = { ...status };\n }\n}\n\nexport async function requireCodexCli(): Promise<string> {\n const status = await refreshCodexStatus();\n if (!status.available || !status.path) {\n throw new CodexCliMissingError(status);\n }\n return status.path;\n}\n","/* eslint-disable-next-line no-control-regex */\nconst ANSI_PATTERN = /\\u001B\\[[0-9;]*m/g;\n\nfunction stripAnsi(value: string): string {\n return value.replace(ANSI_PATTERN, \"\");\n}\n\nfunction normalizeWhitespace(value: string): string {\n return value.replace(/\\s+/g, \" \").trim();\n}\n\nexport function compactErrorText(value: string, maxLength = 220): string {\n if (!value) {\n return \"\";\n }\n const cleaned = normalizeWhitespace(stripAnsi(String(value)));\n if (!cleaned) {\n return \"\";\n }\n if (cleaned.length <= maxLength) {\n return cleaned;\n }\n return `${cleaned.slice(0, maxLength).trimEnd()}…`;\n}\n\nexport function formatUserFacingError(\n error: unknown,\n options: {\n fallback?: string;\n notFoundFallback?: string;\n maxLength?: number;\n } = {},\n): string {\n const fallback = options.fallback ?? \"Something went wrong. Please try again.\";\n if (error === null || typeof error === \"undefined\") {\n return fallback;\n }\n\n const rawMessage =\n typeof error === \"string\"\n ? error\n : error instanceof Error\n ? error.message\n : String(error);\n\n let cleaned = normalizeWhitespace(stripAnsi(rawMessage));\n if (!cleaned) {\n return fallback;\n }\n\n // Strip Electron IPC error prefix\n if (cleaned.startsWith(\"Error invoking remote method\")) {\n cleaned = cleaned.replace(/^Error invoking remote method '[^']+': Error: /, \"\");\n }\n\n const lower = cleaned.toLowerCase();\n\n if (options.notFoundFallback && (lower.includes(\"enoent\") || lower.includes(\"not found\"))) {\n return options.notFoundFallback;\n }\n\n if (lower.includes(\"rate limit\") || lower.includes(\"quota exceeded\") || lower.includes(\"too many requests\") || lower.includes(\"429\")) {\n cleaned = \"Rate limit exceeded. Please wait a moment or upgrade your plan.\";\n } else if (lower.includes(\"timeout\") || lower.includes(\"timed out\")) {\n cleaned = \"Request timed out. Check your connection and try again.\";\n } else if (\n lower.includes(\"network\") ||\n lower.includes(\"econn\") ||\n lower.includes(\"networkerror\") ||\n lower.includes(\"connection\")\n ) {\n cleaned = \"Network issue. Check your connection and retry.\";\n } else if (lower.includes(\"permission\") || lower.includes(\"eacces\")) {\n cleaned = \"Permission denied. Restart CodexUse and retry.\";\n } else if (lower.includes(\"openai codex\") && lower.includes(\"workdir:\")) {\n // If it's just the CLI banner, it's likely a generic failure or the actual error is buried.\n // We'll try to find a more specific error message within it, or default to a generic one.\n if (lower.includes(\"error:\")) {\n // Try to extract the part after \"error:\"\n const parts = cleaned.split(/error:/i);\n if (parts.length > 1) {\n cleaned = parts[parts.length - 1].trim();\n }\n } else {\n cleaned = \"Codex CLI failed to respond. Please try again.\";\n }\n }\n\n const maxLength = typeof options.maxLength === \"number\" ? options.maxLength : 220;\n if (cleaned.length > maxLength) {\n cleaned = `${cleaned.slice(0, maxLength).trimEnd()}…`;\n }\n\n return cleaned;\n}\n","import { licenseService, shouldEnforceProfileLimit } from \"./license-service\";\nimport { ProfileManager } from \"./profile-manager\";\n\nexport const PROJECT_LIMIT_MESSAGE =\n \"CodexUse Free supports up to 2 projects. Upgrade to CodexUse Pro for unlimited projects.\";\n\nexport async function assertProfileCreationAllowed(\n profileManager?: ProfileManager,\n): Promise<void> {\n const manager = profileManager ?? new ProfileManager();\n await manager.initialize();\n\n const license = await licenseService.getStatus();\n const profiles = await manager.listProfiles();\n const licenseWithCounts = licenseService.applyProfileCount(license, profiles.length);\n\n if (\n typeof licenseWithCounts.profileLimit === \"number\" &&\n licenseWithCounts.profilesRemaining !== null &&\n licenseWithCounts.profilesRemaining <= 0\n ) {\n throw new Error(\"CodexUse Free supports up to 2 profiles. Upgrade to CodexUse Pro for unlimited profiles.\");\n }\n}\n\ntype WorkspaceLike = {\n kind?: string | null;\n};\n\nfunction countMainProjects(workspaces: WorkspaceLike[]): number {\n return workspaces.filter((workspace) => (workspace.kind ?? \"main\") !== \"worktree\").length;\n}\n\nexport async function assertProjectCreationAllowed(\n workspaces: WorkspaceLike[],\n): Promise<void> {\n const license = await licenseService.getStatus();\n if (!shouldEnforceProfileLimit(license)) {\n return;\n }\n\n const mainProjectCount = countMainProjects(workspaces);\n if (mainProjectCount >= 2) {\n throw new Error(PROJECT_LIMIT_MESSAGE);\n }\n}\n","import { spawn } from \"node:child_process\";\nimport { statSync } from \"node:fs\";\nimport path from \"node:path\";\n\nconst ENV_HINTS = [\"CODEX_BINARY\", \"CODEX_CLI_PATH\", \"CODEX_PATH\"] as const;\n\nexport type CodexLoginMode = \"browser\" | \"device\";\n\nfunction fileExists(candidate: string | null | undefined): string | null {\n if (!candidate) return null;\n const resolved = path.resolve(candidate);\n try {\n const stat = statSync(resolved);\n if (stat.isFile()) return resolved;\n } catch {\n return null;\n }\n return null;\n}\n\nfunction resolveFromEnv(): string | null {\n for (const key of ENV_HINTS) {\n const value = process.env[key];\n if (!value) continue;\n const resolved = fileExists(value);\n if (resolved) return resolved;\n }\n return null;\n}\n\nfunction resolveFromPath(): string | null {\n const pathValue = process.env.PATH ?? \"\";\n const entries = pathValue.split(path.delimiter).filter(Boolean);\n const names = process.platform === \"win32\"\n ? [\"codex.exe\", \"codex.cmd\", \"codex.bat\", \"codex\"]\n : [\"codex\"];\n\n for (const entry of entries) {\n for (const name of names) {\n const candidate = fileExists(path.join(entry, name));\n if (candidate) return candidate;\n }\n }\n\n return null;\n}\n\nexport function resolveCodexBinary(): string | null {\n return (\n resolveFromEnv() ||\n resolveFromPath()\n );\n}\n\nexport function requireCodexBinary(context?: string): string {\n const resolved = resolveCodexBinary();\n if (resolved) return resolved;\n const hint = \"Install Codex CLI (npm i -g @openai/codex) or set CODEX_BINARY.\";\n const message = context ? `${context} ${hint}` : hint;\n throw new Error(message);\n}\n\nfunction buildCodexCommand(codexPath: string, args: string[]): { command: string; args: string[]; shell: boolean } {\n const normalized = codexPath.toLowerCase();\n const isJs = normalized.endsWith(\".js\");\n if (isJs) {\n return { command: process.execPath, args: [codexPath, ...args], shell: false };\n }\n\n const useShell = process.platform === \"win32\";\n return { command: codexPath, args, shell: useShell };\n}\n\nfunction isHeadless(): boolean {\n if (process.env.CODEXUSE_HEADLESS === \"1\") return true;\n if (process.env.CI) return true;\n if (process.env.SSH_CONNECTION || process.env.SSH_TTY) return true;\n if (process.platform === \"linux\") {\n if (!process.env.DISPLAY && !process.env.WAYLAND_DISPLAY) return true;\n }\n return false;\n}\n\nexport function resolveLoginMode(preferred?: CodexLoginMode | null): CodexLoginMode {\n if (preferred === \"browser\" || preferred === \"device\") {\n return preferred;\n }\n const envMode = process.env.CODEXUSE_LOGIN_MODE;\n if (envMode === \"browser\" || envMode === \"device\") {\n return envMode;\n }\n return isHeadless() ? \"device\" : \"browser\";\n}\n\nexport async function runCodexLogin(mode?: CodexLoginMode | null): Promise<void> {\n const codexPath = requireCodexBinary(\"Codex CLI is required to login.\");\n const resolvedMode = resolveLoginMode(mode ?? null);\n const loginArgs = resolvedMode === \"device\"\n ? [\"login\", \"--device-auth\"]\n : [\"login\"];\n const { command, args, shell } = buildCodexCommand(codexPath, loginArgs);\n\n const child = spawn(command, args, {\n stdio: \"inherit\",\n env: process.env,\n shell,\n });\n\n const exitCode = await new Promise<number>((resolve) => {\n child.on(\"close\", (code) => resolve(code ?? 0));\n });\n\n if (exitCode !== 0) {\n throw new Error(`Codex CLI login failed (exit code ${exitCode}).`);\n }\n}\n","import { spawn } from \"node:child_process\";\nimport readline from \"node:readline\";\nimport { promises as fs } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { requireCodexCli } from \"./codex-cli\";\nimport { logWarn } from \"./logger\";\nimport type { RateLimitSnapshot, RateLimitWindow } from \"./types\";\n\ntype RpcError = {\n code?: number;\n message?: string;\n data?: unknown;\n};\n\ntype RpcMessage = {\n id?: number | string | null;\n method?: string;\n result?: unknown;\n error?: RpcError;\n};\n\ntype RpcRateLimitWindow = {\n usedPercent?: number;\n windowDurationMins?: number;\n resetsAt?: number;\n};\n\ntype RpcRateLimitSnapshot = {\n primary?: RpcRateLimitWindow | null;\n secondary?: RpcRateLimitWindow | null;\n};\n\nconst RPC_TIMEOUT_MS = 10_000;\nconst MAX_STDERR_CAPTURE_CHARS = 32_768;\nconst REFRESH_TOKEN_REDEEMED_SNIPPET = \"refresh token was already used\";\n\ntype AuthRecord = {\n last_refresh?: unknown;\n access_token?: unknown;\n tokens?: {\n last_refresh?: unknown;\n access_token?: unknown;\n };\n};\n\nfunction parseTimestamp(value: unknown): number | null {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n return null;\n }\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? null : parsed;\n}\n\nfunction decodeJwtPayload(token: unknown): Record<string, unknown> | null {\n if (typeof token !== \"string\" || token.trim().length === 0) {\n return null;\n }\n\n const segments = token.split(\".\");\n if (segments.length < 2) {\n return null;\n }\n\n try {\n const payloadRaw = Buffer.from(segments[1], \"base64url\").toString(\"utf8\");\n const payload = JSON.parse(payloadRaw);\n return payload && typeof payload === \"object\" ? (payload as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\nfunction extractJwtIssuedAtMs(token: unknown): number | null {\n const payload = decodeJwtPayload(token);\n if (!payload) {\n return null;\n }\n\n const issuedAt = payload[\"iat\"];\n if (typeof issuedAt !== \"number\" || !Number.isFinite(issuedAt)) {\n return null;\n }\n\n return issuedAt * 1000;\n}\n\nfunction parseAuthRecord(content: string): AuthRecord | null {\n try {\n const parsed = JSON.parse(content);\n return parsed && typeof parsed === \"object\" ? (parsed as AuthRecord) : null;\n } catch {\n return null;\n }\n}\n\nfunction extractAuthRecencyMs(content: string): number | null {\n const parsed = parseAuthRecord(content);\n if (!parsed) {\n return null;\n }\n\n const rootLastRefresh = parseTimestamp(parsed.last_refresh);\n const nestedLastRefresh = parseTimestamp(parsed.tokens?.last_refresh);\n const rootAccessIssuedAt = extractJwtIssuedAtMs(parsed.access_token);\n const nestedAccessIssuedAt = extractJwtIssuedAtMs(parsed.tokens?.access_token);\n const candidates = [rootLastRefresh, nestedLastRefresh, rootAccessIssuedAt, nestedAccessIssuedAt]\n .filter((value): value is number => typeof value === \"number\" && Number.isFinite(value));\n\n if (candidates.length === 0) {\n return null;\n }\n\n return Math.max(...candidates);\n}\n\nfunction shouldWriteBackAuth(\n initialSourceAuth: string | null,\n currentSourceAuth: string | null,\n updatedAuth: string,\n): boolean {\n if (updatedAuth.trim().length === 0) {\n return false;\n }\n\n if (!currentSourceAuth) {\n return true;\n }\n\n if (currentSourceAuth === updatedAuth) {\n return false;\n }\n\n if (currentSourceAuth === initialSourceAuth) {\n return true;\n }\n\n const currentRecency = extractAuthRecencyMs(currentSourceAuth);\n const updatedRecency = extractAuthRecencyMs(updatedAuth);\n\n if (typeof updatedRecency === \"number\" && typeof currentRecency === \"number\") {\n return updatedRecency > currentRecency;\n }\n\n if (typeof updatedRecency === \"number\" && typeof currentRecency !== \"number\") {\n return true;\n }\n\n return false;\n}\n\nfunction inferRefreshFailureHint(stderrOutput: string): string | null {\n if (!stderrOutput) {\n return null;\n }\n\n const normalized = stderrOutput.toLowerCase();\n if (normalized.includes(REFRESH_TOKEN_REDEEMED_SNIPPET)) {\n return REFRESH_TOKEN_REDEEMED_SNIPPET;\n }\n\n return null;\n}\n\nasync function sendPayload(\n child: ReturnType<typeof spawn>,\n payload: Record<string, unknown>,\n): Promise<void> {\n child.stdin?.write(JSON.stringify(payload));\n child.stdin?.write(\"\\n\");\n}\n\nfunction isRpcResponseForRequest(message: RpcMessage, requestId: number): boolean {\n if (message.id !== requestId) {\n return false;\n }\n return (\n Object.prototype.hasOwnProperty.call(message, \"result\") ||\n Object.prototype.hasOwnProperty.call(message, \"error\")\n );\n}\n\nexport async function readRpcResponseById(\n rl: readline.Interface,\n requestId: number,\n timeoutMs: number,\n): Promise<RpcMessage> {\n return new Promise<RpcMessage>((resolve, reject) => {\n const timer = setTimeout(() => {\n cleanup();\n reject(new Error(\"codex RPC timed out\"));\n }, Math.max(1, timeoutMs));\n\n const cleanup = () => {\n clearTimeout(timer);\n rl.off(\"line\", onLine);\n rl.off(\"close\", onClose);\n };\n\n const onClose = () => {\n cleanup();\n reject(new Error(\"codex RPC stream closed before response\"));\n };\n\n const onLine = (line: string) => {\n let parsed: RpcMessage;\n try {\n parsed = JSON.parse(line) as RpcMessage;\n } catch {\n cleanup();\n reject(new Error(\"codex RPC returned malformed JSON\"));\n return;\n }\n\n if (!isRpcResponseForRequest(parsed, requestId)) {\n return;\n }\n\n cleanup();\n resolve(parsed);\n };\n\n rl.on(\"line\", onLine);\n rl.on(\"close\", onClose);\n });\n}\n\nfunction formatRpcError(method: string, error: RpcError): string {\n const codeText = typeof error.code === \"number\" ? ` (code ${error.code})` : \"\";\n const message =\n typeof error.message === \"string\" && error.message.trim().length > 0\n ? error.message.trim()\n : \"Unknown RPC error\";\n return `${method} failed${codeText}: ${message}`;\n}\n\nfunction toWindow(rpc?: RpcRateLimitWindow | null): RateLimitWindow | undefined {\n if (!rpc) return undefined;\n const usedPercent =\n typeof rpc.usedPercent === \"number\" && Number.isFinite(rpc.usedPercent)\n ? rpc.usedPercent\n : undefined;\n const windowMinutes =\n typeof rpc.windowDurationMins === \"number\" && Number.isFinite(rpc.windowDurationMins)\n ? rpc.windowDurationMins\n : undefined;\n\n let resetsAt: string | undefined;\n let resetsInSeconds: number | undefined;\n if (typeof rpc.resetsAt === \"number\" && Number.isFinite(rpc.resetsAt)) {\n const ms = rpc.resetsAt > 10_000_000_000 ? rpc.resetsAt : rpc.resetsAt * 1000;\n resetsAt = new Date(ms).toISOString();\n resetsInSeconds = Math.max(0, Math.round((ms - Date.now()) / 1000));\n }\n\n if (\n typeof usedPercent === \"undefined\" &&\n typeof windowMinutes === \"undefined\" &&\n typeof resetsAt === \"undefined\"\n ) {\n return undefined;\n }\n\n const window: RateLimitWindow = {};\n if (typeof usedPercent === \"number\") {\n window.usedPercent = usedPercent;\n }\n if (typeof windowMinutes === \"number\") {\n window.windowMinutes = windowMinutes;\n }\n if (typeof resetsAt === \"string\") {\n window.resetsAt = resetsAt;\n }\n if (typeof resetsInSeconds === \"number\") {\n window.resetsInSeconds = resetsInSeconds;\n }\n return window;\n}\n\nexport function parseRateLimitSnapshotFromRpcMessage(\n message: RpcMessage,\n): RateLimitSnapshot | null {\n if (message.error) {\n throw new Error(formatRpcError(\"account/rateLimits/read\", message.error));\n }\n\n const result = message.result as { rateLimits?: RpcRateLimitSnapshot } | undefined;\n const limits = result?.rateLimits;\n const primary = toWindow(limits?.primary ?? null);\n const secondary = toWindow(limits?.secondary ?? null);\n\n if (!primary && !secondary) {\n return null;\n }\n\n const snapshot: RateLimitSnapshot = {\n lastUpdated: new Date().toISOString(),\n source: \"codex-rpc\",\n };\n if (primary) {\n snapshot.primary = primary;\n }\n if (secondary) {\n snapshot.secondary = secondary;\n }\n return snapshot;\n}\n\nexport async function fetchRateLimitsViaRpc(\n envOverride?: NodeJS.ProcessEnv,\n options: { authPath?: string; codexPath?: string } = {},\n): Promise<RateLimitSnapshot | null> {\n const binaryPath = options.codexPath ?? await requireCodexCli();\n const tempHome = await fs.mkdtemp(path.join(os.tmpdir(), \"codex-rpc-\"));\n const tempAuthPath = path.join(tempHome, \"auth.json\");\n let initialSourceAuth: string | null = null;\n\n const sourceAuthPath =\n options.authPath ??\n (envOverride?.CODEX_HOME\n ? path.join(envOverride.CODEX_HOME, \"auth.json\")\n : path.join(\n envOverride?.HOME ?? process.env.HOME ?? process.env.USERPROFILE ?? os.homedir(),\n \".codex\",\n \"auth.json\",\n ));\n\n try {\n initialSourceAuth = await fs.readFile(sourceAuthPath, \"utf8\").catch(() => null);\n if (!initialSourceAuth) {\n return null;\n }\n await fs.writeFile(tempAuthPath, initialSourceAuth, \"utf8\");\n } catch {\n await fs.rm(tempHome, { recursive: true, force: true }).catch(() => {});\n return null;\n }\n\n const child = spawn(process.execPath, [binaryPath, \"-s\", \"read-only\", \"-a\", \"untrusted\", \"app-server\"], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: {\n ...process.env,\n ...(envOverride ?? {}),\n HOME: tempHome,\n USERPROFILE: tempHome,\n CODEX_HOME: tempHome,\n CODEX_TELEMETRY_LABEL: \"codex-rpc\",\n ELECTRON_RUN_AS_NODE: \"1\",\n },\n });\n\n const rl = readline.createInterface({\n input: child.stdout!,\n crlfDelay: Infinity,\n });\n let stderrOutput = \"\";\n child.stderr?.on(\"data\", chunk => {\n if (stderrOutput.length >= MAX_STDERR_CAPTURE_CHARS) {\n return;\n }\n const text = chunk.toString(\"utf8\");\n const remaining = MAX_STDERR_CAPTURE_CHARS - stderrOutput.length;\n stderrOutput += text.slice(0, Math.max(0, remaining));\n });\n\n try {\n await sendPayload(child, {\n id: 1,\n method: \"initialize\",\n params: { clientInfo: { name: \"codexuse\", version: \"0.0.0\" } },\n });\n const initializeResponse = await readRpcResponseById(rl, 1, RPC_TIMEOUT_MS);\n if (initializeResponse.error) {\n throw new Error(formatRpcError(\"initialize\", initializeResponse.error));\n }\n\n await sendPayload(child, { method: \"initialized\", params: {} });\n\n await sendPayload(child, { id: 2, method: \"account/rateLimits/read\", params: {} });\n const message = await readRpcResponseById(rl, 2, RPC_TIMEOUT_MS);\n if (message.error) {\n const base = formatRpcError(\"account/rateLimits/read\", message.error);\n const hint = inferRefreshFailureHint(stderrOutput);\n if (hint && !base.toLowerCase().includes(hint)) {\n throw new Error(`${base}; ${hint}`);\n }\n throw new Error(base);\n }\n\n return parseRateLimitSnapshotFromRpcMessage(message);\n } finally {\n child.kill();\n rl.close();\n try {\n const updatedAuth = await fs.readFile(tempAuthPath, \"utf8\");\n if (updatedAuth.trim().length > 0) {\n const currentSourceAuth = await fs.readFile(sourceAuthPath, \"utf8\").catch(() => null);\n if (shouldWriteBackAuth(initialSourceAuth, currentSourceAuth, updatedAuth)) {\n await fs.writeFile(sourceAuthPath, updatedAuth, \"utf8\");\n } else if (\n currentSourceAuth &&\n currentSourceAuth !== updatedAuth &&\n currentSourceAuth !== initialSourceAuth\n ) {\n logWarn(\"Skipped stale auth sync-back after rate-limit probe; source auth changed in flight.\", {\n sourceAuthPath,\n currentRecencyMs: extractAuthRecencyMs(currentSourceAuth),\n updatedRecencyMs: extractAuthRecencyMs(updatedAuth),\n });\n }\n }\n } catch {\n // Best effort: if auth sync-back fails, keep existing source auth.\n }\n await fs.rm(tempHome, { recursive: true, force: true }).catch(() => {});\n }\n}\n","import type { RateLimitSnapshot } from \"@/lib/types\";\n\ntype Notify = (payload: { title: string; body: string }) => void;\n\ninterface RateLimitNotifierOptions {\n notify: Notify;\n now?: () => number;\n approachThresholdPercent?: number;\n approachCooldownMs?: number;\n resetCooldownMs?: number;\n exhaustedThresholdPercent?: number;\n recoveryThresholdPercent?: number;\n}\n\nconst DEFAULT_APPROACH_THRESHOLD = 95;\nconst DEFAULT_APPROACH_COOLDOWN_MS = 30 * 60 * 1000; // 30 minutes\nconst DEFAULT_RESET_COOLDOWN_MS = 5 * 60 * 1000; // 5 minutes\nconst DEFAULT_EXHAUSTED_THRESHOLD = 98;\nconst DEFAULT_RECOVERY_THRESHOLD = 50;\nconst APPROACH_RENOTIFY_FLOOR_MS = 2 * 60 * 1000; // Prevents back-to-back alerts when windows jitter\nconst RESET_WINDOW_BUCKET_MS = 5 * 60 * 1000;\n\ninterface RateLimitState {\n lastSnapshot: RateLimitSnapshot | null;\n lastApproachWindow: string | null;\n lastApproachAt: number | null;\n lastResetAt: number | null;\n exhaustedWindow: string | null;\n}\n\nfunction pickResetsAt(snapshot: RateLimitSnapshot | null | undefined): string | null {\n if (!snapshot) {\n return null;\n }\n\n return snapshot.primary?.resetsAt ?? snapshot.secondary?.resetsAt ?? null;\n}\n\nexport function maxUsedPercent(snapshot: RateLimitSnapshot | null | undefined): number | null {\n if (!snapshot) {\n return null;\n }\n\n const candidates = [\n snapshot.primary?.usedPercent,\n snapshot.secondary?.usedPercent,\n ].filter((value): value is number => typeof value === \"number\" && Number.isFinite(value));\n\n if (candidates.length === 0) {\n return null;\n }\n\n return Math.max(...candidates);\n}\n\nfunction normalizeResetWindowKey(resetsAt: string | null | undefined): string | null {\n if (!resetsAt) {\n return null;\n }\n\n const parsed = Date.parse(resetsAt);\n if (Number.isNaN(parsed)) {\n return resetsAt;\n }\n\n const bucket = Math.floor(parsed / RESET_WINDOW_BUCKET_MS);\n return `reset-${bucket}`;\n}\n\nfunction formatResetWindow(snapshot: RateLimitSnapshot | null | undefined): string | null {\n const resetsInSeconds = snapshot?.primary?.resetsInSeconds ?? snapshot?.secondary?.resetsInSeconds ?? null;\n if (typeof resetsInSeconds !== \"number\" || Number.isNaN(resetsInSeconds)) {\n return null;\n }\n\n const minutes = Math.max(0, Math.round(resetsInSeconds / 60));\n if (minutes >= 120) {\n const hours = Math.round(minutes / 60);\n return `${hours}h`;\n }\n\n return `${minutes}m`;\n}\n\nexport class RateLimitNotifier {\n private readonly notify: Notify;\n private readonly now: () => number;\n private readonly approachThreshold: number;\n private readonly approachCooldownMs: number;\n private readonly resetCooldownMs: number;\n private readonly exhaustedThreshold: number;\n private readonly recoveryThreshold: number;\n\n private readonly states = new Map<string, RateLimitState>();\n\n constructor(options: RateLimitNotifierOptions) {\n this.notify = options.notify;\n this.now = options.now ?? (() => Date.now());\n this.approachThreshold = options.approachThresholdPercent ?? DEFAULT_APPROACH_THRESHOLD;\n this.approachCooldownMs = options.approachCooldownMs ?? DEFAULT_APPROACH_COOLDOWN_MS;\n this.resetCooldownMs = options.resetCooldownMs ?? DEFAULT_RESET_COOLDOWN_MS;\n this.exhaustedThreshold = options.exhaustedThresholdPercent ?? DEFAULT_EXHAUSTED_THRESHOLD;\n this.recoveryThreshold = options.recoveryThresholdPercent ?? DEFAULT_RECOVERY_THRESHOLD;\n }\n\n handleSnapshot(accountId: string, profileName: string, snapshot: RateLimitSnapshot | null | undefined): void {\n if (!accountId || !profileName) {\n return;\n }\n\n const state = this.states.get(accountId) ?? {\n lastSnapshot: null,\n lastApproachAt: null,\n lastApproachWindow: null,\n lastResetAt: null,\n exhaustedWindow: null,\n };\n\n const previousUsage = maxUsedPercent(state.lastSnapshot);\n const currentUsage = maxUsedPercent(snapshot);\n const previousWindow = pickResetsAt(state.lastSnapshot);\n const currentWindow = pickResetsAt(snapshot);\n const normalizedPreviousWindow = normalizeResetWindowKey(previousWindow);\n const normalizedCurrentWindow = normalizeResetWindowKey(currentWindow);\n const now = this.now();\n\n const wasExhausted =\n typeof previousUsage === \"number\" && previousUsage >= this.exhaustedThreshold;\n const currentWindowKey =\n normalizedCurrentWindow ??\n normalizedPreviousWindow ??\n currentWindow ??\n previousWindow ??\n \"unknown\";\n\n if (wasExhausted) {\n state.exhaustedWindow = normalizedPreviousWindow ?? state.exhaustedWindow ?? currentWindowKey;\n }\n\n // Reset notifications disabled - they're just noise. Nobody waits around for limits to reset.\n // Clear exhausted state silently so we can re-notify on next approach.\n if (this.shouldNotifyReset(state, currentUsage, currentWindowKey, previousWindow, now)) {\n state.lastResetAt = now;\n state.exhaustedWindow = null;\n state.lastApproachWindow = null;\n state.lastApproachAt = null;\n }\n\n if (\n typeof currentUsage === \"number\" &&\n currentUsage >= this.approachThreshold &&\n this.canNotifyApproach(state, currentWindowKey, now)\n ) {\n const windowText = formatResetWindow(snapshot);\n const body = windowText\n ? `${currentUsage}% used. Resets in ${windowText}.`\n : `${currentUsage}% used.`;\n this.notify({\n title: `${profileName} is nearing its limit`,\n body,\n });\n state.lastApproachWindow = currentWindowKey;\n state.lastApproachAt = now;\n }\n\n if (typeof currentUsage === \"number\" && currentUsage >= this.exhaustedThreshold) {\n state.exhaustedWindow = currentWindowKey;\n }\n\n state.lastSnapshot = snapshot ?? null;\n this.states.set(accountId, state);\n }\n\n private canNotifyApproach(state: RateLimitState, windowKey: string, now: number): boolean {\n if (!windowKey) {\n return false;\n }\n\n if (typeof state.lastApproachAt === \"number\" && now - state.lastApproachAt < APPROACH_RENOTIFY_FLOOR_MS) {\n return false;\n }\n\n if (state.lastApproachWindow !== windowKey) {\n return true;\n }\n\n if (typeof state.lastApproachAt !== \"number\") {\n return true;\n }\n\n return now - state.lastApproachAt >= this.approachCooldownMs;\n }\n\n private shouldNotifyReset(\n state: RateLimitState,\n currentUsage: number | null,\n currentWindowKey: string,\n previousWindow: string | null,\n now: number,\n ): boolean {\n if (!state.exhaustedWindow) {\n return false;\n }\n\n const windowChanged =\n Boolean(currentWindowKey) && currentWindowKey !== state.exhaustedWindow;\n const usageRecovered =\n typeof currentUsage === \"number\" && currentUsage <= this.recoveryThreshold && Boolean(previousWindow);\n\n if (!windowChanged && !usageRecovered) {\n return false;\n }\n\n if (typeof state.lastResetAt === \"number\" && now - state.lastResetAt < this.resetCooldownMs) {\n return false;\n }\n\n return true;\n }\n}\n","import { promises as fs, type Dirent } from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { normalizeAutoRollSettings, type AutoRollSettings } from \"./auto-roll-settings\";\nimport {\n getAppState,\n getUserDataDir,\n updateAppState,\n type AppState,\n type AppStatePatch,\n type ProfileRecordState,\n type SkillsInstallState,\n} from \"./app-state\";\nimport { LEGACY_LOCALSTORAGE_KEYS, type LegacyLocalStorageKey } from \"./legacy-localstorage-keys\";\nimport type { ProfileData, ProfileMetadata } from \"./types\";\nimport { logWarn } from \"./logger\";\n\nconst SQLITE_STORAGE_DIR = \".f86eb5e712267207\";\nconst LEGACY_SETTINGS_FILE = \"settings.json\";\nconst LEGACY_SETTINGS_BACKUP_FILE = \"settings.json.bak\";\nconst LEGACY_SYNC_STATE_FILE = \"sync-state.json\";\nconst LEGACY_PROFILE_HOMES_DIR = \"profile-homes\";\nconst LEGACY_SKILLS_DIR = \"skills\";\nconst LEGACY_SKILL_CACHE_DIR = \"skill-cache\";\nconst LEGACY_SKILLS_REPOS_FILE = \"repos.json\";\nconst LEGACY_SKILL_MANIFEST = \".codexuse-skill.json\";\nconst LEGACY_LICENSE_SECRET_FILE = \"license.secret\";\n\ntype LegacyLocalStorageMergeResult = {\n patch: AppStatePatch;\n consumedKeys: string[];\n skippedKeys: string[];\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asString(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction resolveHomeDir(): string {\n const home = process.env.HOME || process.env.USERPROFILE || os.homedir();\n if (!home) {\n throw new Error(\"HOME is not set.\");\n }\n return home;\n}\n\nfunction resolveCodexDir(): string {\n return path.join(resolveHomeDir(), \".codex\");\n}\n\nfunction resolveLegacyPath(...segments: string[]): string {\n return path.join(resolveCodexDir(), ...segments);\n}\n\nasync function readJsonFile(filePath: string): Promise<unknown> {\n const raw = await fs.readFile(filePath, \"utf8\");\n return JSON.parse(raw) as unknown;\n}\n\nasync function readJsonFileIfExists(filePath: string): Promise<unknown | null> {\n try {\n return await readJsonFile(filePath);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n}\n\nasync function copyDirectoryManual(source: string, destination: string): Promise<void> {\n await fs.mkdir(destination, { recursive: true });\n const entries = await fs.readdir(source, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = path.join(source, entry.name);\n const destPath = path.join(destination, entry.name);\n\n if (entry.isSymbolicLink()) {\n const linkTarget = await fs.readlink(srcPath);\n await fs.symlink(linkTarget, destPath).catch(error => {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n });\n continue;\n }\n\n if (entry.isDirectory()) {\n await copyDirectoryManual(srcPath, destPath);\n continue;\n }\n\n if (entry.isFile()) {\n await fs.copyFile(srcPath, destPath);\n }\n }\n}\n\nasync function copyDirIfExists(source: string, destination: string): Promise<void> {\n let stats: Awaited<ReturnType<typeof fs.stat>> | null = null;\n try {\n stats = await fs.stat(source);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return;\n }\n throw error;\n }\n\n if (!stats.isDirectory()) {\n return;\n }\n\n // Retry-safe migration: clear partial destination from prior failed runs.\n await fs.rm(destination, { recursive: true, force: true });\n await fs.mkdir(path.dirname(destination), { recursive: true });\n try {\n await fs.cp(source, destination, {\n recursive: true,\n errorOnExist: false,\n force: true,\n dereference: false,\n verbatimSymlinks: true,\n });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ERR_FS_CP_EINVAL\") {\n await copyDirectoryManual(source, destination);\n return;\n }\n throw error;\n }\n}\n\nasync function copyFileIfExists(\n source: string,\n destination: string,\n options?: { mode?: number },\n): Promise<void> {\n try {\n const sourceStat = await fs.stat(source);\n if (!sourceStat.isFile()) {\n return;\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return;\n }\n throw error;\n }\n\n try {\n const destinationStat = await fs.stat(destination);\n if (destinationStat.isFile()) {\n return;\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n\n await fs.mkdir(path.dirname(destination), { recursive: true });\n await fs.copyFile(source, destination);\n if (typeof options?.mode === \"number\") {\n await fs.chmod(destination, options.mode).catch(() => undefined);\n }\n}\n\nasync function cleanupCopiedSkillsMetadata(skillsDir: string): Promise<void> {\n await removeIfExists(path.join(skillsDir, LEGACY_SKILLS_REPOS_FILE));\n\n let entries: Dirent[] = [];\n try {\n entries = await fs.readdir(skillsDir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) {\n continue;\n }\n await removeIfExists(path.join(skillsDir, entry.name, LEGACY_SKILL_MANIFEST));\n }\n}\n\nasync function migrateLegacyDirectoriesToUserData(): Promise<void> {\n const userDataDir = getUserDataDir();\n const legacyCodexDir = resolveCodexDir();\n\n await copyDirIfExists(\n path.join(legacyCodexDir, LEGACY_PROFILE_HOMES_DIR),\n path.join(userDataDir, LEGACY_PROFILE_HOMES_DIR),\n );\n await copyDirIfExists(\n path.join(legacyCodexDir, LEGACY_SKILLS_DIR),\n path.join(userDataDir, LEGACY_SKILLS_DIR),\n );\n await copyDirIfExists(\n path.join(legacyCodexDir, LEGACY_SKILL_CACHE_DIR),\n path.join(userDataDir, LEGACY_SKILL_CACHE_DIR),\n );\n await copyFileIfExists(\n path.join(legacyCodexDir, LEGACY_LICENSE_SECRET_FILE),\n path.join(userDataDir, LEGACY_LICENSE_SECRET_FILE),\n { mode: 0o600 },\n );\n\n await cleanupCopiedSkillsMetadata(path.join(userDataDir, LEGACY_SKILLS_DIR));\n}\n\nfunction pickAutoRoll(raw: unknown): AutoRollSettings | null {\n if (!raw) {\n return null;\n }\n try {\n return normalizeAutoRollSettings(raw as Partial<AutoRollSettings>);\n } catch {\n return null;\n }\n}\n\nfunction parseLegacyLicense(raw: unknown): AppState[\"license\"] {\n if (!isRecord(raw)) {\n return {\n licenseKey: null,\n purchaseEmail: null,\n lastVerifiedAt: null,\n nextCheckAt: null,\n lastVerificationError: null,\n status: \"inactive\",\n signature: null,\n };\n }\n\n const statusCandidate = asString(raw.status);\n const status = [\"inactive\", \"active\", \"grace\", \"error\"].includes(statusCandidate ?? \"\")\n ? (statusCandidate as AppState[\"license\"][\"status\"])\n : \"inactive\";\n\n return {\n licenseKey: asString(raw.licenseKey ?? raw.license_key),\n purchaseEmail: asString(raw.purchaseEmail ?? raw.purchase_email),\n lastVerifiedAt: asString(raw.lastVerifiedAt ?? raw.last_verified_at),\n nextCheckAt: asString(raw.nextCheckAt ?? raw.next_check_at),\n lastVerificationError: asString(raw.lastVerificationError ?? raw.last_verification_error),\n status,\n signature: asString(raw.signature),\n };\n}\n\nfunction parseLegacyProfileRecord(name: string, raw: unknown): ProfileRecordState | null {\n if (!isRecord(raw)) {\n return null;\n }\n\n const dataRaw = raw.data;\n let data: ProfileData | null = null;\n if (isRecord(dataRaw)) {\n data = dataRaw as ProfileData;\n } else if (typeof dataRaw === \"string\") {\n try {\n data = JSON.parse(dataRaw) as ProfileData;\n } catch {\n data = null;\n }\n }\n\n if (!data) {\n return null;\n }\n\n return {\n name,\n displayName: asString(raw.displayName ?? raw.display_name) ?? name,\n data,\n metadata: isRecord(raw.metadata) ? (raw.metadata as ProfileMetadata) : undefined,\n accountId: asString(raw.accountId ?? raw.account_id),\n workspaceId: asString(raw.workspaceId ?? raw.workspace_id),\n workspaceName: asString(raw.workspaceName ?? raw.workspace_name),\n email: asString(raw.email),\n authMethod: asString(raw.authMethod ?? raw.auth_method),\n createdAt: asString(raw.createdAt ?? raw.created_at),\n updatedAt: asString(raw.updatedAt ?? raw.updated_at),\n };\n}\n\nasync function loadLegacySettingsPatch(): Promise<AppStatePatch> {\n const filePath = resolveLegacyPath(LEGACY_SETTINGS_FILE);\n const raw = await readJsonFileIfExists(filePath);\n if (!isRecord(raw)) {\n return {};\n }\n\n const autoRoll = pickAutoRoll(raw.autoRoll ?? raw.auto_roll);\n const license = parseLegacyLicense(raw.license ?? raw.license_data ?? raw.license_state);\n\n return {\n app: {\n lastAppVersion: asString(raw.lastAppVersion ?? raw.last_app_version),\n pendingUpdateVersion: asString(raw.pendingUpdateVersion ?? raw.pending_update_version),\n lastProfileName: asString(raw.lastProfileName ?? raw.last_profile_name),\n },\n license,\n autoRoll: autoRoll\n ? {\n enabled: autoRoll.enabled,\n warningThreshold: autoRoll.warningThreshold,\n switchThreshold: autoRoll.switchThreshold,\n }\n : undefined,\n };\n}\n\nasync function loadLegacySyncPatch(): Promise<AppStatePatch> {\n const filePath = resolveLegacyPath(LEGACY_SYNC_STATE_FILE);\n const raw = await readJsonFileIfExists(filePath);\n if (!isRecord(raw)) {\n return {};\n }\n\n return {\n sync: {\n lastPushAt: asString(raw.lastPushAt),\n lastPullAt: asString(raw.lastPullAt),\n lastError: asString(raw.lastError),\n remoteUpdatedAt: asString(raw.remoteUpdatedAt),\n },\n };\n}\n\nasync function loadLegacyProfilesPatch(): Promise<AppStatePatch> {\n const root = resolveLegacyPath(LEGACY_PROFILE_HOMES_DIR);\n let entries: Dirent[] = [];\n try {\n entries = await fs.readdir(root, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return {};\n }\n throw error;\n }\n\n const profilesByName: Record<string, ProfileRecordState> = {};\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) {\n continue;\n }\n const profileFile = path.join(root, entry.name, \"profile.json\");\n const raw = await readJsonFileIfExists(profileFile);\n if (!raw) {\n continue;\n }\n\n const parsed = parseLegacyProfileRecord(entry.name, raw);\n if (!parsed) {\n continue;\n }\n\n profilesByName[entry.name] = parsed;\n }\n\n if (Object.keys(profilesByName).length === 0) {\n return {};\n }\n\n return { profilesByName };\n}\n\nfunction parseSkillInstallMetadata(raw: unknown): SkillsInstallState | null {\n if (!isRecord(raw)) {\n return null;\n }\n\n const id = asString(raw.id);\n if (!id) {\n return null;\n }\n\n return {\n id,\n repo: asString(raw.repo),\n repoPath: asString(raw.repoPath),\n sourceLabel: asString(raw.sourceLabel),\n sourceType:\n raw.sourceType === \"official\" || raw.sourceType === \"community\" || raw.sourceType === \"local\"\n ? raw.sourceType\n : undefined,\n viewUrl: asString(raw.viewUrl),\n createdAt: asString(raw.createdAt),\n };\n}\n\nasync function loadLegacySkillsPatch(): Promise<AppStatePatch> {\n const skillsRoot = resolveLegacyPath(LEGACY_SKILLS_DIR);\n const reposPath = path.join(skillsRoot, LEGACY_SKILLS_REPOS_FILE);\n const reposRaw = await readJsonFileIfExists(reposPath);\n\n const installsBySlug: Record<string, SkillsInstallState> = {};\n let dirEntries: Array<Dirent> = [];\n\n try {\n dirEntries = await fs.readdir(skillsRoot, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n\n for (const entry of dirEntries) {\n if (!entry.isDirectory()) {\n continue;\n }\n if (entry.name.startsWith(\".\")) {\n continue;\n }\n const manifestPath = path.join(skillsRoot, entry.name, LEGACY_SKILL_MANIFEST);\n const manifestRaw = await readJsonFileIfExists(manifestPath);\n const parsed = parseSkillInstallMetadata(manifestRaw);\n if (!parsed) {\n continue;\n }\n installsBySlug[entry.name] = parsed;\n }\n\n const sources = isRecord(reposRaw) && Array.isArray(reposRaw.sources)\n ? (reposRaw.sources as AppState[\"skills\"][\"sources\"])\n : [];\n\n if (sources.length === 0 && Object.keys(installsBySlug).length === 0) {\n return {};\n }\n\n return {\n skills: {\n sources,\n installsBySlug,\n },\n };\n}\n\nfunction mergeLegacyLocalStoragePatch(payload: Record<string, unknown>): LegacyLocalStorageMergeResult {\n const patch: AppStatePatch = {};\n const consumedKeys = new Set<string>();\n const skippedKeys = new Set<string>();\n const legacyPayloadKeys = new Set<LegacyLocalStorageKey>(\n Object.keys(payload).filter((key): key is LegacyLocalStorageKey =>\n (LEGACY_LOCALSTORAGE_KEYS as readonly string[]).includes(key),\n ),\n );\n const hasKey = (key: LegacyLocalStorageKey) => legacyPayloadKeys.has(key);\n const markSkippedIfPresent = (key: LegacyLocalStorageKey, consumed: boolean) => {\n if (!hasKey(key)) {\n return;\n }\n if (consumed) {\n consumedKeys.add(key);\n } else {\n skippedKeys.add(key);\n }\n };\n\n const settingsStorage = payload[\"settings-storage\"];\n if (isRecord(settingsStorage)) {\n const nextExcludeFolders = Array.isArray(settingsStorage.excludeFolders)\n ? (settingsStorage.excludeFolders.filter(item => typeof item === \"string\") as string[])\n : undefined;\n const nextBeep =\n typeof settingsStorage.enableTaskCompleteBeep === \"boolean\"\n ? settingsStorage.enableTaskCompleteBeep\n : undefined;\n const nextSleep =\n typeof settingsStorage.preventSleepDuringTasks === \"boolean\"\n ? settingsStorage.preventSleepDuringTasks\n : undefined;\n patch.preferences = {\n excludeFolders: nextExcludeFolders,\n enableTaskCompleteBeep: nextBeep,\n preventSleepDuringTasks: nextSleep,\n };\n markSkippedIfPresent(\n \"settings-storage\",\n nextExcludeFolders !== undefined || nextBeep !== undefined || nextSleep !== undefined,\n );\n } else {\n markSkippedIfPresent(\"settings-storage\", false);\n }\n\n const provider = payload.provider;\n if (isRecord(provider)) {\n const list = Array.isArray(provider.providers)\n ? (provider.providers\n .filter(isRecord)\n .map(item => ({\n id: asString(item.id) ?? \"\",\n name: asString(item.name) ?? \"\",\n models: Array.isArray(item.models)\n ? (item.models.filter(model => typeof model === \"string\") as string[])\n : [],\n apiKey: asString(item.apiKey) ?? undefined,\n baseUrl: asString(item.baseUrl) ?? undefined,\n }))\n .filter(item => item.id && item.name) as AppState[\"providers\"][\"list\"])\n : undefined;\n\n const overridesByPath = isRecord(provider.selectionsByCwd)\n ? (provider.selectionsByCwd as AppState[\"providers\"][\"overridesByPath\"])\n : undefined;\n\n patch.providers = {\n list,\n selectedProviderId: asString(provider.selectedProviderId) ?? undefined,\n defaultModel: asString(provider.defaultModel ?? provider.selectedModel),\n defaultReasoningEffort:\n typeof provider.defaultReasoningEffort === \"string\"\n ? (provider.defaultReasoningEffort as AppState[\"providers\"][\"defaultReasoningEffort\"])\n : typeof provider.reasoningEffort === \"string\"\n ? (provider.reasoningEffort as AppState[\"providers\"][\"defaultReasoningEffort\"])\n : undefined,\n overridesByPath,\n };\n markSkippedIfPresent(\n \"provider\",\n list !== undefined ||\n asString(provider.selectedProviderId) !== null ||\n asString(provider.defaultModel ?? provider.selectedModel) !== null ||\n typeof provider.defaultReasoningEffort === \"string\" ||\n typeof provider.reasoningEffort === \"string\" ||\n overridesByPath !== undefined,\n );\n } else {\n markSkippedIfPresent(\"provider\", false);\n }\n\n const sandbox = payload[\"sandbox-storage\"];\n if (isRecord(sandbox)) {\n const defaultMode = asString(sandbox.defaultMode ?? sandbox.mode) ?? undefined;\n const defaultApprovalPolicy =\n asString(sandbox.defaultApprovalPolicy ?? sandbox.approvalPolicy) ?? undefined;\n const overridesByPath = isRecord(sandbox.selectionsByCwd)\n ? (sandbox.selectionsByCwd as AppState[\"sandbox\"][\"overridesByPath\"])\n : undefined;\n patch.sandbox = {\n defaultMode,\n defaultApprovalPolicy,\n overridesByPath,\n };\n markSkippedIfPresent(\n \"sandbox-storage\",\n defaultMode !== undefined || defaultApprovalPolicy !== undefined || overridesByPath !== undefined,\n );\n } else {\n markSkippedIfPresent(\"sandbox-storage\", false);\n }\n\n const projectSettings = payload[\"project-settings-storage\"];\n if (isRecord(projectSettings) && isRecord(projectSettings.settingsByPath)) {\n patch.workspaceSettingsByPath = projectSettings.settingsByPath as AppState[\"workspaceSettingsByPath\"];\n markSkippedIfPresent(\"project-settings-storage\", true);\n } else {\n markSkippedIfPresent(\"project-settings-storage\", false);\n }\n\n const folder = payload[\"folder-storage\"];\n if (isRecord(folder)) {\n const folderHistory = Array.isArray(folder.folderHistory)\n ? (folder.folderHistory.filter(isRecord) as AppState[\"preferences\"][\"folderHistory\"])\n : undefined;\n const pinnedPaths = Array.isArray(folder.pinnedPaths)\n ? (folder.pinnedPaths.filter(item => typeof item === \"string\") as string[])\n : undefined;\n patch.preferences = {\n ...(patch.preferences ?? {}),\n folderHistory,\n pinnedPaths,\n };\n markSkippedIfPresent(\"folder-storage\", folderHistory !== undefined || pinnedPaths !== undefined);\n } else {\n markSkippedIfPresent(\"folder-storage\", false);\n }\n\n const categories = payload[\"conversation-categories-storage\"];\n let consumedCategories = false;\n if (isRecord(categories)) {\n if (isRecord(categories.categoriesByCwd)) {\n patch.conversationCategoriesByCwd =\n categories.categoriesByCwd as AppState[\"conversationCategoriesByCwd\"];\n consumedCategories = true;\n }\n if (isRecord(categories.conversationCategoryByCwd)) {\n patch.conversationCategoryAssignmentsByCwd =\n categories.conversationCategoryByCwd as AppState[\"conversationCategoryAssignmentsByCwd\"];\n consumedCategories = true;\n }\n }\n markSkippedIfPresent(\"conversation-categories-storage\", consumedCategories);\n\n const legacyAutoRoll = payload[\"codex:auto-roll-settings\"];\n const autoRoll = pickAutoRoll(legacyAutoRoll);\n if (autoRoll) {\n patch.autoRoll = {\n enabled: autoRoll.enabled,\n warningThreshold: autoRoll.warningThreshold,\n switchThreshold: autoRoll.switchThreshold,\n };\n markSkippedIfPresent(\"codex:auto-roll-settings\", true);\n } else {\n markSkippedIfPresent(\"codex:auto-roll-settings\", false);\n }\n\n return {\n patch,\n consumedKeys: Array.from(consumedKeys),\n skippedKeys: Array.from(skippedKeys),\n };\n}\n\nasync function removeIfExists(target: string): Promise<void> {\n await fs.rm(target, { recursive: true, force: true });\n}\n\nasync function cleanupLegacyCanonicalSources(): Promise<void> {\n const homeDir = resolveHomeDir();\n\n await removeIfExists(path.join(homeDir, SQLITE_STORAGE_DIR));\n await removeIfExists(resolveLegacyPath(LEGACY_SETTINGS_FILE));\n await removeIfExists(resolveLegacyPath(LEGACY_SETTINGS_BACKUP_FILE));\n await removeIfExists(resolveLegacyPath(LEGACY_SYNC_STATE_FILE));\n await removeIfExists(resolveLegacyPath(LEGACY_LICENSE_SECRET_FILE));\n await removeIfExists(resolveLegacyPath(LEGACY_SKILLS_DIR, LEGACY_SKILLS_REPOS_FILE));\n\n const profileHomesRoot = resolveLegacyPath(LEGACY_PROFILE_HOMES_DIR);\n try {\n const profileHomes = await fs.readdir(profileHomesRoot, { withFileTypes: true });\n for (const profileHome of profileHomes) {\n if (!profileHome.isDirectory()) {\n continue;\n }\n const profileDir = path.join(profileHomesRoot, profileHome.name);\n let files: string[] = [];\n try {\n files = await fs.readdir(profileDir);\n } catch {\n continue;\n }\n for (const file of files) {\n if (!file.startsWith(\"profile.json\")) {\n continue;\n }\n await removeIfExists(path.join(profileDir, file));\n }\n }\n } catch (error) {\n // cleanup is best-effort; log for diagnostics without failing migration\n logWarn(\"Failed cleaning legacy profile metadata:\", {\n profileHomesRoot,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n\n const skillsRoot = resolveLegacyPath(LEGACY_SKILLS_DIR);\n try {\n const skillDirs = await fs.readdir(skillsRoot, { withFileTypes: true });\n for (const entry of skillDirs) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) {\n continue;\n }\n await removeIfExists(path.join(skillsRoot, entry.name, LEGACY_SKILL_MANIFEST));\n }\n } catch (error) {\n // cleanup is best-effort; log for diagnostics without failing migration\n logWarn(\"Failed cleaning legacy skills metadata:\", {\n skillsRoot,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n}\n\nexport async function runStorageMigrationV1(): Promise<AppState> {\n const current = await getAppState();\n if (current.migration.status === \"complete\" || current.migration.status === \"pending_local_storage\") {\n return current;\n }\n\n const startedAt = new Date().toISOString();\n\n try {\n await migrateLegacyDirectoriesToUserData();\n const patches = await Promise.all([\n loadLegacySettingsPatch(),\n loadLegacySyncPatch(),\n loadLegacyProfilesPatch(),\n loadLegacySkillsPatch(),\n ]);\n\n const mergedPatch: AppStatePatch = patches.reduce((acc, patch) => {\n return {\n ...acc,\n ...patch,\n app: { ...(acc.app ?? {}), ...(patch.app ?? {}) },\n license: { ...(acc.license ?? {}), ...(patch.license ?? {}) },\n autoRoll: { ...(acc.autoRoll ?? {}), ...(patch.autoRoll ?? {}) },\n providers: { ...(acc.providers ?? {}), ...(patch.providers ?? {}) },\n sandbox: { ...(acc.sandbox ?? {}), ...(patch.sandbox ?? {}) },\n preferences: { ...(acc.preferences ?? {}), ...(patch.preferences ?? {}) },\n sync: { ...(acc.sync ?? {}), ...(patch.sync ?? {}) },\n profilesByName: { ...(acc.profilesByName ?? {}), ...(patch.profilesByName ?? {}) },\n workspaceSettingsByPath: {\n ...(acc.workspaceSettingsByPath ?? {}),\n ...(patch.workspaceSettingsByPath ?? {}),\n },\n conversationCategoriesByCwd: {\n ...(acc.conversationCategoriesByCwd ?? {}),\n ...(patch.conversationCategoriesByCwd ?? {}),\n },\n conversationCategoryAssignmentsByCwd: {\n ...(acc.conversationCategoryAssignmentsByCwd ?? {}),\n ...(patch.conversationCategoryAssignmentsByCwd ?? {}),\n },\n skills: {\n ...(acc.skills ?? {}),\n ...(patch.skills ?? {}),\n sources: patch.skills?.sources ?? acc.skills?.sources,\n installsBySlug: {\n ...(acc.skills?.installsBySlug ?? {}),\n ...(patch.skills?.installsBySlug ?? {}),\n },\n },\n };\n }, {} as AppStatePatch);\n\n return await updateAppState((state) => ({\n ...state,\n ...mergedPatch,\n app: { ...state.app, ...(mergedPatch.app ?? {}) },\n license: { ...state.license, ...(mergedPatch.license ?? {}) },\n autoRoll: { ...state.autoRoll, ...(mergedPatch.autoRoll ?? {}) },\n providers: {\n ...state.providers,\n ...(mergedPatch.providers ?? {}),\n overridesByPath: {\n ...state.providers.overridesByPath,\n ...(mergedPatch.providers?.overridesByPath ?? {}),\n },\n },\n sandbox: {\n ...state.sandbox,\n ...(mergedPatch.sandbox ?? {}),\n overridesByPath: {\n ...state.sandbox.overridesByPath,\n ...(mergedPatch.sandbox?.overridesByPath ?? {}),\n },\n },\n preferences: { ...state.preferences, ...(mergedPatch.preferences ?? {}) },\n sync: { ...state.sync, ...(mergedPatch.sync ?? {}) },\n profilesByName: {\n ...state.profilesByName,\n ...(mergedPatch.profilesByName ?? {}),\n },\n workspaceSettingsByPath: {\n ...state.workspaceSettingsByPath,\n ...(mergedPatch.workspaceSettingsByPath ?? {}),\n },\n conversationCategoriesByCwd: {\n ...state.conversationCategoriesByCwd,\n ...(mergedPatch.conversationCategoriesByCwd ?? {}),\n },\n conversationCategoryAssignmentsByCwd: {\n ...state.conversationCategoryAssignmentsByCwd,\n ...(mergedPatch.conversationCategoryAssignmentsByCwd ?? {}),\n },\n skills: {\n ...state.skills,\n ...(mergedPatch.skills ?? {}),\n installsBySlug: {\n ...state.skills.installsBySlug,\n ...(mergedPatch.skills?.installsBySlug ?? {}),\n },\n },\n migration: {\n ...state.migration,\n status: \"pending_local_storage\",\n startedAt: state.migration.startedAt ?? startedAt,\n completedAt: null,\n localStorageImportedAt: null,\n lastError: null,\n },\n }), {\n mode: \"replace\",\n allowBeforeMigrationComplete: true,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n await updateAppState((state) => ({\n ...state,\n migration: {\n ...state.migration,\n status: \"pending\",\n startedAt: state.migration.startedAt ?? startedAt,\n lastError: message,\n },\n }), {\n mode: \"replace\",\n allowBeforeMigrationComplete: true,\n });\n throw error;\n }\n}\n\nexport async function importLegacyLocalStorageOnce(\n payload: Record<string, unknown>,\n): Promise<{ completed: boolean; importedKeys: string[]; skippedKeys?: string[] }> {\n const current = await getAppState();\n if (current.migration.status === \"complete\") {\n return { completed: true, importedKeys: [], skippedKeys: [] };\n }\n\n if (current.migration.status !== \"pending_local_storage\") {\n return { completed: false, importedKeys: [], skippedKeys: [] };\n }\n\n if (!payload || !isRecord(payload)) {\n return { completed: false, importedKeys: [], skippedKeys: [] };\n }\n\n const { patch, consumedKeys, skippedKeys } = mergeLegacyLocalStoragePatch(payload);\n\n const completedAt = new Date().toISOString();\n const next = await updateAppState((state) => {\n if (state.migration.status !== \"pending_local_storage\") {\n return state;\n }\n\n return {\n ...state,\n ...patch,\n app: { ...state.app, ...(patch.app ?? {}) },\n autoRoll: { ...state.autoRoll, ...(patch.autoRoll ?? {}) },\n license: { ...state.license, ...(patch.license ?? {}) },\n providers: {\n ...state.providers,\n ...(patch.providers ?? {}),\n overridesByPath: {\n ...state.providers.overridesByPath,\n ...(patch.providers?.overridesByPath ?? {}),\n },\n },\n sandbox: {\n ...state.sandbox,\n ...(patch.sandbox ?? {}),\n overridesByPath: {\n ...state.sandbox.overridesByPath,\n ...(patch.sandbox?.overridesByPath ?? {}),\n },\n },\n preferences: { ...state.preferences, ...(patch.preferences ?? {}) },\n workspaceSettingsByPath: {\n ...state.workspaceSettingsByPath,\n ...(patch.workspaceSettingsByPath ?? {}),\n },\n conversationCategoriesByCwd: {\n ...state.conversationCategoriesByCwd,\n ...(patch.conversationCategoriesByCwd ?? {}),\n },\n conversationCategoryAssignmentsByCwd: {\n ...state.conversationCategoryAssignmentsByCwd,\n ...(patch.conversationCategoryAssignmentsByCwd ?? {}),\n },\n migration: {\n ...state.migration,\n status: \"complete\",\n completedAt,\n localStorageImportedAt: completedAt,\n lastError: null,\n },\n };\n }, {\n mode: \"replace\",\n allowBeforeMigrationComplete: true,\n });\n\n if (next.migration.status !== \"complete\") {\n return { completed: false, importedKeys: [], skippedKeys: [] };\n }\n\n await cleanupLegacyCanonicalSources();\n return { completed: true, importedKeys: consumedKeys, skippedKeys };\n}\n","export const LEGACY_LOCALSTORAGE_KEYS = [\n \"settings-storage\",\n \"provider\",\n \"sandbox-storage\",\n \"project-settings-storage\",\n \"folder-storage\",\n \"conversation-categories-storage\",\n \"codex:auto-roll-settings\",\n] as const;\n\nexport const ORPHAN_LOCALSTORAGE_KEYS = [\n \"token-count-storage\",\n \"codexia-chat-input-store\",\n \"codex\",\n] as const;\n\nexport type LegacyLocalStorageKey = (typeof LEGACY_LOCALSTORAGE_KEYS)[number];\n","import path from \"node:path\";\nimport { CodexAppServer } from \"../../../lib/codex-app-server\";\nimport { licenseService } from \"../../../lib/license-service\";\nimport { assertProjectCreationAllowed } from \"../../../lib/license-guard\";\nimport {\n addParityWorkspace,\n connectParityWorkspace,\n getParityWorkspaceById,\n listParityWorkspaces,\n type WorkspaceInfo as ProjectInfo,\n} from \"../../../lib/workspace-parity-store\";\nimport { createTelegramBridge } from \"../../../electron/telegram-bridge\";\n\ntype DaemonStartOptions = {\n telegramBotToken: string;\n projectPath: string | null;\n version: string;\n};\n\nfunction hasFlag(args: string[], flag: string): boolean {\n return args.includes(flag);\n}\n\nfunction stripFlags(args: string[]): string[] {\n return args.filter(arg => !arg.startsWith(\"-\"));\n}\n\nfunction parseStringFlag(flags: string[], name: string): string | null {\n const explicit = flags.find(flag => flag.startsWith(`${name}=`));\n if (!explicit) {\n return null;\n }\n const value = explicit.slice(`${name}=`.length).trim();\n return value.length > 0 ? value : \"\";\n}\n\nfunction printDaemonHelp(version: string): void {\n console.log(`CodexUse CLI v${version}\n\nUsage:\n codexuse daemon start --telegram-bot-token=<token> [--project-path=/abs/path]\n\nEnvironment:\n CODEXUSE_TELEGRAM_BOT_TOKEN Telegram bot token fallback\n\nNotes:\n - Runs Codex app-server + Telegram bridge in headless mode (no desktop app).\n - --project-path auto-registers that path and makes it the default project for new chats.\n - Use on VPS/Linux with a process manager (systemd, pm2, supervisord).\n - Stop with Ctrl+C or SIGTERM.\n`);\n}\n\nasync function ensureProjectRegistered(projectPath: string): Promise<ProjectInfo> {\n const resolvedPath = path.resolve(projectPath);\n const projects = await listParityWorkspaces();\n const existing = projects.find(entry => path.resolve(entry.path) === resolvedPath) ?? null;\n if (!existing) {\n await assertProjectCreationAllowed(projects);\n const added = await addParityWorkspace(resolvedPath);\n console.log(`Added project: ${added.name} (${added.path})`);\n return added;\n }\n if (!existing.connected) {\n const connected = await connectParityWorkspace(existing.id);\n console.log(`Connected project: ${connected.name} (${connected.path})`);\n return connected;\n }\n return existing;\n}\n\nasync function resolveProEnabled(): Promise<boolean> {\n const cached = await licenseService.getCachedStatus().catch(() => null);\n if (cached?.isPro) {\n return true;\n }\n const refreshed = await licenseService.getStatus().catch(() => cached);\n return Boolean(refreshed?.isPro);\n}\n\nfunction parseProcessExitPayload(payload: unknown): string {\n if (!payload || typeof payload !== \"object\") {\n return \"\";\n }\n const record = payload as Record<string, unknown>;\n const code = typeof record.code === \"number\" ? record.code : null;\n const signal = typeof record.signal === \"string\" ? record.signal : null;\n if (code !== null && signal) {\n return `code=${code}, signal=${signal}`;\n }\n if (code !== null) {\n return `code=${code}`;\n }\n if (signal) {\n return `signal=${signal}`;\n }\n return \"\";\n}\n\nasync function runDaemonStart(options: DaemonStartOptions): Promise<void> {\n if (!options.telegramBotToken) {\n throw new Error(\n \"Telegram bot token is required. Pass --telegram-bot-token=<token> or set CODEXUSE_TELEGRAM_BOT_TOKEN.\",\n );\n }\n\n let preferredProject: ProjectInfo | null = null;\n if (options.projectPath) {\n preferredProject = await ensureProjectRegistered(options.projectPath);\n }\n\n const appServer = new CodexAppServer();\n await appServer.initialize({\n name: \"codexuse-cli-daemon\",\n title: \"CodexUse CLI Daemon\",\n version: options.version,\n });\n\n const bridge = createTelegramBridge({\n getAppServer: () => appServer,\n listProjects: () => listParityWorkspaces(),\n getProjectById: (id: string) => getParityWorkspaceById(id),\n isProEnabled: () => resolveProEnabled(),\n getDefaultProjectId: () => preferredProject?.id ?? null,\n });\n\n await bridge.applyRuntimeSettings({\n telegramBridgeEnabled: true,\n telegramBotToken: options.telegramBotToken,\n });\n\n const status = bridge.getStatus();\n if (!status.running) {\n await bridge.dispose().catch(() => undefined);\n await appServer.stop().catch(() => undefined);\n throw new Error(status.lastError || \"Telegram bridge failed to start.\");\n }\n\n const botLabel = status.botUsername ? `@${status.botUsername}` : \"(unknown)\";\n const projects = await listParityWorkspaces().catch(() => [] as ProjectInfo[]);\n console.log(`Daemon started. Telegram bot: ${botLabel}`);\n console.log(`Streaming mode: ${status.streamMode}`);\n if (preferredProject) {\n console.log(`Default project: ${preferredProject.name} [${preferredProject.id}]`);\n }\n console.log(`Projects available: ${projects.length}`);\n console.log(\"Running until SIGINT/SIGTERM...\");\n\n let stopping = false;\n let resolveWait: (() => void) | null = null;\n\n const stop = async (reason: string, exitCode: number) => {\n if (stopping) {\n return;\n }\n stopping = true;\n process.exitCode = exitCode;\n console.log(`Stopping daemon (${reason})...`);\n await bridge.dispose().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(`Failed to stop Telegram bridge cleanly: ${message}`);\n });\n await appServer.stop().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(`Failed to stop app-server cleanly: ${message}`);\n });\n resolveWait?.();\n };\n\n const onSigInt = () => {\n void stop(\"SIGINT\", 0);\n };\n const onSigTerm = () => {\n void stop(\"SIGTERM\", 0);\n };\n const onProcessExited = (payload: unknown) => {\n const suffix = parseProcessExitPayload(payload);\n const detail = suffix ? ` (${suffix})` : \"\";\n console.error(`Codex app-server exited unexpectedly${detail}.`);\n void stop(\"app-server-exited\", 1);\n };\n\n process.once(\"SIGINT\", onSigInt);\n process.once(\"SIGTERM\", onSigTerm);\n appServer.once(\"codex:process-exited\", onProcessExited);\n\n try {\n await new Promise<void>((resolve) => {\n resolveWait = resolve;\n });\n } finally {\n process.off(\"SIGINT\", onSigInt);\n process.off(\"SIGTERM\", onSigTerm);\n appServer.off(\"codex:process-exited\", onProcessExited);\n }\n}\n\nexport async function handleDaemonCommand(args: string[], version: string): Promise<void> {\n const flags = args.filter(arg => arg.startsWith(\"-\"));\n const params = stripFlags(args);\n const sub = params[0];\n\n if (!sub || hasFlag(flags, \"--help\") || hasFlag(flags, \"-h\")) {\n printDaemonHelp(version);\n return;\n }\n\n switch (sub) {\n case \"start\":\n {\n const tokenFlag =\n parseStringFlag(flags, \"--telegram-bot-token\")\n ?? parseStringFlag(flags, \"--bot-token\");\n const tokenEnv = process.env.CODEXUSE_TELEGRAM_BOT_TOKEN?.trim() || null;\n const telegramBotToken = (tokenFlag && tokenFlag.trim()) || tokenEnv || \"\";\n const projectPath =\n parseStringFlag(flags, \"--project-path\")\n ?? parseStringFlag(flags, \"--project\")\n ?? null;\n\n await runDaemonStart({\n telegramBotToken,\n projectPath,\n version,\n });\n return;\n }\n default:\n printDaemonHelp(version);\n return;\n }\n}\n","import { spawn, spawnSync, type ChildProcessWithoutNullStreams } from \"node:child_process\";\nimport { EventEmitter } from \"node:events\";\nimport readline from \"node:readline\";\nimport path from \"node:path\";\nimport { requireCodexCli } from \"./codex-cli\";\nimport {\n buildAppsListPayload,\n isAppsListMethod,\n isAppsListThreadNotFoundError,\n isMethodUnavailableError,\n type AppsListParams,\n} from \"./apps-list-rpc\";\nimport { buildCliEnv } from \"./cli-env\";\nimport { logError, logInfo, logWarn } from \"./logger\";\n\ntype JsonRpcId = number | string;\n\ntype JsonRpcRequest = {\n id: JsonRpcId;\n method: string;\n params?: unknown;\n};\n\ntype JsonRpcNotification = {\n method: string;\n params?: unknown;\n};\n\ntype JsonRpcError = {\n code: number;\n message: string;\n data?: unknown;\n};\n\ntype JsonRpcResponse = {\n id: JsonRpcId;\n result?: unknown;\n error?: JsonRpcError;\n};\n\ntype PendingRequest = {\n method: string;\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n};\n\ntype PendingRequestKind = \"exec\" | \"patch\" | \"approval\" | \"user_input\";\n\ntype PendingServerRequest = {\n id: JsonRpcId;\n kind: PendingRequestKind;\n method: string;\n};\n\nexport type CodexReviewDecision = \"approved\" | \"approved_for_session\" | \"denied\" | \"abort\";\n\nexport type CodexAppServerEventName =\n | \"codex:event\"\n | \"codex:notification\"\n | \"codex:auth-status\"\n | \"codex:login-complete\"\n | \"codex:exec-command-request\"\n | \"codex:apply-patch-request\"\n | \"codex:server-request\"\n | \"codex:backend-error\"\n | \"codex:process-exited\";\n\nexport interface CodexClientInfo {\n name: string;\n title?: string;\n version?: string;\n}\n\nexport interface CodexEventPayload {\n method: string;\n params?: unknown;\n}\n\nexport interface CodexNotificationPayload {\n method: string;\n params?: unknown;\n}\n\nexport interface CodexExecCommandRequestPayload {\n requestToken: string;\n params: Record<string, unknown>;\n}\n\nexport interface CodexApplyPatchRequestPayload {\n requestToken: string;\n params: Record<string, unknown>;\n}\n\nexport interface CodexServerRequestPayload {\n requestId: JsonRpcId;\n method: string;\n params: Record<string, unknown>;\n}\n\nexport interface CodexBackendErrorPayload {\n code: number;\n message: string;\n data?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\" && !Array.isArray(value));\n}\n\nfunction requestIdToToken(id: JsonRpcId): string {\n return typeof id === \"string\" ? id : String(id);\n}\n\nfunction isAlreadyInitializedError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const message = (error as { message?: unknown }).message;\n return typeof message === \"string\" && message.toLowerCase().includes(\"already initialized\");\n}\n\nfunction isThreadNotFoundError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const message = (error as { message?: unknown }).message;\n if (typeof message !== \"string\") return false;\n const lower = message.toLowerCase();\n return lower.includes(\"thread not found\") || lower.includes(\"rollout\");\n}\n\nfunction isMethodPayloadUnsupportedError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n const code = (error as { code?: unknown }).code;\n if (typeof code !== \"number\" || code !== -32600) {\n return false;\n }\n const message = (error as { message?: unknown }).message;\n if (typeof message !== \"string\") {\n return false;\n }\n const normalized = message.toLowerCase();\n return (\n normalized.includes(\"invalid request\")\n || normalized.includes(\"missing field\")\n || normalized.includes(\"unknown field\")\n );\n}\n\nfunction asString(value: unknown): string {\n return typeof value === \"string\" ? value : value != null ? String(value) : \"\";\n}\n\nfunction isInlineImageValue(value: string): boolean {\n const normalized = value.trim().toLowerCase();\n return (\n normalized.startsWith(\"data:\")\n || normalized.startsWith(\"http://\")\n || normalized.startsWith(\"https://\")\n );\n}\n\nfunction normalizeSendUserMessageItem(\n value: unknown,\n): Record<string, unknown> | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const type = asString(value.type).trim();\n if (!type) {\n return null;\n }\n\n const data = isRecord(value.data) ? value.data : {};\n\n if (type === \"text\") {\n const text = asString(data.text ?? value.text);\n if (!text.trim()) {\n return null;\n }\n return { type: \"text\", data: { text } };\n }\n\n if (type === \"image\") {\n const imageUrl = asString(\n data.image_url\n ?? data.imageUrl\n ?? data.url\n ?? value.image_url\n ?? value.imageUrl\n ?? value.url,\n ).trim();\n if (!imageUrl) {\n return null;\n }\n return { type: \"image\", data: { image_url: imageUrl } };\n }\n\n if (type === \"localImage\") {\n const path = asString(data.path ?? value.path).trim();\n if (!path) {\n return null;\n }\n return { type: \"localImage\", data: { path } };\n }\n\n return value;\n}\n\nfunction buildSendUserMessageItemsFromLegacyParams(\n params: Record<string, unknown>,\n): Record<string, unknown>[] | null {\n const items: Record<string, unknown>[] = [];\n\n const text = asString(params.text);\n if (text.trim()) {\n items.push({\n type: \"text\",\n data: { text },\n });\n }\n\n if (Array.isArray(params.images)) {\n for (const candidate of params.images) {\n const image = asString(candidate).trim();\n if (!image) {\n continue;\n }\n if (isInlineImageValue(image)) {\n items.push({\n type: \"image\",\n data: { image_url: image },\n });\n continue;\n }\n items.push({\n type: \"localImage\",\n data: { path: image },\n });\n }\n }\n\n if (items.length === 0) {\n return null;\n }\n return items;\n}\n\nfunction normalizeSendUserMessageParams(\n params: Record<string, unknown>,\n): Record<string, unknown> {\n const normalized: Record<string, unknown> = { ...params };\n const conversationId = asString(\n params.conversationId\n ?? params.conversation_id\n ?? params.threadId\n ?? params.thread_id\n ?? \"\",\n ).trim();\n if (conversationId && !asString(params.conversationId).trim()) {\n normalized.conversationId = conversationId;\n }\n\n const items = Array.isArray(params.items)\n ? params.items\n .map((item) => normalizeSendUserMessageItem(item))\n .filter((item): item is Record<string, unknown> => item !== null)\n : null;\n if (items && items.length > 0) {\n normalized.items = items;\n return normalized;\n }\n\n const legacyItems = buildSendUserMessageItemsFromLegacyParams(params);\n if (legacyItems) {\n normalized.items = legacyItems;\n }\n return normalized;\n}\n\nfunction normalizeTurnInputParams(\n params: Record<string, unknown>,\n): Record<string, unknown> {\n const normalized: Record<string, unknown> = { ...params };\n const threadId = asString(\n params.threadId\n ?? params.thread_id\n ?? params.conversationId\n ?? params.conversation_id\n ?? \"\",\n ).trim();\n if (threadId && !asString(params.threadId).trim()) {\n normalized.threadId = threadId;\n }\n\n const expectedTurnId = asString(\n params.expectedTurnId\n ?? params.expected_turn_id\n ?? params.turnId\n ?? params.turn_id\n ?? \"\",\n ).trim();\n if (expectedTurnId && !asString(params.expectedTurnId).trim()) {\n normalized.expectedTurnId = expectedTurnId;\n }\n const turnId = asString(params.turnId ?? params.turn_id ?? expectedTurnId).trim();\n if (turnId && !asString(params.turnId).trim()) {\n normalized.turnId = turnId;\n }\n\n const providedInput = Array.isArray(params.input)\n ? params.input.filter((entry) => isRecord(entry))\n : [];\n if (providedInput.length > 0) {\n normalized.input = providedInput;\n return normalized;\n }\n\n const providedItems = Array.isArray(params.items)\n ? params.items\n .map((item) => normalizeSendUserMessageItem(item))\n .filter((item): item is Record<string, unknown> => item !== null)\n : [];\n if (providedItems.length > 0) {\n const input = providedItems.flatMap((item) => {\n const type = asString(item.type).trim();\n const data = isRecord(item.data) ? item.data : item;\n if (type === \"text\") {\n const text = asString(data.text).trim();\n return text ? [{ type: \"text\", text }] : [];\n }\n if (type === \"localImage\") {\n const path = asString(data.path).trim();\n return path ? [{ type: \"localImage\", path }] : [];\n }\n return [];\n });\n if (input.length > 0) {\n normalized.input = input;\n return normalized;\n }\n }\n\n const input: Record<string, unknown>[] = [];\n const text = asString(params.text);\n if (text.trim()) {\n input.push({ type: \"text\", text });\n }\n if (Array.isArray(params.images)) {\n for (const candidate of params.images) {\n const image = asString(candidate).trim();\n if (!image || isInlineImageValue(image)) {\n continue;\n }\n input.push({\n type: \"localImage\",\n path: image,\n });\n }\n }\n if (input.length > 0) {\n normalized.input = input;\n }\n return normalized;\n}\n\nfunction pickMethodKind(method: string, params: unknown): PendingRequestKind | null {\n const normalized = method.toLowerCase();\n if (normalized.includes(\"requestapproval\")) return \"approval\";\n if (normalized.includes(\"requestuserinput\")) return \"user_input\";\n if (isRecord(params)) {\n if (\"file_changes\" in params || \"fileChanges\" in params || \"grant_root\" in params || \"grantRoot\" in params) {\n return \"patch\";\n }\n if (\"command\" in params || \"parsed_cmd\" in params || \"parsedCmd\" in params || \"cwd\" in params) {\n return \"exec\";\n }\n }\n if (normalized.includes(\"apply\") && normalized.includes(\"patch\")) return \"patch\";\n if (normalized.includes(\"file\") && normalized.includes(\"change\")) return \"patch\";\n if (normalized.includes(\"exec\") || normalized.includes(\"command\")) return \"exec\";\n return null;\n}\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 45_000;\nconst THREAD_LIST_REQUEST_TIMEOUT_MS = 180_000;\nconst MAX_PARSE_BUFFER_CHARS = 2_000_000;\nconst DEFAULT_THREAD_LIVE_WORKSPACE_ID = \"__default__\";\nconst REQUEST_TIMEOUT_WARNING_COOLDOWN_MS = 30_000;\n\nfunction isLikelyRecoverableJsonParseError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n const message = error.message.toLowerCase();\n return (\n message.includes(\"unterminated string\") ||\n message.includes(\"unexpected end of json input\") ||\n message.includes(\"bad control character\")\n );\n}\n\nfunction isIgnorableAppsListTransportStderr(message: string): boolean {\n const normalized = message.toLowerCase();\n if (!normalized.includes(\"backend-api/wham/apps\")) {\n return false;\n }\n return (\n normalized.includes(\"worker quit with fatal\") &&\n normalized.includes(\"transport channel closed\")\n );\n}\n\nfunction isIgnorableMissingSkillsSymlinkStderr(message: string): boolean {\n const normalized = message.toLowerCase();\n return (\n normalized.includes(\"codex_core::skills::loader\") &&\n normalized.includes(\"failed to stat skills entry\") &&\n normalized.includes(\"(symlink)\") &&\n normalized.includes(\"no such file or directory\")\n );\n}\n\nfunction isRequestTimeoutErrorMessage(value: unknown): boolean {\n if (typeof value !== \"string\") {\n return false;\n }\n return value.toLowerCase().includes(\"request timed out\");\n}\n\nfunction getRequestTimeoutMs(method: string): number {\n if (method === \"thread/list\") {\n return THREAD_LIST_REQUEST_TIMEOUT_MS;\n }\n return DEFAULT_REQUEST_TIMEOUT_MS;\n}\n\nfunction normalizeThreadLiveWorkspaceId(value: unknown): string {\n const workspaceId = asString(value).trim();\n return workspaceId || DEFAULT_THREAD_LIVE_WORKSPACE_ID;\n}\n\nfunction threadLiveKey(workspaceId: string, threadId: string): string {\n return `${workspaceId}:${threadId}`;\n}\n\nfunction escapeInvalidJsonStringChars(input: string): string {\n let output = \"\";\n let inString = false;\n let escaped = false;\n\n for (let i = 0; i < input.length; i += 1) {\n const char = input[i];\n\n if (escaped) {\n output += char;\n escaped = false;\n continue;\n }\n if (char === \"\\\\\") {\n output += char;\n escaped = true;\n continue;\n }\n if (char === \"\\\"\") {\n output += char;\n inString = !inString;\n continue;\n }\n if (inString) {\n if (char === \"\\n\") {\n output += \"\\\\n\";\n continue;\n }\n if (char === \"\\r\") {\n output += \"\\\\r\";\n continue;\n }\n if (char === \"\\t\") {\n output += \"\\\\t\";\n continue;\n }\n const code = char.charCodeAt(0);\n if (code >= 0 && code < 0x20) {\n output += `\\\\u${code.toString(16).padStart(4, \"0\")}`;\n continue;\n }\n }\n\n output += char;\n }\n\n return output;\n}\n\nlet cachedRuntimeBinary: string | null = null;\n\nfunction resolveRuntimeBinary(env?: NodeJS.ProcessEnv): string {\n const override =\n env?.CODEX_NODE_RUNTIME?.trim() ||\n env?.CODEX_NODE_BIN?.trim() ||\n env?.CODEX_NODE?.trim() ||\n process.env.CODEX_NODE_RUNTIME?.trim() ||\n process.env.CODEX_NODE_BIN?.trim() ||\n process.env.CODEX_NODE?.trim() ||\n null;\n if (override) {\n return override;\n }\n\n if (cachedRuntimeBinary) {\n return cachedRuntimeBinary;\n }\n\n const runtimeEnv: NodeJS.ProcessEnv = { ...process.env, ...env };\n const homeDir = runtimeEnv.HOME ?? runtimeEnv.USERPROFILE ?? \"\";\n const pathHints = (runtimeEnv.CODEX_PATH_HINTS ?? process.env.CODEX_PATH_HINTS ?? \"\")\n .split(path.delimiter)\n .map(entry => entry.trim())\n .filter(Boolean);\n const extraPathEntries = [\n \"/usr/local/bin\",\n \"/opt/homebrew/bin\",\n path.join(homeDir, \".local\", \"bin\"),\n path.join(homeDir, \".fnm\", \"aliases\", \"default\", \"bin\"),\n path.join(homeDir, \".fnm\", \"current\", \"bin\"),\n ...pathHints,\n ].filter(Boolean);\n const currentPath = runtimeEnv.PATH ?? \"\";\n runtimeEnv.PATH = Array.from(\n new Set([...extraPathEntries, ...currentPath.split(path.delimiter).filter(Boolean)]),\n ).join(path.delimiter);\n\n const candidates = Array.from(\n new Set(\n [\n runtimeEnv.CODEX_NODE_RUNTIME?.trim(),\n runtimeEnv.CODEX_NODE_BIN?.trim(),\n runtimeEnv.CODEX_NODE?.trim(),\n \"/opt/homebrew/bin/node\",\n \"/usr/local/bin/node\",\n \"node\",\n ].filter(Boolean),\n ),\n );\n\n for (const candidate of candidates) {\n const probe = spawnSync(candidate, [\"-v\"], { env: runtimeEnv, stdio: \"ignore\" });\n if (!probe.error && probe.status === 0) {\n cachedRuntimeBinary = candidate;\n return candidate;\n }\n }\n\n cachedRuntimeBinary = process.execPath;\n return process.execPath;\n}\n\nexport class CodexAppServer extends EventEmitter {\n private child: ChildProcessWithoutNullStreams | null = null;\n private reader: readline.Interface | null = null;\n private nextRequestId = 1;\n private pendingRequests = new Map<string, PendingRequest>();\n private pendingServerRequests = new Map<string, PendingServerRequest>();\n private timeoutRecoveryPromise: Promise<void> | null = null;\n private lastTimeoutWarningAtByMethod = new Map<string, number>();\n private startPromise: Promise<void> | null = null;\n private initializePromise: Promise<unknown> | null = null;\n private initializeResponse: unknown | null = null;\n private parseLineBuffer: string | null = null;\n private threadLiveSubscriptionIdByKey = new Map<string, string>();\n private threadLiveModeByKey = new Map<string, \"listener\">();\n private addConversationListenerSupported: boolean | null = null;\n\n constructor() {\n super();\n this.setMaxListeners(50);\n }\n\n async start(): Promise<void> {\n if (this.child) {\n return;\n }\n if (!this.startPromise) {\n this.startPromise = this.spawnProcess().finally(() => {\n this.startPromise = null;\n });\n }\n await this.startPromise;\n }\n\n async stop(): Promise<void> {\n if (this.reader) {\n this.reader.close();\n this.reader = null;\n }\n if (this.child) {\n const child = this.child;\n this.child = null;\n try {\n child.kill();\n } catch {\n // ignore kill errors\n }\n }\n this.initializePromise = null;\n this.initializeResponse = null;\n this.parseLineBuffer = null;\n this.threadLiveSubscriptionIdByKey.clear();\n this.threadLiveModeByKey.clear();\n this.addConversationListenerSupported = null;\n this.clearPendingRequests(new Error(\"codex app-server stopped\"));\n }\n\n isRunning(): boolean {\n return Boolean(this.child && !this.child.killed);\n }\n\n async initialize(clientInfo?: CodexClientInfo): Promise<unknown> {\n if (this.initializeResponse) {\n return this.initializeResponse;\n }\n if (!this.initializePromise) {\n this.initializePromise = (async () => {\n await this.start();\n const payload: Record<string, unknown> = {\n clientInfo: clientInfo ?? {\n name: \"codexuse\",\n title: \"CodexUse\",\n version: \"0.0.0\",\n },\n };\n try {\n const response = await this.request(\"initialize\", payload);\n await this.notify(\"initialized\", {});\n this.initializeResponse = response;\n return response;\n } catch (error) {\n if (isAlreadyInitializedError(error)) {\n this.initializeResponse = this.initializeResponse ?? {};\n return this.initializeResponse;\n }\n throw error;\n }\n })().finally(() => {\n this.initializePromise = null;\n });\n }\n return this.initializePromise;\n }\n\n async getAccount(refreshToken = false): Promise<unknown> {\n return this.request(\"account/read\", { refreshToken });\n }\n\n async getAccountRateLimits(): Promise<unknown> {\n return this.request(\"account/rateLimits/read\");\n }\n\n async loginAccount(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"account/login/start\", params);\n }\n\n async cancelLoginAccount(loginId: string): Promise<unknown> {\n return this.request(\"account/login/cancel\", { loginId });\n }\n\n async logoutAccount(): Promise<unknown> {\n return this.request(\"account/logout\");\n }\n\n async newConversation(params: Record<string, unknown>, overrides?: Record<string, unknown> | null): Promise<unknown> {\n const merged = overrides ? { ...params, ...overrides } : params;\n return this.request(\"newConversation\", merged);\n }\n\n async resumeConversation(params: Record<string, unknown>, overrides?: Record<string, unknown> | null): Promise<unknown> {\n const merged = overrides ? { ...params, ...overrides } : params;\n return this.request(\"resumeConversation\", merged);\n }\n\n private async addConversationListenerWithResumeFallback(\n threadId: string,\n workspaceId: string | null = null,\n ): Promise<Record<string, unknown> | null> {\n if (this.addConversationListenerSupported === false) {\n return {};\n }\n const listenerParams: Record<string, unknown> = {\n conversationId: threadId,\n };\n const resolvedWorkspaceId = workspaceId ? workspaceId.trim() : \"\";\n if (resolvedWorkspaceId) {\n listenerParams.workspaceId = resolvedWorkspaceId;\n listenerParams.workspace_id = resolvedWorkspaceId;\n }\n try {\n const response = await this.request(\"addConversationListener\", listenerParams);\n this.addConversationListenerSupported = true;\n return isRecord(response) ? response : null;\n } catch (error) {\n if (isMethodUnavailableError(error, \"addConversationListener\")) {\n this.addConversationListenerSupported = false;\n return {};\n }\n if (!isThreadNotFoundError(error)) {\n throw error;\n }\n await this.threadResume(\n resolvedWorkspaceId\n ? { threadId, workspaceId: resolvedWorkspaceId, workspace_id: resolvedWorkspaceId }\n : { threadId },\n );\n try {\n const response = await this.request(\"addConversationListener\", listenerParams);\n this.addConversationListenerSupported = true;\n return isRecord(response) ? response : null;\n } catch (resumeError) {\n if (isMethodUnavailableError(resumeError, \"addConversationListener\")) {\n this.addConversationListenerSupported = false;\n return {};\n }\n throw resumeError;\n }\n }\n }\n\n private async removeConversationListenerBySubscriptionId(\n subscriptionId: string,\n ): Promise<void> {\n if (!subscriptionId || this.addConversationListenerSupported === false) {\n return;\n }\n try {\n await this.request(\"removeConversationListener\", { subscriptionId });\n } catch (error) {\n if (isMethodUnavailableError(error, \"removeConversationListener\")) {\n this.addConversationListenerSupported = false;\n return;\n }\n throw error;\n }\n }\n\n async addConversationListener(params: Record<string, unknown>): Promise<unknown> {\n if (this.addConversationListenerSupported === false) {\n return {};\n }\n const conversationId = asString(\n params.conversationId ?? params.threadId ?? params.thread_id ?? \"\",\n ).trim();\n const workspaceId = asString(\n params.workspaceId ?? params.workspace_id ?? \"\",\n ).trim();\n if (!conversationId) {\n try {\n const response = await this.request(\"addConversationListener\", params);\n this.addConversationListenerSupported = true;\n return response;\n } catch (error) {\n if (isMethodUnavailableError(error, \"addConversationListener\")) {\n this.addConversationListenerSupported = false;\n return {};\n }\n throw error;\n }\n }\n return this.addConversationListenerWithResumeFallback(\n conversationId,\n workspaceId || null,\n );\n }\n\n async removeConversationListener(params: Record<string, unknown>): Promise<unknown> {\n if (this.addConversationListenerSupported === false) {\n return {};\n }\n try {\n return await this.request(\"removeConversationListener\", params);\n } catch (error) {\n if (isMethodUnavailableError(error, \"removeConversationListener\")) {\n this.addConversationListenerSupported = false;\n return {};\n }\n throw error;\n }\n }\n\n async threadLiveSubscribe(params: Record<string, unknown>): Promise<unknown> {\n const workspaceId = normalizeThreadLiveWorkspaceId(\n params.workspaceId ?? params.workspace_id,\n );\n const threadId = asString(\n params.threadId ?? params.thread_id ?? params.conversationId,\n ).trim();\n if (!threadId) {\n return {};\n }\n\n const key = threadLiveKey(workspaceId, threadId);\n this.threadLiveModeByKey.set(key, \"listener\");\n this.threadLiveSubscriptionIdByKey.delete(key);\n return {};\n }\n\n async threadLiveUnsubscribe(\n params: Record<string, unknown>,\n ): Promise<unknown> {\n const workspaceId = normalizeThreadLiveWorkspaceId(\n params.workspaceId ?? params.workspace_id,\n );\n const threadId = asString(\n params.threadId ?? params.thread_id ?? params.conversationId,\n ).trim();\n if (!threadId) {\n return {};\n }\n\n const key = threadLiveKey(workspaceId, threadId);\n this.threadLiveModeByKey.delete(key);\n const subscriptionId = this.threadLiveSubscriptionIdByKey.get(key) ?? null;\n this.threadLiveSubscriptionIdByKey.delete(key);\n\n if (subscriptionId) {\n await this.removeConversationListenerBySubscriptionId(subscriptionId);\n }\n return {};\n }\n\n async sendUserMessage(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"turn/start\", normalizeTurnInputParams(params));\n }\n\n async threadStart(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"thread/start\", params);\n }\n\n async threadResume(params: Record<string, unknown>): Promise<unknown> {\n const sanitized = { ...params };\n delete sanitized.rolloutPath;\n delete sanitized.rollout_path;\n return this.request(\"thread/resume\", sanitized);\n }\n\n async turnStart(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"turn/start\", normalizeTurnInputParams(params));\n }\n\n async steerTurn(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"turn/steer\", normalizeTurnInputParams(params));\n }\n\n async interruptTurn(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"turn/interrupt\", params);\n }\n\n async turnSteer(params: Record<string, unknown>): Promise<unknown> {\n return this.steerTurn(params);\n }\n\n async turnInterrupt(params: Record<string, unknown>): Promise<unknown> {\n return this.interruptTurn(params);\n }\n\n async interruptConversation(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"interruptConversation\", params);\n }\n\n async archiveConversation(conversationId: string): Promise<void> {\n try {\n await this.request(\"thread/archive\", { threadId: conversationId });\n return;\n } catch {\n // fall through to legacy endpoint\n }\n try {\n await this.request(\"archiveConversation\", { conversationId });\n } catch {\n // ignore archive failures\n }\n }\n\n async listConversations(params: {\n cursor?: string | null;\n limit?: number;\n cwd?: string | null;\n sortKey?: \"created_at\" | \"updated_at\" | null;\n searchQuery?: string | null;\n sourceKinds?: string[] | null;\n archived?: boolean | null;\n modelProviders?: string[] | null;\n }): Promise<unknown> {\n return this.request(\"thread/list\", {\n cursor: params.cursor ?? null,\n limit: params.limit ?? 20,\n cwd: params.cwd ?? null,\n sortKey: params.sortKey ?? null,\n searchQuery: params.searchQuery ?? null,\n sourceKinds: params.sourceKinds ?? null,\n archived: params.archived ?? null,\n modelProviders: params.modelProviders ?? null,\n });\n }\n\n async listSkillsCore(params?: {\n cwd?: string | null;\n forceReload?: boolean;\n }): Promise<unknown> {\n const cwd = typeof params?.cwd === \"string\" ? params.cwd.trim() : \"\";\n return this.request(\"skills/list\", {\n cwds: cwd ? [cwd] : [],\n forceReload: Boolean(params?.forceReload),\n });\n }\n\n async listApps(params?: AppsListParams): Promise<unknown> {\n const payload = buildAppsListPayload(params);\n const methods = [\"app/list\", \"apps/list\", \"apps_list\"] as const;\n for (let index = 0; index < methods.length; index += 1) {\n const method = methods[index];\n try {\n return await this.request(method, payload);\n } catch (error) {\n const hasLegacyFallback = index < methods.length - 1;\n if (hasLegacyFallback && isMethodUnavailableError(error, method)) {\n continue;\n }\n if (isAppsListThreadNotFoundError(error)) {\n return { data: [] };\n }\n throw error;\n }\n }\n throw new Error(\"Apps list is unavailable from the connected Codex backend.\");\n }\n\n async setSkillEnabledCore(params: { path: string; enabled: boolean }): Promise<unknown> {\n const skillPath = typeof params.path === \"string\" ? params.path.trim() : \"\";\n if (!skillPath) {\n throw new Error(\"Skill path is required.\");\n }\n return this.request(\"skills/config/write\", {\n path: skillPath,\n enabled: Boolean(params.enabled),\n });\n }\n\n async readThread(params: { threadId: string; includeTurns?: boolean | null }): Promise<unknown> {\n return this.request(\"thread/read\", {\n threadId: params.threadId,\n includeTurns: Boolean(params.includeTurns),\n });\n }\n\n async setThreadName(threadId: string, name: string): Promise<unknown> {\n return this.request(\"thread/name/set\", { threadId, name });\n }\n\n async startReview(params: Record<string, unknown>): Promise<unknown> {\n return this.request(\"review/start\", params);\n }\n\n async startCompact(params: Record<string, unknown>): Promise<unknown> {\n try {\n return await this.request(\"thread/compact/start\", params);\n } catch {\n try {\n return await this.request(\"thread/compact\", params);\n } catch {\n return this.request(\"compactThread\", params);\n }\n }\n }\n\n async respondExecCommandRequest(requestToken: string, decision: CodexReviewDecision): Promise<void> {\n await this.respondReviewDecision(requestToken, \"exec\", decision);\n }\n\n async respondApplyPatchRequest(requestToken: string, decision: CodexReviewDecision): Promise<void> {\n await this.respondReviewDecision(requestToken, \"patch\", decision);\n }\n\n async respondToServerRequest(requestId: JsonRpcId, result: Record<string, unknown>): Promise<void> {\n const token = requestIdToToken(requestId);\n const pending = this.pendingServerRequests.get(token);\n if (!pending) {\n throw new Error(`Unknown server request: ${requestId}`);\n }\n this.pendingServerRequests.delete(token);\n await this.sendResponse(pending.id, result ?? {});\n }\n\n private async spawnProcess(): Promise<void> {\n const codexPath = await requireCodexCli();\n const env = buildCliEnv(codexPath, { ELECTRON_RUN_AS_NODE: \"1\" });\n const runtimeBin = resolveRuntimeBinary(env);\n const child = spawn(runtimeBin, [codexPath, \"app-server\"], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env,\n });\n this.child = child;\n this.initializeResponse = null;\n this.initializePromise = null;\n this.parseLineBuffer = null;\n this.addConversationListenerSupported = null;\n\n child.on(\"exit\", (code, signal) => {\n logWarn(\"[app-server] exited\", { code, signal });\n this.child = null;\n this.initializeResponse = null;\n this.initializePromise = null;\n this.threadLiveSubscriptionIdByKey.clear();\n this.threadLiveModeByKey.clear();\n this.addConversationListenerSupported = null;\n this.clearPendingRequests(new Error(\"codex app-server exited\"));\n this.emit(\"codex:process-exited\", {});\n });\n child.on(\"error\", error => {\n logError(\"[app-server] process error\", error);\n this.threadLiveSubscriptionIdByKey.clear();\n this.threadLiveModeByKey.clear();\n this.addConversationListenerSupported = null;\n this.emit(\"codex:process-exited\", {});\n });\n\n if (child.stderr) {\n child.stderr.on(\"data\", chunk => {\n const lines = chunk.toString().split(/\\r?\\n/);\n for (const line of lines) {\n const message = line.trim();\n if (!message) continue;\n // Filter out known harmless errors from the Rust backend's state db reconciliation.\n // These occur when the db has thread entries for session files that no longer exist.\n const normalized = message.toLowerCase();\n if (normalized.includes(\"state db missing rollout path for thread\")) {\n continue;\n }\n // The app-server may emit this during recorder initialization; it's noisy/non-actionable in UI logs.\n if (\n normalized.includes(\"rollout::recorder\") &&\n normalized.includes(\"falling back on rollout system\")\n ) {\n continue;\n }\n if (isIgnorableAppsListTransportStderr(message)) {\n continue;\n }\n if (isIgnorableMissingSkillsSymlinkStderr(message)) {\n continue;\n }\n logWarn(\"[app-server] stderr\", message);\n }\n });\n }\n\n if (!child.stdout) {\n throw new Error(\"codex app-server missing stdout\");\n }\n\n this.reader = readline.createInterface({\n input: child.stdout,\n crlfDelay: Infinity,\n });\n\n this.reader.on(\"line\", line => {\n this.handleIncomingLine(line);\n });\n\n logInfo(\"[app-server] started\");\n }\n\n private handleIncomingLine(line: string): void {\n if (this.parseLineBuffer !== null) {\n const merged = `${this.parseLineBuffer}\\n${line}`;\n const handled = this.tryHandleMessage(merged);\n if (handled) {\n this.parseLineBuffer = null;\n return;\n }\n if (merged.length < MAX_PARSE_BUFFER_CHARS) {\n this.parseLineBuffer = merged;\n return;\n }\n this.logParseFailure(\n merged,\n new Error(\"Buffered JSON message exceeded max size while recovering malformed output.\"),\n );\n this.parseLineBuffer = null;\n return;\n }\n\n if (!line.trim()) {\n return;\n }\n\n const handled = this.tryHandleMessage(line);\n if (handled) {\n return;\n }\n\n if (line.trimStart().startsWith(\"{\")) {\n this.parseLineBuffer = line;\n }\n }\n\n private tryHandleMessage(line: string): boolean {\n let parsed: unknown;\n let parseError: unknown = null;\n try {\n parsed = JSON.parse(line) as unknown;\n } catch (error) {\n parseError = error;\n const repaired = escapeInvalidJsonStringChars(line);\n if (repaired !== line) {\n try {\n parsed = JSON.parse(repaired) as unknown;\n parseError = null;\n } catch (repairError) {\n parseError = repairError;\n }\n }\n }\n\n if (parseError) {\n if (isLikelyRecoverableJsonParseError(parseError)) {\n return false;\n }\n this.logParseFailure(line, parseError);\n return true;\n }\n if (!isRecord(parsed)) {\n logWarn(\"[app-server] unexpected JSON message\", parsed);\n return true;\n }\n\n const hasId = \"id\" in parsed;\n const hasMethod = typeof parsed.method === \"string\";\n const hasResult = \"result\" in parsed;\n const hasError = \"error\" in parsed;\n\n if (hasMethod && hasId) {\n this.handleServerRequest(parsed as JsonRpcRequest);\n return true;\n }\n\n if (hasMethod) {\n this.handleNotification(parsed as JsonRpcNotification);\n return true;\n }\n\n if (hasId && (hasResult || hasError)) {\n this.handleResponse(parsed as JsonRpcResponse);\n return true;\n }\n\n logWarn(\"[app-server] unknown message shape\", parsed);\n return true;\n }\n\n private logParseFailure(line: string, error: unknown): void {\n const message = error instanceof Error ? error.message : String(error);\n logWarn(\"[app-server] failed to parse JSON\", {\n error: message,\n length: line.length,\n startsWithJsonObject: line.trimStart().startsWith(\"{\"),\n });\n }\n\n private handleResponse(response: JsonRpcResponse): void {\n const token = requestIdToToken(response.id);\n const pending = this.pendingRequests.get(token);\n if (!pending) {\n logWarn(\"[app-server] response with no pending request\", response.id);\n return;\n }\n this.pendingRequests.delete(token);\n\n if (response.error) {\n const error = new Error(response.error.message || \"codex app-server error\");\n (error as Error & { code?: number; data?: unknown }).code = response.error.code;\n (error as Error & { code?: number; data?: unknown }).data = response.error.data;\n const suppressBackendErrorEvent =\n isAppsListMethod(pending.method) ||\n (pending.method === \"addConversationListener\" && isThreadNotFoundError(error)) ||\n (pending.method === \"thread/resume\" && isThreadNotFoundError(error));\n if (!suppressBackendErrorEvent) {\n this.emit(\"codex:backend-error\", {\n code: response.error.code,\n message: response.error.message,\n data: response.error.data,\n } satisfies CodexBackendErrorPayload);\n }\n pending.reject(error);\n return;\n }\n\n pending.resolve(response.result);\n }\n\n private handleNotification(notification: JsonRpcNotification): void {\n const { method, params } = notification;\n if (method.startsWith(\"codex/event/\")) {\n this.emit(\"codex:event\", { method, params } satisfies CodexEventPayload);\n return;\n }\n\n const normalized = method.toLowerCase();\n if (normalized.includes(\"auth\") && normalized.includes(\"status\")) {\n this.emit(\"codex:auth-status\", params ?? {});\n return;\n }\n if (normalized.includes(\"login\") && normalized.includes(\"complete\")) {\n this.emit(\"codex:login-complete\", params ?? {});\n return;\n }\n\n this.emit(\"codex:notification\", { method, params } satisfies CodexNotificationPayload);\n }\n\n private handleServerRequest(request: JsonRpcRequest): void {\n const kind = pickMethodKind(request.method, request.params);\n if (!kind) {\n void this.sendError(request.id, {\n code: -32601,\n message: `Unsupported request: ${request.method}`,\n });\n return;\n }\n\n const token = requestIdToToken(request.id);\n this.pendingServerRequests.set(token, { id: request.id, kind, method: request.method });\n\n const params = isRecord(request.params) ? request.params : {};\n if (kind === \"exec\") {\n this.emit(\"codex:exec-command-request\", {\n requestToken: token,\n params,\n } satisfies CodexExecCommandRequestPayload);\n } else if (kind === \"patch\") {\n this.emit(\"codex:apply-patch-request\", {\n requestToken: token,\n params,\n } satisfies CodexApplyPatchRequestPayload);\n } else {\n this.emit(\"codex:server-request\", {\n requestId: request.id,\n method: request.method,\n params,\n } satisfies CodexServerRequestPayload);\n }\n }\n\n private async respondReviewDecision(\n requestToken: string,\n kind: PendingRequestKind,\n decision: CodexReviewDecision,\n ): Promise<void> {\n const pending = this.pendingServerRequests.get(requestToken);\n if (!pending) {\n throw new Error(`Unknown approval request: ${requestToken}`);\n }\n if (pending.kind !== kind) {\n throw new Error(`Mismatched approval request type for ${requestToken}`);\n }\n this.pendingServerRequests.delete(requestToken);\n await this.sendResponse(pending.id, { decision });\n }\n\n private async request(method: string, params?: unknown): Promise<unknown> {\n // Skip initialization check for the initialize method itself to avoid recursive deadlock\n if (method !== \"initialize\") {\n await this.initialize();\n } else {\n await this.start();\n }\n const id = this.nextRequestId++;\n const token = requestIdToToken(id);\n const timeoutMs = getRequestTimeoutMs(method);\n const payload: JsonRpcRequest = params ? { id, method, params } : { id, method };\n const result = new Promise<unknown>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const pending = this.pendingRequests.get(token);\n if (!pending) {\n return;\n }\n this.pendingRequests.delete(token);\n const timeoutError = new Error(\n `codex app-server request timed out after ${timeoutMs}ms (${method})`,\n );\n pending.reject(timeoutError);\n this.maybeRecoverFromTimeout(method, timeoutError);\n }, timeoutMs);\n\n this.pendingRequests.set(token, {\n method,\n resolve: (value) => {\n clearTimeout(timeout);\n resolve(value);\n },\n reject: (error) => {\n clearTimeout(timeout);\n reject(error);\n },\n });\n });\n await this.writeMessage(payload);\n return result;\n }\n\n private async notify(method: string, params?: unknown): Promise<void> {\n await this.start();\n const payload: JsonRpcNotification = params ? { method, params } : { method };\n await this.writeMessage(payload);\n }\n\n private async sendResponse(id: JsonRpcId, result: unknown): Promise<void> {\n await this.writeMessage({ id, result });\n }\n\n private async sendError(id: JsonRpcId, error: JsonRpcError): Promise<void> {\n await this.writeMessage({ id, error });\n }\n\n private async writeMessage(message: Record<string, unknown>): Promise<void> {\n if (!this.child || !this.child.stdin) {\n throw new Error(\"codex app-server is not running\");\n }\n const payload = JSON.stringify({ jsonrpc: \"2.0\", ...message });\n this.child.stdin.write(`${payload}\\n`);\n }\n\n private clearPendingRequests(error: Error): void {\n for (const pending of this.pendingRequests.values()) {\n pending.reject(error);\n }\n this.pendingRequests.clear();\n this.pendingServerRequests.clear();\n this.threadLiveSubscriptionIdByKey.clear();\n this.threadLiveModeByKey.clear();\n }\n\n private maybeRecoverFromTimeout(method: string, error: unknown): void {\n const message = error instanceof Error ? error.message : String(error ?? \"\");\n if (!isRequestTimeoutErrorMessage(message)) {\n return;\n }\n // Runtime methods may time out transiently (network/auth/backend contention).\n // Hard-recycling the app-server here causes request-failure storms and severe UI jank.\n // Keep automatic recycle only for initialize-timeouts.\n if (method !== \"initialize\") {\n const now = Date.now();\n const lastWarning = this.lastTimeoutWarningAtByMethod.get(method) ?? 0;\n if (now - lastWarning >= REQUEST_TIMEOUT_WARNING_COOLDOWN_MS) {\n this.lastTimeoutWarningAtByMethod.set(method, now);\n logWarn(\"[app-server] request timed out (keeping process alive)\", { method });\n }\n return;\n }\n if (this.timeoutRecoveryPromise) {\n return;\n }\n this.timeoutRecoveryPromise = (async () => {\n logWarn(\"[app-server] recycling after request timeout\", { method });\n try {\n await this.stop();\n } catch (stopError) {\n logWarn(\"[app-server] failed to recycle after timeout\", stopError);\n }\n })().finally(() => {\n this.timeoutRecoveryPromise = null;\n });\n }\n}\n","export type AppsListParams = {\n workspaceId?: string | null;\n threadId?: string | null;\n cursor?: string | null;\n limit?: number | null;\n};\n\nconst APPS_LIST_METHODS = new Set([\"app/list\", \"apps/list\", \"apps_list\"]);\n\nexport function isAppsListMethod(method: string): boolean {\n return APPS_LIST_METHODS.has(method);\n}\n\nexport function buildAppsListPayload(params?: AppsListParams): {\n threadId: string | null;\n cursor: string | null;\n limit: number | null;\n} {\n return {\n threadId: params?.threadId ?? null,\n cursor: params?.cursor ?? null,\n limit: params?.limit ?? null,\n };\n}\n\nexport function isMethodUnavailableError(error: unknown, method: string): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n const code = typeof (error as { code?: unknown }).code === \"number\"\n ? ((error as { code: number }).code)\n : null;\n if (code !== -32601 && code !== -32600) {\n return false;\n }\n const message = typeof (error as { message?: unknown }).message === \"string\"\n ? ((error as { message: string }).message).toLowerCase()\n : \"\";\n if (!message) {\n return false;\n }\n const normalizedMethod = method.toLowerCase();\n if (message.includes(\"method not found\") || message.includes(\"unknown method\")) {\n return true;\n }\n return message.includes(\"unknown variant\") && message.includes(normalizedMethod);\n}\n\nexport function isAppsListSoftFailure(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n const message = typeof (error as { message?: unknown }).message === \"string\"\n ? ((error as { message: string }).message).toLowerCase()\n : \"\";\n if (!message) {\n return false;\n }\n const mentionsAppsFailure = message.includes(\"failed to list apps\");\n if (!mentionsAppsFailure) {\n return false;\n }\n const hasTransportFailure =\n message.includes(\"failed to send request\") ||\n message.includes(\"transport channel closed\") ||\n message.includes(\"connection closed via error\") ||\n message.includes(\"reqwest::error\");\n if (hasTransportFailure) {\n return true;\n }\n const has403 =\n message.includes(\"status 403\") ||\n message.includes(\"403 forbidden\") ||\n message.includes(\"forbidden\");\n const hasConnectorDirectory = message.includes(\"connectors/directory/list\");\n const hasChallengeMarkers =\n message.includes(\"just a moment\") ||\n message.includes(\"cdn-cgi/challenge-platform\") ||\n message.includes(\"_cf_chl_opt\");\n const hasHtmlPayload = message.includes(\"<!doctype html\") || message.includes(\"<html\");\n return has403 && (hasConnectorDirectory || hasChallengeMarkers || hasHtmlPayload);\n}\n\nexport function isAppsListThreadNotFoundError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n const message = typeof (error as { message?: unknown }).message === \"string\"\n ? ((error as { message: string }).message).toLowerCase()\n : \"\";\n if (!message) {\n return false;\n }\n const mentionsThread = message.includes(\"thread\");\n const mentionsNotFound =\n message.includes(\"not found\") || message.includes(\"unknown thread\");\n return mentionsThread && mentionsNotFound;\n}\n","import path from \"path\";\n\nexport function buildCliEnv(codexPath: string, overrides: Partial<NodeJS.ProcessEnv> = {}): NodeJS.ProcessEnv {\n const env = { ...process.env, ...overrides };\n const currentPath = env.PATH ?? \"\";\n const codexDir = path.dirname(codexPath);\n const homeDir = process.env.HOME ?? \"\";\n const extraPathHints = (process.env.CODEX_PATH_HINTS ?? \"\")\n .split(path.delimiter)\n .map(entry => entry.trim())\n .filter(Boolean);\n const extras = [\n codexDir,\n \"/usr/local/bin\",\n \"/opt/homebrew/bin\",\n path.join(homeDir, \".local\", \"bin\"),\n path.join(homeDir, \".fnm\", \"aliases\", \"default\", \"bin\"),\n path.join(homeDir, \".fnm\", \"current\", \"bin\"),\n ...extraPathHints,\n ].filter(Boolean);\n\n const segments = [\n ...extras,\n ...currentPath.split(path.delimiter).filter(Boolean),\n ];\n\n env.PATH = Array.from(new Set(segments)).join(path.delimiter);\n return env;\n}\n","import path from \"node:path\";\nimport fs from \"node:fs/promises\";\nimport { randomUUID } from \"node:crypto\";\nimport { getAppState, getUserDataDir } from \"./app-state\";\nimport { cloneRepositoryFromUrl } from \"./git\";\nimport { FREE_PROFILE_LIMIT, licenseService, shouldEnforceProfileLimit } from \"./license-service\";\n\nconst STORE_FILE = \"workspace-parity.json\";\nconst LEGACY_STORE_FILE = \"workspace-parity.json\";\nconst PROFILE_ROOT_DIR = \"profiles\";\nconst PROFILE_PARITY_DIR = \"parity\";\nconst LEGACY_MIGRATION_MARKER_FILE = \"workspace-parity-profile-migration.json\";\n\nexport type WorkspaceSettings = {\n sidebarCollapsed: boolean;\n sortOrder?: number | null;\n groupId?: string | null;\n cloneSourceWorkspaceId?: string | null;\n gitRoot?: string | null;\n launchScript?: string | null;\n launchScripts?:\n | Array<{\n id: string;\n script: string;\n icon: string;\n label?: string | null;\n }>\n | null;\n worktreeSetupScript?: string | null;\n};\n\nexport type WorkspaceKind = \"main\" | \"worktree\";\n\nexport type WorkspaceInfo = {\n id: string;\n name: string;\n path: string;\n connected: boolean;\n kind?: WorkspaceKind;\n parentId?: string | null;\n worktree?: { branch: string } | null;\n settings: WorkspaceSettings;\n};\n\ntype WorkspaceStore = {\n version: 1;\n workspaces: WorkspaceInfo[];\n};\n\ntype LegacyMigrationMarker = {\n version: 1;\n migratedToProfileKey: string;\n migratedAt: string;\n};\n\ntype ActiveProfileContext = {\n profileName: string | null;\n profileKey: string;\n profileRootDir: string;\n parityStoreDir: string;\n};\n\nfunction defaultSettings(): WorkspaceSettings {\n return {\n sidebarCollapsed: false,\n sortOrder: null,\n groupId: null,\n cloneSourceWorkspaceId: null,\n gitRoot: null,\n launchScript: null,\n launchScripts: null,\n worktreeSetupScript: null,\n };\n}\n\nfunction defaultStore(): WorkspaceStore {\n return {\n version: 1,\n workspaces: [],\n };\n}\n\nfunction normalizeProfileName(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction toProfileStorageKey(profileName: string | null): string {\n const normalized = (profileName ?? \"default\")\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return normalized || \"default\";\n}\n\nasync function getActiveProfileContext(): Promise<ActiveProfileContext> {\n let profileName: string | null = null;\n try {\n const state = await getAppState();\n profileName = normalizeProfileName(state.app.lastProfileName);\n } catch {\n profileName = null;\n }\n const profileKey = toProfileStorageKey(profileName);\n const profileRootDir = path.join(getUserDataDir(), PROFILE_ROOT_DIR, profileKey);\n return {\n profileName,\n profileKey,\n profileRootDir,\n parityStoreDir: path.join(profileRootDir, PROFILE_PARITY_DIR),\n };\n}\n\nfunction toWorkspaceName(inputPath: string): string {\n const normalized = inputPath.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n const parts = normalized.split(\"/\").filter(Boolean);\n return parts[parts.length - 1] ?? inputPath;\n}\n\nasync function ensureStoreDir(): Promise<string> {\n const context = await getActiveProfileContext();\n const dir = context.parityStoreDir;\n await fs.mkdir(dir, { recursive: true });\n return dir;\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction legacyStorePath(): string {\n return path.join(getUserDataDir(), LEGACY_STORE_FILE);\n}\n\nfunction legacyMigrationMarkerPath(): string {\n return path.join(getUserDataDir(), LEGACY_MIGRATION_MARKER_FILE);\n}\n\nasync function readLegacyMigrationMarker(): Promise<LegacyMigrationMarker | null> {\n try {\n const raw = await fs.readFile(legacyMigrationMarkerPath(), \"utf8\");\n const parsed = JSON.parse(raw) as LegacyMigrationMarker;\n if (\n parsed &&\n parsed.version === 1 &&\n typeof parsed.migratedToProfileKey === \"string\" &&\n parsed.migratedToProfileKey.trim()\n ) {\n return parsed;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nasync function writeLegacyMigrationMarker(profileKey: string): Promise<void> {\n const marker: LegacyMigrationMarker = {\n version: 1,\n migratedToProfileKey: profileKey,\n migratedAt: new Date().toISOString(),\n };\n const markerPath = legacyMigrationMarkerPath();\n await fs.mkdir(path.dirname(markerPath), { recursive: true });\n await fs.writeFile(markerPath, JSON.stringify(marker, null, 2), \"utf8\");\n}\n\nasync function migrateLegacyStoreIfNeeded(scopedStorePath: string): Promise<void> {\n if (await fileExists(scopedStorePath)) {\n return;\n }\n\n const context = await getActiveProfileContext();\n const legacyPath = legacyStorePath();\n if (!(await fileExists(legacyPath))) {\n return;\n }\n\n const marker = await readLegacyMigrationMarker();\n if (\n marker &&\n marker.migratedToProfileKey &&\n marker.migratedToProfileKey !== context.profileKey\n ) {\n return;\n }\n\n await fs.mkdir(path.dirname(scopedStorePath), { recursive: true });\n await fs.copyFile(legacyPath, scopedStorePath);\n await writeLegacyMigrationMarker(context.profileKey);\n}\n\nasync function storePath(): Promise<string> {\n const dir = await ensureStoreDir();\n const scopedPath = path.join(dir, STORE_FILE);\n await migrateLegacyStoreIfNeeded(scopedPath);\n return scopedPath;\n}\n\nfunction sanitizeWorkspace(entry: Partial<WorkspaceInfo>): WorkspaceInfo | null {\n if (!entry || typeof entry !== \"object\") {\n return null;\n }\n const id = typeof entry.id === \"string\" && entry.id.trim() ? entry.id.trim() : null;\n const workspacePath = typeof entry.path === \"string\" && entry.path.trim() ? path.resolve(entry.path) : null;\n if (!id || !workspacePath) {\n return null;\n }\n const name =\n typeof entry.name === \"string\" && entry.name.trim()\n ? entry.name.trim()\n : toWorkspaceName(workspacePath);\n const branch =\n entry.worktree && typeof entry.worktree === \"object\" && typeof entry.worktree.branch === \"string\"\n ? entry.worktree.branch.trim() || \"main\"\n : \"main\";\n\n return {\n id,\n name,\n path: workspacePath,\n connected: Boolean(entry.connected),\n kind: entry.kind === \"worktree\" ? \"worktree\" : \"main\",\n parentId: typeof entry.parentId === \"string\" && entry.parentId.trim() ? entry.parentId.trim() : null,\n worktree: entry.kind === \"worktree\" ? { branch } : null,\n settings: {\n ...defaultSettings(),\n ...(entry.settings ?? {}),\n },\n };\n}\n\nasync function readStore(): Promise<WorkspaceStore> {\n const filePath = await storePath();\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n const parsed = JSON.parse(raw) as WorkspaceStore;\n const source = Array.isArray(parsed?.workspaces) ? parsed.workspaces : [];\n const workspaces = source\n .map((entry) => sanitizeWorkspace(entry))\n .filter((entry): entry is WorkspaceInfo => Boolean(entry));\n return {\n version: 1,\n workspaces,\n };\n } catch {\n return defaultStore();\n }\n}\n\nasync function writeStore(store: WorkspaceStore): Promise<void> {\n const filePath = await storePath();\n await fs.writeFile(filePath, JSON.stringify(store, null, 2), \"utf8\");\n}\n\nfunction dedupeByPath(workspaces: WorkspaceInfo[]): WorkspaceInfo[] {\n const seen = new Set<string>();\n const ordered: WorkspaceInfo[] = [];\n for (const workspace of workspaces) {\n const key = workspace.path.toLowerCase();\n if (seen.has(key)) {\n continue;\n }\n seen.add(key);\n ordered.push(workspace);\n }\n return ordered;\n}\n\nasync function upsertStore(mutator: (store: WorkspaceStore) => WorkspaceStore): Promise<WorkspaceStore> {\n const current = await readStore();\n const next = mutator(current);\n await writeStore(next);\n return next;\n}\n\nfunction isMainWorkspace(workspace: WorkspaceInfo): boolean {\n return (workspace.kind ?? \"main\") !== \"worktree\";\n}\n\nfunction pruneToFreeProjectLimit(workspaces: WorkspaceInfo[]): WorkspaceInfo[] {\n const mainWorkspaces = workspaces.filter((workspace) => isMainWorkspace(workspace));\n if (mainWorkspaces.length <= FREE_PROFILE_LIMIT) {\n return workspaces;\n }\n\n const keptMainIds = new Set(mainWorkspaces.slice(0, FREE_PROFILE_LIMIT).map((workspace) => workspace.id));\n return workspaces.filter((workspace) => {\n if (isMainWorkspace(workspace)) {\n return keptMainIds.has(workspace.id);\n }\n return typeof workspace.parentId === \"string\" && keptMainIds.has(workspace.parentId);\n });\n}\n\nasync function enforceFreeProjectLimitIfNeeded(workspaces: WorkspaceInfo[]): Promise<WorkspaceInfo[]> {\n const license = await licenseService.getStatus().catch(() => null);\n if (!license || !shouldEnforceProfileLimit(license)) {\n return workspaces;\n }\n\n const pruned = pruneToFreeProjectLimit(workspaces);\n if (pruned.length === workspaces.length) {\n return workspaces;\n }\n\n await writeStore({\n version: 1,\n workspaces: pruned,\n });\n return pruned;\n}\n\nfunction parseRepoName(gitUrl: string): string {\n const cleaned = gitUrl.trim().replace(/\\/+$/, \"\").replace(/\\.git$/, \"\");\n const parts = cleaned.split(/[/:]/).filter(Boolean);\n return parts[parts.length - 1] ?? \"workspace\";\n}\n\nexport async function listParityWorkspaces(): Promise<WorkspaceInfo[]> {\n const store = await readStore();\n const deduped = dedupeByPath(store.workspaces);\n return enforceFreeProjectLimitIfNeeded(deduped);\n}\n\nexport async function getParityWorkspaceById(id: string): Promise<WorkspaceInfo | null> {\n const workspaces = await listParityWorkspaces();\n return workspaces.find((entry) => entry.id === id) ?? null;\n}\n\nexport async function addParityWorkspace(targetPath: string): Promise<WorkspaceInfo> {\n const resolved = path.resolve(targetPath);\n const name = toWorkspaceName(resolved);\n await fs.mkdir(resolved, { recursive: true });\n\n const nextWorkspace: WorkspaceInfo = {\n id: randomUUID(),\n name,\n path: resolved,\n connected: true,\n kind: \"main\",\n parentId: null,\n worktree: null,\n settings: defaultSettings(),\n };\n\n await upsertStore((store) => ({\n version: 1,\n workspaces: dedupeByPath([nextWorkspace, ...store.workspaces]),\n }));\n\n return nextWorkspace;\n}\n\nexport async function addParityWorkspaceFromGitUrl(options: {\n url: string;\n targetParentPath?: string | null;\n name?: string | null;\n}): Promise<WorkspaceInfo> {\n const repoName = options.name?.trim() || parseRepoName(options.url);\n const context = await getActiveProfileContext();\n const parentPath =\n options.targetParentPath?.trim() || path.join(context.profileRootDir, \"workspaces\");\n\n const resolvedParent = path.resolve(parentPath);\n await fs.mkdir(resolvedParent, { recursive: true });\n\n const cloneResult = await cloneRepositoryFromUrl({\n url: options.url,\n destinationPath: resolvedParent,\n targetFolderName: repoName,\n });\n\n return addParityWorkspace(cloneResult.path);\n}\n\nexport async function addParityClone(options: {\n parentId: string;\n branch: string;\n name?: string | null;\n copyAgentsMd?: boolean;\n targetParentPath?: string | null;\n}): Promise<WorkspaceInfo> {\n const parent = await getParityWorkspaceById(options.parentId);\n if (!parent) {\n throw new Error(`Parent workspace '${options.parentId}' not found.`);\n }\n const branch = options.branch?.trim() || \"main\";\n const cloneName = options.name?.trim() || `${parent.name}-${branch}`;\n const cloneParentPath =\n typeof options.targetParentPath === \"string\" &&\n options.targetParentPath.trim().length > 0\n ? options.targetParentPath.trim()\n : path.dirname(parent.path);\n const clonePath = path.resolve(cloneParentPath, cloneName);\n await fs.mkdir(clonePath, { recursive: true });\n\n const workspace: WorkspaceInfo = {\n id: randomUUID(),\n name: cloneName,\n path: clonePath,\n connected: true,\n kind: \"worktree\",\n parentId: parent.id,\n worktree: { branch },\n settings: {\n ...defaultSettings(),\n cloneSourceWorkspaceId: parent.id,\n },\n };\n\n await upsertStore((store) => ({\n version: 1,\n workspaces: dedupeByPath([workspace, ...store.workspaces]),\n }));\n\n return workspace;\n}\n\nexport async function addParityWorktree(options: {\n parentId: string;\n branch: string;\n name?: string | null;\n copyAgentsMd?: boolean;\n targetParentPath?: string | null;\n}): Promise<WorkspaceInfo> {\n return addParityClone(options);\n}\n\nexport async function updateParityWorkspaceSettings(\n id: string,\n settings: Partial<WorkspaceSettings>,\n): Promise<WorkspaceInfo> {\n let updated: WorkspaceInfo | null = null;\n await upsertStore((store) => {\n const next = store.workspaces.map((entry) => {\n if (entry.id !== id) {\n return entry;\n }\n updated = {\n ...entry,\n settings: {\n ...entry.settings,\n ...settings,\n },\n };\n return updated;\n });\n return {\n version: 1,\n workspaces: next,\n };\n });\n\n if (!updated) {\n throw new Error(`Workspace '${id}' not found.`);\n }\n return updated;\n}\n\nexport async function removeParityWorkspace(id: string): Promise<void> {\n await upsertStore((store) => ({\n version: 1,\n workspaces: store.workspaces.filter((entry) => entry.id !== id && entry.parentId !== id),\n }));\n}\n\nexport async function removeParityWorktree(id: string): Promise<void> {\n await upsertStore((store) => ({\n version: 1,\n workspaces: store.workspaces.filter((entry) => entry.id !== id),\n }));\n}\n\nexport async function renameParityWorktree(id: string, branch: string): Promise<WorkspaceInfo> {\n const normalizedBranch = branch.trim();\n if (!normalizedBranch) {\n throw new Error(\"Branch name is required.\");\n }\n\n let updated: WorkspaceInfo | null = null;\n await upsertStore((store) => {\n const next = store.workspaces.map((entry) => {\n if (entry.id !== id) {\n return entry;\n }\n updated = {\n ...entry,\n name: normalizedBranch,\n worktree: {\n branch: normalizedBranch,\n },\n };\n return updated;\n });\n return {\n version: 1,\n workspaces: next,\n };\n });\n\n if (!updated) {\n throw new Error(`Workspace '${id}' not found.`);\n }\n return updated;\n}\n\nexport async function renameParityWorktreeUpstream(\n id: string,\n oldBranch: string,\n newBranch: string,\n): Promise<WorkspaceInfo> {\n void oldBranch;\n return renameParityWorktree(id, newBranch);\n}\n\nexport async function connectParityWorkspace(id: string): Promise<WorkspaceInfo> {\n let updated: WorkspaceInfo | null = null;\n await upsertStore((store) => {\n const next = store.workspaces.map((entry) => {\n if (entry.id !== id) {\n return entry;\n }\n updated = {\n ...entry,\n connected: true,\n };\n return updated;\n });\n return {\n version: 1,\n workspaces: next,\n };\n });\n\n if (!updated) {\n throw new Error(`Workspace '${id}' not found.`);\n }\n return updated;\n}\n","/**\n * Git Service\n *\n * Core git operations using native git CLI (CodexMonitor approach).\n * CLI is used first, isomorphic-git is fallback for edge cases.\n */\n\nimport git from \"isomorphic-git\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type {\n GitFileChange,\n GitFileStatus,\n GitRepoStatus,\n GitCommitOptions,\n GitCommitResult,\n GitAuthor,\n GitHubPullRequest,\n GitHubPullRequestComment,\n GitHubPullRequestDiff,\n GitCloneFromUrlOptions,\n GitCloneFromUrlResult,\n GitInitRepoResult,\n GitCreateGitHubRepoResult,\n GitPushCurrentBranchResult,\n} from \"./git-types\";\nimport * as cli from \"./git-cli\";\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Check if a directory is a git repository (CLI first)\n */\nexport async function isGitRepo(dir: string): Promise<boolean> {\n // Try CLI first\n const cliResult = await cli.isGitRepoCli(dir);\n if (cliResult) {\n return true;\n }\n // Fallback to isomorphic-git\n try {\n await git.findRoot({ fs, filepath: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the root directory of a git repo (CLI first)\n */\nexport async function getRepoRoot(dir: string): Promise<string | null> {\n // Try CLI first\n const cliResult = await cli.getRepoRootCli(dir);\n if (cliResult) {\n return cliResult;\n }\n // Fallback to isomorphic-git\n try {\n return await git.findRoot({ fs, filepath: dir });\n } catch {\n return null;\n }\n}\n\n/**\n * Get the current branch name (CLI first)\n */\nexport async function getCurrentBranch(dir: string): Promise<string | null> {\n // Try CLI first\n const cliResult = await cli.getCurrentBranchCli(dir);\n if (cliResult) {\n return cliResult;\n }\n // Fallback to isomorphic-git\n try {\n return (await git.currentBranch({ fs, dir, fullname: false })) ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Convert isomorphic-git status matrix to our file status\n * Status matrix format: [HEAD, WORKDIR, STAGE]\n * Values: 0 = absent, 1 = identical to HEAD, 2 = different from HEAD\n */\nfunction parseFileStatus(row: [string, number, number, number]): GitFileChange | null {\n const [filepath, head, workdir, stage] = row;\n\n // Skip unchanged files\n if (head === 1 && workdir === 1 && stage === 1) {\n return null;\n }\n\n let status: GitFileStatus = \"unchanged\";\n let staged = false;\n\n // Determine status based on the matrix\n if (head === 0 && workdir === 2 && stage === 0) {\n // New file, not staged (untracked)\n status = \"untracked\";\n } else if (head === 0 && workdir === 2 && stage === 2) {\n // New file, staged\n status = \"new\";\n staged = true;\n } else if (head === 0 && stage === 2) {\n // New file, staged\n status = \"new\";\n staged = true;\n } else if (head === 1 && workdir === 2 && stage === 1) {\n // Modified, not staged\n status = \"modified\";\n } else if (head === 1 && workdir === 2 && stage === 2) {\n // Modified, staged\n status = \"modified\";\n staged = true;\n } else if (head === 1 && stage === 2) {\n // Modified and staged\n status = \"modified\";\n staged = true;\n } else if (head === 1 && workdir === 0) {\n // Deleted\n status = \"deleted\";\n staged = stage === 0;\n } else if (head === 1 && workdir === 2 && stage === 3) {\n // Modified with staged and unstaged changes\n status = \"modified\";\n staged = true;\n }\n\n if (status === \"unchanged\") {\n return null;\n }\n\n return { filepath, status, staged };\n}\n\n/**\n * Calculate how many commits the local branch is ahead/behind the remote.\n * Uses the configured upstream or falls back to origin/<branch>.\n */\nasync function getAheadBehind(\n dir: string,\n branch: string | null\n): Promise<{ ahead: number; behind: number }> {\n if (!branch) {\n return { ahead: 0, behind: 0 };\n }\n\n try {\n // Try to find the remote tracking branch\n const remotes = await git.listRemotes({ fs, dir });\n if (remotes.length === 0) {\n return { ahead: 0, behind: 0 };\n }\n\n // Use 'origin' as default remote, or first available\n const remoteName = remotes.find((r) => r.remote === \"origin\")?.remote ?? remotes[0]?.remote;\n if (!remoteName) {\n return { ahead: 0, behind: 0 };\n }\n\n const remoteRef = `refs/remotes/${remoteName}/${branch}`;\n\n // Check if remote ref exists\n let remoteOid: string;\n try {\n remoteOid = await git.resolveRef({ fs, dir, ref: remoteRef });\n } catch {\n // Remote branch doesn't exist (e.g., new branch not pushed yet)\n // Count all local commits as \"ahead\"\n try {\n const localCommits = await git.log({ fs, dir, depth: 1000 });\n return { ahead: localCommits.length, behind: 0 };\n } catch {\n return { ahead: 0, behind: 0 };\n }\n }\n\n // Get local HEAD\n let localOid: string;\n try {\n localOid = await git.resolveRef({ fs, dir, ref: \"HEAD\" });\n } catch {\n return { ahead: 0, behind: 0 };\n }\n\n if (localOid === remoteOid) {\n return { ahead: 0, behind: 0 };\n }\n\n // Find merge base (common ancestor)\n const mergeBase = await git.findMergeBase({\n fs,\n dir,\n oids: [localOid, remoteOid],\n });\n\n if (!mergeBase || mergeBase.length === 0) {\n // No common ancestor - diverged completely\n return { ahead: 0, behind: 0 };\n }\n\n const baseOid = mergeBase[0];\n\n // Count commits from base to local (ahead)\n let ahead = 0;\n try {\n const localCommits = await git.log({ fs, dir, ref: localOid, depth: 1000 });\n for (const commit of localCommits) {\n if (commit.oid === baseOid) break;\n ahead++;\n }\n } catch {\n ahead = 0;\n }\n\n // Count commits from base to remote (behind)\n let behind = 0;\n try {\n const remoteCommits = await git.log({ fs, dir, ref: remoteOid, depth: 1000 });\n for (const commit of remoteCommits) {\n if (commit.oid === baseOid) break;\n behind++;\n }\n } catch {\n behind = 0;\n }\n\n return { ahead, behind };\n } catch (error) {\n console.error(\"Failed to calculate ahead/behind:\", error);\n return { ahead: 0, behind: 0 };\n }\n}\n\n/**\n * Get the status of all files in a git repository\n */\nexport async function getStatus(dir: string): Promise<GitRepoStatus> {\n // Check if it's a repo\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return {\n isRepo: false,\n branch: null,\n changes: [],\n hasChanges: false,\n ahead: 0,\n behind: 0,\n };\n }\n\n // Get branch\n const branch = await getCurrentBranch(repoRoot);\n\n // Try CLI first (CodexMonitor approach) - more reliable than isomorphic-git\n const cliStatus = await cli.getStatusCli(repoRoot);\n if (cliStatus) {\n return cliStatus;\n }\n\n // Fallback to isomorphic-git if CLI fails\n try {\n const statusMatrix = await git.statusMatrix({ fs, dir: repoRoot });\n\n const changes: GitFileChange[] = [];\n for (const row of statusMatrix) {\n const change = parseFileStatus(row as [string, number, number, number]);\n if (change) {\n changes.push(change);\n }\n }\n\n changes.sort((a, b) => {\n if (a.staged !== b.staged) {\n return a.staged ? -1 : 1;\n }\n return a.filepath.localeCompare(b.filepath);\n });\n\n const { ahead, behind } = await getAheadBehind(repoRoot, branch);\n\n return {\n isRepo: true,\n branch,\n changes,\n hasChanges: changes.length > 0,\n ahead,\n behind,\n };\n } catch (error) {\n console.error(\"Failed to read git status via isomorphic-git:\", error);\n\n return {\n isRepo: true,\n branch,\n changes: [],\n hasChanges: false,\n ahead: 0,\n behind: 0,\n };\n }\n}\n\n/**\n * Stage files for commit (CLI first)\n */\nexport async function stageFiles(dir: string, files: string[]): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository\");\n }\n\n // Try CLI first\n const cliResult = await cli.stageFilesCli(repoRoot, files);\n if (cliResult) {\n return;\n }\n\n // Fallback to isomorphic-git\n for (const filepath of files) {\n await git.add({ fs, dir: repoRoot, filepath });\n }\n}\n\n/**\n * Stage all changed files (CLI first)\n */\nexport async function stageAll(dir: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository\");\n }\n\n // Try CLI first\n const cliResult = await cli.stageAllCli(repoRoot);\n if (cliResult) {\n return;\n }\n\n // Fallback to isomorphic-git\n const status = await getStatus(repoRoot);\n\n for (const change of status.changes) {\n if (change.status === \"deleted\") {\n await git.remove({ fs, dir: repoRoot, filepath: change.filepath });\n } else {\n await git.add({ fs, dir: repoRoot, filepath: change.filepath });\n }\n }\n}\n\n/**\n * Create a commit (CLI first)\n */\nexport async function commit(options: GitCommitOptions): Promise<GitCommitResult> {\n const { dir, message, author, files } = options;\n\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return {\n sha: \"\",\n success: false,\n error: \"Not a git repository\",\n };\n }\n\n try {\n // Stage files if specified, otherwise stage all\n if (files && files.length > 0) {\n await stageFiles(repoRoot, files);\n } else {\n await stageAll(repoRoot);\n }\n\n // Try CLI first\n const cliResult = await cli.commitCli(repoRoot, message, author);\n if (cliResult.success) {\n return cliResult;\n }\n\n // Fallback to isomorphic-git\n const sha = await git.commit({\n fs,\n dir: repoRoot,\n message,\n author: {\n name: author.name,\n email: author.email,\n },\n });\n\n return {\n sha,\n success: true,\n };\n } catch (error) {\n return {\n sha: \"\",\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Get recent commits (CLI first)\n */\nexport async function getRecentCommits(\n dir: string,\n limit: number = 10\n): Promise<Array<{ sha: string; message: string; author: string; date: Date }>> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return [];\n }\n\n // Try CLI first\n const cliResult = await cli.getLogSummaryCli(repoRoot, limit);\n if (cliResult.length > 0) {\n return cliResult.map((c) => ({\n sha: c.sha,\n message: c.message,\n author: c.author,\n date: new Date(c.date),\n }));\n }\n\n // Fallback to isomorphic-git\n try {\n const commits = await git.log({ fs, dir: repoRoot, depth: limit });\n return commits.map((c) => ({\n sha: c.oid,\n message: c.commit.message,\n author: c.commit.author.name,\n date: new Date(c.commit.author.timestamp * 1000),\n }));\n } catch {\n return [];\n }\n}\n\n/**\n * Get default author from git config\n */\nexport async function getDefaultAuthor(dir: string): Promise<GitAuthor | null> {\n const cwd = await resolveGitCommandCwd(dir);\n\n const scopedName = await readGitConfigValue(cwd, [\"config\", \"--get\", \"user.name\"]);\n const scopedEmail = await readGitConfigValue(cwd, [\"config\", \"--get\", \"user.email\"]);\n\n let name = scopedName;\n let email = scopedEmail;\n\n if (!name || !email) {\n const globalName = await readGitConfigValue(cwd, [\"config\", \"--global\", \"--get\", \"user.name\"]);\n const globalEmail = await readGitConfigValue(cwd, [\"config\", \"--global\", \"--get\", \"user.email\"]);\n name = name ?? globalName;\n email = email ?? globalEmail;\n }\n\n if (!name || !email) {\n return null;\n }\n\n return { name, email };\n}\n\n/**\n * Simple line-by-line diff result\n */\nexport interface DiffLine {\n type: \"add\" | \"remove\" | \"context\";\n content: string;\n oldLineNumber?: number;\n newLineNumber?: number;\n}\n\nexport interface FileDiff {\n filepath: string;\n status: GitFileStatus;\n lines: DiffLine[];\n oldContent: string | null;\n newContent: string | null;\n isBinary: boolean;\n}\n\n/**\n * Check if content appears to be binary\n */\nfunction isBinaryContent(content: string): boolean {\n // Check for null bytes which indicate binary content\n return content.includes(\"\\0\");\n}\n\n/**\n * Simple diff algorithm - computes line-by-line changes\n */\nfunction computeLineDiff(oldContent: string, newContent: string): DiffLine[] {\n const oldLines = oldContent.split(\"\\n\");\n const newLines = newContent.split(\"\\n\");\n const result: DiffLine[] = [];\n\n // Use a simple LCS-based diff\n const lcs = computeLCS(oldLines, newLines);\n\n let oldIdx = 0;\n let newIdx = 0;\n let oldLineNum = 1;\n let newLineNum = 1;\n\n for (const [commonOldIdx, commonNewIdx] of lcs) {\n // Add removed lines before the common line\n while (oldIdx < commonOldIdx) {\n result.push({\n type: \"remove\",\n content: oldLines[oldIdx],\n oldLineNumber: oldLineNum++,\n });\n oldIdx++;\n }\n\n // Add inserted lines before the common line\n while (newIdx < commonNewIdx) {\n result.push({\n type: \"add\",\n content: newLines[newIdx],\n newLineNumber: newLineNum++,\n });\n newIdx++;\n }\n\n // Add the common line as context\n result.push({\n type: \"context\",\n content: oldLines[oldIdx],\n oldLineNumber: oldLineNum++,\n newLineNumber: newLineNum++,\n });\n oldIdx++;\n newIdx++;\n }\n\n // Add remaining removed lines\n while (oldIdx < oldLines.length) {\n result.push({\n type: \"remove\",\n content: oldLines[oldIdx],\n oldLineNumber: oldLineNum++,\n });\n oldIdx++;\n }\n\n // Add remaining inserted lines\n while (newIdx < newLines.length) {\n result.push({\n type: \"add\",\n content: newLines[newIdx],\n newLineNumber: newLineNum++,\n });\n newIdx++;\n }\n\n return result;\n}\n\n/**\n * Compute Longest Common Subsequence indices\n */\nfunction computeLCS(a: string[], b: string[]): [number, number][] {\n const m = a.length;\n const n = b.length;\n\n // Build LCS table\n const dp: number[][] = Array(m + 1)\n .fill(null)\n .map(() => Array(n + 1).fill(0));\n\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n if (a[i - 1] === b[j - 1]) {\n dp[i][j] = dp[i - 1][j - 1] + 1;\n } else {\n dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);\n }\n }\n }\n\n // Backtrack to find the actual LCS\n const result: [number, number][] = [];\n let i = m;\n let j = n;\n\n while (i > 0 && j > 0) {\n if (a[i - 1] === b[j - 1]) {\n result.unshift([i - 1, j - 1]);\n i--;\n j--;\n } else if (dp[i - 1][j] > dp[i][j - 1]) {\n i--;\n } else {\n j--;\n }\n }\n\n return result;\n}\n\n/**\n * Get the diff for a specific file\n */\nexport async function getFileDiff(dir: string, filepath: string): Promise<FileDiff | null> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return null;\n }\n\n try {\n // Get the file status first\n const status = await getStatus(repoRoot);\n const fileChange = status.changes.find((c) => c.filepath === filepath);\n\n if (!fileChange) {\n return null;\n }\n\n const fullPath = path.join(repoRoot, filepath);\n let oldContent: string | null = null;\n let newContent: string | null = null;\n\n // Get the HEAD version of the file\n if (fileChange.status !== \"new\" && fileChange.status !== \"untracked\") {\n try {\n const headCommit = await git.resolveRef({ fs, dir: repoRoot, ref: \"HEAD\" });\n const { blob } = await git.readBlob({\n fs,\n dir: repoRoot,\n oid: headCommit,\n filepath,\n });\n oldContent = new TextDecoder().decode(blob);\n } catch {\n // File doesn't exist in HEAD (new file)\n oldContent = null;\n }\n }\n\n // Get the working directory version\n if (fileChange.status !== \"deleted\") {\n try {\n newContent = await fs.promises.readFile(fullPath, \"utf-8\");\n } catch {\n newContent = null;\n }\n }\n\n // Check for binary content\n const isBinary =\n (oldContent !== null && isBinaryContent(oldContent)) ||\n (newContent !== null && isBinaryContent(newContent));\n\n if (isBinary) {\n return {\n filepath,\n status: fileChange.status,\n lines: [],\n oldContent: null,\n newContent: null,\n isBinary: true,\n };\n }\n\n // Compute the diff\n const lines = computeLineDiff(oldContent ?? \"\", newContent ?? \"\");\n\n return {\n filepath,\n status: fileChange.status,\n lines,\n oldContent,\n newContent,\n isBinary: false,\n };\n } catch (error) {\n console.error(\"Failed to get file diff:\", error);\n return null;\n }\n}\n\n/**\n * Discard changes for specific files (CLI first)\n * - For modified/deleted files: Restore content from HEAD\n * - For new/untracked files: Delete from disk\n */\nexport async function discardChanges(dir: string, filepaths: string[]): Promise<boolean> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) return false;\n\n // Try CLI first\n const cliResult = await cli.discardChangesCli(repoRoot, filepaths);\n if (cliResult) {\n return true;\n }\n\n // Fallback to isomorphic-git\n try {\n // Get HEAD commit\n const commits = await git.log({ fs, dir: repoRoot, depth: 1 });\n if (commits.length === 0) {\n // No commits yet, just delete all files\n for (const filepath of filepaths) {\n const fullPath = path.join(repoRoot, filepath);\n if (fs.existsSync(fullPath)) {\n await fs.promises.unlink(fullPath);\n }\n }\n return true;\n }\n\n const headCommit = commits[0].oid;\n\n for (const filepath of filepaths) {\n const fullPath = path.join(repoRoot, filepath);\n\n try {\n // Try to read file from HEAD commit\n const { blob } = await git.readBlob({\n fs,\n dir: repoRoot,\n oid: headCommit,\n filepath,\n });\n\n // File exists in HEAD - restore it\n await fs.promises.writeFile(fullPath, blob);\n\n // Also remove from staging area by resetting the index entry\n await git.resetIndex({ fs, dir: repoRoot, filepath });\n } catch {\n // File doesn't exist in HEAD (untracked/new) - delete it\n if (fs.existsSync(fullPath)) {\n await fs.promises.unlink(fullPath);\n }\n\n // If it was staged as new, remove from index\n try {\n await git.remove({ fs, dir: repoRoot, filepath });\n } catch {\n // Ignore if already not in index\n }\n }\n }\n return true;\n } catch (error) {\n console.error(\"Failed to discard changes:\", error);\n return false;\n }\n}\n\nfunction parseGitHubRepo(remoteUrl: string): string | null {\n if (!remoteUrl) {\n return null;\n }\n const trimmed = remoteUrl.trim();\n const scpMatch = /^git@github\\.com:([^/]+\\/[^/]+?)(?:\\.git)?$/i.exec(trimmed);\n if (scpMatch?.[1]) {\n return scpMatch[1];\n }\n\n try {\n const parsed = new URL(trimmed);\n if (parsed.hostname.toLowerCase() !== \"github.com\") {\n return null;\n }\n const pathname = parsed.pathname.replace(/^\\/+|\\/+$/g, \"\");\n if (!pathname) {\n return null;\n }\n return pathname.replace(/\\.git$/i, \"\");\n } catch {\n return null;\n }\n}\n\nasync function getGitHubRepoName(dir: string): Promise<{ repoRoot: string; repoName: string }> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n const remotes = await git.listRemotes({ fs, dir: repoRoot });\n if (!remotes.length) {\n throw new Error(\"No git remote configured.\");\n }\n const preferred = remotes.find((remote) => remote.remote === \"origin\") ?? remotes[0];\n const repoName = parseGitHubRepo(preferred.url ?? \"\");\n if (!repoName) {\n throw new Error(\"Remote is not a GitHub repository.\");\n }\n return { repoRoot, repoName };\n}\n\nfunction commandFailureDetail(\n stdout: string | Buffer | undefined,\n stderr: string | Buffer | undefined,\n fallback: string,\n): string {\n const stderrText = typeof stderr === \"string\" ? stderr : stderr?.toString(\"utf8\") ?? \"\";\n const stdoutText = typeof stdout === \"string\" ? stdout : stdout?.toString(\"utf8\") ?? \"\";\n const detail = (stderrText.trim() || stdoutText.trim());\n return detail || fallback;\n}\n\nasync function runGhCommand(\n repoRoot: string,\n args: string[],\n): Promise<{ stdout: string; stderr: string }> {\n try {\n const { stdout, stderr } = await execFileAsync(\"gh\", args, {\n cwd: repoRoot,\n maxBuffer: 25 * 1024 * 1024,\n });\n return { stdout: String(stdout ?? \"\"), stderr: String(stderr ?? \"\") };\n } catch (error) {\n const record = error as {\n stdout?: string | Buffer;\n stderr?: string | Buffer;\n message?: string;\n };\n const detail = commandFailureDetail(\n record.stdout,\n record.stderr,\n record.message ?? \"GitHub CLI command failed.\",\n );\n throw new Error(detail);\n }\n}\n\nasync function runGitCommand(\n cwd: string,\n args: string[],\n): Promise<{ stdout: string; stderr: string }> {\n try {\n const { stdout, stderr } = await execFileAsync(\"git\", args, {\n cwd,\n maxBuffer: 50 * 1024 * 1024,\n });\n return { stdout: String(stdout ?? \"\"), stderr: String(stderr ?? \"\") };\n } catch (error) {\n const record = error as {\n stdout?: string | Buffer;\n stderr?: string | Buffer;\n message?: string;\n };\n const detail = commandFailureDetail(\n record.stdout,\n record.stderr,\n record.message ?? \"Git command failed.\",\n );\n throw new Error(detail);\n }\n}\n\nasync function resolveGitCommandCwd(value: string): Promise<string> {\n const trimmed = value.trim();\n const fallback = process.cwd();\n if (!trimmed) {\n return fallback;\n }\n const resolved = path.resolve(trimmed);\n try {\n const stats = await fs.promises.stat(resolved);\n if (stats.isDirectory()) {\n return resolved;\n }\n return path.dirname(resolved);\n } catch {\n return fallback;\n }\n}\n\nasync function readGitConfigValue(cwd: string, args: string[]): Promise<string | null> {\n try {\n const { stdout } = await runGitCommand(cwd, args);\n const value = stdout.trim();\n return value.length > 0 ? value : null;\n } catch {\n return null;\n }\n}\n\nfunction defaultRepoNameFromUrl(url: string): string | null {\n const trimmed = url.trim().replace(/\\/+$/, \"\");\n if (!trimmed) {\n return null;\n }\n const tail = trimmed.split(\"/\").pop()?.trim() ?? \"\";\n if (!tail) {\n return null;\n }\n const withoutGit = tail.replace(/\\.git$/i, \"\");\n return withoutGit.trim() ? withoutGit.trim() : null;\n}\n\nfunction validateTargetFolderName(value: string): string {\n const trimmed = value.trim();\n if (!trimmed) {\n throw new Error(\"Target folder name is required.\");\n }\n if (trimmed.includes(\"/\") || trimmed.includes(\"\\\\\")) {\n throw new Error(\"Target folder name must not include path separators.\");\n }\n if (trimmed === \".\" || trimmed === \"..\") {\n throw new Error(\"Target folder name is invalid.\");\n }\n return trimmed;\n}\n\nfunction validateBranchName(name: string): string {\n const trimmed = name.trim();\n if (!trimmed) {\n throw new Error(\"Branch name is required.\");\n }\n if (/\\s/.test(trimmed)) {\n throw new Error(\"Branch name cannot contain whitespace.\");\n }\n if (trimmed.startsWith(\"/\") || trimmed.endsWith(\"/\")) {\n throw new Error(\"Branch name cannot start or end with '/'.\");\n }\n if (trimmed.includes(\"..\") || trimmed.includes(\"@{\") || trimmed.includes(\"//\")) {\n throw new Error(\"Branch name is invalid.\");\n }\n if (/[~^:?*[\\]\\\\]/.test(trimmed) || trimmed.endsWith(\".\")) {\n throw new Error(\"Branch name contains invalid characters.\");\n }\n return trimmed;\n}\n\nfunction validateRepoName(value: string): string {\n const trimmed = value.trim();\n if (!trimmed) {\n throw new Error(\"Repository name is required.\");\n }\n if (/\\s/.test(trimmed)) {\n throw new Error(\"Repository name cannot contain spaces.\");\n }\n if (trimmed.startsWith(\"/\") || trimmed.endsWith(\"/\")) {\n throw new Error(\"Repository name cannot start or end with '/'.\");\n }\n if (trimmed.includes(\"//\")) {\n throw new Error(\"Repository name is invalid.\");\n }\n return trimmed\n .replace(/^https?:\\/\\/github\\.com\\//i, \"\")\n .replace(/^git@github\\.com:/i, \"\")\n .replace(/\\.git$/i, \"\")\n .replace(/\\/+$/, \"\");\n}\n\nfunction parsePullRequestDiff(diffText: string): GitHubPullRequestDiff[] {\n const entries: GitHubPullRequestDiff[] = [];\n let currentLines: string[] = [];\n let currentOldPath: string | null = null;\n let currentNewPath: string | null = null;\n let currentStatus: string | null = null;\n\n const finalizeCurrent = () => {\n if (!currentLines.length) {\n return;\n }\n const diff = currentLines.join(\"\\n\");\n if (!diff.trim()) {\n return;\n }\n const status = currentStatus ?? \"M\";\n const resolvedPath =\n status === \"D\" ? currentOldPath : currentNewPath ?? currentOldPath;\n if (!resolvedPath) {\n return;\n }\n entries.push({\n path: resolvedPath.replace(/\\\\/g, \"/\"),\n status,\n diff,\n });\n };\n\n diffText.split(/\\r?\\n/).forEach((line) => {\n if (line.startsWith(\"diff --git \")) {\n finalizeCurrent();\n currentLines = [line];\n currentOldPath = null;\n currentNewPath = null;\n currentStatus = null;\n\n const rest = line.slice(\"diff --git \".length).trim();\n const [rawOldPath = \"\", rawNewPath = \"\"] = rest.split(/\\s+/);\n const oldPath = rawOldPath.replace(/^a\\//, \"\");\n const newPath = rawNewPath.replace(/^b\\//, \"\");\n currentOldPath = oldPath || null;\n currentNewPath = newPath || null;\n return;\n }\n\n if (line.startsWith(\"new file mode \")) {\n currentStatus = \"A\";\n } else if (line.startsWith(\"deleted file mode \")) {\n currentStatus = \"D\";\n } else if (line.startsWith(\"rename from \")) {\n currentStatus = \"R\";\n const renamedFrom = line.slice(\"rename from \".length).trim();\n if (renamedFrom) {\n currentOldPath = renamedFrom;\n }\n } else if (line.startsWith(\"rename to \")) {\n currentStatus = \"R\";\n const renamedTo = line.slice(\"rename to \".length).trim();\n if (renamedTo) {\n currentNewPath = renamedTo;\n }\n }\n\n currentLines.push(line);\n });\n\n finalizeCurrent();\n return entries;\n}\n\nexport async function getGitHubPullRequest(\n dir: string,\n prNumber: number,\n): Promise<GitHubPullRequest> {\n if (!Number.isFinite(prNumber) || prNumber <= 0) {\n throw new Error(\"Invalid pull request number.\");\n }\n const { repoRoot, repoName } = await getGitHubRepoName(dir);\n const { stdout } = await runGhCommand(repoRoot, [\n \"pr\",\n \"view\",\n String(prNumber),\n \"--repo\",\n repoName,\n \"--json\",\n \"number,title,url,updatedAt,createdAt,body,headRefName,baseRefName,isDraft,author\",\n ]);\n const parsed = JSON.parse(stdout) as GitHubPullRequest;\n return parsed;\n}\n\nexport async function getGitHubPullRequestDiff(\n dir: string,\n prNumber: number,\n): Promise<GitHubPullRequestDiff[]> {\n if (!Number.isFinite(prNumber) || prNumber <= 0) {\n throw new Error(\"Invalid pull request number.\");\n }\n const { repoRoot, repoName } = await getGitHubRepoName(dir);\n const { stdout } = await runGhCommand(repoRoot, [\n \"pr\",\n \"diff\",\n String(prNumber),\n \"--repo\",\n repoName,\n \"--color\",\n \"never\",\n ]);\n return parsePullRequestDiff(stdout);\n}\n\nexport async function getGitHubPullRequestComments(\n dir: string,\n prNumber: number,\n): Promise<GitHubPullRequestComment[]> {\n if (!Number.isFinite(prNumber) || prNumber <= 0) {\n throw new Error(\"Invalid pull request number.\");\n }\n const { repoRoot, repoName } = await getGitHubRepoName(dir);\n const { stdout } = await runGhCommand(repoRoot, [\n \"api\",\n `/repos/${repoName}/issues/${prNumber}/comments?per_page=30`,\n ]);\n const parsed = JSON.parse(stdout) as Array<Record<string, unknown>>;\n return parsed.map((comment) => ({\n id:\n typeof comment.id === \"number\" || typeof comment.id === \"string\"\n ? comment.id\n : \"\",\n body: typeof comment.body === \"string\" ? comment.body : \"\",\n createdAt:\n typeof comment.created_at === \"string\" ? comment.created_at : \"\",\n url: typeof comment.html_url === \"string\" ? comment.html_url : \"\",\n author:\n comment.user && typeof comment.user === \"object\"\n ? {\n login:\n typeof (comment.user as Record<string, unknown>).login === \"string\"\n ? String((comment.user as Record<string, unknown>).login)\n : \"unknown\",\n }\n : null,\n }));\n}\n\nexport async function checkoutGitHubPullRequest(\n dir: string,\n prNumber: number,\n): Promise<{ branch: string | null }> {\n if (!Number.isFinite(prNumber) || prNumber <= 0) {\n throw new Error(\"Invalid pull request number.\");\n }\n const { repoRoot } = await getGitHubRepoName(dir);\n await runGhCommand(repoRoot, [\"pr\", \"checkout\", String(prNumber)]);\n const branch = await getCurrentBranch(repoRoot);\n return { branch };\n}\n\nasync function countEffectiveDirEntries(root: string): Promise<number> {\n const entries = await fs.promises.readdir(root);\n let count = 0;\n for (const entry of entries) {\n if (entry === \".git\" || entry === \".DS_Store\" || entry === \"Thumbs.db\") {\n continue;\n }\n count += 1;\n }\n return count;\n}\n\nexport async function cloneRepositoryFromUrl(\n options: GitCloneFromUrlOptions,\n): Promise<GitCloneFromUrlResult> {\n const url = options.url?.trim() ?? \"\";\n if (!url) {\n throw new Error(\"Remote Git URL is required.\");\n }\n\n const destinationPath = options.destinationPath?.trim() ?? \"\";\n if (!destinationPath) {\n throw new Error(\"Destination folder is required.\");\n }\n\n const destination = path.resolve(destinationPath);\n let destinationStats: fs.Stats;\n try {\n destinationStats = await fs.promises.stat(destination);\n } catch {\n throw new Error(\"Destination folder must exist.\");\n }\n if (!destinationStats.isDirectory()) {\n throw new Error(\"Destination folder must be a directory.\");\n }\n\n const rawFolderName =\n options.targetFolderName?.trim() || defaultRepoNameFromUrl(url);\n if (!rawFolderName) {\n throw new Error(\"Could not determine target folder name.\");\n }\n const folderName = validateTargetFolderName(rawFolderName);\n const clonePath = path.join(destination, folderName);\n\n const cloneExists = await fs.promises\n .stat(clonePath)\n .then((value) => value.isDirectory())\n .catch(() => false);\n if (cloneExists) {\n const entryCount = await countEffectiveDirEntries(clonePath);\n if (entryCount > 0) {\n throw new Error(\"Destination path already exists and is not empty.\");\n }\n }\n\n try {\n await runGitCommand(destination, [\"clone\", url, clonePath]);\n } catch (error) {\n await fs.promises.rm(clonePath, { recursive: true, force: true }).catch(() => undefined);\n throw error;\n }\n\n return {\n path: clonePath,\n name: path.basename(clonePath),\n };\n}\n\nexport async function initGitRepository(\n dir: string,\n branch: string,\n force = false,\n): Promise<GitInitRepoResult> {\n const workspacePath = path.resolve(dir.trim());\n const normalizedBranch = validateBranchName(branch);\n\n let stats: fs.Stats;\n try {\n stats = await fs.promises.stat(workspacePath);\n } catch {\n throw new Error(\"Workspace path does not exist.\");\n }\n if (!stats.isDirectory()) {\n throw new Error(\"Workspace path must be a directory.\");\n }\n\n const existingRoot = await getRepoRoot(workspacePath);\n if (existingRoot) {\n return { status: \"already_initialized\" };\n }\n\n const entryCount = await countEffectiveDirEntries(workspacePath);\n if (entryCount > 0 && !force) {\n return { status: \"needs_confirmation\", entryCount };\n }\n\n await runGitCommand(workspacePath, [\"init\", \"-b\", normalizedBranch]);\n\n let commitError: string | null = null;\n if (entryCount > 0) {\n await runGitCommand(workspacePath, [\"add\", \"--all\"]);\n try {\n await runGitCommand(workspacePath, [\"commit\", \"-m\", \"chore: initial commit\"]);\n } catch (error) {\n commitError = error instanceof Error ? error.message : String(error);\n }\n }\n\n return {\n status: \"initialized\",\n commitError,\n };\n}\n\nfunction isRepoAlreadyExistsMessage(message: string): boolean {\n const lower = message.toLowerCase();\n return (\n lower.includes(\"already exists\")\n || lower.includes(\"name already exists\")\n || lower.includes(\"has already been taken\")\n );\n}\n\nexport async function createGitHubRepo(\n dir: string,\n repo: string,\n visibility: \"private\" | \"public\",\n branch: string,\n): Promise<GitCreateGitHubRepoResult> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n\n const repoName = validateRepoName(repo);\n const normalizedBranch = validateBranchName(branch);\n const visibilityFlag = visibility === \"public\" ? \"--public\" : \"--private\";\n\n const remotes = await git.listRemotes({ fs, dir: repoRoot });\n const originExists = remotes.some((entry) => entry.remote === \"origin\");\n\n try {\n if (originExists) {\n await runGhCommand(repoRoot, [\"repo\", \"create\", repoName, visibilityFlag]);\n } else {\n await runGhCommand(repoRoot, [\n \"repo\",\n \"create\",\n repoName,\n visibilityFlag,\n \"--source=.\",\n \"--remote=origin\",\n ]);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (!isRepoAlreadyExistsMessage(message)) {\n throw error;\n }\n }\n\n let pushError: string | null = null;\n let defaultBranchError: string | null = null;\n\n const hasHeadCommit = await runGitCommand(repoRoot, [\"rev-parse\", \"--verify\", \"HEAD\"])\n .then(() => true)\n .catch(() => false);\n\n if (hasHeadCommit) {\n try {\n await runGitCommand(repoRoot, [\"push\", \"-u\", \"origin\", normalizedBranch]);\n } catch (error) {\n pushError = error instanceof Error ? error.message : String(error);\n }\n } else {\n pushError = \"No commits yet. Create a commit before publishing.\";\n }\n\n try {\n await runGhCommand(repoRoot, [\"repo\", \"edit\", repoName, \"--default-branch\", normalizedBranch]);\n } catch (error) {\n defaultBranchError = error instanceof Error ? error.message : String(error);\n }\n\n const remoteUrl = await runGitCommand(repoRoot, [\"remote\", \"get-url\", \"origin\"])\n .then((result) => result.stdout.trim() || null)\n .catch(() => null);\n\n return {\n status: pushError || defaultBranchError ? \"partial\" : \"ok\",\n pushError,\n defaultBranchError,\n remoteUrl,\n };\n}\n\nexport async function pushCurrentBranch(\n dir: string,\n branch?: string,\n): Promise<GitPushCurrentBranchResult> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n\n const branchName = branch?.trim()\n ? validateBranchName(branch)\n : await getCurrentBranch(repoRoot);\n if (!branchName) {\n throw new Error(\"Detached HEAD. Checkout a branch before pushing.\");\n }\n\n const remotes = await git.listRemotes({ fs, dir: repoRoot });\n const remoteName = remotes.find((entry) => entry.remote === \"origin\")?.remote ?? remotes[0]?.remote;\n if (!remoteName) {\n throw new Error(\"No git remote configured. Add a remote and push again.\");\n }\n\n const hasHeadCommit = await runGitCommand(repoRoot, [\"rev-parse\", \"--verify\", \"HEAD\"])\n .then(() => true)\n .catch(() => false);\n if (!hasHeadCommit) {\n throw new Error(\"No commits yet. Create a commit before pushing.\");\n }\n\n const { stdout, stderr } = await runGitCommand(repoRoot, [\"push\", \"-u\", remoteName, branchName]);\n const output = `${stdout}\\n${stderr}`;\n const remoteUrl = await runGitCommand(repoRoot, [\"remote\", \"get-url\", remoteName])\n .then((result) => result.stdout.trim() || null)\n .catch(() => null);\n\n return {\n status: /everything up[\\s-]*to[\\s-]*date/i.test(output) ? \"up_to_date\" : \"ok\",\n branch: branchName,\n remote: remoteName,\n remoteBranch: branchName,\n remoteUrl,\n };\n}\n\nconst MAX_COMMIT_DIFF_CHARS = 30_000;\n\nfunction trimCommitDiff(value: string): string {\n const normalized = value.trim();\n if (normalized.length <= MAX_COMMIT_DIFF_CHARS) {\n return normalized;\n }\n const truncated = normalized.slice(0, MAX_COMMIT_DIFF_CHARS);\n return `${truncated}\\n\\n[diff truncated]`;\n}\n\nexport async function getCommitMessageDiff(dir: string): Promise<string> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n\n const stagedRaw = await runGitCommand(repoRoot, [\"diff\", \"--cached\", \"--no-color\", \"--\"]).then((value) => value.stdout);\n const staged = stagedRaw.trim();\n\n if (staged) {\n return trimCommitDiff(staged);\n }\n\n throw new Error(\"No staged changes found to summarize.\");\n}\n\nconst IMAGE_EXTENSIONS = new Set([\n \".png\",\n \".jpg\",\n \".jpeg\",\n \".gif\",\n \".webp\",\n \".bmp\",\n \".svg\",\n \".tif\",\n \".tiff\",\n \".ico\",\n \".avif\",\n \".heic\",\n]);\n\nfunction isImagePath(targetPath: string): boolean {\n const extension = path.extname(targetPath).toLowerCase();\n return IMAGE_EXTENSIONS.has(extension);\n}\n\nfunction toDiffString(lines: DiffLine[]): string {\n return lines\n .map((line) => {\n if (line.type === \"add\") {\n return `+${line.content}`;\n }\n if (line.type === \"remove\") {\n return `-${line.content}`;\n }\n return ` ${line.content}`;\n })\n .join(\"\\n\");\n}\n\ntype FlatGitDiff = {\n path: string;\n status: string;\n diff: string;\n oldLines?: string[];\n newLines?: string[];\n isBinary?: boolean;\n isImage?: boolean;\n oldImageData?: string | null;\n newImageData?: string | null;\n oldImageMime?: string | null;\n newImageMime?: string | null;\n};\n\ntype FlatGitLogEntry = {\n sha: string;\n summary: string;\n author: string;\n timestamp: number;\n};\n\nexport type GitLogSummary = {\n total: number;\n entries: FlatGitLogEntry[];\n ahead: number;\n behind: number;\n aheadEntries: FlatGitLogEntry[];\n behindEntries: FlatGitLogEntry[];\n upstream: string | null;\n};\n\nfunction parseLogEntries(stdout: string): FlatGitLogEntry[] {\n return stdout\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => {\n const [sha = \"\", summary = \"\", author = \"\", timestampRaw = \"0\"] =\n line.split(\"\\x1f\");\n const timestampSeconds = Number(timestampRaw);\n const timestamp = Number.isFinite(timestampSeconds)\n ? Math.max(0, Math.trunc(timestampSeconds * 1000))\n : 0;\n return {\n sha,\n summary,\n author,\n timestamp,\n };\n })\n .filter((entry) => entry.sha.length > 0);\n}\n\nexport async function listGitRoots(dir: string, depth = 2): Promise<string[]> {\n const start = path.resolve(dir);\n const queue: Array<{ current: string; remaining: number }> = [\n { current: start, remaining: Math.max(0, Math.trunc(depth)) },\n ];\n const visited = new Set<string>();\n const results: string[] = [];\n\n while (queue.length > 0) {\n const next = queue.shift();\n if (!next) continue;\n if (visited.has(next.current)) continue;\n visited.add(next.current);\n\n const gitPath = path.join(next.current, \".git\");\n const hasGit = await fs.promises\n .stat(gitPath)\n .then((stats) => stats.isDirectory() || stats.isFile())\n .catch(() => false);\n if (hasGit) {\n results.push(next.current);\n continue;\n }\n\n if (next.remaining <= 0) {\n continue;\n }\n\n const children = await fs.promises\n .readdir(next.current, { withFileTypes: true })\n .catch(() => [] as fs.Dirent[]);\n for (const child of children) {\n if (!child.isDirectory()) continue;\n if (child.name === \".git\" || child.name === \"node_modules\") continue;\n if (child.name.startsWith(\".\")) continue;\n queue.push({\n current: path.join(next.current, child.name),\n remaining: next.remaining - 1,\n });\n }\n }\n\n return results.sort((a, b) => a.localeCompare(b));\n}\n\nexport async function listBranches(\n dir: string,\n): Promise<Array<{ name: string; lastCommit: number }>> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return [];\n }\n const { stdout } = await runGitCommand(repoRoot, [\n \"for-each-ref\",\n \"--sort=-committerdate\",\n \"--format=%(refname:short)\\t%(committerdate:unix)\",\n \"refs/heads\",\n ]);\n return stdout\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => {\n const [name = \"\", timestampRaw = \"0\"] = line.split(\"\\t\");\n const timestampSeconds = Number(timestampRaw);\n return {\n name,\n lastCommit: Number.isFinite(timestampSeconds)\n ? Math.max(0, Math.trunc(timestampSeconds * 1000))\n : 0,\n };\n })\n .filter((entry) => entry.name.length > 0);\n}\n\nexport async function checkoutBranch(dir: string, name: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n const branch = validateBranchName(name);\n await runGitCommand(repoRoot, [\"checkout\", branch]);\n}\n\nexport async function createBranch(dir: string, name: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n const branch = validateBranchName(name);\n await runGitCommand(repoRoot, [\"checkout\", \"-b\", branch]);\n}\n\nexport async function getRemoteUrl(dir: string): Promise<string | null> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return null;\n }\n try {\n const { stdout } = await runGitCommand(repoRoot, [\n \"remote\",\n \"get-url\",\n \"origin\",\n ]);\n const value = stdout.trim();\n return value || null;\n } catch {\n return null;\n }\n}\n\nexport async function getGitLogSummary(\n dir: string,\n limit = 40,\n): Promise<GitLogSummary> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return {\n total: 0,\n entries: [],\n ahead: 0,\n behind: 0,\n aheadEntries: [],\n behindEntries: [],\n upstream: null,\n };\n }\n\n const logLimit = Number.isFinite(limit) && limit > 0 ? Math.floor(limit) : 40;\n const format = \"%H%x1f%s%x1f%an%x1f%at\";\n const [entriesResult, upstreamResult] = await Promise.all([\n runGitCommand(repoRoot, [\"log\", `--pretty=format:${format}`, `-n${logLimit}`]).catch(\n () => ({ stdout: \"\", stderr: \"\" }),\n ),\n runGitCommand(repoRoot, [\n \"rev-parse\",\n \"--abbrev-ref\",\n \"--symbolic-full-name\",\n \"@{upstream}\",\n ]).catch(() => ({ stdout: \"\", stderr: \"\" }),\n ),\n ]);\n\n const entries = parseLogEntries(entriesResult.stdout);\n const upstream = upstreamResult.stdout.trim() || null;\n let aheadEntries: FlatGitLogEntry[] = [];\n let behindEntries: FlatGitLogEntry[] = [];\n\n if (upstream) {\n const [aheadResult, behindResult] = await Promise.all([\n runGitCommand(repoRoot, [\n \"log\",\n `--pretty=format:${format}`,\n `${upstream}..HEAD`,\n ]).catch(() => ({ stdout: \"\", stderr: \"\" }),\n ),\n runGitCommand(repoRoot, [\n \"log\",\n `--pretty=format:${format}`,\n `HEAD..${upstream}`,\n ]).catch(() => ({ stdout: \"\", stderr: \"\" }),\n ),\n ]);\n aheadEntries = parseLogEntries(aheadResult.stdout);\n behindEntries = parseLogEntries(behindResult.stdout);\n }\n\n return {\n total: entries.length,\n entries,\n ahead: aheadEntries.length,\n behind: behindEntries.length,\n aheadEntries,\n behindEntries,\n upstream,\n };\n}\n\nexport async function getDiffs(dir: string): Promise<FlatGitDiff[]> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return [];\n }\n const status = await getStatus(repoRoot);\n const results: FlatGitDiff[] = [];\n for (const change of status.changes) {\n const fileDiff = await getFileDiff(repoRoot, change.filepath);\n if (!fileDiff) {\n continue;\n }\n const image = isImagePath(change.filepath);\n results.push({\n path: change.filepath,\n status: change.status,\n diff: fileDiff.isBinary ? \"\" : toDiffString(fileDiff.lines),\n oldLines: fileDiff.oldContent?.split(\"\\n\"),\n newLines: fileDiff.newContent?.split(\"\\n\"),\n isBinary: fileDiff.isBinary,\n isImage: image,\n oldImageData: null,\n newImageData: null,\n oldImageMime: null,\n newImageMime: null,\n });\n }\n return results;\n}\n\nexport async function getCommitDiff(\n dir: string,\n sha: string,\n): Promise<FlatGitDiff[]> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n return [];\n }\n const normalizedSha = sha.trim();\n if (!normalizedSha) {\n throw new Error(\"Commit SHA is required.\");\n }\n const { stdout } = await runGitCommand(repoRoot, [\n \"show\",\n \"--format=\",\n \"--no-color\",\n \"--binary\",\n normalizedSha,\n ]);\n return parsePullRequestDiff(stdout).map((entry) => ({\n path: entry.path,\n status: entry.status,\n diff: entry.diff,\n }));\n}\n\nexport async function stageFile(dir: string, filepath: string): Promise<void> {\n const normalized = filepath.trim();\n if (!normalized) {\n throw new Error(\"File path is required.\");\n }\n await stageFiles(dir, [normalized]);\n}\n\nexport async function unstageFile(dir: string, filepath: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n const normalized = filepath.trim();\n if (!normalized) {\n throw new Error(\"File path is required.\");\n }\n try {\n await runGitCommand(repoRoot, [\"restore\", \"--staged\", \"--\", normalized]);\n } catch {\n await runGitCommand(repoRoot, [\"reset\", \"HEAD\", \"--\", normalized]);\n }\n}\n\nexport async function revertFile(dir: string, filepath: string): Promise<void> {\n const normalized = filepath.trim();\n if (!normalized) {\n throw new Error(\"File path is required.\");\n }\n const success = await discardChanges(dir, [normalized]);\n if (!success) {\n throw new Error(`Failed to revert '${normalized}'.`);\n }\n}\n\nexport async function revertAll(dir: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n const status = await getStatus(repoRoot);\n if (status.changes.length === 0) {\n return;\n }\n const success = await discardChanges(\n repoRoot,\n status.changes.map((change) => change.filepath),\n );\n if (!success) {\n throw new Error(\"Failed to revert all changes.\");\n }\n}\n\nexport async function pull(dir: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n await runGitCommand(repoRoot, [\"pull\", \"--ff-only\"]);\n}\n\nexport async function fetch(dir: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n await runGitCommand(repoRoot, [\"fetch\", \"--all\", \"--prune\"]);\n}\n\nfunction isMissingTrackingBranchError(message: string): boolean {\n const normalized = message.toLowerCase();\n return (\n normalized.includes(\"no tracking information\") ||\n normalized.includes(\"no upstream configured\")\n );\n}\n\nexport async function sync(dir: string): Promise<void> {\n const repoRoot = await getRepoRoot(dir);\n if (!repoRoot) {\n throw new Error(\"Not a git repository.\");\n }\n await fetch(repoRoot);\n try {\n await pull(repoRoot);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (!isMissingTrackingBranchError(message)) {\n throw error;\n }\n }\n await pushCurrentBranch(repoRoot);\n}\n\nexport async function getGitHubIssues(\n dir: string,\n): Promise<{ total: number; issues: Array<{ number: number; title: string; url: string; updatedAt: string }> }> {\n const { repoRoot, repoName } = await getGitHubRepoName(dir);\n const { stdout } = await runGhCommand(repoRoot, [\n \"api\",\n `/repos/${repoName}/issues?state=open&per_page=30`,\n ]);\n const parsed = JSON.parse(stdout) as Array<Record<string, unknown>>;\n const issues = parsed\n .filter((entry) => !(\"pull_request\" in entry))\n .map((entry) => ({\n number: Number(entry.number ?? 0),\n title: String(entry.title ?? \"\"),\n url: String(entry.html_url ?? entry.url ?? \"\"),\n updatedAt: String(entry.updated_at ?? \"\"),\n }))\n .filter((entry) => Number.isFinite(entry.number) && entry.number > 0);\n return {\n total: issues.length,\n issues,\n };\n}\n\nexport async function getGitHubPullRequests(\n dir: string,\n): Promise<{ total: number; pullRequests: GitHubPullRequest[] }> {\n const { repoRoot, repoName } = await getGitHubRepoName(dir);\n const { stdout } = await runGhCommand(repoRoot, [\n \"pr\",\n \"list\",\n \"--repo\",\n repoName,\n \"--state\",\n \"open\",\n \"--limit\",\n \"30\",\n \"--json\",\n \"number,title,url,updatedAt,createdAt,body,headRefName,baseRefName,isDraft,author\",\n ]);\n const pullRequests = JSON.parse(stdout) as GitHubPullRequest[];\n return {\n total: pullRequests.length,\n pullRequests,\n };\n}\n","/**\n * Git CLI Operations\n *\n * All git operations using native git CLI (CodexMonitor approach).\n * CLI is used first, isomorphic-git is only fallback.\n */\n\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type {\n GitFileChange,\n GitFileStatus,\n GitRepoStatus,\n GitAuthor,\n} from \"./git-types\";\n\nconst execFileAsync = promisify(execFile);\nconst MAX_BUFFER_BYTES = 10 * 1024 * 1024;\n\n/**\n * Check if a directory is a git repository (CLI version)\n */\nexport async function isGitRepoCli(dir: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"rev-parse\", \"--git-dir\"], {\n cwd: dir,\n encoding: \"utf8\",\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the root directory of a git repo (CLI version)\n */\nexport async function getRepoRootCli(dir: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"rev-parse\", \"--show-toplevel\"],\n { cwd: dir, encoding: \"utf8\" }\n );\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the current branch name (CLI version)\n */\nexport async function getCurrentBranchCli(dir: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"],\n { cwd: dir, encoding: \"utf8\" }\n );\n const branch = stdout.trim();\n return branch === \"HEAD\" ? null : branch;\n } catch {\n return null;\n }\n}\n\nfunction parseBranchLine(line: string): {\n branch: string | null;\n ahead: number;\n behind: number;\n} {\n const trimmed = line.trim();\n let branch: string | null = null;\n\n if (trimmed.startsWith(\"No commits yet on \")) {\n branch = trimmed.slice(\"No commits yet on \".length).trim();\n } else if (trimmed.startsWith(\"Initial commit on \")) {\n branch = trimmed.slice(\"Initial commit on \".length).trim();\n } else if (trimmed.startsWith(\"HEAD\")) {\n branch = null;\n } else {\n branch = trimmed.split(\"...\")[0]?.trim() ?? null;\n }\n\n const aheadMatch = trimmed.match(/ahead (\\d+)/);\n const behindMatch = trimmed.match(/behind (\\d+)/);\n\n return {\n branch,\n ahead: aheadMatch ? Number(aheadMatch[1]) : 0,\n behind: behindMatch ? Number(behindMatch[1]) : 0,\n };\n}\n\nfunction mapStatusFromXY(xy: string): { status: GitFileStatus; staged: boolean } | null {\n if (xy.length < 2 || xy === \"??\") {\n return null;\n }\n\n const x = xy[0];\n const y = xy[1];\n\n if (x === \" \" && y === \" \") {\n return null;\n }\n\n let status: GitFileStatus = \"modified\";\n\n if (x === \"D\" || y === \"D\") {\n status = \"deleted\";\n } else if (x === \"A\" || y === \"A\") {\n status = \"new\";\n } else if (\n x === \"M\" ||\n y === \"M\" ||\n x === \"R\" ||\n y === \"R\" ||\n x === \"C\" ||\n y === \"C\" ||\n x === \"U\" ||\n y === \"U\"\n ) {\n status = \"modified\";\n } else {\n return null;\n }\n\n const staged = x !== \" \" && x !== \"?\";\n\n return { status, staged };\n}\n\n/**\n * Get git status (CLI version)\n */\nexport async function getStatusCli(dir: string): Promise<GitRepoStatus | null> {\n const repoRoot = await getRepoRootCli(dir);\n if (!repoRoot) {\n return { isRepo: false, branch: null, changes: [], hasChanges: false, ahead: 0, behind: 0 };\n }\n\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"-c\", \"core.quotepath=false\", \"status\", \"--porcelain=1\", \"--branch\", \"-z\"],\n {\n cwd: repoRoot,\n encoding: \"utf8\",\n maxBuffer: MAX_BUFFER_BYTES,\n }\n );\n\n const records = stdout.split(\"\\0\");\n let branch: string | null = null;\n let ahead = 0;\n let behind = 0;\n const changes: GitFileChange[] = [];\n\n for (let i = 0; i < records.length; i++) {\n const record = records[i];\n if (!record) {\n continue;\n }\n\n if (record.startsWith(\"## \")) {\n const parsed = parseBranchLine(record.slice(3));\n branch = parsed.branch;\n ahead = parsed.ahead;\n behind = parsed.behind;\n continue;\n }\n\n if (record.length < 3) {\n continue;\n }\n\n const xy = record.slice(0, 2);\n let filepath = record.slice(3);\n\n if (!filepath) {\n continue;\n }\n\n if (xy === \"??\") {\n changes.push({ filepath, status: \"untracked\", staged: false });\n continue;\n }\n\n if (xy.includes(\"R\") || xy.includes(\"C\")) {\n const renamed = records[i + 1];\n if (renamed) {\n filepath = renamed;\n i += 1;\n }\n }\n\n const parsed = mapStatusFromXY(xy);\n if (!parsed) {\n continue;\n }\n\n changes.push({ filepath, status: parsed.status, staged: parsed.staged });\n }\n\n changes.sort((a, b) => {\n if (a.staged !== b.staged) {\n return a.staged ? -1 : 1;\n }\n return a.filepath.localeCompare(b.filepath);\n });\n\n return {\n isRepo: true,\n branch,\n changes,\n hasChanges: changes.length > 0,\n ahead,\n behind,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Stage files (CLI version)\n */\nexport async function stageFilesCli(dir: string, files: string[]): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"add\", \"--\", ...files], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Stage all changes (CLI version)\n */\nexport async function stageAllCli(dir: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"add\", \"-A\"], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Unstage files (CLI version)\n */\nexport async function unstageFilesCli(dir: string, files: string[]): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"reset\", \"HEAD\", \"--\", ...files], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Unstage all (CLI version)\n */\nexport async function unstageAllCli(dir: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"reset\", \"HEAD\"], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Create a commit (CLI version)\n */\nexport async function commitCli(\n dir: string,\n message: string,\n author?: { name: string; email: string }\n): Promise<{ sha: string; success: boolean; error?: string }> {\n try {\n const env: Record<string, string> = {};\n if (author) {\n env.GIT_AUTHOR_NAME = author.name;\n env.GIT_AUTHOR_EMAIL = author.email;\n }\n\n await execFileAsync(\"git\", [\"commit\", \"-m\", message], {\n cwd: dir,\n env: { ...process.env, ...env },\n });\n\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"HEAD\"], {\n cwd: dir,\n encoding: \"utf8\",\n });\n\n return { sha: stdout.trim(), success: true };\n } catch (error) {\n return {\n sha: \"\",\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Get default author (CLI version)\n */\nexport async function getDefaultAuthorCli(dir: string): Promise<GitAuthor | null> {\n try {\n const [{ stdout: name }, { stdout: email }] = await Promise.all([\n execFileAsync(\"git\", [\"config\", \"user.name\"], { cwd: dir, encoding: \"utf8\" }),\n execFileAsync(\"git\", [\"config\", \"user.email\"], { cwd: dir, encoding: \"utf8\" }),\n ]);\n\n const nameStr = name.trim();\n const emailStr = email.trim();\n\n if (!nameStr || !emailStr) {\n return null;\n }\n\n return { name: nameStr, email: emailStr };\n } catch {\n return null;\n }\n}\n\n/**\n * List remotes (CLI version)\n */\nexport async function listRemotesCli(\n dir: string\n): Promise<{ remote: string; url: string }[]> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"remote\", \"-v\"], {\n cwd: dir,\n encoding: \"utf8\",\n });\n\n const remotes: { remote: string; url: string }[] = [];\n const seen = new Set<string>();\n\n for (const line of stdout.split(\"\\n\")) {\n const match = line.match(/^(\\S+)\\s+(\\S+)\\s+\\(fetch\\)$/);\n if (match) {\n const [, name, url] = match;\n if (!seen.has(name)) {\n seen.add(name);\n remotes.push({ remote: name, url });\n }\n }\n }\n\n return remotes;\n } catch {\n return [];\n }\n}\n\n/**\n * Get remote URL (CLI version)\n */\nexport async function getRemoteUrlCli(dir: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"config\", \"--get\", \"remote.origin.url\"],\n { cwd: dir, encoding: \"utf8\" }\n );\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Pull (CLI version)\n */\nexport async function pullCli(dir: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"pull\"], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Fetch (CLI version)\n */\nexport async function fetchCli(dir: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"fetch\"], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Push (CLI version)\n */\nexport async function pushCli(dir: string, branch?: string): Promise<boolean> {\n try {\n const args = branch ? [\"push\", \"origin\", branch] : [\"push\"];\n await execFileAsync(\"git\", args, { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Checkout branch (CLI version)\n */\nexport async function checkoutBranchCli(dir: string, name: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"checkout\", name], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Create branch (CLI version)\n */\nexport async function createBranchCli(dir: string, name: string): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"checkout\", \"-b\", name], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * List branches (CLI version)\n */\nexport async function listBranchesCli(dir: string): Promise<string[]> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"branch\", \"-a\", \"--format=%(refname:short)\"],\n { cwd: dir, encoding: \"utf8\" }\n );\n\n return stdout\n .split(\"\\n\")\n .map((b) => b.trim())\n .filter((b) => b && !b.startsWith(\"HEAD\"));\n } catch {\n return [];\n }\n}\n\n/**\n * Get file diff (CLI version)\n */\nexport async function getFileDiffCli(\n dir: string,\n filepath: string\n): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\", \"HEAD\", \"--\", filepath],\n { cwd: dir, encoding: \"utf8\", maxBuffer: MAX_BUFFER_BYTES }\n );\n return stdout;\n } catch {\n return null;\n }\n}\n\n/**\n * Get diff for unstaged files (CLI version)\n */\nexport async function getUnstagedDiffCli(dir: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\"],\n { cwd: dir, encoding: \"utf8\", maxBuffer: MAX_BUFFER_BYTES }\n );\n return stdout;\n } catch {\n return null;\n }\n}\n\n/**\n * Get diff for staged files (CLI version)\n */\nexport async function getStagedDiffCli(dir: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\", \"--cached\"],\n { cwd: dir, encoding: \"utf8\", maxBuffer: MAX_BUFFER_BYTES }\n );\n return stdout;\n } catch {\n return null;\n }\n}\n\n/**\n * Discard changes (CLI version)\n */\nexport async function discardChangesCli(\n dir: string,\n filepaths: string[]\n): Promise<boolean> {\n try {\n await execFileAsync(\"git\", [\"checkout\", \"--\", ...filepaths], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get log summary (CLI version)\n */\nexport async function getLogSummaryCli(\n dir: string,\n limit = 40\n): Promise<\n {\n sha: string;\n message: string;\n author: string;\n date: string;\n }[]\n> {\n try {\n const format = \"%H%x00%s%x00%an%x00%ai%x00--SEP--\";\n const { stdout } = await execFileAsync(\n \"git\",\n [\"log\", `--max-count=${limit}`, `--pretty=format:${format}`],\n { cwd: dir, encoding: \"utf8\" }\n );\n\n return stdout\n .split(\"--SEP--\")\n .map((entry) => {\n const [sha, message, author, date] = entry.trim().split(\"\\x00\");\n if (!sha) return null;\n return { sha: sha.trim(), message: message || \"\", author: author || \"\", date: date || \"\" };\n })\n .filter((e): e is NonNullable<typeof e> => e !== null);\n } catch {\n return [];\n }\n}\n\n/**\n * Get ahead/behind (CLI version)\n */\nexport async function getAheadBehindCli(\n dir: string,\n branch: string | null\n): Promise<{ ahead: number; behind: number }> {\n if (!branch) {\n return { ahead: 0, behind: 0 };\n }\n\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"rev-list\", \"--left-right\", \"--count\", `${branch}...@{u}`],\n { cwd: dir, encoding: \"utf8\" }\n );\n\n const match = stdout.trim().match(/(\\d+)\\s+(\\d+)/);\n if (match) {\n return { ahead: Number(match[1]), behind: Number(match[2]) };\n }\n } catch {\n // No upstream\n }\n\n return { ahead: 0, behind: 0 };\n}\n\n/**\n * Init repository (CLI version)\n */\nexport async function initRepoCli(\n dir: string,\n branch = \"main\"\n): Promise<{ success: boolean; error?: string }> {\n try {\n await execFileAsync(\"git\", [\"init\", \"-b\", branch], { cwd: dir });\n return { success: true };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Clone repository (CLI version)\n */\nexport async function cloneRepoCli(\n url: string,\n dir: string\n): Promise<{ success: boolean; error?: string }> {\n try {\n await execFileAsync(\"git\", [\"clone\", url, dir], { maxBuffer: MAX_BUFFER_BYTES });\n return { success: true };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type {\n CodexAppServer,\n CodexApplyPatchRequestPayload,\n CodexEventPayload,\n CodexExecCommandRequestPayload,\n CodexNotificationPayload,\n CodexServerRequestPayload,\n} from \"../lib/codex-app-server\";\nimport type { WorkspaceInfo as ProjectInfo } from \"../lib/workspace-parity-store\";\nimport { isRetryableTurnErrorPayload } from \"../lib/retryable-turn-error\";\nimport { logInfo, logWarn } from \"../lib/logger\";\nimport { getUserDataDir } from \"../lib/app-state\";\n\ntype JsonRecord = Record<string, unknown>;\n\ntype TelegramBridgeOptions = {\n getAppServer: () => CodexAppServer | null;\n listProjects: () => Promise<ProjectInfo[]>;\n getProjectById: (id: string) => Promise<ProjectInfo | null>;\n isProEnabled: () => Promise<boolean>;\n getDefaultProjectId?: () => Promise<string | null> | string | null;\n};\n\ntype TelegramBridgeSettings = {\n enabled: boolean;\n token: string | null;\n};\n\ntype TelegramBridgeStreamMode = \"draft\" | \"message\" | \"none\";\n\nexport type TelegramBridgeStatus = {\n state: \"stopped\" | \"running\" | \"error\";\n running: boolean;\n botUsername: string | null;\n allowedChats: number;\n activeChats: number;\n streamMode: TelegramBridgeStreamMode;\n lastError: string | null;\n startedAtMs: number | null;\n};\n\ntype TelegramTokenTestResult = {\n ok: boolean;\n username: string | null;\n error: string | null;\n};\n\ntype TelegramApiResponse<T> = {\n ok: boolean;\n result?: T;\n description?: string;\n error_code?: number;\n parameters?: {\n retry_after?: number;\n };\n};\n\ntype TelegramUpdate = {\n update_id?: number;\n message?: JsonRecord;\n callback_query?: JsonRecord;\n my_chat_member?: JsonRecord;\n};\n\ntype ChatSession = {\n chatId: string;\n projectId: string | null;\n threadId: string | null;\n listenerSubscriptionId: string | null;\n activeTurnId: string | null;\n processing: boolean;\n finalizeInFlight: boolean;\n lastProjectOrder: string[];\n lastThreadOrder: string[];\n completedTextCandidate: string | null;\n recentFinalizedTurnIds: string[];\n recentFinalSignatures: Array<{ signature: string; at: number }>;\n recentIncomingMessageIds: number[];\n streamFlushPromise: Promise<void> | null;\n streamFlushPending: boolean;\n lastDeliveredFinalText: string | null;\n lastDeliveredFinalAtMs: number;\n typingTimer: NodeJS.Timeout | null;\n stream: {\n draftId: string;\n buffer: string;\n lastSent: string;\n flushTimer: NodeJS.Timeout | null;\n messageId: number | null;\n } | null;\n};\n\ntype PendingApprovalAction = {\n id: string;\n kind: \"exec\" | \"patch\";\n chatId: string;\n requestToken: string;\n createdAtMs: number;\n};\n\ntype PendingUserInput = {\n chatId: string;\n requestId: string | number;\n method: string;\n params: JsonRecord;\n createdAtMs: number;\n};\n\nconst TELEGRAM_API_BASE = \"https://api.telegram.org\";\nconst TELEGRAM_POLL_TIMEOUT_SECONDS = 30;\nconst TELEGRAM_API_TIMEOUT_MS = 40_000;\nconst TELEGRAM_STREAM_FLUSH_MS = 300;\nconst TELEGRAM_MAX_MESSAGE_LENGTH = 4096;\nconst TELEGRAM_PENDING_TTL_MS = 30 * 60 * 1000;\nconst TELEGRAM_RETRY_LIMIT_MS = 30_000;\nconst TELEGRAM_MIN_SEND_INTERVAL_MS = 500;\nconst TELEGRAM_FINAL_TEXT_DEDUPE_MS = 2_500;\nconst TELEGRAM_RECENT_FINALIZED_TURNS_MAX = 24;\nconst TELEGRAM_FINAL_SIGNATURE_DEDUPE_MS = 20_000;\nconst TELEGRAM_RECENT_FINAL_SIGNATURES_MAX = 40;\nconst TELEGRAM_RECENT_INCOMING_MESSAGES_MAX = 32;\nconst TELEGRAM_TYPING_HEARTBEAT_MS = 4_000;\nconst TELEGRAM_BRIDGE_LOCK_FILE_PREFIX = \"telegram-bridge\";\n\nfunction asRecord(value: unknown): JsonRecord {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as JsonRecord)\n : {};\n}\n\nfunction asString(value: unknown): string {\n return typeof value === \"string\" ? value : value != null ? String(value) : \"\";\n}\n\nfunction asTrimmedString(value: unknown): string {\n return asString(value).trim();\n}\n\nfunction asNumber(value: unknown): number | null {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n if (typeof value === \"string\" && value.trim()) {\n const parsed = Number(value.trim());\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n return null;\n}\n\nfunction normalizeChatId(value: unknown): string | null {\n const trimmed = asTrimmedString(value);\n if (!trimmed) {\n return null;\n }\n if (!/^-?[0-9]+$/.test(trimmed)) {\n return null;\n }\n return trimmed;\n}\n\nfunction extractThreadId(value: unknown): string {\n const params = asRecord(value);\n const turn = asRecord(params.turn);\n const thread = asRecord(params.thread);\n const item = asRecord(params.item);\n const msg = asRecord(params.msg);\n const msgItem = asRecord(msg.item);\n return asTrimmedString(\n params.threadId ??\n params.thread_id ??\n params.conversationId ??\n params.conversation_id ??\n turn.threadId ??\n turn.thread_id ??\n thread.id ??\n thread.threadId ??\n thread.thread_id ??\n item.threadId ??\n item.thread_id ??\n item.conversationId ??\n item.conversation_id ??\n msg.threadId ??\n msg.thread_id ??\n msg.conversationId ??\n msg.conversation_id ??\n msgItem.threadId ??\n msgItem.thread_id ??\n msgItem.conversationId ??\n msgItem.conversation_id ??\n \"\",\n );\n}\n\nfunction extractTurnId(value: unknown): string {\n const params = asRecord(value);\n const turn = asRecord(params.turn);\n const msg = asRecord(params.msg);\n const msgTurn = asRecord(msg.turn);\n return asTrimmedString(\n turn.id ??\n turn.turnId ??\n turn.turn_id ??\n params.turnId ??\n params.turn_id ??\n msg.turnId ??\n msg.turn_id ??\n msgTurn.id ??\n msgTurn.turnId ??\n msgTurn.turn_id ??\n \"\",\n );\n}\n\nfunction extractText(value: unknown, depth = 0): string {\n if (typeof value === \"string\") {\n return value;\n }\n if (depth > 4 || value == null) {\n return \"\";\n }\n if (Array.isArray(value)) {\n return value.map((entry) => extractText(entry, depth + 1)).join(\"\");\n }\n if (typeof value !== \"object\") {\n return \"\";\n }\n const record = value as JsonRecord;\n return (\n extractText(record.text, depth + 1) ||\n extractText(record.delta, depth + 1) ||\n extractText(record.message, depth + 1) ||\n extractText(record.content, depth + 1) ||\n extractText(record.value, depth + 1)\n );\n}\n\nfunction extractDeltaFromNotification(params: JsonRecord): string {\n const msg = asRecord(params.msg);\n return (\n asString(params.delta) ||\n extractText(params.delta) ||\n extractText(msg.delta ?? msg.message ?? msg.content ?? msg.value)\n );\n}\n\nfunction looksLikeAssistantItem(item: JsonRecord): boolean {\n const itemType = asTrimmedString(item.type).toLowerCase();\n if (\n itemType === \"agentmessage\" ||\n itemType === \"agent_message\" ||\n itemType === \"assistantmessage\" ||\n itemType === \"assistant_message\"\n ) {\n return true;\n }\n const itemRole = asTrimmedString(\n item.role ?? item.authorRole ?? item.author_role ?? item.senderRole ?? item.sender_role,\n ).toLowerCase();\n if (itemRole === \"assistant\" || itemRole === \"agent\") {\n return true;\n }\n const itemId = asTrimmedString(item.id);\n return itemId.startsWith(\"msg_\");\n}\n\nfunction extractAssistantTextFromItemCompleted(params: JsonRecord): string {\n const item = asRecord(params.item);\n if (!looksLikeAssistantItem(item)) {\n return \"\";\n }\n return asString(item.text) || extractText(item.content) || extractText(params.msg) || \"\";\n}\n\nfunction extractCommandText(params: JsonRecord): string {\n const command = params.command;\n if (typeof command === \"string\") {\n return command.trim();\n }\n if (Array.isArray(command)) {\n const parts = command.map((entry) => asString(entry).trim()).filter(Boolean);\n if (parts.length > 0) {\n return parts.join(\" \");\n }\n }\n const parsed = asRecord(params.parsed_cmd ?? params.parsedCmd);\n const parsedText = asTrimmedString(parsed.text ?? parsed.command);\n if (parsedText) {\n return parsedText;\n }\n return asTrimmedString(params.cmd ?? \"\");\n}\n\nfunction summarizePatchRequest(params: JsonRecord): string {\n const fileChanges = params.file_changes ?? params.fileChanges;\n if (Array.isArray(fileChanges)) {\n const count = fileChanges.length;\n return `${count} file ${count === 1 ? \"change\" : \"changes\"}`;\n }\n const summary = extractText(params);\n return summary.trim() || \"Apply patch request\";\n}\n\nfunction splitMessage(text: string, maxLength = TELEGRAM_MAX_MESSAGE_LENGTH): string[] {\n const normalized = text.trim();\n if (!normalized) {\n return [];\n }\n if (normalized.length <= maxLength) {\n return [normalized];\n }\n const parts: string[] = [];\n let index = 0;\n while (index < normalized.length) {\n const remaining = normalized.slice(index);\n if (remaining.length <= maxLength) {\n parts.push(remaining);\n break;\n }\n let cut = maxLength;\n const newlineCut = remaining.lastIndexOf(\"\\n\", maxLength);\n if (newlineCut >= Math.floor(maxLength * 0.5)) {\n cut = newlineCut;\n }\n const chunk = remaining.slice(0, cut).trim();\n parts.push(chunk || remaining.slice(0, maxLength));\n index += cut;\n }\n return parts;\n}\n\nfunction mergeStreamDeltaBuffer(current: string, incoming: string): string {\n if (!incoming) {\n return current;\n }\n if (!current) {\n return incoming;\n }\n if (current.endsWith(incoming)) {\n return current;\n }\n if (incoming.startsWith(current)) {\n return incoming;\n }\n\n // Some event sources send cumulative text while others send token deltas.\n // Merge on suffix/prefix overlap so we do not duplicate content in Telegram output.\n const maxProbe = Math.min(current.length, incoming.length, 2_048);\n for (let size = maxProbe; size > 0; size -= 1) {\n if (current.slice(-size) === incoming.slice(0, size)) {\n return current + incoming.slice(size);\n }\n }\n return current + incoming;\n}\n\nfunction nowMs(): number {\n return Date.now();\n}\n\nexport class TelegramBridge {\n private readonly options: TelegramBridgeOptions;\n private settings: TelegramBridgeSettings = {\n enabled: false,\n token: null,\n };\n\n private status: TelegramBridgeStatus = {\n state: \"stopped\",\n running: false,\n botUsername: null,\n allowedChats: 0,\n activeChats: 0,\n streamMode: \"message\",\n lastError: null,\n startedAtMs: null,\n };\n\n private running = false;\n private pollAbortController: AbortController | null = null;\n private pollLoopPromise: Promise<void> | null = null;\n private updateOffset: number | null = null;\n private draftStreamingEnabled = false;\n private messageStreamingEnabled = true;\n\n private sessionsByChatId = new Map<string, ChatSession>();\n private chatIdByThreadId = new Map<string, string>();\n private pendingApprovalById = new Map<string, PendingApprovalAction>();\n private pendingUserInputByRequestId = new Map<string, PendingUserInput>();\n\n private appServerListenersBound = false;\n\n private readonly recentDeltaBySignature = new Map<string, number>();\n private readonly lastSendAtByChatId = new Map<string, number>();\n private runtimeLockPath: string | null = null;\n\n private readonly handleCodexNotification = (payload: CodexNotificationPayload) => {\n this.handleNotification(payload).catch((error) => {\n logWarn(\"[telegram-bridge] notification handling failed\", error);\n });\n };\n\n private readonly handleCodexEvent = (payload: CodexEventPayload) => {\n this.handleEvent(payload).catch((error) => {\n logWarn(\"[telegram-bridge] event handling failed\", error);\n });\n };\n\n private readonly handleExecApprovalRequest = (payload: CodexExecCommandRequestPayload) => {\n this.handleApprovalRequest(\"exec\", payload.requestToken, payload.params).catch((error) => {\n logWarn(\"[telegram-bridge] exec approval handling failed\", error);\n });\n };\n\n private readonly handlePatchApprovalRequest = (payload: CodexApplyPatchRequestPayload) => {\n this.handleApprovalRequest(\"patch\", payload.requestToken, payload.params).catch((error) => {\n logWarn(\"[telegram-bridge] patch approval handling failed\", error);\n });\n };\n\n private readonly handleServerRequest = (payload: CodexServerRequestPayload) => {\n this.handleUserInputRequest(payload).catch((error) => {\n logWarn(\"[telegram-bridge] user-input request handling failed\", error);\n });\n };\n\n constructor(options: TelegramBridgeOptions) {\n this.options = options;\n }\n\n private getCurrentStreamMode(): TelegramBridgeStreamMode {\n if (this.messageStreamingEnabled) {\n return \"message\";\n }\n if (this.draftStreamingEnabled) {\n return \"draft\";\n }\n return \"none\";\n }\n\n public getStatus(): TelegramBridgeStatus {\n return {\n ...this.status,\n allowedChats: 0,\n activeChats: this.sessionsByChatId.size,\n streamMode: this.getCurrentStreamMode(),\n };\n }\n\n public async testToken(tokenInput?: string | null): Promise<TelegramTokenTestResult> {\n const token = asTrimmedString(tokenInput) || this.settings.token || \"\";\n if (!token) {\n return {\n ok: false,\n username: null,\n error: \"Telegram bot token is required.\",\n };\n }\n try {\n const response = await this.callTelegramApi<{ username?: unknown }>(\n token,\n \"getMe\",\n {},\n { retry429: false },\n );\n const username = asTrimmedString(asRecord(response).username);\n return {\n ok: true,\n username: username || null,\n error: null,\n };\n } catch (error) {\n return {\n ok: false,\n username: null,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n public async applyRuntimeSettings(settings: JsonRecord): Promise<void> {\n const next = this.extractSettings(settings);\n const tokenChanged = next.token !== this.settings.token;\n const enabledChanged = next.enabled !== this.settings.enabled;\n this.settings = next;\n this.status.allowedChats = 0;\n if (tokenChanged) {\n this.status.botUsername = null;\n this.draftStreamingEnabled = false;\n this.messageStreamingEnabled = true;\n this.status.streamMode = this.getCurrentStreamMode();\n }\n const shouldRestart = tokenChanged || enabledChanged;\n await this.syncRuntimeState({ shouldRestart });\n }\n\n public async dispose(): Promise<void> {\n await this.stop(\"Bridge disposed.\");\n }\n\n public async stop(reason?: string): Promise<void> {\n if (!this.running && !this.pollLoopPromise) {\n await this.releaseRuntimeLock();\n this.status.state = \"stopped\";\n this.status.running = false;\n this.status.startedAtMs = null;\n if (reason) {\n this.status.lastError = null;\n }\n return;\n }\n\n this.running = false;\n this.status.running = false;\n this.status.state = \"stopped\";\n this.status.startedAtMs = null;\n\n if (this.pollAbortController) {\n this.pollAbortController.abort();\n this.pollAbortController = null;\n }\n\n if (this.pollLoopPromise) {\n try {\n await this.pollLoopPromise;\n } catch {\n // Ignore poll loop termination errors during shutdown.\n }\n this.pollLoopPromise = null;\n }\n\n this.detachAppServerListeners();\n await this.detachAllConversationListeners();\n this.clearSessionState();\n await this.releaseRuntimeLock();\n\n if (reason) {\n logInfo(\"[telegram-bridge] stopped\", reason);\n }\n }\n\n private extractSettings(raw: JsonRecord): TelegramBridgeSettings {\n return {\n enabled: raw.telegramBridgeEnabled === true,\n token: (() => {\n const token = asTrimmedString(raw.telegramBotToken);\n return token || null;\n })(),\n };\n }\n\n private async syncRuntimeState(options: { shouldRestart: boolean }): Promise<void> {\n const shouldRun =\n this.settings.enabled &&\n Boolean(this.settings.token);\n\n if (!shouldRun) {\n await this.stop(\"Disabled or incomplete Telegram settings.\");\n this.status.state = \"stopped\";\n this.status.lastError = null;\n return;\n }\n\n const isPro = await this.options.isProEnabled().catch((error) => {\n logWarn(\"[telegram-bridge] failed to verify Pro status\", error);\n return false;\n });\n\n if (!isPro) {\n await this.stop(\"Telegram bridge requires Pro.\");\n this.status.state = \"error\";\n this.status.lastError = \"Telegram mobile access requires Pro.\";\n return;\n }\n\n if (this.running && options.shouldRestart) {\n await this.stop(\"Restarting Telegram bridge after settings change.\");\n }\n\n if (this.running) {\n return;\n }\n\n await this.start();\n }\n\n private async start(): Promise<void> {\n const token = this.settings.token;\n if (!token) {\n this.status.state = \"error\";\n this.status.lastError = \"Telegram bot token is missing.\";\n return;\n }\n\n const me = await this.testToken(token);\n if (!me.ok) {\n this.status.state = \"error\";\n this.status.lastError = me.error;\n this.status.botUsername = null;\n return;\n }\n\n try {\n await this.acquireRuntimeLock(token);\n } catch (error) {\n this.status.state = \"error\";\n this.status.lastError = error instanceof Error ? error.message : String(error);\n return;\n }\n\n this.status.botUsername = me.username;\n this.status.lastError = null;\n this.status.state = \"running\";\n this.status.running = true;\n this.status.startedAtMs = nowMs();\n this.running = true;\n\n this.attachAppServerListeners();\n\n this.pollAbortController = new AbortController();\n this.pollLoopPromise = this.runPolling(this.pollAbortController.signal).finally(() => {\n this.pollLoopPromise = null;\n });\n\n logInfo(\"[telegram-bridge] started\", {\n allowedChats: \"all-private-chats\",\n botUsername: this.status.botUsername,\n });\n }\n\n private async runPolling(signal: AbortSignal): Promise<void> {\n const token = this.settings.token;\n if (!token) {\n return;\n }\n\n // Ensure polling mode is enabled in case webhook was configured externally.\n await this.callTelegramApi(token, \"deleteWebhook\", { drop_pending_updates: false }).catch(\n (error) => {\n logWarn(\"[telegram-bridge] deleteWebhook failed\", error);\n },\n );\n\n let backoffMs = 1_000;\n\n while (!signal.aborted && this.running) {\n try {\n this.prunePendingActions();\n const updates = await this.callTelegramApi<TelegramUpdate[]>(\n token,\n \"getUpdates\",\n {\n offset: this.updateOffset,\n timeout: TELEGRAM_POLL_TIMEOUT_SECONDS,\n allowed_updates: [\"message\", \"callback_query\", \"my_chat_member\"],\n },\n {\n signal,\n retry429: true,\n },\n );\n\n const list = Array.isArray(updates) ? updates : [];\n for (const update of list) {\n const updateId = asNumber(update.update_id);\n if (updateId !== null) {\n this.updateOffset = updateId + 1;\n }\n await this.handleUpdate(update);\n }\n\n backoffMs = 1_000;\n } catch (error) {\n if (signal.aborted || !this.running) {\n break;\n }\n const message = error instanceof Error ? error.message : String(error);\n this.status.state = \"error\";\n this.status.lastError = message;\n logWarn(\"[telegram-bridge] polling error\", message);\n await this.sleep(Math.min(backoffMs, TELEGRAM_RETRY_LIMIT_MS));\n backoffMs = Math.min(backoffMs * 2, TELEGRAM_RETRY_LIMIT_MS);\n }\n }\n\n if (!signal.aborted && this.running) {\n this.status.state = \"error\";\n this.status.lastError = \"Telegram polling stopped unexpectedly.\";\n }\n }\n\n private async handleUpdate(update: TelegramUpdate): Promise<void> {\n const record = asRecord(update);\n if (record.callback_query) {\n await this.handleCallbackQuery(asRecord(record.callback_query));\n return;\n }\n if (record.message) {\n await this.handleMessage(asRecord(record.message));\n return;\n }\n if (record.my_chat_member) {\n this.handleMembershipUpdate(asRecord(record.my_chat_member));\n return;\n }\n }\n\n private handleMembershipUpdate(payload: JsonRecord): void {\n const chat = asRecord(payload.chat);\n const chatId = normalizeChatId(chat.id);\n if (!chatId) {\n return;\n }\n const newMember = asRecord(payload.new_chat_member);\n const status = asTrimmedString(newMember.status).toLowerCase();\n if (status === \"kicked\" || status === \"left\") {\n void this.resetSession(chatId);\n }\n }\n\n private async handleMessage(message: JsonRecord): Promise<void> {\n const chat = asRecord(message.chat);\n const chatId = normalizeChatId(chat.id);\n if (!chatId) {\n return;\n }\n const session = this.getOrCreateSession(chatId);\n const messageId = asNumber(message.message_id ?? message.messageId);\n if (messageId !== null && this.isDuplicateIncomingMessage(session, messageId)) {\n return;\n }\n\n const chatType = asTrimmedString(chat.type).toLowerCase();\n if (chatType && chatType !== \"private\") {\n await this.sendSimpleMessage(chatId, \"Private chats only. Use me in a direct chat.\");\n return;\n }\n\n const text = asTrimmedString(message.text);\n if (!text) {\n return;\n }\n\n const parsedCommand = this.parseCommand(text);\n if (parsedCommand) {\n const handled = await this.handleCommand(chatId, parsedCommand.command, parsedCommand.args);\n if (handled) {\n return;\n }\n }\n\n await this.handlePromptText(chatId, text);\n }\n\n private async handleCallbackQuery(callbackQuery: JsonRecord): Promise<void> {\n const callbackId = asTrimmedString(callbackQuery.id);\n const message = asRecord(callbackQuery.message);\n const chat = asRecord(message.chat);\n const chatId = normalizeChatId(chat.id);\n const data = asTrimmedString(callbackQuery.data);\n\n if (!callbackId || !chatId || !data) {\n return;\n }\n\n const approvalMatch = /^cu:ap:([a-z0-9]+):(approved|approved_for_session|denied|abort)$/i.exec(\n data,\n );\n if (approvalMatch) {\n const actionId = approvalMatch[1];\n const decision = approvalMatch[2] as \"approved\" | \"approved_for_session\" | \"denied\" | \"abort\";\n const action = this.pendingApprovalById.get(actionId);\n if (!action || action.chatId !== chatId) {\n await this.answerCallbackQuery(callbackId, \"Action expired.\");\n return;\n }\n\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.answerCallbackQuery(callbackId, \"Backend unavailable.\");\n return;\n }\n\n try {\n if (action.kind === \"exec\") {\n await appServer.respondExecCommandRequest(action.requestToken, decision);\n } else {\n await appServer.respondApplyPatchRequest(action.requestToken, decision);\n }\n this.pendingApprovalById.delete(actionId);\n await this.answerCallbackQuery(callbackId, `Recorded: ${decision}`);\n await this.sendSimpleMessage(chatId, `Approval decision sent: ${decision}.`);\n } catch (error) {\n await this.answerCallbackQuery(callbackId, \"Failed to submit decision.\");\n await this.sendSimpleMessage(\n chatId,\n `Failed to submit approval decision: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n return;\n }\n\n await this.answerCallbackQuery(callbackId, \"Unknown action.\");\n }\n\n private parseCommand(text: string): { command: string; args: string } | null {\n const trimmed = text.trim();\n if (!trimmed.startsWith(\"/\")) {\n return null;\n }\n const [head, ...rest] = trimmed.split(/\\s+/g);\n const commandWithSlash = head.slice(1);\n const command = commandWithSlash.split(\"@\")[0]?.trim().toLowerCase();\n if (!command) {\n return null;\n }\n return {\n command,\n args: rest.join(\" \").trim(),\n };\n }\n\n private async handleCommand(chatId: string, command: string, args: string): Promise<boolean> {\n switch (command) {\n case \"start\":\n case \"help\": {\n await this.sendHelp(chatId);\n return true;\n }\n case \"status\": {\n await this.sendStatus(chatId);\n return true;\n }\n case \"projects\":\n case \"workspaces\": {\n await this.sendProjects(chatId);\n return true;\n }\n case \"project\":\n case \"workspace\": {\n await this.selectProject(chatId, args);\n return true;\n }\n case \"new\": {\n await this.createNewThread(chatId);\n return true;\n }\n case \"threads\": {\n await this.listThreads(chatId);\n return true;\n }\n case \"thread\": {\n await this.selectThread(chatId, args);\n return true;\n }\n case \"interrupt\": {\n await this.interruptTurn(chatId);\n return true;\n }\n case \"input\": {\n await this.submitUserInput(chatId, args);\n return true;\n }\n default:\n return false;\n }\n }\n\n private async sendHelp(chatId: string): Promise<void> {\n const lines = [\n \"CodexUse Telegram bridge is connected.\",\n \"\",\n \"Commands:\",\n \"/status - Show current status\",\n \"/projects - List available projects\",\n \"/project <index|id> - Select active project\",\n \"/new - Start a new thread in active project\",\n \"/threads - List recent threads in active project\",\n \"/thread <index|id> - Switch active thread\",\n \"/interrupt - Interrupt active turn\",\n \"/input <request-id> qid=answer;... - Reply to request-user-input\",\n \"\",\n \"Send any normal text message to run it in the active thread.\",\n ];\n await this.sendSimpleMessage(chatId, lines.join(\"\\n\"));\n }\n\n private async sendStatus(chatId: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n const status = this.getStatus();\n const lines = [\n `Bridge: ${status.state}`,\n `Streaming mode: ${status.streamMode}`,\n \"Allowed chats: all private chats\",\n `Bot: ${status.botUsername ? `@${status.botUsername}` : \"(unknown)\"}`,\n `Active project: ${session.projectId ?? \"(not selected)\"}`,\n `Active thread: ${session.threadId ?? \"(none)\"}`,\n `Processing: ${session.processing ? \"yes\" : \"no\"}`,\n ];\n if (status.lastError) {\n lines.push(`Last error: ${status.lastError}`);\n }\n await this.sendSimpleMessage(chatId, lines.join(\"\\n\"));\n }\n\n private async sendProjects(chatId: string): Promise<void> {\n const projects = await this.options.listProjects();\n const session = this.getOrCreateSession(chatId);\n if (projects.length === 0) {\n await this.sendSimpleMessage(chatId, \"No projects found in this desktop app.\");\n return;\n }\n session.lastProjectOrder = projects.map((entry) => entry.id);\n const lines = [\"Projects:\"];\n projects.forEach((project, index) => {\n const isActive = project.id === session.projectId;\n lines.push(\n `${index + 1}. ${project.name}${isActive ? \" (active)\" : \"\"} [${project.id}]`,\n );\n });\n await this.sendSimpleMessage(chatId, lines.join(\"\\n\"));\n }\n\n private async selectProject(chatId: string, args: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n const projects = await this.options.listProjects();\n if (projects.length === 0) {\n await this.sendSimpleMessage(chatId, \"No projects available.\");\n return;\n }\n\n const selected = this.resolveProjectSelection(args, projects, session.lastProjectOrder);\n if (!selected) {\n await this.sendSimpleMessage(\n chatId,\n \"Project not found. Use /projects, then /project <index|id>.\",\n );\n return;\n }\n\n if (session.projectId !== selected.id) {\n await this.detachConversationListener(session);\n session.projectId = selected.id;\n session.threadId = null;\n session.activeTurnId = null;\n session.processing = false;\n session.completedTextCandidate = null;\n this.resetStream(session);\n }\n\n await this.sendSimpleMessage(chatId, `Active project set to: ${selected.name}.`);\n }\n\n private resolveProjectSelection(\n args: string,\n projects: ProjectInfo[],\n order: string[],\n ): ProjectInfo | null {\n const input = args.trim();\n if (!input) {\n return null;\n }\n\n const numeric = Number(input);\n if (Number.isInteger(numeric) && numeric >= 1) {\n if (order.length > 0 && numeric <= order.length) {\n const id = order[numeric - 1];\n return projects.find((entry) => entry.id === id) ?? null;\n }\n if (numeric <= projects.length) {\n return projects[numeric - 1] ?? null;\n }\n }\n\n return projects.find((entry) => entry.id === input) ?? null;\n }\n\n private async createNewThread(chatId: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n const project = await this.ensureSessionProject(session, chatId);\n if (!project) {\n return;\n }\n\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return;\n }\n\n try {\n const response = await appServer.threadStart({\n workspaceId: project.id,\n workspace_id: project.id,\n cwd: project.path,\n });\n const threadId = this.extractThreadIdFromResponse(response);\n if (!threadId) {\n await this.sendSimpleMessage(chatId, \"Thread started, but thread id was missing.\");\n return;\n }\n session.threadId = threadId;\n session.activeTurnId = null;\n session.processing = false;\n session.completedTextCandidate = null;\n this.resetStream(session);\n await this.attachConversationListener(session, project.id, threadId);\n await this.sendSimpleMessage(chatId, `Started new thread: ${threadId}`);\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to start a new thread: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private async listThreads(chatId: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n const project = await this.ensureSessionProject(session, chatId);\n if (!project) {\n return;\n }\n\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return;\n }\n\n try {\n const response = await appServer.listConversations({\n cwd: project.path,\n limit: 20,\n sortKey: \"updated_at\",\n archived: false,\n });\n const threads = this.extractThreadList(response);\n if (threads.length === 0) {\n await this.sendSimpleMessage(chatId, \"No threads found for this project.\");\n return;\n }\n session.lastThreadOrder = threads.map((entry) => entry.id);\n const lines = [\"Threads:\"];\n threads.forEach((thread, index) => {\n const isActive = thread.id === session.threadId;\n const title = thread.title || \"(untitled)\";\n lines.push(`${index + 1}. ${title}${isActive ? \" (active)\" : \"\"} [${thread.id}]`);\n });\n await this.sendSimpleMessage(chatId, lines.join(\"\\n\"));\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to list threads: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private async selectThread(chatId: string, args: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n const project = await this.ensureSessionProject(session, chatId);\n if (!project) {\n return;\n }\n\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return;\n }\n\n const input = args.trim();\n if (!input) {\n await this.sendSimpleMessage(chatId, \"Usage: /thread <index|id>\");\n return;\n }\n\n let threadId = \"\";\n const numeric = Number(input);\n if (Number.isInteger(numeric) && numeric >= 1) {\n if (session.lastThreadOrder.length > 0 && numeric <= session.lastThreadOrder.length) {\n threadId = session.lastThreadOrder[numeric - 1] ?? \"\";\n }\n }\n if (!threadId) {\n threadId = input;\n }\n\n try {\n await appServer.threadResume({\n workspaceId: project.id,\n workspace_id: project.id,\n threadId,\n });\n session.threadId = threadId;\n session.activeTurnId = null;\n session.processing = false;\n session.completedTextCandidate = null;\n this.resetStream(session);\n await this.attachConversationListener(session, project.id, threadId);\n await this.sendSimpleMessage(chatId, `Active thread set to: ${threadId}`);\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to switch thread: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private async interruptTurn(chatId: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n const project = await this.ensureSessionProject(session, chatId);\n if (!project || !session.threadId) {\n await this.sendSimpleMessage(chatId, \"No active thread to interrupt.\");\n return;\n }\n\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return;\n }\n\n const turnId = session.activeTurnId || \"pending\";\n try {\n await appServer.interruptTurn({\n workspaceId: project.id,\n workspace_id: project.id,\n threadId: session.threadId,\n turnId,\n });\n session.processing = false;\n session.activeTurnId = null;\n this.resetStream(session);\n await this.sendSimpleMessage(chatId, \"Interrupt requested.\");\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to interrupt turn: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private async submitUserInput(chatId: string, args: string): Promise<void> {\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return;\n }\n\n const trimmed = args.trim();\n if (!trimmed) {\n await this.sendSimpleMessage(\n chatId,\n \"Usage: /input <request-id> qid=answer; qid2=answer\",\n );\n return;\n }\n\n const [requestTokenPart, ...restParts] = trimmed.split(/\\s+/g);\n let requestIdToken = requestTokenPart.trim();\n let bodyText = restParts.join(\" \").trim();\n\n if (!requestIdToken || requestIdToken.includes(\"=\")) {\n const pendingForChat = Array.from(this.pendingUserInputByRequestId.values()).filter(\n (entry) => entry.chatId === chatId,\n );\n if (pendingForChat.length !== 1) {\n await this.sendSimpleMessage(\n chatId,\n \"Request id is required. Use /input <request-id> qid=answer;...\",\n );\n return;\n }\n requestIdToken = String(pendingForChat[0].requestId);\n bodyText = trimmed;\n }\n\n const pending = this.pendingUserInputByRequestId.get(requestIdToken);\n if (!pending || pending.chatId !== chatId) {\n await this.sendSimpleMessage(chatId, \"Unknown or expired request id.\");\n return;\n }\n\n const answers = this.parseUserInputAnswers(bodyText, pending.params);\n if (!answers) {\n await this.sendSimpleMessage(\n chatId,\n \"Could not parse answers. Format: /input <request-id> qid=answer; qid2=answer\",\n );\n return;\n }\n\n try {\n await appServer.respondToServerRequest(pending.requestId, {\n answers,\n });\n this.pendingUserInputByRequestId.delete(requestIdToken);\n await this.sendSimpleMessage(chatId, \"Input submitted.\");\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to submit input: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private parseUserInputAnswers(\n bodyText: string,\n params: JsonRecord,\n ): Record<string, { answers: string[] }> | null {\n const questionsRaw = Array.isArray(params.questions) ? params.questions : [];\n const questions = questionsRaw\n .map((entry) => asRecord(entry))\n .filter((entry) => asTrimmedString(entry.id));\n\n const questionIds = new Set(questions.map((entry) => asTrimmedString(entry.id)));\n const answers: Record<string, { answers: string[] }> = {};\n\n const segments = bodyText\n .split(\";\")\n .map((segment) => segment.trim())\n .filter(Boolean);\n\n if (segments.length === 0) {\n if (questions.length === 1 && bodyText.trim()) {\n const id = asTrimmedString(questions[0].id);\n answers[id] = { answers: [bodyText.trim()] };\n return answers;\n }\n return null;\n }\n\n for (const segment of segments) {\n const eqIndex = segment.indexOf(\"=\");\n if (eqIndex <= 0) {\n if (questions.length === 1) {\n const id = asTrimmedString(questions[0].id);\n answers[id] = { answers: [segment.trim()] };\n continue;\n }\n return null;\n }\n const key = segment.slice(0, eqIndex).trim();\n const value = segment.slice(eqIndex + 1).trim();\n if (!key || !value || !questionIds.has(key)) {\n return null;\n }\n const splitValues = value\n .split(\",\")\n .map((entry) => entry.trim())\n .filter(Boolean);\n answers[key] = {\n answers: splitValues.length > 0 ? splitValues : [value],\n };\n }\n\n return Object.keys(answers).length > 0 ? answers : null;\n }\n\n private async handlePromptText(chatId: string, text: string): Promise<void> {\n const session = this.getOrCreateSession(chatId);\n if (session.processing) {\n await this.sendSimpleMessage(\n chatId,\n \"A response is already in progress. Wait for completion or use /interrupt.\",\n );\n return;\n }\n\n const project = await this.ensureSessionProject(session, chatId);\n if (!project) {\n return;\n }\n\n const threadId = session.threadId || (await this.startThreadForSession(chatId, session, project));\n if (!threadId) {\n return;\n }\n\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return;\n }\n\n try {\n session.completedTextCandidate = null;\n this.resetStream(session);\n const response = await appServer.sendUserMessage({\n workspaceId: project.id,\n workspace_id: project.id,\n threadId,\n thread_id: threadId,\n conversationId: threadId,\n conversation_id: threadId,\n text,\n });\n\n const turnId = this.extractTurnIdFromResponse(response);\n session.processing = true;\n session.activeTurnId = turnId || null;\n this.ensureTypingIndicator(session);\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to send message: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private async startThreadForSession(\n chatId: string,\n session: ChatSession,\n project: ProjectInfo,\n ): Promise<string | null> {\n const appServer = this.options.getAppServer();\n if (!appServer) {\n await this.sendSimpleMessage(chatId, \"Backend unavailable.\");\n return null;\n }\n\n try {\n const response = await appServer.threadStart({\n workspaceId: project.id,\n workspace_id: project.id,\n cwd: project.path,\n });\n const threadId = this.extractThreadIdFromResponse(response);\n if (!threadId) {\n await this.sendSimpleMessage(chatId, \"Could not create thread (missing thread id).\");\n return null;\n }\n session.threadId = threadId;\n await this.attachConversationListener(session, project.id, threadId);\n return threadId;\n } catch (error) {\n await this.sendSimpleMessage(\n chatId,\n `Failed to create thread: ${error instanceof Error ? error.message : String(error)}`,\n );\n return null;\n }\n }\n\n private async ensureSessionProject(\n session: ChatSession,\n chatId: string,\n ): Promise<ProjectInfo | null> {\n if (session.projectId) {\n const existing = await this.options.getProjectById(session.projectId);\n if (existing) {\n return existing;\n }\n session.projectId = null;\n session.threadId = null;\n }\n\n const defaultProjectId = await this.resolveDefaultProjectId();\n if (defaultProjectId) {\n const preferred = await this.options.getProjectById(defaultProjectId).catch(() => null);\n if (preferred) {\n session.projectId = preferred.id;\n return preferred;\n }\n }\n\n const projects = await this.options.listProjects();\n if (projects.length === 0) {\n await this.sendSimpleMessage(chatId, \"No projects found. Add a project in desktop settings first.\");\n return null;\n }\n\n const connected = projects.find((entry) => entry.connected);\n const selected = connected ?? projects[0];\n session.projectId = selected.id;\n session.lastProjectOrder = projects.map((entry) => entry.id);\n return selected;\n }\n\n private async resolveDefaultProjectId(): Promise<string | null> {\n const resolver = this.options.getDefaultProjectId;\n if (!resolver) {\n return null;\n }\n try {\n const value = await resolver();\n const normalized = asTrimmedString(value);\n return normalized || null;\n } catch {\n return null;\n }\n }\n\n private extractThreadIdFromResponse(value: unknown): string {\n const record = asRecord(value);\n const result = asRecord(record.result);\n const thread = asRecord(result.thread ?? record.thread);\n return asTrimmedString(\n thread.id ??\n thread.threadId ??\n thread.thread_id ??\n result.threadId ??\n result.thread_id ??\n record.threadId ??\n record.thread_id ??\n result.conversationId ??\n result.conversation_id ??\n \"\",\n );\n }\n\n private extractTurnIdFromResponse(value: unknown): string {\n const record = asRecord(value);\n const result = asRecord(record.result);\n const turn = asRecord(result.turn ?? record.turn);\n return asTrimmedString(\n turn.id ??\n turn.turnId ??\n turn.turn_id ??\n result.turnId ??\n result.turn_id ??\n record.turnId ??\n record.turn_id ??\n \"\",\n );\n }\n\n private extractThreadList(value: unknown): Array<{ id: string; title: string }> {\n const root = asRecord(value);\n const primary = Array.isArray(value)\n ? (value as unknown[])\n : (Array.isArray(root.data)\n ? root.data\n : Array.isArray(root.threads)\n ? root.threads\n : Array.isArray(root.items)\n ? root.items\n : []);\n const result: Array<{ id: string; title: string }> = [];\n for (const entry of primary) {\n const thread = asRecord(entry);\n const id = asTrimmedString(\n thread.id ??\n thread.threadId ??\n thread.thread_id ??\n thread.conversationId ??\n thread.conversation_id ??\n \"\",\n );\n if (!id) {\n continue;\n }\n const title =\n asTrimmedString(\n thread.name ?? thread.title ?? thread.preview ?? thread.summary ?? thread.path ?? \"\",\n ) || \"(untitled)\";\n result.push({ id, title });\n }\n return result;\n }\n\n private getOrCreateSession(chatId: string): ChatSession {\n const existing = this.sessionsByChatId.get(chatId);\n if (existing) {\n return existing;\n }\n const session: ChatSession = {\n chatId,\n projectId: null,\n threadId: null,\n listenerSubscriptionId: null,\n activeTurnId: null,\n processing: false,\n finalizeInFlight: false,\n lastProjectOrder: [],\n lastThreadOrder: [],\n completedTextCandidate: null,\n recentFinalizedTurnIds: [],\n recentFinalSignatures: [],\n recentIncomingMessageIds: [],\n streamFlushPromise: null,\n streamFlushPending: false,\n lastDeliveredFinalText: null,\n lastDeliveredFinalAtMs: 0,\n typingTimer: null,\n stream: null,\n };\n this.sessionsByChatId.set(chatId, session);\n this.status.activeChats = this.sessionsByChatId.size;\n return session;\n }\n\n private async resetSession(chatId: string): Promise<void> {\n const session = this.sessionsByChatId.get(chatId);\n if (!session) {\n return;\n }\n await this.detachConversationListener(session);\n this.stopTypingIndicator(session);\n if (session.threadId) {\n this.chatIdByThreadId.delete(session.threadId);\n }\n this.sessionsByChatId.delete(chatId);\n this.status.activeChats = this.sessionsByChatId.size;\n }\n\n private async attachConversationListener(\n session: ChatSession,\n projectId: string,\n threadId: string,\n ): Promise<void> {\n const appServer = this.options.getAppServer();\n if (!appServer) {\n return;\n }\n\n await this.detachConversationListener(session);\n\n try {\n const response = await appServer.addConversationListener({\n conversationId: threadId,\n workspaceId: projectId,\n workspace_id: projectId,\n });\n const responseRecord = asRecord(response);\n const subscriptionId = asTrimmedString(responseRecord.subscriptionId);\n session.listenerSubscriptionId = subscriptionId || null;\n session.threadId = threadId;\n this.chatIdByThreadId.set(threadId, session.chatId);\n } catch (error) {\n logWarn(\"[telegram-bridge] failed to attach conversation listener\", error);\n }\n }\n\n private async detachConversationListener(session: ChatSession): Promise<void> {\n const appServer = this.options.getAppServer();\n if (!appServer) {\n session.listenerSubscriptionId = null;\n return;\n }\n\n const subscriptionId = session.listenerSubscriptionId;\n session.listenerSubscriptionId = null;\n if (!subscriptionId) {\n return;\n }\n\n try {\n await appServer.removeConversationListener({\n subscriptionId,\n });\n } catch (error) {\n logWarn(\"[telegram-bridge] failed to remove conversation listener\", error);\n }\n }\n\n private async detachAllConversationListeners(): Promise<void> {\n const sessions = Array.from(this.sessionsByChatId.values());\n await Promise.all(sessions.map((session) => this.detachConversationListener(session)));\n }\n\n private clearSessionState(): void {\n for (const session of this.sessionsByChatId.values()) {\n this.resetStream(session);\n }\n this.sessionsByChatId.clear();\n this.chatIdByThreadId.clear();\n this.pendingApprovalById.clear();\n this.pendingUserInputByRequestId.clear();\n this.recentDeltaBySignature.clear();\n this.lastSendAtByChatId.clear();\n this.status.activeChats = 0;\n }\n\n private attachAppServerListeners(): void {\n if (this.appServerListenersBound) {\n return;\n }\n const appServer = this.options.getAppServer();\n if (!appServer) {\n this.status.state = \"error\";\n this.status.lastError = \"Codex app-server is unavailable.\";\n return;\n }\n\n appServer.on(\"codex:notification\", this.handleCodexNotification);\n appServer.on(\"codex:event\", this.handleCodexEvent);\n appServer.on(\"codex:exec-command-request\", this.handleExecApprovalRequest);\n appServer.on(\"codex:apply-patch-request\", this.handlePatchApprovalRequest);\n appServer.on(\"codex:server-request\", this.handleServerRequest);\n this.appServerListenersBound = true;\n }\n\n private detachAppServerListeners(): void {\n if (!this.appServerListenersBound) {\n return;\n }\n const appServer = this.options.getAppServer();\n if (!appServer) {\n this.appServerListenersBound = false;\n return;\n }\n\n appServer.off(\"codex:notification\", this.handleCodexNotification);\n appServer.off(\"codex:event\", this.handleCodexEvent);\n appServer.off(\"codex:exec-command-request\", this.handleExecApprovalRequest);\n appServer.off(\"codex:apply-patch-request\", this.handlePatchApprovalRequest);\n appServer.off(\"codex:server-request\", this.handleServerRequest);\n this.appServerListenersBound = false;\n }\n\n private async handleNotification(payload: CodexNotificationPayload): Promise<void> {\n if (!this.running) {\n return;\n }\n const method = asTrimmedString(payload.method);\n if (!method) {\n return;\n }\n const params = asRecord(payload.params);\n const threadId = extractThreadId(params);\n if (!threadId) {\n return;\n }\n const session = this.resolveSessionByThreadId(threadId);\n if (!session) {\n return;\n }\n\n if (method === \"turn/started\") {\n const turnId = extractTurnId(params);\n session.processing = true;\n if (turnId) {\n session.activeTurnId = turnId;\n }\n this.ensureTypingIndicator(session);\n return;\n }\n\n if (method === \"item/agentMessage/delta\") {\n const delta = extractDeltaFromNotification(params);\n if (!delta) {\n return;\n }\n if (this.isDuplicateDelta(`${threadId}|${delta}`)) {\n return;\n }\n this.appendAssistantDelta(session, delta);\n return;\n }\n\n if (method === \"item/completed\") {\n const text = extractAssistantTextFromItemCompleted(params);\n if (text.trim()) {\n session.completedTextCandidate = text;\n }\n return;\n }\n\n if (method === \"turn/completed\") {\n await this.finalizeTurn(session);\n return;\n }\n\n if (method === \"error\") {\n if (!isRetryableTurnErrorPayload(params)) {\n const errorMessage =\n asTrimmedString(asRecord(params.error).message) ||\n asTrimmedString(params.message) ||\n \"Turn failed.\";\n await this.sendSimpleMessage(session.chatId, `Turn error: ${errorMessage}`);\n }\n await this.finalizeTurn(session);\n return;\n }\n }\n\n private async handleEvent(payload: CodexEventPayload): Promise<void> {\n if (!this.running) {\n return;\n }\n const method = asTrimmedString(payload.method);\n if (!method.startsWith(\"codex/event/\")) {\n return;\n }\n const params = asRecord(payload.params);\n const threadId = extractThreadId(params);\n if (!threadId) {\n return;\n }\n const session = this.resolveSessionByThreadId(threadId);\n if (!session) {\n return;\n }\n\n const msg = asRecord(params.msg);\n const msgType = asTrimmedString(msg.type).toLowerCase();\n\n if (msgType === \"agent_message_delta\" || msgType === \"agent_message_content_delta\") {\n const delta = extractText(msg.delta ?? msg.message ?? msg.content ?? msg.value);\n if (!delta) {\n return;\n }\n if (this.isDuplicateDelta(`${threadId}|${delta}`)) {\n return;\n }\n this.appendAssistantDelta(session, delta);\n return;\n }\n\n if (msgType === \"agent_message\") {\n const text = extractText(msg.message ?? msg.content ?? msg.text ?? msg.value);\n if (text.trim()) {\n session.completedTextCandidate = text;\n }\n return;\n }\n\n if (msgType === \"task_started\") {\n session.processing = true;\n const turnId = extractTurnId(params);\n if (turnId) {\n session.activeTurnId = turnId;\n }\n this.ensureTypingIndicator(session);\n return;\n }\n\n if (msgType === \"task_complete\" || msgType === \"turn_aborted\") {\n await this.finalizeTurn(session);\n return;\n }\n\n if (msgType === \"error\" || msgType === \"stream_error\") {\n if (!isRetryableTurnErrorPayload(msg)) {\n const errorMessage =\n asTrimmedString(msg.message) || asTrimmedString(msg.error) || \"Turn failed.\";\n await this.sendSimpleMessage(session.chatId, `Turn error: ${errorMessage}`);\n }\n await this.finalizeTurn(session);\n }\n }\n\n private resolveSessionByThreadId(threadId: string): ChatSession | null {\n const chatId = this.chatIdByThreadId.get(threadId);\n if (!chatId) {\n return null;\n }\n const session = this.sessionsByChatId.get(chatId);\n if (!session || session.threadId !== threadId) {\n return null;\n }\n return session;\n }\n\n private appendAssistantDelta(session: ChatSession, delta: string): void {\n if (!session.stream) {\n session.stream = {\n draftId: randomUUID().slice(0, 12),\n buffer: \"\",\n lastSent: \"\",\n flushTimer: null,\n messageId: null,\n };\n }\n const nextBuffer = mergeStreamDeltaBuffer(session.stream.buffer, delta);\n if (nextBuffer === session.stream.buffer) {\n return;\n }\n session.stream.buffer = nextBuffer;\n session.processing = true;\n this.ensureTypingIndicator(session);\n this.scheduleDraftFlush(session, false);\n }\n\n private scheduleDraftFlush(session: ChatSession, force: boolean): void {\n if (!session.stream) {\n return;\n }\n\n if (force) {\n if (session.stream.flushTimer) {\n clearTimeout(session.stream.flushTimer);\n session.stream.flushTimer = null;\n }\n if (session.streamFlushPromise) {\n session.streamFlushPending = true;\n return;\n }\n void this.flushDraft(session, true);\n return;\n }\n\n if (session.streamFlushPromise) {\n session.streamFlushPending = true;\n return;\n }\n\n if (session.stream.flushTimer) {\n return;\n }\n\n session.stream.flushTimer = setTimeout(() => {\n if (session.stream) {\n session.stream.flushTimer = null;\n }\n void this.flushDraft(session, false);\n }, TELEGRAM_STREAM_FLUSH_MS);\n }\n\n private async flushDraft(session: ChatSession, force: boolean): Promise<void> {\n if (!this.running) {\n return;\n }\n\n if (session.streamFlushPromise) {\n if (force) {\n session.streamFlushPending = true;\n }\n return;\n }\n\n const currentStream = session.stream;\n if (!currentStream) {\n return;\n }\n\n const draftId = currentStream.draftId;\n const rawText = currentStream.buffer;\n if (!rawText.trim()) {\n return;\n }\n\n const draftText =\n rawText.length <= TELEGRAM_MAX_MESSAGE_LENGTH\n ? rawText\n : rawText.slice(rawText.length - TELEGRAM_MAX_MESSAGE_LENGTH);\n\n if (!force && draftText === currentStream.lastSent) {\n return;\n }\n\n const runFlush = async () => {\n if (this.draftStreamingEnabled) {\n try {\n await this.sendDraftMessage(session.chatId, draftText, draftId);\n const activeStream = this.getStreamByDraftId(session, draftId);\n if (activeStream) {\n activeStream.lastSent = draftText;\n }\n this.status.streamMode = this.getCurrentStreamMode();\n return;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (this.isDraftStreamingUnsupportedError(message)) {\n this.draftStreamingEnabled = false;\n this.status.streamMode = this.getCurrentStreamMode();\n logWarn(\n \"[telegram-bridge] sendMessageDraft unavailable, falling back to message edit streaming\",\n message,\n );\n } else {\n logWarn(\"[telegram-bridge] failed to flush draft\", message);\n return;\n }\n }\n }\n\n if (!this.messageStreamingEnabled) {\n return;\n }\n\n try {\n await this.sendOrEditStreamMessage(session, draftText, draftId);\n const activeStream = this.getStreamByDraftId(session, draftId);\n if (activeStream) {\n activeStream.lastSent = draftText;\n }\n this.status.streamMode = this.getCurrentStreamMode();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (this.isMessageStreamingUnsupportedError(message)) {\n this.messageStreamingEnabled = false;\n this.status.streamMode = this.getCurrentStreamMode();\n logWarn(\"[telegram-bridge] edit streaming unavailable, disabling streaming\", message);\n return;\n }\n logWarn(\"[telegram-bridge] failed to flush message-edit stream\", message);\n }\n };\n\n const flushPromise = runFlush();\n session.streamFlushPromise = flushPromise;\n try {\n await flushPromise;\n } finally {\n if (session.streamFlushPromise === flushPromise) {\n session.streamFlushPromise = null;\n }\n if (session.streamFlushPending && this.running && session.stream) {\n session.streamFlushPending = false;\n void this.flushDraft(session, false);\n }\n }\n }\n\n private async finalizeTurn(session: ChatSession): Promise<void> {\n if (session.finalizeInFlight) {\n return;\n }\n if (!session.processing && !session.stream?.buffer && !session.completedTextCandidate) {\n return;\n }\n\n session.finalizeInFlight = true;\n try {\n await this.flushDraft(session, true);\n if (session.streamFlushPromise) {\n await session.streamFlushPromise.catch(() => undefined);\n }\n if (session.streamFlushPending && session.stream) {\n session.streamFlushPending = false;\n await this.flushDraft(session, true);\n if (session.streamFlushPromise) {\n await session.streamFlushPromise.catch(() => undefined);\n }\n }\n\n const finalText = (session.completedTextCandidate ?? session.stream?.buffer ?? \"\").trim();\n const turnId = session.activeTurnId;\n const alreadyFinalizedTurn = turnId\n ? session.recentFinalizedTurnIds.includes(turnId)\n : false;\n const now = nowMs();\n const duplicateByRecentText =\n finalText.length > 0 &&\n session.lastDeliveredFinalText === finalText &&\n now - session.lastDeliveredFinalAtMs <= TELEGRAM_FINAL_TEXT_DEDUPE_MS;\n const duplicateByFinalSignature = this.isDuplicateFinalSignature(session, finalText, now);\n\n if (finalText && !alreadyFinalizedTurn && !duplicateByRecentText && !duplicateByFinalSignature) {\n const chunks = splitMessage(finalText, TELEGRAM_MAX_MESSAGE_LENGTH);\n let chunkStartIndex = 0;\n const streamMessageId = session.stream?.messageId ?? null;\n if (streamMessageId !== null && chunks.length > 0) {\n const reused = await this.tryFinalizeStreamMessage(session.chatId, streamMessageId, chunks[0]);\n if (!reused) {\n await this.sendSimpleMessage(session.chatId, chunks[0]);\n }\n chunkStartIndex = 1;\n }\n for (let index = chunkStartIndex; index < chunks.length; index += 1) {\n await this.sendSimpleMessage(session.chatId, chunks[index]);\n }\n session.lastDeliveredFinalText = finalText;\n session.lastDeliveredFinalAtMs = now;\n this.recordFinalSignature(session, finalText, now);\n if (turnId) {\n session.recentFinalizedTurnIds.push(turnId);\n if (session.recentFinalizedTurnIds.length > TELEGRAM_RECENT_FINALIZED_TURNS_MAX) {\n session.recentFinalizedTurnIds.splice(\n 0,\n session.recentFinalizedTurnIds.length - TELEGRAM_RECENT_FINALIZED_TURNS_MAX,\n );\n }\n }\n }\n } finally {\n session.processing = false;\n session.activeTurnId = null;\n session.completedTextCandidate = null;\n this.resetStream(session);\n session.finalizeInFlight = false;\n }\n }\n\n private resetStream(session: ChatSession): void {\n this.stopTypingIndicator(session);\n if (session.stream?.flushTimer) {\n clearTimeout(session.stream.flushTimer);\n }\n session.streamFlushPending = false;\n session.streamFlushPromise = null;\n session.stream = null;\n }\n\n private ensureTypingIndicator(session: ChatSession): void {\n if (!this.running || !session.processing) {\n return;\n }\n if (session.typingTimer) {\n return;\n }\n void this.sendTypingAction(session.chatId);\n session.typingTimer = setInterval(() => {\n if (!this.running || !session.processing) {\n this.stopTypingIndicator(session);\n return;\n }\n void this.sendTypingAction(session.chatId);\n }, TELEGRAM_TYPING_HEARTBEAT_MS);\n }\n\n private stopTypingIndicator(session: ChatSession): void {\n if (session.typingTimer) {\n clearInterval(session.typingTimer);\n session.typingTimer = null;\n }\n }\n\n private isDraftStreamingUnsupportedError(message: string): boolean {\n const lower = message.toLowerCase();\n return (\n lower.includes(\"sendmessagedraft\") ||\n lower.includes(\"method not found\") ||\n lower.includes(\"there is no method\") ||\n lower.includes(\"text must be non-empty\") ||\n lower.includes(\"random_id_invalid\") ||\n lower.includes(\"random id invalid\") ||\n lower.includes(\"not found\")\n );\n }\n\n private isMessageStreamingUnsupportedError(message: string): boolean {\n const lower = message.toLowerCase();\n return (\n lower.includes(\"editmessagetext\") &&\n (lower.includes(\"method not found\") || lower.includes(\"there is no method\"))\n );\n }\n\n private async sendOrEditStreamMessage(\n session: ChatSession,\n text: string,\n draftId: string,\n ): Promise<void> {\n const stream = this.getStreamByDraftId(session, draftId);\n if (!stream) {\n return;\n }\n const existingMessageId = stream.messageId;\n if (existingMessageId !== null) {\n const edited = await this.tryEditMessageText(session.chatId, existingMessageId, text);\n if (edited) {\n return;\n }\n const activeStream = this.getStreamByDraftId(session, draftId);\n if (activeStream) {\n activeStream.messageId = null;\n }\n }\n\n const sent = await this.sendSimpleMessage(session.chatId, text);\n const messageId = this.extractTelegramMessageId(sent);\n if (messageId !== null) {\n const activeStream = this.getStreamByDraftId(session, draftId);\n if (activeStream) {\n activeStream.messageId = messageId;\n }\n }\n }\n\n private getStreamByDraftId(\n session: ChatSession,\n draftId: string,\n ): ChatSession[\"stream\"] {\n const stream = session.stream;\n if (!stream || stream.draftId !== draftId) {\n return null;\n }\n return stream;\n }\n\n private async tryFinalizeStreamMessage(\n chatId: string,\n messageId: number,\n text: string,\n ): Promise<boolean> {\n return this.tryEditMessageText(chatId, messageId, text);\n }\n\n private async tryEditMessageText(\n chatId: string,\n messageId: number,\n text: string,\n ): Promise<boolean> {\n try {\n await this.editMessageText(chatId, messageId, text);\n return true;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const lower = message.toLowerCase();\n if (lower.includes(\"message is not modified\")) {\n return true;\n }\n if (\n lower.includes(\"message to edit not found\") ||\n lower.includes(\"message can't be edited\") ||\n lower.includes(\"message cant be edited\")\n ) {\n return false;\n }\n throw error;\n }\n }\n\n private isDuplicateIncomingMessage(session: ChatSession, messageId: number): boolean {\n if (session.recentIncomingMessageIds.includes(messageId)) {\n return true;\n }\n session.recentIncomingMessageIds.push(messageId);\n if (session.recentIncomingMessageIds.length > TELEGRAM_RECENT_INCOMING_MESSAGES_MAX) {\n session.recentIncomingMessageIds.splice(\n 0,\n session.recentIncomingMessageIds.length - TELEGRAM_RECENT_INCOMING_MESSAGES_MAX,\n );\n }\n return false;\n }\n\n private buildFinalSignature(session: ChatSession, finalText: string): string {\n const normalized = finalText.trim();\n if (!normalized) {\n return \"\";\n }\n const threadKey = session.threadId ?? \"no-thread\";\n const digest = createHash(\"sha1\").update(normalized).digest(\"hex\");\n return `${threadKey}|${digest}`;\n }\n\n private isDuplicateFinalSignature(\n session: ChatSession,\n finalText: string,\n now: number,\n ): boolean {\n const signature = this.buildFinalSignature(session, finalText);\n if (!signature) {\n return false;\n }\n\n let duplicated = false;\n const kept: Array<{ signature: string; at: number }> = [];\n for (const entry of session.recentFinalSignatures) {\n if (now - entry.at > TELEGRAM_FINAL_SIGNATURE_DEDUPE_MS) {\n continue;\n }\n if (entry.signature === signature) {\n duplicated = true;\n }\n kept.push(entry);\n }\n session.recentFinalSignatures = kept;\n return duplicated;\n }\n\n private recordFinalSignature(session: ChatSession, finalText: string, now: number): void {\n const signature = this.buildFinalSignature(session, finalText);\n if (!signature) {\n return;\n }\n\n const kept = session.recentFinalSignatures.filter(\n (entry) =>\n entry.signature !== signature && now - entry.at <= TELEGRAM_FINAL_SIGNATURE_DEDUPE_MS,\n );\n kept.push({ signature, at: now });\n if (kept.length > TELEGRAM_RECENT_FINAL_SIGNATURES_MAX) {\n kept.splice(0, kept.length - TELEGRAM_RECENT_FINAL_SIGNATURES_MAX);\n }\n session.recentFinalSignatures = kept;\n }\n\n private isDuplicateDelta(signature: string): boolean {\n const now = nowMs();\n const previous = this.recentDeltaBySignature.get(signature) ?? 0;\n this.recentDeltaBySignature.set(signature, now);\n if (this.recentDeltaBySignature.size > 2_048) {\n for (const [key, at] of this.recentDeltaBySignature) {\n if (now - at > 5_000) {\n this.recentDeltaBySignature.delete(key);\n }\n }\n }\n return previous > 0 && now - previous <= 500;\n }\n\n private async handleApprovalRequest(\n kind: \"exec\" | \"patch\",\n requestToken: string,\n params: JsonRecord,\n ): Promise<void> {\n if (!this.running) {\n return;\n }\n\n const chatId = this.resolveChatIdForRequest(params);\n if (!chatId) {\n return;\n }\n\n const actionId = randomUUID().replace(/-/g, \"\").slice(0, 10);\n this.pendingApprovalById.set(actionId, {\n id: actionId,\n kind,\n chatId,\n requestToken,\n createdAtMs: nowMs(),\n });\n\n const threadId = extractThreadId(params);\n const title = kind === \"exec\" ? \"Command approval required\" : \"Patch approval required\";\n const detail = kind === \"exec\" ? extractCommandText(params) : summarizePatchRequest(params);\n const lines = [title];\n if (threadId) {\n lines.push(`Thread: ${threadId}`);\n }\n if (detail) {\n lines.push(`Detail: ${detail}`);\n }\n\n await this.sendSimpleMessage(chatId, lines.join(\"\\n\"), {\n reply_markup: {\n inline_keyboard: [\n [\n { text: \"Approve\", callback_data: `cu:ap:${actionId}:approved` },\n { text: \"Approve session\", callback_data: `cu:ap:${actionId}:approved_for_session` },\n ],\n [\n { text: \"Deny\", callback_data: `cu:ap:${actionId}:denied` },\n { text: \"Abort\", callback_data: `cu:ap:${actionId}:abort` },\n ],\n ],\n },\n });\n }\n\n private async handleUserInputRequest(payload: CodexServerRequestPayload): Promise<void> {\n if (!this.running) {\n return;\n }\n const method = asTrimmedString(payload.method).toLowerCase();\n if (!method.includes(\"requestuserinput\")) {\n return;\n }\n\n const params = asRecord(payload.params);\n const chatId = this.resolveChatIdForRequest(params);\n if (!chatId) {\n return;\n }\n\n const token = String(payload.requestId);\n this.pendingUserInputByRequestId.set(token, {\n chatId,\n requestId: payload.requestId,\n method: payload.method,\n params,\n createdAtMs: nowMs(),\n });\n\n const questions = Array.isArray(params.questions)\n ? params.questions.map((entry) => asRecord(entry)).filter((entry) => asTrimmedString(entry.id))\n : [];\n\n const lines = [\n \"Input required.\",\n `Request ID: ${token}`,\n \"Reply with: /input <request-id> qid=answer; qid2=answer\",\n ];\n\n if (questions.length > 0) {\n lines.push(\"\");\n for (const question of questions) {\n const qid = asTrimmedString(question.id);\n const qtext = asTrimmedString(question.question) || asTrimmedString(question.header) || \"Question\";\n lines.push(`${qid}: ${qtext}`);\n const options = Array.isArray(question.options)\n ? question.options.map((entry) => asRecord(entry)).map((entry) => asTrimmedString(entry.label)).filter(Boolean)\n : [];\n if (options.length > 0) {\n lines.push(`Options: ${options.join(\", \")}`);\n }\n }\n }\n\n await this.sendSimpleMessage(chatId, lines.join(\"\\n\"));\n }\n\n private resolveChatIdForRequest(params: JsonRecord): string | null {\n const threadId = extractThreadId(params);\n if (threadId) {\n const mapped = this.chatIdByThreadId.get(threadId);\n if (mapped) {\n return mapped;\n }\n }\n const sessions = Array.from(this.sessionsByChatId.values());\n if (sessions.length === 1) {\n return sessions[0].chatId;\n }\n return null;\n }\n\n private prunePendingActions(): void {\n const threshold = nowMs() - TELEGRAM_PENDING_TTL_MS;\n for (const [id, entry] of this.pendingApprovalById) {\n if (entry.createdAtMs < threshold) {\n this.pendingApprovalById.delete(id);\n }\n }\n for (const [requestId, entry] of this.pendingUserInputByRequestId) {\n if (entry.createdAtMs < threshold) {\n this.pendingUserInputByRequestId.delete(requestId);\n }\n }\n }\n\n private async answerCallbackQuery(callbackQueryId: string, text?: string): Promise<void> {\n const token = this.settings.token;\n if (!token) {\n return;\n }\n await this.callTelegramApi(\n token,\n \"answerCallbackQuery\",\n {\n callback_query_id: callbackQueryId,\n text: text || undefined,\n },\n {\n retry429: false,\n },\n ).catch(() => undefined);\n }\n\n private async sendTypingAction(chatId: string): Promise<void> {\n const token = this.settings.token;\n if (!token) {\n return;\n }\n await this.callTelegramApi(\n token,\n \"sendChatAction\",\n {\n chat_id: chatId,\n action: \"typing\",\n },\n {\n retry429: false,\n },\n ).catch(() => undefined);\n }\n\n private async sendDraftMessage(chatId: string, text: string, draftId: string): Promise<void> {\n const token = this.settings.token;\n if (!token) {\n return;\n }\n await this.sendWithRateLimit(chatId);\n await this.callTelegramApi(\n token,\n \"sendMessageDraft\",\n {\n chat_id: chatId,\n text,\n message_text: text,\n draft_id: draftId,\n },\n {\n retry429: true,\n },\n );\n }\n\n private async sendSimpleMessage(\n chatId: string,\n text: string,\n extra?: Record<string, unknown>,\n ): Promise<JsonRecord | null> {\n const token = this.settings.token;\n if (!token) {\n return null;\n }\n const payload: Record<string, unknown> = {\n chat_id: chatId,\n text,\n ...extra,\n };\n await this.sendWithRateLimit(chatId);\n const result = await this.callTelegramApi<JsonRecord>(token, \"sendMessage\", payload, {\n retry429: true,\n });\n return asRecord(result);\n }\n\n private async editMessageText(chatId: string, messageId: number, text: string): Promise<void> {\n const token = this.settings.token;\n if (!token) {\n return;\n }\n await this.sendWithRateLimit(chatId);\n await this.callTelegramApi(\n token,\n \"editMessageText\",\n {\n chat_id: chatId,\n message_id: messageId,\n text,\n },\n {\n retry429: true,\n },\n );\n }\n\n private extractTelegramMessageId(value: unknown): number | null {\n const record = asRecord(value);\n return asNumber(record.message_id ?? record.messageId);\n }\n\n private async sendWithRateLimit(chatId: string): Promise<void> {\n const lastSend = this.lastSendAtByChatId.get(chatId) ?? 0;\n const now = nowMs();\n const waitMs = TELEGRAM_MIN_SEND_INTERVAL_MS - (now - lastSend);\n if (waitMs > 0) {\n await this.sleep(waitMs);\n }\n this.lastSendAtByChatId.set(chatId, nowMs());\n }\n\n private async callTelegramApi<T>(\n token: string,\n method: string,\n payload: Record<string, unknown>,\n options?: { signal?: AbortSignal; retry429?: boolean },\n ): Promise<T> {\n const url = `${TELEGRAM_API_BASE}/bot${token}/${method}`;\n\n const execute = async (): Promise<TelegramApiResponse<T>> => {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, TELEGRAM_API_TIMEOUT_MS);\n\n const signal = options?.signal;\n let externalAbortListener: (() => void) | null = null;\n if (signal) {\n if (signal.aborted) {\n clearTimeout(timeoutId);\n controller.abort();\n } else {\n externalAbortListener = () => controller.abort();\n signal.addEventListener(\"abort\", externalAbortListener, { once: true });\n }\n }\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n const json = (await response.json()) as TelegramApiResponse<T>;\n return json;\n } finally {\n clearTimeout(timeoutId);\n if (signal && externalAbortListener) {\n signal.removeEventListener(\"abort\", externalAbortListener);\n }\n }\n };\n\n const response = await execute();\n if (response.ok) {\n return response.result as T;\n }\n\n const retryAfterSeconds = response.parameters?.retry_after;\n if (\n options?.retry429 &&\n response.error_code === 429 &&\n typeof retryAfterSeconds === \"number\" &&\n retryAfterSeconds > 0\n ) {\n await this.sleep(retryAfterSeconds * 1000);\n const retried = await execute();\n if (retried.ok) {\n return retried.result as T;\n }\n throw new Error(retried.description || `${method} failed (code ${retried.error_code ?? \"unknown\"})`);\n }\n\n throw new Error(response.description || `${method} failed (code ${response.error_code ?? \"unknown\"})`);\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, Math.max(0, Math.floor(ms)));\n });\n }\n\n private buildRuntimeLockPath(token: string): string {\n const tokenHash = createHash(\"sha1\").update(token).digest(\"hex\").slice(0, 16);\n return path.join(getUserDataDir(), `${TELEGRAM_BRIDGE_LOCK_FILE_PREFIX}-${tokenHash}.lock`);\n }\n\n private async acquireRuntimeLock(token: string): Promise<void> {\n if (this.runtimeLockPath) {\n return;\n }\n const lockPath = this.buildRuntimeLockPath(token);\n await fs.mkdir(path.dirname(lockPath), { recursive: true });\n\n const payload = JSON.stringify(\n {\n pid: process.pid,\n startedAt: new Date().toISOString(),\n },\n null,\n 2,\n );\n\n try {\n await fs.writeFile(lockPath, payload, { encoding: \"utf8\", flag: \"wx\" });\n this.runtimeLockPath = lockPath;\n return;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") {\n throw error;\n }\n }\n\n const existingPid = await this.readLockPid(lockPath);\n if (existingPid && existingPid !== process.pid && this.isProcessAlive(existingPid)) {\n throw new Error(\n `Telegram bridge already running in another process (pid ${existingPid}). Stop the other instance to avoid duplicate replies.`,\n );\n }\n\n await fs.unlink(lockPath).catch(() => undefined);\n await fs.writeFile(lockPath, payload, { encoding: \"utf8\", flag: \"wx\" });\n this.runtimeLockPath = lockPath;\n }\n\n private async releaseRuntimeLock(): Promise<void> {\n const lockPath = this.runtimeLockPath;\n this.runtimeLockPath = null;\n if (!lockPath) {\n return;\n }\n await fs.unlink(lockPath).catch(() => undefined);\n }\n\n private async readLockPid(lockPath: string): Promise<number | null> {\n try {\n const raw = await fs.readFile(lockPath, \"utf8\");\n const parsed = JSON.parse(raw) as { pid?: unknown };\n const pid = asNumber(parsed.pid);\n if (pid === null || pid <= 0) {\n return null;\n }\n return Math.trunc(pid);\n } catch {\n return null;\n }\n }\n\n private isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n return code === \"EPERM\";\n }\n }\n}\n\nexport function createTelegramBridge(options: TelegramBridgeOptions): TelegramBridge {\n return new TelegramBridge(options);\n}\n","type JsonRecord = Record<string, unknown>;\n\nconst RETRY_FLAG_KEYS = [\n \"willRetry\",\n \"will_retry\",\n \"retryable\",\n \"retryable_error\",\n \"shouldRetry\",\n \"should_retry\",\n \"retry\",\n] as const;\n\nconst RETRY_PROGRESS_MESSAGE_RE =\n /(?:reconnecting|retrying)(?:\\.\\.\\.)?(?:\\s+\\d+\\s*\\/\\s*\\d+)?/i;\n\nfunction asRecord(value: unknown): JsonRecord {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as JsonRecord)\n : {};\n}\n\nfunction asString(value: unknown): string {\n return typeof value === \"string\" ? value : value != null ? String(value) : \"\";\n}\n\nfunction parseBooleanLike(value: unknown): boolean | null {\n if (typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"number\") {\n if (value === 1) {\n return true;\n }\n if (value === 0) {\n return false;\n }\n return null;\n }\n if (typeof value === \"string\") {\n const normalized = value.trim().toLowerCase();\n if (!normalized) {\n return null;\n }\n if (normalized === \"true\" || normalized === \"1\") {\n return true;\n }\n if (normalized === \"false\" || normalized === \"0\") {\n return false;\n }\n }\n return null;\n}\n\nfunction extractRetryFlag(payload: unknown): boolean | null {\n const root = asRecord(payload);\n const nestedCandidates = [\n root,\n asRecord(root.error),\n asRecord(root.details),\n asRecord(root.data),\n asRecord(root.meta),\n ];\n\n for (const candidate of nestedCandidates) {\n for (const key of RETRY_FLAG_KEYS) {\n const parsed = parseBooleanLike(candidate[key]);\n if (parsed !== null) {\n return parsed;\n }\n }\n }\n\n return null;\n}\n\nfunction isRetryProgressMessage(message: string): boolean {\n const trimmed = message.trim();\n if (!trimmed) {\n return false;\n }\n return RETRY_PROGRESS_MESSAGE_RE.test(trimmed);\n}\n\nfunction extractErrorMessageCandidates(payload: unknown): string[] {\n const root = asRecord(payload);\n const error = asRecord(root.error);\n\n return [\n asString(root.message),\n asString(root.detail),\n asString(root.reason),\n asString(root.error),\n asString(error.message),\n asString(error.detail),\n asString(error.reason),\n asString(error.error),\n ]\n .map(value => value.trim())\n .filter(Boolean);\n}\n\nexport function isRetryableTurnErrorPayload(payload: unknown): boolean {\n const retryFlag = extractRetryFlag(payload);\n if (retryFlag !== null) {\n return retryFlag;\n }\n return extractErrorMessageCandidates(payload).some(isRetryProgressMessage);\n}\n","import { ProfileManager } from \"../../../lib/profile-manager\";\nimport { licenseService } from \"../../../lib/license-service\";\nimport { getCloudSyncStatus, pullCloudSync, pushCloudSync } from \"../../../lib/cloud-sync-service\";\nimport { assertProfileCreationAllowed } from \"../../../lib/license-guard\";\nimport { runCodexLogin, resolveCodexBinary, resolveLoginMode, type CodexLoginMode } from \"./codex-cli\";\nimport { fetchRateLimitsViaRpc } from \"../../../lib/codex-rpc\";\nimport { maxUsedPercent } from \"../../../lib/rate-limit-notifier\";\nimport { getAppState, getUserDataDir, initializeAppState } from \"../../../lib/app-state\";\nimport { importLegacyLocalStorageOnce, runStorageMigrationV1 } from \"../../../lib/storage-migration-v1\";\nimport { getStoredAutoRollSettings } from \"../../../lib/codex-settings\";\nimport { handleDaemonCommand } from \"./daemon\";\nimport type { OrganizationInfo, Profile, RateLimitSnapshot, RateLimitWindow } from \"../../../lib/types\";\n\ndeclare const __CODEXUSE_CLI_VERSION__: string;\n\nconst VERSION = typeof __CODEXUSE_CLI_VERSION__ === \"string\"\n ? __CODEXUSE_CLI_VERSION__\n : \"0.0.0\";\nlet cliStorageReadyPromise: Promise<void> | null = null;\n\nasync function ensureCliStorageReady(): Promise<void> {\n if (cliStorageReadyPromise) {\n return cliStorageReadyPromise;\n }\n\n cliStorageReadyPromise = (async () => {\n await initializeAppState(getUserDataDir());\n const migrated = await runStorageMigrationV1();\n if (migrated.migration.status === \"pending_local_storage\") {\n await importLegacyLocalStorageOnce({});\n }\n\n const state = await getAppState();\n if (state.migration.status !== \"complete\") {\n throw new Error(\n `Storage migration is not complete (status: ${state.migration.status}). CLI cannot continue until migration succeeds.`,\n );\n }\n })().catch((error) => {\n cliStorageReadyPromise = null;\n throw error;\n });\n\n return cliStorageReadyPromise;\n}\n\nfunction printHelp(): void {\n console.log(`CodexUse CLI v${VERSION}\n\nUsage:\n codexuse profile list [--no-usage] [--compact]\n codexuse profile current\n codexuse profile add <name> [--skip-login] [--device-auth] [--login=browser|device]\n codexuse profile refresh <name> [--skip-login] [--device-auth] [--login=browser|device]\n codexuse profile switch <name>\n codexuse profile autoroll [--threshold=50-100] [--dry-run] [--watch] [--interval=seconds]\n codexuse profile delete <name>\n codexuse profile rename <old> <new>\n\n codexuse license status [--refresh]\n codexuse license activate <license-key>\n\n codexuse sync status\n codexuse sync pull\n codexuse sync push\n\n codexuse daemon start --telegram-bot-token=<token> [--project-path=/abs/path]\n\nFlags:\n -h, --help Show help\n -v, --version Show version\n --no-usage Skip rate-limit usage fetch\n --compact Names only\n --device-auth Use device auth for Codex login\n --login=MODE Login mode: browser | device\n --threshold=NN Auto-roll switch threshold percent (50-100)\n --watch Keep checking and auto-switch when threshold is reached\n --interval=SEC Watch interval in seconds (default: 30)\n --dry-run Print planned switch without changing active profile\n --telegram-bot-token=TOKEN Telegram bot token for daemon mode\n --project-path=PATH Optional path to auto-register and set as default project in daemon mode\n`);\n}\n\nfunction hasFlag(args: string[], flag: string): boolean {\n return args.includes(flag);\n}\n\nfunction stripFlags(args: string[]): string[] {\n return args.filter(arg => !arg.startsWith(\"-\"));\n}\n\nfunction parseLoginMode(flags: string[]): CodexLoginMode | null {\n if (flags.includes(\"--device-auth\")) return \"device\";\n const explicit = flags.find(flag => flag.startsWith(\"--login=\"));\n if (!explicit) return null;\n const value = explicit.split(\"=\")[1];\n if (value === \"browser\" || value === \"device\") {\n return value;\n }\n return null;\n}\n\nconst DEFAULT_AUTOROLL_INTERVAL_SECONDS = 30;\nconst DEFAULT_AUTOROLL_THRESHOLD = 95;\n\nfunction parseNumericFlag(flags: string[], name: string): number | null {\n const explicit = flags.find(flag => flag.startsWith(`${name}=`));\n if (!explicit) {\n return null;\n }\n const raw = explicit.slice(`${name}=`.length);\n const value = Number.parseFloat(raw);\n return Number.isFinite(value) ? value : Number.NaN;\n}\n\nfunction parseIntegerFlag(flags: string[], name: string): number | null {\n const explicit = flags.find(flag => flag.startsWith(`${name}=`));\n if (!explicit) {\n return null;\n }\n const raw = explicit.slice(`${name}=`.length);\n const value = Number.parseInt(raw, 10);\n return Number.isFinite(value) ? value : Number.NaN;\n}\n\nfunction formatProfileLabel(name: string, displayName?: string | null): string {\n if (displayName && displayName.trim() && displayName !== name) {\n return `${displayName} (${name})`;\n }\n return name;\n}\n\nfunction toTitleCase(value: string): string {\n return value.replace(/\\w\\S*/g, word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());\n}\n\nfunction formatShortDate(value?: string | null): string | null {\n if (!value) return null;\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return null;\n if (typeof Intl !== \"undefined\" && Intl.DateTimeFormat) {\n return new Intl.DateTimeFormat(undefined, { month: \"short\", day: \"numeric\" }).format(date);\n }\n return date.toLocaleDateString();\n}\n\nfunction formatRelativeTime(value?: string | null): string | null {\n if (!value) return null;\n const parsed = Date.parse(value);\n if (Number.isNaN(parsed)) return null;\n const diffMs = parsed - Date.now();\n const absMs = Math.abs(diffMs);\n if (absMs < 60_000) {\n return null;\n }\n const minutes = Math.round(absMs / 60_000);\n if (minutes < 60) {\n return diffMs >= 0 ? `in ${minutes}m` : `${minutes}m ago`;\n }\n const hours = Math.round(minutes / 60);\n if (hours < 24) {\n return diffMs >= 0 ? `in ${hours}h` : `${hours}h ago`;\n }\n const days = Math.round(hours / 24);\n return diffMs >= 0 ? `in ${days}d` : `${days}d ago`;\n}\n\nfunction formatOrganizations(organizations?: OrganizationInfo[]): string | null {\n if (!organizations || !Array.isArray(organizations) || organizations.length === 0) {\n return null;\n }\n const parts = organizations\n .map(org => {\n if (!org) return null;\n const name = org.title || org.id;\n if (!name) return null;\n return org.role ? `${name} (${org.role})` : name;\n })\n .filter((value): value is string => Boolean(value));\n return parts.length > 0 ? parts.join(\", \") : null;\n}\n\nfunction formatWindowLabel(windowMinutes?: number): string | null {\n if (typeof windowMinutes !== \"number\" || Number.isNaN(windowMinutes)) {\n return null;\n }\n if (windowMinutes >= 2880) {\n const days = windowMinutes / 1440;\n const rounded = Math.round(days * 10) / 10;\n const display = Number.isInteger(rounded) ? rounded.toFixed(0) : rounded.toFixed(1);\n return `${display.replace(/\\.0$/, \"\")}d window`;\n }\n if (windowMinutes >= 60) {\n const hours = windowMinutes / 60;\n const rounded = Math.round(hours * 10) / 10;\n const display = Number.isInteger(rounded) ? rounded.toFixed(0) : rounded.toFixed(1);\n return `${display.replace(/\\.0$/, \"\")}h window`;\n }\n const minutes = Math.round(windowMinutes);\n return `${minutes}m window`;\n}\n\nfunction formatDurationFromSeconds(seconds?: number | null): string | null {\n if (typeof seconds !== \"number\" || Number.isNaN(seconds)) {\n return null;\n }\n if (seconds <= 0) {\n return \"now\";\n }\n const minutes = Math.floor(seconds / 60);\n if (minutes === 0) {\n return `${Math.max(1, Math.round(seconds))}s`;\n }\n if (minutes < 60) {\n return `${minutes}m`;\n }\n const hours = Math.floor(minutes / 60);\n const remainingMinutes = minutes % 60;\n if (hours < 24) {\n return remainingMinutes ? `${hours}h ${remainingMinutes}m` : `${hours}h`;\n }\n const days = Math.floor(hours / 24);\n const remainingHours = hours % 24;\n return remainingHours ? `${days}d ${remainingHours}h` : `${days}d`;\n}\n\nfunction formatResetText(window: RateLimitWindow): string | null {\n if (window.resetsAt) {\n return formatRelativeTime(window.resetsAt) ?? window.resetsAt;\n }\n const durationText = formatDurationFromSeconds(window.resetsInSeconds);\n if (!durationText) return null;\n if (durationText === \"now\") return \"now\";\n return `in ${durationText}`;\n}\n\ntype RateLimitRow = {\n label: string;\n used: string;\n reset: string | null;\n};\n\nfunction formatWindowUsage(window: RateLimitWindow): RateLimitRow | null {\n const label = formatWindowLabel(window.windowMinutes) ?? \"window\";\n const usedPercent =\n typeof window.usedPercent === \"number\" && Number.isFinite(window.usedPercent)\n ? `${Math.round(Math.max(0, Math.min(100, window.usedPercent)))}%`\n : \"n/a\";\n const resetText = formatResetText(window);\n return {\n label,\n used: usedPercent,\n reset: resetText ? `reset ${resetText}` : null,\n };\n}\n\ntype UsageInfo = {\n summary: string;\n rows: RateLimitRow[] | null;\n usageSummary: RateLimitUsageSummary;\n};\n\ntype RateLimitUsageKey = \"primary\" | \"secondary\";\n\ntype RateLimitUsageSummary = {\n windowKey: RateLimitUsageKey;\n usagePercent: number;\n hasUsage: boolean;\n resetsInSeconds: number | null;\n windowMinutes: number | null;\n};\n\nconst EMPTY_USAGE_SUMMARY: RateLimitUsageSummary = {\n windowKey: \"primary\",\n usagePercent: 0,\n hasUsage: false,\n resetsInSeconds: null,\n windowMinutes: null,\n};\n\nfunction toFiniteNumberOrNull(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction summarizeRateLimitSnapshot(snapshot: RateLimitSnapshot | null | undefined): RateLimitUsageSummary {\n if (!snapshot) {\n return { ...EMPTY_USAGE_SUMMARY };\n }\n\n const entries: Array<{ key: RateLimitUsageKey; window: RateLimitWindow | undefined }> = [\n { key: \"primary\", window: snapshot.primary },\n { key: \"secondary\", window: snapshot.secondary },\n ];\n\n let summary: RateLimitUsageSummary = { ...EMPTY_USAGE_SUMMARY };\n let initialized = false;\n\n for (const entry of entries) {\n if (!entry.window) {\n continue;\n }\n\n const usageValueRaw = toFiniteNumberOrNull(entry.window.usedPercent);\n const usageValue = usageValueRaw === null ? 0 : Math.max(0, Math.min(100, usageValueRaw));\n const hasUsage = usageValueRaw !== null;\n const resetsInSeconds = toFiniteNumberOrNull(entry.window.resetsInSeconds);\n const windowMinutes = toFiniteNumberOrNull(entry.window.windowMinutes);\n\n if (!initialized) {\n initialized = true;\n summary = {\n windowKey: entry.key,\n usagePercent: usageValue,\n hasUsage,\n resetsInSeconds,\n windowMinutes,\n };\n continue;\n }\n\n if (hasUsage && summary.hasUsage && usageValue > summary.usagePercent) {\n summary = {\n windowKey: entry.key,\n usagePercent: usageValue,\n hasUsage,\n resetsInSeconds,\n windowMinutes,\n };\n continue;\n }\n\n if (!hasUsage && !summary.hasUsage && summary.resetsInSeconds !== null) {\n if (resetsInSeconds !== null && resetsInSeconds < summary.resetsInSeconds) {\n summary = {\n windowKey: entry.key,\n usagePercent: usageValue,\n hasUsage,\n resetsInSeconds,\n windowMinutes,\n };\n }\n continue;\n }\n\n if (!hasUsage && !summary.hasUsage && summary.resetsInSeconds === null && resetsInSeconds !== null) {\n summary = {\n windowKey: entry.key,\n usagePercent: usageValue,\n hasUsage,\n resetsInSeconds,\n windowMinutes,\n };\n continue;\n }\n\n if (hasUsage && !summary.hasUsage) {\n summary = {\n windowKey: entry.key,\n usagePercent: usageValue,\n hasUsage,\n resetsInSeconds,\n windowMinutes,\n };\n }\n }\n\n return summary;\n}\n\nfunction fallbackUsage(profile: Profile): UsageInfo {\n const usageSummary = summarizeRateLimitSnapshot(profile.rateLimit ?? null);\n if (!profile.isValid) {\n return { summary: \"invalid\", rows: null, usageSummary };\n }\n if (profile.tokenStatus?.requiresUserAction) {\n return { summary: \"auth required\", rows: null, usageSummary };\n }\n return { summary: \"n/a\", rows: null, usageSummary };\n}\n\nasync function resolveProfileUsage(\n manager: ProfileManager,\n profile: Profile,\n codexPath: string,\n): Promise<UsageInfo> {\n if (!profile.isValid || profile.tokenStatus?.requiresUserAction) {\n return fallbackUsage(profile);\n }\n\n try {\n const snapshot = await manager.runWithProfileAuth(profile.name, (env) =>\n fetchRateLimitsViaRpc(env, { codexPath }),\n );\n if (!snapshot) {\n const usageSummary = summarizeRateLimitSnapshot(profile.rateLimit ?? null);\n return { summary: \"n/a\", rows: null, usageSummary };\n }\n const rows: RateLimitRow[] = [];\n if (snapshot.primary) {\n const row = formatWindowUsage(snapshot.primary);\n if (row) rows.push(row);\n }\n if (snapshot.secondary) {\n const row = formatWindowUsage(snapshot.secondary);\n if (row) rows.push(row);\n }\n const maxPercent = maxUsedPercent(snapshot);\n const summary = typeof maxPercent === \"number\"\n ? `${Math.round(maxPercent)}%`\n : \"n/a\";\n return { summary, rows: rows.length > 0 ? rows : null, usageSummary: summarizeRateLimitSnapshot(snapshot) };\n } catch {\n return fallbackUsage(profile);\n }\n}\n\ntype AutoRollCandidate = {\n profile: Profile;\n usageSummary: RateLimitUsageSummary;\n};\n\nfunction compareAutoRollCandidates(a: AutoRollCandidate, b: AutoRollCandidate): number {\n if (a.usageSummary.usagePercent !== b.usageSummary.usagePercent) {\n return a.usageSummary.usagePercent - b.usageSummary.usagePercent;\n }\n const aReset = a.usageSummary.resetsInSeconds ?? Number.POSITIVE_INFINITY;\n const bReset = b.usageSummary.resetsInSeconds ?? Number.POSITIVE_INFINITY;\n if (aReset !== bReset) {\n return aReset - bReset;\n }\n return a.profile.name.localeCompare(b.profile.name);\n}\n\nfunction computeAutoRollCandidate(\n profiles: Profile[],\n usageMap: Map<string, UsageInfo>,\n currentProfileName: string,\n currentSummary: RateLimitUsageSummary,\n switchThreshold: number,\n): AutoRollCandidate | null {\n const candidates = profiles\n .filter(profile => profile.name !== currentProfileName && profile.isValid && !profile.tokenStatus?.requiresUserAction)\n .map(profile => ({\n profile,\n usageSummary: usageMap.get(profile.name)?.usageSummary ?? summarizeRateLimitSnapshot(profile.rateLimit ?? null),\n }));\n\n if (candidates.length === 0) {\n return null;\n }\n\n const belowThreshold = candidates\n .filter(candidate => candidate.usageSummary.hasUsage && candidate.usageSummary.usagePercent < switchThreshold)\n .sort(compareAutoRollCandidates);\n let selected = belowThreshold[0] ?? null;\n\n if (!selected) {\n selected = candidates\n .filter(candidate => candidate.usageSummary.hasUsage)\n .sort(compareAutoRollCandidates)[0] ?? null;\n }\n\n if (!selected) {\n selected = candidates\n .filter(candidate => !candidate.usageSummary.hasUsage)\n .sort((a, b) => {\n const aReset = a.usageSummary.resetsInSeconds ?? Number.POSITIVE_INFINITY;\n const bReset = b.usageSummary.resetsInSeconds ?? Number.POSITIVE_INFINITY;\n if (aReset !== bReset) {\n return aReset - bReset;\n }\n return a.profile.name.localeCompare(b.profile.name);\n })[0] ?? null;\n }\n\n if (!selected) {\n return null;\n }\n\n if (selected.usageSummary.hasUsage && currentSummary.hasUsage) {\n if (selected.usageSummary.usagePercent > currentSummary.usagePercent) {\n return null;\n }\n if (selected.usageSummary.usagePercent === currentSummary.usagePercent) {\n const selectedReset = selected.usageSummary.resetsInSeconds ?? Number.POSITIVE_INFINITY;\n const currentReset = currentSummary.resetsInSeconds ?? Number.POSITIVE_INFINITY;\n if (selectedReset >= currentReset) {\n return null;\n }\n }\n }\n\n return selected;\n}\n\nfunction formatPlan(profile: Profile): string {\n const metadata = profile.metadata;\n if (!metadata) {\n return \"No plan details\";\n }\n const parts: string[] = [];\n if (metadata.planType) {\n parts.push(toTitleCase(metadata.planType));\n }\n const until = metadata.subscription?.activeUntil;\n if (until) {\n const formatted = formatShortDate(until);\n if (formatted) {\n parts.push(`Until ${formatted}`);\n }\n }\n return parts.join(\" · \") || \"No plan details\";\n}\n\nfunction formatAuth(profile: Profile): string {\n const metadata = profile.metadata;\n const relative = formatRelativeTime(metadata?.tokenAuthTime);\n if (relative) return relative;\n if (metadata?.tokenAuthTime) return metadata.tokenAuthTime;\n return \"Not authenticated yet\";\n}\n\nfunction printProfileDetails(profile: Profile, usage?: UsageInfo | null): void {\n const email = profile.email ?? \"Unknown\";\n const plan = formatPlan(profile);\n const orgs = formatOrganizations(profile.metadata?.organizations) ?? \"No organizations\";\n const auth = formatAuth(profile);\n const workspace = profile.workspaceName ?? profile.workspaceId ?? null;\n\n const entries: Array<{ label: string; value: string }> = [\n { label: \"email\", value: email },\n { label: \"plan\", value: plan },\n { label: \"orgs\", value: orgs },\n { label: \"auth\", value: auth },\n ];\n if (workspace) {\n entries.push({ label: \"workspace\", value: workspace });\n }\n const pad = Math.max(...entries.map(entry => entry.label.length));\n for (const entry of entries) {\n console.log(` ${entry.label.padEnd(pad)} : ${entry.value}`);\n }\n\n if (usage) {\n if (usage.rows && usage.rows.length > 0) {\n const labelPad = Math.max(...usage.rows.map(row => row.label.length));\n const usedPad = Math.max(...usage.rows.map(row => row.used.length));\n console.log(` rate limits:`);\n for (const row of usage.rows) {\n const resetText = row.reset ? ` ${row.reset}` : \"\";\n console.log(` ${row.label.padEnd(labelPad)} ${row.used.padStart(usedPad)}${resetText}`);\n }\n return;\n }\n console.log(` rate limits: ${usage.summary}`);\n }\n}\n\nasync function mapWithConcurrency<T, R>(\n items: T[],\n limit: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = new Array(items.length);\n const workerCount = Math.max(1, Math.min(limit, items.length));\n let nextIndex = 0;\n\n const workers = Array.from({ length: workerCount }, async () => {\n while (true) {\n const current = nextIndex++;\n if (current >= items.length) {\n return;\n }\n results[current] = await fn(items[current], current);\n }\n });\n\n await Promise.all(workers);\n return results;\n}\n\nfunction parseAutoRollThreshold(flags: string[], fallbackThreshold: number): number {\n const explicitThreshold = parseNumericFlag(flags, \"--threshold\");\n if (explicitThreshold === null) {\n return fallbackThreshold;\n }\n if (Number.isNaN(explicitThreshold)) {\n throw new Error(\"Invalid --threshold value. Use --threshold=50-100.\");\n }\n if (explicitThreshold < 50 || explicitThreshold > 100) {\n throw new Error(\"Invalid --threshold value. Use a number between 50 and 100.\");\n }\n return Math.round(explicitThreshold);\n}\n\nfunction parseAutoRollIntervalSeconds(flags: string[]): number {\n const explicitInterval = parseIntegerFlag(flags, \"--interval\");\n if (explicitInterval === null) {\n return DEFAULT_AUTOROLL_INTERVAL_SECONDS;\n }\n if (Number.isNaN(explicitInterval) || explicitInterval <= 0) {\n throw new Error(\"Invalid --interval value. Use --interval=<seconds> with a positive integer.\");\n }\n return explicitInterval;\n}\n\nasync function collectUsageMap(\n manager: ProfileManager,\n profiles: Profile[],\n codexPath: string,\n): Promise<Map<string, UsageInfo>> {\n const usageMap = new Map<string, UsageInfo>();\n const limitEnv = Number.parseInt(process.env.CODEXUSE_CLI_USAGE_CONCURRENCY ?? \"3\", 10);\n const limit = Number.isFinite(limitEnv) && limitEnv > 0 ? limitEnv : 3;\n const results = await mapWithConcurrency(profiles, limit, (profile) =>\n resolveProfileUsage(manager, profile, codexPath),\n );\n for (const [index, profile] of profiles.entries()) {\n usageMap.set(profile.name, results[index]);\n }\n return usageMap;\n}\n\nasync function runAutoRollPass(\n manager: ProfileManager,\n options: {\n threshold: number;\n dryRun: boolean;\n },\n): Promise<{ switched: boolean; message: string; source: string | null; target: string | null }> {\n const profiles = await manager.listProfiles();\n if (!profiles.length) {\n return { switched: false, message: \"No profiles found.\", source: null, target: null };\n }\n\n const current = await manager.getCurrentProfile();\n if (!current.name) {\n return { switched: false, message: \"No active profile.\", source: null, target: null };\n }\n\n const codexPath = resolveCodexBinary();\n if (!codexPath) {\n throw new Error(\"Codex CLI binary not found on PATH. Auto-roll requires codex for live rate limits.\");\n }\n\n const usageMap = await collectUsageMap(manager, profiles, codexPath);\n const currentProfile = profiles.find(profile => profile.name === current.name);\n if (!currentProfile) {\n return {\n switched: false,\n message: `Current profile '${current.name}' is missing from saved profiles.`,\n source: current.name,\n target: null,\n };\n }\n\n const currentUsage = usageMap.get(current.name)?.usageSummary ?? summarizeRateLimitSnapshot(currentProfile.rateLimit ?? null);\n if (!currentUsage.hasUsage) {\n return {\n switched: false,\n message: `No live rate-limit usage for '${current.name}'. Skipping auto-roll.`,\n source: current.name,\n target: null,\n };\n }\n\n if (currentUsage.usagePercent < options.threshold) {\n return {\n switched: false,\n message: `'${current.name}' at ${Math.round(currentUsage.usagePercent)}%, below threshold ${options.threshold}%.`,\n source: current.name,\n target: null,\n };\n }\n\n const candidate = computeAutoRollCandidate(\n profiles,\n usageMap,\n current.name,\n currentUsage,\n options.threshold,\n );\n if (!candidate) {\n return {\n switched: false,\n message: `No eligible profile to switch from '${current.name}' at ${Math.round(currentUsage.usagePercent)}%.`,\n source: current.name,\n target: null,\n };\n }\n\n const candidateUsage = candidate.usageSummary.hasUsage ? `${Math.round(candidate.usageSummary.usagePercent)}%` : \"n/a\";\n if (options.dryRun) {\n return {\n switched: false,\n message: `[dry-run] Would switch '${current.name}' (${Math.round(currentUsage.usagePercent)}%) -> '${candidate.profile.name}' (${candidateUsage}).`,\n source: current.name,\n target: candidate.profile.name,\n };\n }\n\n await manager.switchToProfile(candidate.profile.name);\n return {\n switched: true,\n message: `Auto-rolled '${current.name}' (${Math.round(currentUsage.usagePercent)}%) -> '${candidate.profile.name}' (${candidateUsage}).`,\n source: current.name,\n target: candidate.profile.name,\n };\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nasync function handleProfile(args: string[]): Promise<void> {\n const flags = args.filter(arg => arg.startsWith(\"-\"));\n const params = stripFlags(args);\n const sub = params[0];\n\n if (!sub || hasFlag(flags, \"--help\") || hasFlag(flags, \"-h\")) {\n printHelp();\n return;\n }\n\n const manager = new ProfileManager();\n\n switch (sub) {\n case \"list\": {\n const profiles = await manager.listProfiles();\n const current = await manager.getCurrentProfile();\n if (!profiles.length) {\n console.log(\"No profiles found.\");\n return;\n }\n const compact = hasFlag(flags, \"--compact\");\n const withUsage = !hasFlag(flags, \"--no-usage\");\n let usageMap: Map<string, UsageInfo> | null = null;\n if (withUsage) {\n const codexPath = resolveCodexBinary();\n if (!codexPath) {\n usageMap = new Map();\n for (const profile of profiles) {\n usageMap.set(profile.name, {\n summary: \"codex cli missing\",\n rows: null,\n usageSummary: summarizeRateLimitSnapshot(profile.rateLimit ?? null),\n });\n }\n } else {\n usageMap = await collectUsageMap(manager, profiles, codexPath);\n }\n }\n for (const [index, profile] of profiles.entries()) {\n const marker = current.name === profile.name ? \"*\" : \" \";\n const label = formatProfileLabel(profile.name, profile.displayName);\n if (index > 0) {\n console.log(\"\");\n }\n const activeLabel = current.name === profile.name ? \" (active)\" : \"\";\n console.log(`${marker} ${label}${activeLabel}`);\n if (compact) continue;\n const usage = usageMap?.get(profile.name) ?? null;\n printProfileDetails(profile, usage);\n }\n return;\n }\n case \"current\": {\n const current = await manager.getCurrentProfile();\n if (!current.name) {\n console.log(\"No active profile.\");\n return;\n }\n console.log(current.name);\n return;\n }\n case \"add\": {\n const name = params[1];\n if (!name) {\n throw new Error(\"Profile name is required.\");\n }\n await assertProfileCreationAllowed(manager);\n if (!hasFlag(flags, \"--skip-login\")) {\n const loginMode = resolveLoginMode(parseLoginMode(flags));\n await runCodexLogin(loginMode);\n }\n const profile = await manager.createProfile(name);\n const label = profile ? formatProfileLabel(profile.name, profile.displayName) : name;\n console.log(`Profile created: ${label}`);\n return;\n }\n case \"refresh\": {\n const name = params[1];\n if (!name) {\n throw new Error(\"Profile name is required.\");\n }\n if (!hasFlag(flags, \"--skip-login\")) {\n const loginMode = resolveLoginMode(parseLoginMode(flags));\n await runCodexLogin(loginMode);\n }\n const profile = await manager.refreshProfileAuth(name);\n const label = formatProfileLabel(profile.name, profile.displayName);\n console.log(`Profile refreshed: ${label}`);\n return;\n }\n case \"switch\": {\n const name = params[1];\n if (!name) {\n throw new Error(\"Profile name is required.\");\n }\n await manager.switchToProfile(name);\n console.log(`Switched to profile: ${name}`);\n return;\n }\n case \"autoroll\":\n case \"auto-roll\": {\n const watch = hasFlag(flags, \"--watch\");\n const dryRun = hasFlag(flags, \"--dry-run\");\n const settings = await getStoredAutoRollSettings().catch(() => null);\n const fallbackThreshold =\n typeof settings?.switchThreshold === \"number\" && Number.isFinite(settings.switchThreshold)\n ? Math.round(settings.switchThreshold)\n : DEFAULT_AUTOROLL_THRESHOLD;\n const threshold = parseAutoRollThreshold(flags, fallbackThreshold);\n const intervalSeconds = parseAutoRollIntervalSeconds(flags);\n\n if (watch) {\n console.log(`Auto-roll watch: threshold ${threshold}% | interval ${intervalSeconds}s${dryRun ? \" | dry-run\" : \"\"}`);\n let stop = false;\n process.on(\"SIGINT\", () => {\n stop = true;\n });\n process.on(\"SIGTERM\", () => {\n stop = true;\n });\n\n while (!stop) {\n const result = await runAutoRollPass(manager, { threshold, dryRun });\n console.log(result.message);\n if (stop) {\n break;\n }\n await delay(intervalSeconds * 1000);\n }\n console.log(\"Auto-roll watch stopped.\");\n return;\n }\n\n const result = await runAutoRollPass(manager, { threshold, dryRun });\n console.log(result.message);\n return;\n }\n case \"delete\": {\n const name = params[1];\n if (!name) {\n throw new Error(\"Profile name is required.\");\n }\n await manager.deleteProfile(name);\n console.log(`Profile deleted: ${name}`);\n return;\n }\n case \"rename\": {\n const from = params[1];\n const to = params[2];\n if (!from || !to) {\n throw new Error(\"Old and new profile names are required.\");\n }\n await manager.renameProfile(from, to);\n console.log(`Profile renamed: ${from} -> ${to}`);\n return;\n }\n default:\n printHelp();\n return;\n }\n}\n\nasync function handleLicense(args: string[]): Promise<void> {\n const flags = args.filter(arg => arg.startsWith(\"-\"));\n const params = stripFlags(args);\n const sub = params[0];\n\n if (!sub || hasFlag(flags, \"--help\") || hasFlag(flags, \"-h\")) {\n printHelp();\n return;\n }\n\n switch (sub) {\n case \"status\": {\n const forceRefresh = hasFlag(flags, \"--refresh\");\n const status = await licenseService.getStatus({ forceRefresh });\n console.log(`Tier: ${status.tier}`);\n console.log(`State: ${status.state}`);\n if (status.profileLimit !== null) {\n console.log(`Profile limit: ${status.profileLimit}`);\n }\n if (status.profilesRemaining !== null) {\n console.log(`Profiles remaining: ${status.profilesRemaining}`);\n }\n if (status.purchaseEmail) {\n console.log(`Email: ${status.purchaseEmail}`);\n }\n if (status.maskedLicenseKey) {\n console.log(`License: ${status.maskedLicenseKey}`);\n }\n if (status.message) {\n console.log(`Message: ${status.message}`);\n }\n if (status.error) {\n console.log(`Error: ${status.error}`);\n }\n return;\n }\n case \"activate\": {\n const key = params[1];\n if (!key) {\n throw new Error(\"License key is required.\");\n }\n const status = await licenseService.activate(key);\n console.log(status.message ?? \"License activated.\");\n return;\n }\n default:\n printHelp();\n return;\n }\n}\n\nfunction printSyncResult(result: Awaited<ReturnType<typeof pushCloudSync>>): void {\n console.log(result.message);\n if (result.localUpdatedAt) {\n console.log(`Local snapshot: ${result.localUpdatedAt}`);\n }\n if (result.remoteUpdatedAt) {\n console.log(`Remote snapshot: ${result.remoteUpdatedAt}`);\n }\n}\n\nasync function handleSync(args: string[]): Promise<void> {\n const flags = args.filter(arg => arg.startsWith(\"-\"));\n const params = stripFlags(args);\n const sub = params[0];\n\n if (!sub || hasFlag(flags, \"--help\") || hasFlag(flags, \"-h\")) {\n printHelp();\n return;\n }\n\n switch (sub) {\n case \"status\": {\n const status = await getCloudSyncStatus();\n console.log(`Endpoint: ${status.endpoint}`);\n console.log(`Can sync: ${status.canSync ? \"yes\" : \"no\"}`);\n console.log(`Has key: ${status.hasLicenseKey ? \"yes\" : \"no\"}`);\n if (status.licenseState) {\n console.log(`License state: ${status.licenseState}`);\n }\n if (status.reason) {\n console.log(`Reason: ${status.reason}`);\n }\n if (status.remoteUpdatedAt) {\n console.log(`Remote snapshot: ${status.remoteUpdatedAt}`);\n }\n if (status.lastPushAt) {\n console.log(`Last push: ${status.lastPushAt}`);\n }\n if (status.lastPullAt) {\n console.log(`Last pull: ${status.lastPullAt}`);\n }\n if (status.lastError) {\n console.log(`Last error: ${status.lastError}`);\n }\n return;\n }\n case \"pull\": {\n const result = await pullCloudSync();\n printSyncResult(result);\n if (result.status === \"error\") {\n process.exitCode = 1;\n }\n return;\n }\n case \"push\": {\n const result = await pushCloudSync();\n printSyncResult(result);\n if (result.status === \"error\") {\n process.exitCode = 1;\n }\n return;\n }\n default:\n printHelp();\n return;\n }\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n\n if (args.length === 0) {\n printHelp();\n return;\n }\n\n if (args[0]?.startsWith(\"-\") && (hasFlag(args, \"--help\") || hasFlag(args, \"-h\"))) {\n printHelp();\n return;\n }\n\n if (args[0]?.startsWith(\"-\") && (hasFlag(args, \"--version\") || hasFlag(args, \"-v\"))) {\n console.log(VERSION);\n return;\n }\n\n const command = args[0];\n const rest = args.slice(1);\n\n switch (command) {\n case \"profile\":\n await ensureCliStorageReady();\n await handleProfile(rest);\n return;\n case \"license\":\n await ensureCliStorageReady();\n await handleLicense(rest);\n return;\n case \"sync\":\n await ensureCliStorageReady();\n await handleSync(rest);\n return;\n case \"daemon\":\n await ensureCliStorageReady();\n await handleDaemonCommand(rest, VERSION);\n return;\n default:\n printHelp();\n return;\n }\n}\n\nmain().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n process.exitCode = 1;\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gBAA+B;AAC/B,kBAAiB;AACjB,IAAAA,eAAqB;AACrB,kBAAiC;;;ACG1B,IAAM,4BAA4B;AAClC,IAAM,sCAAsC;AAC5C,IAAM,qCAAqC;AAC3C,IAAM,wBAAwB;AACrC,IAAM,wBAAwB;AAC9B,IAAM,uBAAuB;AAE7B,SAAS,YAAY,OAAe,KAAa,KAAqB;AACpE,SAAO,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC;AAC3C;AAEA,SAAS,oBAAoB,OAAe,UAA0B;AACpE,SAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;AAC1C;AAEO,SAAS,iCAAiC,OAAuB;AACtE,QAAM,UAAU,oBAAoB,OAAO,mCAAmC;AAC9E,SAAO,YAAY,SAAS,uBAAuB,qBAAqB;AAC1E;AAEO,SAAS,gCACd,OACA,kBACQ;AACR,QAAM,mBAAmB,iCAAiC,gBAAgB;AAC1E,QAAM,UAAU,oBAAoB,OAAO,kCAAkC;AAC7E,SAAO,YAAY,SAAS,mBAAmB,GAAG,oBAAoB;AACxE;AAEO,SAAS,2BACd,kBACA,iBACgE;AAChE,QAAM,mBAAmB,iCAAiC,gBAAgB;AAC1E,QAAM,kBAAkB,gCAAgC,iBAAiB,gBAAgB;AACzF,SAAO;AAAA,IACL,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,EACnB;AACF;AAMO,SAAS,0BACd,KACkB;AAClB,QAAM,UAAU,OAAO,KAAK,YAAY,YAAY,IAAI,UAAU;AAClE,QAAM,aAAa;AAAA,IACjB,OAAO,KAAK,qBAAqB,WAAW,IAAI,mBAAmB;AAAA,IACnE;AAAA,EACF;AACA,QAAM,YAAY;AAAA,IAChB,OAAO,KAAK,oBAAoB,WAAW,IAAI,kBAAkB;AAAA,IACjE;AAAA,EACF;AAGA,QAAM,EAAE,kBAAkB,mBAAmB,iBAAiB,iBAAiB,IAAI;AAAA,IACjF;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,EACnB;AACF;;;AC3EA,qBAA+B;AAC/B,8BAAkC;AAClC,uBAAiB;AACjB,qBAAe;;;ACHR,IAAM,0BAA0B;AAChC,IAAM,sBAAsB;AAC5B,IAAM,sBAAsB;AAG5B,SAAS,yBAAyB,OAAuB;AAC9D,MAAI,CAAC,OAAO,SAAS,KAAK,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,QAAM,UAAU,KAAK,MAAM,KAAK;AAChC,SAAO,KAAK,IAAI,qBAAqB,KAAK,IAAI,qBAAqB,OAAO,CAAC;AAC7E;AAMO,SAAS,oCAAoC,OAA+B;AACjF,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,GAAG;AACvD,WAAO,yBAAyB,KAAK;AAAA,EACvC;AAEA,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,SAAS,OAAO,KAAK;AAC3B,QAAI,OAAO,SAAS,MAAM,GAAG;AAC3B,aAAO,yBAAyB,MAAM;AAAA,IACxC;AAAA,EACF;AAEA,SAAO;AACT;;;AClCO,IAAM,gCAAgC;AAAA;AAAA;AAAA;AAO7C,SAAS,qBAAqB,OAAuB;AACnD,SAAO,MAAM,QAAQ,SAAS,IAAI;AACpC;AAEO,SAAS,6BAA6B,OAAiD;AAC5F,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,aAAa,qBAAqB,KAAK,EAAE,KAAK;AACpD,SAAO,WAAW,SAAS,IAAI,aAAa;AAC9C;;;AFHA,IAAM,iBAAiB;AACvB,IAAM,WAAW;AA0JjB,IAAI,wBAAuC;AAC3C,IAAI,gBAAiC;AACrC,IAAI,YAA2B,QAAQ,QAAQ;AAC/C,IAAM,mBAAmB,IAAI,0CAA2B;AAExD,SAAS,SAAS,OAAkD;AAClE,SAAO,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,MAAS,OAAa;AAC7B,SAAO,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AACzC;AAEA,SAAS,4BAAoC;AAC3C,QAAM,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI,eAAe,eAAAC,QAAG,QAAQ;AACvE,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AAEA,MAAI,QAAQ,aAAa,UAAU;AACjC,WAAO,iBAAAC,QAAK,KAAK,MAAM,WAAW,uBAAuB,QAAQ;AAAA,EACnE;AACA,MAAI,QAAQ,aAAa,SAAS;AAChC,UAAM,UAAU,QAAQ,IAAI;AAC5B,QAAI,SAAS;AACX,aAAO,iBAAAA,QAAK,KAAK,SAAS,QAAQ;AAAA,IACpC;AACA,WAAO,iBAAAA,QAAK,KAAK,MAAM,WAAW,WAAW,QAAQ;AAAA,EACvD;AACA,SAAO,iBAAAA,QAAK,KAAK,MAAM,WAAW,QAAQ;AAC5C;AAEO,SAAS,iBAAyB;AACvC,SAAO,yBAAyB,0BAA0B;AAC5D;AAEA,SAAS,sBAA8B;AACrC,SAAO,iBAAAA,QAAK,KAAK,eAAe,GAAG,cAAc;AACnD;AAEA,SAAS,wBAAkC;AACzC,SAAO;AAAA,IACL,eAAe;AAAA,IACf,UAAU;AAAA,MACR,SAAS;AAAA,MACT,kBAAkB;AAAA,MAClB,iBAAiB;AAAA,IACnB;AAAA,IACA,KAAK;AAAA,MACH,gBAAgB;AAAA,MAChB,sBAAsB;AAAA,MACtB,iBAAiB;AAAA,IACnB;AAAA,IACA,SAAS;AAAA,MACP,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,uBAAuB;AAAA,MACvB,QAAQ;AAAA,MACR,WAAW;AAAA,IACb;AAAA,IACA,WAAW;AAAA,MACT,oBAAoB;AAAA,MACpB,cAAc;AAAA,MACd,wBAAwB;AAAA,MACxB,MAAM,CAAC;AAAA,MACP,iBAAiB,CAAC;AAAA,IACpB;AAAA,IACA,SAAS;AAAA,MACP,aAAa;AAAA,MACb,uBAAuB;AAAA,MACvB,iBAAiB,CAAC;AAAA,IACpB;AAAA,IACA,aAAa;AAAA,MACX,gBAAgB,CAAC;AAAA,MACjB,wBAAwB;AAAA,MACxB,yBAAyB;AAAA,MACzB,4BAA4B;AAAA,MAC5B,4BAA4B;AAAA,MAC5B,oCAAoC;AAAA,MACpC,eAAe,CAAC;AAAA,MAChB,aAAa,CAAC;AAAA,IAChB;AAAA,IACA,iBAAiB,CAAC;AAAA,IAClB,yBAAyB,CAAC;AAAA,IAC1B,6BAA6B,CAAC;AAAA,IAC9B,sCAAsC,CAAC;AAAA,IACvC,KAAK;AAAA,MACH,qBAAqB;AAAA,MACrB,sBAAsB;AAAA,IACxB;AAAA,IACA,QAAQ;AAAA,MACN,mBAAmB;AAAA,MACnB,YAAY;AAAA,MACZ,UAAU;AAAA,IACZ;AAAA,IACA,QAAQ;AAAA,MACN,SAAS,CAAC;AAAA,MACV,gBAAgB,CAAC;AAAA,IACnB;AAAA,IACA,MAAM;AAAA,MACJ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,iBAAiB;AAAA,IACnB;AAAA,IACA,WAAW;AAAA,MACT,WAAW;AAAA,MACX,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW;AAAA,IACb;AAAA,IACA,gBAAgB,CAAC;AAAA,IACjB,WAAW;AAAA,MACT,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,aAAa;AAAA,MACb,wBAAwB;AAAA,MACxB,WAAW;AAAA,IACb;AAAA,EACF;AACF;AAEA,SAAS,SAAS,OAA+B;AAC/C,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAAS,kBAAkB,KAAwB;AACjD,QAAM,WAAW,sBAAsB;AACvC,MAAI,CAAC,SAAS,GAAG,GAAG;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,UAAU,UAAU,GAAoB;AACrD,QAAM,SAAS,MAAM,IAAI;AAEzB,SAAO,gBAAgB;AACvB,MAAI,OAAO,OAAO,SAAS,YAAY,WAAW;AAChD,WAAO,SAAS,UAAU;AAAA,EAC5B;AACA,MAAI,CAAC,OAAO,SAAS,OAAO,SAAS,gBAAgB,GAAG;AACtD,WAAO,SAAS,mBAAmB;AAAA,EACrC;AACA,MAAI,CAAC,OAAO,SAAS,OAAO,SAAS,eAAe,GAAG;AACrD,WAAO,SAAS,kBAAkB;AAAA,EACpC;AACA,MAAI,OAAO,SAAS,mBAAmB,MAAM,OAAO,SAAS,mBAAmB,IAAI;AAClF,WAAO,SAAS,mBAAmB;AAAA,EACrC;AACA,MAAI,OAAO,SAAS,mBAAmB,OAAO,SAAS,oBAAoB,OAAO,SAAS,kBAAkB,KAAK;AAChH,WAAO,SAAS,kBAAkB,KAAK,IAAI,KAAK,KAAK,IAAI,OAAO,SAAS,mBAAmB,GAAG,EAAE,CAAC;AAAA,EACpG;AACA,SAAO,IAAI,iBAAiB,SAAS,OAAO,IAAI,cAAc;AAC9D,SAAO,IAAI,uBAAuB,SAAS,OAAO,IAAI,oBAAoB;AAC1E,SAAO,IAAI,kBAAkB,SAAS,OAAO,IAAI,eAAe;AAChE;AACE,UAAM,iBAAiB,IAAI,IAAI,OAAO,KAAK,SAAS,GAAG,CAAC;AACxD,eAAW,OAAO,OAAO,KAAK,OAAO,GAA8B,GAAG;AACpE,UAAI,CAAC,eAAe,IAAI,GAAG,GAAG;AAC5B,eAAQ,OAAO,IAAgC,GAAG;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AAEA,SAAO,QAAQ,aAAa,SAAS,OAAO,QAAQ,UAAU;AAC9D,SAAO,QAAQ,gBAAgB,SAAS,OAAO,QAAQ,aAAa;AACpE,SAAO,QAAQ,iBAAiB,SAAS,OAAO,QAAQ,cAAc;AACtE,SAAO,QAAQ,cAAc,SAAS,OAAO,QAAQ,WAAW;AAChE,SAAO,QAAQ,wBAAwB,SAAS,OAAO,QAAQ,qBAAqB;AACpF,SAAO,QAAQ,YAAY,SAAS,OAAO,QAAQ,SAAS;AAC5D,MAAI,CAAC,CAAC,YAAY,UAAU,SAAS,OAAO,EAAE,SAAS,OAAO,QAAQ,MAAM,GAAG;AAC7E,WAAO,QAAQ,SAAS;AAAA,EAC1B;AAEA,MAAI,CAAC,MAAM,QAAQ,OAAO,UAAU,IAAI,GAAG;AACzC,WAAO,UAAU,OAAO,CAAC;AAAA,EAC3B;AACA,SAAO,UAAU,qBAAqB,SAAS,OAAO,UAAU,kBAAkB,KAAK;AACvF,SAAO,UAAU,eAAe,SAAS,OAAO,UAAU,YAAY;AACtE,MAAI,CAAC,CAAC,WAAW,OAAO,UAAU,QAAQ,SAAS,MAAM,EAAE,SAAS,OAAO,UAAU,sBAAsB,GAAG;AAC5G,WAAO,UAAU,yBAAyB;AAAA,EAC5C;AAEA,MAAI,CAAC,SAAS,OAAO,UAAU,eAAe,GAAG;AAC/C,WAAO,UAAU,kBAAkB,CAAC;AAAA,EACtC;AACA,MAAI,CAAC,SAAS,OAAO,QAAQ,eAAe,GAAG;AAC7C,WAAO,QAAQ,kBAAkB,CAAC;AAAA,EACpC;AAEA,MAAI,CAAC,MAAM,QAAQ,OAAO,YAAY,cAAc,GAAG;AACrD,WAAO,YAAY,iBAAiB,CAAC;AAAA,EACvC;AACA,MAAI,OAAO,OAAO,YAAY,2BAA2B,WAAW;AAClE,WAAO,YAAY,yBAAyB;AAAA,EAC9C;AACA,MAAI,OAAO,OAAO,YAAY,4BAA4B,WAAW;AACnE,WAAO,YAAY,0BAA0B;AAAA,EAC/C;AACA,SAAO,YAAY,6BAA6B;AAAA,IAC9C,OAAO,YAAY;AAAA,EACrB;AACA,MAAI,OAAO,OAAO,YAAY,+BAA+B,WAAW;AACtE,WAAO,YAAY,6BAA6B;AAAA,EAClD;AACA,MAAI,OAAO,OAAO,YAAY,uCAAuC,WAAW;AAC9E,WAAO,YAAY,qCAAqC;AAAA,EAC1D;AACA,MAAI,CAAC,MAAM,QAAQ,OAAO,YAAY,aAAa,GAAG;AACpD,WAAO,YAAY,gBAAgB,CAAC;AAAA,EACtC;AACA,MAAI,CAAC,MAAM,QAAQ,OAAO,YAAY,WAAW,GAAG;AAClD,WAAO,YAAY,cAAc,CAAC;AAAA,EACpC;AACA;AACE,UAAM,wBAAwB,IAAI,IAAI,OAAO,KAAK,SAAS,WAAW,CAAC;AACvE,eAAW,OAAO,OAAO,KAAK,OAAO,WAAsC,GAAG;AAC5E,UAAI,CAAC,sBAAsB,IAAI,GAAG,GAAG;AACnC,eAAQ,OAAO,YAAwC,GAAG;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,OAAO,eAAe,GAAG;AACrC,WAAO,kBAAkB,CAAC;AAAA,EAC5B;AAEA,QAAM,8BAA8B;AAAA,IACjC,IAAgC;AAAA,EACnC,IACM,IACC,wBACH;AACJ,MAAI,CAAC,SAAS,OAAO,uBAAuB,GAAG;AAC7C,WAAO,0BAA0B,CAAC;AAAA,EACpC;AACA,MAAI,6BAA6B;AAC/B,WAAO,0BAA0B;AAAA,MAC/B,GAAG;AAAA,MACH,GAAG,OAAO;AAAA,IACZ;AAAA,EACF;AACA,SAAQ,OAAmC;AAC3C,MAAI,CAAC,SAAS,OAAO,2BAA2B,GAAG;AACjD,WAAO,8BAA8B,CAAC;AAAA,EACxC;AACA,MAAI,CAAC,SAAS,OAAO,oCAAoC,GAAG;AAC1D,WAAO,uCAAuC,CAAC;AAAA,EACjD;AACA,MAAI,CAAC,SAAS,OAAO,GAAG,GAAG;AACzB,WAAO,MAAM,MAAM,SAAS,GAAG;AAAA,EACjC;AACA,SAAO,IAAI,sBACT,6BAA6B,OAAO,IAAI,mBAAmB,KAC3D;AACF,SAAO,IAAI,uBAAuB,SAAS,OAAO,IAAI,oBAAoB;AAE1E,MAAI,CAAC,SAAS,OAAO,MAAM,GAAG;AAC5B,WAAO,SAAS,MAAM,SAAS,MAAM;AAAA,EACvC;AACA,MAAI,OAAO,OAAO,OAAO,sBAAsB,WAAW;AACxD,WAAO,OAAO,oBAAoB,SAAS,OAAO;AAAA,EACpD;AACA,MAAI,CAAC,OAAO,SAAS,OAAO,OAAO,UAAU,GAAG;AAC9C,WAAO,OAAO,aAAa,SAAS,OAAO;AAAA,EAC7C;AACA,SAAO,OAAO,aAAa,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,MAAM,OAAO,OAAO,UAAU,CAAC,CAAC;AACzF,MAAI,CAAC,OAAO,SAAS,OAAO,OAAO,QAAQ,GAAG;AAC5C,WAAO,OAAO,WAAW,SAAS,OAAO;AAAA,EAC3C;AACA,SAAO,OAAO,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,OAAO,QAAQ,CAAC,CAAC;AAEpF,MAAI,CAAC,SAAS,OAAO,MAAM,GAAG;AAC5B,WAAO,SAAS,MAAM,SAAS,MAAM;AAAA,EACvC;AACA,MAAI,CAAC,MAAM,QAAQ,OAAO,OAAO,OAAO,GAAG;AACzC,WAAO,OAAO,UAAU,CAAC;AAAA,EAC3B;AACA,MAAI,CAAC,SAAS,OAAO,OAAO,cAAc,GAAG;AAC3C,WAAO,OAAO,iBAAiB,CAAC;AAAA,EAClC;AAEA,MAAI,CAAC,SAAS,OAAO,IAAI,GAAG;AAC1B,WAAO,OAAO,MAAM,SAAS,IAAI;AAAA,EACnC;AACA,SAAO,KAAK,aAAa,SAAS,OAAO,KAAK,UAAU;AACxD,SAAO,KAAK,aAAa,SAAS,OAAO,KAAK,UAAU;AACxD,SAAO,KAAK,YAAY,SAAS,OAAO,KAAK,SAAS;AACtD,SAAO,KAAK,kBAAkB,SAAS,OAAO,KAAK,eAAe;AAElE,MAAI,CAAC,SAAS,OAAO,SAAS,GAAG;AAC/B,WAAO,YAAY,MAAM,SAAS,SAAS;AAAA,EAC7C;AACA,SAAO,UAAU,YAAY,SAAS,OAAO,UAAU,SAAS;AAChE,MAAI,OAAO,OAAO,UAAU,YAAY,WAAW;AACjD,WAAO,UAAU,UAAU;AAAA,EAC7B;AACA,SAAO,UAAU,cAAc,SAAS,OAAO,UAAU,WAAW;AACpE,SAAO,UAAU,YAAY,SAAS,OAAO,UAAU,SAAS;AAEhE,MAAI,CAAC,SAAS,OAAO,cAAc,GAAG;AACpC,WAAO,iBAAiB,CAAC;AAAA,EAC3B;AAEA,MAAI,CAAC,SAAS,OAAO,SAAS,GAAG;AAC/B,WAAO,YAAY,MAAM,SAAS,SAAS;AAAA,EAC7C;AACA,MAAI,CAAC,CAAC,WAAW,yBAAyB,UAAU,EAAE,SAAS,OAAO,UAAU,MAAM,GAAG;AACvF,WAAO,UAAU,SAAS;AAAA,EAC5B;AACA,SAAO,UAAU,YAAY,SAAS,OAAO,UAAU,SAAS;AAChE,SAAO,UAAU,cAAc,SAAS,OAAO,UAAU,WAAW;AACpE,SAAO,UAAU,yBAAyB,SAAS,OAAO,UAAU,sBAAsB;AAC1F,SAAO,UAAU,YAAY,SAAS,OAAO,UAAU,SAAS;AAEhE,SAAO;AACT;AAEA,SAAS,UAAa,MAAS,OAA0B;AACvD,MAAI,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,KAAK,GAAG;AACvC,WAAO,MAAO,SAAe,IAAI;AAAA,EACnC;AAEA,QAAM,OAAgC,EAAE,GAAI,KAAiC;AAC7E,aAAW,CAAC,KAAK,UAAU,KAAK,OAAO,QAAQ,KAAK,GAAG;AACrD,QAAI,eAAe,QAAW;AAC5B;AAAA,IACF;AAEA,UAAM,eAAe,KAAK,GAAG;AAC7B,QAAI,MAAM,QAAQ,UAAU,GAAG;AAC7B,WAAK,GAAG,IAAI,MAAM,UAAU;AAC5B;AAAA,IACF;AAEA,QAAI,SAAS,YAAY,KAAK,SAAS,UAAU,GAAG;AAClD,WAAK,GAAG,IAAI,UAAU,cAAc,UAA8C;AAClF;AAAA,IACF;AAEA,SAAK,GAAG,IAAI,MAAM,UAAU;AAAA,EAC9B;AAEA,SAAO;AACT;AAEA,eAAe,YAAY,UAAkB,UAAiC;AAC5E,QAAM,MAAM,iBAAAA,QAAK,QAAQ,QAAQ;AACjC,QAAM,OAAO,iBAAAA,QAAK,SAAS,QAAQ;AACnC,QAAM,QAAQ,GAAG,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AACjF,QAAM,WAAW,iBAAAA,QAAK,KAAK,KAAK,GAAG,IAAI,IAAI,KAAK,MAAM;AAEtD,QAAM,eAAAC,SAAG,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACvC,QAAM,eAAAA,SAAG,UAAU,UAAU,UAAU,MAAM;AAC7C,MAAI;AACF,UAAM,eAAAA,SAAG,OAAO,UAAU,QAAQ;AAAA,EACpC,UAAE;AACA,UAAM,eAAAA,SAAG,GAAG,UAAU,EAAE,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,EAC9D;AACF;AAEA,eAAe,oBAAoB,OAAgC;AACjE,QAAM,WAAW,oBAAoB;AACrC,QAAM,YAAY,UAAU,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,CAAI;AACnE;AAEA,eAAe,uBAAiD;AAC9D,QAAM,WAAW,oBAAoB;AACrC,MAAI;AACF,UAAM,MAAM,MAAM,eAAAA,SAAG,SAAS,UAAU,MAAM;AAC9C,WAAO,kBAAkB,KAAK,MAAM,GAAG,CAAY;AAAA,EACrD,SAAS,OAAO;AACd,UAAM,OAAQ,MAAgC;AAC9C,QAAI,SAAS,UAAU;AACrB,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAe,oBAAuC;AACpD,MAAI,eAAe;AACjB,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,oBAAoB;AACrC,QAAM,eAAAA,SAAG,MAAM,iBAAAD,QAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAE1D,QAAM,SAAS,MAAM,qBAAqB;AAC1C,QAAM,aAAa,UAAU,kBAAkB,IAAI;AACnD,kBAAgB;AAEhB,MAAI,WAAW,MAAM;AACnB,UAAM,oBAAoB,UAAU;AAAA,EACtC;AAEA,SAAO;AACT;AAEA,eAAe,cAAiB,MAAoC;AAClE,MAAI,iBAAiB,SAAS,GAAG;AAC/B,WAAO,KAAK;AAAA,EACd;AAEA,QAAM,WAAW;AACjB,MAAI;AACJ,cAAY,IAAI,QAAc,aAAW;AACvC,cAAU;AAAA,EACZ,CAAC;AAED,QAAM;AACN,MAAI;AACF,WAAO,MAAM,iBAAiB,IAAI,MAAM,IAAI;AAAA,EAC9C,UAAE;AACA,QAAI,SAAS;AACX,cAAQ;AAAA,IACV;AAAA,EACF;AACF;AAEA,eAAsB,mBAAmB,aAAwC;AAC/E,0BAAwB;AACxB,QAAM,QAAQ,MAAM,kBAAkB;AACtC,SAAO,MAAM,KAAK;AACpB;AAEA,eAAsB,cAAiC;AACrD,QAAM,QAAQ,MAAM,kBAAkB;AACtC,SAAO,MAAM,KAAK;AACpB;AAEA,eAAsB,eACpB,WACA,UAAiC,CAAC,GACf;AACnB,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,+BAA+B,QAAQ,iCAAiC;AAE9E,SAAO,cAAc,YAAY;AAC/B,UAAM,UAAW,MAAM,qBAAqB,KAAO,MAAM,kBAAkB;AAC3E,oBAAgB;AAChB,QAAI,CAAC,gCAAgC,QAAQ,UAAU,WAAW,YAAY;AAC5E,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AAEA,UAAM,cAAc,UAAU,MAAM,OAAO,CAAC;AAC5C,UAAM,YAAY,SAAS,YACvB,kBAAkB,WAAW,IAC7B,kBAAkB,UAAU,SAAS,WAA4B,CAAC;AACtE,UAAM,oBAAoB,SAAS;AACnC,oBAAgB;AAChB,WAAO,MAAM,SAAS;AAAA,EACxB,CAAC;AACH;AAEA,eAAsB,cAAc,OAAyC;AAC3E,SAAO,eAAe,MAAM,OAAO;AAAA,IACjC,MAAM;AAAA,IACN,8BAA8B;AAAA,EAChC,CAAC;AACH;;;AG3kBA,SAASE,UAAS,OAA+B;AAC/C,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAASC,UAAS,OAAkD;AAClE,SAAO,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,mBAAmB,KAAqC;AAC/D,MAAI,CAACA,UAAS,GAAG,GAAG;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,kBAAkBD,UAAS,IAAI,MAAM;AAC3C,QAAM,SAAS,CAAC,YAAY,UAAU,SAAS,OAAO,EAAE,SAAS,mBAAmB,EAAE,IACjF,kBACD;AAEJ,QAAM,UAAyB;AAAA,IAC7B,YAAYA,UAAS,IAAI,cAAc,IAAI,WAAW;AAAA,IACtD,eAAeA,UAAS,IAAI,iBAAiB,IAAI,cAAc;AAAA,IAC/D,gBAAgBA,UAAS,IAAI,kBAAkB,IAAI,gBAAgB;AAAA,IACnE,aAAaA,UAAS,IAAI,eAAe,IAAI,aAAa;AAAA,IAC1D,uBAAuBA,UAAS,IAAI,yBAAyB,IAAI,uBAAuB;AAAA,IACxF;AAAA,IACA,WAAWA,UAAS,IAAI,SAAS;AAAA,EACnC;AAEA,QAAM,WAAW;AAAA,IACf,QAAQ,cACN,QAAQ,iBACR,QAAQ,kBACR,QAAQ,eACR,QAAQ,yBACR,QAAQ;AAAA,EACZ;AAEA,SAAO,WAAW,UAAU;AAC9B;AAEA,SAAS,cAAc,KAAuC;AAC5D,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,0BAA0B,GAAgC;AAAA,EACnE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AA6CA,eAAsB,qBAA6C;AACjE,QAAM,QAAQ,MAAM,YAAY;AAChC,SAAOE,UAAS,MAAM,IAAI,eAAe;AAC3C;AAEA,eAAsB,uBAAuB,aAA2C;AACtF,QAAM,cAAc;AAAA,IAClB,KAAK;AAAA,MACH,iBAAiBA,UAAS,WAAW;AAAA,IACvC;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,mBAAkD;AACtE,QAAM,QAAQ,MAAM,YAAY;AAChC,SAAO,mBAAmB,MAAM,OAAO;AACzC;AAEA,eAAsB,eAAe,SAA8C;AACjF,QAAM,SAAS,mBAAmB,OAAO;AACzC,QAAM,cAAc;AAAA,IAClB,SAAS,SACL;AAAA,MACE,YAAY,OAAO,cAAc;AAAA,MACjC,eAAe,OAAO,iBAAiB;AAAA,MACvC,gBAAgB,OAAO,kBAAkB;AAAA,MACzC,aAAa,OAAO,eAAe;AAAA,MACnC,uBAAuB,OAAO,yBAAyB;AAAA,MACvD,QAAQ,OAAO,UAAU;AAAA,MACzB,WAAW,OAAO,aAAa;AAAA,IACjC,IACA;AAAA,MACE,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,uBAAuB;AAAA,MACvB,QAAQ;AAAA,MACR,WAAW;AAAA,IACb;AAAA,EACN,CAAC;AACH;AAEA,eAAsB,4BAA8D;AAClF,QAAM,QAAQ,MAAM,YAAY;AAChC,SAAO,0BAA0B,MAAM,QAAQ;AACjD;AAuCA,eAAsB,2BAA6D;AACjF,QAAM,QAAQ,MAAM,YAAY;AAChC,SAAO;AAAA,IACL,iBAAiB,MAAM,IAAI;AAAA,IAC3B,gBAAgB,MAAM,IAAI;AAAA,IAC1B,sBAAsB,MAAM,IAAI;AAAA,IAChC,UAAU,MAAM;AAAA,IAChB,SAAS,MAAM;AAAA,IACf,WAAW,MAAM,UAAU;AAAA,IAC3B,oBAAoB,MAAM,UAAU;AAAA,IACpC,cAAc,MAAM,UAAU;AAAA,IAC9B,wBAAwB,MAAM,UAAU;AAAA,IACxC,iBAAiB,MAAM,UAAU;AAAA,IACjC,MAAM,MAAM,QAAQ;AAAA,IACpB,gBAAgB,MAAM,QAAQ;AAAA,IAC9B,wBAAwB,MAAM,QAAQ;AAAA,IACtC,gBAAgB,MAAM,YAAY;AAAA,IAClC,wBAAwB,MAAM,YAAY;AAAA,IAC1C,yBAAyB,MAAM,YAAY;AAAA,IAC3C,4BAA4B,MAAM,YAAY;AAAA,IAC9C,oCACE,MAAM,YAAY;AAAA,IACpB,eAAe,MAAM,YAAY;AAAA,IACjC,aAAa,MAAM,YAAY;AAAA,IAC/B,yBAAyB,MAAM;AAAA;AAAA,IAE/B,uBAAuB,MAAM;AAAA,IAC7B,iBAAiB,MAAM;AAAA,IACvB,2BAA2B,MAAM;AAAA,IACjC,KAAK,MAAM;AAAA,IACX,QAAQ,MAAM;AAAA,IACd,MAAM,MAAM;AAAA,EACd;AACF;AAEA,eAAsB,0BAA0B,SAAoE;AAClH,MAAI,CAACC,UAAS,OAAO,GAAG;AACtB;AAAA,EACF;AAEA,QAAM,WAAW,cAAc,QAAQ,YAAY,QAAQ,SAAS;AACpE,QAAM,UAAU,mBAAmB,QAAQ,OAAO;AAElD,QAAM,cAAc;AAAA,IAClB,KAAK;AAAA,MACH,iBAAiBC,UAAS,QAAQ,mBAAmB,QAAQ,iBAAiB;AAAA,MAC9E,gBAAgBA,UAAS,QAAQ,kBAAkB,QAAQ,gBAAgB;AAAA,MAC3E,sBAAsBA,UAAS,QAAQ,wBAAwB,QAAQ,sBAAsB;AAAA,IAC/F;AAAA,IACA,UAAU,WACN;AAAA,MACE,SAAS,SAAS;AAAA,MAClB,kBAAkB,SAAS;AAAA,MAC3B,iBAAiB,SAAS;AAAA,IAC5B,IACA;AAAA,IACJ,SAAS,UACL;AAAA,MACE,YAAY,QAAQ,cAAc;AAAA,MAClC,eAAe,QAAQ,iBAAiB;AAAA,MACxC,gBAAgB,QAAQ,kBAAkB;AAAA,MAC1C,aAAa,QAAQ,eAAe;AAAA,MACpC,uBAAuB,QAAQ,yBAAyB;AAAA,MACxD,QAAQ,QAAQ,UAAU;AAAA,MAC1B,WAAW,QAAQ,aAAa;AAAA,IAClC,IACA;AAAA,IACJ,WAAW;AAAA,MACT,MAAM,MAAM,QAAQ,QAAQ,SAAS,IAChC,QAAQ,YACT;AAAA,MACJ,oBAAoBA,UAAS,QAAQ,kBAAkB,KAAK;AAAA,MAC5D,cAAcA,UAAS,QAAQ,gBAAgB,QAAQ,aAAa;AAAA,MACpE,wBACE,OAAO,QAAQ,2BAA2B,WACrC,QAAQ,yBACT,OAAO,QAAQ,oBAAoB,WAChC,QAAQ,kBACT;AAAA,MACR,iBACED,UAAS,QAAQ,eAAe,IAAK,QAAQ,kBAA+D;AAAA,IAChH;AAAA,IACA,SAAS;AAAA,MACP,aAAaC,UAAS,QAAQ,QAAQ,QAAQ,WAAW,KAAK;AAAA,MAC9D,uBACEA,UAAS,QAAQ,kBAAkB,QAAQ,qBAAqB,KAAK;AAAA,MACvE,iBACED,UAAS,QAAQ,sBAAsB,IAClC,QAAQ,yBACT;AAAA,IACR;AAAA,IACA,aAAa;AAAA,MACX,gBAAgB,MAAM,QAAQ,QAAQ,cAAc,IAC/C,QAAQ,iBACT;AAAA,MACJ,wBACE,OAAO,QAAQ,2BAA2B,YACtC,QAAQ,yBACR;AAAA,MACN,yBACE,OAAO,QAAQ,4BAA4B,YACvC,QAAQ,0BACR;AAAA,MACN,4BACE,OAAO,QAAQ,+BAA+B,YAC1C,QAAQ,6BACR;AAAA,MACN,oCACE,OAAO,QAAQ,uCAAuC,YAClD,QAAQ,qCACR;AAAA,MACN,eAAe,MAAM,QAAQ,QAAQ,aAAa,IAC7C,QAAQ,gBACT;AAAA,MACJ,aAAa,MAAM,QAAQ,QAAQ,WAAW,IACzC,QAAQ,cACT;AAAA,IACN;AAAA,IACA,yBAAyBA,UAAS,QAAQ,uBAAuB,IAC5D,QAAQ,0BACTA,UAAS,QAAQ,qBAAqB,IACnC,QAAQ,wBACT;AAAA,IACN,6BAA6BA,UAAS,QAAQ,eAAe,IACxD,QAAQ,kBACT;AAAA,IACJ,sCAAsCA,UAAS,QAAQ,yBAAyB,IAC3E,QAAQ,4BACT;AAAA,IACJ,KAAKA,UAAS,QAAQ,GAAG,IACpB,QAAQ,MACT;AAAA,IACJ,QAAQA,UAAS,QAAQ,MAAM,IAC1B,QAAQ,SACT;AAAA,IACJ,MAAMA,UAAS,QAAQ,IAAI,IAAK,QAAQ,OAA4B;AAAA,EACtE,CAAC;AACH;;;AC/WA,IAAM,YACJ,QAAQ,IAAI,aAAa,UACzB,QAAQ,IAAI,WAAW,UACvB,QAAQ,IAAI,WAAW;AAEzB,SAAS,SAAS,IAAsB;AACtC,SAAO,QAAQ,MAAM,OAAO,OAAO,cAAc,UAAW,EAA8B;AAC5F;AAEO,SAAS,WAAW,MAA6C;AACtE,MAAI,aAAa,CAAC,SAAS,QAAQ,IAAI,GAAG;AACxC;AAAA,EACF;AACA,UAAQ,KAAK,GAAG,IAAI;AACtB;AAEO,SAAS,YAAY,MAA8C;AACxE,MAAI,aAAa,CAAC,SAAS,QAAQ,KAAK,GAAG;AACzC;AAAA,EACF;AACA,UAAQ,MAAM,GAAG,IAAI;AACvB;AAEO,SAAS,WAAW,MAA6C;AACtE,MAAI,aAAa,CAAC,SAAS,QAAQ,IAAI,GAAG;AACxC;AAAA,EACF;AACA,UAAQ,KAAK,GAAG,IAAI;AACtB;;;ANRA,IAAM,gCAAgC,KAAK,KAAK;AACzC,IAAM,iCAAiC;AACvC,IAAM,gCACX;AACF,IAAM,6BAA6B;AACnC,IAAM,uBAAuB;AAC7B,IAAI,qBAAoC,QAAQ,QAAQ;AAqCjD,IAAM,iBAAN,MAAqB;AAAA,EAM1B,cAAc;AACZ,UAAM,UAAU,QAAQ,IAAI,QAAQ,QAAQ,IAAI,eAAe;AAC/D,SAAK,eAAW,mBAAK,SAAS,QAAQ;AACtC,SAAK,uBAAmB,mBAAK,eAAe,GAAG,eAAe;AAC9D,SAAK,iBAAa,mBAAK,KAAK,UAAU,WAAW;AACjD,SAAK,mBAAmB,GAAG,KAAK,UAAU;AAC1C,SAAK,+BAA+B;AAAA,EACtC;AAAA,EAEQ,iBAAiB,MAA0D;AACjF,QAAI,CAAC,MAAM;AACT,aAAO;AAAA,IACT;AACA,QAAI,OAAO,KAAK,YAAY,YAAY,KAAK,QAAQ,KAAK,GAAG;AAC3D,YAAM,SAAS,KAAK,MAAM,KAAK,OAAO;AACtC,UAAI,CAAC,OAAO,MAAM,MAAM,GAAG;AACzB,eAAO,IAAI,KAAK,MAAM,EAAE,YAAY;AAAA,MACtC;AAAA,IACF;AACA,UAAM,YAAY,OAAO,KAAK,eAAe,YAAY,OAAO,SAAS,KAAK,UAAU,IACpF,KAAK,aACL;AACJ,UAAM,WACJ,OAAO,KAAK,cAAc,YAAY,OAAO,SAAS,KAAK,SAAS,IAChE,KAAK,YACL;AACN,UAAM,WAAW,WAAW,WAAW;AACvC,UAAM,SAAS,YAAY,KAAK,IAAI;AACpC,QAAI,aAAa,YAAY,GAAG;AAC9B,aAAO,IAAI,KAAK,SAAS,YAAY,GAAI,EAAE,YAAY;AAAA,IACzD;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,qBAAqB,MAAsB;AACjD,QAAI,OAAO,SAAS,UAAU;AAC5B,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAEA,QAAI,YAAY,OAAO,YAAY,MAAM;AACvC,YAAM,IAAI,MAAM,iBAAiB,IAAI,mBAAmB;AAAA,IAC1D;AAEA,QAAI,QAAQ,KAAK,OAAO,GAAG;AACzB,YAAM,IAAI,MAAM,8CAA8C;AAAA,IAChE;AAEA,QAAI,QAAQ,SAAS,IAAI,GAAG;AAC1B,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,OAAyB;AAC/C,WAAO;AAAA,MACL,SACE,OAAO,UAAU,YACjB,UAAU,SACT,MAAgC,SAAS;AAAA,IAC9C;AAAA,EACF;AAAA,EAEA,MAAc,2BAAmD;AAC/D,QAAI;AACF,aAAO,MAAM,mBAAmB;AAAA,IAClC,SAAS,OAAO;AACd,cAAQ,0CAA0C,KAAK;AACvD,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,4BAA4B,MAAoC;AAC5E,QAAI;AACF,YAAM,uBAAuB,IAAI;AAAA,IACnC,SAAS,OAAO;AACd,cAAQ,6CAA6C,KAAK;AAAA,IAC5D;AAAA,EACF;AAAA,EAEQ,cAAc,QAA2C;AAC/D,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,MACb,aAAa,OAAO,eAAe;AAAA,MACnC,MAAM,OAAO;AAAA,MACb,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO,aAAa;AAAA,MAC/B,aAAa,OAAO,eAAe;AAAA,MACnC,eAAe,OAAO,iBAAiB;AAAA,MACvC,OAAO,OAAO,SAAS;AAAA,MACvB,YAAY,OAAO,cAAc;AAAA,MACjC,WAAW,OAAO,aAAa;AAAA,MAC/B,WAAW,OAAO,aAAa;AAAA,IACjC;AAAA,EACF;AAAA,EAEQ,gBAAgB,aAAqB,KAA+C;AAC1F,QAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,IAAI;AACpB,QAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa,OAAO,IAAI,gBAAgB,WAAW,IAAI,cAAc;AAAA,MACrE,MAAM;AAAA,MACN,UAAU,IAAI;AAAA,MACd,WAAW,OAAO,IAAI,cAAc,WAAW,IAAI,YAAY;AAAA,MAC/D,aAAa,OAAO,IAAI,gBAAgB,WAAW,IAAI,cAAc;AAAA,MACrE,eAAe,OAAO,IAAI,kBAAkB,WAAW,IAAI,gBAAgB;AAAA,MAC3E,OAAO,OAAO,IAAI,UAAU,WAAW,IAAI,QAAQ;AAAA,MACnD,YAAY,OAAO,IAAI,eAAe,WAAW,IAAI,aAAa;AAAA,MAClE,WAAW,OAAO,IAAI,cAAc,WAAW,IAAI,YAAY;AAAA,MAC/D,WAAW,OAAO,IAAI,cAAc,WAAW,IAAI,YAAY;AAAA,IACjE;AAAA,EACF;AAAA,EAEA,MAAc,uBAAoE;AAChF,UAAM,QAAQ,MAAM,YAAY;AAChC,WAAO,EAAE,GAAI,MAAM,kBAAkB,CAAC,EAAG;AAAA,EAC3C;AAAA,EAEA,MAAc,sBAAsB,SAA4D;AAC9F,UAAM,eAAe,CAAC,WAAW;AAAA,MAC/B,GAAG;AAAA,MACH,gBAAgB;AAAA,IAClB,IAAI,EAAE,MAAM,UAAU,CAAC;AAAA,EACzB;AAAA,EAEA,MAAc,kBAAkB,aAAoD;AAClF,UAAM,MAAM,MAAM,KAAK,qBAAqB;AAC5C,UAAM,MAAM,IAAI,WAAW;AAC3B,QAAI,CAAC,KAAK;AACR,aAAO;AAAA,IACT;AACA,WAAO,KAAK,gBAAgB,aAAa,GAAG;AAAA,EAC9C;AAAA,EAEA,MAAc,qBAA+C;AAC3D,UAAM,MAAM,MAAM,KAAK,qBAAqB;AAC5C,UAAM,UAA2B,CAAC;AAClC,eAAW,CAAC,aAAa,GAAG,KAAK,OAAO,QAAQ,GAAG,GAAG;AACpD,YAAM,SAAS,KAAK,gBAAgB,aAAa,GAAG;AACpD,UAAI,QAAQ;AACV,gBAAQ,KAAK,MAAM;AAAA,MACrB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,mBAAmB,QAAsC;AACrE,UAAM,MAAM,MAAM,KAAK,qBAAqB;AAC5C,QAAI,OAAO,IAAI,IAAI,KAAK,cAAc,MAAM;AAC5C,UAAM,KAAK,sBAAsB,GAAG;AAAA,EACtC;AAAA,EAEA,MAAc,oBAAoB,MAA6B;AAC7D,UAAM,MAAM,MAAM,KAAK,qBAAqB;AAC5C,QAAI,CAAC,OAAO,UAAU,eAAe,KAAK,KAAK,IAAI,GAAG;AACpD;AAAA,IACF;AACA,WAAO,IAAI,IAAI;AACf,UAAM,KAAK,sBAAsB,GAAG;AAAA,EACtC;AAAA,EAEQ,kBAAkB,MAA8C;AACtE,UAAM,MAAM,OAAO,MAAM,gBAAgB,WAAW,KAAK,YAAY,KAAK,EAAE,YAAY,IAAI;AAC5F,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAc,qBAAiD;AAC7D,QAAI;AACF,YAAM,MAAM,MAAM,UAAAE,SAAG,SAAS,KAAK,YAAY,MAAM;AACrD,YAAM,UAAU,IAAI,KAAK;AACzB,UAAI,CAAC,SAAS;AACZ,eAAO;AAAA,MACT;AACA,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B,SAAS,OAAO;AACd,UAAI,KAAK,gBAAgB,KAAK,GAAG;AAC/B,eAAO;AAAA,MACT;AACA,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,YAAM,YAAY,OAAO,YAAY,WAAW,GAAG,OAAO,IAAI,KAAK,UAAU,KAAK,KAAK;AACvF,UAAI,KAAK,iCAAiC,WAAW;AACnD,gBAAQ,oCAAoC,KAAK;AACjD,aAAK,+BAA+B;AAAA,MACtC;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,yBAAsD;AAClE,UAAM,aAAa,MAAM,KAAK,mBAAmB;AACjD,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AACA,WAAO,KAAK,qBAAqB,UAAU;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,OAAuD;AAC9E,QAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,MAAM,MAAM,GAAG;AAChC,QAAI,SAAS,SAAS,GAAG;AACvB,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,UAAU,OAAO,KAAK,SAAS,CAAC,GAAG,WAAW,EAAE,SAAS,MAAM;AACrE,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,uBAAuB,SAAsC;AACnE,QAAI,OAAO,YAAY,YAAY,OAAO,MAAM,OAAO,GAAG;AACxD,aAAO;AAAA,IACT;AAEA,QAAI;AACF,aAAO,IAAI,KAAK,UAAU,GAAI,EAAE,YAAY;AAAA,IAC9C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,wBAAwB,OAAoC;AAClE,QAAI,OAAO,UAAU,UAAU;AAC7B,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,CAAC,WAAW,QAAQ,SAAS,GAAG,GAAG;AACrC,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,QAAQ,QAAQ,GAAG;AACnC,QAAI,WAAW,KAAK,YAAY,QAAQ,SAAS,GAAG;AAClD,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,QAAQ,MAAM,UAAU,CAAC;AACxC,QAAI,CAAC,UAAU,CAAC,OAAO,SAAS,GAAG,GAAG;AACpC,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAe,YAA2D;AAChF,eAAW,aAAa,YAAY;AAClC,YAAM,aAAa,KAAK,wBAAwB,SAAS;AACzD,UAAI,YAAY;AACd,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAkB,OAAgB,OAAO,oBAAI,IAAa,GAAuB;AACvF,QAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,IAAI,KAAK,GAAG;AACnB,aAAO;AAAA,IACT;AACA,SAAK,IAAI,KAAK;AAEd,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,iBAAW,SAAS,OAAO;AACzB,cAAM,SAAS,KAAK,kBAAkB,OAAO,IAAI;AACjD,YAAI,QAAQ;AACV,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAgC,GAAG;AAC3E,UAAI,OAAO,UAAU,UAAU;AAC7B,cAAM,aAAa,KAAK,wBAAwB,KAAK;AACrD,cAAM,WAAW,IAAI,YAAY;AACjC,cAAM,kBACJ,SAAS,SAAS,OAAO,KACzB,SAAS,SAAS,SAAS,KAC3B,SAAS,SAAS,UAAU,KAC5B,SAAS,SAAS,OAAO;AAE3B,YAAI,eAAe,mBAAmB,MAAM,SAAS,GAAG,IAAI;AAC1D,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,UAAI,SAAS,OAAO,UAAU,UAAU;AACtC,cAAM,SAAS,KAAK,kBAAkB,OAAO,IAAI;AACjD,YAAI,QAAQ;AACV,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,oBAAoB,MAAmB,UAAgD;AAC7F,UAAM,SAAS,KAAK,wBAAwB,KAAK,KAAK;AACtD,QAAI,QAAQ;AACV,aAAO;AAAA,IACT;AAEA,QAAI,UAAU,OAAO;AACnB,aAAO,SAAS;AAAA,IAClB;AAEA,WAAO,KAAK,kBAAkB,IAAI;AAAA,EACpC;AAAA,EAEQ,oBAAoB,MAAmB,UAAyC;AACtF,UAAM,YAAY,UAAU,kBAAkB,KAAK,iBAAiB,IAAI;AACxE,UAAM,eAAe,YAAY,KAAK,MAAM,SAAS,IAAI,OAAO;AAChE,UAAM,YAAY,CAAC,OAAO,MAAM,YAAY;AAC5C,UAAM,aAAa,KAAK;AAExB,QAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,OAAO,KAAK,IAAI,EAAE,WAAW,GAAG;AACvE,aAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR;AAAA,QACA,OAAO;AAAA,QACP,oBAAoB;AAAA,MACtB;AAAA,IACF;AAEA,QAAI,YAAY,OAAO;AACrB,YAAM,SAAS,OAAO,WAAW,WAAW,YAAY,WAAW,OAAO,KAAK,EAAE,SAAS,IACtF,WAAW,OAAO,KAAK,IACvB,WAAW,UAAU,qBACnB,gCACA;AACN,YAAM,QAAS,WAAW,SAAwB;AAClD,aAAO;AAAA,QACL,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA,oBAAoB;AAAA,MACtB;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,cAAc;AACtB,aAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR;AAAA,QACA,OAAO;AAAA,QACP,oBAAoB;AAAA,MACtB;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,iBAAiB,KAAK,YAAY,GAAG;AAC7C,aAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR;AAAA,QACA,OAAO;AAAA,QACP,oBAAoB;AAAA,MACtB;AAAA,IACF;AAEA,UAAM,eAAe,OAAO,KAAK,kBAAkB,WAAW,KAAK,cAAc,KAAK,IAAI;AAC1F,QAAI,CAAC,cAAc;AACjB,aAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR;AAAA,QACA,OAAO;AAAA,QACP,oBAAoB;AAAA,MACtB;AAAA,IACF;AAEA,QAAI,WAAW;AACb,YAAM,OAAO,eAAe,KAAK,IAAI;AACrC,UAAI,QAAQ,GAAG;AACb,eAAO;AAAA,UACL,OAAO;AAAA,UACP,QAAQ;AAAA,UACR;AAAA,UACA,oBAAoB;AAAA,UACpB,OAAO;AAAA,UACP,oBAAoB;AAAA,QACtB;AAAA,MACF;AAEA,UAAI,QAAQ,+BAA+B;AACzC,eAAO;AAAA,UACL,OAAO;AAAA,UACP,QAAQ;AAAA,UACR;AAAA,UACA,OAAO;AAAA,UACP,oBAAoB;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,MACP;AAAA,MACA,oBAAoB;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,uBAAuB,MAAgD;AAC7E,UAAM,YAAY,KAAK,iBAAiB,KAAK,QAAQ;AACrD,UAAM,gBAAgB,KAAK,iBAAiB,KAAK,YAAY;AAE7D,QAAI,CAAC,aAAa,CAAC,eAAe;AAChC,aAAO;AAAA,IACT;AAEA,UAAM,WAAY,YAAY,6BAA6B,KACzD,gBAAgB,6BAA6B;AAE/C,UAAM,cAAc,gBAAgB,gCAAgC;AAEpE,UAAM,YAAY,CAAC,KAAiD,QAClE,OAAO,MAAM,GAAG,MAAM,WAAY,IAAI,GAAG,IAAe;AAE1D,UAAM,YAAY,CAAC,KAAiD,QAClE,OAAO,MAAM,GAAG,MAAM,WAAY,IAAI,GAAG,IAAe;AAE1D,UAAM,MAAM,UAAU,WAAW,KAAK,KAAK,UAAU,eAAe,KAAK;AACzE,UAAM,MAAM,UAAU,WAAW,KAAK,KAAK,UAAU,eAAe,KAAK;AACzE,UAAM,WAAW,UAAU,WAAW,WAAW,KAAK,UAAU,eAAe,WAAW;AAE1F,UAAM,mBAAmB,MAAM,QAAQ,WAAW,eAAe,CAAC,IAC7D,WAAW,eAAe,IAC3B;AAEJ,UAAM,gBAAgB,mBAClB,iBACG,IAAI,CAAC,QAA0B;AAC9B,YAAM,SAAS;AACf,aAAO;AAAA,QACL,IAAI,UAAU,QAAQ,IAAI;AAAA,QAC1B,OAAO,UAAU,QAAQ,OAAO;AAAA,QAChC,MAAM,UAAU,QAAQ,MAAM;AAAA,QAC9B,WAAW,OAAO,SAAS,YAAY,MAAM,YAAa,SAAS,YAAY,IAAgB;AAAA,MACjG;AAAA,IACF,CAAC,EACA;AAAA,MACC,SACE,IAAI,MACJ,IAAI,SACJ,IAAI,QACJ,OAAO,IAAI,cAAc;AAAA,IAC7B,IACF;AAEJ,UAAM,SAAS,MAAM,QAAQ,WAAW,QAAQ,CAAC,KAC5C,WAAW,QAAQ,GAAgB,OAAO,CAAC,UAA2B,OAAO,UAAU,QAAQ,IAChG;AAEJ,UAAM,gBACJ,OAAO,cAAc,gBAAgB,MAAM,YACtC,cAAc,gBAAgB,IAC/B,OAAO,YAAY,gBAAgB,MAAM,YACtC,YAAY,gBAAgB,IAC7B,OAAO,gBAAgB,gBAAgB,MAAM,YAC1C,gBAAgB,gBAAgB,IACjC;AAEV,UAAM,QACJ,KAAK,eAAe;AAAA,MAClB,UAAU,aAAa,OAAO;AAAA,MAC9B,UAAU,aAAa,eAAe;AAAA,MACtC,UAAU,aAAa,eAAe;AAAA,MACtC,UAAU,aAAa,eAAe;AAAA,MACtC,UAAU,aAAa,eAAe;AAAA,IACxC,CAAC,KACD,KAAK,kBAAkB,WAAW,KAClC,KAAK,eAAe;AAAA,MAClB,UAAU,UAAU,YAAY;AAAA,MAChC,UAAU,UAAU,OAAO;AAAA,MAC3B,UAAU,UAAU,WAAW;AAAA,MAC/B,UAAU,UAAU,oBAAoB;AAAA,IAC1C,CAAC,KACD,KAAK,kBAAkB,QAAQ,KAC/B,KAAK,eAAe;AAAA,MAClB,UAAU,WAAW,OAAO;AAAA,MAC5B,UAAU,WAAW,oBAAoB;AAAA,MACzC,UAAU,WAAW,UAAU;AAAA,IACjC,CAAC,KACD,KAAK,kBAAkB,SAAS,KAChC,KAAK,eAAe;AAAA,MAClB,UAAU,eAAe,OAAO;AAAA,IAClC,CAAC,KACD,KAAK,kBAAkB,aAAa;AAEtC,UAAM,eAA6C,WAC/C;AAAA,MACE,aAAa,UAAU,UAAU,mCAAmC;AAAA,MACpE,aAAa,UAAU,UAAU,mCAAmC;AAAA,MACpE,aAAa,UAAU,UAAU,mCAAmC;AAAA,IACtE,IACA;AAEJ,UAAM,WAAW,UAAU,UAAU,mBAAmB;AACxD,UAAM,gBAAgB,UAAU,UAAU,iBAAiB;AAC3D,UAAM,uBAAuB,UAAU,UAAU,yBAAyB;AAC1E,UAAM,SACJ,UAAU,UAAU,SAAS,KAC7B,wBACA,UAAU,aAAa,QAAW,KAAK,KACvC,UAAU,iBAAiB,QAAW,KAAK;AAE7C,UAAM,WAA4B;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB,KAAK,uBAAuB,GAAG;AAAA,MAC/C,eAAe,KAAK,uBAAuB,GAAG;AAAA,MAC9C,eAAe,KAAK,uBAAuB,QAAQ;AAAA,IACrD;AAEA,UAAM,oBACJ,QAAQ,SAAS,QAAQ,KACzB;AAAA,MACE,SAAS,iBACN,SAAS,aAAa,eACrB,SAAS,aAAa,eACtB,SAAS,aAAa;AAAA,IAC5B,KACA,QAAQ,SAAS,iBAAiB,SAAS,cAAc,SAAS,CAAC,KACnE,QAAQ,SAAS,UAAU,SAAS,OAAO,SAAS,CAAC,KACrD,QAAQ,SAAS,MAAM,KACvB,QAAQ,SAAS,aAAa,KAC9B,QAAQ,SAAS,KAAK,KACtB,OAAO,SAAS,kBAAkB,aAClC,QAAQ,SAAS,cAAc,KAC/B,QAAQ,SAAS,aAAa,KAC9B,QAAQ,SAAS,aAAa;AAEhC,WAAO,oBAAoB,WAAW;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAA4B;AAChC,SAAK,uBAAmB,mBAAK,eAAe,GAAG,eAAe;AAE9D,QAAI;AACF,YAAM,UAAAA,SAAG,MAAM,KAAK,UAAU,EAAE,WAAW,KAAK,CAAC;AAAA,IACnD,SAAS,OAAO;AACd,eAAS,4CAA4C,KAAK;AAC1D,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AACA,QAAI;AACF,YAAM,UAAAA,SAAG,MAAM,KAAK,kBAAkB,EAAE,WAAW,KAAK,CAAC;AAAA,IAC3D,SAAS,OAAO;AACd,eAAS,oDAAoD,KAAK;AAClE,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AAEA,UAAM,KAAK,wBAAwB;AAAA,EACrC;AAAA,EAEQ,gBAAmB,MAAoC;AAC7D,UAAM,MAAM,mBAAmB,KAAK,MAAM,IAAI;AAC9C,yBAAqB,IAAI;AAAA,MACvB,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,0BAAyC;AACrD,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,UAAAA,SAAG,SAAS,KAAK,kBAAkB,MAAM;AAAA,IAC1D,SAAS,OAAO;AACd,UAAI,CAAC,KAAK,gBAAgB,KAAK,GAAG;AAChC,gBAAQ,yCAAyC,KAAK;AAAA,MACxD;AACA;AAAA,IACF;AAEA,QAAI;AACF,UAAI,WAAW,4BAA4B;AACzC,cAAM,UAAAA,SAAG,GAAG,KAAK,YAAY,EAAE,OAAO,KAAK,CAAC;AAAA,MAC9C,OAAO;AACL,YAAI;AACF,gBAAM,KAAK,YAAY,KAAK,YAAY,MAAM;AAAA,QAChD,SAAS,OAAO;AACd,kBAAQ,4EAA4E,KAAK;AACzF,cAAI;AACF,kBAAM,UAAAA,SAAG,UAAU,KAAK,YAAY,QAAQ,MAAM;AAAA,UACpD,SAAS,eAAe;AACtB,oBAAQ,2DAA2D,aAAa;AAAA,UAClF;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,8CAA8C,KAAK;AAAA,IAC7D;AAEA,QAAI;AACF,YAAM,UAAAA,SAAG,GAAG,KAAK,kBAAkB,EAAE,OAAO,KAAK,CAAC;AAAA,IACpD,SAAS,OAAO;AACd,UAAI,CAAC,KAAK,gBAAgB,KAAK,GAAG;AAChC,gBAAQ,wCAAwC,KAAK;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,YAAY,UAAkB,UAAiC;AAC3E,UAAM,WAAW,GAAG,QAAQ;AAC5B,UAAM,MAAM,YAAAC,QAAK,QAAQ,QAAQ;AACjC,UAAM,UAAAD,SAAG,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AAEvC,UAAM,UAAAA,SAAG,UAAU,UAAU,UAAU,MAAM;AAC7C,QAAI;AACF,YAAM,UAAAA,SAAG,OAAO,UAAU,QAAQ;AAAA,IACpC,SAAS,OAAO;AAEd,UAAI;AACF,cAAM,UAAAA,SAAG,UAAU,UAAU,UAAU,MAAM;AAAA,MAC/C,SAAS,YAAY;AAEnB,cAAM,WAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACtE,cAAM,WAAW,sBAAsB,QAAQ,WAAW,UAAU,OAAO,UAAU;AACrF,cAAM,IAAI,MAAM,gCAAgC,QAAQ,mBAAmB,QAAQ,GAAG;AAAA,MACxF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,UAAAA,SAAG,GAAG,UAAU,EAAE,OAAO,KAAK,CAAC;AAAA,IACvC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,MAAoD;AAC/E,QAAI,gBAAgB,QAAQ,OAAO,KAAK,eAAe,YAAY,KAAK,WAAW,KAAK,GAAG;AACzF,aAAO,KAAK,WAAW,KAAK;AAAA,IAC9B;AAEA,QAAI,YAAY,QAAQ,KAAK,UAAU,OAAO,KAAK,WAAW,UAAU;AACtE,YAAM,YAAa,KAAK,OAAoC;AAC5D,UAAI,OAAO,cAAc,YAAY,UAAU,KAAK,GAAG;AACrD,eAAO,UAAU,KAAK;AAAA,MACxB;AAAA,IACF;AAEA,UAAM,YACJ,gBAAgB,QAAQ,OAAQ,KAAqB,eAAe,WAC/D,KAAqB,YAAY,KAAK,IACvC;AACN,QAAI,WAAW;AACb,aAAO;AAAA,IACT;AAEA,UAAM,QACJ,WAAW,QAAQ,OAAQ,KAAqB,UAAU,WACrD,KAAqB,OAAO,KAAK,IAClC;AACN,WAAO,SAAS;AAAA,EAClB;AAAA,EAEQ,yBAAyB,MAAgC,UAA2D;AAC1H,UAAM,WACJ,kBAAkB,QAAQ,OAAO,KAAK,iBAAiB,WACnD,KAAK,aAAa,KAAK,IACvB;AACN,UAAM,aACJ,oBAAoB,QAAQ,OAAO,KAAK,mBAAmB,WACvD,KAAK,eAAe,KAAK,IACzB;AAEN,QAAI,UAAU;AACZ,aAAO,EAAE,IAAI,UAAU,MAAM,WAAW;AAAA,IAC1C;AAEA,UAAM,gBAAgB,UAAU;AAChC,QAAI,iBAAiB,cAAc,SAAS,GAAG;AAC7C,YAAM,YAAY,cAAc,KAAK,SAAO,IAAI,SAAS,KAAK,cAAc,CAAC;AAC7E,UAAI,WAAW,IAAI;AACjB,eAAO,EAAE,IAAI,UAAU,IAAI,MAAM,UAAU,SAAS,WAAW;AAAA,MACjE;AAAA,IACF;AAEA,WAAO,EAAE,IAAI,sBAAsB,MAAM,WAAW;AAAA,EACtD;AAAA,EAEA,MAAc,oBAAoB,MAAkD;AAClF,UAAM,aAAa,KAAK,qBAAqB,IAAI;AACjD,UAAM,SAAS,MAAM,KAAK,kBAAkB,UAAU;AACtD,WAAO,UAAU;AAAA,EACnB;AAAA,EAEA,MAAc,yBACZ,WACA,SACoC;AACpC,UAAM,UAAU,MAAM,KAAK,mBAAmB;AAC9C,UAAM,UAAU,QAAQ,OAAO,YAAU;AACvC,YAAM,kBAAkB,OAAO,aAAa,KAAK,qBAAqB,OAAO,IAAI;AACjF,aAAO,oBAAoB;AAAA,IAC7B,CAAC;AAED,QAAI,QAAQ,WAAW,GAAG;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,OAAO,SAAS,eAAe,WAAW,QAAQ,WAAW,KAAK,EAAE,YAAY,IAAI;AACtG,QAAI,WAAW;AACb,aAAO,QAAQ,KAAK,YAAU,KAAK,kBAAkB,OAAO,IAAI,MAAM,SAAS;AAAA,IACjF;AAEA,UAAM,SAAS,OAAO,SAAS,qBAAqB,WAAW,QAAQ,iBAAiB,KAAK,EAAE,YAAY,IAAI;AAC/G,QAAI,QAAQ;AACV,aAAO,QAAQ,KAAK,YAAU,KAAK,kBAAkB,OAAO,IAAI,MAAM,MAAM,KAAK,QAAQ,CAAC;AAAA,IAC5F;AAEA,WAAO,QAAQ,CAAC;AAAA,EAClB;AAAA,EAEA,MAAc,mCACZ,WACA,aACA,SACoC;AACpC,UAAM,eAAe,eAAe,YAAY,KAAK,EAAE,SAAS,IAAI,YAAY,KAAK,IAAI;AACzF,UAAM,UAAU,MAAM,KAAK,mBAAmB;AAC9C,UAAM,UAAU,QAAQ,OAAO,YAAU;AACvC,YAAM,kBAAkB,OAAO,aAAa,KAAK,qBAAqB,OAAO,IAAI;AACjF,UAAI,oBAAoB,WAAW;AACjC,eAAO;AAAA,MACT;AACA,YAAM,kBAAkB,OAAO,eAAe,OAAO,KAAK,gBAAgB;AAC1E,cAAQ,mBAAmB,gBAAgB,KAAK,IAAI,gBAAgB,KAAK,IAAI,0BAA0B;AAAA,IACzG,CAAC;AAED,QAAI,QAAQ,WAAW,GAAG;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,OAAO,SAAS,eAAe,WAAW,QAAQ,WAAW,KAAK,EAAE,YAAY,IAAI;AACtG,QAAI,WAAW;AACb,aAAO,QAAQ,KAAK,YAAU,KAAK,kBAAkB,OAAO,IAAI,MAAM,SAAS;AAAA,IACjF;AAEA,UAAM,SAAS,OAAO,SAAS,qBAAqB,WAAW,QAAQ,iBAAiB,KAAK,EAAE,YAAY,IAAI;AAC/G,QAAI,QAAQ;AACV,aAAO,QAAQ,KAAK,YAAU,KAAK,kBAAkB,OAAO,IAAI,MAAM,MAAM,KAAK,QAAQ,CAAC;AAAA,IAC5F;AAEA,WAAO,QAAQ,CAAC;AAAA,EAClB;AAAA,EAEA,MAAc,qBACZ,MACA,MACA,UACA,SACe;AACf,UAAM,eAAe,KAAK,qBAAqB,IAAI;AACnD,UAAM,iBAAiB,MAAM,KAAK,kBAAkB,YAAY;AAChE,QAAI,OAAO,KAAK,gBAAgB,UAAU;AACxC,WAAK,cAAc,KAAK,YAAY,KAAK,EAAE,YAAY;AAAA,IACzD;AACA,QAAI,CAAC,KAAK,aAAa;AACrB,WAAK,cAAc;AAAA,IACrB;AACA,UAAM,mBAAmB,YAAY,KAAK,uBAAuB,IAAI,KAAK,gBAAgB;AAC1F,UAAM,YAAY,KAAK,yBAAyB,MAAM,gBAAgB;AACtE,UAAM,cAAc,UAAU,MAAM;AACpC,UAAM,gBAAgB,UAAU,QAAQ;AACxC,QAAI,CAAC,KAAK,cAAc;AACtB,WAAK,eAAe;AAAA,IACtB;AACA,QAAI,CAAC,KAAK,kBAAkB,eAAe;AACzC,WAAK,iBAAiB;AAAA,IACxB;AAEA,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,UAAM,YAAY,KAAK,qBAAqB,IAAI,KAAK;AACrD,UAAM,gBAAgB,KAAK,oBAAoB,MAAM,gBAAgB,KAAK,KAAK,SAAS;AACxF,QAAI,eAAe;AACjB,WAAK,QAAQ;AAAA,IACf;AACA,UAAM,YAAY,KAAK,cAAc,gBAAgB,aAAa;AAClE,SAAK,aAAa;AAClB,UAAM,YAAY,KAAK,cAAc;AACrC,SAAK,aAAa;AAElB,UAAM,cACJ,OAAO,SAAS,gBAAgB,YAAY,QAAQ,YAAY,KAAK,EAAE,SAAS,IAC5E,QAAQ,YAAY,KAAK,IACzB,gBAAgB,eAAe;AAErC,UAAM,SAAwB;AAAA,MAC5B,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA,aAAa,KAAK,gBAAgB;AAAA,MAClC,eAAe,KAAK,kBAAkB;AAAA,MACtC,OAAO,iBAAiB;AAAA,MACxB,YAAY,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AAAA,MACtE;AAAA,MACA;AAAA,IACF;AAEA,UAAM,UAAAA,SAAG,MAAM,KAAK,mBAAmB,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AACzE,UAAM,KAAK,mBAAmB,MAAM;AAAA,EACtC;AAAA,EAEQ,oBAAoB,KAA6B;AACvD,UAAM,UAAU,KAAK,qBAAqB,IAAI,MAAM,IAAI,MAAM;AAAA,MAC5D,aAAa,IAAI,eAAe;AAAA,MAChC,OAAO,IAAI,SAAS;AAAA,MACpB,WAAW,IAAI,aAAa;AAAA,MAC5B,YAAY,IAAI,cAAc;AAAA,MAC9B,WAAW,IAAI,aAAa;AAAA,MAC5B,aAAa,IAAI,eAAe;AAAA,MAChC,eAAe,IAAI,iBAAiB;AAAA,MACpC,UAAU,IAAI;AAAA,IAChB,CAAC;AAED,WAAO;AAAA,EACT;AAAA,EAEQ,qBACN,MACA,MACA,UAWS;AACT,UAAM,WAAW,UAAU,YAAY,KAAK,uBAAuB,IAAI;AACvE,UAAM,YAAY,KAAK,yBAAyB,MAAM,QAAQ;AAC9D,UAAM,cAAc,UAAU,MAAM,UAAU,eAAe;AAC7D,UAAM,gBAAgB,UAAU,QAAQ,UAAU,iBAAiB;AACnE,UAAM,QAAQ,KAAK,oBAAoB,MAAM,QAAQ,KAAK,UAAU,SAAS;AAC7E,UAAM,cAAc,KAAK,oBAAoB,MAAM,QAAQ;AAC3D,UAAM,YAAY,KAAK,qBAAqB,IAAI,KAAK,UAAU;AAC/D,UAAM,YACJ,OAAO,KAAK,eAAe,YAAY,KAAK,WAAW,KAAK,EAAE,SAAS,IACnE,KAAK,WAAW,KAAK,IACrB,UAAU;AAEhB,WAAO;AAAA,MACL;AAAA,MACA,aAAa,UAAU,eAAe;AAAA,MACtC,SAAS,QAAQ,QAAQ,OAAO,KAAK,IAAI,EAAE,SAAS,CAAC;AAAA,MACrD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,KAAK,cAAc,UAAU,aAAa;AAAA,MACrD,YAAY,OAAO,KAAK,gBAAgB,WACpC,KAAK,YAAY,KAAK,EAAE,YAAY,IACpC,UAAU,cAAc;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eAAe,OAAsC;AAC3D,QAAI,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,IAAI;AACpD,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,WAAO,OAAO,MAAM,MAAM,IAAI,OAAO;AAAA,EACvC;AAAA,EAEQ,6BAA6B,GAAY,GAAoB;AACnE,QAAI,QAAQ,EAAE,OAAO,MAAM,QAAQ,EAAE,OAAO,GAAG;AAC7C,aAAO,EAAE,UAAU,KAAK;AAAA,IAC1B;AAEA,UAAM,aAAa,KAAK,eAAe,EAAE,aAAa,IAAI;AAC1D,UAAM,aAAa,KAAK,eAAe,EAAE,aAAa,IAAI;AAE1D,QAAI,eAAe,QAAQ,eAAe,MAAM;AAC9C,UAAI,eAAe,QAAQ,eAAe,MAAM;AAC9C,YAAI,aAAa,YAAY;AAC3B,iBAAO;AAAA,QACT;AACA,YAAI,aAAa,YAAY;AAC3B,iBAAO;AAAA,QACT;AAAA,MACF,WAAW,eAAe,MAAM;AAC9B,eAAO;AAAA,MACT,OAAO;AACL,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,EACpC;AAAA,EAEQ,uBAAuB,UAA8B;AAC3D,QAAI,SAAS,UAAU,GAAG;AACxB,aAAO,SAAS,CAAC;AAAA,IACnB;AAEA,WAAO,SACJ,MAAM,EACN,KAAK,CAAC,GAAG,MAAM,KAAK,6BAA6B,GAAG,CAAC,CAAC,EAAE,CAAC;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,MAA+B;AAE1D,QAAI,YAAY,MAAM;AACpB,aAAO;AAAA,IACT;AAIA,UAAM,cAAc,OAAO,KAAK,iBAAiB,WAAW,KAAK,aAAa,KAAK,IAAI;AACvF,QAAI,wBAAwB,YAAY,SAAS,IAAI,cAAc;AACnE,QAAI,CAAC,uBAAuB;AAC1B,YAAM,gBAAgB,KAAK,iBAAiB,KAAK,YAAY;AAC7D,YAAM,gBAAgB,OAAO,eAAe,QAAQ,WAChD,KAAK,uBAAuB,cAAc,GAAG,IAC7C;AACJ,UAAI,eAAe;AACjB,gCAAwB;AAAA,MAC1B;AAAA,IACF;AACA,QAAI,CAAC,uBAAuB;AAC1B,YAAM,YAAY,OAAO,KAAK,eAAe,WAAW,KAAK,WAAW,KAAK,IAAI;AACjF,UAAI,WAAW;AACb,gCAAwB;AAAA,MAC1B;AAAA,IACF;AACA,UAAM,YAAwB;AAAA,MAC5B,gBAAgB;AAAA,MAChB,QAAQ;AAAA,QACN,UAAU,KAAK;AAAA,QACf,cAAc,KAAK;AAAA,QACnB,eAAe,KAAK;AAAA,QACpB,YAAY,KAAK;AAAA,QACjB,GAAI,wBAAwB,EAAE,cAAc,sBAAsB,IAAI,CAAC;AAAA,MACzE;AAAA,IACF;AACA,QAAI,uBAAuB;AACzB,gBAAU,eAAe;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,MAA+B;AAE1D,QAAI,cAAc,MAAM;AACtB,aAAO;AAAA,IACT;AAGA,UAAM,SAAS,KAAK,UAAU,CAAC;AAC/B,UAAM,UAAuB;AAAA,MAC3B,UAAU,OAAO;AAAA,MACjB,cAAc,OAAO;AAAA,MACrB,eAAe,OAAO;AAAA,MACtB,YAAY,OAAO;AAAA,IACrB;AACA,UAAM,mBAAmB,OAAO,OAAO,iBAAiB,WAAW,OAAO,aAAa,KAAK,IAAI;AAChG,UAAM,kBAAkB,OAAO,KAAK,iBAAiB,WAAW,KAAK,aAAa,KAAK,IAAI;AAC3F,UAAM,wBAAwB,oBAAoB;AAClD,QAAI,uBAAuB;AACzB,cAAQ,eAAe;AAAA,IACzB;AAEA,QAAI,KAAK,OAAO;AACd,cAAQ,QAAQ,KAAK;AAAA,IACvB;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,oBAAoB,UAAuB,UAGjD;AACA,UAAM,SAAsB;AAAA,MAC1B,GAAG;AAAA,MACH,GAAG;AAAA,MACH,YAAY,SAAS,cAAc,SAAS,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,IACnF;AAEA,QAAI,OAAO,OAAO,gBAAgB,UAAU;AAC1C,aAAO,cAAc,OAAO,YAAY,KAAK,EAAE,YAAY;AAAA,IAC7D;AACA,QAAI,CAAC,OAAO,aAAa;AACvB,aAAO,cAAc;AAAA,IACvB;AAEA,UAAM,WAAW,KAAK,uBAAuB,MAAM;AACnD,UAAM,gBAAgB,KAAK,oBAAoB,QAAQ,QAAQ;AAE/D,QAAI,eAAe;AACjB,aAAO,QAAQ;AAAA,IACjB;AAEA,UAAM,YAAY,KAAK,yBAAyB,QAAQ,QAAQ;AAChE,QAAI,CAAC,OAAO,cAAc;AACxB,aAAO,eAAe,UAAU,MAAM,SAAS,gBAAgB;AAAA,IACjE;AACA,QAAI,CAAC,OAAO,gBAAgB;AAC1B,aAAO,iBAAiB,UAAU,QAAQ,SAAS;AAAA,IACrD;AAEA,QAAI,KAAK,gBAAgB,UAAU,QAAQ,GAAG;AAC5C,aAAO,OAAO;AAAA,IAChB;AAEA,WAAO,EAAE,SAAS,QAAQ,SAAS;AAAA,EACrC;AAAA,EAEQ,gBAAgB,UAAuB,UAAgC;AAC7E,UAAM,YAAsC;AAAA,MAC1C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,WAAO,UAAU,KAAK,SAAO;AAC3B,YAAM,YAAY,SAAS,GAAG;AAC9B,UAAI,OAAO,cAAc,YAAY,UAAU,WAAW,GAAG;AAC3D,eAAO;AAAA,MACT;AACA,aAAO,cAAc,SAAS,GAAG;AAAA,IACnC,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cACJ,MACA,OACA,QACA,SACe;AACf,UAAM,KAAK,WAAW;AACtB,UAAM,cAAc,KAAK,qBAAqB,IAAI;AAClD,UAAM,SAAS,MAAM,KAAK,oBAAoB,WAAW;AACzD,QAAI,CAAC,QAAQ;AACX,cAAQ,2BAA2B,KAAK,0BAA0B,WAAW,IAAI;AACjF;AAAA,IACF;AAEA,UAAM,aAAa,SAAS,aAAa,KAAK,MAAM,QAAQ,UAAU,IAAI;AAC1E,UAAM,YAAY,OAAO,YAAY,KAAK,MAAM,OAAO,SAAS,IAAI;AACpE,QAAI,eAAe,QAAQ,cAAc,QAAQ,cAAc,WAAW;AACxE;AAAA,IACF;AAEA,UAAM,OAAoB,OAAO;AAEjC,UAAM,gBAAgB,OAAO,WAAW,YAAY,OAAO,KAAK,EAAE,SAAS,IAAI,OAAO,KAAK,IAAI;AAC/F,UAAM,aAAa,eAAe,YAAY,KAAK;AACnD,UAAM,eAAe,UAAU,qBAC1B,WAAW,SAAS,8BAA8B,IACjD,gCACA,iBAAiB,gCACnB;AACJ,UAAM,QAAoB;AAAA,MACxB;AAAA,MACA,QAAQ;AAAA,MACR,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IACrC;AAEA,SAAK,aAAa;AAElB,QAAI;AACF,YAAM,WAAW,KAAK,uBAAuB,IAAI;AACjD,YAAM,KAAK,qBAAqB,aAAa,MAAM,QAAQ;AAAA,IAC7D,SAAS,OAAO;AACd,eAAS,8CAA8C,WAAW,MAAM,KAAK;AAAA,IAC/E;AAAA,EACF;AAAA,EAEA,MAAM,yBAAyB,MAAc,QAAiB,SAAkD;AAC9G,UAAM,KAAK,cAAc,MAAM,oBAAoB,QAAQ,OAAO;AAAA,EACpE;AAAA,EAEA,MAAc,gCACZ,aACA,iBACA,UACe;AACf,UAAM,aAAa,YAAY,KAAK;AACpC,QAAI;AACF,YAAM,UAAU,MAAM,UAAAA,SAAG,SAAS,YAAY,MAAM;AACpD,YAAM,KAAK,iCAAiC,aAAa,iBAAiB,OAAO;AAAA,IACnF,SAAS,OAAO;AACd,UAAI,CAAC,KAAK,gBAAgB,KAAK,GAAG;AAChC,gBAAQ,kCAAkC,WAAW,2BAA2B,KAAK;AAAA,MACvF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,iCACZ,aACA,iBACA,aACe;AACf,QAAI;AACJ,QAAI;AACF,mBAAa,KAAK,MAAM,WAAW;AAAA,IACrC,SAAS,OAAO;AACd,cAAQ,wDAAwD,WAAW,MAAM,KAAK;AACtF;AAAA,IACF;AAEA,UAAM,aAAa,KAAK,qBAAqB,UAAU;AACvD,UAAM,WAAW,KAAK,uBAAuB,UAAU;AACvD,UAAM,YAAY,KAAK,yBAAyB,YAAY,QAAQ;AACpE,eAAW,eAAe,WAAW,gBAAgB,UAAU,MAAM;AACrE,QAAI,UAAU,MAAM;AAClB,iBAAW,iBAAiB,WAAW,kBAAkB,UAAU;AAAA,IACrE;AACA,UAAM,YACJ,OAAO,WAAW,aAAa,YAC/B,OAAO,WAAW,iBAAiB,YACnC,OAAO,WAAW,kBAAkB;AAEtC,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,QAAI,WAAW;AACf,UAAM,YAAY,MAAM,KAAK,oBAAoB,WAAW;AAC5D,QAAI,WAAW;AACb,iBAAW,UAAU;AAAA,IACvB;AAEA,UAAM,oBAAoB,KAAK,qBAAqB,QAAQ;AAC5D,UAAM,eAAe,KAAK,qBAAqB,UAAU;AAEzD,QAAI,qBAAqB,gBAAgB,sBAAsB,cAAc;AAC3E;AAAA,QACE,uCAAuC,WAAW,6CAA6C,YAAY;AAAA,MAC7G;AACA;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,gBAAgB,UAAU,UAAU,GAAG;AAC/C;AAAA,IACF;AAEA,UAAM,EAAE,SAAS,QAAQ,UAAU,eAAe,IAAI,KAAK,oBAAoB,UAAU,UAAU;AAEnG,QAAI;AACF,YAAM,KAAK,qBAAqB,aAAa,QAAQ,cAAc;AAAA,IACrE,SAAS,OAAO;AACd,eAAS,mDAAmD,WAAW,MAAM,KAAK;AAAA,IACpF;AAAA,EACF;AAAA,EAEA,MAAc,gBAAgB,iBAAwC;AACpE,UAAM,aAAa,CAAC,eAAe,eAAe,eAAe,YAAY;AAC7E,eAAW,QAAQ,YAAY;AAC7B,YAAM,aAAS,mBAAK,KAAK,UAAU,IAAI;AACvC,YAAM,kBAAc,mBAAK,iBAAiB,IAAI;AAC9C,UAAI;AACF,cAAM,UAAAA,SAAG,SAAS,QAAQ,WAAW;AAAA,MACvC,SAAS,OAAO;AACd,YAAI,CAAC,KAAK,gBAAgB,KAAK,GAAG;AAChC,kBAAQ,gCAAgC,IAAI,sBAAsB,KAAK;AAAA,QACzE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,mBAAmB,aAA6B;AACtD,eAAO,mBAAK,KAAK,kBAAkB,WAAW;AAAA,EAChD;AAAA,EAEQ,sBAAsB,SAAyB;AACrD,WAAO,QAAQ,SAAS,IAAI,IAAI,UAAU,GAAG,OAAO;AAAA;AAAA,EACtD;AAAA,EAEA,MAAc,sBAAsB,aAAoC;AACtE,UAAM,iBAAa,mBAAK,aAAa,aAAa;AAClD,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,UAAAA,SAAG,SAAS,YAAY,MAAM;AAAA,IAC5C,SAAS,OAAO;AACd,UAAI,CAAC,KAAK,gBAAgB,KAAK,GAAG;AAChC,gBAAQ,2CAA2C,WAAW,MAAM,KAAK;AAAA,MAC3E;AACA;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,mBAAS,mBAAM,GAAG;AAAA,IACpB,SAAS,OAAO;AACd,cAAQ,iDAAiD,WAAW,MAAM,KAAK;AAC/E;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQ,wBAAwB,GAAG;AAC3E;AAAA,IACF;AAEA,WAAO,OAAO,wBAAwB;AACtC,UAAM,YAAY,KAAK,0BAAsB,uBAAU,MAAiC,CAAC;AACzF,QAAI;AACF,YAAM,UAAAA,SAAG,UAAU,YAAY,WAAW,MAAM;AAAA,IAClD,SAAS,OAAO;AACd,cAAQ,2DAA2D,WAAW,MAAM,KAAK;AAAA,IAC3F;AAAA,EACF;AAAA,EAEA,MAAc,mBAAmB,aAAqB,UAAuC;AAC3F,UAAM,cAAc,KAAK,mBAAmB,WAAW;AACvD,UAAM,UAAAA,SAAG,MAAM,aAAa,EAAE,WAAW,KAAK,CAAC;AAC/C,UAAM,eAAW,mBAAK,aAAa,WAAW;AAC9C,UAAM,KAAK,YAAY,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAClE,UAAM,KAAK,gBAAgB,WAAW;AACtC,UAAM,KAAK,sBAAsB,WAAW;AAC5C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,MAAgC;AAClD,UAAM,KAAK,WAAW;AACtB,UAAM,cAAc,KAAK,qBAAqB,IAAI;AAClD,WAAO,QAAQ,MAAM,KAAK,oBAAoB,WAAW,CAAC;AAAA,EAC5D;AAAA,EAEA,MAAM,eAAmC;AACvC,UAAM,KAAK,WAAW;AACtB,QAAI;AACF,YAAM,UAAU,MAAM,KAAK,mBAAmB;AAC9C,aAAO,QACJ,IAAI,YAAU,KAAK,oBAAoB,MAAM,CAAC,EAC9C,OAAO,aAAW,CAAC,QAAQ,cAAc,QAAQ,eAAe,WAAW,EAC3E,KAAK,CAAC,GAAG,MAAM;AACd,cAAM,SAAS,EAAE,eAAe,EAAE;AAClC,cAAM,SAAS,EAAE,eAAe,EAAE;AAClC,cAAM,OAAO,OAAO,cAAc,MAAM;AACxC,eAAO,SAAS,IAAI,OAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,MACxD,CAAC;AAAA,IACL,SAAS,OAAO;AACd,eAAS,qCAAqC,KAAK;AACnD,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,MAAuC;AACzD,UAAM,KAAK,WAAW;AAEtB,UAAM,cAAc,KAAK,qBAAqB,IAAI;AAClD,QAAI,MAAM,KAAK,oBAAoB,WAAW,GAAG;AAC/C,YAAM,IAAI,MAAM,YAAY,WAAW,mBAAmB;AAAA,IAC5D;AAEA,QAAI;AACJ,QAAI;AACF,YAAM,UAAU,MAAM,UAAAA,SAAG,SAAS,KAAK,YAAY,MAAM;AACzD,iBAAW,KAAK,MAAM,OAAO;AAAA,IAC/B,SAAS,OAAO;AACd,eAAS,2BAA2B,KAAK;AACzC,YAAM,IAAI,MAAM,mFAAmF;AAAA,IACrG;AAEA,UAAM,oBAAoB,KAAK,qBAAqB,QAAQ;AAC5D,sBAAkB,aAAa,kBAAkB,eAAc,oBAAI,KAAK,GAAE,YAAY;AACtF,QAAI,OAAO,kBAAkB,gBAAgB,UAAU;AACrD,wBAAkB,cAAc,kBAAkB,YAAY,KAAK,EAAE,YAAY;AAAA,IACnF;AACA,sBAAkB,cAAc,kBAAkB,eAAe;AAEjE,UAAM,WAAW,KAAK,uBAAuB,iBAAiB;AAC9D,UAAM,YAAY,KAAK,yBAAyB,mBAAmB,QAAQ;AAC3E,sBAAkB,eAAe,kBAAkB,gBAAgB,UAAU,MAAM;AACnF,QAAI,UAAU,MAAM;AAClB,wBAAkB,iBAAiB,kBAAkB,kBAAkB,UAAU;AAAA,IACnF;AAEA,UAAM,YAAY,KAAK,qBAAqB,iBAAiB;AAC7D,QAAI,WAAW;AACb,YAAM,qBAAqB,kBAAkB,gBAAgB;AAC7D,YAAM,YAAY,MAAM,KAAK,mCAAmC,WAAW,oBAAoB,EAAE,YAAY,YAAY,CAAC;AAC1H,UAAI,WAAW;AACb,0BAAkB,eAAe,GAAG,kBAAkB,IAAI,WAAW;AACrE,0BAAkB,iBAAiB,kBAAkB,kBAAkB;AAAA,MACzE;AAAA,IACF;AAEA,UAAM,gBAAgB,KAAK,oBAAoB,mBAAmB,QAAQ;AAC1E,QAAI,eAAe;AACjB,wBAAkB,QAAQ;AAAA,IAC5B;AAEA,QAAI;AACF,YAAM,KAAK,qBAAqB,aAAa,mBAAmB,QAAQ;AACxE,YAAM,SAAS,MAAM,KAAK,oBAAoB,WAAW;AACzD,aAAO,SAAS,KAAK,oBAAoB,MAAM,IAAI;AAAA,IACrD,SAAS,OAAO;AACd,eAAS,2BAA2B,KAAK;AACzC,YAAM,IAAI,MAAM,mFAAmF;AAAA,IACrG;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,MAAgC;AACpD,UAAM,KAAK,WAAW;AACtB,UAAM,cAAc,KAAK,qBAAqB,IAAI;AAClD,UAAM,SAAS,MAAM,KAAK,oBAAoB,WAAW;AACzD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,YAAY,WAAW,cAAc;AAAA,IACvD;AAEA,QAAI;AACF,YAAM,cAAc,OAAO;AAC3B,YAAM,cAAc,KAAK,qBAAqB,WAAW;AACzD,YAAM,KAAK,YAAY,KAAK,YAAY,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;AAC5E,YAAM,KAAK,4BAA4B,WAAW;AAClD,aAAO;AAAA,IACT,SAAS,OAAO;AACd,eAAS,4BAA4B,KAAK;AAC1C,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,MAAM,mBAAmB,MAAgC;AACvD,UAAM,KAAK,WAAW;AAEtB,UAAM,cAAc,KAAK,qBAAqB,IAAI;AAClD,UAAM,SAAS,MAAM,KAAK,oBAAoB,WAAW;AACzD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,YAAY,WAAW,cAAc;AAAA,IACvD;AAEA,UAAM,WAAwB,OAAO;AACrC,QAAI;AACJ,QAAI;AACF,YAAM,cAAc,MAAM,UAAAA,SAAG,SAAS,KAAK,YAAY,MAAM;AAC7D,mBAAa,KAAK,MAAM,WAAW;AAAA,IACrC,SAAS,OAAO;AACd,UAAI,KAAK,gBAAgB,KAAK,GAAG;AAC/B,cAAM,IAAI,MAAM,4FAA4F;AAAA,MAC9G;AACA,eAAS,kDAAkD,KAAK;AAChE,YAAM,IAAI,MAAM,mEAAmE;AAAA,IACrF;AAEA,UAAM,aAAa,KAAK,qBAAqB,UAAU;AACvD,UAAM,oBAAoB,KAAK,qBAAqB,QAAQ;AAC5D,UAAM,eAAe,KAAK,qBAAqB,UAAU;AACzD,UAAM,qBAAqB,KAAK,uBAAuB,UAAU;AACjE,UAAM,sBAAsB,KAAK,yBAAyB,YAAY,kBAAkB;AACxF,eAAW,eAAe,WAAW,gBAAgB,oBAAoB,MAAM;AAC/E,QAAI,oBAAoB,MAAM;AAC5B,iBAAW,iBAAiB,WAAW,kBAAkB,oBAAoB;AAAA,IAC/E;AAEA,QAAI,qBAAqB,gBAAgB,sBAAsB,cAAc;AAC3E,YAAM,IAAI;AAAA,QACR,sCAAsC,YAAY,mBAAmB,WAAW,iBAAiB,iBAAiB;AAAA,MACpH;AAAA,IACF;AAEA,QAAI,qBAAqB,WAAW,cAAc;AAChD,YAAM,mBAAmB,KAAK,yBAAyB,UAAU,KAAK,uBAAuB,QAAQ,CAAC;AACtG,YAAM,oBAAoB,WAAW;AACrC,YAAM,qBAAqB,iBAAiB,MAAM;AAClD,UAAI,sBAAsB,oBAAoB;AAC5C,cAAM,YAAY,MAAM,KAAK,mCAAmC,mBAAmB,mBAAmB;AAAA,UACpG,YAAY,KAAK,kBAAkB,QAAQ;AAAA,QAC7C,CAAC;AACD,YAAI,aAAa,UAAU,SAAS,aAAa;AAC/C,gBAAM,IAAI;AAAA,YACR,wCAAwC,UAAU,IAAI;AAAA,UACxD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,EAAE,SAAS,QAAQ,SAAS,IAAI,KAAK,oBAAoB,UAAU,UAAU;AACnF,WAAO,OAAO;AAEd,UAAM,KAAK,qBAAqB,aAAa,QAAQ,QAAQ;AAC7D,UAAM,UAAU,MAAM,KAAK,oBAAoB,WAAW;AAC1D,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AAEA,UAAM,UAAU,KAAK,oBAAoB,OAAO;AAChD,QAAI,UAAU;AACZ,cAAQ,WAAW;AACnB,cAAQ,cAAc,KAAK,oBAAoB,QAAQ,QAAQ;AAAA,IACjE;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,mBACJ,MACA,QACY;AACZ,WAAO,KAAK,gBAAgB,YAAY;AACtC,YAAM,KAAK,WAAW;AACtB,YAAM,cAAc,KAAK,qBAAqB,IAAI;AAClD,YAAM,SAAS,MAAM,KAAK,oBAAoB,WAAW;AACzD,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,YAAY,WAAW,cAAc;AAAA,MACvD;AAEA,UAAI,cAA2B,OAAO;AAGtC,YAAM,KAAK,gCAAgC,aAAa,WAAW;AACnE,YAAM,gBAAgB,MAAM,KAAK,oBAAoB,WAAW;AAChE,UAAI,eAAe;AACjB,sBAAc,cAAc;AAAA,MAC9B;AACA,YAAM,cAAc,KAAK,mBAAmB,WAAW;AACvD,YAAM,UAAAA,SAAG,MAAM,aAAa,EAAE,WAAW,KAAK,CAAC;AAE/C,UAAI,YAAY,eAAe,YAAY,gBAAgB,aAAa;AACtE,cAAM,IAAI,MAAM,mDAAmD;AAAA,MACrE;AACA,YAAM,cAAc,KAAK,qBAAqB,WAAW;AACzD,YAAM,KAAK,mBAAmB,aAAa,WAAW;AACtD,YAAM,WAAW,YAAAC,QAAK,KAAK,aAAa,WAAW;AAEnD,YAAM,eAAkC;AAAA,QACtC,GAAG,QAAQ;AAAA,QACX,MAAM;AAAA,QACN,aAAa;AAAA,QACb,YAAY;AAAA,MACd;AAEA,UAAI;AACF,eAAO,MAAM,OAAO,YAAY;AAAA,MAClC,UAAE;AACA,YAAI,mBAAkC;AACtC,YAAI;AACF,6BAAmB,MAAM,UAAAD,SAAG,SAAS,UAAU,MAAM;AAAA,QACvD,SAAS,OAAO;AACd,cAAI,CAAC,KAAK,gBAAgB,KAAK,GAAG;AAChC,oBAAQ,qCAAqC,WAAW,mBAAmB,KAAK;AAAA,UAClF;AAAA,QACF;AAEA,YAAI;AACF,cAAI,kBAAkB;AACpB,kBAAM,KAAK,iCAAiC,aAAa,aAAa,gBAAgB;AAAA,UACxF,OAAO;AACL,kBAAM,KAAK,gCAAgC,aAAa,aAAa,QAAQ;AAAA,UAC/E;AAAA,QACF,SAAS,OAAO;AACd,kBAAQ,gDAAgD,WAAW,MAAM,KAAK;AAAA,QAChF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,SAAiB,SAAmC;AACtE,UAAM,KAAK,WAAW;AACtB,UAAM,aAAa,KAAK,qBAAqB,OAAO;AACpD,UAAM,aAAa,KAAK,qBAAqB,OAAO;AAEpD,UAAM,WAAW,MAAM,KAAK,oBAAoB,UAAU;AAC1D,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,YAAY,UAAU,cAAc;AAAA,IACtD;AAEA,QAAI,MAAM,KAAK,oBAAoB,UAAU,GAAG;AAC9C,YAAM,IAAI,MAAM,YAAY,UAAU,mBAAmB;AAAA,IAC3D;AAEA,UAAM,YAAY,MAAM,KAAK,yBAAyB;AACtD,QAAI,aAAa,cAAc,YAAY;AACzC,YAAM,KAAK,4BAA4B,UAAU;AAAA,IACnD;AAEA,UAAM,UAAU,KAAK,mBAAmB,UAAU;AAClD,UAAM,UAAU,KAAK,mBAAmB,UAAU;AAClD,QAAI;AACF,YAAM,UAAAA,SAAG,MAAM,KAAK,kBAAkB,EAAE,WAAW,KAAK,CAAC;AACzD,YAAM,UAAAA,SAAG,OAAO,SAAS,OAAO;AAAA,IAClC,SAAS,OAAO;AACd,UAAI,CAAC,KAAK,gBAAgB,KAAK,GAAG;AAChC,gBAAQ,qCAAqC,UAAU,SAAS,UAAU,MAAM,KAAK;AAAA,MACvF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,gBAA+B;AAAA,QACnC,GAAG;AAAA,QACH,MAAM;AAAA,MACR;AACA,YAAM,KAAK,mBAAmB,aAAa;AAC3C,YAAM,KAAK,oBAAoB,UAAU;AAAA,IAC3C,SAAS,OAAO;AACd,cAAQ,oDAAoD,UAAU,SAAS,UAAU,MAAM,KAAK;AAAA,IACtG;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,yBAAyB,MAAc,aAAuC;AAClF,UAAM,KAAK,WAAW;AAEtB,UAAM,cAAc,KAAK,qBAAqB,IAAI;AAClD,UAAM,SAAS,MAAM,KAAK,oBAAoB,WAAW;AACzD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,YAAY,WAAW,cAAc;AAAA,IACvD;AAEA,UAAM,UAAU,OAAO,gBAAgB,WAAW,YAAY,KAAK,IAAI;AACvE,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAEA,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,WAAO,cAAc;AACrB,WAAO,YAAY;AACnB,IAAC,OAAO,KAA+C,aAAa;AAEpE,UAAM,KAAK,mBAAmB,MAAM;AACpC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,MAAgC;AAClD,UAAM,KAAK,WAAW;AACtB,UAAM,cAAc,KAAK,qBAAqB,IAAI;AAClD,UAAM,SAAS,MAAM,KAAK,oBAAoB,WAAW;AACzD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,YAAY,WAAW,cAAc;AAAA,IACvD;AACA,UAAM,YAAY,MAAM,KAAK,yBAAyB;AACtD,QAAI,aAAa,cAAc,aAAa;AAC1C,YAAM,KAAK,4BAA4B,IAAI;AAAA,IAC7C;AACA,QAAI;AACF,YAAM,UAAAA,SAAG,GAAG,KAAK,mBAAmB,WAAW,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACpF,SAAS,OAAO;AACd,UAAI,CAAC,KAAK,gBAAgB,KAAK,GAAG;AAChC,gBAAQ,sCAAsC,WAAW,MAAM,KAAK;AAAA,MACtE;AAAA,IACF;AACA,UAAM,KAAK,oBAAoB,WAAW;AAC1C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,oBAAoB,cAAmD;AAC3E,UAAM,KAAK,WAAW;AACtB,UAAM,aAAa,oBAAI,IAAY;AACnC,eAAW,QAAQ,cAAc;AAC/B,UAAI;AACF,mBAAW,IAAI,KAAK,qBAAqB,IAAI,CAAC;AAAA,MAChD,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,KAAK,mBAAmB;AAC9C,UAAM,mBAAmB,QACtB,IAAI,YAAU;AACb,UAAI;AACF,eAAO,KAAK,qBAAqB,OAAO,IAAI;AAAA,MAC9C,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF,CAAC,EACA,OAAO,CAAC,SAAyB,QAAQ,IAAI,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC;AAE1E,QAAI,iBAAiB,WAAW,GAAG;AACjC,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,UAAoB,CAAC;AAC3B,eAAW,QAAQ,kBAAkB;AACnC,UAAI;AACF,cAAM,UAAAA,SAAG,GAAG,KAAK,mBAAmB,IAAI,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAC3E,cAAM,KAAK,oBAAoB,IAAI;AACnC,gBAAQ,KAAK,IAAI;AAAA,MACnB,SAAS,OAAO;AACd,YAAI,CAAC,KAAK,gBAAgB,KAAK,GAAG;AAChC,kBAAQ,6BAA6B,IAAI,8BAA8B,KAAK;AAAA,QAC9E;AAAA,MACF;AAAA,IACF;AACA,UAAM,YAAY,MAAM,KAAK,yBAAyB;AACtD,QAAI,aAAa,QAAQ,SAAS,SAAS,GAAG;AAC5C,YAAM,KAAK,4BAA4B,IAAI;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBAAwE;AAC5E,UAAM,KAAK,WAAW;AACtB,UAAM,gBAAgB,MAAM,KAAK,yBAAyB;AAC1D,QAAI,eAAe;AACjB,UAAI;AACF,cAAM,sBAAsB,KAAK,qBAAqB,aAAa;AACnE,cAAM,kBAAkB,MAAM,KAAK,oBAAoB,mBAAmB;AAC1E,YAAI,iBAAiB;AACnB,iBAAO,EAAE,MAAM,qBAAqB,SAAS,KAAK;AAAA,QACpD;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AACA,UAAM,aAAa,MAAM,KAAK,mBAAmB;AAEjD,QAAI,YAAY;AACd,YAAM,iBAAiB,KAAK,qBAAqB,UAAU;AAC3D,YAAM,eAAe,KAAK,uBAAuB,cAAc;AAC/D,YAAM,YAAY,KAAK,yBAAyB,gBAAgB,YAAY;AAC5E,YAAM,kBAAkB,KAAK,qBAAqB,cAAc;AAEhE,UAAI,iBAAiB;AACnB,cAAM,SAAS,MAAM,KAAK,mCAAmC,iBAAiB,UAAU,MAAM,sBAAsB;AAAA,UAClH,kBAAkB;AAAA,QACpB,CAAC;AACD,YAAI,QAAQ;AACV,gBAAM,aAAa,KAAK,qBAAqB,OAAO,IAAI;AACxD,gBAAM,KAAK,4BAA4B,UAAU;AACjD,iBAAO,EAAE,MAAM,YAAY,SAAS,KAAK;AAAA,QAC3C;AAEA,cAAM,WAAW,MAAM,KAAK,yBAAyB,iBAAiB,EAAE,kBAAkB,YAAY,CAAC;AACvG,YAAI,UAAU;AACZ,gBAAM,aAAa,KAAK,qBAAqB,SAAS,IAAI;AAC1D,gBAAM,KAAK,4BAA4B,UAAU;AACjD,iBAAO,EAAE,MAAM,YAAY,SAAS,KAAK;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAY,MAAM,KAAK,yBAAyB;AACtD,QAAI,WAAW;AACb,UAAI;AACF,cAAM,aAAa,KAAK,qBAAqB,SAAS;AACtD,cAAM,SAAS,MAAM,KAAK,oBAAoB,UAAU;AACxD,YAAI,QAAQ;AACV,iBAAO,EAAE,MAAM,YAAY,SAAS,KAAK;AAAA,QAC3C;AAAA,MACF,QAAQ;AACN,cAAM,KAAK,4BAA4B,IAAI;AAC3C,eAAO,EAAE,MAAM,MAAM,SAAS,MAAM;AAAA,MACtC;AACA,YAAM,KAAK,4BAA4B,IAAI;AAAA,IAC7C;AAEA,WAAO,EAAE,MAAM,MAAM,SAAS,MAAM;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAc,MAWjB;AACD,UAAM,KAAK,WAAW;AACtB,UAAM,cAAc,KAAK,qBAAqB,IAAI;AAClD,UAAM,SAAS,MAAM,KAAK,oBAAoB,WAAW;AACzD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,YAAY,WAAW,cAAc;AAAA,IACvD;AAEA,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,MACb,aAAa,OAAO;AAAA,MACpB,OAAO,OAAO;AAAA,MACd,WAAW,OAAO;AAAA,MAClB,aAAa,OAAO;AAAA,MACpB,eAAe,OAAO;AAAA,MACtB,YAAY,OAAO;AAAA,MACnB,WAAW,OAAO;AAAA,MAClB,UAAU,OAAO;AAAA,MACjB,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,6BAAgE;AACpE,UAAM,KAAK,WAAW;AACtB,UAAM,UAAU,MAAM,KAAK,mBAAmB;AAC9C,WAAO,QAAQ,IAAI,aAAW;AAAA,MAC5B,MAAM,OAAO;AAAA,MACb,aAAa,OAAO;AAAA,MACpB,MAAM,OAAO;AAAA,MACb,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,MAClB,aAAa,OAAO;AAAA,MACpB,eAAe,OAAO;AAAA,MACtB,OAAO,OAAO;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,WAAW,OAAO;AAAA,MAClB,WAAW,OAAO;AAAA,IACpB,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,6BAA6B,SAAmF;AACpH,UAAM,KAAK,WAAW;AACtB,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,UAAM,aAAa,oBAAI,IAA2B;AAClD,UAAM,cAAc,MAAM,KAAK,qBAAqB;AACpD,UAAM,gBAAgB,IAAI,IAAI,OAAO,KAAK,WAAW,CAAC;AAEtD,eAAW,aAAa,WAAW,CAAC,GAAG;AACrC,UAAI;AACF,cAAM,OAAO,KAAK,qBAAqB,WAAW,QAAQ,EAAE;AAC5D,cAAM,OACJ,aAAa,OAAO,UAAU,SAAS,YAAY,UAAU,SAAS,OACjE,UAAU,OACX;AACN,YAAI,CAAC,MAAM;AACT;AAAA,QACF;AAEA,cAAM,WACJ,UAAU,YAAY,OAAO,UAAU,aAAa,WAChD,UAAU,WACV;AAEN,cAAM,SAAwB;AAAA,UAC5B;AAAA,UACA,aAAa,OAAO,UAAU,gBAAgB,WAAW,UAAU,cAAc;AAAA,UACjF;AAAA,UACA;AAAA,UACA,WAAW,OAAO,UAAU,cAAc,WAAW,UAAU,YAAY;AAAA,UAC3E,aAAa,OAAO,UAAU,gBAAgB,WAAW,UAAU,cAAc;AAAA,UACjF,eAAe,OAAO,UAAU,kBAAkB,WAAW,UAAU,gBAAgB;AAAA,UACvF,OAAO,OAAO,UAAU,UAAU,WAAW,UAAU,QAAQ;AAAA,UAC/D,YAAY,OAAO,UAAU,eAAe,WAAW,UAAU,aAAa,KAAK,kBAAkB,IAAI;AAAA,UACzG,WAAW,OAAO,UAAU,cAAc,WAAW,UAAU,YAAY;AAAA,UAC3E,WAAW,OAAO,UAAU,cAAc,WAAW,UAAU,YAAY;AAAA,QAC7E;AAEA,mBAAW,IAAI,MAAM,MAAM;AAAA,MAC7B,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,UAAM,UAA8C,CAAC;AACrD,eAAW,UAAU,WAAW,OAAO,GAAG;AACxC,cAAQ,OAAO,IAAI,IAAI,KAAK,cAAc,MAAM;AAAA,IAClD;AACA,UAAM,KAAK,sBAAsB,OAAO;AAExC,QAAI,UAAU;AAEd,eAAW,QAAQ,eAAe;AAChC,UAAI,WAAW,IAAI,IAAI,GAAG;AACxB;AAAA,MACF;AACA,UAAI;AACF,cAAM,UAAAA,SAAG,GAAG,KAAK,mBAAmB,IAAI,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAC3E,mBAAW;AAAA,MACb,SAAS,OAAO;AACd,YAAI,CAAC,KAAK,gBAAgB,KAAK,GAAG;AAChC,kBAAQ,6BAA6B,IAAI,gCAAgC,KAAK;AAAA,QAChF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAY,MAAM,KAAK,yBAAyB;AACtD,QAAI,WAAW;AACb,UAAI;AACF,cAAM,sBAAsB,KAAK,qBAAqB,SAAS;AAC/D,YAAI,CAAC,WAAW,IAAI,mBAAmB,GAAG;AACxC,gBAAM,KAAK,4BAA4B,IAAI;AAAA,QAC7C;AAAA,MACF,QAAQ;AACN,cAAM,KAAK,4BAA4B,IAAI;AAAA,MAC7C;AAAA,IACF;AAEA,WAAO;AAAA,MACL,UAAU,WAAW;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACF;;;AOj5DA,IAAAE,sBAAmB;;;ACAnB,IAAAC,kBAA+B;AAC/B,IAAAC,oBAAiB;AACjB,yBAAmB;AAGnB,IAAM,cAAc;AAEpB,SAAS,oBAA4B;AACnC,SAAO,kBAAAC,QAAK,KAAK,eAAe,GAAG,WAAW;AAChD;AAEA,eAAe,iBAAkC;AAC/C,SAAO,mBAAAC,QAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AAC9C;AAEA,eAAe,mBAAmB,YAA4C;AAC5E,MAAI;AACF,UAAM,WAAW,MAAM,gBAAAC,SAAG,SAAS,YAAY,MAAM;AACrD,UAAM,UAAU,SAAS,KAAK;AAC9B,QAAI,QAAQ,SAAS,GAAG;AACtB,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,UAAU;AACtD,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAe,YAAY,YAAoB,QAA+B;AAC5E,QAAM,gBAAAA,SAAG,MAAM,kBAAAF,QAAK,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5D,QAAM,gBAAAE,SAAG,UAAU,YAAY,GAAG,MAAM;AAAA,GAAM,EAAE,MAAM,IAAM,CAAC;AAC7D,QAAM,gBAAAA,SAAG,MAAM,YAAY,GAAK,EAAE,MAAM,MAAM,MAAS;AACzD;AAEA,eAAsB,mBAAoC;AACxD,QAAM,aAAa,kBAAkB;AACrC,QAAM,WAAW,MAAM,mBAAmB,UAAU;AACpD,MAAI,UAAU;AACZ,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,MAAM,eAAe;AACpC,QAAM,YAAY,YAAY,MAAM;AACpC,SAAO;AACT;;;AC5BO,SAAS,iBAA8B;AAC5C,QAAM,eAAe;AACrB,QAAM,kBAAkB;AACxB,QAAM,eAAe,gBAAgB,MAAM,mBAAmB;AAE9D,SAAO;AAAA,IACL;AAAA,IACA,kBAAkB,IAAI,YAAY;AAAA,IAClC,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA,kBAAkB,IAAI,aAAa,QAAQ,CAAC,CAAC;AAAA,IAC7C,UAAU;AAAA,IACV,UAAU;AAAA,IACV,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,EACnB;AACF;AAEO,SAAS,iBACdC,QACA,KACQ;AACR,QAAM,OAAOA,OAAM;AACnB,QAAM,aAAaA,OAAM,YAAYA,OAAM,aACvC,GAAG,IAAI,IAAIA,OAAM,UAAU,KAC3B;AAEJ,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,IAAI,gBAAgB;AACnC,SAAO,IAAI,cAAc,IAAI,MAAM;AACnC,SAAO,IAAI,cAAc,IAAI,MAAM;AACnC,MAAI,IAAI,UAAU;AAChB,WAAO,IAAI,gBAAgB,IAAI,QAAQ;AAAA,EACzC,WAAWA,OAAM,UAAU;AACzB,WAAO,IAAI,gBAAgBA,OAAM,QAAQ;AAAA,EAC3C;AAEA,SAAO,GAAG,UAAU,IAAI,OAAO,SAAS,CAAC;AAC3C;;;AFxDA,IAAM,QAAQ,eAAe;AAC7B,IAAM,oBAAoB,MAAM;AAChC,IAAM,aAAa;AACnB,IAAM,cAAc,iBAAiB,KAAK;AAC1C,IAAM,wBAAwB,MAAM,WAAW,MAAM,mBAAmB,MAAM;AAC9E,IAAM,qBAAqB,MAAM;AACjC,IAAM,aAAa,MAAM;AACzB,IAAM,gBAAgB,MAAM;AAC5B,IAAM,eAAe,MAAM;AAC3B,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,8BAA8B,IAAI,KAAK;AAC7C,IAAM,oBAAoB,KAAK,KAAK;AACpC,IAAM,mBAAmB,IAAI,KAAK,KAAK;AAgDvC,IAAM,eAAN,cAA2B,MAAM;AAAA,EAG/B,YAAY,SAAiB,MAAyC;AACpE,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AACF;AAEA,SAAS,SAAiB;AACxB,UAAO,oBAAI,KAAK,GAAE,YAAY;AAChC;AAEA,SAAS,eAAe,KAA+C;AACrE,MAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,QAAQ,UAAU,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,QAAQ,MAAM,EAAE;AAChC,SAAO,2BAAO,OAAO;AACvB;AAEA,SAAS,yBAAyB,OAAsB,iBAAwC;AAC9F,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,SAAO,KAAK,IAAI,GAAG,QAAQ,eAAe;AAC5C;AAEA,SAAS,wBAAwB,QAA2C;AAC1E,MAAI,CAAC,UAAU,CAAC,OAAO,YAAY;AACjC,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,WAAW,YAAY;AAChC,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,wBAAwB,SAAgC;AAC/D,QAAM,UAAU;AAAA,IACd,YAAY,QAAQ,cAAc;AAAA,IAClC,eAAe,QAAQ,iBAAiB;AAAA,IACxC,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,aAAa,QAAQ,eAAe;AAAA,IACpC,uBAAuB,QAAQ,yBAAyB;AAAA,IACxD,QAAQ,QAAQ,UAAU;AAAA,EAC5B;AACA,SAAO,KAAK,UAAU,OAAO;AAC/B;AAEA,SAAS,YAAY,SAAwB,QAAwB;AACnE,SAAO,oBAAAC,QAAO,WAAW,UAAU,MAAM,EAAE,OAAO,wBAAwB,OAAO,CAAC,EAAE,OAAO,KAAK;AAClG;AAEA,SAAS,cAAc,SAAwB,QAA+B;AAC5E,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW,YAAY,SAAS,MAAM;AAAA,EACxC;AACF;AAEA,SAAS,iBAAiB,SAAwB,QAAyB;AACzE,MAAI,CAAC,QAAQ,WAAW;AACtB,WAAO;AAAA,EACT;AACA,QAAM,WAAW,YAAY,SAAS,MAAM;AAC5C,SAAO,aAAa,QAAQ;AAC9B;AAEA,eAAe,qBAAqB,YAAoB,MAAyD;AAC/G,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,GAAM;AAE3D,MAAI;AACF,UAAM,OAAO,IAAI,gBAAgB;AAAA,MAC/B,mBAAmB;AAAA,MACnB,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,sBAAsB,SAAS,eAAe,SAAS;AAAA,IACzD,CAAC;AAED,UAAM,WAAW,MAAM,MAAM,8CAA8C;AAAA,MACzE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA;AAAA,MACA,QAAQ,WAAW;AAAA,IACrB,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACxD,YAAM,UAAU,YACZ,gCAAgC,SAAS,MAAM,MAAM,SAAS,KAC9D,gCAAgC,SAAS,MAAM;AACnD,YAAM,IAAI,aAAa,SAAS,SAAS;AAAA,IAC3C;AAEA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,cAAc;AACjC,YAAM;AAAA,IACR;AAEA,QAAI,iBAAiB,SAAS,MAAM,SAAS,cAAc;AACzD,YAAM,IAAI,aAAa,mCAAmC,SAAS;AAAA,IACrE;AAEA,UAAM,IAAI;AAAA,MACR,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MACzC;AAAA,IACF;AAAA,EACF,UAAE;AACA,iBAAa,OAAO;AAAA,EACtB;AACF;AAEA,SAAS,4BAA4B,UAA4D;AAC/F,MAAI,CAAC,SAAS,SAAS;AACrB,UAAM,UAAU,SAAS,WAAW;AACpC,UAAM,IAAI,aAAa,SAAS,SAAS;AAAA,EAC3C;AAEA,MAAI,CAAC,SAAS,UAAU;AACtB,UAAM,IAAI,aAAa,iDAAiD,SAAS;AAAA,EACnF;AAEA,MAAI,SAAS,SAAS,gBAAgB,SAAS,SAAS,YAAY,SAAS,kBAAkB;AAC7F,UAAM,IAAI,aAAa,8CAA8C,SAAS;AAAA,EAChF;AAEA,MAAI,SAAS,SAAS,0BAA0B,SAAS,SAAS,qBAAqB;AACrF,UAAM,IAAI,aAAa,kDAAkD,SAAS;AAAA,EACpF;AAEA,QAAM,QAAQ,SAAS,SAAS,SAAS;AACzC,SAAO,EAAE,MAAM;AACjB;AAEA,SAAS,qBAAqB,UAAwC;AACpE,MAAI,CAAC,SAAS,SAAS;AACrB;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,SAAS,UAAU;AACrC;AAAA,EACF;AAEA,MAAI,SAAS,OAAO,kBAAkB;AACpC,UAAM,IAAI;AAAA,MACR,kDAAkD,gBAAgB;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,QAA8B,YAAoC,CAAC,GAAkB;AAC5G,QAAM,OAAO,wBAAwB,MAAM;AAC3C,QAAM,QAAQ,SAAS;AAEvB,QAAM,QACJ,UAAU,OAAO,SACb,OAAO,SACP,QACE,WACA;AAER,QAAM,OAAsB;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,QAAQ,OAAO;AAAA,IAC7B,mBAAmB;AAAA,IACnB,eAAe,QAAQ,iBAAiB;AAAA,IACxC,kBAAkB,eAAe,QAAQ,UAAU;AAAA,IACnD,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,aAAa,QAAQ,eAAe;AAAA,IACpC,SAAS;AAAA,IACT,OAAO,QAAQ,yBAAyB;AAAA,IACxC,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,WAAW,eAAe,aAAa;AAAA,IACvC,cAAc,eAAe,gBAAgB;AAAA,IAC7C,YAAY;AAAA,EACd;AAEA,SAAO,EAAE,GAAG,MAAM,GAAG,UAAU;AACjC;AAEA,SAAS,eAAe,OAAiD;AACvE,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,IAAI;AACpD,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,SAAO,OAAO,MAAM,MAAM,IAAI,OAAO;AACvC;AAEA,IAAM,iBAAN,MAAqB;AAAA,EAArB;AACE,SAAQ,QAA8B;AACtC,SAAQ,iBAAuC;AAC/C,SAAQ,sBAAqD;AAAA;AAAA,EAE7D,MAAM,kBAA0C;AAC9C,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,MAAM,UAAU,UAAsC,CAAC,GAA2B;AAChF,UAAM,eAAe,QAAQ,QAAQ,YAAY;AACjD,UAAM,SAAS,MAAM,iBAAiB;AACtC,UAAM,SAAS,MAAM,iBAAiB;AAEtC,QAAI,CAAC,QAAQ,YAAY;AACvB,YAAM,SAAS,gBAAgB,IAAI;AACnC,WAAK,QAAQ;AACb,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,cAAc,eAAe,OAAO,WAAW;AACrD,UAAM,iBAAiB,eAAe,OAAO,cAAc;AAC3D,UAAM,cACH,OAAO,WAAW,WAAW,OAAO,WAAW,aAC/C,mBAAmB,QAAQ,iBAAiB,mBAAmB;AAElE,QAAI,gBAA+B,EAAE,GAAG,OAAO;AAC/C,UAAM,iBAAiB,iBAAiB,eAAe,MAAM;AAE7D,QAAI,oBAAoB;AAExB,QAAI,gBAAgB,QAAQ,cAAc,MAAM,mBAAmB;AACjE,0BAAoB;AACpB,YAAM,UAAU;AAAA,QACd,GAAG;AAAA,QACH,aAAa,IAAI,KAAK,iBAAiB,EAAE,YAAY;AAAA,MACvD;AACA,YAAM,SAAS,cAAc,SAAS,MAAM;AAC5C,sBAAgB;AAChB,YAAM,eAAe,MAAM;AAAA,IAC7B;AAEA,UAAM,WAAW,QAAQ,cAAc,UAAU,KAAK,CAAC;AAEvD,UAAM,SAAS,WACX,gBAAgB,MAAM;AAAA,MACpB,OAAO;AAAA,MACP,SAAS;AAAA,MACT,OAAO;AAAA,IACT,CAAC,IACD,gBAAgB,aAAa;AACjC,SAAK,QAAQ;AAEb,UAAM,gBACJ,gBAAgB,cAAc,YAAY,sBAAsB,QAAQ,qBAAqB;AAE/F,QAAI,CAAC,eAAe;AAClB,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,uBAAuB,CAAC,cAAc;AAC7C,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,SAAS,YAAoC;AACjD,UAAI;AACF,cAAM,SAAS,MAAM,qBAAqB,cAAc,YAAa,SAAS;AAC9E,6BAAqB,MAAM;AAC3B,cAAM,aAAa,4BAA4B,MAAM;AACrD,cAAM,UAAyB;AAAA,UAC7B,YAAY,cAAc;AAAA,UAC1B,eAAe,WAAW;AAAA,UAC1B,gBAAgB,OAAO;AAAA,UACvB,aAAa,IAAI,KAAK,KAAK,IAAI,IAAI,2BAA2B,EAAE,YAAY;AAAA,UAC5E,QAAQ;AAAA,UACR,uBAAuB;AAAA,QACzB;AAEA,cAAM,SAAS,cAAc,SAAS,MAAM;AAE5C,cAAM,eAAe,MAAM;AAC3B,cAAM,SAAS,gBAAgB,MAAM;AACrC,aAAK,QAAQ;AACb,eAAO;AAAA,MACT,SAAS,OAAO;AACd,cAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AAEzD,YAAI,iBAAiB,gBAAgB,MAAM,SAAS,WAAW;AAC7D,gBAAMC,kBAAgC;AAAA,YACpC;AAAA,cACE,GAAG;AAAA,cACH,QAAQ,WAAW,aAAa,cAAc,WAAW,aAAa,aAAa;AAAA,cACnF,uBAAuB;AAAA,cACvB,aAAa,IAAI,KAAK,KAAK,IAAI,IAAI,2BAA2B,EAAE,YAAY;AAAA,YAC9E;AAAA,YACA;AAAA,UACF;AACA,gBAAM,eAAeA,eAAc;AACnC,gBAAMC,YAAW,gBAAgBD,iBAAgB;AAAA,YAC/C,OAAOA,gBAAe,UAAU;AAAA,YAChC,OAAO;AAAA,UACT,CAAC;AACD,eAAK,QAAQC;AACb,iBAAOA;AAAA,QACT;AAEA,cAAM,iBAAgC,cAAc;AAAA,UAClD,YAAY,cAAc;AAAA,UAC1B,eAAe,cAAc,iBAAiB;AAAA,UAC9C,gBAAgB,cAAc,kBAAkB;AAAA,UAChD,aAAa;AAAA,UACb,QAAQ;AAAA,UACR,uBAAuB;AAAA,QACzB,GAAG,MAAM;AACT,cAAM,eAAe,cAAc;AACnC,cAAM,WAAW,gBAAgB,gBAAgB,EAAE,OAAO,QAAQ,CAAC;AACnE,aAAK,QAAQ;AACb,eAAO;AAAA,MACT;AAAA,IACF;AAEA,SAAK,sBAAsB,OAAO;AAClC,QAAI;AACF,aAAO,MAAM,KAAK;AAAA,IACpB,UAAE;AACA,WAAK,sBAAsB;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,YAA4C;AACzD,UAAM,UAAU,WAAW,KAAK;AAChC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAM,SAAS,MAAM,iBAAiB;AACtC,UAAM,SAAS,oBAAAF,QAAO,WAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AAEvE,UAAM,SAAS,MAAM,qBAAqB,SAAS,YAAY;AAC/D,yBAAqB,MAAM;AAC3B,UAAM,aAAa,4BAA4B,MAAM;AACrD,UAAM,SAAwB;AAAA,MAC5B,YAAY;AAAA,MACZ,eAAe,WAAW;AAAA,MAC1B,gBAAgB,OAAO;AAAA,MACvB,aAAa,IAAI,KAAK,KAAK,IAAI,IAAI,2BAA2B,EAAE,YAAY;AAAA,MAC5E,QAAQ;AAAA,MACR,uBAAuB;AAAA,IACzB;AAEA,UAAM,SAAS,cAAc,QAAQ,MAAM;AAE3C,UAAM,eAAe,MAAM;AAC3B,UAAM,SAAS,gBAAgB,QAAQ;AAAA,MACrC,SAAS,qBAAqB,OAAO,MAAM,GAAG,CAAC,CAAC;AAAA,IAClD,CAAC;AACD,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AAAA,EAEA,kBAAkB,QAAuB,cAAqC;AAC5E,UAAM,oBAAoB,yBAAyB,OAAO,cAAc,YAAY;AACpF,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,0BAA0B,UAA+B,CAAC,GAAS;AACjE,QAAI,KAAK,gBAAgB;AACvB;AAAA,IACF;AAEA,UAAM,eAAe,QAAQ,QAAQ,KAAK;AAC1C,SAAK,kBAAkB,YAAY;AACjC,UAAI;AACF,cAAM,KAAK,UAAU,EAAE,aAAa,CAAC;AAAA,MACvC,SAAS,OAAO;AACd,gBAAQ,KAAK,sCAAsC,KAAK;AAAA,MAC1D,UAAE;AACA,aAAK,iBAAiB;AAAA,MACxB;AAAA,IACF,GAAG;AAAA,EACL;AACF;AAEO,IAAM,iBAAiB,IAAI,eAAe;AAIjD,SAAS,uBAAuB,SAA6C;AAC3E,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,QAAM,aAAa,QAAQ,YAAY;AACvC,SACE,WAAW,SAAS,SAAS,KAC7B,WAAW,SAAS,UAAU,KAC9B,WAAW,SAAS,SAAS,KAC7B,WAAW,SAAS,kBAAkB;AAE1C;AAOO,SAAS,0BAA0B,QAAgC;AACxE,MAAI,OAAO,OAAO;AAChB,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,UAAU,WAAW,OAAO,UAAU,eAAe,OAAO,UAAU,SAAS;AACxF,WAAO;AAAA,EACT;AAEA,MAAI,uBAAuB,OAAO,KAAK,GAAG;AACxC,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,UAAU;AAC1B;;;AGpfA,IAAAG,kBAA+B;AAC/B,IAAAC,oBAAiB;;;ACCV,IAAM,4BAA4B;;;ACFlC,SAASC,UAAS,OAAkD;AACzE,SAAO,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEO,SAAS,YAAY,OAA+B;AACzD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,SAAO,OAAO,MAAM,MAAM,IAAI,OAAO,IAAI,KAAK,MAAM,EAAE,YAAY;AACpE;;;ACFA,IAAM,kCAAkC;AACxC,IAAM,wBAAwB;AAEvB,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAG9C,YAAY,SAAiB,SAAwB,MAAM;AACzD,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AACF;AAEA,SAAS,iBAAiB,OAAuB;AAC/C,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,QAAQ,SAAS,GAAG,IAAI,QAAQ,MAAM,GAAG,EAAE,IAAI;AACxD;AAEO,SAAS,yBAAiC;AAC/C,QAAM,UAAU,OAAO,QAAQ,IAAI,0BAA0B,WACzD,QAAQ,IAAI,wBACZ;AAEJ,MAAI,QAAQ,KAAK,EAAE,WAAW,GAAG;AAC/B,WAAO;AAAA,EACT;AAEA,SAAO,iBAAiB,OAAO;AACjC;AAEA,SAAS,aAAa,UAA0B;AAC9C,QAAM,UAAU,uBAAuB;AACvC,QAAM,iBAAiB,SAAS,WAAW,GAAG,IAAI,WAAW,IAAI,QAAQ;AACzE,SAAO,GAAG,OAAO,GAAG,cAAc;AACpC;AAEA,SAAS,kBAAkB,OAA0C;AACnE,MAAI,CAACC,UAAS,KAAK,GAAG;AACpB,WAAO;AAAA,EACT;AAIA,MAAIA,UAAS,MAAM,QAAQ,GAAG;AAC5B,UAAM,SAAS,kBAAkB,MAAM,QAAQ;AAC/C,QAAI,QAAQ;AACV,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,YAAY,YAAY,MAAM,SAAS;AAC7C,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,OAAO,MAAM,aAAa;AAChD,MAAI,CAAC,OAAO,SAAS,aAAa,KAAK,kBAAkB,2BAA2B;AAClF,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,MAAM,QAAQ,MAAM,QAAQ,IAAI,MAAM,WAAW,CAAC;AACtE,QAAM,WAAW,YACd,IAAI,CAAC,UAAWA,UAAS,KAAK,IAAI,QAAQ,IAAK,EAC/C,OAAO,CAAC,UAA4C,QAAQ,KAAK,CAAC,EAClE,IAAI,CAAC,UAAU;AACd,UAAM,OAAOA,UAAS,MAAM,IAAI,IAAI,MAAM,OAAO,CAAC;AAClD,UAAM,WAAWA,UAAS,MAAM,QAAQ,IAAI,MAAM,WAAW;AAC7D,WAAO;AAAA,MACL,MAAM,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;AAAA,MACpD,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc;AAAA,MACzE;AAAA,MACA;AAAA,MACA,WAAW,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAAA,MACnE,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc;AAAA,MACzE,eAAe,OAAO,MAAM,kBAAkB,WAAW,MAAM,gBAAgB;AAAA,MAC/E,OAAO,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAAA,MACvD,YAAY,OAAO,MAAM,eAAe,WAAW,MAAM,aAAa;AAAA,MACtE,WAAW,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAAA,MACnE,WAAW,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAAA,IACrE;AAAA,EACF,CAAC,EACA,OAAO,CAAC,UAAU,MAAM,KAAK,KAAK,EAAE,SAAS,CAAC;AAEjD,QAAM,cAAc,MAAM;AAC1B,QAAM,eAAeA,UAAS,WAAW,IAAI,cAAc;AAE3D,SAAO;AAAA,IACL,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA,mBAAmB,OAAO,MAAM,sBAAsB,WAAW,MAAM,oBAAoB;AAAA,IAC3F;AAAA,EACF;AACF;AAEA,eAAe,YACb,QACA,UACA,YACA,MACA,SACY;AACZ,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,qBAAqB;AAE1E,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,aAAa,QAAQ,GAAG;AAAA,MACnD;AAAA,MACA,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,0BAA0B;AAAA,MAC5B;AAAA,MACA,MAAM,OAAO,YAAY,WACrB,UACA,SAAS,SACP,SACA,KAAK,UAAU,IAAI;AAAA,MACzB,QAAQ,WAAW;AAAA,IACrB,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,UAAU,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACpD,YAAM,IAAI;AAAA,QACR,WAAW,8BAA8B,SAAS,MAAM;AAAA,QACxD,SAAS;AAAA,MACX;AAAA,IACF;AAEA,WAAQ,MAAM,SAAS,KAAK;AAAA,EAC9B,SAAS,OAAO;AACd,QAAI,iBAAiB,sBAAsB;AACzC,YAAM;AAAA,IACR;AAEA,QAAI,iBAAiB,SAAS,MAAM,SAAS,cAAc;AACzD,YAAM,IAAI,qBAAqB,+BAA+B;AAAA,IAChE;AAEA,UAAM,IAAI;AAAA,MACR,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF,UAAE;AACA,iBAAa,OAAO;AAAA,EACtB;AACF;AAEA,eAAsB,oBAAoB,YAAuD;AAC/F,QAAM,WAAW,MAAM,YAAkC,OAAO,qBAAqB,UAAU;AAC/F,SAAO,kBAAkB,SAAS,QAAQ;AAC5C;AAEA,eAAsB,wBAAwB,YAA4C;AACxF,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,YAAY,SAAS,SAAS;AACvC;AAEA,eAAsB,mBACpB,YACA,UACA,SAC+B;AAC/B,QAAM,qBAAqB,OAAO,SAAS,uBAAuB,WAC9D,QAAQ,qBACR,KAAK,UAAU,QAAQ;AAC3B,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,kBAAkB;AAAA,EACnC;AAEA,QAAM,aAAa,kBAAkB,SAAS,QAAQ;AACtD,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,qBAAqB,yDAAyD;AAAA,EAC1F;AAEA,QAAM,SAAS,SAAS,WAAW,UAAU,UAAU;AACvD,SAAO;AAAA,IACL;AAAA,IACA,UAAU;AAAA,EACZ;AACF;;;ACnMA,IAAAC,mBAAiD;AACjD,IAAAC,oBAAiB;AACjB,IAAAC,eAAiC;;;ACFjC,gCAAsB;AACtB,sBAAyB;AACzB,IAAAC,oBAAiB;;;ACFjB,IAAAC,kBAAuC;AACvC,IAAAC,oBAAiB;AAKjB,IAAM,iBAAkC;AACxC,IAAM,YAAY,CAAC,gBAAgB,kBAAkB,YAAY;AAEjE,IAAI,eAAqC;AAEzC,SAAS,WAAW,WAAqD;AACvE,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,kBAAAC,QAAK,QAAQ,SAAS;AAEzC,MAAI;AACF,UAAM,YAAQ,0BAAS,UAAU;AACjC,QAAI,MAAM,OAAO,GAAG;AAClB,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAEA,SAAS,4BAA2C;AAClD,QAAM,aAAuB,CAAC;AAC9B,QAAM,uBAAuB;AAC7B,QAAM,gBAAgB,qBAAqB;AAC3C,QAAM,kBAAkB,CAAC,WAAW,OAAO;AAE3C,MAAI,eAAe;AACjB,eAAW;AAAA,MACT,kBAAAA,QAAK,KAAK,eAAe,qBAAqB,gBAAgB,GAAG,iBAAiB,OAAO,UAAU;AAAA,IACrG;AACA,eAAW;AAAA,MACT,kBAAAA,QAAK,KAAK,eAAe,qBAAqB,gBAAgB,GAAG,iBAAiB,OAAO,OAAO;AAAA,IAClG;AAAA,EACF;AAEA,QAAM,cAAc,QAAQ,IAAI;AAChC,aAAW,KAAK,kBAAAA,QAAK,KAAK,aAAa,gBAAgB,GAAG,iBAAiB,OAAO,UAAU,CAAC;AAC7F,aAAW,KAAK,kBAAAA,QAAK,KAAK,aAAa,gBAAgB,GAAG,iBAAiB,OAAO,OAAO,CAAC;AAE1F,aAAW,aAAa,YAAY;AAClC,UAAM,WAAW,WAAW,SAAS;AACrC,QAAI,UAAU;AACZ,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,oBAA6B;AACpC,SAAO,OAAO,QAAQ,UAAU,aAAa,YAAY,QAAQ,SAAS,SAAS,SAAS;AAC9F;AAEA,SAAS,sBAAqC;AAC5C,aAAW,OAAO,WAAW;AAC3B,UAAM,QAAQ,QAAQ,IAAI,GAAG;AAC7B,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AACA,UAAM,WAAW,WAAW,KAAK;AACjC,QAAI,UAAU;AACZ,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,8BAA6C;AACpD,QAAM,kBAAkB,CAAC,WAAW,SAAS,KAAK;AAClD,QAAM,YAAY,CAAC,YAAY,OAAO;AAEtC,MAAI,UAAU,kBAAAA,QAAK,QAAQ,SAAS;AACpC,MAAI,OAAO;AACX,SAAO,YAAY,MAAM;AACvB,eAAW,YAAY,WAAW;AAChC,YAAM,YAAY;AAAA,QAChB,kBAAAA,QAAK,KAAK,SAAS,gBAAgB,GAAG,iBAAiB,QAAQ;AAAA,MACjE;AACA,UAAI,WAAW;AACb,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AACP,cAAU,kBAAAA,QAAK,QAAQ,OAAO;AAAA,EAChC;AACA,SAAO;AACT;AAEA,SAAS,uBAAsC;AAC7C,QAAM,YAAY,QAAQ,IAAI,QAAQ;AACtC,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AACA,QAAM,UAAU,UACb,MAAM,kBAAAA,QAAK,SAAS,EACpB,IAAI,WAAS,MAAM,KAAK,CAAC,EACzB,OAAO,OAAO;AACjB,QAAM,QAAQ,QAAQ,aAAa,UAC/B,CAAC,aAAa,aAAa,aAAa,OAAO,IAC/C,CAAC,OAAO;AAEZ,aAAW,SAAS,SAAS;AAC3B,eAAW,QAAQ,OAAO;AACxB,YAAM,YAAY,WAAW,kBAAAA,QAAK,KAAK,OAAO,IAAI,CAAC;AACnD,UAAI,WAAW;AACb,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AA4BA,SAAS,uBAAuB,QAAgC;AAC9D,SAAO;AAAA,IACL,WAAW;AAAA,IACX,MAAM;AAAA,IACN,QAAQ,UAAU;AAAA,IAClB,QAAQ;AAAA,IACR,SAAS;AAAA,EACX;AACF;AAEA,SAAS,4BAA2C;AAClD,QAAM,eAAe,0BAA0B;AAC/C,MAAI,cAAc;AAChB,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO,uBAAuB,mDAAmD;AACnF;AAEA,SAAS,yBAAwC;AAC/C,QAAM,UAAU,oBAAoB;AACpC,MAAI,SAAS;AACX,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,kBAAkB,4BAA4B;AACpD,MAAI,iBAAiB;AACnB,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,eAAe,qBAAqB;AAC1C,MAAI,cAAc;AAChB,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO,uBAAuB;AAChC;AAEA,SAAS,yBAAwC;AAC/C,QAAM,gBAAgB,0BAA0B;AAChD,MAAI,cAAc,WAAW;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB,uBAAuB;AAC9C,MAAI,eAAe,WAAW;AAC5B,WAAO;AAAA,EACT;AAGA,MAAI,kBAAkB,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,eAAsB,qBAAqD;AACzE,iBAAe,uBAAuB;AACtC,SAAO,EAAE,GAAG,aAAa;AAC3B;AAkBO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAG9C,YAAY,QAA+B,SAAkB;AAC3D,UAAM,WAAW,OAAO,UAAU,4BAA4B;AAC9D,WAAO,eAAe,MAAM,WAAW,SAAS;AAChD,SAAK,OAAO;AACZ,SAAK,SAAS,EAAE,GAAG,OAAO;AAAA,EAC5B;AACF;AAEA,eAAsB,kBAAmC;AACvD,QAAM,SAAS,MAAM,mBAAmB;AACxC,MAAI,CAAC,OAAO,aAAa,CAAC,OAAO,MAAM;AACrC,UAAM,IAAI,qBAAqB,MAAM;AAAA,EACvC;AACA,SAAO,OAAO;AAChB;;;ADtPA,IAAM,oBAAoB;AAC1B,IAAM,wBAAwB;AAE9B,IAAM,iCAAiC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,wBAAwB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAI,gBAA4C;AAChD,IAAI,kBAAkB;AAEtB,SAASC,UAAS,OAAkD;AAClE,SAAO,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,aAAa,QAA4B;AAChD,SAAO,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AACtE;AAEA,eAAe,WACb,SACA,MACA,YAAY,KAC0C;AACtD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,YAAQ,iCAAM,SAAS,MAAM;AAAA,MACjC,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,MAChC,KAAK,QAAQ;AAAA,IACf,CAAC;AAED,QAAI,SAAS;AACb,QAAI,SAAS;AAEb,UAAM,QAAQ,GAAG,QAAQ,WAAS;AAChC,gBAAU,MAAM,SAAS;AAAA,IAC3B,CAAC;AAED,UAAM,QAAQ,GAAG,QAAQ,WAAS;AAChC,gBAAU,MAAM,SAAS;AAAA,IAC3B,CAAC;AAED,UAAM,UAAU,WAAW,MAAM;AAC/B,YAAM,KAAK;AACX,aAAO,IAAI,MAAM,sBAAsB,OAAO,IAAI,KAAK,KAAK,GAAG,CAAC,EAAE,CAAC;AAAA,IACrE,GAAG,SAAS;AAEZ,UAAM,GAAG,SAAS,WAAS;AACzB,mBAAa,OAAO;AACpB,aAAO,KAAK;AAAA,IACd,CAAC;AAED,UAAM,GAAG,SAAS,UAAQ;AACxB,mBAAa,OAAO;AACpB,UAAI,SAAS,KAAK,CAAC,OAAO,KAAK,KAAK,OAAO,KAAK,GAAG;AACjD,gBAAQ,EAAE,QAAQ,QAAQ,UAAU,KAAK,CAAC;AAC1C;AAAA,MACF;AACA,cAAQ,EAAE,QAAQ,UAAU,KAAK,CAAC;AAAA,IACpC,CAAC;AAAA,EACH,CAAC;AACH;AAEA,eAAe,gBAAgB,MAAsE;AACnG,QAAM,YAAY,MAAM,gBAAgB;AACxC,QAAM,eAAe,UAAU,SAAS,KAAK;AAC7C,QAAM,UAAU,eAAe,QAAQ,WAAW;AAClD,QAAM,cAAc,eAAe,CAAC,WAAW,GAAG,IAAI,IAAI;AAC1D,SAAO,WAAW,SAAS,WAAW;AACxC;AAEA,SAAS,oBAAoB,QAA4C;AACvE,QAAM,UAAsC,CAAC;AAC7C,QAAM,QAAQ,OAAO,MAAM,OAAO,EAAE,IAAI,UAAQ,KAAK,KAAK,CAAC,EAAE,OAAO,OAAO;AAE3E,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,KAAK,MAAM,8EAA8E;AACvG,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AACA,UAAM,CAAC,EAAE,KAAK,UAAU,UAAU,IAAI;AACtC,UAAM,QAAQ,SAAS,YAAY;AACnC,YAAQ,KAAK;AAAA,MACX;AAAA,MACA;AAAA,MACA,SAAS,eAAe;AAAA,IAC1B,CAAC;AAAA,EACH;AAEA,SAAO,QAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,cAAc,EAAE,GAAG,CAAC;AAC1D;AAEA,SAAS,gBAAgB,WAAsE;AAC7F,QAAM,SAAS,KAAK,MAAM,SAAS;AACnC,MAAI,CAACA,UAAS,MAAM,GAAG;AACrB,WAAO;AAAA,MACL,cAAc;AAAA,MACd,aAAa;AAAA,IACf;AAAA,EACF;AAEA,QAAM,aAAaA,UAAS,OAAO,UAAU,IAAI,OAAO,aAAa,CAAC;AACtE,QAAM,eAAe,aAAa,OAAO,KAAK,UAAU,CAAC;AAEzD,QAAM,WAAWA,UAAS,WAAW,QAAQ,IAAI,WAAW,WAAW,CAAC;AACxE,QAAM,oBAAoBA,UAAS,SAAS,UAAU,IAAI,SAAS,aAAa,CAAC;AACjF,QAAM,cAAc,aAAa,OAAO,KAAK,iBAAiB,CAAC;AAE/D,SAAO;AAAA,IACL,cAAc,aAAa,SAAS,IAAI,eAAe;AAAA,IACvD,aAAa,YAAY,SAAS,IAAI,cAAc;AAAA,EACtD;AACF;AAEA,eAAe,sBAA8C;AAC3D,QAAM,aAAa;AAAA,IACjB,QAAQ,IAAI;AAAA,IACZ,kBAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,YAAY,QAAQ,oBAAoB;AAAA,IACjE,kBAAAA,QAAK,KAAK,QAAQ,IAAI,GAAG,gBAAgB,WAAW,SAAS,YAAY,QAAQ,oBAAoB;AAAA,EACvG,EAAE,OAAO,CAAC,cAAmC,QAAQ,SAAS,CAAC;AAE/D,aAAW,aAAa,YAAY;AAClC,QAAI;AACF,aAAO,UAAM,0BAAS,WAAW,MAAM;AAAA,IACzC,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAe,uBAA+C;AAC5D,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,IAAK;AAE1D,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,mBAAmB;AAAA,MAC9C,QAAQ,WAAW;AAAA,MACnB,SAAS;AAAA,QACP,cAAc;AAAA,MAChB;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,aAAO;AAAA,IACT;AAEA,WAAO,MAAM,SAAS,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,iBAAa,OAAO;AAAA,EACtB;AACF;AAEA,eAAe,iBAA6E;AAC1F,QAAM,QAAQ,MAAM,oBAAoB;AACxC,MAAI,OAAO;AACT,QAAI;AACF,aAAO,gBAAgB,KAAK;AAAA,IAC9B,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,qBAAqB;AAC1C,MAAI,QAAQ;AACV,QAAI;AACF,aAAO,gBAAgB,MAAM;AAAA,IAC/B,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AAAA,IACL,cAAc;AAAA,IACd,aAAa;AAAA,EACf;AACF;AAEA,eAAe,mBAA2C;AACxD,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,gBAAgB,CAAC,WAAW,CAAC;AACtD,UAAM,QAAQ,OAAO,KAAK;AAC1B,WAAO,MAAM,SAAS,IAAI,QAAQ;AAAA,EACpC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,qBAA0D;AACvE,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,gBAAgB,CAAC,YAAY,MAAM,CAAC;AAC7D,WAAO,oBAAoB,MAAM;AAAA,EACnC,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,eAAsB,uBAAuB,eAAe,OAAqC;AAC/F,QAAM,MAAM,KAAK,IAAI;AACrB,MAAI,CAAC,gBAAgB,iBAAkB,MAAM,kBAAmB,uBAAuB;AACrF,WAAO;AAAA,EACT;AAEA,QAAM,CAAC,YAAY,gBAAgB,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,IACnE,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,EACnB,CAAC;AAED,QAAM,aAAa,oBAAI,IAAsC;AAC7D,aAAW,SAAS,gBAAgB;AAClC,eAAW,IAAI,MAAM,KAAK,KAAK;AAAA,EACjC;AAEA,aAAW,cAAc,WAAW,aAAa;AAC/C,QAAI,CAAC,WAAW,IAAI,UAAU,GAAG;AAC/B,iBAAW,IAAI,YAAY;AAAA,QACzB,KAAK;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,uBAAuB,MAAM,KAAK,WAAW,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,cAAc,EAAE,GAAG,CAAC;AAEtG,QAAM,WAAgC;AAAA,IACpC,oBAAoB,aAAa,WAAW,YAAY;AAAA,IACxD,mBAAmB,aAAa,WAAW,WAAW;AAAA,IACtD,gBAAgB;AAAA,IAChB;AAAA,IACA,WAAW;AAAA,EACb;AAEA,kBAAgB;AAChB,oBAAkB;AAClB,SAAO;AACT;;;AEjWA,IAAM,eAAe;AAErB,SAAS,UAAU,OAAuB;AACxC,SAAO,MAAM,QAAQ,cAAc,EAAE;AACvC;AAEA,SAAS,oBAAoB,OAAuB;AAClD,SAAO,MAAM,QAAQ,QAAQ,GAAG,EAAE,KAAK;AACzC;AAgBO,SAAS,sBACd,OACA,UAII,CAAC,GACG;AACR,QAAM,WAAW,QAAQ,YAAY;AACrC,MAAI,UAAU,QAAQ,OAAO,UAAU,aAAa;AAClD,WAAO;AAAA,EACT;AAEA,QAAM,aACJ,OAAO,UAAU,WACb,QACA,iBAAiB,QACf,MAAM,UACN,OAAO,KAAK;AAEpB,MAAI,UAAU,oBAAoB,UAAU,UAAU,CAAC;AACvD,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,WAAW,8BAA8B,GAAG;AACtD,cAAU,QAAQ,QAAQ,kDAAkD,EAAE;AAAA,EAChF;AAEA,QAAM,QAAQ,QAAQ,YAAY;AAElC,MAAI,QAAQ,qBAAqB,MAAM,SAAS,QAAQ,KAAK,MAAM,SAAS,WAAW,IAAI;AACzF,WAAO,QAAQ;AAAA,EACjB;AAEA,MAAI,MAAM,SAAS,YAAY,KAAK,MAAM,SAAS,gBAAgB,KAAK,MAAM,SAAS,mBAAmB,KAAK,MAAM,SAAS,KAAK,GAAG;AACpI,cAAU;AAAA,EACZ,WAAW,MAAM,SAAS,SAAS,KAAK,MAAM,SAAS,WAAW,GAAG;AACnE,cAAU;AAAA,EACZ,WACE,MAAM,SAAS,SAAS,KACxB,MAAM,SAAS,OAAO,KACtB,MAAM,SAAS,cAAc,KAC7B,MAAM,SAAS,YAAY,GAC3B;AACA,cAAU;AAAA,EACZ,WAAW,MAAM,SAAS,YAAY,KAAK,MAAM,SAAS,QAAQ,GAAG;AACnE,cAAU;AAAA,EACZ,WAAW,MAAM,SAAS,cAAc,KAAK,MAAM,SAAS,UAAU,GAAG;AAGvE,QAAI,MAAM,SAAS,QAAQ,GAAG;AAE5B,YAAM,QAAQ,QAAQ,MAAM,SAAS;AACrC,UAAI,MAAM,SAAS,GAAG;AACpB,kBAAU,MAAM,MAAM,SAAS,CAAC,EAAE,KAAK;AAAA,MACzC;AAAA,IACF,OAAO;AACL,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,YAAY,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY;AAC9E,MAAI,QAAQ,SAAS,WAAW;AAC9B,cAAU,GAAG,QAAQ,MAAM,GAAG,SAAS,EAAE,QAAQ,CAAC;AAAA,EACpD;AAEA,SAAO;AACT;;;AHwCA,IAAM,0BAA0B;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AAQX,IAAM,cAAwC;AAAA,EAC5C,OAAO;AAAA,EACP,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,WAAW;AAAA,EACX,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,4BAA4B;AAAA,EAC5B,UAAU;AAAA,IACR,aAAa;AAAA,IACb,eAAe;AAAA,EACjB;AAAA,EACA,QAAQ;AAAA,IACN,uBAAuB;AAAA,IACvB,0BAA0B;AAAA,IAC1B,yBAAyB;AAAA,EAC3B;AACF;AAEA,SAAS,iBAAyB;AAChC,QAAM,UAAU,QAAQ,IAAI,QAAQ,QAAQ,IAAI;AAChD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AACA,SAAO;AACT;AAEA,SAAS,gBAAwB;AAC/B,QAAM,UAAU,eAAe;AAC/B,SAAO,kBAAAC,QAAK,KAAK,SAAS,UAAU,aAAa;AACnD;AAEA,eAAe,sBAAsB,UAAiC;AACpE,QAAM,MAAM,kBAAAA,QAAK,QAAQ,QAAQ;AACjC,YAAM,wBAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACtC;AAEA,SAASC,sBAAqB,SAAyB;AACrD,SAAO,QAAQ,QAAQ,SAAS,IAAI;AACtC;AAEA,SAAS,sBAAsB,SAAyB;AACtD,SAAO,QAAQ,SAAS,IAAI,IAAI,UAAU,GAAG,OAAO;AAAA;AACtD;AAEA,SAAS,aAAa,SAA+B;AACnD,MAAI;AACF,UAAM,aAAS,oBAAM,OAAO;AAC5B,WAAO,EAAE,MAAM,UAAU,CAAC,GAAG,OAAO,KAAK;AAAA,EAC3C,SAAS,OAAO;AACd,UAAM,QAAQ;AACd,UAAM,OAAO,OAAO,OAAO,SAAS,WAAW,MAAM,OAAO;AAC5D,UAAM,SAAS,OAAO,OAAO,WAAW,WAAW,MAAM,SAAS,OAAO,OAAO,QAAQ,WAAW,MAAM,MAAM;AAC/G,UAAM,WAAW,SAAS,OAAO,QAAQ,IAAI,GAAG,WAAW,OAAO,YAAY,MAAM,KAAK,EAAE,KAAK;AAEhG,UAAM,WAAW,sBAAsB,OAAO;AAAA,MAC5C,UAAU;AAAA,MACV,WAAW;AAAA,IACb,CAAC;AACD,UAAM,UAAU,WAAW,GAAG,QAAQ,UAAU,QAAQ,OAAO;AAC/D,WAAO,EAAE,MAAM,MAAM,OAAO,QAAQ;AAAA,EACtC;AACF;AAEA,SAAS,eAAe,OAA+B;AACrD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAAS,gBAAgB,OAAgC;AACvD,MAAI,OAAO,UAAU,WAAW;AAC9B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,eAAe,OAA+B;AACrD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,SAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;AAC1C;AAEA,SAAS,cAAc,OAA0B;AAC/C,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,WAAO,CAAC;AAAA,EACV;AACA,SAAO,MACJ,IAAI,WAAU,OAAO,UAAU,WAAW,MAAM,KAAK,IAAI,EAAG,EAC5D,OAAO,WAAS,MAAM,SAAS,CAAC;AACrC;AAEA,SAAS,eAAe,OAAwC;AAC9D,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AACvE,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,SAAiC,CAAC;AACxC,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC9C,QAAI,OAAO,QAAQ,UAAU;AAC3B;AAAA,IACF;AACA,UAAM,gBAAgB,IAAI,KAAK;AAC/B,UAAM,kBAAkB,IAAI,KAAK;AACjC,QAAI,CAAC,iBAAiB,CAAC,iBAAiB;AACtC;AAAA,IACF;AACA,WAAO,aAAa,IAAI;AAAA,EAC1B;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,MAAoD;AAChF,QAAM,kBAAkB,QAAQ,OAAO,KAAK,QAAQ,MAAM,YAAY,KAAK,QAAQ,MAAM,OACpF,KAAK,QAAQ,IACd;AAEJ,QAAM,oBACJ,QAAQ,OAAO,KAAK,UAAU,MAAM,YAAY,KAAK,UAAU,MAAM,QAAQ,CAAC,MAAM,QAAQ,KAAK,UAAU,CAAC,IACvG,KAAK,UAAU,IAChB;AAEN,QAAM,iBACJ,QAAQ,OAAO,KAAK,OAAO,MAAM,YAAY,KAAK,OAAO,MAAM,QAAQ,CAAC,MAAM,QAAQ,KAAK,OAAO,CAAC,IAC9F,KAAK,OAAO,IACb;AAEN,QAAM,gBAAgD,CAAC;AACvD,MAAI,mBAAmB;AACrB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,iBAAiB,GAAG;AAC5D,oBAAc,GAAG,IAAI,gBAAgB,KAAK;AAAA,IAC5C;AAAA,EACF;AAEA,QAAM,qBAAqB,kBAAkB,eAAe,gBAAgB,kBAAkB,CAAC,IAAI,CAAC;AAEpG,SAAO;AAAA,IACL,OAAO,OAAO,eAAe,KAAK,OAAO,CAAC,IAAI;AAAA,IAC9C,aAAa,OAAO,eAAe,KAAK,cAAc,CAAC,IAAI;AAAA,IAC3D,sBAAsB,OAAO,eAAe,KAAK,wBAAwB,CAAC,IAAI;AAAA,IAC9E,uBAAuB,OAAO,eAAe,KAAK,yBAAyB,CAAC,IAAI;AAAA,IAChF,gBAAgB,OAAO,eAAe,KAAK,iBAAiB,CAAC,IAAI;AAAA,IACjE,gBAAgB,OAAO,eAAe,KAAK,iBAAiB,CAAC,IAAI;AAAA,IACjE,aAAa,OAAO,eAAe,KAAK,cAAc,CAAC,IAAI;AAAA,IAC3D,WAAW,OAAO,eAAe,KAAK,YAAY,CAAC,IAAI;AAAA,IACvD,aAAa,OAAO,eAAe,KAAK,aAAa,CAAC,IAAI;AAAA,IAC1D,sBAAsB,OAAO,eAAe,KAAK,yBAAyB,CAAC,IAAI;AAAA,IAC/E,4BAA4B,OAAO,eAAe,KAAK,gCAAgC,CAAC,IAAI;AAAA,IAC5F,oBAAoB,OAAO,eAAe,KAAK,sBAAsB,CAAC,IAAI;AAAA,IAC1E,UAAU;AAAA,MACR,aAAa,oBAAoB,gBAAgB,kBAAkB,cAAc,CAAC,IAAI;AAAA,MACtF,eAAe,oBAAoB,gBAAgB,kBAAkB,gBAAgB,CAAC,IAAI;AAAA,MAC1F,QAAQ;AAAA,IACV;AAAA,IACA,OAAO;AAAA,MACL,WAAW,iBAAiB,gBAAgB,eAAe,YAAY,CAAC,IAAI;AAAA,MAC5E,WAAW,iBAAiB,gBAAgB,eAAe,YAAY,CAAC,IAAI;AAAA,IAC9E;AAAA,IACA,QAAQ;AAAA,MACN,uBAAuB,kBAAkB,gBAAgB,gBAAgB,0BAA0B,CAAC,IAAI;AAAA,MACxG,0BAA0B,kBAAkB,gBAAgB,gBAAgB,8BAA8B,CAAC,IAAI;AAAA,MAC/G,wCAAwC,kBACpC,gBAAgB,gBAAgB,yCAAyC,CAAC,IAC1E;AAAA,MACJ,yBAAyB,kBAAkB,gBAAgB,gBAAgB,6BAA6B,CAAC,IAAI;AAAA,MAC7G,iBAAiB,OAAO,KAAK,kBAAkB,EAAE,SAAS,IAAI,qBAAqB;AAAA,IACrF;AAAA,EACF;AACF;AAuBA,SAAS,uBAAuB,MAAiC;AAC/D,QAAM,cACJ,QAAQ,OAAO,KAAK,UAAU,MAAM,YAAY,KAAK,UAAU,MAAM,QAAQ,CAAC,MAAM,QAAQ,KAAK,UAAU,CAAC,IACvG,KAAK,UAAU,IAChB;AAEN,MAAI,eAAe,OAAO,YAAY,aAAa,MAAM,WAAW;AAClE,WAAO,YAAY,aAAa;AAAA,EAClC;AAEA,MAAI,QAAQ,OAAO,KAAK,8BAA8B,MAAM,WAAW;AACrE,WAAO,KAAK,8BAA8B;AAAA,EAC5C;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,MAAc,UAA2C;AAC/E,MAAI,OAAO,aAAa,YAAY,aAAa,QAAQ,MAAM,QAAQ,QAAQ,GAAG;AAChF,WAAO;AAAA,EACT;AACA,QAAM,MAAM;AACZ,QAAM,YAAY,eAAe,IAAI,MAAM,CAAC;AAC5C,QAAM,UAAU,eAAe,IAAI,SAAS,CAAC;AAC7C,QAAM,OAAO,cAAc,IAAI,MAAM,CAAC;AACtC,QAAM,MAAM,eAAe,IAAI,KAAK,CAAC;AACrC,QAAM,UAAU,cAAc,IAAI,UAAU,CAAC;AAC7C,QAAM,MAAM,eAAe,IAAI,KAAK,CAAC;AACrC,QAAM,MAAM,eAAe,IAAI,KAAK,CAAC;AACrC,QAAM,oBAAoB,eAAe,IAAI,sBAAsB,CAAC;AACpE,QAAM,cAAc,eAAe,IAAI,cAAc,CAAC;AACtD,QAAM,iBAAiB,eAAe,IAAI,kBAAkB,CAAC;AAC7D,QAAM,oBAAoB,eAAe,IAAI,qBAAqB,CAAC;AACnE,QAAM,iBAAiB,eAAe,IAAI,kBAAkB,CAAC;AAC7D,QAAM,eAAe,cAAc,IAAI,eAAe,CAAC;AACvD,QAAM,gBAAgB,cAAc,IAAI,gBAAgB,CAAC;AACzD,QAAM,UAAU,OAAO,IAAI,SAAS,MAAM,YAAY,IAAI,SAAS,IAAI;AACvE,QAAM,YACJ,cAAc,WAAW,cAAc,UAAU,cAAc,QAC3D,YACA,MACE,SACA;AAER,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,KAAK,SAAS,IAAI,OAAO;AAAA,IAC/B;AAAA,IACA,KAAK,OAAO,KAAK,GAAG,EAAE,SAAS,IAAI,MAAM;AAAA,IACzC,SAAS,QAAQ,SAAS,IAAI,UAAU;AAAA,IACxC;AAAA,IACA;AAAA,IACA,aAAa,OAAO,KAAK,WAAW,EAAE,SAAS,IAAI,cAAc;AAAA,IACjE,gBAAgB,OAAO,KAAK,cAAc,EAAE,SAAS,IAAI,iBAAiB;AAAA,IAC1E;AAAA,IACA;AAAA,IACA,cAAc,aAAa,SAAS,IAAI,eAAe;AAAA,IACvD,eAAe,cAAc,SAAS,IAAI,gBAAgB;AAAA,EAC5D;AACF;AAEA,SAAS,oBAAoB,MAA2C;AACtE,QAAM,aAAa,OAAO,aAAa;AACvC,MAAI,OAAO,eAAe,YAAY,eAAe,QAAQ,MAAM,QAAQ,UAAU,GAAG;AACtF,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,UAA6B,CAAC;AACpC,aAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,UAAU,GAAG;AACzD,UAAM,SAAS,eAAe,MAAM,QAAQ;AAC5C,QAAI,QAAQ;AACV,cAAQ,KAAK,MAAM;AAAA,IACrB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,UAA+B,YAAuC;AAC7F,QAAM,QAAQ,SAAS,eAAe,KAAK,WAAS,MAAM,QAAQ,UAAU;AAC5E,SAAO,OAAO,SAAS;AACzB;AAEA,SAAS,qBAAqB,OAAwB;AACpD,QAAM,aAAa,MAAM,KAAK;AAC9B,MAAI,WAAW,SAAS,IAAI;AAC1B,WAAO;AAAA,EACT;AACA,MAAI,KAAK,KAAK,UAAU,GAAG;AACzB,WAAO;AAAA,EACT;AACA,MAAI,CAAC,qBAAqB,KAAK,UAAU,GAAG;AAC1C,WAAO;AAAA,EACT;AACA,QAAM,aAAa,WAAW,KAAK,UAAU;AAC7C,QAAM,aAAa,KAAK,KAAK,UAAU;AACvC,SAAO,cAAc;AACvB;AAEA,SAAS,uBACP,MACA,SACA,YACA,UACyB;AACzB,QAAM,cAAuC,CAAC;AAE9C,QAAM,eACJ,QAAQ,OAAO,KAAK,UAAU,MAAM,YAAY,KAAK,UAAU,MAAM,QAAQ,CAAC,MAAM,QAAQ,KAAK,UAAU,CAAC,IACvG,KAAK,UAAU,IAChB;AAEN,QAAM,oBAAoB,IAAI,IAAI,SAAS,kBAAkB;AAC7D,MAAI,MAAM;AACR,eAAW,OAAO,OAAO,KAAK,IAAI,GAAG;AACnC,UAAI,kBAAkB,IAAI,GAAG,GAAG;AAC9B;AAAA,MACF;AACA,kBAAY,KAAK;AAAA,QACf,IAAI,qBAAqB,GAAG;AAAA,QAC5B,UAAU;AAAA,QACV,UAAU;AAAA,QACV,OAAO,uBAAuB,GAAG;AAAA,QACjC,SAAS;AAAA,QACT,OAAO;AAAA,QACP,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,cAAc;AAChB,UAAM,mBAAmB,IAAI,IAAI,SAAS,iBAAiB;AAC3D,eAAW,CAAC,UAAU,KAAK,OAAO,QAAQ,YAAY,GAAG;AACvD,UAAI,CAAC,iBAAiB,IAAI,UAAU,GAAG;AACrC,oBAAY,KAAK;AAAA,UACf,IAAI,mBAAmB,UAAU;AAAA,UACjC,UAAU;AAAA,UACV,UAAU;AAAA,UACV,OAAO,kCAAkC,UAAU;AAAA,UACnD,SAAS;AAAA,UACT,OAAO,kBAAkB,UAAU;AAAA,UACnC,UAAU;AAAA,QACZ,CAAC;AACD;AAAA,MACF;AAEA,YAAM,QAAQ,gBAAgB,UAAU,UAAU;AAClD,UAAI,UAAU,cAAc;AAC1B,oBAAY,KAAK;AAAA,UACf,IAAI,sBAAsB,UAAU;AAAA,UACpC,UAAU;AAAA,UACV,UAAU;AAAA,UACV,OAAO,qCAAqC,UAAU;AAAA,UACtD,SAAS;AAAA,UACT,OAAO,kBAAkB,UAAU;AAAA,UACnC,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,aAAW,UAAU,YAAY;AAC/B,QAAI,OAAO,cAAc,WAAW,OAAO,MAAM;AAC/C,eAAS,QAAQ,GAAG,QAAQ,OAAO,KAAK,QAAQ,SAAS,GAAG;AAC1D,cAAM,QAAQ,OAAO,KAAK,KAAK,KAAK;AACpC,YAAI,qCAAqC,KAAK,KAAK,GAAG;AACpD,sBAAY,KAAK;AAAA,YACf,IAAI,kBAAkB,OAAO,IAAI,IAAI,KAAK;AAAA,YAC1C,UAAU;AAAA,YACV,UAAU;AAAA,YACV,OAAO,iCAAiC,OAAO,IAAI;AAAA,YACnD,SAAS;AAAA,YACT,OAAO;AAAA,YACP,UAAU;AAAA,UACZ,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,QAAI,OAAO,aAAa;AACtB,iBAAW,CAAC,QAAQ,WAAW,KAAK,OAAO,QAAQ,OAAO,WAAW,GAAG;AACtE,YAAI,CAAC,qBAAqB,WAAW,GAAG;AACtC;AAAA,QACF;AACA,oBAAY,KAAK;AAAA,UACf,IAAI,qBAAqB,OAAO,IAAI,IAAI,MAAM;AAAA,UAC9C,UAAU;AAAA,UACV,UAAU;AAAA,UACV,OAAO,mCAAmC,OAAO,IAAI;AAAA,UACrD,SAAS,gBAAgB,MAAM;AAAA,UAC/B,OAAO;AAAA,UACP,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,mBAAmB,WAAW,QAAQ,gBAAgB,sBAAsB;AACtF,gBAAY,KAAK;AAAA,MACf,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,MACT,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,cAAc,SAA8C;AACnE,SACE,QAAQ,UAAU,YAAY,SAC9B,QAAQ,gBAAgB,YAAY,eACpC,QAAQ,yBAAyB,YAAY,wBAC7C,QAAQ,0BAA0B,YAAY,yBAC9C,QAAQ,mBAAmB,YAAY,kBACvC,QAAQ,mBAAmB,YAAY,kBACvC,QAAQ,gBAAgB,YAAY,eACpC,QAAQ,cAAc,YAAY,aAClC,QAAQ,gBAAgB,YAAY,eACpC,QAAQ,yBAAyB,YAAY,wBAC7C,QAAQ,+BAA+B,YAAY,8BACnD,QAAQ,SAAS,gBAAgB,QACjC,QAAQ,SAAS,kBAAkB,QACnC,QAAQ,OAAO,0BAA0B,QACzC,QAAQ,OAAO,6BAA6B,QAC5C,QAAQ,OAAO,4BAA4B;AAE/C;AAEA,eAAe,oBAAmE;AAChF,QAAM,aAAa,cAAc;AACjC,MAAI;AACF,UAAM,UAAU,UAAM,2BAAS,YAAY,MAAM;AACjD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAASC,sBAAqB,OAAO;AAAA,IACvC;AAAA,EACF,SAAS,OAAO;AACd,UAAM,YAAY;AAClB,QAAI,UAAU,SAAS,UAAU;AAC/B,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,MACX;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAe,mBAAmB,SAAgC;AAChE,QAAM,aAAa,cAAc;AACjC,QAAM,sBAAsB,UAAU;AACtC,QAAM,aAAa,sBAAsBA,sBAAqB,OAAO,CAAC;AACtE,YAAM,4BAAU,YAAY,YAAY,MAAM;AAChD;AAEA,eAAe,aAAa,YAAoB,QAAyC;AACvF,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,QAAQ,UAAM,uBAAK,UAAU;AACnC,WAAO,MAAM;AAAA,EACf,SAAS,OAAO;AACd,UAAM,YAAY;AAClB,QAAI,UAAU,SAAS,UAAU;AAC/B,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAe,cAAc,SAAiB,QAAsD;AAClG,QAAM,aAAa,cAAc;AACjC,QAAM,SAAS,aAAa,OAAO;AACnC,QAAM,UAAU,qBAAqB,OAAO,IAAI;AAChD,QAAM,YAAY,MAAM,aAAa,YAAY,MAAM;AACvD,QAAM,aAAa,oBAAoB,OAAO,IAAI;AAClD,QAAM,oBAAoB,uBAAuB,OAAO,IAAI;AAC5D,QAAM,WAAW,MAAM,uBAAuB;AAC9C,QAAM,cAAc,OAAO,QACvB,CAAC,IACD,uBAAuB,OAAO,MAAM,SAAS,YAAY,QAAQ;AAErE,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,YAAY,OAAO;AAAA,IACnB,cAAc,OAAO,QAAQ,QAAQ,cAAc,OAAO;AAAA,IAC1D;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAiZA,eAAsB,yBAA8D;AAClF,QAAM,EAAE,SAAS,OAAO,IAAI,MAAM,kBAAkB;AACpD,SAAO,cAAc,SAAS,MAAM;AACtC;AAEA,eAAsB,uBAAuB,SAAsD;AACjG,QAAM,aAAa,sBAAsBC,sBAAqB,OAAO,CAAC;AACtE,QAAM,SAAS,aAAa,UAAU;AACtC,MAAI,CAAC,OAAO,MAAM;AAChB,UAAM,IAAI,MAAM,OAAO,SAAS,2CAA2C;AAAA,EAC7E;AACA,QAAM,mBAAmB,UAAU;AACnC,SAAO,cAAc,YAAY,IAAI;AACvC;;;AJrhCA,IAAM,kBAAkB;AACxB,IAAM,yBAAyB;AAC/B,IAAM,yBAAyB;AAC/B,IAAM,6BAA6B;AACnC,IAAM,uBAAuB,IAAI,OAAO;AACxC,IAAM,sBAAsB,IAAI,OAAO;AACvC,IAAM,aAAa,OAAO;AAoB1B,SAAS,wBAAwB,KAAwC;AACvE,MAAI,CAACC,UAAS,GAAG,GAAG;AAClB,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAAqC,CAAC;AAE5C,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC/C,QAAI,CAACA,UAAS,KAAK,GAAG;AACpB;AAAA,IACF;AAEA,UAAM,OAAOA,UAAS,MAAM,IAAI,IAAI,MAAM,OAAO;AACjD,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AAEA,UAAM,iBAAiB,OAAO,SAAS,WAAW,KAAK,KAAK,IAAI;AAChE,QAAI,CAAC,gBAAgB;AACnB;AAAA,IACF;AAEA,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc;AAAA,MACzE;AAAA,MACA,UAAUA,UAAS,MAAM,QAAQ,IAAI,MAAM,WAAW;AAAA,MACtD,WAAW,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAAA,MACnE,aAAa,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc;AAAA,MACzE,eAAe,OAAO,MAAM,kBAAkB,WAAW,MAAM,gBAAgB;AAAA,MAC/E,OAAO,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAAA,MACvD,YAAY,OAAO,MAAM,eAAe,WAAW,MAAM,aAAa;AAAA,MACtE,WAAW,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAAA,MACnE,WAAW,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAAA,IACrE,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,kBAAkB,UAIzB;AACA,QAAM,cACJ,OAAO,SAAS,sBAAsB,WAAW,SAAS,kBAAkB,SAAS;AACvF,QAAM,eACJA,UAAS,SAAS,YAAY,IAAI,OAAO,KAAK,SAAS,YAAY,EAAE,SAAS;AAEhF,SAAO;AAAA,IACL,UAAU,SAAS,SAAS;AAAA,IAC5B;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,YAAyC;AACtD,QAAM,QAAQ,MAAM,YAAY;AAChC,SAAO;AAAA,IACL,YAAY,MAAM,KAAK,cAAc;AAAA,IACrC,YAAY,MAAM,KAAK,cAAc;AAAA,IACrC,WAAW,MAAM,KAAK,aAAa;AAAA,IACnC,iBAAiB,MAAM,KAAK,mBAAmB;AAAA,EACjD;AACF;AAEA,eAAe,WAAW,OAAmD;AAC3E,QAAM,cAAc;AAAA,IAClB,MAAM;AAAA,MACJ,GAAI,OAAO,MAAM,eAAe,WAAW,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,MAC/E,GAAI,OAAO,MAAM,eAAe,WAAW,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,MAC/E,GAAI,OAAO,MAAM,cAAc,WAAW,EAAE,WAAW,MAAM,UAAU,IAAI,MAAM,cAAc,SAAY,EAAE,WAAW,KAAK,IAAI,CAAC;AAAA,MAClI,GAAI,OAAO,MAAM,oBAAoB,WACjC,EAAE,iBAAiB,MAAM,gBAAgB,IACzC,CAAC;AAAA,IACP;AAAA,EACF,CAAC;AACH;AAEA,eAAe,qBAA2C;AACxD,QAAM,SAAS,MAAM,iBAAiB;AACtC,QAAM,aAAa,OAAO,QAAQ,eAAe,WAAW,OAAO,WAAW,KAAK,IAAI;AAEvF,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,eAAe,UAAU;AAC9C,QAAM,SAAS,OAAO,UAAU,YAAY,OAAO,UAAU;AAC7D,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR;AAAA,MACA,cAAc,OAAO;AAAA,IACvB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR;AAAA,IACA,cAAc,OAAO;AAAA,EACvB;AACF;AAEA,SAAS,gBAAgB,OAAuB;AAC9C,UAAQ,QAAQ,YAAY,QAAQ,CAAC;AACvC;AAEA,SAAS,wBAAgC;AACvC,SAAO,kBAAAC,QAAK,KAAK,eAAe,GAAG,eAAe;AACpD;AAEA,SAAS,qBAAqB,KAAqB;AACjD,SAAO,IAAI,QAAQ,MAAM,GAAG;AAC9B;AAEA,eAAe,uBAAuB,YAAmC;AACvE,QAAM,UAAU,MAAM,gBAAAC,SAAG,QAAQ,YAAY,EAAE,eAAe,KAAK,CAAC;AACpE,QAAM,QAAQ,QACX;AAAA,IACC,CAAC,UACC,MAAM,OAAO,KACb,MAAM,KAAK,WAAW,sBAAsB,KAC5C,MAAM,KAAK,SAAS,sBAAsB;AAAA,EAC9C,EACC,IAAI,CAAC,UAAU,MAAM,IAAI,EACzB,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAEpC,MAAI,MAAM,UAAU,4BAA4B;AAC9C;AAAA,EACF;AAEA,aAAW,SAAS,MAAM,MAAM,0BAA0B,GAAG;AAC3D,UAAM,gBAAAA,SAAG,GAAG,kBAAAD,QAAK,KAAK,YAAY,KAAK,GAAG,EAAE,OAAO,KAAK,CAAC;AAAA,EAC3D;AACF;AAEA,eAAe,oBAAoB,gBAAiD;AAClF,QAAM,WAAW,MAAM,mBAAmB,gBAAgB;AAAA,IACxD,mBAAmB;AAAA,EACrB,CAAC;AACD,QAAM,aAAa,sBAAsB;AACzC,QAAM,gBAAAC,SAAG,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;AAE9C,QAAM,YAAY,sBAAqB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAC/D,QAAM,aAAa,kBAAAD,QAAK;AAAA,IACtB;AAAA,IACA,GAAG,sBAAsB,GAAG,SAAS,GAAG,sBAAsB;AAAA,EAChE;AACA,QAAM,gBAAAC,SAAG,UAAU,YAAY,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AAC/E,QAAM,uBAAuB,UAAU;AAEvC,UAAQ,wCAAwC,EAAE,WAAW,CAAC;AAC9D,SAAO;AACT;AAEA,eAAe,mBACb,gBACA,UAAqC,CAAC,GACV;AAC5B,QAAM,oBAAoB,QAAQ,sBAAsB;AACxD,QAAM,sBAAsB,MAAM,eAAe,2BAA2B;AAC5E,QAAM,QAAQ,MAAM,YAAY;AAChC,QAAM,oBAAoB,wBAAwB,MAAM,cAAc;AACtE,QAAM,WAAW,oBAAoB,SAAS,IAAI,sBAAsB;AACxE,QAAM,SAAS,MAAM,uBAAuB;AAC5C,QAAM,eAAe,MAAM,yBAAyB;AAEpD,QAAM,cAAc,SAAS,SAAS;AACtC,QAAM,YAAY,OAAO,OAAO,YAAY,YAAY,OAAO,QAAQ,KAAK,EAAE,SAAS;AACvF,QAAM,cAAcF,UAAS,YAAY,KAAK,OAAO,KAAK,YAAY,EAAE,SAAS;AAEjF,MAAI,qBAAqB,CAAC,eAAe,CAAC,aAAa,CAAC,aAAa;AACnE,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,QAAM,WAA8B;AAAA,IAClC,eAAe;AAAA,IACf,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,IACA,mBAAmB,OAAO,SAAS,OAAO,UAAU;AAAA,IACpD;AAAA,EACF;AAEA,MAAI,CAAC,mBAAmB;AACtB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,eAAe,oBAAoB,gBAAgC,UAA4C;AAC7G,QAAM,eAAe,6BAA6B,SAAS,YAAY,CAAC,CAAC;AAEzE,MAAI,OAAO,SAAS,sBAAsB,UAAU;AAClD,UAAM,uBAAuB,SAAS,iBAAiB;AAAA,EACzD;AAEA,MAAI,SAAS,gBAAgBA,UAAS,SAAS,YAAY,GAAG;AAC5D,UAAM,0BAA0B,SAAS,YAAY;AAAA,EACvD,OAAO;AACL,UAAM,0BAA0B,CAAC,CAAC;AAAA,EACpC;AACF;AAEA,SAAS,WAAW,MAAuB,OAA2C;AACpF,QAAM,UAAU,sBAAsB,OAAO;AAAA,IAC3C,UAAU,cAAc,IAAI;AAAA,EAC9B,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,EACnB;AACF;AAEA,eAAsB,qBAAsD;AAC1E,QAAM,cAAc,MAAM,mBAAmB;AAC7C,QAAM,QAAQ,MAAM,UAAU;AAE9B,MAAI,kBAAiC,MAAM,mBAAmB;AAC9D,MAAI,YAAY,WAAW,YAAY,YAAY;AACjD,QAAI;AACF,wBAAkB,MAAM,wBAAwB,YAAY,UAAU;AAAA,IACxE,SAAS,OAAO;AACd,UAAI,iBAAiB,wBAAwB,MAAM,WAAW,KAAK;AACjE,YAAI;AACF,gBAAM,SAAS,MAAM,oBAAoB,YAAY,UAAU;AAC/D,4BAAkB,QAAQ,aAAa;AAAA,QACzC,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IAEF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,YAAY;AAAA,IACrB,QAAQ,YAAY;AAAA,IACpB,cAAc,YAAY;AAAA,IAC1B,eAAe,QAAQ,YAAY,UAAU;AAAA,IAC7C,YAAY,MAAM,cAAc;AAAA,IAChC,YAAY,MAAM,cAAc;AAAA,IAChC,WAAW,MAAM,aAAa;AAAA,IAC9B;AAAA,EACF;AACF;AAEA,eAAsB,gBAAoD;AACxE,QAAM,cAAc,MAAM,mBAAmB;AAC7C,MAAI,CAAC,YAAY,WAAW,CAAC,YAAY,YAAY;AACnD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,YAAY,UAAU;AAAA,MAC/B,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,IACnB;AAAA,EACF;AAEA,QAAM,iBAAiB,IAAI,eAAe;AAE1C,MAAI;AACF,UAAM,eAAe,WAAW;AAChC,UAAM,gBAAgB,MAAM,mBAAmB,gBAAgB,EAAE,mBAAmB,KAAK,CAAC;AAC1F,UAAM,qBAAqB,KAAK,UAAU,aAAa;AACvD,UAAM,gBAAgB,OAAO,WAAW,oBAAoB,MAAM;AAClE,QAAI,gBAAgB,sBAAsB;AACxC,cAAQ,uCAAuC;AAAA,QAC7C,OAAO;AAAA,QACP,WAAW,gBAAgB,aAAa;AAAA,MAC1C,CAAC;AAAA,IACH;AACA,QAAI,gBAAgB,qBAAqB;AACvC,YAAM,IAAI;AAAA,QACR,+BAA+B,gBAAgB,aAAa,CAAC;AAAA,MAC/D;AAAA,IACF;AACA,QAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,cAAQ,sCAAsC,kBAAkB,aAAa,CAAC;AAAA,IAChF;AACA,UAAM,SAAS,MAAM,mBAAmB,YAAY,YAAY,eAAe;AAAA,MAC7E;AAAA,IACF,CAAC;AAED,UAAM,WAAW;AAAA,MACf,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,iBAAiB,OAAO,SAAS;AAAA,MACjC,WAAW;AAAA,IACb,CAAC;AAED,QAAI,OAAO,WAAW,SAAS;AAC7B,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,gBAAgB,cAAc;AAAA,QAC9B,iBAAiB,OAAO,SAAS;AAAA,MACnC;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,gBAAgB,cAAc;AAAA,MAC9B,iBAAiB,OAAO,SAAS;AAAA,IACnC;AAAA,EACF,SAAS,OAAO;AACd,UAAM,SAAS,WAAW,QAAQ,KAAK;AACvC,UAAM,YAAY,iBAAiB,uBAAuB,MAAM,UAAU,OAAO;AACjF,UAAM,WAAW,EAAE,UAAU,CAAC;AAC9B,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,gBAAoD;AACxE,QAAM,cAAc,MAAM,mBAAmB;AAC7C,MAAI,CAAC,YAAY,WAAW,CAAC,YAAY,YAAY;AACnD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,YAAY,UAAU;AAAA,MAC/B,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,IACnB;AAAA,EACF;AAEA,QAAM,iBAAiB,IAAI,eAAe;AAE1C,MAAI;AACF,UAAM,eAAe,WAAW;AAChC,UAAM,SAAS,MAAM,oBAAoB,YAAY,UAAU;AAE/D,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,iBAAiB;AAAA,MACnB;AAAA,IACF;AAEA,QAAI,sBAAsB;AAC1B,QAAI;AACF,YAAM,oBAAoB,cAAc;AAAA,IAC1C,SAAS,aAAa;AACpB,cAAQ,wDAAwD,WAAW;AAC3E,YAAM,SAAS,sBAAsB,aAAa,EAAE,UAAU,gBAAgB,CAAC;AAC/E,4BAAsB,qCAAqC,MAAM;AAAA,IACnE;AACA,UAAM,oBAAoB,gBAAgB,MAAM;AAChD,UAAM,WAAW;AAAA,MACf,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,iBAAiB,OAAO;AAAA,MACxB,WAAW;AAAA,IACb,CAAC;AAED,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,6BAA6B,mBAAmB;AAAA,MACzD,gBAAgB,OAAO;AAAA,MACvB,iBAAiB,OAAO;AAAA,IAC1B;AAAA,EACF,SAAS,OAAO;AACd,UAAM,SAAS,WAAW,QAAQ,KAAK;AACvC,UAAM,YAAY,iBAAiB,uBAAuB,MAAM,UAAU,OAAO;AACjF,UAAM,WAAW,EAAE,UAAU,CAAC;AAC9B,WAAO;AAAA,EACT;AACF;;;AQlbO,IAAM,wBACX;AAEF,eAAsB,6BACpB,gBACe;AACf,QAAM,UAAU,kBAAkB,IAAI,eAAe;AACrD,QAAM,QAAQ,WAAW;AAEzB,QAAM,UAAU,MAAM,eAAe,UAAU;AAC/C,QAAM,WAAW,MAAM,QAAQ,aAAa;AAC5C,QAAM,oBAAoB,eAAe,kBAAkB,SAAS,SAAS,MAAM;AAEnF,MACE,OAAO,kBAAkB,iBAAiB,YAC1C,kBAAkB,sBAAsB,QACxC,kBAAkB,qBAAqB,GACvC;AACA,UAAM,IAAI,MAAM,0FAA0F;AAAA,EAC5G;AACF;AAMA,SAAS,kBAAkB,YAAqC;AAC9D,SAAO,WAAW,OAAO,CAAC,eAAe,UAAU,QAAQ,YAAY,UAAU,EAAE;AACrF;AAEA,eAAsB,6BACpB,YACe;AACf,QAAM,UAAU,MAAM,eAAe,UAAU;AAC/C,MAAI,CAAC,0BAA0B,OAAO,GAAG;AACvC;AAAA,EACF;AAEA,QAAM,mBAAmB,kBAAkB,UAAU;AACrD,MAAI,oBAAoB,GAAG;AACzB,UAAM,IAAI,MAAM,qBAAqB;AAAA,EACvC;AACF;;;AC7CA,IAAAG,6BAAsB;AACtB,IAAAC,kBAAyB;AACzB,IAAAC,oBAAiB;AAEjB,IAAMC,aAAY,CAAC,gBAAgB,kBAAkB,YAAY;AAIjE,SAASC,YAAW,WAAqD;AACvE,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,WAAW,kBAAAC,QAAK,QAAQ,SAAS;AACvC,MAAI;AACF,UAAMC,YAAO,0BAAS,QAAQ;AAC9B,QAAIA,MAAK,OAAO,EAAG,QAAO;AAAA,EAC5B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,iBAAgC;AACvC,aAAW,OAAOH,YAAW;AAC3B,UAAM,QAAQ,QAAQ,IAAI,GAAG;AAC7B,QAAI,CAAC,MAAO;AACZ,UAAM,WAAWC,YAAW,KAAK;AACjC,QAAI,SAAU,QAAO;AAAA,EACvB;AACA,SAAO;AACT;AAEA,SAAS,kBAAiC;AACxC,QAAM,YAAY,QAAQ,IAAI,QAAQ;AACtC,QAAM,UAAU,UAAU,MAAM,kBAAAC,QAAK,SAAS,EAAE,OAAO,OAAO;AAC9D,QAAM,QAAQ,QAAQ,aAAa,UAC/B,CAAC,aAAa,aAAa,aAAa,OAAO,IAC/C,CAAC,OAAO;AAEZ,aAAW,SAAS,SAAS;AAC3B,eAAW,QAAQ,OAAO;AACxB,YAAM,YAAYD,YAAW,kBAAAC,QAAK,KAAK,OAAO,IAAI,CAAC;AACnD,UAAI,UAAW,QAAO;AAAA,IACxB;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,qBAAoC;AAClD,SACE,eAAe,KACf,gBAAgB;AAEpB;AAEO,SAAS,mBAAmB,SAA0B;AAC3D,QAAM,WAAW,mBAAmB;AACpC,MAAI,SAAU,QAAO;AACrB,QAAM,OAAO;AACb,QAAM,UAAU,UAAU,GAAG,OAAO,IAAI,IAAI,KAAK;AACjD,QAAM,IAAI,MAAM,OAAO;AACzB;AAEA,SAAS,kBAAkB,WAAmB,MAAqE;AACjH,QAAM,aAAa,UAAU,YAAY;AACzC,QAAM,OAAO,WAAW,SAAS,KAAK;AACtC,MAAI,MAAM;AACR,WAAO,EAAE,SAAS,QAAQ,UAAU,MAAM,CAAC,WAAW,GAAG,IAAI,GAAG,OAAO,MAAM;AAAA,EAC/E;AAEA,QAAM,WAAW,QAAQ,aAAa;AACtC,SAAO,EAAE,SAAS,WAAW,MAAM,OAAO,SAAS;AACrD;AAEA,SAAS,aAAsB;AAC7B,MAAI,QAAQ,IAAI,sBAAsB,IAAK,QAAO;AAClD,MAAI,QAAQ,IAAI,GAAI,QAAO;AAC3B,MAAI,QAAQ,IAAI,kBAAkB,QAAQ,IAAI,QAAS,QAAO;AAC9D,MAAI,QAAQ,aAAa,SAAS;AAChC,QAAI,CAAC,QAAQ,IAAI,WAAW,CAAC,QAAQ,IAAI,gBAAiB,QAAO;AAAA,EACnE;AACA,SAAO;AACT;AAEO,SAAS,iBAAiB,WAAmD;AAClF,MAAI,cAAc,aAAa,cAAc,UAAU;AACrD,WAAO;AAAA,EACT;AACA,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,YAAY,aAAa,YAAY,UAAU;AACjD,WAAO;AAAA,EACT;AACA,SAAO,WAAW,IAAI,WAAW;AACnC;AAEA,eAAsB,cAAc,MAA6C;AAC/E,QAAM,YAAY,mBAAmB,iCAAiC;AACtE,QAAM,eAAe,iBAAiB,QAAQ,IAAI;AAClD,QAAM,YAAY,iBAAiB,WAC/B,CAAC,SAAS,eAAe,IACzB,CAAC,OAAO;AACZ,QAAM,EAAE,SAAS,MAAM,MAAM,IAAI,kBAAkB,WAAW,SAAS;AAEvE,QAAM,YAAQ,kCAAM,SAAS,MAAM;AAAA,IACjC,OAAO;AAAA,IACP,KAAK,QAAQ;AAAA,IACb;AAAA,EACF,CAAC;AAED,QAAM,WAAW,MAAM,IAAI,QAAgB,CAAC,YAAY;AACtD,UAAM,GAAG,SAAS,CAAC,SAAS,QAAQ,QAAQ,CAAC,CAAC;AAAA,EAChD,CAAC;AAED,MAAI,aAAa,GAAG;AAClB,UAAM,IAAI,MAAM,qCAAqC,QAAQ,IAAI;AAAA,EACnE;AACF;;;ACnHA,IAAAE,6BAAsB;AACtB,2BAAqB;AACrB,IAAAC,kBAA+B;AAC/B,IAAAC,kBAAe;AACf,IAAAC,oBAAiB;AA6BjB,IAAM,iBAAiB;AACvB,IAAM,2BAA2B;AACjC,IAAMC,kCAAiC;AAWvC,SAASC,gBAAe,OAA+B;AACrD,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,WAAW,GAAG;AAC1D,WAAO;AAAA,EACT;AACA,QAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,SAAO,OAAO,MAAM,MAAM,IAAI,OAAO;AACvC;AAEA,SAAS,iBAAiB,OAAgD;AACxE,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,WAAW,GAAG;AAC1D,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,MAAM,MAAM,GAAG;AAChC,MAAI,SAAS,SAAS,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,aAAa,OAAO,KAAK,SAAS,CAAC,GAAG,WAAW,EAAE,SAAS,MAAM;AACxE,UAAM,UAAU,KAAK,MAAM,UAAU;AACrC,WAAO,WAAW,OAAO,YAAY,WAAY,UAAsC;AAAA,EACzF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,qBAAqB,OAA+B;AAC3D,QAAM,UAAU,iBAAiB,KAAK;AACtC,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,QAAQ,KAAK;AAC9B,MAAI,OAAO,aAAa,YAAY,CAAC,OAAO,SAAS,QAAQ,GAAG;AAC9D,WAAO;AAAA,EACT;AAEA,SAAO,WAAW;AACpB;AAEA,SAAS,gBAAgB,SAAoC;AAC3D,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,OAAO;AACjC,WAAO,UAAU,OAAO,WAAW,WAAY,SAAwB;AAAA,EACzE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,qBAAqB,SAAgC;AAC5D,QAAM,SAAS,gBAAgB,OAAO;AACtC,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,QAAM,kBAAkBA,gBAAe,OAAO,YAAY;AAC1D,QAAM,oBAAoBA,gBAAe,OAAO,QAAQ,YAAY;AACpE,QAAM,qBAAqB,qBAAqB,OAAO,YAAY;AACnE,QAAM,uBAAuB,qBAAqB,OAAO,QAAQ,YAAY;AAC7E,QAAM,aAAa,CAAC,iBAAiB,mBAAmB,oBAAoB,oBAAoB,EAC7F,OAAO,CAAC,UAA2B,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,CAAC;AAEzF,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,SAAO,KAAK,IAAI,GAAG,UAAU;AAC/B;AAEA,SAAS,oBACP,mBACA,mBACA,aACS;AACT,MAAI,YAAY,KAAK,EAAE,WAAW,GAAG;AACnC,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,mBAAmB;AACtB,WAAO;AAAA,EACT;AAEA,MAAI,sBAAsB,aAAa;AACrC,WAAO;AAAA,EACT;AAEA,MAAI,sBAAsB,mBAAmB;AAC3C,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB,qBAAqB,iBAAiB;AAC7D,QAAM,iBAAiB,qBAAqB,WAAW;AAEvD,MAAI,OAAO,mBAAmB,YAAY,OAAO,mBAAmB,UAAU;AAC5E,WAAO,iBAAiB;AAAA,EAC1B;AAEA,MAAI,OAAO,mBAAmB,YAAY,OAAO,mBAAmB,UAAU;AAC5E,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,wBAAwB,cAAqC;AACpE,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,aAAa,YAAY;AAC5C,MAAI,WAAW,SAASD,+BAA8B,GAAG;AACvD,WAAOA;AAAA,EACT;AAEA,SAAO;AACT;AAEA,eAAe,YACb,OACA,SACe;AACf,QAAM,OAAO,MAAM,KAAK,UAAU,OAAO,CAAC;AAC1C,QAAM,OAAO,MAAM,IAAI;AACzB;AAEA,SAAS,wBAAwB,SAAqB,WAA4B;AAChF,MAAI,QAAQ,OAAO,WAAW;AAC5B,WAAO;AAAA,EACT;AACA,SACE,OAAO,UAAU,eAAe,KAAK,SAAS,QAAQ,KACtD,OAAO,UAAU,eAAe,KAAK,SAAS,OAAO;AAEzD;AAEA,eAAsB,oBACpB,IACA,WACA,WACqB;AACrB,SAAO,IAAI,QAAoB,CAAC,SAAS,WAAW;AAClD,UAAM,QAAQ,WAAW,MAAM;AAC7B,cAAQ;AACR,aAAO,IAAI,MAAM,qBAAqB,CAAC;AAAA,IACzC,GAAG,KAAK,IAAI,GAAG,SAAS,CAAC;AAEzB,UAAM,UAAU,MAAM;AACpB,mBAAa,KAAK;AAClB,SAAG,IAAI,QAAQ,MAAM;AACrB,SAAG,IAAI,SAAS,OAAO;AAAA,IACzB;AAEA,UAAM,UAAU,MAAM;AACpB,cAAQ;AACR,aAAO,IAAI,MAAM,yCAAyC,CAAC;AAAA,IAC7D;AAEA,UAAM,SAAS,CAAC,SAAiB;AAC/B,UAAI;AACJ,UAAI;AACF,iBAAS,KAAK,MAAM,IAAI;AAAA,MAC1B,QAAQ;AACN,gBAAQ;AACR,eAAO,IAAI,MAAM,mCAAmC,CAAC;AACrD;AAAA,MACF;AAEA,UAAI,CAAC,wBAAwB,QAAQ,SAAS,GAAG;AAC/C;AAAA,MACF;AAEA,cAAQ;AACR,cAAQ,MAAM;AAAA,IAChB;AAEA,OAAG,GAAG,QAAQ,MAAM;AACpB,OAAG,GAAG,SAAS,OAAO;AAAA,EACxB,CAAC;AACH;AAEA,SAAS,eAAe,QAAgB,OAAyB;AAC/D,QAAM,WAAW,OAAO,MAAM,SAAS,WAAW,UAAU,MAAM,IAAI,MAAM;AAC5E,QAAM,UACJ,OAAO,MAAM,YAAY,YAAY,MAAM,QAAQ,KAAK,EAAE,SAAS,IAC/D,MAAM,QAAQ,KAAK,IACnB;AACN,SAAO,GAAG,MAAM,UAAU,QAAQ,KAAK,OAAO;AAChD;AAEA,SAAS,SAAS,KAA8D;AAC9E,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,cACJ,OAAO,IAAI,gBAAgB,YAAY,OAAO,SAAS,IAAI,WAAW,IAClE,IAAI,cACJ;AACN,QAAM,gBACJ,OAAO,IAAI,uBAAuB,YAAY,OAAO,SAAS,IAAI,kBAAkB,IAChF,IAAI,qBACJ;AAEN,MAAI;AACJ,MAAI;AACJ,MAAI,OAAO,IAAI,aAAa,YAAY,OAAO,SAAS,IAAI,QAAQ,GAAG;AACrE,UAAM,KAAK,IAAI,WAAW,OAAiB,IAAI,WAAW,IAAI,WAAW;AACzE,eAAW,IAAI,KAAK,EAAE,EAAE,YAAY;AACpC,sBAAkB,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK,KAAK,IAAI,KAAK,GAAI,CAAC;AAAA,EACpE;AAEA,MACE,OAAO,gBAAgB,eACvB,OAAO,kBAAkB,eACzB,OAAO,aAAa,aACpB;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAA0B,CAAC;AACjC,MAAI,OAAO,gBAAgB,UAAU;AACnC,WAAO,cAAc;AAAA,EACvB;AACA,MAAI,OAAO,kBAAkB,UAAU;AACrC,WAAO,gBAAgB;AAAA,EACzB;AACA,MAAI,OAAO,aAAa,UAAU;AAChC,WAAO,WAAW;AAAA,EACpB;AACA,MAAI,OAAO,oBAAoB,UAAU;AACvC,WAAO,kBAAkB;AAAA,EAC3B;AACA,SAAO;AACT;AAEO,SAAS,qCACd,SAC0B;AAC1B,MAAI,QAAQ,OAAO;AACjB,UAAM,IAAI,MAAM,eAAe,2BAA2B,QAAQ,KAAK,CAAC;AAAA,EAC1E;AAEA,QAAM,SAAS,QAAQ;AACvB,QAAM,SAAS,QAAQ;AACvB,QAAM,UAAU,SAAS,QAAQ,WAAW,IAAI;AAChD,QAAM,YAAY,SAAS,QAAQ,aAAa,IAAI;AAEpD,MAAI,CAAC,WAAW,CAAC,WAAW;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,WAA8B;AAAA,IAClC,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,QAAQ;AAAA,EACV;AACA,MAAI,SAAS;AACX,aAAS,UAAU;AAAA,EACrB;AACA,MAAI,WAAW;AACb,aAAS,YAAY;AAAA,EACvB;AACA,SAAO;AACT;AAEA,eAAsB,sBACpB,aACA,UAAqD,CAAC,GACnB;AACnC,QAAM,aAAa,QAAQ,aAAa,MAAM,gBAAgB;AAC9D,QAAM,WAAW,MAAM,gBAAAE,SAAG,QAAQ,kBAAAC,QAAK,KAAK,gBAAAC,QAAG,OAAO,GAAG,YAAY,CAAC;AACtE,QAAM,eAAe,kBAAAD,QAAK,KAAK,UAAU,WAAW;AACpD,MAAI,oBAAmC;AAEvC,QAAM,iBACJ,QAAQ,aACP,aAAa,aACV,kBAAAA,QAAK,KAAK,YAAY,YAAY,WAAW,IAC7C,kBAAAA,QAAK;AAAA,IACL,aAAa,QAAQ,QAAQ,IAAI,QAAQ,QAAQ,IAAI,eAAe,gBAAAC,QAAG,QAAQ;AAAA,IAC/E;AAAA,IACA;AAAA,EACF;AAEJ,MAAI;AACF,wBAAoB,MAAM,gBAAAF,SAAG,SAAS,gBAAgB,MAAM,EAAE,MAAM,MAAM,IAAI;AAC9E,QAAI,CAAC,mBAAmB;AACtB,aAAO;AAAA,IACT;AACA,UAAM,gBAAAA,SAAG,UAAU,cAAc,mBAAmB,MAAM;AAAA,EAC5D,QAAQ;AACN,UAAM,gBAAAA,SAAG,GAAG,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACtE,WAAO;AAAA,EACT;AAEA,QAAM,YAAQ,kCAAM,QAAQ,UAAU,CAAC,YAAY,MAAM,aAAa,MAAM,aAAa,YAAY,GAAG;AAAA,IACtG,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,IAC9B,KAAK;AAAA,MACH,GAAG,QAAQ;AAAA,MACX,GAAI,eAAe,CAAC;AAAA,MACpB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,uBAAuB;AAAA,MACvB,sBAAsB;AAAA,IACxB;AAAA,EACF,CAAC;AAED,QAAM,KAAK,qBAAAG,QAAS,gBAAgB;AAAA,IAClC,OAAO,MAAM;AAAA,IACb,WAAW;AAAA,EACb,CAAC;AACD,MAAI,eAAe;AACnB,QAAM,QAAQ,GAAG,QAAQ,WAAS;AAChC,QAAI,aAAa,UAAU,0BAA0B;AACnD;AAAA,IACF;AACA,UAAM,OAAO,MAAM,SAAS,MAAM;AAClC,UAAM,YAAY,2BAA2B,aAAa;AAC1D,oBAAgB,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,SAAS,CAAC;AAAA,EACtD,CAAC;AAED,MAAI;AACF,UAAM,YAAY,OAAO;AAAA,MACvB,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,SAAS,QAAQ,EAAE;AAAA,IAC/D,CAAC;AACD,UAAM,qBAAqB,MAAM,oBAAoB,IAAI,GAAG,cAAc;AAC1E,QAAI,mBAAmB,OAAO;AAC5B,YAAM,IAAI,MAAM,eAAe,cAAc,mBAAmB,KAAK,CAAC;AAAA,IACxE;AAEA,UAAM,YAAY,OAAO,EAAE,QAAQ,eAAe,QAAQ,CAAC,EAAE,CAAC;AAE9D,UAAM,YAAY,OAAO,EAAE,IAAI,GAAG,QAAQ,2BAA2B,QAAQ,CAAC,EAAE,CAAC;AACjF,UAAM,UAAU,MAAM,oBAAoB,IAAI,GAAG,cAAc;AAC/D,QAAI,QAAQ,OAAO;AACjB,YAAM,OAAO,eAAe,2BAA2B,QAAQ,KAAK;AACpE,YAAM,OAAO,wBAAwB,YAAY;AACjD,UAAI,QAAQ,CAAC,KAAK,YAAY,EAAE,SAAS,IAAI,GAAG;AAC9C,cAAM,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,EAAE;AAAA,MACpC;AACA,YAAM,IAAI,MAAM,IAAI;AAAA,IACtB;AAEA,WAAO,qCAAqC,OAAO;AAAA,EACrD,UAAE;AACA,UAAM,KAAK;AACX,OAAG,MAAM;AACT,QAAI;AACF,YAAM,cAAc,MAAM,gBAAAH,SAAG,SAAS,cAAc,MAAM;AAC1D,UAAI,YAAY,KAAK,EAAE,SAAS,GAAG;AACjC,cAAM,oBAAoB,MAAM,gBAAAA,SAAG,SAAS,gBAAgB,MAAM,EAAE,MAAM,MAAM,IAAI;AACpF,YAAI,oBAAoB,mBAAmB,mBAAmB,WAAW,GAAG;AAC1E,gBAAM,gBAAAA,SAAG,UAAU,gBAAgB,aAAa,MAAM;AAAA,QACxD,WACE,qBACA,sBAAsB,eACtB,sBAAsB,mBACtB;AACA,kBAAQ,uFAAuF;AAAA,YAC7F;AAAA,YACA,kBAAkB,qBAAqB,iBAAiB;AAAA,YACxD,kBAAkB,qBAAqB,WAAW;AAAA,UACpD,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AACA,UAAM,gBAAAA,SAAG,GAAG,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACxE;AACF;;;ACjZA,IAAM,+BAA+B,KAAK,KAAK;AAC/C,IAAM,4BAA4B,IAAI,KAAK;AAG3C,IAAM,6BAA6B,IAAI,KAAK;AAC5C,IAAM,yBAAyB,IAAI,KAAK;AAkBjC,SAAS,eAAe,UAA+D;AAC5F,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,QAAM,aAAa;AAAA,IACjB,SAAS,SAAS;AAAA,IAClB,SAAS,WAAW;AAAA,EACtB,EAAE,OAAO,CAAC,UAA2B,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,CAAC;AAExF,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,SAAO,KAAK,IAAI,GAAG,UAAU;AAC/B;;;ACrDA,IAAAI,kBAA4C;AAC5C,IAAAC,oBAAiB;AACjB,IAAAC,kBAAe;;;ACFR,IAAM,2BAA2B;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ADSA,IAAM,qBAAqB;AAC3B,IAAM,uBAAuB;AAC7B,IAAM,8BAA8B;AACpC,IAAM,yBAAyB;AAC/B,IAAM,2BAA2B;AACjC,IAAM,oBAAoB;AAC1B,IAAM,yBAAyB;AAC/B,IAAM,2BAA2B;AACjC,IAAM,wBAAwB;AAC9B,IAAM,6BAA6B;AAQnC,SAASC,UAAS,OAAkD;AAClE,SAAO,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAASC,UAAS,OAA+B;AAC/C,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAASC,kBAAyB;AAChC,QAAM,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI,eAAe,gBAAAC,QAAG,QAAQ;AACvE,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,kBAAkB;AAAA,EACpC;AACA,SAAO;AACT;AAEA,SAAS,kBAA0B;AACjC,SAAO,kBAAAC,QAAK,KAAKF,gBAAe,GAAG,QAAQ;AAC7C;AAEA,SAAS,qBAAqB,UAA4B;AACxD,SAAO,kBAAAE,QAAK,KAAK,gBAAgB,GAAG,GAAG,QAAQ;AACjD;AAEA,eAAe,aAAa,UAAoC;AAC9D,QAAM,MAAM,MAAM,gBAAAC,SAAG,SAAS,UAAU,MAAM;AAC9C,SAAO,KAAK,MAAM,GAAG;AACvB;AAEA,eAAe,qBAAqB,UAA2C;AAC7E,MAAI;AACF,WAAO,MAAM,aAAa,QAAQ;AAAA,EACpC,SAAS,OAAO;AACd,UAAM,OAAQ,MAAgC;AAC9C,QAAI,SAAS,UAAU;AACrB,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAe,oBAAoB,QAAgB,aAAoC;AACrF,QAAM,gBAAAA,SAAG,MAAM,aAAa,EAAE,WAAW,KAAK,CAAC;AAC/C,QAAM,UAAU,MAAM,gBAAAA,SAAG,QAAQ,QAAQ,EAAE,eAAe,KAAK,CAAC;AAEhE,aAAW,SAAS,SAAS;AAC3B,UAAM,UAAU,kBAAAD,QAAK,KAAK,QAAQ,MAAM,IAAI;AAC5C,UAAM,WAAW,kBAAAA,QAAK,KAAK,aAAa,MAAM,IAAI;AAElD,QAAI,MAAM,eAAe,GAAG;AAC1B,YAAM,aAAa,MAAM,gBAAAC,SAAG,SAAS,OAAO;AAC5C,YAAM,gBAAAA,SAAG,QAAQ,YAAY,QAAQ,EAAE,MAAM,WAAS;AACpD,YAAK,MAAgC,SAAS,UAAU;AACtD,gBAAM;AAAA,QACR;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAEA,QAAI,MAAM,YAAY,GAAG;AACvB,YAAM,oBAAoB,SAAS,QAAQ;AAC3C;AAAA,IACF;AAEA,QAAI,MAAM,OAAO,GAAG;AAClB,YAAM,gBAAAA,SAAG,SAAS,SAAS,QAAQ;AAAA,IACrC;AAAA,EACF;AACF;AAEA,eAAe,gBAAgB,QAAgB,aAAoC;AACjF,MAAI,QAAoD;AACxD,MAAI;AACF,YAAQ,MAAM,gBAAAA,SAAG,KAAK,MAAM;AAAA,EAC9B,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,UAAU;AACtD;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAEA,MAAI,CAAC,MAAM,YAAY,GAAG;AACxB;AAAA,EACF;AAGA,QAAM,gBAAAA,SAAG,GAAG,aAAa,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACzD,QAAM,gBAAAA,SAAG,MAAM,kBAAAD,QAAK,QAAQ,WAAW,GAAG,EAAE,WAAW,KAAK,CAAC;AAC7D,MAAI;AACF,UAAM,gBAAAC,SAAG,GAAG,QAAQ,aAAa;AAAA,MAC/B,WAAW;AAAA,MACX,cAAc;AAAA,MACd,OAAO;AAAA,MACP,aAAa;AAAA,MACb,kBAAkB;AAAA,IACpB,CAAC;AAAA,EACH,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,oBAAoB;AAChE,YAAM,oBAAoB,QAAQ,WAAW;AAC7C;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAe,iBACb,QACA,aACA,SACe;AACf,MAAI;AACF,UAAM,aAAa,MAAM,gBAAAA,SAAG,KAAK,MAAM;AACvC,QAAI,CAAC,WAAW,OAAO,GAAG;AACxB;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,UAAU;AACtD;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAEA,MAAI;AACF,UAAM,kBAAkB,MAAM,gBAAAA,SAAG,KAAK,WAAW;AACjD,QAAI,gBAAgB,OAAO,GAAG;AAC5B;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,UAAU;AACtD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,gBAAAA,SAAG,MAAM,kBAAAD,QAAK,QAAQ,WAAW,GAAG,EAAE,WAAW,KAAK,CAAC;AAC7D,QAAM,gBAAAC,SAAG,SAAS,QAAQ,WAAW;AACrC,MAAI,OAAO,SAAS,SAAS,UAAU;AACrC,UAAM,gBAAAA,SAAG,MAAM,aAAa,QAAQ,IAAI,EAAE,MAAM,MAAM,MAAS;AAAA,EACjE;AACF;AAEA,eAAe,4BAA4B,WAAkC;AAC3E,QAAM,eAAe,kBAAAD,QAAK,KAAK,WAAW,wBAAwB,CAAC;AAEnE,MAAI,UAAoB,CAAC;AACzB,MAAI;AACF,cAAU,MAAM,gBAAAC,SAAG,QAAQ,WAAW,EAAE,eAAe,KAAK,CAAC;AAAA,EAC/D,QAAQ;AACN;AAAA,EACF;AAEA,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,YAAY,KAAK,MAAM,KAAK,WAAW,GAAG,GAAG;AACtD;AAAA,IACF;AACA,UAAM,eAAe,kBAAAD,QAAK,KAAK,WAAW,MAAM,MAAM,qBAAqB,CAAC;AAAA,EAC9E;AACF;AAEA,eAAe,qCAAoD;AACjE,QAAM,cAAc,eAAe;AACnC,QAAM,iBAAiB,gBAAgB;AAEvC,QAAM;AAAA,IACJ,kBAAAA,QAAK,KAAK,gBAAgB,wBAAwB;AAAA,IAClD,kBAAAA,QAAK,KAAK,aAAa,wBAAwB;AAAA,EACjD;AACA,QAAM;AAAA,IACJ,kBAAAA,QAAK,KAAK,gBAAgB,iBAAiB;AAAA,IAC3C,kBAAAA,QAAK,KAAK,aAAa,iBAAiB;AAAA,EAC1C;AACA,QAAM;AAAA,IACJ,kBAAAA,QAAK,KAAK,gBAAgB,sBAAsB;AAAA,IAChD,kBAAAA,QAAK,KAAK,aAAa,sBAAsB;AAAA,EAC/C;AACA,QAAM;AAAA,IACJ,kBAAAA,QAAK,KAAK,gBAAgB,0BAA0B;AAAA,IACpD,kBAAAA,QAAK,KAAK,aAAa,0BAA0B;AAAA,IACjD,EAAE,MAAM,IAAM;AAAA,EAChB;AAEA,QAAM,4BAA4B,kBAAAA,QAAK,KAAK,aAAa,iBAAiB,CAAC;AAC7E;AAEA,SAAS,aAAa,KAAuC;AAC3D,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,0BAA0B,GAAgC;AAAA,EACnE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,mBAAmB,KAAmC;AAC7D,MAAI,CAACJ,UAAS,GAAG,GAAG;AAClB,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,uBAAuB;AAAA,MACvB,QAAQ;AAAA,MACR,WAAW;AAAA,IACb;AAAA,EACF;AAEA,QAAM,kBAAkBC,UAAS,IAAI,MAAM;AAC3C,QAAM,SAAS,CAAC,YAAY,UAAU,SAAS,OAAO,EAAE,SAAS,mBAAmB,EAAE,IACjF,kBACD;AAEJ,SAAO;AAAA,IACL,YAAYA,UAAS,IAAI,cAAc,IAAI,WAAW;AAAA,IACtD,eAAeA,UAAS,IAAI,iBAAiB,IAAI,cAAc;AAAA,IAC/D,gBAAgBA,UAAS,IAAI,kBAAkB,IAAI,gBAAgB;AAAA,IACnE,aAAaA,UAAS,IAAI,eAAe,IAAI,aAAa;AAAA,IAC1D,uBAAuBA,UAAS,IAAI,yBAAyB,IAAI,uBAAuB;AAAA,IACxF;AAAA,IACA,WAAWA,UAAS,IAAI,SAAS;AAAA,EACnC;AACF;AAEA,SAAS,yBAAyB,MAAc,KAAyC;AACvF,MAAI,CAACD,UAAS,GAAG,GAAG;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,IAAI;AACpB,MAAI,OAA2B;AAC/B,MAAIA,UAAS,OAAO,GAAG;AACrB,WAAO;AAAA,EACT,WAAW,OAAO,YAAY,UAAU;AACtC,QAAI;AACF,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA,aAAaC,UAAS,IAAI,eAAe,IAAI,YAAY,KAAK;AAAA,IAC9D;AAAA,IACA,UAAUD,UAAS,IAAI,QAAQ,IAAK,IAAI,WAA+B;AAAA,IACvE,WAAWC,UAAS,IAAI,aAAa,IAAI,UAAU;AAAA,IACnD,aAAaA,UAAS,IAAI,eAAe,IAAI,YAAY;AAAA,IACzD,eAAeA,UAAS,IAAI,iBAAiB,IAAI,cAAc;AAAA,IAC/D,OAAOA,UAAS,IAAI,KAAK;AAAA,IACzB,YAAYA,UAAS,IAAI,cAAc,IAAI,WAAW;AAAA,IACtD,WAAWA,UAAS,IAAI,aAAa,IAAI,UAAU;AAAA,IACnD,WAAWA,UAAS,IAAI,aAAa,IAAI,UAAU;AAAA,EACrD;AACF;AAEA,eAAe,0BAAkD;AAC/D,QAAM,WAAW,kBAAkB,oBAAoB;AACvD,QAAM,MAAM,MAAM,qBAAqB,QAAQ;AAC/C,MAAI,CAACD,UAAS,GAAG,GAAG;AAClB,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAAW,aAAa,IAAI,YAAY,IAAI,SAAS;AAC3D,QAAM,UAAU,mBAAmB,IAAI,WAAW,IAAI,gBAAgB,IAAI,aAAa;AAEvF,SAAO;AAAA,IACL,KAAK;AAAA,MACH,gBAAgBC,UAAS,IAAI,kBAAkB,IAAI,gBAAgB;AAAA,MACnE,sBAAsBA,UAAS,IAAI,wBAAwB,IAAI,sBAAsB;AAAA,MACrF,iBAAiBA,UAAS,IAAI,mBAAmB,IAAI,iBAAiB;AAAA,IACxE;AAAA,IACA;AAAA,IACA,UAAU,WACN;AAAA,MACE,SAAS,SAAS;AAAA,MAClB,kBAAkB,SAAS;AAAA,MAC3B,iBAAiB,SAAS;AAAA,IAC5B,IACA;AAAA,EACN;AACF;AAEA,eAAe,sBAA8C;AAC3D,QAAM,WAAW,kBAAkB,sBAAsB;AACzD,QAAM,MAAM,MAAM,qBAAqB,QAAQ;AAC/C,MAAI,CAACD,UAAS,GAAG,GAAG;AAClB,WAAO,CAAC;AAAA,EACV;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,MACJ,YAAYC,UAAS,IAAI,UAAU;AAAA,MACnC,YAAYA,UAAS,IAAI,UAAU;AAAA,MACnC,WAAWA,UAAS,IAAI,SAAS;AAAA,MACjC,iBAAiBA,UAAS,IAAI,eAAe;AAAA,IAC/C;AAAA,EACF;AACF;AAEA,eAAe,0BAAkD;AAC/D,QAAM,OAAO,kBAAkB,wBAAwB;AACvD,MAAI,UAAoB,CAAC;AACzB,MAAI;AACF,cAAU,MAAM,gBAAAI,SAAG,QAAQ,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,EAC1D,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,UAAU;AACtD,aAAO,CAAC;AAAA,IACV;AACA,UAAM;AAAA,EACR;AAEA,QAAM,iBAAqD,CAAC;AAC5D,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,YAAY,KAAK,MAAM,KAAK,WAAW,GAAG,GAAG;AACtD;AAAA,IACF;AACA,UAAM,cAAc,kBAAAD,QAAK,KAAK,MAAM,MAAM,MAAM,cAAc;AAC9D,UAAM,MAAM,MAAM,qBAAqB,WAAW;AAClD,QAAI,CAAC,KAAK;AACR;AAAA,IACF;AAEA,UAAM,SAAS,yBAAyB,MAAM,MAAM,GAAG;AACvD,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AAEA,mBAAe,MAAM,IAAI,IAAI;AAAA,EAC/B;AAEA,MAAI,OAAO,KAAK,cAAc,EAAE,WAAW,GAAG;AAC5C,WAAO,CAAC;AAAA,EACV;AAEA,SAAO,EAAE,eAAe;AAC1B;AAEA,SAAS,0BAA0B,KAAyC;AAC1E,MAAI,CAACJ,UAAS,GAAG,GAAG;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,KAAKC,UAAS,IAAI,EAAE;AAC1B,MAAI,CAAC,IAAI;AACP,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAMA,UAAS,IAAI,IAAI;AAAA,IACvB,UAAUA,UAAS,IAAI,QAAQ;AAAA,IAC/B,aAAaA,UAAS,IAAI,WAAW;AAAA,IACrC,YACE,IAAI,eAAe,cAAc,IAAI,eAAe,eAAe,IAAI,eAAe,UAClF,IAAI,aACJ;AAAA,IACN,SAASA,UAAS,IAAI,OAAO;AAAA,IAC7B,WAAWA,UAAS,IAAI,SAAS;AAAA,EACnC;AACF;AAEA,eAAe,wBAAgD;AAC7D,QAAM,aAAa,kBAAkB,iBAAiB;AACtD,QAAM,YAAY,kBAAAG,QAAK,KAAK,YAAY,wBAAwB;AAChE,QAAM,WAAW,MAAM,qBAAqB,SAAS;AAErD,QAAM,iBAAqD,CAAC;AAC5D,MAAI,aAA4B,CAAC;AAEjC,MAAI;AACF,iBAAa,MAAM,gBAAAC,SAAG,QAAQ,YAAY,EAAE,eAAe,KAAK,CAAC;AAAA,EACnE,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,UAAU;AACtD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,aAAW,SAAS,YAAY;AAC9B,QAAI,CAAC,MAAM,YAAY,GAAG;AACxB;AAAA,IACF;AACA,QAAI,MAAM,KAAK,WAAW,GAAG,GAAG;AAC9B;AAAA,IACF;AACA,UAAM,eAAe,kBAAAD,QAAK,KAAK,YAAY,MAAM,MAAM,qBAAqB;AAC5E,UAAM,cAAc,MAAM,qBAAqB,YAAY;AAC3D,UAAM,SAAS,0BAA0B,WAAW;AACpD,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AACA,mBAAe,MAAM,IAAI,IAAI;AAAA,EAC/B;AAEA,QAAM,UAAUJ,UAAS,QAAQ,KAAK,MAAM,QAAQ,SAAS,OAAO,IAC/D,SAAS,UACV,CAAC;AAEL,MAAI,QAAQ,WAAW,KAAK,OAAO,KAAK,cAAc,EAAE,WAAW,GAAG;AACpE,WAAO,CAAC;AAAA,EACV;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,6BAA6B,SAAiE;AACrG,QAAM,QAAuB,CAAC;AAC9B,QAAM,eAAe,oBAAI,IAAY;AACrC,QAAM,cAAc,oBAAI,IAAY;AACpC,QAAM,oBAAoB,IAAI;AAAA,IAC5B,OAAO,KAAK,OAAO,EAAE;AAAA,MAAO,CAAC,QAC1B,yBAA+C,SAAS,GAAG;AAAA,IAC9D;AAAA,EACF;AACA,QAAM,SAAS,CAAC,QAA+B,kBAAkB,IAAI,GAAG;AACxE,QAAM,uBAAuB,CAAC,KAA4B,aAAsB;AAC9E,QAAI,CAAC,OAAO,GAAG,GAAG;AAChB;AAAA,IACF;AACA,QAAI,UAAU;AACZ,mBAAa,IAAI,GAAG;AAAA,IACtB,OAAO;AACL,kBAAY,IAAI,GAAG;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,kBAAkB,QAAQ,kBAAkB;AAClD,MAAIA,UAAS,eAAe,GAAG;AAC7B,UAAM,qBAAqB,MAAM,QAAQ,gBAAgB,cAAc,IAClE,gBAAgB,eAAe,OAAO,UAAQ,OAAO,SAAS,QAAQ,IACvE;AACJ,UAAM,WACJ,OAAO,gBAAgB,2BAA2B,YAC9C,gBAAgB,yBAChB;AACN,UAAM,YACJ,OAAO,gBAAgB,4BAA4B,YAC/C,gBAAgB,0BAChB;AACN,UAAM,cAAc;AAAA,MAClB,gBAAgB;AAAA,MAChB,wBAAwB;AAAA,MACxB,yBAAyB;AAAA,IAC3B;AACA;AAAA,MACE;AAAA,MACA,uBAAuB,UAAa,aAAa,UAAa,cAAc;AAAA,IAC9E;AAAA,EACF,OAAO;AACL,yBAAqB,oBAAoB,KAAK;AAAA,EAChD;AAEA,QAAM,WAAW,QAAQ;AACzB,MAAIA,UAAS,QAAQ,GAAG;AACtB,UAAM,OAAO,MAAM,QAAQ,SAAS,SAAS,IACxC,SAAS,UACP,OAAOA,SAAQ,EACf,IAAI,WAAS;AAAA,MACZ,IAAIC,UAAS,KAAK,EAAE,KAAK;AAAA,MACzB,MAAMA,UAAS,KAAK,IAAI,KAAK;AAAA,MAC7B,QAAQ,MAAM,QAAQ,KAAK,MAAM,IAC5B,KAAK,OAAO,OAAO,WAAS,OAAO,UAAU,QAAQ,IACtD,CAAC;AAAA,MACL,QAAQA,UAAS,KAAK,MAAM,KAAK;AAAA,MACjC,SAASA,UAAS,KAAK,OAAO,KAAK;AAAA,IACrC,EAAE,EACD,OAAO,UAAQ,KAAK,MAAM,KAAK,IAAI,IACtC;AAEJ,UAAM,kBAAkBD,UAAS,SAAS,eAAe,IACpD,SAAS,kBACV;AAEJ,UAAM,YAAY;AAAA,MAChB;AAAA,MACA,oBAAoBC,UAAS,SAAS,kBAAkB,KAAK;AAAA,MAC7D,cAAcA,UAAS,SAAS,gBAAgB,SAAS,aAAa;AAAA,MACtE,wBACE,OAAO,SAAS,2BAA2B,WACtC,SAAS,yBACV,OAAO,SAAS,oBAAoB,WACjC,SAAS,kBACV;AAAA,MACR;AAAA,IACF;AACA;AAAA,MACE;AAAA,MACA,SAAS,UACPA,UAAS,SAAS,kBAAkB,MAAM,QAC1CA,UAAS,SAAS,gBAAgB,SAAS,aAAa,MAAM,QAC9D,OAAO,SAAS,2BAA2B,YAC3C,OAAO,SAAS,oBAAoB,YACpC,oBAAoB;AAAA,IACxB;AAAA,EACF,OAAO;AACL,yBAAqB,YAAY,KAAK;AAAA,EACxC;AAEA,QAAM,UAAU,QAAQ,iBAAiB;AACzC,MAAID,UAAS,OAAO,GAAG;AACrB,UAAM,cAAcC,UAAS,QAAQ,eAAe,QAAQ,IAAI,KAAK;AACrE,UAAM,wBACJA,UAAS,QAAQ,yBAAyB,QAAQ,cAAc,KAAK;AACvE,UAAM,kBAAkBD,UAAS,QAAQ,eAAe,IACnD,QAAQ,kBACT;AACJ,UAAM,UAAU;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA;AAAA,MACE;AAAA,MACA,gBAAgB,UAAa,0BAA0B,UAAa,oBAAoB;AAAA,IAC1F;AAAA,EACF,OAAO;AACL,yBAAqB,mBAAmB,KAAK;AAAA,EAC/C;AAEA,QAAM,kBAAkB,QAAQ,0BAA0B;AAC1D,MAAIA,UAAS,eAAe,KAAKA,UAAS,gBAAgB,cAAc,GAAG;AACzE,UAAM,0BAA0B,gBAAgB;AAChD,yBAAqB,4BAA4B,IAAI;AAAA,EACvD,OAAO;AACL,yBAAqB,4BAA4B,KAAK;AAAA,EACxD;AAEA,QAAM,SAAS,QAAQ,gBAAgB;AACvC,MAAIA,UAAS,MAAM,GAAG;AACpB,UAAM,gBAAgB,MAAM,QAAQ,OAAO,aAAa,IACnD,OAAO,cAAc,OAAOA,SAAQ,IACrC;AACJ,UAAM,cAAc,MAAM,QAAQ,OAAO,WAAW,IAC/C,OAAO,YAAY,OAAO,UAAQ,OAAO,SAAS,QAAQ,IAC3D;AACJ,UAAM,cAAc;AAAA,MAClB,GAAI,MAAM,eAAe,CAAC;AAAA,MAC1B;AAAA,MACA;AAAA,IACF;AACA,yBAAqB,kBAAkB,kBAAkB,UAAa,gBAAgB,MAAS;AAAA,EACjG,OAAO;AACL,yBAAqB,kBAAkB,KAAK;AAAA,EAC9C;AAEA,QAAM,aAAa,QAAQ,iCAAiC;AAC5D,MAAI,qBAAqB;AACzB,MAAIA,UAAS,UAAU,GAAG;AACxB,QAAIA,UAAS,WAAW,eAAe,GAAG;AACxC,YAAM,8BACJ,WAAW;AACb,2BAAqB;AAAA,IACvB;AACA,QAAIA,UAAS,WAAW,yBAAyB,GAAG;AAClD,YAAM,uCACJ,WAAW;AACb,2BAAqB;AAAA,IACvB;AAAA,EACF;AACA,uBAAqB,mCAAmC,kBAAkB;AAE1E,QAAM,iBAAiB,QAAQ,0BAA0B;AACzD,QAAM,WAAW,aAAa,cAAc;AAC5C,MAAI,UAAU;AACZ,UAAM,WAAW;AAAA,MACf,SAAS,SAAS;AAAA,MAClB,kBAAkB,SAAS;AAAA,MAC3B,iBAAiB,SAAS;AAAA,IAC5B;AACA,yBAAqB,4BAA4B,IAAI;AAAA,EACvD,OAAO;AACL,yBAAqB,4BAA4B,KAAK;AAAA,EACxD;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAc,MAAM,KAAK,YAAY;AAAA,IACrC,aAAa,MAAM,KAAK,WAAW;AAAA,EACrC;AACF;AAEA,eAAe,eAAe,QAA+B;AAC3D,QAAM,gBAAAK,SAAG,GAAG,QAAQ,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACtD;AAEA,eAAe,gCAA+C;AAC5D,QAAM,UAAUH,gBAAe;AAE/B,QAAM,eAAe,kBAAAE,QAAK,KAAK,SAAS,kBAAkB,CAAC;AAC3D,QAAM,eAAe,kBAAkB,oBAAoB,CAAC;AAC5D,QAAM,eAAe,kBAAkB,2BAA2B,CAAC;AACnE,QAAM,eAAe,kBAAkB,sBAAsB,CAAC;AAC9D,QAAM,eAAe,kBAAkB,0BAA0B,CAAC;AAClE,QAAM,eAAe,kBAAkB,mBAAmB,wBAAwB,CAAC;AAEnF,QAAM,mBAAmB,kBAAkB,wBAAwB;AACnE,MAAI;AACF,UAAM,eAAe,MAAM,gBAAAC,SAAG,QAAQ,kBAAkB,EAAE,eAAe,KAAK,CAAC;AAC/E,eAAW,eAAe,cAAc;AACtC,UAAI,CAAC,YAAY,YAAY,GAAG;AAC9B;AAAA,MACF;AACA,YAAM,aAAa,kBAAAD,QAAK,KAAK,kBAAkB,YAAY,IAAI;AAC/D,UAAI,QAAkB,CAAC;AACvB,UAAI;AACF,gBAAQ,MAAM,gBAAAC,SAAG,QAAQ,UAAU;AAAA,MACrC,QAAQ;AACN;AAAA,MACF;AACA,iBAAW,QAAQ,OAAO;AACxB,YAAI,CAAC,KAAK,WAAW,cAAc,GAAG;AACpC;AAAA,QACF;AACA,cAAM,eAAe,kBAAAD,QAAK,KAAK,YAAY,IAAI,CAAC;AAAA,MAClD;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAEd,YAAQ,4CAA4C;AAAA,MAClD;AAAA,MACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D,CAAC;AAAA,EACH;AAEA,QAAM,aAAa,kBAAkB,iBAAiB;AACtD,MAAI;AACF,UAAM,YAAY,MAAM,gBAAAC,SAAG,QAAQ,YAAY,EAAE,eAAe,KAAK,CAAC;AACtE,eAAW,SAAS,WAAW;AAC7B,UAAI,CAAC,MAAM,YAAY,KAAK,MAAM,KAAK,WAAW,GAAG,GAAG;AACtD;AAAA,MACF;AACA,YAAM,eAAe,kBAAAD,QAAK,KAAK,YAAY,MAAM,MAAM,qBAAqB,CAAC;AAAA,IAC/E;AAAA,EACF,SAAS,OAAO;AAEd,YAAQ,2CAA2C;AAAA,MACjD;AAAA,MACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D,CAAC;AAAA,EACH;AACF;AAEA,eAAsB,wBAA2C;AAC/D,QAAM,UAAU,MAAM,YAAY;AAClC,MAAI,QAAQ,UAAU,WAAW,cAAc,QAAQ,UAAU,WAAW,yBAAyB;AACnG,WAAO;AAAA,EACT;AAEA,QAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AAEzC,MAAI;AACF,UAAM,mCAAmC;AACzC,UAAM,UAAU,MAAM,QAAQ,IAAI;AAAA,MAChC,wBAAwB;AAAA,MACxB,oBAAoB;AAAA,MACpB,wBAAwB;AAAA,MACxB,sBAAsB;AAAA,IACxB,CAAC;AAED,UAAM,cAA6B,QAAQ,OAAO,CAAC,KAAK,UAAU;AAChE,aAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG;AAAA,QACH,KAAK,EAAE,GAAI,IAAI,OAAO,CAAC,GAAI,GAAI,MAAM,OAAO,CAAC,EAAG;AAAA,QAChD,SAAS,EAAE,GAAI,IAAI,WAAW,CAAC,GAAI,GAAI,MAAM,WAAW,CAAC,EAAG;AAAA,QAC5D,UAAU,EAAE,GAAI,IAAI,YAAY,CAAC,GAAI,GAAI,MAAM,YAAY,CAAC,EAAG;AAAA,QAC/D,WAAW,EAAE,GAAI,IAAI,aAAa,CAAC,GAAI,GAAI,MAAM,aAAa,CAAC,EAAG;AAAA,QAClE,SAAS,EAAE,GAAI,IAAI,WAAW,CAAC,GAAI,GAAI,MAAM,WAAW,CAAC,EAAG;AAAA,QAC5D,aAAa,EAAE,GAAI,IAAI,eAAe,CAAC,GAAI,GAAI,MAAM,eAAe,CAAC,EAAG;AAAA,QACxE,MAAM,EAAE,GAAI,IAAI,QAAQ,CAAC,GAAI,GAAI,MAAM,QAAQ,CAAC,EAAG;AAAA,QACnD,gBAAgB,EAAE,GAAI,IAAI,kBAAkB,CAAC,GAAI,GAAI,MAAM,kBAAkB,CAAC,EAAG;AAAA,QACjF,yBAAyB;AAAA,UACvB,GAAI,IAAI,2BAA2B,CAAC;AAAA,UACpC,GAAI,MAAM,2BAA2B,CAAC;AAAA,QACxC;AAAA,QACA,6BAA6B;AAAA,UAC3B,GAAI,IAAI,+BAA+B,CAAC;AAAA,UACxC,GAAI,MAAM,+BAA+B,CAAC;AAAA,QAC5C;AAAA,QACA,sCAAsC;AAAA,UACpC,GAAI,IAAI,wCAAwC,CAAC;AAAA,UACjD,GAAI,MAAM,wCAAwC,CAAC;AAAA,QACrD;AAAA,QACA,QAAQ;AAAA,UACN,GAAI,IAAI,UAAU,CAAC;AAAA,UACnB,GAAI,MAAM,UAAU,CAAC;AAAA,UACrB,SAAS,MAAM,QAAQ,WAAW,IAAI,QAAQ;AAAA,UAC9C,gBAAgB;AAAA,YACd,GAAI,IAAI,QAAQ,kBAAkB,CAAC;AAAA,YACnC,GAAI,MAAM,QAAQ,kBAAkB,CAAC;AAAA,UACvC;AAAA,QACF;AAAA,MACF;AAAA,IACF,GAAG,CAAC,CAAkB;AAEtB,WAAO,MAAM,eAAe,CAAC,WAAW;AAAA,MACtC,GAAG;AAAA,MACH,GAAG;AAAA,MACH,KAAK,EAAE,GAAG,MAAM,KAAK,GAAI,YAAY,OAAO,CAAC,EAAG;AAAA,MAChD,SAAS,EAAE,GAAG,MAAM,SAAS,GAAI,YAAY,WAAW,CAAC,EAAG;AAAA,MAC5D,UAAU,EAAE,GAAG,MAAM,UAAU,GAAI,YAAY,YAAY,CAAC,EAAG;AAAA,MAC/D,WAAW;AAAA,QACT,GAAG,MAAM;AAAA,QACT,GAAI,YAAY,aAAa,CAAC;AAAA,QAC9B,iBAAiB;AAAA,UACf,GAAG,MAAM,UAAU;AAAA,UACnB,GAAI,YAAY,WAAW,mBAAmB,CAAC;AAAA,QACjD;AAAA,MACF;AAAA,MACA,SAAS;AAAA,QACP,GAAG,MAAM;AAAA,QACT,GAAI,YAAY,WAAW,CAAC;AAAA,QAC5B,iBAAiB;AAAA,UACf,GAAG,MAAM,QAAQ;AAAA,UACjB,GAAI,YAAY,SAAS,mBAAmB,CAAC;AAAA,QAC/C;AAAA,MACF;AAAA,MACA,aAAa,EAAE,GAAG,MAAM,aAAa,GAAI,YAAY,eAAe,CAAC,EAAG;AAAA,MACxE,MAAM,EAAE,GAAG,MAAM,MAAM,GAAI,YAAY,QAAQ,CAAC,EAAG;AAAA,MACnD,gBAAgB;AAAA,QACd,GAAG,MAAM;AAAA,QACT,GAAI,YAAY,kBAAkB,CAAC;AAAA,MACrC;AAAA,MACA,yBAAyB;AAAA,QACvB,GAAG,MAAM;AAAA,QACT,GAAI,YAAY,2BAA2B,CAAC;AAAA,MAC9C;AAAA,MACA,6BAA6B;AAAA,QAC3B,GAAG,MAAM;AAAA,QACT,GAAI,YAAY,+BAA+B,CAAC;AAAA,MAClD;AAAA,MACA,sCAAsC;AAAA,QACpC,GAAG,MAAM;AAAA,QACT,GAAI,YAAY,wCAAwC,CAAC;AAAA,MAC3D;AAAA,MACA,QAAQ;AAAA,QACN,GAAG,MAAM;AAAA,QACT,GAAI,YAAY,UAAU,CAAC;AAAA,QAC3B,gBAAgB;AAAA,UACd,GAAG,MAAM,OAAO;AAAA,UAChB,GAAI,YAAY,QAAQ,kBAAkB,CAAC;AAAA,QAC7C;AAAA,MACF;AAAA,MACA,WAAW;AAAA,QACT,GAAG,MAAM;AAAA,QACT,QAAQ;AAAA,QACR,WAAW,MAAM,UAAU,aAAa;AAAA,QACxC,aAAa;AAAA,QACb,wBAAwB;AAAA,QACxB,WAAW;AAAA,MACb;AAAA,IACF,IAAI;AAAA,MACF,MAAM;AAAA,MACN,8BAA8B;AAAA,IAChC,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,eAAe,CAAC,WAAW;AAAA,MAC/B,GAAG;AAAA,MACH,WAAW;AAAA,QACT,GAAG,MAAM;AAAA,QACT,QAAQ;AAAA,QACR,WAAW,MAAM,UAAU,aAAa;AAAA,QACxC,WAAW;AAAA,MACb;AAAA,IACF,IAAI;AAAA,MACF,MAAM;AAAA,MACN,8BAA8B;AAAA,IAChC,CAAC;AACD,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,6BACpB,SACiF;AACjF,QAAM,UAAU,MAAM,YAAY;AAClC,MAAI,QAAQ,UAAU,WAAW,YAAY;AAC3C,WAAO,EAAE,WAAW,MAAM,cAAc,CAAC,GAAG,aAAa,CAAC,EAAE;AAAA,EAC9D;AAEA,MAAI,QAAQ,UAAU,WAAW,yBAAyB;AACxD,WAAO,EAAE,WAAW,OAAO,cAAc,CAAC,GAAG,aAAa,CAAC,EAAE;AAAA,EAC/D;AAEA,MAAI,CAAC,WAAW,CAACJ,UAAS,OAAO,GAAG;AAClC,WAAO,EAAE,WAAW,OAAO,cAAc,CAAC,GAAG,aAAa,CAAC,EAAE;AAAA,EAC/D;AAEA,QAAM,EAAE,OAAO,cAAc,YAAY,IAAI,6BAA6B,OAAO;AAEjF,QAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC3C,QAAM,OAAO,MAAM,eAAe,CAAC,UAAU;AAC3C,QAAI,MAAM,UAAU,WAAW,yBAAyB;AACtD,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,MACH,KAAK,EAAE,GAAG,MAAM,KAAK,GAAI,MAAM,OAAO,CAAC,EAAG;AAAA,MAC1C,UAAU,EAAE,GAAG,MAAM,UAAU,GAAI,MAAM,YAAY,CAAC,EAAG;AAAA,MACzD,SAAS,EAAE,GAAG,MAAM,SAAS,GAAI,MAAM,WAAW,CAAC,EAAG;AAAA,MACtD,WAAW;AAAA,QACT,GAAG,MAAM;AAAA,QACT,GAAI,MAAM,aAAa,CAAC;AAAA,QACxB,iBAAiB;AAAA,UACf,GAAG,MAAM,UAAU;AAAA,UACnB,GAAI,MAAM,WAAW,mBAAmB,CAAC;AAAA,QAC3C;AAAA,MACF;AAAA,MACA,SAAS;AAAA,QACP,GAAG,MAAM;AAAA,QACT,GAAI,MAAM,WAAW,CAAC;AAAA,QACtB,iBAAiB;AAAA,UACf,GAAG,MAAM,QAAQ;AAAA,UACjB,GAAI,MAAM,SAAS,mBAAmB,CAAC;AAAA,QACzC;AAAA,MACF;AAAA,MACA,aAAa,EAAE,GAAG,MAAM,aAAa,GAAI,MAAM,eAAe,CAAC,EAAG;AAAA,MAClE,yBAAyB;AAAA,QACvB,GAAG,MAAM;AAAA,QACT,GAAI,MAAM,2BAA2B,CAAC;AAAA,MACxC;AAAA,MACA,6BAA6B;AAAA,QAC3B,GAAG,MAAM;AAAA,QACT,GAAI,MAAM,+BAA+B,CAAC;AAAA,MAC5C;AAAA,MACA,sCAAsC;AAAA,QACpC,GAAG,MAAM;AAAA,QACT,GAAI,MAAM,wCAAwC,CAAC;AAAA,MACrD;AAAA,MACA,WAAW;AAAA,QACT,GAAG,MAAM;AAAA,QACT,QAAQ;AAAA,QACR;AAAA,QACA,wBAAwB;AAAA,QACxB,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF,GAAG;AAAA,IACD,MAAM;AAAA,IACN,8BAA8B;AAAA,EAChC,CAAC;AAED,MAAI,KAAK,UAAU,WAAW,YAAY;AACxC,WAAO,EAAE,WAAW,OAAO,cAAc,CAAC,GAAG,aAAa,CAAC,EAAE;AAAA,EAC/D;AAEA,QAAM,8BAA8B;AACpC,SAAO,EAAE,WAAW,MAAM,cAAc,cAAc,YAAY;AACpE;;;AEj4BA,IAAAM,qBAAiB;;;ACAjB,IAAAC,6BAAsE;AACtE,yBAA6B;AAC7B,IAAAC,wBAAqB;AACrB,IAAAC,qBAAiB;;;ACIjB,IAAM,oBAAoB,oBAAI,IAAI,CAAC,YAAY,aAAa,WAAW,CAAC;AAEjE,SAAS,iBAAiB,QAAyB;AACxD,SAAO,kBAAkB,IAAI,MAAM;AACrC;AAEO,SAAS,qBAAqB,QAInC;AACA,SAAO;AAAA,IACL,UAAU,QAAQ,YAAY;AAAA,IAC9B,QAAQ,QAAQ,UAAU;AAAA,IAC1B,OAAO,QAAQ,SAAS;AAAA,EAC1B;AACF;AAEO,SAAS,yBAAyB,OAAgB,QAAyB;AAChF,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,EACT;AACA,QAAM,OAAO,OAAQ,MAA6B,SAAS,WACrD,MAA2B,OAC7B;AACJ,MAAI,SAAS,UAAU,SAAS,QAAQ;AACtC,WAAO;AAAA,EACT;AACA,QAAM,UAAU,OAAQ,MAAgC,YAAY,WAC9D,MAA8B,QAAS,YAAY,IACrD;AACJ,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,QAAM,mBAAmB,OAAO,YAAY;AAC5C,MAAI,QAAQ,SAAS,kBAAkB,KAAK,QAAQ,SAAS,gBAAgB,GAAG;AAC9E,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,SAAS,iBAAiB,KAAK,QAAQ,SAAS,gBAAgB;AACjF;AAqCO,SAAS,8BAA8B,OAAyB;AACrE,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,EACT;AACA,QAAM,UAAU,OAAQ,MAAgC,YAAY,WAC9D,MAA8B,QAAS,YAAY,IACrD;AACJ,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,QAAM,iBAAiB,QAAQ,SAAS,QAAQ;AAChD,QAAM,mBACJ,QAAQ,SAAS,WAAW,KAAK,QAAQ,SAAS,gBAAgB;AACpE,SAAO,kBAAkB;AAC3B;;;ACjGA,IAAAC,eAAiB;AAEV,SAAS,YAAY,WAAmB,YAAwC,CAAC,GAAsB;AAC5G,QAAM,MAAM,EAAE,GAAG,QAAQ,KAAK,GAAG,UAAU;AAC3C,QAAM,cAAc,IAAI,QAAQ;AAChC,QAAM,WAAW,aAAAC,QAAK,QAAQ,SAAS;AACvC,QAAM,UAAU,QAAQ,IAAI,QAAQ;AACpC,QAAM,kBAAkB,QAAQ,IAAI,oBAAoB,IACrD,MAAM,aAAAA,QAAK,SAAS,EACpB,IAAI,WAAS,MAAM,KAAK,CAAC,EACzB,OAAO,OAAO;AACjB,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAAA,QAAK,KAAK,SAAS,UAAU,KAAK;AAAA,IAClC,aAAAA,QAAK,KAAK,SAAS,QAAQ,WAAW,WAAW,KAAK;AAAA,IACtD,aAAAA,QAAK,KAAK,SAAS,QAAQ,WAAW,KAAK;AAAA,IAC3C,GAAG;AAAA,EACL,EAAE,OAAO,OAAO;AAEhB,QAAM,WAAW;AAAA,IACf,GAAG;AAAA,IACH,GAAG,YAAY,MAAM,aAAAA,QAAK,SAAS,EAAE,OAAO,OAAO;AAAA,EACrD;AAEA,MAAI,OAAO,MAAM,KAAK,IAAI,IAAI,QAAQ,CAAC,EAAE,KAAK,aAAAA,QAAK,SAAS;AAC5D,SAAO;AACT;;;AF6EA,SAASC,UAAS,OAAkD;AAClE,SAAO,QAAQ,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,CAAC;AAC5E;AAEA,SAAS,iBAAiB,IAAuB;AAC/C,SAAO,OAAO,OAAO,WAAW,KAAK,OAAO,EAAE;AAChD;AAEA,SAAS,0BAA0B,OAAyB;AAC1D,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,UAAW,MAAgC;AACjD,SAAO,OAAO,YAAY,YAAY,QAAQ,YAAY,EAAE,SAAS,qBAAqB;AAC5F;AAEA,SAAS,sBAAsB,OAAyB;AACtD,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,UAAW,MAAgC;AACjD,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,QAAM,QAAQ,QAAQ,YAAY;AAClC,SAAO,MAAM,SAAS,kBAAkB,KAAK,MAAM,SAAS,SAAS;AACvE;AAsBA,SAASC,UAAS,OAAwB;AACxC,SAAO,OAAO,UAAU,WAAW,QAAQ,SAAS,OAAO,OAAO,KAAK,IAAI;AAC7E;AAEA,SAAS,mBAAmB,OAAwB;AAClD,QAAM,aAAa,MAAM,KAAK,EAAE,YAAY;AAC5C,SACE,WAAW,WAAW,OAAO,KAC1B,WAAW,WAAW,SAAS,KAC/B,WAAW,WAAW,UAAU;AAEvC;AAEA,SAAS,6BACP,OACgC;AAChC,MAAI,CAACC,UAAS,KAAK,GAAG;AACpB,WAAO;AAAA,EACT;AAEA,QAAM,OAAOD,UAAS,MAAM,IAAI,EAAE,KAAK;AACvC,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,QAAM,OAAOC,UAAS,MAAM,IAAI,IAAI,MAAM,OAAO,CAAC;AAElD,MAAI,SAAS,QAAQ;AACnB,UAAM,OAAOD,UAAS,KAAK,QAAQ,MAAM,IAAI;AAC7C,QAAI,CAAC,KAAK,KAAK,GAAG;AAChB,aAAO;AAAA,IACT;AACA,WAAO,EAAE,MAAM,QAAQ,MAAM,EAAE,KAAK,EAAE;AAAA,EACxC;AAEA,MAAI,SAAS,SAAS;AACpB,UAAM,WAAWA;AAAA,MACf,KAAK,aACF,KAAK,YACL,KAAK,OACL,MAAM,aACN,MAAM,YACN,MAAM;AAAA,IACX,EAAE,KAAK;AACP,QAAI,CAAC,UAAU;AACb,aAAO;AAAA,IACT;AACA,WAAO,EAAE,MAAM,SAAS,MAAM,EAAE,WAAW,SAAS,EAAE;AAAA,EACxD;AAEA,MAAI,SAAS,cAAc;AACzB,UAAME,SAAOF,UAAS,KAAK,QAAQ,MAAM,IAAI,EAAE,KAAK;AACpD,QAAI,CAACE,QAAM;AACT,aAAO;AAAA,IACT;AACA,WAAO,EAAE,MAAM,cAAc,MAAM,EAAE,MAAAA,OAAK,EAAE;AAAA,EAC9C;AAEA,SAAO;AACT;AAyEA,SAAS,yBACP,QACyB;AACzB,QAAM,aAAsC,EAAE,GAAG,OAAO;AACxD,QAAM,WAAWC;AAAA,IACf,OAAO,YACJ,OAAO,aACP,OAAO,kBACP,OAAO,mBACP;AAAA,EACL,EAAE,KAAK;AACP,MAAI,YAAY,CAACA,UAAS,OAAO,QAAQ,EAAE,KAAK,GAAG;AACjD,eAAW,WAAW;AAAA,EACxB;AAEA,QAAM,iBAAiBA;AAAA,IACrB,OAAO,kBACJ,OAAO,oBACP,OAAO,UACP,OAAO,WACP;AAAA,EACL,EAAE,KAAK;AACP,MAAI,kBAAkB,CAACA,UAAS,OAAO,cAAc,EAAE,KAAK,GAAG;AAC7D,eAAW,iBAAiB;AAAA,EAC9B;AACA,QAAM,SAASA,UAAS,OAAO,UAAU,OAAO,WAAW,cAAc,EAAE,KAAK;AAChF,MAAI,UAAU,CAACA,UAAS,OAAO,MAAM,EAAE,KAAK,GAAG;AAC7C,eAAW,SAAS;AAAA,EACtB;AAEA,QAAM,gBAAgB,MAAM,QAAQ,OAAO,KAAK,IAC5C,OAAO,MAAM,OAAO,CAAC,UAAUC,UAAS,KAAK,CAAC,IAC9C,CAAC;AACL,MAAI,cAAc,SAAS,GAAG;AAC5B,eAAW,QAAQ;AACnB,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,MAAM,QAAQ,OAAO,KAAK,IAC5C,OAAO,MACN,IAAI,CAAC,SAAS,6BAA6B,IAAI,CAAC,EAChD,OAAO,CAAC,SAA0C,SAAS,IAAI,IAChE,CAAC;AACL,MAAI,cAAc,SAAS,GAAG;AAC5B,UAAMC,SAAQ,cAAc,QAAQ,CAAC,SAAS;AAC5C,YAAM,OAAOF,UAAS,KAAK,IAAI,EAAE,KAAK;AACtC,YAAM,OAAOC,UAAS,KAAK,IAAI,IAAI,KAAK,OAAO;AAC/C,UAAI,SAAS,QAAQ;AACnB,cAAME,QAAOH,UAAS,KAAK,IAAI,EAAE,KAAK;AACtC,eAAOG,QAAO,CAAC,EAAE,MAAM,QAAQ,MAAAA,MAAK,CAAC,IAAI,CAAC;AAAA,MAC5C;AACA,UAAI,SAAS,cAAc;AACzB,cAAMC,SAAOJ,UAAS,KAAK,IAAI,EAAE,KAAK;AACtC,eAAOI,SAAO,CAAC,EAAE,MAAM,cAAc,MAAAA,OAAK,CAAC,IAAI,CAAC;AAAA,MAClD;AACA,aAAO,CAAC;AAAA,IACV,CAAC;AACD,QAAIF,OAAM,SAAS,GAAG;AACpB,iBAAW,QAAQA;AACnB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,QAAmC,CAAC;AAC1C,QAAM,OAAOF,UAAS,OAAO,IAAI;AACjC,MAAI,KAAK,KAAK,GAAG;AACf,UAAM,KAAK,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,EACnC;AACA,MAAI,MAAM,QAAQ,OAAO,MAAM,GAAG;AAChC,eAAW,aAAa,OAAO,QAAQ;AACrC,YAAM,QAAQA,UAAS,SAAS,EAAE,KAAK;AACvC,UAAI,CAAC,SAAS,mBAAmB,KAAK,GAAG;AACvC;AAAA,MACF;AACA,YAAM,KAAK;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAAA,EACF;AACA,MAAI,MAAM,SAAS,GAAG;AACpB,eAAW,QAAQ;AAAA,EACrB;AACA,SAAO;AACT;AAEA,SAAS,eAAe,QAAgB,QAA4C;AAClF,QAAM,aAAa,OAAO,YAAY;AACtC,MAAI,WAAW,SAAS,iBAAiB,EAAG,QAAO;AACnD,MAAI,WAAW,SAAS,kBAAkB,EAAG,QAAO;AACpD,MAAIC,UAAS,MAAM,GAAG;AACpB,QAAI,kBAAkB,UAAU,iBAAiB,UAAU,gBAAgB,UAAU,eAAe,QAAQ;AAC1G,aAAO;AAAA,IACT;AACA,QAAI,aAAa,UAAU,gBAAgB,UAAU,eAAe,UAAU,SAAS,QAAQ;AAC7F,aAAO;AAAA,IACT;AAAA,EACF;AACA,MAAI,WAAW,SAAS,OAAO,KAAK,WAAW,SAAS,OAAO,EAAG,QAAO;AACzE,MAAI,WAAW,SAAS,MAAM,KAAK,WAAW,SAAS,QAAQ,EAAG,QAAO;AACzE,MAAI,WAAW,SAAS,MAAM,KAAK,WAAW,SAAS,SAAS,EAAG,QAAO;AAC1E,SAAO;AACT;AAEA,IAAM,6BAA6B;AACnC,IAAM,iCAAiC;AACvC,IAAM,yBAAyB;AAC/B,IAAM,mCAAmC;AACzC,IAAM,sCAAsC;AAE5C,SAAS,kCAAkC,OAAyB;AAClE,MAAI,EAAE,iBAAiB,QAAQ;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,UAAU,MAAM,QAAQ,YAAY;AAC1C,SACE,QAAQ,SAAS,qBAAqB,KACtC,QAAQ,SAAS,8BAA8B,KAC/C,QAAQ,SAAS,uBAAuB;AAE5C;AAEA,SAAS,mCAAmC,SAA0B;AACpE,QAAM,aAAa,QAAQ,YAAY;AACvC,MAAI,CAAC,WAAW,SAAS,uBAAuB,GAAG;AACjD,WAAO;AAAA,EACT;AACA,SACE,WAAW,SAAS,wBAAwB,KAC5C,WAAW,SAAS,0BAA0B;AAElD;AAEA,SAAS,sCAAsC,SAA0B;AACvE,QAAM,aAAa,QAAQ,YAAY;AACvC,SACE,WAAW,SAAS,4BAA4B,KAChD,WAAW,SAAS,6BAA6B,KACjD,WAAW,SAAS,WAAW,KAC/B,WAAW,SAAS,2BAA2B;AAEnD;AAEA,SAAS,6BAA6B,OAAyB;AAC7D,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,SAAO,MAAM,YAAY,EAAE,SAAS,mBAAmB;AACzD;AAEA,SAAS,oBAAoB,QAAwB;AACnD,MAAI,WAAW,eAAe;AAC5B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,+BAA+B,OAAwB;AAC9D,QAAM,cAAcD,UAAS,KAAK,EAAE,KAAK;AACzC,SAAO,eAAe;AACxB;AAEA,SAAS,cAAc,aAAqB,UAA0B;AACpE,SAAO,GAAG,WAAW,IAAI,QAAQ;AACnC;AAEA,SAAS,6BAA6B,OAAuB;AAC3D,MAAI,SAAS;AACb,MAAI,WAAW;AACf,MAAI,UAAU;AAEd,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AACxC,UAAM,OAAO,MAAM,CAAC;AAEpB,QAAI,SAAS;AACX,gBAAU;AACV,gBAAU;AACV;AAAA,IACF;AACA,QAAI,SAAS,MAAM;AACjB,gBAAU;AACV,gBAAU;AACV;AAAA,IACF;AACA,QAAI,SAAS,KAAM;AACjB,gBAAU;AACV,iBAAW,CAAC;AACZ;AAAA,IACF;AACA,QAAI,UAAU;AACZ,UAAI,SAAS,MAAM;AACjB,kBAAU;AACV;AAAA,MACF;AACA,UAAI,SAAS,MAAM;AACjB,kBAAU;AACV;AAAA,MACF;AACA,UAAI,SAAS,KAAM;AACjB,kBAAU;AACV;AAAA,MACF;AACA,YAAM,OAAO,KAAK,WAAW,CAAC;AAC9B,UAAI,QAAQ,KAAK,OAAO,IAAM;AAC5B,kBAAU,MAAM,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC;AAClD;AAAA,MACF;AAAA,IACF;AAEA,cAAU;AAAA,EACZ;AAEA,SAAO;AACT;AAEA,IAAI,sBAAqC;AAEzC,SAAS,qBAAqB,KAAiC;AAC7D,QAAM,WACJ,KAAK,oBAAoB,KAAK,KAC9B,KAAK,gBAAgB,KAAK,KAC1B,KAAK,YAAY,KAAK,KACtB,QAAQ,IAAI,oBAAoB,KAAK,KACrC,QAAQ,IAAI,gBAAgB,KAAK,KACjC,QAAQ,IAAI,YAAY,KAAK,KAC7B;AACF,MAAI,UAAU;AACZ,WAAO;AAAA,EACT;AAEA,MAAI,qBAAqB;AACvB,WAAO;AAAA,EACT;AAEA,QAAM,aAAgC,EAAE,GAAG,QAAQ,KAAK,GAAG,IAAI;AAC/D,QAAM,UAAU,WAAW,QAAQ,WAAW,eAAe;AAC7D,QAAM,aAAa,WAAW,oBAAoB,QAAQ,IAAI,oBAAoB,IAC/E,MAAM,mBAAAI,QAAK,SAAS,EACpB,IAAI,WAAS,MAAM,KAAK,CAAC,EACzB,OAAO,OAAO;AACjB,QAAM,mBAAmB;AAAA,IACvB;AAAA,IACA;AAAA,IACA,mBAAAA,QAAK,KAAK,SAAS,UAAU,KAAK;AAAA,IAClC,mBAAAA,QAAK,KAAK,SAAS,QAAQ,WAAW,WAAW,KAAK;AAAA,IACtD,mBAAAA,QAAK,KAAK,SAAS,QAAQ,WAAW,KAAK;AAAA,IAC3C,GAAG;AAAA,EACL,EAAE,OAAO,OAAO;AAChB,QAAM,cAAc,WAAW,QAAQ;AACvC,aAAW,OAAO,MAAM;AAAA,IACtB,oBAAI,IAAI,CAAC,GAAG,kBAAkB,GAAG,YAAY,MAAM,mBAAAA,QAAK,SAAS,EAAE,OAAO,OAAO,CAAC,CAAC;AAAA,EACrF,EAAE,KAAK,mBAAAA,QAAK,SAAS;AAErB,QAAM,aAAa,MAAM;AAAA,IACvB,IAAI;AAAA,MACF;AAAA,QACE,WAAW,oBAAoB,KAAK;AAAA,QACpC,WAAW,gBAAgB,KAAK;AAAA,QAChC,WAAW,YAAY,KAAK;AAAA,QAC5B;AAAA,QACA;AAAA,QACA;AAAA,MACF,EAAE,OAAO,OAAO;AAAA,IAClB;AAAA,EACF;AAEA,aAAW,aAAa,YAAY;AAClC,UAAM,YAAQ,sCAAU,WAAW,CAAC,IAAI,GAAG,EAAE,KAAK,YAAY,OAAO,SAAS,CAAC;AAC/E,QAAI,CAAC,MAAM,SAAS,MAAM,WAAW,GAAG;AACtC,4BAAsB;AACtB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,wBAAsB,QAAQ;AAC9B,SAAO,QAAQ;AACjB;AAEO,IAAM,iBAAN,cAA6B,gCAAa;AAAA,EAgB/C,cAAc;AACZ,UAAM;AAhBR,SAAQ,QAA+C;AACvD,SAAQ,SAAoC;AAC5C,SAAQ,gBAAgB;AACxB,SAAQ,kBAAkB,oBAAI,IAA4B;AAC1D,SAAQ,wBAAwB,oBAAI,IAAkC;AACtE,SAAQ,yBAA+C;AACvD,SAAQ,+BAA+B,oBAAI,IAAoB;AAC/D,SAAQ,eAAqC;AAC7C,SAAQ,oBAA6C;AACrD,SAAQ,qBAAqC;AAC7C,SAAQ,kBAAiC;AACzC,SAAQ,gCAAgC,oBAAI,IAAoB;AAChE,SAAQ,sBAAsB,oBAAI,IAAwB;AAC1D,SAAQ,mCAAmD;AAIzD,SAAK,gBAAgB,EAAE;AAAA,EACzB;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,OAAO;AACd;AAAA,IACF;AACA,QAAI,CAAC,KAAK,cAAc;AACtB,WAAK,eAAe,KAAK,aAAa,EAAE,QAAQ,MAAM;AACpD,aAAK,eAAe;AAAA,MACtB,CAAC;AAAA,IACH;AACA,UAAM,KAAK;AAAA,EACb;AAAA,EAEA,MAAM,OAAsB;AAC1B,QAAI,KAAK,QAAQ;AACf,WAAK,OAAO,MAAM;AAClB,WAAK,SAAS;AAAA,IAChB;AACA,QAAI,KAAK,OAAO;AACd,YAAM,QAAQ,KAAK;AACnB,WAAK,QAAQ;AACb,UAAI;AACF,cAAM,KAAK;AAAA,MACb,QAAQ;AAAA,MAER;AAAA,IACF;AACA,SAAK,oBAAoB;AACzB,SAAK,qBAAqB;AAC1B,SAAK,kBAAkB;AACvB,SAAK,8BAA8B,MAAM;AACzC,SAAK,oBAAoB,MAAM;AAC/B,SAAK,mCAAmC;AACxC,SAAK,qBAAqB,IAAI,MAAM,0BAA0B,CAAC;AAAA,EACjE;AAAA,EAEA,YAAqB;AACnB,WAAO,QAAQ,KAAK,SAAS,CAAC,KAAK,MAAM,MAAM;AAAA,EACjD;AAAA,EAEA,MAAM,WAAW,YAAgD;AAC/D,QAAI,KAAK,oBAAoB;AAC3B,aAAO,KAAK;AAAA,IACd;AACA,QAAI,CAAC,KAAK,mBAAmB;AAC3B,WAAK,qBAAqB,YAAY;AACpC,cAAM,KAAK,MAAM;AACjB,cAAM,UAAmC;AAAA,UACvC,YAAY,cAAc;AAAA,YACxB,MAAM;AAAA,YACN,OAAO;AAAA,YACP,SAAS;AAAA,UACX;AAAA,QACF;AACA,YAAI;AACF,gBAAM,WAAW,MAAM,KAAK,QAAQ,cAAc,OAAO;AACzD,gBAAM,KAAK,OAAO,eAAe,CAAC,CAAC;AACnC,eAAK,qBAAqB;AAC1B,iBAAO;AAAA,QACT,SAAS,OAAO;AACd,cAAI,0BAA0B,KAAK,GAAG;AACpC,iBAAK,qBAAqB,KAAK,sBAAsB,CAAC;AACtD,mBAAO,KAAK;AAAA,UACd;AACA,gBAAM;AAAA,QACR;AAAA,MACF,GAAG,EAAE,QAAQ,MAAM;AACjB,aAAK,oBAAoB;AAAA,MAC3B,CAAC;AAAA,IACH;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,WAAW,eAAe,OAAyB;AACvD,WAAO,KAAK,QAAQ,gBAAgB,EAAE,aAAa,CAAC;AAAA,EACtD;AAAA,EAEA,MAAM,uBAAyC;AAC7C,WAAO,KAAK,QAAQ,yBAAyB;AAAA,EAC/C;AAAA,EAEA,MAAM,aAAa,QAAmD;AACpE,WAAO,KAAK,QAAQ,uBAAuB,MAAM;AAAA,EACnD;AAAA,EAEA,MAAM,mBAAmB,SAAmC;AAC1D,WAAO,KAAK,QAAQ,wBAAwB,EAAE,QAAQ,CAAC;AAAA,EACzD;AAAA,EAEA,MAAM,gBAAkC;AACtC,WAAO,KAAK,QAAQ,gBAAgB;AAAA,EACtC;AAAA,EAEA,MAAM,gBAAgB,QAAiC,WAA8D;AACnH,UAAM,SAAS,YAAY,EAAE,GAAG,QAAQ,GAAG,UAAU,IAAI;AACzD,WAAO,KAAK,QAAQ,mBAAmB,MAAM;AAAA,EAC/C;AAAA,EAEA,MAAM,mBAAmB,QAAiC,WAA8D;AACtH,UAAM,SAAS,YAAY,EAAE,GAAG,QAAQ,GAAG,UAAU,IAAI;AACzD,WAAO,KAAK,QAAQ,sBAAsB,MAAM;AAAA,EAClD;AAAA,EAEA,MAAc,0CACZ,UACA,cAA6B,MACY;AACzC,QAAI,KAAK,qCAAqC,OAAO;AACnD,aAAO,CAAC;AAAA,IACV;AACA,UAAM,iBAA0C;AAAA,MAC9C,gBAAgB;AAAA,IAClB;AACA,UAAM,sBAAsB,cAAc,YAAY,KAAK,IAAI;AAC/D,QAAI,qBAAqB;AACvB,qBAAe,cAAc;AAC7B,qBAAe,eAAe;AAAA,IAChC;AACA,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,2BAA2B,cAAc;AAC7E,WAAK,mCAAmC;AACxC,aAAOH,UAAS,QAAQ,IAAI,WAAW;AAAA,IACzC,SAAS,OAAO;AACd,UAAI,yBAAyB,OAAO,yBAAyB,GAAG;AAC9D,aAAK,mCAAmC;AACxC,eAAO,CAAC;AAAA,MACV;AACA,UAAI,CAAC,sBAAsB,KAAK,GAAG;AACjC,cAAM;AAAA,MACR;AACA,YAAM,KAAK;AAAA,QACT,sBACI,EAAE,UAAU,aAAa,qBAAqB,cAAc,oBAAoB,IAChF,EAAE,SAAS;AAAA,MACjB;AACA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK,QAAQ,2BAA2B,cAAc;AAC7E,aAAK,mCAAmC;AACxC,eAAOA,UAAS,QAAQ,IAAI,WAAW;AAAA,MACzC,SAAS,aAAa;AACpB,YAAI,yBAAyB,aAAa,yBAAyB,GAAG;AACpE,eAAK,mCAAmC;AACxC,iBAAO,CAAC;AAAA,QACV;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,2CACZ,gBACe;AACf,QAAI,CAAC,kBAAkB,KAAK,qCAAqC,OAAO;AACtE;AAAA,IACF;AACA,QAAI;AACF,YAAM,KAAK,QAAQ,8BAA8B,EAAE,eAAe,CAAC;AAAA,IACrE,SAAS,OAAO;AACd,UAAI,yBAAyB,OAAO,4BAA4B,GAAG;AACjE,aAAK,mCAAmC;AACxC;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,wBAAwB,QAAmD;AAC/E,QAAI,KAAK,qCAAqC,OAAO;AACnD,aAAO,CAAC;AAAA,IACV;AACA,UAAM,iBAAiBD;AAAA,MACrB,OAAO,kBAAkB,OAAO,YAAY,OAAO,aAAa;AAAA,IAClE,EAAE,KAAK;AACP,UAAM,cAAcA;AAAA,MAClB,OAAO,eAAe,OAAO,gBAAgB;AAAA,IAC/C,EAAE,KAAK;AACP,QAAI,CAAC,gBAAgB;AACnB,UAAI;AACF,cAAM,WAAW,MAAM,KAAK,QAAQ,2BAA2B,MAAM;AACrE,aAAK,mCAAmC;AACxC,eAAO;AAAA,MACT,SAAS,OAAO;AACd,YAAI,yBAAyB,OAAO,yBAAyB,GAAG;AAC9D,eAAK,mCAAmC;AACxC,iBAAO,CAAC;AAAA,QACV;AACA,cAAM;AAAA,MACR;AAAA,IACF;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA,eAAe;AAAA,IACjB;AAAA,EACF;AAAA,EAEA,MAAM,2BAA2B,QAAmD;AAClF,QAAI,KAAK,qCAAqC,OAAO;AACnD,aAAO,CAAC;AAAA,IACV;AACA,QAAI;AACF,aAAO,MAAM,KAAK,QAAQ,8BAA8B,MAAM;AAAA,IAChE,SAAS,OAAO;AACd,UAAI,yBAAyB,OAAO,4BAA4B,GAAG;AACjE,aAAK,mCAAmC;AACxC,eAAO,CAAC;AAAA,MACV;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,oBAAoB,QAAmD;AAC3E,UAAM,cAAc;AAAA,MAClB,OAAO,eAAe,OAAO;AAAA,IAC/B;AACA,UAAM,WAAWA;AAAA,MACf,OAAO,YAAY,OAAO,aAAa,OAAO;AAAA,IAChD,EAAE,KAAK;AACP,QAAI,CAAC,UAAU;AACb,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,MAAM,cAAc,aAAa,QAAQ;AAC/C,SAAK,oBAAoB,IAAI,KAAK,UAAU;AAC5C,SAAK,8BAA8B,OAAO,GAAG;AAC7C,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,MAAM,sBACJ,QACkB;AAClB,UAAM,cAAc;AAAA,MAClB,OAAO,eAAe,OAAO;AAAA,IAC/B;AACA,UAAM,WAAWA;AAAA,MACf,OAAO,YAAY,OAAO,aAAa,OAAO;AAAA,IAChD,EAAE,KAAK;AACP,QAAI,CAAC,UAAU;AACb,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,MAAM,cAAc,aAAa,QAAQ;AAC/C,SAAK,oBAAoB,OAAO,GAAG;AACnC,UAAM,iBAAiB,KAAK,8BAA8B,IAAI,GAAG,KAAK;AACtE,SAAK,8BAA8B,OAAO,GAAG;AAE7C,QAAI,gBAAgB;AAClB,YAAM,KAAK,2CAA2C,cAAc;AAAA,IACtE;AACA,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,MAAM,gBAAgB,QAAmD;AACvE,WAAO,KAAK,QAAQ,cAAc,yBAAyB,MAAM,CAAC;AAAA,EACpE;AAAA,EAEA,MAAM,YAAY,QAAmD;AACnE,WAAO,KAAK,QAAQ,gBAAgB,MAAM;AAAA,EAC5C;AAAA,EAEA,MAAM,aAAa,QAAmD;AACpE,UAAM,YAAY,EAAE,GAAG,OAAO;AAC9B,WAAO,UAAU;AACjB,WAAO,UAAU;AACjB,WAAO,KAAK,QAAQ,iBAAiB,SAAS;AAAA,EAChD;AAAA,EAEA,MAAM,UAAU,QAAmD;AACjE,WAAO,KAAK,QAAQ,cAAc,yBAAyB,MAAM,CAAC;AAAA,EACpE;AAAA,EAEA,MAAM,UAAU,QAAmD;AACjE,WAAO,KAAK,QAAQ,cAAc,yBAAyB,MAAM,CAAC;AAAA,EACpE;AAAA,EAEA,MAAM,cAAc,QAAmD;AACrE,WAAO,KAAK,QAAQ,kBAAkB,MAAM;AAAA,EAC9C;AAAA,EAEA,MAAM,UAAU,QAAmD;AACjE,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B;AAAA,EAEA,MAAM,cAAc,QAAmD;AACrE,WAAO,KAAK,cAAc,MAAM;AAAA,EAClC;AAAA,EAEA,MAAM,sBAAsB,QAAmD;AAC7E,WAAO,KAAK,QAAQ,yBAAyB,MAAM;AAAA,EACrD;AAAA,EAEA,MAAM,oBAAoB,gBAAuC;AAC/D,QAAI;AACF,YAAM,KAAK,QAAQ,kBAAkB,EAAE,UAAU,eAAe,CAAC;AACjE;AAAA,IACF,QAAQ;AAAA,IAER;AACA,QAAI;AACF,YAAM,KAAK,QAAQ,uBAAuB,EAAE,eAAe,CAAC;AAAA,IAC9D,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,QASH;AACnB,WAAO,KAAK,QAAQ,eAAe;AAAA,MACjC,QAAQ,OAAO,UAAU;AAAA,MACzB,OAAO,OAAO,SAAS;AAAA,MACvB,KAAK,OAAO,OAAO;AAAA,MACnB,SAAS,OAAO,WAAW;AAAA,MAC3B,aAAa,OAAO,eAAe;AAAA,MACnC,aAAa,OAAO,eAAe;AAAA,MACnC,UAAU,OAAO,YAAY;AAAA,MAC7B,gBAAgB,OAAO,kBAAkB;AAAA,IAC3C,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,eAAe,QAGA;AACnB,UAAM,MAAM,OAAO,QAAQ,QAAQ,WAAW,OAAO,IAAI,KAAK,IAAI;AAClE,WAAO,KAAK,QAAQ,eAAe;AAAA,MACjC,MAAM,MAAM,CAAC,GAAG,IAAI,CAAC;AAAA,MACrB,aAAa,QAAQ,QAAQ,WAAW;AAAA,IAC1C,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,SAAS,QAA2C;AACxD,UAAM,UAAU,qBAAqB,MAAM;AAC3C,UAAM,UAAU,CAAC,YAAY,aAAa,WAAW;AACrD,aAAS,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACtD,YAAM,SAAS,QAAQ,KAAK;AAC5B,UAAI;AACF,eAAO,MAAM,KAAK,QAAQ,QAAQ,OAAO;AAAA,MAC3C,SAAS,OAAO;AACd,cAAM,oBAAoB,QAAQ,QAAQ,SAAS;AACnD,YAAI,qBAAqB,yBAAyB,OAAO,MAAM,GAAG;AAChE;AAAA,QACF;AACA,YAAI,8BAA8B,KAAK,GAAG;AACxC,iBAAO,EAAE,MAAM,CAAC,EAAE;AAAA,QACpB;AACA,cAAM;AAAA,MACR;AAAA,IACF;AACA,UAAM,IAAI,MAAM,4DAA4D;AAAA,EAC9E;AAAA,EAEA,MAAM,oBAAoB,QAA8D;AACtF,UAAM,YAAY,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK,KAAK,IAAI;AACzE,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AACA,WAAO,KAAK,QAAQ,uBAAuB;AAAA,MACzC,MAAM;AAAA,MACN,SAAS,QAAQ,OAAO,OAAO;AAAA,IACjC,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,WAAW,QAA+E;AAC9F,WAAO,KAAK,QAAQ,eAAe;AAAA,MACjC,UAAU,OAAO;AAAA,MACjB,cAAc,QAAQ,OAAO,YAAY;AAAA,IAC3C,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cAAc,UAAkB,MAAgC;AACpE,WAAO,KAAK,QAAQ,mBAAmB,EAAE,UAAU,KAAK,CAAC;AAAA,EAC3D;AAAA,EAEA,MAAM,YAAY,QAAmD;AACnE,WAAO,KAAK,QAAQ,gBAAgB,MAAM;AAAA,EAC5C;AAAA,EAEA,MAAM,aAAa,QAAmD;AACpE,QAAI;AACF,aAAO,MAAM,KAAK,QAAQ,wBAAwB,MAAM;AAAA,IAC1D,QAAQ;AACN,UAAI;AACF,eAAO,MAAM,KAAK,QAAQ,kBAAkB,MAAM;AAAA,MACpD,QAAQ;AACN,eAAO,KAAK,QAAQ,iBAAiB,MAAM;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,0BAA0B,cAAsB,UAA8C;AAClG,UAAM,KAAK,sBAAsB,cAAc,QAAQ,QAAQ;AAAA,EACjE;AAAA,EAEA,MAAM,yBAAyB,cAAsB,UAA8C;AACjG,UAAM,KAAK,sBAAsB,cAAc,SAAS,QAAQ;AAAA,EAClE;AAAA,EAEA,MAAM,uBAAuB,WAAsB,QAAgD;AACjG,UAAM,QAAQ,iBAAiB,SAAS;AACxC,UAAM,UAAU,KAAK,sBAAsB,IAAI,KAAK;AACpD,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,2BAA2B,SAAS,EAAE;AAAA,IACxD;AACA,SAAK,sBAAsB,OAAO,KAAK;AACvC,UAAM,KAAK,aAAa,QAAQ,IAAI,UAAU,CAAC,CAAC;AAAA,EAClD;AAAA,EAEA,MAAc,eAA8B;AAC1C,UAAM,YAAY,MAAM,gBAAgB;AACxC,UAAM,MAAM,YAAY,WAAW,EAAE,sBAAsB,IAAI,CAAC;AAChE,UAAM,aAAa,qBAAqB,GAAG;AAC3C,UAAM,YAAQ,kCAAM,YAAY,CAAC,WAAW,YAAY,GAAG;AAAA,MACzD,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,MAC9B;AAAA,IACF,CAAC;AACD,SAAK,QAAQ;AACb,SAAK,qBAAqB;AAC1B,SAAK,oBAAoB;AACzB,SAAK,kBAAkB;AACvB,SAAK,mCAAmC;AAExC,UAAM,GAAG,QAAQ,CAAC,MAAM,WAAW;AACjC,cAAQ,uBAAuB,EAAE,MAAM,OAAO,CAAC;AAC/C,WAAK,QAAQ;AACb,WAAK,qBAAqB;AAC1B,WAAK,oBAAoB;AACzB,WAAK,8BAA8B,MAAM;AACzC,WAAK,oBAAoB,MAAM;AAC/B,WAAK,mCAAmC;AACxC,WAAK,qBAAqB,IAAI,MAAM,yBAAyB,CAAC;AAC9D,WAAK,KAAK,wBAAwB,CAAC,CAAC;AAAA,IACtC,CAAC;AACD,UAAM,GAAG,SAAS,WAAS;AACzB,eAAS,8BAA8B,KAAK;AAC5C,WAAK,8BAA8B,MAAM;AACzC,WAAK,oBAAoB,MAAM;AAC/B,WAAK,mCAAmC;AACxC,WAAK,KAAK,wBAAwB,CAAC,CAAC;AAAA,IACtC,CAAC;AAED,QAAI,MAAM,QAAQ;AAChB,YAAM,OAAO,GAAG,QAAQ,WAAS;AAC/B,cAAM,QAAQ,MAAM,SAAS,EAAE,MAAM,OAAO;AAC5C,mBAAW,QAAQ,OAAO;AACxB,gBAAM,UAAU,KAAK,KAAK;AAC1B,cAAI,CAAC,QAAS;AAGd,gBAAM,aAAa,QAAQ,YAAY;AACvC,cAAI,WAAW,SAAS,0CAA0C,GAAG;AACnE;AAAA,UACF;AAEA,cACE,WAAW,SAAS,mBAAmB,KACvC,WAAW,SAAS,gCAAgC,GACpD;AACA;AAAA,UACF;AACA,cAAI,mCAAmC,OAAO,GAAG;AAC/C;AAAA,UACF;AACA,cAAI,sCAAsC,OAAO,GAAG;AAClD;AAAA,UACF;AACA,kBAAQ,uBAAuB,OAAO;AAAA,QACxC;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,MAAM,QAAQ;AACjB,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAEA,SAAK,SAAS,sBAAAK,QAAS,gBAAgB;AAAA,MACrC,OAAO,MAAM;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAED,SAAK,OAAO,GAAG,QAAQ,UAAQ;AAC7B,WAAK,mBAAmB,IAAI;AAAA,IAC9B,CAAC;AAED,YAAQ,sBAAsB;AAAA,EAChC;AAAA,EAEQ,mBAAmB,MAAoB;AAC7C,QAAI,KAAK,oBAAoB,MAAM;AACjC,YAAM,SAAS,GAAG,KAAK,eAAe;AAAA,EAAK,IAAI;AAC/C,YAAMC,WAAU,KAAK,iBAAiB,MAAM;AAC5C,UAAIA,UAAS;AACX,aAAK,kBAAkB;AACvB;AAAA,MACF;AACA,UAAI,OAAO,SAAS,wBAAwB;AAC1C,aAAK,kBAAkB;AACvB;AAAA,MACF;AACA,WAAK;AAAA,QACH;AAAA,QACA,IAAI,MAAM,4EAA4E;AAAA,MACxF;AACA,WAAK,kBAAkB;AACvB;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,KAAK,GAAG;AAChB;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,iBAAiB,IAAI;AAC1C,QAAI,SAAS;AACX;AAAA,IACF;AAEA,QAAI,KAAK,UAAU,EAAE,WAAW,GAAG,GAAG;AACpC,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA,EAEQ,iBAAiB,MAAuB;AAC9C,QAAI;AACJ,QAAI,aAAsB;AAC1B,QAAI;AACF,eAAS,KAAK,MAAM,IAAI;AAAA,IAC1B,SAAS,OAAO;AACd,mBAAa;AACb,YAAM,WAAW,6BAA6B,IAAI;AAClD,UAAI,aAAa,MAAM;AACrB,YAAI;AACF,mBAAS,KAAK,MAAM,QAAQ;AAC5B,uBAAa;AAAA,QACf,SAAS,aAAa;AACpB,uBAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAEA,QAAI,YAAY;AACd,UAAI,kCAAkC,UAAU,GAAG;AACjD,eAAO;AAAA,MACT;AACA,WAAK,gBAAgB,MAAM,UAAU;AACrC,aAAO;AAAA,IACT;AACA,QAAI,CAACL,UAAS,MAAM,GAAG;AACrB,cAAQ,wCAAwC,MAAM;AACtD,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,QAAQ;AACtB,UAAM,YAAY,OAAO,OAAO,WAAW;AAC3C,UAAM,YAAY,YAAY;AAC9B,UAAM,WAAW,WAAW;AAE5B,QAAI,aAAa,OAAO;AACtB,WAAK,oBAAoB,MAAwB;AACjD,aAAO;AAAA,IACT;AAEA,QAAI,WAAW;AACb,WAAK,mBAAmB,MAA6B;AACrD,aAAO;AAAA,IACT;AAEA,QAAI,UAAU,aAAa,WAAW;AACpC,WAAK,eAAe,MAAyB;AAC7C,aAAO;AAAA,IACT;AAEA,YAAQ,sCAAsC,MAAM;AACpD,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,MAAc,OAAsB;AAC1D,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,YAAQ,qCAAqC;AAAA,MAC3C,OAAO;AAAA,MACP,QAAQ,KAAK;AAAA,MACb,sBAAsB,KAAK,UAAU,EAAE,WAAW,GAAG;AAAA,IACvD,CAAC;AAAA,EACH;AAAA,EAEQ,eAAe,UAAiC;AACtD,UAAM,QAAQ,iBAAiB,SAAS,EAAE;AAC1C,UAAM,UAAU,KAAK,gBAAgB,IAAI,KAAK;AAC9C,QAAI,CAAC,SAAS;AACZ,cAAQ,iDAAiD,SAAS,EAAE;AACpE;AAAA,IACF;AACA,SAAK,gBAAgB,OAAO,KAAK;AAEjC,QAAI,SAAS,OAAO;AAClB,YAAM,QAAQ,IAAI,MAAM,SAAS,MAAM,WAAW,wBAAwB;AAC1E,MAAC,MAAoD,OAAO,SAAS,MAAM;AAC3E,MAAC,MAAoD,OAAO,SAAS,MAAM;AAC3E,YAAM,4BACJ,iBAAiB,QAAQ,MAAM,KAC9B,QAAQ,WAAW,6BAA6B,sBAAsB,KAAK,KAC3E,QAAQ,WAAW,mBAAmB,sBAAsB,KAAK;AACpE,UAAI,CAAC,2BAA2B;AAC9B,aAAK,KAAK,uBAAuB;AAAA,UAC/B,MAAM,SAAS,MAAM;AAAA,UACrB,SAAS,SAAS,MAAM;AAAA,UACxB,MAAM,SAAS,MAAM;AAAA,QACvB,CAAoC;AAAA,MACtC;AACA,cAAQ,OAAO,KAAK;AACpB;AAAA,IACF;AAEA,YAAQ,QAAQ,SAAS,MAAM;AAAA,EACjC;AAAA,EAEQ,mBAAmB,cAAyC;AAClE,UAAM,EAAE,QAAQ,OAAO,IAAI;AAC3B,QAAI,OAAO,WAAW,cAAc,GAAG;AACrC,WAAK,KAAK,eAAe,EAAE,QAAQ,OAAO,CAA6B;AACvE;AAAA,IACF;AAEA,UAAM,aAAa,OAAO,YAAY;AACtC,QAAI,WAAW,SAAS,MAAM,KAAK,WAAW,SAAS,QAAQ,GAAG;AAChE,WAAK,KAAK,qBAAqB,UAAU,CAAC,CAAC;AAC3C;AAAA,IACF;AACA,QAAI,WAAW,SAAS,OAAO,KAAK,WAAW,SAAS,UAAU,GAAG;AACnE,WAAK,KAAK,wBAAwB,UAAU,CAAC,CAAC;AAC9C;AAAA,IACF;AAEA,SAAK,KAAK,sBAAsB,EAAE,QAAQ,OAAO,CAAoC;AAAA,EACvF;AAAA,EAEQ,oBAAoB,SAA+B;AACzD,UAAM,OAAO,eAAe,QAAQ,QAAQ,QAAQ,MAAM;AAC1D,QAAI,CAAC,MAAM;AACT,WAAK,KAAK,UAAU,QAAQ,IAAI;AAAA,QAC9B,MAAM;AAAA,QACN,SAAS,wBAAwB,QAAQ,MAAM;AAAA,MACjD,CAAC;AACD;AAAA,IACF;AAEA,UAAM,QAAQ,iBAAiB,QAAQ,EAAE;AACzC,SAAK,sBAAsB,IAAI,OAAO,EAAE,IAAI,QAAQ,IAAI,MAAM,QAAQ,QAAQ,OAAO,CAAC;AAEtF,UAAM,SAASA,UAAS,QAAQ,MAAM,IAAI,QAAQ,SAAS,CAAC;AAC5D,QAAI,SAAS,QAAQ;AACnB,WAAK,KAAK,8BAA8B;AAAA,QACtC,cAAc;AAAA,QACd;AAAA,MACF,CAA0C;AAAA,IAC5C,WAAW,SAAS,SAAS;AAC3B,WAAK,KAAK,6BAA6B;AAAA,QACrC,cAAc;AAAA,QACd;AAAA,MACF,CAAyC;AAAA,IAC3C,OAAO;AACL,WAAK,KAAK,wBAAwB;AAAA,QAChC,WAAW,QAAQ;AAAA,QACnB,QAAQ,QAAQ;AAAA,QAChB;AAAA,MACF,CAAqC;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,MAAc,sBACZ,cACA,MACA,UACe;AACf,UAAM,UAAU,KAAK,sBAAsB,IAAI,YAAY;AAC3D,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,6BAA6B,YAAY,EAAE;AAAA,IAC7D;AACA,QAAI,QAAQ,SAAS,MAAM;AACzB,YAAM,IAAI,MAAM,wCAAwC,YAAY,EAAE;AAAA,IACxE;AACA,SAAK,sBAAsB,OAAO,YAAY;AAC9C,UAAM,KAAK,aAAa,QAAQ,IAAI,EAAE,SAAS,CAAC;AAAA,EAClD;AAAA,EAEA,MAAc,QAAQ,QAAgB,QAAoC;AAExE,QAAI,WAAW,cAAc;AAC3B,YAAM,KAAK,WAAW;AAAA,IACxB,OAAO;AACL,YAAM,KAAK,MAAM;AAAA,IACnB;AACA,UAAM,KAAK,KAAK;AAChB,UAAM,QAAQ,iBAAiB,EAAE;AACjC,UAAM,YAAY,oBAAoB,MAAM;AAC5C,UAAM,UAA0B,SAAS,EAAE,IAAI,QAAQ,OAAO,IAAI,EAAE,IAAI,OAAO;AAC/E,UAAM,SAAS,IAAI,QAAiB,CAAC,SAAS,WAAW;AACvD,YAAM,UAAU,WAAW,MAAM;AAC/B,cAAM,UAAU,KAAK,gBAAgB,IAAI,KAAK;AAC9C,YAAI,CAAC,SAAS;AACZ;AAAA,QACF;AACA,aAAK,gBAAgB,OAAO,KAAK;AACjC,cAAM,eAAe,IAAI;AAAA,UACvB,4CAA4C,SAAS,OAAO,MAAM;AAAA,QACpE;AACA,gBAAQ,OAAO,YAAY;AAC3B,aAAK,wBAAwB,QAAQ,YAAY;AAAA,MACnD,GAAG,SAAS;AAEZ,WAAK,gBAAgB,IAAI,OAAO;AAAA,QAC9B;AAAA,QACA,SAAS,CAAC,UAAU;AAClB,uBAAa,OAAO;AACpB,kBAAQ,KAAK;AAAA,QACf;AAAA,QACA,QAAQ,CAAC,UAAU;AACjB,uBAAa,OAAO;AACpB,iBAAO,KAAK;AAAA,QACd;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AACD,UAAM,KAAK,aAAa,OAAO;AAC/B,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,OAAO,QAAgB,QAAiC;AACpE,UAAM,KAAK,MAAM;AACjB,UAAM,UAA+B,SAAS,EAAE,QAAQ,OAAO,IAAI,EAAE,OAAO;AAC5E,UAAM,KAAK,aAAa,OAAO;AAAA,EACjC;AAAA,EAEA,MAAc,aAAa,IAAe,QAAgC;AACxE,UAAM,KAAK,aAAa,EAAE,IAAI,OAAO,CAAC;AAAA,EACxC;AAAA,EAEA,MAAc,UAAU,IAAe,OAAoC;AACzE,UAAM,KAAK,aAAa,EAAE,IAAI,MAAM,CAAC;AAAA,EACvC;AAAA,EAEA,MAAc,aAAa,SAAiD;AAC1E,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,MAAM,OAAO;AACpC,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AACA,UAAM,UAAU,KAAK,UAAU,EAAE,SAAS,OAAO,GAAG,QAAQ,CAAC;AAC7D,SAAK,MAAM,MAAM,MAAM,GAAG,OAAO;AAAA,CAAI;AAAA,EACvC;AAAA,EAEQ,qBAAqB,OAAoB;AAC/C,eAAW,WAAW,KAAK,gBAAgB,OAAO,GAAG;AACnD,cAAQ,OAAO,KAAK;AAAA,IACtB;AACA,SAAK,gBAAgB,MAAM;AAC3B,SAAK,sBAAsB,MAAM;AACjC,SAAK,8BAA8B,MAAM;AACzC,SAAK,oBAAoB,MAAM;AAAA,EACjC;AAAA,EAEQ,wBAAwB,QAAgB,OAAsB;AACpE,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,SAAS,EAAE;AAC3E,QAAI,CAAC,6BAA6B,OAAO,GAAG;AAC1C;AAAA,IACF;AAIA,QAAI,WAAW,cAAc;AAC3B,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,cAAc,KAAK,6BAA6B,IAAI,MAAM,KAAK;AACrE,UAAI,MAAM,eAAe,qCAAqC;AAC5D,aAAK,6BAA6B,IAAI,QAAQ,GAAG;AACjD,gBAAQ,0DAA0D,EAAE,OAAO,CAAC;AAAA,MAC9E;AACA;AAAA,IACF;AACA,QAAI,KAAK,wBAAwB;AAC/B;AAAA,IACF;AACA,SAAK,0BAA0B,YAAY;AACzC,cAAQ,gDAAgD,EAAE,OAAO,CAAC;AAClE,UAAI;AACF,cAAM,KAAK,KAAK;AAAA,MAClB,SAAS,WAAW;AAClB,gBAAQ,gDAAgD,SAAS;AAAA,MACnE;AAAA,IACF,GAAG,EAAE,QAAQ,MAAM;AACjB,WAAK,yBAAyB;AAAA,IAChC,CAAC;AAAA,EACH;AACF;;;AG31CA,IAAAM,qBAAiB;AACjB,IAAAC,mBAAe;AACf,IAAAC,sBAA2B;;;ACM3B,IAAAC,kBAAe;AACf,IAAAC,qBAAiB;AACjB,IAAAC,6BAAyB;AACzB,IAAAC,oBAA0B;;;ACJ1B,IAAAC,6BAAyB;AACzB,uBAA0B;AAQ1B,IAAM,oBAAgB,4BAAU,mCAAQ;AACxC,IAAM,mBAAmB,KAAK,OAAO;;;ADarC,IAAMC,qBAAgB,6BAAU,mCAAQ;;;ADvBxC,IAAM,aAAa;AACnB,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,+BAA+B;AAmDrC,SAAS,kBAAqC;AAC5C,SAAO;AAAA,IACL,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,SAAS;AAAA,IACT,wBAAwB;AAAA,IACxB,SAAS;AAAA,IACT,cAAc;AAAA,IACd,eAAe;AAAA,IACf,qBAAqB;AAAA,EACvB;AACF;AAEA,SAAS,eAA+B;AACtC,SAAO;AAAA,IACL,SAAS;AAAA,IACT,YAAY,CAAC;AAAA,EACf;AACF;AAEA,SAAS,qBAAqB,OAA+B;AAC3D,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAAS,oBAAoB,aAAoC;AAC/D,QAAM,cAAc,eAAe,WAChC,YAAY,EACZ,QAAQ,kBAAkB,GAAG,EAC7B,QAAQ,OAAO,GAAG,EAClB,QAAQ,YAAY,EAAE;AACzB,SAAO,cAAc;AACvB;AAEA,eAAe,0BAAyD;AACtE,MAAI,cAA6B;AACjC,MAAI;AACF,UAAM,QAAQ,MAAM,YAAY;AAChC,kBAAc,qBAAqB,MAAM,IAAI,eAAe;AAAA,EAC9D,QAAQ;AACN,kBAAc;AAAA,EAChB;AACA,QAAM,aAAa,oBAAoB,WAAW;AAClD,QAAM,iBAAiB,mBAAAC,QAAK,KAAK,eAAe,GAAG,kBAAkB,UAAU;AAC/E,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB,mBAAAA,QAAK,KAAK,gBAAgB,kBAAkB;AAAA,EAC9D;AACF;AAEA,SAAS,gBAAgB,WAA2B;AAClD,QAAM,aAAa,UAAU,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AACnE,QAAM,QAAQ,WAAW,MAAM,GAAG,EAAE,OAAO,OAAO;AAClD,SAAO,MAAM,MAAM,SAAS,CAAC,KAAK;AACpC;AAEA,eAAe,iBAAkC;AAC/C,QAAM,UAAU,MAAM,wBAAwB;AAC9C,QAAM,MAAM,QAAQ;AACpB,QAAM,iBAAAC,QAAG,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACvC,SAAO;AACT;AAEA,eAAeC,YAAW,UAAoC;AAC5D,MAAI;AACF,UAAM,iBAAAD,QAAG,OAAO,QAAQ;AACxB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,kBAA0B;AACjC,SAAO,mBAAAD,QAAK,KAAK,eAAe,GAAG,iBAAiB;AACtD;AAEA,SAAS,4BAAoC;AAC3C,SAAO,mBAAAA,QAAK,KAAK,eAAe,GAAG,4BAA4B;AACjE;AAEA,eAAe,4BAAmE;AAChF,MAAI;AACF,UAAM,MAAM,MAAM,iBAAAC,QAAG,SAAS,0BAA0B,GAAG,MAAM;AACjE,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,QACE,UACA,OAAO,YAAY,KACnB,OAAO,OAAO,yBAAyB,YACvC,OAAO,qBAAqB,KAAK,GACjC;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,2BAA2B,YAAmC;AAC3E,QAAM,SAAgC;AAAA,IACpC,SAAS;AAAA,IACT,sBAAsB;AAAA,IACtB,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,EACrC;AACA,QAAM,aAAa,0BAA0B;AAC7C,QAAM,iBAAAA,QAAG,MAAM,mBAAAD,QAAK,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5D,QAAM,iBAAAC,QAAG,UAAU,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,GAAG,MAAM;AACxE;AAEA,eAAe,2BAA2B,iBAAwC;AAChF,MAAI,MAAMC,YAAW,eAAe,GAAG;AACrC;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,wBAAwB;AAC9C,QAAM,aAAa,gBAAgB;AACnC,MAAI,CAAE,MAAMA,YAAW,UAAU,GAAI;AACnC;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,0BAA0B;AAC/C,MACE,UACA,OAAO,wBACP,OAAO,yBAAyB,QAAQ,YACxC;AACA;AAAA,EACF;AAEA,QAAM,iBAAAD,QAAG,MAAM,mBAAAD,QAAK,QAAQ,eAAe,GAAG,EAAE,WAAW,KAAK,CAAC;AACjE,QAAM,iBAAAC,QAAG,SAAS,YAAY,eAAe;AAC7C,QAAM,2BAA2B,QAAQ,UAAU;AACrD;AAEA,eAAe,YAA6B;AAC1C,QAAM,MAAM,MAAM,eAAe;AACjC,QAAM,aAAa,mBAAAD,QAAK,KAAK,KAAK,UAAU;AAC5C,QAAM,2BAA2B,UAAU;AAC3C,SAAO;AACT;AAEA,SAAS,kBAAkB,OAAqD;AAC9E,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,EACT;AACA,QAAM,KAAK,OAAO,MAAM,OAAO,YAAY,MAAM,GAAG,KAAK,IAAI,MAAM,GAAG,KAAK,IAAI;AAC/E,QAAM,gBAAgB,OAAO,MAAM,SAAS,YAAY,MAAM,KAAK,KAAK,IAAI,mBAAAA,QAAK,QAAQ,MAAM,IAAI,IAAI;AACvG,MAAI,CAAC,MAAM,CAAC,eAAe;AACzB,WAAO;AAAA,EACT;AACA,QAAM,OACJ,OAAO,MAAM,SAAS,YAAY,MAAM,KAAK,KAAK,IAC9C,MAAM,KAAK,KAAK,IAChB,gBAAgB,aAAa;AACnC,QAAM,SACJ,MAAM,YAAY,OAAO,MAAM,aAAa,YAAY,OAAO,MAAM,SAAS,WAAW,WACrF,MAAM,SAAS,OAAO,KAAK,KAAK,SAChC;AAEN,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,WAAW,QAAQ,MAAM,SAAS;AAAA,IAClC,MAAM,MAAM,SAAS,aAAa,aAAa;AAAA,IAC/C,UAAU,OAAO,MAAM,aAAa,YAAY,MAAM,SAAS,KAAK,IAAI,MAAM,SAAS,KAAK,IAAI;AAAA,IAChG,UAAU,MAAM,SAAS,aAAa,EAAE,OAAO,IAAI;AAAA,IACnD,UAAU;AAAA,MACR,GAAG,gBAAgB;AAAA,MACnB,GAAI,MAAM,YAAY,CAAC;AAAA,IACzB;AAAA,EACF;AACF;AAEA,eAAe,YAAqC;AAClD,QAAM,WAAW,MAAM,UAAU;AACjC,MAAI;AACF,UAAM,MAAM,MAAM,iBAAAC,QAAG,SAAS,UAAU,MAAM;AAC9C,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAM,SAAS,MAAM,QAAQ,QAAQ,UAAU,IAAI,OAAO,aAAa,CAAC;AACxE,UAAM,aAAa,OAChB,IAAI,CAAC,UAAU,kBAAkB,KAAK,CAAC,EACvC,OAAO,CAAC,UAAkC,QAAQ,KAAK,CAAC;AAC3D,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO,aAAa;AAAA,EACtB;AACF;AAEA,eAAe,WAAW,OAAsC;AAC9D,QAAM,WAAW,MAAM,UAAU;AACjC,QAAM,iBAAAA,QAAG,UAAU,UAAU,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG,MAAM;AACrE;AAEA,SAAS,aAAa,YAA8C;AAClE,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,UAA2B,CAAC;AAClC,aAAW,aAAa,YAAY;AAClC,UAAM,MAAM,UAAU,KAAK,YAAY;AACvC,QAAI,KAAK,IAAI,GAAG,GAAG;AACjB;AAAA,IACF;AACA,SAAK,IAAI,GAAG;AACZ,YAAQ,KAAK,SAAS;AAAA,EACxB;AACA,SAAO;AACT;AAEA,eAAe,YAAY,SAA6E;AACtG,QAAM,UAAU,MAAM,UAAU;AAChC,QAAM,OAAO,QAAQ,OAAO;AAC5B,QAAM,WAAW,IAAI;AACrB,SAAO;AACT;AAEA,SAAS,gBAAgB,WAAmC;AAC1D,UAAQ,UAAU,QAAQ,YAAY;AACxC;AAEA,SAAS,wBAAwB,YAA8C;AAC7E,QAAM,iBAAiB,WAAW,OAAO,CAAC,cAAc,gBAAgB,SAAS,CAAC;AAClF,MAAI,eAAe,UAAU,oBAAoB;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,IAAI,IAAI,eAAe,MAAM,GAAG,kBAAkB,EAAE,IAAI,CAAC,cAAc,UAAU,EAAE,CAAC;AACxG,SAAO,WAAW,OAAO,CAAC,cAAc;AACtC,QAAI,gBAAgB,SAAS,GAAG;AAC9B,aAAO,YAAY,IAAI,UAAU,EAAE;AAAA,IACrC;AACA,WAAO,OAAO,UAAU,aAAa,YAAY,YAAY,IAAI,UAAU,QAAQ;AAAA,EACrF,CAAC;AACH;AAEA,eAAe,gCAAgC,YAAuD;AACpG,QAAM,UAAU,MAAM,eAAe,UAAU,EAAE,MAAM,MAAM,IAAI;AACjE,MAAI,CAAC,WAAW,CAAC,0BAA0B,OAAO,GAAG;AACnD,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,wBAAwB,UAAU;AACjD,MAAI,OAAO,WAAW,WAAW,QAAQ;AACvC,WAAO;AAAA,EACT;AAEA,QAAM,WAAW;AAAA,IACf,SAAS;AAAA,IACT,YAAY;AAAA,EACd,CAAC;AACD,SAAO;AACT;AAQA,eAAsB,uBAAiD;AACrE,QAAM,QAAQ,MAAM,UAAU;AAC9B,QAAM,UAAU,aAAa,MAAM,UAAU;AAC7C,SAAO,gCAAgC,OAAO;AAChD;AAEA,eAAsB,uBAAuB,IAA2C;AACtF,QAAM,aAAa,MAAM,qBAAqB;AAC9C,SAAO,WAAW,KAAK,CAAC,UAAU,MAAM,OAAO,EAAE,KAAK;AACxD;AAEA,eAAsB,mBAAmB,YAA4C;AACnF,QAAM,WAAW,mBAAAE,QAAK,QAAQ,UAAU;AACxC,QAAM,OAAO,gBAAgB,QAAQ;AACrC,QAAM,iBAAAC,QAAG,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AAE5C,QAAM,gBAA+B;AAAA,IACnC,QAAI,gCAAW;AAAA,IACf;AAAA,IACA,MAAM;AAAA,IACN,WAAW;AAAA,IACX,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU,gBAAgB;AAAA,EAC5B;AAEA,QAAM,YAAY,CAAC,WAAW;AAAA,IAC5B,SAAS;AAAA,IACT,YAAY,aAAa,CAAC,eAAe,GAAG,MAAM,UAAU,CAAC;AAAA,EAC/D,EAAE;AAEF,SAAO;AACT;AAoKA,eAAsB,uBAAuB,IAAoC;AAC/E,MAAI,UAAgC;AACpC,QAAM,YAAY,CAAC,UAAU;AAC3B,UAAM,OAAO,MAAM,WAAW,IAAI,CAAC,UAAU;AAC3C,UAAI,MAAM,OAAO,IAAI;AACnB,eAAO;AAAA,MACT;AACA,gBAAU;AAAA,QACR,GAAG;AAAA,QACH,WAAW;AAAA,MACb;AACA,aAAO;AAAA,IACT,CAAC;AACD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,YAAY;AAAA,IACd;AAAA,EACF,CAAC;AAED,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,cAAc,EAAE,cAAc;AAAA,EAChD;AACA,SAAO;AACT;;;AGpiBA,IAAAC,sBAAuC;AACvC,IAAAC,mBAAe;AACf,IAAAC,qBAAiB;;;ACAjB,IAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,4BACJ;AAEF,SAAS,SAAS,OAA4B;AAC5C,SAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAC5D,QACD,CAAC;AACP;AAEA,SAASC,UAAS,OAAwB;AACxC,SAAO,OAAO,UAAU,WAAW,QAAQ,SAAS,OAAO,OAAO,KAAK,IAAI;AAC7E;AAEA,SAAS,iBAAiB,OAAgC;AACxD,MAAI,OAAO,UAAU,WAAW;AAC9B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,UAAU,GAAG;AACf,aAAO;AAAA,IACT;AACA,QAAI,UAAU,GAAG;AACf,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,aAAa,MAAM,KAAK,EAAE,YAAY;AAC5C,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AACA,QAAI,eAAe,UAAU,eAAe,KAAK;AAC/C,aAAO;AAAA,IACT;AACA,QAAI,eAAe,WAAW,eAAe,KAAK;AAChD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,SAAkC;AAC1D,QAAM,OAAO,SAAS,OAAO;AAC7B,QAAM,mBAAmB;AAAA,IACvB;AAAA,IACA,SAAS,KAAK,KAAK;AAAA,IACnB,SAAS,KAAK,OAAO;AAAA,IACrB,SAAS,KAAK,IAAI;AAAA,IAClB,SAAS,KAAK,IAAI;AAAA,EACpB;AAEA,aAAW,aAAa,kBAAkB;AACxC,eAAW,OAAO,iBAAiB;AACjC,YAAM,SAAS,iBAAiB,UAAU,GAAG,CAAC;AAC9C,UAAI,WAAW,MAAM;AACnB,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,uBAAuB,SAA0B;AACxD,QAAM,UAAU,QAAQ,KAAK;AAC7B,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,SAAO,0BAA0B,KAAK,OAAO;AAC/C;AAEA,SAAS,8BAA8B,SAA4B;AACjE,QAAM,OAAO,SAAS,OAAO;AAC7B,QAAM,QAAQ,SAAS,KAAK,KAAK;AAEjC,SAAO;AAAA,IACLA,UAAS,KAAK,OAAO;AAAA,IACrBA,UAAS,KAAK,MAAM;AAAA,IACpBA,UAAS,KAAK,MAAM;AAAA,IACpBA,UAAS,KAAK,KAAK;AAAA,IACnBA,UAAS,MAAM,OAAO;AAAA,IACtBA,UAAS,MAAM,MAAM;AAAA,IACrBA,UAAS,MAAM,MAAM;AAAA,IACrBA,UAAS,MAAM,KAAK;AAAA,EACtB,EACG,IAAI,WAAS,MAAM,KAAK,CAAC,EACzB,OAAO,OAAO;AACnB;AAEO,SAAS,4BAA4B,SAA2B;AACrE,QAAM,YAAY,iBAAiB,OAAO;AAC1C,MAAI,cAAc,MAAM;AACtB,WAAO;AAAA,EACT;AACA,SAAO,8BAA8B,OAAO,EAAE,KAAK,sBAAsB;AAC3E;;;ADIA,IAAM,oBAAoB;AAC1B,IAAM,gCAAgC;AACtC,IAAM,0BAA0B;AAChC,IAAM,2BAA2B;AACjC,IAAM,8BAA8B;AACpC,IAAM,0BAA0B,KAAK,KAAK;AAC1C,IAAM,0BAA0B;AAChC,IAAM,gCAAgC;AACtC,IAAM,gCAAgC;AACtC,IAAM,sCAAsC;AAC5C,IAAM,qCAAqC;AAC3C,IAAM,uCAAuC;AAC7C,IAAM,wCAAwC;AAC9C,IAAM,+BAA+B;AACrC,IAAM,mCAAmC;AAEzC,SAASC,UAAS,OAA4B;AAC5C,SAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAC5D,QACD,CAAC;AACP;AAEA,SAASC,UAAS,OAAwB;AACxC,SAAO,OAAO,UAAU,WAAW,QAAQ,SAAS,OAAO,OAAO,KAAK,IAAI;AAC7E;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,SAAOA,UAAS,KAAK,EAAE,KAAK;AAC9B;AAEA,SAAS,SAAS,OAA+B;AAC/C,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,GAAG;AACvD,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,GAAG;AAC7C,UAAM,SAAS,OAAO,MAAM,KAAK,CAAC;AAClC,QAAI,OAAO,SAAS,MAAM,GAAG;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,OAA+B;AACtD,QAAM,UAAU,gBAAgB,KAAK;AACrC,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,MAAI,CAAC,aAAa,KAAK,OAAO,GAAG;AAC/B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,QAAM,SAASD,UAAS,KAAK;AAC7B,QAAM,OAAOA,UAAS,OAAO,IAAI;AACjC,QAAM,SAASA,UAAS,OAAO,MAAM;AACrC,QAAM,OAAOA,UAAS,OAAO,IAAI;AACjC,QAAM,MAAMA,UAAS,OAAO,GAAG;AAC/B,QAAM,UAAUA,UAAS,IAAI,IAAI;AACjC,SAAO;AAAA,IACL,OAAO,YACL,OAAO,aACP,OAAO,kBACP,OAAO,mBACP,KAAK,YACL,KAAK,aACL,OAAO,MACP,OAAO,YACP,OAAO,aACP,KAAK,YACL,KAAK,aACL,KAAK,kBACL,KAAK,mBACL,IAAI,YACJ,IAAI,aACJ,IAAI,kBACJ,IAAI,mBACJ,QAAQ,YACR,QAAQ,aACR,QAAQ,kBACR,QAAQ,mBACR;AAAA,EACJ;AACF;AAEA,SAAS,cAAc,OAAwB;AAC7C,QAAM,SAASA,UAAS,KAAK;AAC7B,QAAM,OAAOA,UAAS,OAAO,IAAI;AACjC,QAAM,MAAMA,UAAS,OAAO,GAAG;AAC/B,QAAM,UAAUA,UAAS,IAAI,IAAI;AACjC,SAAO;AAAA,IACL,KAAK,MACH,KAAK,UACL,KAAK,WACL,OAAO,UACP,OAAO,WACP,IAAI,UACJ,IAAI,WACJ,QAAQ,MACR,QAAQ,UACR,QAAQ,WACR;AAAA,EACJ;AACF;AAEA,SAAS,YAAY,OAAgB,QAAQ,GAAW;AACtD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,KAAK,SAAS,MAAM;AAC9B,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,UAAU,YAAY,OAAO,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE;AAAA,EACpE;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,SAAS;AACf,SACE,YAAY,OAAO,MAAM,QAAQ,CAAC,KAClC,YAAY,OAAO,OAAO,QAAQ,CAAC,KACnC,YAAY,OAAO,SAAS,QAAQ,CAAC,KACrC,YAAY,OAAO,SAAS,QAAQ,CAAC,KACrC,YAAY,OAAO,OAAO,QAAQ,CAAC;AAEvC;AAEA,SAAS,6BAA6B,QAA4B;AAChE,QAAM,MAAMA,UAAS,OAAO,GAAG;AAC/B,SACEC,UAAS,OAAO,KAAK,KACrB,YAAY,OAAO,KAAK,KACxB,YAAY,IAAI,SAAS,IAAI,WAAW,IAAI,WAAW,IAAI,KAAK;AAEpE;AAEA,SAAS,uBAAuB,MAA2B;AACzD,QAAM,WAAW,gBAAgB,KAAK,IAAI,EAAE,YAAY;AACxD,MACE,aAAa,kBACb,aAAa,mBACb,aAAa,sBACb,aAAa,qBACb;AACA,WAAO;AAAA,EACT;AACA,QAAM,WAAW;AAAA,IACf,KAAK,QAAQ,KAAK,cAAc,KAAK,eAAe,KAAK,cAAc,KAAK;AAAA,EAC9E,EAAE,YAAY;AACd,MAAI,aAAa,eAAe,aAAa,SAAS;AACpD,WAAO;AAAA,EACT;AACA,QAAM,SAAS,gBAAgB,KAAK,EAAE;AACtC,SAAO,OAAO,WAAW,MAAM;AACjC;AAEA,SAAS,sCAAsC,QAA4B;AACzE,QAAM,OAAOD,UAAS,OAAO,IAAI;AACjC,MAAI,CAAC,uBAAuB,IAAI,GAAG;AACjC,WAAO;AAAA,EACT;AACA,SAAOC,UAAS,KAAK,IAAI,KAAK,YAAY,KAAK,OAAO,KAAK,YAAY,OAAO,GAAG,KAAK;AACxF;AAEA,SAAS,mBAAmB,QAA4B;AACtD,QAAM,UAAU,OAAO;AACvB,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO,QAAQ,KAAK;AAAA,EACtB;AACA,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,UAAM,QAAQ,QAAQ,IAAI,CAAC,UAAUA,UAAS,KAAK,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAC3E,QAAI,MAAM,SAAS,GAAG;AACpB,aAAO,MAAM,KAAK,GAAG;AAAA,IACvB;AAAA,EACF;AACA,QAAM,SAASD,UAAS,OAAO,cAAc,OAAO,SAAS;AAC7D,QAAM,aAAa,gBAAgB,OAAO,QAAQ,OAAO,OAAO;AAChE,MAAI,YAAY;AACd,WAAO;AAAA,EACT;AACA,SAAO,gBAAgB,OAAO,OAAO,EAAE;AACzC;AAEA,SAAS,sBAAsB,QAA4B;AACzD,QAAM,cAAc,OAAO,gBAAgB,OAAO;AAClD,MAAI,MAAM,QAAQ,WAAW,GAAG;AAC9B,UAAM,QAAQ,YAAY;AAC1B,WAAO,GAAG,KAAK,SAAS,UAAU,IAAI,WAAW,SAAS;AAAA,EAC5D;AACA,QAAM,UAAU,YAAY,MAAM;AAClC,SAAO,QAAQ,KAAK,KAAK;AAC3B;AAEA,SAAS,aAAa,MAAc,YAAY,6BAAuC;AACrF,QAAM,aAAa,KAAK,KAAK;AAC7B,MAAI,CAAC,YAAY;AACf,WAAO,CAAC;AAAA,EACV;AACA,MAAI,WAAW,UAAU,WAAW;AAClC,WAAO,CAAC,UAAU;AAAA,EACpB;AACA,QAAM,QAAkB,CAAC;AACzB,MAAI,QAAQ;AACZ,SAAO,QAAQ,WAAW,QAAQ;AAChC,UAAM,YAAY,WAAW,MAAM,KAAK;AACxC,QAAI,UAAU,UAAU,WAAW;AACjC,YAAM,KAAK,SAAS;AACpB;AAAA,IACF;AACA,QAAI,MAAM;AACV,UAAM,aAAa,UAAU,YAAY,MAAM,SAAS;AACxD,QAAI,cAAc,KAAK,MAAM,YAAY,GAAG,GAAG;AAC7C,YAAM;AAAA,IACR;AACA,UAAM,QAAQ,UAAU,MAAM,GAAG,GAAG,EAAE,KAAK;AAC3C,UAAM,KAAK,SAAS,UAAU,MAAM,GAAG,SAAS,CAAC;AACjD,aAAS;AAAA,EACX;AACA,SAAO;AACT;AAEA,SAAS,uBAAuB,SAAiB,UAA0B;AACzE,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AACA,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,SAAS,QAAQ,GAAG;AAC9B,WAAO;AAAA,EACT;AACA,MAAI,SAAS,WAAW,OAAO,GAAG;AAChC,WAAO;AAAA,EACT;AAIA,QAAM,WAAW,KAAK,IAAI,QAAQ,QAAQ,SAAS,QAAQ,IAAK;AAChE,WAAS,OAAO,UAAU,OAAO,GAAG,QAAQ,GAAG;AAC7C,QAAI,QAAQ,MAAM,CAAC,IAAI,MAAM,SAAS,MAAM,GAAG,IAAI,GAAG;AACpD,aAAO,UAAU,SAAS,MAAM,IAAI;AAAA,IACtC;AAAA,EACF;AACA,SAAO,UAAU;AACnB;AAEA,SAAS,QAAgB;AACvB,SAAO,KAAK,IAAI;AAClB;AAEO,IAAM,iBAAN,MAAqB;AAAA,EAkE1B,YAAY,SAAgC;AAhE5C,SAAQ,WAAmC;AAAA,MACzC,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAEA,SAAQ,SAA+B;AAAA,MACrC,OAAO;AAAA,MACP,SAAS;AAAA,MACT,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,aAAa;AAAA,IACf;AAEA,SAAQ,UAAU;AAClB,SAAQ,sBAA8C;AACtD,SAAQ,kBAAwC;AAChD,SAAQ,eAA8B;AACtC,SAAQ,wBAAwB;AAChC,SAAQ,0BAA0B;AAElC,SAAQ,mBAAmB,oBAAI,IAAyB;AACxD,SAAQ,mBAAmB,oBAAI,IAAoB;AACnD,SAAQ,sBAAsB,oBAAI,IAAmC;AACrE,SAAQ,8BAA8B,oBAAI,IAA8B;AAExE,SAAQ,0BAA0B;AAElC,SAAiB,yBAAyB,oBAAI,IAAoB;AAClE,SAAiB,qBAAqB,oBAAI,IAAoB;AAC9D,SAAQ,kBAAiC;AAEzC,SAAiB,0BAA0B,CAAC,YAAsC;AAChF,WAAK,mBAAmB,OAAO,EAAE,MAAM,CAAC,UAAU;AAChD,gBAAQ,kDAAkD,KAAK;AAAA,MACjE,CAAC;AAAA,IACH;AAEA,SAAiB,mBAAmB,CAAC,YAA+B;AAClE,WAAK,YAAY,OAAO,EAAE,MAAM,CAAC,UAAU;AACzC,gBAAQ,2CAA2C,KAAK;AAAA,MAC1D,CAAC;AAAA,IACH;AAEA,SAAiB,4BAA4B,CAAC,YAA4C;AACxF,WAAK,sBAAsB,QAAQ,QAAQ,cAAc,QAAQ,MAAM,EAAE,MAAM,CAAC,UAAU;AACxF,gBAAQ,mDAAmD,KAAK;AAAA,MAClE,CAAC;AAAA,IACH;AAEA,SAAiB,6BAA6B,CAAC,YAA2C;AACxF,WAAK,sBAAsB,SAAS,QAAQ,cAAc,QAAQ,MAAM,EAAE,MAAM,CAAC,UAAU;AACzF,gBAAQ,oDAAoD,KAAK;AAAA,MACnE,CAAC;AAAA,IACH;AAEA,SAAiB,sBAAsB,CAAC,YAAuC;AAC7E,WAAK,uBAAuB,OAAO,EAAE,MAAM,CAAC,UAAU;AACpD,gBAAQ,wDAAwD,KAAK;AAAA,MACvE,CAAC;AAAA,IACH;AAGE,SAAK,UAAU;AAAA,EACjB;AAAA,EAEQ,uBAAiD;AACvD,QAAI,KAAK,yBAAyB;AAChC,aAAO;AAAA,IACT;AACA,QAAI,KAAK,uBAAuB;AAC9B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEO,YAAkC;AACvC,WAAO;AAAA,MACL,GAAG,KAAK;AAAA,MACR,cAAc;AAAA,MACd,aAAa,KAAK,iBAAiB;AAAA,MACnC,YAAY,KAAK,qBAAqB;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,MAAa,UAAU,YAA8D;AACnF,UAAM,QAAQ,gBAAgB,UAAU,KAAK,KAAK,SAAS,SAAS;AACpE,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,OAAO;AAAA,MACT;AAAA,IACF;AACA,QAAI;AACF,YAAM,WAAW,MAAM,KAAK;AAAA,QAC1B;AAAA,QACA;AAAA,QACA,CAAC;AAAA,QACD,EAAE,UAAU,MAAM;AAAA,MACpB;AACA,YAAM,WAAW,gBAAgBA,UAAS,QAAQ,EAAE,QAAQ;AAC5D,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,UAAU,YAAY;AAAA,QACtB,OAAO;AAAA,MACT;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAa,qBAAqB,UAAqC;AACrE,UAAM,OAAO,KAAK,gBAAgB,QAAQ;AAC1C,UAAM,eAAe,KAAK,UAAU,KAAK,SAAS;AAClD,UAAM,iBAAiB,KAAK,YAAY,KAAK,SAAS;AACtD,SAAK,WAAW;AAChB,SAAK,OAAO,eAAe;AAC3B,QAAI,cAAc;AAChB,WAAK,OAAO,cAAc;AAC1B,WAAK,wBAAwB;AAC7B,WAAK,0BAA0B;AAC/B,WAAK,OAAO,aAAa,KAAK,qBAAqB;AAAA,IACrD;AACA,UAAM,gBAAgB,gBAAgB;AACtC,UAAM,KAAK,iBAAiB,EAAE,cAAc,CAAC;AAAA,EAC/C;AAAA,EAEA,MAAa,UAAyB;AACpC,UAAM,KAAK,KAAK,kBAAkB;AAAA,EACpC;AAAA,EAEA,MAAa,KAAK,QAAgC;AAChD,QAAI,CAAC,KAAK,WAAW,CAAC,KAAK,iBAAiB;AAC1C,YAAM,KAAK,mBAAmB;AAC9B,WAAK,OAAO,QAAQ;AACpB,WAAK,OAAO,UAAU;AACtB,WAAK,OAAO,cAAc;AAC1B,UAAI,QAAQ;AACV,aAAK,OAAO,YAAY;AAAA,MAC1B;AACA;AAAA,IACF;AAEA,SAAK,UAAU;AACf,SAAK,OAAO,UAAU;AACtB,SAAK,OAAO,QAAQ;AACpB,SAAK,OAAO,cAAc;AAE1B,QAAI,KAAK,qBAAqB;AAC5B,WAAK,oBAAoB,MAAM;AAC/B,WAAK,sBAAsB;AAAA,IAC7B;AAEA,QAAI,KAAK,iBAAiB;AACxB,UAAI;AACF,cAAM,KAAK;AAAA,MACb,QAAQ;AAAA,MAER;AACA,WAAK,kBAAkB;AAAA,IACzB;AAEA,SAAK,yBAAyB;AAC9B,UAAM,KAAK,+BAA+B;AAC1C,SAAK,kBAAkB;AACvB,UAAM,KAAK,mBAAmB;AAE9B,QAAI,QAAQ;AACV,cAAQ,6BAA6B,MAAM;AAAA,IAC7C;AAAA,EACF;AAAA,EAEQ,gBAAgB,KAAyC;AAC/D,WAAO;AAAA,MACL,SAAS,IAAI,0BAA0B;AAAA,MACvC,QAAQ,MAAM;AACZ,cAAM,QAAQ,gBAAgB,IAAI,gBAAgB;AAClD,eAAO,SAAS;AAAA,MAClB,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EAEA,MAAc,iBAAiB,SAAoD;AACjF,UAAM,YACJ,KAAK,SAAS,WACd,QAAQ,KAAK,SAAS,KAAK;AAE7B,QAAI,CAAC,WAAW;AACd,YAAM,KAAK,KAAK,2CAA2C;AAC3D,WAAK,OAAO,QAAQ;AACpB,WAAK,OAAO,YAAY;AACxB;AAAA,IACF;AAEA,UAAM,QAAQ,MAAM,KAAK,QAAQ,aAAa,EAAE,MAAM,CAAC,UAAU;AAC/D,cAAQ,iDAAiD,KAAK;AAC9D,aAAO;AAAA,IACT,CAAC;AAED,QAAI,CAAC,OAAO;AACV,YAAM,KAAK,KAAK,+BAA+B;AAC/C,WAAK,OAAO,QAAQ;AACpB,WAAK,OAAO,YAAY;AACxB;AAAA,IACF;AAEA,QAAI,KAAK,WAAW,QAAQ,eAAe;AACzC,YAAM,KAAK,KAAK,mDAAmD;AAAA,IACrE;AAEA,QAAI,KAAK,SAAS;AAChB;AAAA,IACF;AAEA,UAAM,KAAK,MAAM;AAAA,EACnB;AAAA,EAEA,MAAc,QAAuB;AACnC,UAAM,QAAQ,KAAK,SAAS;AAC5B,QAAI,CAAC,OAAO;AACV,WAAK,OAAO,QAAQ;AACpB,WAAK,OAAO,YAAY;AACxB;AAAA,IACF;AAEA,UAAM,KAAK,MAAM,KAAK,UAAU,KAAK;AACrC,QAAI,CAAC,GAAG,IAAI;AACV,WAAK,OAAO,QAAQ;AACpB,WAAK,OAAO,YAAY,GAAG;AAC3B,WAAK,OAAO,cAAc;AAC1B;AAAA,IACF;AAEA,QAAI;AACF,YAAM,KAAK,mBAAmB,KAAK;AAAA,IACrC,SAAS,OAAO;AACd,WAAK,OAAO,QAAQ;AACpB,WAAK,OAAO,YAAY,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC7E;AAAA,IACF;AAEA,SAAK,OAAO,cAAc,GAAG;AAC7B,SAAK,OAAO,YAAY;AACxB,SAAK,OAAO,QAAQ;AACpB,SAAK,OAAO,UAAU;AACtB,SAAK,OAAO,cAAc,MAAM;AAChC,SAAK,UAAU;AAEf,SAAK,yBAAyB;AAE9B,SAAK,sBAAsB,IAAI,gBAAgB;AAC/C,SAAK,kBAAkB,KAAK,WAAW,KAAK,oBAAoB,MAAM,EAAE,QAAQ,MAAM;AACpF,WAAK,kBAAkB;AAAA,IACzB,CAAC;AAED,YAAQ,6BAA6B;AAAA,MACnC,cAAc;AAAA,MACd,aAAa,KAAK,OAAO;AAAA,IAC3B,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,WAAW,QAAoC;AAC3D,UAAM,QAAQ,KAAK,SAAS;AAC5B,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AAGA,UAAM,KAAK,gBAAgB,OAAO,iBAAiB,EAAE,sBAAsB,MAAM,CAAC,EAAE;AAAA,MAClF,CAAC,UAAU;AACT,gBAAQ,0CAA0C,KAAK;AAAA,MACzD;AAAA,IACF;AAEA,QAAI,YAAY;AAEhB,WAAO,CAAC,OAAO,WAAW,KAAK,SAAS;AACtC,UAAI;AACF,aAAK,oBAAoB;AACzB,cAAM,UAAU,MAAM,KAAK;AAAA,UACzB;AAAA,UACA;AAAA,UACA;AAAA,YACE,QAAQ,KAAK;AAAA,YACb,SAAS;AAAA,YACT,iBAAiB,CAAC,WAAW,kBAAkB,gBAAgB;AAAA,UACjE;AAAA,UACA;AAAA,YACE;AAAA,YACA,UAAU;AAAA,UACZ;AAAA,QACF;AAEA,cAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC;AACjD,mBAAW,UAAU,MAAM;AACzB,gBAAM,WAAW,SAAS,OAAO,SAAS;AAC1C,cAAI,aAAa,MAAM;AACrB,iBAAK,eAAe,WAAW;AAAA,UACjC;AACA,gBAAM,KAAK,aAAa,MAAM;AAAA,QAChC;AAEA,oBAAY;AAAA,MACd,SAAS,OAAO;AACd,YAAI,OAAO,WAAW,CAAC,KAAK,SAAS;AACnC;AAAA,QACF;AACA,cAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,aAAK,OAAO,QAAQ;AACpB,aAAK,OAAO,YAAY;AACxB,gBAAQ,mCAAmC,OAAO;AAClD,cAAM,KAAK,MAAM,KAAK,IAAI,WAAW,uBAAuB,CAAC;AAC7D,oBAAY,KAAK,IAAI,YAAY,GAAG,uBAAuB;AAAA,MAC7D;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,WAAW,KAAK,SAAS;AACnC,WAAK,OAAO,QAAQ;AACpB,WAAK,OAAO,YAAY;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,MAAc,aAAa,QAAuC;AAChE,UAAM,SAASA,UAAS,MAAM;AAC9B,QAAI,OAAO,gBAAgB;AACzB,YAAM,KAAK,oBAAoBA,UAAS,OAAO,cAAc,CAAC;AAC9D;AAAA,IACF;AACA,QAAI,OAAO,SAAS;AAClB,YAAM,KAAK,cAAcA,UAAS,OAAO,OAAO,CAAC;AACjD;AAAA,IACF;AACA,QAAI,OAAO,gBAAgB;AACzB,WAAK,uBAAuBA,UAAS,OAAO,cAAc,CAAC;AAC3D;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,uBAAuB,SAA2B;AACxD,UAAM,OAAOA,UAAS,QAAQ,IAAI;AAClC,UAAM,SAAS,gBAAgB,KAAK,EAAE;AACtC,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AACA,UAAM,YAAYA,UAAS,QAAQ,eAAe;AAClD,UAAM,SAAS,gBAAgB,UAAU,MAAM,EAAE,YAAY;AAC7D,QAAI,WAAW,YAAY,WAAW,QAAQ;AAC5C,WAAK,KAAK,aAAa,MAAM;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,SAAoC;AAC9D,UAAM,OAAOA,UAAS,QAAQ,IAAI;AAClC,UAAM,SAAS,gBAAgB,KAAK,EAAE;AACtC,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AACA,UAAM,UAAU,KAAK,mBAAmB,MAAM;AAC9C,UAAM,YAAY,SAAS,QAAQ,cAAc,QAAQ,SAAS;AAClE,QAAI,cAAc,QAAQ,KAAK,2BAA2B,SAAS,SAAS,GAAG;AAC7E;AAAA,IACF;AAEA,UAAM,WAAW,gBAAgB,KAAK,IAAI,EAAE,YAAY;AACxD,QAAI,YAAY,aAAa,WAAW;AACtC,YAAM,KAAK,kBAAkB,QAAQ,8CAA8C;AACnF;AAAA,IACF;AAEA,UAAM,OAAO,gBAAgB,QAAQ,IAAI;AACzC,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AAEA,UAAM,gBAAgB,KAAK,aAAa,IAAI;AAC5C,QAAI,eAAe;AACjB,YAAM,UAAU,MAAM,KAAK,cAAc,QAAQ,cAAc,SAAS,cAAc,IAAI;AAC1F,UAAI,SAAS;AACX;AAAA,MACF;AAAA,IACF;AAEA,UAAM,KAAK,iBAAiB,QAAQ,IAAI;AAAA,EAC1C;AAAA,EAEA,MAAc,oBAAoB,eAA0C;AAC1E,UAAM,aAAa,gBAAgB,cAAc,EAAE;AACnD,UAAM,UAAUA,UAAS,cAAc,OAAO;AAC9C,UAAM,OAAOA,UAAS,QAAQ,IAAI;AAClC,UAAM,SAAS,gBAAgB,KAAK,EAAE;AACtC,UAAM,OAAO,gBAAgB,cAAc,IAAI;AAE/C,QAAI,CAAC,cAAc,CAAC,UAAU,CAAC,MAAM;AACnC;AAAA,IACF;AAEA,UAAM,gBAAgB,oEAAoE;AAAA,MACxF;AAAA,IACF;AACA,QAAI,eAAe;AACjB,YAAM,WAAW,cAAc,CAAC;AAChC,YAAM,WAAW,cAAc,CAAC;AAChC,YAAM,SAAS,KAAK,oBAAoB,IAAI,QAAQ;AACpD,UAAI,CAAC,UAAU,OAAO,WAAW,QAAQ;AACvC,cAAM,KAAK,oBAAoB,YAAY,iBAAiB;AAC5D;AAAA,MACF;AAEA,YAAM,YAAY,KAAK,QAAQ,aAAa;AAC5C,UAAI,CAAC,WAAW;AACd,cAAM,KAAK,oBAAoB,YAAY,sBAAsB;AACjE;AAAA,MACF;AAEA,UAAI;AACF,YAAI,OAAO,SAAS,QAAQ;AAC1B,gBAAM,UAAU,0BAA0B,OAAO,cAAc,QAAQ;AAAA,QACzE,OAAO;AACL,gBAAM,UAAU,yBAAyB,OAAO,cAAc,QAAQ;AAAA,QACxE;AACA,aAAK,oBAAoB,OAAO,QAAQ;AACxC,cAAM,KAAK,oBAAoB,YAAY,aAAa,QAAQ,EAAE;AAClE,cAAM,KAAK,kBAAkB,QAAQ,2BAA2B,QAAQ,GAAG;AAAA,MAC7E,SAAS,OAAO;AACd,cAAM,KAAK,oBAAoB,YAAY,4BAA4B;AACvE,cAAM,KAAK;AAAA,UACT;AAAA,UACA,uCAAuC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAC/F;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,KAAK,oBAAoB,YAAY,iBAAiB;AAAA,EAC9D;AAAA,EAEQ,aAAa,MAAwD;AAC3E,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,QAAQ,WAAW,GAAG,GAAG;AAC5B,aAAO;AAAA,IACT;AACA,UAAM,CAAC,MAAM,GAAG,IAAI,IAAI,QAAQ,MAAM,MAAM;AAC5C,UAAM,mBAAmB,KAAK,MAAM,CAAC;AACrC,UAAM,UAAU,iBAAiB,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,EAAE,YAAY;AACnE,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL;AAAA,MACA,MAAM,KAAK,KAAK,GAAG,EAAE,KAAK;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,QAAgB,SAAiB,MAAgC;AAC3F,YAAQ,SAAS;AAAA,MACf,KAAK;AAAA,MACL,KAAK,QAAQ;AACX,cAAM,KAAK,SAAS,MAAM;AAC1B,eAAO;AAAA,MACT;AAAA,MACA,KAAK,UAAU;AACb,cAAM,KAAK,WAAW,MAAM;AAC5B,eAAO;AAAA,MACT;AAAA,MACA,KAAK;AAAA,MACL,KAAK,cAAc;AACjB,cAAM,KAAK,aAAa,MAAM;AAC9B,eAAO;AAAA,MACT;AAAA,MACA,KAAK;AAAA,MACL,KAAK,aAAa;AAChB,cAAM,KAAK,cAAc,QAAQ,IAAI;AACrC,eAAO;AAAA,MACT;AAAA,MACA,KAAK,OAAO;AACV,cAAM,KAAK,gBAAgB,MAAM;AACjC,eAAO;AAAA,MACT;AAAA,MACA,KAAK,WAAW;AACd,cAAM,KAAK,YAAY,MAAM;AAC7B,eAAO;AAAA,MACT;AAAA,MACA,KAAK,UAAU;AACb,cAAM,KAAK,aAAa,QAAQ,IAAI;AACpC,eAAO;AAAA,MACT;AAAA,MACA,KAAK,aAAa;AAChB,cAAM,KAAK,cAAc,MAAM;AAC/B,eAAO;AAAA,MACT;AAAA,MACA,KAAK,SAAS;AACZ,cAAM,KAAK,gBAAgB,QAAQ,IAAI;AACvC,eAAO;AAAA,MACT;AAAA,MACA;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEA,MAAc,SAAS,QAA+B;AACpD,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,kBAAkB,QAAQ,MAAM,KAAK,IAAI,CAAC;AAAA,EACvD;AAAA,EAEA,MAAc,WAAW,QAA+B;AACtD,UAAM,UAAU,KAAK,mBAAmB,MAAM;AAC9C,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAM,QAAQ;AAAA,MACZ,WAAW,OAAO,KAAK;AAAA,MACvB,mBAAmB,OAAO,UAAU;AAAA,MACpC;AAAA,MACA,QAAQ,OAAO,cAAc,IAAI,OAAO,WAAW,KAAK,WAAW;AAAA,MACnE,mBAAmB,QAAQ,aAAa,gBAAgB;AAAA,MACxD,kBAAkB,QAAQ,YAAY,QAAQ;AAAA,MAC9C,eAAe,QAAQ,aAAa,QAAQ,IAAI;AAAA,IAClD;AACA,QAAI,OAAO,WAAW;AACpB,YAAM,KAAK,eAAe,OAAO,SAAS,EAAE;AAAA,IAC9C;AACA,UAAM,KAAK,kBAAkB,QAAQ,MAAM,KAAK,IAAI,CAAC;AAAA,EACvD;AAAA,EAEA,MAAc,aAAa,QAA+B;AACxD,UAAM,WAAW,MAAM,KAAK,QAAQ,aAAa;AACjD,UAAM,UAAU,KAAK,mBAAmB,MAAM;AAC9C,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,KAAK,kBAAkB,QAAQ,wCAAwC;AAC7E;AAAA,IACF;AACA,YAAQ,mBAAmB,SAAS,IAAI,CAAC,UAAU,MAAM,EAAE;AAC3D,UAAM,QAAQ,CAAC,WAAW;AAC1B,aAAS,QAAQ,CAAC,SAAS,UAAU;AACnC,YAAM,WAAW,QAAQ,OAAO,QAAQ;AACxC,YAAM;AAAA,QACJ,GAAG,QAAQ,CAAC,KAAK,QAAQ,IAAI,GAAG,WAAW,cAAc,EAAE,KAAK,QAAQ,EAAE;AAAA,MAC5E;AAAA,IACF,CAAC;AACD,UAAM,KAAK,kBAAkB,QAAQ,MAAM,KAAK,IAAI,CAAC;AAAA,EACvD;AAAA,EAEA,MAAc,cAAc,QAAgB,MAA6B;AACvE,UAAM,UAAU,KAAK,mBAAmB,MAAM;AAC9C,UAAM,WAAW,MAAM,KAAK,QAAQ,aAAa;AACjD,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,KAAK,kBAAkB,QAAQ,wBAAwB;AAC7D;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,wBAAwB,MAAM,UAAU,QAAQ,gBAAgB;AACtF,QAAI,CAAC,UAAU;AACb,YAAM,KAAK;AAAA,QACT;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,QAAQ,cAAc,SAAS,IAAI;AACrC,YAAM,KAAK,2BAA2B,OAAO;AAC7C,cAAQ,YAAY,SAAS;AAC7B,cAAQ,WAAW;AACnB,cAAQ,eAAe;AACvB,cAAQ,aAAa;AACrB,cAAQ,yBAAyB;AACjC,WAAK,YAAY,OAAO;AAAA,IAC1B;AAEA,UAAM,KAAK,kBAAkB,QAAQ,0BAA0B,SAAS,IAAI,GAAG;AAAA,EACjF;AAAA,EAEQ,wBACN,MACA,UACA,OACoB;AACpB,UAAM,QAAQ,KAAK,KAAK;AACxB,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,OAAO,KAAK;AAC5B,QAAI,OAAO,UAAU,OAAO,KAAK,WAAW,GAAG;AAC7C,UAAI,MAAM,SAAS,KAAK,WAAW,MAAM,QAAQ;AAC/C,cAAM,KAAK,MAAM,UAAU,CAAC;AAC5B,eAAO,SAAS,KAAK,CAAC,UAAU,MAAM,OAAO,EAAE,KAAK;AAAA,MACtD;AACA,UAAI,WAAW,SAAS,QAAQ;AAC9B,eAAO,SAAS,UAAU,CAAC,KAAK;AAAA,MAClC;AAAA,IACF;AAEA,WAAO,SAAS,KAAK,CAAC,UAAU,MAAM,OAAO,KAAK,KAAK;AAAA,EACzD;AAAA,EAEA,MAAc,gBAAgB,QAA+B;AAC3D,UAAM,UAAU,KAAK,mBAAmB,MAAM;AAC9C,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS,MAAM;AAC/D,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,QAAQ,aAAa;AAC5C,QAAI,CAAC,WAAW;AACd,YAAM,KAAK,kBAAkB,QAAQ,sBAAsB;AAC3D;AAAA,IACF;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,UAAU,YAAY;AAAA,QAC3C,aAAa,QAAQ;AAAA,QACrB,cAAc,QAAQ;AAAA,QACtB,KAAK,QAAQ;AAAA,MACf,CAAC;AACD,YAAM,WAAW,KAAK,4BAA4B,QAAQ;AAC1D,UAAI,CAAC,UAAU;AACb,cAAM,KAAK,kBAAkB,QAAQ,4CAA4C;AACjF;AAAA,MACF;AACA,cAAQ,WAAW;AACnB,cAAQ,eAAe;AACvB,cAAQ,aAAa;AACrB,cAAQ,yBAAyB;AACjC,WAAK,YAAY,OAAO;AACxB,YAAM,KAAK,2BAA2B,SAAS,QAAQ,IAAI,QAAQ;AACnE,YAAM,KAAK,kBAAkB,QAAQ,uBAAuB,QAAQ,EAAE;AAAA,IACxE,SAAS,OAAO;AACd,YAAM,KAAK;AAAA,QACT;AAAA,QACA,iCAAiC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACzF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,YAAY,QAA+B;AACvD,UAAM,UAAU,KAAK,mBAAmB,MAAM;AAC9C,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS,MAAM;AAC/D,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,QAAQ,aAAa;AAC5C,QAAI,CAAC,WAAW;AACd,YAAM,KAAK,kBAAkB,QAAQ,sBAAsB;AAC3D;AAAA,IACF;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,UAAU,kBAAkB;AAAA,QACjD,KAAK,QAAQ;AAAA,QACb,OAAO;AAAA,QACP,SAAS;AAAA,QACT,UAAU;AAAA,MACZ,CAAC;AACD,YAAM,UAAU,KAAK,kBAAkB,QAAQ;AAC/C,UAAI,QAAQ,WAAW,GAAG;AACxB,cAAM,KAAK,kBAAkB,QAAQ,oCAAoC;AACzE;AAAA,MACF;AACA,cAAQ,kBAAkB,QAAQ,IAAI,CAAC,UAAU,MAAM,EAAE;AACzD,YAAM,QAAQ,CAAC,UAAU;AACzB,cAAQ,QAAQ,CAAC,QAAQ,UAAU;AACjC,cAAM,WAAW,OAAO,OAAO,QAAQ;AACvC,cAAM,QAAQ,OAAO,SAAS;AAC9B,cAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,KAAK,GAAG,WAAW,cAAc,EAAE,KAAK,OAAO,EAAE,GAAG;AAAA,MAClF,CAAC;AACD,YAAM,KAAK,kBAAkB,QAAQ,MAAM,KAAK,IAAI,CAAC;AAAA,IACvD,SAAS,OAAO;AACd,YAAM,KAAK;AAAA,QACT;AAAA,QACA,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACnF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,aAAa,QAAgB,MAA6B;AACtE,UAAM,UAAU,KAAK,mBAAmB,MAAM;AAC9C,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS,MAAM;AAC/D,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,QAAQ,aAAa;AAC5C,QAAI,CAAC,WAAW;AACd,YAAM,KAAK,kBAAkB,QAAQ,sBAAsB;AAC3D;AAAA,IACF;AAEA,UAAM,QAAQ,KAAK,KAAK;AACxB,QAAI,CAAC,OAAO;AACV,YAAM,KAAK,kBAAkB,QAAQ,2BAA2B;AAChE;AAAA,IACF;AAEA,QAAI,WAAW;AACf,UAAM,UAAU,OAAO,KAAK;AAC5B,QAAI,OAAO,UAAU,OAAO,KAAK,WAAW,GAAG;AAC7C,UAAI,QAAQ,gBAAgB,SAAS,KAAK,WAAW,QAAQ,gBAAgB,QAAQ;AACnF,mBAAW,QAAQ,gBAAgB,UAAU,CAAC,KAAK;AAAA,MACrD;AAAA,IACF;AACA,QAAI,CAAC,UAAU;AACb,iBAAW;AAAA,IACb;AAEA,QAAI;AACF,YAAM,UAAU,aAAa;AAAA,QAC3B,aAAa,QAAQ;AAAA,QACrB,cAAc,QAAQ;AAAA,QACtB;AAAA,MACF,CAAC;AACD,cAAQ,WAAW;AACnB,cAAQ,eAAe;AACvB,cAAQ,aAAa;AACrB,cAAQ,yBAAyB;AACjC,WAAK,YAAY,OAAO;AACxB,YAAM,KAAK,2BAA2B,SAAS,QAAQ,IAAI,QAAQ;AACnE,YAAM,KAAK,kBAAkB,QAAQ,yBAAyB,QAAQ,EAAE;AAAA,IAC1E,SAAS,OAAO;AACd,YAAM,KAAK;AAAA,QACT;AAAA,QACA,4BAA4B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACpF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,QAA+B;AACzD,UAAM,UAAU,KAAK,mBAAmB,MAAM;AAC9C,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS,MAAM;AAC/D,QAAI,CAAC,WAAW,CAAC,QAAQ,UAAU;AACjC,YAAM,KAAK,kBAAkB,QAAQ,gCAAgC;AACrE;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,QAAQ,aAAa;AAC5C,QAAI,CAAC,WAAW;AACd,YAAM,KAAK,kBAAkB,QAAQ,sBAAsB;AAC3D;AAAA,IACF;AAEA,UAAM,SAAS,QAAQ,gBAAgB;AACvC,QAAI;AACF,YAAM,UAAU,cAAc;AAAA,QAC5B,aAAa,QAAQ;AAAA,QACrB,cAAc,QAAQ;AAAA,QACtB,UAAU,QAAQ;AAAA,QAClB;AAAA,MACF,CAAC;AACD,cAAQ,aAAa;AACrB,cAAQ,eAAe;AACvB,WAAK,YAAY,OAAO;AACxB,YAAM,KAAK,kBAAkB,QAAQ,sBAAsB;AAAA,IAC7D,SAAS,OAAO;AACd,YAAM,KAAK;AAAA,QACT;AAAA,QACA,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,gBAAgB,QAAgB,MAA6B;AACzE,UAAM,YAAY,KAAK,QAAQ,aAAa;AAC5C,QAAI,CAAC,WAAW;AACd,YAAM,KAAK,kBAAkB,QAAQ,sBAAsB;AAC3D;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,SAAS;AACZ,YAAM,KAAK;AAAA,QACT;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,CAAC,kBAAkB,GAAG,SAAS,IAAI,QAAQ,MAAM,MAAM;AAC7D,QAAI,iBAAiB,iBAAiB,KAAK;AAC3C,QAAI,WAAW,UAAU,KAAK,GAAG,EAAE,KAAK;AAExC,QAAI,CAAC,kBAAkB,eAAe,SAAS,GAAG,GAAG;AACnD,YAAM,iBAAiB,MAAM,KAAK,KAAK,4BAA4B,OAAO,CAAC,EAAE;AAAA,QAC3E,CAAC,UAAU,MAAM,WAAW;AAAA,MAC9B;AACA,UAAI,eAAe,WAAW,GAAG;AAC/B,cAAM,KAAK;AAAA,UACT;AAAA,UACA;AAAA,QACF;AACA;AAAA,MACF;AACA,uBAAiB,OAAO,eAAe,CAAC,EAAE,SAAS;AACnD,iBAAW;AAAA,IACb;AAEA,UAAM,UAAU,KAAK,4BAA4B,IAAI,cAAc;AACnE,QAAI,CAAC,WAAW,QAAQ,WAAW,QAAQ;AACzC,YAAM,KAAK,kBAAkB,QAAQ,gCAAgC;AACrE;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,sBAAsB,UAAU,QAAQ,MAAM;AACnE,QAAI,CAAC,SAAS;AACZ,YAAM,KAAK;AAAA,QACT;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI;AACF,YAAM,UAAU,uBAAuB,QAAQ,WAAW;AAAA,QACxD;AAAA,MACF,CAAC;AACD,WAAK,4BAA4B,OAAO,cAAc;AACtD,YAAM,KAAK,kBAAkB,QAAQ,kBAAkB;AAAA,IACzD,SAAS,OAAO;AACd,YAAM,KAAK;AAAA,QACT;AAAA,QACA,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACnF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,sBACN,UACA,QAC8C;AAC9C,UAAM,eAAe,MAAM,QAAQ,OAAO,SAAS,IAAI,OAAO,YAAY,CAAC;AAC3E,UAAM,YAAY,aACf,IAAI,CAAC,UAAUA,UAAS,KAAK,CAAC,EAC9B,OAAO,CAAC,UAAU,gBAAgB,MAAM,EAAE,CAAC;AAE9C,UAAM,cAAc,IAAI,IAAI,UAAU,IAAI,CAAC,UAAU,gBAAgB,MAAM,EAAE,CAAC,CAAC;AAC/E,UAAM,UAAiD,CAAC;AAExD,UAAM,WAAW,SACd,MAAM,GAAG,EACT,IAAI,CAAC,YAAY,QAAQ,KAAK,CAAC,EAC/B,OAAO,OAAO;AAEjB,QAAI,SAAS,WAAW,GAAG;AACzB,UAAI,UAAU,WAAW,KAAK,SAAS,KAAK,GAAG;AAC7C,cAAM,KAAK,gBAAgB,UAAU,CAAC,EAAE,EAAE;AAC1C,gBAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,SAAS,KAAK,CAAC,EAAE;AAC3C,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAEA,eAAW,WAAW,UAAU;AAC9B,YAAM,UAAU,QAAQ,QAAQ,GAAG;AACnC,UAAI,WAAW,GAAG;AAChB,YAAI,UAAU,WAAW,GAAG;AAC1B,gBAAM,KAAK,gBAAgB,UAAU,CAAC,EAAE,EAAE;AAC1C,kBAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,QAAQ,KAAK,CAAC,EAAE;AAC1C;AAAA,QACF;AACA,eAAO;AAAA,MACT;AACA,YAAM,MAAM,QAAQ,MAAM,GAAG,OAAO,EAAE,KAAK;AAC3C,YAAM,QAAQ,QAAQ,MAAM,UAAU,CAAC,EAAE,KAAK;AAC9C,UAAI,CAAC,OAAO,CAAC,SAAS,CAAC,YAAY,IAAI,GAAG,GAAG;AAC3C,eAAO;AAAA,MACT;AACA,YAAM,cAAc,MACjB,MAAM,GAAG,EACT,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,OAAO,OAAO;AACjB,cAAQ,GAAG,IAAI;AAAA,QACb,SAAS,YAAY,SAAS,IAAI,cAAc,CAAC,KAAK;AAAA,MACxD;AAAA,IACF;AAEA,WAAO,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,UAAU;AAAA,EACrD;AAAA,EAEA,MAAc,iBAAiB,QAAgB,MAA6B;AAC1E,UAAM,UAAU,KAAK,mBAAmB,MAAM;AAC9C,QAAI,QAAQ,YAAY;AACtB,YAAM,KAAK;AAAA,QACT;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS,MAAM;AAC/D,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,UAAM,WAAW,QAAQ,YAAa,MAAM,KAAK,sBAAsB,QAAQ,SAAS,OAAO;AAC/F,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,QAAQ,aAAa;AAC5C,QAAI,CAAC,WAAW;AACd,YAAM,KAAK,kBAAkB,QAAQ,sBAAsB;AAC3D;AAAA,IACF;AAEA,QAAI;AACF,cAAQ,yBAAyB;AACjC,WAAK,YAAY,OAAO;AACxB,YAAM,WAAW,MAAM,UAAU,gBAAgB;AAAA,QAC/C,aAAa,QAAQ;AAAA,QACrB,cAAc,QAAQ;AAAA,QACtB;AAAA,QACA,WAAW;AAAA,QACX,gBAAgB;AAAA,QAChB,iBAAiB;AAAA,QACjB;AAAA,MACF,CAAC;AAED,YAAM,SAAS,KAAK,0BAA0B,QAAQ;AACtD,cAAQ,aAAa;AACrB,cAAQ,eAAe,UAAU;AACjC,WAAK,sBAAsB,OAAO;AAAA,IACpC,SAAS,OAAO;AACd,YAAM,KAAK;AAAA,QACT;AAAA,QACA,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACnF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,sBACZ,QACA,SACA,SACwB;AACxB,UAAM,YAAY,KAAK,QAAQ,aAAa;AAC5C,QAAI,CAAC,WAAW;AACd,YAAM,KAAK,kBAAkB,QAAQ,sBAAsB;AAC3D,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,UAAU,YAAY;AAAA,QAC3C,aAAa,QAAQ;AAAA,QACrB,cAAc,QAAQ;AAAA,QACtB,KAAK,QAAQ;AAAA,MACf,CAAC;AACD,YAAM,WAAW,KAAK,4BAA4B,QAAQ;AAC1D,UAAI,CAAC,UAAU;AACb,cAAM,KAAK,kBAAkB,QAAQ,8CAA8C;AACnF,eAAO;AAAA,MACT;AACA,cAAQ,WAAW;AACnB,YAAM,KAAK,2BAA2B,SAAS,QAAQ,IAAI,QAAQ;AACnE,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,KAAK;AAAA,QACT;AAAA,QACA,4BAA4B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACpF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,qBACZ,SACA,QAC6B;AAC7B,QAAI,QAAQ,WAAW;AACrB,YAAM,WAAW,MAAM,KAAK,QAAQ,eAAe,QAAQ,SAAS;AACpE,UAAI,UAAU;AACZ,eAAO;AAAA,MACT;AACA,cAAQ,YAAY;AACpB,cAAQ,WAAW;AAAA,IACrB;AAEA,UAAM,mBAAmB,MAAM,KAAK,wBAAwB;AAC5D,QAAI,kBAAkB;AACpB,YAAM,YAAY,MAAM,KAAK,QAAQ,eAAe,gBAAgB,EAAE,MAAM,MAAM,IAAI;AACtF,UAAI,WAAW;AACb,gBAAQ,YAAY,UAAU;AAC9B,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,KAAK,QAAQ,aAAa;AACjD,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,KAAK,kBAAkB,QAAQ,6DAA6D;AAClG,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,SAAS,KAAK,CAAC,UAAU,MAAM,SAAS;AAC1D,UAAM,WAAW,aAAa,SAAS,CAAC;AACxC,YAAQ,YAAY,SAAS;AAC7B,YAAQ,mBAAmB,SAAS,IAAI,CAAC,UAAU,MAAM,EAAE;AAC3D,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,0BAAkD;AAC9D,UAAM,WAAW,KAAK,QAAQ;AAC9B,QAAI,CAAC,UAAU;AACb,aAAO;AAAA,IACT;AACA,QAAI;AACF,YAAM,QAAQ,MAAM,SAAS;AAC7B,YAAM,aAAa,gBAAgB,KAAK;AACxC,aAAO,cAAc;AAAA,IACvB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,4BAA4B,OAAwB;AAC1D,UAAM,SAASA,UAAS,KAAK;AAC7B,UAAM,SAASA,UAAS,OAAO,MAAM;AACrC,UAAM,SAASA,UAAS,OAAO,UAAU,OAAO,MAAM;AACtD,WAAO;AAAA,MACL,OAAO,MACL,OAAO,YACP,OAAO,aACP,OAAO,YACP,OAAO,aACP,OAAO,YACP,OAAO,aACP,OAAO,kBACP,OAAO,mBACP;AAAA,IACJ;AAAA,EACF;AAAA,EAEQ,0BAA0B,OAAwB;AACxD,UAAM,SAASA,UAAS,KAAK;AAC7B,UAAM,SAASA,UAAS,OAAO,MAAM;AACrC,UAAM,OAAOA,UAAS,OAAO,QAAQ,OAAO,IAAI;AAChD,WAAO;AAAA,MACL,KAAK,MACH,KAAK,UACL,KAAK,WACL,OAAO,UACP,OAAO,WACP,OAAO,UACP,OAAO,WACP;AAAA,IACJ;AAAA,EACF;AAAA,EAEQ,kBAAkB,OAAsD;AAC9E,UAAM,OAAOA,UAAS,KAAK;AAC3B,UAAM,UAAU,MAAM,QAAQ,KAAK,IAC9B,QACA,MAAM,QAAQ,KAAK,IAAI,IACtB,KAAK,OACL,MAAM,QAAQ,KAAK,OAAO,IACxB,KAAK,UACL,MAAM,QAAQ,KAAK,KAAK,IACtB,KAAK,QACL,CAAC;AACX,UAAM,SAA+C,CAAC;AACtD,eAAW,SAAS,SAAS;AAC3B,YAAM,SAASA,UAAS,KAAK;AAC7B,YAAM,KAAK;AAAA,QACT,OAAO,MACL,OAAO,YACP,OAAO,aACP,OAAO,kBACP,OAAO,mBACP;AAAA,MACJ;AACA,UAAI,CAAC,IAAI;AACP;AAAA,MACF;AACA,YAAM,QACJ;AAAA,QACE,OAAO,QAAQ,OAAO,SAAS,OAAO,WAAW,OAAO,WAAW,OAAO,QAAQ;AAAA,MACpF,KAAK;AACP,aAAO,KAAK,EAAE,IAAI,MAAM,CAAC;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,mBAAmB,QAA6B;AACtD,UAAM,WAAW,KAAK,iBAAiB,IAAI,MAAM;AACjD,QAAI,UAAU;AACZ,aAAO;AAAA,IACT;AACA,UAAM,UAAuB;AAAA,MAC3B;AAAA,MACA,WAAW;AAAA,MACX,UAAU;AAAA,MACV,wBAAwB;AAAA,MACxB,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,kBAAkB;AAAA,MAClB,kBAAkB,CAAC;AAAA,MACnB,iBAAiB,CAAC;AAAA,MAClB,wBAAwB;AAAA,MACxB,wBAAwB,CAAC;AAAA,MACzB,uBAAuB,CAAC;AAAA,MACxB,0BAA0B,CAAC;AAAA,MAC3B,oBAAoB;AAAA,MACpB,oBAAoB;AAAA,MACpB,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,MACxB,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AACA,SAAK,iBAAiB,IAAI,QAAQ,OAAO;AACzC,SAAK,OAAO,cAAc,KAAK,iBAAiB;AAChD,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,aAAa,QAA+B;AACxD,UAAM,UAAU,KAAK,iBAAiB,IAAI,MAAM;AAChD,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AACA,UAAM,KAAK,2BAA2B,OAAO;AAC7C,SAAK,oBAAoB,OAAO;AAChC,QAAI,QAAQ,UAAU;AACpB,WAAK,iBAAiB,OAAO,QAAQ,QAAQ;AAAA,IAC/C;AACA,SAAK,iBAAiB,OAAO,MAAM;AACnC,SAAK,OAAO,cAAc,KAAK,iBAAiB;AAAA,EAClD;AAAA,EAEA,MAAc,2BACZ,SACA,WACA,UACe;AACf,UAAM,YAAY,KAAK,QAAQ,aAAa;AAC5C,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,UAAM,KAAK,2BAA2B,OAAO;AAE7C,QAAI;AACF,YAAM,WAAW,MAAM,UAAU,wBAAwB;AAAA,QACvD,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,cAAc;AAAA,MAChB,CAAC;AACD,YAAM,iBAAiBA,UAAS,QAAQ;AACxC,YAAM,iBAAiB,gBAAgB,eAAe,cAAc;AACpE,cAAQ,yBAAyB,kBAAkB;AACnD,cAAQ,WAAW;AACnB,WAAK,iBAAiB,IAAI,UAAU,QAAQ,MAAM;AAAA,IACpD,SAAS,OAAO;AACd,cAAQ,4DAA4D,KAAK;AAAA,IAC3E;AAAA,EACF;AAAA,EAEA,MAAc,2BAA2B,SAAqC;AAC5E,UAAM,YAAY,KAAK,QAAQ,aAAa;AAC5C,QAAI,CAAC,WAAW;AACd,cAAQ,yBAAyB;AACjC;AAAA,IACF;AAEA,UAAM,iBAAiB,QAAQ;AAC/B,YAAQ,yBAAyB;AACjC,QAAI,CAAC,gBAAgB;AACnB;AAAA,IACF;AAEA,QAAI;AACF,YAAM,UAAU,2BAA2B;AAAA,QACzC;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,cAAQ,4DAA4D,KAAK;AAAA,IAC3E;AAAA,EACF;AAAA,EAEA,MAAc,iCAAgD;AAC5D,UAAM,WAAW,MAAM,KAAK,KAAK,iBAAiB,OAAO,CAAC;AAC1D,UAAM,QAAQ,IAAI,SAAS,IAAI,CAAC,YAAY,KAAK,2BAA2B,OAAO,CAAC,CAAC;AAAA,EACvF;AAAA,EAEQ,oBAA0B;AAChC,eAAW,WAAW,KAAK,iBAAiB,OAAO,GAAG;AACpD,WAAK,YAAY,OAAO;AAAA,IAC1B;AACA,SAAK,iBAAiB,MAAM;AAC5B,SAAK,iBAAiB,MAAM;AAC5B,SAAK,oBAAoB,MAAM;AAC/B,SAAK,4BAA4B,MAAM;AACvC,SAAK,uBAAuB,MAAM;AAClC,SAAK,mBAAmB,MAAM;AAC9B,SAAK,OAAO,cAAc;AAAA,EAC5B;AAAA,EAEQ,2BAAiC;AACvC,QAAI,KAAK,yBAAyB;AAChC;AAAA,IACF;AACA,UAAM,YAAY,KAAK,QAAQ,aAAa;AAC5C,QAAI,CAAC,WAAW;AACd,WAAK,OAAO,QAAQ;AACpB,WAAK,OAAO,YAAY;AACxB;AAAA,IACF;AAEA,cAAU,GAAG,sBAAsB,KAAK,uBAAuB;AAC/D,cAAU,GAAG,eAAe,KAAK,gBAAgB;AACjD,cAAU,GAAG,8BAA8B,KAAK,yBAAyB;AACzE,cAAU,GAAG,6BAA6B,KAAK,0BAA0B;AACzE,cAAU,GAAG,wBAAwB,KAAK,mBAAmB;AAC7D,SAAK,0BAA0B;AAAA,EACjC;AAAA,EAEQ,2BAAiC;AACvC,QAAI,CAAC,KAAK,yBAAyB;AACjC;AAAA,IACF;AACA,UAAM,YAAY,KAAK,QAAQ,aAAa;AAC5C,QAAI,CAAC,WAAW;AACd,WAAK,0BAA0B;AAC/B;AAAA,IACF;AAEA,cAAU,IAAI,sBAAsB,KAAK,uBAAuB;AAChE,cAAU,IAAI,eAAe,KAAK,gBAAgB;AAClD,cAAU,IAAI,8BAA8B,KAAK,yBAAyB;AAC1E,cAAU,IAAI,6BAA6B,KAAK,0BAA0B;AAC1E,cAAU,IAAI,wBAAwB,KAAK,mBAAmB;AAC9D,SAAK,0BAA0B;AAAA,EACjC;AAAA,EAEA,MAAc,mBAAmB,SAAkD;AACjF,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AACA,UAAM,SAAS,gBAAgB,QAAQ,MAAM;AAC7C,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AACA,UAAM,SAASA,UAAS,QAAQ,MAAM;AACtC,UAAM,WAAW,gBAAgB,MAAM;AACvC,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AACA,UAAM,UAAU,KAAK,yBAAyB,QAAQ;AACtD,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,QAAI,WAAW,gBAAgB;AAC7B,YAAM,SAAS,cAAc,MAAM;AACnC,cAAQ,aAAa;AACrB,UAAI,QAAQ;AACV,gBAAQ,eAAe;AAAA,MACzB;AACA,WAAK,sBAAsB,OAAO;AAClC;AAAA,IACF;AAEA,QAAI,WAAW,2BAA2B;AACxC,YAAM,QAAQ,6BAA6B,MAAM;AACjD,UAAI,CAAC,OAAO;AACV;AAAA,MACF;AACA,UAAI,KAAK,iBAAiB,GAAG,QAAQ,IAAI,KAAK,EAAE,GAAG;AACjD;AAAA,MACF;AACA,WAAK,qBAAqB,SAAS,KAAK;AACxC;AAAA,IACF;AAEA,QAAI,WAAW,kBAAkB;AAC/B,YAAM,OAAO,sCAAsC,MAAM;AACzD,UAAI,KAAK,KAAK,GAAG;AACf,gBAAQ,yBAAyB;AAAA,MACnC;AACA;AAAA,IACF;AAEA,QAAI,WAAW,kBAAkB;AAC/B,YAAM,KAAK,aAAa,OAAO;AAC/B;AAAA,IACF;AAEA,QAAI,WAAW,SAAS;AACtB,UAAI,CAAC,4BAA4B,MAAM,GAAG;AACxC,cAAM,eACJ,gBAAgBA,UAAS,OAAO,KAAK,EAAE,OAAO,KAC9C,gBAAgB,OAAO,OAAO,KAC9B;AACF,cAAM,KAAK,kBAAkB,QAAQ,QAAQ,eAAe,YAAY,EAAE;AAAA,MAC5E;AACA,YAAM,KAAK,aAAa,OAAO;AAC/B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,YAAY,SAA2C;AACnE,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AACA,UAAM,SAAS,gBAAgB,QAAQ,MAAM;AAC7C,QAAI,CAAC,OAAO,WAAW,cAAc,GAAG;AACtC;AAAA,IACF;AACA,UAAM,SAASA,UAAS,QAAQ,MAAM;AACtC,UAAM,WAAW,gBAAgB,MAAM;AACvC,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AACA,UAAM,UAAU,KAAK,yBAAyB,QAAQ;AACtD,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,UAAM,MAAMA,UAAS,OAAO,GAAG;AAC/B,UAAM,UAAU,gBAAgB,IAAI,IAAI,EAAE,YAAY;AAEtD,QAAI,YAAY,yBAAyB,YAAY,+BAA+B;AAClF,YAAM,QAAQ,YAAY,IAAI,SAAS,IAAI,WAAW,IAAI,WAAW,IAAI,KAAK;AAC9E,UAAI,CAAC,OAAO;AACV;AAAA,MACF;AACA,UAAI,KAAK,iBAAiB,GAAG,QAAQ,IAAI,KAAK,EAAE,GAAG;AACjD;AAAA,MACF;AACA,WAAK,qBAAqB,SAAS,KAAK;AACxC;AAAA,IACF;AAEA,QAAI,YAAY,iBAAiB;AAC/B,YAAM,OAAO,YAAY,IAAI,WAAW,IAAI,WAAW,IAAI,QAAQ,IAAI,KAAK;AAC5E,UAAI,KAAK,KAAK,GAAG;AACf,gBAAQ,yBAAyB;AAAA,MACnC;AACA;AAAA,IACF;AAEA,QAAI,YAAY,gBAAgB;AAC9B,cAAQ,aAAa;AACrB,YAAM,SAAS,cAAc,MAAM;AACnC,UAAI,QAAQ;AACV,gBAAQ,eAAe;AAAA,MACzB;AACA,WAAK,sBAAsB,OAAO;AAClC;AAAA,IACF;AAEA,QAAI,YAAY,mBAAmB,YAAY,gBAAgB;AAC7D,YAAM,KAAK,aAAa,OAAO;AAC/B;AAAA,IACF;AAEA,QAAI,YAAY,WAAW,YAAY,gBAAgB;AACrD,UAAI,CAAC,4BAA4B,GAAG,GAAG;AACrC,cAAM,eACJ,gBAAgB,IAAI,OAAO,KAAK,gBAAgB,IAAI,KAAK,KAAK;AAChE,cAAM,KAAK,kBAAkB,QAAQ,QAAQ,eAAe,YAAY,EAAE;AAAA,MAC5E;AACA,YAAM,KAAK,aAAa,OAAO;AAAA,IACjC;AAAA,EACF;AAAA,EAEQ,yBAAyB,UAAsC;AACrE,UAAM,SAAS,KAAK,iBAAiB,IAAI,QAAQ;AACjD,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AACA,UAAM,UAAU,KAAK,iBAAiB,IAAI,MAAM;AAChD,QAAI,CAAC,WAAW,QAAQ,aAAa,UAAU;AAC7C,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,qBAAqB,SAAsB,OAAqB;AACtE,QAAI,CAAC,QAAQ,QAAQ;AACnB,cAAQ,SAAS;AAAA,QACf,aAAS,gCAAW,EAAE,MAAM,GAAG,EAAE;AAAA,QACjC,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,WAAW;AAAA,MACb;AAAA,IACF;AACA,UAAM,aAAa,uBAAuB,QAAQ,OAAO,QAAQ,KAAK;AACtE,QAAI,eAAe,QAAQ,OAAO,QAAQ;AACxC;AAAA,IACF;AACA,YAAQ,OAAO,SAAS;AACxB,YAAQ,aAAa;AACrB,SAAK,sBAAsB,OAAO;AAClC,SAAK,mBAAmB,SAAS,KAAK;AAAA,EACxC;AAAA,EAEQ,mBAAmB,SAAsB,OAAsB;AACrE,QAAI,CAAC,QAAQ,QAAQ;AACnB;AAAA,IACF;AAEA,QAAI,OAAO;AACT,UAAI,QAAQ,OAAO,YAAY;AAC7B,qBAAa,QAAQ,OAAO,UAAU;AACtC,gBAAQ,OAAO,aAAa;AAAA,MAC9B;AACA,UAAI,QAAQ,oBAAoB;AAC9B,gBAAQ,qBAAqB;AAC7B;AAAA,MACF;AACA,WAAK,KAAK,WAAW,SAAS,IAAI;AAClC;AAAA,IACF;AAEA,QAAI,QAAQ,oBAAoB;AAC9B,cAAQ,qBAAqB;AAC7B;AAAA,IACF;AAEA,QAAI,QAAQ,OAAO,YAAY;AAC7B;AAAA,IACF;AAEA,YAAQ,OAAO,aAAa,WAAW,MAAM;AAC3C,UAAI,QAAQ,QAAQ;AAClB,gBAAQ,OAAO,aAAa;AAAA,MAC9B;AACA,WAAK,KAAK,WAAW,SAAS,KAAK;AAAA,IACrC,GAAG,wBAAwB;AAAA,EAC7B;AAAA,EAEA,MAAc,WAAW,SAAsB,OAA+B;AAC5E,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AAEA,QAAI,QAAQ,oBAAoB;AAC9B,UAAI,OAAO;AACT,gBAAQ,qBAAqB;AAAA,MAC/B;AACA;AAAA,IACF;AAEA,UAAM,gBAAgB,QAAQ;AAC9B,QAAI,CAAC,eAAe;AAClB;AAAA,IACF;AAEA,UAAM,UAAU,cAAc;AAC9B,UAAM,UAAU,cAAc;AAC9B,QAAI,CAAC,QAAQ,KAAK,GAAG;AACnB;AAAA,IACF;AAEA,UAAM,YACJ,QAAQ,UAAU,8BACd,UACA,QAAQ,MAAM,QAAQ,SAAS,2BAA2B;AAEhE,QAAI,CAAC,SAAS,cAAc,cAAc,UAAU;AAClD;AAAA,IACF;AAEA,UAAM,WAAW,YAAY;AAC3B,UAAI,KAAK,uBAAuB;AAC9B,YAAI;AACF,gBAAM,KAAK,iBAAiB,QAAQ,QAAQ,WAAW,OAAO;AAC9D,gBAAM,eAAe,KAAK,mBAAmB,SAAS,OAAO;AAC7D,cAAI,cAAc;AAChB,yBAAa,WAAW;AAAA,UAC1B;AACA,eAAK,OAAO,aAAa,KAAK,qBAAqB;AACnD;AAAA,QACF,SAAS,OAAO;AACd,gBAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,cAAI,KAAK,iCAAiC,OAAO,GAAG;AAClD,iBAAK,wBAAwB;AAC7B,iBAAK,OAAO,aAAa,KAAK,qBAAqB;AACnD;AAAA,cACE;AAAA,cACA;AAAA,YACF;AAAA,UACF,OAAO;AACL,oBAAQ,2CAA2C,OAAO;AAC1D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,KAAK,yBAAyB;AACjC;AAAA,MACF;AAEA,UAAI;AACF,cAAM,KAAK,wBAAwB,SAAS,WAAW,OAAO;AAC9D,cAAM,eAAe,KAAK,mBAAmB,SAAS,OAAO;AAC7D,YAAI,cAAc;AAChB,uBAAa,WAAW;AAAA,QAC1B;AACA,aAAK,OAAO,aAAa,KAAK,qBAAqB;AAAA,MACrD,SAAS,OAAO;AACd,cAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,YAAI,KAAK,mCAAmC,OAAO,GAAG;AACpD,eAAK,0BAA0B;AAC/B,eAAK,OAAO,aAAa,KAAK,qBAAqB;AACnD,kBAAQ,qEAAqE,OAAO;AACpF;AAAA,QACF;AACA,gBAAQ,yDAAyD,OAAO;AAAA,MAC1E;AAAA,IACF;AAEA,UAAM,eAAe,SAAS;AAC9B,YAAQ,qBAAqB;AAC7B,QAAI;AACF,YAAM;AAAA,IACR,UAAE;AACA,UAAI,QAAQ,uBAAuB,cAAc;AAC/C,gBAAQ,qBAAqB;AAAA,MAC/B;AACA,UAAI,QAAQ,sBAAsB,KAAK,WAAW,QAAQ,QAAQ;AAChE,gBAAQ,qBAAqB;AAC7B,aAAK,KAAK,WAAW,SAAS,KAAK;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,aAAa,SAAqC;AAC9D,QAAI,QAAQ,kBAAkB;AAC5B;AAAA,IACF;AACA,QAAI,CAAC,QAAQ,cAAc,CAAC,QAAQ,QAAQ,UAAU,CAAC,QAAQ,wBAAwB;AACrF;AAAA,IACF;AAEA,YAAQ,mBAAmB;AAC3B,QAAI;AACF,YAAM,KAAK,WAAW,SAAS,IAAI;AACnC,UAAI,QAAQ,oBAAoB;AAC9B,cAAM,QAAQ,mBAAmB,MAAM,MAAM,MAAS;AAAA,MACxD;AACA,UAAI,QAAQ,sBAAsB,QAAQ,QAAQ;AAChD,gBAAQ,qBAAqB;AAC7B,cAAM,KAAK,WAAW,SAAS,IAAI;AACnC,YAAI,QAAQ,oBAAoB;AAC9B,gBAAM,QAAQ,mBAAmB,MAAM,MAAM,MAAS;AAAA,QACxD;AAAA,MACF;AAEA,YAAM,aAAa,QAAQ,0BAA0B,QAAQ,QAAQ,UAAU,IAAI,KAAK;AACxF,YAAM,SAAS,QAAQ;AACvB,YAAM,uBAAuB,SACzB,QAAQ,uBAAuB,SAAS,MAAM,IAC9C;AACJ,YAAM,MAAM,MAAM;AAClB,YAAM,wBACJ,UAAU,SAAS,KACnB,QAAQ,2BAA2B,aACnC,MAAM,QAAQ,0BAA0B;AAC1C,YAAM,4BAA4B,KAAK,0BAA0B,SAAS,WAAW,GAAG;AAExF,UAAI,aAAa,CAAC,wBAAwB,CAAC,yBAAyB,CAAC,2BAA2B;AAC9F,cAAM,SAAS,aAAa,WAAW,2BAA2B;AAClE,YAAI,kBAAkB;AACtB,cAAM,kBAAkB,QAAQ,QAAQ,aAAa;AACrD,YAAI,oBAAoB,QAAQ,OAAO,SAAS,GAAG;AACjD,gBAAM,SAAS,MAAM,KAAK,yBAAyB,QAAQ,QAAQ,iBAAiB,OAAO,CAAC,CAAC;AAC7F,cAAI,CAAC,QAAQ;AACX,kBAAM,KAAK,kBAAkB,QAAQ,QAAQ,OAAO,CAAC,CAAC;AAAA,UACxD;AACA,4BAAkB;AAAA,QACpB;AACA,iBAAS,QAAQ,iBAAiB,QAAQ,OAAO,QAAQ,SAAS,GAAG;AACnE,gBAAM,KAAK,kBAAkB,QAAQ,QAAQ,OAAO,KAAK,CAAC;AAAA,QAC5D;AACA,gBAAQ,yBAAyB;AACjC,gBAAQ,yBAAyB;AACjC,aAAK,qBAAqB,SAAS,WAAW,GAAG;AACjD,YAAI,QAAQ;AACV,kBAAQ,uBAAuB,KAAK,MAAM;AAC1C,cAAI,QAAQ,uBAAuB,SAAS,qCAAqC;AAC/E,oBAAQ,uBAAuB;AAAA,cAC7B;AAAA,cACA,QAAQ,uBAAuB,SAAS;AAAA,YAC1C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,UAAE;AACA,cAAQ,aAAa;AACrB,cAAQ,eAAe;AACvB,cAAQ,yBAAyB;AACjC,WAAK,YAAY,OAAO;AACxB,cAAQ,mBAAmB;AAAA,IAC7B;AAAA,EACF;AAAA,EAEQ,YAAY,SAA4B;AAC9C,SAAK,oBAAoB,OAAO;AAChC,QAAI,QAAQ,QAAQ,YAAY;AAC9B,mBAAa,QAAQ,OAAO,UAAU;AAAA,IACxC;AACA,YAAQ,qBAAqB;AAC7B,YAAQ,qBAAqB;AAC7B,YAAQ,SAAS;AAAA,EACnB;AAAA,EAEQ,sBAAsB,SAA4B;AACxD,QAAI,CAAC,KAAK,WAAW,CAAC,QAAQ,YAAY;AACxC;AAAA,IACF;AACA,QAAI,QAAQ,aAAa;AACvB;AAAA,IACF;AACA,SAAK,KAAK,iBAAiB,QAAQ,MAAM;AACzC,YAAQ,cAAc,YAAY,MAAM;AACtC,UAAI,CAAC,KAAK,WAAW,CAAC,QAAQ,YAAY;AACxC,aAAK,oBAAoB,OAAO;AAChC;AAAA,MACF;AACA,WAAK,KAAK,iBAAiB,QAAQ,MAAM;AAAA,IAC3C,GAAG,4BAA4B;AAAA,EACjC;AAAA,EAEQ,oBAAoB,SAA4B;AACtD,QAAI,QAAQ,aAAa;AACvB,oBAAc,QAAQ,WAAW;AACjC,cAAQ,cAAc;AAAA,IACxB;AAAA,EACF;AAAA,EAEQ,iCAAiC,SAA0B;AACjE,UAAM,QAAQ,QAAQ,YAAY;AAClC,WACE,MAAM,SAAS,kBAAkB,KACjC,MAAM,SAAS,kBAAkB,KACjC,MAAM,SAAS,oBAAoB,KACnC,MAAM,SAAS,wBAAwB,KACvC,MAAM,SAAS,mBAAmB,KAClC,MAAM,SAAS,mBAAmB,KAClC,MAAM,SAAS,WAAW;AAAA,EAE9B;AAAA,EAEQ,mCAAmC,SAA0B;AACnE,UAAM,QAAQ,QAAQ,YAAY;AAClC,WACE,MAAM,SAAS,iBAAiB,MAC/B,MAAM,SAAS,kBAAkB,KAAK,MAAM,SAAS,oBAAoB;AAAA,EAE9E;AAAA,EAEA,MAAc,wBACZ,SACA,MACA,SACe;AACf,UAAM,SAAS,KAAK,mBAAmB,SAAS,OAAO;AACvD,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AACA,UAAM,oBAAoB,OAAO;AACjC,QAAI,sBAAsB,MAAM;AAC9B,YAAM,SAAS,MAAM,KAAK,mBAAmB,QAAQ,QAAQ,mBAAmB,IAAI;AACpF,UAAI,QAAQ;AACV;AAAA,MACF;AACA,YAAM,eAAe,KAAK,mBAAmB,SAAS,OAAO;AAC7D,UAAI,cAAc;AAChB,qBAAa,YAAY;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,KAAK,kBAAkB,QAAQ,QAAQ,IAAI;AAC9D,UAAM,YAAY,KAAK,yBAAyB,IAAI;AACpD,QAAI,cAAc,MAAM;AACtB,YAAM,eAAe,KAAK,mBAAmB,SAAS,OAAO;AAC7D,UAAI,cAAc;AAChB,qBAAa,YAAY;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,mBACN,SACA,SACuB;AACvB,UAAM,SAAS,QAAQ;AACvB,QAAI,CAAC,UAAU,OAAO,YAAY,SAAS;AACzC,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,yBACZ,QACA,WACA,MACkB;AAClB,WAAO,KAAK,mBAAmB,QAAQ,WAAW,IAAI;AAAA,EACxD;AAAA,EAEA,MAAc,mBACZ,QACA,WACA,MACkB;AAClB,QAAI;AACF,YAAM,KAAK,gBAAgB,QAAQ,WAAW,IAAI;AAClD,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,YAAM,QAAQ,QAAQ,YAAY;AAClC,UAAI,MAAM,SAAS,yBAAyB,GAAG;AAC7C,eAAO;AAAA,MACT;AACA,UACE,MAAM,SAAS,2BAA2B,KAC1C,MAAM,SAAS,yBAAyB,KACxC,MAAM,SAAS,wBAAwB,GACvC;AACA,eAAO;AAAA,MACT;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,2BAA2B,SAAsB,WAA4B;AACnF,QAAI,QAAQ,yBAAyB,SAAS,SAAS,GAAG;AACxD,aAAO;AAAA,IACT;AACA,YAAQ,yBAAyB,KAAK,SAAS;AAC/C,QAAI,QAAQ,yBAAyB,SAAS,uCAAuC;AACnF,cAAQ,yBAAyB;AAAA,QAC/B;AAAA,QACA,QAAQ,yBAAyB,SAAS;AAAA,MAC5C;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,oBAAoB,SAAsB,WAA2B;AAC3E,UAAM,aAAa,UAAU,KAAK;AAClC,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AACA,UAAM,YAAY,QAAQ,YAAY;AACtC,UAAM,aAAS,gCAAW,MAAM,EAAE,OAAO,UAAU,EAAE,OAAO,KAAK;AACjE,WAAO,GAAG,SAAS,IAAI,MAAM;AAAA,EAC/B;AAAA,EAEQ,0BACN,SACA,WACA,KACS;AACT,UAAM,YAAY,KAAK,oBAAoB,SAAS,SAAS;AAC7D,QAAI,CAAC,WAAW;AACd,aAAO;AAAA,IACT;AAEA,QAAI,aAAa;AACjB,UAAM,OAAiD,CAAC;AACxD,eAAW,SAAS,QAAQ,uBAAuB;AACjD,UAAI,MAAM,MAAM,KAAK,oCAAoC;AACvD;AAAA,MACF;AACA,UAAI,MAAM,cAAc,WAAW;AACjC,qBAAa;AAAA,MACf;AACA,WAAK,KAAK,KAAK;AAAA,IACjB;AACA,YAAQ,wBAAwB;AAChC,WAAO;AAAA,EACT;AAAA,EAEQ,qBAAqB,SAAsB,WAAmB,KAAmB;AACvF,UAAM,YAAY,KAAK,oBAAoB,SAAS,SAAS;AAC7D,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,UAAM,OAAO,QAAQ,sBAAsB;AAAA,MACzC,CAAC,UACC,MAAM,cAAc,aAAa,MAAM,MAAM,MAAM;AAAA,IACvD;AACA,SAAK,KAAK,EAAE,WAAW,IAAI,IAAI,CAAC;AAChC,QAAI,KAAK,SAAS,sCAAsC;AACtD,WAAK,OAAO,GAAG,KAAK,SAAS,oCAAoC;AAAA,IACnE;AACA,YAAQ,wBAAwB;AAAA,EAClC;AAAA,EAEQ,iBAAiB,WAA4B;AACnD,UAAM,MAAM,MAAM;AAClB,UAAM,WAAW,KAAK,uBAAuB,IAAI,SAAS,KAAK;AAC/D,SAAK,uBAAuB,IAAI,WAAW,GAAG;AAC9C,QAAI,KAAK,uBAAuB,OAAO,MAAO;AAC5C,iBAAW,CAAC,KAAK,EAAE,KAAK,KAAK,wBAAwB;AACnD,YAAI,MAAM,KAAK,KAAO;AACpB,eAAK,uBAAuB,OAAO,GAAG;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AACA,WAAO,WAAW,KAAK,MAAM,YAAY;AAAA,EAC3C;AAAA,EAEA,MAAc,sBACZ,MACA,cACA,QACe;AACf,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AAEA,UAAM,SAAS,KAAK,wBAAwB,MAAM;AAClD,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AAEA,UAAM,eAAW,gCAAW,EAAE,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,EAAE;AAC3D,SAAK,oBAAoB,IAAI,UAAU;AAAA,MACrC,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,MAAM;AAAA,IACrB,CAAC;AAED,UAAM,WAAW,gBAAgB,MAAM;AACvC,UAAM,QAAQ,SAAS,SAAS,8BAA8B;AAC9D,UAAM,SAAS,SAAS,SAAS,mBAAmB,MAAM,IAAI,sBAAsB,MAAM;AAC1F,UAAM,QAAQ,CAAC,KAAK;AACpB,QAAI,UAAU;AACZ,YAAM,KAAK,WAAW,QAAQ,EAAE;AAAA,IAClC;AACA,QAAI,QAAQ;AACV,YAAM,KAAK,WAAW,MAAM,EAAE;AAAA,IAChC;AAEA,UAAM,KAAK,kBAAkB,QAAQ,MAAM,KAAK,IAAI,GAAG;AAAA,MACrD,cAAc;AAAA,QACZ,iBAAiB;AAAA,UACf;AAAA,YACE,EAAE,MAAM,WAAW,eAAe,SAAS,QAAQ,YAAY;AAAA,YAC/D,EAAE,MAAM,mBAAmB,eAAe,SAAS,QAAQ,wBAAwB;AAAA,UACrF;AAAA,UACA;AAAA,YACE,EAAE,MAAM,QAAQ,eAAe,SAAS,QAAQ,UAAU;AAAA,YAC1D,EAAE,MAAM,SAAS,eAAe,SAAS,QAAQ,SAAS;AAAA,UAC5D;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,uBAAuB,SAAmD;AACtF,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AACA,UAAM,SAAS,gBAAgB,QAAQ,MAAM,EAAE,YAAY;AAC3D,QAAI,CAAC,OAAO,SAAS,kBAAkB,GAAG;AACxC;AAAA,IACF;AAEA,UAAM,SAASA,UAAS,QAAQ,MAAM;AACtC,UAAM,SAAS,KAAK,wBAAwB,MAAM;AAClD,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AAEA,UAAM,QAAQ,OAAO,QAAQ,SAAS;AACtC,SAAK,4BAA4B,IAAI,OAAO;AAAA,MAC1C;AAAA,MACA,WAAW,QAAQ;AAAA,MACnB,QAAQ,QAAQ;AAAA,MAChB;AAAA,MACA,aAAa,MAAM;AAAA,IACrB,CAAC;AAED,UAAM,YAAY,MAAM,QAAQ,OAAO,SAAS,IAC5C,OAAO,UAAU,IAAI,CAAC,UAAUA,UAAS,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,gBAAgB,MAAM,EAAE,CAAC,IAC5F,CAAC;AAEL,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA,eAAe,KAAK;AAAA,MACpB;AAAA,IACF;AAEA,QAAI,UAAU,SAAS,GAAG;AACxB,YAAM,KAAK,EAAE;AACb,iBAAW,YAAY,WAAW;AAChC,cAAM,MAAM,gBAAgB,SAAS,EAAE;AACvC,cAAM,QAAQ,gBAAgB,SAAS,QAAQ,KAAK,gBAAgB,SAAS,MAAM,KAAK;AACxF,cAAM,KAAK,GAAG,GAAG,KAAK,KAAK,EAAE;AAC7B,cAAM,UAAU,MAAM,QAAQ,SAAS,OAAO,IAC1C,SAAS,QAAQ,IAAI,CAAC,UAAUA,UAAS,KAAK,CAAC,EAAE,IAAI,CAAC,UAAU,gBAAgB,MAAM,KAAK,CAAC,EAAE,OAAO,OAAO,IAC5G,CAAC;AACL,YAAI,QAAQ,SAAS,GAAG;AACtB,gBAAM,KAAK,YAAY,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAEA,UAAM,KAAK,kBAAkB,QAAQ,MAAM,KAAK,IAAI,CAAC;AAAA,EACvD;AAAA,EAEQ,wBAAwB,QAAmC;AACjE,UAAM,WAAW,gBAAgB,MAAM;AACvC,QAAI,UAAU;AACZ,YAAM,SAAS,KAAK,iBAAiB,IAAI,QAAQ;AACjD,UAAI,QAAQ;AACV,eAAO;AAAA,MACT;AAAA,IACF;AACA,UAAM,WAAW,MAAM,KAAK,KAAK,iBAAiB,OAAO,CAAC;AAC1D,QAAI,SAAS,WAAW,GAAG;AACzB,aAAO,SAAS,CAAC,EAAE;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,sBAA4B;AAClC,UAAM,YAAY,MAAM,IAAI;AAC5B,eAAW,CAAC,IAAI,KAAK,KAAK,KAAK,qBAAqB;AAClD,UAAI,MAAM,cAAc,WAAW;AACjC,aAAK,oBAAoB,OAAO,EAAE;AAAA,MACpC;AAAA,IACF;AACA,eAAW,CAAC,WAAW,KAAK,KAAK,KAAK,6BAA6B;AACjE,UAAI,MAAM,cAAc,WAAW;AACjC,aAAK,4BAA4B,OAAO,SAAS;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,oBAAoB,iBAAyB,MAA8B;AACvF,UAAM,QAAQ,KAAK,SAAS;AAC5B,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AACA,UAAM,KAAK;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,QACE,mBAAmB;AAAA,QACnB,MAAM,QAAQ;AAAA,MAChB;AAAA,MACA;AAAA,QACE,UAAU;AAAA,MACZ;AAAA,IACF,EAAE,MAAM,MAAM,MAAS;AAAA,EACzB;AAAA,EAEA,MAAc,iBAAiB,QAA+B;AAC5D,UAAM,QAAQ,KAAK,SAAS;AAC5B,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AACA,UAAM,KAAK;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,QACE,SAAS;AAAA,QACT,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,UAAU;AAAA,MACZ;AAAA,IACF,EAAE,MAAM,MAAM,MAAS;AAAA,EACzB;AAAA,EAEA,MAAc,iBAAiB,QAAgB,MAAc,SAAgC;AAC3F,UAAM,QAAQ,KAAK,SAAS;AAC5B,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AACA,UAAM,KAAK,kBAAkB,MAAM;AACnC,UAAM,KAAK;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,QACE,SAAS;AAAA,QACT;AAAA,QACA,cAAc;AAAA,QACd,UAAU;AAAA,MACZ;AAAA,MACA;AAAA,QACE,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,kBACZ,QACA,MACA,OAC4B;AAC5B,UAAM,QAAQ,KAAK,SAAS;AAC5B,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AACA,UAAM,UAAmC;AAAA,MACvC,SAAS;AAAA,MACT;AAAA,MACA,GAAG;AAAA,IACL;AACA,UAAM,KAAK,kBAAkB,MAAM;AACnC,UAAM,SAAS,MAAM,KAAK,gBAA4B,OAAO,eAAe,SAAS;AAAA,MACnF,UAAU;AAAA,IACZ,CAAC;AACD,WAAOA,UAAS,MAAM;AAAA,EACxB;AAAA,EAEA,MAAc,gBAAgB,QAAgB,WAAmB,MAA6B;AAC5F,UAAM,QAAQ,KAAK,SAAS;AAC5B,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AACA,UAAM,KAAK,kBAAkB,MAAM;AACnC,UAAM,KAAK;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,QACE,SAAS;AAAA,QACT,YAAY;AAAA,QACZ;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,yBAAyB,OAA+B;AAC9D,UAAM,SAASA,UAAS,KAAK;AAC7B,WAAO,SAAS,OAAO,cAAc,OAAO,SAAS;AAAA,EACvD;AAAA,EAEA,MAAc,kBAAkB,QAA+B;AAC7D,UAAM,WAAW,KAAK,mBAAmB,IAAI,MAAM,KAAK;AACxD,UAAM,MAAM,MAAM;AAClB,UAAM,SAAS,iCAAiC,MAAM;AACtD,QAAI,SAAS,GAAG;AACd,YAAM,KAAK,MAAM,MAAM;AAAA,IACzB;AACA,SAAK,mBAAmB,IAAI,QAAQ,MAAM,CAAC;AAAA,EAC7C;AAAA,EAEA,MAAc,gBACZ,OACA,QACA,SACA,SACY;AACZ,UAAM,MAAM,GAAG,iBAAiB,OAAO,KAAK,IAAI,MAAM;AAEtD,UAAM,UAAU,YAA6C;AAC3D,YAAM,aAAa,IAAI,gBAAgB;AACvC,YAAM,YAAY,WAAW,MAAM;AACjC,mBAAW,MAAM;AAAA,MACnB,GAAG,uBAAuB;AAE1B,YAAM,SAAS,SAAS;AACxB,UAAI,wBAA6C;AACjD,UAAI,QAAQ;AACV,YAAI,OAAO,SAAS;AAClB,uBAAa,SAAS;AACtB,qBAAW,MAAM;AAAA,QACnB,OAAO;AACL,kCAAwB,MAAM,WAAW,MAAM;AAC/C,iBAAO,iBAAiB,SAAS,uBAAuB,EAAE,MAAM,KAAK,CAAC;AAAA,QACxE;AAAA,MACF;AAEA,UAAI;AACF,cAAME,YAAW,MAAM,MAAM,KAAK;AAAA,UAChC,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,UAClB;AAAA,UACA,MAAM,KAAK,UAAU,OAAO;AAAA,UAC5B,QAAQ,WAAW;AAAA,QACrB,CAAC;AACD,cAAM,OAAQ,MAAMA,UAAS,KAAK;AAClC,eAAO;AAAA,MACT,UAAE;AACA,qBAAa,SAAS;AACtB,YAAI,UAAU,uBAAuB;AACnC,iBAAO,oBAAoB,SAAS,qBAAqB;AAAA,QAC3D;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,QAAQ;AAC/B,QAAI,SAAS,IAAI;AACf,aAAO,SAAS;AAAA,IAClB;AAEA,UAAM,oBAAoB,SAAS,YAAY;AAC/C,QACE,SAAS,YACT,SAAS,eAAe,OACxB,OAAO,sBAAsB,YAC7B,oBAAoB,GACpB;AACA,YAAM,KAAK,MAAM,oBAAoB,GAAI;AACzC,YAAM,UAAU,MAAM,QAAQ;AAC9B,UAAI,QAAQ,IAAI;AACd,eAAO,QAAQ;AAAA,MACjB;AACA,YAAM,IAAI,MAAM,QAAQ,eAAe,GAAG,MAAM,iBAAiB,QAAQ,cAAc,SAAS,GAAG;AAAA,IACrG;AAEA,UAAM,IAAI,MAAM,SAAS,eAAe,GAAG,MAAM,iBAAiB,SAAS,cAAc,SAAS,GAAG;AAAA,EACvG;AAAA,EAEQ,MAAM,IAA2B;AACvC,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,iBAAW,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC,CAAC;AAAA,IACjD,CAAC;AAAA,EACH;AAAA,EAEQ,qBAAqB,OAAuB;AAClD,UAAM,gBAAY,gCAAW,MAAM,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC5E,WAAO,mBAAAC,QAAK,KAAK,eAAe,GAAG,GAAG,gCAAgC,IAAI,SAAS,OAAO;AAAA,EAC5F;AAAA,EAEA,MAAc,mBAAmB,OAA8B;AAC7D,QAAI,KAAK,iBAAiB;AACxB;AAAA,IACF;AACA,UAAM,WAAW,KAAK,qBAAqB,KAAK;AAChD,UAAM,iBAAAC,QAAG,MAAM,mBAAAD,QAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAE1D,UAAM,UAAU,KAAK;AAAA,MACnB;AAAA,QACE,KAAK,QAAQ;AAAA,QACb,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI;AACF,YAAM,iBAAAC,QAAG,UAAU,UAAU,SAAS,EAAE,UAAU,QAAQ,MAAM,KAAK,CAAC;AACtE,WAAK,kBAAkB;AACvB;AAAA,IACF,SAAS,OAAO;AACd,YAAM,OAAQ,MAAgC;AAC9C,UAAI,SAAS,UAAU;AACrB,cAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,cAAc,MAAM,KAAK,YAAY,QAAQ;AACnD,QAAI,eAAe,gBAAgB,QAAQ,OAAO,KAAK,eAAe,WAAW,GAAG;AAClF,YAAM,IAAI;AAAA,QACR,2DAA2D,WAAW;AAAA,MACxE;AAAA,IACF;AAEA,UAAM,iBAAAA,QAAG,OAAO,QAAQ,EAAE,MAAM,MAAM,MAAS;AAC/C,UAAM,iBAAAA,QAAG,UAAU,UAAU,SAAS,EAAE,UAAU,QAAQ,MAAM,KAAK,CAAC;AACtE,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,MAAc,qBAAoC;AAChD,UAAM,WAAW,KAAK;AACtB,SAAK,kBAAkB;AACvB,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AACA,UAAM,iBAAAA,QAAG,OAAO,QAAQ,EAAE,MAAM,MAAM,MAAS;AAAA,EACjD;AAAA,EAEA,MAAc,YAAY,UAA0C;AAClE,QAAI;AACF,YAAM,MAAM,MAAM,iBAAAA,QAAG,SAAS,UAAU,MAAM;AAC9C,YAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,YAAM,MAAM,SAAS,OAAO,GAAG;AAC/B,UAAI,QAAQ,QAAQ,OAAO,GAAG;AAC5B,eAAO;AAAA,MACT;AACA,aAAO,KAAK,MAAM,GAAG;AAAA,IACvB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,eAAe,KAAsB;AAC3C,QAAI;AACF,cAAQ,KAAK,KAAK,CAAC;AACnB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,OAAQ,MAAgC;AAC9C,aAAO,SAAS;AAAA,IAClB;AAAA,EACF;AACF;AAEO,SAAS,qBAAqB,SAAgD;AACnF,SAAO,IAAI,eAAe,OAAO;AACnC;;;APzgFA,SAAS,QAAQ,MAAgB,MAAuB;AACtD,SAAO,KAAK,SAAS,IAAI;AAC3B;AAEA,SAAS,WAAW,MAA0B;AAC5C,SAAO,KAAK,OAAO,SAAO,CAAC,IAAI,WAAW,GAAG,CAAC;AAChD;AAEA,SAAS,gBAAgB,OAAiB,MAA6B;AACrE,QAAM,WAAW,MAAM,KAAK,UAAQ,KAAK,WAAW,GAAG,IAAI,GAAG,CAAC;AAC/D,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,SAAS,MAAM,GAAG,IAAI,IAAI,MAAM,EAAE,KAAK;AACrD,SAAO,MAAM,SAAS,IAAI,QAAQ;AACpC;AAEA,SAAS,gBAAgB,SAAuB;AAC9C,UAAQ,IAAI,iBAAiB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAarC;AACD;AAEA,eAAe,wBAAwB,aAA2C;AAChF,QAAM,eAAe,mBAAAC,QAAK,QAAQ,WAAW;AAC7C,QAAM,WAAW,MAAM,qBAAqB;AAC5C,QAAM,WAAW,SAAS,KAAK,WAAS,mBAAAA,QAAK,QAAQ,MAAM,IAAI,MAAM,YAAY,KAAK;AACtF,MAAI,CAAC,UAAU;AACb,UAAM,6BAA6B,QAAQ;AAC3C,UAAM,QAAQ,MAAM,mBAAmB,YAAY;AACnD,YAAQ,IAAI,kBAAkB,MAAM,IAAI,KAAK,MAAM,IAAI,GAAG;AAC1D,WAAO;AAAA,EACT;AACA,MAAI,CAAC,SAAS,WAAW;AACvB,UAAM,YAAY,MAAM,uBAAuB,SAAS,EAAE;AAC1D,YAAQ,IAAI,sBAAsB,UAAU,IAAI,KAAK,UAAU,IAAI,GAAG;AACtE,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,eAAe,oBAAsC;AACnD,QAAM,SAAS,MAAM,eAAe,gBAAgB,EAAE,MAAM,MAAM,IAAI;AACtE,MAAI,QAAQ,OAAO;AACjB,WAAO;AAAA,EACT;AACA,QAAM,YAAY,MAAM,eAAe,UAAU,EAAE,MAAM,MAAM,MAAM;AACrE,SAAO,QAAQ,WAAW,KAAK;AACjC;AAEA,SAAS,wBAAwB,SAA0B;AACzD,MAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,WAAO;AAAA,EACT;AACA,QAAM,SAAS;AACf,QAAM,OAAO,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO;AAC7D,QAAM,SAAS,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS;AACnE,MAAI,SAAS,QAAQ,QAAQ;AAC3B,WAAO,QAAQ,IAAI,YAAY,MAAM;AAAA,EACvC;AACA,MAAI,SAAS,MAAM;AACjB,WAAO,QAAQ,IAAI;AAAA,EACrB;AACA,MAAI,QAAQ;AACV,WAAO,UAAU,MAAM;AAAA,EACzB;AACA,SAAO;AACT;AAEA,eAAe,eAAe,SAA4C;AACxE,MAAI,CAAC,QAAQ,kBAAkB;AAC7B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,MAAI,mBAAuC;AAC3C,MAAI,QAAQ,aAAa;AACvB,uBAAmB,MAAM,wBAAwB,QAAQ,WAAW;AAAA,EACtE;AAEA,QAAM,YAAY,IAAI,eAAe;AACrC,QAAM,UAAU,WAAW;AAAA,IACzB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS,QAAQ;AAAA,EACnB,CAAC;AAED,QAAM,SAAS,qBAAqB;AAAA,IAClC,cAAc,MAAM;AAAA,IACpB,cAAc,MAAM,qBAAqB;AAAA,IACzC,gBAAgB,CAAC,OAAe,uBAAuB,EAAE;AAAA,IACzD,cAAc,MAAM,kBAAkB;AAAA,IACtC,qBAAqB,MAAM,kBAAkB,MAAM;AAAA,EACrD,CAAC;AAED,QAAM,OAAO,qBAAqB;AAAA,IAChC,uBAAuB;AAAA,IACvB,kBAAkB,QAAQ;AAAA,EAC5B,CAAC;AAED,QAAM,SAAS,OAAO,UAAU;AAChC,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,OAAO,QAAQ,EAAE,MAAM,MAAM,MAAS;AAC5C,UAAM,UAAU,KAAK,EAAE,MAAM,MAAM,MAAS;AAC5C,UAAM,IAAI,MAAM,OAAO,aAAa,kCAAkC;AAAA,EACxE;AAEA,QAAM,WAAW,OAAO,cAAc,IAAI,OAAO,WAAW,KAAK;AACjE,QAAM,WAAW,MAAM,qBAAqB,EAAE,MAAM,MAAM,CAAC,CAAkB;AAC7E,UAAQ,IAAI,iCAAiC,QAAQ,EAAE;AACvD,UAAQ,IAAI,mBAAmB,OAAO,UAAU,EAAE;AAClD,MAAI,kBAAkB;AACpB,YAAQ,IAAI,oBAAoB,iBAAiB,IAAI,KAAK,iBAAiB,EAAE,GAAG;AAAA,EAClF;AACA,UAAQ,IAAI,uBAAuB,SAAS,MAAM,EAAE;AACpD,UAAQ,IAAI,iCAAiC;AAE7C,MAAI,WAAW;AACf,MAAI,cAAmC;AAEvC,QAAM,OAAO,OAAO,QAAgB,aAAqB;AACvD,QAAI,UAAU;AACZ;AAAA,IACF;AACA,eAAW;AACX,YAAQ,WAAW;AACnB,YAAQ,IAAI,oBAAoB,MAAM,MAAM;AAC5C,UAAM,OAAO,QAAQ,EAAE,MAAM,CAAC,UAAU;AACtC,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,cAAQ,MAAM,2CAA2C,OAAO,EAAE;AAAA,IACpE,CAAC;AACD,UAAM,UAAU,KAAK,EAAE,MAAM,CAAC,UAAU;AACtC,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,cAAQ,MAAM,sCAAsC,OAAO,EAAE;AAAA,IAC/D,CAAC;AACD,kBAAc;AAAA,EAChB;AAEA,QAAM,WAAW,MAAM;AACrB,SAAK,KAAK,UAAU,CAAC;AAAA,EACvB;AACA,QAAM,YAAY,MAAM;AACtB,SAAK,KAAK,WAAW,CAAC;AAAA,EACxB;AACA,QAAM,kBAAkB,CAAC,YAAqB;AAC5C,UAAM,SAAS,wBAAwB,OAAO;AAC9C,UAAM,SAAS,SAAS,KAAK,MAAM,MAAM;AACzC,YAAQ,MAAM,uCAAuC,MAAM,GAAG;AAC9D,SAAK,KAAK,qBAAqB,CAAC;AAAA,EAClC;AAEA,UAAQ,KAAK,UAAU,QAAQ;AAC/B,UAAQ,KAAK,WAAW,SAAS;AACjC,YAAU,KAAK,wBAAwB,eAAe;AAEtD,MAAI;AACF,UAAM,IAAI,QAAc,CAAC,YAAY;AACnC,oBAAc;AAAA,IAChB,CAAC;AAAA,EACH,UAAE;AACA,YAAQ,IAAI,UAAU,QAAQ;AAC9B,YAAQ,IAAI,WAAW,SAAS;AAChC,cAAU,IAAI,wBAAwB,eAAe;AAAA,EACvD;AACF;AAEA,eAAsB,oBAAoB,MAAgB,SAAgC;AACxF,QAAM,QAAQ,KAAK,OAAO,SAAO,IAAI,WAAW,GAAG,CAAC;AACpD,QAAM,SAAS,WAAW,IAAI;AAC9B,QAAM,MAAM,OAAO,CAAC;AAEpB,MAAI,CAAC,OAAO,QAAQ,OAAO,QAAQ,KAAK,QAAQ,OAAO,IAAI,GAAG;AAC5D,oBAAgB,OAAO;AACvB;AAAA,EACF;AAEA,UAAQ,KAAK;AAAA,IACX,KAAK,SACL;AACE,YAAM,YACJ,gBAAgB,OAAO,sBAAsB,KAC1C,gBAAgB,OAAO,aAAa;AACzC,YAAM,WAAW,QAAQ,IAAI,6BAA6B,KAAK,KAAK;AACpE,YAAM,mBAAoB,aAAa,UAAU,KAAK,KAAM,YAAY;AACxE,YAAM,cACJ,gBAAgB,OAAO,gBAAgB,KACpC,gBAAgB,OAAO,WAAW,KAClC;AAEL,YAAM,eAAe;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAAA,IACA;AACE,sBAAgB,OAAO;AACvB;AAAA,EACJ;AACF;;;ASxNA,IAAM,UAAU,OACZ,UACA;AACJ,IAAI,yBAA+C;AAEnD,eAAe,wBAAuC;AACpD,MAAI,wBAAwB;AAC1B,WAAO;AAAA,EACT;AAEA,4BAA0B,YAAY;AACpC,UAAM,mBAAmB,eAAe,CAAC;AACzC,UAAM,WAAW,MAAM,sBAAsB;AAC7C,QAAI,SAAS,UAAU,WAAW,yBAAyB;AACzD,YAAM,6BAA6B,CAAC,CAAC;AAAA,IACvC;AAEA,UAAM,QAAQ,MAAM,YAAY;AAChC,QAAI,MAAM,UAAU,WAAW,YAAY;AACzC,YAAM,IAAI;AAAA,QACR,8CAA8C,MAAM,UAAU,MAAM;AAAA,MACtE;AAAA,IACF;AAAA,EACF,GAAG,EAAE,MAAM,CAAC,UAAU;AACpB,6BAAyB;AACzB,UAAM;AAAA,EACR,CAAC;AAED,SAAO;AACT;AAEA,SAAS,YAAkB;AACzB,UAAQ,IAAI,iBAAiB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAkCrC;AACD;AAEA,SAASC,SAAQ,MAAgB,MAAuB;AACtD,SAAO,KAAK,SAAS,IAAI;AAC3B;AAEA,SAASC,YAAW,MAA0B;AAC5C,SAAO,KAAK,OAAO,SAAO,CAAC,IAAI,WAAW,GAAG,CAAC;AAChD;AAEA,SAAS,eAAe,OAAwC;AAC9D,MAAI,MAAM,SAAS,eAAe,EAAG,QAAO;AAC5C,QAAM,WAAW,MAAM,KAAK,UAAQ,KAAK,WAAW,UAAU,CAAC;AAC/D,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,QAAQ,SAAS,MAAM,GAAG,EAAE,CAAC;AACnC,MAAI,UAAU,aAAa,UAAU,UAAU;AAC7C,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,IAAM,oCAAoC;AAC1C,IAAM,6BAA6B;AAEnC,SAAS,iBAAiB,OAAiB,MAA6B;AACtE,QAAM,WAAW,MAAM,KAAK,UAAQ,KAAK,WAAW,GAAG,IAAI,GAAG,CAAC;AAC/D,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AACA,QAAM,MAAM,SAAS,MAAM,GAAG,IAAI,IAAI,MAAM;AAC5C,QAAM,QAAQ,OAAO,WAAW,GAAG;AACnC,SAAO,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO;AACjD;AAEA,SAAS,iBAAiB,OAAiB,MAA6B;AACtE,QAAM,WAAW,MAAM,KAAK,UAAQ,KAAK,WAAW,GAAG,IAAI,GAAG,CAAC;AAC/D,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AACA,QAAM,MAAM,SAAS,MAAM,GAAG,IAAI,IAAI,MAAM;AAC5C,QAAM,QAAQ,OAAO,SAAS,KAAK,EAAE;AACrC,SAAO,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO;AACjD;AAEA,SAAS,mBAAmB,MAAc,aAAqC;AAC7E,MAAI,eAAe,YAAY,KAAK,KAAK,gBAAgB,MAAM;AAC7D,WAAO,GAAG,WAAW,KAAK,IAAI;AAAA,EAChC;AACA,SAAO;AACT;AAEA,SAAS,YAAY,OAAuB;AAC1C,SAAO,MAAM,QAAQ,UAAU,UAAQ,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,EAAE,YAAY,CAAC;AACnG;AAEA,SAAS,gBAAgB,OAAsC;AAC7D,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO;AACzC,MAAI,OAAO,SAAS,eAAe,KAAK,gBAAgB;AACtD,WAAO,IAAI,KAAK,eAAe,QAAW,EAAE,OAAO,SAAS,KAAK,UAAU,CAAC,EAAE,OAAO,IAAI;AAAA,EAC3F;AACA,SAAO,KAAK,mBAAmB;AACjC;AAEA,SAAS,mBAAmB,OAAsC;AAChE,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,MAAI,OAAO,MAAM,MAAM,EAAG,QAAO;AACjC,QAAM,SAAS,SAAS,KAAK,IAAI;AACjC,QAAM,QAAQ,KAAK,IAAI,MAAM;AAC7B,MAAI,QAAQ,KAAQ;AAClB,WAAO;AAAA,EACT;AACA,QAAM,UAAU,KAAK,MAAM,QAAQ,GAAM;AACzC,MAAI,UAAU,IAAI;AAChB,WAAO,UAAU,IAAI,MAAM,OAAO,MAAM,GAAG,OAAO;AAAA,EACpD;AACA,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,MAAI,QAAQ,IAAI;AACd,WAAO,UAAU,IAAI,MAAM,KAAK,MAAM,GAAG,KAAK;AAAA,EAChD;AACA,QAAM,OAAO,KAAK,MAAM,QAAQ,EAAE;AAClC,SAAO,UAAU,IAAI,MAAM,IAAI,MAAM,GAAG,IAAI;AAC9C;AAEA,SAAS,oBAAoB,eAAmD;AAC9E,MAAI,CAAC,iBAAiB,CAAC,MAAM,QAAQ,aAAa,KAAK,cAAc,WAAW,GAAG;AACjF,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,cACX,IAAI,SAAO;AACV,QAAI,CAAC,IAAK,QAAO;AACjB,UAAM,OAAO,IAAI,SAAS,IAAI;AAC9B,QAAI,CAAC,KAAM,QAAO;AAClB,WAAO,IAAI,OAAO,GAAG,IAAI,KAAK,IAAI,IAAI,MAAM;AAAA,EAC9C,CAAC,EACA,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC;AACpD,SAAO,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI;AAC/C;AAEA,SAAS,kBAAkB,eAAuC;AAChE,MAAI,OAAO,kBAAkB,YAAY,OAAO,MAAM,aAAa,GAAG;AACpE,WAAO;AAAA,EACT;AACA,MAAI,iBAAiB,MAAM;AACzB,UAAM,OAAO,gBAAgB;AAC7B,UAAM,UAAU,KAAK,MAAM,OAAO,EAAE,IAAI;AACxC,UAAM,UAAU,OAAO,UAAU,OAAO,IAAI,QAAQ,QAAQ,CAAC,IAAI,QAAQ,QAAQ,CAAC;AAClF,WAAO,GAAG,QAAQ,QAAQ,QAAQ,EAAE,CAAC;AAAA,EACvC;AACA,MAAI,iBAAiB,IAAI;AACvB,UAAM,QAAQ,gBAAgB;AAC9B,UAAM,UAAU,KAAK,MAAM,QAAQ,EAAE,IAAI;AACzC,UAAM,UAAU,OAAO,UAAU,OAAO,IAAI,QAAQ,QAAQ,CAAC,IAAI,QAAQ,QAAQ,CAAC;AAClF,WAAO,GAAG,QAAQ,QAAQ,QAAQ,EAAE,CAAC;AAAA,EACvC;AACA,QAAM,UAAU,KAAK,MAAM,aAAa;AACxC,SAAO,GAAG,OAAO;AACnB;AAEA,SAAS,0BAA0B,SAAwC;AACzE,MAAI,OAAO,YAAY,YAAY,OAAO,MAAM,OAAO,GAAG;AACxD,WAAO;AAAA,EACT;AACA,MAAI,WAAW,GAAG;AAChB,WAAO;AAAA,EACT;AACA,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,MAAI,YAAY,GAAG;AACjB,WAAO,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,CAAC,CAAC;AAAA,EAC5C;AACA,MAAI,UAAU,IAAI;AAChB,WAAO,GAAG,OAAO;AAAA,EACnB;AACA,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,QAAM,mBAAmB,UAAU;AACnC,MAAI,QAAQ,IAAI;AACd,WAAO,mBAAmB,GAAG,KAAK,KAAK,gBAAgB,MAAM,GAAG,KAAK;AAAA,EACvE;AACA,QAAM,OAAO,KAAK,MAAM,QAAQ,EAAE;AAClC,QAAM,iBAAiB,QAAQ;AAC/B,SAAO,iBAAiB,GAAG,IAAI,KAAK,cAAc,MAAM,GAAG,IAAI;AACjE;AAEA,SAAS,gBAAgB,QAAwC;AAC/D,MAAI,OAAO,UAAU;AACnB,WAAO,mBAAmB,OAAO,QAAQ,KAAK,OAAO;AAAA,EACvD;AACA,QAAM,eAAe,0BAA0B,OAAO,eAAe;AACrE,MAAI,CAAC,aAAc,QAAO;AAC1B,MAAI,iBAAiB,MAAO,QAAO;AACnC,SAAO,MAAM,YAAY;AAC3B;AAQA,SAAS,kBAAkB,QAA8C;AACvE,QAAM,QAAQ,kBAAkB,OAAO,aAAa,KAAK;AACzD,QAAM,cACJ,OAAO,OAAO,gBAAgB,YAAY,OAAO,SAAS,OAAO,WAAW,IACxE,GAAG,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,OAAO,WAAW,CAAC,CAAC,CAAC,MAC7D;AACN,QAAM,YAAY,gBAAgB,MAAM;AACxC,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,OAAO,YAAY,SAAS,SAAS,KAAK;AAAA,EAC5C;AACF;AAkBA,IAAM,sBAA6C;AAAA,EACjD,WAAW;AAAA,EACX,cAAc;AAAA,EACd,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,eAAe;AACjB;AAEA,SAAS,qBAAqB,OAA+B;AAC3D,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;AAEA,SAAS,2BAA2B,UAAuE;AACzG,MAAI,CAAC,UAAU;AACb,WAAO,EAAE,GAAG,oBAAoB;AAAA,EAClC;AAEA,QAAM,UAAkF;AAAA,IACtF,EAAE,KAAK,WAAW,QAAQ,SAAS,QAAQ;AAAA,IAC3C,EAAE,KAAK,aAAa,QAAQ,SAAS,UAAU;AAAA,EACjD;AAEA,MAAI,UAAiC,EAAE,GAAG,oBAAoB;AAC9D,MAAI,cAAc;AAElB,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,QAAQ;AACjB;AAAA,IACF;AAEA,UAAM,gBAAgB,qBAAqB,MAAM,OAAO,WAAW;AACnE,UAAM,aAAa,kBAAkB,OAAO,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,aAAa,CAAC;AACxF,UAAM,WAAW,kBAAkB;AACnC,UAAM,kBAAkB,qBAAqB,MAAM,OAAO,eAAe;AACzE,UAAM,gBAAgB,qBAAqB,MAAM,OAAO,aAAa;AAErE,QAAI,CAAC,aAAa;AAChB,oBAAc;AACd,gBAAU;AAAA,QACR,WAAW,MAAM;AAAA,QACjB,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,YAAY,QAAQ,YAAY,aAAa,QAAQ,cAAc;AACrE,gBAAU;AAAA,QACR,WAAW,MAAM;AAAA,QACjB,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,CAAC,YAAY,CAAC,QAAQ,YAAY,QAAQ,oBAAoB,MAAM;AACtE,UAAI,oBAAoB,QAAQ,kBAAkB,QAAQ,iBAAiB;AACzE,kBAAU;AAAA,UACR,WAAW,MAAM;AAAA,UACjB,cAAc;AAAA,UACd;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,CAAC,YAAY,CAAC,QAAQ,YAAY,QAAQ,oBAAoB,QAAQ,oBAAoB,MAAM;AAClG,gBAAU;AAAA,QACR,WAAW,MAAM;AAAA,QACjB,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,YAAY,CAAC,QAAQ,UAAU;AACjC,gBAAU;AAAA,QACR,WAAW,MAAM;AAAA,QACjB,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,cAAc,SAA6B;AAClD,QAAM,eAAe,2BAA2B,QAAQ,aAAa,IAAI;AACzE,MAAI,CAAC,QAAQ,SAAS;AACpB,WAAO,EAAE,SAAS,WAAW,MAAM,MAAM,aAAa;AAAA,EACxD;AACA,MAAI,QAAQ,aAAa,oBAAoB;AAC3C,WAAO,EAAE,SAAS,iBAAiB,MAAM,MAAM,aAAa;AAAA,EAC9D;AACA,SAAO,EAAE,SAAS,OAAO,MAAM,MAAM,aAAa;AACpD;AAEA,eAAe,oBACb,SACA,SACA,WACoB;AACpB,MAAI,CAAC,QAAQ,WAAW,QAAQ,aAAa,oBAAoB;AAC/D,WAAO,cAAc,OAAO;AAAA,EAC9B;AAEA,MAAI;AACF,UAAM,WAAW,MAAM,QAAQ;AAAA,MAAmB,QAAQ;AAAA,MAAM,CAAC,QAC/D,sBAAsB,KAAK,EAAE,UAAU,CAAC;AAAA,IAC1C;AACA,QAAI,CAAC,UAAU;AACb,YAAM,eAAe,2BAA2B,QAAQ,aAAa,IAAI;AACzE,aAAO,EAAE,SAAS,OAAO,MAAM,MAAM,aAAa;AAAA,IACpD;AACA,UAAM,OAAuB,CAAC;AAC9B,QAAI,SAAS,SAAS;AACpB,YAAM,MAAM,kBAAkB,SAAS,OAAO;AAC9C,UAAI,IAAK,MAAK,KAAK,GAAG;AAAA,IACxB;AACA,QAAI,SAAS,WAAW;AACtB,YAAM,MAAM,kBAAkB,SAAS,SAAS;AAChD,UAAI,IAAK,MAAK,KAAK,GAAG;AAAA,IACxB;AACA,UAAM,aAAa,eAAe,QAAQ;AAC1C,UAAM,UAAU,OAAO,eAAe,WAClC,GAAG,KAAK,MAAM,UAAU,CAAC,MACzB;AACJ,WAAO,EAAE,SAAS,MAAM,KAAK,SAAS,IAAI,OAAO,MAAM,cAAc,2BAA2B,QAAQ,EAAE;AAAA,EAC5G,QAAQ;AACN,WAAO,cAAc,OAAO;AAAA,EAC9B;AACF;AAOA,SAAS,0BAA0B,GAAsB,GAA8B;AACrF,MAAI,EAAE,aAAa,iBAAiB,EAAE,aAAa,cAAc;AAC/D,WAAO,EAAE,aAAa,eAAe,EAAE,aAAa;AAAA,EACtD;AACA,QAAM,SAAS,EAAE,aAAa,mBAAmB,OAAO;AACxD,QAAM,SAAS,EAAE,aAAa,mBAAmB,OAAO;AACxD,MAAI,WAAW,QAAQ;AACrB,WAAO,SAAS;AAAA,EAClB;AACA,SAAO,EAAE,QAAQ,KAAK,cAAc,EAAE,QAAQ,IAAI;AACpD;AAEA,SAAS,yBACP,UACA,UACA,oBACA,gBACA,iBAC0B;AAC1B,QAAM,aAAa,SAChB,OAAO,aAAW,QAAQ,SAAS,sBAAsB,QAAQ,WAAW,CAAC,QAAQ,aAAa,kBAAkB,EACpH,IAAI,cAAY;AAAA,IACf;AAAA,IACA,cAAc,SAAS,IAAI,QAAQ,IAAI,GAAG,gBAAgB,2BAA2B,QAAQ,aAAa,IAAI;AAAA,EAChH,EAAE;AAEJ,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB,WACpB,OAAO,eAAa,UAAU,aAAa,YAAY,UAAU,aAAa,eAAe,eAAe,EAC5G,KAAK,yBAAyB;AACjC,MAAI,WAAW,eAAe,CAAC,KAAK;AAEpC,MAAI,CAAC,UAAU;AACb,eAAW,WACR,OAAO,eAAa,UAAU,aAAa,QAAQ,EACnD,KAAK,yBAAyB,EAAE,CAAC,KAAK;AAAA,EAC3C;AAEA,MAAI,CAAC,UAAU;AACb,eAAW,WACR,OAAO,eAAa,CAAC,UAAU,aAAa,QAAQ,EACpD,KAAK,CAAC,GAAG,MAAM;AACd,YAAM,SAAS,EAAE,aAAa,mBAAmB,OAAO;AACxD,YAAM,SAAS,EAAE,aAAa,mBAAmB,OAAO;AACxD,UAAI,WAAW,QAAQ;AACrB,eAAO,SAAS;AAAA,MAClB;AACA,aAAO,EAAE,QAAQ,KAAK,cAAc,EAAE,QAAQ,IAAI;AAAA,IACpD,CAAC,EAAE,CAAC,KAAK;AAAA,EACb;AAEA,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,aAAa,YAAY,eAAe,UAAU;AAC7D,QAAI,SAAS,aAAa,eAAe,eAAe,cAAc;AACpE,aAAO;AAAA,IACT;AACA,QAAI,SAAS,aAAa,iBAAiB,eAAe,cAAc;AACtE,YAAM,gBAAgB,SAAS,aAAa,mBAAmB,OAAO;AACtE,YAAM,eAAe,eAAe,mBAAmB,OAAO;AAC9D,UAAI,iBAAiB,cAAc;AACjC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,WAAW,SAA0B;AAC5C,QAAM,WAAW,QAAQ;AACzB,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AACA,QAAM,QAAkB,CAAC;AACzB,MAAI,SAAS,UAAU;AACrB,UAAM,KAAK,YAAY,SAAS,QAAQ,CAAC;AAAA,EAC3C;AACA,QAAM,QAAQ,SAAS,cAAc;AACrC,MAAI,OAAO;AACT,UAAM,YAAY,gBAAgB,KAAK;AACvC,QAAI,WAAW;AACb,YAAM,KAAK,SAAS,SAAS,EAAE;AAAA,IACjC;AAAA,EACF;AACA,SAAO,MAAM,KAAK,QAAK,KAAK;AAC9B;AAEA,SAAS,WAAW,SAA0B;AAC5C,QAAM,WAAW,QAAQ;AACzB,QAAM,WAAW,mBAAmB,UAAU,aAAa;AAC3D,MAAI,SAAU,QAAO;AACrB,MAAI,UAAU,cAAe,QAAO,SAAS;AAC7C,SAAO;AACT;AAEA,SAAS,oBAAoB,SAAkB,OAAgC;AAC7E,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,OAAO,WAAW,OAAO;AAC/B,QAAM,OAAO,oBAAoB,QAAQ,UAAU,aAAa,KAAK;AACrE,QAAM,OAAO,WAAW,OAAO;AAC/B,QAAM,YAAY,QAAQ,iBAAiB,QAAQ,eAAe;AAElE,QAAM,UAAmD;AAAA,IACvD,EAAE,OAAO,SAAS,OAAO,MAAM;AAAA,IAC/B,EAAE,OAAO,QAAQ,OAAO,KAAK;AAAA,IAC7B,EAAE,OAAO,QAAQ,OAAO,KAAK;AAAA,IAC7B,EAAE,OAAO,QAAQ,OAAO,KAAK;AAAA,EAC/B;AACA,MAAI,WAAW;AACb,YAAQ,KAAK,EAAE,OAAO,aAAa,OAAO,UAAU,CAAC;AAAA,EACvD;AACA,QAAM,MAAM,KAAK,IAAI,GAAG,QAAQ,IAAI,WAAS,MAAM,MAAM,MAAM,CAAC;AAChE,aAAW,SAAS,SAAS;AAC3B,YAAQ,IAAI,KAAK,MAAM,MAAM,OAAO,GAAG,CAAC,MAAM,MAAM,KAAK,EAAE;AAAA,EAC7D;AAEA,MAAI,OAAO;AACT,QAAI,MAAM,QAAQ,MAAM,KAAK,SAAS,GAAG;AACvC,YAAM,WAAW,KAAK,IAAI,GAAG,MAAM,KAAK,IAAI,SAAO,IAAI,MAAM,MAAM,CAAC;AACpE,YAAM,UAAU,KAAK,IAAI,GAAG,MAAM,KAAK,IAAI,SAAO,IAAI,KAAK,MAAM,CAAC;AAClE,cAAQ,IAAI,gBAAgB;AAC5B,iBAAW,OAAO,MAAM,MAAM;AAC5B,cAAM,YAAY,IAAI,QAAQ,KAAK,IAAI,KAAK,KAAK;AACjD,gBAAQ,IAAI,OAAO,IAAI,MAAM,OAAO,QAAQ,CAAC,KAAK,IAAI,KAAK,SAAS,OAAO,CAAC,GAAG,SAAS,EAAE;AAAA,MAC5F;AACA;AAAA,IACF;AACA,YAAQ,IAAI,kBAAkB,MAAM,OAAO,EAAE;AAAA,EAC/C;AACF;AAEA,eAAe,mBACb,OACA,OACA,IACc;AACd,QAAM,UAAe,IAAI,MAAM,MAAM,MAAM;AAC3C,QAAM,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,MAAM,MAAM,CAAC;AAC7D,MAAI,YAAY;AAEhB,QAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,YAAY,GAAG,YAAY;AAC9D,WAAO,MAAM;AACX,YAAM,UAAU;AAChB,UAAI,WAAW,MAAM,QAAQ;AAC3B;AAAA,MACF;AACA,cAAQ,OAAO,IAAI,MAAM,GAAG,MAAM,OAAO,GAAG,OAAO;AAAA,IACrD;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,IAAI,OAAO;AACzB,SAAO;AACT;AAEA,SAAS,uBAAuB,OAAiB,mBAAmC;AAClF,QAAM,oBAAoB,iBAAiB,OAAO,aAAa;AAC/D,MAAI,sBAAsB,MAAM;AAC9B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,MAAM,iBAAiB,GAAG;AACnC,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACtE;AACA,MAAI,oBAAoB,MAAM,oBAAoB,KAAK;AACrD,UAAM,IAAI,MAAM,6DAA6D;AAAA,EAC/E;AACA,SAAO,KAAK,MAAM,iBAAiB;AACrC;AAEA,SAAS,6BAA6B,OAAyB;AAC7D,QAAM,mBAAmB,iBAAiB,OAAO,YAAY;AAC7D,MAAI,qBAAqB,MAAM;AAC7B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,MAAM,gBAAgB,KAAK,oBAAoB,GAAG;AAC3D,UAAM,IAAI,MAAM,6EAA6E;AAAA,EAC/F;AACA,SAAO;AACT;AAEA,eAAe,gBACb,SACA,UACA,WACiC;AACjC,QAAM,WAAW,oBAAI,IAAuB;AAC5C,QAAM,WAAW,OAAO,SAAS,QAAQ,IAAI,kCAAkC,KAAK,EAAE;AACtF,QAAM,QAAQ,OAAO,SAAS,QAAQ,KAAK,WAAW,IAAI,WAAW;AACrE,QAAM,UAAU,MAAM;AAAA,IAAmB;AAAA,IAAU;AAAA,IAAO,CAAC,YACzD,oBAAoB,SAAS,SAAS,SAAS;AAAA,EACjD;AACA,aAAW,CAAC,OAAO,OAAO,KAAK,SAAS,QAAQ,GAAG;AACjD,aAAS,IAAI,QAAQ,MAAM,QAAQ,KAAK,CAAC;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,eAAe,gBACb,SACA,SAI+F;AAC/F,QAAM,WAAW,MAAM,QAAQ,aAAa;AAC5C,MAAI,CAAC,SAAS,QAAQ;AACpB,WAAO,EAAE,UAAU,OAAO,SAAS,sBAAsB,QAAQ,MAAM,QAAQ,KAAK;AAAA,EACtF;AAEA,QAAM,UAAU,MAAM,QAAQ,kBAAkB;AAChD,MAAI,CAAC,QAAQ,MAAM;AACjB,WAAO,EAAE,UAAU,OAAO,SAAS,sBAAsB,QAAQ,MAAM,QAAQ,KAAK;AAAA,EACtF;AAEA,QAAM,YAAY,mBAAmB;AACrC,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,oFAAoF;AAAA,EACtG;AAEA,QAAM,WAAW,MAAM,gBAAgB,SAAS,UAAU,SAAS;AACnE,QAAM,iBAAiB,SAAS,KAAK,aAAW,QAAQ,SAAS,QAAQ,IAAI;AAC7E,MAAI,CAAC,gBAAgB;AACnB,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS,oBAAoB,QAAQ,IAAI;AAAA,MACzC,QAAQ,QAAQ;AAAA,MAChB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,eAAe,SAAS,IAAI,QAAQ,IAAI,GAAG,gBAAgB,2BAA2B,eAAe,aAAa,IAAI;AAC5H,MAAI,CAAC,aAAa,UAAU;AAC1B,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS,iCAAiC,QAAQ,IAAI;AAAA,MACtD,QAAQ,QAAQ;AAAA,MAChB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,aAAa,eAAe,QAAQ,WAAW;AACjD,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS,IAAI,QAAQ,IAAI,QAAQ,KAAK,MAAM,aAAa,YAAY,CAAC,sBAAsB,QAAQ,SAAS;AAAA,MAC7G,QAAQ,QAAQ;AAAA,MAChB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,QAAQ;AAAA,EACV;AACA,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS,uCAAuC,QAAQ,IAAI,QAAQ,KAAK,MAAM,aAAa,YAAY,CAAC;AAAA,MACzG,QAAQ,QAAQ;AAAA,MAChB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,iBAAiB,UAAU,aAAa,WAAW,GAAG,KAAK,MAAM,UAAU,aAAa,YAAY,CAAC,MAAM;AACjH,MAAI,QAAQ,QAAQ;AAClB,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS,2BAA2B,QAAQ,IAAI,MAAM,KAAK,MAAM,aAAa,YAAY,CAAC,UAAU,UAAU,QAAQ,IAAI,MAAM,cAAc;AAAA,MAC/I,QAAQ,QAAQ;AAAA,MAChB,QAAQ,UAAU,QAAQ;AAAA,IAC5B;AAAA,EACF;AAEA,QAAM,QAAQ,gBAAgB,UAAU,QAAQ,IAAI;AACpD,SAAO;AAAA,IACL,UAAU;AAAA,IACV,SAAS,gBAAgB,QAAQ,IAAI,MAAM,KAAK,MAAM,aAAa,YAAY,CAAC,UAAU,UAAU,QAAQ,IAAI,MAAM,cAAc;AAAA,IACpI,QAAQ,QAAQ;AAAA,IAChB,QAAQ,UAAU,QAAQ;AAAA,EAC5B;AACF;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AACvD;AAEA,eAAe,cAAc,MAA+B;AAC1D,QAAM,QAAQ,KAAK,OAAO,SAAO,IAAI,WAAW,GAAG,CAAC;AACpD,QAAM,SAASA,YAAW,IAAI;AAC9B,QAAM,MAAM,OAAO,CAAC;AAEpB,MAAI,CAAC,OAAOD,SAAQ,OAAO,QAAQ,KAAKA,SAAQ,OAAO,IAAI,GAAG;AAC5D,cAAU;AACV;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,eAAe;AAEnC,UAAQ,KAAK;AAAA,IACX,KAAK,QAAQ;AACX,YAAM,WAAW,MAAM,QAAQ,aAAa;AAC5C,YAAM,UAAU,MAAM,QAAQ,kBAAkB;AAChD,UAAI,CAAC,SAAS,QAAQ;AACpB,gBAAQ,IAAI,oBAAoB;AAChC;AAAA,MACF;AACA,YAAM,UAAUA,SAAQ,OAAO,WAAW;AAC1C,YAAM,YAAY,CAACA,SAAQ,OAAO,YAAY;AAC9C,UAAI,WAA0C;AAC9C,UAAI,WAAW;AACb,cAAM,YAAY,mBAAmB;AACrC,YAAI,CAAC,WAAW;AACd,qBAAW,oBAAI,IAAI;AACnB,qBAAW,WAAW,UAAU;AAC9B,qBAAS,IAAI,QAAQ,MAAM;AAAA,cACzB,SAAS;AAAA,cACT,MAAM;AAAA,cACN,cAAc,2BAA2B,QAAQ,aAAa,IAAI;AAAA,YACpE,CAAC;AAAA,UACH;AAAA,QACF,OAAO;AACL,qBAAW,MAAM,gBAAgB,SAAS,UAAU,SAAS;AAAA,QAC/D;AAAA,MACF;AACA,iBAAW,CAAC,OAAO,OAAO,KAAK,SAAS,QAAQ,GAAG;AACjD,cAAM,SAAS,QAAQ,SAAS,QAAQ,OAAO,MAAM;AACrD,cAAM,QAAQ,mBAAmB,QAAQ,MAAM,QAAQ,WAAW;AAClE,YAAI,QAAQ,GAAG;AACb,kBAAQ,IAAI,EAAE;AAAA,QAChB;AACA,cAAM,cAAc,QAAQ,SAAS,QAAQ,OAAO,cAAc;AAClE,gBAAQ,IAAI,GAAG,MAAM,IAAI,KAAK,GAAG,WAAW,EAAE;AAC9C,YAAI,QAAS;AACb,cAAM,QAAQ,UAAU,IAAI,QAAQ,IAAI,KAAK;AAC7C,4BAAoB,SAAS,KAAK;AAAA,MACpC;AACA;AAAA,IACF;AAAA,IACA,KAAK,WAAW;AACd,YAAM,UAAU,MAAM,QAAQ,kBAAkB;AAChD,UAAI,CAAC,QAAQ,MAAM;AACjB,gBAAQ,IAAI,oBAAoB;AAChC;AAAA,MACF;AACA,cAAQ,IAAI,QAAQ,IAAI;AACxB;AAAA,IACF;AAAA,IACA,KAAK,OAAO;AACV,YAAM,OAAO,OAAO,CAAC;AACrB,UAAI,CAAC,MAAM;AACT,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AACA,YAAM,6BAA6B,OAAO;AAC1C,UAAI,CAACA,SAAQ,OAAO,cAAc,GAAG;AACnC,cAAM,YAAY,iBAAiB,eAAe,KAAK,CAAC;AACxD,cAAM,cAAc,SAAS;AAAA,MAC/B;AACA,YAAM,UAAU,MAAM,QAAQ,cAAc,IAAI;AAChD,YAAM,QAAQ,UAAU,mBAAmB,QAAQ,MAAM,QAAQ,WAAW,IAAI;AAChF,cAAQ,IAAI,oBAAoB,KAAK,EAAE;AACvC;AAAA,IACF;AAAA,IACA,KAAK,WAAW;AACd,YAAM,OAAO,OAAO,CAAC;AACrB,UAAI,CAAC,MAAM;AACT,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AACA,UAAI,CAACA,SAAQ,OAAO,cAAc,GAAG;AACnC,cAAM,YAAY,iBAAiB,eAAe,KAAK,CAAC;AACxD,cAAM,cAAc,SAAS;AAAA,MAC/B;AACA,YAAM,UAAU,MAAM,QAAQ,mBAAmB,IAAI;AACrD,YAAM,QAAQ,mBAAmB,QAAQ,MAAM,QAAQ,WAAW;AAClE,cAAQ,IAAI,sBAAsB,KAAK,EAAE;AACzC;AAAA,IACF;AAAA,IACA,KAAK,UAAU;AACb,YAAM,OAAO,OAAO,CAAC;AACrB,UAAI,CAAC,MAAM;AACT,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AACA,YAAM,QAAQ,gBAAgB,IAAI;AAClC,cAAQ,IAAI,wBAAwB,IAAI,EAAE;AAC1C;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,KAAK,aAAa;AAChB,YAAM,QAAQA,SAAQ,OAAO,SAAS;AACtC,YAAM,SAASA,SAAQ,OAAO,WAAW;AACzC,YAAM,WAAW,MAAM,0BAA0B,EAAE,MAAM,MAAM,IAAI;AACnE,YAAM,oBACJ,OAAO,UAAU,oBAAoB,YAAY,OAAO,SAAS,SAAS,eAAe,IACrF,KAAK,MAAM,SAAS,eAAe,IACnC;AACN,YAAM,YAAY,uBAAuB,OAAO,iBAAiB;AACjE,YAAM,kBAAkB,6BAA6B,KAAK;AAE1D,UAAI,OAAO;AACT,gBAAQ,IAAI,8BAA8B,SAAS,gBAAgB,eAAe,IAAI,SAAS,eAAe,EAAE,EAAE;AAClH,YAAI,OAAO;AACX,gBAAQ,GAAG,UAAU,MAAM;AACzB,iBAAO;AAAA,QACT,CAAC;AACD,gBAAQ,GAAG,WAAW,MAAM;AAC1B,iBAAO;AAAA,QACT,CAAC;AAED,eAAO,CAAC,MAAM;AACZ,gBAAME,UAAS,MAAM,gBAAgB,SAAS,EAAE,WAAW,OAAO,CAAC;AACnE,kBAAQ,IAAIA,QAAO,OAAO;AAC1B,cAAI,MAAM;AACR;AAAA,UACF;AACA,gBAAM,MAAM,kBAAkB,GAAI;AAAA,QACpC;AACA,gBAAQ,IAAI,0BAA0B;AACtC;AAAA,MACF;AAEA,YAAM,SAAS,MAAM,gBAAgB,SAAS,EAAE,WAAW,OAAO,CAAC;AACnE,cAAQ,IAAI,OAAO,OAAO;AAC1B;AAAA,IACF;AAAA,IACA,KAAK,UAAU;AACb,YAAM,OAAO,OAAO,CAAC;AACrB,UAAI,CAAC,MAAM;AACT,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AACA,YAAM,QAAQ,cAAc,IAAI;AAChC,cAAQ,IAAI,oBAAoB,IAAI,EAAE;AACtC;AAAA,IACF;AAAA,IACA,KAAK,UAAU;AACb,YAAM,OAAO,OAAO,CAAC;AACrB,YAAM,KAAK,OAAO,CAAC;AACnB,UAAI,CAAC,QAAQ,CAAC,IAAI;AAChB,cAAM,IAAI,MAAM,yCAAyC;AAAA,MAC3D;AACA,YAAM,QAAQ,cAAc,MAAM,EAAE;AACpC,cAAQ,IAAI,oBAAoB,IAAI,OAAO,EAAE,EAAE;AAC/C;AAAA,IACF;AAAA,IACA;AACE,gBAAU;AACV;AAAA,EACJ;AACF;AAEA,eAAe,cAAc,MAA+B;AAC1D,QAAM,QAAQ,KAAK,OAAO,SAAO,IAAI,WAAW,GAAG,CAAC;AACpD,QAAM,SAASD,YAAW,IAAI;AAC9B,QAAM,MAAM,OAAO,CAAC;AAEpB,MAAI,CAAC,OAAOD,SAAQ,OAAO,QAAQ,KAAKA,SAAQ,OAAO,IAAI,GAAG;AAC5D,cAAU;AACV;AAAA,EACF;AAEA,UAAQ,KAAK;AAAA,IACX,KAAK,UAAU;AACb,YAAM,eAAeA,SAAQ,OAAO,WAAW;AAC/C,YAAM,SAAS,MAAM,eAAe,UAAU,EAAE,aAAa,CAAC;AAC9D,cAAQ,IAAI,SAAS,OAAO,IAAI,EAAE;AAClC,cAAQ,IAAI,UAAU,OAAO,KAAK,EAAE;AACpC,UAAI,OAAO,iBAAiB,MAAM;AAChC,gBAAQ,IAAI,kBAAkB,OAAO,YAAY,EAAE;AAAA,MACrD;AACA,UAAI,OAAO,sBAAsB,MAAM;AACrC,gBAAQ,IAAI,uBAAuB,OAAO,iBAAiB,EAAE;AAAA,MAC/D;AACA,UAAI,OAAO,eAAe;AACxB,gBAAQ,IAAI,UAAU,OAAO,aAAa,EAAE;AAAA,MAC9C;AACA,UAAI,OAAO,kBAAkB;AAC3B,gBAAQ,IAAI,YAAY,OAAO,gBAAgB,EAAE;AAAA,MACnD;AACA,UAAI,OAAO,SAAS;AAClB,gBAAQ,IAAI,YAAY,OAAO,OAAO,EAAE;AAAA,MAC1C;AACA,UAAI,OAAO,OAAO;AAChB,gBAAQ,IAAI,UAAU,OAAO,KAAK,EAAE;AAAA,MACtC;AACA;AAAA,IACF;AAAA,IACA,KAAK,YAAY;AACf,YAAM,MAAM,OAAO,CAAC;AACpB,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC5C;AACA,YAAM,SAAS,MAAM,eAAe,SAAS,GAAG;AAChD,cAAQ,IAAI,OAAO,WAAW,oBAAoB;AAClD;AAAA,IACF;AAAA,IACA;AACE,gBAAU;AACV;AAAA,EACJ;AACF;AAEA,SAAS,gBAAgB,QAAyD;AAChF,UAAQ,IAAI,OAAO,OAAO;AAC1B,MAAI,OAAO,gBAAgB;AACzB,YAAQ,IAAI,mBAAmB,OAAO,cAAc,EAAE;AAAA,EACxD;AACA,MAAI,OAAO,iBAAiB;AAC1B,YAAQ,IAAI,oBAAoB,OAAO,eAAe,EAAE;AAAA,EAC1D;AACF;AAEA,eAAe,WAAW,MAA+B;AACvD,QAAM,QAAQ,KAAK,OAAO,SAAO,IAAI,WAAW,GAAG,CAAC;AACpD,QAAM,SAASC,YAAW,IAAI;AAC9B,QAAM,MAAM,OAAO,CAAC;AAEpB,MAAI,CAAC,OAAOD,SAAQ,OAAO,QAAQ,KAAKA,SAAQ,OAAO,IAAI,GAAG;AAC5D,cAAU;AACV;AAAA,EACF;AAEA,UAAQ,KAAK;AAAA,IACX,KAAK,UAAU;AACb,YAAM,SAAS,MAAM,mBAAmB;AACxC,cAAQ,IAAI,aAAa,OAAO,QAAQ,EAAE;AAC1C,cAAQ,IAAI,aAAa,OAAO,UAAU,QAAQ,IAAI,EAAE;AACxD,cAAQ,IAAI,YAAY,OAAO,gBAAgB,QAAQ,IAAI,EAAE;AAC7D,UAAI,OAAO,cAAc;AACvB,gBAAQ,IAAI,kBAAkB,OAAO,YAAY,EAAE;AAAA,MACrD;AACA,UAAI,OAAO,QAAQ;AACjB,gBAAQ,IAAI,WAAW,OAAO,MAAM,EAAE;AAAA,MACxC;AACA,UAAI,OAAO,iBAAiB;AAC1B,gBAAQ,IAAI,oBAAoB,OAAO,eAAe,EAAE;AAAA,MAC1D;AACA,UAAI,OAAO,YAAY;AACrB,gBAAQ,IAAI,cAAc,OAAO,UAAU,EAAE;AAAA,MAC/C;AACA,UAAI,OAAO,YAAY;AACrB,gBAAQ,IAAI,cAAc,OAAO,UAAU,EAAE;AAAA,MAC/C;AACA,UAAI,OAAO,WAAW;AACpB,gBAAQ,IAAI,eAAe,OAAO,SAAS,EAAE;AAAA,MAC/C;AACA;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,SAAS,MAAM,cAAc;AACnC,sBAAgB,MAAM;AACtB,UAAI,OAAO,WAAW,SAAS;AAC7B,gBAAQ,WAAW;AAAA,MACrB;AACA;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,SAAS,MAAM,cAAc;AACnC,sBAAgB,MAAM;AACtB,UAAI,OAAO,WAAW,SAAS;AAC7B,gBAAQ,WAAW;AAAA,MACrB;AACA;AAAA,IACF;AAAA,IACA;AACE,gBAAU;AACV;AAAA,EACJ;AACF;AAEA,eAAe,OAAsB;AACnC,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AAEjC,MAAI,KAAK,WAAW,GAAG;AACrB,cAAU;AACV;AAAA,EACF;AAEA,MAAI,KAAK,CAAC,GAAG,WAAW,GAAG,MAAMA,SAAQ,MAAM,QAAQ,KAAKA,SAAQ,MAAM,IAAI,IAAI;AAChF,cAAU;AACV;AAAA,EACF;AAEA,MAAI,KAAK,CAAC,GAAG,WAAW,GAAG,MAAMA,SAAQ,MAAM,WAAW,KAAKA,SAAQ,MAAM,IAAI,IAAI;AACnF,YAAQ,IAAI,OAAO;AACnB;AAAA,EACF;AAEA,QAAM,UAAU,KAAK,CAAC;AACtB,QAAM,OAAO,KAAK,MAAM,CAAC;AAEzB,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,YAAM,sBAAsB;AAC5B,YAAM,cAAc,IAAI;AACxB;AAAA,IACF,KAAK;AACH,YAAM,sBAAsB;AAC5B,YAAM,cAAc,IAAI;AACxB;AAAA,IACF,KAAK;AACH,YAAM,sBAAsB;AAC5B,YAAM,WAAW,IAAI;AACrB;AAAA,IACF,KAAK;AACH,YAAM,sBAAsB;AAC5B,YAAM,oBAAoB,MAAM,OAAO;AACvC;AAAA,IACF;AACE,gBAAU;AACV;AAAA,EACJ;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,UAAU;AACtB,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAQ,MAAM,OAAO;AACrB,UAAQ,WAAW;AACrB,CAAC;","names":["import_path","os","path","fs","asString","isRecord","asString","isRecord","asString","fs","path","import_node_crypto","import_node_fs","import_node_path","path","crypto","fs","offer","crypto","fallbackStored","fallback","import_node_fs","import_node_path","isRecord","isRecord","import_promises","import_node_path","import_toml","import_node_path","import_node_fs","import_node_path","path","isRecord","path","path","normalizeLineEndings","normalizeLineEndings","normalizeLineEndings","isRecord","path","fs","import_node_child_process","import_node_fs","import_node_path","ENV_HINTS","fileExists","path","stat","import_node_child_process","import_node_fs","import_node_os","import_node_path","REFRESH_TOKEN_REDEEMED_SNIPPET","parseTimestamp","fs","path","os","readline","import_node_fs","import_node_path","import_node_os","isRecord","asString","resolveHomeDir","os","path","fs","import_node_path","import_node_child_process","import_node_readline","import_node_path","import_path","path","isRecord","asString","isRecord","path","asString","isRecord","input","text","path","readline","handled","import_node_path","import_promises","import_node_crypto","import_node_fs","import_node_path","import_node_child_process","import_node_util","import_node_child_process","execFileAsync","path","fs","fileExists","path","fs","import_node_crypto","import_promises","import_node_path","asString","asRecord","asString","response","path","fs","path","hasFlag","stripFlags","result"]}
|