feat(provider): add ClinePass subscription provider - #880
Conversation
📝 WalkthroughWalkthroughThe change adds the ClinePass provider preset, gateway-object reasoning configuration, hardened OpenAI-compatible response handling, boolean reasoning diagnostics, tests, and localized documentation. ChangesClinePass gateway integration
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant openaiChatAdapter
participant ClinePassGateway
participant RequestLog
Client->>openaiChatAdapter: Send provider request
openaiChatAdapter->>ClinePassGateway: Send gateway-object reasoning payload
ClinePassGateway-->>openaiChatAdapter: Return wrapped response or normalized error data
openaiChatAdapter->>RequestLog: Record reasoning wire fields and usage
openaiChatAdapter-->>Client: Emit reasoning, completion, usage, or error events
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs-site/src/content/docs/guides/providers.md`:
- Around line 193-210: Update the openai-chat adapter reference in the primary
and ja, ko, ru, and zh-cn localized documents to document ClinePass, including
its reasoning object format, the live-verified low reasoning clamp, reasoning
deltas, and usage handling. Use the existing provider guide’s ClinePass facts
and keep the documentation consistent across all adapter references.
In `@src/adapters/base.ts`:
- Around line 51-56: Update the reasoningLog type in the adapter base definition
to a discriminated union keyed by wireField, pairing each field with its valid
wireValue type: boolean only for "reasoning.enabled", numeric values for
"thinking_budget", and string values for the remaining reasoning fields.
Preserve effectiveEffort on every union member so producers and
recordAdapterReasoning retain the existing diagnostics contract.
In `@src/router.ts`:
- Around line 279-281: Add a route test for a matching ClinePass provider whose
config explicitly sets reasoningWireFormat to "gateway-object". Assert that
routeModel() preserves this explicit value rather than replacing it with the
registry entry, alongside the existing registry-backfill and
non-matching-provider cases in cline-pass-provider.test.ts.
In `@src/usage/log.ts`:
- Around line 271-277: Update normalizeUsageAttempt and normalizeUsageEntry so
boolean reasoningWireValue is preserved only when the corresponding
reasoningWireField equals "reasoning.enabled", matching recordAdapterReasoning;
continue accepting string values and non-negative finite numeric values through
their existing paths, and omit mismatched boolean pairs.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 97bd7df2-f305-4852-beef-9753dc6a982b
📒 Files selected for processing (33)
docs-site/src/content/docs/getting-started/quickstart.mddocs-site/src/content/docs/guides/providers.mddocs-site/src/content/docs/ja/getting-started/quickstart.mddocs-site/src/content/docs/ja/guides/providers.mddocs-site/src/content/docs/ja/reference/configuration/providers.mddocs-site/src/content/docs/ko/getting-started/quickstart.mddocs-site/src/content/docs/ko/guides/providers.mddocs-site/src/content/docs/ko/reference/configuration/providers.mddocs-site/src/content/docs/reference/configuration/providers.mddocs-site/src/content/docs/ru/getting-started/quickstart.mddocs-site/src/content/docs/ru/guides/providers.mddocs-site/src/content/docs/ru/reference/configuration/providers.mddocs-site/src/content/docs/zh-cn/getting-started/quickstart.mddocs-site/src/content/docs/zh-cn/guides/providers.mddocs-site/src/content/docs/zh-cn/reference/configuration/providers.mdgui/src/hooks/useJsonConfigEditor.tsgui/src/pages/Logs.tsxgui/src/pages/providers-shared.tssrc/adapters/base.tssrc/adapters/openai-chat.tssrc/providers/derive.tssrc/providers/registry.tssrc/router.tssrc/server/auth-cors.tssrc/server/request-log.tssrc/types.tssrc/usage/log.tstests/cline-pass-provider.test.tstests/openai-chat-eof.test.tstests/openai-chat-hardening.test.tstests/provider-registry-parity.test.tstests/request-log.test.tstests/server-auth.test.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/adapters/openai-chat.ts`:
- Around line 105-115: In src/adapters/openai-chat.ts lines 105-115, update
upstreamErrorEvent to sanitize rawMessage for credential-shaped API keys, bearer
tokens, and OAuth values before constructing message, while preserving benign
text and replacing secrets with a fixed redaction marker. In
tests/cline-pass-provider.test.ts lines 241-245, add a secret-shaped upstream
error fixture and assert the emitted message does not contain the original
secret.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: fcb349ea-76da-45c0-9858-4b7ef18e1afe
📒 Files selected for processing (2)
src/adapters/openai-chat.tstests/cline-pass-provider.test.ts
| error: OpenAIChatError | string | undefined, | ||
| usage?: OcxUsage, | ||
| ): Extract<AdapterEvent, { type: "error" }> { | ||
| const details = typeof error === "string" ? undefined : error; | ||
| const rawMessage = typeof error === "string" | ||
| ? error.trim() || "upstream error" | ||
| : typeof details?.message === "string" ? details.message : "upstream error"; | ||
| const requestId = safeUpstreamRequestId(details?.metadata); | ||
| const message = requestId !== undefined && !rawMessage.includes(requestId) | ||
| ? `${rawMessage} (request ID: ${requestId})` | ||
| : rawMessage; |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Redact credential material before returning upstream error text.
upstreamErrorEvent forwards a string-valued upstream error directly into an AdapterEvent message. A gateway can include an echoed API key, bearer token, or OAuth value in that text. This path can expose configured provider credentials to downstream clients.
Sanitize both raw string errors and details.message at this adapter boundary. Preserve benign messages. Replace credential-shaped values with a fixed redaction marker. Update the test to verify that a secret-shaped upstream error is not returned verbatim.
src/adapters/openai-chat.ts#L105-L115: Redact sensitive values inrawMessagebefore constructingmessage.tests/cline-pass-provider.test.ts#L241-L245: Add a secret-shaped error fixture and assert that the emitted message does not contain the secret.
📍 Affects 2 files
src/adapters/openai-chat.ts#L105-L115(this comment)tests/cline-pass-provider.test.ts#L241-L245
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/adapters/openai-chat.ts` around lines 105 - 115, In
src/adapters/openai-chat.ts lines 105-115, update upstreamErrorEvent to sanitize
rawMessage for credential-shaped API keys, bearer tokens, and OAuth values
before constructing message, while preserving benign text and replacing secrets
with a fixed redaction marker. In tests/cline-pass-provider.test.ts lines
241-245, add a secret-shaped upstream error fixture and assert the emitted
message does not contain the original secret.
Source: Path instructions
Summary
cline-pass/<model>upstream ids and seed context-window and input-modality metadatareasoningWireFormatthrough the safe management DTO and keep GUI diagnostics, provider docs, and all five documentation locales synchronizedWhy
Cline officially supports using ClinePass outside the Cline clients through its OpenAI-compatible Chat Completions API. OpenCodex previously had no canonical preset for that subscription route, so users had to configure the endpoint manually and would lose gateway-specific reasoning, error, and non-stream response behavior.
The adapter fixes are intentionally shared where they describe valid OpenAI-compatible response behavior. Regression coverage protects ordinary non-Cline providers from changes to standard response parsing and pending tool-call termination.
Primary-source evidence
Verified 2026-08-02:
@lidge-junThe public API reference does not currently document the
reasoning: { enabled, effort }request object or the{ success, error, data }non-stream envelope. Those two shapes are explicitly marked in code as live-observed on 2026-08-02. Only the live-acceptedlowreasoning tier is advertised until Cline documents or validates a broader ladder.Security and privacy
https://api.cline.bot/api/v1reasoningWireFormatis added only to the existing non-secret management DTO allowlistThis provider preset changes a credential destination and therefore requires explicit security review before merge.
Validation
bun run typecheckbun run test— 6,973 passed, 8 skipped, 0 failedbun run privacy:scancd gui && bun test tests— 493 passed, 0 failedcd gui && bun run lintcd gui && bun run buildcd docs-site && bun install --frozen-lockfilecd docs-site && bun run build— 206 pages builtSummary by CodeRabbit
New Features
Documentation
Bug Fixes