Commit Graph
591 Commits
Author SHA1 Message Date
Tam Nhu Tran 05e1c35203 refactor: merge facade adoption from #1169 into executor extraction 2026-05-03 11:54:04 -04:00
Tam Nhu Tran 4f6e61739c refactor(config): adopt config-loader-facade across the codebase
Issue #1161. Sweeps 127 files to import from
src/config/config-loader-facade.ts instead of unified-config-loader or
utils/config-manager directly.

WRITE callers (32 files): replaced raw saveUnifiedConfig /
mutateUnifiedConfig / updateUnifiedConfig calls with the facade's
cache-coherent wrappers saveConfig / mutateConfig / updateConfig. This
fixes a latent stale-cache window where direct writes through the
underlying loader bypassed the facade's memoization.

READ callers (95 files): mechanical import-path migration only —
function names unchanged because the facade re-exports them. No
behavior change.

Also updated:
- tests/unit/utils/browser/browser-setup.test.ts (DI interface rename)
- src/management/checks/image-analysis-check.ts (dynamic import rename)
- src/web-server/health-service.ts (dynamic require rename)
- src/ccs.ts (path prefix fix from sweep script)

After sweep: zero raw write callers remain outside src/config/. Direct
imports of config-manager remain only for symbols not in the facade
(getConfigPath, getCcsDirSource, etc). Behavior unchanged; full suite
passes 1824/1824.

Out of scope: switching loadOrCreateUnifiedConfig() callers to
getCachedConfig() — needs per-callsite cache-safety analysis. Tracked
as follow-up.

Refs #1161
2026-05-03 01:42:53 -04:00
Tam Nhu Tran 09268e7e33 refactor(cliproxy/executor): extract model-warnings + claude-launcher and polish orchestrator
Phases 08+09+10 of #1162. Final extractions and orchestrator cleanup:

- src/cliproxy/executor/model-warnings.ts (80 LOC):
  warnBrokenModels — handles composite + simple paths, broken-model
  notification with replacement suggestions.
- src/cliproxy/executor/claude-launcher.ts (161 LOC):
  launchClaude — final args assembly (web search, image analysis, browser
  tool args), trace context env, Windows shell escaping, spawn,
  quota monitor wiring, cleanup handlers.
- New tests: 227 + 217 LOC.
- index.ts cleanup: numbered section comments through orchestrator,
  removed ~17 now-unused imports, re-export block preserved.

index.ts: 665 -> 550 LOC. Final reduction across all 10 phases:
1428 -> 550 (-878, -61%). Behavior unchanged; full suite passes
1824/1824. The remaining 550 LOC is the natural orchestrator floor —
further extraction would require a 15-field context struct, which is
manufactured complexity rather than genuine separation of concerns.

Closes phases 02-10 of #1162.

Refs #1162
2026-05-02 22:39:13 -04:00
Tam Nhu Tran 8b39d8a25f refactor(cliproxy/executor): extract proxy-chain-builder from index.ts
Phase 07 of #1162. Splits tool-sanitization + codex-reasoning proxy spawn
out of the orchestrator:

- src/cliproxy/executor/proxy-chain-builder.ts (185 LOC):
  buildProxyChain + ProxyChainContext / ProxyChainResult types.
  DI escape hatch (_ToolSanitizationProxy / _CodexReasoningProxy) for
  testability without refactoring the proxy classes (Bun module cache
  blocks mock.module of already-loaded modules).
- 9 unit tests covering codex-only, tool-san only, both-together,
  spawn failure swallowing, env propagation.

index.ts: 716 -> 665 LOC (-51). HTTPS tunnel kept inline because
tunnelPort is needed by image-analysis resolution before first-pass
buildClaudeEnvironment — folding it in would also require moving image
analysis. Two-pass buildClaudeEnvironment dance preserved exactly.
Behavior unchanged; full suite passes 1824/1824.

Refs #1162
2026-05-02 22:32:37 -04:00
Tam Nhu Tran 8b7e7f4847 refactor(cliproxy/executor): extract auth-coordinator from index.ts
Phase 06 of #1162. Splits the largest remaining concern out of the
orchestrator into a focused module:

- src/cliproxy/executor/auth-coordinator.ts (397 LOC):
  handleLogout, handleImport, resolveSkipLocalAuth, runAntigravityGate,
  ensureProviderAuthentication, runPreflightQuotaCheck,
  runAccountSafetyGuards, ensureModelConfiguration,
  ensureProviderSettingsFile. Preserves load-bearing ordering of
  antigravity gate -> auth -> token refresh -> quota check.
