@juspay/neurolink 9.76.0 → 9.78.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/CHANGELOG.md +12 -0
- package/dist/browser/neurolink.min.js +341 -341
- package/dist/core/toolRouting.d.ts +9 -0
- package/dist/core/toolRouting.js +178 -1
- package/dist/core/toolRoutingEmbedding.d.ts +112 -0
- package/dist/core/toolRoutingEmbedding.js +322 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +35 -0
- package/dist/lib/core/toolRouting.d.ts +9 -0
- package/dist/lib/core/toolRouting.js +178 -1
- package/dist/lib/core/toolRoutingEmbedding.d.ts +112 -0
- package/dist/lib/core/toolRoutingEmbedding.js +323 -0
- package/dist/lib/index.d.ts +31 -0
- package/dist/lib/index.js +35 -0
- package/dist/lib/neurolink.d.ts +22 -0
- package/dist/lib/neurolink.js +544 -175
- package/dist/lib/routing/index.d.ts +7 -0
- package/dist/lib/routing/index.js +8 -0
- package/dist/lib/routing/modelPool.d.ts +83 -0
- package/dist/lib/routing/modelPool.js +243 -0
- package/dist/lib/routing/requestRouter.d.ts +30 -0
- package/dist/lib/routing/requestRouter.js +81 -0
- package/dist/lib/types/config.d.ts +18 -0
- package/dist/lib/types/index.d.ts +2 -0
- package/dist/lib/types/index.js +4 -0
- package/dist/lib/types/modelPool.d.ts +47 -0
- package/dist/lib/types/modelPool.js +11 -0
- package/dist/lib/types/requestRouter.d.ts +75 -0
- package/dist/lib/types/requestRouter.js +16 -0
- package/dist/lib/types/toolRouting.d.ts +171 -0
- package/dist/lib/utils/providerErrorClassification.d.ts +24 -0
- package/dist/lib/utils/providerErrorClassification.js +89 -0
- package/dist/neurolink.d.ts +22 -0
- package/dist/neurolink.js +544 -175
- package/dist/routing/index.d.ts +7 -0
- package/dist/routing/index.js +7 -0
- package/dist/routing/modelPool.d.ts +83 -0
- package/dist/routing/modelPool.js +242 -0
- package/dist/routing/requestRouter.d.ts +30 -0
- package/dist/routing/requestRouter.js +80 -0
- package/dist/types/config.d.ts +18 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +4 -0
- package/dist/types/modelPool.d.ts +47 -0
- package/dist/types/modelPool.js +10 -0
- package/dist/types/requestRouter.d.ts +75 -0
- package/dist/types/requestRouter.js +15 -0
- package/dist/types/toolRouting.d.ts +171 -0
- package/dist/utils/providerErrorClassification.d.ts +24 -0
- package/dist/utils/providerErrorClassification.js +88 -0
- package/package.json +6 -2
|
@@ -38,6 +38,71 @@ export type ToolRoutingModelConfig = {
|
|
|
38
38
|
/** Router sampling temperature. Default: 0. */
|
|
39
39
|
temperature?: number;
|
|
40
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* Weights for the hybrid scoring formula used by `ToolEmbeddingIndex.rank()`.
|
|
43
|
+
* Scores are computed as: `cosine * cosine + bm25 * bm25Score` then
|
|
44
|
+
* normalized before sorting.
|
|
45
|
+
* Default: `{ cosine: 0.8, bm25: 0.2 }`.
|
|
46
|
+
*/
|
|
47
|
+
export type ToolRetrievalWeights = {
|
|
48
|
+
/** Weight applied to the cosine-similarity (dense) component. */
|
|
49
|
+
cosine: number;
|
|
50
|
+
/** Weight applied to the BM25 (sparse/lexical) component. */
|
|
51
|
+
bm25: number;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Configuration for the L2 embedding fast-path (ITEM B).
|
|
55
|
+
*
|
|
56
|
+
* When enabled and the catalog's total tool count reaches `minToolsToActivate`,
|
|
57
|
+
* a hybrid cosine + BM25 retriever ranks all tools by relevance to the query
|
|
58
|
+
* and takes the top-`topK` candidates. This is far cheaper than an LLM call
|
|
59
|
+
* (sub-10 ms warm) and fires BEFORE or INSTEAD of the LLM router.
|
|
60
|
+
*
|
|
61
|
+
* Fail-open: any embedding error (missing provider, network failure, wrong
|
|
62
|
+
* model) silently falls back to the existing LLM-router / server-granularity
|
|
63
|
+
* path — the turn is never broken.
|
|
64
|
+
*/
|
|
65
|
+
export type ToolRoutingEmbeddingConfig = {
|
|
66
|
+
/**
|
|
67
|
+
* Activate the embedding fast-path. Default: false (backward-compatible).
|
|
68
|
+
* Setting this to true without supplying `provider`/`model` causes the SDK
|
|
69
|
+
* to try the stream call's configured provider; if that provider does not
|
|
70
|
+
* support embeddings the layer fails open.
|
|
71
|
+
*/
|
|
72
|
+
enabled?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Maximum number of top-ranked tool candidates passed to the post-embedding
|
|
75
|
+
* decision stage. Default: 20.
|
|
76
|
+
*/
|
|
77
|
+
topK?: number;
|
|
78
|
+
/**
|
|
79
|
+
* Minimum total tool count in the catalog before the embedding path
|
|
80
|
+
* activates. Below this threshold the catalog is small enough that the LLM
|
|
81
|
+
* router alone is cheap and fast. Default: 20.
|
|
82
|
+
*/
|
|
83
|
+
minToolsToActivate?: number;
|
|
84
|
+
/**
|
|
85
|
+
* Weights for the hybrid scoring formula:
|
|
86
|
+
* score = cosine * cosineSim + bm25 * bm25Score (both normalized to [0,1])
|
|
87
|
+
* Default: `{ cosine: 0.8, bm25: 0.2 }`.
|
|
88
|
+
*/
|
|
89
|
+
weights?: ToolRetrievalWeights;
|
|
90
|
+
/**
|
|
91
|
+
* Provider name to use for the embedding call (e.g. "openai", "vertex").
|
|
92
|
+
* Defaults to the stream/generate call's configured provider. The provider
|
|
93
|
+
* must support `embedMany()`.
|
|
94
|
+
*/
|
|
95
|
+
provider?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Embedding model name (provider-specific). When omitted the provider's
|
|
98
|
+
* default embedding model is used (e.g. text-embedding-3-small for OpenAI).
|
|
99
|
+
*/
|
|
100
|
+
model?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Timeout for embedding calls in milliseconds. Default: 10000.
|
|
103
|
+
*/
|
|
104
|
+
timeoutMs?: number;
|
|
105
|
+
};
|
|
41
106
|
/** Constructor-level configuration for pre-call tool routing. */
|
|
42
107
|
export type ToolRoutingConfig = {
|
|
43
108
|
/** Master switch. Routing runs only when true AND the server catalog is non-empty. */
|
|
@@ -88,6 +153,24 @@ export type ToolRoutingConfig = {
|
|
|
88
153
|
/** Number of turns for which a previously-selected server stays warm. Default: 3. */
|
|
89
154
|
turns?: number;
|
|
90
155
|
};
|
|
156
|
+
/**
|
|
157
|
+
* L2 embedding fast-path (ITEM B). When enabled the SDK ranks tools by
|
|
158
|
+
* semantic + lexical relevance using a hybrid cosine/BM25 score and narrows
|
|
159
|
+
* the candidate set BEFORE (or instead of) the LLM router. Disabled by
|
|
160
|
+
* default for backward compatibility.
|
|
161
|
+
*/
|
|
162
|
+
embedding?: ToolRoutingEmbeddingConfig;
|
|
163
|
+
/**
|
|
164
|
+
* Routing granularity (ITEM D).
|
|
165
|
+
*
|
|
166
|
+
* - `"server"` (default) — routing excludes the tools of entire unpicked
|
|
167
|
+
* servers. This is the original behavior.
|
|
168
|
+
* - `"tool"` — routing excludes individual tools that are not in the
|
|
169
|
+
* embedding top-K candidate set, regardless of which server they belong
|
|
170
|
+
* to. Requires `embedding.enabled: true`; if the embedding fast-path is
|
|
171
|
+
* off (or fails) the granularity falls back to `"server"` automatically.
|
|
172
|
+
*/
|
|
173
|
+
granularity?: "server" | "tool";
|
|
91
174
|
};
|
|
92
175
|
/** Catalog entry pairing a server descriptor with its registered tool names. */
|
|
93
176
|
export type ToolRoutingCatalogEntry = {
|
|
@@ -152,6 +235,19 @@ export type ToolRoutingDecision = {
|
|
|
152
235
|
cacheHit: boolean;
|
|
153
236
|
/** Wall-clock time spent in the routing resolution in milliseconds. */
|
|
154
237
|
durationMs: number;
|
|
238
|
+
/** True when the L2 embedding fast-path ran and produced candidate results. */
|
|
239
|
+
embeddingActivated?: boolean;
|
|
240
|
+
/**
|
|
241
|
+
* Number of tool candidates produced by the embedding retriever before the
|
|
242
|
+
* post-embedding server or tool filtering step.
|
|
243
|
+
*/
|
|
244
|
+
candidateToolCount?: number;
|
|
245
|
+
/**
|
|
246
|
+
* Granularity at which exclusions were applied ("server" or "tool").
|
|
247
|
+
* Matches `ToolRoutingConfig.granularity`; present only when routing was
|
|
248
|
+
* applied (outcome === "applied").
|
|
249
|
+
*/
|
|
250
|
+
granularity?: "server" | "tool";
|
|
155
251
|
};
|
|
156
252
|
/** Parameters for `resolveToolRoutingExclusions()`. */
|
|
157
253
|
export type ToolRoutingResolutionParams = {
|
|
@@ -176,4 +272,79 @@ export type ToolRoutingResolutionParams = {
|
|
|
176
272
|
* the resolver.
|
|
177
273
|
*/
|
|
178
274
|
emitDecision?: (decision: ToolRoutingDecision) => void;
|
|
275
|
+
/**
|
|
276
|
+
* Injected async function that converts an array of texts into embedding
|
|
277
|
+
* vectors. Built by the caller (NeuroLink) from the configured embedding
|
|
278
|
+
* provider so the resolver stays pure and free of provider imports.
|
|
279
|
+
* When undefined the embedding fast-path is skipped entirely.
|
|
280
|
+
*/
|
|
281
|
+
embedFn?: (texts: string[]) => Promise<number[][]>;
|
|
282
|
+
/**
|
|
283
|
+
* Embedding fast-path configuration forwarded from `ToolRoutingConfig`.
|
|
284
|
+
* Only consulted when `embedFn` is provided.
|
|
285
|
+
*/
|
|
286
|
+
embeddingConfig?: ToolRoutingEmbeddingConfig;
|
|
287
|
+
/**
|
|
288
|
+
* Routing granularity forwarded from `ToolRoutingConfig`. Default: "server".
|
|
289
|
+
*/
|
|
290
|
+
granularity?: "server" | "tool";
|
|
291
|
+
/**
|
|
292
|
+
* Optional shared vector cache for the L2 embedding fast-path. When
|
|
293
|
+
* supplied, tool embedding vectors computed on prior turns are reused rather
|
|
294
|
+
* than re-fetched from the embedding provider on every call.
|
|
295
|
+
*
|
|
296
|
+
* The NeuroLink instance manages the lifecycle: it creates the Map once and
|
|
297
|
+
* passes the same reference across turns. It clears the reference when the
|
|
298
|
+
* tool catalog changes (via `setToolRoutingServers`) so stale vectors are
|
|
299
|
+
* never used after a catalog update.
|
|
300
|
+
*/
|
|
301
|
+
embeddingVectorCache?: Map<string, number[]>;
|
|
302
|
+
};
|
|
303
|
+
/**
|
|
304
|
+
* A single item in the tool retrieval catalog, pairing a tool name with the
|
|
305
|
+
* text (tool description + server context) used to build its embedding vector.
|
|
306
|
+
*/
|
|
307
|
+
export type ToolRetrievalItem = {
|
|
308
|
+
/** Fully-qualified tool name (e.g. `${serverId}_${toolName}`). */
|
|
309
|
+
name: string;
|
|
310
|
+
/** Descriptive text used as the embedding document for this tool. */
|
|
311
|
+
text: string;
|
|
312
|
+
};
|
|
313
|
+
/**
|
|
314
|
+
* One ranked result from `ToolEmbeddingIndex.rank()` or
|
|
315
|
+
* `selectRelevantToolNames()`.
|
|
316
|
+
*/
|
|
317
|
+
export type ToolRetrievalRankedResult = {
|
|
318
|
+
/** Tool name (mirrors `ToolRetrievalItem.name`). */
|
|
319
|
+
name: string;
|
|
320
|
+
/** Combined hybrid score (higher = more relevant). */
|
|
321
|
+
score: number;
|
|
322
|
+
};
|
|
323
|
+
/**
|
|
324
|
+
* Options passed to `selectRelevantToolNames()` — the high-level convenience
|
|
325
|
+
* wrapper around `ToolEmbeddingIndex`.
|
|
326
|
+
*/
|
|
327
|
+
export type ToolRetrievalSelectOptions = {
|
|
328
|
+
/** Maximum number of tool names to return. */
|
|
329
|
+
topK: number;
|
|
330
|
+
/** Optional weight override (defaults to `{ cosine: 0.8, bm25: 0.2 }`). */
|
|
331
|
+
weights?: ToolRetrievalWeights;
|
|
332
|
+
/**
|
|
333
|
+
* Async function that converts an array of text strings into embedding
|
|
334
|
+
* vectors. Must return one vector per input text in the same order.
|
|
335
|
+
* Errors thrown here propagate to the caller (so it can fail open).
|
|
336
|
+
*/
|
|
337
|
+
embedFn: (texts: string[]) => Promise<number[][]>;
|
|
338
|
+
/**
|
|
339
|
+
* Optional shared vector cache (keyed by text string). When supplied the
|
|
340
|
+
* underlying `ToolEmbeddingIndex` reads from and writes to this Map so that
|
|
341
|
+
* tool vectors computed on a prior call are reused on subsequent calls for
|
|
342
|
+
* the same item text. Callers that want warm-cache behavior across turns
|
|
343
|
+
* should pass the same Map instance each time.
|
|
344
|
+
*/
|
|
345
|
+
vectorCache?: Map<string, number[]>;
|
|
346
|
+
/**
|
|
347
|
+
* Timeout for each embedding provider call in milliseconds. Default: 10000.
|
|
348
|
+
*/
|
|
349
|
+
timeoutMs?: number;
|
|
179
350
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared provider-error classification utilities used by both neurolink.ts and
|
|
3
|
+
* the ModelPool routing subsystem.
|
|
4
|
+
*
|
|
5
|
+
* Extracted here to avoid duplication and to ensure that typed error classes
|
|
6
|
+
* (AuthenticationError, AuthorizationError, ModelAccessDeniedError) are
|
|
7
|
+
* checked consistently in both code paths.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Detects whether an error object looks like a model-access-denied condition.
|
|
11
|
+
* Matches LiteLLM "team not allowed" / "team can only access models=[...]"
|
|
12
|
+
* plus typed-error name/code markers when the full typed class is not present.
|
|
13
|
+
*/
|
|
14
|
+
export declare function looksLikeModelAccessDenied(error: unknown): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Returns true when the error is definitively non-retryable: typed error
|
|
17
|
+
* classes (auth, access-denied, invalid-model), non-retryable HTTP status
|
|
18
|
+
* codes, or deterministic 400-class message patterns.
|
|
19
|
+
*
|
|
20
|
+
* NOTE: ContextBudgetExceededError is intentionally NOT non-retryable —
|
|
21
|
+
* each provider has its own context window, so a budget rejection on one
|
|
22
|
+
* provider does not preclude another provider accepting the same payload.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isNonRetryableProviderError(error: unknown): boolean;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared provider-error classification utilities used by both neurolink.ts and
|
|
3
|
+
* the ModelPool routing subsystem.
|
|
4
|
+
*
|
|
5
|
+
* Extracted here to avoid duplication and to ensure that typed error classes
|
|
6
|
+
* (AuthenticationError, AuthorizationError, ModelAccessDeniedError) are
|
|
7
|
+
* checked consistently in both code paths.
|
|
8
|
+
*/
|
|
9
|
+
import { AuthenticationError, AuthorizationError, InvalidModelError, ModelAccessDeniedError, } from "../types/index.js";
|
|
10
|
+
import { NON_RETRYABLE_HTTP_STATUS_CODES, isDeterministicClientErrorMessage, } from "./retryability.js";
|
|
11
|
+
/**
|
|
12
|
+
* Detects whether an error object looks like a model-access-denied condition.
|
|
13
|
+
* Matches LiteLLM "team not allowed" / "team can only access models=[...]"
|
|
14
|
+
* plus typed-error name/code markers when the full typed class is not present.
|
|
15
|
+
*/
|
|
16
|
+
export function looksLikeModelAccessDenied(error) {
|
|
17
|
+
if (!error) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const e = error;
|
|
21
|
+
if (e.name === "ModelAccessDeniedError") {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
if (e.code === "MODEL_ACCESS_DENIED") {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
const msg = typeof e.message === "string"
|
|
28
|
+
? e.message
|
|
29
|
+
: error instanceof Error
|
|
30
|
+
? error.message
|
|
31
|
+
: String(error);
|
|
32
|
+
if (!msg) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
const lower = msg.toLowerCase();
|
|
36
|
+
return ((lower.includes("team") && lower.includes("not allowed")) ||
|
|
37
|
+
lower.includes("team can only access") ||
|
|
38
|
+
/not\s+allowed\s+to\s+access\s+(this\s+)?model/i.test(msg));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Returns true when the error is definitively non-retryable: typed error
|
|
42
|
+
* classes (auth, access-denied, invalid-model), non-retryable HTTP status
|
|
43
|
+
* codes, or deterministic 400-class message patterns.
|
|
44
|
+
*
|
|
45
|
+
* NOTE: ContextBudgetExceededError is intentionally NOT non-retryable —
|
|
46
|
+
* each provider has its own context window, so a budget rejection on one
|
|
47
|
+
* provider does not preclude another provider accepting the same payload.
|
|
48
|
+
*/
|
|
49
|
+
export function isNonRetryableProviderError(error) {
|
|
50
|
+
if (error instanceof InvalidModelError) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
if (error instanceof AuthenticationError) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
if (error instanceof AuthorizationError) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
if (error instanceof ModelAccessDeniedError) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
if (error && typeof error === "object") {
|
|
63
|
+
const err = error;
|
|
64
|
+
const status = typeof err.status === "number"
|
|
65
|
+
? err.status
|
|
66
|
+
: typeof err.statusCode === "number"
|
|
67
|
+
? err.statusCode
|
|
68
|
+
: undefined;
|
|
69
|
+
if (status !== undefined &&
|
|
70
|
+
NON_RETRYABLE_HTTP_STATUS_CODES.includes(status)) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (error instanceof Error) {
|
|
75
|
+
const msg = error.message;
|
|
76
|
+
if (msg.includes("NOT_FOUND") ||
|
|
77
|
+
msg.includes("Model Not Found") ||
|
|
78
|
+
msg.includes("model not found") ||
|
|
79
|
+
msg.includes("PERMISSION_DENIED") ||
|
|
80
|
+
msg.includes("UNAUTHENTICATED")) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
if (isDeterministicClientErrorMessage(msg)) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.78.0",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applications with 21+ providers: OpenAI, Anthropic, Google AI Studio, Google Vertex, AWS Bedrock, Azure OpenAI, Mistral, LiteLLM, SageMaker, Hugging Face, Ollama, OpenAI-compatible, OpenRouter, DeepSeek, NVIDIA NIM, LM Studio, llama.cpp, plus voice (OpenAI TTS, ElevenLabs, Deepgram, Azure Speech).",
|
|
6
6
|
"author": {
|
|
@@ -122,11 +122,15 @@
|
|
|
122
122
|
"test:tool-routing-cli": "pnpm run test:tool-routing-cli:vitest && npx tsx test/continuous-test-suite-tool-routing-cli.ts",
|
|
123
123
|
"test:tool-dedup:vitest": "pnpm exec vitest run test/toolDedup.test.ts",
|
|
124
124
|
"test:tool-dedup": "pnpm run test:tool-dedup:vitest && npx tsx test/continuous-test-suite-tool-dedup.ts",
|
|
125
|
+
"test:model-pool:vitest": "pnpm exec vitest run test/modelPool.test.ts",
|
|
126
|
+
"test:model-pool": "pnpm run test:model-pool:vitest && npx tsx test/continuous-test-suite-model-pool.ts",
|
|
125
127
|
"test:ci": "pnpm run test && pnpm run test:client && pnpm run test:hitl",
|
|
126
128
|
"// CI tier — fast, no live AI calls, safe for every commit": "",
|
|
127
129
|
"test:unit:vitest": "pnpm exec vitest run test/toolRouting.test.ts",
|
|
128
130
|
"test:tool-routing": "pnpm run test:unit:vitest && npx tsx test/continuous-test-suite-tool-routing.ts",
|
|
129
|
-
"test:
|
|
131
|
+
"test:tool-routing-semantic:vitest": "pnpm exec vitest run test/toolRoutingSemantic.test.ts",
|
|
132
|
+
"test:tool-routing-semantic": "pnpm run test:tool-routing-semantic:vitest && npx tsx test/continuous-test-suite-tool-routing-semantic.ts",
|
|
133
|
+
"test:unit": "pnpm run test:envguard && pnpm run test:bugfixes && pnpm run test:mcp:infra && pnpm run test:mcp:bash && pnpm run test:mcp:limits && pnpm run test:mcp:spans && pnpm run test:autoresearch:redis && pnpm run test:unit:vitest && pnpm run test:tool-routing-cli:vitest && pnpm run test:tool-dedup:vitest && pnpm run test:model-pool:vitest && pnpm run test:tool-routing-semantic:vitest",
|
|
130
134
|
"// CI tier — live providers, runs only when API keys are present (test:credentials and test:dynamic make real provider calls when keys are set, so they live here, not in test:unit)": "",
|
|
131
135
|
"test:live": "pnpm run test:providers && pnpm run test:mcp:http && pnpm run test:mcp:sdk && pnpm run test:mcp:cli && pnpm run test:observability && pnpm run test:context && pnpm run test:memory && pnpm run test:tool-reliability && pnpm run test:evaluation && pnpm run test:autoresearch && pnpm run test:credentials && pnpm run test:dynamic",
|
|
132
136
|
"// CI tier — product output (image/video/TTS/PPT) — costs $$ per run": "",
|