diff --git a/packages/server/src/server/agent/plugin-provider.test.ts b/packages/server/src/server/agent/plugin-provider.test.ts index afca54d301..c7d5b82972 100644 --- a/packages/server/src/server/agent/plugin-provider.test.ts +++ b/packages/server/src/server/agent/plugin-provider.test.ts @@ -1005,7 +1005,10 @@ describe("PluginAgentClientRegistry", () => { describe("settings", () => { // A plugin that keeps `voice` on "direct" whatever it is asked, and takes `loud` as given. - async function openStubbornVoiceSession(given: Record) { + async function openStubbornVoiceSession( + given: Record, + { refuseAfterChanging = false }: { refuseAfterChanging?: boolean } = {}, + ) { const state = { voice: "direct", loud: false }; let openedSessionId = ""; const settings = () => [ @@ -1055,7 +1058,11 @@ describe("PluginAgentClientRegistry", () => { const loud = input.changes.settings?.loud; if (typeof loud === "boolean") state.loud = loud; emitConfig(emit, input.sessionId); - emit({ type: "request.completed", requestId: input.requestId }); + emit( + refuseAfterChanging + ? { type: "request.failed", requestId: input.requestId, error: { message: "no" } } + : { type: "request.completed", requestId: input.requestId }, + ); return true; } return false; @@ -1088,6 +1095,17 @@ describe("PluginAgentClientRegistry", () => { await session.close(); }); + test("a rejected apply reports what the plugin moved before refusing, since nothing is stored", async () => { + const { session, events } = await openStubbornVoiceSession({}, { refuseAfterChanging: true }); + + await expect(session.applyOptions?.({ loud: true })).rejects.toThrow("no"); + + expect(eventsOfType(events, "options_changed")).toEqual([ + { type: "options_changed", provider: "plugin-direct", patch: { loud: true } }, + ]); + await session.close(); + }); + test("a setting the plugin opened differently is the session's open patch, not an event", async () => { const { session, events } = await openStubbornVoiceSession({ voice: "other", loud: false }); diff --git a/packages/server/src/server/agent/plugin-provider.ts b/packages/server/src/server/agent/plugin-provider.ts index f88da5df67..2cac5c8a2b 100644 --- a/packages/server/src/server/agent/plugin-provider.ts +++ b/packages/server/src/server/agent/plugin-provider.ts @@ -1448,6 +1448,12 @@ class PluginAgentSession implements AgentSession { this.applyingOptions = true; try { await this.bridge.configure({ settings }); + } catch (error) { + // Nothing is stored for a refused patch, so what the plugin moved is reported once the + // call has ended. + this.applyingOptions = false; + for (const event of this.reportSettingChanges()) this.publish(event); + throw error; } finally { this.applyingOptions = false; }