Skip to content

Add OMP (Oh-My-Pi) as a first-class importable provider#1177

Open
jms830 wants to merge 3 commits into
getpaseo:mainfrom
jms830:feat/omp-provider
Open

Add OMP (Oh-My-Pi) as a first-class importable provider#1177
jms830 wants to merge 3 commits into
getpaseo:mainfrom
jms830:feat/omp-provider

Conversation

@jms830
Copy link
Copy Markdown

@jms830 jms830 commented May 25, 2026

Closes #1176.

What

Adds OMP — Oh-My-Pi, a downstream fork of Pi — as a first-class provider alongside claude, codex, opencode, and pi. OMP ships its own binary (omp), home directory (~/.omp), and plugin ecosystem, but preserves Pi's --mode rpc wire protocol and JSONL session schema verbatim.

After this PR, OMP users can:

  • See OMP in paseo provider ls, the in-app provider catalog, and the agent picker
  • Import OMP sessions started in the terminal: paseo import <session-id> --provider omp --cwd <cwd>
  • Define custom providers that extends: "omp" in ~/.paseo/config.json

Why

OMP is a real-world Pi fork with its own omp CLI and ~/.omp/agent/sessions/<sanitized-cwd>/<ts>_<uuid>.jsonl storage layout. Today OMP users have two unappealing options:

  1. Run Paseo against vanilla Pi. Loses access to OMP plugins, OMP-installed extensions, and OMP's session history.
  2. Hack the Pi provider via env + custom-provider extends. Set PI_CODING_AGENT_DIR=~/.omp/agent, define a custom provider with extends: "pi" and command: ["omp", "--mode", "rpc"]. The UI still calls it "Pi", session metadata gets stamped provider: "pi", and any future Pi/OMP divergence breaks silently.

OMP and Pi are binary-compatible (same JSONL header {type:"session",version:3,id,cwd,...}, same RPC shape, same pi-mcp-adapter extension), so first-class support is a near-zero-cost integration that mirrors the existing Pi adapter pattern.

How

The Pi adapter is parameterized over a new PiFamilyConfig:

// packages/server/src/server/agent/providers/pi/family-config.ts
export interface PiFamilyConfig {
  readonly providerId: string;          // "pi" / "omp"
  readonly binaryName: string;          // "pi" / "omp"
  readonly binaryEnvVars: readonly string[];
  readonly homeDirName: string;         // ".pi" / ".omp"
  readonly agentDirEnv: string;
  readonly sessionDirEnv: string;
  readonly displayLabel: string;
  readonly mcpAdapterMarker: string;    // "pi-mcp-adapter" — OMP reuses Pi's adapter
}

export const PI_FAMILY: PiFamilyConfig = { ... };
export const OMP_FAMILY: PiFamilyConfig = { ... };

PiRpcAgentClient / PiRpcAgentSession / PiCliRuntime accept the family via constructor and thread family.providerId through all AgentStreamEvent emissions, AgentPersistenceHandle metadata, diagnostic output, and MCP adapter detection. Pi-side defaults (PI_FAMILY) are unchanged — all existing Pi tests pass byte-for-byte.

OmpRpcAgentClient in providers/omp/agent.ts is a thin subclass of PiRpcAgentClient that injects OMP_FAMILY and overrides listPersistedAgents to use OMP-specific offline JSONL discovery (see next section).

Registered in:

  • packages/server/src/server/agent/provider-manifest.tsAGENT_PROVIDER_DEFINITIONS
  • packages/server/src/server/agent/provider-registry.tsPROVIDER_CLIENT_FACTORIES
  • packages/server/src/shared/importable-providers.tsIMPORTABLE_PROVIDERS
  • packages/server/src/server/persisted-config.tsBUILTIN_PROVIDER_IDS
  • packages/server/src/server/daemon-e2e/agent-configs.tsallProviders
  • packages/cli/src/commands/agent/import.tsIMPORT_PROVIDER_LIST

Session discovery: deliberately split from Pi

#1154 ("Rewind chat or files from any user message") removed providers/pi/session-descriptor.ts and replaced Pi's listPersistedAgents with return [], because Pi now uses the runtime paseo_capture_entries extension to track session identity for sessions started inside Paseo.

That works for Pi-launched-from-Paseo, but it doesn't help users who run omp (or pi) directly in their terminal and later want to import that session into Paseo.

For OMP this PR adds a new providers/omp/session-descriptor.ts that does offline JSONL discovery of ~/.omp/agent/sessions/**/*.jsonl. It mirrors the historical Pi descriptor pattern (resolution order: OMP_CODING_AGENT_SESSION_DIROMP_CODING_AGENT_DIR/settings.json:sessionDir<cwd>/.omp/settings.json:sessionDir~/.omp/agent/sessions/) but parameterized over PiFamilyConfig so future Pi-family forks can reuse it.

