diff --git a/src/handlers/services/requestContext.ts b/src/handlers/services/requestContext.ts index e389e79fc..01eb78c23 100644 --- a/src/handlers/services/requestContext.ts +++ b/src/handlers/services/requestContext.ts @@ -109,9 +109,19 @@ export class RequestContext { get metadata(): Record { try { - return JSON.parse(this.requestHeaders[HEADER_KEYS.METADATA] ?? '{}'); + const headerMetadata = JSON.parse( + this.requestHeaders[HEADER_KEYS.METADATA] ?? '{}' + ); + const configMetadata = this.providerOption.metadata || {}; + + // Merge: config metadata + header metadata (headers win conflicts) + return { + ...configMetadata, + ...headerMetadata, + }; } catch (error) { - return {}; + // Fallback to config metadata only + return this.providerOption.metadata || {}; } } diff --git a/tests/unit/src/handlers/services/requestContext.test.ts b/tests/unit/src/handlers/services/requestContext.test.ts index a5bfd7b87..f432fd26b 100644 --- a/tests/unit/src/handlers/services/requestContext.test.ts +++ b/tests/unit/src/handlers/services/requestContext.test.ts @@ -371,13 +371,67 @@ describe('RequestContext', () => { expect(requestContext.metadata).toEqual({ userId: 'user123' }); }); - it('should return empty object for invalid JSON', () => { + it('should merge provider metadata with header metadata', () => { + const providerOptionWithMetadata = { + ...mockProviderOption, + metadata: { region: 'us-east-1', environment: 'prod', team: 'ai' }, + }; + const headers = { + [HEADER_KEYS.METADATA]: JSON.stringify({ + userId: 'user123', + team: 'overridden', + }), + }; + const context = new RequestContext( + mockContext, + providerOptionWithMetadata, + 'chatComplete' as endpointStrings, + headers, + {}, + 'POST', + 0 + ); + + expect(context.metadata).toEqual({ + region: 'us-east-1', + environment: 'prod', + team: 'overridden', // Header metadata wins + userId: 'user123', + }); + }); + + it('should return provider metadata when no header metadata', () => { + const providerOptionWithMetadata = { + ...mockProviderOption, + metadata: { region: 'us-east-1', environment: 'prod' }, + }; + const context = new RequestContext( + mockContext, + providerOptionWithMetadata, + 'chatComplete' as endpointStrings, + {}, + {}, + 'POST', + 0 + ); + + expect(context.metadata).toEqual({ + region: 'us-east-1', + environment: 'prod', + }); + }); + + it('should fallback to provider metadata for invalid JSON header', () => { + const providerOptionWithMetadata = { + ...mockProviderOption, + metadata: { region: 'us-east-1', fallback: 'true' }, + }; const headers = { [HEADER_KEYS.METADATA]: '{invalid json}', }; const context = new RequestContext( mockContext, - mockProviderOption, + providerOptionWithMetadata, 'chatComplete' as endpointStrings, headers, {}, @@ -385,10 +439,13 @@ describe('RequestContext', () => { 0 ); - expect(context.metadata).toEqual({}); + expect(context.metadata).toEqual({ + region: 'us-east-1', + fallback: 'true', + }); }); - it('should return empty object when no metadata header', () => { + it('should return empty object when no metadata header and no provider metadata', () => { const context = new RequestContext( mockContext, mockProviderOption,