- 36 unit tests covering --auth/--logout/--import early exit,
  antigravity gate refusal/acceptance, OAuth trigger paths, composite
  providers, remote-proxy skipLocalAuth.

index.ts: 895 -> 716 LOC (-179). Behavior unchanged; full suite passes
1824/1824. Module is 397 LOC (over the <200 ideal) — kept whole because
the auth ordering contract should not be split across files.

Refs #1162
2026-05-02 22:03:46 -04:00
Tam Nhu Tran bc48613bbd refactor(cliproxy/executor): extract browser-setup and account-resolution
Phases 04+05 of #1162. Splits two more concerns out of the orchestrator:

- src/cliproxy/executor/browser-launch-setup.ts (118 LOC):
  resolveBrowserLaunchFlags + resolveBrowserRuntime. Encapsulates browser
  flag resolution, attach config, blocked-override warning, and runtime
  setup including MCP sync.
- src/cliproxy/executor/account-resolution.ts (197 LOC):
  resolveRuntimeQuotaMonitorProviders, resolveAccounts (--accounts /
  --use / --nickname / OAuth ban-risk warn / default touch),
  applyAccountSafetyGuards, touchDefaultAccount.
- New tests: 184 + 430 LOC covering both modules.

index.ts: 1045 -> 895 LOC (-150). resolveRuntimeQuotaMonitorProviders
re-exported from index.ts for __testExports backwards compat. Behavior
unchanged; full suite passes 1824/1824.

Refs #1162
2026-05-02 21:47:54 -04:00
Tam Nhu Tran 968681f261 refactor(cliproxy/executor): extract proxy-resolver from index.ts
Phase 03 of #1162. Splits proxy + binary resolution out of the orchestrator
into a focused module:

- src/cliproxy/executor/proxy-resolver.ts (196 LOC):
  ResolvedProxy + ResolveExecutorProxyContext interfaces, resolveExecutorProxy
  function. Encapsulates proxy config resolution, port mutation, remote
  reachability check, fallback prompt, local backend selection, and
  binary acquisition.
- src/cliproxy/executor/__tests__/proxy-resolver.test.ts: 10 unit tests
  covering local/remote/fallback paths.

index.ts: 1168 -> 1045 LOC (-123). Removes 9 now-unused imports. Browser
flag handling intentionally left in index.ts for Phase 04. Behavior
unchanged; full suite passes 1824/1824.

Refs #1162
2026-05-02 21:38:38 -04:00
Tam Nhu Tran 19d24954be refactor(cliproxy/executor): extract arg-parser from index.ts
Phases 01+02 of #1162. Splits executor flag parsing/validation out of the
1428-LOC orchestrator into a focused module:

New files:
- src/cliproxy/executor/arg-parser.ts (~500 LOC):
  readOptionValue, hasGitLabTokenLoginFlag, getGitLabTokenLoginFlagName,
  CCS_FLAGS + filterCcsFlags, ParsedExecutorFlags + parseExecutorFlags,
  validateFlagCombinations (process.exit semantics preserved for parity).
- src/cliproxy/executor/__tests__/arg-parser.test.ts: 45 unit tests.
- src/cliproxy/executor/__tests__/index-characterization.test.ts:
  TDD baseline (16 pass + 7 skipped scenarios at the spawn/dynamic-import
  boundary; mock simplification deferred to a follow-up phase).

index.ts: 1428 -> 1175 LOC (-253). Re-exports preserved at module bottom
for backwards compatibility. Behavior unchanged; full test suite passes
(1824/1824).

