mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-25 16:46:17 +00:00
fix(tui): preserve active session after provider logout (#3212)
This commit is contained in:
parent
d3b27cc778
commit
a664226bf2
5 changed files with 91 additions and 29 deletions
5
.changeset/calm-session-logout.md
Normal file
5
.changeset/calm-session-logout.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@moonshot-ai/kimi-code": patch
|
||||
---
|
||||
|
||||
Preserve the active session and its selected model when logging out of a provider.
|
||||
|
|
@ -241,7 +241,6 @@ export async function handleLogoutCommand(host: SlashCommandHost): Promise<void>
|
|||
|
||||
if (target === currentProvider) {
|
||||
await host.authFlow.refreshConfigAfterLogout();
|
||||
await host.authFlow.clearActiveSessionAfterLogout();
|
||||
} else {
|
||||
const updated = await host.harness.getConfig({ reload: true });
|
||||
host.setAppState({
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@ async function handleProviderDelete(host: SlashCommandHost, providerId: string):
|
|||
// to the marker/default profile, not the logged-out region.
|
||||
refreshKimiRegion();
|
||||
await host.authFlow.refreshConfigAfterLogout();
|
||||
await host.authFlow.clearActiveSessionAfterLogout();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +103,6 @@ async function handleProviderDelete(host: SlashCommandHost, providerId: string):
|
|||
const config = await host.harness.removeProvider(providerId);
|
||||
if (activeProvider === providerId) {
|
||||
await host.authFlow.refreshConfigAfterLogout();
|
||||
await host.authFlow.clearActiveSessionAfterLogout();
|
||||
} else {
|
||||
host.setAppState({
|
||||
availableProviders: config.providers ?? {},
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ export interface AuthFlowHost {
|
|||
resetSessionRuntime(): void;
|
||||
setSession(session: Session): Promise<void>;
|
||||
syncRuntimeState(session?: Session): Promise<void>;
|
||||
closeSession(reason: string): Promise<void>;
|
||||
appendStartupNotice(extra: string): void;
|
||||
hydrateLazyConfigDefaults(): Promise<void>;
|
||||
readonly sessionEventHandler: SessionEventHandler;
|
||||
|
|
@ -134,18 +133,6 @@ export class AuthFlowController {
|
|||
void host.refreshPluginCommands(host.session);
|
||||
}
|
||||
|
||||
async clearActiveSessionAfterLogout(): Promise<void> {
|
||||
await this.host.closeSession('logged out');
|
||||
this.host.resetSessionRuntime();
|
||||
this.host.setAppState({
|
||||
sessionId: '',
|
||||
model: '',
|
||||
sessionTitle: null,
|
||||
});
|
||||
await this.host.refreshSkillCommands();
|
||||
await this.host.refreshPluginCommands();
|
||||
}
|
||||
|
||||
async refreshConfigAfterLogin(): Promise<void> {
|
||||
const { host } = this;
|
||||
const config = await host.harness.getConfig({ reload: true });
|
||||
|
|
@ -183,9 +170,17 @@ export class AuthFlowController {
|
|||
|
||||
async refreshConfigAfterLogout(): Promise<void> {
|
||||
const config = await this.host.harness.getConfig({ reload: true });
|
||||
const availableModels = config.models ?? {};
|
||||
const availableProviders = config.providers ?? {};
|
||||
|
||||
if (this.host.session !== undefined) {
|
||||
this.host.setAppState({ availableModels, availableProviders });
|
||||
return;
|
||||
}
|
||||
|
||||
this.host.setAppState({
|
||||
availableModels: config.models ?? {},
|
||||
availableProviders: config.providers ?? {},
|
||||
availableModels,
|
||||
availableProviders,
|
||||
model: '',
|
||||
thinkingEffort: 'off',
|
||||
maxContextTokens: 0,
|
||||
|
|
|
|||
|
|
@ -1904,21 +1904,33 @@ describe('KimiTUI startup', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('tracks logout after managed credentials and session state are cleared', async () => {
|
||||
it('tracks logout while preserving the active session model', async () => {
|
||||
let loggedOut = false;
|
||||
const session = makeSession();
|
||||
const logout = vi.fn(async () => {
|
||||
loggedOut = true;
|
||||
});
|
||||
const harness = makeHarness(session, {
|
||||
getConfig: vi.fn(async () => ({
|
||||
models: {
|
||||
k2: { provider: 'managed:kimi-code', model: 'moonshot-v1', maxContextSize: 100 },
|
||||
},
|
||||
providers: { 'managed:kimi-code': { type: 'kimi' } },
|
||||
})),
|
||||
getConfig: vi.fn(async () =>
|
||||
loggedOut
|
||||
? { models: {}, providers: {} }
|
||||
: {
|
||||
models: {
|
||||
k2: {
|
||||
provider: 'managed:kimi-code',
|
||||
model: 'moonshot-v1',
|
||||
maxContextSize: 100,
|
||||
},
|
||||
},
|
||||
providers: { 'managed:kimi-code': { type: 'kimi' } },
|
||||
},
|
||||
),
|
||||
auth: {
|
||||
status: vi.fn(async () => ({
|
||||
providers: [{ providerName: 'managed:kimi-code', hasToken: true }],
|
||||
})),
|
||||
login: vi.fn(async () => {}),
|
||||
logout: vi.fn(),
|
||||
logout,
|
||||
getManagedUsage: vi.fn(),
|
||||
},
|
||||
});
|
||||
|
|
@ -1931,13 +1943,66 @@ describe('KimiTUI startup', () => {
|
|||
await handleLogoutCommand(driver as any);
|
||||
|
||||
expect(harness.auth.logout).toHaveBeenCalledWith('managed:kimi-code');
|
||||
expect(session.close).toHaveBeenCalledOnce();
|
||||
expect(session.close).not.toHaveBeenCalled();
|
||||
expect(driver.state.appState).toMatchObject({
|
||||
sessionId: 'ses-1',
|
||||
model: 'k2',
|
||||
sessionTitle: 'Session title',
|
||||
contextTokens: 10,
|
||||
maxContextTokens: 100,
|
||||
availableModels: {},
|
||||
availableProviders: {},
|
||||
});
|
||||
expect(harness.track).toHaveBeenCalledWith('logout', { provider: 'managed:kimi-code' });
|
||||
});
|
||||
|
||||
it('clears the config-derived model when logging out without an active session', async () => {
|
||||
let loggedOut = false;
|
||||
const logout = vi.fn(async () => {
|
||||
loggedOut = true;
|
||||
});
|
||||
const harness = makeHarness(makeSession(), {
|
||||
getConfig: vi.fn(async () =>
|
||||
loggedOut
|
||||
? { models: {}, providers: {} }
|
||||
: {
|
||||
models: {
|
||||
k2: {
|
||||
provider: 'managed:kimi-code',
|
||||
model: 'moonshot-v1',
|
||||
maxContextSize: 100,
|
||||
},
|
||||
},
|
||||
providers: { 'managed:kimi-code': { type: 'kimi' } },
|
||||
defaultModel: 'k2',
|
||||
},
|
||||
),
|
||||
auth: {
|
||||
status: vi.fn(async () => ({
|
||||
providers: [{ providerName: 'managed:kimi-code', hasToken: true }],
|
||||
})),
|
||||
login: vi.fn(async () => {}),
|
||||
logout,
|
||||
getManagedUsage: vi.fn(),
|
||||
},
|
||||
});
|
||||
const driver = makeDriver(harness, { ...makeStartupInput(), engineV2: true });
|
||||
|
||||
await expect(driver.init()).resolves.toBe(false);
|
||||
expect(driver.state.appState.model).toBe('k2');
|
||||
|
||||
vi.mocked(promptLogoutProviderSelection).mockResolvedValue('managed:kimi-code');
|
||||
await handleLogoutCommand(driver as any);
|
||||
|
||||
expect(harness.createSession).not.toHaveBeenCalled();
|
||||
expect(driver.state.appState).toMatchObject({
|
||||
sessionId: '',
|
||||
model: '',
|
||||
sessionTitle: null,
|
||||
contextTokens: 0,
|
||||
maxContextTokens: 0,
|
||||
availableModels: {},
|
||||
availableProviders: {},
|
||||
});
|
||||
expect(harness.track).toHaveBeenCalledWith('logout', { provider: 'managed:kimi-code' });
|
||||
});
|
||||
|
||||
it('keeps the active session when logging out a different provider', async () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue