diff --git a/CHANGELOG.md b/CHANGELOG.md index 53ca7b6817b..15326bc2fba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Docs: https://docs.openclaw.ai - Docs: add direct BotFather link and verification reminder in Telegram setup. (#4064) Thanks @shatner. - Docs: add Mintlify language navigation for zh-Hans. (#6416) Thanks @joshp123. - Telegram: use shared pairing store. (#6127) Thanks @obviyus. +- Agents: add OpenRouter app attribution headers. (#5050) Thanks @alexanderatallah. ### Fixes diff --git a/src/agents/pi-embedded-runner-extraparams.test.ts b/src/agents/pi-embedded-runner-extraparams.test.ts index 574bb550def..2053a87d668 100644 --- a/src/agents/pi-embedded-runner-extraparams.test.ts +++ b/src/agents/pi-embedded-runner-extraparams.test.ts @@ -1,5 +1,8 @@ +import type { StreamFn } from "@mariozechner/pi-agent-core"; +import type { Context, Model, SimpleStreamOptions } from "@mariozechner/pi-ai"; +import { AssistantMessageEventStream } from "@mariozechner/pi-ai"; import { describe, expect, it } from "vitest"; -import { resolveExtraParams } from "./pi-embedded-runner.js"; +import { applyExtraParamsToAgent, resolveExtraParams } from "./pi-embedded-runner.js"; describe("resolveExtraParams", () => { it("returns undefined with no model config", () => { @@ -60,3 +63,32 @@ describe("resolveExtraParams", () => { expect(result).toBeUndefined(); }); }); + +describe("applyExtraParamsToAgent", () => { + it("adds OpenRouter attribution headers to stream options", () => { + const calls: Array = []; + const baseStreamFn: StreamFn = (_model, _context, options) => { + calls.push(options); + return new AssistantMessageEventStream(); + }; + const agent = { streamFn: baseStreamFn }; + + applyExtraParamsToAgent(agent, undefined, "openrouter", "openrouter/auto"); + + const model = { + api: "openai-completions", + provider: "openrouter", + id: "openrouter/auto", + } as Model<"openai-completions">; + const context: Context = { messages: [] }; + + void agent.streamFn?.(model, context, { headers: { "X-Custom": "1" } }); + + expect(calls).toHaveLength(1); + expect(calls[0]?.headers).toEqual({ + "HTTP-Referer": "https://openclaw.ai", + "X-Title": "OpenClaw", + "X-Custom": "1", + }); + }); +}); diff --git a/src/agents/pi-embedded-runner/extra-params.ts b/src/agents/pi-embedded-runner/extra-params.ts index 60a30973ddc..fdfbaa47c21 100644 --- a/src/agents/pi-embedded-runner/extra-params.ts +++ b/src/agents/pi-embedded-runner/extra-params.ts @@ -108,7 +108,7 @@ function createStreamFnWithExtraParams( function createOpenRouterHeadersWrapper(baseStreamFn: StreamFn | undefined): StreamFn { const underlying = baseStreamFn ?? streamSimple; return (model, context, options) => - underlying(model as Model, context, { + underlying(model, context, { ...options, headers: { ...OPENROUTER_APP_HEADERS,