mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 20:03:05 +00:00
Major changes: - Replace monolithic SessionEvent with reason discriminator with individual event types: session_start, session_before_switch, session_switch, session_before_new, session_new, session_before_branch, session_branch, session_before_compact, session_compact, session_shutdown - Each event has dedicated result type (SessionBeforeSwitchResult, etc.) - HookHandler type now allows bare return statements (void in return type) - HookAPI.on() has proper overloads for each event with correct typing Additional fixes: - AgentSession now always subscribes to agent in constructor (was only subscribing when external subscribe() called, breaking internal handlers) - Standardize on undefined over null throughout codebase - HookUIContext methods return undefined instead of null - SessionManager methods return undefined instead of null - Simplify hook exports to 'export type * from types.js' - Add detailed JSDoc for skipConversationRestore vs cancel - Fix createBranchedSession to rebuild index in persist mode - newSession() now returns the session file path Updated all example hooks, tests, and emission sites to use new event types.
46 lines
1.2 KiB
TypeScript
46 lines
1.2 KiB
TypeScript
/**
|
|
* Git Checkpoint Hook
|
|
*
|
|
* Creates git stash checkpoints at each turn so /branch can restore code state.
|
|
* When branching, offers to restore code to that point in history.
|
|
*/
|
|
|
|
import type { HookAPI } from "@mariozechner/pi-coding-agent/hooks";
|
|
|
|
export default function (pi: HookAPI) {
|
|
const checkpoints = new Map<number, string>();
|
|
|
|
pi.on("turn_start", async (event) => {
|
|
// Create a git stash entry before LLM makes changes
|
|
const { stdout } = await pi.exec("git", ["stash", "create"]);
|
|
const ref = stdout.trim();
|
|
if (ref) {
|
|
checkpoints.set(event.turnIndex, ref);
|
|
}
|
|
});
|
|
|
|
pi.on("session_before_branch", async (event, ctx) => {
|
|
const ref = checkpoints.get(event.entryIndex);
|
|
if (!ref) return;
|
|
|
|
if (!ctx.hasUI) {
|
|
// In non-interactive mode, don't restore automatically
|
|
return;
|
|
}
|
|
|
|
const choice = await ctx.ui.select("Restore code state?", [
|
|
"Yes, restore code to that point",
|
|
"No, keep current code",
|
|
]);
|
|
|
|
if (choice?.startsWith("Yes")) {
|
|
await pi.exec("git", ["stash", "apply", ref]);
|
|
ctx.ui.notify("Code restored to checkpoint", "info");
|
|
}
|
|
});
|
|
|
|
pi.on("agent_end", async () => {
|
|
// Clear checkpoints after agent completes
|
|
checkpoints.clear();
|
|
});
|
|
}
|