diff --git a/docs/providers.md b/docs/providers.md index a87fbfc41..5bee5b40b 100644 --- a/docs/providers.md +++ b/docs/providers.md @@ -34,7 +34,7 @@ Pi import discovery reads Pi's persisted JSONL session files because Pi RPC does OMP is a first-class built-in provider, disabled by default. Its launch contract, typed runtime, agent/session behavior, history, permissions, imports, and test fake live under `providers/omp/`; only the provider-neutral JSONL child-process transport is shared with Pi. It launches `omp --mode rpc-ui`, uses OMP's `get_available_commands` RPC for slash-command discovery, bridges OMP `rpc-ui` approval dialogs into Paseo permissions, and imports terminal-started sessions from `~/.omp/agent/sessions` when enabled. -OMP supports native Paseo host tools. The adapter registers the caller-scoped Paseo tool catalog directly with OMP, so `create_agent`, `send_agent_prompt`, `wait_for_agent`, and related tools do not need the internal MCP fallback. OMP's provider-managed task subagents are surfaced as Paseo subagents through `child_session` imports; the parent keeps the subagents track while the child runtime stays owned by OMP. Custom OMP profiles should extend `omp`; other Pi-compatible forks can still extend `pi`, override `command`, and set `params.sessionDir` to their JSONL session directory. +OMP supports native Paseo host tools. The adapter registers the full caller-scoped Paseo tool catalog directly with OMP, matching providers such as Claude that expose the full catalog through MCP. Serialize every OMP host definition with `loadMode: "essential"` so `create_agent`, `send_agent_prompt`, `wait_for_agent`, and related tools remain direct calls; omitting the field makes OMP mount non-built-in names under `xd://` instead. OMP's provider-managed task subagents are surfaced as Paseo subagents through `child_session` imports; the parent keeps the subagents track while the child runtime stays owned by OMP. Custom OMP profiles should extend `omp`; other Pi-compatible forks can still extend `pi`, override `command`, and set `params.sessionDir` to their JSONL session directory. Pi RPC extension UI dialog requests (`select`, `input`, `editor`, `confirm`) are bridged into Paseo question permissions and answered with `extension_ui_response`. Pi extensions such as `ask_user` may chain dialogs: for example, a `select` can be followed by an optional-comment `input`. When an `ask_user` tool call declares `allowComment: true`, Paseo presents the selection and optional comment as one question permission, answers Pi's initial `select` immediately, then auto-answers the follow-up optional `input` with the comment the user already supplied (or an empty string). Preserve placeholders and optional/skip semantics for standalone optional inputs so the app can still distinguish "skip this optional input" from "cancel the whole dialog." Fire-and-forget extension UI requests such as notifications are intentionally ignored by the provider adapter unless Paseo grows first-class UI for them. diff --git a/packages/server/src/server/agent/providers/omp/host-tools.test.ts b/packages/server/src/server/agent/providers/omp/host-tools.test.ts index 7b3d4fac8..70a795a5e 100644 --- a/packages/server/src/server/agent/providers/omp/host-tools.test.ts +++ b/packages/server/src/server/agent/providers/omp/host-tools.test.ts @@ -128,7 +128,7 @@ class OmpHostToolHarness { } describe("OMP host tools", () => { - test("serializes the caller-scoped Paseo catalog for set_host_tools", () => { + test("marks every caller-scoped Paseo tool essential for direct invocation", () => { const catalog = createCatalog([ { name: "create_agent", @@ -137,6 +137,11 @@ describe("OMP host tools", () => { inputSchema: { initialPrompt: z.string().describe("Prompt for the new agent.") }, handler: async () => ({ content: [] }), }, + { + name: "browser_list_tabs", + description: "List browser tabs.", + handler: async () => ({ content: [] }), + }, ]); expect(serializeOmpHostTools(catalog)).toEqual([ @@ -144,8 +149,15 @@ describe("OMP host tools", () => { name: "create_agent", label: "Create agent", description: "Create a Paseo agent.", + loadMode: "essential", parameters: expect.objectContaining({ type: "object", required: ["initialPrompt"] }), }, + { + name: "browser_list_tabs", + description: "List browser tabs.", + loadMode: "essential", + parameters: expect.objectContaining({ type: "object" }), + }, ]); }); diff --git a/packages/server/src/server/agent/providers/omp/host-tools.ts b/packages/server/src/server/agent/providers/omp/host-tools.ts index 865bb4594..9850c654d 100644 --- a/packages/server/src/server/agent/providers/omp/host-tools.ts +++ b/packages/server/src/server/agent/providers/omp/host-tools.ts @@ -35,6 +35,7 @@ export function serializeOmpHostTools(catalog: PaseoToolCatalog): OmpRpcHostTool const definition: OmpRpcHostToolDefinition = { name: tool.name, description: tool.description, + loadMode: "essential", parameters: serializePaseoToolInputParameters(tool), }; if (tool.title) { diff --git a/packages/server/src/server/agent/providers/omp/rpc-types.ts b/packages/server/src/server/agent/providers/omp/rpc-types.ts index e6e530317..33760d480 100644 --- a/packages/server/src/server/agent/providers/omp/rpc-types.ts +++ b/packages/server/src/server/agent/providers/omp/rpc-types.ts @@ -178,6 +178,7 @@ export const OmpRpcHostToolDefinitionSchema = z name: z.string(), label: z.string().optional(), description: z.string(), + loadMode: z.enum(["essential", "discoverable"]).optional(), parameters: z.record(z.string(), z.unknown()), hidden: z.boolean().optional(), })