@juspay/neurolink 10.5.3 → 10.6.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 +12 -0
- package/dist/agent/agent.js +39 -8
- package/dist/agent/agentNetwork.js +62 -20
- package/dist/agent/agentToolRegistrar.d.ts +48 -0
- package/dist/agent/agentToolRegistrar.js +336 -0
- package/dist/agent/index.d.ts +3 -0
- package/dist/agent/index.js +4 -0
- package/dist/agent/isolatedAgentRunner.d.ts +73 -0
- package/dist/agent/isolatedAgentRunner.js +946 -0
- package/dist/agent/structuredRecovery.d.ts +30 -0
- package/dist/agent/structuredRecovery.js +104 -0
- package/dist/browser/neurolink.min.js +414 -398
- package/dist/cli/loop/optionsSchema.d.ts +1 -1
- package/dist/core/baseProvider.d.ts +8 -0
- package/dist/core/baseProvider.js +40 -19
- package/dist/core/modules/GenerationHandler.d.ts +2 -6
- package/dist/core/modules/GenerationHandler.js +10 -1
- package/dist/core/toolExecutionRecorder.d.ts +76 -0
- package/dist/core/toolExecutionRecorder.js +261 -0
- package/dist/evaluation/contextBuilder.js +6 -6
- package/dist/lib/agent/agent.js +39 -8
- package/dist/lib/agent/agentNetwork.js +62 -20
- package/dist/lib/agent/agentToolRegistrar.d.ts +48 -0
- package/dist/lib/agent/agentToolRegistrar.js +337 -0
- package/dist/lib/agent/index.d.ts +3 -0
- package/dist/lib/agent/index.js +4 -0
- package/dist/lib/agent/isolatedAgentRunner.d.ts +73 -0
- package/dist/lib/agent/isolatedAgentRunner.js +947 -0
- package/dist/lib/agent/structuredRecovery.d.ts +30 -0
- package/dist/lib/agent/structuredRecovery.js +105 -0
- package/dist/lib/core/baseProvider.d.ts +8 -0
- package/dist/lib/core/baseProvider.js +40 -19
- package/dist/lib/core/modules/GenerationHandler.d.ts +2 -6
- package/dist/lib/core/modules/GenerationHandler.js +10 -1
- package/dist/lib/core/toolExecutionRecorder.d.ts +76 -0
- package/dist/lib/core/toolExecutionRecorder.js +262 -0
- package/dist/lib/evaluation/contextBuilder.js +6 -6
- package/dist/lib/models/modelRegistry.d.ts +23 -0
- package/dist/lib/models/modelRegistry.js +62 -1
- package/dist/lib/models/modelResolver.js +1 -0
- package/dist/lib/neurolink.d.ts +80 -1
- package/dist/lib/neurolink.js +199 -37
- package/dist/lib/processors/media/index.js +0 -10
- package/dist/lib/providers/amazonBedrock.js +15 -2
- package/dist/lib/providers/anthropic.js +23 -11
- package/dist/lib/providers/googleAiStudio.js +8 -1
- package/dist/lib/providers/googleNativeGemini3.d.ts +2 -0
- package/dist/lib/providers/googleNativeGemini3.js +8 -1
- package/dist/lib/providers/googleVertex.js +56 -16
- package/dist/lib/providers/openaiChatCompletionsClient.js +18 -5
- package/dist/lib/tasks/autoresearchTaskExecutor.js +7 -6
- package/dist/lib/tasks/taskExecutor.js +2 -5
- package/dist/lib/types/agentNetwork.d.ts +23 -8
- package/dist/lib/types/generate.d.ts +62 -5
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/index.js +1 -0
- package/dist/lib/types/isolatedAgent.d.ts +365 -0
- package/dist/lib/types/isolatedAgent.js +12 -0
- package/dist/lib/types/model.d.ts +8 -0
- package/dist/lib/types/stream.d.ts +3 -1
- package/dist/lib/types/task.d.ts +3 -3
- package/dist/lib/utils/logger.d.ts +12 -3
- package/dist/lib/utils/logger.js +11 -3
- package/dist/lib/utils/transformationUtils.d.ts +14 -0
- package/dist/lib/utils/transformationUtils.js +33 -10
- package/dist/lib/voice/livekit/realtimeVoiceAgent.js +6 -3
- package/dist/models/modelRegistry.d.ts +23 -0
- package/dist/models/modelRegistry.js +62 -1
- package/dist/models/modelResolver.js +1 -0
- package/dist/neurolink.d.ts +80 -1
- package/dist/neurolink.js +199 -37
- package/dist/processors/media/index.js +0 -10
- package/dist/providers/amazonBedrock.js +15 -2
- package/dist/providers/anthropic.js +23 -11
- package/dist/providers/googleAiStudio.js +8 -1
- package/dist/providers/googleNativeGemini3.d.ts +2 -0
- package/dist/providers/googleNativeGemini3.js +8 -1
- package/dist/providers/googleVertex.js +56 -16
- package/dist/providers/openaiChatCompletionsClient.js +18 -5
- package/dist/tasks/autoresearchTaskExecutor.js +7 -6
- package/dist/tasks/taskExecutor.js +2 -5
- package/dist/types/agentNetwork.d.ts +23 -8
- package/dist/types/generate.d.ts +62 -5
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/isolatedAgent.d.ts +365 -0
- package/dist/types/isolatedAgent.js +11 -0
- package/dist/types/model.d.ts +8 -0
- package/dist/types/stream.d.ts +3 -1
- package/dist/types/task.d.ts +3 -3
- package/dist/utils/logger.d.ts +12 -3
- package/dist/utils/logger.js +11 -3
- package/dist/utils/transformationUtils.d.ts +14 -0
- package/dist/utils/transformationUtils.js +33 -10
- package/dist/voice/livekit/realtimeVoiceAgent.js +6 -3
- package/package.json +3 -2
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Isolated sub-agent runtime types: worker-mode instances, the
|
|
3
|
+
* runIsolatedAgent() two-pass runner, leashed legs/handles, waste detection,
|
|
4
|
+
* and host-loop delegation (registerAgentTool).
|
|
5
|
+
*
|
|
6
|
+
* Design contract: no product policy lives here — every tunable is an option
|
|
7
|
+
* with a sane default, and all shapes were validated against the three
|
|
8
|
+
* production consumers (Curator's research + log-analysis workers, Yama's
|
|
9
|
+
* ContextExplorerService). See docs/plans/2026-07-27-isolated-agent-runner-rfc.md.
|
|
10
|
+
*/
|
|
11
|
+
import type { z } from "zod";
|
|
12
|
+
import type { TokenUsage } from "./analytics.js";
|
|
13
|
+
import type { AgentDefinition } from "./agentNetwork.js";
|
|
14
|
+
import type { GenerateStopReason, ToolExecutionRecord } from "./generate.js";
|
|
15
|
+
/**
|
|
16
|
+
* A log event forwarded by a worker instance's log bridge.
|
|
17
|
+
*/
|
|
18
|
+
export type WorkerLogEvent = {
|
|
19
|
+
/** Caller-supplied tag identifying which worker produced the event. */
|
|
20
|
+
tag: string;
|
|
21
|
+
/** Log level ("debug" | "info" | "warn" | "error"). */
|
|
22
|
+
level: string;
|
|
23
|
+
/** Log message. */
|
|
24
|
+
message: string;
|
|
25
|
+
/** Epoch milliseconds. */
|
|
26
|
+
timestamp: number;
|
|
27
|
+
/** Structured payload attached to the log call, if any. */
|
|
28
|
+
data?: unknown;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Options for `NeuroLink.createWorkerInstance()`.
|
|
32
|
+
*
|
|
33
|
+
* A worker instance is a sub-agent-grade NeuroLink: conversation memory off,
|
|
34
|
+
* orchestration off, observability inherited from the creating instance with
|
|
35
|
+
* `autoDetectExternalProvider: true` + `skipLangfuseSpanProcessor: true`
|
|
36
|
+
* (so worker spans join the host's tracer without duplicate Langfuse
|
|
37
|
+
* exports), and an internal log bridge attached with a caller-supplied tag.
|
|
38
|
+
*/
|
|
39
|
+
export type WorkerInstanceOptions = {
|
|
40
|
+
/** Tag stamped on every forwarded log event (default "worker"). */
|
|
41
|
+
logTag?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Log bridge sink. Fire-and-forget: listener errors never disrupt the
|
|
44
|
+
* worker.
|
|
45
|
+
*
|
|
46
|
+
* KNOWN LIMITATION: the underlying NeuroLink logger is process-global with
|
|
47
|
+
* a single active emitter, so this bridge receives ALL NeuroLink log
|
|
48
|
+
* events emitted in the process (host, other workers, MCP) for the
|
|
49
|
+
* worker's lifetime, each stamped with this worker's `tag`. The tag
|
|
50
|
+
* identifies which bridge forwarded the event, not which instance emitted
|
|
51
|
+
* it. Per-instance log attribution requires per-instance logger routing —
|
|
52
|
+
* tracked as follow-up work in the RFC.
|
|
53
|
+
*/
|
|
54
|
+
onLog?: (event: WorkerLogEvent) => void;
|
|
55
|
+
/**
|
|
56
|
+
* Share the creating instance's tool registry (custom tools + in-memory
|
|
57
|
+
* MCP servers) so the worker calls tools through the host's existing
|
|
58
|
+
* connections. Default: true.
|
|
59
|
+
*/
|
|
60
|
+
shareToolRegistry?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Extra constructor config merged into the worker (e.g. `credentials`,
|
|
63
|
+
* `tools`, `modelPool`). Worker-mode fields (memory off, orchestration
|
|
64
|
+
* off, observability flags) always win over this merge.
|
|
65
|
+
*/
|
|
66
|
+
config?: Record<string, unknown>;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Structured-extraction configuration for an isolated agent run.
|
|
70
|
+
*
|
|
71
|
+
* The extraction pass always runs tools-off on its own timeout, fed from the
|
|
72
|
+
* run's tool-execution records — so a research generate that died on a
|
|
73
|
+
* provider error still extracts from the records instead of losing the run.
|
|
74
|
+
*/
|
|
75
|
+
export type IsolatedAgentExtraction = {
|
|
76
|
+
/** Local validator (lenient — may carry defaults/catch). Required. */
|
|
77
|
+
schema: z.ZodSchema;
|
|
78
|
+
/**
|
|
79
|
+
* Provider-attached wire schema (strict: no defaults/catch, which many
|
|
80
|
+
* providers reject in constrained decoding). Falls back to `schema`.
|
|
81
|
+
*/
|
|
82
|
+
wireSchema?: z.ZodSchema;
|
|
83
|
+
/**
|
|
84
|
+
* Human/model-readable JSON shape description used in the extraction
|
|
85
|
+
* prompt and in corrective retries alongside validation errors.
|
|
86
|
+
*/
|
|
87
|
+
shapeDoc?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Normalizer applied to every recovery candidate before validation
|
|
90
|
+
* (e.g. wrap a bare top-level array into the expected envelope).
|
|
91
|
+
*/
|
|
92
|
+
coerce?: (candidate: unknown) => unknown;
|
|
93
|
+
/** Corrective re-ask attempts after ladder failure (default 2). */
|
|
94
|
+
maxRetries?: number;
|
|
95
|
+
/**
|
|
96
|
+
* Per-attempt extraction timeout in ms (default 60_000). Never carved out
|
|
97
|
+
* of the research budget.
|
|
98
|
+
*/
|
|
99
|
+
timeoutMs?: number;
|
|
100
|
+
/**
|
|
101
|
+
* Phase-level deadline bounding ALL extraction attempts (ms). Defaults to
|
|
102
|
+
* `(maxRetries + 1) × timeoutMs` — i.e. 180s at the defaults. Callers that
|
|
103
|
+
* derive an outer tool-execution ceiling from the leg budget must add this
|
|
104
|
+
* bound (plus the ~20s next-plan ask in leashed mode) on top of the
|
|
105
|
+
* research budget.
|
|
106
|
+
*/
|
|
107
|
+
totalTimeoutMs?: number;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Definition of an isolated sub-agent: a standard AgentDefinition plus
|
|
111
|
+
* optional structured extraction.
|
|
112
|
+
*/
|
|
113
|
+
export type IsolatedAgentDefinition = AgentDefinition & {
|
|
114
|
+
extraction?: IsolatedAgentExtraction;
|
|
115
|
+
};
|
|
116
|
+
/** Per-run overrides for an isolated agent run (internal-caller knobs). */
|
|
117
|
+
export type AgentRunOverrides = {
|
|
118
|
+
/** Wall-clock cap for the research pass (ms). */
|
|
119
|
+
turnTimeoutMs?: number;
|
|
120
|
+
/** Stall watchdog for the research pass (ms). */
|
|
121
|
+
stallTimeoutMs?: number;
|
|
122
|
+
/** Wrap-up lead for the research pass (ms). */
|
|
123
|
+
wrapupTimeLeadMs?: number;
|
|
124
|
+
/** Max agentic steps for the research pass. */
|
|
125
|
+
maxSteps?: number;
|
|
126
|
+
/** Max output tokens per model call. */
|
|
127
|
+
maxTokens?: number;
|
|
128
|
+
/** Model override (wins over the definition). */
|
|
129
|
+
model?: string;
|
|
130
|
+
/** Provider override (wins over the definition). */
|
|
131
|
+
provider?: string;
|
|
132
|
+
};
|
|
133
|
+
/** Leg budget for leashed mode. Setting either enables leashed mode. */
|
|
134
|
+
export type AgentLegOptions = {
|
|
135
|
+
/** Wall-clock budget for one leg (ms). */
|
|
136
|
+
budgetMs?: number;
|
|
137
|
+
/** Tool-call budget for one leg. */
|
|
138
|
+
budgetToolCalls?: number;
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* Mechanical waste-signature thresholds, checked per tool call. A tripped
|
|
142
|
+
* signature ends the leg early with `wasteSignals` populated.
|
|
143
|
+
*/
|
|
144
|
+
export type AgentWasteThresholds = {
|
|
145
|
+
/**
|
|
146
|
+
* Max times the same call hash (tool + normalized params) may be seen in
|
|
147
|
+
* one run before tripping (default 2 — the third identical call trips).
|
|
148
|
+
*/
|
|
149
|
+
duplicateCallLimit?: number;
|
|
150
|
+
/** Consecutive empty/zero-result calls before tripping (default 3). */
|
|
151
|
+
emptyResultStreakLimit?: number;
|
|
152
|
+
/** Consecutive error results before tripping (default 3). */
|
|
153
|
+
errorStreakLimit?: number;
|
|
154
|
+
/**
|
|
155
|
+
* Calls without a new distinct result payload before tripping
|
|
156
|
+
* (default 8).
|
|
157
|
+
*/
|
|
158
|
+
noNewResultsLimit?: number;
|
|
159
|
+
};
|
|
160
|
+
/** Lifecycle event types emitted by an isolated agent run. */
|
|
161
|
+
export type AgentRunEventType = "start" | "tool_call" | "tool_result" | "phase" | "wrapup" | "leg_end" | "waste" | "complete" | "error";
|
|
162
|
+
/**
|
|
163
|
+
* Lifecycle event for `AgentRunOptions.onEvent`. Fire-and-forget — listener
|
|
164
|
+
* errors never break the run.
|
|
165
|
+
*
|
|
166
|
+
* Note: `tool_call` and `tool_result` both fire AFTER the execution
|
|
167
|
+
* completes (they are driven by the capture record) — a long-running tool
|
|
168
|
+
* emits nothing until it returns. Treat them as accounting events, not
|
|
169
|
+
* live started/finished signals.
|
|
170
|
+
*/
|
|
171
|
+
export type AgentRunEvent = {
|
|
172
|
+
type: AgentRunEventType;
|
|
173
|
+
/** Run id (also the default tool-context sessionId). */
|
|
174
|
+
runId: string;
|
|
175
|
+
/** Agent definition id. */
|
|
176
|
+
agentId: string;
|
|
177
|
+
/** Epoch milliseconds. */
|
|
178
|
+
timestamp: number;
|
|
179
|
+
/** Current phase, on `phase` events. */
|
|
180
|
+
phase?: "research" | "extraction";
|
|
181
|
+
/** Tool name, on tool_call/tool_result events. */
|
|
182
|
+
toolName?: string;
|
|
183
|
+
/** Tool params, on tool_call events. */
|
|
184
|
+
params?: unknown;
|
|
185
|
+
/** Bounded result summary, on tool_result events. */
|
|
186
|
+
resultSummary?: string;
|
|
187
|
+
/** Whether the tool result was an error, on tool_result events. */
|
|
188
|
+
isError?: boolean;
|
|
189
|
+
/** Leg index, on leg_end events (leashed mode). */
|
|
190
|
+
legIndex?: number;
|
|
191
|
+
/** Tripped waste signatures, on waste events. */
|
|
192
|
+
wasteSignals?: string[];
|
|
193
|
+
/** Error message, on error events. */
|
|
194
|
+
error?: string;
|
|
195
|
+
/** Final status, on complete events. */
|
|
196
|
+
status?: AgentRunStatus;
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Options for one isolated agent run (`NeuroLink.runIsolatedAgent`).
|
|
200
|
+
*/
|
|
201
|
+
export type AgentRunOptions = {
|
|
202
|
+
/**
|
|
203
|
+
* Parent cancellation. When provided it MUST be honored: an aborted parent
|
|
204
|
+
* stops research AND extraction cleanly, the outcome reports the run was
|
|
205
|
+
* cancelled, and no ghost workers survive.
|
|
206
|
+
*/
|
|
207
|
+
abortSignal?: AbortSignal;
|
|
208
|
+
/** Per-run overrides (internal-caller knobs). */
|
|
209
|
+
overrides?: AgentRunOverrides;
|
|
210
|
+
/**
|
|
211
|
+
* Set on the worker for EVERY tool call (merged into the worker's tool
|
|
212
|
+
* context), including a caller-supplied `sessionId`; the run id is used
|
|
213
|
+
* when no sessionId is supplied.
|
|
214
|
+
*/
|
|
215
|
+
toolContext?: Record<string, unknown>;
|
|
216
|
+
/** Lifecycle event stream. Fire-and-forget. */
|
|
217
|
+
onEvent?: (event: AgentRunEvent) => void;
|
|
218
|
+
/** Leg budget — enables leashed mode. */
|
|
219
|
+
leg?: AgentLegOptions;
|
|
220
|
+
/** TTL for a leashed handle in ms (default 600_000 = 10 min). */
|
|
221
|
+
handleTtlMs?: number;
|
|
222
|
+
/** Waste-signature thresholds (defaults apply when omitted). */
|
|
223
|
+
waste?: AgentWasteThresholds;
|
|
224
|
+
/**
|
|
225
|
+
* Bounds for the run's tool execution records. Raise `maxResultChars`
|
|
226
|
+
* when the CALLER verifies evidence from `toolExecutions` (raw result
|
|
227
|
+
* texts must be available up to the cap).
|
|
228
|
+
*/
|
|
229
|
+
capture?: {
|
|
230
|
+
maxResultChars?: number;
|
|
231
|
+
maxRecords?: number;
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
/** Terminal (or leg-boundary) status of an isolated agent run. */
|
|
235
|
+
export type AgentRunStatus = "completed" | "partial" | "in_progress" | "insufficient_data" | "error";
|
|
236
|
+
/** Per-leg accounting for leashed runs. */
|
|
237
|
+
export type AgentRunLegInfo = {
|
|
238
|
+
/** 0-based leg index. */
|
|
239
|
+
index: number;
|
|
240
|
+
/** Tool calls made this leg. */
|
|
241
|
+
toolCalls: number;
|
|
242
|
+
/** Wall-clock duration of this leg (ms). */
|
|
243
|
+
durationMs: number;
|
|
244
|
+
};
|
|
245
|
+
/** Cumulative budget accounting for leashed runs. */
|
|
246
|
+
export type AgentRunBudget = {
|
|
247
|
+
/** Total wall-clock spent across legs (ms). */
|
|
248
|
+
spentMs: number;
|
|
249
|
+
/** Remaining wall-clock vs the leg budget (ms; 0 when exhausted). */
|
|
250
|
+
remainingMs: number;
|
|
251
|
+
/** Total tool calls across legs. */
|
|
252
|
+
spentToolCalls: number;
|
|
253
|
+
};
|
|
254
|
+
/**
|
|
255
|
+
* Outcome of an isolated agent run.
|
|
256
|
+
*
|
|
257
|
+
* Delivery guarantee: a run with a non-empty execution record never returns
|
|
258
|
+
* an empty result — when extraction is unrecoverable, `data` carries a
|
|
259
|
+
* mechanical digest (which tools ran, ok/failed counts, bounded excerpts of
|
|
260
|
+
* successful payloads).
|
|
261
|
+
*/
|
|
262
|
+
export type AgentRunOutcome = {
|
|
263
|
+
status: AgentRunStatus;
|
|
264
|
+
/** Schema-valid extraction output when `extraction.schema` was given. */
|
|
265
|
+
data?: unknown;
|
|
266
|
+
/** Final research-pass text (the worker's own narrative). */
|
|
267
|
+
content?: string;
|
|
268
|
+
/** Why the research turn ended (honest — see GenerateStopReason). */
|
|
269
|
+
stopReason?: GenerateStopReason | string;
|
|
270
|
+
/**
|
|
271
|
+
* Real tool execution records (params/results/timing). Terminal outcomes
|
|
272
|
+
* carry the WHOLE run's records (all legs — what `data` was built from);
|
|
273
|
+
* `in_progress` legs carry this leg's records only.
|
|
274
|
+
*/
|
|
275
|
+
toolExecutions: ToolExecutionRecord[];
|
|
276
|
+
/** Aggregated token usage for the run (research + extraction). */
|
|
277
|
+
usage?: TokenUsage;
|
|
278
|
+
/** Wall-clock duration of this call (ms). */
|
|
279
|
+
durationMs: number;
|
|
280
|
+
/** Present when extraction fell back through the recovery ladder. */
|
|
281
|
+
extractionSource?: string;
|
|
282
|
+
/** Extraction/validation error summary when data is a mechanical digest. */
|
|
283
|
+
extractionError?: string;
|
|
284
|
+
/** Resume handle (status "in_progress" only). */
|
|
285
|
+
handle?: string;
|
|
286
|
+
/** This leg's accounting. */
|
|
287
|
+
leg?: AgentRunLegInfo;
|
|
288
|
+
/** One-line query→outcome summaries for this leg. */
|
|
289
|
+
delta?: string[];
|
|
290
|
+
/** The worker's own stated intent for the next leg. */
|
|
291
|
+
nextPlan?: string;
|
|
292
|
+
/** Tripped waste signatures, if any. */
|
|
293
|
+
wasteSignals?: string[];
|
|
294
|
+
/** Cumulative budget accounting. */
|
|
295
|
+
budget?: AgentRunBudget;
|
|
296
|
+
};
|
|
297
|
+
/** Where a recovered value came from, for observability and outcome fields. */
|
|
298
|
+
export type StructuredRecoverySource = "structured-data" | "raw-json" | "json-fence" | "brace-span" | "top-level-array";
|
|
299
|
+
/** One recovery candidate: source label + parsed (uncoerced) value. */
|
|
300
|
+
export type StructuredRecoveryCandidate = {
|
|
301
|
+
source: StructuredRecoverySource;
|
|
302
|
+
value: unknown;
|
|
303
|
+
};
|
|
304
|
+
/** Result of a structured recovery attempt. */
|
|
305
|
+
export type StructuredRecoveryResult = {
|
|
306
|
+
/** Schema-valid data, when any candidate survived validation. */
|
|
307
|
+
data?: unknown;
|
|
308
|
+
/** Which ladder rung produced the winning candidate. */
|
|
309
|
+
source?: StructuredRecoverySource;
|
|
310
|
+
/** Validation error summaries per failed candidate (for re-ask prompts). */
|
|
311
|
+
errors: string[];
|
|
312
|
+
};
|
|
313
|
+
/** Mechanical digest shape (delivery-guarantee fallback payload). */
|
|
314
|
+
export type AgentMechanicalDigest = {
|
|
315
|
+
kind: "mechanical-digest";
|
|
316
|
+
toolsRun: Record<string, {
|
|
317
|
+
calls: number;
|
|
318
|
+
ok: number;
|
|
319
|
+
failed: number;
|
|
320
|
+
}>;
|
|
321
|
+
excerpts: Array<{
|
|
322
|
+
toolName: string;
|
|
323
|
+
params: string;
|
|
324
|
+
resultText: string;
|
|
325
|
+
}>;
|
|
326
|
+
};
|
|
327
|
+
/**
|
|
328
|
+
* Options for `NeuroLink.registerAgentTool()` — wraps an isolated agent as a
|
|
329
|
+
* tool on the HOST instance so its existing generate() loop delegates
|
|
330
|
+
* without a second router generate.
|
|
331
|
+
*/
|
|
332
|
+
export type AgentToolRegistrationOptions = {
|
|
333
|
+
/** Tool name (default: the agent definition id). */
|
|
334
|
+
name?: string;
|
|
335
|
+
/**
|
|
336
|
+
* Max delegations to this tool per top-level generate() turn, counted in
|
|
337
|
+
* the loop itself. A refused call returns a recovery instruction, never a
|
|
338
|
+
* silent failure.
|
|
339
|
+
*/
|
|
340
|
+
maxDelegationsPerTurn?: number;
|
|
341
|
+
/**
|
|
342
|
+
* Max delegation depth (via tool context `agentDepth`). At the limit the
|
|
343
|
+
* tool is withheld from the request entirely.
|
|
344
|
+
*/
|
|
345
|
+
maxDepth?: number;
|
|
346
|
+
/**
|
|
347
|
+
* Process-wide concurrent delegation pool size. The pool is shared across
|
|
348
|
+
* all registered agent tools; the largest registered value wins (default
|
|
349
|
+
* 4) — registering raises the pool and can never lower it, so this is NOT
|
|
350
|
+
* a per-agent throttle. Nested delegations (agentDepth > 0) bypass the
|
|
351
|
+
* pool: the outer delegation already holds a slot, and queueing nested
|
|
352
|
+
* work behind a full pool would deadlock it.
|
|
353
|
+
*/
|
|
354
|
+
maxConcurrent?: number;
|
|
355
|
+
/** Queue timeout when the pool is saturated (ms, default 30_000). */
|
|
356
|
+
poolQueueTimeoutMs?: number;
|
|
357
|
+
/** Leashed-by-default leg budget for this tool. */
|
|
358
|
+
leg?: AgentLegOptions;
|
|
359
|
+
/** Handle TTL for leashed delegations (ms, default 600_000). */
|
|
360
|
+
handleTtlMs?: number;
|
|
361
|
+
/** Waste thresholds forwarded to each delegated run. */
|
|
362
|
+
waste?: AgentWasteThresholds;
|
|
363
|
+
/** Per-run overrides forwarded to each delegated run. */
|
|
364
|
+
overrides?: AgentRunOverrides;
|
|
365
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Isolated sub-agent runtime types: worker-mode instances, the
|
|
3
|
+
* runIsolatedAgent() two-pass runner, leashed legs/handles, waste detection,
|
|
4
|
+
* and host-loop delegation (registerAgentTool).
|
|
5
|
+
*
|
|
6
|
+
* Design contract: no product policy lives here — every tunable is an option
|
|
7
|
+
* with a sane default, and all shapes were validated against the three
|
|
8
|
+
* production consumers (Curator's research + log-analysis workers, Yama's
|
|
9
|
+
* ContextExplorerService). See docs/plans/2026-07-27-isolated-agent-runner-rfc.md.
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
package/dist/types/model.d.ts
CHANGED
|
@@ -122,6 +122,14 @@ export type ModelCapabilities = {
|
|
|
122
122
|
multimodal: boolean;
|
|
123
123
|
streaming: boolean;
|
|
124
124
|
jsonMode: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Whether the model accepts classic sampling parameters
|
|
127
|
+
* (`temperature` / `topP`). Reasoning-effort models (Claude Sonnet 5,
|
|
128
|
+
* Opus 4.7+, Fable 5 families) reject them. Optional: unset means
|
|
129
|
+
* supported, and `modelSupportsSamplingParams` falls back to the known
|
|
130
|
+
* family patterns.
|
|
131
|
+
*/
|
|
132
|
+
samplingParams?: boolean;
|
|
125
133
|
};
|
|
126
134
|
/**
|
|
127
135
|
* Model pricing information
|
package/dist/types/stream.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import type { JsonValue, UnknownRecord } from "./common.js";
|
|
|
10
10
|
import type { Content, ImageWithAltText } from "./content.js";
|
|
11
11
|
import type { ChatMessage } from "./conversation.js";
|
|
12
12
|
import type { StreamNoOutputSentinel } from "./noOutputSentinel.js";
|
|
13
|
-
import type { AdditionalMemoryUser, GenerateStopReason } from "./generate.js";
|
|
13
|
+
import type { AdditionalMemoryUser, GenerateStopReason, ToolExecutionCaptureOptions } from "./generate.js";
|
|
14
14
|
import type { AIModelProviderConfig, NeurolinkCredentials } from "./providers.js";
|
|
15
15
|
import type { TTSChunk, TTSOptions, TTSResult } from "./tts.js";
|
|
16
16
|
import type { STTOptions, STTResult } from "./stt.js";
|
|
@@ -354,6 +354,8 @@ export type StreamOptions = {
|
|
|
354
354
|
toolTimeoutMs?: number;
|
|
355
355
|
/** AbortSignal for external cancellation of the AI call */
|
|
356
356
|
abortSignal?: AbortSignal;
|
|
357
|
+
/** Bounds for tool execution capture. See GenerateOptions.toolExecutionCapture. */
|
|
358
|
+
toolExecutionCapture?: ToolExecutionCaptureOptions;
|
|
357
359
|
disableTools?: boolean;
|
|
358
360
|
/** Disable the schema-driven tool call repair mechanism (BZ-665). Default: false (repair enabled). */
|
|
359
361
|
disableToolCallRepair?: boolean;
|
package/dist/types/task.d.ts
CHANGED
|
@@ -220,9 +220,9 @@ export type NeuroLinkExecutable = {
|
|
|
220
220
|
generate(optionsOrPrompt: unknown): Promise<{
|
|
221
221
|
content: string;
|
|
222
222
|
toolExecutions?: Array<{
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
223
|
+
toolName: string;
|
|
224
|
+
params: unknown;
|
|
225
|
+
resultText: string;
|
|
226
226
|
}>;
|
|
227
227
|
usage?: {
|
|
228
228
|
input?: number;
|
package/dist/utils/logger.d.ts
CHANGED
|
@@ -32,9 +32,16 @@ declare class NeuroLinkLogger {
|
|
|
32
32
|
}): void;
|
|
33
33
|
/**
|
|
34
34
|
* Clears the event emitter reference.
|
|
35
|
-
* Should be called when a NeuroLink instance is disposed to prevent memory
|
|
35
|
+
* Should be called when a NeuroLink instance is disposed to prevent memory
|
|
36
|
+
* leaks. Pass the disposing instance's emitter so a short-lived instance
|
|
37
|
+
* (e.g. a worker sub-agent) only clears the bridge when it actually owns
|
|
38
|
+
* it — never yanking a host instance's live log bridge.
|
|
39
|
+
*
|
|
40
|
+
* @param ifEmitter - When provided, clear only if it is the current emitter
|
|
36
41
|
*/
|
|
37
|
-
clearEventEmitter(
|
|
42
|
+
clearEventEmitter(ifEmitter?: {
|
|
43
|
+
emit: (event: string, ...args: unknown[]) => boolean;
|
|
44
|
+
}): void;
|
|
38
45
|
/**
|
|
39
46
|
* Sets the minimum log level that will be processed and output.
|
|
40
47
|
* Log messages with a level lower than this will be ignored.
|
|
@@ -220,7 +227,9 @@ export declare const logger: {
|
|
|
220
227
|
setEventEmitter: (emitter: {
|
|
221
228
|
emit: (event: string, ...args: unknown[]) => boolean;
|
|
222
229
|
}) => void;
|
|
223
|
-
clearEventEmitter: (
|
|
230
|
+
clearEventEmitter: (ifEmitter?: {
|
|
231
|
+
emit: (event: string, ...args: unknown[]) => boolean;
|
|
232
|
+
}) => void;
|
|
224
233
|
};
|
|
225
234
|
/**
|
|
226
235
|
* MCP compatibility exports - all use the same unified logger instance.
|
package/dist/utils/logger.js
CHANGED
|
@@ -64,9 +64,17 @@ class NeuroLinkLogger {
|
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
66
66
|
* Clears the event emitter reference.
|
|
67
|
-
* Should be called when a NeuroLink instance is disposed to prevent memory
|
|
67
|
+
* Should be called when a NeuroLink instance is disposed to prevent memory
|
|
68
|
+
* leaks. Pass the disposing instance's emitter so a short-lived instance
|
|
69
|
+
* (e.g. a worker sub-agent) only clears the bridge when it actually owns
|
|
70
|
+
* it — never yanking a host instance's live log bridge.
|
|
71
|
+
*
|
|
72
|
+
* @param ifEmitter - When provided, clear only if it is the current emitter
|
|
68
73
|
*/
|
|
69
|
-
clearEventEmitter() {
|
|
74
|
+
clearEventEmitter(ifEmitter) {
|
|
75
|
+
if (ifEmitter !== undefined && this.eventEmitter !== ifEmitter) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
70
78
|
this.eventEmitter = undefined;
|
|
71
79
|
}
|
|
72
80
|
/**
|
|
@@ -462,7 +470,7 @@ export const logger = {
|
|
|
462
470
|
getLogs: (level) => neuroLinkLogger.getLogs(level),
|
|
463
471
|
clearLogs: () => neuroLinkLogger.clearLogs(),
|
|
464
472
|
setEventEmitter: (emitter) => neuroLinkLogger.setEventEmitter(emitter),
|
|
465
|
-
clearEventEmitter: () => neuroLinkLogger.clearEventEmitter(),
|
|
473
|
+
clearEventEmitter: (ifEmitter) => neuroLinkLogger.clearEventEmitter(ifEmitter),
|
|
466
474
|
};
|
|
467
475
|
/**
|
|
468
476
|
* MCP compatibility exports - all use the same unified logger instance.
|
|
@@ -34,6 +34,20 @@ export declare function transformToolExecutionsForMCP(toolExecutions?: unknown[]
|
|
|
34
34
|
success: boolean;
|
|
35
35
|
serverId?: string;
|
|
36
36
|
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Convert ToolExecutionRecord entries (or legacy-shaped entries) to the
|
|
39
|
+
* TaskRunResult.toolCalls shape. Single source for the task executors so the
|
|
40
|
+
* name fallback (`toolName` → legacy `name`) can't drift between them.
|
|
41
|
+
*/
|
|
42
|
+
export declare function toolExecutionRecordsToToolCalls(records: Array<{
|
|
43
|
+
toolName?: string;
|
|
44
|
+
params?: unknown;
|
|
45
|
+
resultText?: string;
|
|
46
|
+
}> | undefined): Array<{
|
|
47
|
+
name: string;
|
|
48
|
+
input: unknown;
|
|
49
|
+
output: unknown;
|
|
50
|
+
}> | undefined;
|
|
37
51
|
/**
|
|
38
52
|
* Transform available tools from internal format to GenerateResult format
|
|
39
53
|
* Ensures consistent tool information structure across the API with schema normalization
|
|
@@ -60,8 +60,9 @@ export function transformToolExecutions(toolExecutions) {
|
|
|
60
60
|
rawRecordKeys: Object.keys(teRecord),
|
|
61
61
|
};
|
|
62
62
|
logger.debug("[TransformationUtils] Tool parameter extraction analysis", parameterExtractionData);
|
|
63
|
-
// Enhanced input extraction
|
|
63
|
+
// Enhanced input extraction (params = ToolExecutionRecord)
|
|
64
64
|
let input = teRecord.input ||
|
|
65
|
+
teRecord.params ||
|
|
65
66
|
teRecord.parameters ||
|
|
66
67
|
teRecord.args ||
|
|
67
68
|
{};
|
|
@@ -149,12 +150,15 @@ export function transformToolExecutions(toolExecutions) {
|
|
|
149
150
|
};
|
|
150
151
|
logger.debug("[TransformationUtils] Final parameter extraction result", finalExtractionSummary);
|
|
151
152
|
// Enhanced output extraction with success indication
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
teRecord.
|
|
153
|
+
// (resultText = ToolExecutionRecord — preserve the captured result)
|
|
154
|
+
const output = teRecord.output ??
|
|
155
|
+
teRecord.result ??
|
|
156
|
+
teRecord.response ??
|
|
157
|
+
teRecord.resultText ??
|
|
155
158
|
"success";
|
|
156
|
-
// Enhanced duration extraction
|
|
157
|
-
const duration = teRecord.
|
|
159
|
+
// Enhanced duration extraction (durationMs = ToolExecutionRecord)
|
|
160
|
+
const duration = teRecord.durationMs ??
|
|
161
|
+
teRecord.duration ??
|
|
158
162
|
teRecord.executionTime ??
|
|
159
163
|
teRecord.responseTime ??
|
|
160
164
|
0;
|
|
@@ -193,15 +197,19 @@ export function transformToolExecutionsForMCP(toolExecutions) {
|
|
|
193
197
|
if (!toolName) {
|
|
194
198
|
toolName = `mcp_tool_execution_${index}`;
|
|
195
199
|
}
|
|
196
|
-
// Enhanced execution time extraction
|
|
197
|
-
const executionTime = teRecord.
|
|
200
|
+
// Enhanced execution time extraction (durationMs = ToolExecutionRecord)
|
|
201
|
+
const executionTime = teRecord.durationMs ??
|
|
202
|
+
teRecord.duration ??
|
|
198
203
|
teRecord.executionTime ??
|
|
199
204
|
teRecord.responseTime ??
|
|
200
205
|
0;
|
|
201
206
|
// Enhanced success detection - check for actual success indicators
|
|
202
207
|
let success = true; // Default to true
|
|
203
|
-
// Check for explicit success/error indicators
|
|
204
|
-
if (teRecord.
|
|
208
|
+
// Check for explicit success/error indicators (isError = ToolExecutionRecord)
|
|
209
|
+
if (teRecord.isError !== undefined) {
|
|
210
|
+
success = !teRecord.isError;
|
|
211
|
+
}
|
|
212
|
+
else if (teRecord.success !== undefined) {
|
|
205
213
|
success = Boolean(teRecord.success);
|
|
206
214
|
}
|
|
207
215
|
else if (teRecord.error !== undefined) {
|
|
@@ -234,6 +242,21 @@ export function transformToolExecutionsForMCP(toolExecutions) {
|
|
|
234
242
|
};
|
|
235
243
|
});
|
|
236
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* Convert ToolExecutionRecord entries (or legacy-shaped entries) to the
|
|
247
|
+
* TaskRunResult.toolCalls shape. Single source for the task executors so the
|
|
248
|
+
* name fallback (`toolName` → legacy `name`) can't drift between them.
|
|
249
|
+
*/
|
|
250
|
+
export function toolExecutionRecordsToToolCalls(records) {
|
|
251
|
+
return records?.map((te) => {
|
|
252
|
+
const legacy = te;
|
|
253
|
+
return {
|
|
254
|
+
name: te.toolName ?? legacy.name ?? "unknown",
|
|
255
|
+
input: te.params ?? legacy.input,
|
|
256
|
+
output: te.resultText ?? legacy.output,
|
|
257
|
+
};
|
|
258
|
+
});
|
|
259
|
+
}
|
|
237
260
|
// ============================================================================
|
|
238
261
|
// AVAILABLE TOOLS TRANSFORMATIONS
|
|
239
262
|
// ============================================================================
|
|
@@ -163,7 +163,7 @@ export function defineRealtimeVoiceAgent(config = {}) {
|
|
|
163
163
|
const sinceConnect = () => Date.now() - connectedAt;
|
|
164
164
|
if (onLog) {
|
|
165
165
|
const room = ctx.room.name ?? "unknown";
|
|
166
|
-
|
|
166
|
+
const voiceLogEmitter = {
|
|
167
167
|
emit: (event, ...args) => {
|
|
168
168
|
if (event === "log-event") {
|
|
169
169
|
const decoded = realtimeLogEventSchema.safeParse(args[0]);
|
|
@@ -178,9 +178,12 @@ export function defineRealtimeVoiceAgent(config = {}) {
|
|
|
178
178
|
}
|
|
179
179
|
return true;
|
|
180
180
|
},
|
|
181
|
-
}
|
|
181
|
+
};
|
|
182
|
+
logger.setEventEmitter(voiceLogEmitter);
|
|
182
183
|
ctx.addShutdownCallback(async () => {
|
|
183
|
-
|
|
184
|
+
// Clear only if this agent's emitter is still the active sink —
|
|
185
|
+
// never yank a bridge some other instance installed since.
|
|
186
|
+
logger.clearEventEmitter(voiceLogEmitter);
|
|
184
187
|
});
|
|
185
188
|
}
|
|
186
189
|
logger.info("realtime.room.joined", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.6.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": {
|
|
@@ -142,6 +142,7 @@
|
|
|
142
142
|
"test:model-pool:vitest": "pnpm exec vitest run test/modelPool.test.ts",
|
|
143
143
|
"test:model-pool": "pnpm run test:model-pool:vitest && npx tsx test/continuous-test-suite-model-pool.ts",
|
|
144
144
|
"test:model-capabilities:vitest": "pnpm exec vitest run test/modelCapabilities.test.ts",
|
|
145
|
+
"test:agent-runtime:vitest": "pnpm exec vitest run test/agentRuntime.test.ts test/agentDelegation.test.ts test/agentPlumbing.test.ts test/toolExecutionRecorder.test.ts test/samplingParams.test.ts test/structuredRecovery.test.ts",
|
|
145
146
|
"test:ci": "pnpm run test && pnpm run test:client && pnpm run test:hitl",
|
|
146
147
|
"// CI tier — fast, no live AI calls, safe for every commit": "",
|
|
147
148
|
"test:unit:vitest": "pnpm exec vitest run test/toolRouting.test.ts",
|
|
@@ -150,7 +151,7 @@
|
|
|
150
151
|
"test:system-messages:vitest": "pnpm exec vitest run test/systemMessages.test.ts",
|
|
151
152
|
"test:tool-routing-semantic:vitest": "pnpm exec vitest run test/toolRoutingSemantic.test.ts",
|
|
152
153
|
"test:tool-routing-semantic": "pnpm run test:tool-routing-semantic:vitest && npx tsx test/continuous-test-suite-tool-routing-semantic.ts",
|
|
153
|
-
"test:unit": "pnpm run test:envguard && pnpm run test:bugfixes && pnpm run test:file-detector-extension && pnpm run test:file-detector-magic-bytes && 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:litellm-context:vitest && pnpm run test:step-budget-guard:vitest && pnpm run test:system-messages:vitest && pnpm run test:tool-routing-semantic:vitest && pnpm run test:anthropic-tools-policy && pnpm run test:sagemaker-tools && pnpm run test:anthropic-multimodal && pnpm run test:excel-interop && pnpm run test:model-capabilities:vitest",
|
|
154
|
+
"test:unit": "pnpm run test:envguard && pnpm run test:bugfixes && pnpm run test:file-detector-extension && pnpm run test:file-detector-magic-bytes && 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:litellm-context:vitest && pnpm run test:step-budget-guard:vitest && pnpm run test:system-messages:vitest && pnpm run test:tool-routing-semantic:vitest && pnpm run test:anthropic-tools-policy && pnpm run test:sagemaker-tools && pnpm run test:anthropic-multimodal && pnpm run test:excel-interop && pnpm run test:model-capabilities:vitest && pnpm run test:agent-runtime:vitest",
|
|
154
155
|
"// 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)": "",
|
|
155
156
|
"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",
|
|
156
157
|
"// CI tier — product output (image/video/TTS/PPT) — costs $$ per run": "",
|