-
Notifications
You must be signed in to change notification settings - Fork 235
feat(runtime): retire the Claude subscription OAuth provider #3183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Joob1n
wants to merge
10
commits into
apache:main
Choose a base branch
from
Joob1n:feat/retire-claude-subscription-oauth
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,568
−2,387
Open
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
66f94be
feat(runtime): retire the Claude subscription OAuth provider
Joob1n 6fc4447
fix(desktop): drop palette commands for retired connections
Joob1n 8b45b5b
fix(runtime): close the retired-provider selection and upgrade paths
Joob1n 366e70f
Merge remote-tracking branch 'origin/main' into feat/retire-claude-su…
Joob1n bded591
test(runtime-host): adapt the DeepSeek auxiliary case to the retired …
Joob1n 5da258d
chore: retrigger CI for a second windows_recovery data point
Joob1n 942e52e
chore: retrigger CI — two identical trees flaked on disjoint Windows …
Joob1n 985802b
fix(desktop): keep retired connections out of the subagent editor
Joob1n df59be7
fix(storage): plan retained retired connections as skipped on import
Joob1n 46d9eff
fix(storage): refuse editing a retained retired connection
Joob1n File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
67 changes: 67 additions & 0 deletions
67
apps/desktop/src/main/__tests__/command-palette-retired.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| import assert from 'node:assert/strict'; | ||
| import { test } from 'node:test'; | ||
| import type { LlmConnection } from '@maka/core/llm-connections'; | ||
| import { buildCommandList } from '../../renderer/command-palette-commands.js'; | ||
|
|
||
| function connection(overrides: Partial<LlmConnection> = {}): LlmConnection { | ||
| return { | ||
| slug: 'openai-live', | ||
| name: 'OpenAI Live', | ||
| providerType: 'openai', | ||
| defaultModel: 'gpt-4.1', | ||
| enabled: true, | ||
| models: [{ id: 'gpt-4.1' }], | ||
| modelSource: 'fetched', | ||
| createdAt: 1, | ||
| updatedAt: 1, | ||
| ...overrides, | ||
| }; | ||
| } | ||
|
|
||
| // A retained retired row is still enabled: retirement keeps the connection so | ||
| // the credential stays visible and deletable, and nothing flips its flag. | ||
| const retired = connection({ | ||
| slug: 'claude-subscription', | ||
| name: 'Claude Subscription', | ||
| providerType: 'claude-subscription', | ||
| defaultModel: 'claude-opus-5', | ||
| models: [{ id: 'claude-opus-5' }], | ||
| }); | ||
|
|
||
| function commandIds(connections: LlmConnection[], defaultSlug: string | null): string[] { | ||
| return buildCommandList({ | ||
| locale: 'en', | ||
| activeSessionId: undefined, | ||
| themePref: 'auto', | ||
| connections, | ||
| defaultSlug, | ||
| onNewChat: () => {}, | ||
| onOpenSettings: () => {}, | ||
| onOpenSettingsSection: () => {}, | ||
| onOpenShortcuts: () => {}, | ||
| onSetTheme: () => {}, | ||
| onTestConnection: () => {}, | ||
| onSetDefaultConnection: () => {}, | ||
| }).map((command) => command.id); | ||
| } | ||
|
|
||
| test('a retained retired connection gets no palette commands', () => { | ||
| // Settings hides "set as default" and "test connection" for a retired row, | ||
| // but the palette used to filter on `enabled` alone — offering commands the | ||
| // storage default-target gate and the hidden auth actions then refuse. | ||
| const live = connection({ slug: 'anthropic-live', name: 'Anthropic Live' }); | ||
| const ids = commandIds([connection(), live, retired], 'openai-live'); | ||
| // Positive control: a live non-default connection keeps both commands, so an | ||
| // over-broad filter cannot pass this test by dropping everything. | ||
| assert.ok(ids.includes(`connection:set-default:${live.slug}`)); | ||
| assert.ok(ids.includes(`connection:test:${live.slug}`)); | ||
| assert.ok(!ids.includes(`connection:set-default:${retired.slug}`)); | ||
| assert.ok(!ids.includes(`connection:test:${retired.slug}`)); | ||
| }); | ||
|
|
||
| test('a stale in-memory default pointing at a retired connection is not testable', () => { | ||
| // The catalog releases such a default on load; this covers the window where | ||
| // the renderer still holds the old slug. | ||
| const ids = commandIds([retired, connection()], retired.slug); | ||
| assert.ok(!ids.includes('diag:test-default')); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
apps/desktop/src/main/__tests__/provider-connection-status.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import assert from 'node:assert/strict'; | ||
| import { test } from 'node:test'; | ||
| import type { LlmConnection } from '@maka/core/llm-connections'; | ||
| import { connectionChipStatus } from '../../renderer/settings/provider-connection-status.js'; | ||
|
|
||
| function connection(overrides: Partial<LlmConnection> = {}): LlmConnection { | ||
| return { | ||
| slug: 'openai-live', | ||
| name: 'OpenAI Live', | ||
| providerType: 'openai', | ||
| defaultModel: 'gpt-4.1', | ||
| enabled: true, | ||
| models: [{ id: 'gpt-4.1' }], | ||
| modelSource: 'fetched', | ||
| createdAt: 1, | ||
| updatedAt: 1, | ||
| ...overrides, | ||
| }; | ||
| } | ||
|
|
||
| const retired = connection({ | ||
| slug: 'claude-subscription', | ||
| name: 'Claude Subscription', | ||
| providerType: 'claude-subscription', | ||
| defaultModel: 'claude-opus-5', | ||
| models: [{ id: 'claude-opus-5' }], | ||
| }); | ||
|
|
||
| test('a retired connection reads as broken rather than repairable', () => { | ||
| // Nothing else in the list marks this row, so without a status the only | ||
| // signal that it has to go is on the detail page the user has no reason to | ||
| // open. | ||
| assert.deepEqual(connectionChipStatus(retired, 'zh'), { | ||
| label: '已停用 · 请删除', | ||
| tone: 'error', | ||
| }); | ||
| assert.deepEqual(connectionChipStatus(retired, 'en'), { | ||
| label: 'Retired · delete it', | ||
| tone: 'error', | ||
| }); | ||
| }); | ||
|
|
||
| test('retirement outranks every repairable state', () => { | ||
| // Each of these would otherwise render a "sign in again" or "it failed, try | ||
| // again" status, and for a retired provider both point at nothing. | ||
| for (const overrides of [ | ||
| { lastTestStatus: 'needs_reauth' as const }, | ||
| { lastTestStatus: 'error' as const }, | ||
| { lastTestStatus: 'verified' as const }, | ||
| { enabled: false }, | ||
| ]) { | ||
| assert.deepEqual( | ||
| connectionChipStatus({ ...retired, ...overrides }, 'zh'), | ||
| { label: '已停用 · 请删除', tone: 'error' }, | ||
| `retirement must win over ${JSON.stringify(overrides)}`, | ||
| ); | ||
| } | ||
| }); | ||
|
|
||
| test('a live connection keeps its existing statuses', () => { | ||
| assert.equal(connectionChipStatus(connection({ lastTestStatus: 'verified' }), 'zh'), null); | ||
| assert.deepEqual(connectionChipStatus(connection({ lastTestStatus: 'needs_reauth' }), 'zh'), { | ||
| label: '需要重新登录', | ||
| tone: 'attention', | ||
| }); | ||
| assert.deepEqual(connectionChipStatus(connection({ enabled: false }), 'zh'), { | ||
| label: '暂不可用', | ||
| tone: 'neutral', | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.