@ctxprotocol/sdk 0.8.4 → 0.9.0
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 +16 -5
- package/dist/client/index.cjs +56 -50
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +147 -10
- package/dist/client/index.d.ts +147 -10
- package/dist/client/index.js +56 -50
- package/dist/client/index.js.map +1 -1
- package/dist/index.cjs +56 -50
- 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 +56 -50
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17,6 +17,14 @@ var Discovery = class {
|
|
|
17
17
|
constructor(client) {
|
|
18
18
|
this.client = client;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Fetch a single marketplace tool by its unique ID.
|
|
22
|
+
*/
|
|
23
|
+
async get(toolId) {
|
|
24
|
+
return this.client._fetch(
|
|
25
|
+
`/api/v1/tools/${encodeURIComponent(toolId)}`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
20
28
|
async search(queryOrOptions, limit) {
|
|
21
29
|
const options = typeof queryOrOptions === "string" ? { query: queryOrOptions, limit } : queryOrOptions;
|
|
22
30
|
const params = new URLSearchParams();
|
|
@@ -340,7 +348,7 @@ var Query = class {
|
|
|
340
348
|
* Run an agentic query and wait for the full response.
|
|
341
349
|
*
|
|
342
350
|
* The server discovers relevant tools (or uses the ones you specify),
|
|
343
|
-
* executes the
|
|
351
|
+
* executes the discovery-first pipeline (up to 100 MCP calls per tool),
|
|
344
352
|
* and returns an AI-synthesized answer. Payment is settled after
|
|
345
353
|
* successful execution via deferred settlement.
|
|
346
354
|
*
|
|
@@ -369,48 +377,25 @@ var Query = class {
|
|
|
369
377
|
*/
|
|
370
378
|
async run(options) {
|
|
371
379
|
const opts = typeof options === "string" ? { query: options } : options;
|
|
372
|
-
|
|
373
|
-
const
|
|
374
|
-
"
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
queryDepth: opts.queryDepth,
|
|
386
|
-
stream: false
|
|
387
|
-
})
|
|
380
|
+
let terminalError;
|
|
381
|
+
for await (const event of this.stream(opts)) {
|
|
382
|
+
if (event.type === "error") {
|
|
383
|
+
terminalError = {
|
|
384
|
+
error: event.error,
|
|
385
|
+
...event.code ? { code: event.code } : {},
|
|
386
|
+
...event.scope ? { scope: event.scope } : {},
|
|
387
|
+
...event.reasonCode ? { reasonCode: event.reasonCode } : {}
|
|
388
|
+
};
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
if (event.type === "done") {
|
|
392
|
+
return event.result;
|
|
388
393
|
}
|
|
389
|
-
);
|
|
390
|
-
if ("error" in response) {
|
|
391
|
-
throw new ContextError(
|
|
392
|
-
response.error,
|
|
393
|
-
response.code,
|
|
394
|
-
void 0,
|
|
395
|
-
response.helpUrl
|
|
396
|
-
);
|
|
397
394
|
}
|
|
398
|
-
if (
|
|
399
|
-
|
|
400
|
-
toolsUsed: response.toolsUsed,
|
|
401
|
-
durationMs: response.durationMs
|
|
402
|
-
}) : void 0);
|
|
403
|
-
return {
|
|
404
|
-
response: response.response,
|
|
405
|
-
toolsUsed: response.toolsUsed,
|
|
406
|
-
cost: response.cost,
|
|
407
|
-
durationMs: response.durationMs,
|
|
408
|
-
data: response.data,
|
|
409
|
-
dataUrl: response.dataUrl,
|
|
410
|
-
developerTrace
|
|
411
|
-
};
|
|
395
|
+
if (terminalError) {
|
|
396
|
+
throw new ContextError(terminalError.error, terminalError.code);
|
|
412
397
|
}
|
|
413
|
-
throw new ContextError("
|
|
398
|
+
throw new ContextError("Streaming query ended before done event");
|
|
414
399
|
}
|
|
415
400
|
/**
|
|
416
401
|
* Run an agentic query with streaming. Returns an async iterable that
|
|
@@ -420,6 +405,7 @@ var Query = class {
|
|
|
420
405
|
* - `tool-status` — A tool started executing or changed status
|
|
421
406
|
* - `text-delta` — A chunk of the AI response text
|
|
422
407
|
* - `developer-trace` — Runtime trace metadata (when includeDeveloperTrace=true)
|
|
408
|
+
* - `error` — A structured query/runtime error emitted before stream completion
|
|
423
409
|
* - `done` — The full response is complete (includes final `QueryResult`)
|
|
424
410
|
*
|
|
425
411
|
* @param options - Query options or a plain string question
|
|
@@ -441,6 +427,9 @@ var Query = class {
|
|
|
441
427
|
* case "done":
|
|
442
428
|
* console.log("\nCost:", event.result.cost.totalCostUsd);
|
|
443
429
|
* break;
|
|
430
|
+
* case "error":
|
|
431
|
+
* console.error("Stream error:", event.error);
|
|
432
|
+
* break;
|
|
444
433
|
* }
|
|
445
434
|
* }
|
|
446
435
|
* ```
|
|
@@ -459,6 +448,7 @@ var Query = class {
|
|
|
459
448
|
includeDataUrl: opts.includeDataUrl,
|
|
460
449
|
includeDeveloperTrace: opts.includeDeveloperTrace,
|
|
461
450
|
queryDepth: opts.queryDepth,
|
|
451
|
+
debugScoutDeepMode: opts.debugScoutDeepMode,
|
|
462
452
|
stream: true
|
|
463
453
|
})
|
|
464
454
|
});
|
|
@@ -496,10 +486,13 @@ var Query = class {
|
|
|
496
486
|
event.result.developerTrace
|
|
497
487
|
);
|
|
498
488
|
if (!mergedTrace && opts.includeDeveloperTrace) {
|
|
499
|
-
mergedTrace = this.buildSyntheticTraceFromStreamStatus({
|
|
489
|
+
mergedTrace = statusTimeline.length > 0 ? this.buildSyntheticTraceFromStreamStatus({
|
|
500
490
|
statusTimeline,
|
|
501
491
|
toolsUsed: event.result.toolsUsed,
|
|
502
492
|
durationMs: event.result.durationMs
|
|
493
|
+
}) : this.buildSyntheticTraceFromRunResult({
|
|
494
|
+
toolsUsed: event.result.toolsUsed,
|
|
495
|
+
durationMs: event.result.durationMs
|
|
503
496
|
});
|
|
504
497
|
}
|
|
505
498
|
if (mergedTrace) {
|
|
@@ -616,30 +609,34 @@ var ContextClient = class {
|
|
|
616
609
|
*
|
|
617
610
|
* @internal
|
|
618
611
|
*/
|
|
619
|
-
async _fetch(endpoint, options = {}) {
|
|
612
|
+
async _fetch(endpoint, options = {}, fetchOptions) {
|
|
620
613
|
if (this._closed) {
|
|
621
614
|
throw new ContextError("Client has been closed");
|
|
622
615
|
}
|
|
623
616
|
const url = `${this.baseUrl}${endpoint}`;
|
|
624
617
|
const maxRetries = 3;
|
|
625
618
|
const timeoutMs = this.requestTimeoutMs;
|
|
619
|
+
const method = (options.method ?? "GET").toUpperCase();
|
|
620
|
+
const requestHeaders = new Headers(options.headers);
|
|
621
|
+
const canRetryRequest = fetchOptions?.retry === false ? false : method === "GET" || method === "HEAD" || method === "OPTIONS" || requestHeaders.has("Idempotency-Key");
|
|
626
622
|
let lastError;
|
|
627
623
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
628
624
|
const controller = new AbortController();
|
|
629
625
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
626
|
+
const mergedHeaders = new Headers(requestHeaders);
|
|
627
|
+
if (!mergedHeaders.has("Content-Type")) {
|
|
628
|
+
mergedHeaders.set("Content-Type", "application/json");
|
|
629
|
+
}
|
|
630
|
+
mergedHeaders.set("Authorization", `Bearer ${this.apiKey}`);
|
|
630
631
|
try {
|
|
631
632
|
const response = await fetch(url, {
|
|
632
633
|
...options,
|
|
633
634
|
signal: controller.signal,
|
|
634
|
-
headers:
|
|
635
|
-
"Content-Type": "application/json",
|
|
636
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
637
|
-
...options.headers
|
|
638
|
-
}
|
|
635
|
+
headers: mergedHeaders
|
|
639
636
|
});
|
|
640
637
|
clearTimeout(timeout);
|
|
641
638
|
if (!response.ok) {
|
|
642
|
-
if (response.status >= 500 && attempt < maxRetries) {
|
|
639
|
+
if (response.status >= 500 && canRetryRequest && attempt < maxRetries) {
|
|
643
640
|
const delay = Math.min(1e3 * 2 ** attempt, 1e4);
|
|
644
641
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
645
642
|
continue;
|
|
@@ -658,7 +655,16 @@ var ContextClient = class {
|
|
|
658
655
|
}
|
|
659
656
|
throw new ContextError(errorMessage, errorCode, response.status, helpUrl);
|
|
660
657
|
}
|
|
661
|
-
|
|
658
|
+
try {
|
|
659
|
+
return await response.json();
|
|
660
|
+
} catch (error) {
|
|
661
|
+
const parseError = error instanceof Error ? error : new Error(String(error));
|
|
662
|
+
throw new ContextError(
|
|
663
|
+
`Failed to parse JSON response: ${parseError.message}`,
|
|
664
|
+
void 0,
|
|
665
|
+
response.status
|
|
666
|
+
);
|
|
667
|
+
}
|
|
662
668
|
} catch (error) {
|
|
663
669
|
clearTimeout(timeout);
|
|
664
670
|
if (error instanceof ContextError) {
|
|
@@ -666,7 +672,7 @@ var ContextClient = class {
|
|
|
666
672
|
}
|
|
667
673
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
668
674
|
const isRetryable = lastError.name === "AbortError" || lastError.message.includes("fetch failed") || lastError.message.includes("ECONNRESET") || lastError.message.includes("ETIMEDOUT");
|
|
669
|
-
if (isRetryable && attempt < maxRetries) {
|
|
675
|
+
if (isRetryable && canRetryRequest && attempt < maxRetries) {
|
|
670
676
|
const delay = Math.min(1e3 * 2 ** attempt, 1e4);
|
|
671
677
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
672
678
|
continue;
|