Commit Graph
3846 Commits
Author SHA1 Message Date
github-actions[bot] 5e06010a4e chore(release): 7.77.1-dev.5 2026-05-07 06:17:52 -04:00
Kai (Tam Nhu) TranandGitHub 1b5376239f fix: preserve native Claude passthrough args
Closes #1189
2026-05-07 06:14:12 -04:00
github-actions[bot] 7e958784c4 chore(release): 7.77.1-dev.4 2026-05-06 17:39:30 -04:00
Kai (Tam Nhu) TranandGitHub ba18b68494 fix: count CLIProxy OAuth usage in dashboard stats (#1190)
* fix: count CLIProxy OAuth usage in dashboard stats

* fix: fill cliproxy oauth usage details from logs

* fix: keep mixed cliproxy oauth usage details

* fix: avoid aggregate usage enrichment inflation

* fix: cover oauth source prefixes and full log scans

* fix: preserve distinct oauth usage details

* fix: dedupe oauth log usage by auth identity

* fix: drain usage queue and preserve repeated oauth requests

* fix: guard usage queue drain against repeated full batches

* fix(cliproxy): harden oauth usage stats merging
2026-05-06 17:35:00 -04:00
github-actions[bot] a45b692c7a chore(release): 7.77.1-dev.3 2026-05-05 13:36:45 -04:00
Kai (Tam Nhu) TranandGitHub be9effcce3 feat: clarify account history sync route (#1187)
* feat: clarify account history sync route

* fix: clarify shared context command examples

* fix: report missing bare profile settings
2026-05-05 13:33:04 -04:00
github-actions[bot] 8df43585f4 chore(release): 7.77.1-dev.2 2026-05-05 11:55:33 -04:00
Kai (Tam Nhu) TranandGitHub 407a39c905 Merge pull request #1185 from kaitranntt/kai/fix/1183-openrouter-api-v1-path
fix: route OpenRouter profiles through v1 API
2026-05-05 11:52:01 -04:00
Kai (Tam Nhu) TranandGitHub b05bb30d44 fix(ui): surface Claude Opus 4.7 in Claude picker (#1184) 2026-05-05 11:49:53 -04:00
Tam Nhu Tran dc8bbd85e7 fix: route OpenRouter profiles through v1 API 2026-05-05 11:44:58 -04:00
Tam Nhu Tran 58af9cd501 fix(ui): surface Claude Opus 4.7 in Claude picker 2026-05-05 11:38:00 -04:00
github-actions[bot] fcfd2d279e chore(release): 7.77.1-dev.1 2026-05-04 20:26:33 -04:00
d6b705e6a9 fix(dispatcher): re-inject anthropic auth env for anthropic-compatible api profiles (#1181)
* fix(dispatcher): preserve anthropic auth env for settings profiles on non-proxy path

API profiles whose `ANTHROPIC_BASE_URL` is classified as `'anthropic'`
(anthropic.com, paths containing `/anthropic`, ollama.com) skip the
local OpenAI-compat proxy. The non-proxy launch path stripped
`ANTHROPIC_BASE_URL` / `ANTHROPIC_AUTH_TOKEN` / `ANTHROPIC_API_KEY`
from the subprocess env without re-injecting them, so Claude Code
launched with no routing/auth in `process.env` and failed with
`Not logged in - Please run /login`. The `--settings` env block does
not satisfy Claude Code's auth check.

Pre-existing for `anthropic.com` and `/anthropic` profiles. Newly
broken in v7.77.0 for Ollama Cloud profiles - PR #1175 reclassified
`ollama.com` from `generic-chat-completion-api` to `anthropic`,
moving it from the proxy path onto this broken non-proxy path.

Fix by extending `stripAnthropicRoutingEnv` with an optional
`preserveFrom` parameter. Routing keys present in `preserveFrom`
survive the strip (with values from `preserveFrom`). Settings-type
profiles pass their own `settings.env` as the preserve source so
routing they explicitly supplied is kept while routing leaked from
the parent shell or `global.env` is dropped.

Wired into both call sites:
- `headless-executor.ts` (the `-p` headless executor)
- `settings-flow.ts` (the interactive flow, which then calls
  `execClaude` - whose own `stripAnthropicRoutingEnv` pass on the
  merged env now also takes `envVars` as the preserve source so the
  caller-supplied routing is not stripped a second time before spawn)

Native Anthropic / Bedrock / Vertex profiles are unaffected (they
don't put routing keys in `settings.env`). The OpenAI-compat proxy
path is unaffected because `buildOpenAICompatProxyEnv` overrides
`BASE_URL` / `AUTH_TOKEN` with localhost values and explicitly deletes
`API_KEY` after this strip.

Replaces the Apr 21 defensive double-strip test (which was the
mechanism causing this regression on the interactive path) with a
test asserting the new contract: caller-supplied routing in `envVars`
survives, parent-process routing is still stripped.

* test: harden anthropic settings env preservation coverage

* fix: preserve explicit blank anthropic routing env

---------

Co-authored-by: Tam Nhu Tran <kaitran.ntt@gmail.com>
2026-05-04 20:22:13 -04:00
semantic-release-bot 95ad454ed5 chore(release): 7.77.1 [skip ci]
## [7.77.1](https://github.com/kaitranntt/ccs/compare/v7.77.0...v7.77.1) (2026-05-04)

### Bug Fixes

* harden cursor daemon model fallback ([5f05dea](https://github.com/kaitranntt/ccs/commit/5f05dea5acac9b07aa55b6d66215419cb26320e7))
* preserve arm64 compatibility for CLIProxy assets ([2274cef](https://github.com/kaitranntt/ccs/commit/2274cef6588b01e818b60e042481d31dc2f83dd1))
* preserve CLIProxy platform arch compatibility ([9a687fc](https://github.com/kaitranntt/ccs/commit/9a687fc03cf704a11e804780185ba24153766fd5))
* use aarch64 for CLIProxy arm assets ([190e820](https://github.com/kaitranntt/ccs/commit/190e820f99b100420f987c6669c2d89c0ce51d30))
* use aarch64 for CLIProxy arm assets ([70bf080](https://github.com/kaitranntt/ccs/commit/70bf0806f33bcf33e74dbe7a10b258879dc9f104))

### Styles

* apply prettier formatting ([4acc81c](https://github.com/kaitranntt/ccs/commit/4acc81c08221dbdff79319998ab1e290645ebb45))
2026-05-04 12:14:11 -04:00
Kai (Tam Nhu) TranandGitHub c371ba1044 Merge pull request #1180 from kaitranntt/dev
fix: promote CLIProxy ARM asset patch
2026-05-04 12:11:16 -04:00
github-actions[bot] 6089e1b178 chore(release): 7.77.0-dev.2 2026-05-04 11:59:13 -04:00
Tam Nhu Tran 5f05dea5ac fix: harden cursor daemon model fallback 2026-05-04 11:51:22 -04:00
Tam Nhu Tran 9a687fc03c fix: preserve CLIProxy platform arch compatibility 2026-05-04 11:39:47 -04:00
github-actions[bot] 4a0620d6c5 chore(release): 7.77.0-dev.1 2026-05-04 10:59:26 -04:00
Kai (Tam Nhu) TranandGitHub 190e820f99 fix: use aarch64 for CLIProxy arm assets
Preserve contributor commits and add maintainer compatibility coverage.
2026-05-04 10:55:52 -04:00
Tam Nhu Tran 2274cef658 fix: preserve arm64 compatibility for CLIProxy assets 2026-05-04 10:44:20 -04:00
juwain 4acc81c082 style: apply prettier formatting 2026-05-04 15:36:37 +03:00
juwain 70bf0806f3 fix: use aarch64 for CLIProxy arm assets 2026-05-04 14:59:14 +03:00
semantic-release-bot f1515961c4 chore(release): 7.77.0 [skip ci]
## [7.77.0](https://github.com/kaitranntt/ccs/compare/v7.76.0...v7.77.0) (2026-05-04)

### Features

* **cliproxy:** route plus dashboard to maintained fork ([#1173](https://github.com/kaitranntt/ccs/issues/1173)) ([923683b](https://github.com/kaitranntt/ccs/commit/923683bf303984959f8d5308bfd4c4294651d257))
* support ollama cloud anthropic compatible api ([#1175](https://github.com/kaitranntt/ccs/issues/1175)) ([4e2def6](https://github.com/kaitranntt/ccs/commit/4e2def6769ec71da2063588f867adaea7600df96))

### Bug Fixes

* **analytics:** cache native Codex usage scans ([11b12f1](https://github.com/kaitranntt/ccs/commit/11b12f146d65c32ef6b837b3daddc453d8bca11e))
* **cliproxy:** harden custom local port handling ([3862411](https://github.com/kaitranntt/ccs/commit/3862411bb7ac61fb52a13e53db95ae3b99d49c4b))
* **cliproxy:** refresh upstream model and quota surfaces ([#1158](https://github.com/kaitranntt/ccs/issues/1158)) ([50b0ffb](https://github.com/kaitranntt/ccs/commit/50b0ffba759b7de6fac525e31e5d02bde20b54f3))
* **cliproxy:** respect configured local port instead of hardcoding 8317 ([509bd5d](https://github.com/kaitranntt/ccs/commit/509bd5dbef008e1e0b5cf129744887cee99b9726))
* **config/loader:** break runtime cycle from normalizers to channels-runtime ([b6a49ee](https://github.com/kaitranntt/ccs/commit/b6a49eeab702906f8fb5e81d5022f1348fe4cd17)), closes [#1168](https://github.com/kaitranntt/ccs/issues/1168) [#1135](https://github.com/kaitranntt/ccs/issues/1135)

### Code Refactoring

* **cliproxy/executor:** extract arg-parser from index.ts ([19d2495](https://github.com/kaitranntt/ccs/commit/19d24954be62410b84f0a81f86f05716d5419da5)), closes [#1162](https://github.com/kaitranntt/ccs/issues/1162)
* **cliproxy/executor:** extract auth-coordinator from index.ts ([8b7e7f4](https://github.com/kaitranntt/ccs/commit/8b7e7f4847eec98b39cd1bac883cf4dd5aa30a2d)), closes [#1162](https://github.com/kaitranntt/ccs/issues/1162)
* **cliproxy/executor:** extract browser-setup and account-resolution ([bc48613](https://github.com/kaitranntt/ccs/commit/bc48613bbd06e8ca17d4b8acff466690d152f8ba)), closes [#1162](https://github.com/kaitranntt/ccs/issues/1162)
* **cliproxy/executor:** extract concerns from index.ts ([#1166](https://github.com/kaitranntt/ccs/issues/1166)) ([f7b8540](https://github.com/kaitranntt/ccs/commit/f7b854047e03cb3838fdd0dc4b1f4dc650e1c172)), closes [#1162](https://github.com/kaitranntt/ccs/issues/1162)
* **cliproxy/executor:** extract model-warnings + claude-launcher and polish orchestrator ([09268e7](https://github.com/kaitranntt/ccs/commit/09268e7e3307aea1508505692f83a2131e15f8a9)), closes [#1162](https://github.com/kaitranntt/ccs/issues/1162)
* **cliproxy/executor:** extract proxy-chain-builder from index.ts ([8b39d8a](https://github.com/kaitranntt/ccs/commit/8b39d8a25f3af8e6829b0164932e6a30c71ea20f)), closes [#1162](https://github.com/kaitranntt/ccs/issues/1162)
* **cliproxy/executor:** extract proxy-resolver from index.ts ([968681f](https://github.com/kaitranntt/ccs/commit/968681f261f6d0f00168347f4bdc203a151ef542)), closes [#1162](https://github.com/kaitranntt/ccs/issues/1162)
* **config/loader:** extract defaults-merger, config-getters, polish orchestrator ([f3e79fd](https://github.com/kaitranntt/ccs/commit/f3e79fd4e8c4986eea90fd37ffefac861e8e1598)), closes [#1164](https://github.com/kaitranntt/ccs/issues/1164)
* **config/loader:** extract io-locks, normalizers, yaml-serializer ([315ae19](https://github.com/kaitranntt/ccs/commit/315ae19387e90b55385fe631ca0b3187c8eeacc9)), closes [#1164](https://github.com/kaitranntt/ccs/issues/1164)
* **config/loader:** split unified-config-loader.ts ([#1168](https://github.com/kaitranntt/ccs/issues/1168)) ([2408987](https://github.com/kaitranntt/ccs/commit/240898785942194227b471486f4f05c88114478f)), closes [#1164](https://github.com/kaitranntt/ccs/issues/1164)
* **config:** adopt config-loader-facade across codebase ([#1169](https://github.com/kaitranntt/ccs/issues/1169)) ([df8efc9](https://github.com/kaitranntt/ccs/commit/df8efc985eb9b500b46baabf99a42c7e9aa71b6e)), closes [#1161](https://github.com/kaitranntt/ccs/issues/1161)
* **config:** adopt config-loader-facade across the codebase ([4f6e617](https://github.com/kaitranntt/ccs/commit/4f6e61739c13323484bcb036980e2553e6bb31bd)), closes [#1161](https://github.com/kaitranntt/ccs/issues/1161)
* **dispatcher:** extract bootstrap and pre-dispatch handlers from ccs.ts ([0cf4ad7](https://github.com/kaitranntt/ccs/commit/0cf4ad7b48b644c30d29dbce7fdfd78400320df4)), closes [#1165](https://github.com/kaitranntt/ccs/issues/1165)
* **dispatcher:** extract concerns from ccs.ts ([#1167](https://github.com/kaitranntt/ccs/issues/1167)) ([33de23c](https://github.com/kaitranntt/ccs/commit/33de23c6471b016bd669701bb3512ea900c14a7d)), closes [#1165](https://github.com/kaitranntt/ccs/issues/1165)
* **dispatcher:** extract per-profile flows from ccs.ts ([0910a75](https://github.com/kaitranntt/ccs/commit/0910a75850c149f29493d4a5db0c09486a8ac443)), closes [#1165](https://github.com/kaitranntt/ccs/issues/1165)
* **dispatcher:** extract profile and target detection from ccs.ts ([a807de6](https://github.com/kaitranntt/ccs/commit/a807de6f4cc3d328349075699b5fb27efd3e6e80)), closes [#1165](https://github.com/kaitranntt/ccs/issues/1165)
* **dispatcher:** scaffold src/dispatcher/ and extract pure helpers from ccs.ts ([f759cfe](https://github.com/kaitranntt/ccs/commit/f759cfeaaaef26591060a2746319cc5156287da8)), closes [#1165](https://github.com/kaitranntt/ccs/issues/1165)
* merge facade adoption from [#1169](https://github.com/kaitranntt/ccs/issues/1169) into ccs.ts dispatcher ([70b5dc2](https://github.com/kaitranntt/ccs/commit/70b5dc247f38af45b0cb622ed63dc3a05ae68ce1))
* merge facade adoption from [#1169](https://github.com/kaitranntt/ccs/issues/1169) into executor extraction ([05e1c35](https://github.com/kaitranntt/ccs/commit/05e1c352033afc1c141b60a64d88b6782124b621))
* structural maintainability batch ([#1171](https://github.com/kaitranntt/ccs/issues/1171)) ([b4d55d0](https://github.com/kaitranntt/ccs/commit/b4d55d0fda712f550510b3fc71bfc76b8f9fec40)), closes [#1135](https://github.com/kaitranntt/ccs/issues/1135)
2026-05-03 23:23:53 -04:00
Kai (Tam Nhu) TranandGitHub 0132b299a2 Merge pull request #1176 from kaitranntt/dev
feat: promote dev to main
2026-05-03 23:21:00 -04:00
github-actions[bot] adb1fff50c chore(release): 7.76.0-dev.6 2026-05-03 22:33:02 -04:00
4e2def6769 feat: support ollama cloud anthropic compatible api (#1175)
* feat(droid-provider): support ollama cloud anthropic compatible api

* fix(droid-provider): move ollama.com to anthropic block to prevent model inference override

* fix(droid-provider): move pathname-based generic checks before host-based anthropic check

* test(proxy): cover ollama cloud native routing boundaries

---------

Co-authored-by: Tam Nhu Tran <kaitran.ntt@gmail.com>
2026-05-03 22:28:38 -04:00
github-actions[bot] 0070f79b90 chore(release): 7.76.0-dev.5 2026-05-03 14:37:47 -04:00
Kai (Tam Nhu) TranandGitHub ea46dd0a54 Merge pull request #1170 from roeseth/fix/cliproxy-local-port-config
fix(cliproxy): respect configured local port instead of hardcoding 8317
2026-05-03 14:34:14 -04:00
Tam Nhu Tran 3862411bb7 fix(cliproxy): harden custom local port handling 2026-05-03 14:07:31 -04:00
Tam Nhu Tran a7c10be72e Merge origin/dev into fix/cliproxy-local-port-config
Resolve the dispatcher and dashboard conflicts from origin/dev while preserving the configured local CLIProxy port behavior. Also harden lifecycle port fallback and wait for the actual stopped port during binary installs.
2026-05-03 13:56:43 -04:00
github-actions[bot] 4aca635fbe chore(release): 7.76.0-dev.4 2026-05-03 13:04:37 -04:00
Kai (Tam Nhu) TranandGitHub 923683bf30 feat(cliproxy): route plus dashboard to maintained fork (#1173) 2026-05-03 13:01:04 -04:00
github-actions[bot] 0f36f7c845 chore(release): 7.76.0-dev.3 2026-05-03 12:28:26 -04:00
Kai (Tam Nhu) TranandGitHub b4d55d0fda refactor: structural maintainability batch (#1171)
refactor: structural maintainability batch (#1135)
2026-05-03 12:24:52 -04:00
Tam Nhu Tran b6a49eeab7 fix(config/loader): break runtime cycle from normalizers to channels-runtime
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
2026-05-03 12:20:32 -04:00
Tam Nhu Tran 164dcabd20 Merge remote-tracking branch 'origin/dev' into kai/refactor/1135-structural-maintainability 2026-05-03 12:00:48 -04:00
Kai (Tam Nhu) TranandGitHub 33de23c647 refactor(dispatcher): extract concerns from ccs.ts (#1167)
refactor(dispatcher): extract concerns from ccs.ts (#1165)
2026-05-03 11:57:26 -04:00
Tam Nhu Tran 70b5dc247f refactor: merge facade adoption from #1169 into ccs.ts dispatcher 2026-05-03 11:56:38 -04:00
Kai (Tam Nhu) TranandGitHub f7b854047e refactor(cliproxy/executor): extract concerns from index.ts (#1166)
refactor(cliproxy/executor): extract concerns from index.ts (#1162)
2026-05-03 11:54:58 -04:00
Tam Nhu Tran 05e1c35203 refactor: merge facade adoption from #1169 into executor extraction 2026-05-03 11:54:04 -04:00
Kai (Tam Nhu) TranandGitHub df8efc985e refactor(config): adopt config-loader-facade across codebase (#1169)
refactor(config): adopt config-loader-facade across codebase (#1161)
2026-05-03 11:51:14 -04:00
Kai (Tam Nhu) TranandGitHub 2408987859 refactor(config/loader): split unified-config-loader.ts (#1168)
refactor(config/loader): split unified-config-loader.ts (#1164)
2026-05-03 11:50:56 -04:00
MolkoandClaude Opus 4.7 509bd5dbef fix(cliproxy): respect configured local port instead of hardcoding 8317
All call sites that spawn or probe CLIProxyApiPlus now read
cliproxy_server.local.port from config via resolveLifecyclePort()
instead of using the hardcoded CLIPROXY_DEFAULT_PORT constant.

- Move resolveLifecyclePort helper to src/cliproxy/config/port-manager.ts
- Fix 7 call sites: ccs.ts, config-command.ts, copilot-executor.ts,
  lifecycle.ts, binary-manager.ts, cliproxy-stats-routes.ts,
  cliproxy-local-proxy.ts
- Remove duplicate resolveLocalCliproxyPort helper
- Cache port resolution in /proxy-status handler to avoid repeated I/O

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 07:40:48 -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 f3e79fd4e8 refactor(config/loader): extract defaults-merger, config-getters, polish orchestrator
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
2026-05-03 01:04:57 -04:00
Tam Nhu Tran 315ae19387 refactor(config/loader): extract io-locks, normalizers, yaml-serializer
Phases 1-3 of #1164. Pure code-motion split of unified-config-loader.ts
(1508 LOC) into focused modules:

- src/config/loader/io-locks.ts (301 LOC):
  Path constants, lock primitives (acquireLock, releaseLock,
  processExists), hasUnifiedConfig, hasLegacyConfig, getConfigFormat,
  sleepSync, withConfigWriteLock, loadUnifiedConfigWithLockHeld,
  writeUnifiedConfigWithLockHeld.
- src/config/loader/normalizers.ts (228 LOC):
  Browser config normalizers, session affinity TTL,
  validateCompositeVariants, continuity normalizers,
  normalizeOfficialChannelsConfig, LegacyDiscordChannelsConfig.
- src/config/loader/yaml-serializer.ts (349 LOC):
  generateYamlHeader, generateYamlWithComments.

unified-config-loader.ts: 1508 -> 827 LOC (-681). Orchestrator
re-exports moved symbols for backwards compat.

Forward-reference workaround: loadUnifiedConfigWithLockHeld and
writeUnifiedConfigWithLockHeld take mergeWithDefaults / serializer
callbacks as parameters to avoid circular imports. Phases 4-5 can
replace with direct imports once those modules extract their
dependencies.

Behavior unchanged; full suite passes 1824/1824.

Refs #1164
2026-05-03 00:28:22 -04:00
Tam Nhu Tran 0910a75850 refactor(dispatcher): extract per-profile flows from ccs.ts
Phases 5+6 of #1165. Final big extraction: collapses the 6-branch
profileInfo.type switch in main() into a single dispatchProfile call.

- src/dispatcher/dispatcher-context.ts (40 LOC): ProfileDispatchContext type
- src/dispatcher/flows/cliproxy-flow.ts (211 LOC)
- src/dispatcher/flows/copilot-flow.ts (66 LOC)
- src/dispatcher/flows/cursor-flow.ts (54 LOC)
- src/dispatcher/flows/settings-flow.ts (400 LOC)
- src/dispatcher/flows/settings-image-analysis-prep.ts (126 LOC):
  split out per plan to keep settings-flow control flow whole
- src/dispatcher/flows/account-flow.ts (63 LOC)
- src/dispatcher/flows/default-flow.ts (136 LOC)
- src/dispatcher/target-executor.ts (+38 LOC): dispatchProfile switch

settings-flow stays at 400 LOC — flow control (3 pre-flight blocks +
env construction + 2 dispatch paths) is maximally cohesive. Further
splitting would fragment dispatch logic per plan note.

process.exit parity preserved exactly (cliproxy non-claude path uses
process.exitCode=1; return; others use process.exit(1)).

ccs.ts: 1040 -> 170 LOC (-870). Full reduction across phases 1-6:
1775 -> 170 (-1605, -90%). main() body now ~100 LOC of awaited phase
calls. Behavior unchanged; full suite passes 1824/1824.

Refs #1165
2026-05-02 23:52:25 -04:00
Tam Nhu Tran a807de6f4c refactor(dispatcher): extract profile and target detection from ccs.ts
Phase 4 of #1165. Extracts the largest remaining concern in main():
profile detection, target resolution, Claude CLI detection, adapter
lookup, compatibility preflight, binary detection, droid prune, and
per-target arg normalization.

- src/dispatcher/profile-resolver.ts (358 LOC):
  resolveProfileAndTarget + ProfileResolutionContext / ResolvedProfile
  types. Includes droid + codex per-target arg normalization (cohesive
  with profile resolution; splitting would create incomplete extraction).
- 7 unit tests covering default, gemini, codex, unknown profile, droid,
  and compatibility preflight runs.

Compatibility preflight duplication between this phase and the settings
flow (Phase E) is preserved exactly per plan risk note 5 — do not dedupe
in this PR. Module is 358 LOC (over 300 ideal) — kept whole because the
profile resolution + per-target normalization form a single dependency
chain.

ccs.ts: 1262 -> 1040 LOC (-222). Behavior unchanged; full suite passes
1824/1824.

Refs #1165
2026-05-02 23:41:48 -04:00
Tam Nhu Tran 0cf4ad7b48 refactor(dispatcher): extract bootstrap and pre-dispatch handlers from ccs.ts
Phases 2+3 of #1165. Extracts main() bootstrap + pre-dispatch handler
chain into focused dispatcher modules:

- src/dispatcher/cli-argument-parser.ts (+138 LOC):
  bootstrapAndParseEarlyCli + DispatcherBootstrap. Encapsulates UI init,
  --config-dir parse/validate, cloud-sync warnings, completion command
  short-circuit, legacy cursor arg normalization, browser launch flag
  resolution, and native codex passthrough escape.
- src/dispatcher/pre-dispatch.ts (155 LOC):
  runPreDispatchHandlers. Wraps update check, root command router,
  provider help shortcut, copilot/cursor subcommand routing, first-time
  install hint. Returns boolean consumed signal.
- New tests: 12 + 7 covering both modules.

Adapter registration intentionally stays in main() — singleton wiring
with no arg dependency; folding it into bootstrap would conflate
concerns. ccs.ts: 1475 -> 1262 LOC (-213). Behavior unchanged; full
suite passes 1824/1824.

Refs #1165
2026-05-02 23:27:05 -04:00