fix(providers): sent anthropic search metadata
Forwarded the active web search session id as Anthropic Messages metadata.user_id so enterprise gateways can attribute and rate-limit search calls consistently with the main streaming path. Added a focused Anthropic web search request-shape regression test. Fixes #2295
This commit is contained in:
@@ -45,6 +45,7 @@
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed Anthropic web search requests to include `metadata.user_id` from the active session id, matching the main Messages path for gateway attribution ([#2295](https://github.com/can1357/oh-my-pi/issues/2295)).
|
||||
- Fixed `irc` live message delivery so successfully handed-off messages are no longer enqueued as mailbox mail, so they do not inflate unread `irc` counts
|
||||
- Fixed `irc send` with `await: true` to wait for a fresh reply to the current call instead of consuming previously buffered messages
|
||||
- Fixed main-session chat output to stop duplicating outbound `irc` sends from the main agent as relay cards
|
||||
|
||||
@@ -82,6 +82,7 @@ function buildSystemBlocks(
|
||||
* @param auth - Authentication configuration (API key or OAuth)
|
||||
* @param model - Model identifier to use
|
||||
* @param query - Search query from the user
|
||||
* @param sessionId - Optional session id forwarded as Anthropic metadata.user_id
|
||||
* @param systemPrompt - Optional system prompt for guiding response style
|
||||
* @returns Raw API response from Anthropic
|
||||
* @throws {SearchProviderError} If the API request fails
|
||||
@@ -90,6 +91,7 @@ async function callSearch(
|
||||
auth: AnthropicAuthConfig,
|
||||
model: string,
|
||||
query: string,
|
||||
sessionId?: string,
|
||||
systemPrompt?: string,
|
||||
maxTokens?: number,
|
||||
temperature?: number,
|
||||
@@ -113,6 +115,10 @@ async function callSearch(
|
||||
],
|
||||
};
|
||||
|
||||
if (sessionId) {
|
||||
body.metadata = { user_id: sessionId };
|
||||
}
|
||||
|
||||
if (temperature !== undefined) {
|
||||
body.temperature = temperature;
|
||||
}
|
||||
@@ -280,6 +286,7 @@ export async function searchAnthropic(
|
||||
buildAnthropicAuthConfig(key, searchBaseUrl),
|
||||
model,
|
||||
params.query,
|
||||
"authStorage" in params ? params.sessionId : undefined,
|
||||
systemPrompt,
|
||||
maxTokens,
|
||||
params.temperature,
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { describe, expect, it } from "bun:test";
|
||||
import * as path from "node:path";
|
||||
import type { FetchImpl } from "@oh-my-pi/pi-ai";
|
||||
import { AuthStorage } from "@oh-my-pi/pi-coding-agent/session/auth-storage";
|
||||
import { searchAnthropic } from "@oh-my-pi/pi-coding-agent/web/search/providers/anthropic";
|
||||
import { TempDir } from "@oh-my-pi/pi-utils";
|
||||
|
||||
describe("Anthropic search request body", () => {
|
||||
it("passes the session id as Messages metadata.user_id", async () => {
|
||||
using tempDir = TempDir.createSync("@pi-anthropic-search-");
|
||||
const authStorage = await AuthStorage.create(path.join(tempDir.path(), "auth.db"));
|
||||
try {
|
||||
authStorage.setRuntimeApiKey("anthropic", "test-key");
|
||||
|
||||
let capturedBody: Record<string, unknown> | undefined;
|
||||
const fetchMock: FetchImpl = async (_input, init) => {
|
||||
capturedBody = JSON.parse(String(init?.body));
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
id: "msg_test",
|
||||
model: "claude-haiku-4-5",
|
||||
content: [],
|
||||
usage: { input_tokens: 1, output_tokens: 2 },
|
||||
}),
|
||||
{ status: 200, headers: { "Content-Type": "application/json" } },
|
||||
);
|
||||
};
|
||||
|
||||
await searchAnthropic({
|
||||
query: "gateway attribution requirements",
|
||||
systemPrompt: "Use web search.",
|
||||
sessionId: "session-2295",
|
||||
authStorage,
|
||||
fetch: fetchMock,
|
||||
});
|
||||
|
||||
expect(capturedBody?.metadata).toEqual({ user_id: "session-2295" });
|
||||
} finally {
|
||||
authStorage.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user