@juspay/neurolink 10.4.0 → 10.4.2
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 +382 -382
- package/dist/core/modules/GenerationHandler.d.ts +24 -0
- package/dist/core/modules/GenerationHandler.js +18 -3
- package/dist/lib/core/modules/GenerationHandler.d.ts +24 -0
- package/dist/lib/core/modules/GenerationHandler.js +18 -3
- package/dist/lib/providers/anthropic.js +18 -1
- package/dist/lib/providers/googleAiStudio.js +18 -1
- package/dist/lib/providers/googleNativeGemini3.d.ts +19 -1
- package/dist/lib/providers/googleNativeGemini3.js +61 -4
- package/dist/lib/providers/googleVertex.d.ts +48 -0
- package/dist/lib/providers/googleVertex.js +204 -108
- package/dist/lib/providers/openaiChatCompletionsBase.js +34 -2
- package/dist/lib/providers/openaiChatCompletionsClient.d.ts +11 -5
- package/dist/lib/providers/openaiChatCompletionsClient.js +14 -8
- package/dist/lib/tools/toolDiscovery.d.ts +25 -3
- package/dist/lib/tools/toolDiscovery.js +76 -4
- package/dist/lib/types/toolResolution.d.ts +10 -0
- package/dist/providers/anthropic.js +18 -1
- package/dist/providers/googleAiStudio.js +18 -1
- package/dist/providers/googleNativeGemini3.d.ts +19 -1
- package/dist/providers/googleNativeGemini3.js +61 -4
- package/dist/providers/googleVertex.d.ts +48 -0
- package/dist/providers/googleVertex.js +204 -108
- package/dist/providers/openaiChatCompletionsBase.js +34 -2
- package/dist/providers/openaiChatCompletionsClient.d.ts +11 -5
- package/dist/providers/openaiChatCompletionsClient.js +14 -8
- package/dist/tools/toolDiscovery.d.ts +25 -3
- package/dist/tools/toolDiscovery.js +76 -4
- package/dist/types/toolResolution.d.ts +10 -0
- package/package.json +1 -1
|
@@ -6,12 +6,19 @@
|
|
|
6
6
|
* requested tools, and previously discovered tools) plus ONE `search_tools`
|
|
7
7
|
* meta-tool whose description embeds a compact name+summary catalog of the
|
|
8
8
|
* deferred tools. Calling `search_tools` loads matching tools:
|
|
9
|
-
* - immediately into the live tool record
|
|
10
|
-
* record between agent-loop steps
|
|
11
|
-
*
|
|
9
|
+
* - immediately into the live tool record — the AI SDK path re-reads the
|
|
10
|
+
* record between agent-loop steps, and the native loops (Vertex
|
|
11
|
+
* Gemini/Claude, AI Studio, chat-completions, direct Anthropic) re-resolve
|
|
12
|
+
* against it on a dispatch miss and refresh their wire declarations per
|
|
13
|
+
* step — so discovered tools are callable on the very next step, and
|
|
12
14
|
* - into the session pin set (all providers include them in full on every
|
|
13
15
|
* subsequent call of the session).
|
|
14
16
|
*
|
|
17
|
+
* The record additionally carries a symbol-keyed {@link DeferredToolResolver}
|
|
18
|
+
* (see `resolveDeferredTool`) so a loop can hydrate a cataloged tool the
|
|
19
|
+
* model called directly by name WITHOUT a prior search_tools call — the
|
|
20
|
+
* catalog advertises exact names, so models legitimately do this.
|
|
21
|
+
*
|
|
15
22
|
* Evidence for this design: catalogs past ~30-50 tools measurably degrade
|
|
16
23
|
* tool-selection accuracy, and deferral+search both cuts definition tokens by
|
|
17
24
|
* ~85% and RAISES selection accuracy (Anthropic MCP-eval 49%→74% on Opus 4).
|
|
@@ -23,6 +30,14 @@ import { z } from "zod";
|
|
|
23
30
|
import { tool as createAISDKTool } from "../utils/tool.js";
|
|
24
31
|
import { convertZodToJsonSchema } from "../utils/schemaConversion.js";
|
|
25
32
|
import { logger } from "../utils/logger.js";
|
|
33
|
+
/**
|
|
34
|
+
* Symbol key under which the hot record carries its deferred-tool resolver.
|
|
35
|
+
* Symbol-keyed properties are skipped by Object.keys/entries, for-in, and
|
|
36
|
+
* JSON.stringify, so no declaration builder (or the AI SDK) ever sees the
|
|
37
|
+
* resolver as a tool. `Symbol.for` (global registry) keeps the key stable
|
|
38
|
+
* even if this module is loaded twice (ESM/CJS dual load of the bundle).
|
|
39
|
+
*/
|
|
40
|
+
const DEFERRED_TOOL_RESOLVER_KEY = Symbol.for("neurolink.deferredToolResolver");
|
|
26
41
|
/**
|
|
27
42
|
* Above this many tools, a WARN suggests enabling `tools.discovery` when it
|
|
28
43
|
* is off. Chosen from the measured degradation range (30-50 tools).
|
|
@@ -162,6 +177,35 @@ export function partitionToolsForDiscovery(tools, args) {
|
|
|
162
177
|
};
|
|
163
178
|
});
|
|
164
179
|
hot["search_tools"] = buildSearchTool(entries, tools, hot, args.onHydrate);
|
|
180
|
+
// Dispatch-miss escape hatch for the native agent loops: hydrate a
|
|
181
|
+
// deferred tool the model called directly by its cataloged name (the
|
|
182
|
+
// catalog advertises exact names, so this is legitimate model behavior,
|
|
183
|
+
// not hallucination). Hydration mutates the hot record and persists the
|
|
184
|
+
// session pin — identical side effects to a search_tools hit.
|
|
185
|
+
const resolver = (name) => {
|
|
186
|
+
if (name in hot) {
|
|
187
|
+
return hot[name];
|
|
188
|
+
}
|
|
189
|
+
if (!deferredSet.has(name)) {
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
192
|
+
const toolDef = tools[name];
|
|
193
|
+
if (!toolDef) {
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
hot[name] = toolDef;
|
|
197
|
+
args.onHydrate([name]);
|
|
198
|
+
logger.debug("[ToolDiscovery] Auto-hydrated deferred tool on direct call", {
|
|
199
|
+
name,
|
|
200
|
+
});
|
|
201
|
+
return toolDef;
|
|
202
|
+
};
|
|
203
|
+
Object.defineProperty(hot, DEFERRED_TOOL_RESOLVER_KEY, {
|
|
204
|
+
value: resolver,
|
|
205
|
+
enumerable: false,
|
|
206
|
+
writable: false,
|
|
207
|
+
configurable: true,
|
|
208
|
+
});
|
|
165
209
|
logger.debug("[ToolDiscovery] Deferred external tools behind search_tools", {
|
|
166
210
|
hotCount: Object.keys(hot).length - 1,
|
|
167
211
|
deferredCount: deferredNames.length,
|
|
@@ -169,6 +213,34 @@ export function partitionToolsForDiscovery(tools, args) {
|
|
|
169
213
|
});
|
|
170
214
|
return hot;
|
|
171
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Hydrate-and-return a deferred tool by name, when `record` was produced by
|
|
218
|
+
* `partitionToolsForDiscovery` and `name` is in its deferred catalog.
|
|
219
|
+
* Returns `undefined` for records without a resolver (discovery off) and for
|
|
220
|
+
* names that are genuinely unknown — callers keep their hallucinated-name
|
|
221
|
+
* handling for that case.
|
|
222
|
+
*/
|
|
223
|
+
export function resolveDeferredTool(record, name) {
|
|
224
|
+
if (!record) {
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
const resolver = record[DEFERRED_TOOL_RESOLVER_KEY];
|
|
228
|
+
return typeof resolver === "function"
|
|
229
|
+
? resolver(name)
|
|
230
|
+
: undefined;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Live tool lookup for native agent loops on a dispatch miss: first re-reads
|
|
234
|
+
* the record (a tool hydrated by search_tools after the loop built its
|
|
235
|
+
* pre-step snapshot), then falls back to auto-hydrating from the deferred
|
|
236
|
+
* catalog. Returns `undefined` only when the name is genuinely unknown.
|
|
237
|
+
*/
|
|
238
|
+
export function resolveLiveTool(record, name) {
|
|
239
|
+
if (!record) {
|
|
240
|
+
return undefined;
|
|
241
|
+
}
|
|
242
|
+
return record[name] ?? resolveDeferredTool(record, name);
|
|
243
|
+
}
|
|
172
244
|
function buildSearchTool(entries, allTools, hotRecord, onHydrate) {
|
|
173
245
|
const catalog = renderCatalog(entries);
|
|
174
246
|
const searchTool = createAISDKTool({
|
|
@@ -221,7 +293,7 @@ function buildSearchTool(entries, allTools, hotRecord, onHydrate) {
|
|
|
221
293
|
return {
|
|
222
294
|
found: loaded.length,
|
|
223
295
|
tools: loaded,
|
|
224
|
-
message: "These tools are now loaded for this session. Call them directly by name with arguments matching their inputSchema.
|
|
296
|
+
message: "These tools are now loaded for this session. Call them directly by name with arguments matching their inputSchema.",
|
|
225
297
|
};
|
|
226
298
|
},
|
|
227
299
|
});
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* `BaseProvider` that every generate/stream path passes through.
|
|
9
9
|
*/
|
|
10
10
|
import type { ToolConfig } from "./config.js";
|
|
11
|
+
import type { Tool } from "./tools.js";
|
|
11
12
|
/**
|
|
12
13
|
* The resolved, merged tool policy for one request. Produced by
|
|
13
14
|
* `resolveToolPolicy()` (src/lib/tools/toolPolicy.ts) and consumed by
|
|
@@ -71,3 +72,12 @@ export type DeferredToolIndexEntry = {
|
|
|
71
72
|
/** Originating MCP server id, when known. */
|
|
72
73
|
serverId?: string;
|
|
73
74
|
};
|
|
75
|
+
/**
|
|
76
|
+
* Resolver attached (under a symbol key, invisible to enumeration) to the
|
|
77
|
+
* hot tool record by `partitionToolsForDiscovery`. Given a deferred tool's
|
|
78
|
+
* name it hydrates that tool into the record, persists the session pin, and
|
|
79
|
+
* returns it — `undefined` when the name is not in the deferred catalog.
|
|
80
|
+
* Native agent loops call it on a dispatch miss so a model that calls a
|
|
81
|
+
* cataloged tool directly (without `search_tools` first) still succeeds.
|
|
82
|
+
*/
|
|
83
|
+
export type DeferredToolResolver = (name: string) => Tool | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "10.4.
|
|
3
|
+
"version": "10.4.2",
|
|
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": {
|