Release · Pi · earendil-works

Pi v0.84.0

What's new in Pi v0.84.0, released Aug 6, 2026 (). Newer: v1.4.0 (Oct 21, 2026)

Release notes

Pi v0.84.0

New Features
  • Fullscreen TUI mode — Switch between regular and fullscreen modes at runtime, with a sticky editor and footer, independently scrollable transcript, and draggable scrollbars. See UI & Display.
  • Mermaid and LaTeX rendering — Render Mermaid diagrams and terminal-friendly Unicode math in interactive transcripts. See Markdown settings and TUI Markdown.
  • Per-directory context overrides — Use AGENTS.override.md to replace context files for a specific directory. See Context Files.
  • Advanced custom model sampling — Configure arbitrary OpenAI-compatible samplingParams and opt-in vLLM thinking_token_budget values. See Sampling Parameters.
  • Baseten provider — Use built-in Baseten authentication and model support. See API Keys.
Breaking Changes
  • Renamed the inherited pi-ai ModelsStreamTransforms interface to ModelsRequestTransforms because its header transformation now applies to all authenticated provider requests.

  • Changed JSON and RPC message_update events to emit only assistantMessageEvent deltas, removing the cumulative message and assistantMessageEvent.partial fields that caused quadratic output growth. Clients that need partial messages must assemble deltas between message_start and message_end; the latter remains authoritative (#7290).

  • ModelRegistry.getApiKeyAndHeaders() now returns ProviderHeaders with string | null values and preserves null header-deletion markers. Extensions that inspect returned headers must handle null; extensions forwarding them to pi-ai streams should pass them through unchanged. This prevents placeholder OpenAI credentials from being sent through Cloudflare AI Gateway (#7030).

  • Changed ModelRegistry.refresh() to accept ModelsRefreshOptions and return ModelsRefreshResult instead of discarding cancellation and provider errors.

  • Changed ModelRuntime.setRuntimeApiKey() to accept auth cancellation options rather than catalog refresh options. Call refresh({ providers: [providerId], signal }) separately when remote freshness is required.

  • Required config-form extension OAuth refreshToken(credentials, signal) callbacks to accept and honor a concrete abort signal.

  • Replaced dynamic provider refresh context store access with the read-only context.stored snapshot and generation-checked context.publish() transaction.

    Providers built with createProvider({ fetchModels }): no catalog-publication migration is required. Before and after, return the fetched models and register the resulting provider; createProvider() owns restoration, persistence, and in-memory publication.

    // Before
    const beforeProvider = createProvider({
      // ...
      fetchModels: async ({ signal }) => {
        const response = await fetch(catalogUrl, { signal });
        return parseModels(await response.json());
      },
    });
    pi.registerProvider(beforeProvider);
    
    // After: unchanged
    const afterProvider = createProvider({
      // ...
      fetchModels: async ({ signal }) => {
        const response = await fetch(catalogUrl, { signal });
        return parseModels(await response.json());
      },
    });
    pi.registerProvider(afterProvider);
    

    Handwritten native Provider.refreshModels(): replace direct store access and pre-publication mutation with generation-guarded publications.

    // Before
    refreshModels: async (context) => {
      const stored = await context.store.read();
      if (stored) currentModels = stored.models;
      if (!context.allowNetwork) return;
    
      const refreshed = await fetchModels(context.signal);
      currentModels = refreshed;
      await context.store.write({ models: refreshed, checkedAt: Date.now() });
    },
    
    // After
    refreshModels: async (context) => {
      if (context.stored) {
        const restored = context.stored.models;
        if (!(await context.publish({
          update: () => { currentModels = restored; },
        }))) return;
      }
      if (!context.allowNetwork) return;
    
      const refreshed = await fetchModels(context.signal);
      if (context.signal.aborted) return;
      await context.publish({
        persist: { models: refreshed, checkedAt: Date.now() },
        update: () => { currentModels = refreshed; },
      });
    },
    

    For the config-form pi.registerProvider(name, { refreshModels }), callbacks that only return models remain unchanged; pi publishes the returned list. If such a callback previously used context.store for custom persistence, read context.stored and call context.publish({ persist: entry }). In publish(), omit persist to leave storage unchanged, pass a ModelsStoreEntry to write it, or pass persist: null to delete it.

  • Replaced the inherited pi-agent-core harness session model with the v4 lane-based Session, SessionStorage, and SessionRepo APIs, including durable operation records, global facts, shared sequence numbers, and tree-scoped lane views.

  • Promoted the inherited v2 session and AgentHarness API from pi-agent-core's experimental entrypoint to its default export and removed the experimental subpaths.

  • Removed the inherited legacy JSONL and in-memory repository APIs. Use pi-agent-core's v4 JsonlSessionRepo or InMemorySessionRepo, both implementing the new SessionRepo contract.

  • Added the inherited required pi-agent-core FileSystem.renameFile() operation for atomic JSONL publication; custom harness file-system implementations must provide same-filesystem replacement semantics (#7707 by @davidbrai).

  • Replaced experimental remote-session list summaries with durable SessionMetadata; RemoteSession.sessions no longer exposes runtime phase, model, thinking, attachment, or lock state, which remains available from acquired SessionSnapshot values (#7708).

Added
  • Added built-in Baseten provider support with BASETEN_API_KEY authentication and zai-org/GLM-5.2 as the default model.
  • Added experimental remote-session client APIs: the transport-neutral PiClient, CBOR protocol, Unix-socket transport, and @earendil-works/pi-coding-agent/client RemoteSession controller with transcript reducers. See Pi Client and Remote Protocol (#7344, #7348, #7371, #7409).
  • Added CredentialSynchronizationError for credential changes that commit successfully but fail to synchronize local model state.
  • Added chainable pi.registerMarkdownTransformer() hooks for display-only transformation of user and assistant Markdown. See pi.registerMarkdownTransformer() (#7231

…