@juspay/neurolink 11.10.0 → 11.11.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 +2 -2
- package/dist/core/loopEngine.js +7 -0
- package/dist/lib/core/loopEngine.js +7 -0
- package/dist/lib/providers/anthropic/loopAdapter.js +12 -2
- package/dist/lib/providers/googleAiStudio/client.js +10 -1
- package/dist/lib/types/loopEngine.d.ts +14 -0
- package/dist/providers/anthropic/loopAdapter.js +12 -2
- package/dist/providers/googleAiStudio/client.js +10 -1
- package/dist/types/loopEngine.d.ts +14 -0
- package/package.json +1 -1
package/dist/core/loopEngine.js
CHANGED
|
@@ -150,9 +150,11 @@ export function runAgenticLoop(adapter, initialConversation, options) {
|
|
|
150
150
|
permanentlyFailed: true,
|
|
151
151
|
});
|
|
152
152
|
allToolExecutions.push({
|
|
153
|
+
id: call.id,
|
|
153
154
|
name: call.name,
|
|
154
155
|
input: call.args,
|
|
155
156
|
output,
|
|
157
|
+
error: output.error,
|
|
156
158
|
});
|
|
157
159
|
continue;
|
|
158
160
|
}
|
|
@@ -181,9 +183,11 @@ export function runAgenticLoop(adapter, initialConversation, options) {
|
|
|
181
183
|
permanentlyFailed: !!breaker,
|
|
182
184
|
});
|
|
183
185
|
allToolExecutions.push({
|
|
186
|
+
id: call.id,
|
|
184
187
|
name: call.name,
|
|
185
188
|
input: call.args,
|
|
186
189
|
output,
|
|
190
|
+
error: output.error,
|
|
187
191
|
});
|
|
188
192
|
continue;
|
|
189
193
|
}
|
|
@@ -194,6 +198,7 @@ export function runAgenticLoop(adapter, initialConversation, options) {
|
|
|
194
198
|
});
|
|
195
199
|
toolResults.push({ ...call, output });
|
|
196
200
|
allToolExecutions.push({
|
|
201
|
+
id: call.id,
|
|
197
202
|
name: call.name,
|
|
198
203
|
input: call.args,
|
|
199
204
|
output,
|
|
@@ -213,9 +218,11 @@ export function runAgenticLoop(adapter, initialConversation, options) {
|
|
|
213
218
|
const output = { error: message, status: "failed" };
|
|
214
219
|
toolResults.push({ ...call, output, error: message });
|
|
215
220
|
allToolExecutions.push({
|
|
221
|
+
id: call.id,
|
|
216
222
|
name: call.name,
|
|
217
223
|
input: call.args,
|
|
218
224
|
output,
|
|
225
|
+
error: message,
|
|
219
226
|
});
|
|
220
227
|
}
|
|
221
228
|
}
|
|
@@ -150,9 +150,11 @@ export function runAgenticLoop(adapter, initialConversation, options) {
|
|
|
150
150
|
permanentlyFailed: true,
|
|
151
151
|
});
|
|
152
152
|
allToolExecutions.push({
|
|
153
|
+
id: call.id,
|
|
153
154
|
name: call.name,
|
|
154
155
|
input: call.args,
|
|
155
156
|
output,
|
|
157
|
+
error: output.error,
|
|
156
158
|
});
|
|
157
159
|
continue;
|
|
158
160
|
}
|
|
@@ -181,9 +183,11 @@ export function runAgenticLoop(adapter, initialConversation, options) {
|
|
|
181
183
|
permanentlyFailed: !!breaker,
|
|
182
184
|
});
|
|
183
185
|
allToolExecutions.push({
|
|
186
|
+
id: call.id,
|
|
184
187
|
name: call.name,
|
|
185
188
|
input: call.args,
|
|
186
189
|
output,
|
|
190
|
+
error: output.error,
|
|
187
191
|
});
|
|
188
192
|
continue;
|
|
189
193
|
}
|
|
@@ -194,6 +198,7 @@ export function runAgenticLoop(adapter, initialConversation, options) {
|
|
|
194
198
|
});
|
|
195
199
|
toolResults.push({ ...call, output });
|
|
196
200
|
allToolExecutions.push({
|
|
201
|
+
id: call.id,
|
|
197
202
|
name: call.name,
|
|
198
203
|
input: call.args,
|
|
199
204
|
output,
|
|
@@ -213,9 +218,11 @@ export function runAgenticLoop(adapter, initialConversation, options) {
|
|
|
213
218
|
const output = { error: message, status: "failed" };
|
|
214
219
|
toolResults.push({ ...call, output, error: message });
|
|
215
220
|
allToolExecutions.push({
|
|
221
|
+
id: call.id,
|
|
216
222
|
name: call.name,
|
|
217
223
|
input: call.args,
|
|
218
224
|
output,
|
|
225
|
+
error: message,
|
|
219
226
|
});
|
|
220
227
|
}
|
|
221
228
|
}
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import { resolveDeferredTool } from "../../tools/toolDiscovery.js";
|
|
25
25
|
import { stringifyAnthropicToolOutput } from "./toolOutput.js";
|
|
26
|
+
import { stringifyFinalResultInput } from "./structuredOutput.js";
|
|
26
27
|
/** Map Anthropic's stop_reason onto the unified finish reason. */
|
|
27
28
|
function mapAnthropicFinishReason(rawStopReason, hadToolCallsAtCap) {
|
|
28
29
|
switch (rawStopReason) {
|
|
@@ -271,10 +272,19 @@ export function createAnthropicLoopAdapter(config) {
|
|
|
271
272
|
// never dispatched, never counted against the breaker, and never shows
|
|
272
273
|
// up as a tool execution.
|
|
273
274
|
const terminal = config.finalResultToolName
|
|
274
|
-
?
|
|
275
|
+
? [...toolByIndex.values()].find((pending) => pending.name === config.finalResultToolName)
|
|
275
276
|
: undefined;
|
|
276
277
|
const toolCalls = terminal ? [] : allCalls;
|
|
277
|
-
|
|
278
|
+
// The RAW accumulated input_json, never the parsed-then-restringified
|
|
279
|
+
// args. `parseArgs` yields {} for a payload the token cap cut off
|
|
280
|
+
// mid-string, so re-stringifying would turn a truncated answer into
|
|
281
|
+
// "{}" and lose it outright. `stringifyFinalResultInput` canonicalizes
|
|
282
|
+
// when the JSON parses and returns it verbatim when it does not, which
|
|
283
|
+
// is what lets the caller's coercion layer repair a partial payload
|
|
284
|
+
// into a partial object instead of nothing.
|
|
285
|
+
const finalText = terminal
|
|
286
|
+
? stringifyFinalResultInput(terminal.inputJson)
|
|
287
|
+
: text;
|
|
278
288
|
return {
|
|
279
289
|
text: finalText,
|
|
280
290
|
...(reasoning ? { reasoning } : {}),
|
|
@@ -1001,7 +1001,16 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
1001
1001
|
if (wantsNativeJsonRequested && exclusionInForce) {
|
|
1002
1002
|
logger.warn("[GoogleAIStudio] Gemini does not support tools and JSON schema output simultaneously. Disabling tools for this request (generate()).");
|
|
1003
1003
|
}
|
|
1004
|
-
|
|
1004
|
+
// Both conjuncts, matching the warning directly above and the
|
|
1005
|
+
// stream path's gate. `isToolsSchemaExclusionInForce` answers "does
|
|
1006
|
+
// the tools/schema exclusion APPLY to this provider and model", and
|
|
1007
|
+
// is true for any Gemini request that has tools at all — it is not
|
|
1008
|
+
// "the exclusion is triggered". Testing `!exclusionInForce` alone
|
|
1009
|
+
// therefore made this branch reachable only when there were NO
|
|
1010
|
+
// tools, so every caller-supplied tool was dropped on the generate
|
|
1011
|
+
// path whether or not structured output was ever requested.
|
|
1012
|
+
if (shouldUseTools &&
|
|
1013
|
+
!(wantsNativeJsonRequested && exclusionInForce)) {
|
|
1005
1014
|
const tools = options.tools || {};
|
|
1006
1015
|
if (Object.keys(tools).length > 0) {
|
|
1007
1016
|
const result = toNativeToolDeclarations(tools, "functionDeclarations");
|
|
@@ -271,10 +271,24 @@ export type AgenticLoopOptions = {
|
|
|
271
271
|
export type AgenticLoopResult<TConversation> = {
|
|
272
272
|
text: string;
|
|
273
273
|
toolCalls: AgenticLoopToolCall[];
|
|
274
|
+
/**
|
|
275
|
+
* Every tool dispatch the loop performed, in order, including the ones that
|
|
276
|
+
* failed.
|
|
277
|
+
*
|
|
278
|
+
* `id` and `error` are carried because providers persist tool activity as
|
|
279
|
+
* paired call/result records keyed by the provider's own tool-call id, and
|
|
280
|
+
* a result that failed is stored differently from one that succeeded. A
|
|
281
|
+
* shape with only name/input/output cannot reconstruct either, so a
|
|
282
|
+
* provider migrating its hand-rolled loop onto this engine would have to
|
|
283
|
+
* silently drop both from its history — which is a behaviour change, not a
|
|
284
|
+
* refactor.
|
|
285
|
+
*/
|
|
274
286
|
toolExecutions: Array<{
|
|
287
|
+
id: string;
|
|
275
288
|
name: string;
|
|
276
289
|
input: Record<string, unknown>;
|
|
277
290
|
output: unknown;
|
|
291
|
+
error?: string;
|
|
278
292
|
}>;
|
|
279
293
|
usage: AgenticLoopUsage;
|
|
280
294
|
finishReason: string;
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import { resolveDeferredTool } from "../../tools/toolDiscovery.js";
|
|
25
25
|
import { stringifyAnthropicToolOutput } from "./toolOutput.js";
|
|
26
|
+
import { stringifyFinalResultInput } from "./structuredOutput.js";
|
|
26
27
|
/** Map Anthropic's stop_reason onto the unified finish reason. */
|
|
27
28
|
function mapAnthropicFinishReason(rawStopReason, hadToolCallsAtCap) {
|
|
28
29
|
switch (rawStopReason) {
|
|
@@ -271,10 +272,19 @@ export function createAnthropicLoopAdapter(config) {
|
|
|
271
272
|
// never dispatched, never counted against the breaker, and never shows
|
|
272
273
|
// up as a tool execution.
|
|
273
274
|
const terminal = config.finalResultToolName
|
|
274
|
-
?
|
|
275
|
+
? [...toolByIndex.values()].find((pending) => pending.name === config.finalResultToolName)
|
|
275
276
|
: undefined;
|
|
276
277
|
const toolCalls = terminal ? [] : allCalls;
|
|
277
|
-
|
|
278
|
+
// The RAW accumulated input_json, never the parsed-then-restringified
|
|
279
|
+
// args. `parseArgs` yields {} for a payload the token cap cut off
|
|
280
|
+
// mid-string, so re-stringifying would turn a truncated answer into
|
|
281
|
+
// "{}" and lose it outright. `stringifyFinalResultInput` canonicalizes
|
|
282
|
+
// when the JSON parses and returns it verbatim when it does not, which
|
|
283
|
+
// is what lets the caller's coercion layer repair a partial payload
|
|
284
|
+
// into a partial object instead of nothing.
|
|
285
|
+
const finalText = terminal
|
|
286
|
+
? stringifyFinalResultInput(terminal.inputJson)
|
|
287
|
+
: text;
|
|
278
288
|
return {
|
|
279
289
|
text: finalText,
|
|
280
290
|
...(reasoning ? { reasoning } : {}),
|
|
@@ -1001,7 +1001,16 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
1001
1001
|
if (wantsNativeJsonRequested && exclusionInForce) {
|
|
1002
1002
|
logger.warn("[GoogleAIStudio] Gemini does not support tools and JSON schema output simultaneously. Disabling tools for this request (generate()).");
|
|
1003
1003
|
}
|
|
1004
|
-
|
|
1004
|
+
// Both conjuncts, matching the warning directly above and the
|
|
1005
|
+
// stream path's gate. `isToolsSchemaExclusionInForce` answers "does
|
|
1006
|
+
// the tools/schema exclusion APPLY to this provider and model", and
|
|
1007
|
+
// is true for any Gemini request that has tools at all — it is not
|
|
1008
|
+
// "the exclusion is triggered". Testing `!exclusionInForce` alone
|
|
1009
|
+
// therefore made this branch reachable only when there were NO
|
|
1010
|
+
// tools, so every caller-supplied tool was dropped on the generate
|
|
1011
|
+
// path whether or not structured output was ever requested.
|
|
1012
|
+
if (shouldUseTools &&
|
|
1013
|
+
!(wantsNativeJsonRequested && exclusionInForce)) {
|
|
1005
1014
|
const tools = options.tools || {};
|
|
1006
1015
|
if (Object.keys(tools).length > 0) {
|
|
1007
1016
|
const result = toNativeToolDeclarations(tools, "functionDeclarations");
|
|
@@ -271,10 +271,24 @@ export type AgenticLoopOptions = {
|
|
|
271
271
|
export type AgenticLoopResult<TConversation> = {
|
|
272
272
|
text: string;
|
|
273
273
|
toolCalls: AgenticLoopToolCall[];
|
|
274
|
+
/**
|
|
275
|
+
* Every tool dispatch the loop performed, in order, including the ones that
|
|
276
|
+
* failed.
|
|
277
|
+
*
|
|
278
|
+
* `id` and `error` are carried because providers persist tool activity as
|
|
279
|
+
* paired call/result records keyed by the provider's own tool-call id, and
|
|
280
|
+
* a result that failed is stored differently from one that succeeded. A
|
|
281
|
+
* shape with only name/input/output cannot reconstruct either, so a
|
|
282
|
+
* provider migrating its hand-rolled loop onto this engine would have to
|
|
283
|
+
* silently drop both from its history — which is a behaviour change, not a
|
|
284
|
+
* refactor.
|
|
285
|
+
*/
|
|
274
286
|
toolExecutions: Array<{
|
|
287
|
+
id: string;
|
|
275
288
|
name: string;
|
|
276
289
|
input: Record<string, unknown>;
|
|
277
290
|
output: unknown;
|
|
291
|
+
error?: string;
|
|
278
292
|
}>;
|
|
279
293
|
usage: AgenticLoopUsage;
|
|
280
294
|
finishReason: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.11.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": {
|