Skip to content

Commit 164af64

Browse files
committed
refactor: name the managed provider after the platform serving it
The managed OAuth provider authenticates against auth.kimi.com and serves its models from api.kimi.com, but it was registered as `managed:pythinker-code`. In a client that talks to several providers that reads as a first-party service rather than the one it actually is, and the models it installed carried a `pythinker-code/` prefix that said the same thing. It is now `managed:kimi-code`, with `kimi-code/*` model aliases and credentials under `oauth/kimi-code`. The provider name also stops being redeclared as a bare literal in four places and comes from the single exported constant instead. Existing configs are not rewritten: signing in again provisions the provider under its current name.
1 parent a48d656 commit 164af64

77 files changed

Lines changed: 949 additions & 942 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.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@pythoughts/pythinker-code": minor
3+
"@pythoughts/pythinker-code-sdk": minor
4+
---
5+
6+
Name the managed OAuth provider after the platform that serves it. It is reached over `auth.kimi.com` and `api.kimi.com`, but it was registered as `managed:pythinker-code`, which read as a first-party service in a client that talks to several providers. The provider id is now `managed:kimi-code`, its models are aliased `kimi-code/*`, and its credentials are stored under `oauth/kimi-code`.
7+
8+
This is a breaking change for an existing config: the previous entries are not rewritten, so run `pythinker login` once to provision the managed provider under its current name, then remove the stale `managed:pythinker-code` entry.

apps/pythinker-code/src/cli/sub/provider.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
CustomRegistryApiError,
1818
fetchCustomRegistry,
1919
type CustomRegistrySource,
20-
type ManagedPythinkerConfigShape,
20+
type ManagedKimiConfigShape,
2121
} from '@pythoughts/pythinker-code-oauth';
2222
import {
2323
catalogConnectionWire,
@@ -517,8 +517,8 @@ function resolveApiKey(flag: string | undefined, env: NodeJS.ProcessEnv): string
517517
return undefined;
518518
}
519519

520-
function asManaged(config: PythinkerConfig): ManagedPythinkerConfigShape {
521-
return config as unknown as ManagedPythinkerConfigShape;
520+
function asManaged(config: PythinkerConfig): ManagedKimiConfigShape {
521+
return config as unknown as ManagedKimiConfigShape;
522522
}
523523

524524
function providerSourceLabel(provider: PythinkerConfig['providers'][string]): string {

apps/pythinker-code/src/cli/telemetry.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createPythinkerDeviceId, PYTHINKER_CODE_PROVIDER_NAME } from '@pythoughts/pythinker-code-oauth';
1+
import { createPythinkerDeviceId, KIMI_CODE_PROVIDER_NAME } from '@pythoughts/pythinker-code-oauth';
22
import {
33
PythinkerAuthFacade,
44
loadRuntimeConfigSafe,
@@ -55,7 +55,7 @@ export function initializeCliTelemetry(options: InitializeCliTelemetryOptions):
5555
uiMode: options.uiMode,
5656
model: options.model ?? options.config.defaultModel,
5757
getAccessToken: async () =>
58-
(await options.harness.auth.getCachedAccessToken(PYTHINKER_CODE_PROVIDER_NAME)) ?? null,
58+
(await options.harness.auth.getCachedAccessToken(KIMI_CODE_PROVIDER_NAME)) ?? null,
5959
});
6060
if (options.bootstrap.firstLaunch) {
6161
options.harness.track('first_launch');
@@ -102,7 +102,7 @@ export function initializeServerTelemetry(
102102
version: options.version,
103103
uiMode: WEB_UI_MODE,
104104
model: config.defaultModel,
105-
getAccessToken: async () => (await auth.getCachedAccessToken(PYTHINKER_CODE_PROVIDER_NAME)) ?? null,
105+
getAccessToken: async () => (await auth.getCachedAccessToken(KIMI_CODE_PROVIDER_NAME)) ?? null,
106106
});
107107

