Skip to content

fix: subscription truncation orphans, stale credential sync, header leak - #9

Merged
0xPuncker merged 3 commits into
mainfrom
feat/check-cc-proxy-usage
Jun 25, 2026
Merged

fix: subscription truncation orphans, stale credential sync, header leak#9
0xPuncker merged 3 commits into
mainfrom
feat/check-cc-proxy-usage

Conversation

@0xPuncker

Copy link
Copy Markdown
Owner

Restores the Claude subscription path through the proxy by fixing three defects. Context-window truncation could leave an orphaned tool_result as the first message (its tool_use was dropped), which Anthropic rejected with messages.0.content.0: unexpected tool_use_id and cascaded into all-provider failure — truncation now trims the front boundary to a valid leading user turn. The com.claude.sync-credentials LaunchAgent pointed at a script inside a deleted Conductor workspace, so credential sync silently died and the OAuth token went stale (invalid_grant); setup now installs the script to the stable ~/.claude path and generates the plist there. Also stops leaking Anthropic auth headers to fallback providers (OpenRouter/Z.AI). Adds tests for orphan repair, pair integrity, and header isolation; full suite passes (104) and lint is clean.

…iders

buildProviderHeaders forwarded all of Claude Code's incoming headers to
OpenRouter/Z.AI except 4 hop-by-hop ones, including x-api-key. OpenRouter
treats a stray x-api-key as a restricted data-policy request and returns
'404: No endpoints available matching your guardrail restrictions' — so
the OpenRouter fallback was dead for every real (Claude Code) request,
even though the model slug and endpoint were correct.

Strip Anthropic-specific routing/auth headers (x-api-key, anthropic-version,
anthropic-beta, anthropic-dangerous-direct-browser-access) and content-length
(recomputed after cleanBody) from the cross-provider passthrough. Verified
end-to-end: OpenRouter now returns 200 with full Opus via ~anthropic/claude-opus-latest.
When a conversation exceeded the context-window threshold, truncation kept
a contiguous suffix of the most recent messages but could leave a `user`
turn whose leading `tool_result` referenced a `tool_use` from an assistant
message that was just dropped. Anthropic rejected this with:

  messages.0.content.0: unexpected `tool_use_id` found in `tool_result`
  blocks ... Each `tool_result` block must have a corresponding `tool_use`
  block in the previous message.

The subscription request 400'd and both fallbacks (Anthropic API / Z.AI)
also failed, surfacing a hard error to the client on long agentic sessions.

Fix: after selecting the kept window, trim from the front until it starts
on a valid leading turn (a `user` message with no orphaned tool_result).
Front-only trimming is safe — every tool_use/tool_result pair inside the
suffix stays intact; only the boundary can be orphaned. Guard the degenerate
empty-window case by skipping truncation rather than emitting empty messages.

Adds tests for orphan repair and pair integrity within the kept window.
The LaunchAgent was pointed at the sync script inside a Conductor workspace
(.../worcester/scripts/sync-credentials.sh). When that workspace was deleted
the script vanished, the agent failed every 5 min (exit 127), and the mounted
credentials file went stale — the subscription OAuth refresh token rotated on
the host and Anthropic invalidated the proxy's copy (invalid_grant), taking
the subscription provider offline.

- setup-credential-sync.sh now installs sync-credentials.sh to ~/.claude/
  (workspace-independent) and generates the plist pointing there, instead of
  sed-rewriting a hardcoded per-user workspace path. Uses bootstrap/bootout
  with load/unload fallback and kickstarts once to verify.
- Update the committed plist template to the stable ~/.claude path.

Survives workspace deletion; the proxy reads the file per-request so refreshed
tokens are picked up with no restart.
@0xPuncker
0xPuncker merged commit c0e2ab5 into main Jun 25, 2026
3 checks passed
@0xPuncker
0xPuncker deleted the feat/check-cc-proxy-usage branch June 25, 2026 12:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant