mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-25 08:34:39 +00:00
* feat(migration-legacy): migrate user skills from kimi-cli The first-launch migration previously left ~/.kimi/skills/ behind: the new scanner only reads ~/.kimi-code/skills/ and ~/.agents/skills/, so any custom skills authored against kimi-cli silently disappeared after the upgrade. Adds a skills step that copies top-level entries from ~/.kimi/skills/ into ~/.kimi-code/skills/ with skip-existing semantics, wires it into the existing run-migration pipeline and result screen, and surfaces the count alongside config/mcp/REPL-history. * refactor(migration): hide OAuth from migration UX OAuth credentials are deliberately never migrated (refresh tokens rotate server-side, so two installs sharing one token would fight over who gets refreshed). The previous UX framed this as a limitation: the result screen carried a yellow ⚠ "kimi-cli login not migrated — run /login" line, and the pre-migration summary listed "kimi-cli login (needs /login)" alongside real migratable data classes, making users think a login was about to be transferred and only the last step had failed. Drops both surfaces and short-circuits the pre-migration screen when the only legacy data is `credentials/*.json`. kimi-code's own /login flow handles re-auth on first use, so a dedicated migration notice is redundant. The `report.notices.oauthLoginsRequiringRelogin` JSON field is left intact for debugging. * chore: changeset for skills migration and OAuth UX cleanup
69 lines
2.3 KiB
TypeScript
69 lines
2.3 KiB
TypeScript
import { describe, expect, it, beforeEach, afterEach } from 'vitest';
|
|
import { mkdtemp, readFile, rm } from 'node:fs/promises';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import { writeReport } from '../src/report.js';
|
|
import type { MigrationReport } from '../src/types.js';
|
|
|
|
let tgt: string;
|
|
beforeEach(async () => {
|
|
tgt = await mkdtemp(join(tmpdir(), 'rpt-'));
|
|
});
|
|
afterEach(async () => {
|
|
await rm(tgt, { recursive: true, force: true });
|
|
});
|
|
|
|
describe('writeReport', () => {
|
|
it('serializes the report at <target>/migration-report.json', async () => {
|
|
const report: MigrationReport = {
|
|
startedAt: 's',
|
|
completedAt: 'e',
|
|
migratorVersion: '0.1.1',
|
|
source: '/x',
|
|
target: tgt,
|
|
summary: {
|
|
config: {
|
|
migrated: false,
|
|
tuiExtracted: false,
|
|
droppedProviders: [],
|
|
droppedModels: [],
|
|
droppedKeys: [],
|
|
configConflicts: [],
|
|
wroteSiblingDueToConflict: false,
|
|
wroteTuiSibling: false,
|
|
migratedHooks: 0,
|
|
droppedHooks: 0,
|
|
siblingContents: { providers: [], models: [], hooks: 0 },
|
|
},
|
|
mcp: { mergedServers: [], keptNewForConflicts: [], droppedServers: [], wroteSiblingDueToConflict: false },
|
|
userHistory: { copied: 0, skippedExisting: 0 },
|
|
skills: { copied: 0, skippedExisting: 0 },
|
|
sessions: {
|
|
scope: 'all',
|
|
bucketsScanned: 0,
|
|
bucketsSkippedNonlocalKaos: 0,
|
|
bucketsSkippedNoWorkdirFound: 0,
|
|
sessionsAttempted: 0,
|
|
sessionsMigrated: 0,
|
|
sessionsAlreadyMigrated: 0,
|
|
sessionsSkippedPlaceholder: 0,
|
|
sessionsSkippedEmpty: 0,
|
|
sessionsSkippedMalformed: 0,
|
|
sessionsFailed: [],
|
|
sessionsConflicts: [],
|
|
},
|
|
},
|
|
notices: {
|
|
mcpOauthServersRequiringReauth: [],
|
|
oauthLoginsRequiringRelogin: [],
|
|
detectedPlugins: [],
|
|
configConflictNotice: null,
|
|
tuiConflictNotice: null,
|
|
},
|
|
};
|
|
await writeReport(tgt, report);
|
|
const text = await readFile(join(tgt, 'migration-report.json'), 'utf-8');
|
|
const parsed: unknown = JSON.parse(text);
|
|
expect((parsed as { migratorVersion: string }).migratorVersion).toBe('0.1.1');
|
|
});
|
|
});
|