import type { AgentTool, AgentToolResult } from "@earendil-works/pi-agent-core"; import { type ContextUsage, type ExtensionAPI, type ExtensionContext, type ExtensionToolContext, type RegisteredCommand, SessionManager, SettingsManager, type SessionBoundaryDraft, type ToolDefinition } from "@earendil-works/pi-coding-agent"; import { type OperationError, type TextWindow } from "../../src/tools/result.js"; export type ExtensionTestEnvironment = { readonly cwd: string; readonly agentDir: string; beforeEach(): void; afterEach(): void; newNotesRoot(): string; dispose(): void; }; /** * Install the process-level settings and notes roots needed by one test file. * The caller owns the lifecycle hooks; this helper never registers tests or hooks. */ export declare function installExtensionTestEnvironment(prefix?: string): ExtensionTestEnvironment; export type Notice = { message: string; type?: "info" | "warning" | "error"; }; export declare function writeJson(path: string, value: unknown): void; export type SettingsFixture = { cwd: string; agentDir: string; }; /** * Materialize global (agentDir/settings.json) and project (cwd/.pi/settings.json) * settings in temp directories, then read them back through the same public * SettingsManager.create the extension uses. Never touches the real ~/.pi. */ export declare function settingsFixture(options?: { global?: Record; project?: Record; reserveTokens?: number; }): SettingsFixture; export type EventHandler = (event: never, ctx: ExtensionContext) => unknown; type SendMessageArg = Parameters[0]; export type SentMessage = { message: SendMessageArg; options: { triggerTurn?: boolean; } | undefined; }; export type Captured = { tools: Map; handlers: Map; commands: Map; sent: SentMessage[]; contextMessages: unknown[]; flags: string[]; }; export type CommandOptions = Omit; export type CompactionHookResult = { cancel: true; } | { compaction: { summary: string; firstKeptEntryId: string | null; tokensBefore: number; details?: unknown; }; } | undefined; /** TypeBox's TSchema does not expose `type`/`required` statically; read them structurally. */ export declare function objectSchema(tool: ToolDefinition | undefined): { type?: string; required?: string[]; } | undefined; export declare function manager(persisted?: boolean): SessionManager; export declare function makeExtension(sessionManager: SessionManager, settingsManager?: SettingsManager): Captured; export declare function explicitBoot(ctx: ExtensionContext, currentWindowId: string, previousWindowId: string | undefined): Promise; export declare function context(sessionManager: SessionManager, compact?: ExtensionContext["compact"], usage?: ContextUsage, idle?: boolean, cwd?: string, projectTrusted?: boolean, model?: string | { provider: string; id: string; }): ExtensionContext; export declare function noticesOf(ctx: ExtensionContext): Notice[]; export declare function sentOf(captured: Captured, customType: string): SentMessage[]; export declare function call(captured: Captured, name: string, params: Record, ctx: ExtensionContext): Promise>; /** * The context Pi hands a registered tool: the session context plus the nested-call surface * (ExtensionToolContext). The registered notes/history tools never call another tool, so `tools` * is empty and `executeTool` refuses instead of pretending a runtime exists. */ export declare function toolContext(ctx: ExtensionContext, callable?: readonly AgentTool[]): ExtensionToolContext; /** Decoded JSON of a tool that has not moved to structured outcomes: reset and budget tools only. */ export declare function resultJson(result: AgentToolResult): T; /** Data of a successful outcome, asserting both the structured success and the non-error result. */ export declare function resultData(result: AgentToolResult): T; /** The typed refusal of a failed outcome, asserting the error result and the refusal shape. */ export declare function resultError(result: AgentToolResult): OperationError; /** Identity a read outcome carries next to its window; tests narrow it with an explicit type. */ export type ReadIdentity = { metadata?: Record; address?: string; seq?: number; window_id?: string; }; /** The structured data of a read outcome: the window plus whatever identity the operation adds. */ export type ReadOutcome = { window: TextWindow; } & T; /** A read as tests consume it: its window fields, plus `content` as a test-only alias for `window.text`. */ export type ReadWindowResult = TextWindow & { content: string; } & T; export declare function resultRead(result: AgentToolResult): ReadWindowResult; /** Assert both surfaces of one result fit the wire budget: the model text and the structured payload. */ export declare function assertWithinBudget(result: AgentToolResult, message: string): void; export declare function runManualCompact(captured: Captured, ctx: ExtensionContext): Promise; export declare function runHandlers(captured: Captured, name: string, event: unknown, ctx: ExtensionContext): Promise; export declare function runCommand(captured: Captured, name: string, args: string, ctx: ExtensionContext): Promise; export type ContextHookResult = { messages: unknown[]; } | undefined; export declare function runContextHook(captured: Captured, ctx: ExtensionContext, eventOverride?: Record): Promise; export declare function runContextWithSystemHook(captured: Captured, ctx: ExtensionContext, messages: unknown[]): Promise; export declare function commitTurnEndBoundary(captured: Captured, sessionManager: SessionManager, ctx: ExtensionContext): Promise<{ entries: SessionBoundaryDraft[]; continue: boolean; }>; export declare function appendText(sessionManager: SessionManager, role: "user" | "assistant" | "toolResult", text: string, toolName?: string): string; export {};