fix(omp): expose injected Paseo tools directly (#2418)

This commit is contained in:
Derek Perez
2026-07-27 14:44:25 -07:00
committed by GitHub
parent e59c94812b
commit 5bd317205c
4 changed files with 16 additions and 2 deletions

View File

@@ -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.

View File

@@ -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" }),
},
]);
});

View File

@@ -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) {

View File

@@ -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(),
})