feat(provider): add ClinePass subscription provider - #880
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 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
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/adapters/openai-chat.ts (1)
1050-1054: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winPreserve usage in the failure-envelope fallback.
If
json.success === falseand the unwrapped payload has noerror, this return occurs beforeusageis parsed. A malformed failure response that includes usage therefore loses that metadata, while the later no-choice and no-message branches preserve it.Move usage extraction before this check and include it in the fallback error. Add a regression fixture with
success: false,usage, and noerror.Proposed fix
const payload = unwrapChatCompletionPayload(json); + const usage = usageFromOpenAIChat(payload.usage as Record<string, unknown> | undefined); if (json.success === false && payload.error === undefined) { - return [{ type: "error", message: "upstream reported failure without an error payload" }]; + return [{ + type: "error", + message: "upstream reported failure without an error payload", + ...(usage ? { usage } : {}), + }]; } - const usage = usageFromOpenAIChat(payload.usage as Record<string, unknown> | undefined);🤖 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 1050 - 1054, In the response handling flow around unwrapChatCompletionPayload, extract usage before the json.success === false fallback check and include the parsed usage in that error result. Preserve existing behavior for normal failure and no-choice/no-message paths, and add a regression fixture covering success: false with usage present but no error.
🤖 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.
Outside diff comments:
In `@src/adapters/openai-chat.ts`:
- Around line 1050-1054: In the response handling flow around
unwrapChatCompletionPayload, extract usage before the json.success === false
fallback check and include the parsed usage in that error result. Preserve
existing behavior for normal failure and no-choice/no-message paths, and add a
regression fixture covering success: false with usage present but no error.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 6f01aa80-dd5b-4b24-82e7-2bb5be8f9cd5
📒 Files selected for processing (2)
src/adapters/openai-chat.tstests/cline-pass-provider.test.ts
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/adapters/openai-chat.ts (2)
850-856: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winUse explicit error-presence checks.
In
src/adapters/openai-chat.ts, Line 850 and Line 1059 use truthiness to detect errors. This skips numeric0and empty-string errors, even though the adapter now classifies numeric and string upstream errors. In the streaming path, the adapter can then emit a successfuldoneevent. In the non-stream path, it reports the wrong no-choices error. Handle only missing ornullvalues as absent, and pass other values toupstreamErrorEvent.As per path instructions, add focused Bun regressions under
tests/**for streaming and non-streaming error payloads.Also applies to: 1052-1060
🤖 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 850 - 856, Replace truthiness-based error checks in the streaming branch around chunk.error and the non-streaming branch near the corresponding error handling with explicit checks that treat only missing or null values as absent; pass numeric 0 and empty-string payloads to upstreamErrorEvent. Add focused Bun regressions under tests/** covering both streaming and non-streaming numeric/string upstream error payloads, including the streaming terminate/error event and correct non-stream error behavior.Source: Path instructions
865-873: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick winValidate response choice shapes before dereferencing.
In
src/adapters/openai-chat.ts, Line 870 allowschoices: {}to pass the stream guard. Line 871 then readschoices[0].finish_reasonand throws. In the non-stream path, Line 1072 acceptschoices: [null], and Line 1073 dereferences the null value. These malformed upstream responses reject the request with an uncaughtTypeErrorinstead of a normalized adapter error.Check
Array.isArray(choices)and validate that the first choice is a non-null object before readingfinish_reason,delta,message, orerror. Preserve usage-only frames whenchoicesis absent, but terminate with a normalized malformed-response error for invalid choice shapes.As per path instructions, add focused Bun regressions under
tests/**for invalid stream and non-stream choice shapes.Also applies to: 1063-1074
🤖 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 865 - 873, Validate response shapes in the streaming and non-streaming parsing paths around the choices handling: require choices to be an array when present and require its first entry to be a non-null object before accessing finish_reason, delta, message, or error. Preserve usage-only frames when choices is absent, but route malformed choices—including an empty object or [null]—through the adapter’s normalized malformed-response error handling. Add focused Bun regressions under tests/** covering invalid stream and non-stream choice shapes.Source: Path instructions
🤖 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.
Outside diff comments:
In `@src/adapters/openai-chat.ts`:
- Around line 850-856: Replace truthiness-based error checks in the streaming
branch around chunk.error and the non-streaming branch near the corresponding
error handling with explicit checks that treat only missing or null values as
absent; pass numeric 0 and empty-string payloads to upstreamErrorEvent. Add
focused Bun regressions under tests/** covering both streaming and non-streaming
numeric/string upstream error payloads, including the streaming terminate/error
event and correct non-stream error behavior.
- Around line 865-873: Validate response shapes in the streaming and
non-streaming parsing paths around the choices handling: require choices to be
an array when present and require its first entry to be a non-null object before
accessing finish_reason, delta, message, or error. Preserve usage-only frames
when choices is absent, but route malformed choices—including an empty object or
[null]—through the adapter’s normalized malformed-response error handling. Add
focused Bun regressions under tests/** covering invalid stream and non-stream
choice shapes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 9f420986-e319-44fb-b27f-1d4f3ea97844
📒 Files selected for processing (2)
src/adapters/openai-chat.tstests/cline-pass-provider.test.ts
[shipping-github] Verdict: approve-commentPR: Semantic propagation
Linked: none UsefulnessReal user value: a canonical ClinePass preset with the 11 documented subscription slugs, a Cline usage-billing preset, and shared adapter hardening (non-stream Bugs / correctness
Security
Spec / standards
Reviews
Base / CI
GateNo draft/WIP/do-not-merge; Simplification (approved)Approved candidates C1-C6 applied and validated, no rollback needed:
Validation on the post-simplification head: typecheck, 136/136 focused tests, full-suite no-regression, privacy scan, GUI tests/lint/build — all green; each commit is independently revertable. The complete full review was re-run on the exact post-simplification head with simplification disabled. Bottom lineUseful, well-tested provider addition with no confirmed bugs or security findings, all bot feedback addressed, CI green on a dev-merged head. Approve on this evidence; the only unverified items are GitHub-side (ruleset/thread-resolution state) that this machine cannot query — a maintainer's final look before merge covers them. If |
… helpers Behavior-preserving simplification of the ClinePass adapter changes: - stopReasonFor() single-sources the finish_reason mapping used by the stream, EOF-residual, and non-stream done events. - reasoningTextFrom() shares the reasoning_content/reasoning delta extraction between stream and non-stream paths. - invalidChoicesEvent() replaces the three identical invalid-choices error constructions. - closeToolCalls() unifies the flush/discard/finally call-closing loops, and terminateWithError() shares the terminal stream error sequence.
isValidReasoningWireValue() now owns the value-shape invariant shared by recordAdapterReasoning and both persisted-usage normalizers, so the boolean-only-for-reasoning.enabled pairing cannot drift between the live capture path and persisted rows.
a1cea88 to
6f1efd7
Compare
|
Thanks @n3wr1ch — merging this. Why it helps: opencodex gets a canonical ClinePass preset with the 11 documented subscription slugs plus a Cline usage-billing preset, so users can point Codex and Claude at Cline's gateway without hand-rolled config. It also hardens the shared Ship it. |
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