mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-13 18:15:23 +00:00
refactor(cliproxy): flatten module structure and colocate tests (#1135)
- Split types.ts (331 LOC) into 4 concern-based files under types/: platform-types, binary-types, provider-types, config-types - Preserve backward compat via barrel re-export (types.ts → types/index) - Reorganize 53 root-level files into 8 subdirectories: accounts/, ai-providers/, auth/, binary/, config/, executor/, management/, proxy/, quota/, routing/, services/, sync/ - Reduce src/cliproxy/ root from 65 to 8 files (target: ≤10) - Colocate 87 unit tests from tests/unit/cliproxy/ into src/cliproxy/*/__tests__/ (13 colocated test directories) - Update import paths across 40+ consumer files - Add TDD backward-compat test for types split Refs #1135
This commit is contained in:
1 parent
561189efe6
commit
1c72b4b8d5
225 files changed
+935
-905
No files matched your search
@@ -1,16 +1,16 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { getCcsDir, loadConfigSafe } from '../../utils/config-manager';
|
import { getCcsDir, loadConfigSafe } from '../../utils/config-manager';
|
||||||
import { buildProxyUrl, getProxyTarget } from '../../cliproxy/proxy-target-resolver';
|
import { buildProxyUrl, getProxyTarget } from '../../cliproxy/proxy/proxy-target-resolver';
|
||||||
import { getEffectiveApiKey } from '../../cliproxy/auth-token-manager';
|
import { getEffectiveApiKey } from '../../cliproxy/auth/auth-token-manager';
|
||||||
import { getModelMappingFromConfig } from '../../cliproxy/base-config-loader';
|
import { getModelMappingFromConfig } from '../../cliproxy/config/base-config-loader';
|
||||||
import {
|
import {
|
||||||
CLIPROXY_PROVIDER_IDS,
|
CLIPROXY_PROVIDER_IDS,
|
||||||
getProviderDescription,
|
getProviderDescription,
|
||||||
getProviderDisplayName,
|
getProviderDisplayName,
|
||||||
mapExternalProviderName,
|
mapExternalProviderName,
|
||||||
} from '../../cliproxy/provider-capabilities';
|
} from '../../cliproxy/provider-capabilities';
|
||||||
import { extractProviderFromPathname } from '../../cliproxy/model-id-normalizer';
|
import { extractProviderFromPathname } from '../../cliproxy/ai-providers/model-id-normalizer';
|
||||||
import { isUnifiedMode, loadOrCreateUnifiedConfig } from '../../config/unified-config-loader';
|
import { isUnifiedMode, loadOrCreateUnifiedConfig } from '../../config/unified-config-loader';
|
||||||
import type { TargetType } from '../../targets/target-adapter';
|
import type { TargetType } from '../../targets/target-adapter';
|
||||||
import type { Settings } from '../../types/config';
|
import type { Settings } from '../../types/config';
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
import {
|
import {
|
||||||
extractProviderFromPathname,
|
extractProviderFromPathname,
|
||||||
getDeniedModelIdReasonForProvider,
|
getDeniedModelIdReasonForProvider,
|
||||||
} from '../../cliproxy/model-id-normalizer';
|
} from '../../cliproxy/ai-providers/model-id-normalizer';
|
||||||
import { mapExternalProviderName } from '../../cliproxy/provider-capabilities';
|
import { mapExternalProviderName } from '../../cliproxy/provider-capabilities';
|
||||||
import type { CLIProxyProvider } from '../../cliproxy/types';
|
import type { CLIProxyProvider } from '../../cliproxy/types';
|
||||||
import type { ProfileValidationIssue, ProfileValidationSummary } from './profile-types';
|
import type { ProfileValidationIssue, ProfileValidationSummary } from './profile-types';
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { mapExternalProviderName } from '../../cliproxy/provider-capabilities';
|
|||||||
import {
|
import {
|
||||||
extractProviderFromPathname,
|
extractProviderFromPathname,
|
||||||
getDeniedModelIdReasonForProvider,
|
getDeniedModelIdReasonForProvider,
|
||||||
} from '../../cliproxy/model-id-normalizer';
|
} from '../../cliproxy/ai-providers/model-id-normalizer';
|
||||||
import type { CLIProxyProvider } from '../../cliproxy/types';
|
import type { CLIProxyProvider } from '../../cliproxy/types';
|
||||||
import type {
|
import type {
|
||||||
ModelMapping,
|
ModelMapping,
|
||||||
|
|||||||
File renamed without changes.
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
import { describe, it, expect } from 'bun:test';
|
import { describe, it, expect } from 'bun:test';
|
||||||
import { findModel, supportsThinking } from '../../../src/cliproxy/model-catalog';
|
import { findModel, supportsThinking } from '../model-catalog';
|
||||||
import {
|
import {
|
||||||
PROVIDER_TO_CHANNEL,
|
PROVIDER_TO_CHANNEL,
|
||||||
SYNCABLE_PROVIDERS,
|
SYNCABLE_PROVIDERS,
|
||||||
mergeCatalog,
|
mergeCatalog,
|
||||||
} from '../../../src/cliproxy/catalog-cache';
|
} from '../services/catalog-cache';
|
||||||
|
|
||||||
describe('model-catalog compatibility lookups', () => {
|
describe('model-catalog compatibility lookups', () => {
|
||||||
it('finds agy Claude models using dotted major.minor IDs', () => {
|
it('finds agy Claude models using dotted major.minor IDs', () => {
|
||||||
File renamed without changes.
File renamed without changes.
+3
-3
@@ -13,11 +13,11 @@ import {
|
|||||||
isQuotaSupportedProvider,
|
isQuotaSupportedProvider,
|
||||||
QUOTA_PROVIDER_OPTION_VALUES,
|
QUOTA_PROVIDER_OPTION_VALUES,
|
||||||
QUOTA_PROVIDER_HELP_TEXT,
|
QUOTA_PROVIDER_HELP_TEXT,
|
||||||
} from '../../../src/cliproxy/provider-capabilities';
|
} from '../provider-capabilities';
|
||||||
import {
|
import {
|
||||||
OAUTH_CALLBACK_PORTS as DIAGNOSTIC_CALLBACK_PORTS,
|
OAUTH_CALLBACK_PORTS as DIAGNOSTIC_CALLBACK_PORTS,
|
||||||
OAUTH_FLOW_TYPES,
|
OAUTH_FLOW_TYPES,
|
||||||
} from '../../../src/management/oauth-port-diagnostics';
|
} from '../../management/oauth-port-diagnostics';
|
||||||
import {
|
import {
|
||||||
DEFAULT_KIRO_AUTH_METHOD,
|
DEFAULT_KIRO_AUTH_METHOD,
|
||||||
getKiroCallbackPort,
|
getKiroCallbackPort,
|
||||||
@@ -27,7 +27,7 @@ import {
|
|||||||
normalizeKiroAuthMethod,
|
normalizeKiroAuthMethod,
|
||||||
OAUTH_CALLBACK_PORTS as AUTH_CALLBACK_PORTS,
|
OAUTH_CALLBACK_PORTS as AUTH_CALLBACK_PORTS,
|
||||||
toKiroManagementMethod,
|
toKiroManagementMethod,
|
||||||
} from '../../../src/cliproxy/auth/auth-types';
|
} from '../auth/auth-types';
|
||||||
|
|
||||||
describe('provider-capabilities', () => {
|
describe('provider-capabilities', () => {
|
||||||
it('keeps canonical provider IDs backward-compatible', () => {
|
it('keeps canonical provider IDs backward-compatible', () => {
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
import { describe, it, expect } from 'bun:test';
|
import { describe, it, expect } from 'bun:test';
|
||||||
import { parseThinkingOverride } from '../../../src/cliproxy/executor/thinking-arg-parser';
|
import { parseThinkingOverride } from '../executor/thinking-arg-parser';
|
||||||
|
|
||||||
describe('parseThinkingOverride', () => {
|
describe('parseThinkingOverride', () => {
|
||||||
it('parses --thinking with separate value', () => {
|
it('parses --thinking with separate value', () => {
|
||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
import { describe, expect, it } from 'bun:test';
|
import { describe, expect, it } from 'bun:test';
|
||||||
import type { ThinkingConfig } from '../../../src/config/unified-config-types';
|
import type { ThinkingConfig } from '../../config/unified-config-types';
|
||||||
import {
|
import {
|
||||||
buildThinkingStartupStatus,
|
buildThinkingStartupStatus,
|
||||||
parseEnvThinkingOverride,
|
parseEnvThinkingOverride,
|
||||||
resolveRuntimeThinkingOverride,
|
resolveRuntimeThinkingOverride,
|
||||||
shouldDisableCodexReasoning,
|
shouldDisableCodexReasoning,
|
||||||
} from '../../../src/cliproxy/executor/thinking-override-resolver';
|
} from '../executor/thinking-override-resolver';
|
||||||
|
|
||||||
const baseConfig: ThinkingConfig = {
|
const baseConfig: ThinkingConfig = {
|
||||||
mode: 'auto',
|
mode: 'auto',
|
||||||
+1
-1
@@ -13,7 +13,7 @@ import {
|
|||||||
THINKING_BUDGET_MIN,
|
THINKING_BUDGET_MIN,
|
||||||
THINKING_BUDGET_MAX,
|
THINKING_BUDGET_MAX,
|
||||||
THINKING_BUDGET_DEFAULT_MIN,
|
THINKING_BUDGET_DEFAULT_MIN,
|
||||||
} from '../../../src/cliproxy/thinking-validator';
|
} from '../thinking-validator';
|
||||||
|
|
||||||
describe('Thinking Validator', () => {
|
describe('Thinking Validator', () => {
|
||||||
describe('Constants', () => {
|
describe('Constants', () => {
|
||||||
+19
-19
@@ -29,18 +29,18 @@ describe('Account Manager - discoverExistingAccounts', () => {
|
|||||||
process.env.CCS_HOME = testDir;
|
process.env.CCS_HOME = testDir;
|
||||||
|
|
||||||
// Clear cache and reload - must clear all modular submodules too
|
// Clear cache and reload - must clear all modular submodules too
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/account-manager')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/account-manager')];
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/config-generator')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')];
|
||||||
delete require.cache[require.resolve('../../../dist/utils/config-manager')];
|
delete require.cache[require.resolve('../../../../dist/utils/config-manager')];
|
||||||
// Clear new modular structure (accounts/ and config/ submodules)
|
// Clear new modular structure (accounts/ and config/ submodules)
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/accounts/index')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/index')];
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/accounts/registry')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/registry')];
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/accounts/token-file-ops')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/token-file-ops')];
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/accounts/query')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/query')];
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/accounts/types')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/types')];
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/config/index')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/config/index')];
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/config/path-resolver')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/config/path-resolver')];
|
||||||
accountManager = require('../../../dist/cliproxy/account-manager');
|
accountManager = require('../../../../dist/cliproxy/account-manager');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -269,10 +269,10 @@ describe('Account Manager - discoverExistingAccounts', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Reload module to clear in-memory cache (including all submodules)
|
// Reload module to clear in-memory cache (including all submodules)
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/account-manager')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/account-manager')];
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/accounts/index')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/index')];
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/accounts/registry')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/registry')];
|
||||||
accountManager = require('../../../dist/cliproxy/account-manager');
|
accountManager = require('../../../../dist/cliproxy/account-manager');
|
||||||
accountManager.discoverExistingAccounts();
|
accountManager.discoverExistingAccounts();
|
||||||
|
|
||||||
const accounts = getAccountsFile();
|
const accounts = getAccountsFile();
|
||||||
@@ -353,10 +353,10 @@ describe('Account Manager - discoverExistingAccounts', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Reload module to pick up pre-existing accounts.json (including all submodules)
|
// Reload module to pick up pre-existing accounts.json (including all submodules)
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/account-manager')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/account-manager')];
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/accounts/index')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/index')];
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/accounts/registry')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/registry')];
|
||||||
accountManager = require('../../../dist/cliproxy/account-manager');
|
accountManager = require('../../../../dist/cliproxy/account-manager');
|
||||||
accountManager.discoverExistingAccounts();
|
accountManager.discoverExistingAccounts();
|
||||||
|
|
||||||
const accounts = getAccountsFile();
|
const accounts = getAccountsFile();
|
||||||
+3
-3
@@ -2,7 +2,7 @@ import { describe, expect, it, spyOn } from 'bun:test';
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { runWithScopedCcsHome } from '../../../src/utils/config-manager';
|
import { runWithScopedCcsHome } from '../../../utils/config-manager';
|
||||||
|
|
||||||
async function withIsolatedHome<T>(fn: (homeDir: string) => Promise<T> | T): Promise<T> {
|
async function withIsolatedHome<T>(fn: (homeDir: string) => Promise<T> | T): Promise<T> {
|
||||||
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ccs-account-registry-'));
|
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ccs-account-registry-'));
|
||||||
@@ -14,11 +14,11 @@ async function withIsolatedHome<T>(fn: (homeDir: string) => Promise<T> | T): Pro
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loadRegistryModule() {
|
async function loadRegistryModule() {
|
||||||
return import(`../../../src/cliproxy/accounts/registry?registry-integrity=${Date.now()}`);
|
return import(`../registry?registry-integrity=${Date.now()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadAccountManager() {
|
async function loadAccountManager() {
|
||||||
return import(`../../../src/cliproxy/account-manager?account-registry-integrity=${Date.now()}`);
|
return import(`../account-manager?account-registry-integrity=${Date.now()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function captureConsoleError<T>(fn: () => Promise<T> | T): Promise<{ result: T; messages: string[] }> {
|
async function captureConsoleError<T>(fn: () => Promise<T> | T): Promise<{ result: T; messages: string[] }> {
|
||||||
+2
-2
@@ -2,10 +2,10 @@ import { describe, expect, it } from 'bun:test';
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { runWithScopedCcsHome } from '../../../src/utils/config-manager';
|
import { runWithScopedCcsHome } from '../../../utils/config-manager';
|
||||||
|
|
||||||
async function loadAccountManager() {
|
async function loadAccountManager() {
|
||||||
return import(`../../../src/cliproxy/account-manager?optional-nickname=${Date.now()}`);
|
return import(`../account-manager?optional-nickname=${Date.now()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeTokenFile(homeDir: string, tokenFile: string): void {
|
function writeTokenFile(homeDir: string, tokenFile: string): void {
|
||||||
+18
-18
@@ -19,8 +19,8 @@ import {
|
|||||||
maskEmail,
|
maskEmail,
|
||||||
pauseAccountForQuotaCooldown,
|
pauseAccountForQuotaCooldown,
|
||||||
restoreExpiredQuotaPauses,
|
restoreExpiredQuotaPauses,
|
||||||
} from '../../../src/cliproxy/account-safety';
|
} from '../../accounts/account-safety';
|
||||||
import { sanitizeEmail } from '../../../src/cliproxy/auth-utils';
|
import { sanitizeEmail } from '../../auth/auth-utils';
|
||||||
|
|
||||||
// Setup test isolation
|
// Setup test isolation
|
||||||
let tmpDir: string;
|
let tmpDir: string;
|
||||||
@@ -243,7 +243,7 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { isOnCooldown } = await import('../../../src/cliproxy/quota-manager');
|
const { isOnCooldown } = await import('../../quota/quota-manager');
|
||||||
|
|
||||||
const result = await handleQuotaExhaustion('agy', 'exhausted@gmail.com', 10);
|
const result = await handleQuotaExhaustion('agy', 'exhausted@gmail.com', 10);
|
||||||
|
|
||||||
@@ -285,7 +285,7 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const result = await handleQuotaExhaustion('agy', 'only@gmail.com', 10);
|
const result = await handleQuotaExhaustion('agy', 'only@gmail.com', 10);
|
||||||
const { getAccount } = await import('../../../src/cliproxy/account-manager');
|
const { getAccount } = await import('../account-manager');
|
||||||
|
|
||||||
// Should return gracefully with null switched
|
// Should return gracefully with null switched
|
||||||
expect(result.switchedTo).toBeNull();
|
expect(result.switchedTo).toBeNull();
|
||||||
@@ -343,7 +343,7 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
|
|
||||||
const result = await handleQuotaExhaustion('claude', 'exhausted@example.com', 10);
|
const result = await handleQuotaExhaustion('claude', 'exhausted@example.com', 10);
|
||||||
const { getAccount, getDefaultAccount } = await import(
|
const { getAccount, getDefaultAccount } = await import(
|
||||||
'../../../src/cliproxy/account-manager'
|
'../account-manager'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.switchedTo).toBe('fallback@example.com');
|
expect(result.switchedTo).toBe('fallback@example.com');
|
||||||
@@ -430,7 +430,7 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
|
|
||||||
const result = await handleQuotaExhaustion('codex', 'exhausted@example.com', 10);
|
const result = await handleQuotaExhaustion('codex', 'exhausted@example.com', 10);
|
||||||
const { getAccount, getDefaultAccount } = await import(
|
const { getAccount, getDefaultAccount } = await import(
|
||||||
'../../../src/cliproxy/account-manager'
|
'../account-manager'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.switchedTo).toBe('fallback@example.com');
|
expect(result.switchedTo).toBe('fallback@example.com');
|
||||||
@@ -490,9 +490,9 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
)
|
)
|
||||||
) as typeof fetch;
|
) as typeof fetch;
|
||||||
|
|
||||||
const { preflightCheck } = await import('../../../src/cliproxy/quota-manager');
|
const { preflightCheck } = await import('../../quota/quota-manager');
|
||||||
const result = await preflightCheck('codex');
|
const result = await preflightCheck('codex');
|
||||||
const { getAccount } = await import('../../../src/cliproxy/account-manager');
|
const { getAccount } = await import('../account-manager');
|
||||||
|
|
||||||
expect(result.accountId).toBe('only-codex@example.com');
|
expect(result.accountId).toBe('only-codex@example.com');
|
||||||
expect(result.switchedFrom).toBeUndefined();
|
expect(result.switchedFrom).toBeUndefined();
|
||||||
@@ -567,10 +567,10 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
);
|
);
|
||||||
}) as typeof fetch;
|
}) as typeof fetch;
|
||||||
|
|
||||||
const { preflightCheck } = await import('../../../src/cliproxy/quota-manager');
|
const { preflightCheck } = await import('../../quota/quota-manager');
|
||||||
const result = await preflightCheck('codex');
|
const result = await preflightCheck('codex');
|
||||||
const { getAccount, getDefaultAccount } = await import(
|
const { getAccount, getDefaultAccount } = await import(
|
||||||
'../../../src/cliproxy/account-manager'
|
'../account-manager'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.switchedFrom).toBe('preflight-exhausted@example.com');
|
expect(result.switchedFrom).toBe('preflight-exhausted@example.com');
|
||||||
@@ -647,10 +647,10 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
);
|
);
|
||||||
}) as typeof fetch;
|
}) as typeof fetch;
|
||||||
|
|
||||||
const { preflightCheck } = await import('../../../src/cliproxy/quota-manager');
|
const { preflightCheck } = await import('../../quota/quota-manager');
|
||||||
const result = await preflightCheck('codex');
|
const result = await preflightCheck('codex');
|
||||||
const { getAccount, getDefaultAccount } = await import(
|
const { getAccount, getDefaultAccount } = await import(
|
||||||
'../../../src/cliproxy/account-manager'
|
'../account-manager'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.switchedFrom).toBe('preflight-unknown-exhausted@example.com');
|
expect(result.switchedFrom).toBe('preflight-unknown-exhausted@example.com');
|
||||||
@@ -737,7 +737,7 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
|
|
||||||
const result = await handleQuotaExhaustion('gemini', 'gemini-exhausted@example.com', 10);
|
const result = await handleQuotaExhaustion('gemini', 'gemini-exhausted@example.com', 10);
|
||||||
const { getAccount, getDefaultAccount } = await import(
|
const { getAccount, getDefaultAccount } = await import(
|
||||||
'../../../src/cliproxy/account-manager'
|
'../account-manager'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.switchedTo).toBe('gemini-fallback@example.com');
|
expect(result.switchedTo).toBe('gemini-fallback@example.com');
|
||||||
@@ -805,7 +805,7 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
|
|
||||||
const result = await handleQuotaExhaustion('ghcp', 'ghcp-exhausted', 10);
|
const result = await handleQuotaExhaustion('ghcp', 'ghcp-exhausted', 10);
|
||||||
const { getAccount, getDefaultAccount } = await import(
|
const { getAccount, getDefaultAccount } = await import(
|
||||||
'../../../src/cliproxy/account-manager'
|
'../account-manager'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.switchedTo).toBe('ghcp-fallback');
|
expect(result.switchedTo).toBe('ghcp-fallback');
|
||||||
@@ -869,7 +869,7 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
|
|
||||||
const result = await handleQuotaExhaustion('ghcp', 'ghcp-partial-exhausted', 10);
|
const result = await handleQuotaExhaustion('ghcp', 'ghcp-partial-exhausted', 10);
|
||||||
const { getAccount, getDefaultAccount } = await import(
|
const { getAccount, getDefaultAccount } = await import(
|
||||||
'../../../src/cliproxy/account-manager'
|
'../account-manager'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.switchedTo).toBe('ghcp-partial-fallback');
|
expect(result.switchedTo).toBe('ghcp-partial-fallback');
|
||||||
@@ -986,7 +986,7 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
expect(pauseAccountForQuotaCooldown('agy', 'cooldown@gmail.com', 5, now)).toBe(true);
|
expect(pauseAccountForQuotaCooldown('agy', 'cooldown@gmail.com', 5, now)).toBe(true);
|
||||||
|
|
||||||
const { getAccount } = await import('../../../src/cliproxy/account-manager');
|
const { getAccount } = await import('../account-manager');
|
||||||
expect(getAccount('agy', 'cooldown@gmail.com')?.paused).toBe(true);
|
expect(getAccount('agy', 'cooldown@gmail.com')?.paused).toBe(true);
|
||||||
|
|
||||||
const resumed = restoreExpiredQuotaPauses(now + 6 * 60 * 1000);
|
const resumed = restoreExpiredQuotaPauses(now + 6 * 60 * 1000);
|
||||||
@@ -1030,7 +1030,7 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
fs.writeFileSync(registryPath, JSON.stringify(registry, null, 2));
|
fs.writeFileSync(registryPath, JSON.stringify(registry, null, 2));
|
||||||
|
|
||||||
const resumed = restoreExpiredQuotaPauses(now + 6 * 60 * 1000);
|
const resumed = restoreExpiredQuotaPauses(now + 6 * 60 * 1000);
|
||||||
const { getAccount } = await import('../../../src/cliproxy/account-manager');
|
const { getAccount } = await import('../account-manager');
|
||||||
|
|
||||||
expect(resumed).toBe(0);
|
expect(resumed).toBe(0);
|
||||||
expect(getAccount('agy', 'cooldown@gmail.com')?.paused).toBe(true);
|
expect(getAccount('agy', 'cooldown@gmail.com')?.paused).toBe(true);
|
||||||
@@ -1067,7 +1067,7 @@ describe('Quota Exhaustion Handlers', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const resumed = restoreExpiredQuotaPauses(now + 6 * 60 * 1000);
|
const resumed = restoreExpiredQuotaPauses(now + 6 * 60 * 1000);
|
||||||
const { getAccount } = await import('../../../src/cliproxy/account-manager');
|
const { getAccount } = await import('../account-manager');
|
||||||
const quotaPausedPath = path.join(tmpDir, '.ccs', 'cliproxy', 'quota-paused.json');
|
const quotaPausedPath = path.join(tmpDir, '.ccs', 'cliproxy', 'quota-paused.json');
|
||||||
const quotaPaused = JSON.parse(fs.readFileSync(quotaPausedPath, 'utf8')) as {
|
const quotaPaused = JSON.parse(fs.readFileSync(quotaPausedPath, 'utf8')) as {
|
||||||
entries?: Array<{ accountId?: string }>;
|
entries?: Array<{ accountId?: string }>;
|
||||||
+1
-1
@@ -19,7 +19,7 @@ import {
|
|||||||
checkNewAccountConflict,
|
checkNewAccountConflict,
|
||||||
handleBanDetection,
|
handleBanDetection,
|
||||||
warnCrossProviderDuplicates,
|
warnCrossProviderDuplicates,
|
||||||
} from '../../../src/cliproxy/account-safety';
|
} from '../../accounts/account-safety';
|
||||||
|
|
||||||
// --- Test isolation: use temp CCS_HOME ---
|
// --- Test isolation: use temp CCS_HOME ---
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ export type {
|
|||||||
ProviderAccounts,
|
ProviderAccounts,
|
||||||
BulkOperationResult,
|
BulkOperationResult,
|
||||||
SoloOperationResult,
|
SoloOperationResult,
|
||||||
} from './accounts';
|
} from '.';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
PROVIDERS_WITHOUT_EMAIL,
|
PROVIDERS_WITHOUT_EMAIL,
|
||||||
@@ -56,4 +56,4 @@ export {
|
|||||||
bulkPauseAccounts,
|
bulkPauseAccounts,
|
||||||
bulkResumeAccounts,
|
bulkResumeAccounts,
|
||||||
soloAccount,
|
soloAccount,
|
||||||
} from './accounts';
|
} from '.';
|
||||||
@@ -11,10 +11,10 @@
|
|||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { warn, info } from '../utils/ui';
|
import { warn, info } from '../../utils/ui';
|
||||||
import { CLIProxyProvider } from './types';
|
import { CLIProxyProvider } from '../types';
|
||||||
import { loadAccountsRegistry, pauseAccount, resumeAccount } from './accounts/registry';
|
import { loadAccountsRegistry, pauseAccount, resumeAccount } from './registry';
|
||||||
import { getCcsDir } from '../utils/config-manager';
|
import { getCcsDir } from '../../utils/config-manager';
|
||||||
|
|
||||||
const ISSUE_509_URL = 'https://github.com/kaitranntt/ccs/issues/509';
|
const ISSUE_509_URL = 'https://github.com/kaitranntt/ccs/issues/509';
|
||||||
|
|
||||||
@@ -688,9 +688,9 @@ export async function handleQuotaExhaustion(
|
|||||||
cooldownMinutes: number
|
cooldownMinutes: number
|
||||||
): Promise<{ switchedTo: string | null; reason: string }> {
|
): Promise<{ switchedTo: string | null; reason: string }> {
|
||||||
// Dynamic imports to avoid circular dependencies
|
// Dynamic imports to avoid circular dependencies
|
||||||
const { applyCooldown, findHealthyAccount } = await import('./quota-manager');
|
const { applyCooldown, findHealthyAccount } = await import('../quota/quota-manager');
|
||||||
const { setDefaultAccount, touchAccount } = await import('./account-manager');
|
const { setDefaultAccount, touchAccount } = await import('./account-manager');
|
||||||
const { loadOrCreateUnifiedConfig } = await import('../config/unified-config-loader');
|
const { loadOrCreateUnifiedConfig } = await import('../../config/unified-config-loader');
|
||||||
const config = loadOrCreateUnifiedConfig();
|
const config = loadOrCreateUnifiedConfig();
|
||||||
const threshold = config.quota_management?.auto?.exhaustion_threshold ?? 5;
|
const threshold = config.quota_management?.auto?.exhaustion_threshold ?? 5;
|
||||||
|
|
||||||
File renamed without changes.
@@ -8,7 +8,7 @@ import * as path from 'path';
|
|||||||
import * as lockfile from 'proper-lockfile';
|
import * as lockfile from 'proper-lockfile';
|
||||||
import { CLIProxyProvider } from '../types';
|
import { CLIProxyProvider } from '../types';
|
||||||
import { PROVIDER_TYPE_VALUES } from '../auth/auth-types';
|
import { PROVIDER_TYPE_VALUES } from '../auth/auth-types';
|
||||||
import { getAuthDir, getCliproxyDir } from '../config-generator';
|
import { getAuthDir, getCliproxyDir } from '../config/config-generator';
|
||||||
import { AccountsRegistry, AccountInfo, PROVIDERS_WITHOUT_EMAIL } from './types';
|
import { AccountsRegistry, AccountInfo, PROVIDERS_WITHOUT_EMAIL } from './types';
|
||||||
import {
|
import {
|
||||||
getAccountsRegistryPath,
|
getAccountsRegistryPath,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { getCliproxyDir, getAuthDir } from '../config-generator';
|
import { getCliproxyDir, getAuthDir } from '../config/config-generator';
|
||||||
import type { CLIProxyProvider } from '../types';
|
import type { CLIProxyProvider } from '../types';
|
||||||
import { AccountInfo } from './types';
|
import { AccountInfo } from './types';
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@ import * as fs from 'fs';
|
|||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { afterEach, describe, expect, it, mock, spyOn } from 'bun:test';
|
import { afterEach, describe, expect, it, mock, spyOn } from 'bun:test';
|
||||||
import { clearQuotaCache } from '../../../src/cliproxy/quota-response-cache';
|
import { clearQuotaCache } from '../../quota/quota-response-cache';
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
clearQuotaCache();
|
clearQuotaCache();
|
||||||
@@ -39,7 +39,7 @@ function createCodexSettingsFixture(haikuModel: string = 'gpt-5.4-mini'): {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function importCompatibilityModule(cacheTag: string) {
|
async function importCompatibilityModule(cacheTag: string) {
|
||||||
return import(`../../../src/cliproxy/codex-plan-compatibility?${cacheTag}=${Date.now()}`);
|
return import(`../../codex-plan-compatibility?${cacheTag}=${Date.now()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const identity = (message: string) => message;
|
const identity = (message: string) => message;
|
||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
import { describe, expect, it } from 'bun:test';
|
import { describe, expect, it } from 'bun:test';
|
||||||
import { getProviderCatalog, getModelMaxLevel } from '../../../src/cliproxy/model-catalog';
|
import { getProviderCatalog, getModelMaxLevel } from '../../model-catalog';
|
||||||
import {
|
import {
|
||||||
getDefaultCodexModel,
|
getDefaultCodexModel,
|
||||||
getFreePlanFallbackCodexModel,
|
getFreePlanFallbackCodexModel,
|
||||||
parseCodexUnsupportedModelError,
|
parseCodexUnsupportedModelError,
|
||||||
resolveRuntimeCodexFallbackModel,
|
resolveRuntimeCodexFallbackModel,
|
||||||
} from '../../../src/cliproxy/codex-plan-compatibility';
|
} from '../../ai-providers/codex-plan-compatibility';
|
||||||
|
|
||||||
describe('codex plan compatibility', () => {
|
describe('codex plan compatibility', () => {
|
||||||
it('uses a cross-plan safe Codex default', () => {
|
it('uses a cross-plan safe Codex default', () => {
|
||||||
+2
-2
@@ -4,12 +4,12 @@ import {
|
|||||||
buildCodexModelEffortMap,
|
buildCodexModelEffortMap,
|
||||||
CodexReasoningProxy,
|
CodexReasoningProxy,
|
||||||
getEffortForModel,
|
getEffortForModel,
|
||||||
} from '../../../src/cliproxy/codex-reasoning-proxy';
|
} from '../../ai-providers/codex-reasoning-proxy';
|
||||||
import {
|
import {
|
||||||
parseEnvThinkingOverride,
|
parseEnvThinkingOverride,
|
||||||
resolveRuntimeThinkingOverride,
|
resolveRuntimeThinkingOverride,
|
||||||
shouldDisableCodexReasoning,
|
shouldDisableCodexReasoning,
|
||||||
} from '../../../src/cliproxy/executor/thinking-override-resolver';
|
} from '../../executor/thinking-override-resolver';
|
||||||
|
|
||||||
type JsonRecord = Record<string, unknown>;
|
type JsonRecord = Record<string, unknown>;
|
||||||
|
|
||||||
+1
-1
@@ -4,7 +4,7 @@ const {
|
|||||||
buildCodexModelEffortMap,
|
buildCodexModelEffortMap,
|
||||||
getEffortForModel,
|
getEffortForModel,
|
||||||
injectReasoningEffortIntoBody,
|
injectReasoningEffortIntoBody,
|
||||||
} = require('../../../dist/cliproxy/codex-reasoning-proxy');
|
} = require('../../../../dist/cliproxy/codex-reasoning-proxy');
|
||||||
|
|
||||||
describe('Codex Reasoning Proxy', () => {
|
describe('Codex Reasoning Proxy', () => {
|
||||||
describe('buildCodexModelEffortMap', () => {
|
describe('buildCodexModelEffortMap', () => {
|
||||||
+1
-1
@@ -7,7 +7,7 @@ import {
|
|||||||
applyExtendedContextSuffix,
|
applyExtendedContextSuffix,
|
||||||
shouldApplyExtendedContext,
|
shouldApplyExtendedContext,
|
||||||
applyExtendedContextConfig,
|
applyExtendedContextConfig,
|
||||||
} from '../../../src/cliproxy/config/extended-context-config';
|
} from '../../config/extended-context-config';
|
||||||
|
|
||||||
describe('applyExtendedContextSuffix', () => {
|
describe('applyExtendedContextSuffix', () => {
|
||||||
it('appends [1m] to model without suffix', () => {
|
it('appends [1m] to model without suffix', () => {
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
import { afterEach, describe, expect, it, mock } from 'bun:test';
|
import { afterEach, describe, expect, it, mock } from 'bun:test';
|
||||||
import { ensureManagedModelPrefixes } from '../../../src/cliproxy/managed-model-prefixes';
|
import { ensureManagedModelPrefixes } from '../managed-model-prefixes';
|
||||||
|
|
||||||
const originalFetch = global.fetch;
|
const originalFetch = global.fetch;
|
||||||
|
|
||||||
+1
-1
@@ -12,7 +12,7 @@ import {
|
|||||||
normalizeModelIdForProvider,
|
normalizeModelIdForProvider,
|
||||||
normalizeModelIdForRouting,
|
normalizeModelIdForRouting,
|
||||||
normalizeModelEnvVarsForProvider,
|
normalizeModelEnvVarsForProvider,
|
||||||
} from '../../../src/cliproxy/model-id-normalizer';
|
} from '../model-id-normalizer';
|
||||||
|
|
||||||
describe('model-id-normalizer', () => {
|
describe('model-id-normalizer', () => {
|
||||||
describe('provider parsing', () => {
|
describe('provider parsing', () => {
|
||||||
+1
-1
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'bun:test';
|
|||||||
import {
|
import {
|
||||||
buildCliproxyRoutingHints,
|
buildCliproxyRoutingHints,
|
||||||
getManagedModelPrefix,
|
getManagedModelPrefix,
|
||||||
} from '../../../src/shared/cliproxy-model-routing';
|
} from '../../../shared/cliproxy-model-routing';
|
||||||
|
|
||||||
describe('cliproxy model routing hints', () => {
|
describe('cliproxy model routing hints', () => {
|
||||||
it('uses short managed prefixes for overlapping Gemini and Antigravity models', () => {
|
it('uses short managed prefixes for overlapping Gemini and Antigravity models', () => {
|
||||||
+5
-5
@@ -17,12 +17,12 @@ describe('openai-compat manager', () => {
|
|||||||
process.env.CCS_HOME = testDir;
|
process.env.CCS_HOME = testDir;
|
||||||
process.env.CCS_DIR = path.join(testDir, '.ccs');
|
process.env.CCS_DIR = path.join(testDir, '.ccs');
|
||||||
|
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/config-generator')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')];
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/openai-compat-manager')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/openai-compat-manager')];
|
||||||
delete require.cache[require.resolve('../../../dist/utils/config-manager')];
|
delete require.cache[require.resolve('../../../../dist/utils/config-manager')];
|
||||||
|
|
||||||
configGenerator = require('../../../dist/cliproxy/config-generator');
|
configGenerator = require('../../../../dist/cliproxy/config-generator');
|
||||||
openAICompatManager = require('../../../dist/cliproxy/openai-compat-manager');
|
openAICompatManager = require('../../../../dist/cliproxy/openai-compat-manager');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { describe, expect, test } from 'bun:test';
|
import { describe, expect, test } from 'bun:test';
|
||||||
import { sanitizeInputSchema, sanitizeToolSchemas } from '../../../src/cliproxy/schema-sanitizer';
|
import { sanitizeInputSchema, sanitizeToolSchemas } from '../schema-sanitizer';
|
||||||
|
|
||||||
describe('sanitizeInputSchema', () => {
|
describe('sanitizeInputSchema', () => {
|
||||||
test('preserves Gemini-supported properties', () => {
|
test('preserves Gemini-supported properties', () => {
|
||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
|
||||||
const { ToolNameMapper } = require('../../../dist/cliproxy/tool-name-mapper');
|
const { ToolNameMapper } = require('../../../../dist/cliproxy/tool-name-mapper');
|
||||||
|
|
||||||
describe('Tool Name Mapper', () => {
|
describe('Tool Name Mapper', () => {
|
||||||
describe('registerTools', () => {
|
describe('registerTools', () => {
|
||||||
+1
-1
@@ -10,7 +10,7 @@ const {
|
|||||||
smartTruncate,
|
smartTruncate,
|
||||||
sanitizeToolName,
|
sanitizeToolName,
|
||||||
GEMINI_MAX_TOOL_NAME_LENGTH,
|
GEMINI_MAX_TOOL_NAME_LENGTH,
|
||||||
} = require('../../../dist/cliproxy/tool-name-sanitizer');
|
} = require('../../../../dist/cliproxy/tool-name-sanitizer');
|
||||||
|
|
||||||
describe('Tool Name Sanitizer', () => {
|
describe('Tool Name Sanitizer', () => {
|
||||||
describe('GEMINI_MAX_TOOL_NAME_LENGTH', () => {
|
describe('GEMINI_MAX_TOOL_NAME_LENGTH', () => {
|
||||||
+6
-6
@@ -1,10 +1,10 @@
|
|||||||
import { getDefaultAccount } from './account-manager';
|
import { getDefaultAccount } from '../accounts/account-manager';
|
||||||
import { getProviderCatalog } from './model-catalog';
|
import { getProviderCatalog } from '../model-catalog';
|
||||||
import { normalizeModelIdForProvider } from './model-id-normalizer';
|
import { normalizeModelIdForProvider } from './model-id-normalizer';
|
||||||
import { fetchCodexQuota } from './quota-fetcher-codex';
|
import { fetchCodexQuota } from '../quota/quota-fetcher-codex';
|
||||||
import { getCachedQuota, setCachedQuota } from './quota-response-cache';
|
import { getCachedQuota, setCachedQuota } from '../quota/quota-response-cache';
|
||||||
import type { CodexQuotaResult } from './quota-types';
|
import type { CodexQuotaResult } from '../quota/quota-types';
|
||||||
import { info, warn } from '../utils/ui';
|
import { info, warn } from '../../utils/ui';
|
||||||
|
|
||||||
export type CodexPlanType = CodexQuotaResult['planType'];
|
export type CodexPlanType = CodexQuotaResult['planType'];
|
||||||
|
|
||||||
+1
-1
@@ -6,7 +6,7 @@ import {
|
|||||||
parseCodexUnsupportedModelError,
|
parseCodexUnsupportedModelError,
|
||||||
resolveRuntimeCodexFallbackModel,
|
resolveRuntimeCodexFallbackModel,
|
||||||
} from './codex-plan-compatibility';
|
} from './codex-plan-compatibility';
|
||||||
import { getModelMaxLevel } from './model-catalog';
|
import { getModelMaxLevel } from '../model-catalog';
|
||||||
|
|
||||||
export type CodexReasoningEffort = 'medium' | 'high' | 'xhigh';
|
export type CodexReasoningEffort = 'medium' | 'high' | 'xhigh';
|
||||||
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { randomUUID } from 'crypto';
|
import { randomUUID } from 'crypto';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as yaml from 'js-yaml';
|
import * as yaml from 'js-yaml';
|
||||||
import { configExists, getCliproxyConfigPath, regenerateConfig } from '../config-generator';
|
import { configExists, getCliproxyConfigPath, regenerateConfig } from '../config/config-generator';
|
||||||
import { getProxyTarget } from '../proxy-target-resolver';
|
import { getProxyTarget } from '../proxy/proxy-target-resolver';
|
||||||
import { createManagementClient } from '../management-api-client';
|
import { createManagementClient } from '../management/management-api-client';
|
||||||
import { rewriteTopLevelYamlSection } from './config-yaml-sections';
|
import { rewriteTopLevelYamlSection } from './config-yaml-sections';
|
||||||
import type {
|
import type {
|
||||||
AiProviderApiKeyEntry,
|
AiProviderApiKeyEntry,
|
||||||
|
|||||||
+4
-4
@@ -1,7 +1,7 @@
|
|||||||
import { getManagedModelPrefix } from '../shared/cliproxy-model-routing';
|
import { getManagedModelPrefix } from '../../shared/cliproxy-model-routing';
|
||||||
import { buildManagementHeaders, buildProxyUrl, getProxyTarget } from './proxy-target-resolver';
|
import { buildManagementHeaders, buildProxyUrl, getProxyTarget } from '../proxy/proxy-target-resolver';
|
||||||
import { mapExternalProviderName } from './provider-capabilities';
|
import { mapExternalProviderName } from '../provider-capabilities';
|
||||||
import type { CLIProxyProvider } from './types';
|
import type { CLIProxyProvider } from '../types';
|
||||||
|
|
||||||
const MANAGED_PREFIX_REQUEST_TIMEOUT_MS = 3000;
|
const MANAGED_PREFIX_REQUEST_TIMEOUT_MS = 3000;
|
||||||
|
|
||||||
+2
-2
@@ -5,8 +5,8 @@
|
|||||||
* model version formats (e.g., 4.6 vs 4-6).
|
* model version formats (e.g., 4.6 vs 4-6).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { CLIProxyProvider } from './types';
|
import type { CLIProxyProvider } from '../types';
|
||||||
import { ANTHROPIC_MODEL_ENV_KEYS } from '../shared/extended-context-utils';
|
import { ANTHROPIC_MODEL_ENV_KEYS } from '../../shared/extended-context-utils';
|
||||||
|
|
||||||
/** Env vars that carry model identifiers. */
|
/** Env vars that carry model identifiers. */
|
||||||
export const MODEL_ENV_VAR_KEYS = ANTHROPIC_MODEL_ENV_KEYS;
|
export const MODEL_ENV_VAR_KEYS = ANTHROPIC_MODEL_ENV_KEYS;
|
||||||
+3
-2
@@ -7,8 +7,9 @@
|
|||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as yaml from 'js-yaml';
|
import * as yaml from 'js-yaml';
|
||||||
import { configExists, getCliproxyConfigPath, regenerateConfig } from './config-generator';
|
import { configExists, regenerateConfig } from '../config/generator';
|
||||||
import { rewriteTopLevelYamlSection } from './ai-providers/config-yaml-sections';
|
import { getCliproxyConfigPath } from '../config/path-resolver';
|
||||||
|
import { rewriteTopLevelYamlSection } from './config-yaml-sections';
|
||||||
|
|
||||||
/** Model alias configuration */
|
/** Model alias configuration */
|
||||||
export interface OpenAICompatModel {
|
export interface OpenAICompatModel {
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -8,7 +8,7 @@ import {
|
|||||||
hasAntigravityRiskAcceptanceFlag,
|
hasAntigravityRiskAcceptanceFlag,
|
||||||
isAntigravityResponsibilityBypassEnabled,
|
isAntigravityResponsibilityBypassEnabled,
|
||||||
validateAntigravityRiskAcknowledgement,
|
validateAntigravityRiskAcknowledgement,
|
||||||
} from '../../../src/cliproxy/antigravity-responsibility';
|
} from '../../auth/antigravity-responsibility';
|
||||||
|
|
||||||
describe('antigravity-responsibility', () => {
|
describe('antigravity-responsibility', () => {
|
||||||
let tempHome = '';
|
let tempHome = '';
|
||||||
+4
-4
@@ -19,8 +19,8 @@ describe('Auth Token Manager', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// Clear cache and reload
|
// Clear cache and reload
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/auth-token-manager')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/auth-token-manager')];
|
||||||
const authTokenManager = require('../../../dist/cliproxy/auth-token-manager');
|
const authTokenManager = require('../../../../dist/cliproxy/auth-token-manager');
|
||||||
generateSecureToken = authTokenManager.generateSecureToken;
|
generateSecureToken = authTokenManager.generateSecureToken;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -398,8 +398,8 @@ describe('Auth Token Manager', () => {
|
|||||||
let CCS_CONTROL_PANEL_SECRET;
|
let CCS_CONTROL_PANEL_SECRET;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/config-generator')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')];
|
||||||
const configGenerator = require('../../../dist/cliproxy/config-generator');
|
const configGenerator = require('../../../../dist/cliproxy/config-generator');
|
||||||
CCS_INTERNAL_API_KEY = configGenerator.CCS_INTERNAL_API_KEY;
|
CCS_INTERNAL_API_KEY = configGenerator.CCS_INTERNAL_API_KEY;
|
||||||
CCS_CONTROL_PANEL_SECRET = configGenerator.CCS_CONTROL_PANEL_SECRET;
|
CCS_CONTROL_PANEL_SECRET = configGenerator.CCS_CONTROL_PANEL_SECRET;
|
||||||
});
|
});
|
||||||
+1
-1
@@ -3,7 +3,7 @@ import {
|
|||||||
getManagementAuthUrlPath,
|
getManagementAuthUrlPath,
|
||||||
getPasteCallbackStartPath,
|
getPasteCallbackStartPath,
|
||||||
getManagementOAuthCallbackPath,
|
getManagementOAuthCallbackPath,
|
||||||
} from '../../../src/cliproxy/auth/auth-types';
|
} from '../auth-types';
|
||||||
|
|
||||||
describe('auth-types paste-callback start path', () => {
|
describe('auth-types paste-callback start path', () => {
|
||||||
it('maps providers to CLIProxyAPI management auth-url routes', () => {
|
it('maps providers to CLIProxyAPI management auth-url routes', () => {
|
||||||
+1
-1
@@ -9,7 +9,7 @@ import {
|
|||||||
getTokenExpiryTimestamp,
|
getTokenExpiryTimestamp,
|
||||||
isTokenExpired,
|
isTokenExpired,
|
||||||
sanitizeEmail,
|
sanitizeEmail,
|
||||||
} from '../../../src/cliproxy/auth-utils';
|
} from '../../auth/auth-utils';
|
||||||
|
|
||||||
describe('Auth Utilities', () => {
|
describe('Auth Utilities', () => {
|
||||||
describe('sanitizeEmail', () => {
|
describe('sanitizeEmail', () => {
|
||||||
File renamed without changes.
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
import { describe, expect, it } from 'bun:test';
|
import { describe, expect, it } from 'bun:test';
|
||||||
import { parseGitLabPatAuthResponse } from '../../../src/cliproxy/auth/gitlab-pat-response';
|
import { parseGitLabPatAuthResponse } from '../gitlab-pat-response';
|
||||||
|
|
||||||
describe('parseGitLabPatAuthResponse', () => {
|
describe('parseGitLabPatAuthResponse', () => {
|
||||||
it('sanitizes HTML error bodies for non-ok responses', () => {
|
it('sanitizes HTML error bodies for non-ok responses', () => {
|
||||||
+20
-20
@@ -2,9 +2,9 @@ import { afterEach, describe, expect, it, mock, spyOn } from 'bun:test';
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import type { ProxyTarget } from '../../../src/cliproxy/proxy-target-resolver';
|
import type { ProxyTarget } from '../../proxy/proxy-target-resolver';
|
||||||
import { InteractivePrompt } from '../../../src/utils/prompt';
|
import { InteractivePrompt } from '../../../utils/prompt';
|
||||||
import { getCapturedFetchRequests, mockFetch, restoreFetch } from '../../mocks';
|
import { getCapturedFetchRequests, mockFetch, restoreFetch } from '../../../../tests/mocks';
|
||||||
|
|
||||||
const remoteTarget: ProxyTarget = {
|
const remoteTarget: ProxyTarget = {
|
||||||
host: 'proxy.example.com',
|
host: 'proxy.example.com',
|
||||||
@@ -28,7 +28,7 @@ describe('requestPasteCallbackStart', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const { requestPasteCallbackStart } = await import(
|
const { requestPasteCallbackStart } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?request-claude-start=${Date.now()}`
|
`../oauth-handler?request-claude-start=${Date.now()}`
|
||||||
);
|
);
|
||||||
const startData = await requestPasteCallbackStart('claude', remoteTarget);
|
const startData = await requestPasteCallbackStart('claude', remoteTarget);
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ describe('requestPasteCallbackStart', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const { requestPasteCallbackStart } = await import(
|
const { requestPasteCallbackStart } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?request-kiro-start=${Date.now()}`
|
`../oauth-handler?request-kiro-start=${Date.now()}`
|
||||||
);
|
);
|
||||||
const startData = await requestPasteCallbackStart('kiro', remoteTarget, {
|
const startData = await requestPasteCallbackStart('kiro', remoteTarget, {
|
||||||
kiroMethod: 'aws',
|
kiroMethod: 'aws',
|
||||||
@@ -71,7 +71,7 @@ describe('requestPasteCallbackStart', () => {
|
|||||||
|
|
||||||
it('throws for Kiro methods that require the local callback server flow', async () => {
|
it('throws for Kiro methods that require the local callback server flow', async () => {
|
||||||
const { requestPasteCallbackStart } = await import(
|
const { requestPasteCallbackStart } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?request-kiro-authcode-start=${Date.now()}`
|
`../oauth-handler?request-kiro-authcode-start=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
@@ -83,7 +83,7 @@ describe('requestPasteCallbackStart', () => {
|
|||||||
describe('usesKiroLocalCallbackReplay', () => {
|
describe('usesKiroLocalCallbackReplay', () => {
|
||||||
it('limits local callback replay to CLI auth-code flows', async () => {
|
it('limits local callback replay to CLI auth-code flows', async () => {
|
||||||
const { usesKiroLocalCallbackReplay } = await import(
|
const { usesKiroLocalCallbackReplay } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?kiro-local-callback-mode=${Date.now()}`
|
`../oauth-handler?kiro-local-callback-mode=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(usesKiroLocalCallbackReplay('aws-authcode', 'authcode')).toBe(true);
|
expect(usesKiroLocalCallbackReplay('aws-authcode', 'authcode')).toBe(true);
|
||||||
@@ -97,7 +97,7 @@ describe('usesKiroLocalCallbackReplay', () => {
|
|||||||
describe('resolvePasteCallbackAuthUrl', () => {
|
describe('resolvePasteCallbackAuthUrl', () => {
|
||||||
it('returns the immediate auth URL without polling', async () => {
|
it('returns the immediate auth URL without polling', async () => {
|
||||||
const { resolvePasteCallbackAuthUrl } = await import(
|
const { resolvePasteCallbackAuthUrl } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?resolve-immediate-auth-url=${Date.now()}`
|
`../oauth-handler?resolve-immediate-auth-url=${Date.now()}`
|
||||||
);
|
);
|
||||||
const authUrl = await resolvePasteCallbackAuthUrl(
|
const authUrl = await resolvePasteCallbackAuthUrl(
|
||||||
remoteTarget,
|
remoteTarget,
|
||||||
@@ -119,7 +119,7 @@ describe('resolvePasteCallbackAuthUrl', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const { resolvePasteCallbackAuthUrl } = await import(
|
const { resolvePasteCallbackAuthUrl } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?resolve-polled-auth-url=${Date.now()}`
|
`../oauth-handler?resolve-polled-auth-url=${Date.now()}`
|
||||||
);
|
);
|
||||||
const authUrl = await resolvePasteCallbackAuthUrl(remoteTarget, { state: 'state-123' }, 50, 0);
|
const authUrl = await resolvePasteCallbackAuthUrl(remoteTarget, { state: 'state-123' }, 50, 0);
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ describe('findNewTokenSnapshotForManualAuth', () => {
|
|||||||
const existingMtimeMs = fs.statSync(existingFile).mtimeMs;
|
const existingMtimeMs = fs.statSync(existingFile).mtimeMs;
|
||||||
|
|
||||||
const { findNewTokenSnapshotForManualAuth } = await import(
|
const { findNewTokenSnapshotForManualAuth } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?manual-auth-new-token=${Date.now()}`
|
`../oauth-handler?manual-auth-new-token=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
const newFile = path.join(tokenDir, 'kiro-new.json');
|
const newFile = path.join(tokenDir, 'kiro-new.json');
|
||||||
@@ -165,7 +165,7 @@ describe('findNewTokenSnapshotForManualAuth', () => {
|
|||||||
const existingMtimeMs = fs.statSync(tokenFile).mtimeMs;
|
const existingMtimeMs = fs.statSync(tokenFile).mtimeMs;
|
||||||
|
|
||||||
const { findNewTokenSnapshotForManualAuth } = await import(
|
const { findNewTokenSnapshotForManualAuth } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?manual-auth-updated-token=${Date.now()}`
|
`../oauth-handler?manual-auth-updated-token=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
fs.writeFileSync(tokenFile, JSON.stringify({ type: 'kiro', email: 'existing@example.com', refreshed: true }));
|
fs.writeFileSync(tokenFile, JSON.stringify({ type: 'kiro', email: 'existing@example.com', refreshed: true }));
|
||||||
@@ -187,7 +187,7 @@ describe('findNewTokenSnapshotForManualAuth', () => {
|
|||||||
describe('getCliAuthNicknameError', () => {
|
describe('getCliAuthNicknameError', () => {
|
||||||
it('allows omitted nicknames for no-email providers', async () => {
|
it('allows omitted nicknames for no-email providers', async () => {
|
||||||
const { getCliAuthNicknameError } = await import(
|
const { getCliAuthNicknameError } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?cli-nickname-empty=${Date.now()}`
|
`../oauth-handler?cli-nickname-empty=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(getCliAuthNicknameError('kiro', undefined, [])).toBeNull();
|
expect(getCliAuthNicknameError('kiro', undefined, [])).toBeNull();
|
||||||
@@ -196,7 +196,7 @@ describe('getCliAuthNicknameError', () => {
|
|||||||
|
|
||||||
it('rejects invalid supplied nicknames before OAuth starts', async () => {
|
it('rejects invalid supplied nicknames before OAuth starts', async () => {
|
||||||
const { getCliAuthNicknameError } = await import(
|
const { getCliAuthNicknameError } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?cli-nickname-invalid=${Date.now()}`
|
`../oauth-handler?cli-nickname-invalid=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(getCliAuthNicknameError('kiro', 'bad nickname', [])).toBe(
|
expect(getCliAuthNicknameError('kiro', 'bad nickname', [])).toBe(
|
||||||
@@ -206,7 +206,7 @@ describe('getCliAuthNicknameError', () => {
|
|||||||
|
|
||||||
it('rejects supplied nicknames that collide with existing ids or nicknames', async () => {
|
it('rejects supplied nicknames that collide with existing ids or nicknames', async () => {
|
||||||
const { getCliAuthNicknameError } = await import(
|
const { getCliAuthNicknameError } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?cli-nickname-conflict=${Date.now()}`
|
`../oauth-handler?cli-nickname-conflict=${Date.now()}`
|
||||||
);
|
);
|
||||||
const existingAccounts = [
|
const existingAccounts = [
|
||||||
{ id: 'github-ABC123', nickname: 'work' },
|
{ id: 'github-ABC123', nickname: 'work' },
|
||||||
@@ -223,7 +223,7 @@ describe('getCliAuthNicknameError', () => {
|
|||||||
|
|
||||||
it('allows reauth when the supplied nickname already belongs to the same account', async () => {
|
it('allows reauth when the supplied nickname already belongs to the same account', async () => {
|
||||||
const { getCliAuthNicknameError } = await import(
|
const { getCliAuthNicknameError } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?cli-nickname-reauth=${Date.now()}`
|
`../oauth-handler?cli-nickname-reauth=${Date.now()}`
|
||||||
);
|
);
|
||||||
const existingAccounts = [
|
const existingAccounts = [
|
||||||
{ id: 'github-ABC123', nickname: 'work' },
|
{ id: 'github-ABC123', nickname: 'work' },
|
||||||
@@ -242,7 +242,7 @@ describe('promptGitLabPersonalAccessToken', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { promptGitLabPersonalAccessToken } = await import(
|
const { promptGitLabPersonalAccessToken } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?gitlab-pat-prompt=${Date.now()}`
|
`../oauth-handler?gitlab-pat-prompt=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(promptGitLabPersonalAccessToken()).resolves.toBe('glpat-secret-token');
|
await expect(promptGitLabPersonalAccessToken()).resolves.toBe('glpat-secret-token');
|
||||||
@@ -255,7 +255,7 @@ describe('promptGitLabPersonalAccessToken', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { promptGitLabPersonalAccessToken } = await import(
|
const { promptGitLabPersonalAccessToken } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?gitlab-pat-prompt-blank=${Date.now()}`
|
`../oauth-handler?gitlab-pat-prompt-blank=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(promptGitLabPersonalAccessToken()).resolves.toBeNull();
|
await expect(promptGitLabPersonalAccessToken()).resolves.toBeNull();
|
||||||
@@ -266,7 +266,7 @@ describe('promptGitLabPersonalAccessToken', () => {
|
|||||||
describe('normalizeGitLabBaseUrl', () => {
|
describe('normalizeGitLabBaseUrl', () => {
|
||||||
it('returns undefined for blank values', async () => {
|
it('returns undefined for blank values', async () => {
|
||||||
const { normalizeGitLabBaseUrl } = await import(
|
const { normalizeGitLabBaseUrl } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?gitlab-url-empty=${Date.now()}`
|
`../oauth-handler?gitlab-url-empty=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(normalizeGitLabBaseUrl(undefined)).toBeUndefined();
|
expect(normalizeGitLabBaseUrl(undefined)).toBeUndefined();
|
||||||
@@ -275,7 +275,7 @@ describe('normalizeGitLabBaseUrl', () => {
|
|||||||
|
|
||||||
it('normalizes whitespace and trailing slashes for self-hosted URLs', async () => {
|
it('normalizes whitespace and trailing slashes for self-hosted URLs', async () => {
|
||||||
const { normalizeGitLabBaseUrl } = await import(
|
const { normalizeGitLabBaseUrl } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?gitlab-url-normalize=${Date.now()}`
|
`../oauth-handler?gitlab-url-normalize=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(normalizeGitLabBaseUrl(' https://gitlab.example.com/custom/ ')).toBe(
|
expect(normalizeGitLabBaseUrl(' https://gitlab.example.com/custom/ ')).toBe(
|
||||||
@@ -285,7 +285,7 @@ describe('normalizeGitLabBaseUrl', () => {
|
|||||||
|
|
||||||
it('rejects malformed or scheme-less URLs before hitting CLIProxy', async () => {
|
it('rejects malformed or scheme-less URLs before hitting CLIProxy', async () => {
|
||||||
const { normalizeGitLabBaseUrl } = await import(
|
const { normalizeGitLabBaseUrl } = await import(
|
||||||
`../../../src/cliproxy/auth/oauth-handler?gitlab-url-invalid=${Date.now()}`
|
`../oauth-handler?gitlab-url-invalid=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(() => normalizeGitLabBaseUrl('gitlab.example.com')).toThrow(
|
expect(() => normalizeGitLabBaseUrl('gitlab.example.com')).toThrow(
|
||||||
+1
-1
@@ -7,7 +7,7 @@ import {
|
|||||||
getExpectedLocalCallback,
|
getExpectedLocalCallback,
|
||||||
getKiroBuilderIdSelectionInput,
|
getKiroBuilderIdSelectionInput,
|
||||||
validateManualCallbackUrl,
|
validateManualCallbackUrl,
|
||||||
} from '../../../src/cliproxy/auth/oauth-process';
|
} from '../oauth-process';
|
||||||
|
|
||||||
describe('oauth-process stderr parsing', () => {
|
describe('oauth-process stderr parsing', () => {
|
||||||
it('does not match provider-specific patterns for other providers', () => {
|
it('does not match provider-specific patterns for other providers', () => {
|
||||||
+2
-2
@@ -7,8 +7,8 @@ import * as assert from 'assert';
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
describe('Profile Mapper', () => {
|
describe('Profile Mapper', () => {
|
||||||
const profileMapper = require('../../../dist/cliproxy/sync/profile-mapper');
|
const profileMapper = require('../../../../dist/cliproxy/sync/profile-mapper');
|
||||||
const profileReader = require('../../../dist/api/services/profile-reader');
|
const profileReader = require('../../../../dist/api/services/profile-reader');
|
||||||
|
|
||||||
describe('mapProfileToClaudeKey', () => {
|
describe('mapProfileToClaudeKey', () => {
|
||||||
it('returns null when env is missing', () => {
|
it('returns null when env is missing', () => {
|
||||||
File renamed without changes.
+2
-2
@@ -9,8 +9,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { createInterface, Interface } from 'readline';
|
import { createInterface, Interface } from 'readline';
|
||||||
import { fail, info, ok, warn } from '../utils/ui';
|
import { fail, info, ok, warn } from '../../utils/ui';
|
||||||
import { getCliproxySafetyConfig } from '../config/unified-config-loader';
|
import { getCliproxySafetyConfig } from '../../config/unified-config-loader';
|
||||||
|
|
||||||
export const ANTIGRAVITY_RISK_ISSUE_URL = 'https://github.com/kaitranntt/ccs/issues/509';
|
export const ANTIGRAVITY_RISK_ISSUE_URL = 'https://github.com/kaitranntt/ccs/issues/509';
|
||||||
export const ANTIGRAVITY_ACK_VERSION = '2026-02-24-antigravity-oauth-v2';
|
export const ANTIGRAVITY_ACK_VERSION = '2026-02-24-antigravity-oauth-v2';
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Re-export types
|
// Re-export types
|
||||||
export type { AuthStatus, ProviderOAuthConfig, OAuthOptions } from './auth';
|
export type { AuthStatus, ProviderOAuthConfig, OAuthOptions } from '.';
|
||||||
|
|
||||||
// Re-export configurations
|
// Re-export configurations
|
||||||
export {
|
export {
|
||||||
@@ -29,7 +29,7 @@ export {
|
|||||||
PROVIDER_AUTH_PREFIXES,
|
PROVIDER_AUTH_PREFIXES,
|
||||||
PROVIDER_TYPE_VALUES,
|
PROVIDER_TYPE_VALUES,
|
||||||
getOAuthConfig,
|
getOAuthConfig,
|
||||||
} from './auth';
|
} from '.';
|
||||||
|
|
||||||
// Re-export token management functions
|
// Re-export token management functions
|
||||||
export {
|
export {
|
||||||
@@ -40,7 +40,7 @@ export {
|
|||||||
getAllAuthStatus,
|
getAllAuthStatus,
|
||||||
clearAuth,
|
clearAuth,
|
||||||
displayAuthStatus,
|
displayAuthStatus,
|
||||||
} from './auth';
|
} from '.';
|
||||||
|
|
||||||
// Re-export environment detection functions
|
// Re-export environment detection functions
|
||||||
export {
|
export {
|
||||||
@@ -48,13 +48,13 @@ export {
|
|||||||
killProcessOnPort,
|
killProcessOnPort,
|
||||||
getTimeoutTroubleshooting,
|
getTimeoutTroubleshooting,
|
||||||
showStep,
|
showStep,
|
||||||
} from './auth';
|
} from '.';
|
||||||
|
|
||||||
// Re-export OAuth handling functions
|
// Re-export OAuth handling functions
|
||||||
export { triggerOAuth, ensureAuth } from './auth';
|
export { triggerOAuth, ensureAuth } from '.';
|
||||||
|
|
||||||
// Re-export account management initialization
|
// Re-export account management initialization
|
||||||
import { discoverExistingAccounts } from './account-manager';
|
import { discoverExistingAccounts } from '../accounts/account-manager';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize accounts registry from existing tokens
|
* Initialize accounts registry from existing tokens
|
||||||
File renamed without changes.
@@ -8,8 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { randomBytes } from 'crypto';
|
import { randomBytes } from 'crypto';
|
||||||
import { loadOrCreateUnifiedConfig, mutateUnifiedConfig } from '../config/unified-config-loader';
|
import { loadOrCreateUnifiedConfig, mutateUnifiedConfig } from '../../config/unified-config-loader';
|
||||||
import { CCS_INTERNAL_API_KEY, CCS_CONTROL_PANEL_SECRET } from './config-generator';
|
import { CCS_INTERNAL_API_KEY, CCS_CONTROL_PANEL_SECRET } from '../config/generator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a cryptographically secure token.
|
* Generate a cryptographically secure token.
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { CLIProxyProvider } from '../types';
|
import { CLIProxyProvider } from '../types';
|
||||||
import type { AccountInfo } from '../account-manager';
|
import type { AccountInfo } from '../accounts/account-manager';
|
||||||
import {
|
import {
|
||||||
buildProviderMap,
|
buildProviderMap,
|
||||||
CLIPROXY_PROVIDER_IDS,
|
CLIPROXY_PROVIDER_IDS,
|
||||||
|
|||||||
File renamed without changes.
File renamed without changes.
@@ -8,7 +8,7 @@
|
|||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import { info, ok, fail } from '../../utils/ui';
|
import { info, ok, fail } from '../../utils/ui';
|
||||||
import { ensureCLIProxyBinary } from '../binary-manager';
|
import { ensureCLIProxyBinary } from '../binary-manager';
|
||||||
import { generateConfig } from '../config-generator';
|
import { generateConfig } from '../config/config-generator';
|
||||||
import { getProviderTokenDir } from './token-manager';
|
import { getProviderTokenDir } from './token-manager';
|
||||||
|
|
||||||
export interface KiroImportResult {
|
export interface KiroImportResult {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { fail, info, warn, color, ok } from '../../utils/ui';
|
import { fail, info, warn, color, ok } from '../../utils/ui';
|
||||||
import { ensureCLIProxyBinary } from '../binary-manager';
|
import { ensureCLIProxyBinary } from '../binary-manager';
|
||||||
import { generateConfig } from '../config-generator';
|
import { generateConfig } from '../config/config-generator';
|
||||||
import { CLIProxyProvider } from '../types';
|
import { CLIProxyProvider } from '../types';
|
||||||
import {
|
import {
|
||||||
AccountInfo,
|
AccountInfo,
|
||||||
@@ -24,7 +24,7 @@ import {
|
|||||||
findAccountNameMatch,
|
findAccountNameMatch,
|
||||||
PROVIDERS_WITHOUT_EMAIL,
|
PROVIDERS_WITHOUT_EMAIL,
|
||||||
validateNickname,
|
validateNickname,
|
||||||
} from '../account-manager';
|
} from '../accounts/account-manager';
|
||||||
import {
|
import {
|
||||||
enhancedPreflightOAuthCheck,
|
enhancedPreflightOAuthCheck,
|
||||||
OAUTH_CALLBACK_PORTS as OAUTH_PORTS,
|
OAUTH_CALLBACK_PORTS as OAUTH_PORTS,
|
||||||
@@ -62,14 +62,14 @@ import {
|
|||||||
buildProxyUrl,
|
buildProxyUrl,
|
||||||
buildManagementHeaders,
|
buildManagementHeaders,
|
||||||
type ProxyTarget,
|
type ProxyTarget,
|
||||||
} from '../proxy-target-resolver';
|
} from '../proxy/proxy-target-resolver';
|
||||||
import {
|
import {
|
||||||
checkNewAccountConflict,
|
checkNewAccountConflict,
|
||||||
warnNewAccountConflict,
|
warnNewAccountConflict,
|
||||||
warnOAuthBanRisk,
|
warnOAuthBanRisk,
|
||||||
warnPossible403Ban,
|
warnPossible403Ban,
|
||||||
} from '../account-safety';
|
} from '../accounts/account-safety';
|
||||||
import { ensureCliAntigravityResponsibility } from '../antigravity-responsibility';
|
import { ensureCliAntigravityResponsibility } from '../auth/antigravity-responsibility';
|
||||||
import { InteractivePrompt } from '../../utils/prompt';
|
import { InteractivePrompt } from '../../utils/prompt';
|
||||||
|
|
||||||
interface PasteCallbackStartData {
|
interface PasteCallbackStartData {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { ok, fail, info, warn } from '../../utils/ui';
|
|||||||
import { killWithEscalation } from '../../utils/process-utils';
|
import { killWithEscalation } from '../../utils/process-utils';
|
||||||
import { tryKiroImport } from './kiro-import';
|
import { tryKiroImport } from './kiro-import';
|
||||||
import { CLIProxyProvider } from '../types';
|
import { CLIProxyProvider } from '../types';
|
||||||
import { AccountInfo } from '../account-manager';
|
import { AccountInfo } from '../accounts/account-manager';
|
||||||
import {
|
import {
|
||||||
parseProjectList,
|
parseProjectList,
|
||||||
parseDefaultProject,
|
parseDefaultProject,
|
||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
cancelProjectSelection,
|
cancelProjectSelection,
|
||||||
type GCloudProject,
|
type GCloudProject,
|
||||||
type ProjectSelectionPrompt,
|
type ProjectSelectionPrompt,
|
||||||
} from '../project-selection-handler';
|
} from '../auth/project-selection-handler';
|
||||||
import { KiroAuthMethod, ProviderOAuthConfig } from './auth-types';
|
import { KiroAuthMethod, ProviderOAuthConfig } from './auth-types';
|
||||||
import { getTimeoutTroubleshooting, showStep } from './environment-detector';
|
import { getTimeoutTroubleshooting, showStep } from './environment-detector';
|
||||||
import {
|
import {
|
||||||
@@ -34,14 +34,14 @@ import {
|
|||||||
deviceCodeEvents,
|
deviceCodeEvents,
|
||||||
DEVICE_CODE_TIMEOUT_MS,
|
DEVICE_CODE_TIMEOUT_MS,
|
||||||
type DeviceCodePrompt,
|
type DeviceCodePrompt,
|
||||||
} from '../device-code-handler';
|
} from '../auth/device-code-handler';
|
||||||
import { OAUTH_FLOW_TYPES } from '../../management';
|
import { OAUTH_FLOW_TYPES } from '../../management';
|
||||||
import {
|
import {
|
||||||
registerAuthSession,
|
registerAuthSession,
|
||||||
attachProcessToSession,
|
attachProcessToSession,
|
||||||
unregisterAuthSession,
|
unregisterAuthSession,
|
||||||
authSessionEvents,
|
authSessionEvents,
|
||||||
} from '../auth-session-manager';
|
} from '../auth/auth-session-manager';
|
||||||
|
|
||||||
/** Options for OAuth process execution */
|
/** Options for OAuth process execution */
|
||||||
export interface OAuthProcessOptions {
|
export interface OAuthProcessOptions {
|
||||||
|
|||||||
File renamed without changes.
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import type { AccountTier } from './accounts/types';
|
import type { AccountTier } from '../accounts/types';
|
||||||
import type {
|
import type {
|
||||||
ProviderAccessState,
|
ProviderAccessState,
|
||||||
ProviderCapacityState,
|
ProviderCapacityState,
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import type { AccountTier } from './accounts/types';
|
import type { AccountTier } from '../accounts/types';
|
||||||
|
|
||||||
export type ProviderEntitlementSource =
|
export type ProviderEntitlementSource =
|
||||||
| 'runtime_api'
|
| 'runtime_api'
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { CLIProxyProvider } from '../../types';
|
import { CLIProxyProvider } from '../../types';
|
||||||
import { getProviderAccounts } from '../../account-manager';
|
import { getProviderAccounts } from '../../accounts/account-manager';
|
||||||
import {
|
import {
|
||||||
getTokenRefreshOwnership,
|
getTokenRefreshOwnership,
|
||||||
isRefreshDelegatedToCLIProxy,
|
isRefreshDelegatedToCLIProxy,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import * as fs from 'fs';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { CLIProxyProvider } from '../types';
|
import { CLIProxyProvider } from '../types';
|
||||||
import { CLIPROXY_PROFILES } from '../../auth/profile-detector';
|
import { CLIPROXY_PROFILES } from '../../auth/profile-detector';
|
||||||
import { getProviderAccounts, getAccountTokenPath } from '../account-manager';
|
import { getProviderAccounts, getAccountTokenPath } from '../accounts/account-manager';
|
||||||
import { isRefreshDelegated } from './provider-refreshers';
|
import { isRefreshDelegated } from './provider-refreshers';
|
||||||
|
|
||||||
/** Preemptive refresh time: refresh tokens 45 minutes before expiry */
|
/** Preemptive refresh time: refresh tokens 45 minutes before expiry */
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import * as path from 'path';
|
|||||||
import { createHash } from 'crypto';
|
import { createHash } from 'crypto';
|
||||||
import { CLIProxyProvider } from '../types';
|
import { CLIProxyProvider } from '../types';
|
||||||
import { CLIPROXY_PROFILES } from '../../auth/profile-detector';
|
import { CLIPROXY_PROFILES } from '../../auth/profile-detector';
|
||||||
import { getProviderAuthDir } from '../config-generator';
|
import { getProviderAuthDir } from '../config/config-generator';
|
||||||
import { getProviderAccounts, getDefaultAccount } from '../account-manager';
|
import { getProviderAccounts, getDefaultAccount } from '../accounts/account-manager';
|
||||||
import { deleteTokenFile, extractAccountIdFromTokenFile } from '../accounts/token-file-ops';
|
import { deleteTokenFile, extractAccountIdFromTokenFile } from '../accounts/token-file-ops';
|
||||||
import { buildEmailBackedAccountId } from '../accounts/email-account-identity';
|
import { buildEmailBackedAccountId } from '../accounts/email-account-identity';
|
||||||
import { getTokenRefreshOwnership } from '../provider-capabilities';
|
import { getTokenRefreshOwnership } from '../provider-capabilities';
|
||||||
@@ -367,8 +367,8 @@ export function registerAccountFromToken(
|
|||||||
nickname?: string,
|
nickname?: string,
|
||||||
verbose = false,
|
verbose = false,
|
||||||
expectedAccountId?: string
|
expectedAccountId?: string
|
||||||
): import('../account-manager').AccountInfo | null {
|
): import('../accounts/account-manager').AccountInfo | null {
|
||||||
const { registerAccount } = require('../account-manager');
|
const { registerAccount } = require('../accounts/account-manager');
|
||||||
let selectedCandidate: Omit<TokenCandidate, 'mtimeMs'> | null = null;
|
let selectedCandidate: Omit<TokenCandidate, 'mtimeMs'> | null = null;
|
||||||
try {
|
try {
|
||||||
const candidates = listTokenCandidates(provider, tokenDir);
|
const candidates = listTokenCandidates(provider, tokenDir);
|
||||||
@@ -438,7 +438,7 @@ export function registerAccountFromToken(
|
|||||||
*/
|
*/
|
||||||
function uploadTokenToRemoteAsync(tokenPath: string, verbose: boolean): void {
|
function uploadTokenToRemoteAsync(tokenPath: string, verbose: boolean): void {
|
||||||
// Dynamic import to avoid circular dependencies
|
// Dynamic import to avoid circular dependencies
|
||||||
import('../remote-token-uploader')
|
import('../management/remote-token-uploader')
|
||||||
.then(({ uploadTokenToRemote, isRemoteUploadEnabled }) => {
|
.then(({ uploadTokenToRemote, isRemoteUploadEnabled }) => {
|
||||||
if (isRemoteUploadEnabled()) {
|
if (isRemoteUploadEnabled()) {
|
||||||
// uploadTokenToRemote handles its own success/failure logging
|
// uploadTokenToRemote handles its own success/failure logging
|
||||||
|
|||||||
@@ -8,14 +8,14 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { info, warn } from '../utils/ui';
|
import { info, warn } from '../utils/ui';
|
||||||
import { getBinDir, CLIPROXY_DEFAULT_PORT } from './config-generator';
|
import { getBinDir, CLIPROXY_DEFAULT_PORT } from './config/config-generator';
|
||||||
import { BinaryInfo, BinaryManagerConfig } from './types';
|
import { BinaryInfo, BinaryManagerConfig } from './types';
|
||||||
import {
|
import {
|
||||||
BACKEND_CONFIG,
|
BACKEND_CONFIG,
|
||||||
DEFAULT_BACKEND,
|
DEFAULT_BACKEND,
|
||||||
CLIPROXY_MAX_STABLE_VERSION,
|
CLIPROXY_MAX_STABLE_VERSION,
|
||||||
getExecutableName,
|
getExecutableName,
|
||||||
} from './platform-detector';
|
} from './binary/platform-detector';
|
||||||
import { stopProxy } from './services/proxy-lifecycle-service';
|
import { stopProxy } from './services/proxy-lifecycle-service';
|
||||||
import { waitForPortFree } from '../utils/port-utils';
|
import { waitForPortFree } from '../utils/port-utils';
|
||||||
import { loadOrCreateUnifiedConfig } from '../config/unified-config-loader';
|
import { loadOrCreateUnifiedConfig } from '../config/unified-config-loader';
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
|
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
|
||||||
import { __testExports } from '../../../src/cliproxy/binary/downloader';
|
import { __testExports } from '../downloader';
|
||||||
|
|
||||||
const { getProxyUrl, shouldBypassProxy, getHostname, getProxyAgent } = __testExports;
|
const { getProxyUrl, shouldBypassProxy, getHostname, getProxyAgent } = __testExports;
|
||||||
|
|
||||||
+1
-1
@@ -9,7 +9,7 @@ import * as fs from 'fs';
|
|||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
|
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
|
||||||
import { deleteBinary } from '../../../src/cliproxy/binary/installer';
|
import { deleteBinary } from '../installer';
|
||||||
|
|
||||||
describe('deleteBinary ETXTBSY guard', () => {
|
describe('deleteBinary ETXTBSY guard', () => {
|
||||||
let tmpDir: string;
|
let tmpDir: string;
|
||||||
+14
-14
@@ -29,7 +29,7 @@ describe('installCliproxyVersion', () => {
|
|||||||
let seenBackend: string | undefined;
|
let seenBackend: string | undefined;
|
||||||
|
|
||||||
const binaryManager = await import(
|
const binaryManager = await import(
|
||||||
`../../../src/cliproxy/binary-manager?binary-manager-explicit-plus=${Date.now()}`
|
`../../binary-manager?binary-manager-explicit-plus=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
await binaryManager.installCliproxyVersion('6.7.1', false, 'plus', {
|
await binaryManager.installCliproxyVersion('6.7.1', false, 'plus', {
|
||||||
@@ -53,7 +53,7 @@ describe('installCliproxyVersion', () => {
|
|||||||
|
|
||||||
it('returns plus and emits an informational notice when plus backend is resolved locally', async () => {
|
it('returns plus and emits an informational notice when plus backend is resolved locally', async () => {
|
||||||
const binaryManager = await import(
|
const binaryManager = await import(
|
||||||
`../../../src/cliproxy/binary-manager?binary-manager-warning=${Date.now()}`
|
`../../binary-manager?binary-manager-warning=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
const writes: string[] = [];
|
const writes: string[] = [];
|
||||||
@@ -75,12 +75,12 @@ describe('installCliproxyVersion', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('uses plus binary and pin state when local runtime is configured for plus', async () => {
|
it('uses plus binary and pin state when local runtime is configured for plus', async () => {
|
||||||
const { createEmptyUnifiedConfig } = await import('../../../src/config/unified-config-types');
|
const { createEmptyUnifiedConfig } = await import('../../../config/unified-config-types');
|
||||||
const { saveUnifiedConfig } = await import('../../../src/config/unified-config-loader');
|
const { saveUnifiedConfig } = await import('../../../config/unified-config-loader');
|
||||||
const { savePinnedVersion } = await import('../../../src/cliproxy/binary/version-cache');
|
const { savePinnedVersion } = await import('../version-cache');
|
||||||
const { getExecutableName } = await import('../../../src/cliproxy/platform-detector');
|
const { getExecutableName } = await import('../platform-detector');
|
||||||
const binaryService = await import(
|
const binaryService = await import(
|
||||||
`../../../src/cliproxy/services/binary-service?binary-service-plus-migration=${Date.now()}`
|
`../../services/binary-service?binary-service-plus-migration=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
const config = createEmptyUnifiedConfig();
|
const config = createEmptyUnifiedConfig();
|
||||||
@@ -101,12 +101,12 @@ describe('installCliproxyVersion', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('copies plus binary and pin state when legacy deleted upstream fallback is active', async () => {
|
it('copies plus binary and pin state when legacy deleted upstream fallback is active', async () => {
|
||||||
const { createEmptyUnifiedConfig } = await import('../../../src/config/unified-config-types');
|
const { createEmptyUnifiedConfig } = await import('../../../config/unified-config-types');
|
||||||
const { saveUnifiedConfig } = await import('../../../src/config/unified-config-loader');
|
const { saveUnifiedConfig } = await import('../../../config/unified-config-loader');
|
||||||
const { savePinnedVersion } = await import('../../../src/cliproxy/binary/version-cache');
|
const { savePinnedVersion } = await import('../version-cache');
|
||||||
const platformDetector = await import('../../../src/cliproxy/platform-detector');
|
const platformDetector = await import('../platform-detector');
|
||||||
const binaryService = await import(
|
const binaryService = await import(
|
||||||
`../../../src/cliproxy/services/binary-service?binary-service-legacy-plus-fallback=${Date.now()}`
|
`../../services/binary-service?binary-service-legacy-plus-fallback=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
const plusConfig = platformDetector.BACKEND_CONFIG.plus as unknown as { repo: string };
|
const plusConfig = platformDetector.BACKEND_CONFIG.plus as unknown as { repo: string };
|
||||||
@@ -147,7 +147,7 @@ describe('installCliproxyVersion', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const binaryManager = await import(
|
const binaryManager = await import(
|
||||||
`../../../src/cliproxy/binary-manager?binary-manager-install=${Date.now()}`
|
`../../binary-manager?binary-manager-install=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
await binaryManager.installCliproxyVersion('6.7.1', false, 'plus', {
|
await binaryManager.installCliproxyVersion('6.7.1', false, 'plus', {
|
||||||
@@ -182,7 +182,7 @@ describe('installCliproxyVersion', () => {
|
|||||||
|
|
||||||
it('fails fast when runtime startup forbids installing a missing binary', async () => {
|
it('fails fast when runtime startup forbids installing a missing binary', async () => {
|
||||||
const binaryManager = await import(
|
const binaryManager = await import(
|
||||||
`../../../src/cliproxy/binary-manager?binary-manager-runtime=${Date.now()}`
|
`../../binary-manager?binary-manager-runtime=${Date.now()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
File renamed without changes.
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ArchiveExtension, CLIProxyBackend } from '../types';
|
import { ArchiveExtension, CLIProxyBackend } from '../types';
|
||||||
import { DEFAULT_BACKEND } from '../platform-detector';
|
import { DEFAULT_BACKEND } from '../binary/platform-detector';
|
||||||
import { extractTarGz } from './tar-extractor';
|
import { extractTarGz } from './tar-extractor';
|
||||||
import { extractZip } from './zip-extractor';
|
import { extractZip } from './zip-extractor';
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
getChecksumsUrl,
|
getChecksumsUrl,
|
||||||
getExecutableName,
|
getExecutableName,
|
||||||
DEFAULT_BACKEND,
|
DEFAULT_BACKEND,
|
||||||
} from '../platform-detector';
|
} from '../binary/platform-detector';
|
||||||
import { downloadWithRetry } from './downloader';
|
import { downloadWithRetry } from './downloader';
|
||||||
import { verifyChecksum, computeChecksum } from './verifier';
|
import { verifyChecksum, computeChecksum } from './verifier';
|
||||||
import { extractArchive } from './extractor';
|
import { extractArchive } from './extractor';
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ import {
|
|||||||
} from './version-checker';
|
} from './version-checker';
|
||||||
import { downloadAndInstall, deleteBinary, getBinaryPath } from './installer';
|
import { downloadAndInstall, deleteBinary, getBinaryPath } from './installer';
|
||||||
import { info, warn } from '../../utils/ui';
|
import { info, warn } from '../../utils/ui';
|
||||||
import { isCliproxyRunning } from '../stats-fetcher';
|
import { isCliproxyRunning } from '../services/stats-fetcher';
|
||||||
import { CLIPROXY_DEFAULT_PORT } from '../config-generator';
|
import { CLIPROXY_DEFAULT_PORT } from '../config/config-generator';
|
||||||
import {
|
import {
|
||||||
CLIPROXY_MAX_STABLE_VERSION,
|
CLIPROXY_MAX_STABLE_VERSION,
|
||||||
CLIPROXY_FAULTY_RANGE,
|
CLIPROXY_FAULTY_RANGE,
|
||||||
DEFAULT_BACKEND,
|
DEFAULT_BACKEND,
|
||||||
} from '../platform-detector';
|
} from '../binary/platform-detector';
|
||||||
|
|
||||||
/** Log helper */
|
/** Log helper */
|
||||||
function log(message: string, verbose: boolean): void {
|
function log(message: string, verbose: boolean): void {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
SupportedArch,
|
SupportedArch,
|
||||||
ArchiveExtension,
|
ArchiveExtension,
|
||||||
CLIProxyBackend,
|
CLIProxyBackend,
|
||||||
} from './types';
|
} from '../types';
|
||||||
|
|
||||||
/** Backend configuration */
|
/** Backend configuration */
|
||||||
export const BACKEND_CONFIG = {
|
export const BACKEND_CONFIG = {
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as zlib from 'zlib';
|
import * as zlib from 'zlib';
|
||||||
import { getExecutableName, getArchiveBinaryName, DEFAULT_BACKEND } from '../platform-detector';
|
import { getExecutableName, getArchiveBinaryName, DEFAULT_BACKEND } from '../binary/platform-detector';
|
||||||
import type { CLIProxyBackend } from '../types';
|
import type { CLIProxyBackend } from '../types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { getBinDir } from '../config-generator';
|
import { getBinDir } from '../config/config-generator';
|
||||||
import {
|
import {
|
||||||
VersionCache,
|
VersionCache,
|
||||||
VERSION_CACHE_DURATION_MS,
|
VERSION_CACHE_DURATION_MS,
|
||||||
VERSION_PIN_FILE,
|
VERSION_PIN_FILE,
|
||||||
VersionListCache,
|
VersionListCache,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { DEFAULT_BACKEND } from '../platform-detector';
|
import { DEFAULT_BACKEND } from '../binary/platform-detector';
|
||||||
import type { CLIProxyBackend } from '../types';
|
import type { CLIProxyBackend } from '../types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
CLIPROXY_MAX_STABLE_VERSION,
|
CLIPROXY_MAX_STABLE_VERSION,
|
||||||
CLIPROXY_FAULTY_RANGE,
|
CLIPROXY_FAULTY_RANGE,
|
||||||
DEFAULT_BACKEND,
|
DEFAULT_BACKEND,
|
||||||
} from '../platform-detector';
|
} from '../binary/platform-detector';
|
||||||
import type { CLIProxyBackend } from '../types';
|
import type { CLIProxyBackend } from '../types';
|
||||||
|
|
||||||
interface FetchLatestVersionDeps {
|
interface FetchLatestVersionDeps {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as zlib from 'zlib';
|
import * as zlib from 'zlib';
|
||||||
import { getExecutableName, getArchiveBinaryName, DEFAULT_BACKEND } from '../platform-detector';
|
import { getExecutableName, getArchiveBinaryName, DEFAULT_BACKEND } from '../binary/platform-detector';
|
||||||
import type { CLIProxyBackend } from '../types';
|
import type { CLIProxyBackend } from '../types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+2
-2
@@ -6,8 +6,8 @@
|
|||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
|
||||||
describe('Backend Selection', () => {
|
describe('Backend Selection', () => {
|
||||||
const platformDetector = require('../../../dist/cliproxy/platform-detector');
|
const platformDetector = require('../../../../dist/cliproxy/platform-detector');
|
||||||
const types = require('../../../dist/cliproxy/types');
|
const types = require('../../../../dist/cliproxy/types');
|
||||||
|
|
||||||
describe('BACKEND_CONFIG', () => {
|
describe('BACKEND_CONFIG', () => {
|
||||||
it('has correct configuration for original backend', () => {
|
it('has correct configuration for original backend', () => {
|
||||||
+6
-6
@@ -5,26 +5,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { describe, expect, test } from 'bun:test';
|
import { describe, expect, test } from 'bun:test';
|
||||||
import { CLIPROXY_DEFAULT_PORT as BACKEND_CLIPROXY_DEFAULT_PORT } from '../../../src/cliproxy/config/port-manager';
|
import { CLIPROXY_DEFAULT_PORT as BACKEND_CLIPROXY_DEFAULT_PORT } from '../port-manager';
|
||||||
import { DEFAULT_CURSOR_PORT as BACKEND_CURSOR_DEFAULT_PORT } from '../../../src/cursor/cursor-models';
|
import { DEFAULT_CURSOR_PORT as BACKEND_CURSOR_DEFAULT_PORT } from '../../../cursor/cursor-models';
|
||||||
import {
|
import {
|
||||||
CLIPROXY_PROVIDER_IDS as BACKEND_CLIPROXY_PROVIDER_IDS,
|
CLIPROXY_PROVIDER_IDS as BACKEND_CLIPROXY_PROVIDER_IDS,
|
||||||
getProviderDescription as getBackendProviderDescription,
|
getProviderDescription as getBackendProviderDescription,
|
||||||
getProviderDisplayName as getBackendProviderDisplayName,
|
getProviderDisplayName as getBackendProviderDisplayName,
|
||||||
getProvidersByOAuthFlow,
|
getProvidersByOAuthFlow,
|
||||||
} from '../../../src/cliproxy/provider-capabilities';
|
} from '../../provider-capabilities';
|
||||||
import {
|
import {
|
||||||
CLIPROXY_DEFAULT_PORT as UI_CLIPROXY_DEFAULT_PORT,
|
CLIPROXY_DEFAULT_PORT as UI_CLIPROXY_DEFAULT_PORT,
|
||||||
DEFAULT_CURSOR_PORT as UI_CURSOR_DEFAULT_PORT,
|
DEFAULT_CURSOR_PORT as UI_CURSOR_DEFAULT_PORT,
|
||||||
} from '../../../ui/src/lib/default-ports';
|
} from '../../../../ui/src/lib/default-ports';
|
||||||
import {
|
import {
|
||||||
CLIPROXY_PROVIDERS as UI_CLIPROXY_PROVIDERS,
|
CLIPROXY_PROVIDERS as UI_CLIPROXY_PROVIDERS,
|
||||||
CORE_CLIPROXY_PROVIDERS as UI_CORE_CLIPROXY_PROVIDERS,
|
CORE_CLIPROXY_PROVIDERS as UI_CORE_CLIPROXY_PROVIDERS,
|
||||||
DEVICE_CODE_PROVIDERS as UI_DEVICE_CODE_PROVIDERS,
|
DEVICE_CODE_PROVIDERS as UI_DEVICE_CODE_PROVIDERS,
|
||||||
PLUS_EXTRA_CLIPROXY_PROVIDERS as UI_PLUS_EXTRA_CLIPROXY_PROVIDERS,
|
PLUS_EXTRA_CLIPROXY_PROVIDERS as UI_PLUS_EXTRA_CLIPROXY_PROVIDERS,
|
||||||
PROVIDER_METADATA as UI_PROVIDER_METADATA,
|
PROVIDER_METADATA as UI_PROVIDER_METADATA,
|
||||||
} from '../../../ui/src/lib/provider-config';
|
} from '../../../../ui/src/lib/provider-config';
|
||||||
import { PLUS_ONLY_PROVIDERS as BACKEND_PLUS_ONLY_PROVIDERS } from '../../../src/cliproxy/types';
|
import { PLUS_ONLY_PROVIDERS as BACKEND_PLUS_ONLY_PROVIDERS } from '../../types/index';
|
||||||
|
|
||||||
function sorted(values: readonly string[]): string[] {
|
function sorted(values: readonly string[]): string[] {
|
||||||
return [...values].sort((a, b) => a.localeCompare(b));
|
return [...values].sort((a, b) => a.localeCompare(b));
|
||||||
+2
-2
@@ -6,8 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { describe, expect, test } from 'bun:test';
|
import { describe, expect, test } from 'bun:test';
|
||||||
import { CLIPROXY_PROFILES } from '../../../src/auth/profile-detector';
|
import { CLIPROXY_PROFILES } from '../../../auth/profile-detector';
|
||||||
import { CLIPROXY_PROVIDERS } from '../../../ui/src/lib/provider-config';
|
import { CLIPROXY_PROVIDERS } from '../../../../ui/src/lib/provider-config';
|
||||||
|
|
||||||
describe('Provider Sync', () => {
|
describe('Provider Sync', () => {
|
||||||
test('backend CLIPROXY_PROFILES matches UI CLIPROXY_PROVIDERS', () => {
|
test('backend CLIPROXY_PROFILES matches UI CLIPROXY_PROVIDERS', () => {
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from 'bun:test';
|
import { describe, expect, it } from 'bun:test';
|
||||||
|
|
||||||
import { loadBaseConfig } from '../../../src/cliproxy/base-config-loader';
|
import { loadBaseConfig } from '../../config/base-config-loader';
|
||||||
|
|
||||||
describe('base-config-loader new providers', () => {
|
describe('base-config-loader new providers', () => {
|
||||||
it.each([
|
it.each([
|
||||||
+1
-1
@@ -6,7 +6,7 @@ import { describe, it, expect } from 'bun:test';
|
|||||||
import {
|
import {
|
||||||
validateCompositeDefaultTier,
|
validateCompositeDefaultTier,
|
||||||
validateCompositeTiers,
|
validateCompositeTiers,
|
||||||
} from '../../../src/cliproxy/composite-validator';
|
} from '../../config/composite-validator';
|
||||||
|
|
||||||
const validTier = {
|
const validTier = {
|
||||||
provider: 'agy',
|
provider: 'agy',
|
||||||
+1
-1
@@ -26,7 +26,7 @@ const {
|
|||||||
deleteConfigForPort,
|
deleteConfigForPort,
|
||||||
deleteConfig,
|
deleteConfig,
|
||||||
CLIPROXY_DEFAULT_PORT,
|
CLIPROXY_DEFAULT_PORT,
|
||||||
} = require('../../../dist/cliproxy/config-generator');
|
} = require('../../../../dist/cliproxy/config-generator');
|
||||||
|
|
||||||
describe('Config Generator Port', function () {
|
describe('Config Generator Port', function () {
|
||||||
let cliproxyDir;
|
let cliproxyDir;
|
||||||
+10
-10
@@ -7,7 +7,7 @@ const assert = require('assert');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
// Mock the config-manager module to provide test paths
|
// Mock the config-manager module to provide test paths
|
||||||
const originalModule = require.cache[require.resolve('../../../dist/utils/config-manager')];
|
const originalModule = require.cache[require.resolve('../../../../dist/utils/config-manager')];
|
||||||
|
|
||||||
describe('Config Generator', () => {
|
describe('Config Generator', () => {
|
||||||
let configGenerator;
|
let configGenerator;
|
||||||
@@ -15,7 +15,7 @@ describe('Config Generator', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// Clear the require cache to reload module with fresh mocks
|
// Clear the require cache to reload module with fresh mocks
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/config-generator')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')];
|
||||||
|
|
||||||
// Set up a temporary test directory as CCS_HOME
|
// Set up a temporary test directory as CCS_HOME
|
||||||
mockCcsDir = '/test/home/.ccs';
|
mockCcsDir = '/test/home/.ccs';
|
||||||
@@ -174,8 +174,8 @@ describe('Config Generator', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// Clear cache and reload module
|
// Clear cache and reload module
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/config-generator')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')];
|
||||||
const configGenerator = require('../../../dist/cliproxy/config-generator');
|
const configGenerator = require('../../../../dist/cliproxy/config-generator');
|
||||||
parseUserApiKeys = configGenerator.parseUserApiKeys;
|
parseUserApiKeys = configGenerator.parseUserApiKeys;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -374,9 +374,9 @@ auth-dir: "/test"
|
|||||||
process.env.CCS_HOME = testDir;
|
process.env.CCS_HOME = testDir;
|
||||||
|
|
||||||
// Clear cache and reload module
|
// Clear cache and reload module
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/config-generator')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')];
|
||||||
delete require.cache[require.resolve('../../../dist/utils/config-manager')];
|
delete require.cache[require.resolve('../../../../dist/utils/config-manager')];
|
||||||
const configGenerator = require('../../../dist/cliproxy/config-generator');
|
const configGenerator = require('../../../../dist/cliproxy/config-generator');
|
||||||
regenerateConfig = configGenerator.regenerateConfig;
|
regenerateConfig = configGenerator.regenerateConfig;
|
||||||
getCliproxyConfigPath = configGenerator.getCliproxyConfigPath;
|
getCliproxyConfigPath = configGenerator.getCliproxyConfigPath;
|
||||||
});
|
});
|
||||||
@@ -596,9 +596,9 @@ auth-dir: "${cliproxyDir.replace(/\\/g, '/')}/auth"
|
|||||||
originalCcsHome = process.env.CCS_HOME;
|
originalCcsHome = process.env.CCS_HOME;
|
||||||
process.env.CCS_HOME = testDir;
|
process.env.CCS_HOME = testDir;
|
||||||
|
|
||||||
delete require.cache[require.resolve('../../../dist/cliproxy/config-generator')];
|
delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')];
|
||||||
delete require.cache[require.resolve('../../../dist/utils/config-manager')];
|
delete require.cache[require.resolve('../../../../dist/utils/config-manager')];
|
||||||
const configGenerator = require('../../../dist/cliproxy/config-generator');
|
const configGenerator = require('../../../../dist/cliproxy/config-generator');
|
||||||
regenerateConfig = configGenerator.regenerateConfig;
|
regenerateConfig = configGenerator.regenerateConfig;
|
||||||
});
|
});
|
||||||
|
|
||||||
File renamed without changes.
+1
-1
@@ -5,7 +5,7 @@ import { afterEach, beforeEach, describe, expect, it } from 'bun:test';
|
|||||||
import {
|
import {
|
||||||
ensureProviderSettings,
|
ensureProviderSettings,
|
||||||
getEffectiveEnvVars,
|
getEffectiveEnvVars,
|
||||||
} from '../../../src/cliproxy/config/env-builder';
|
} from '../env-builder';
|
||||||
|
|
||||||
interface EnvSettings {
|
interface EnvSettings {
|
||||||
ANTHROPIC_BASE_URL: string;
|
ANTHROPIC_BASE_URL: string;
|
||||||
+2
-2
@@ -12,8 +12,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { describe, it, expect } from 'bun:test';
|
import { describe, it, expect } from 'bun:test';
|
||||||
import { validatePort, CLIPROXY_DEFAULT_PORT } from '../../../src/cliproxy/config-generator';
|
import { validatePort, CLIPROXY_DEFAULT_PORT } from '../config-generator';
|
||||||
import { resolveProxyConfig } from '../../../src/cliproxy/proxy-config-resolver';
|
import { resolveProxyConfig } from '../../proxy/proxy-config-resolver';
|
||||||
|
|
||||||
describe('Port Validation', () => {
|
describe('Port Validation', () => {
|
||||||
describe('validatePort()', () => {
|
describe('validatePort()', () => {
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import type { CLIProxyProvider, ProviderModelMapping } from './types';
|
import type { CLIProxyProvider, ProviderModelMapping } from '../types';
|
||||||
|
|
||||||
/** Base settings file structure */
|
/** Base settings file structure */
|
||||||
interface BaseSettings {
|
interface BaseSettings {
|
||||||
@@ -3,10 +3,10 @@
|
|||||||
* Used by API routes, service layer, and config loader to avoid contract drift.
|
* Used by API routes, service layer, and config loader to avoid contract drift.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CLIPROXY_SUPPORTED_PROVIDERS } from '../config/unified-config-types';
|
import { CLIPROXY_SUPPORTED_PROVIDERS } from '../../config/unified-config-types';
|
||||||
import type { CompositeTierConfig } from '../config/unified-config-types';
|
import type { CompositeTierConfig } from '../../config/unified-config-types';
|
||||||
import type { CLIProxyProvider } from './types';
|
import type { CLIProxyProvider } from '../types';
|
||||||
import { getDeniedModelIdReasonForProvider } from './model-id-normalizer';
|
import { getDeniedModelIdReasonForProvider } from '../ai-providers/model-id-normalizer';
|
||||||
|
|
||||||
export const VALID_COMPOSITE_TIERS = ['opus', 'sonnet', 'haiku'] as const;
|
export const VALID_COMPOSITE_TIERS = ['opus', 'sonnet', 'haiku'] as const;
|
||||||
export type CompositeTierName = (typeof VALID_COMPOSITE_TIERS)[number];
|
export type CompositeTierName = (typeof VALID_COMPOSITE_TIERS)[number];
|
||||||
@@ -13,4 +13,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Re-export all modules for backwards compatibility
|
// Re-export all modules for backwards compatibility
|
||||||
export * from './config';
|
export * from '.';
|
||||||
@@ -6,9 +6,9 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import type { CLIProxyProvider, ProviderModelMapping } from '../types';
|
import type { CLIProxyProvider, ProviderModelMapping } from '../types';
|
||||||
import { getModelMappingFromConfig, getEnvVarsFromConfig } from '../base-config-loader';
|
import { getModelMappingFromConfig, getEnvVarsFromConfig } from '../config/base-config-loader';
|
||||||
import { getGlobalEnvConfig } from '../../config/unified-config-loader';
|
import { getGlobalEnvConfig } from '../../config/unified-config-loader';
|
||||||
import { getEffectiveApiKey } from '../auth-token-manager';
|
import { getEffectiveApiKey } from '../auth/auth-token-manager';
|
||||||
import { expandPath } from '../../utils/helpers';
|
import { expandPath } from '../../utils/helpers';
|
||||||
import { warn } from '../../utils/ui';
|
import { warn } from '../../utils/ui';
|
||||||
import type { CompositeTierConfig } from '../../config/unified-config-types';
|
import type { CompositeTierConfig } from '../../config/unified-config-types';
|
||||||
@@ -30,7 +30,7 @@ import {
|
|||||||
normalizeModelEnvVarsForProvider,
|
normalizeModelEnvVarsForProvider,
|
||||||
normalizeIFlowLegacyModelAliases,
|
normalizeIFlowLegacyModelAliases,
|
||||||
normalizeModelIdForProvider,
|
normalizeModelIdForProvider,
|
||||||
} from '../model-id-normalizer';
|
} from '../ai-providers/model-id-normalizer';
|
||||||
|
|
||||||
/** Settings file structure for user overrides */
|
/** Settings file structure for user overrides */
|
||||||
interface ProviderSettings {
|
interface ProviderSettings {
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import * as fs from 'fs';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import type { CLIProxyProvider, ProviderConfig } from '../types';
|
import type { CLIProxyProvider, ProviderConfig } from '../types';
|
||||||
import { getProviderDisplayName } from '../provider-capabilities';
|
import { getProviderDisplayName } from '../provider-capabilities';
|
||||||
import { getModelMappingFromConfig } from '../base-config-loader';
|
import { getModelMappingFromConfig } from '../config/base-config-loader';
|
||||||
import { AI_PROVIDER_FAMILY_IDS } from '../ai-providers/types';
|
import { AI_PROVIDER_FAMILY_IDS } from '../ai-providers/types';
|
||||||
import { loadOrCreateUnifiedConfig } from '../../config/unified-config-loader';
|
import { loadOrCreateUnifiedConfig } from '../../config/unified-config-loader';
|
||||||
import { getEffectiveApiKey, getEffectiveManagementSecret } from '../auth-token-manager';
|
import { getEffectiveApiKey, getEffectiveManagementSecret } from '../auth/auth-token-manager';
|
||||||
import { getDeniedModelIdReasonForProvider } from '../model-id-normalizer';
|
import { getDeniedModelIdReasonForProvider } from '../ai-providers/model-id-normalizer';
|
||||||
import { getAuthDir, getProviderAuthDir, getConfigPathForPort } from './path-resolver';
|
import { getAuthDir, getProviderAuthDir, getConfigPathForPort } from './path-resolver';
|
||||||
import { CLIPROXY_DEFAULT_PORT } from './port-manager';
|
import { CLIPROXY_DEFAULT_PORT } from './port-manager';
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import { InteractivePrompt } from '../utils/prompt';
|
import { InteractivePrompt } from '../../utils/prompt';
|
||||||
import { getProviderCatalog, supportsModelConfig, ModelEntry } from './model-catalog';
|
import { getProviderCatalog, supportsModelConfig, ModelEntry } from '../model-catalog';
|
||||||
import { getClaudeEnvVars, resolveProviderSettingsPath } from './config-generator';
|
import { getClaudeEnvVars, resolveProviderSettingsPath } from './config-generator';
|
||||||
import { CLIProxyProvider } from './types';
|
import { CLIProxyProvider } from '../types';
|
||||||
import { initUI, color, bold, dim, ok, info, header } from '../utils/ui';
|
import { initUI, color, bold, dim, ok, info, header } from '../../utils/ui';
|
||||||
import { getCcsDir } from '../utils/config-manager';
|
import { getCcsDir } from '../../utils/config-manager';
|
||||||
import { normalizeModelIdForProvider } from './model-id-normalizer';
|
import { normalizeModelIdForProvider } from '../ai-providers/model-id-normalizer';
|
||||||
|
|
||||||
function canonicalizeModelForProvider(provider: CLIProxyProvider, model: string): string {
|
function canonicalizeModelForProvider(provider: CLIProxyProvider, model: string): string {
|
||||||
return normalizeModelIdForProvider(model, provider);
|
return normalizeModelIdForProvider(model, provider);
|
||||||
Loaded 100 of 225 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user