/** * PiSessionAdapter — ISessionClient adapter for the Pi (plugin) platform. * * Pi does NOT expose a programmatic session management API to extensions. * Extensions get an ExtensionContext (ctx) which has ctx.sessionManager * for the CURRENT session only. This adapter provides graceful degradation * for all unsupported operations and filesystem-backed reading for * session data by scanning Pi JSONL session files. * * Pi stores sessions as JSONL files organized by workspace path within * the session directory. Each JSONL file represents one session, with one * JSON object per line (each line is a message). * * Session directory structure: * {sessionDir}/{workspace-dir-name}/{sessionId}.jsonl * * Must NOT import from any Pi or opencode SDK. * * @module */ import type { ISessionClient } from "../../ports/session-client.ts"; import type { SessionInfo, Message, FileDiff, Todo, SessionStatus } from "../../types.ts"; /** * Return true when a message contains any tool part whose state is * 'pending' or 'running' — i.e. an active tool/shell command. * * Mirrors the tool-part state vocabulary in src/session/types.ts * (ToolPart.state.status: "pending" | "running" | "completed" | "error"). * Used by status() to avoid deriving a false 'idle' while a node executes * shell commands, regardless of the message's `time.completed`. */ export declare function hasInFlightToolPart(msg?: Message): boolean; /** * ISessionClient adapter for the Pi platform. * * Supports read-only session operations via filesystem scanning * of Pi's JSONL session directory, plus filesystem-backed forking * (copying a session JSONL to a new id). The remaining mutation * methods (prompt, promptSync, create, abort) remain unsupported * and return null/false. */ export declare class PiSessionAdapter implements ISessionClient { /** Directory where Pi stores session JSONL files. */ readonly sessionDir: string; private _log; constructor( /** Directory where Pi stores session JSONL files. */ sessionDir?: string); /** * Resolve the session directory, expanding ~ if present. */ private _resolvedDir; /** * Get the workspace subdirectory path for a given working directory. * When directory is not provided, returns the root session dir. */ private _workspacePath; /** * Parse a JSONL file into an array of Message objects. * Each line of the JSONL file should be a valid JSON object * representing a Message (with `info` and `parts` fields). * Lines that fail to parse are skipped with a debug log. */ private _parseMessages; /** * Build a SessionInfo from parsed messages and session ID. * Extracts metadata from the messages: title from first user message, * timestamps from first/last messages, model from any message. */ private _buildSessionInfo; /** * List all JSONL session files in a given directory. * When `recurse` is true (root dir), also scans one level of * workspace subdirectories. * Returns a generator of { id, filePath } pairs. */ private _scanSessionFiles; /** * Find a session file by ID across all workspace subdirectories * (or within a specific workspace directory if provided). */ private _findSessionFile; /** * Pi doesn't allow extensions to prompt sessions — return null. */ prompt(_id: string, _options: { parts: Array<{ type: string; text: string; }>; noReply?: boolean; system?: string; agent?: string; model?: { providerID: string; modelID: string; }; }): Promise<{ id: string; } | null>; /** * Pi doesn't allow extensions to prompt sessions — return null. */ promptSync(_id: string, _options: { parts: Array<{ type: string; text: string; }>; agent?: string; signal?: AbortSignal; }): Promise<{ parts: Array<{ type: string; text?: string; }>; } | null>; /** * Pi manages session lifecycle internally — return null. */ create(_options: { directory: string; agent?: string; parentID?: string; }): Promise; /** * Pi manages session lifecycle internally — return false. */ abort(_id: string): Promise; /** * Pi does not support session compaction — always returns false. */ compact(_id: string): Promise; /** * Fork a session by copying its JSONL file to a new session id within * the same workspace directory. * * When `options.messageID` is provided, the fork keeps only the messages * up to and including that message (truncated prefix). When the messageID * is not found in the source session, no truncation is applied and all * messages are copied. * * Returns a fresh SessionInfo derived from the copied file, or null only * when the source session file does not exist. */ fork(id: string, options?: { directory?: string; messageID?: string; }): Promise; /** * List sessions by scanning Pi JSONL session files. * * When `directory` is provided, filters to sessions in that workspace. * Workspace directories are derived from the path using Pi's path encoding. * * Returns session metadata derived from the JSONL content. */ list(directory?: string): Promise; /** * Get a single session by ID. * Searches workspace subdirectories (or a specific directory if provided). * Falls back to the retained rolebox sidecar when no Pi-native session * file exists (sub-agent transcripts spawned via `pi --no-session`). */ get(id: string, directory?: string): Promise; /** * Get messages for a session by parsing its JSONL file. * Optionally limits the number of messages returned. * * Falls back to the retained rolebox sidecar * (`.rolebox/pi-sessions/{id}.jsonl`) when the session has no Pi-native * session file — this is how sub-agent transcripts survive after their * `pi --no-session` child exits (see sidecar-persister.ts). */ messages(id: string, options?: { directory?: string; limit?: number; }): Promise; /** * Get child sessions — unsupported on Pi. * * Pi stores each session as a single JSONL file where all messages * share the same sessionID. There is no parent-child relationship * data available in the file format, so this always returns empty. */ children(_id: string, _directory?: string): Promise; /** * Get todo items from a session's messages. * Searches message parts for structured data with todo-like content. */ todo(id: string, directory?: string): Promise; /** * Get file diffs from a session's messages. * Searches message parts for tool call results containing file diffs. * Optionally filters by messageID. */ diff(id: string, options?: { directory?: string; messageID?: string; }): Promise; /** * Get the status of a session. * Derives status from the session's message content. * Returns "idle" for sessions with complete messages, * "busy" if the last message has no completion time. * Falls back to the retained sidecar for sessions without a * Pi-native file (sub-agent transcripts). */ status(id: string, directory?: string): Promise; /** * Resolve the rolebox sidecar path for a session id: * `{cwd}/.rolebox/pi-sessions/{id}.jsonl` (the same layout used by * sidecar-persister.ts). */ private _sidecarPath; /** * Read messages from the retained rolebox sidecar for a session. * Returns `null` when no sidecar exists (session genuinely unknown), * otherwise replays the raw pi JSON events into Message objects. */ private _messagesFromSidecar; /** Derive a SessionStatus from parsed messages (shared by status paths). */ private _deriveStatus; } //# sourceMappingURL=session.d.ts.map