108108
return {

apps/pythinker-code/src/constant/app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const PYTHINKER_CODE_BANNER_DIR_NAME = 'banner';
3434
export const PYTHINKER_CODE_BANNER_STATE_FILE_NAME = 'state.json';
3535

3636
// Managed Pythinker auth provider key shared with OAuth/SDK config.
37-
export const DEFAULT_OAUTH_PROVIDER_NAME = 'managed:pythinker-code';
37+
export { KIMI_CODE_PROVIDER_NAME as DEFAULT_OAUTH_PROVIDER_NAME } from '@pythoughts/pythinker-code-oauth';
3838

3939
// SDK/core error code that tells the TUI to show a login-required startup
4040
// notice. Derived from sdk's ErrorCodes so a future rename in core

apps/pythinker-code/src/tui/commands/auth.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import {
1010
OpenAICodexApiError,
1111
OpenPlatformApiError,
1212
runOpenAICodexOAuthFlow,
13-
type ManagedPythinkerCodeModelInfo,
14-
type ManagedPythinkerConfigShape,
13+
type ManagedKimiCodeModelInfo,
14+
type ManagedKimiConfigShape,
1515
type OpenPlatformDefinition,
1616
} from '@pythoughts/pythinker-code-oauth';
1717
import {
@@ -54,7 +54,7 @@ export async function handleLoginCommand(host: SlashCommandHost): Promise<void>
5454
return;
5555
}
5656

57-
if (platformId === 'pythinker-code') {
57+
if (platformId === 'kimi-code') {
5858
await handlePythinkerCodeOAuthLogin(host);
5959
return;
6060
}
@@ -156,7 +156,7 @@ async function handleOpenPlatformLogin(
156156
};
157157
host.cancelInFlight = cancelLogin;
158158

159-
let models: ManagedPythinkerCodeModelInfo[];
159+
let models: ManagedKimiCodeModelInfo[];
160160
try {
161161
models = await fetchOpenPlatformModels(platform, apiKey, fetch, controller.signal);
162162
models = filterModelsByPrefix(models, platform);
@@ -193,7 +193,7 @@ async function handleOpenPlatformLogin(
193193
}
194194

195195
const config = await host.harness.getConfig();
196-
applyOpenPlatformConfig(config as ManagedPythinkerConfigShape, {
196+
applyOpenPlatformConfig(config as ManagedKimiConfigShape, {
197197
platform,
198198
models,
199199
selectedModel: selection.model,
@@ -358,7 +358,7 @@ async function handleOpenAICodexOAuthLogin(host: SlashCommandHost): Promise<void
358358
await host.harness.removeProvider(OPENAI_CODEX_PROVIDER_ID);
359359
}
360360

361-
let models: ManagedPythinkerCodeModelInfo[];
361+
let models: ManagedKimiCodeModelInfo[];
362362
try {
363363
models = await fetchOpenAICodexModels({
364364
accessToken: tokens.accessToken,
@@ -388,7 +388,7 @@ async function handleOpenAICodexOAuthLogin(host: SlashCommandHost): Promise<void
388388
if (selection === undefined) return;
389389

390390
const config = await host.harness.getConfig();
391-
applyOpenAICodexOAuthConfig(config as ManagedPythinkerConfigShape, {
391+
applyOpenAICodexOAuthConfig(config as ManagedKimiConfigShape, {
392392
accessToken: tokens.accessToken,
393393
refreshToken: tokens.refreshToken,
394394
accountId: tokens.accountId,

apps/pythinker-code/src/tui/commands/prompts.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
} from '@pythoughts/pythinker-code-sdk';
1111
import { capabilitiesForModel } from '@pythoughts/pythinker-code-oauth';
1212
import type {
13-
ManagedPythinkerCodeModelInfo,
13+
ManagedKimiCodeModelInfo,
1414
OpenPlatformDefinition,
1515
} from '@pythoughts/pythinker-code-oauth';
1616

@@ -159,9 +159,9 @@ export function promptCatalogProviderSelection(host: SlashCommandHost, catalog:
159159

160160
export async function promptModelSelectionForOpenPlatform(
161161
host: SlashCommandHost,
162-
models: ManagedPythinkerCodeModelInfo[],
162+
models: ManagedKimiCodeModelInfo[],
163163
platform: OpenPlatformDefinition,
164-
): Promise<{ model: ManagedPythinkerCodeModelInfo; effort: string } | undefined> {
164+
): Promise<{ model: ManagedKimiCodeModelInfo; effort: string } | undefined> {
165165
const modelDict: Record<string, ModelAlias> = {};
166166
for (const m of models) {
167167
modelDict[`${platform.id}/${m.id}`] = {

apps/pythinker-code/src/tui/commands/provider.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {
22
applyCustomRegistryEntries,
33
fetchCustomRegistry,
44
type CustomRegistrySource,
5-
type ManagedPythinkerConfigShape,
5+
type ManagedKimiConfigShape,
66
} from '@pythoughts/pythinker-code-oauth';
77
import {
88
CatalogFetchError,
@@ -212,7 +212,7 @@ async function handleCustomRegistryAddViaDialog(host: SlashCommandHost): Promise
212212
try {
213213
const config = await host.harness.getConfig();
214214
applyCustomRegistryEntries(
215-
config as unknown as ManagedPythinkerConfigShape,
215+
config as unknown as ManagedKimiConfigShape,
216216
entries,
217217
source,
218218
);

apps/pythinker-code/src/tui/components/dialogs/model-selector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export function modelDisplayName(alias: string, model: ModelAlias | undefined):
5858
}
5959

6060
export function providerDisplayName(provider: string): string {
61-
if (provider === DEFAULT_OAUTH_PROVIDER_NAME) return 'Pythinker';
61+
if (provider === DEFAULT_OAUTH_PROVIDER_NAME) return 'Kimi';
6262
if (provider.startsWith('managed:')) return provider.slice('managed:'.length);
6363
return provider;
6464
}

apps/pythinker-code/src/tui/components/dialogs/platform-selector.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ function buildPlatformOptions(catalog: Catalog): readonly ChoiceOption[] {
4444
label: OPENAI_CODEX_OAUTH_LOGIN.name,
4545
description: 'OAuth',
4646
},
47-
{ value: 'pythinker-code', label: 'Pythinker (OAuth)', description: 'OAuth' },
47+
{ value: 'kimi-code', label: 'Kimi (OAuth)', description: 'OAuth' },
4848
];
49-
const seen = new Set(['pythinker-code', OPENAI_CODEX_OAUTH_LOGIN.id]);
49+
const seen = new Set(['kimi-code', OPENAI_CODEX_OAUTH_LOGIN.id]);
5050

5151
for (const featured of FEATURED_CATALOG_PROVIDERS) {
5252
const entry = catalog[featured.id];

apps/pythinker-code/src/tui/utils/refresh-providers.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import {
2-
PYTHINKER_CODE_PLATFORM_ID,
3-
PYTHINKER_CODE_PROVIDER_NAME,
2+
KIMI_CODE_PLATFORM_ID,
3+
KIMI_CODE_PROVIDER_NAME,
44
OPENAI_CODEX_PROVIDER_ID,
5-
applyManagedPythinkerCodeConfig,
5+
applyManagedKimiCodeConfig,
66
applyOpenAICodexOAuthConfig,
77
applyOpenPlatformConfig,
88
applyCustomRegistryProvider,
99
fetchCustomRegistry,
10-
fetchManagedPythinkerCodeModels,
10+
fetchManagedKimiCodeModels,
1111
fetchOpenAICodexModels,
1212
fetchOpenPlatformModels,
1313
filterModelsByPrefix,
1414
getOpenPlatformById,
1515
isOpenPlatformId,
1616
removeCustomRegistryProvider,
17-
resolvePythinkerCodeRuntimeAuth,
17+
resolveKimiCodeRuntimeAuth,
1818
type CustomRegistrySource,
19-
type ManagedPythinkerConfigShape,
19+
type ManagedKimiConfigShape,
2020
} from '@pythoughts/pythinker-code-oauth';
2121
import {
2222
applyCatalogProvider,
@@ -116,8 +116,8 @@ async function fetchCustomRegistryFromSources(
116116
throw new Error('No custom registry sources configured.');
117117
}
118118

119-
function asManaged(config: PythinkerConfig): ManagedPythinkerConfigShape {
120-
return config as unknown as ManagedPythinkerConfigShape;
119+
function asManaged(config: PythinkerConfig): ManagedKimiConfigShape {
120+
return config as unknown as ManagedKimiConfigShape;
121121
}
122122

123123
function collectModelIdsForAliases(config: PythinkerConfig, aliasKeys: ReadonlySet<string>): Set<string> {
@@ -341,25 +341,25 @@ export async function refreshAllProviderModels(
341341
// -------------------------------------------------------------------------
342342
// 1. Managed Pythinker Code (OAuth)
343343
// -------------------------------------------------------------------------
344-
const managedProvider = config.providers[PYTHINKER_CODE_PROVIDER_NAME];
344+
const managedProvider = config.providers[KIMI_CODE_PROVIDER_NAME];
345345
if (
346346
managedProvider !== undefined &&
347347
managedProvider.type === 'pythinker' &&
348348
managedProvider.oauth !== undefined
349349
) {
350350
try {
351-
const auth = resolvePythinkerCodeRuntimeAuth({
351+
const auth = resolveKimiCodeRuntimeAuth({
352352
configuredBaseUrl: managedProvider.baseUrl,
353353
configuredOAuthRef: managedProvider.oauth,
354354
});
355-
const accessToken = await host.resolveOAuthToken(PYTHINKER_CODE_PROVIDER_NAME, auth.oauthRef);
356-
const models = await fetchManagedPythinkerCodeModels({
355+
const accessToken = await host.resolveOAuthToken(KIMI_CODE_PROVIDER_NAME, auth.oauthRef);
356+
const models = await fetchManagedKimiCodeModels({
357357
accessToken,
358358
baseUrl: auth.baseUrl,
359359
});
360360
if (models.length > 0) {
361361
const next = structuredClone(config);
362-
applyManagedPythinkerCodeConfig(asManaged(next), {
362+
applyManagedKimiCodeConfig(asManaged(next), {
363363
models,
364364
baseUrl: auth.baseUrl,
365365
oauthKey: auth.oauthRef.key,
@@ -369,33 +369,33 @@ export async function refreshAllProviderModels(
369369
const refreshedAliasKeys = providerRefreshAliasKeys(
370370
config,
371371
next,
372-
PYTHINKER_CODE_PROVIDER_NAME,
373-
`${PYTHINKER_CODE_PLATFORM_ID}/`,
372+
KIMI_CODE_PROVIDER_NAME,
373+
`${KIMI_CODE_PLATFORM_ID}/`,
374374
);
375375
restoreProviderAliases(
376376
next,
377-
preserveUserProviderAliases(config, PYTHINKER_CODE_PROVIDER_NAME, refreshedAliasKeys),
377+
preserveUserProviderAliases(config, KIMI_CODE_PROVIDER_NAME, refreshedAliasKeys),
378378
);
379379
restoreDefaultSelection(next, config.defaultModel, config.defaultThinking);
380380
clampDanglingDefault(next);
381381
clearDefaultThinkingWhenDefaultRemoved(next, config.defaultModel);
382382

383-
if (providerModelsEqual(config, next, PYTHINKER_CODE_PROVIDER_NAME, refreshedAliasKeys)) {
384-
unchanged.push(PYTHINKER_CODE_PROVIDER_NAME);
383+
if (providerModelsEqual(config, next, KIMI_CODE_PROVIDER_NAME, refreshedAliasKeys)) {
384+
unchanged.push(KIMI_CODE_PROVIDER_NAME);
385385
} else {
386386
const { added, removed } = computeChanges(
387387
collectModelIdsForAliases(config, refreshedAliasKeys),
388388
collectModelIdsForAliases(next, refreshedAliasKeys),
389389
);
390-
await host.removeProvider(PYTHINKER_CODE_PROVIDER_NAME);
390+
await host.removeProvider(KIMI_CODE_PROVIDER_NAME);
391391
config = await host.setConfig({
392392
providers: next.providers,
393393
models: next.models,
394394
defaultModel: next.defaultModel,
395395
defaultThinking: next.defaultThinking,
396396
});
397397
changed.push({
398-
providerId: PYTHINKER_CODE_PROVIDER_NAME,
398+
providerId: KIMI_CODE_PROVIDER_NAME,
399399
providerName: PRODUCT_NAME,
400400
added,
401401
removed,
@@ -404,7 +404,7 @@ export async function refreshAllProviderModels(
404404
}
405405
} catch (error) {
406406
failed.push({
407-
provider: PYTHINKER_CODE_PROVIDER_NAME,
407+
provider: KIMI_CODE_PROVIDER_NAME,
408408
reason: error instanceof Error ? error.message : String(error),
409409
});
410410
}
@@ -688,7 +688,7 @@ export async function refreshAllProviderModels(
688688
}
689689
>();
690690
for (const [providerId, providerConfig] of Object.entries(config.providers)) {
691-
if (providerId === PYTHINKER_CODE_PROVIDER_NAME) continue;
691+
if (providerId === KIMI_CODE_PROVIDER_NAME) continue;
692692
if (providerId === OPENAI_CODEX_PROVIDER_ID) continue;
693693
if (isOpenPlatformId(providerId)) continue;
694694
const source = readCustomRegistrySource(providerConfig);

0 commit comments

Comments
 (0)