@juspay/neurolink 12.11.2 → 12.12.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 +533 -581
- package/dist/constants/enums.d.ts +13 -0
- package/dist/constants/enums.js +14 -0
- package/dist/core/baseProvider.d.ts +71 -3
- package/dist/core/baseProvider.js +152 -44
- package/dist/core/modules/GenerationHandler.d.ts +22 -24
- package/dist/core/modules/GenerationHandler.js +28 -463
- package/dist/core/nativeGenerateLoop.d.ts +35 -0
- package/dist/core/nativeGenerateLoop.js +261 -0
- package/dist/files/fileTools.d.ts +5 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -0
- package/dist/mcp/toolRegistry.js +7 -0
- package/dist/middleware/builtin/guardrails.d.ts +0 -5
- package/dist/middleware/builtin/guardrails.js +33 -5
- package/dist/middleware/factory.js +1 -1
- package/dist/middleware/wrapLanguageModel.d.ts +18 -0
- package/dist/middleware/wrapLanguageModel.js +53 -0
- package/dist/neurolink.d.ts +7 -0
- package/dist/neurolink.js +61 -11
- package/dist/processors/media/AudioProcessor.js +46 -11
- package/dist/providers/amazonSagemaker.d.ts +17 -1
- package/dist/providers/amazonSagemaker.js +110 -0
- package/dist/providers/anthropic/client.d.ts +11 -0
- package/dist/providers/anthropic/client.js +148 -1
- package/dist/providers/catalog/index.generated.d.ts +1 -1
- package/dist/providers/catalog/index.generated.js +3 -0
- package/dist/providers/catalog/loader.js +1 -0
- package/dist/providers/catalog/mancer.json +192 -0
- package/dist/providers/configuredOpenAICompat.d.ts +11 -0
- package/dist/providers/configuredOpenAICompat.js +16 -0
- package/dist/providers/googleVertex/client.d.ts +0 -9
- package/dist/providers/googleVertex/client.js +0 -33
- package/dist/providers/openaiChatCompletionsBase.d.ts +21 -1
- package/dist/providers/openaiChatCompletionsBase.js +178 -0
- package/dist/providers/providerTypeUtils.d.ts +1 -2
- package/dist/providers/providerTypeUtils.js +5 -1
- package/dist/types/aiCompat.d.ts +485 -0
- package/dist/types/aiCompat.js +17 -0
- package/dist/types/conversation.d.ts +1 -1
- package/dist/types/generate.d.ts +52 -0
- package/dist/types/middleware.d.ts +3 -6
- package/dist/types/providerCatalog.generated.d.ts +2 -2
- package/dist/types/providers.d.ts +14 -1
- package/dist/types/tools.d.ts +25 -2
- package/dist/utils/errorHandling.d.ts +20 -3
- package/dist/utils/errorHandling.js +22 -5
- package/dist/utils/generationErrors.d.ts +78 -6
- package/dist/utils/generationErrors.js +114 -6
- package/dist/utils/mcpDefaults.d.ts +1 -1
- package/dist/utils/mcpDefaults.js +4 -1
- package/dist/utils/nativeSingleShot.d.ts +3 -0
- package/dist/utils/nativeSingleShot.js +83 -0
- package/dist/utils/tool.d.ts +30 -5
- package/dist/utils/tool.js +43 -5
- package/package.json +3 -6
- package/dist/utils/generation.d.ts +0 -8
- package/dist/utils/generation.js +0 -8
package/dist/types/tools.d.ts
CHANGED
|
@@ -9,8 +9,8 @@ import type { ValidationError } from "../utils/parameterValidation.js";
|
|
|
9
9
|
import type { MCPToolAnnotations } from "./mcp.js";
|
|
10
10
|
import type { Logger } from "./utilities.js";
|
|
11
11
|
import type { HITLExecutionState } from "./hitl.js";
|
|
12
|
-
import type { Tool } from "
|
|
13
|
-
export type { Tool, ToolSet, ToolChoice,
|
|
12
|
+
import type { Tool } from "./aiCompat.js";
|
|
13
|
+
export type { Tool, ToolSet, ToolChoice, ToolExecuteFunction, ToolApprovalRequest, ToolApprovalResponse, InferToolInput, InferToolOutput, Schema, FlexibleSchema, InferSchema, } from "./aiCompat.js";
|
|
14
14
|
/**
|
|
15
15
|
* Commonly used Zod schema type aliases for cleaner type declarations
|
|
16
16
|
*/
|
|
@@ -87,6 +87,12 @@ export type ToolInfo = {
|
|
|
87
87
|
/** Per-tool timeout in milliseconds, set at registration time */
|
|
88
88
|
timeoutMs?: number;
|
|
89
89
|
maxRetries?: number;
|
|
90
|
+
/**
|
|
91
|
+
* Ceiling on the WHOLE execution — every attempt plus the delays between
|
|
92
|
+
* them. Declared explicitly rather than left to the index signature below,
|
|
93
|
+
* which would type it `unknown` and silently defeat the default.
|
|
94
|
+
*/
|
|
95
|
+
totalTimeoutMs?: number;
|
|
90
96
|
[key: string]: unknown;
|
|
91
97
|
};
|
|
92
98
|
/**
|
|
@@ -103,6 +109,13 @@ export type ToolImplementation = {
|
|
|
103
109
|
/** Per-tool timeout in milliseconds, set at registration time */
|
|
104
110
|
timeoutMs?: number;
|
|
105
111
|
maxRetries?: number;
|
|
112
|
+
/**
|
|
113
|
+
* Ceiling on the WHOLE execution — every attempt plus the delays between
|
|
114
|
+
* them — in milliseconds. `timeoutMs` bounds one attempt; without this, a
|
|
115
|
+
* tool that reliably hangs burns `timeoutMs * (maxRetries + 1)`.
|
|
116
|
+
* Defaults to exactly that product, so behaviour is unchanged unless set.
|
|
117
|
+
*/
|
|
118
|
+
totalTimeoutMs?: number;
|
|
106
119
|
};
|
|
107
120
|
/**
|
|
108
121
|
* Tool execution options for enhanced control
|
|
@@ -130,6 +143,13 @@ export type ToolExecutionOptions = {
|
|
|
130
143
|
*/
|
|
131
144
|
timeoutMs?: number;
|
|
132
145
|
maxRetries?: number;
|
|
146
|
+
/**
|
|
147
|
+
* Ceiling on the WHOLE execution — every attempt plus the delays between
|
|
148
|
+
* them. `timeout` bounds one attempt. Defaults to
|
|
149
|
+
* `timeout * (maxRetries + 1)`, which is what the retry loop already spent,
|
|
150
|
+
* so supplying nothing changes nothing.
|
|
151
|
+
*/
|
|
152
|
+
totalTimeoutMs?: number;
|
|
133
153
|
};
|
|
134
154
|
/**
|
|
135
155
|
* Options for tool registration via registerTool()
|
|
@@ -153,6 +173,9 @@ export type ToolRegistrationOptions = {
|
|
|
153
173
|
* When omitted, the SDK's global default (2 retries) is used.
|
|
154
174
|
* Set to 0 to disable retries for this tool. */
|
|
155
175
|
maxRetries?: number;
|
|
176
|
+
/** Ceiling on the whole execution across every attempt and the delays
|
|
177
|
+
* between them. When omitted, `timeout * (maxRetries + 1)` is used. */
|
|
178
|
+
totalTimeoutMs?: number;
|
|
156
179
|
/**
|
|
157
180
|
* Whether this tool's result may be served from the tool-result cache
|
|
158
181
|
* (default true).
|
|
@@ -108,9 +108,26 @@ export declare class ErrorFactory {
|
|
|
108
108
|
*/
|
|
109
109
|
static toolExecutionFailed(toolName: string, originalError: Error, serverId?: string): NeuroLinkError;
|
|
110
110
|
/**
|
|
111
|
-
* Create a tool timeout error
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
* Create a tool timeout error.
|
|
112
|
+
*
|
|
113
|
+
* `timeoutMs` is the bound that was actually exceeded. Pass `budget` when
|
|
114
|
+
* the timeout happened inside a retry loop, so the error can say which
|
|
115
|
+
* number it is reporting: a reader who sees `timeoutMs: 120000` next to an
|
|
116
|
+
* `executionTime` of 483005 will otherwise conclude the timeout was never
|
|
117
|
+
* enforced, when in fact four attempts of 120s each were.
|
|
118
|
+
*
|
|
119
|
+
* `budget.exhausted` marks the case where the whole-execution ceiling ran
|
|
120
|
+
* out rather than a single attempt overrunning; that error is NOT retriable,
|
|
121
|
+
* because there is no budget left to retry into.
|
|
122
|
+
*/
|
|
123
|
+
static toolTimeout(toolName: string, timeoutMs: number, serverId?: string, budget?: {
|
|
124
|
+
attempt?: number;
|
|
125
|
+
maxAttempts?: number;
|
|
126
|
+
attemptTimeoutMs?: number;
|
|
127
|
+
totalTimeoutMs?: number;
|
|
128
|
+
elapsedMs?: number;
|
|
129
|
+
exhausted?: boolean;
|
|
130
|
+
}): NeuroLinkError;
|
|
114
131
|
/**
|
|
115
132
|
* Create a parameter validation error
|
|
116
133
|
*/
|
|
@@ -164,16 +164,33 @@ export class ErrorFactory {
|
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
166
|
/**
|
|
167
|
-
* Create a tool timeout error
|
|
167
|
+
* Create a tool timeout error.
|
|
168
|
+
*
|
|
169
|
+
* `timeoutMs` is the bound that was actually exceeded. Pass `budget` when
|
|
170
|
+
* the timeout happened inside a retry loop, so the error can say which
|
|
171
|
+
* number it is reporting: a reader who sees `timeoutMs: 120000` next to an
|
|
172
|
+
* `executionTime` of 483005 will otherwise conclude the timeout was never
|
|
173
|
+
* enforced, when in fact four attempts of 120s each were.
|
|
174
|
+
*
|
|
175
|
+
* `budget.exhausted` marks the case where the whole-execution ceiling ran
|
|
176
|
+
* out rather than a single attempt overrunning; that error is NOT retriable,
|
|
177
|
+
* because there is no budget left to retry into.
|
|
168
178
|
*/
|
|
169
|
-
static toolTimeout(toolName, timeoutMs, serverId) {
|
|
179
|
+
static toolTimeout(toolName, timeoutMs, serverId, budget) {
|
|
180
|
+
const scope = budget?.exhausted
|
|
181
|
+
? `exhausted its ${budget.totalTimeoutMs}ms total budget`
|
|
182
|
+
: budget?.maxAttempts && budget.maxAttempts > 1
|
|
183
|
+
? `timed out after ${timeoutMs}ms on attempt ${budget.attempt ?? 1} of ${budget.maxAttempts}`
|
|
184
|
+
: `timed out after ${timeoutMs}ms`;
|
|
170
185
|
return new NeuroLinkError({
|
|
171
186
|
code: ERROR_CODES.TOOL_TIMEOUT,
|
|
172
|
-
message: `Tool '${toolName}'
|
|
187
|
+
message: `Tool '${toolName}' ${scope}`,
|
|
173
188
|
category: ErrorCategory.TIMEOUT,
|
|
174
189
|
severity: ErrorSeverity.HIGH,
|
|
175
|
-
|
|
176
|
-
|
|
190
|
+
// A single attempt timing out is worth another try; an exhausted total
|
|
191
|
+
// budget is not — retrying it can only overshoot the caller's ceiling.
|
|
192
|
+
retriable: budget?.exhausted !== true,
|
|
193
|
+
context: { timeoutMs, ...(budget ?? {}) },
|
|
177
194
|
toolName,
|
|
178
195
|
serverId,
|
|
179
196
|
});
|
|
@@ -1,10 +1,82 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Error classes surfaced by the generation pipeline.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* These used to be re-exported from the `ai` package. They are now declared
|
|
5
|
+
* here, because every path that threw them upstream is gone: generation is
|
|
6
|
+
* native end to end, and the only one this repo still constructs is
|
|
7
|
+
* NoOutputGeneratedError.
|
|
8
|
+
*
|
|
9
|
+
* The marker symbols are deliberately identical to the upstream ones
|
|
10
|
+
* (`Symbol.for("vercel.ai.error.<name>")`). `isInstance` is a marker check, not
|
|
11
|
+
* an `instanceof`, precisely so it survives across duplicate module copies —
|
|
12
|
+
* and keeping the same symbol means an error raised by any remaining upstream
|
|
13
|
+
* code is still recognised by these classes, and vice versa. Switching to a
|
|
14
|
+
* private symbol would have silently broken that recognition at exactly the
|
|
15
|
+
* points that matter: retry classification and the no-output sentinel.
|
|
16
|
+
*/
|
|
17
|
+
/** Base for the generation errors; stamps the upstream-compatible marker. */
|
|
18
|
+
declare class GenerationError extends Error {
|
|
19
|
+
readonly cause?: unknown;
|
|
20
|
+
constructor(markerName: string, message: string, cause?: unknown);
|
|
21
|
+
}
|
|
22
|
+
export declare class NoOutputGeneratedError extends GenerationError {
|
|
23
|
+
constructor(options?: {
|
|
24
|
+
message?: string;
|
|
25
|
+
cause?: unknown;
|
|
26
|
+
});
|
|
27
|
+
static isInstance(error: unknown): error is NoOutputGeneratedError;
|
|
28
|
+
}
|
|
29
|
+
export declare class NoObjectGeneratedError extends GenerationError {
|
|
30
|
+
readonly text?: string;
|
|
31
|
+
readonly finishReason?: string;
|
|
32
|
+
constructor(options?: {
|
|
33
|
+
message?: string;
|
|
34
|
+
cause?: unknown;
|
|
35
|
+
text?: string;
|
|
36
|
+
finishReason?: string;
|
|
37
|
+
});
|
|
38
|
+
static isInstance(error: unknown): error is NoObjectGeneratedError;
|
|
39
|
+
}
|
|
40
|
+
export declare class NoSuchToolError extends GenerationError {
|
|
41
|
+
readonly toolName?: string;
|
|
42
|
+
constructor(options?: {
|
|
43
|
+
message?: string;
|
|
44
|
+
toolName?: string;
|
|
45
|
+
});
|
|
46
|
+
static isInstance(error: unknown): error is NoSuchToolError;
|
|
47
|
+
}
|
|
48
|
+
export declare class InvalidToolInputError extends GenerationError {
|
|
49
|
+
readonly toolName?: string;
|
|
50
|
+
constructor(options?: {
|
|
51
|
+
message?: string;
|
|
52
|
+
toolName?: string;
|
|
53
|
+
cause?: unknown;
|
|
54
|
+
});
|
|
55
|
+
static isInstance(error: unknown): error is InvalidToolInputError;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Transport-level failure. This repo only ever CATCHES and classifies these —
|
|
59
|
+
* `providerRetry` and the error classifier duck-type `.statusCode` — so the
|
|
60
|
+
* class exists to keep those `isInstance` checks working for errors raised by
|
|
61
|
+
* the provider clients, which stamp the same marker.
|
|
8
62
|
*/
|
|
9
|
-
export
|
|
10
|
-
|
|
63
|
+
export declare class APICallError extends GenerationError {
|
|
64
|
+
readonly url?: string;
|
|
65
|
+
readonly statusCode?: number;
|
|
66
|
+
readonly responseBody?: string;
|
|
67
|
+
readonly responseHeaders?: Record<string, string>;
|
|
68
|
+
readonly isRetryable: boolean;
|
|
69
|
+
readonly requestBodyValues?: unknown;
|
|
70
|
+
constructor(options?: {
|
|
71
|
+
message?: string;
|
|
72
|
+
url?: string;
|
|
73
|
+
statusCode?: number;
|
|
74
|
+
responseBody?: string;
|
|
75
|
+
responseHeaders?: Record<string, string>;
|
|
76
|
+
isRetryable?: boolean;
|
|
77
|
+
requestBodyValues?: unknown;
|
|
78
|
+
cause?: unknown;
|
|
79
|
+
});
|
|
80
|
+
static isInstance(error: unknown): error is APICallError;
|
|
81
|
+
}
|
|
82
|
+
export {};
|
|
@@ -1,10 +1,118 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Error classes surfaced by the generation pipeline.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* These used to be re-exported from the `ai` package. They are now declared
|
|
5
|
+
* here, because every path that threw them upstream is gone: generation is
|
|
6
|
+
* native end to end, and the only one this repo still constructs is
|
|
7
|
+
* NoOutputGeneratedError.
|
|
8
|
+
*
|
|
9
|
+
* The marker symbols are deliberately identical to the upstream ones
|
|
10
|
+
* (`Symbol.for("vercel.ai.error.<name>")`). `isInstance` is a marker check, not
|
|
11
|
+
* an `instanceof`, precisely so it survives across duplicate module copies —
|
|
12
|
+
* and keeping the same symbol means an error raised by any remaining upstream
|
|
13
|
+
* code is still recognised by these classes, and vice versa. Switching to a
|
|
14
|
+
* private symbol would have silently broken that recognition at exactly the
|
|
15
|
+
* points that matter: retry classification and the no-output sentinel.
|
|
16
|
+
*/
|
|
17
|
+
const markerSymbolFor = (name) => Symbol.for(`vercel.ai.error.${name}`);
|
|
18
|
+
const hasMarker = (error, name) => {
|
|
19
|
+
const marker = markerSymbolFor(name);
|
|
20
|
+
return (error !== null &&
|
|
21
|
+
typeof error === "object" &&
|
|
22
|
+
marker in error &&
|
|
23
|
+
error[marker] === true);
|
|
24
|
+
};
|
|
25
|
+
/** Base for the generation errors; stamps the upstream-compatible marker. */
|
|
26
|
+
class GenerationError extends Error {
|
|
27
|
+
cause;
|
|
28
|
+
constructor(markerName, message, cause) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = markerName;
|
|
31
|
+
if (cause !== undefined) {
|
|
32
|
+
this.cause = cause;
|
|
33
|
+
}
|
|
34
|
+
Object.defineProperty(this, markerSymbolFor(markerName), {
|
|
35
|
+
value: true,
|
|
36
|
+
enumerable: false,
|
|
37
|
+
writable: false,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export class NoOutputGeneratedError extends GenerationError {
|
|
42
|
+
constructor(options = {}) {
|
|
43
|
+
super("AI_NoOutputGeneratedError", options.message ?? "No output generated.", options.cause);
|
|
44
|
+
}
|
|
45
|
+
static isInstance(error) {
|
|
46
|
+
return hasMarker(error, "AI_NoOutputGeneratedError");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export class NoObjectGeneratedError extends GenerationError {
|
|
50
|
+
text;
|
|
51
|
+
finishReason;
|
|
52
|
+
constructor(options = {}) {
|
|
53
|
+
super("AI_NoObjectGeneratedError", options.message ?? "No object generated.", options.cause);
|
|
54
|
+
this.text = options.text;
|
|
55
|
+
this.finishReason = options.finishReason;
|
|
56
|
+
}
|
|
57
|
+
static isInstance(error) {
|
|
58
|
+
return hasMarker(error, "AI_NoObjectGeneratedError");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export class NoSuchToolError extends GenerationError {
|
|
62
|
+
toolName;
|
|
63
|
+
constructor(options = {}) {
|
|
64
|
+
super("AI_NoSuchToolError", options.message ??
|
|
65
|
+
`Model tried to call unavailable tool '${options.toolName ?? "unknown"}'.`);
|
|
66
|
+
this.toolName = options.toolName;
|
|
67
|
+
}
|
|
68
|
+
static isInstance(error) {
|
|
69
|
+
return hasMarker(error, "AI_NoSuchToolError");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export class InvalidToolInputError extends GenerationError {
|
|
73
|
+
toolName;
|
|
74
|
+
constructor(options = {}) {
|
|
75
|
+
super("AI_InvalidToolInputError", options.message ??
|
|
76
|
+
`Invalid input for tool '${options.toolName ?? "unknown"}'.`, options.cause);
|
|
77
|
+
this.toolName = options.toolName;
|
|
78
|
+
}
|
|
79
|
+
static isInstance(error) {
|
|
80
|
+
return hasMarker(error, "AI_InvalidToolInputError");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Transport-level failure. This repo only ever CATCHES and classifies these —
|
|
85
|
+
* `providerRetry` and the error classifier duck-type `.statusCode` — so the
|
|
86
|
+
* class exists to keep those `isInstance` checks working for errors raised by
|
|
87
|
+
* the provider clients, which stamp the same marker.
|
|
8
88
|
*/
|
|
9
|
-
export
|
|
10
|
-
|
|
89
|
+
export class APICallError extends GenerationError {
|
|
90
|
+
url;
|
|
91
|
+
statusCode;
|
|
92
|
+
responseBody;
|
|
93
|
+
responseHeaders;
|
|
94
|
+
isRetryable;
|
|
95
|
+
requestBodyValues;
|
|
96
|
+
constructor(options = {}) {
|
|
97
|
+
super("AI_APICallError", options.message ?? "API call error.", options.cause);
|
|
98
|
+
this.url = options.url;
|
|
99
|
+
this.statusCode = options.statusCode;
|
|
100
|
+
this.responseBody = options.responseBody;
|
|
101
|
+
this.responseHeaders = options.responseHeaders;
|
|
102
|
+
// Upstream derives this from the status code when the caller does not say,
|
|
103
|
+
// and `providerRetry` reads it as a plain boolean — leaving it undefined
|
|
104
|
+
// would make every classified APICallError non-retryable by accident.
|
|
105
|
+
this.isRetryable =
|
|
106
|
+
options.isRetryable ??
|
|
107
|
+
(options.statusCode !== null &&
|
|
108
|
+
options.statusCode !== undefined &&
|
|
109
|
+
(options.statusCode === 408 ||
|
|
110
|
+
options.statusCode === 409 ||
|
|
111
|
+
options.statusCode === 429 ||
|
|
112
|
+
options.statusCode >= 500));
|
|
113
|
+
this.requestBodyValues = options.requestBodyValues;
|
|
114
|
+
}
|
|
115
|
+
static isInstance(error) {
|
|
116
|
+
return hasMarker(error, "AI_APICallError");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -37,7 +37,7 @@ export declare function createMCPServerInfo(options: {
|
|
|
37
37
|
* Create MCPServerInfo for custom tool registration
|
|
38
38
|
* Specialized version with smart defaults for registerTool usage
|
|
39
39
|
*/
|
|
40
|
-
export declare function createCustomToolServerInfo(toolName: string, tool: MCPExecutableTool, timeoutMs?: number, maxRetries?: number): MCPServerInfo;
|
|
40
|
+
export declare function createCustomToolServerInfo(toolName: string, tool: MCPExecutableTool, timeoutMs?: number, maxRetries?: number, totalTimeoutMs?: number): MCPServerInfo;
|
|
41
41
|
/**
|
|
42
42
|
* Create MCPServerInfo for external servers
|
|
43
43
|
* Specialized version with smart defaults for external server usage
|
|
@@ -93,7 +93,7 @@ export function createMCPServerInfo(options) {
|
|
|
93
93
|
* Create MCPServerInfo for custom tool registration
|
|
94
94
|
* Specialized version with smart defaults for registerTool usage
|
|
95
95
|
*/
|
|
96
|
-
export function createCustomToolServerInfo(toolName, tool, timeoutMs, maxRetries) {
|
|
96
|
+
export function createCustomToolServerInfo(toolName, tool, timeoutMs, maxRetries, totalTimeoutMs) {
|
|
97
97
|
const serverInfo = createMCPServerInfo({
|
|
98
98
|
id: `custom-tool-${toolName}`,
|
|
99
99
|
name: toolName,
|
|
@@ -112,6 +112,9 @@ export function createCustomToolServerInfo(toolName, tool, timeoutMs, maxRetries
|
|
|
112
112
|
if (maxRetries !== undefined) {
|
|
113
113
|
serverInfo.metadata.toolMaxRetries = maxRetries;
|
|
114
114
|
}
|
|
115
|
+
if (totalTimeoutMs !== undefined) {
|
|
116
|
+
serverInfo.metadata.toolTotalTimeoutMs = totalTimeoutMs;
|
|
117
|
+
}
|
|
115
118
|
}
|
|
116
119
|
return serverInfo;
|
|
117
120
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** One no-tool turn against a provider's delegating model, without ai's loop. */
|
|
2
|
+
import type { SingleShotRequest, SingleShotResult } from "../types/index.js";
|
|
3
|
+
export declare function generateOnceNative(model: unknown, request: SingleShotRequest): Promise<SingleShotResult>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const hasDoGenerate = (value) => typeof value === "object" &&
|
|
2
|
+
value !== null &&
|
|
3
|
+
typeof value.doGenerate === "function";
|
|
4
|
+
/**
|
|
5
|
+
* v3 reports `inputTokens` / `outputTokens` as objects carrying a `total`,
|
|
6
|
+
* while `SingleShotResult` — and `extractTokenUsage` downstream — accept only
|
|
7
|
+
* numbers. Passing the nested shape straight through recorded 0/0/0 for every
|
|
8
|
+
* caller of this helper, which is the whole of the video-frame formatting
|
|
9
|
+
* path's usage accounting.
|
|
10
|
+
*/
|
|
11
|
+
const readCount = (value) => {
|
|
12
|
+
if (typeof value === "number") {
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
if (typeof value === "object" &&
|
|
16
|
+
value !== null &&
|
|
17
|
+
typeof value.total === "number") {
|
|
18
|
+
return value.total;
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
};
|
|
22
|
+
const normalizeUsage = (usage) => {
|
|
23
|
+
if (typeof usage !== "object" || usage === null) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const shaped = usage;
|
|
27
|
+
const input = readCount(shaped.inputTokens);
|
|
28
|
+
const output = readCount(shaped.outputTokens);
|
|
29
|
+
if (input === undefined && output === undefined) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
inputTokens: input ?? 0,
|
|
34
|
+
outputTokens: output ?? 0,
|
|
35
|
+
totalTokens: (input ?? 0) + (output ?? 0),
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
const textFromContent = (content) => Array.isArray(content)
|
|
39
|
+
? content
|
|
40
|
+
.filter((part) => typeof part === "object" &&
|
|
41
|
+
part !== null &&
|
|
42
|
+
part.type === "text" &&
|
|
43
|
+
typeof part.text === "string")
|
|
44
|
+
.map((part) => part.text)
|
|
45
|
+
.join("")
|
|
46
|
+
: typeof content === "string"
|
|
47
|
+
? content
|
|
48
|
+
: "";
|
|
49
|
+
export async function generateOnceNative(model, request) {
|
|
50
|
+
if (!hasDoGenerate(model)) {
|
|
51
|
+
throw new Error("generateOnceNative: model handle exposes no doGenerate()");
|
|
52
|
+
}
|
|
53
|
+
const prompt = [];
|
|
54
|
+
if (request.system) {
|
|
55
|
+
prompt.push({ role: "system", content: request.system });
|
|
56
|
+
}
|
|
57
|
+
prompt.push({
|
|
58
|
+
role: "user",
|
|
59
|
+
content: [{ type: "text", text: request.prompt }],
|
|
60
|
+
});
|
|
61
|
+
const raw = await model.doGenerate({
|
|
62
|
+
prompt,
|
|
63
|
+
...(request.maxOutputTokens
|
|
64
|
+
? { maxOutputTokens: request.maxOutputTokens }
|
|
65
|
+
: {}),
|
|
66
|
+
...(request.temperature !== undefined
|
|
67
|
+
? { temperature: request.temperature }
|
|
68
|
+
: {}),
|
|
69
|
+
...(request.abortSignal ? { abortSignal: request.abortSignal } : {}),
|
|
70
|
+
});
|
|
71
|
+
const shaped = raw;
|
|
72
|
+
return {
|
|
73
|
+
text: typeof shaped.text === "string"
|
|
74
|
+
? shaped.text
|
|
75
|
+
: textFromContent(shaped.content),
|
|
76
|
+
...(normalizeUsage(shaped.usage)
|
|
77
|
+
? { usage: normalizeUsage(shaped.usage) }
|
|
78
|
+
: {}),
|
|
79
|
+
...(typeof shaped.finishReason === "string"
|
|
80
|
+
? { finishReason: shaped.finishReason }
|
|
81
|
+
: {}),
|
|
82
|
+
};
|
|
83
|
+
}
|
package/dist/utils/tool.d.ts
CHANGED
|
@@ -1,8 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tool
|
|
2
|
+
* Tool and schema primitives.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* the
|
|
6
|
-
*
|
|
4
|
+
* These were re-exported from the `ai` package. They are implemented here now,
|
|
5
|
+
* against the local type algebra in `types/aiCompat.ts`. The function and the
|
|
6
|
+
* type had to move together: replacing `tool()` alone leaves it producing an
|
|
7
|
+
* upstream `Tool` that no longer matches the local one, which is how the first
|
|
8
|
+
* attempt failed.
|
|
9
|
+
*
|
|
10
|
+
* Upstream behaviour, reproduced exactly:
|
|
11
|
+
* - `tool()` is identity. It exists for inference, not for runtime.
|
|
12
|
+
* - `jsonSchema()` wraps a raw JSON Schema in the duck-typed shape the rest of
|
|
13
|
+
* this repo reads — `convertZodToJsonSchema` looks for the `jsonSchema`
|
|
14
|
+
* property, not for the brand — and still stamps
|
|
15
|
+
* `Symbol.for("vercel.ai.schema")` so anything that does check it keeps
|
|
16
|
+
* working.
|
|
17
|
+
* - `stepCountIs(n)` returns `({steps}) => steps.length === n`.
|
|
7
18
|
*/
|
|
8
|
-
|
|
19
|
+
import type { JSONSchema7, Schema, Tool } from "../types/index.js";
|
|
20
|
+
export declare function tool<INPUT, OUTPUT>(definition: Tool<INPUT, OUTPUT>): Tool<INPUT, OUTPUT>;
|
|
21
|
+
export declare function tool<INPUT>(definition: Tool<INPUT, never>): Tool<INPUT, never>;
|
|
22
|
+
export declare function jsonSchema<OBJECT = unknown>(schema: JSONSchema7 | (() => JSONSchema7), options?: {
|
|
23
|
+
validate?: (value: unknown) => {
|
|
24
|
+
success: true;
|
|
25
|
+
value: OBJECT;
|
|
26
|
+
} | {
|
|
27
|
+
success: false;
|
|
28
|
+
error: unknown;
|
|
29
|
+
};
|
|
30
|
+
}): Schema<OBJECT>;
|
|
31
|
+
export declare const stepCountIs: (stepCount: number) => ({ steps }: {
|
|
32
|
+
steps: unknown[];
|
|
33
|
+
}) => boolean;
|
package/dist/utils/tool.js
CHANGED
|
@@ -1,8 +1,46 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tool
|
|
2
|
+
* Tool and schema primitives.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* the
|
|
6
|
-
*
|
|
4
|
+
* These were re-exported from the `ai` package. They are implemented here now,
|
|
5
|
+
* against the local type algebra in `types/aiCompat.ts`. The function and the
|
|
6
|
+
* type had to move together: replacing `tool()` alone leaves it producing an
|
|
7
|
+
* upstream `Tool` that no longer matches the local one, which is how the first
|
|
8
|
+
* attempt failed.
|
|
9
|
+
*
|
|
10
|
+
* Upstream behaviour, reproduced exactly:
|
|
11
|
+
* - `tool()` is identity. It exists for inference, not for runtime.
|
|
12
|
+
* - `jsonSchema()` wraps a raw JSON Schema in the duck-typed shape the rest of
|
|
13
|
+
* this repo reads — `convertZodToJsonSchema` looks for the `jsonSchema`
|
|
14
|
+
* property, not for the brand — and still stamps
|
|
15
|
+
* `Symbol.for("vercel.ai.schema")` so anything that does check it keeps
|
|
16
|
+
* working.
|
|
17
|
+
* - `stepCountIs(n)` returns `({steps}) => steps.length === n`.
|
|
7
18
|
*/
|
|
8
|
-
|
|
19
|
+
const SCHEMA_MARKER = Symbol.for("vercel.ai.schema");
|
|
20
|
+
/* eslint-disable no-redeclare, @typescript-eslint/no-explicit-any --
|
|
21
|
+
TypeScript overload implementation signature. It must be assignable from
|
|
22
|
+
both exported overloads above, which only `any` expresses; the exported
|
|
23
|
+
signatures themselves stay precise. */
|
|
24
|
+
export function tool(definition) {
|
|
25
|
+
return definition;
|
|
26
|
+
}
|
|
27
|
+
/* eslint-enable no-redeclare, @typescript-eslint/no-explicit-any */
|
|
28
|
+
export function jsonSchema(schema, options = {}) {
|
|
29
|
+
let resolved = schema;
|
|
30
|
+
const wrapper = {
|
|
31
|
+
[SCHEMA_MARKER]: true,
|
|
32
|
+
_type: undefined,
|
|
33
|
+
get jsonSchema() {
|
|
34
|
+
if (typeof resolved === "function") {
|
|
35
|
+
resolved = resolved();
|
|
36
|
+
}
|
|
37
|
+
return resolved;
|
|
38
|
+
},
|
|
39
|
+
...(options.validate ? { validate: options.validate } : {}),
|
|
40
|
+
};
|
|
41
|
+
return wrapper;
|
|
42
|
+
}
|
|
43
|
+
export const stepCountIs = (stepCount) => ({ steps }) => steps.length === stepCount;
|
|
44
|
+
// `Output` still comes from the upstream package: its only consumer is the
|
|
45
|
+
// GenerationHandler path that the native provider loops made unreachable, and
|
|
46
|
+
// that whole path is removed in a following change rather than kept alive here.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.12.0",
|
|
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": {
|
|
@@ -110,6 +110,7 @@
|
|
|
110
110
|
"test:matrix:cli": "pnpm exec tsx test/continuous-test-suite-provider-matrix-cli.ts",
|
|
111
111
|
"test:mcp:spans": "pnpm exec tsx test/continuous-test-suite-mcp-spans.ts",
|
|
112
112
|
"test:mcp:infra": "pnpm exec tsx test/continuous-test-suite-mcp-infra.ts",
|
|
113
|
+
"test:vendor-recovery": "pnpm exec tsx test/continuous-test-suite-native-vendor-recovery.ts",
|
|
113
114
|
"test:providers-mocked": "pnpm exec tsx test/continuous-test-suite-providers-mocked.ts",
|
|
114
115
|
"scaffold:provider": "pnpm exec tsx tools/scaffold-provider.ts",
|
|
115
116
|
"verify:provider-onboarding": "pnpm exec tsx tools/verify-provider-onboarding.ts",
|
|
@@ -360,10 +361,6 @@
|
|
|
360
361
|
}
|
|
361
362
|
},
|
|
362
363
|
"dependencies": {
|
|
363
|
-
"@ai-sdk/anthropic": "^3.0.50",
|
|
364
|
-
"@ai-sdk/mistral": "^3.0.21",
|
|
365
|
-
"@ai-sdk/openai": "^3.0.37",
|
|
366
|
-
"@ai-sdk/provider": "^3.0.8",
|
|
367
364
|
"@anthropic-ai/sdk": "^0.102.0",
|
|
368
365
|
"@anthropic-ai/vertex-sdk": "^0.16.0",
|
|
369
366
|
"@aws-sdk/types": "^3.862.0",
|
|
@@ -381,8 +378,8 @@
|
|
|
381
378
|
"@opentelemetry/sdk-metrics": "^2.6.1",
|
|
382
379
|
"@opentelemetry/sdk-trace-base": "^2.6.0",
|
|
383
380
|
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
381
|
+
"@types/json-schema": "^7.0.15",
|
|
384
382
|
"adm-zip": "^0.6.0",
|
|
385
|
-
"ai": "^6.0.134",
|
|
386
383
|
"chalk": "^5.6.2",
|
|
387
384
|
"chardet": "2.1.1",
|
|
388
385
|
"croner": "^9.1.0",
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generation, streaming, embedding, and middleware-composition primitives.
|
|
3
|
-
*
|
|
4
|
-
* Today these resolve through the upstream generation library; this file is
|
|
5
|
-
* the only internal source so the implementation can be replaced without
|
|
6
|
-
* touching call sites.
|
|
7
|
-
*/
|
|
8
|
-
export { generateText, streamText, generateObject, streamObject, embed, embedMany, wrapLanguageModel, experimental_transcribe, } from "ai";
|
package/dist/utils/generation.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generation, streaming, embedding, and middleware-composition primitives.
|
|
3
|
-
*
|
|
4
|
-
* Today these resolve through the upstream generation library; this file is
|
|
5
|
-
* the only internal source so the implementation can be replaced without
|
|
6
|
-
* touching call sites.
|
|
7
|
-
*/
|
|
8
|
-
export { generateText, streamText, generateObject, streamObject, embed, embedMany, wrapLanguageModel, experimental_transcribe, } from "ai";
|