{"version":3,"file":"piHost.cjs","names":["connectDoomCordisHost"],"sources":["../../../src/adapters/testing/piHost.ts"],"sourcesContent":["import type { ExtensionAPI, ExtensionContext, ToolDefinition } from '@earendil-works/pi-coding-agent';\nimport type { TSchema } from 'typebox';\nimport { connectDoomCordisHost, type DoomCordisHostConnection } from '../pi/cordisHost.ts';\n\n/**\n * A Pi host a test drives, in place of the one Pi builds at runtime.\n *\n * Every extension package needs one, and before this each wrote its own as an\n * `as unknown as ExtensionAPI` cast over the four or five members that package\n * happened to call. A cast type-checks whatever Pi's interface becomes, so the\n * casts all kept passing while diverging from each other and from Pi.\n *\n * `pi` here is a plain `ExtensionAPI`, assigned without a cast. When a Pi\n * upgrade adds or reshapes a member, this file stops compiling, which is the\n * whole point: one place to notice, instead of ninety places that never do.\n *\n * `ExtensionContext` cannot be held to the same standard and is built with one\n * cast, named at the site. Three of its members are unsatisfiable by an object\n * literal: `modelRegistry` is a class with a private field, so it is nominally\n * typed; `ui.theme` is typed from a module Pi does not export; and `model` is\n * a populated provider record no test asserts on. The context is otherwise\n * built member by member, and the surface extensions actually program against,\n * `ExtensionAPI`, carries no cast at all.\n */\n\n/**\n * Every handler Pi's 34 `on` overloads accept, stored as one.\n *\n * `never` in the parameter positions is what makes all 34 assignable: a handler\n * is only accepted where the stored type asks for less than the handler does.\n * The consequence is that a stored handler cannot be called without widening it\n * back, which `invokable` does once, below. No single type both accepts every\n * overload and is callable with an arbitrary payload.\n */\ntype LifecycleHandler = (event: never, context: never) => unknown;\n/** One stored handler, widened at the single point that calls it. */\ntype InvokableHandler = (event: unknown, context: unknown) => unknown;\n\nfunction invokable(handler: LifecycleHandler): InvokableHandler {\n  return handler as InvokableHandler;\n}\n\n/** Types Pi declares but does not re-export from its package root. */\ntype SessionManagerView = ExtensionContext['sessionManager'];\ntype RunMode = ExtensionContext['mode'];\ntype ShortcutId = Parameters<ExtensionAPI['registerShortcut']>[0];\ntype ShortcutOptions = Parameters<ExtensionAPI['registerShortcut']>[1];\ntype CommandOptions = Parameters<ExtensionAPI['registerCommand']>[1];\ntype FlagOptions = Parameters<ExtensionAPI['registerFlag']>[1];\ntype CustomMessagePayload = Parameters<ExtensionAPI['sendMessage']>[0];\ntype SendMessageOptions = Parameters<ExtensionAPI['sendMessage']>[1];\ntype UserMessageContent = Parameters<ExtensionAPI['sendUserMessage']>[0];\ntype SendUserMessageOptions = Parameters<ExtensionAPI['sendUserMessage']>[1];\ntype RegisteredTool = Parameters<ExtensionAPI['registerTool']>[0];\ntype ToolUpdateCallback = Parameters<RegisteredTool['execute']>[3];\ntype ExecutionResult = Awaited<ReturnType<ExtensionAPI['exec']>>;\ntype ExecutionOptions = Parameters<ExtensionAPI['exec']>[2];\ntype ThinkingLevelValue = ReturnType<ExtensionAPI['getThinkingLevel']>;\ntype WidgetContent = Parameters<ExtensionContext['ui']['setWidget']>[1];\n\nexport interface RecordedCommand {\n  name: string;\n  options: CommandOptions;\n}\nexport interface RecordedShortcut {\n  shortcut: ShortcutId;\n  options: ShortcutOptions;\n}\nexport interface RecordedRenderer {\n  customType: string;\n  renderer: unknown;\n}\n/** A `registerProvider` call in either of its two shapes. */\nexport interface RecordedProvider {\n  /** Present for the `(name, config)` overload. */\n  name?: string;\n  value: unknown;\n}\nexport interface RecordedMessage {\n  message: CustomMessagePayload;\n  options: SendMessageOptions;\n}\nexport interface RecordedUserMessage {\n  content: UserMessageContent;\n  options: SendUserMessageOptions;\n}\nexport interface RecordedEntry {\n  customType: string;\n  data: unknown;\n}\nexport interface RecordedExec {\n  command: string;\n  args: string[];\n  options: ExecutionOptions;\n}\nexport interface RecordedNotification {\n  sessionId: string;\n  message: string;\n  level: 'info' | 'warning' | 'error' | undefined;\n}\nexport interface RecordedWidget {\n  sessionId: string;\n  key: string;\n  content: WidgetContent;\n}\nexport interface RecordedStatus {\n  sessionId: string;\n  key: string;\n  text: string | undefined;\n}\n\n/**\n * What the extension's dialogs answer.\n *\n * Every default is the dismissal, because that is the answer a headless host\n * gives and the one an extension is most likely to mishandle.\n */\nexport interface PiTestDialogAnswers {\n  select(title: string, options: string[]): string | undefined;\n  confirm(title: string, message: string): boolean;\n  input(title: string, placeholder: string | undefined): string | undefined;\n  editor(title: string, prefill: string | undefined): string | undefined;\n}\n\nexport interface PiTestContextOptions {\n  sessionId?: string;\n  cwd?: string;\n  hasUI?: boolean;\n  mode?: RunMode;\n  isIdle?: boolean;\n  isProjectTrusted?: boolean;\n  signal?: AbortSignal;\n  answers?: Partial<PiTestDialogAnswers>;\n  systemPrompt?: string;\n}\n\nexport interface PiTestHostOptions extends PiTestContextOptions {\n  /** Answers `pi.exec`; the default reports a command that ran and printed nothing. */\n  exec?: (command: string, args: string[]) => ExecutionResult | Promise<ExecutionResult>;\n}\n\nexport interface PiTestHost {\n  /** The host an extension factory receives. */\n  readonly pi: ExtensionAPI;\n  readonly tools: readonly RegisteredTool[];\n  readonly commands: readonly RecordedCommand[];\n  readonly shortcuts: readonly RecordedShortcut[];\n  readonly flags: ReadonlyMap<string, FlagOptions>;\n  readonly messageRenderers: readonly RecordedRenderer[];\n  readonly entryRenderers: readonly RecordedRenderer[];\n  readonly markdownTransformers: readonly unknown[];\n  readonly providers: readonly RecordedProvider[];\n  readonly unregisteredProviders: readonly string[];\n  readonly messages: readonly RecordedMessage[];\n  readonly userMessages: readonly RecordedUserMessage[];\n  readonly entries: readonly RecordedEntry[];\n  readonly execs: readonly RecordedExec[];\n  readonly notifications: readonly RecordedNotification[];\n  readonly statuses: readonly RecordedStatus[];\n  readonly widgets: readonly RecordedWidget[];\n  /** Tool names Pi would offer the model right now. */\n  activeTools(): readonly string[];\n  tool(name: string): RegisteredTool | undefined;\n  command(name: string): RecordedCommand | undefined;\n  /** Lifecycle handlers registered for one event, in registration order. */\n  handlers(event: string): readonly InvokableHandler[];\n  /** A context for this host; each call builds a fresh one, as Pi does per event. */\n  context(options?: PiTestContextOptions): ExtensionContext;\n  /**\n   * Runs every handler for one lifecycle event and returns what they answered.\n   *\n   * Sequential and awaited, matching Pi, so a test can observe one handler's\n   * effect on the next.\n   */\n  emit(event: string, payload?: unknown, context?: ExtensionContext): Promise<unknown[]>;\n  /** Calls a registered tool the way Pi's runner does. */\n  callTool(\n    name: string,\n    params?: unknown,\n    options?: {\n      toolCallId?: string;\n      signal?: AbortSignal;\n      onUpdate?: ToolUpdateCallback;\n      context?: ExtensionContext;\n    },\n  ): Promise<unknown>;\n  /** Runs a registered slash command the way Pi's palette does. */\n  runCommand(name: string, args?: string, context?: ExtensionContext): Promise<void>;\n  /** The real Cordis host on this runner, installed on first use and disposed by `dispose`. */\n  cordis(source?: string): Promise<DoomCordisHostConnection>;\n  dispose(): Promise<void>;\n}\n\nconst DEFAULT_CWD = '/repo';\nconst DEFAULT_SESSION_ID = 'test-session';\nconst DEFAULT_MODE: RunMode = 'tui';\nconst DEFAULT_SYSTEM_PROMPT = '';\nconst DEFAULT_CORDIS_SOURCE = 'pi-test-host';\nconst DEFAULT_EXEC: ExecutionResult = { code: 0, killed: false, stdout: '', stderr: '' };\n\nconst DISMISSED: PiTestDialogAnswers = {\n  select: () => undefined,\n  confirm: () => false,\n  input: () => undefined,\n  editor: () => undefined,\n};\n\n/**\n * A Pi host and the records of what an extension did to it.\n *\n * Nothing here is a spy from a test framework: the records are plain arrays, so\n * the harness works under any runner and adds no dependency to a package that\n * every extension already installs.\n */\nexport function createPiTestHost(options: PiTestHostOptions = {}): PiTestHost {\n  const tools: RegisteredTool[] = [];\n  const commands: RecordedCommand[] = [];\n  const shortcuts: RecordedShortcut[] = [];\n  const flags = new Map<string, FlagOptions>();\n  const messageRenderers: RecordedRenderer[] = [];\n  const entryRenderers: RecordedRenderer[] = [];\n  const markdownTransformers: unknown[] = [];\n  const providers: RecordedProvider[] = [];\n  const unregisteredProviders: string[] = [];\n  const messages: RecordedMessage[] = [];\n  const userMessages: RecordedUserMessage[] = [];\n  const entries: RecordedEntry[] = [];\n  const execs: RecordedExec[] = [];\n  const notifications: RecordedNotification[] = [];\n  const statuses: RecordedStatus[] = [];\n  const widgets: RecordedWidget[] = [];\n\n  const lifecycle = new Map<string, LifecycleHandler[]>();\n  const channels = new Map<string, Set<(data: unknown) => void>>();\n  let activeToolNames: string[] = [];\n  let sessionName: string | undefined;\n  let thinkingLevel: ThinkingLevelValue = 'off';\n  let cordisConnection: DoomCordisHostConnection | undefined;\n\n  const runExec = options.exec ?? ((): ExecutionResult => DEFAULT_EXEC);\n\n  const pi: ExtensionAPI = {\n    on(event: string, handler: LifecycleHandler): void {\n      const registered = lifecycle.get(event) ?? [];\n      registered.push(handler);\n      lifecycle.set(event, registered);\n    },\n    // Generic exactly as Pi declares it. Storage erases the schema generics; the\n    // signature is the half that has to keep matching.\n    registerTool<TParams extends TSchema = TSchema, TDetails = unknown, TState = unknown>(\n      tool: ToolDefinition<TParams, TDetails, TState>,\n    ): void {\n      tools.push(tool as unknown as RegisteredTool);\n      activeToolNames.push(tool.name);\n    },\n    registerCommand(name: string, commandOptions: CommandOptions): void {\n      commands.push({ name, options: commandOptions });\n    },\n    registerShortcut(shortcut: ShortcutId, shortcutOptions: ShortcutOptions): void {\n      shortcuts.push({ shortcut, options: shortcutOptions });\n    },\n    registerFlag(name: string, flagOptions: FlagOptions): void {\n      flags.set(name, flagOptions);\n    },\n    getFlag(name: string): boolean | string | undefined {\n      return flags.get(name)?.default;\n    },\n    registerMessageRenderer(customType: string, renderer: unknown): void {\n      messageRenderers.push({ customType, renderer });\n    },\n    registerMarkdownTransformer(transformer: unknown): void {\n      markdownTransformers.push(transformer);\n    },\n    registerEntryRenderer(customType: string, renderer: unknown): void {\n      entryRenderers.push({ customType, renderer });\n    },\n    sendMessage(message: CustomMessagePayload, sendOptions?: SendMessageOptions): void {\n      messages.push({ message, options: sendOptions });\n    },\n    sendUserMessage(content: UserMessageContent, sendOptions?: SendUserMessageOptions): void {\n      userMessages.push({ content, options: sendOptions });\n    },\n    appendEntry(customType: string, data?: unknown): void {\n      entries.push({ customType, data });\n    },\n    setSessionName(name: string): void {\n      sessionName = name;\n    },\n    getSessionName(): string | undefined {\n      return sessionName;\n    },\n    setLabel(): void {\n      // Labels are session bookmarks; no DoomPi extension reads them back.\n    },\n    async exec(command: string, args: string[], execOptions?: ExecutionOptions): Promise<ExecutionResult> {\n      execs.push({ command, args, options: execOptions });\n      return runExec(command, args);\n    },\n    getActiveTools(): string[] {\n      return [...activeToolNames];\n    },\n    getAllTools(): never[] {\n      // Pi's inventory folds in built-in and MCP tools this host has none of.\n      return [];\n    },\n    setActiveTools(toolNames: string[]): void {\n      activeToolNames = [...toolNames];\n    },\n    getCommands(): never[] {\n      return [];\n    },\n    async setModel(): Promise<boolean> {\n      // No API key is configured, which is the answer Pi gives for the same reason.\n      return false;\n    },\n    getThinkingLevel(): ThinkingLevelValue {\n      return thinkingLevel;\n    },\n    setThinkingLevel(level: ThinkingLevelValue): void {\n      thinkingLevel = level;\n    },\n    registerProvider(providerOrName: unknown, config?: unknown): void {\n      providers.push(\n        typeof providerOrName === 'string' ? { name: providerOrName, value: config } : { value: providerOrName },\n      );\n    },\n    unregisterProvider(name: string): void {\n      unregisteredProviders.push(name);\n    },\n    events: {\n      emit(channel: string, data: unknown): void {\n        // A snapshot: a listener that unsubscribes on delivery would otherwise\n        // reshape the set this loop is walking.\n        const delivered = [...(channels.get(channel) ?? [])];\n        for (const listener of delivered) listener(data);\n      },\n      on(channel: string, listener: (data: unknown) => void): () => void {\n        const listeners = channels.get(channel) ?? new Set<(data: unknown) => void>();\n        listeners.add(listener);\n        channels.set(channel, listeners);\n        return () => listeners.delete(listener);\n      },\n    },\n  };\n\n  function buildContext(contextOptions: PiTestContextOptions = {}): ExtensionContext {\n    const sessionId = contextOptions.sessionId ?? options.sessionId ?? DEFAULT_SESSION_ID;\n    const cwd = contextOptions.cwd ?? options.cwd ?? DEFAULT_CWD;\n    const answers = { ...DISMISSED, ...options.answers, ...contextOptions.answers };\n    const sessionManager = {\n      getCwd: () => cwd,\n      getSessionId: () => sessionId,\n      getSessionName: () => sessionName,\n      getSessionDir: () => cwd,\n      getSessionFile: () => `${cwd}/${sessionId}.jsonl`,\n      getLeafId: () => undefined,\n      getLeafEntry: () => undefined,\n      getEntry: () => undefined,\n      getLabel: () => undefined,\n      getBranch: () => [],\n      buildContextEntries: () => [],\n      getHeader: () => undefined,\n      getEntries: () => [],\n      getTree: () => [],\n    };\n    const ui = {\n      select: async (title: string, selectOptions: string[]) => answers.select(title, selectOptions),\n      confirm: async (title: string, message: string) => answers.confirm(title, message),\n      input: async (title: string, placeholder?: string) => answers.input(title, placeholder),\n      editor: async (title: string, prefill?: string) => answers.editor(title, prefill),\n      notify: (message: string, level?: 'info' | 'warning' | 'error') => {\n        notifications.push({ sessionId, message, level });\n      },\n      onTerminalInput: () => () => undefined,\n      setStatus: (key: string, text: string | undefined) => {\n        statuses.push({ sessionId, key, text });\n      },\n      setWorkingMessage: () => undefined,\n      setWorkingVisible: () => undefined,\n      setWorkingIndicator: () => undefined,\n      setHiddenThinkingLabel: () => undefined,\n      setWidget: (key: string, content: WidgetContent) => {\n        widgets.push({ sessionId, key, content });\n      },\n      setFooter: () => undefined,\n      setHeader: () => undefined,\n      setTitle: () => undefined,\n      // A custom component needs a real TUI to resolve, so it never does. An\n      // extension awaiting one must stay responsive, which is what this proves.\n      custom: () => new Promise<never>(() => undefined),\n      pasteToEditor: () => undefined,\n      setEditorText: () => undefined,\n      getEditorText: () => '',\n      addAutocompleteProvider: () => undefined,\n      setEditorComponent: () => undefined,\n      getEditorComponent: () => undefined,\n      theme: undefined,\n      getAllThemes: () => [],\n      getTheme: () => undefined,\n      setTheme: () => ({ success: false, error: 'This host renders nothing.' }),\n      getToolsExpanded: () => false,\n      setToolsExpanded: () => undefined,\n    };\n    const context = {\n      ui,\n      mode: contextOptions.mode ?? options.mode ?? DEFAULT_MODE,\n      hasUI: contextOptions.hasUI ?? options.hasUI ?? true,\n      cwd,\n      sessionManager: sessionManager as unknown as SessionManagerView,\n      modelRegistry: undefined,\n      model: undefined,\n      scopedModels: [],\n      isIdle: () => contextOptions.isIdle ?? options.isIdle ?? true,\n      isProjectTrusted: () => contextOptions.isProjectTrusted ?? options.isProjectTrusted ?? true,\n      signal: contextOptions.signal ?? options.signal,\n      abort: () => undefined,\n      hasPendingMessages: () => false,\n      shutdown: () => undefined,\n      getContextUsage: () => undefined,\n      compact: () => undefined,\n      getSystemPrompt: () => contextOptions.systemPrompt ?? options.systemPrompt ?? DEFAULT_SYSTEM_PROMPT,\n      // Command handlers receive the wider context, and an extension that only\n      // reads it should not have to be handed a second fixture to be exercised.\n      getSystemPromptOptions: () => ({}),\n      waitForIdle: async () => undefined,\n      newSession: async () => ({ cancelled: true }),\n      fork: async () => ({ cancelled: true }),\n      navigateTree: async () => ({ cancelled: true }),\n      switchSession: async () => ({ cancelled: true }),\n      reload: async () => undefined,\n    };\n    // The one cast. `modelRegistry` is a class with a private field and so is\n    // nominally typed, `ui.theme` is typed from a module Pi does not export,\n    // and `model` is a populated provider record. No object literal can satisfy\n    // those three, and no DoomPi extension reads them.\n    return context as unknown as ExtensionContext;\n  }\n\n  return {\n    pi,\n    tools,\n    commands,\n    shortcuts,\n    flags,\n    messageRenderers,\n    entryRenderers,\n    markdownTransformers,\n    providers,\n    unregisteredProviders,\n    messages,\n    userMessages,\n    entries,\n    execs,\n    notifications,\n    statuses,\n    widgets,\n    activeTools: () => [...activeToolNames],\n    tool: (name) => tools.find((candidate) => candidate.name === name),\n    command: (name) => commands.find((candidate) => candidate.name === name),\n    handlers: (event) => (lifecycle.get(event) ?? []).map(invokable),\n    context: buildContext,\n    async emit(event, payload, context) {\n      const eventContext = context ?? buildContext();\n      const answered: unknown[] = [];\n      // A snapshot, because a handler may register another for the same event\n      // and Pi does not deliver this emission to it.\n      const delivered = [...(lifecycle.get(event) ?? [])];\n      for (const handler of delivered) {\n        answered.push(await invokable(handler)({ type: event, ...(payload as object) }, eventContext));\n      }\n      return answered;\n    },\n    async callTool(name, params = {}, callOptions = {}) {\n      const tool = tools.find((candidate) => candidate.name === name);\n      if (!tool) throw new Error(`No tool named '${name}' is registered on this host.`);\n      return tool.execute(\n        callOptions.toolCallId ?? `call-${String(tools.indexOf(tool))}`,\n        params,\n        callOptions.signal,\n        callOptions.onUpdate,\n        callOptions.context ?? buildContext(),\n      );\n    },\n    async runCommand(name, args = '', context) {\n      const command = commands.find((candidate) => candidate.name === name);\n      if (!command) throw new Error(`No command named '${name}' is registered on this host.`);\n      await command.options.handler(args, (context ?? buildContext()) as never);\n    },\n    async cordis(source = DEFAULT_CORDIS_SOURCE) {\n      cordisConnection ??= await connectDoomCordisHost(pi, source);\n      return cordisConnection;\n    },\n    async dispose() {\n      await cordisConnection?.dispose();\n      cordisConnection = undefined;\n    },\n  };\n}\n"],"mappings":"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"}