edit session
This commit is contained in:
@@ -7,8 +7,22 @@
|
||||
|
||||
import type { ExtensionAPI, SessionBeforeSwitchEvent, SessionMessageEntry } from "@mariozechner/pi-coding-agent";
|
||||
|
||||
// Flag to track if we're in the middle of an edit-session reload
|
||||
let skipNextSwitchConfirm = false;
|
||||
|
||||
export default function (pi: ExtensionAPI) {
|
||||
// Listen for edit-session reload signal
|
||||
pi.events.on("edit-session:reload", () => {
|
||||
skipNextSwitchConfirm = true;
|
||||
});
|
||||
|
||||
pi.on("session_before_switch", async (event: SessionBeforeSwitchEvent, ctx) => {
|
||||
// Skip confirmation if this is an edit-session reload
|
||||
if (skipNextSwitchConfirm) {
|
||||
skipNextSwitchConfirm = false; // Reset the flag
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.reason === "new") {
|
||||
// Emit event for sound extensions (before hasUI check)
|
||||
pi.events.emit("peon:input_required", { source: "confirm-destructive", action: "clear-session" });
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Edit Session Extension
|
||||
*
|
||||
* Adds /edit-session command to open the current session JSONL in your default editor.
|
||||
*
|
||||
* Usage:
|
||||
* /edit-session - Open current session file in $EDITOR
|
||||
*
|
||||
* The editor is determined by $VISUAL, then $EDITOR, then falls back to 'vi'.
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI, ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
|
||||
import type { TUI, Theme, KeybindingsManager, Component } from "@mariozechner/pi-tui";
|
||||
import { spawnSync } from "node:child_process";
|
||||
|
||||
export default function editSessionExtension(pi: ExtensionAPI) {
|
||||
|
||||
pi.registerCommand("edit-session", {
|
||||
description: "Open session JSONL in default editor ($VISUAL/$EDITOR/vi)",
|
||||
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
||||
const sessionFile = ctx.sessionManager.getSessionFile();
|
||||
|
||||
if (!sessionFile) {
|
||||
ctx.ui.notify("No session file (ephemeral mode)", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const editorCmd = process.env.VISUAL || process.env.EDITOR;
|
||||
if (!editorCmd) {
|
||||
ctx.ui.notify("No editor configured. Set $VISUAL or $EDITOR.", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
// Factory function to create component and run editor
|
||||
const factory = (
|
||||
tui: TUI,
|
||||
_theme: Theme,
|
||||
_kb: KeybindingsManager,
|
||||
done: (result: void) => void
|
||||
): Component => {
|
||||
// Stop TUI to release terminal (same as Ctrl+G)
|
||||
tui.stop();
|
||||
|
||||
// Split editor command to support args (e.g., "code --wait")
|
||||
const [editor, ...editorArgs] = editorCmd.split(" ");
|
||||
|
||||
// Spawn editor synchronously with inherited stdio
|
||||
const result = spawnSync(editor, [...editorArgs, sessionFile], {
|
||||
stdio: "inherit",
|
||||
shell: process.platform === "win32",
|
||||
});
|
||||
|
||||
// Restart TUI
|
||||
tui.start();
|
||||
// Force full re-render since external editor uses alternate screen
|
||||
tui.requestRender(true);
|
||||
|
||||
if (result.status !== 0 && result.status !== null) {
|
||||
ctx.ui.notify(`Editor exited with code ${result.status}`, "warning");
|
||||
}
|
||||
|
||||
done();
|
||||
|
||||
// Return dummy component
|
||||
return createDummyComponent();
|
||||
};
|
||||
|
||||
// Use ctx.ui.custom to get access to the TUI
|
||||
await ctx.ui.custom<void>(factory);
|
||||
|
||||
// Signal that we're about to reload the session (so confirm-destructive skips)
|
||||
pi.events.emit("edit-session:reload");
|
||||
|
||||
// Reload the session by switching to the same file (forces re-read from disk)
|
||||
ctx.ui.notify("Reloading session...", "info");
|
||||
const result = await ctx.switchSession(sessionFile);
|
||||
|
||||
if (result.cancelled) {
|
||||
// If still cancelled (by another extension), just notify without warning
|
||||
ctx.ui.notify("Session reload skipped. Run /reload to apply changes.", "info");
|
||||
} else {
|
||||
ctx.ui.notify("Session reloaded with changes.", "info");
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function createDummyComponent(): Component {
|
||||
return {
|
||||
render: (_width: number): string[] => [],
|
||||
invalidate: (): void => {},
|
||||
};
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"lastChangelogVersion": "0.57.1",
|
||||
"defaultProvider": "opencode-go",
|
||||
"defaultModel": "kimi-k2.5",
|
||||
"defaultThinkingLevel": "low",
|
||||
"defaultThinkingLevel": "off",
|
||||
"theme": "matugen",
|
||||
"lsp": {
|
||||
"hookMode": "edit_write"
|
||||
|
||||
Reference in New Issue
Block a user