@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.
Files changed (59) hide show
  1. package/CHANGELOG.md +3 -3
  2. package/dist/browser/neurolink.min.js +533 -581
  3. package/dist/constants/enums.d.ts +13 -0
  4. package/dist/constants/enums.js +14 -0
  5. package/dist/core/baseProvider.d.ts +71 -3
  6. package/dist/core/baseProvider.js +152 -44
  7. package/dist/core/modules/GenerationHandler.d.ts +22 -24
  8. package/dist/core/modules/GenerationHandler.js +28 -463
  9. package/dist/core/nativeGenerateLoop.d.ts +35 -0
  10. package/dist/core/nativeGenerateLoop.js +261 -0
  11. package/dist/files/fileTools.d.ts +5 -5
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.js +4 -0
  14. package/dist/mcp/toolRegistry.js +7 -0
  15. package/dist/middleware/builtin/guardrails.d.ts +0 -5
  16. package/dist/middleware/builtin/guardrails.js +33 -5
  17. package/dist/middleware/factory.js +1 -1
  18. package/dist/middleware/wrapLanguageModel.d.ts +18 -0
  19. package/dist/middleware/wrapLanguageModel.js +53 -0
  20. package/dist/neurolink.d.ts +7 -0
  21. package/dist/neurolink.js +61 -11
  22. package/dist/processors/media/AudioProcessor.js +46 -11
  23. package/dist/providers/amazonSagemaker.d.ts +17 -1
  24. package/dist/providers/amazonSagemaker.js +110 -0
  25. package/dist/providers/anthropic/client.d.ts +11 -0
  26. package/dist/providers/anthropic/client.js +148 -1
  27. package/dist/providers/catalog/index.generated.d.ts +1 -1
  28. package/dist/providers/catalog/index.generated.js +3 -0
  29. package/dist/providers/catalog/loader.js +1 -0
  30. package/dist/providers/catalog/mancer.json +192 -0
  31. package/dist/providers/configuredOpenAICompat.d.ts +11 -0
  32. package/dist/providers/configuredOpenAICompat.js +16 -0
  33. package/dist/providers/googleVertex/client.d.ts +0 -9
  34. package/dist/providers/googleVertex/client.js +0 -33
  35. package/dist/providers/openaiChatCompletionsBase.d.ts +21 -1
  36. package/dist/providers/openaiChatCompletionsBase.js +178 -0
  37. package/dist/providers/providerTypeUtils.d.ts +1 -2
  38. package/dist/providers/providerTypeUtils.js +5 -1
  39. package/dist/types/aiCompat.d.ts +485 -0
  40. package/dist/types/aiCompat.js +17 -0
  41. package/dist/types/conversation.d.ts +1 -1
  42. package/dist/types/generate.d.ts +52 -0
  43. package/dist/types/middleware.d.ts +3 -6
  44. package/dist/types/providerCatalog.generated.d.ts +2 -2
  45. package/dist/types/providers.d.ts +14 -1
  46. package/dist/types/tools.d.ts +25 -2
  47. package/dist/utils/errorHandling.d.ts +20 -3
  48. package/dist/utils/errorHandling.js +22 -5
  49. package/dist/utils/generationErrors.d.ts +78 -6
  50. package/dist/utils/generationErrors.js +114 -6
  51. package/dist/utils/mcpDefaults.d.ts +1 -1
  52. package/dist/utils/mcpDefaults.js +4 -1
  53. package/dist/utils/nativeSingleShot.d.ts +3 -0
  54. package/dist/utils/nativeSingleShot.js +83 -0
  55. package/dist/utils/tool.d.ts +30 -5
  56. package/dist/utils/tool.js +43 -5
  57. package/package.json +3 -6
  58. package/dist/utils/generation.d.ts +0 -8
  59. package/dist/utils/generation.js +0 -8
@@ -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 "ai";
13
- export type { Tool, ToolSet, ToolChoice, ToolCallOptions, ToolExecuteFunction, ToolApprovalRequest, ToolApprovalResponse, InferToolInput, InferToolOutput, Schema, FlexibleSchema, InferSchema, } from "ai";
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
- static toolTimeout(toolName: string, timeoutMs: number, serverId?: string): NeuroLinkError;
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}' timed out after ${timeoutMs}ms`,
187
+ message: `Tool '${toolName}' ${scope}`,
173
188
  category: ErrorCategory.TIMEOUT,
174
189
  severity: ErrorSeverity.HIGH,
175
- retriable: true,
176
- context: { timeoutMs },
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
- * Used with `.isInstance(e)` checks and instanceof guards in retry,
5
- * tool-call repair, and stream handling. Today these resolve through the
6
- * upstream generation library; this file is the only internal source so the
7
- * implementation can be replaced without touching call sites.
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 { NoOutputGeneratedError, NoObjectGeneratedError, NoSuchToolError, InvalidToolInputError, } from "ai";
10
- export { APICallError } from "@ai-sdk/provider";
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
- * Used with `.isInstance(e)` checks and instanceof guards in retry,
5
- * tool-call repair, and stream handling. Today these resolve through the
6
- * upstream generation library; this file is the only internal source so the
7
- * implementation can be replaced without touching call sites.
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 { NoOutputGeneratedError, NoObjectGeneratedError, NoSuchToolError, InvalidToolInputError, } from "ai";
10
- export { APICallError } from "@ai-sdk/provider";
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
+ }
@@ -1,8 +1,33 @@
1
1
  /**
2
- * Tool definition helpers + structured-output spec.
2
+ * Tool and schema primitives.
3
3
  *
4
- * Today these resolve through the upstream generation library; this file is
5
- * the only internal source for them so the implementation can be replaced
6
- * without touching call sites.
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
- export { tool, jsonSchema, Output, stepCountIs } from "ai";
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;
@@ -1,8 +1,46 @@
1
1
  /**
2
- * Tool definition helpers + structured-output spec.
2
+ * Tool and schema primitives.
3
3
  *
4
- * Today these resolve through the upstream generation library; this file is
5
- * the only internal source for them so the implementation can be replaced
6
- * without touching call sites.
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
- export { tool, jsonSchema, Output, stepCountIs } from "ai";
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.11.2",
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";
@@ -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";