Pi continues to use the runtime extension path as its canonical import strategy. The OMP descriptor is scoped to OMP paths and does not alter Pi behavior.

If reviewers want Pi import restored on the same offline-JSONL path (e.g. by passing PI_FAMILY to listOmpPersistedAgents and renaming the module to providers/pi-family/session-descriptor.ts), it's a one-line wiring change from this shape. I left Pi untouched on this PR to keep the review surface minimal and not contradict #1154's direction.

Testing

Layer Result
Pi regression 34/34 pre-existing Pi tests pass unchanged
OMP unit 11 new tests: 7 in omp/session-descriptor.test.ts (default path, env override, settings override, project .omp/settings.json, symlinks, sort+filter, family isolation), 4 in omp/agent.test.ts (provider id, session provider id, end-to-end listPersistedAgents, isolation from PI_CODING_AGENT_DIR)
Full server test suite 1649 passed / 40 skipped (153 test files), zero new failures
Format / lint / typecheck npm run format:check, npm run lint, npm run typecheck clean across all 8 workspaces
Live smoke (against a real OMP install) OmpRpcAgentClient.listPersistedAgents() against this dev's real ~/.omp/agent/sessions/ returned 5 well-formed PersistedAgentDescriptor objects with provider:"omp", correct cwds, titles, and JSONL nativeHandles. paseo provider ls --json shows OMP as a first-class entry. paseo agent import <id> --provider omp --cwd <cwd> reaches OmpRpcAgentClient.resumeSession and spawns the real omp --mode rpc process.

What this does NOT change

Files

  • New: packages/server/src/server/agent/providers/pi/family-config.ts
  • New: packages/server/src/server/agent/providers/omp/agent.ts
  • New: packages/server/src/server/agent/providers/omp/session-descriptor.ts
  • New: packages/server/src/server/agent/providers/omp/session-descriptor.test.ts
  • New: packages/server/src/server/agent/providers/omp/agent.test.ts
  • Modified: packages/server/src/server/agent/providers/pi/agent.ts (parameterize over family, PI_PROVIDERthis.providerId, helpers take family arg, runtimeSettings becomes protected)
  • Modified: packages/server/src/server/agent/providers/pi/cli-runtime.ts (accept family, default to PI_FAMILY)
  • Modified: packages/server/src/server/agent/provider-manifest.ts, provider-registry.ts, shared/importable-providers.ts, persisted-config.ts, daemon-e2e/agent-configs.ts, CLI agent/import.ts
  • Modified: docs/providers.md, public-docs/supported-providers.md, CHANGELOG.md

16 files, +1140 / -67 lines.

Follow-ups (out of scope here)

  • Lift omp/session-descriptor.ts to providers/pi-family/session-descriptor.ts if you want Pi imports restored on the same offline path.
  • Add an omp icon to the in-app provider catalog (matches Pi for now via the generic terminal icon).
  • Add a one-click install path for OMP in the in-app provider catalog (the same surface Pi has).
  • Factor history-mapper.ts, tool-call-mapper.ts, rpc-types.ts into providers/pi-family/ if OMP plugins ever start emitting JSONL frames Pi can't parse.

Parameterizes the Pi adapter over a PiFamilyConfig (binary name, home dir,
env-var prefix, display label, MCP adapter marker) and ships OMP_FAMILY
alongside PI_FAMILY. OmpRpcAgentClient is a thin subclass of
PiRpcAgentClient that injects OMP_FAMILY.

OMP and Pi share session lifecycle, history mapping, tool-call translation,
permission dialog bridging, MCP adapter detection, and the --mode rpc
client. Only the binary name (omp vs pi), home directory (~/.omp vs ~/.pi),
env-var prefix (OMP_CODING_AGENT_* vs PI_CODING_AGENT_*), and display label
differ.

OMP sessions started outside Paseo (in the terminal) are discovered by
reading ~/.omp/agent/sessions/**/*.jsonl via the new
providers/omp/session-descriptor.ts. This mirrors the historical Pi
descriptor (removed upstream in getpaseo#1154 in favor of runtime extension
capture) but is scoped to OMP paths so it does not contradict the Pi
direction — Pi continues to use paseo_capture_entries at runtime.

Pi behavior is unchanged. All 34 pre-existing Pi tests pass. 11 new tests
cover OMP-side session discovery, env-var precedence, family isolation
(OMP cannot see Pi sessions and vice versa), and the OmpRpcAgentClient
subclass surface.
@jms830 jms830 force-pushed the feat/omp-provider branch from 9f213cd to b15f5e0 Compare May 25, 2026 12:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add OMP (Oh-My-Pi) as a first-class importable provider

1 participant