Skip to content

Commit 54ac427

Browse files
authored
feat: add kimi and minimax oauth login (#291)
## Related Issue No tracking issue — maintainer-directed change in the repository owner's branch. ## Problem Two independent gaps: 1. The login flow only offered API-key platforms and OpenAI Codex OAuth. Kimi For Coding and MiniMax (global and China) subscriptions could not be connected from pythinker-code. 2. OpenCode Go requires the `x-opencode-session` header (one stable id per conversation) on gateway requests; pythinker-code did not send it. OpenCode billing rejections such as `401 Insufficient balance` were also being mislabeled as authentication failures. ## What changed - Added Kimi For Coding and MiniMax OAuth sign-in for global and China regions. - Kimi now uses the official device flow, stable device identity headers, sanitized host OS release, persisted OAuth credentials, refresh-token rotation, and restart-safe runtime refresh. - MiniMax now follows the official MiniMax CLI PKCE/state device flow, including `user_code`, millisecond `expired_in`, provider-specific polling semantics, persisted OAuth credentials, refresh-token rotation, and regional endpoints. - OAuth bearer tokens and refresh tokens are no longer embedded in `config.toml`; providers reference the existing credential store instead. - Runtime OAuth refresh uses a five-minute proactive refresh window, forced refresh after authorization failure, single-flight refresh for concurrent requests, and persistence of rotated credentials. - Device authorization cancellation now aborts the initial request and cannot open a browser after cancellation. Kimi/MiniMax cancellation during model selection/config loading resolves the login flow as `false` without committing config. - `scripts/check-product-boundaries.mjs`: the hosted-inference-endpoint guard exempts `packages/oauth/src/kimi-oauth.ts` via the existing allow mechanism because the direct device-OAuth login legitimately targets that upstream; every other surface stays banned. - Model requests to HTTPS OpenCode gateway hosts (`opencode.ai` and subdomains) send `x-opencode-session` with a stable conversation id. HTTP and lookalike hosts receive no session header. The one-shot connectivity probe generates a fresh UUID for every probe. - OpenCode `401 Insufficient balance` responses are classified as provider/billing failures rather than `provider.auth_error`; ordinary invalid-credential 401 responses remain authentication errors. - Added focused regression coverage for OAuth protocol behavior, refresh/rotation, cancellation, credential references, OpenCode billing classification, HTTPS-only session headers, and fresh ping session IDs. - Changesets are included for the user-facing changes. ## Checklist - [x] I have read the [CONTRIBUTING](https://github.com/PyModel/pythinker-code/blob/main/CONTRIBUTING.md) document. - [x] No related issue is required for this maintainer-directed change. - [x] I have added tests that prove the feature and fixes work. - [x] Ran `gen-changesets` skill, or this PR needs no additional changeset. - [x] Ran `gen-docs` skill, or this PR needs no doc update. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added OAuth sign-in for Kimi For Coding and MiniMax in global and China regions. * Added device-code authentication, model selection, cancellation, and account configuration. * Added per-conversation session support for OpenCode Go requests. * Added custom request-header support across supported AI providers. * Added a workspace endpoint for adding directories. * **Bug Fixes** * Improved OAuth refresh reliability, concurrency protection, timeouts, and credential preservation. * Improved browser sign-in fallback and Windows Codex login. * Improved authentication, billing, and quota error handling. * Updated permission-mode labels and trust-prompt defaults. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 7838e5e commit 54ac427

124 files changed

Lines changed: 4332 additions & 633 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/agent-core-review/slop/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Severity grades, merge/block verdicts, and "is splitting worth it" calls live do
2424

2525
## When to use
2626

27-
Apply this lens only when the user asks for it explicitly (for example "用单一抽象层次审视一下", "check whether this function does too much", "errors should be handled above/below, right?"). Leave general reviews and refactors to other lenses unless the user names this one.
27+
Apply this lens only when the user asks for it explicitly (for example "review the levels of abstraction", "check whether this function does too much", "errors should be handled above/below, right?"). Leave general reviews and refactors to other lenses unless the user names this one.
2828

2929
## The principle
3030

.agents/skills/write-tui/DESIGN.md

Lines changed: 137 additions & 137 deletions
Large diffs are not rendered by default.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pymodel/pythinker-code": minor
3+
---
4+
5+
Add OAuth sign-in for Kimi For Coding and MiniMax (global and China) to the login flow.

.changeset/kimi-refresh-token.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pymodel/pythinker-code": patch
3+
---
4+
5+
Keep the stored refresh token when a provider refresh response omits a replacement.

.changeset/never-ask-guard.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pymodel/pythinker-code": patch
3+
---
4+
5+
Stop blocking dangerous Bash commands in Never Ask mode.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pymodel/pythinker-code": patch
3+
---
4+
5+
Prevent concurrent sessions from overwriting each other's refreshed sign-in tokens.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pymodel/pythinker-code": patch
3+
---
4+
5+
Bound OAuth refresh requests with a timeout and reject tokens that arrive after expiry.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pymodel/pythinker-code": patch
3+
---
4+
5+
Send OpenCode Go requests with a per-conversation session header.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pymodel/pythinker-code": patch
3+
---
4+
5+
Rename the permission modes to Always Ask, Ask When Needed, and Never Ask, and open the mode list for /yolo and /auto.

.changeset/trust-prompt-default.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pymodel/pythinker-code": patch
3+
---
4+
5+
Default the workspace trust prompt to Trust this folder and require Enter to confirm.

0 commit comments

Comments
 (0)