The same atomic-rename divergence occurs in the plugins subtree: a
plugin install inside a session rewrites plugins/installed_plugins.json,
replacing the instance-level symlink with a regular file. The per-launch
relink then discarded it, so the plugin was effectively uninstalled on
every relaunch while settings.json still marked it enabled — sessions
then fail with 'Unknown skill: <plugin>:<skill>'.
Move adoptDivergedFileContent to fs-helpers (avoids a circular import)
and apply it to file-type plugin entries before re-linking.
Claude Code saves settings.json atomically (temp file + rename), which
replaces the managed shared symlink with a regular file holding the
user's latest changes (see #57). The launch-time relink then deleted
that file without reading it, silently reverting plugin enables and any
other in-session settings change on every profile relaunch.
Adopt the diverged file's content into the canonical ~/.claude file
(with a .bak-ccs-adopt backup) before restoring the symlink, at both
the shared-level and instance-level reconciliation points.
Fixes#1681
The CCS Bar server was crash-looping with:
[X] Cannot read properties of undefined (reading 'length')
Usage records from partially-written or legacy persisted files (e.g. a
Codex rollout scanned mid-write) can be missing modelBreakdowns despite
the type. getHourlyRequestCount() and the daily/monthly/hourly merges
read it unguarded, and the Bar re-runs aggregation every ~5 min and
restarts on crash - hence the loop.
Default modelBreakdowns to [] at every use site and fall back to 0 for
request count. Regression test added for all three merges.
I don't normally work in TS and this was heavily tool-assisted, but it
has fixed the crash loop on my machine.
Add explicit `claude-sonnet-5` and `claude-sonnet-5-thinking` entries to the
web-server PRICING_REGISTRY at the standard Sonnet rates ($3/$15 in/out,
$3.75/$0.30 cache).
The model catalog and dashboard already ship Sonnet 5 (it is the Claude
default), but pricing was missing: getModelPricing() fell through to
UNKNOWN_MODEL_PRICING, which only coincidentally matches Sonnet rates. As a
result hasCustomPricing('claude-sonnet-5') returned false and getKnownModels()
omitted it, so Sonnet 5 was treated as an unknown model in cost accounting and
known-model listings.
Registering it explicitly makes the pricing intentional and consistent with
every other Claude model, without changing any resolved values.
Built [OnSteroids](https://onsteroids.ai)
generateThinkingSignature() returned an object
({type, hash, length, timestamp}) but Anthropic requires a thinking
block's `signature` to be a non-empty opaque STRING. The object made
the thinking block invalid, breaking the stream against reasoning
backends and surfacing as a false 502 "did not respond within 600s".
Return a deterministic base64 token instead (no Date.now()), and
narrow ThinkingSignature to a string alias so existing imports stay
intact. The signature is only ever assigned, never read as an object,
so consumers are unaffected. Update the existing unit test to the
corrected string contract.
Built [OnSteroids](https://onsteroids.ai)
Add two contract tests on the public proxy path
createAnthropicProxyResponse: JSON and SSE. Anthropic requires a
thinking block's signature to be a non-empty opaque string, but ccs
currently fabricates the signature as an object via
generateThinkingSignature(), which breaks the stream against reasoning
backends.
Built [OnSteroids](https://onsteroids.ai)
Google retired the gemini CLI on 2026-06-18, so the gemini websearch fallback no longer
works. Add agy (Antigravity) as the primary CLI websearch provider end to end: runtime spawn
in websearch-transformer.cjs (agy --dangerously-skip-permissions --print-timeout Ns -p),
detection (agy.ts), config schema and defaults, hook env, status, dashboard persistence, and docs.
The legacy gemini provider stays present but is marked deprecated for enterprise users who
retain access. Image analysis already supported the agy provider (no change). The CLIProxy
gemini quota fetcher (Gemini API OAuth, not the cli binary) is untouched.
Validation: typecheck, lint, and the websearch + config + web-server unit suites pass.
Add a Requesty provider preset to the provider preset catalog, mirroring the existing OpenRouter preset (base https://router.requesty.ai/v1, default model openai/gpt-4o-mini, OpenAI-compatible).