Download packages/migration-legacy/test/migration-errors-log.test.ts from SaylorTwift/kimi-code: direct link, hf CLI and curl.
- Browser
- Download file 4.97 kB
-
https://huggingface.co/SaylorTwift/kimi-code/resolve/main/packages/migration-legacy/test/migration-errors-log.test.ts
- Command line
-
hf download hf://SaylorTwift/kimi-code/packages/migration-legacy/test/migration-errors-log.test.ts
-
curl -L -o migration-errors-log.test.ts https://huggingface.co/SaylorTwift/kimi-code/resolve/main/packages/migration-legacy/test/migration-errors-log.test.ts
4.97 kB
| import { describe, expect, it, beforeEach, afterEach } from 'vitest'; | |
| import { mkdtemp, mkdir, writeFile, readFile, rm } from 'node:fs/promises'; | |
| import { tmpdir } from 'node:os'; | |
| import { join } from 'node:path'; | |
| import { writeMigrationErrorsLog } from '../src/migration-errors-log.js'; | |
| import { migrationErrorsLogFile } from '../src/paths.js'; | |
| let tgt: string; | |
| let src: string; | |
| beforeEach(async () => { | |
| tgt = await mkdtemp(join(tmpdir(), 'errlog-tgt-')); | |
| src = await mkdtemp(join(tmpdir(), 'errlog-src-')); | |
| }); | |
| afterEach(async () => { | |
| await rm(tgt, { recursive: true, force: true }); | |
| await rm(src, { recursive: true, force: true }); | |
| }); | |
| describe('writeMigrationErrorsLog', () => { | |
| it('appends a "no failures" marker block on a successful run', async () => { | |
| await writeMigrationErrorsLog(tgt, { | |
| startedAt: '2026-05-19T00:00:00Z', | |
| failures: [], | |
| }); | |
| const log = await readFile(migrationErrorsLogFile(tgt), 'utf-8'); | |
| expect(log).toContain('===== migration run @ 2026-05-19T00:00:00Z ====='); | |
| expect(log).toContain('no failures.'); | |
| }); | |
| it('writes a diagnostic block per failure with a context.jsonl role histogram', async () => { | |
| const sessionDir = join(src, 'ses-1'); | |
| await mkdir(sessionDir, { recursive: true }); | |
| await writeFile( | |
| join(sessionDir, 'context.jsonl'), | |
| '{"role":"_system_prompt","content":"x"}\n{"role":"user","content":"hi"}\n', | |
| ); | |
| await writeMigrationErrorsLog(tgt, { | |
| startedAt: '2026-05-19T00:00:00Z', | |
| failures: [{ sourcePath: sessionDir, reason: 'write failed: ENOSPC' }], | |
| }); | |
| const log = await readFile(migrationErrorsLogFile(tgt), 'utf-8'); | |
| expect(log).toContain('===== migration run @ 2026-05-19T00:00:00Z ====='); | |
| expect(log).toContain('1 session(s) failed to migrate.'); | |
| expect(log).toContain(sessionDir); | |
| expect(log).toContain('write failed: ENOSPC'); | |
| expect(log).toContain('context.jsonl: 2 lines'); | |
| expect(log).toContain('_system_prompt=1'); | |
| expect(log).toContain('user=1'); | |
| }); | |
| it('notes an unreadable context.jsonl rather than throwing', async () => { | |
| const sessionDir = join(src, 'gone'); | |
| await writeMigrationErrorsLog(tgt, { | |
| startedAt: '2026-05-19T00:00:00Z', | |
| failures: [{ sourcePath: sessionDir, reason: 'cannot read context.jsonl' }], | |
| }); | |
| const log = await readFile(migrationErrorsLogFile(tgt), 'utf-8'); | |
| expect(log).toContain('context.jsonl: unreadable'); | |
| }); | |
| it('appends a second block when a later run also has failures', async () => { | |
| // Cross-run history: a user who retries the migration and hits failures | |
| // each time must end up with one log that shows every attempt — the team | |
| // can analyze the full retry sequence from a single file. | |
| const ses1 = join(src, 'ses-1'); | |
| const ses2 = join(src, 'ses-2'); | |
| await mkdir(ses1, { recursive: true }); | |
| await mkdir(ses2, { recursive: true }); | |
| await writeFile(join(ses1, 'context.jsonl'), '{"role":"user","content":"a"}\n'); | |
| await writeFile(join(ses2, 'context.jsonl'), '{"role":"user","content":"b"}\n'); | |
| await writeMigrationErrorsLog(tgt, { | |
| startedAt: '2026-05-19T00:00:00Z', | |
| failures: [{ sourcePath: ses1, reason: 'first-run reason' }], | |
| }); | |
| await writeMigrationErrorsLog(tgt, { | |
| startedAt: '2026-05-20T00:00:00Z', | |
| failures: [{ sourcePath: ses2, reason: 'second-run reason' }], | |
| }); | |
| const log = await readFile(migrationErrorsLogFile(tgt), 'utf-8'); | |
| // Both run headers survive (append-only, no overwrite). | |
| const headerMatches = log.match(/===== migration run @ /g) ?? []; | |
| expect(headerMatches).toHaveLength(2); | |
| expect(log).toContain('2026-05-19T00:00:00Z'); | |
| expect(log).toContain('2026-05-20T00:00:00Z'); | |
| // Both runs' failure data survive. | |
| expect(log).toContain('first-run reason'); | |
| expect(log).toContain('second-run reason'); | |
| expect(log).toContain(ses1); | |
| expect(log).toContain(ses2); | |
| }); | |
| it('appends after an earlier failed run when the later run has no failures', async () => { | |
| // The earlier failure record must NOT be deleted by a successful retry — | |
| // we want the timeline visible even after the user recovers. | |
| const ses1 = join(src, 'ses-1'); | |
| await mkdir(ses1, { recursive: true }); | |
| await writeFile(join(ses1, 'context.jsonl'), '{"role":"user","content":"a"}\n'); | |
| await writeMigrationErrorsLog(tgt, { | |
| startedAt: '2026-05-19T00:00:00Z', | |
| failures: [{ sourcePath: ses1, reason: 'first-run reason' }], | |
| }); | |
| await writeMigrationErrorsLog(tgt, { | |
| startedAt: '2026-05-20T00:00:00Z', | |
| failures: [], | |
| }); | |
| const log = await readFile(migrationErrorsLogFile(tgt), 'utf-8'); | |
| expect(log).toContain('===== migration run @ 2026-05-19T00:00:00Z ====='); | |
| expect(log).toContain('first-run reason'); | |
| expect(log).toContain('===== migration run @ 2026-05-20T00:00:00Z ====='); | |
| expect(log).toContain('no failures.'); | |
| }); | |
| }); | |