@juspay/neurolink 13.5.1 → 13.6.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 +3 -3
- package/dist/browser/neurolink.min.js +421 -421
- package/dist/core/baseProvider.d.ts +3 -1
- package/dist/core/baseProvider.js +28 -8
- package/dist/core/modules/ToolsManager.js +11 -3
- package/dist/core/nativeGenerateLoop.d.ts +2 -0
- package/dist/core/nativeGenerateLoop.js +34 -8
- package/dist/providers/openaiChatCompletionsBase.js +25 -14
- package/dist/tools/toolDiscovery.js +2 -1
- package/dist/tools/toolPolicy.js +22 -2
- package/dist/types/config.d.ts +19 -0
- package/dist/types/generate.d.ts +7 -1
- package/dist/types/toolResolution.d.ts +5 -1
- package/package.json +1 -1
|
@@ -152,7 +152,9 @@ export declare abstract class BaseProvider implements AIProvider {
|
|
|
152
152
|
private sortToolRecord;
|
|
153
153
|
/**
|
|
154
154
|
* On-demand discovery (`tools.discovery: true`): defer external MCP tool
|
|
155
|
-
* schemas
|
|
155
|
+
* schemas — or, with `tools.discoveryScope: "all"`, every non-built-in
|
|
156
|
+
* tool — behind one `search_tools` meta-tool, except names matching
|
|
157
|
+
* `tools.discoveryAlwaysVisible`. Built-in tools, per-call
|
|
156
158
|
* tools, explicitly whitelisted tools, and session-pinned (previously
|
|
157
159
|
* discovered) tools always stay hot. No-op when discovery is off — with a
|
|
158
160
|
* one-time WARN when the catalog is large enough that selection accuracy
|
|
@@ -1246,7 +1246,9 @@ export class BaseProvider {
|
|
|
1246
1246
|
}
|
|
1247
1247
|
/**
|
|
1248
1248
|
* On-demand discovery (`tools.discovery: true`): defer external MCP tool
|
|
1249
|
-
* schemas
|
|
1249
|
+
* schemas — or, with `tools.discoveryScope: "all"`, every non-built-in
|
|
1250
|
+
* tool — behind one `search_tools` meta-tool, except names matching
|
|
1251
|
+
* `tools.discoveryAlwaysVisible`. Built-in tools, per-call
|
|
1250
1252
|
* tools, explicitly whitelisted tools, and session-pinned (previously
|
|
1251
1253
|
* discovered) tools always stay hot. No-op when discovery is off — with a
|
|
1252
1254
|
* one-time WARN when the catalog is large enough that selection accuracy
|
|
@@ -1273,8 +1275,13 @@ export class BaseProvider {
|
|
|
1273
1275
|
}
|
|
1274
1276
|
return tools;
|
|
1275
1277
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
+
// "external" defers only attached MCP servers' tools; "all" defers every
|
|
1279
|
+
// tool in the record except the built-ins.
|
|
1280
|
+
const builtinNames = new Set(Object.keys(this.directTools ?? {}));
|
|
1281
|
+
const candidateNames = policy.discoveryScope === "all"
|
|
1282
|
+
? Object.keys(tools).filter((name) => !builtinNames.has(name))
|
|
1283
|
+
: (this.neurolink?.getExternalMCPTools() ?? []).map((t) => t.name);
|
|
1284
|
+
if (candidateNames.length === 0) {
|
|
1278
1285
|
return tools;
|
|
1279
1286
|
}
|
|
1280
1287
|
// Session pinning requires a caller-provided sessionId. Without one there
|
|
@@ -1305,12 +1312,15 @@ export class BaseProvider {
|
|
|
1305
1312
|
explicitPatterns.push(toolChoice.toolName);
|
|
1306
1313
|
}
|
|
1307
1314
|
const explicitMatcher = explicitPatterns.length > 0 ? toolNameMatcher(explicitPatterns) : null;
|
|
1308
|
-
const
|
|
1309
|
-
|
|
1310
|
-
|
|
1315
|
+
const alwaysVisiblePatterns = policy.discoveryAlwaysVisible ?? [];
|
|
1316
|
+
const alwaysVisibleMatcher = alwaysVisiblePatterns.length > 0
|
|
1317
|
+
? toolNameMatcher(alwaysVisiblePatterns)
|
|
1318
|
+
: null;
|
|
1319
|
+
const deferrableNames = candidateNames.filter((name) => name in tools &&
|
|
1311
1320
|
!perCallNames.has(name) &&
|
|
1312
|
-
!(explicitMatcher ? explicitMatcher(name) : false)
|
|
1313
|
-
|
|
1321
|
+
!(explicitMatcher ? explicitMatcher(name) : false) &&
|
|
1322
|
+
!(alwaysVisibleMatcher ? alwaysVisibleMatcher(name) : false));
|
|
1323
|
+
const partitioned = partitionToolsForDiscovery(tools, {
|
|
1314
1324
|
deferrableNames,
|
|
1315
1325
|
pinnedNames,
|
|
1316
1326
|
onHydrate: (names) => {
|
|
@@ -1319,6 +1329,16 @@ export class BaseProvider {
|
|
|
1319
1329
|
}
|
|
1320
1330
|
},
|
|
1321
1331
|
});
|
|
1332
|
+
// The meta-tool is built after the event wrappers ran, so without this
|
|
1333
|
+
// a search_tools call never reaches tool:start / tool:end listeners.
|
|
1334
|
+
const metaTool = partitioned["search_tools"];
|
|
1335
|
+
if (isDiscoveryMetaTool(metaTool)) {
|
|
1336
|
+
partitioned["search_tools"] =
|
|
1337
|
+
this.toolsManager.wrapExternalToolsWithEvents({
|
|
1338
|
+
search_tools: metaTool,
|
|
1339
|
+
})["search_tools"];
|
|
1340
|
+
}
|
|
1341
|
+
return partitioned;
|
|
1322
1342
|
}
|
|
1323
1343
|
static warnedLargeCatalog = false;
|
|
1324
1344
|
warnLargeCatalogOnce(toolCount) {
|
|
@@ -512,6 +512,14 @@ export class ToolsManager {
|
|
|
512
512
|
const idField = typeof toolCallId === "string" && toolCallId.length > 0
|
|
513
513
|
? { toolCallId }
|
|
514
514
|
: {};
|
|
515
|
+
// Same per-invocation id executeTool gives registered tools, so a
|
|
516
|
+
// listener can pair this start with its end.
|
|
517
|
+
const eventIds = {
|
|
518
|
+
...idField,
|
|
519
|
+
executionId: `${toolName}-${Date.now()}-${Math.random()
|
|
520
|
+
.toString(36)
|
|
521
|
+
.slice(2, 11)}`,
|
|
522
|
+
};
|
|
515
523
|
return withSpan({
|
|
516
524
|
name: toolSpanName(toolName),
|
|
517
525
|
tracer: tracers.mcp,
|
|
@@ -521,7 +529,7 @@ export class ToolsManager {
|
|
|
521
529
|
const startTime = Date.now();
|
|
522
530
|
this.emitToolEvent("tool:start", toolName, {
|
|
523
531
|
input: params,
|
|
524
|
-
...
|
|
532
|
+
...eventIds,
|
|
525
533
|
});
|
|
526
534
|
let result;
|
|
527
535
|
try {
|
|
@@ -533,7 +541,7 @@ export class ToolsManager {
|
|
|
533
541
|
error: errorMsg,
|
|
534
542
|
success: false,
|
|
535
543
|
responseTime: Date.now() - startTime,
|
|
536
|
-
...
|
|
544
|
+
...eventIds,
|
|
537
545
|
});
|
|
538
546
|
throw error;
|
|
539
547
|
}
|
|
@@ -549,7 +557,7 @@ export class ToolsManager {
|
|
|
549
557
|
success: isErrorText === undefined,
|
|
550
558
|
...(isErrorText !== undefined ? { error: isErrorText } : {}),
|
|
551
559
|
responseTime: Date.now() - startTime,
|
|
552
|
-
...
|
|
560
|
+
...eventIds,
|
|
553
561
|
});
|
|
554
562
|
return result;
|
|
555
563
|
});
|
|
@@ -84,6 +84,8 @@ export declare const toPrepareStepRecord: (step: {
|
|
|
84
84
|
export declare const hasNativeDoGenerate: (value: unknown) => value is {
|
|
85
85
|
doGenerate: (options: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
86
86
|
};
|
|
87
|
+
/** A tool's inputSchema with its lazy (function) form, if any, resolved. */
|
|
88
|
+
export declare const resolveToolInputSchema: (schema: Tool["inputSchema"]) => Exclude<Tool["inputSchema"], (...args: never[]) => unknown>;
|
|
87
89
|
/**
|
|
88
90
|
* Spell a JSON Schema into the conversation's system turn.
|
|
89
91
|
*
|
|
@@ -17,6 +17,7 @@ import { observeGeneration } from "../telemetry/observation.js";
|
|
|
17
17
|
import { StepSpans, withGeneration } from "../telemetry/withSpan.js";
|
|
18
18
|
import { logger } from "../utils/logger.js";
|
|
19
19
|
import { guardToolExecutor } from "./toolExecutionGuards.js";
|
|
20
|
+
import { resolveLiveTool } from "../tools/toolDiscovery.js";
|
|
20
21
|
const DEFAULT_TOOL_CHOICE_STEPS = 1;
|
|
21
22
|
/**
|
|
22
23
|
* A choice that compels a tool call: `"required"` or a named tool, in either
|
|
@@ -74,9 +75,9 @@ const warnUndeclaredForcedTool = (toolName, step, source) => {
|
|
|
74
75
|
};
|
|
75
76
|
/**
|
|
76
77
|
* The names this request actually carries, in the record shape
|
|
77
|
-
* `declaredTools` takes.
|
|
78
|
-
*
|
|
79
|
-
*
|
|
78
|
+
* `declaredTools` takes. `args.toolsRecord` can hold more than is declared
|
|
79
|
+
* (discovery hydrates into it), so only the sent declarations answer "is it
|
|
80
|
+
* offered".
|
|
80
81
|
* Null prototype: a tool may be named `__proto__` or `constructor`.
|
|
81
82
|
*/
|
|
82
83
|
const declaredToolRecord = (tools) => {
|
|
@@ -336,6 +337,8 @@ const parseToolInput = (raw) => {
|
|
|
336
337
|
return { input: {}, error: "arguments were not valid JSON" };
|
|
337
338
|
}
|
|
338
339
|
};
|
|
340
|
+
/** A tool's inputSchema with its lazy (function) form, if any, resolved. */
|
|
341
|
+
export const resolveToolInputSchema = (schema) => typeof schema === "function" ? resolveToolInputSchema(schema()) : schema;
|
|
339
342
|
/**
|
|
340
343
|
* Validate parsed input against the tool's own schema when it exposes one.
|
|
341
344
|
*
|
|
@@ -346,8 +349,12 @@ const parseToolInput = (raw) => {
|
|
|
346
349
|
* validator this loop has no business carrying.
|
|
347
350
|
*/
|
|
348
351
|
const validateToolInput = (tool, input) => {
|
|
349
|
-
const schema = tool?.inputSchema
|
|
350
|
-
|
|
352
|
+
const schema = tool?.inputSchema
|
|
353
|
+
? resolveToolInputSchema(tool.inputSchema)
|
|
354
|
+
: undefined;
|
|
355
|
+
if (!schema ||
|
|
356
|
+
!("safeParse" in schema) ||
|
|
357
|
+
typeof schema.safeParse !== "function") {
|
|
351
358
|
return undefined;
|
|
352
359
|
}
|
|
353
360
|
const result = schema.safeParse(input);
|
|
@@ -478,11 +485,28 @@ async function runGenerateSteps(args, toolExecutionSummaries, stepSpans) {
|
|
|
478
485
|
// answer is that result — not a thrown turn.
|
|
479
486
|
let preReask;
|
|
480
487
|
const hasTools = Boolean(args.tools && args.tools.length > 0);
|
|
488
|
+
// The declarations actually sent. Starts as the caller's list and grows when
|
|
489
|
+
// a tool joins toolsRecord mid-turn (discovery loads tools into it).
|
|
490
|
+
const liveTools = args.tools ? [...args.tools] : undefined;
|
|
491
|
+
const declaredNames = declaredToolRecord(args.tools);
|
|
481
492
|
// Completed-step records for `prepareStep`; one per step that returned.
|
|
482
493
|
const stepRecords = [];
|
|
483
494
|
for (let step = 0; step < args.maxSteps; step++) {
|
|
484
495
|
steps = step + 1;
|
|
485
496
|
stepSpans.begin(steps);
|
|
497
|
+
if (liveTools && args.declareTool) {
|
|
498
|
+
const loaded = [];
|
|
499
|
+
for (const name of Object.keys(args.toolsRecord)) {
|
|
500
|
+
if (!declaredNames[name]) {
|
|
501
|
+
liveTools.push(args.declareTool(name, args.toolsRecord[name]));
|
|
502
|
+
declaredNames[name] = true;
|
|
503
|
+
loaded.push(name);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
if (loaded.length > 0) {
|
|
507
|
+
logger.debug(`[nativeGenerateLoop] ${loaded.length} tool(s) hydrated mid-turn via discovery: ${loaded.join(", ")}`);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
486
510
|
// The forced-choice window and the caller's hook are resolved BEFORE the
|
|
487
511
|
// re-ask override below: the re-ask has to win, since its whole point is
|
|
488
512
|
// a request with tools disabled.
|
|
@@ -498,7 +522,7 @@ async function runGenerateSteps(args, toolExecutionSummaries, stepSpans) {
|
|
|
498
522
|
steps: stepRecords,
|
|
499
523
|
maxSteps: args.maxSteps,
|
|
500
524
|
model: args.modelId,
|
|
501
|
-
declaredTools: declaredToolRecord(
|
|
525
|
+
declaredTools: declaredToolRecord(liveTools),
|
|
502
526
|
...(args.abortSignal ? { abortSignal: args.abortSignal } : {}),
|
|
503
527
|
})
|
|
504
528
|
: undefined;
|
|
@@ -519,7 +543,7 @@ async function runGenerateSteps(args, toolExecutionSummaries, stepSpans) {
|
|
|
519
543
|
}
|
|
520
544
|
const runThisStep = () => generateObservedStep(args, {
|
|
521
545
|
prompt: args.conversation,
|
|
522
|
-
...(
|
|
546
|
+
...(liveTools && liveTools.length > 0 ? { tools: liveTools } : {}),
|
|
523
547
|
// The v3 call option is an OBJECT — `{ type: "none" }`. Passing the
|
|
524
548
|
// bare string "none" type-checks against `unknown` and is then
|
|
525
549
|
// dropped by every converter that switches on `choice.type`, so the
|
|
@@ -688,7 +712,9 @@ async function runGenerateSteps(args, toolExecutionSummaries, stepSpans) {
|
|
|
688
712
|
const startTime = new Date();
|
|
689
713
|
const parsed = parseToolInput(call.input);
|
|
690
714
|
const input = parsed.input;
|
|
691
|
-
|
|
715
|
+
// resolveLiveTool also loads a deferred tool the model called by its
|
|
716
|
+
// catalog name without searching first.
|
|
717
|
+
const tool = resolveLiveTool(args.toolsRecord, name);
|
|
692
718
|
let output;
|
|
693
719
|
let failure;
|
|
694
720
|
const rejection = parsed.error ??
|
|
@@ -36,7 +36,7 @@ import { NoOutputGeneratedError } from "../utils/generationErrors.js";
|
|
|
36
36
|
import { buildNoOutputSentinel, stampNoOutputSpan, } from "../utils/noOutputSentinel.js";
|
|
37
37
|
import { composeAbortSignalsScoped, createTimeoutController, mergeAbortSignals, TimeoutError, } from "../utils/timeout.js";
|
|
38
38
|
import { resolveRequestKind } from "../core/resolveRequestKind.js";
|
|
39
|
-
import { appendJsonSchemaInstruction, hasNativeDoGenerate, resolveStepToolChoice, runNativeGenerateLoop, toPrepareStepRecord, } from "../core/nativeGenerateLoop.js";
|
|
39
|
+
import { appendJsonSchemaInstruction, hasNativeDoGenerate, resolveToolInputSchema, resolveStepToolChoice, runNativeGenerateLoop, toPrepareStepRecord, } from "../core/nativeGenerateLoop.js";
|
|
40
40
|
import { resolveToolExecutionRecords, toolCallsFromSummaries, } from "../core/toolExecutionRecorder.js";
|
|
41
41
|
import { convertZodToJsonSchema } from "../utils/schemaConversion.js";
|
|
42
42
|
import { coerceJsonToSchema, recoverScalarRoot, schemaAccepts, } from "../utils/json/coerce.js";
|
|
@@ -925,18 +925,19 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
925
925
|
? options.tools || (await this.getAllTools())
|
|
926
926
|
: {};
|
|
927
927
|
// v3 tool shape — the same one doGenerate already converts internally.
|
|
928
|
+
// Also handed to the loop, which declares tools discovery loads mid-turn.
|
|
929
|
+
const declareTool = (name, tool) => {
|
|
930
|
+
return {
|
|
931
|
+
type: "function",
|
|
932
|
+
name,
|
|
933
|
+
description: tool.description ?? "",
|
|
934
|
+
inputSchema: tool.inputSchema
|
|
935
|
+
? convertZodToJsonSchema(resolveToolInputSchema(tool.inputSchema))
|
|
936
|
+
: { type: "object", properties: {} },
|
|
937
|
+
};
|
|
938
|
+
};
|
|
928
939
|
const v3Tools = shouldUseTools
|
|
929
|
-
? Object.entries(toolsRecord).map(([name, t]) =>
|
|
930
|
-
const tool = t;
|
|
931
|
-
return {
|
|
932
|
-
type: "function",
|
|
933
|
-
name,
|
|
934
|
-
description: tool.description ?? "",
|
|
935
|
-
inputSchema: (tool.inputSchema
|
|
936
|
-
? convertZodToJsonSchema(tool.inputSchema)
|
|
937
|
-
: { type: "object", properties: {} }),
|
|
938
|
-
};
|
|
939
|
-
})
|
|
940
|
+
? Object.entries(toolsRecord).map(([name, t]) => declareTool(name, t))
|
|
940
941
|
: undefined;
|
|
941
942
|
const hasTools = !!v3Tools && v3Tools.length > 0;
|
|
942
943
|
// Structured output rides response_format, which is what Output.object did
|
|
@@ -964,6 +965,14 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
964
965
|
// model has already given. Dropping them is what makes `response_format`
|
|
965
966
|
// legal again on a vendor that refuses the two together.
|
|
966
967
|
withTools = true) => {
|
|
968
|
+
// What this pass sends: the initial declarations plus any the loop adds
|
|
969
|
+
// for tools discovery loads mid-turn, so the guard counts them too.
|
|
970
|
+
const passTools = withTools && v3Tools ? [...v3Tools] : undefined;
|
|
971
|
+
const declarePassTool = (name, tool) => {
|
|
972
|
+
const declaration = declareTool(name, tool);
|
|
973
|
+
passTools?.push(declaration);
|
|
974
|
+
return declaration;
|
|
975
|
+
};
|
|
967
976
|
return runNativeGenerateLoop({
|
|
968
977
|
doGenerate,
|
|
969
978
|
provider: this.providerName,
|
|
@@ -983,12 +992,14 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
983
992
|
// the estimate past the reclaim threshold and drop older tool
|
|
984
993
|
// exchanges out of a reformat request that would have fit.
|
|
985
994
|
getFixedOverheadTokens: () => estimateTokens(serializeForEstimate({
|
|
986
|
-
...(
|
|
995
|
+
...(passTools ? { tools: passTools } : {}),
|
|
987
996
|
responseFormat: format,
|
|
988
997
|
}), this.providerName),
|
|
989
998
|
}),
|
|
990
999
|
conversation: conv,
|
|
991
|
-
...(
|
|
1000
|
+
...(passTools
|
|
1001
|
+
? { tools: [...passTools], declareTool: declarePassTool }
|
|
1002
|
+
: {}),
|
|
992
1003
|
toolsRecord,
|
|
993
1004
|
...(withTools && hasTools && options.toolChoice
|
|
994
1005
|
? { toolChoice: resolveToolChoice(options, toolsRecord, true) }
|
|
@@ -244,7 +244,8 @@ export function resolveLiveTool(record, name) {
|
|
|
244
244
|
function buildSearchTool(entries, allTools, hotRecord, onHydrate) {
|
|
245
245
|
const catalog = renderCatalog(entries);
|
|
246
246
|
const searchTool = createAISDKTool({
|
|
247
|
-
description: `Search and load additional tools on demand. ${entries.length} more tools are available but not yet loaded
|
|
247
|
+
description: `Search and load additional tools on demand. ${entries.length} more tools are available but not yet loaded. ` +
|
|
248
|
+
`Before telling the user you cannot do something, check this catalog: if a listed tool fits, call it directly by its exact name, or call search_tools with a short description of the task.\n` +
|
|
248
249
|
`${catalog}\n` +
|
|
249
250
|
`Call this with a task description or an exact tool name; matching tools are loaded and become directly callable.`,
|
|
250
251
|
inputSchema: z.object({
|
package/dist/tools/toolPolicy.js
CHANGED
|
@@ -186,8 +186,28 @@ export function resolveToolPolicy(input) {
|
|
|
186
186
|
}
|
|
187
187
|
// --- discovery -----------------------------------------------------------
|
|
188
188
|
const discovery = instanceConfig?.discovery === true;
|
|
189
|
+
let discoveryScope = "external";
|
|
190
|
+
let discoveryAlwaysVisible = [];
|
|
189
191
|
if (discovery) {
|
|
190
192
|
sources.push("tools.discovery");
|
|
191
|
-
|
|
192
|
-
|
|
193
|
+
const configScope = instanceConfig?.discoveryScope;
|
|
194
|
+
if (configScope === "all") {
|
|
195
|
+
discoveryScope = "all";
|
|
196
|
+
}
|
|
197
|
+
else if (configScope !== undefined && configScope !== "external") {
|
|
198
|
+
warnOnce("shape:tools.discoveryScope", `[ToolPolicy] Ignoring unknown tools.discoveryScope; using "external"`, { received: configScope });
|
|
199
|
+
}
|
|
200
|
+
discoveryAlwaysVisible =
|
|
201
|
+
normalizeConfigList(instanceConfig?.discoveryAlwaysVisible, "tools.discoveryAlwaysVisible", false) ?? [];
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
enabled,
|
|
205
|
+
include,
|
|
206
|
+
includeBound,
|
|
207
|
+
exclude,
|
|
208
|
+
discovery,
|
|
209
|
+
discoveryScope,
|
|
210
|
+
discoveryAlwaysVisible,
|
|
211
|
+
sources,
|
|
212
|
+
};
|
|
193
213
|
}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -446,6 +446,25 @@ export type ToolConfig = {
|
|
|
446
446
|
* Default: false.
|
|
447
447
|
*/
|
|
448
448
|
discovery?: boolean;
|
|
449
|
+
/**
|
|
450
|
+
* Which tools `discovery` may defer.
|
|
451
|
+
* - `"external"`: tools of servers attached with `addExternalMCPServer`.
|
|
452
|
+
* - `"all"`: every tool in the request's record except the built-in tools,
|
|
453
|
+
* so tools registered with `registerTool`/`registerTools` and in-process
|
|
454
|
+
* MCP tools are deferred as well.
|
|
455
|
+
* Per-call tools, per-call whitelists, forced `toolChoice` tools and
|
|
456
|
+
* already-discovered tools stay hot in both scopes. Ignored unless
|
|
457
|
+
* `discovery` is true.
|
|
458
|
+
* Default: "external".
|
|
459
|
+
*/
|
|
460
|
+
discoveryScope?: "external" | "all";
|
|
461
|
+
/**
|
|
462
|
+
* Tool-name patterns (exact names or `*` globs) that `discovery` never
|
|
463
|
+
* defers, in either scope. E.g. `["utility-server_*"]` keeps every tool
|
|
464
|
+
* whose name starts with `utility-server_` in full on every request.
|
|
465
|
+
* Ignored unless `discovery` is true.
|
|
466
|
+
*/
|
|
467
|
+
discoveryAlwaysVisible?: string[];
|
|
449
468
|
/** Whether built-in tools should be disabled (equivalent to excluding all direct tools) */
|
|
450
469
|
disableBuiltinTools?: boolean;
|
|
451
470
|
/** Whether custom tools are allowed */
|
package/dist/types/generate.d.ts
CHANGED
|
@@ -1839,7 +1839,13 @@ export type NativeGenerateLoopArgs = {
|
|
|
1839
1839
|
/** Tool declarations in the v3 shape doGenerate already knows how to convert. */
|
|
1840
1840
|
tools?: Array<Record<string, unknown>>;
|
|
1841
1841
|
/** Registered tools, used to execute a call the model asks for. */
|
|
1842
|
-
toolsRecord: Record<string,
|
|
1842
|
+
toolsRecord: Record<string, Tool>;
|
|
1843
|
+
/**
|
|
1844
|
+
* Builds the v3 declaration for one tool. When set, every step declares any
|
|
1845
|
+
* tool that joined `toolsRecord` mid-turn (discovery's search_tools loads
|
|
1846
|
+
* tools into it), so the model can call what it just loaded.
|
|
1847
|
+
*/
|
|
1848
|
+
declareTool?: (name: string, tool: Tool) => Record<string, unknown>;
|
|
1843
1849
|
/** The turn's resolved tool choice, applied per step via `resolveStepToolChoice`. */
|
|
1844
1850
|
toolChoice?: unknown;
|
|
1845
1851
|
/** Leading steps a forced `toolChoice` stays in force (default 1). */
|
|
@@ -35,8 +35,12 @@ export type ResolvedToolPolicy = {
|
|
|
35
35
|
includeBound?: string[];
|
|
36
36
|
/** Denylist of tool-name patterns (exact names or `*` globs), applied after include. */
|
|
37
37
|
exclude: string[];
|
|
38
|
-
/** Defer
|
|
38
|
+
/** Defer tool schemas behind the search_tools meta-tool. */
|
|
39
39
|
discovery: boolean;
|
|
40
|
+
/** Which tools discovery may defer. Absent means "external". */
|
|
41
|
+
discoveryScope?: "external" | "all";
|
|
42
|
+
/** Tool-name patterns (exact names or `*` globs) discovery never defers. Absent means none. */
|
|
43
|
+
discoveryAlwaysVisible?: string[];
|
|
40
44
|
/** Which option/config sources contributed to this policy (telemetry/debugging). */
|
|
41
45
|
sources: string[];
|
|
42
46
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.6.0",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
|
|
6
6
|
"author": {
|