UNPKG

accf

Version:

Claude-Code Flow - One-click configuration tool for Claude Code

420 lines (416 loc) 13.5 kB
import ansis from 'ansis'; import inquirer from 'inquirer'; import { a1 as readCodexConfig, a2 as backupCodexComplete, a3 as writeCodexConfig, a4 as writeAuthFile, a5 as ensureI18nInitialized, a6 as detectConfigManagementMode, a0 as i18n, a7 as addNumbersToChoices } from './simple-config.mjs'; import 'node:fs'; import 'node:process'; import 'node:child_process'; import 'node:os'; import 'node:util'; import 'dayjs'; import 'pathe'; import 'node:url'; import 'ora'; import 'semver'; import 'smol-toml'; import 'tinyexec'; import 'node:fs/promises'; import 'i18next'; import 'i18next-fs-backend'; const ERROR_MESSAGES = { NO_CONFIG: "No existing configuration found", BACKUP_FAILED: "Failed to create backup", PROVIDER_EXISTS: (id) => `Provider with ID "${id}" already exists`, PROVIDER_NOT_FOUND: (id) => `Provider with ID "${id}" not found`, NO_PROVIDERS_SPECIFIED: "No providers specified for deletion", PROVIDERS_NOT_FOUND: (providers) => `Some providers not found: ${providers.join(", ")}`, CANNOT_DELETE_ALL: "Cannot delete all providers. At least one provider must remain." }; async function addProviderToExisting(provider, apiKey) { try { const existingConfig = readCodexConfig(); if (!existingConfig) { return { success: false, error: ERROR_MESSAGES.NO_CONFIG }; } const existingProvider = existingConfig.providers.find((p) => p.id === provider.id); if (existingProvider) { return { success: false, error: ERROR_MESSAGES.PROVIDER_EXISTS(provider.id) }; } const backupPath = backupCodexComplete(); if (!backupPath) { return { success: false, error: ERROR_MESSAGES.BACKUP_FAILED }; } const updatedConfig = { ...existingConfig, providers: [...existingConfig.providers, provider] }; writeCodexConfig(updatedConfig); const authEntries = {}; authEntries[provider.envKey] = apiKey; writeAuthFile(authEntries); return { success: true, backupPath, addedProvider: provider }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : "Unknown error" }; } } async function editExistingProvider(providerId, updates) { try { const existingConfig = readCodexConfig(); if (!existingConfig) { return { success: false, error: ERROR_MESSAGES.NO_CONFIG }; } const providerIndex = existingConfig.providers.findIndex((p) => p.id === providerId); if (providerIndex === -1) { return { success: false, error: ERROR_MESSAGES.PROVIDER_NOT_FOUND(providerId) }; } const backupPath = backupCodexComplete(); if (!backupPath) { return { success: false, error: ERROR_MESSAGES.BACKUP_FAILED }; } const updatedProvider = { ...existingConfig.providers[providerIndex], ...updates.name && { name: updates.name }, ...updates.baseUrl && { baseUrl: updates.baseUrl }, ...updates.wireApi && { wireApi: updates.wireApi } }; const updatedProviders = [...existingConfig.providers]; updatedProviders[providerIndex] = updatedProvider; const updatedConfig = { ...existingConfig, providers: updatedProviders }; writeCodexConfig(updatedConfig); if (updates.apiKey) { const authEntries = {}; authEntries[updatedProvider.envKey] = updates.apiKey; writeAuthFile(authEntries); } return { success: true, backupPath, updatedProvider }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : "Unknown error" }; } } async function deleteProviders(providerIds) { try { const existingConfig = readCodexConfig(); if (!existingConfig) { return { success: false, error: ERROR_MESSAGES.NO_CONFIG }; } if (!providerIds || providerIds.length === 0) { return { success: false, error: ERROR_MESSAGES.NO_PROVIDERS_SPECIFIED }; } const notFoundProviders = providerIds.filter( (id) => !existingConfig.providers.some((p) => p.id === id) ); if (notFoundProviders.length > 0) { return { success: false, error: ERROR_MESSAGES.PROVIDERS_NOT_FOUND(notFoundProviders) }; } const remainingProviders = existingConfig.providers.filter( (p) => !providerIds.includes(p.id) ); if (remainingProviders.length === 0) { return { success: false, error: ERROR_MESSAGES.CANNOT_DELETE_ALL }; } const backupPath = backupCodexComplete(); if (!backupPath) { return { success: false, error: ERROR_MESSAGES.BACKUP_FAILED }; } let newDefaultProvider = existingConfig.modelProvider; if (providerIds.includes(existingConfig.modelProvider || "")) { newDefaultProvider = remainingProviders[0].id; } const updatedConfig = { ...existingConfig, modelProvider: newDefaultProvider, providers: remainingProviders }; writeCodexConfig(updatedConfig); const result = { success: true, backupPath, deletedProviders: providerIds, remainingProviders }; if (newDefaultProvider !== existingConfig.modelProvider) { result.newDefaultProvider = newDefaultProvider || void 0; } return result; } catch (error) { return { success: false, error: error instanceof Error ? error.message : "Unknown error" }; } } async function configureIncrementalManagement() { ensureI18nInitialized(); const managementMode = detectConfigManagementMode(); if (managementMode.mode !== "management" || !managementMode.hasProviders) { console.log(ansis.yellow(i18n.t("codex:noExistingProviders"))); return; } console.log(ansis.cyan(i18n.t("codex:incrementalManagementTitle"))); console.log(ansis.gray(i18n.t("codex:currentProviderCount", { count: managementMode.providerCount }))); if (managementMode.currentProvider) { console.log(ansis.gray(i18n.t("codex:currentDefaultProvider", { provider: managementMode.currentProvider }))); } const choices = [ { name: i18n.t("codex:addProvider"), value: "add" }, { name: i18n.t("codex:editProvider"), value: "edit" }, { name: i18n.t("codex:deleteProvider"), value: "delete" }, { name: i18n.t("common:skip"), value: "skip" } ]; const { action } = await inquirer.prompt([{ type: "list", name: "action", message: i18n.t("codex:selectAction"), choices: addNumbersToChoices(choices) }]); if (!action || action === "skip") { console.log(ansis.yellow(i18n.t("common:skip"))); return; } switch (action) { case "add": await handleAddProvider(); break; case "edit": await handleEditProvider(managementMode.providers); break; case "delete": await handleDeleteProvider(managementMode.providers); break; } } async function handleAddProvider() { const answers = await inquirer.prompt([ { type: "input", name: "providerName", message: i18n.t("codex:providerNamePrompt"), validate: (input) => { const trimmed = input.trim(); if (!trimmed) return i18n.t("codex:providerNameRequired"); if (!/^[\w\-\s]+$/.test(trimmed)) return i18n.t("codex:providerNameInvalid"); return true; } }, { type: "input", name: "baseUrl", message: i18n.t("codex:providerBaseUrlPrompt"), default: "https://api.openai.com/v1", validate: (input) => !!input.trim() || i18n.t("codex:providerBaseUrlRequired") }, { type: "list", name: "wireApi", message: i18n.t("codex:providerProtocolPrompt"), choices: [ { name: i18n.t("codex:protocolResponses"), value: "responses" }, { name: i18n.t("codex:protocolChat"), value: "chat" } ], default: "responses" }, { type: "password", name: "apiKey", message: i18n.t("codex:providerApiKeyPrompt") + i18n.t("common:inputHidden"), validate: (input) => !!input.trim() || i18n.t("codex:providerApiKeyRequired") } ]); const providerId = answers.providerName.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9\-]/g, ""); const provider = { id: providerId, name: answers.providerName.trim(), baseUrl: answers.baseUrl.trim(), wireApi: answers.wireApi, envKey: `${providerId.toUpperCase().replace(/-/g, "_")}_API_KEY`, requiresOpenaiAuth: true }; const result = await addProviderToExisting(provider, answers.apiKey.trim()); if (result.success) { console.log(ansis.green(i18n.t("codex:providerAdded", { name: result.addedProvider?.name }))); if (result.backupPath) { console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath }))); } } else { console.log(ansis.red(i18n.t("codex:providerAddFailed", { error: result.error }))); } } async function handleEditProvider(providers) { const choices = providers.map((provider2) => ({ name: `${provider2.name} (${provider2.baseUrl})`, value: provider2.id })); const { selectedProviderId } = await inquirer.prompt([{ type: "list", name: "selectedProviderId", message: i18n.t("codex:selectProviderToEdit"), choices: addNumbersToChoices(choices) }]); if (!selectedProviderId) { console.log(ansis.yellow(i18n.t("common:cancelled"))); return; } const provider = providers.find((p) => p.id === selectedProviderId); if (!provider) { console.log(ansis.red(i18n.t("codex:providerNotFound"))); return; } const answers = await inquirer.prompt([ { type: "input", name: "providerName", message: i18n.t("codex:providerNamePrompt"), default: provider.name, validate: (input) => { const trimmed = input.trim(); if (!trimmed) return i18n.t("codex:providerNameRequired"); if (!/^[\w\-\s]+$/.test(trimmed)) return i18n.t("codex:providerNameInvalid"); return true; } }, { type: "input", name: "baseUrl", message: i18n.t("codex:providerBaseUrlPrompt"), default: provider.baseUrl, validate: (input) => !!input.trim() || i18n.t("codex:providerBaseUrlRequired") }, { type: "list", name: "wireApi", message: i18n.t("codex:providerProtocolPrompt"), choices: [ { name: i18n.t("codex:protocolResponses"), value: "responses" }, { name: i18n.t("codex:protocolChat"), value: "chat" } ], default: provider.wireApi }, { type: "password", name: "apiKey", message: i18n.t("codex:providerApiKeyPrompt") + i18n.t("common:inputHidden"), validate: (input) => !!input.trim() || i18n.t("codex:providerApiKeyRequired") } ]); const updates = { name: answers.providerName.trim(), baseUrl: answers.baseUrl.trim(), wireApi: answers.wireApi, apiKey: answers.apiKey.trim() }; const result = await editExistingProvider(selectedProviderId, updates); if (result.success) { console.log(ansis.green(i18n.t("codex:providerUpdated", { name: result.updatedProvider?.name }))); if (result.backupPath) { console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath }))); } } else { console.log(ansis.red(i18n.t("codex:providerUpdateFailed", { error: result.error }))); } } async function handleDeleteProvider(providers) { const choices = providers.map((provider) => ({ name: `${provider.name} (${provider.baseUrl})`, value: provider.id })); const { selectedProviderIds } = await inquirer.prompt({ type: "checkbox", name: "selectedProviderIds", message: i18n.t("codex:selectProvidersToDelete"), choices, validate: (input) => { const selected = input; if (!selected || selected.length === 0) { return i18n.t("codex:selectAtLeastOne"); } if (selected.length === providers.length) { return i18n.t("codex:cannotDeleteAll"); } return true; } }); if (!selectedProviderIds || selectedProviderIds.length === 0) { console.log(ansis.yellow(i18n.t("common:cancelled"))); return; } const selectedNames = selectedProviderIds.map( (id) => providers.find((p) => p.id === id)?.name || id ).join(", "); const { confirmDelete } = await inquirer.prompt([{ type: "confirm", name: "confirmDelete", message: i18n.t("codex:confirmDeleteProviders", { providers: selectedNames }), default: false }]); if (!confirmDelete) { console.log(ansis.yellow(i18n.t("common:cancelled"))); return; } const result = await deleteProviders(selectedProviderIds); if (result.success) { console.log(ansis.green(i18n.t("codex:providersDeleted", { count: selectedProviderIds.length }))); if (result.newDefaultProvider) { console.log(ansis.cyan(i18n.t("codex:newDefaultProvider", { provider: result.newDefaultProvider }))); } if (result.backupPath) { console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath }))); } } else { console.log(ansis.red(i18n.t("codex:providersDeleteFailed", { error: result.error }))); } } const codexConfigSwitch = { configureIncrementalManagement }; export { configureIncrementalManagement, codexConfigSwitch as default };