Custom tools with session lifecycle, examples for hooks and tools

- Custom tools: TypeScript modules that extend pi with new tools
  - Custom TUI rendering via renderCall/renderResult
  - User interaction via pi.ui (select, confirm, input, notify)
  - Session lifecycle via onSession callback for state reconstruction
  - Examples: todo.ts, question.ts, hello.ts

- Hook examples: permission-gate, git-checkpoint, protected-paths

- Session lifecycle centralized in AgentSession
  - Works across all modes (interactive, print, RPC)
  - Unified session event for hooks (replaces session_start/session_switch)

- Box component added to pi-tui

- Examples bundled in npm and binary releases

Fixes #190
This commit is contained in:
Mario Zechner 2025-12-17 16:03:23 +01:00
parent 295f51b53f
commit e7097d911a
33 changed files with 1926 additions and 117 deletions

View file

@ -27,6 +27,9 @@ export async function runPrintMode(
initialMessage?: string,
initialAttachments?: Attachment[],
): Promise<void> {
// Load entries once for session start events
const entries = session.sessionManager.loadEntries();
// Hook runner already has no-op UI context by default (set in main.ts)
// Set up hooks for print mode (no UI)
const hookRunner = session.hookRunner;
@ -40,8 +43,30 @@ export async function runPrintMode(
hookRunner.setSendHandler(() => {
console.error("Warning: pi.send() is not supported in print mode");
});
// Emit session_start event
await hookRunner.emit({ type: "session_start" });
// Emit session event
await hookRunner.emit({
type: "session",
entries,
sessionFile: session.sessionFile,
previousSessionFile: null,
reason: "start",
});
}
// Emit session start event to custom tools (no UI in print mode)
for (const { tool } of session.customTools) {
if (tool.onSession) {
try {
await tool.onSession({
entries,
sessionFile: session.sessionFile,
previousSessionFile: null,
reason: "start",
});
} catch (_err) {
// Silently ignore tool errors
}
}
}
// Always subscribe to enable session persistence via _handleAgentEvent