diff --git a/.pi/hooks/test-command.ts b/.pi/hooks/test-command.ts index 52382d85..7f737498 100644 --- a/.pi/hooks/test-command.ts +++ b/.pi/hooks/test-command.ts @@ -2,7 +2,7 @@ * Test hook demonstrating custom commands, message rendering, and before_agent_start. */ import type { BeforeAgentStartEvent, HookAPI } from "@mariozechner/pi-coding-agent"; -import { Box, Text } from "@mariozechner/pi-tui"; +import { Box, Spacer, Text } from "@mariozechner/pi-tui"; export default function (pi: HookAPI) { // Track whether injection is enabled @@ -10,20 +10,22 @@ export default function (pi: HookAPI) { // Register a custom message renderer for our "test-info" type pi.registerMessageRenderer("test-info", (message, options, theme) => { - const box = new Box(0, 0, (t) => theme.bg("customMessageBg", t)); + const box = new Box(1, 1, (t) => theme.bg("customMessageBg", t)); const label = theme.fg("success", "[TEST INFO]"); box.addChild(new Text(label, 0, 0)); + box.addChild(new Spacer(1)); const content = typeof message.content === "string" ? message.content : message.content.map((c) => (c.type === "text" ? c.text : "[image]")).join(""); - box.addChild(new Text(theme.fg("text", content), 0, 1)); + box.addChild(new Text(theme.fg("text", content), 0, 0)); if (options.expanded && message.details) { - box.addChild(new Text(theme.fg("dim", `Details: ${JSON.stringify(message.details)}`), 0, 2)); + box.addChild(new Spacer(1)); + box.addChild(new Text(theme.fg("dim", `Details: ${JSON.stringify(message.details)}`), 0, 0)); } return box; diff --git a/packages/coding-agent/src/core/hooks/index.ts b/packages/coding-agent/src/core/hooks/index.ts index 6f34fe00..395d15e0 100644 --- a/packages/coding-agent/src/core/hooks/index.ts +++ b/packages/coding-agent/src/core/hooks/index.ts @@ -33,6 +33,7 @@ export type { HookMessageRenderOptions, HookUIContext, LsToolResultEvent, + ReadonlySessionManager, ReadToolResultEvent, RegisteredCommand, SessionEvent, diff --git a/packages/coding-agent/src/core/hooks/types.ts b/packages/coding-agent/src/core/hooks/types.ts index fa753b7e..e97e20e0 100644 --- a/packages/coding-agent/src/core/hooks/types.ts +++ b/packages/coding-agent/src/core/hooks/types.ts @@ -13,7 +13,34 @@ import type { CompactionPreparation, CompactionResult } from "../compaction.js"; import type { ExecOptions, ExecResult } from "../exec.js"; import type { HookMessage } from "../messages.js"; import type { ModelRegistry } from "../model-registry.js"; -import type { CompactionEntry, SessionManager } from "../session-manager.js"; +import type { + CompactionEntry, + SessionEntry, + SessionHeader, + SessionManager, + SessionTreeNode, +} from "../session-manager.js"; + +/** + * Read-only view of SessionManager for hooks. + * Hooks should use pi.sendMessage() and pi.appendEntry() for writes. + */ +export type ReadonlySessionManager = Pick< + SessionManager, + | "getCwd" + | "getSessionDir" + | "getSessionId" + | "getSessionFile" + | "getLeafUuid" + | "getLeafEntry" + | "getEntry" + | "getLabel" + | "getPath" + | "getHeader" + | "getEntries" + | "getTree" +>; + import type { EditToolDetails } from "../tools/edit.js"; import type { BashToolDetails, @@ -76,8 +103,8 @@ export interface HookEventContext { hasUI: boolean; /** Current working directory */ cwd: string; - /** Session manager instance - use for entries, session file, etc. */ - sessionManager: SessionManager; + /** Session manager (read-only) - use pi.sendMessage()/pi.appendEntry() for writes */ + sessionManager: ReadonlySessionManager; /** Model registry - use for API key resolution and model retrieval */ modelRegistry: ModelRegistry; } @@ -430,8 +457,8 @@ export interface HookCommandContext { hasUI: boolean; /** Current working directory */ cwd: string; - /** Session manager for reading/writing session entries */ - sessionManager: SessionManager; + /** Session manager (read-only) - use pi.sendMessage()/pi.appendEntry() for writes */ + sessionManager: ReadonlySessionManager; /** Model registry for API keys */ modelRegistry: ModelRegistry; }