@ctxprotocol/sdk 0.8.3 → 0.8.5
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 +26 -3
- package/dist/client/index.cjs +207 -45
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +218 -8
- package/dist/client/index.d.ts +218 -8
- package/dist/client/index.js +207 -45
- package/dist/client/index.js.map +1 -1
- package/dist/index.cjs +207 -45
- 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 +207 -45
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/client/index.d.ts
CHANGED
|
@@ -299,12 +299,14 @@ interface ExecutionResult<T = unknown> {
|
|
|
299
299
|
}
|
|
300
300
|
/** Supported orchestration depth modes for query execution. */
|
|
301
301
|
type QueryDepth = "fast" | "auto" | "deep";
|
|
302
|
+
type QueryDeepMode = "deep-light" | "deep-heavy";
|
|
302
303
|
/**
|
|
303
304
|
* Options for the agentic query endpoint (pay-per-response).
|
|
304
305
|
*
|
|
305
306
|
* Unlike `execute()` which calls a single tool once, `query()` sends a
|
|
306
|
-
* natural-language question and lets the server handle
|
|
307
|
-
*
|
|
307
|
+
* natural-language question and lets the server handle discovery-first
|
|
308
|
+
* orchestration (`discover/probe -> plan-from-evidence -> execute ->
|
|
309
|
+
* bounded fallback`) plus synthesis.
|
|
308
310
|
* One flat fee covers up to 100 MCP skill calls per tool.
|
|
309
311
|
*/
|
|
310
312
|
interface QueryOptions {
|
|
@@ -331,6 +333,12 @@ interface QueryOptions {
|
|
|
331
333
|
* Useful for large payload workflows where inline JSON is not ideal.
|
|
332
334
|
*/
|
|
333
335
|
includeDataUrl?: boolean;
|
|
336
|
+
/**
|
|
337
|
+
* Include machine-readable developer trace output for this query response.
|
|
338
|
+
* When enabled, the server may return summary counters plus diagnostics
|
|
339
|
+
* for lane selection, scout probe adequacy, and bounded fallback behavior.
|
|
340
|
+
*/
|
|
341
|
+
includeDeveloperTrace?: boolean;
|
|
334
342
|
/**
|
|
335
343
|
* Query orchestration depth mode:
|
|
336
344
|
* - `fast`: lower-latency path
|
|
@@ -338,12 +346,168 @@ interface QueryOptions {
|
|
|
338
346
|
* - `deep`: full completeness-oriented path
|
|
339
347
|
*/
|
|
340
348
|
queryDepth?: QueryDepth;
|
|
349
|
+
/**
|
|
350
|
+
* Development/testing only: force the server's internal deep lane.
|
|
351
|
+
* Ignored by normal production usage and invalid when `queryDepth` is `fast`.
|
|
352
|
+
*/
|
|
353
|
+
debugScoutDeepMode?: QueryDeepMode;
|
|
341
354
|
/**
|
|
342
355
|
* Optional idempotency key (UUID recommended).
|
|
343
356
|
* Reuse the same key when retrying the same logical request.
|
|
344
357
|
*/
|
|
345
358
|
idempotencyKey?: string;
|
|
346
359
|
}
|
|
360
|
+
/**
|
|
361
|
+
* Tool reference attached to developer trace timeline steps.
|
|
362
|
+
*/
|
|
363
|
+
interface QueryDeveloperTraceToolRef {
|
|
364
|
+
id?: string;
|
|
365
|
+
name?: string;
|
|
366
|
+
method?: string;
|
|
367
|
+
[key: string]: unknown;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Loop metadata attached to developer trace timeline steps.
|
|
371
|
+
*/
|
|
372
|
+
interface QueryDeveloperTraceLoopInfo {
|
|
373
|
+
name?: string;
|
|
374
|
+
iteration?: number;
|
|
375
|
+
maxIterations?: number;
|
|
376
|
+
[key: string]: unknown;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Tool selection metadata attached to discovery/planning diagnostics.
|
|
380
|
+
*/
|
|
381
|
+
interface QueryDeveloperTraceToolSelection {
|
|
382
|
+
toolId: string;
|
|
383
|
+
toolName: string;
|
|
384
|
+
selectedMethodCount: number;
|
|
385
|
+
selectedMethods: string[];
|
|
386
|
+
omittedSelectedMethodCount: number;
|
|
387
|
+
priceUsd?: string;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Initial planner diagnostic details.
|
|
391
|
+
*/
|
|
392
|
+
interface QueryPlanningTraceDiagnostic {
|
|
393
|
+
plannerQuery: string;
|
|
394
|
+
scoutEvidenceAttached: boolean;
|
|
395
|
+
scoutEvidencePromptBlock: string | null;
|
|
396
|
+
allowedModules: string[];
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Rediscovery/fallback diagnostic details.
|
|
400
|
+
*/
|
|
401
|
+
interface QueryRediscoveryTraceDiagnostic {
|
|
402
|
+
considered: boolean;
|
|
403
|
+
executed: boolean;
|
|
404
|
+
skipReason: string | null;
|
|
405
|
+
missingCapability: string | null;
|
|
406
|
+
rediscoveryQuery: string | null;
|
|
407
|
+
capabilityLooksLikeSearchNeed: boolean;
|
|
408
|
+
allowSearchFallbackOnElapsedCap: boolean;
|
|
409
|
+
searchFallbackUsed: boolean;
|
|
410
|
+
preRediscoveryBudgetReasonCode: string | null;
|
|
411
|
+
candidateSearchResults: QueryDeveloperTraceToolSelection[];
|
|
412
|
+
selectedAlternatives: QueryDeveloperTraceToolSelection[];
|
|
413
|
+
mergedTools: QueryDeveloperTraceToolSelection[];
|
|
414
|
+
usingPaidFallback: boolean;
|
|
415
|
+
branchPlan: QueryPlanningTraceDiagnostic | null;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Rich developer-trace diagnostics for discovery-first orchestration internals.
|
|
419
|
+
*/
|
|
420
|
+
interface QueryDeveloperTraceDiagnostics {
|
|
421
|
+
selection: {
|
|
422
|
+
selectedDepth: string;
|
|
423
|
+
deepMode: string | null;
|
|
424
|
+
debugScoutDeepMode: string | null;
|
|
425
|
+
plannerReasoningStage: string;
|
|
426
|
+
scoutEnabled: boolean;
|
|
427
|
+
preserveFastOneShot: boolean;
|
|
428
|
+
candidateMethodCount: number;
|
|
429
|
+
scoutProbeStatus: string;
|
|
430
|
+
scoutProbeAdequacy: string;
|
|
431
|
+
scoutProbeConfidence: number;
|
|
432
|
+
scoutMetadataConfidence: number;
|
|
433
|
+
scoutProbeShortlistedMethodCount: number;
|
|
434
|
+
scoutProbeMissingCapability: string | null;
|
|
435
|
+
scoutPrePlanProbeCalls: number;
|
|
436
|
+
scoutPrePlanProbeBudgetReasonCode: string | null;
|
|
437
|
+
scoutChangedInitialPlan: boolean;
|
|
438
|
+
scoutChangedPlannerReasoningStage: boolean;
|
|
439
|
+
scoutInitialSelectedDepth: string;
|
|
440
|
+
scoutInitialDeepMode: string | null;
|
|
441
|
+
scoutInitialPlannerReasoningStage: string;
|
|
442
|
+
scoutInitialReasonCode: string;
|
|
443
|
+
scoutFinalReasonCode: string;
|
|
444
|
+
scoutEvidenceAttachedToPlanning: boolean;
|
|
445
|
+
scoutLlmSelectionUsed: boolean;
|
|
446
|
+
scoutLlmSelectionFallback: boolean;
|
|
447
|
+
scoutLlmSelectionLatencyMs: number | null;
|
|
448
|
+
selectedTools: QueryDeveloperTraceToolSelection[];
|
|
449
|
+
};
|
|
450
|
+
planning: {
|
|
451
|
+
initial: QueryPlanningTraceDiagnostic;
|
|
452
|
+
};
|
|
453
|
+
cost?: {
|
|
454
|
+
planningCostUsd: number;
|
|
455
|
+
initialExecutionCostUsd: number;
|
|
456
|
+
rediscoveryAdditionalCostUsd: number;
|
|
457
|
+
synthesisCostUsd: number;
|
|
458
|
+
totalModelCostUsd: number;
|
|
459
|
+
toolCostUsd: number;
|
|
460
|
+
totalChargedUsd: number;
|
|
461
|
+
};
|
|
462
|
+
completeness: {
|
|
463
|
+
evaluations: unknown[];
|
|
464
|
+
triggerNeedsDifferentTools: boolean;
|
|
465
|
+
triggerMissingCapability: string | null;
|
|
466
|
+
};
|
|
467
|
+
rediscovery: QueryRediscoveryTraceDiagnostic | null;
|
|
468
|
+
[key: string]: unknown;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* A single developer-trace timeline step.
|
|
472
|
+
*/
|
|
473
|
+
interface QueryDeveloperTraceStep {
|
|
474
|
+
stepType?: string;
|
|
475
|
+
event?: string;
|
|
476
|
+
status?: string;
|
|
477
|
+
message?: string;
|
|
478
|
+
timestampMs?: number;
|
|
479
|
+
tool?: QueryDeveloperTraceToolRef;
|
|
480
|
+
attempt?: number;
|
|
481
|
+
loop?: QueryDeveloperTraceLoopInfo;
|
|
482
|
+
metadata?: Record<string, unknown>;
|
|
483
|
+
[key: string]: unknown;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Aggregate counters that summarize developer-trace behavior.
|
|
487
|
+
*/
|
|
488
|
+
interface QueryDeveloperTraceSummary {
|
|
489
|
+
toolCalls?: number;
|
|
490
|
+
retryCount?: number;
|
|
491
|
+
selfHealCount?: number;
|
|
492
|
+
fallbackCount?: number;
|
|
493
|
+
failureCount?: number;
|
|
494
|
+
recoveryCount?: number;
|
|
495
|
+
completionChecks?: number;
|
|
496
|
+
loopCount?: number;
|
|
497
|
+
[key: string]: unknown;
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Developer Mode trace payload returned per query response (opt-in).
|
|
501
|
+
*/
|
|
502
|
+
interface QueryDeveloperTrace {
|
|
503
|
+
summary?: QueryDeveloperTraceSummary;
|
|
504
|
+
timeline?: QueryDeveloperTraceStep[];
|
|
505
|
+
requestId?: string;
|
|
506
|
+
query?: string;
|
|
507
|
+
source?: string;
|
|
508
|
+
diagnostics?: QueryDeveloperTraceDiagnostics;
|
|
509
|
+
[key: string]: unknown;
|
|
510
|
+
}
|
|
347
511
|
/**
|
|
348
512
|
* Information about a tool that was used during a query response
|
|
349
513
|
*/
|
|
@@ -367,6 +531,19 @@ interface QueryCost {
|
|
|
367
531
|
/** Total cost (model + tools) */
|
|
368
532
|
totalCostUsd: string;
|
|
369
533
|
}
|
|
534
|
+
/**
|
|
535
|
+
* High-level orchestration outcome metrics returned by the query API.
|
|
536
|
+
*/
|
|
537
|
+
interface QueryOrchestrationMetrics {
|
|
538
|
+
parityStage: string;
|
|
539
|
+
orchestrationMode: string;
|
|
540
|
+
/** Whether the first plan path succeeded without fallback. */
|
|
541
|
+
firstPassSuccess: boolean;
|
|
542
|
+
/** Whether execution signaled a missing capability on first pass. */
|
|
543
|
+
capabilityMissSignaled: boolean;
|
|
544
|
+
/** Whether bounded rediscovery/fallback executed. */
|
|
545
|
+
rediscoveryExecuted: boolean;
|
|
546
|
+
}
|
|
370
547
|
/**
|
|
371
548
|
* The resolved result of a pay-per-response query
|
|
372
549
|
*/
|
|
@@ -383,6 +560,10 @@ interface QueryResult {
|
|
|
383
560
|
data?: unknown;
|
|
384
561
|
/** Optional blob URL for persisted execution data (when includeDataUrl=true) */
|
|
385
562
|
dataUrl?: string;
|
|
563
|
+
/** Optional machine-readable Developer Mode trace payload */
|
|
564
|
+
developerTrace?: QueryDeveloperTrace;
|
|
565
|
+
/** Optional orchestration outcome metrics for benchmarking and rollout analysis */
|
|
566
|
+
orchestrationMetrics?: QueryOrchestrationMetrics;
|
|
386
567
|
}
|
|
387
568
|
/**
|
|
388
569
|
* Successful response from the /api/v1/query endpoint
|
|
@@ -395,6 +576,8 @@ interface QueryApiSuccessResponse {
|
|
|
395
576
|
durationMs: number;
|
|
396
577
|
data?: unknown;
|
|
397
578
|
dataUrl?: string;
|
|
579
|
+
developerTrace?: QueryDeveloperTrace;
|
|
580
|
+
orchestrationMetrics?: QueryOrchestrationMetrics;
|
|
398
581
|
}
|
|
399
582
|
/**
|
|
400
583
|
* Raw API response from the query endpoint
|
|
@@ -414,15 +597,28 @@ interface QueryStreamTextDeltaEvent {
|
|
|
414
597
|
type: "text-delta";
|
|
415
598
|
delta: string;
|
|
416
599
|
}
|
|
600
|
+
/** Emitted when the server streams developer trace updates/chunks */
|
|
601
|
+
interface QueryStreamDeveloperTraceEvent {
|
|
602
|
+
type: "developer-trace";
|
|
603
|
+
trace: QueryDeveloperTrace;
|
|
604
|
+
}
|
|
417
605
|
/** Emitted when the full response is complete */
|
|
418
606
|
interface QueryStreamDoneEvent {
|
|
419
607
|
type: "done";
|
|
420
608
|
result: QueryResult;
|
|
421
609
|
}
|
|
610
|
+
/** Emitted when the server reports a recoverable or terminal query error */
|
|
611
|
+
interface QueryStreamErrorEvent {
|
|
612
|
+
type: "error";
|
|
613
|
+
error: string;
|
|
614
|
+
code?: ContextErrorCode | string;
|
|
615
|
+
scope?: string;
|
|
616
|
+
reasonCode?: string;
|
|
617
|
+
}
|
|
422
618
|
/**
|
|
423
619
|
* Union of all events emitted during a streaming query
|
|
424
620
|
*/
|
|
425
|
-
type QueryStreamEvent = QueryStreamToolStatusEvent | QueryStreamTextDeltaEvent | QueryStreamDoneEvent;
|
|
621
|
+
type QueryStreamEvent = QueryStreamToolStatusEvent | QueryStreamTextDeltaEvent | QueryStreamDeveloperTraceEvent | QueryStreamDoneEvent | QueryStreamErrorEvent;
|
|
426
622
|
/**
|
|
427
623
|
* Specific error codes returned by the Context Protocol API
|
|
428
624
|
*/
|
|
@@ -524,8 +720,8 @@ declare class Tools {
|
|
|
524
720
|
*
|
|
525
721
|
* Unlike `tools.execute()` which calls a single tool once (pay-per-request),
|
|
526
722
|
* the Query resource sends a natural-language question and lets the server
|
|
527
|
-
* handle
|
|
528
|
-
*
|
|
723
|
+
* handle discovery-first orchestration (`discover/probe -> plan-from-evidence ->
|
|
724
|
+
* execute -> bounded fallback`) plus AI synthesis — all for one flat fee.
|
|
529
725
|
*
|
|
530
726
|
* This is the "prepared meal" vs "raw ingredients" distinction:
|
|
531
727
|
* - `tools.execute()` = raw data, full control, predictable cost
|
|
@@ -534,11 +730,15 @@ declare class Tools {
|
|
|
534
730
|
declare class Query {
|
|
535
731
|
private client;
|
|
536
732
|
constructor(client: ContextClient);
|
|
733
|
+
private buildSyntheticTraceFromRunResult;
|
|
734
|
+
private buildSyntheticTraceFromStreamStatus;
|
|
735
|
+
private mergeDeveloperTrace;
|
|
736
|
+
private parseStreamEvent;
|
|
537
737
|
/**
|
|
538
738
|
* Run an agentic query and wait for the full response.
|
|
539
739
|
*
|
|
540
740
|
* The server discovers relevant tools (or uses the ones you specify),
|
|
541
|
-
* executes the
|
|
741
|
+
* executes the discovery-first pipeline (up to 100 MCP calls per tool),
|
|
542
742
|
* and returns an AI-synthesized answer. Payment is settled after
|
|
543
743
|
* successful execution via deferred settlement.
|
|
544
744
|
*
|
|
@@ -573,6 +773,8 @@ declare class Query {
|
|
|
573
773
|
* Event types:
|
|
574
774
|
* - `tool-status` — A tool started executing or changed status
|
|
575
775
|
* - `text-delta` — A chunk of the AI response text
|
|
776
|
+
* - `developer-trace` — Runtime trace metadata (when includeDeveloperTrace=true)
|
|
777
|
+
* - `error` — A structured query/runtime error emitted before stream completion
|
|
576
778
|
* - `done` — The full response is complete (includes final `QueryResult`)
|
|
577
779
|
*
|
|
578
780
|
* @param options - Query options or a plain string question
|
|
@@ -588,9 +790,15 @@ declare class Query {
|
|
|
588
790
|
* case "text-delta":
|
|
589
791
|
* process.stdout.write(event.delta);
|
|
590
792
|
* break;
|
|
793
|
+
* case "developer-trace":
|
|
794
|
+
* console.log("Trace summary:", event.trace.summary);
|
|
795
|
+
* break;
|
|
591
796
|
* case "done":
|
|
592
797
|
* console.log("\nCost:", event.result.cost.totalCostUsd);
|
|
593
798
|
* break;
|
|
799
|
+
* case "error":
|
|
800
|
+
* console.error("Stream error:", event.error);
|
|
801
|
+
* break;
|
|
594
802
|
* }
|
|
595
803
|
* }
|
|
596
804
|
* ```
|
|
@@ -666,7 +874,9 @@ declare class ContextClient {
|
|
|
666
874
|
*
|
|
667
875
|
* @internal
|
|
668
876
|
*/
|
|
669
|
-
_fetch<T>(endpoint: string, options?: RequestInit
|
|
877
|
+
_fetch<T>(endpoint: string, options?: RequestInit, fetchOptions?: {
|
|
878
|
+
retry?: boolean;
|
|
879
|
+
}): Promise<T>;
|
|
670
880
|
/**
|
|
671
881
|
* Internal method for making authenticated HTTP requests that returns
|
|
672
882
|
* the raw Response object. Used for streaming endpoints (SSE).
|
|
@@ -677,4 +887,4 @@ declare class ContextClient {
|
|
|
677
887
|
_fetchRaw(endpoint: string, options?: RequestInit): Promise<Response>;
|
|
678
888
|
}
|
|
679
889
|
|
|
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 };
|
|
890
|
+
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 QueryDeepMode, type QueryDeveloperTrace, type QueryDeveloperTraceLoopInfo, type QueryDeveloperTraceStep, type QueryDeveloperTraceSummary, type QueryDeveloperTraceToolRef, type QueryOptions, type QueryResult, type QueryStreamDeveloperTraceEvent, type QueryStreamDoneEvent, type QueryStreamErrorEvent, type QueryStreamEvent, type QueryStreamTextDeltaEvent, type QueryStreamToolStatusEvent, type QueryToolUsage, type SearchOptions, type SearchResponse, type Tool, Tools };
|
package/dist/client/index.js
CHANGED
|
@@ -226,11 +226,119 @@ var Query = class {
|
|
|
226
226
|
constructor(client) {
|
|
227
227
|
this.client = client;
|
|
228
228
|
}
|
|
229
|
+
buildSyntheticTraceFromRunResult(params) {
|
|
230
|
+
const timeline = params.toolsUsed.map((tool, index) => ({
|
|
231
|
+
stepType: "tool-call",
|
|
232
|
+
event: "tool-call",
|
|
233
|
+
status: "success",
|
|
234
|
+
timestampMs: index,
|
|
235
|
+
tool: {
|
|
236
|
+
id: tool.id,
|
|
237
|
+
name: tool.name
|
|
238
|
+
},
|
|
239
|
+
metadata: {
|
|
240
|
+
skillCalls: tool.skillCalls,
|
|
241
|
+
synthetic: true
|
|
242
|
+
}
|
|
243
|
+
}));
|
|
244
|
+
const toolCalls = params.toolsUsed.reduce(
|
|
245
|
+
(sum, tool) => sum + Math.max(tool.skillCalls, 0),
|
|
246
|
+
0
|
|
247
|
+
);
|
|
248
|
+
return {
|
|
249
|
+
summary: {
|
|
250
|
+
toolCalls,
|
|
251
|
+
retryCount: 0,
|
|
252
|
+
selfHealCount: 0,
|
|
253
|
+
fallbackCount: 0,
|
|
254
|
+
failureCount: 0,
|
|
255
|
+
recoveryCount: 0,
|
|
256
|
+
completionChecks: 0,
|
|
257
|
+
loopCount: 0
|
|
258
|
+
},
|
|
259
|
+
timeline,
|
|
260
|
+
source: "sdk-fallback",
|
|
261
|
+
synthetic: true,
|
|
262
|
+
reason: "backend_trace_missing",
|
|
263
|
+
durationMs: params.durationMs
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
buildSyntheticTraceFromStreamStatus(params) {
|
|
267
|
+
const timeline = params.statusTimeline.map((entry, index) => ({
|
|
268
|
+
stepType: "tool-status",
|
|
269
|
+
event: "tool-status",
|
|
270
|
+
status: entry.status,
|
|
271
|
+
timestampMs: index,
|
|
272
|
+
tool: entry.tool.name || entry.tool.id ? {
|
|
273
|
+
id: entry.tool.id || void 0,
|
|
274
|
+
name: entry.tool.name || void 0
|
|
275
|
+
} : void 0,
|
|
276
|
+
metadata: { synthetic: true }
|
|
277
|
+
}));
|
|
278
|
+
const toolCallsFromUsage = params.toolsUsed.reduce(
|
|
279
|
+
(sum, tool) => sum + Math.max(tool.skillCalls, 0),
|
|
280
|
+
0
|
|
281
|
+
);
|
|
282
|
+
const toolCallsFromStatus = params.statusTimeline.filter(
|
|
283
|
+
(entry) => entry.status === "tool-complete"
|
|
284
|
+
).length;
|
|
285
|
+
const toolCalls = toolCallsFromUsage > 0 ? toolCallsFromUsage : toolCallsFromStatus;
|
|
286
|
+
const retryCount = params.statusTimeline.filter(
|
|
287
|
+
(entry) => /(retry|fix|reflect|recover)/i.test(entry.status)
|
|
288
|
+
).length;
|
|
289
|
+
const completionChecks = params.statusTimeline.filter(
|
|
290
|
+
(entry) => /complet/i.test(entry.status)
|
|
291
|
+
).length;
|
|
292
|
+
return {
|
|
293
|
+
summary: {
|
|
294
|
+
toolCalls,
|
|
295
|
+
retryCount,
|
|
296
|
+
selfHealCount: retryCount,
|
|
297
|
+
fallbackCount: 0,
|
|
298
|
+
failureCount: 0,
|
|
299
|
+
recoveryCount: 0,
|
|
300
|
+
completionChecks,
|
|
301
|
+
loopCount: retryCount
|
|
302
|
+
},
|
|
303
|
+
timeline,
|
|
304
|
+
source: "sdk-fallback",
|
|
305
|
+
synthetic: true,
|
|
306
|
+
reason: "backend_trace_missing",
|
|
307
|
+
durationMs: params.durationMs
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
mergeDeveloperTrace(first, second) {
|
|
311
|
+
if (!first) return second;
|
|
312
|
+
if (!second) return first;
|
|
313
|
+
const firstTimeline = Array.isArray(first.timeline) ? first.timeline : [];
|
|
314
|
+
const secondTimeline = Array.isArray(second.timeline) ? second.timeline : [];
|
|
315
|
+
const mergedTimeline = [...firstTimeline, ...secondTimeline];
|
|
316
|
+
return {
|
|
317
|
+
...first,
|
|
318
|
+
...second,
|
|
319
|
+
summary: {
|
|
320
|
+
...typeof first.summary === "object" && first.summary ? first.summary : {},
|
|
321
|
+
...typeof second.summary === "object" && second.summary ? second.summary : {}
|
|
322
|
+
},
|
|
323
|
+
...mergedTimeline.length > 0 ? { timeline: mergedTimeline } : {}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
parseStreamEvent(rawData) {
|
|
327
|
+
const parsed = JSON.parse(rawData);
|
|
328
|
+
if (!parsed || typeof parsed !== "object") {
|
|
329
|
+
return void 0;
|
|
330
|
+
}
|
|
331
|
+
const event = parsed;
|
|
332
|
+
if (typeof event.type !== "string") {
|
|
333
|
+
return void 0;
|
|
334
|
+
}
|
|
335
|
+
return event;
|
|
336
|
+
}
|
|
229
337
|
/**
|
|
230
338
|
* Run an agentic query and wait for the full response.
|
|
231
339
|
*
|
|
232
340
|
* The server discovers relevant tools (or uses the ones you specify),
|
|
233
|
-
* executes the
|
|
341
|
+
* executes the discovery-first pipeline (up to 100 MCP calls per tool),
|
|
234
342
|
* and returns an AI-synthesized answer. Payment is settled after
|
|
235
343
|
* successful execution via deferred settlement.
|
|
236
344
|
*
|
|
@@ -259,42 +367,25 @@ var Query = class {
|
|
|
259
367
|
*/
|
|
260
368
|
async run(options) {
|
|
261
369
|
const opts = typeof options === "string" ? { query: options } : options;
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
"
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
stream: false
|
|
276
|
-
})
|
|
370
|
+
let terminalError;
|
|
371
|
+
for await (const event of this.stream(opts)) {
|
|
372
|
+
if (event.type === "error") {
|
|
373
|
+
terminalError = {
|
|
374
|
+
error: event.error,
|
|
375
|
+
...event.code ? { code: event.code } : {},
|
|
376
|
+
...event.scope ? { scope: event.scope } : {},
|
|
377
|
+
...event.reasonCode ? { reasonCode: event.reasonCode } : {}
|
|
378
|
+
};
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
if (event.type === "done") {
|
|
382
|
+
return event.result;
|
|
277
383
|
}
|
|
278
|
-
);
|
|
279
|
-
if ("error" in response) {
|
|
280
|
-
throw new ContextError(
|
|
281
|
-
response.error,
|
|
282
|
-
response.code,
|
|
283
|
-
void 0,
|
|
284
|
-
response.helpUrl
|
|
285
|
-
);
|
|
286
384
|
}
|
|
287
|
-
if (
|
|
288
|
-
|
|
289
|
-
response: response.response,
|
|
290
|
-
toolsUsed: response.toolsUsed,
|
|
291
|
-
cost: response.cost,
|
|
292
|
-
durationMs: response.durationMs,
|
|
293
|
-
data: response.data,
|
|
294
|
-
dataUrl: response.dataUrl
|
|
295
|
-
};
|
|
385
|
+
if (terminalError) {
|
|
386
|
+
throw new ContextError(terminalError.error, terminalError.code);
|
|
296
387
|
}
|
|
297
|
-
throw new ContextError("
|
|
388
|
+
throw new ContextError("Streaming query ended before done event");
|
|
298
389
|
}
|
|
299
390
|
/**
|
|
300
391
|
* Run an agentic query with streaming. Returns an async iterable that
|
|
@@ -303,6 +394,8 @@ var Query = class {
|
|
|
303
394
|
* Event types:
|
|
304
395
|
* - `tool-status` — A tool started executing or changed status
|
|
305
396
|
* - `text-delta` — A chunk of the AI response text
|
|
397
|
+
* - `developer-trace` — Runtime trace metadata (when includeDeveloperTrace=true)
|
|
398
|
+
* - `error` — A structured query/runtime error emitted before stream completion
|
|
306
399
|
* - `done` — The full response is complete (includes final `QueryResult`)
|
|
307
400
|
*
|
|
308
401
|
* @param options - Query options or a plain string question
|
|
@@ -318,9 +411,15 @@ var Query = class {
|
|
|
318
411
|
* case "text-delta":
|
|
319
412
|
* process.stdout.write(event.delta);
|
|
320
413
|
* break;
|
|
414
|
+
* case "developer-trace":
|
|
415
|
+
* console.log("Trace summary:", event.trace.summary);
|
|
416
|
+
* break;
|
|
321
417
|
* case "done":
|
|
322
418
|
* console.log("\nCost:", event.result.cost.totalCostUsd);
|
|
323
419
|
* break;
|
|
420
|
+
* case "error":
|
|
421
|
+
* console.error("Stream error:", event.error);
|
|
422
|
+
* break;
|
|
324
423
|
* }
|
|
325
424
|
* }
|
|
326
425
|
* ```
|
|
@@ -337,7 +436,9 @@ var Query = class {
|
|
|
337
436
|
modelId: opts.modelId,
|
|
338
437
|
includeData: opts.includeData,
|
|
339
438
|
includeDataUrl: opts.includeDataUrl,
|
|
439
|
+
includeDeveloperTrace: opts.includeDeveloperTrace,
|
|
340
440
|
queryDepth: opts.queryDepth,
|
|
441
|
+
debugScoutDeepMode: opts.debugScoutDeepMode,
|
|
341
442
|
stream: true
|
|
342
443
|
})
|
|
343
444
|
});
|
|
@@ -348,6 +449,48 @@ var Query = class {
|
|
|
348
449
|
const reader = body.getReader();
|
|
349
450
|
const decoder = new TextDecoder();
|
|
350
451
|
let buffer = "";
|
|
452
|
+
let aggregatedTrace;
|
|
453
|
+
const statusTimeline = [];
|
|
454
|
+
const parseAndHydrateEvent = (rawData) => {
|
|
455
|
+
const event = this.parseStreamEvent(rawData);
|
|
456
|
+
if (!event) {
|
|
457
|
+
return void 0;
|
|
458
|
+
}
|
|
459
|
+
if (event.type === "developer-trace") {
|
|
460
|
+
aggregatedTrace = this.mergeDeveloperTrace(aggregatedTrace, event.trace);
|
|
461
|
+
return event;
|
|
462
|
+
}
|
|
463
|
+
if (event.type === "tool-status") {
|
|
464
|
+
statusTimeline.push({
|
|
465
|
+
status: event.status,
|
|
466
|
+
tool: {
|
|
467
|
+
id: event.tool.id,
|
|
468
|
+
name: event.tool.name
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
return event;
|
|
472
|
+
}
|
|
473
|
+
if (event.type === "done") {
|
|
474
|
+
let mergedTrace = this.mergeDeveloperTrace(
|
|
475
|
+
aggregatedTrace,
|
|
476
|
+
event.result.developerTrace
|
|
477
|
+
);
|
|
478
|
+
if (!mergedTrace && opts.includeDeveloperTrace) {
|
|
479
|
+
mergedTrace = statusTimeline.length > 0 ? this.buildSyntheticTraceFromStreamStatus({
|
|
480
|
+
statusTimeline,
|
|
481
|
+
toolsUsed: event.result.toolsUsed,
|
|
482
|
+
durationMs: event.result.durationMs
|
|
483
|
+
}) : this.buildSyntheticTraceFromRunResult({
|
|
484
|
+
toolsUsed: event.result.toolsUsed,
|
|
485
|
+
durationMs: event.result.durationMs
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
if (mergedTrace) {
|
|
489
|
+
event.result.developerTrace = mergedTrace;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return event;
|
|
493
|
+
};
|
|
351
494
|
try {
|
|
352
495
|
while (true) {
|
|
353
496
|
const { done, value } = await reader.read();
|
|
@@ -361,7 +504,10 @@ var Query = class {
|
|
|
361
504
|
const data = trimmed.slice(6);
|
|
362
505
|
if (data === "[DONE]") return;
|
|
363
506
|
try {
|
|
364
|
-
|
|
507
|
+
const event = parseAndHydrateEvent(data);
|
|
508
|
+
if (event) {
|
|
509
|
+
yield event;
|
|
510
|
+
}
|
|
365
511
|
} catch {
|
|
366
512
|
}
|
|
367
513
|
}
|
|
@@ -371,7 +517,10 @@ var Query = class {
|
|
|
371
517
|
const data = buffer.trim().slice(6);
|
|
372
518
|
if (data !== "[DONE]") {
|
|
373
519
|
try {
|
|
374
|
-
|
|
520
|
+
const event = parseAndHydrateEvent(data);
|
|
521
|
+
if (event) {
|
|
522
|
+
yield event;
|
|
523
|
+
}
|
|
375
524
|
} catch {
|
|
376
525
|
}
|
|
377
526
|
}
|
|
@@ -450,30 +599,34 @@ var ContextClient = class {
|
|
|
450
599
|
*
|
|
451
600
|
* @internal
|
|
452
601
|
*/
|
|
453
|
-
async _fetch(endpoint, options = {}) {
|
|
602
|
+
async _fetch(endpoint, options = {}, fetchOptions) {
|
|
454
603
|
if (this._closed) {
|
|
455
604
|
throw new ContextError("Client has been closed");
|
|
456
605
|
}
|
|
457
606
|
const url = `${this.baseUrl}${endpoint}`;
|
|
458
607
|
const maxRetries = 3;
|
|
459
608
|
const timeoutMs = this.requestTimeoutMs;
|
|
609
|
+
const method = (options.method ?? "GET").toUpperCase();
|
|
610
|
+
const requestHeaders = new Headers(options.headers);
|
|
611
|
+
const canRetryRequest = fetchOptions?.retry === false ? false : method === "GET" || method === "HEAD" || method === "OPTIONS" || requestHeaders.has("Idempotency-Key");
|
|
460
612
|
let lastError;
|
|
461
613
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
462
614
|
const controller = new AbortController();
|
|
463
615
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
616
|
+
const mergedHeaders = new Headers(requestHeaders);
|
|
617
|
+
if (!mergedHeaders.has("Content-Type")) {
|
|
618
|
+
mergedHeaders.set("Content-Type", "application/json");
|
|
619
|
+
}
|
|
620
|
+
mergedHeaders.set("Authorization", `Bearer ${this.apiKey}`);
|
|
464
621
|
try {
|
|
465
622
|
const response = await fetch(url, {
|
|
466
623
|
...options,
|
|
467
624
|
signal: controller.signal,
|
|
468
|
-
headers:
|
|
469
|
-
"Content-Type": "application/json",
|
|
470
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
471
|
-
...options.headers
|
|
472
|
-
}
|
|
625
|
+
headers: mergedHeaders
|
|
473
626
|
});
|
|
474
627
|
clearTimeout(timeout);
|
|
475
628
|
if (!response.ok) {
|
|
476
|
-
if (response.status >= 500 && attempt < maxRetries) {
|
|
629
|
+
if (response.status >= 500 && canRetryRequest && attempt < maxRetries) {
|
|
477
630
|
const delay = Math.min(1e3 * 2 ** attempt, 1e4);
|
|
478
631
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
479
632
|
continue;
|
|
@@ -492,7 +645,16 @@ var ContextClient = class {
|
|
|
492
645
|
}
|
|
493
646
|
throw new ContextError(errorMessage, errorCode, response.status, helpUrl);
|
|
494
647
|
}
|
|
495
|
-
|
|
648
|
+
try {
|
|
649
|
+
return await response.json();
|
|
650
|
+
} catch (error) {
|
|
651
|
+
const parseError = error instanceof Error ? error : new Error(String(error));
|
|
652
|
+
throw new ContextError(
|
|
653
|
+
`Failed to parse JSON response: ${parseError.message}`,
|
|
654
|
+
void 0,
|
|
655
|
+
response.status
|
|
656
|
+
);
|
|
657
|
+
}
|
|
496
658
|
} catch (error) {
|
|
497
659
|
clearTimeout(timeout);
|
|
498
660
|
if (error instanceof ContextError) {
|
|
@@ -500,7 +662,7 @@ var ContextClient = class {
|
|
|
500
662
|
}
|
|
501
663
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
502
664
|
const isRetryable = lastError.name === "AbortError" || lastError.message.includes("fetch failed") || lastError.message.includes("ECONNRESET") || lastError.message.includes("ETIMEDOUT");
|
|
503
|
-
if (isRetryable && attempt < maxRetries) {
|
|
665
|
+
if (isRetryable && canRetryRequest && attempt < maxRetries) {
|
|
504
666
|
const delay = Math.min(1e3 * 2 ** attempt, 1e4);
|
|
505
667
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
506
668
|
continue;
|