accf
Version:
Claude-Code Flow - One-click configuration tool for Claude Code
420 lines (416 loc) • 13.5 kB
JavaScript
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 };