pi-mono/packages/coding-agent/test/keybindings-migration.test.ts
Mario Zechner 9f9277ccdd refactor(coding-agent): replace AgentSessionRuntimeHost with closure-based AgentSessionRuntime
- Replace AgentSessionRuntimeHost and bootstrap abstractions with AgentSessionRuntime
- Runtime creation is now closure-based via CreateAgentSessionRuntimeFactory
- Factory closes over process-global fixed inputs, recreates cwd-bound services per effective cwd
- Session config (model, thinking, tools, scoped models) re-resolved per target cwd
- CLI resource paths resolved once at startup as absolute paths
- Swap lifecycle: teardown old, create next, apply next (hard fail on creation error)
- Unified diagnostics model (info/warning/error) for args, services, session resolution, resources
- No logging or process exits inside creation/parsing logic
- Removed session_directory support
- Removed session_switch and session_fork extension events (use session_start with reason)
- Moved package/config CLI to package-manager-cli.ts
- Fixed theme init for --resume session picker
- Fixed flaky reftable footer test (content-based polling)
- Fixed silent drop of unknown single-dash CLI flags
- Added error diagnostics for missing explicit CLI resource paths
- Updated SDK docs, examples, plans, exports, tests, changelog

fixes #2753
2026-04-03 20:14:12 +02:00

88 lines
2.6 KiB
TypeScript

import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { ENV_AGENT_DIR } from "../src/config.js";
import { KeybindingsManager } from "../src/core/keybindings.js";
import { runMigrations } from "../src/migrations.js";
describe("keybindings migration", () => {
const tempDirs: string[] = [];
afterEach(() => {
for (const dir of tempDirs.splice(0)) {
fs.rmSync(dir, { recursive: true, force: true });
}
});
function createAgentDir(config: Record<string, unknown>): string {
const agentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-keybindings-test-"));
tempDirs.push(agentDir);
fs.writeFileSync(path.join(agentDir, "keybindings.json"), `${JSON.stringify(config, null, 2)}\n`, "utf-8");
return agentDir;
}
it("rewrites old key names to namespaced ids", () => {
const agentDir = createAgentDir({
cursorUp: ["up", "ctrl+p"],
expandTools: "ctrl+x",
});
const previousAgentDir = process.env[ENV_AGENT_DIR];
process.env[ENV_AGENT_DIR] = agentDir;
runMigrations(agentDir);
if (previousAgentDir === undefined) {
delete process.env[ENV_AGENT_DIR];
} else {
process.env[ENV_AGENT_DIR] = previousAgentDir;
}
const migrated = JSON.parse(fs.readFileSync(path.join(agentDir, "keybindings.json"), "utf-8")) as Record<
string,
unknown
>;
expect(migrated).toEqual({
"tui.editor.cursorUp": ["up", "ctrl+p"],
"app.tools.expand": "ctrl+x",
});
});
it("keeps the namespaced value when old and new names both exist", () => {
const agentDir = createAgentDir({
expandTools: "ctrl+x",
"app.tools.expand": "ctrl+y",
});
const previousAgentDir = process.env[ENV_AGENT_DIR];
process.env[ENV_AGENT_DIR] = agentDir;
runMigrations(agentDir);
if (previousAgentDir === undefined) {
delete process.env[ENV_AGENT_DIR];
} else {
process.env[ENV_AGENT_DIR] = previousAgentDir;
}
const migrated = JSON.parse(fs.readFileSync(path.join(agentDir, "keybindings.json"), "utf-8")) as Record<
string,
unknown
>;
expect(migrated).toEqual({
"app.tools.expand": "ctrl+y",
});
});
it("loads old key names in memory before the file is rewritten", () => {
const agentDir = createAgentDir({
selectConfirm: "enter",
interrupt: "ctrl+x",
});
const keybindings = KeybindingsManager.create(agentDir);
expect(keybindings.getUserBindings()).toEqual({
"tui.select.confirm": "enter",
"app.interrupt": "ctrl+x",
});
const effective = keybindings.getEffectiveConfig();
expect(effective["tui.select.confirm"]).toBe("enter");
expect(effective["app.interrupt"]).toBe("ctrl+x");
});
});