14
14
15
15
import { ToolboxTool } from './tool.js' ;
16
16
import axios from 'axios' ;
17
- import { type AxiosInstance , type AxiosResponse } from 'axios' ;
17
+ import {
18
+ type AxiosInstance ,
19
+ type AxiosRequestConfig ,
20
+ type AxiosResponse ,
21
+ } from 'axios' ;
18
22
import { ZodManifestSchema , createZodSchemaFromParams } from './protocol.js' ;
19
23
import { logApiError } from './errorUtils.js' ;
20
24
import { ZodError } from 'zod' ;
21
- import { BoundParams , BoundValue } from './utils.js' ;
25
+ import { BoundParams , BoundValue , resolveValue } from './utils.js' ;
22
26
23
27
type Manifest = import ( 'zod' ) . infer < typeof ZodManifestSchema > ;
24
28
type ToolSchemaFromManifest = Manifest [ 'tools' ] [ string ] ;
25
29
30
+ // Types for dynamic headers
31
+ export type HeaderFunction = ( ) => string | Promise < string > ;
32
+ export type ClientHeaderProvider = string | HeaderFunction ;
33
+ export type ClientHeadersConfig = Record < string , ClientHeaderProvider > ;
34
+
26
35
/**
27
36
* An asynchronous client for interacting with a Toolbox service.
28
- * Manages an Axios Client Session, if not provided.
29
37
*/
30
38
class ToolboxClient {
31
39
#baseUrl: string ;
32
40
#session: AxiosInstance ;
41
+ #clientHeaders: ClientHeadersConfig ;
33
42
34
43
/**
35
44
* Initializes the ToolboxClient.
36
45
* @param {string } url - The base URL for the Toolbox service API (e.g., "http://localhost:5000").
37
46
* @param {AxiosInstance } [session] - Optional Axios instance for making HTTP
38
47
* requests. If not provided, a new one will be created.
48
+ * @param {ClientHeadersConfig } [clientHeaders] - Optional initial headers to
49
+ * be included in each request.
39
50
*/
40
- constructor ( url : string , session ?: AxiosInstance ) {
51
+ constructor (
52
+ url : string ,
53
+ session ?: AxiosInstance | null ,
54
+ clientHeaders ?: ClientHeadersConfig | null
55
+ ) {
41
56
this . #baseUrl = url ;
42
57
this . #session = session || axios . create ( { baseURL : this . #baseUrl} ) ;
58
+ this . #clientHeaders = clientHeaders || { } ;
59
+ }
60
+
61
+ /**
62
+ * Resolves client headers from their provider functions.
63
+ * @returns {Promise<Record<string, string>> } A promise that resolves to the resolved headers.
64
+ */
65
+ async #resolveClientHeaders( ) : Promise < Record < string , string > > {
66
+ const resolvedEntries = await Promise . all (
67
+ Object . entries ( this . #clientHeaders) . map ( async ( [ key , value ] ) => {
68
+ const resolved = await resolveValue ( value ) ;
69
+ return [ key , String ( resolved ) ] ;
70
+ } )
71
+ ) ;
72
+ return Object . fromEntries ( resolvedEntries ) ;
43
73
}
44
74
45
75
/**
@@ -51,7 +81,9 @@ class ToolboxClient {
51
81
async #fetchAndParseManifest( apiPath : string ) : Promise < Manifest > {
52
82
const url = `${ this . #baseUrl} ${ apiPath } ` ;
53
83
try {
54
- const response : AxiosResponse = await this . #session. get ( url ) ;
84
+ const headers = await this . #resolveClientHeaders( ) ;
85
+ const config : AxiosRequestConfig = { headers} ;
86
+ const response : AxiosResponse = await this . #session. get ( url , config ) ;
55
87
const responseData = response . data ;
56
88
57
89
try {
@@ -114,7 +146,8 @@ class ToolboxClient {
114
146
toolName ,
115
147
toolSchema . description ,
116
148
paramZodSchema ,
117
- boundParams
149
+ applicableBoundParams ,
150
+ this . #clientHeaders
118
151
) ;
119
152
return { tool, usedBoundKeys} ;
120
153
}
@@ -125,8 +158,8 @@ class ToolboxClient {
125
158
* returns a callable (`ToolboxTool`) that can be used to invoke the
126
159
* tool remotely.
127
160
*
128
- * @param {BoundParams } [boundParams] - Optional parameters to pre-bind to the tool.
129
161
* @param {string } name - The unique name or identifier of the tool to load.
162
+ * @param {BoundParams } [boundParams] - Optional parameters to pre-bind to the tool.
130
163
* @returns {Promise<ReturnType<typeof ToolboxTool>> } A promise that resolves
131
164
* to a ToolboxTool function, ready for execution.
132
165
* @throws {Error } If the tool is not found in the manifest, the manifest structure is invalid,
@@ -157,7 +190,9 @@ class ToolboxClient {
157
190
158
191
if ( unusedBound . length > 0 ) {
159
192
throw new Error (
160
- `Validation failed for tool '${ name } ': unused bound parameters: ${ unusedBound . join ( ', ' ) } .`
193
+ `Validation failed for tool '${ name } ': unused bound parameters: ${ unusedBound . join (
194
+ ', '
195
+ ) } .`
161
196
) ;
162
197
}
163
198
return tool ;
@@ -205,7 +240,9 @@ class ToolboxClient {
205
240
throw new Error (
206
241
`Validation failed for toolset '${
207
242
name || 'default'
208
- } ': unused bound parameters could not be applied to any tool: ${ unusedBound . join ( ', ' ) } .`
243
+ } ': unused bound parameters could not be applied to any tool: ${ unusedBound . join (
244
+ ', '
245
+ ) } .`
209
246
) ;
210
247
}
211
248
return tools ;
0 commit comments