Make tier_lock a per-provider map and honor it in findHealthyAccount and
preflightCheck for the selected provider only, so locking one provider never
disables failover for others. Add POST /api/accounts/tier-lock with tier
validation against known tiers, and serialize quota_management on config write
so the lock persists.
The normalizers extraction in #1168 introduced a circular module-load
chain that crashed the built CLI:
ccs.js -> errors -> services/logging -> log-config -> config-loader-facade
-> unified-config-loader -> loader/normalizers -> channels/official-channels-runtime
-> utils/claude-detector -> utils/shell-executor -> utils/websearch-manager
-> utils/websearch/hook-env -> utils/websearch/trace
-> services/logging (mid-load - createLogger undefined) -> CRASH
normalizers only needed three pure helpers from official-channels-runtime
(isOfficialChannelId, normalizeOfficialChannelIds, resolveLegacyDiscord
Selection) but pulled in the whole file's claude-detector / shell-
executor / websearch chain.
Fix: extract those three helpers + OFFICIAL_CHANNEL_IDS into a leaf
module src/channels/official-channels-ids.ts with no runtime deps.
Update normalizers.ts and config-getters.ts to import from the leaf.
official-channels-runtime.ts re-exports from the leaf for callers that
still want the bundled API.
Also revert the over-eager facade-import migration in
src/utils/config-manager.ts (it was importing from config-loader-facade
which re-exports from itself, creating a direct cycle).
Verified: dist/ccs.js boots cleanly (--version returns); test:all
1828/1828 pass; typecheck/lint/format clean.
Refs #1135
Phases 4-6 of #1164. Final extractions and orchestrator cleanup:
- src/config/loader/defaults-merger.ts (323 LOC):
mergeWithDefaults — pure transform that fills defaults across browser,
websearch, dashboard auth, image analysis, logging, cursor, continuity,
official channels.
- src/config/loader/config-getters.ts (339 LOC):
getWebSearchConfig, getGlobalEnvConfig, getContinuityInheritanceMap,
getCliproxySafetyConfig, getThinkingConfig, getOfficialChannelsConfig,
isDashboardAuthEnabled, getDashboardAuthConfig, getBrowserConfig,
getImageAnalysisConfig, getLoggingConfig, getCursorConfig,
GeminiWebSearchInfo. Lazy require('../unified-config-loader') call-time
resolution preserves spy-based test compatibility while breaking the
config-getters -> orchestrator cycle.
- unified-config-loader.ts: rewritten as 268-LOC orchestrator. Hosts core
load/save/mutate logic + re-exports of all moved symbols for backwards
compat with codebase imports.
Forward-reference callbacks in io-locks.ts kept as-is — defaults-merger
and normalizers don't import from io-locks (no cycle), but simplifying
io-locks's internal callback API risks lock-semantics regression.
Deferred per KISS.
unified-config-loader.ts: 1508 -> 268 LOC (-1240, -82%). Behavior
unchanged; full suite passes 1824/1824.
Refs #1164
getCachedConfig() now checks config file mtime on each call.
If external code writes via unified-config-loader directly,
the facade detects the file change and re-reads from disk
automatically. Resolves PR-Agent "Stale Cache" finding.
Document that uncached reads (loadOrCreateUnifiedConfig)
bypass the cache and callers should use
invalidateConfigCache() if they mix uncached reads
with cached writes outside the facade. Resolves
remaining PR-Agent concern from #1150 comment.
PR-Agent #1150 review flagged that re-exporting
saveUnifiedConfig/mutateUnifiedConfig/updateUnifiedConfig
allows callers to bypass the cache. Only export the
cache-coherent wrappers (saveConfig/mutateConfig/updateConfig).
Raw functions still available via direct import from
unified-config-loader if needed.
- Remove raw write re-exports from facade
- Add test verifying raw writes are NOT exported
- Add test verifying cache-coherent wrappers ARE exported
- config-loader-facade: use structuredClone() to prevent cache aliasing
- retry-strategy: re-cap delay after jitter to enforce maxDelayMs boundary
- retry-strategy: wire retryAfter from RetryableError into delay computation
- retry-strategy: guard against negative maxRetries
- error-types: rename RetryableError.cause to originalError to avoid shadowing Error.cause
- Tests updated for all fixes
Single import path for all config loading. Re-exports all 26 functions
from unified-config-loader and 4 from config-manager. Adds memoization
for loadOrCreateUnifiedConfig via getCachedConfig() with automatic cache
invalidation on write operations (mutateConfig, updateConfig). Pure
structural refactor -- no existing imports modified.
The upstream router-for-me/CLIProxyAPIPlus repo was deleted, breaking any
install/update path that resolved backend: plus. Existing users with
`backend: plus` saved in config.yaml hit 404s on every bootstrap.
Changes:
- Flip DEFAULT_BACKEND from 'plus' to 'original' (platform-detector.ts)
- Flip default cliproxy.backend in createEmptyUnifiedConfig() to 'original'
- Runtime 404 fallback: getConfiguredBackend() degrades 'plus' -> 'original'
with a one-time warning, so existing installations keep working without a
manual reconfig step
- Update CLIProxyBackend docblock to document the fallback behavior
- Update tests to match new default
Retains the 'plus' type and BACKEND_CONFIG entry for forward compatibility
once CCS self-maintains its own Plus fork.
Closes#1062
- Updated websearch.md to include SearXNG in the configuration guide.
- Implemented SearXNG JSON API integration in websearch-transformer.cjs.
- Enhanced unified-config-loader.ts to support SearXNG settings.
- Defined SearXNG configuration types in unified-config-types.ts.
- Updated hook-env.ts to manage SearXNG environment variables.
- Modified status.ts to include SearXNG in web search provider checks.
- Added SearXNG routes and validation in websearch-routes.ts.
- Implemented SearXNG provider tests in websearch-transformer.test.ts.
- Updated readiness tests to account for SearXNG in status.test.ts.
- Enhanced websearch routes tests to validate SearXNG settings.
- Added SearXNG configuration fields in the UI settings.
- add dependency injection to export-command, binary-manager,
codex-plan-compatibility, config-command, and usage-syncer
- override process.exit in api-export test to prevent silent
termination in Bun's parallel test runner
- harden test-environment bootstrap with process.env isolation
- fix auth middleware to avoid config upgrade during checks