fix(cursor): exposed mounted xd devices to cursor-agent

Forwarded the session xd registry into Cursor provider tool contexts.

Routed Cursor MCP execution through the mounted registry fallback and added regression coverage for built-in devices and external MCP tools.

Fixes #5650
This commit is contained in:
roboomp
2026-07-16 03:15:32 +00:00
parent ed4ddcba6c
commit 8386ab2c0b
8 changed files with 150 additions and 4 deletions
@@ -2,6 +2,7 @@ import { describe, expect, it, mock } from "bun:test";
import { type AssistantMessage, type Context, z } from "@oh-my-pi/pi-ai";
import { createMockModel } from "@oh-my-pi/pi-ai/providers/mock";
import { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
import { buildModel } from "@oh-my-pi/pi-catalog/build";
import { Agent } from "../src/agent";
import type { AgentTool } from "../src/types";
@@ -39,6 +40,19 @@ function testAssistantMessage(text: string): AssistantMessage {
};
}
const cursorModel = buildModel({
id: "cursor-test",
name: "Cursor Test",
api: "cursor-agent",
provider: "cursor",
baseUrl: "https://example.invalid",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 8_192,
maxTokens: 2_048,
});
describe("Agent — buildSideRequestContext", () => {
const model = createMockModel({ responses: [] });
const tool: AgentTool = {
@@ -109,6 +123,43 @@ describe("Agent — buildSideRequestContext", () => {
});
});
it("adds mounted Cursor tools to main and side provider contexts", async () => {
await withNativeDialectEnv(async () => {
const mountedTool: AgentTool = {
...tool,
name: "mcp__fixture_report",
label: "Fixture Report",
};
let mainContext: Context | undefined;
const agent = new Agent({
initialState: {
model: cursorModel,
systemPrompt: ["system"],
tools: [tool],
},
getCursorTools: () => [tool, mountedTool],
streamFn: (_model, context) => {
mainContext = context;
const stream = new AssistantMessageEventStream();
queueMicrotask(() => {
const message = testAssistantMessage("ok");
stream.push({ type: "text_delta", contentIndex: 0, delta: "ok", partial: message });
stream.push({ type: "done", reason: "stop", message });
});
return stream;
},
});
await agent.prompt("Q?");
const sideContext = await agent.buildSideRequestContext([
{ role: "user", content: [{ type: "text", text: "Q?" }], timestamp: Date.now() },
]);
expect(mainContext?.tools?.map(entry => entry.name)).toEqual(["test_tool", "mcp__fixture_report"]);
expect(sideContext.tools?.map(entry => entry.name)).toEqual(["test_tool", "mcp__fixture_report"]);
});
});
it("returns empty tools when owned dialect is active", async () => {
const agent = new Agent({
initialState: {