mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-17 04:17:11 +00:00
refactor(cliproxy): extract service layer from cliproxy-command
- create cliproxy/services/ with 6 modules (1179 → 634 lines) - variant-service, variant-settings, variant-config-adapter - proxy-lifecycle-service, binary-service - separate CLI parsing from business logic Phase 5: Command Refactor (cliproxy-command.ts)
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* CLIProxy Binary Service
|
||||
*
|
||||
* Handles CLIProxyAPI binary version management:
|
||||
* - Get current version status
|
||||
* - Install specific versions
|
||||
* - Install latest version
|
||||
* - Version pinning
|
||||
*/
|
||||
|
||||
import {
|
||||
getInstalledCliproxyVersion,
|
||||
installCliproxyVersion,
|
||||
fetchLatestCliproxyVersion,
|
||||
isCLIProxyInstalled,
|
||||
getCLIProxyPath,
|
||||
getPinnedVersion,
|
||||
savePinnedVersion,
|
||||
clearPinnedVersion,
|
||||
isVersionPinned,
|
||||
} from '../binary-manager';
|
||||
import { CLIPROXY_FALLBACK_VERSION } from '../platform-detector';
|
||||
|
||||
/** Binary status result */
|
||||
export interface BinaryStatusResult {
|
||||
installed: boolean;
|
||||
currentVersion: string | null;
|
||||
pinnedVersion: string | null;
|
||||
binaryPath: string;
|
||||
fallbackVersion: string;
|
||||
}
|
||||
|
||||
/** Install result */
|
||||
export interface InstallResult {
|
||||
success: boolean;
|
||||
version: string;
|
||||
error?: string;
|
||||
wasPinned?: boolean;
|
||||
}
|
||||
|
||||
/** Latest version check result */
|
||||
export interface LatestVersionResult {
|
||||
success: boolean;
|
||||
latestVersion?: string;
|
||||
currentVersion?: string;
|
||||
updateAvailable?: boolean;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current binary status
|
||||
*/
|
||||
export function getBinaryStatus(): BinaryStatusResult {
|
||||
return {
|
||||
installed: isCLIProxyInstalled(),
|
||||
currentVersion: getInstalledCliproxyVersion(),
|
||||
pinnedVersion: getPinnedVersion(),
|
||||
binaryPath: getCLIProxyPath(),
|
||||
fallbackVersion: CLIPROXY_FALLBACK_VERSION,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for latest version
|
||||
*/
|
||||
export async function checkLatestVersion(): Promise<LatestVersionResult> {
|
||||
try {
|
||||
const latestVersion = await fetchLatestCliproxyVersion();
|
||||
const currentVersion = getInstalledCliproxyVersion();
|
||||
const updateAvailable = latestVersion !== currentVersion;
|
||||
|
||||
return {
|
||||
success: true,
|
||||
latestVersion,
|
||||
currentVersion: currentVersion || undefined,
|
||||
updateAvailable,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: (error as Error).message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate version format
|
||||
*/
|
||||
export function isValidVersionFormat(version: string): boolean {
|
||||
return /^\d+\.\d+\.\d+$/.test(version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a specific version and pin it
|
||||
*/
|
||||
export async function installVersion(version: string, verbose = false): Promise<InstallResult> {
|
||||
if (!isValidVersionFormat(version)) {
|
||||
return {
|
||||
success: false,
|
||||
version,
|
||||
error: 'Invalid version format. Expected format: X.Y.Z (e.g., 6.5.53)',
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
await installCliproxyVersion(version, verbose);
|
||||
savePinnedVersion(version);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
version,
|
||||
wasPinned: true,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
version,
|
||||
error: (error as Error).message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install latest version and clear any pin
|
||||
*/
|
||||
export async function installLatest(verbose = false): Promise<InstallResult> {
|
||||
try {
|
||||
const latestVersion = await fetchLatestCliproxyVersion();
|
||||
const currentVersion = getInstalledCliproxyVersion();
|
||||
const wasPinned = isVersionPinned();
|
||||
|
||||
if (isCLIProxyInstalled() && latestVersion === currentVersion && !wasPinned) {
|
||||
return {
|
||||
success: true,
|
||||
version: latestVersion,
|
||||
error: `Already running latest version: v${latestVersion}`,
|
||||
};
|
||||
}
|
||||
|
||||
await installCliproxyVersion(latestVersion, verbose);
|
||||
clearPinnedVersion();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
version: latestVersion,
|
||||
wasPinned,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
version: '',
|
||||
error: (error as Error).message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a version is pinned
|
||||
*/
|
||||
export function isPinned(): boolean {
|
||||
return isVersionPinned();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pinned version if any
|
||||
*/
|
||||
export function getPinned(): string | null {
|
||||
return getPinnedVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear version pin
|
||||
*/
|
||||
export function clearPin(): void {
|
||||
clearPinnedVersion();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* CLIProxy Services
|
||||
* Central export point for cliproxy service layer
|
||||
*/
|
||||
|
||||
// Variant management
|
||||
export {
|
||||
validateProfileName,
|
||||
variantExists,
|
||||
listVariants,
|
||||
createVariant,
|
||||
removeVariant,
|
||||
type VariantConfig,
|
||||
type VariantOperationResult,
|
||||
} from './variant-service';
|
||||
|
||||
// Proxy lifecycle
|
||||
export {
|
||||
getProxyStatus,
|
||||
stopProxy,
|
||||
isProxyRunning,
|
||||
getActiveSessionCount,
|
||||
type ProxyStatusResult,
|
||||
type StopProxyResult,
|
||||
} from './proxy-lifecycle-service';
|
||||
|
||||
// Binary management
|
||||
export {
|
||||
getBinaryStatus,
|
||||
checkLatestVersion,
|
||||
isValidVersionFormat,
|
||||
installVersion,
|
||||
installLatest,
|
||||
isPinned,
|
||||
getPinned,
|
||||
clearPin,
|
||||
type BinaryStatusResult,
|
||||
type InstallResult,
|
||||
type LatestVersionResult,
|
||||
} from './binary-service';
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* CLIProxy Proxy Lifecycle Service
|
||||
*
|
||||
* Handles start/stop/status operations for CLIProxy instances.
|
||||
* Delegates to session-tracker for actual process management.
|
||||
*/
|
||||
|
||||
import {
|
||||
stopProxy as stopProxySession,
|
||||
getProxyStatus as getProxyStatusSession,
|
||||
} from '../session-tracker';
|
||||
|
||||
/** Proxy status result */
|
||||
export interface ProxyStatusResult {
|
||||
running: boolean;
|
||||
port?: number;
|
||||
pid?: number;
|
||||
sessionCount?: number;
|
||||
startedAt?: string;
|
||||
}
|
||||
|
||||
/** Stop proxy result */
|
||||
export interface StopProxyResult {
|
||||
stopped: boolean;
|
||||
pid?: number;
|
||||
sessionCount?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current proxy status
|
||||
*/
|
||||
export function getProxyStatus(): ProxyStatusResult {
|
||||
return getProxyStatusSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the running CLIProxy instance
|
||||
*/
|
||||
export async function stopProxy(): Promise<StopProxyResult> {
|
||||
return stopProxySession();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if proxy is currently running
|
||||
*/
|
||||
export function isProxyRunning(): boolean {
|
||||
const status = getProxyStatusSession();
|
||||
return status.running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active session count
|
||||
*/
|
||||
export function getActiveSessionCount(): number {
|
||||
const status = getProxyStatusSession();
|
||||
return status.sessionCount ?? 0;
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* CLIProxy Variant Config Adapters
|
||||
*
|
||||
* Handles reading/writing variant config in both unified and legacy formats.
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import { getConfigPath, loadConfig } from '../../utils/config-manager';
|
||||
import { CLIProxyProvider } from '../types';
|
||||
import {
|
||||
loadOrCreateUnifiedConfig,
|
||||
saveUnifiedConfig,
|
||||
isUnifiedMode,
|
||||
} from '../../config/unified-config-loader';
|
||||
|
||||
/** Variant configuration structure */
|
||||
export interface VariantConfig {
|
||||
provider: string;
|
||||
settings?: string;
|
||||
account?: string;
|
||||
model?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if variant exists in config
|
||||
*/
|
||||
export function variantExistsInConfig(name: string): boolean {
|
||||
try {
|
||||
if (isUnifiedMode()) {
|
||||
const config = loadOrCreateUnifiedConfig();
|
||||
return !!(config.cliproxy?.variants && name in config.cliproxy.variants);
|
||||
}
|
||||
const config = loadConfig();
|
||||
return !!(config.cliproxy && name in config.cliproxy);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List variants from config
|
||||
*/
|
||||
export function listVariantsFromConfig(): Record<string, VariantConfig> {
|
||||
try {
|
||||
if (isUnifiedMode()) {
|
||||
const unifiedConfig = loadOrCreateUnifiedConfig();
|
||||
const variants = unifiedConfig.cliproxy?.variants || {};
|
||||
const result: Record<string, VariantConfig> = {};
|
||||
for (const name of Object.keys(variants)) {
|
||||
const v = variants[name];
|
||||
result[name] = { provider: v.provider, settings: v.settings, account: v.account };
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const config = loadConfig();
|
||||
const variants = config.cliproxy || {};
|
||||
const result: Record<string, VariantConfig> = {};
|
||||
for (const name of Object.keys(variants)) {
|
||||
const v = variants[name] as { provider: string; settings: string; account?: string };
|
||||
result[name] = { provider: v.provider, settings: v.settings, account: v.account };
|
||||
}
|
||||
return result;
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save variant to unified config
|
||||
*/
|
||||
export function saveVariantUnified(
|
||||
name: string,
|
||||
provider: CLIProxyProvider,
|
||||
settingsPath: string,
|
||||
account?: string
|
||||
): void {
|
||||
const config = loadOrCreateUnifiedConfig();
|
||||
|
||||
if (!config.cliproxy) {
|
||||
config.cliproxy = {
|
||||
oauth_accounts: {},
|
||||
providers: ['gemini', 'codex', 'agy', 'qwen', 'iflow'],
|
||||
variants: {},
|
||||
};
|
||||
}
|
||||
if (!config.cliproxy.variants) {
|
||||
config.cliproxy.variants = {};
|
||||
}
|
||||
|
||||
config.cliproxy.variants[name] = {
|
||||
provider,
|
||||
account,
|
||||
settings: settingsPath,
|
||||
};
|
||||
|
||||
saveUnifiedConfig(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save variant to legacy JSON config
|
||||
*/
|
||||
export function saveVariantLegacy(
|
||||
name: string,
|
||||
provider: string,
|
||||
settingsPath: string,
|
||||
account?: string
|
||||
): void {
|
||||
const configPath = getConfigPath();
|
||||
|
||||
let config: { profiles: Record<string, string>; cliproxy?: Record<string, unknown> };
|
||||
try {
|
||||
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||
} catch {
|
||||
config = { profiles: {} };
|
||||
}
|
||||
|
||||
if (!config.cliproxy) {
|
||||
config.cliproxy = {};
|
||||
}
|
||||
|
||||
const variantConfig: { provider: string; settings: string; account?: string } = {
|
||||
provider,
|
||||
settings: settingsPath,
|
||||
};
|
||||
if (account) {
|
||||
variantConfig.account = account;
|
||||
}
|
||||
config.cliproxy[name] = variantConfig;
|
||||
|
||||
const tempPath = configPath + '.tmp';
|
||||
fs.writeFileSync(tempPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
||||
fs.renameSync(tempPath, configPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove variant from unified config
|
||||
*/
|
||||
export function removeVariantFromUnifiedConfig(name: string): VariantConfig | null {
|
||||
const config = loadOrCreateUnifiedConfig();
|
||||
|
||||
if (!config.cliproxy?.variants || !(name in config.cliproxy.variants)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const variant = config.cliproxy.variants[name];
|
||||
delete config.cliproxy.variants[name];
|
||||
saveUnifiedConfig(config);
|
||||
|
||||
return { provider: variant.provider, settings: variant.settings };
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove variant from legacy JSON config
|
||||
*/
|
||||
export function removeVariantFromLegacyConfig(name: string): VariantConfig | null {
|
||||
const configPath = getConfigPath();
|
||||
|
||||
let config: { profiles: Record<string, string>; cliproxy?: Record<string, unknown> };
|
||||
try {
|
||||
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!config.cliproxy || !(name in config.cliproxy)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const variant = config.cliproxy[name] as { provider: string; settings: string };
|
||||
delete config.cliproxy[name];
|
||||
|
||||
if (Object.keys(config.cliproxy).length === 0) {
|
||||
delete config.cliproxy;
|
||||
}
|
||||
|
||||
const tempPath = configPath + '.tmp';
|
||||
fs.writeFileSync(tempPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
||||
fs.renameSync(tempPath, configPath);
|
||||
|
||||
return variant;
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* CLIProxy Variant Service
|
||||
*
|
||||
* Handles CRUD operations for CLIProxy variant profiles.
|
||||
* Supports both unified config (config.yaml) and legacy JSON format.
|
||||
*/
|
||||
|
||||
import * as path from 'path';
|
||||
import { CLIProxyProfileName } from '../../auth/profile-detector';
|
||||
import { CLIProxyProvider } from '../types';
|
||||
import { isReservedName } from '../../config/reserved-names';
|
||||
import { isUnifiedMode } from '../../config/unified-config-loader';
|
||||
import {
|
||||
createSettingsFile,
|
||||
createSettingsFileUnified,
|
||||
deleteSettingsFile,
|
||||
getRelativeSettingsPath,
|
||||
} from './variant-settings';
|
||||
import {
|
||||
VariantConfig,
|
||||
variantExistsInConfig,
|
||||
listVariantsFromConfig,
|
||||
saveVariantUnified,
|
||||
saveVariantLegacy,
|
||||
removeVariantFromUnifiedConfig,
|
||||
removeVariantFromLegacyConfig,
|
||||
} from './variant-config-adapter';
|
||||
|
||||
// Re-export VariantConfig from adapter
|
||||
export type { VariantConfig } from './variant-config-adapter';
|
||||
|
||||
/** Result of variant operations */
|
||||
export interface VariantOperationResult {
|
||||
success: boolean;
|
||||
error?: string;
|
||||
variant?: VariantConfig;
|
||||
settingsPath?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate CLIProxy profile name
|
||||
*/
|
||||
export function validateProfileName(name: string): string | null {
|
||||
if (!name) {
|
||||
return 'Profile name is required';
|
||||
}
|
||||
if (!/^[a-zA-Z][a-zA-Z0-9._-]*$/.test(name)) {
|
||||
return 'Name must start with letter, contain only letters, numbers, dot, dash, underscore';
|
||||
}
|
||||
if (name.length > 32) {
|
||||
return 'Name must be 32 characters or less';
|
||||
}
|
||||
if (isReservedName(name)) {
|
||||
return `'${name}' is a reserved name`;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if CLIProxy variant profile exists
|
||||
*/
|
||||
export function variantExists(name: string): boolean {
|
||||
return variantExistsInConfig(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all CLIProxy variants
|
||||
*/
|
||||
export function listVariants(): Record<string, VariantConfig> {
|
||||
return listVariantsFromConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new CLIProxy variant
|
||||
*/
|
||||
export function createVariant(
|
||||
name: string,
|
||||
provider: CLIProxyProfileName,
|
||||
model: string,
|
||||
account?: string
|
||||
): VariantOperationResult {
|
||||
try {
|
||||
let settingsPath: string;
|
||||
|
||||
if (isUnifiedMode()) {
|
||||
settingsPath = createSettingsFileUnified(name, provider, model);
|
||||
saveVariantUnified(
|
||||
name,
|
||||
provider as CLIProxyProvider,
|
||||
getRelativeSettingsPath(provider, name),
|
||||
account
|
||||
);
|
||||
} else {
|
||||
settingsPath = createSettingsFile(name, provider, model);
|
||||
saveVariantLegacy(name, provider, `~/.ccs/${path.basename(settingsPath)}`, account);
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
settingsPath,
|
||||
variant: { provider, model, account },
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: (error as Error).message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a CLIProxy variant
|
||||
*/
|
||||
export function removeVariant(name: string): VariantOperationResult {
|
||||
try {
|
||||
let variant: VariantConfig | null;
|
||||
|
||||
if (isUnifiedMode()) {
|
||||
const unifiedVariant = removeVariantFromUnifiedConfig(name);
|
||||
if (unifiedVariant?.settings) {
|
||||
deleteSettingsFile(unifiedVariant.settings);
|
||||
}
|
||||
variant = unifiedVariant;
|
||||
} else {
|
||||
variant = removeVariantFromLegacyConfig(name);
|
||||
if (variant?.settings) {
|
||||
deleteSettingsFile(variant.settings);
|
||||
}
|
||||
}
|
||||
|
||||
if (!variant) {
|
||||
return { success: false, error: `Variant '${name}' not found` };
|
||||
}
|
||||
|
||||
return { success: true, variant };
|
||||
} catch (error) {
|
||||
return { success: false, error: (error as Error).message };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* CLIProxy Variant Settings File Manager
|
||||
*
|
||||
* Handles creation of settings.json files for CLIProxy variants.
|
||||
* These files contain environment variables for Claude CLI integration.
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import { CLIProxyProfileName } from '../../auth/profile-detector';
|
||||
import { getCcsDir } from '../../utils/config-manager';
|
||||
import { getClaudeEnvVars, CLIPROXY_DEFAULT_PORT } from '../config-generator';
|
||||
import { CLIProxyProvider } from '../types';
|
||||
|
||||
/** Environment settings structure */
|
||||
interface SettingsEnv {
|
||||
ANTHROPIC_BASE_URL: string;
|
||||
ANTHROPIC_AUTH_TOKEN: string;
|
||||
ANTHROPIC_MODEL: string;
|
||||
ANTHROPIC_DEFAULT_OPUS_MODEL: string;
|
||||
ANTHROPIC_DEFAULT_SONNET_MODEL: string;
|
||||
ANTHROPIC_DEFAULT_HAIKU_MODEL: string;
|
||||
}
|
||||
|
||||
interface SettingsFile {
|
||||
env: SettingsEnv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build settings env object for a variant
|
||||
*/
|
||||
function buildSettingsEnv(provider: CLIProxyProfileName, model: string): SettingsEnv {
|
||||
const baseEnv = getClaudeEnvVars(provider as CLIProxyProvider, CLIPROXY_DEFAULT_PORT);
|
||||
|
||||
return {
|
||||
ANTHROPIC_BASE_URL: baseEnv.ANTHROPIC_BASE_URL || '',
|
||||
ANTHROPIC_AUTH_TOKEN: baseEnv.ANTHROPIC_AUTH_TOKEN || '',
|
||||
ANTHROPIC_MODEL: model,
|
||||
ANTHROPIC_DEFAULT_OPUS_MODEL: model,
|
||||
ANTHROPIC_DEFAULT_SONNET_MODEL: model,
|
||||
ANTHROPIC_DEFAULT_HAIKU_MODEL: baseEnv.ANTHROPIC_DEFAULT_HAIKU_MODEL || model,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure directory exists
|
||||
*/
|
||||
function ensureDir(dir: string): void {
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write settings file atomically
|
||||
*/
|
||||
function writeSettings(filePath: string, settings: SettingsFile): void {
|
||||
fs.writeFileSync(filePath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get settings file path for a variant
|
||||
*/
|
||||
export function getSettingsFilePath(provider: CLIProxyProfileName, name: string): string {
|
||||
const ccsDir = getCcsDir();
|
||||
return path.join(ccsDir, `${provider}-${name}.settings.json`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get settings file name (without path)
|
||||
*/
|
||||
export function getSettingsFileName(provider: CLIProxyProfileName, name: string): string {
|
||||
return `${provider}-${name}.settings.json`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get relative settings path with ~ prefix
|
||||
*/
|
||||
export function getRelativeSettingsPath(provider: CLIProxyProfileName, name: string): string {
|
||||
return `~/.ccs/${getSettingsFileName(provider, name)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create settings.json file for CLIProxy variant (legacy mode)
|
||||
*/
|
||||
export function createSettingsFile(
|
||||
name: string,
|
||||
provider: CLIProxyProfileName,
|
||||
model: string
|
||||
): string {
|
||||
const ccsDir = getCcsDir();
|
||||
const settingsPath = getSettingsFilePath(provider, name);
|
||||
|
||||
const settings: SettingsFile = {
|
||||
env: buildSettingsEnv(provider, model),
|
||||
};
|
||||
|
||||
ensureDir(ccsDir);
|
||||
writeSettings(settingsPath, settings);
|
||||
|
||||
return settingsPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create settings.json file for CLIProxy variant (unified mode)
|
||||
*/
|
||||
export function createSettingsFileUnified(
|
||||
name: string,
|
||||
provider: CLIProxyProfileName,
|
||||
model: string
|
||||
): string {
|
||||
const ccsDir = path.join(os.homedir(), '.ccs');
|
||||
const settingsPath = path.join(ccsDir, getSettingsFileName(provider, name));
|
||||
|
||||
const settings: SettingsFile = {
|
||||
env: buildSettingsEnv(provider, model),
|
||||
};
|
||||
|
||||
ensureDir(ccsDir);
|
||||
writeSettings(settingsPath, settings);
|
||||
|
||||
return settingsPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete settings file if it exists
|
||||
*/
|
||||
export function deleteSettingsFile(settingsPath: string): boolean {
|
||||
const resolvedPath = settingsPath.replace(/^~/, os.homedir());
|
||||
if (fs.existsSync(resolvedPath)) {
|
||||
fs.unlinkSync(resolvedPath);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
+259
-812
File diff suppressed because it is too large
Load Diff
@@ -449,6 +449,16 @@ export function updateUnifiedConfig(updates: Partial<UnifiedConfig>): UnifiedCon
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if unified config mode is active.
|
||||
* Returns true if config.yaml exists OR CCS_UNIFIED_CONFIG=1.
|
||||
*
|
||||
* Use this centralized function instead of duplicating the logic.
|
||||
*/
|
||||
export function isUnifiedMode(): boolean {
|
||||
return hasUnifiedConfig() || isUnifiedConfigEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set default profile name.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user