1+ import { defu } from 'defu' ;
12import type { Arrayable } from 'type-fest' ;
23import { createMCPClient } from '../mcp-client' ;
34import { type RpcActionResponse , RpcClient } from '../rpc-client' ;
5+ import { type StackOneHeaders , stackOneHeadersSchema } from '../schemas/headers' ;
46import { BaseTool , Tools } from '../tool' ;
57import type {
68 ExecuteOptions ,
@@ -11,6 +13,7 @@ import type {
1113} from '../types' ;
1214import { toArray } from '../utils/array' ;
1315import { StackOneError } from '../utils/errors' ;
16+ import { normaliseHeaders } from '../utils/headers' ;
1417
1518/**
1619 * Converts RpcActionResponse to JsonDict in a type-safe manner.
@@ -304,23 +307,14 @@ export abstract class ToolSet {
304307 typeof inputParams === 'string' ? JSON . parse ( inputParams ) : ( inputParams ?? { } ) ;
305308
306309 const currentHeaders = tool . getHeaders ( ) ;
307- const actionHeaders = this . buildActionHeaders ( currentHeaders ) ;
310+ const baseHeaders = this . buildActionHeaders ( currentHeaders ) ;
308311
309312 const pathParams = this . extractRecord ( parsedParams , 'path' ) ;
310313 const queryParams = this . extractRecord ( parsedParams , 'query' ) ;
311314 const additionalHeaders = this . extractRecord ( parsedParams , 'headers' ) ;
312- if ( additionalHeaders ) {
313- for ( const [ key , value ] of Object . entries ( additionalHeaders ) ) {
314- if ( value === undefined || value === null ) continue ;
315- if ( typeof value === 'string' ) {
316- actionHeaders [ key ] = value ;
317- } else if ( typeof value === 'number' || typeof value === 'boolean' ) {
318- actionHeaders [ key ] = String ( value ) ;
319- } else {
320- actionHeaders [ key ] = JSON . stringify ( value ) ;
321- }
322- }
323- }
315+ const extraHeaders = normaliseHeaders ( additionalHeaders ) ;
316+ // defu merges extraHeaders into baseHeaders, both are already branded types
317+ const actionHeaders = defu ( extraHeaders , baseHeaders ) as StackOneHeaders ;
324318
325319 const bodyPayload = this . extractRecord ( parsedParams , 'body' ) ;
326320 const rpcBody : JsonDict = bodyPayload ? { ...bodyPayload } : { } ;
@@ -369,12 +363,14 @@ export abstract class ToolSet {
369363 return tool ;
370364 }
371365
372- private buildActionHeaders ( headers : Record < string , string > ) : Record < string , string > {
366+ private buildActionHeaders ( headers : Record < string , string > ) : StackOneHeaders {
373367 const sanitizedEntries = Object . entries ( headers ) . filter (
374368 ( [ key ] ) => key . toLowerCase ( ) !== 'authorization' ,
375369 ) ;
376370
377- return Object . fromEntries ( sanitizedEntries . map ( ( [ key , value ] ) => [ key , String ( value ) ] ) ) ;
371+ return stackOneHeadersSchema . parse (
372+ Object . fromEntries ( sanitizedEntries . map ( ( [ key , value ] ) => [ key , String ( value ) ] ) ) ,
373+ ) ;
378374 }
379375
380376 private extractRecord (
0 commit comments