co-mono/img-hook.ts
Mario Zechner 7c553acd1e Add hooks system with pi.send() for external message injection
- 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
2025-12-10 00:50:30 +01:00

38 lines
1.1 KiB
TypeScript

import * as fs from "node:fs";
import * as path from "node:path";
import * as os from "node:os";
import * as crypto from "node:crypto";
import type { HookAPI } from "./packages/coding-agent/src/index.js";
export default function (pi: HookAPI) {
pi.on("session_start", async (_event, ctx) => {
const desktop = path.join(os.homedir(), "Desktop");
const seen = new Set(fs.readdirSync(desktop).filter((f) => f.endsWith(".png")));
ctx.ui.notify(`Watching ${desktop} for new .png files`, "info");
fs.watch(desktop, (event, file) => {
if (!file?.endsWith(".png") || event !== "rename" || seen.has(file)) return;
setTimeout(() => {
const filePath = path.join(desktop, file);
if (!fs.existsSync(filePath)) return;
seen.add(file);
const content = fs.readFileSync(filePath);
const stats = fs.statSync(filePath);
pi.send(`Use \`say\` to describe the image. Make it concise and hilarious`, [
{
id: crypto.randomUUID(),
type: "image",
fileName: file,
mimeType: "image/png",
size: stats.size,
content: content.toString("base64"),
},
]);
}, 500);
});
});
}