@ctxprotocol/sdk 0.8.1 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -31
- package/dist/client/index.cjs +166 -32
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +155 -17
- package/dist/client/index.d.ts +155 -17
- package/dist/client/index.js +166 -32
- package/dist/client/index.js.map +1 -1
- package/dist/index.cjs +166 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +166 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/client/index.d.ts
CHANGED
|
@@ -9,9 +9,19 @@ interface ContextClientOptions {
|
|
|
9
9
|
apiKey: string;
|
|
10
10
|
/**
|
|
11
11
|
* Base URL for the Context Protocol API
|
|
12
|
-
* @default "https://ctxprotocol.com"
|
|
12
|
+
* @default "https://www.ctxprotocol.com"
|
|
13
13
|
*/
|
|
14
14
|
baseUrl?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Request timeout for non-streaming API calls in milliseconds.
|
|
17
|
+
* @default 300000
|
|
18
|
+
*/
|
|
19
|
+
requestTimeoutMs?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Request timeout for establishing streaming API calls in milliseconds.
|
|
22
|
+
* @default 600000
|
|
23
|
+
*/
|
|
24
|
+
streamTimeoutMs?: number;
|
|
15
25
|
}
|
|
16
26
|
/**
|
|
17
27
|
* An individual MCP tool exposed by a tool listing
|
|
@@ -30,7 +40,27 @@ interface McpToolRateLimitHints {
|
|
|
30
40
|
/** Optional human-readable notes for planning */
|
|
31
41
|
notes?: string;
|
|
32
42
|
}
|
|
43
|
+
type DiscoveryMode = "query" | "execute";
|
|
44
|
+
type McpToolSurface = "answer" | "execute" | "both";
|
|
45
|
+
type McpToolLatencyClass = "instant" | "fast" | "slow" | "streaming";
|
|
46
|
+
interface McpToolPricingMeta {
|
|
47
|
+
executeUsd?: string;
|
|
48
|
+
queryUsd?: string;
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
}
|
|
33
51
|
interface McpToolMeta {
|
|
52
|
+
/** Declared method surface */
|
|
53
|
+
surface?: McpToolSurface;
|
|
54
|
+
/** Whether this method can be selected in query mode */
|
|
55
|
+
queryEligible?: boolean;
|
|
56
|
+
/** Declared latency class for planner/runtime gating */
|
|
57
|
+
latencyClass?: McpToolLatencyClass;
|
|
58
|
+
/** Method-level pricing metadata */
|
|
59
|
+
pricing?: McpToolPricingMeta;
|
|
60
|
+
/** Derived discovery flag for execute eligibility */
|
|
61
|
+
executeEligible?: boolean;
|
|
62
|
+
/** Derived discovery field for explicit execute pricing visibility */
|
|
63
|
+
executePriceUsd?: string;
|
|
34
64
|
/** Context injection requirements handled by the Context runtime */
|
|
35
65
|
contextRequirements?: string[];
|
|
36
66
|
/**
|
|
@@ -48,6 +78,14 @@ interface McpToolMeta {
|
|
|
48
78
|
notes?: string;
|
|
49
79
|
[key: string]: unknown;
|
|
50
80
|
}
|
|
81
|
+
interface StructuredMethodGuidanceHints {
|
|
82
|
+
/** Suggested call-order sequence extracted from method descriptions */
|
|
83
|
+
callOrderHints?: string[];
|
|
84
|
+
/** Parameter usage caveats extracted from method descriptions */
|
|
85
|
+
parameterCaveats?: string[];
|
|
86
|
+
/** Edge-case behavior notes extracted from method descriptions */
|
|
87
|
+
edgeCaseNotes?: string[];
|
|
88
|
+
}
|
|
51
89
|
interface McpTool {
|
|
52
90
|
/** Name of the MCP tool method */
|
|
53
91
|
name: string;
|
|
@@ -65,6 +103,14 @@ interface McpTool {
|
|
|
65
103
|
outputSchema?: Record<string, unknown>;
|
|
66
104
|
/** MCP metadata extensions (context injection, rate-limit hints) */
|
|
67
105
|
_meta?: McpToolMeta;
|
|
106
|
+
/** Explicit execute eligibility in discovery responses */
|
|
107
|
+
executeEligible?: boolean;
|
|
108
|
+
/** Explicit execute price visibility in discovery responses */
|
|
109
|
+
executePriceUsd?: string | null;
|
|
110
|
+
/** Whether this method has normalized structured guidance hints */
|
|
111
|
+
hasStructuredGuidance?: boolean;
|
|
112
|
+
/** Optional structured guidance hints derived from the method description */
|
|
113
|
+
structuredGuidance?: StructuredMethodGuidanceHints;
|
|
68
114
|
}
|
|
69
115
|
/**
|
|
70
116
|
* Represents a tool available on the Context Protocol marketplace
|
|
@@ -106,6 +152,8 @@ interface Tool {
|
|
|
106
152
|
interface SearchResponse {
|
|
107
153
|
/** Array of matching tools */
|
|
108
154
|
tools: Tool[];
|
|
155
|
+
/** Discovery mode used by the server */
|
|
156
|
+
mode?: DiscoveryMode;
|
|
109
157
|
/** The search query that was used */
|
|
110
158
|
query: string;
|
|
111
159
|
/** Total number of results */
|
|
@@ -119,6 +167,18 @@ interface SearchOptions {
|
|
|
119
167
|
query?: string;
|
|
120
168
|
/** Maximum number of results (1-50, default 10) */
|
|
121
169
|
limit?: number;
|
|
170
|
+
/** Discovery mode with billing semantics */
|
|
171
|
+
mode?: DiscoveryMode;
|
|
172
|
+
/** Optional explicit method surface filter */
|
|
173
|
+
surface?: McpToolSurface;
|
|
174
|
+
/** Require methods marked query eligible */
|
|
175
|
+
queryEligible?: boolean;
|
|
176
|
+
/** Require explicit method execute pricing */
|
|
177
|
+
requireExecutePricing?: boolean;
|
|
178
|
+
/** Exclude methods by latency class */
|
|
179
|
+
excludeLatencyClasses?: McpToolLatencyClass[];
|
|
180
|
+
/** Convenience switch to exclude slow methods in query mode */
|
|
181
|
+
excludeSlow?: boolean;
|
|
122
182
|
}
|
|
123
183
|
/**
|
|
124
184
|
* Options for executing a tool
|
|
@@ -135,12 +195,36 @@ interface ExecuteOptions {
|
|
|
135
195
|
* Reuse the same key when retrying the same logical request.
|
|
136
196
|
*/
|
|
137
197
|
idempotencyKey?: string;
|
|
198
|
+
/** Explicit execute mode label for request clarity */
|
|
199
|
+
mode?: "execute";
|
|
200
|
+
/** Optional execute session identifier */
|
|
201
|
+
sessionId?: string;
|
|
202
|
+
/** Optional per-session spend budget envelope (USD) */
|
|
203
|
+
maxSpendUsd?: string;
|
|
204
|
+
/** Request session closure after this execute call settles */
|
|
205
|
+
closeSession?: boolean;
|
|
206
|
+
}
|
|
207
|
+
type ExecuteSessionStatus = "open" | "closed" | "expired";
|
|
208
|
+
interface ExecuteSessionSpend {
|
|
209
|
+
mode: "execute";
|
|
210
|
+
sessionId: string | null;
|
|
211
|
+
methodPrice: string;
|
|
212
|
+
spent: string;
|
|
213
|
+
remaining: string | null;
|
|
214
|
+
maxSpend: string | null;
|
|
215
|
+
/** Optional lifecycle fields when the API returns session state */
|
|
216
|
+
status?: ExecuteSessionStatus;
|
|
217
|
+
expiresAt?: string;
|
|
218
|
+
closeRequested?: boolean;
|
|
219
|
+
pendingAccruedCount?: number;
|
|
220
|
+
pendingAccruedUsd?: string;
|
|
138
221
|
}
|
|
139
222
|
/**
|
|
140
223
|
* Successful execution response from the API
|
|
141
224
|
*/
|
|
142
225
|
interface ExecuteApiSuccessResponse {
|
|
143
226
|
success: true;
|
|
227
|
+
mode: "execute";
|
|
144
228
|
/** The result data from the tool execution */
|
|
145
229
|
result: unknown;
|
|
146
230
|
/** Information about the executed tool */
|
|
@@ -148,6 +232,13 @@ interface ExecuteApiSuccessResponse {
|
|
|
148
232
|
id: string;
|
|
149
233
|
name: string;
|
|
150
234
|
};
|
|
235
|
+
/** Method-level execute pricing used for this call */
|
|
236
|
+
method: {
|
|
237
|
+
name: string;
|
|
238
|
+
executePriceUsd: string;
|
|
239
|
+
};
|
|
240
|
+
/** Spend envelope visibility for execute sessions */
|
|
241
|
+
session: ExecuteSessionSpend;
|
|
151
242
|
/** Execution duration in milliseconds */
|
|
152
243
|
durationMs: number;
|
|
153
244
|
}
|
|
@@ -157,19 +248,38 @@ interface ExecuteApiSuccessResponse {
|
|
|
157
248
|
interface ExecuteApiErrorResponse {
|
|
158
249
|
/** Human-readable error message */
|
|
159
250
|
error: string;
|
|
251
|
+
/** Explicit mode label for clarity */
|
|
252
|
+
mode?: "execute";
|
|
160
253
|
/** Error code for programmatic handling */
|
|
161
254
|
code?: ContextErrorCode;
|
|
162
255
|
/** URL to help resolve the issue */
|
|
163
256
|
helpUrl?: string;
|
|
257
|
+
/** Optional spend envelope context when available */
|
|
258
|
+
session?: ExecuteSessionSpend;
|
|
164
259
|
}
|
|
165
260
|
/**
|
|
166
261
|
* Raw API response from the execute endpoint
|
|
167
262
|
*/
|
|
168
263
|
type ExecuteApiResponse = ExecuteApiSuccessResponse | ExecuteApiErrorResponse;
|
|
264
|
+
interface ExecuteSessionStartOptions {
|
|
265
|
+
/** Maximum spend budget for the session (USD string) */
|
|
266
|
+
maxSpendUsd: string;
|
|
267
|
+
}
|
|
268
|
+
interface ExecuteSessionApiSuccessResponse {
|
|
269
|
+
success: true;
|
|
270
|
+
mode: "execute";
|
|
271
|
+
session: ExecuteSessionSpend;
|
|
272
|
+
}
|
|
273
|
+
type ExecuteSessionApiResponse = ExecuteSessionApiSuccessResponse | ExecuteApiErrorResponse;
|
|
274
|
+
interface ExecuteSessionResult {
|
|
275
|
+
mode: "execute";
|
|
276
|
+
session: ExecuteSessionSpend;
|
|
277
|
+
}
|
|
169
278
|
/**
|
|
170
279
|
* The resolved result returned to the user after SDK processing
|
|
171
280
|
*/
|
|
172
281
|
interface ExecutionResult<T = unknown> {
|
|
282
|
+
mode: "execute";
|
|
173
283
|
/** The data returned by the tool */
|
|
174
284
|
result: T;
|
|
175
285
|
/** Information about the executed tool */
|
|
@@ -177,9 +287,18 @@ interface ExecutionResult<T = unknown> {
|
|
|
177
287
|
id: string;
|
|
178
288
|
name: string;
|
|
179
289
|
};
|
|
290
|
+
/** Method-level execute pricing used for this call */
|
|
291
|
+
method: {
|
|
292
|
+
name: string;
|
|
293
|
+
executePriceUsd: string;
|
|
294
|
+
};
|
|
295
|
+
/** Spend envelope visibility for execute calls */
|
|
296
|
+
session: ExecuteSessionSpend;
|
|
180
297
|
/** Execution duration in milliseconds */
|
|
181
298
|
durationMs: number;
|
|
182
299
|
}
|
|
300
|
+
/** Supported orchestration depth modes for query execution. */
|
|
301
|
+
type QueryDepth = "fast" | "auto" | "deep";
|
|
183
302
|
/**
|
|
184
303
|
* Options for the agentic query endpoint (pay-per-response).
|
|
185
304
|
*
|
|
@@ -212,6 +331,13 @@ interface QueryOptions {
|
|
|
212
331
|
* Useful for large payload workflows where inline JSON is not ideal.
|
|
213
332
|
*/
|
|
214
333
|
includeDataUrl?: boolean;
|
|
334
|
+
/**
|
|
335
|
+
* Query orchestration depth mode:
|
|
336
|
+
* - `fast`: lower-latency path
|
|
337
|
+
* - `auto`: server decides between fast/deep
|
|
338
|
+
* - `deep`: full completeness-oriented path
|
|
339
|
+
*/
|
|
340
|
+
queryDepth?: QueryDepth;
|
|
215
341
|
/**
|
|
216
342
|
* Optional idempotency key (UUID recommended).
|
|
217
343
|
* Reuse the same key when retrying the same logical request.
|
|
@@ -300,7 +426,7 @@ type QueryStreamEvent = QueryStreamToolStatusEvent | QueryStreamTextDeltaEvent |
|
|
|
300
426
|
/**
|
|
301
427
|
* Specific error codes returned by the Context Protocol API
|
|
302
428
|
*/
|
|
303
|
-
type ContextErrorCode = "unauthorized" | "no_wallet" | "insufficient_allowance" | "payment_failed" | "execution_failed" | "query_failed";
|
|
429
|
+
type ContextErrorCode = "unauthorized" | "no_wallet" | "insufficient_allowance" | "payment_failed" | "execution_failed" | "query_failed" | "invalid_tool_method" | "method_not_execute_eligible" | "invalid_max_spend" | "session_not_found" | "session_forbidden" | "session_closed" | "session_expired" | "max_spend_mismatch" | "session_budget_exceeded";
|
|
304
430
|
/**
|
|
305
431
|
* Error thrown by the Context Protocol client
|
|
306
432
|
*/
|
|
@@ -318,20 +444,14 @@ declare class Discovery {
|
|
|
318
444
|
private client;
|
|
319
445
|
constructor(client: ContextClient);
|
|
320
446
|
/**
|
|
321
|
-
* Search for tools matching a query string
|
|
322
|
-
*
|
|
323
|
-
* @param query - The search query (e.g., "gas prices", "nft metadata")
|
|
324
|
-
* @param limit - Maximum number of results (1-50, default 10)
|
|
325
|
-
* @returns Array of matching tools
|
|
447
|
+
* Search for tools matching a query string.
|
|
326
448
|
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
* console.log(tools[0].name); // "Gas Price Oracle"
|
|
331
|
-
* console.log(tools[0].mcpTools); // Available methods
|
|
332
|
-
* ```
|
|
449
|
+
* Backward-compatible signatures:
|
|
450
|
+
* - `search("gas prices", 10)`
|
|
451
|
+
* - `search({ query: "gas prices", limit: 10, mode: "execute" })`
|
|
333
452
|
*/
|
|
334
453
|
search(query: string, limit?: number): Promise<Tool[]>;
|
|
454
|
+
search(options: SearchOptions): Promise<Tool[]>;
|
|
335
455
|
/**
|
|
336
456
|
* Get featured/popular tools (empty query search)
|
|
337
457
|
*
|
|
@@ -343,7 +463,7 @@ declare class Discovery {
|
|
|
343
463
|
* const featured = await client.discovery.getFeatured(5);
|
|
344
464
|
* ```
|
|
345
465
|
*/
|
|
346
|
-
getFeatured(limit?: number): Promise<Tool[]>;
|
|
466
|
+
getFeatured(limit?: number, options?: Omit<SearchOptions, "query" | "limit">): Promise<Tool[]>;
|
|
347
467
|
}
|
|
348
468
|
|
|
349
469
|
/**
|
|
@@ -384,6 +504,19 @@ declare class Tools {
|
|
|
384
504
|
* ```
|
|
385
505
|
*/
|
|
386
506
|
execute<T = unknown>(options: ExecuteOptions): Promise<ExecutionResult<T>>;
|
|
507
|
+
/**
|
|
508
|
+
* Start an execute session with a max spend budget.
|
|
509
|
+
*/
|
|
510
|
+
startSession(options: ExecuteSessionStartOptions): Promise<ExecuteSessionResult>;
|
|
511
|
+
/**
|
|
512
|
+
* Fetch current execute session status by ID.
|
|
513
|
+
*/
|
|
514
|
+
getSession(sessionId: string): Promise<ExecuteSessionResult>;
|
|
515
|
+
/**
|
|
516
|
+
* Close an execute session by ID.
|
|
517
|
+
*/
|
|
518
|
+
closeSession(sessionId: string): Promise<ExecuteSessionResult>;
|
|
519
|
+
private resolveSessionLifecycleResponse;
|
|
387
520
|
}
|
|
388
521
|
|
|
389
522
|
/**
|
|
@@ -493,6 +626,8 @@ declare class Query {
|
|
|
493
626
|
declare class ContextClient {
|
|
494
627
|
private readonly apiKey;
|
|
495
628
|
private readonly baseUrl;
|
|
629
|
+
private readonly requestTimeoutMs;
|
|
630
|
+
private readonly streamTimeoutMs;
|
|
496
631
|
private _closed;
|
|
497
632
|
/**
|
|
498
633
|
* Discovery resource for searching tools
|
|
@@ -515,7 +650,9 @@ declare class ContextClient {
|
|
|
515
650
|
*
|
|
516
651
|
* @param options - Client configuration options
|
|
517
652
|
* @param options.apiKey - Your Context Protocol API key (format: sk_live_...)
|
|
518
|
-
* @param options.baseUrl - Optional base URL override (defaults to https://ctxprotocol.com)
|
|
653
|
+
* @param options.baseUrl - Optional base URL override (defaults to https://www.ctxprotocol.com)
|
|
654
|
+
* @param options.requestTimeoutMs - Optional timeout for non-streaming requests (default 300000ms)
|
|
655
|
+
* @param options.streamTimeoutMs - Optional timeout for establishing stream requests (default 600000ms)
|
|
519
656
|
*/
|
|
520
657
|
constructor(options: ContextClientOptions);
|
|
521
658
|
/**
|
|
@@ -525,7 +662,7 @@ declare class ContextClient {
|
|
|
525
662
|
close(): void;
|
|
526
663
|
/**
|
|
527
664
|
* Internal method for making authenticated HTTP requests
|
|
528
|
-
* Includes timeout
|
|
665
|
+
* Includes timeout and retry with exponential backoff for transient errors
|
|
529
666
|
*
|
|
530
667
|
* @internal
|
|
531
668
|
*/
|
|
@@ -533,10 +670,11 @@ declare class ContextClient {
|
|
|
533
670
|
/**
|
|
534
671
|
* Internal method for making authenticated HTTP requests that returns
|
|
535
672
|
* the raw Response object. Used for streaming endpoints (SSE).
|
|
673
|
+
* Includes a configurable timeout for stream setup.
|
|
536
674
|
*
|
|
537
675
|
* @internal
|
|
538
676
|
*/
|
|
539
677
|
_fetchRaw(endpoint: string, options?: RequestInit): Promise<Response>;
|
|
540
678
|
}
|
|
541
679
|
|
|
542
|
-
export { ContextClient, type ContextClientOptions, ContextError, type ContextErrorCode, Discovery, type ExecuteApiErrorResponse, type ExecuteApiResponse, type ExecuteApiSuccessResponse, type ExecuteOptions, type ExecutionResult, type McpTool, type McpToolMeta, type McpToolRateLimitHints, Query, type QueryApiResponse, type QueryApiSuccessResponse, type QueryCost, type QueryOptions, type QueryResult, type QueryStreamDoneEvent, type QueryStreamEvent, type QueryStreamTextDeltaEvent, type QueryStreamToolStatusEvent, type QueryToolUsage, type SearchOptions, type SearchResponse, type Tool, Tools };
|
|
680
|
+
export { ContextClient, type ContextClientOptions, ContextError, type ContextErrorCode, Discovery, type ExecuteApiErrorResponse, type ExecuteApiResponse, type ExecuteApiSuccessResponse, type ExecuteOptions, type ExecuteSessionApiResponse, type ExecuteSessionApiSuccessResponse, type ExecuteSessionResult, type ExecuteSessionSpend, type ExecuteSessionStartOptions, type ExecuteSessionStatus, type ExecutionResult, type McpTool, type McpToolMeta, type McpToolRateLimitHints, Query, type QueryApiResponse, type QueryApiSuccessResponse, type QueryCost, type QueryOptions, type QueryResult, type QueryStreamDoneEvent, type QueryStreamEvent, type QueryStreamTextDeltaEvent, type QueryStreamToolStatusEvent, type QueryToolUsage, type SearchOptions, type SearchResponse, type Tool, Tools };
|
package/dist/client/index.js
CHANGED
|
@@ -15,27 +15,36 @@ var Discovery = class {
|
|
|
15
15
|
constructor(client) {
|
|
16
16
|
this.client = client;
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
* @param query - The search query (e.g., "gas prices", "nft metadata")
|
|
22
|
-
* @param limit - Maximum number of results (1-50, default 10)
|
|
23
|
-
* @returns Array of matching tools
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```typescript
|
|
27
|
-
* const tools = await client.discovery.search("gas prices");
|
|
28
|
-
* console.log(tools[0].name); // "Gas Price Oracle"
|
|
29
|
-
* console.log(tools[0].mcpTools); // Available methods
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
async search(query, limit) {
|
|
18
|
+
async search(queryOrOptions, limit) {
|
|
19
|
+
const options = typeof queryOrOptions === "string" ? { query: queryOrOptions, limit } : queryOrOptions;
|
|
33
20
|
const params = new URLSearchParams();
|
|
21
|
+
const query = options.query ?? "";
|
|
34
22
|
if (query) {
|
|
35
23
|
params.set("q", query);
|
|
36
24
|
}
|
|
37
|
-
if (limit !== void 0) {
|
|
38
|
-
params.set("limit", String(limit));
|
|
25
|
+
if (options.limit !== void 0) {
|
|
26
|
+
params.set("limit", String(options.limit));
|
|
27
|
+
}
|
|
28
|
+
if (options.mode) {
|
|
29
|
+
params.set("mode", options.mode);
|
|
30
|
+
}
|
|
31
|
+
if (options.surface) {
|
|
32
|
+
params.set("surface", options.surface);
|
|
33
|
+
}
|
|
34
|
+
if (options.queryEligible !== void 0) {
|
|
35
|
+
params.set("queryEligible", String(options.queryEligible));
|
|
36
|
+
}
|
|
37
|
+
if (options.requireExecutePricing !== void 0) {
|
|
38
|
+
params.set(
|
|
39
|
+
"requireExecutePricing",
|
|
40
|
+
String(options.requireExecutePricing)
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
if (options.excludeLatencyClasses && options.excludeLatencyClasses.length > 0) {
|
|
44
|
+
params.set("excludeLatency", options.excludeLatencyClasses.join(","));
|
|
45
|
+
}
|
|
46
|
+
if (options.excludeSlow !== void 0) {
|
|
47
|
+
params.set("excludeSlow", String(options.excludeSlow));
|
|
39
48
|
}
|
|
40
49
|
const queryString = params.toString();
|
|
41
50
|
const endpoint = `/api/v1/tools/search${queryString ? `?${queryString}` : ""}`;
|
|
@@ -53,8 +62,12 @@ var Discovery = class {
|
|
|
53
62
|
* const featured = await client.discovery.getFeatured(5);
|
|
54
63
|
* ```
|
|
55
64
|
*/
|
|
56
|
-
async getFeatured(limit) {
|
|
57
|
-
return this.search(
|
|
65
|
+
async getFeatured(limit, options) {
|
|
66
|
+
return this.search({
|
|
67
|
+
...options ?? {},
|
|
68
|
+
query: "",
|
|
69
|
+
...limit !== void 0 ? { limit } : {}
|
|
70
|
+
});
|
|
58
71
|
}
|
|
59
72
|
};
|
|
60
73
|
|
|
@@ -95,14 +108,31 @@ var Tools = class {
|
|
|
95
108
|
* ```
|
|
96
109
|
*/
|
|
97
110
|
async execute(options) {
|
|
98
|
-
const {
|
|
111
|
+
const {
|
|
112
|
+
toolId,
|
|
113
|
+
toolName,
|
|
114
|
+
args,
|
|
115
|
+
idempotencyKey,
|
|
116
|
+
mode,
|
|
117
|
+
sessionId,
|
|
118
|
+
maxSpendUsd,
|
|
119
|
+
closeSession
|
|
120
|
+
} = options;
|
|
99
121
|
const headers = idempotencyKey ? { "Idempotency-Key": idempotencyKey } : void 0;
|
|
100
122
|
const response = await this.client._fetch(
|
|
101
123
|
"/api/v1/tools/execute",
|
|
102
124
|
{
|
|
103
125
|
method: "POST",
|
|
104
126
|
headers,
|
|
105
|
-
body: JSON.stringify({
|
|
127
|
+
body: JSON.stringify({
|
|
128
|
+
toolId,
|
|
129
|
+
toolName,
|
|
130
|
+
args,
|
|
131
|
+
mode: mode ?? "execute",
|
|
132
|
+
sessionId,
|
|
133
|
+
maxSpendUsd,
|
|
134
|
+
closeSession
|
|
135
|
+
})
|
|
106
136
|
}
|
|
107
137
|
);
|
|
108
138
|
if ("error" in response) {
|
|
@@ -116,13 +146,79 @@ var Tools = class {
|
|
|
116
146
|
}
|
|
117
147
|
if (response.success) {
|
|
118
148
|
return {
|
|
149
|
+
mode: response.mode,
|
|
119
150
|
result: response.result,
|
|
120
151
|
tool: response.tool,
|
|
152
|
+
method: response.method,
|
|
153
|
+
session: response.session,
|
|
121
154
|
durationMs: response.durationMs
|
|
122
155
|
};
|
|
123
156
|
}
|
|
124
157
|
throw new ContextError("Unexpected response format from API");
|
|
125
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Start an execute session with a max spend budget.
|
|
161
|
+
*/
|
|
162
|
+
async startSession(options) {
|
|
163
|
+
const response = await this.client._fetch(
|
|
164
|
+
"/api/v1/tools/execute/sessions",
|
|
165
|
+
{
|
|
166
|
+
method: "POST",
|
|
167
|
+
body: JSON.stringify({
|
|
168
|
+
mode: "execute",
|
|
169
|
+
maxSpendUsd: options.maxSpendUsd
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
return this.resolveSessionLifecycleResponse(response);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Fetch current execute session status by ID.
|
|
177
|
+
*/
|
|
178
|
+
async getSession(sessionId) {
|
|
179
|
+
if (!sessionId) {
|
|
180
|
+
throw new ContextError("sessionId is required");
|
|
181
|
+
}
|
|
182
|
+
const encodedSessionId = encodeURIComponent(sessionId);
|
|
183
|
+
const response = await this.client._fetch(
|
|
184
|
+
`/api/v1/tools/execute/sessions/${encodedSessionId}`
|
|
185
|
+
);
|
|
186
|
+
return this.resolveSessionLifecycleResponse(response);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Close an execute session by ID.
|
|
190
|
+
*/
|
|
191
|
+
async closeSession(sessionId) {
|
|
192
|
+
if (!sessionId) {
|
|
193
|
+
throw new ContextError("sessionId is required");
|
|
194
|
+
}
|
|
195
|
+
const encodedSessionId = encodeURIComponent(sessionId);
|
|
196
|
+
const response = await this.client._fetch(
|
|
197
|
+
`/api/v1/tools/execute/sessions/${encodedSessionId}/close`,
|
|
198
|
+
{
|
|
199
|
+
method: "POST",
|
|
200
|
+
body: JSON.stringify({ mode: "execute" })
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
return this.resolveSessionLifecycleResponse(response);
|
|
204
|
+
}
|
|
205
|
+
resolveSessionLifecycleResponse(response) {
|
|
206
|
+
if ("error" in response) {
|
|
207
|
+
throw new ContextError(
|
|
208
|
+
response.error,
|
|
209
|
+
response.code,
|
|
210
|
+
void 0,
|
|
211
|
+
response.helpUrl
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
if (response.success) {
|
|
215
|
+
return {
|
|
216
|
+
mode: response.mode,
|
|
217
|
+
session: response.session
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
throw new ContextError("Unexpected response format from API");
|
|
221
|
+
}
|
|
126
222
|
};
|
|
127
223
|
|
|
128
224
|
// src/client/resources/query.ts
|
|
@@ -175,6 +271,7 @@ var Query = class {
|
|
|
175
271
|
modelId: opts.modelId,
|
|
176
272
|
includeData: opts.includeData,
|
|
177
273
|
includeDataUrl: opts.includeDataUrl,
|
|
274
|
+
queryDepth: opts.queryDepth,
|
|
178
275
|
stream: false
|
|
179
276
|
})
|
|
180
277
|
}
|
|
@@ -240,6 +337,7 @@ var Query = class {
|
|
|
240
337
|
modelId: opts.modelId,
|
|
241
338
|
includeData: opts.includeData,
|
|
242
339
|
includeDataUrl: opts.includeDataUrl,
|
|
340
|
+
queryDepth: opts.queryDepth,
|
|
243
341
|
stream: true
|
|
244
342
|
})
|
|
245
343
|
});
|
|
@@ -285,9 +383,14 @@ var Query = class {
|
|
|
285
383
|
};
|
|
286
384
|
|
|
287
385
|
// src/client/client.ts
|
|
386
|
+
var DEFAULT_BASE_URL = "https://www.ctxprotocol.com";
|
|
387
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 3e5;
|
|
388
|
+
var DEFAULT_STREAM_TIMEOUT_MS = 6e5;
|
|
288
389
|
var ContextClient = class {
|
|
289
390
|
apiKey;
|
|
290
391
|
baseUrl;
|
|
392
|
+
requestTimeoutMs;
|
|
393
|
+
streamTimeoutMs;
|
|
291
394
|
_closed = false;
|
|
292
395
|
/**
|
|
293
396
|
* Discovery resource for searching tools
|
|
@@ -310,14 +413,26 @@ var ContextClient = class {
|
|
|
310
413
|
*
|
|
311
414
|
* @param options - Client configuration options
|
|
312
415
|
* @param options.apiKey - Your Context Protocol API key (format: sk_live_...)
|
|
313
|
-
* @param options.baseUrl - Optional base URL override (defaults to https://ctxprotocol.com)
|
|
416
|
+
* @param options.baseUrl - Optional base URL override (defaults to https://www.ctxprotocol.com)
|
|
417
|
+
* @param options.requestTimeoutMs - Optional timeout for non-streaming requests (default 300000ms)
|
|
418
|
+
* @param options.streamTimeoutMs - Optional timeout for establishing stream requests (default 600000ms)
|
|
314
419
|
*/
|
|
315
420
|
constructor(options) {
|
|
316
421
|
if (!options.apiKey) {
|
|
317
422
|
throw new ContextError("API key is required");
|
|
318
423
|
}
|
|
424
|
+
const requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
425
|
+
const streamTimeoutMs = options.streamTimeoutMs ?? DEFAULT_STREAM_TIMEOUT_MS;
|
|
426
|
+
if (!Number.isFinite(requestTimeoutMs) || requestTimeoutMs <= 0) {
|
|
427
|
+
throw new ContextError("requestTimeoutMs must be a positive number");
|
|
428
|
+
}
|
|
429
|
+
if (!Number.isFinite(streamTimeoutMs) || streamTimeoutMs <= 0) {
|
|
430
|
+
throw new ContextError("streamTimeoutMs must be a positive number");
|
|
431
|
+
}
|
|
319
432
|
this.apiKey = options.apiKey;
|
|
320
|
-
this.baseUrl = (options.baseUrl ??
|
|
433
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
434
|
+
this.requestTimeoutMs = requestTimeoutMs;
|
|
435
|
+
this.streamTimeoutMs = streamTimeoutMs;
|
|
321
436
|
this.discovery = new Discovery(this);
|
|
322
437
|
this.tools = new Tools(this);
|
|
323
438
|
this.query = new Query(this);
|
|
@@ -331,7 +446,7 @@ var ContextClient = class {
|
|
|
331
446
|
}
|
|
332
447
|
/**
|
|
333
448
|
* Internal method for making authenticated HTTP requests
|
|
334
|
-
* Includes timeout
|
|
449
|
+
* Includes timeout and retry with exponential backoff for transient errors
|
|
335
450
|
*
|
|
336
451
|
* @internal
|
|
337
452
|
*/
|
|
@@ -341,7 +456,7 @@ var ContextClient = class {
|
|
|
341
456
|
}
|
|
342
457
|
const url = `${this.baseUrl}${endpoint}`;
|
|
343
458
|
const maxRetries = 3;
|
|
344
|
-
const timeoutMs =
|
|
459
|
+
const timeoutMs = this.requestTimeoutMs;
|
|
345
460
|
let lastError;
|
|
346
461
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
347
462
|
const controller = new AbortController();
|
|
@@ -409,6 +524,7 @@ var ContextClient = class {
|
|
|
409
524
|
/**
|
|
410
525
|
* Internal method for making authenticated HTTP requests that returns
|
|
411
526
|
* the raw Response object. Used for streaming endpoints (SSE).
|
|
527
|
+
* Includes a configurable timeout for stream setup.
|
|
412
528
|
*
|
|
413
529
|
* @internal
|
|
414
530
|
*/
|
|
@@ -417,14 +533,32 @@ var ContextClient = class {
|
|
|
417
533
|
throw new ContextError("Client has been closed");
|
|
418
534
|
}
|
|
419
535
|
const url = `${this.baseUrl}${endpoint}`;
|
|
420
|
-
const
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
...options
|
|
536
|
+
const controller = new AbortController();
|
|
537
|
+
const timeout = setTimeout(() => controller.abort(), this.streamTimeoutMs);
|
|
538
|
+
let response;
|
|
539
|
+
try {
|
|
540
|
+
response = await fetch(url, {
|
|
541
|
+
...options,
|
|
542
|
+
signal: controller.signal,
|
|
543
|
+
headers: {
|
|
544
|
+
"Content-Type": "application/json",
|
|
545
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
546
|
+
...options.headers
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
} catch (error) {
|
|
550
|
+
clearTimeout(timeout);
|
|
551
|
+
const lastError = error instanceof Error ? error : new Error(String(error));
|
|
552
|
+
if (lastError.name === "AbortError") {
|
|
553
|
+
throw new ContextError(
|
|
554
|
+
`Streaming request timed out after ${this.streamTimeoutMs / 1e3}s`,
|
|
555
|
+
void 0,
|
|
556
|
+
408
|
|
557
|
+
);
|
|
426
558
|
}
|
|
427
|
-
|
|
559
|
+
throw new ContextError(lastError.message);
|
|
560
|
+
}
|
|
561
|
+
clearTimeout(timeout);
|
|
428
562
|
if (!response.ok) {
|
|
429
563
|
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
430
564
|
let errorCode;
|