fix(coding-agent): wire extension editor component replacement

This commit is contained in:
conway
2026-05-01 16:51:51 -07:00
committed by Cherub Kumar
parent 225fee1fd3
commit fd946a649e
4 changed files with 151 additions and 4 deletions
@@ -0,0 +1,89 @@
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "bun:test";
import * as path from "node:path";
import { Agent } from "@oh-my-pi/pi-agent-core";
import { _resetSettingsForTest, Settings } from "@oh-my-pi/pi-coding-agent/config/settings";
import { initTheme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
import { Editor } from "@oh-my-pi/pi-tui";
import { TempDir } from "@oh-my-pi/pi-utils";
import { ModelRegistry } from "../src/config/model-registry";
import { CustomEditor } from "../src/modes/components/custom-editor";
import { InteractiveMode } from "../src/modes/interactive-mode";
import { AgentSession } from "../src/session/agent-session";
import { AuthStorage } from "../src/session/auth-storage";
import { SessionManager } from "../src/session/session-manager";
class TestModalEditor extends CustomEditor {}
describe("InteractiveMode.setEditorComponent", () => {
let tempDir: TempDir;
let authStorage: AuthStorage;
let session: AgentSession;
let mode: InteractiveMode;
beforeAll(() => {
initTheme();
});
beforeEach(async () => {
_resetSettingsForTest();
tempDir = TempDir.createSync("@pi-editor-component-");
await Settings.init({ inMemory: true, cwd: tempDir.path() });
authStorage = await AuthStorage.create(path.join(tempDir.path(), "testauth.db"));
const modelRegistry = new ModelRegistry(authStorage);
const model = modelRegistry.find("anthropic", "claude-sonnet-4-5");
if (!model) {
throw new Error("Expected claude-sonnet-4-5 to exist in registry");
}
session = new AgentSession({
agent: new Agent({
initialState: {
model,
systemPrompt: "Test",
tools: [],
messages: [],
},
}),
sessionManager: SessionManager.create(tempDir.path(), tempDir.path()),
settings: Settings.isolated(),
modelRegistry,
});
mode = new InteractiveMode(session, "test");
});
afterEach(async () => {
vi.restoreAllMocks();
mode?.stop();
await session?.dispose();
authStorage?.close();
tempDir?.removeSync();
_resetSettingsForTest();
});
it("replaces the editor and rebinds interactive handlers", () => {
mode.editor.setText("draft prompt");
const previousEditor = mode.editor;
const refreshSpy = vi.spyOn(mode, "refreshSlashCommandState").mockResolvedValue();
mode.setEditorComponent((_tui, editorTheme) => new TestModalEditor(editorTheme));
expect(mode.editor).toBeInstanceOf(TestModalEditor);
expect(mode.editor).not.toBe(previousEditor);
expect(mode.editor.getText()).toBe("draft prompt");
expect(mode.editor.onSubmit).toBeDefined();
expect(mode.editor.onEscape).toBeDefined();
expect(refreshSpy).toHaveBeenCalled();
});
it("keeps the current editor when factory returns a non-CustomEditor", () => {
const previousEditor = mode.editor;
const warningSpy = vi.spyOn(mode, "showWarning");
mode.setEditorComponent((_tui, editorTheme) => new Editor(editorTheme));
expect(mode.editor).toBe(previousEditor);
expect(warningSpy).toHaveBeenCalledWith(
"Custom editor components must implement CustomEditor-compatible interactive methods.",
);
});
});