mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 17:00:59 +00:00
- Hook discovery from ~/.pi/agent/hooks/, .pi/hooks/, --hook flag - Events: session_start, session_switch, agent_start/end, turn_start/end, tool_call, tool_result, branch - tool_call can block execution, tool_result can modify results - pi.send(text, attachments?) to inject messages from external sources - UI primitives: ctx.ui.select/confirm/input/notify - Context: ctx.exec(), ctx.cwd, ctx.sessionFile, ctx.hasUI - Docs shipped with npm package and binary builds - System prompt references docs folder
56 lines
1.5 KiB
TypeScript
56 lines
1.5 KiB
TypeScript
import * as fs from "node:fs";
|
|
import type { HookAPI } from "./packages/coding-agent/src/index.js";
|
|
|
|
export default function (pi: HookAPI) {
|
|
pi.on("session_start", async (_event, ctx) => {
|
|
ctx.ui.notify("Test hook loaded!", "info");
|
|
|
|
// Set up a file watcher to demonstrate pi.send()
|
|
const triggerFile = "/tmp/pi-trigger.txt";
|
|
|
|
// Create empty trigger file if it doesn't exist
|
|
if (!fs.existsSync(triggerFile)) {
|
|
fs.writeFileSync(triggerFile, "");
|
|
}
|
|
|
|
fs.watch(triggerFile, () => {
|
|
try {
|
|
const content = fs.readFileSync(triggerFile, "utf-8").trim();
|
|
if (content) {
|
|
pi.send(`[External trigger]: ${content}`);
|
|
fs.writeFileSync(triggerFile, ""); // Clear after reading
|
|
}
|
|
} catch {
|
|
// File might be in flux
|
|
}
|
|
});
|
|
|
|
ctx.ui.notify("Watching /tmp/pi-trigger.txt for external messages", "info");
|
|
});
|
|
|
|
pi.on("tool_call", async (event, ctx) => {
|
|
console.log(`[test-hook] tool_call: ${event.toolName}`);
|
|
|
|
// Example: block dangerous bash commands
|
|
if (event.toolName === "bash") {
|
|
const cmd = event.input.command as string;
|
|
if (/rm\s+-rf/.test(cmd)) {
|
|
const ok = await ctx.ui.confirm("Dangerous command", `Allow: ${cmd}?`);
|
|
if (!ok) {
|
|
return { block: true, reason: "User blocked rm -rf" };
|
|
}
|
|
}
|
|
}
|
|
|
|
return undefined;
|
|
});
|
|
|
|
pi.on("tool_result", async (event, _ctx) => {
|
|
console.log(`[test-hook] tool_result: ${event.toolName} (${event.result.length} chars)`);
|
|
return undefined;
|
|
});
|
|
|
|
pi.on("turn_end", async (event, _ctx) => {
|
|
console.log(`[test-hook] turn_end: turn ${event.turnIndex}`);
|
|
});
|
|
}
|