Skip to content

Commit 9c797b7

Browse files
refactor(session): replace MigrationEngine and isolate migrate command (#1195)
* refactor(session): simplify migration preview Refs #1140 * refactor(session): split migration command Keep session command modules below the production file-size limit without changing CLI behavior.
1 parent fe3b906 commit 9c797b7

6 files changed

Lines changed: 949 additions & 889 deletions

File tree

‎src/__tests__/migrate-guard.test.ts‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { describe, expect, it, beforeAll, afterAll } from 'vitest';
1111
import os from 'node:os';
1212
import type { AgentAdapter, SessionMeta } from '../session-flow/adapters/base.js';
1313
import { ADAPTER_REGISTRY, type AdapterFactory } from '../session-flow/adapters/index.js';
14-
import { fidelityFromSession } from '../session-flow/migrate.js';
14+
import { fidelityFromSession, previewMigration } from '../session-flow/migrate.js';
1515
import { AgentSession } from '../session-flow/agent-session.js';
1616
import type { Session } from '../session-flow/ir.js';
1717

@@ -217,3 +217,21 @@ describe('fidelityFromSession — 真实统计', () => {
217217
});
218218
});
219219
});
220+
221+
describe('previewMigration', () => {
222+
it('returns the source, target, session metadata, and computed fidelity', () => {
223+
const session = makeSession();
224+
const sourcePlatform = session.platform;
225+
const targetPlatform = 'cursor';
226+
227+
expect(previewMigration(session, sourcePlatform, targetPlatform)).toEqual({
228+
sourcePlatform,
229+
targetPlatform,
230+
sessionId: session.sessionId,
231+
sessionTitle: session.title,
232+
cwd: session.cwd,
233+
messageCount: session.messages.length,
234+
fidelity: fidelityFromSession(session, targetPlatform),
235+
});
236+
});
237+
});

‎src/__tests__/session-cmd.test.ts‎

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const mocks = vi.hoisted(() => ({
3232
adaptersByPlatform: {} as Record<string, unknown>,
3333
/** migrate.js mock 的 preview 返回值(Error 时抛出);agent-session.js mock 的 copy 返回值 */
3434
previewResult: null as unknown,
35+
previewCalls: [] as Array<{ session: unknown; source: string; target: string }>,
3536
copyResult: null as unknown,
3637
/** The OS the commands' `noAdapter` checks judge by; this machine's when unset. */
3738
os: undefined as NodeJS.Platform | undefined,
@@ -119,14 +120,9 @@ vi.mock('../session-flow/adapters/index.js', () => ({
119120
}));
120121

121122
vi.mock('../session-flow/migrate.js', () => ({
122-
MigrationEngine: class {
123-
constructor(
124-
public readonly source: string,
125-
public readonly target: string,
126-
) {}
127-
preview(): unknown {
128-
return mocks.previewResult;
129-
}
123+
previewMigration: (session: unknown, source: string, target: string): unknown => {
124+
mocks.previewCalls.push({ session, source, target });
125+
return mocks.previewResult;
130126
},
131127
resolveTargetCwd: (explicit: string | undefined, sourceCwd: string | undefined) => explicit ?? sourceCwd,
132128
}));
@@ -186,6 +182,7 @@ beforeEach(() => {
186182
mocks.gitCalls.length = 0;
187183
mocks.adaptersByPlatform = {};
188184
mocks.previewResult = null;
185+
mocks.previewCalls.length = 0;
189186
mocks.copyResult = null;
190187
mocks.os = undefined;
191188
mocks.heldArchiveLock = '';
@@ -714,16 +711,13 @@ describe('session migrate interactive picker', () => {
714711
filePath: '/tmp/tgt.jsonl',
715712
fidelity: { score: 1 },
716713
};
717-
const { MigrationEngine } = await import('../session-flow/migrate.js');
718-
const previewSpy = vi.spyOn(MigrationEngine.prototype, 'preview');
719-
720714
feedAnswers(['n', '11']);
721715
await runSession('migrate', '-s', 'fakeplat', '-t', 'tgtplat', '--cwd', '/run/dir');
722716

723717
// The picker is on page 2 by the time the number is entered, and the
724718
// selected id is the 11th newest -- unreachable before paging existed.
725719
expect(out.join('\n')).toContain('page 2/2');
726-
expect(previewSpy).toHaveBeenCalledWith(sessions[1]);
720+
expect(mocks.previewCalls).toContainEqual({ session: sessions[1], source: 'fakeplat', target: 'tgtplat' });
727721
});
728722

729723
it('cancels on an empty answer instead of paging forever', async () => {

‎src/session-flow/migrate.ts‎

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -258,30 +258,21 @@ export function resolveTargetCwd(
258258
return fallback;
259259
}
260260

261-
// ---------------------------------------------------------------------------
262-
// MigrationEngine
263-
// ---------------------------------------------------------------------------
264-
265-
export class MigrationEngine {
266-
constructor(
267-
private sourcePlatform: string,
268-
private targetPlatform: string,
269-
) {}
270-
271-
/** What migrating `session`, read from the source platform, would carry over. */
272-
preview(session: Session): MigrationPreview {
273-
const fidelity = fidelityFromSession(session, this.targetPlatform);
274-
275-
return {
276-
sourcePlatform: this.sourcePlatform,
277-
targetPlatform: this.targetPlatform,
278-
sessionId: session.sessionId,
279-
sessionTitle: session.title,
280-
cwd: session.cwd,
281-
messageCount: session.messages.length,
282-
fidelity,
283-
};
284-
}
261+
/** What migrating `session`, read from `sourcePlatform`, would carry over. */
262+
export function previewMigration(
263+
session: Session,
264+
sourcePlatform: string,
265+
targetPlatform: string,
266+
): MigrationPreview {
267+
return {
268+
sourcePlatform,
269+
targetPlatform,
270+
sessionId: session.sessionId,
271+
sessionTitle: session.title,
272+
cwd: session.cwd,
273+
messageCount: session.messages.length,
274+
fidelity: fidelityFromSession(session, targetPlatform),
275+
};
285276
}
286277

287278
export { getAdapter, listAvailablePlatforms, listInstalledPlatforms };

0 commit comments

Comments
 (0)