@juspay/neurolink 12.12.7 → 12.12.9
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/CHANGELOG.md +2 -2
- package/dist/browser/neurolink.min.js +371 -371
- package/dist/core/toolExecutionRecorder.d.ts +16 -1
- package/dist/core/toolExecutionRecorder.js +21 -0
- package/dist/middleware/builtin/guardrails.js +67 -17
- package/dist/neurolink.js +6 -0
- package/dist/providers/amazonSagemaker.js +2 -1
- package/dist/providers/anthropic/client.js +2 -1
- package/dist/providers/openaiChatCompletionsBase.js +2 -1
- package/dist/types/generate.d.ts +6 -0
- package/dist/types/middleware.d.ts +1 -1
- package/dist/utils/schemaConversion.d.ts +9 -0
- package/dist/utils/schemaConversion.js +12 -1
- package/package.json +3 -1
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* params, timing, and error status. Memory is bounded: serialized results are
|
|
10
10
|
* capped at `maxResultChars` and the record list at `maxRecords`.
|
|
11
11
|
*/
|
|
12
|
-
import type { Tool, ToolExecutionCaptureOptions, ToolExecutionRecord } from "../types/index.js";
|
|
12
|
+
import type { Tool, ToolExecutionCaptureOptions, ToolExecutionRecord, StandardRecord, ToolExecutionSummaryInternal } from "../types/index.js";
|
|
13
13
|
/** Default cap on serialized result characters kept per record (~8KB). */
|
|
14
14
|
export declare const DEFAULT_TOOL_RESULT_CAPTURE_CHARS = 8192;
|
|
15
15
|
/** Default cap on records kept per turn. */
|
|
@@ -73,4 +73,19 @@ export declare function toToolExecutionRecords(legacyExecutions: unknown[] | und
|
|
|
73
73
|
* carried a recorder that saw executions, else a conversion of the loop's
|
|
74
74
|
* legacy accumulator entries.
|
|
75
75
|
*/
|
|
76
|
+
/**
|
|
77
|
+
* The public `toolCalls` view of a native turn's execution summaries.
|
|
78
|
+
*
|
|
79
|
+
* The native generate loops record every executed call in
|
|
80
|
+
* `ToolExecutionSummaryInternal[]` and surface it as `toolExecutions`, but
|
|
81
|
+
* never mapped it onto `EnhancedGenerateResult.toolCalls` — the field the type
|
|
82
|
+
* has always declared and the ai-package formatter used to fill. A caller
|
|
83
|
+
* reading `result.toolCalls` after a tool ran saw nothing. This is the one
|
|
84
|
+
* place that mapping lives, so the three native paths cannot drift apart.
|
|
85
|
+
*/
|
|
86
|
+
export declare function toolCallsFromSummaries(summaries: ReadonlyArray<ToolExecutionSummaryInternal>): Array<{
|
|
87
|
+
toolCallId: string;
|
|
88
|
+
toolName: string;
|
|
89
|
+
args: StandardRecord;
|
|
90
|
+
}>;
|
|
76
91
|
export declare function resolveToolExecutionRecords(options: unknown, legacyExecutions?: unknown[]): ToolExecutionRecord[];
|
|
@@ -247,6 +247,27 @@ export function toToolExecutionRecords(legacyExecutions, capture) {
|
|
|
247
247
|
* carried a recorder that saw executions, else a conversion of the loop's
|
|
248
248
|
* legacy accumulator entries.
|
|
249
249
|
*/
|
|
250
|
+
/**
|
|
251
|
+
* The public `toolCalls` view of a native turn's execution summaries.
|
|
252
|
+
*
|
|
253
|
+
* The native generate loops record every executed call in
|
|
254
|
+
* `ToolExecutionSummaryInternal[]` and surface it as `toolExecutions`, but
|
|
255
|
+
* never mapped it onto `EnhancedGenerateResult.toolCalls` — the field the type
|
|
256
|
+
* has always declared and the ai-package formatter used to fill. A caller
|
|
257
|
+
* reading `result.toolCalls` after a tool ran saw nothing. This is the one
|
|
258
|
+
* place that mapping lives, so the three native paths cannot drift apart.
|
|
259
|
+
*/
|
|
260
|
+
export function toolCallsFromSummaries(summaries) {
|
|
261
|
+
return summaries.map((summary) => ({
|
|
262
|
+
toolCallId: summary.toolCallId,
|
|
263
|
+
toolName: summary.toolName,
|
|
264
|
+
args: summary.input !== null &&
|
|
265
|
+
typeof summary.input === "object" &&
|
|
266
|
+
!Array.isArray(summary.input)
|
|
267
|
+
? summary.input
|
|
268
|
+
: {},
|
|
269
|
+
}));
|
|
270
|
+
}
|
|
250
271
|
export function resolveToolExecutionRecords(options, legacyExecutions) {
|
|
251
272
|
const recorder = ToolExecutionRecorder.from(options);
|
|
252
273
|
if (recorder?.hasRecords()) {
|
|
@@ -1,6 +1,45 @@
|
|
|
1
1
|
import { createBlockedResponse, createBlockedStream, applyContentFiltering, handlePrecallGuardrails, } from "../utils/guardrailsUtils.js";
|
|
2
2
|
import { logger } from "../../utils/logger.js";
|
|
3
3
|
import { generateOnceNative } from "../../utils/nativeSingleShot.js";
|
|
4
|
+
/**
|
|
5
|
+
* Filter each contiguous run of text parts as one string.
|
|
6
|
+
*
|
|
7
|
+
* A prohibited term that straddles two adjacent text parts is invisible to a
|
|
8
|
+
* per-part filter, and the parts are concatenated downstream (`lifecycle.ts`
|
|
9
|
+
* joins adjacent text), so the term reached the caller whole. Anthropic's
|
|
10
|
+
* native path emits one text part per content block, so adjacent parts are a
|
|
11
|
+
* real shape, not a theoretical one. Non-text parts keep their position; a run
|
|
12
|
+
* is rebuilt as a single text part only when the filter changed it.
|
|
13
|
+
*/
|
|
14
|
+
const filterTextRuns = (content, badWords, context) => {
|
|
15
|
+
const out = [];
|
|
16
|
+
let run = [];
|
|
17
|
+
const flushRun = () => {
|
|
18
|
+
if (run.length === 0) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const merged = run.map((part) => part.text).join("");
|
|
22
|
+
const filtered = applyContentFiltering(merged, badWords, context);
|
|
23
|
+
if (filtered.hasChanges) {
|
|
24
|
+
out.push({ ...run[0], text: filtered.filteredText });
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
out.push(...run);
|
|
28
|
+
}
|
|
29
|
+
run = [];
|
|
30
|
+
};
|
|
31
|
+
for (const part of content) {
|
|
32
|
+
if (part.type === "text") {
|
|
33
|
+
run.push(part);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
flushRun();
|
|
37
|
+
out.push(part);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
flushRun();
|
|
41
|
+
return out;
|
|
42
|
+
};
|
|
4
43
|
/**
|
|
5
44
|
* Create Guardrails AI middleware for content filtering and policy enforcement
|
|
6
45
|
* @param config Configuration for the guardrails middleware
|
|
@@ -61,12 +100,7 @@ export function createGuardrailsMiddleware(config = {}) {
|
|
|
61
100
|
let result = await doGenerate();
|
|
62
101
|
result = {
|
|
63
102
|
...result,
|
|
64
|
-
content: result.content
|
|
65
|
-
? {
|
|
66
|
-
...part,
|
|
67
|
-
text: applyContentFiltering(part.text, config.badWords, "generate").filteredText,
|
|
68
|
-
}
|
|
69
|
-
: part),
|
|
103
|
+
content: filterTextRuns(result.content, config.badWords, "generate"),
|
|
70
104
|
};
|
|
71
105
|
if (config.modelFilter?.enabled && config.modelFilter.filterModel) {
|
|
72
106
|
logger.debug(`[GuardrailsMiddleware] Invoking model-based filter.`);
|
|
@@ -113,22 +147,38 @@ export function createGuardrailsMiddleware(config = {}) {
|
|
|
113
147
|
}
|
|
114
148
|
const { stream, ...rest } = await doStream();
|
|
115
149
|
let hasYieldedChunks = false;
|
|
150
|
+
// With bad-word filtering on, a text run is buffered and filtered as one
|
|
151
|
+
// string: a term split across deltas is invisible per delta and every
|
|
152
|
+
// consumer reassembles it. The run is released when a non-text part
|
|
153
|
+
// arrives or the stream ends, so the guardrail trades incremental
|
|
154
|
+
// delivery of that run for not being bypassable by chunking. With
|
|
155
|
+
// filtering off, deltas pass through untouched and unbuffered.
|
|
156
|
+
const bufferTextRuns = config.badWords?.enabled === true;
|
|
157
|
+
let pendingText;
|
|
158
|
+
const releaseText = (controller) => {
|
|
159
|
+
if (!pendingText) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const filtered = applyContentFiltering(pendingText.delta, config.badWords, "stream");
|
|
163
|
+
controller.enqueue(filtered.hasChanges
|
|
164
|
+
? { ...pendingText, delta: filtered.filteredText }
|
|
165
|
+
: pendingText);
|
|
166
|
+
pendingText = undefined;
|
|
167
|
+
};
|
|
116
168
|
const transformStream = new TransformStream({
|
|
117
169
|
transform(chunk, controller) {
|
|
118
170
|
hasYieldedChunks = true;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
...filteredChunk,
|
|
125
|
-
delta: filterResult.filteredText,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
171
|
+
if (chunk.type === "text-delta" && bufferTextRuns) {
|
|
172
|
+
pendingText = pendingText
|
|
173
|
+
? { ...pendingText, delta: pendingText.delta + chunk.delta }
|
|
174
|
+
: chunk;
|
|
175
|
+
return;
|
|
128
176
|
}
|
|
129
|
-
controller
|
|
177
|
+
releaseText(controller);
|
|
178
|
+
controller.enqueue(chunk);
|
|
130
179
|
},
|
|
131
|
-
flush() {
|
|
180
|
+
flush(controller) {
|
|
181
|
+
releaseText(controller);
|
|
132
182
|
if (!hasYieldedChunks) {
|
|
133
183
|
logger.warn(`[GuardrailsMiddleware] Stream ended without yielding any chunks`);
|
|
134
184
|
}
|
package/dist/neurolink.js
CHANGED
|
@@ -4359,6 +4359,7 @@ Current user's request: ${currentInput}`;
|
|
|
4359
4359
|
: undefined,
|
|
4360
4360
|
responseTime: textResult.responseTime,
|
|
4361
4361
|
toolsUsed: textResult.toolsUsed,
|
|
4362
|
+
toolCalls: textResult.toolCalls ?? [],
|
|
4362
4363
|
toolExecutions: toToolExecutionRecords(textResult.toolExecutions),
|
|
4363
4364
|
enhancedWithTools: textResult.enhancedWithTools,
|
|
4364
4365
|
availableTools: transformAvailableTools(textResult.availableTools),
|
|
@@ -5877,6 +5878,7 @@ Current user's request: ${currentInput}`;
|
|
|
5877
5878
|
rawFinishReason: result.rawFinishReason,
|
|
5878
5879
|
stepsUsed: result.stepsUsed,
|
|
5879
5880
|
toolsUsed: result.toolsUsed || [],
|
|
5881
|
+
toolCalls: result.toolCalls ?? [],
|
|
5880
5882
|
toolExecutions: transformedToolExecutions,
|
|
5881
5883
|
enhancedWithTools: Boolean(hasToolExecutions),
|
|
5882
5884
|
availableTools: transformToolsForMCP(transformToolsToExpectedFormat(availableTools)),
|
|
@@ -6028,6 +6030,7 @@ Current user's request: ${currentInput}`;
|
|
|
6028
6030
|
rawFinishReason: poolResult.rawFinishReason,
|
|
6029
6031
|
stepsUsed: poolResult.stepsUsed,
|
|
6030
6032
|
toolsUsed: poolResult.toolsUsed || [],
|
|
6033
|
+
toolCalls: poolResult.toolCalls ?? [],
|
|
6031
6034
|
// Lossless pass-through: keep the full ToolExecutionRecord
|
|
6032
6035
|
// fields (params/resultText/isError/timing) alongside the
|
|
6033
6036
|
// legacy {toolName,executionTime,success} shape this internal
|
|
@@ -6398,6 +6401,9 @@ Current user's request: ${currentInput}`;
|
|
|
6398
6401
|
rawFinishReason: result.rawFinishReason,
|
|
6399
6402
|
stepsUsed: result.stepsUsed,
|
|
6400
6403
|
toolsUsed: result.toolsUsed || [],
|
|
6404
|
+
// The providers record executed calls; without this line the public
|
|
6405
|
+
// result never carried them, whatever the provider returned.
|
|
6406
|
+
toolCalls: result.toolCalls ?? [],
|
|
6401
6407
|
// Lossless pass-through: keep the full ToolExecutionRecord fields
|
|
6402
6408
|
// alongside the legacy {toolName,executionTime,success} shape this
|
|
6403
6409
|
// internal result declares, so the final GenerateResult mapping
|
|
@@ -2,7 +2,7 @@ import { BaseProvider } from "../core/baseProvider.js";
|
|
|
2
2
|
import { createStreamChannel } from "../core/streamChannel.js";
|
|
3
3
|
import { logger } from "../utils/logger.js";
|
|
4
4
|
import { resolveRequestKind } from "../core/resolveRequestKind.js";
|
|
5
|
-
import { resolveToolExecutionRecords } from "../core/toolExecutionRecorder.js";
|
|
5
|
+
import { resolveToolExecutionRecords, toolCallsFromSummaries, } from "../core/toolExecutionRecorder.js";
|
|
6
6
|
import { transformToolExecutions } from "../utils/transformationUtils.js";
|
|
7
7
|
import { convertZodToJsonSchema } from "../utils/schemaConversion.js";
|
|
8
8
|
import { withProviderRetry } from "../utils/providerRetry.js";
|
|
@@ -198,6 +198,7 @@ export class AmazonSageMakerProvider extends BaseProvider {
|
|
|
198
198
|
},
|
|
199
199
|
responseTime: Date.now() - startTime,
|
|
200
200
|
toolsUsed: loop.toolsUsed,
|
|
201
|
+
toolCalls: toolCallsFromSummaries(toolExecutionSummaries),
|
|
201
202
|
toolExecutions: resolveToolExecutionRecords(options, transformToolExecutions(toolExecutionSummaries)),
|
|
202
203
|
enhancedWithTools: loop.toolsUsed.length > 0,
|
|
203
204
|
};
|
|
@@ -28,7 +28,7 @@ import { runAgenticLoop } from "../../core/loopEngine.js";
|
|
|
28
28
|
import { hasNativeDoGenerate, runNativeGenerateLoop, } from "../../core/nativeGenerateLoop.js";
|
|
29
29
|
import { withProviderRetry } from "../../utils/providerRetry.js";
|
|
30
30
|
import { resolveRequestKind } from "../../core/resolveRequestKind.js";
|
|
31
|
-
import { resolveToolExecutionRecords } from "../../core/toolExecutionRecorder.js";
|
|
31
|
+
import { resolveToolExecutionRecords, toolCallsFromSummaries, } from "../../core/toolExecutionRecorder.js";
|
|
32
32
|
import { transformToolExecutions } from "../../utils/transformationUtils.js";
|
|
33
33
|
import { createAnthropicConfig, getProviderModel, validateApiKey, } from "../../utils/providerConfig.js";
|
|
34
34
|
import { composeAbortSignals, createTimeoutController, mergeAbortSignals, TimeoutError, } from "../../utils/timeout.js";
|
|
@@ -1479,6 +1479,7 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
1479
1479
|
},
|
|
1480
1480
|
responseTime: Date.now() - startTime,
|
|
1481
1481
|
toolsUsed: loop.toolsUsed,
|
|
1482
|
+
toolCalls: toolCallsFromSummaries(toolExecutionSummaries),
|
|
1482
1483
|
toolExecutions: resolveToolExecutionRecords(options, transformToolExecutions(toolExecutionSummaries)),
|
|
1483
1484
|
enhancedWithTools: loop.toolsUsed.length > 0,
|
|
1484
1485
|
};
|
|
@@ -34,7 +34,7 @@ import { composeAbortSignalsScoped, createTimeoutController, mergeAbortSignals,
|
|
|
34
34
|
import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
|
|
35
35
|
import { resolveRequestKind } from "../core/resolveRequestKind.js";
|
|
36
36
|
import { appendJsonSchemaInstruction, hasNativeDoGenerate, runNativeGenerateLoop, } from "../core/nativeGenerateLoop.js";
|
|
37
|
-
import { resolveToolExecutionRecords } from "../core/toolExecutionRecorder.js";
|
|
37
|
+
import { resolveToolExecutionRecords, toolCallsFromSummaries, } from "../core/toolExecutionRecorder.js";
|
|
38
38
|
import { convertZodToJsonSchema } from "../utils/schemaConversion.js";
|
|
39
39
|
import { coerceJsonToSchema, schemaAccepts } from "../utils/json/coerce.js";
|
|
40
40
|
import { resolveToolChoice } from "../utils/toolChoice.js";
|
|
@@ -989,6 +989,7 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
989
989
|
},
|
|
990
990
|
responseTime: Date.now() - startTime,
|
|
991
991
|
toolsUsed,
|
|
992
|
+
toolCalls: toolCallsFromSummaries(toolExecutionSummaries),
|
|
992
993
|
toolExecutions: resolveToolExecutionRecords(options, transformToolExecutions(toolExecutionSummaries)),
|
|
993
994
|
enhancedWithTools: toolsUsed.length > 0,
|
|
994
995
|
};
|
package/dist/types/generate.d.ts
CHANGED
|
@@ -1490,6 +1490,12 @@ export type TextGenerationResult = {
|
|
|
1490
1490
|
model?: string;
|
|
1491
1491
|
usage?: TokenUsage;
|
|
1492
1492
|
responseTime?: number;
|
|
1493
|
+
/** The executed tool calls of a native turn — the same shape `GenerateResult` exposes. */
|
|
1494
|
+
toolCalls?: Array<{
|
|
1495
|
+
toolCallId: string;
|
|
1496
|
+
toolName: string;
|
|
1497
|
+
args: StandardRecord;
|
|
1498
|
+
}>;
|
|
1493
1499
|
toolsUsed?: string[];
|
|
1494
1500
|
toolExecutions?: Array<{
|
|
1495
1501
|
toolName: string;
|
|
@@ -3,7 +3,7 @@ import type { EvaluationData, GetPromptFunction } from "./evaluation.js";
|
|
|
3
3
|
import type { AuthenticatedUser, RouteDefinition, ServerContext } from "./server.js";
|
|
4
4
|
import type { LanguageModelMiddleware as BaseLanguageModelMiddleware } from "./aiCompat.js";
|
|
5
5
|
export type { LanguageModelMiddleware } from "./aiCompat.js";
|
|
6
|
-
export type { LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3Message, LanguageModelV3Prompt, LanguageModelV3StreamPart, LanguageModelV3ToolCall, LanguageModelV3ToolChoice, LanguageModelV3Source, LanguageModelV3Middleware, LanguageModelV3GenerateResult, LanguageModelV3StreamResult, JSONSchema7, } from "./aiCompat.js";
|
|
6
|
+
export type { LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3Message, LanguageModelV3Prompt, LanguageModelV3StreamPart, LanguageModelV3Content, LanguageModelV3ToolCall, LanguageModelV3ToolChoice, LanguageModelV3Source, LanguageModelV3Middleware, LanguageModelV3GenerateResult, LanguageModelV3StreamResult, JSONSchema7, } from "./aiCompat.js";
|
|
7
7
|
/**
|
|
8
8
|
* Metadata type for NeuroLink middleware
|
|
9
9
|
* Provides additional information about middleware without affecting execution
|
|
@@ -49,6 +49,15 @@ export declare function normalizeWireToolSchema(schema: unknown): Record<string,
|
|
|
49
49
|
* Check if a value is a Zod schema
|
|
50
50
|
*/
|
|
51
51
|
export declare function isZodSchema(value: unknown): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Whether a schema was built by Zod 4 specifically.
|
|
54
|
+
*
|
|
55
|
+
* Zod 4 hangs its internals off `_zod` (and `z.toJSONSchema` reads
|
|
56
|
+
* `schema._zod.def`); Zod 3 has only `_def`. The two can coexist in one install
|
|
57
|
+
* — a host on Zod 3 still resolves NeuroLink's own Zod 4 — so the presence of
|
|
58
|
+
* `z.toJSONSchema` says nothing about the schema actually being handed to it.
|
|
59
|
+
*/
|
|
60
|
+
export declare function isZod4Schema(value: unknown): boolean;
|
|
52
61
|
/**
|
|
53
62
|
* Convert JSON Schema to Zod schema format using official json-schema-to-zod library
|
|
54
63
|
* This ensures complete preservation of all schema structure and validation rules
|
|
@@ -340,7 +340,7 @@ target = "jsonSchema7") {
|
|
|
340
340
|
// Translate our `target` to Zod 4's native dialect identifier so the
|
|
341
341
|
// openApi3 path emits the OpenAPI 3 schema shape Vertex/Gemini expect
|
|
342
342
|
// (and not the default draft-07 anyOf/null union).
|
|
343
|
-
if (zodToJsonSchemaV4) {
|
|
343
|
+
if (zodToJsonSchemaV4 && isZod4Schema(zodSchema)) {
|
|
344
344
|
const nativeTarget = target === "openApi3" ? "openapi-3.0" : "draft-07";
|
|
345
345
|
try {
|
|
346
346
|
const native = zodToJsonSchemaV4(zodSchema, {
|
|
@@ -572,6 +572,17 @@ export function isZodSchema(value) {
|
|
|
572
572
|
"_def" in value &&
|
|
573
573
|
typeof value.parse === "function");
|
|
574
574
|
}
|
|
575
|
+
/**
|
|
576
|
+
* Whether a schema was built by Zod 4 specifically.
|
|
577
|
+
*
|
|
578
|
+
* Zod 4 hangs its internals off `_zod` (and `z.toJSONSchema` reads
|
|
579
|
+
* `schema._zod.def`); Zod 3 has only `_def`. The two can coexist in one install
|
|
580
|
+
* — a host on Zod 3 still resolves NeuroLink's own Zod 4 — so the presence of
|
|
581
|
+
* `z.toJSONSchema` says nothing about the schema actually being handed to it.
|
|
582
|
+
*/
|
|
583
|
+
export function isZod4Schema(value) {
|
|
584
|
+
return !!(value && typeof value === "object" && "_zod" in value);
|
|
585
|
+
}
|
|
575
586
|
/**
|
|
576
587
|
* Convert JSON Schema to Zod schema format using official json-schema-to-zod library
|
|
577
588
|
* This ensures complete preservation of all schema structure and validation rules
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.12.
|
|
3
|
+
"version": "12.12.9",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "TypeScript AI SDK with 24+ LLM providers behind one consistent API. MCP-native (connect any MCP server), voice TTS/STT/realtime, RAG, agents, memory, context compaction. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · DeepSeek · NVIDIA NIM and more.",
|
|
6
6
|
"author": {
|
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
"test:openai-compat-streaming-retry": "pnpm exec tsx test/continuous-test-suite-openai-compat-streaming-retry.ts",
|
|
97
97
|
"test:anthropic-streaming-retry": "pnpm exec tsx test/continuous-test-suite-anthropic-streaming-retry.ts",
|
|
98
98
|
"test:adjust-body-after-400": "pnpm exec tsx test/continuous-test-suite-adjust-body-after-400.ts",
|
|
99
|
+
"test:zod3-schema-native-path": "pnpm exec tsx test/continuous-test-suite-zod3-schema-native-path.ts",
|
|
99
100
|
"test:error-classification-e2e": "pnpm exec tsx test/continuous-test-suite-error-classification-e2e.ts",
|
|
100
101
|
"test:error-classifier-contract": "pnpm exec tsx test/continuous-test-suite-error-classifier-contract.ts",
|
|
101
102
|
"test:bedrock-inference-profile": "pnpm exec tsx test/continuous-test-suite-bedrock-inference-profile.ts",
|
|
@@ -112,6 +113,7 @@
|
|
|
112
113
|
"test:mcp:spans": "pnpm exec tsx test/continuous-test-suite-mcp-spans.ts",
|
|
113
114
|
"test:mcp:infra": "pnpm exec tsx test/continuous-test-suite-mcp-infra.ts",
|
|
114
115
|
"test:vendor-recovery": "pnpm exec tsx test/continuous-test-suite-native-vendor-recovery.ts",
|
|
116
|
+
"test:browser-bundle": "pnpm exec tsx test/continuous-test-suite-browser-bundle.ts",
|
|
115
117
|
"test:providers-mocked": "pnpm exec tsx test/continuous-test-suite-providers-mocked.ts",
|
|
116
118
|
"scaffold:provider": "pnpm exec tsx tools/scaffold-provider.ts",
|
|
117
119
|
"verify:provider-onboarding": "pnpm exec tsx tools/verify-provider-onboarding.ts",
|