Refs #1162
2026-05-02 21:17:07 -04:00
Kai (Tam Nhu) TranandGitHub 50b0ffba75 fix(cliproxy): refresh upstream model and quota surfaces (#1158)
* fix(cliproxy): refresh upstream model and quota surfaces

* test(cliproxy): cover codex legacy model fallback
2026-05-01 02:19:31 -04:00
Kai (Tam Nhu) TranandGitHub b892739756 Merge pull request #1146 from kaitranntt/kai/feat/1138-logs-ui-redesign
feat(ui): redesign dashboard logs page (#1142)
2026-04-30 13:14:47 -04:00
Tam Nhu Tran bf8759460d feat(auth,commands): instrument oauth handler, profile registry, and doctor pipeline
Emit auth-stage events around OAuth round-trips and profile lookups so auth
flows are traceable end-to-end. Doctor command emits dispatch stages around
each health-check phase for clearer diagnostic logs.

Refs #1141, #1138
2026-04-30 13:00:16 -04:00
Tam Nhu Tran 33a1553431 test: include colocated cliproxy tests in buckets 2026-04-30 12:49:57 -04:00
Tam Nhu Tran 20c2005df9 fix(cliproxy): clear stale cleanup timer and fix session/tunnel edge cases
- Stop cleanup interval when all auth sessions are removed (unregister,
  cancel, cancelAll) so the Node event loop isn't held alive.
- getActiveSessionForProvider now returns the most recent session by
  startedAt instead of the first map entry.
- HTTPS tunnel includes port in Host header when non-443.
2026-04-29 18:13:15 -04:00
Tam Nhu Tran 6633bf456b fix(cliproxy): handle all invalid prefixes and reverse-order collisions
forceValidChars() now ensures leading char is letter or underscore
(catches dot, hyphen, colon, slash — not just digits). registerTools()
always registers in mapping so collisions are detected regardless of
tool registration order.
2026-04-29 18:04:19 -04:00
Tam Nhu Tran 218d0cf6c6 fix(cliproxy): sanitize invalid tool name chars and disambiguate collisions
sanitizeToolName() fallback now forces valid characters (replaces
unsupported chars with underscores, ensures leading letter/underscore)
instead of only truncating. registerTools() disambiguates colliding
sanitized names with numeric suffixes so restoreToolUse() always maps
back to the correct original.
2026-04-29 17:57:11 -04:00
Tam Nhu Tran 31dc18657c fix(cliproxy): fix base-config-loader __dirname path and stale mock.module paths
- base-config-loader.ts moved from src/cliproxy/ to src/cliproxy/config/,
  so __dirname relative path needs one more .. to reach config/ dir
- Update mock.module paths for proxy-detector and routing-strategy
  in non-colocated test files
2026-04-29 17:40:33 -04:00
Tam Nhu Tran c3c8cb7a82 fix(cliproxy): exclude colocated tests from tsconfig and eslint
- Add src/**/__tests__/** to tsconfig.json exclude list
- Add ignores pattern for __tests__ in eslint.config.mjs
- Fix ui/src/lib/api-client.ts import path for provider-entitlement-types
- Remove stale build artifacts from ui/src/lib/ and tests/mocks/
2026-04-29 17:18:23 -04:00
Tam Nhu Tran 273214d166 fix(cliproxy): correct relative import paths in colocated tests 2026-04-29 17:10:05 -04:00
Tam Nhu Tran 1c72b4b8d5 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
2026-04-29 17:06:39 -04:00
Tam Nhu Tran 5013d411a7 feat(cliproxy): self-pause exhausted quota accounts 2026-04-28 20:35:15 -04:00
Tam Nhu Tran 73c82b3567 Merge remote-tracking branch 'origin/dev' into kai/fix/1118-ai-provider-model-rules 2026-04-28 14:27:53 -04:00
Tam Nhu Tran 9a28ca55d8 fix(cliproxy): tolerate plain AI provider model rules 2026-04-28 14:19:21 -04:00
Tam Nhu Tran aa7f155161 test(cliproxy): stabilize routing endpoint coverage 2026-04-28 14:07:15 -04:00
Tam Nhu Tran 8ef703024b fix(cliproxy): probe routing via management endpoint 2026-04-28 14:02:58 -04:00
Kai (Tam Nhu) TranandGitHub b6432f783e Merge pull request #1114 from yousiki/fix/claude-utilization-percent-unit
fix(cliproxy): use explicit utilization unit per Claude payload form
2026-04-28 13:41:31 -04:00
Kai (Tam Nhu) TranandGitHub a8e0d95bc8 Merge pull request #1117 from kaitranntt/kai/feat/1115-session-affinity
feat: add local CLIProxy session affinity controls
2026-04-28 13:37:37 -04:00
Tam Nhu Tran 5267c421ca fix(cliproxy): harden session affinity behavior 2026-04-28 13:27:05 -04:00
Tam Nhu Tran 20f3916d55 fix(cliproxy): tighten session affinity status handling 2026-04-28 12:26:42 -04:00
Tam Nhu Tran 4309db89c3 feat(cliproxy): add local session affinity controls 2026-04-28 12:17:26 -04:00
2c82c81342 Update src/cliproxy/quota-fetcher-claude-normalizer.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-27 16:36:41 +09:00
yousiki 942a8ce12d fix(cliproxy): parse Codex additional_rate_limits for Spark quota
The Codex wham/usage API moved GPT-5.3 Codex Spark quota out of
code_review_rate_limit (now null) into a new additional_rate_limits[]
array. Parse the new field and surface it as Spark windows in the quota
view. Adds explicit category/cadence/featureLabel metadata on
CodexQuotaWindow so display logic does not depend on label sniffing.
The legacy label-sniffing path is preserved as a fallback so cached
windows from older versions still render correctly.
2026-04-27 15:07:44 +09:00
yousiki 9808ebfe36 fix(cliproxy): use explicit utilization unit per Claude payload form
Anthropic OAuth usage returns utilization as a percent (0-100) while the
older policy-limits restrictions payload returns a 0-1 ratio. The shared
heuristic "value <= 1 means ratio" misinterpreted percent values like
1.0, rendering 1% Sonnet usage as 100% used. Pass the unit explicitly
from each payload branch so the same boundary value is interpreted
correctly in either format.
2026-04-27 15:06:04 +09:00
Kai (Tam Nhu) TranandGitHub db3becfbe0 Merge pull request #1104 from sgaluza/sgaluza/fix-test-mock-contamination
test(cliproxy): replace process-wide mock.module with DI seams
2026-04-26 10:17:45 -04:00
Sergey Galuza a7871283d4 test(cliproxy): replace process-wide mock.module with DI seams
Bun's `mock.module()` is process-wide and is NOT undone by `mock.restore()`.
Two test files used module-level mocks that leaked across test runs,
silently breaking unrelated suites that imported the mocked modules
transitively:

- tests/unit/cliproxy/version-checker-stale-cache.test.ts mocked
  binary/version-checker, contaminating cliproxy-stats-routes-install
  and cliproxy-stats-routes-model-update suites that import a route
  module which transitively imports version-checker.
- tests/unit/cliproxy/service-manager-startup.test.ts mocked 8 modules
  at top level (binary-manager, stats-fetcher, etc.), contaminating any
  later file that imports them.

CI happens to be green because file ordering on the GitHub runner places
victim files BEFORE contaminators in `bun test`. On Linux locally the
order is reversed, producing 6 reproducible test failures on every
`bun run test:fast` run. A change in OS, bun version, or new test files
that import the mocked modules could silently flip the CI runner's
order and surface these failures unexpectedly.

Replaced module-level mocks with explicit dependency-injection seams in
production code, following the existing pattern in version-checker.ts
and version-cache.ts (`fetchJsonFn?`, `fetchLatestVersionFn?`):

- src/cliproxy/types.ts: `BinaryManagerConfig.checkForUpdatesFn` (optional)
- src/cliproxy/binary/lifecycle.ts: route through new fn with default
- src/cliproxy/service-manager.ts: `ensureCliproxyService(deps?)` with
  optional `ensureBinaryFn`, `detectRunningProxyFn`,
  `configNeedsRegenerationFn`, `withStartupLockFn`

All deps fields are optional with real-implementation defaults, so
production callers are unchanged. Tests now inject deterministic stubs
through call-site parameters instead of module-level mocks.

Verified locally: \`bun run validate\` is now 2540 pass / 0 fail
(previously 2534 pass / 6 fail at the same upstream/main HEAD).

Built [OnSteroids](https://onsteroids.ai)
2026-04-26 09:43:09 +02:00
Kai (Tam Nhu) TranandGitHub 5dd5878bb4 Merge pull request #1086 from BlackJulySnow/main
feat: add extra models support for API profiles
2026-04-25 12:07:01 -04:00
Tam Nhu Tran b1a0d1a175 fix(cliproxy/sync): dedup ANTHROPIC_EXTRA_MODELS entries against primary model 2026-04-25 11:30:33 -04:00
B1GGersnow 2915ab0c40 feat: add extra models support for API profiles
Add ANTHROPIC_EXTRA_MODELS env var to allow each API profile to
configure additional models alongside the primary ANTHROPIC_MODEL.
These are synced to CLIProxy config.yaml during ccs cliproxy sync.

- profile-mapper.ts: parse ANTHROPIC_EXTRA_MODELS on sync
- profile-writer.ts: write extra models to settings.json
- shared.ts + create-command.ts: --extra-models CLI flag
- profile-routes.ts + route-helpers.ts: REST API support
- profile-dialog.tsx + api-client.ts: frontend input
2026-04-25 03:20:29 +08:00
Tam Nhu Tran 4efd61ee34 feat: add gpt-5.5 to codex model catalogs 2026-04-24 10:30:59 -04:00
Tam Nhu Tran 7dd9aba810 chore: merge main hotfixes into dev 2026-04-23 23:49:18 -04:00
Tam Nhu Tran 7a9e67e6dc fix: route codex remote https through local proxy chain 2026-04-23 23:00:59 -04:00
Tam Nhu Tran 3d22bb07f0 fix(cliproxy): route plus backend to maintained fork 2026-04-23 21:25:29 -04:00
Tam Nhu Tran 50fa27f0a5 test(browser): split Browser MCP hook coverage by domain 2026-04-22 23:07:50 -04:00
Tam Nhu Tran 5ff0370c1c chore: merge origin/dev into pr-1061 fix branch 2026-04-22 22:38:20 -04:00
Tam Nhu Tran c24033dc6b fix(browser): preserve opt-in browser settings and env isolation 2026-04-22 22:35:02 -04:00
Kai (Tam Nhu) TranandGitHub 142381078e Merge pull request #1069 from sgaluza/feat/opus-4-7-adaptive-thinking
fix(cliproxy): use adaptive thinking for Opus 4.7 + add 'max' level
2026-04-22 22:03:21 -04:00
Tam Nhu Tran b3bc17639c fix(ui): surface the max thinking level in settings and help 2026-04-22 21:43:32 -04:00
Tam Nhu Tran 71deda553a fix(cliproxy): preserve adaptive thinking on opus 4.7 paths 2026-04-22 21:43:11 -04:00
Sergey GaluzaandOnSteroids 45fe7ab086 feat(cliproxy): add 'max' thinking level for Claude Opus 4.7
Anthropic exposes `max` as a distinct adaptive-thinking effort above
`xhigh` on Opus 4.7. Previously the validator aliased user input `max`
down to `xhigh`, so users couldn't reach the real top-tier effort
through CCS.

Extend the validator:
- Add `max` to VALID_THINKING_LEVELS and THINKING_LEVEL_RANK (rank 6,
  above xhigh)
- Add `max` to THINKING_LEVEL_BUDGETS (65536, CCS-internal numeric
  mapping for closest-level lookups)
- Widen ThinkingSupport.maxLevel union to include 'max'

The existing `max: 'xhigh'` alias in findClosestLevel is kept as a
graceful fallback for models whose levels list does not include `max`
(e.g. Codex `gpt-5.4`), because exact-match on validLevels takes
priority — so Opus 4.7 returns `max` directly while Codex still maps
`max` -> `xhigh`.

Update the claude.claude-opus-4-7 catalog entry to expose
`['low', 'medium', 'high', 'xhigh', 'max']` with `maxLevel: 'max'`.

Built [OnSteroids](https://onsteroids.ai)

Co-Authored-By: OnSteroids <built@onsteroids.ai>
2026-04-22 21:32:14 +02:00
Sergey GaluzaandOnSteroids 46920dbc08 fix(cliproxy): use adaptive thinking for Claude Opus 4.7
Per Anthropic docs, Claude Opus 4.7 only supports adaptive thinking;
manual `thinking.type: "enabled"` with `budget_tokens` is rejected
with HTTP 400.

Switch the claude provider's `claude-opus-4-7` entry from
`type: 'budget'` to `type: 'levels'` with the effort tiers exposed
by the API: `low | medium | high | xhigh`. The proxy is expected to
translate these into `thinking.type: "adaptive"` with the effort
parameter.

Opus 4.6 and Sonnet 4.6 keep `type: 'budget'` for now since the
deprecated mode is still functional on those models.

Built [OnSteroids](https://onsteroids.ai)

Co-Authored-By: OnSteroids <built@onsteroids.ai>
2026-04-22 21:09:21 +02:00
Tam Nhu Tran e2ca197397 fix: preserve codex effort suffixes in dashboard profiles 2026-04-22 14:24:00 -04:00