/** * Contract: `createSettingsAwareStreamFn` layers session provider settings * (`providers.openrouterVariant`, `providers.antigravityEndpoint`, * `providers.maxInFlightRequests`, `model.loopGuard.*`, `textVerbosity` for * Responses-family requests) onto every call while letting caller-supplied * options win — the same wiring the main agent and the advisor agent share so * OpenRouter sticky-routing / response caching behaves the same on advisor turns * (can1357/oh-my-pi#3639). */ import { describe, expect, it } from "bun:test"; import type { StreamFn } from "@oh-my-pi/pi-agent-core"; import type { Context, Model, SimpleStreamOptions } from "@oh-my-pi/pi-ai"; import { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream"; import { Settings } from "@oh-my-pi/pi-coding-agent/config/settings"; import { createSettingsAwareStreamFn } from "@oh-my-pi/pi-coding-agent/session/settings-stream-fn"; function captureBase(): { fn: StreamFn; calls: Array<{ options?: SimpleStreamOptions }> } { const calls: Array<{ options?: SimpleStreamOptions }> = []; const fn: StreamFn = (_model, _context, options) => { calls.push({ options }); return new AssistantMessageEventStream(); }; return { fn, calls }; } const stubModel = {} as unknown as Model; const stubCodexModel = { api: "openai-codex-responses" } as unknown as Model; const stubResponsesModel = { api: "openai-responses" } as unknown as Model; const stubContext = { messages: [], tools: [], systemPrompt: [] } as unknown as Context; describe("createSettingsAwareStreamFn", () => { it("applies provider settings to the forwarded options when caller omits them", () => { const settings = Settings.isolated({ "providers.openrouterVariant": "floor", "providers.antigravityEndpoint": "sandbox", "providers.maxInFlightRequests": { openrouter: 4 }, "model.loopGuard.enabled": true, "model.loopGuard.checkAssistantContent": true, }); const { fn: base, calls } = captureBase(); const wrapped = createSettingsAwareStreamFn(settings, base); wrapped(stubModel, stubContext, { apiKey: "k" }); const options = calls[0]?.options; expect(options?.openrouterVariant).toBe("floor"); expect(options?.antigravityEndpointMode).toBe("sandbox"); expect(options?.maxInFlightRequests).toEqual({ openrouter: 4 }); expect(options?.loopGuard).toEqual({ enabled: true, checkAssistantContent: true }); // caller's own option is preserved expect(options?.apiKey).toBe("k"); }); it("applies Responses-family text verbosity from settings while preserving caller overrides", () => { const settings = Settings.isolated({ textVerbosity: "low" }); const { fn: base, calls } = captureBase(); const wrapped = createSettingsAwareStreamFn(settings, base); wrapped(stubCodexModel, stubContext, undefined); wrapped(stubResponsesModel, stubContext, undefined); wrapped(stubResponsesModel, stubContext, { textVerbosity: "medium" }); expect(calls[0]?.options?.textVerbosity).toBe("low"); expect(calls[1]?.options?.textVerbosity).toBe("low"); expect(calls[2]?.options?.textVerbosity).toBe("medium"); }); it("treats the default openrouterVariant as absent so the base call carries no variant", () => { const settings = Settings.isolated({ "providers.openrouterVariant": "default" }); const { fn: base, calls } = captureBase(); const wrapped = createSettingsAwareStreamFn(settings, base); wrapped(stubModel, stubContext, undefined); expect(calls[0]?.options?.openrouterVariant).toBeUndefined(); }); it("lets caller-supplied options override the session settings", () => { const settings = Settings.isolated({ "providers.openrouterVariant": "floor", "providers.antigravityEndpoint": "sandbox", "providers.maxInFlightRequests": { openrouter: 4 }, "model.loopGuard.enabled": true, }); const { fn: base, calls } = captureBase(); const wrapped = createSettingsAwareStreamFn(settings, base); wrapped(stubModel, stubContext, { openrouterVariant: "nitro", antigravityEndpointMode: "production", maxInFlightRequests: { openrouter: 1 }, loopGuard: { enabled: false }, }); const options = calls[0]?.options; expect(options?.openrouterVariant).toBe("nitro"); expect(options?.antigravityEndpointMode).toBe("production"); expect(options?.maxInFlightRequests).toEqual({ openrouter: 1 }); // Loop guard merges per-field: caller wins on `enabled`, settings fill // the rest (the inline closure the main agent used has the same shape). expect(options?.loopGuard?.enabled).toBe(false); expect(options?.loopGuard?.checkAssistantContent).toBe(true); }); });