diff --git a/packages/server/src/server/agent/plugin-provider.test.ts b/packages/server/src/server/agent/plugin-provider.test.ts index ae8ed805d7..aa0aa1a924 100644 --- a/packages/server/src/server/agent/plugin-provider.test.ts +++ b/packages/server/src/server/agent/plugin-provider.test.ts @@ -761,6 +761,72 @@ describe("PluginAgentClientRegistry", () => { await expect.poll(harness.closeCount).toBe(1); expect(harness.inputs.map((input) => input.type)).toContain("session.close"); }); + + test("delivers a supported steer to the active turn", async () => { + const harness = createProviderHarness({ + capabilities: [...CAPABILITIES, "prompt.steer"], + handleInput: async (input, emit) => { + if (input.type !== "session.prompt") return false; + emit({ + type: "session.prompt_result", + sessionId: input.sessionId, + clientMessageId: input.prompt.clientMessageId, + result: { type: "steer", turnId: "turn-1" }, + }); + return true; + }, + }); + const registry = new PluginAgentClientRegistry(createTestLogger()); + registry.replace([harness.registration]); + const client = registry.clients()[harness.registration.id]!; + const session = await client.createSession({ provider: harness.registration.id, cwd: "/tmp" }); + try { + await expect( + session.steerActiveTurn!("follow up", { + expectedTurnId: "turn-1", + clientMessageId: "steer-1", + clearPendingPermissions: true, + }), + ).resolves.toEqual({ status: "accepted" }); + expect(harness.inputs.find((input) => input.type === "session.prompt")).toMatchObject({ + prompt: { + delivery: "steer", + clientMessageId: "steer-1", + input: { type: "message", content: [{ type: "text", text: "follow up" }] }, + clearPendingPermissions: true, + }, + }); + } finally { + await session.close(); + registry.replace([]); + } + }); + + test("returns unavailable when steering a provider without prompt.steer capability", async () => { + const harness = createProviderHarness({ + capabilities: [ + "prompt.message", + "session.configure", + "session.persistence", + "session.subsession", + "permission", + ], + }); + const registry = new PluginAgentClientRegistry(createTestLogger()); + registry.replace([harness.registration]); + const session = await registry.clients()[harness.registration.id]!.createSession({ + provider: harness.registration.id, + cwd: "/workspace", + }); + try { + const result = await session.steerActiveTurn!("hello", { expectedTurnId: "turn-1" }); + expect(result).toEqual({ status: "unavailable" }); + expect(harness.inputs.filter((input) => input.type === "session.prompt")).toHaveLength(0); + } finally { + await session.close(); + registry.replace([]); + } + }); }); type RequestKind = "session.open" | "catalog" | "session.configure" | "session.prompt"; diff --git a/packages/server/src/server/agent/plugin-provider.ts b/packages/server/src/server/agent/plugin-provider.ts index e575ff0d45..db5d7651a2 100644 --- a/packages/server/src/server/agent/plugin-provider.ts +++ b/packages/server/src/server/agent/plugin-provider.ts @@ -1175,6 +1175,9 @@ class PluginAgentSession implements AgentSession { prompt: AgentPromptInput, options: SteerActiveTurnOptions, ): Promise { + if (!this.bridge.negotiatedCapabilities.includes("prompt.steer")) { + return { status: "unavailable" }; + } const result = await this.bridge.prompt({ clientMessageId: options.clientMessageId ?? randomUUID(), delivery: "steer",