feat(ai): add requestMetadata support to BedrockOptions for cost allocation tagging (#2511)
Add an optional requestMetadata field to BedrockOptions that forwards key-value pairs to the Bedrock Converse API ConverseStreamCommand. Tags appear in AWS Cost Explorer split cost allocation data, enabling callers to attribute inference costs to specific applications or contexts. Changes: - Add requestMetadata?: Record<string, string> to BedrockOptions with JSDoc documenting AWS constraints (max 50 pairs, key 64 chars, value 256 chars, no aws: prefix) - Pass requestMetadata to commandInput via conditional spread to avoid sending undefined when omitted - Export BedrockOptions from package root (consistent with other provider option types) - Add E2E tests: metadata forwarded to SDK payload, and omitted when not provided closes #2510
This commit is contained in:
@@ -1246,6 +1246,60 @@ describe("Generate E2E Tests", () => {
|
||||
expect(payload.additionalModelRequestFields?.output_config).toEqual({ effort: "max" });
|
||||
expect(payload.additionalModelRequestFields?.anthropic_beta).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should pass requestMetadata to the SDK payload", { retry: 3 }, async () => {
|
||||
const llmSonnet = getModel("amazon-bedrock", "global.anthropic.claude-sonnet-4-5-20250929-v1:0");
|
||||
let capturedPayload: unknown;
|
||||
const metadata = { app: "pi-test", env: "ci" };
|
||||
const response = await complete(
|
||||
llmSonnet,
|
||||
{
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: "Say hi.",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
requestMetadata: metadata,
|
||||
onPayload: (payload) => {
|
||||
capturedPayload = payload;
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(response.stopReason, `Error: ${response.errorMessage}`).not.toBe("error");
|
||||
expect(capturedPayload).toBeTruthy();
|
||||
expect((capturedPayload as { requestMetadata?: unknown }).requestMetadata).toEqual(metadata);
|
||||
});
|
||||
|
||||
it("should omit requestMetadata from payload when not provided", { retry: 3 }, async () => {
|
||||
const llmSonnet = getModel("amazon-bedrock", "global.anthropic.claude-sonnet-4-5-20250929-v1:0");
|
||||
let capturedPayload: unknown;
|
||||
const response = await complete(
|
||||
llmSonnet,
|
||||
{
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: "Say hi.",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
onPayload: (payload) => {
|
||||
capturedPayload = payload;
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(response.stopReason, `Error: ${response.errorMessage}`).not.toBe("error");
|
||||
expect(capturedPayload).toBeTruthy();
|
||||
expect("requestMetadata" in (capturedPayload as object)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Check if ollama is installed and local LLM tests are enabled
|
||||
|
||||
Reference in New Issue
Block a user