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
This commit is contained in:
Mario Zechner 2025-12-10 00:50:30 +01:00
parent 942d8d3c95
commit 7c553acd1e
21 changed files with 1307 additions and 83 deletions

View file

@ -9,28 +9,6 @@
import type { Attachment } from "@mariozechner/pi-agent-core";
import type { AssistantMessage } from "@mariozechner/pi-ai";
import type { AgentSession } from "../core/agent-session.js";
import type { HookUIContext } from "../core/hooks/index.js";
/**
* Create a no-op hook UI context for print mode.
* Hooks can still run but can't prompt the user interactively.
*/
function createNoOpHookUIContext(): HookUIContext {
return {
async select() {
return null;
},
async confirm() {
return false;
},
async input() {
return null;
},
notify() {
// Silent in print mode
},
};
}
/**
* Run in print (single-shot) mode.
@ -49,11 +27,21 @@ export async function runPrintMode(
initialMessage?: string,
initialAttachments?: Attachment[],
): Promise<void> {
// Initialize hooks with no-op UI context (hooks run but can't prompt)
session.setHookUIContext(createNoOpHookUIContext(), (err) => {
console.error(`Hook error (${err.hookPath}): ${err.error}`);
});
await session.initHooks();
// Hook runner already has no-op UI context by default (set in main.ts)
// Set up hooks for print mode (no UI, ephemeral session)
const hookRunner = session.hookRunner;
if (hookRunner) {
hookRunner.setSessionFile(null); // Print mode is ephemeral
hookRunner.onError((err) => {
console.error(`Hook error (${err.hookPath}): ${err.error}`);
});
// No-op send handler for print mode (single-shot, no async messages)
hookRunner.setSendHandler(() => {
console.error("Warning: pi.send() is not supported in print mode");
});
// Emit session_start event
await hookRunner.emit({ type: "session_start" });
}
if (mode === "json") {
// Output all events as JSON