import { DoomCordisHostConnection } from "../pi/cordisHost.cjs"; import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; //#region src/adapters/testing/piHost.d.ts /** One stored handler, widened at the single point that calls it. */ type InvokableHandler = (event: unknown, context: unknown) => unknown; type RunMode = ExtensionContext['mode']; type ShortcutId = Parameters[0]; type ShortcutOptions = Parameters[1]; type CommandOptions = Parameters[1]; type FlagOptions = Parameters[1]; type CustomMessagePayload = Parameters[0]; type SendMessageOptions = Parameters[1]; type UserMessageContent = Parameters[0]; type SendUserMessageOptions = Parameters[1]; type RegisteredTool = Parameters[0]; type ToolUpdateCallback = Parameters[3]; type ExecutionResult = Awaited>; type ExecutionOptions = Parameters[2]; type WidgetContent = Parameters[1]; export interface RecordedCommand { name: string; options: CommandOptions; } export interface RecordedShortcut { shortcut: ShortcutId; options: ShortcutOptions; } export interface RecordedRenderer { customType: string; renderer: unknown; } /** A `registerProvider` call in either of its two shapes. */ export interface RecordedProvider { /** Present for the `(name, config)` overload. */ name?: string; value: unknown; } export interface RecordedMessage { message: CustomMessagePayload; options: SendMessageOptions; } export interface RecordedUserMessage { content: UserMessageContent; options: SendUserMessageOptions; } export interface RecordedEntry { customType: string; data: unknown; } export interface RecordedExec { command: string; args: string[]; options: ExecutionOptions; } export interface RecordedNotification { sessionId: string; message: string; level: 'info' | 'warning' | 'error' | undefined; } export interface RecordedWidget { sessionId: string; key: string; content: WidgetContent; } export interface RecordedStatus { sessionId: string; key: string; text: string | undefined; } /** * What the extension's dialogs answer. * * Every default is the dismissal, because that is the answer a headless host * gives and the one an extension is most likely to mishandle. */ export interface PiTestDialogAnswers { select(title: string, options: string[]): string | undefined; confirm(title: string, message: string): boolean; input(title: string, placeholder: string | undefined): string | undefined; editor(title: string, prefill: string | undefined): string | undefined; } export interface PiTestContextOptions { sessionId?: string; cwd?: string; hasUI?: boolean; mode?: RunMode; isIdle?: boolean; isProjectTrusted?: boolean; signal?: AbortSignal; answers?: Partial; systemPrompt?: string; } export interface PiTestHostOptions extends PiTestContextOptions { /** Answers `pi.exec`; the default reports a command that ran and printed nothing. */ exec?: (command: string, args: string[]) => ExecutionResult | Promise; } export interface PiTestHost { /** The host an extension factory receives. */ readonly pi: ExtensionAPI; readonly tools: readonly RegisteredTool[]; readonly commands: readonly RecordedCommand[]; readonly shortcuts: readonly RecordedShortcut[]; readonly flags: ReadonlyMap; readonly messageRenderers: readonly RecordedRenderer[]; readonly entryRenderers: readonly RecordedRenderer[]; readonly markdownTransformers: readonly unknown[]; readonly providers: readonly RecordedProvider[]; readonly unregisteredProviders: readonly string[]; readonly messages: readonly RecordedMessage[]; readonly userMessages: readonly RecordedUserMessage[]; readonly entries: readonly RecordedEntry[]; readonly execs: readonly RecordedExec[]; readonly notifications: readonly RecordedNotification[]; readonly statuses: readonly RecordedStatus[]; readonly widgets: readonly RecordedWidget[]; /** Tool names Pi would offer the model right now. */ activeTools(): readonly string[]; tool(name: string): RegisteredTool | undefined; command(name: string): RecordedCommand | undefined; /** Lifecycle handlers registered for one event, in registration order. */ handlers(event: string): readonly InvokableHandler[]; /** A context for this host; each call builds a fresh one, as Pi does per event. */ context(options?: PiTestContextOptions): ExtensionContext; /** * Runs every handler for one lifecycle event and returns what they answered. * * Sequential and awaited, matching Pi, so a test can observe one handler's * effect on the next. */ emit(event: string, payload?: unknown, context?: ExtensionContext): Promise; /** Calls a registered tool the way Pi's runner does. */ callTool(name: string, params?: unknown, options?: { toolCallId?: string; signal?: AbortSignal; onUpdate?: ToolUpdateCallback; context?: ExtensionContext; }): Promise; /** Runs a registered slash command the way Pi's palette does. */ runCommand(name: string, args?: string, context?: ExtensionContext): Promise; /** The real Cordis host on this runner, installed on first use and disposed by `dispose`. */ cordis(source?: string): Promise; dispose(): Promise; } /** * A Pi host and the records of what an extension did to it. * * Nothing here is a spy from a test framework: the records are plain arrays, so * the harness works under any runner and adds no dependency to a package that * every extension already installs. */ export declare function createPiTestHost(options?: PiTestHostOptions): PiTestHost; //#endregion //# sourceMappingURL=piHost.d.cts.map