@juspay/neurolink 11.24.2 → 11.25.1
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 +3 -3
- package/dist/browser/neurolink.min.js +68 -68
- package/dist/core/baseProvider.js +8 -2
- package/dist/neurolink.js +10 -0
- package/dist/providers/anthropic/client.js +22 -0
- package/dist/types/stream.d.ts +11 -0
- package/package.json +1 -1
|
@@ -247,8 +247,14 @@ export class BaseProvider {
|
|
|
247
247
|
return this.wrapStreamWithLifecycleCallbacks(realStreamResult, options);
|
|
248
248
|
}
|
|
249
249
|
catch (realStreamError) {
|
|
250
|
-
//
|
|
251
|
-
//
|
|
250
|
+
// The fallback is BROAD, not narrow: only the terminal errors listed
|
|
251
|
+
// below (abort, timeout, 401/403, quota, rate limit, authentication)
|
|
252
|
+
// re-throw. Every other failure — including a genuine configuration or
|
|
253
|
+
// programming error — is masked as a degraded fake stream whenever
|
|
254
|
+
// tools are enabled. Narrowing this to "streaming with tools is
|
|
255
|
+
// unsupported" failures would change behaviour for every provider at
|
|
256
|
+
// once, so it needs its own characterization PR first; until then this
|
|
257
|
+
// comment records what the code does, not what a narrower design would.
|
|
252
258
|
const errMsg = realStreamError instanceof Error
|
|
253
259
|
? realStreamError.message
|
|
254
260
|
: String(realStreamError);
|
package/dist/neurolink.js
CHANGED
|
@@ -7354,7 +7354,17 @@ Current user's request: ${currentInput}`;
|
|
|
7354
7354
|
// Reviewer follow-up: fire fallback when no *non-sentinel*
|
|
7355
7355
|
// output was produced — sentinel-only and truly empty streams
|
|
7356
7356
|
// both qualify, but media-only streams (audio/image) do not.
|
|
7357
|
+
//
|
|
7358
|
+
// fallbackOnMaxSteps: false exempts one no-output shape — a turn
|
|
7359
|
+
// the provider reports as ended at the caller's own maxSteps bound
|
|
7360
|
+
// (metadata.stopReason "step-cap", a mutable reference the native
|
|
7361
|
+
// loops fill by drain time). That bound is the caller's budget,
|
|
7362
|
+
// not a provider failure, and retrying it on another provider
|
|
7363
|
+
// spends that provider's tokens to exceed a budget the caller set.
|
|
7364
|
+
const cappedByCallerBudget = enhancedOptions.fallbackOnMaxSteps === false &&
|
|
7365
|
+
providerStreamMetadata?.stopReason === "step-cap";
|
|
7357
7366
|
if (realOutputChunks === 0 &&
|
|
7367
|
+
!cappedByCallerBudget &&
|
|
7358
7368
|
!metadata.fallbackAttempted &&
|
|
7359
7369
|
!enhancedOptions.disableInternalFallback &&
|
|
7360
7370
|
streamState.toolCalls.length === 0 &&
|
|
@@ -1455,6 +1455,13 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
1455
1455
|
const client = this.client;
|
|
1456
1456
|
const toolsUsed = [];
|
|
1457
1457
|
const streamStartTime = Date.now();
|
|
1458
|
+
// Mutable-reference contract from StreamResult.metadata: created before
|
|
1459
|
+
// the loop and filled once the turn drains, because wrapper spreads
|
|
1460
|
+
// snapshot top-level result fields before the loop resolves. This is how
|
|
1461
|
+
// the Gemini/Vertex native paths already report their resolved outcome;
|
|
1462
|
+
// without it a consumer (e.g. the SDK's no-output fallback gate) cannot
|
|
1463
|
+
// tell a step-capped turn from a failed one.
|
|
1464
|
+
const turnMetadata = {};
|
|
1458
1465
|
// Hoisted out of runLoop so the error path can resolve the usage
|
|
1459
1466
|
// accumulated by steps that completed BEFORE the failure — those steps
|
|
1460
1467
|
// were billed and must not be reported as zero.
|
|
@@ -1738,6 +1745,20 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
1738
1745
|
totalCacheRead += result.usage.cacheReadTokens ?? 0;
|
|
1739
1746
|
totalCacheWrite += result.usage.cacheWriteTokens ?? 0;
|
|
1740
1747
|
lastStop = result.rawStopReason ?? lastStop;
|
|
1748
|
+
turnMetadata.finishReason = result.finishReason;
|
|
1749
|
+
if (result.rawStopReason) {
|
|
1750
|
+
turnMetadata.rawFinishReason = result.rawStopReason;
|
|
1751
|
+
}
|
|
1752
|
+
// "tool-calls" after a drained turn means the model still wanted tools
|
|
1753
|
+
// when the step budget ran out — the engine breaks at maxSteps, and a
|
|
1754
|
+
// model turn that finished normally maps to "stop". The one other
|
|
1755
|
+
// producer of stop_reason "tool_use" at turn end is a final_result
|
|
1756
|
+
// call (structured output), which `finalResultText` identifies, so it
|
|
1757
|
+
// must not read as a capped turn.
|
|
1758
|
+
if (result.finishReason === "tool-calls" &&
|
|
1759
|
+
finalResultText === undefined) {
|
|
1760
|
+
turnMetadata.stopReason = "step-cap";
|
|
1761
|
+
}
|
|
1741
1762
|
resolveUsage(buildDeferredUsage());
|
|
1742
1763
|
resolveFinish(lastStop ?? "stop");
|
|
1743
1764
|
};
|
|
@@ -1822,6 +1843,7 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
1822
1843
|
model: this.modelName,
|
|
1823
1844
|
toolCalls: [],
|
|
1824
1845
|
toolResults: [],
|
|
1846
|
+
metadata: turnMetadata,
|
|
1825
1847
|
// Wire the deferred usage/finish promises into the analytics collector
|
|
1826
1848
|
// (mirrors openaiChatCompletionsBase). Without this the loop computed a
|
|
1827
1849
|
// fully correct aggregate that was consumed only by the OTel span —
|
package/dist/types/stream.d.ts
CHANGED
|
@@ -409,6 +409,17 @@ export type StreamOptions = {
|
|
|
409
409
|
* Used by the Claude proxy so the proxy itself can own fallback order.
|
|
410
410
|
*/
|
|
411
411
|
disableInternalFallback?: boolean;
|
|
412
|
+
/**
|
|
413
|
+
* Whether a turn that ended at the caller's own `maxSteps` bound may still
|
|
414
|
+
* trigger the internal no-output provider fallback. Reaching `maxSteps` is
|
|
415
|
+
* a budget the caller set, not a provider failure, but such a turn can end
|
|
416
|
+
* with no text output and would otherwise be retried on a different
|
|
417
|
+
* provider — spending that provider's tokens because the caller's own
|
|
418
|
+
* budget ran out. Set `false` to surface the capped turn as-is
|
|
419
|
+
* (`metadata.stopReason === "step-cap"`). Default (unset/true) preserves
|
|
420
|
+
* the existing fallback behaviour.
|
|
421
|
+
*/
|
|
422
|
+
fallbackOnMaxSteps?: boolean;
|
|
412
423
|
/**
|
|
413
424
|
* Skip injecting tool schemas into the system prompt.
|
|
414
425
|
* When true, tools are ONLY passed natively via the provider's `tools` parameter,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.25.1",
|
|
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": {
|