@juspay/neurolink 12.9.0 → 12.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -3
- package/dist/browser/neurolink.min.js +344 -344
- package/dist/cli/commands/proxy.js +35 -2
- package/dist/constants/enums.d.ts +17 -2
- package/dist/constants/enums.js +17 -2
- package/dist/core/baseProvider.d.ts +56 -0
- package/dist/core/baseProvider.js +308 -17
- package/dist/providers/catalog/cerebras.json +15 -5
- package/dist/providers/catalog/cloudflare.json +17 -13
- package/dist/providers/catalog/fireworks.json +74 -43
- package/dist/providers/catalog/groq.json +81 -32
- package/dist/providers/catalog/loader.js +3 -0
- package/dist/providers/catalog/mistral.json +27 -23
- package/dist/providers/catalog/provider-catalog.schema.json +5 -0
- package/dist/providers/catalog/sambanova.json +36 -11
- package/dist/providers/catalog/schema.d.ts +2 -1
- package/dist/providers/catalog/schema.js +1 -0
- package/dist/providers/catalog/xai.json +39 -26
- package/dist/providers/configuredOpenAICompat.d.ts +18 -1
- package/dist/providers/configuredOpenAICompat.js +48 -0
- package/dist/providers/openaiChatCompletionsBase.d.ts +15 -0
- package/dist/providers/openaiChatCompletionsBase.js +20 -0
- package/dist/proxy/proxyActivity.d.ts +2 -0
- package/dist/proxy/proxyActivity.js +18 -0
- package/dist/server/routes/codexProxyRoutes.js +3 -2
- package/dist/types/providerCatalog.d.ts +6 -0
- package/dist/types/providers.d.ts +3 -0
- package/package.json +2 -1
|
@@ -47,8 +47,8 @@ export declare const providerCatalogJsonSchema: z.ZodObject<{
|
|
|
47
47
|
vision: z.ZodBoolean;
|
|
48
48
|
status: z.ZodEnum<{
|
|
49
49
|
production: "production";
|
|
50
|
-
preview: "preview";
|
|
51
50
|
retired: "retired";
|
|
51
|
+
preview: "preview";
|
|
52
52
|
}>;
|
|
53
53
|
description: z.ZodString;
|
|
54
54
|
enumMember: z.ZodOptional<z.ZodString>;
|
|
@@ -81,6 +81,7 @@ export declare const providerCatalogJsonSchema: z.ZodObject<{
|
|
|
81
81
|
}, z.core.$strict>>;
|
|
82
82
|
quirks: z.ZodOptional<z.ZodObject<{
|
|
83
83
|
timeoutErrorClass: z.ZodOptional<z.ZodLiteral<"provider">>;
|
|
84
|
+
messageContentFormat: z.ZodOptional<z.ZodLiteral<"string">>;
|
|
84
85
|
registryDefaultIgnoresModelEnvVar: z.ZodOptional<z.ZodBoolean>;
|
|
85
86
|
}, z.core.$strict>>;
|
|
86
87
|
setup: z.ZodObject<{
|
|
@@ -136,6 +136,7 @@ const catalogErrorRuleJsonSchema = z
|
|
|
136
136
|
});
|
|
137
137
|
const catalogQuirksSchema = z.strictObject({
|
|
138
138
|
timeoutErrorClass: z.literal("provider").optional(),
|
|
139
|
+
messageContentFormat: z.literal("string").optional(),
|
|
139
140
|
registryDefaultIgnoresModelEnvVar: z.boolean().optional(),
|
|
140
141
|
});
|
|
141
142
|
const catalogBillingPolicySchema = z.enum([
|
|
@@ -8,23 +8,38 @@
|
|
|
8
8
|
"baseURL": "https://api.x.ai/v1"
|
|
9
9
|
},
|
|
10
10
|
"models": {
|
|
11
|
-
"default": "grok-
|
|
12
|
-
"fallbacks": [
|
|
13
|
-
"grok-3",
|
|
14
|
-
"grok-3-mini",
|
|
15
|
-
"grok-2-latest",
|
|
16
|
-
"grok-2-vision-latest",
|
|
17
|
-
"grok-beta"
|
|
18
|
-
],
|
|
11
|
+
"default": "grok-4.6",
|
|
12
|
+
"fallbacks": ["grok-4.6", "grok-4.5", "grok-4.3", "grok-3", "grok-3-mini"],
|
|
19
13
|
"defaultContextWindow": 131072,
|
|
20
14
|
"defaultMaxOutputTokens": 4096,
|
|
21
15
|
"catalog": {
|
|
16
|
+
"grok-4.6": {
|
|
17
|
+
"enumMember": "GROK_4_6",
|
|
18
|
+
"contextWindow": 131072,
|
|
19
|
+
"vision": true,
|
|
20
|
+
"status": "production",
|
|
21
|
+
"description": "Recommended - Grok 4.6, current flagship; vision-capable"
|
|
22
|
+
},
|
|
23
|
+
"grok-4.5": {
|
|
24
|
+
"enumMember": "GROK_4_5",
|
|
25
|
+
"contextWindow": 131072,
|
|
26
|
+
"vision": true,
|
|
27
|
+
"status": "production",
|
|
28
|
+
"description": "Grok 4.5 — vision-capable"
|
|
29
|
+
},
|
|
30
|
+
"grok-4.3": {
|
|
31
|
+
"enumMember": "GROK_4_3",
|
|
32
|
+
"contextWindow": 131072,
|
|
33
|
+
"vision": true,
|
|
34
|
+
"status": "production",
|
|
35
|
+
"description": "Grok 4.3 — vision-capable"
|
|
36
|
+
},
|
|
22
37
|
"grok-3": {
|
|
23
38
|
"contextWindow": 131072,
|
|
24
39
|
"pricingPerMTok": { "input": 3.0, "output": 15.0 },
|
|
25
40
|
"vision": false,
|
|
26
41
|
"status": "production",
|
|
27
|
-
"description": "
|
|
42
|
+
"description": "Grok 3 — still served, though absent from the /models roster"
|
|
28
43
|
},
|
|
29
44
|
"grok-3-mini": {
|
|
30
45
|
"contextWindow": 131072,
|
|
@@ -37,31 +52,26 @@
|
|
|
37
52
|
"contextWindow": 131072,
|
|
38
53
|
"pricingPerMTok": { "input": 2.0, "output": 10.0 },
|
|
39
54
|
"vision": false,
|
|
40
|
-
"status": "
|
|
41
|
-
"description": "
|
|
55
|
+
"status": "retired",
|
|
56
|
+
"description": "Retired 2026-08 — xAI rejects it as an invalid model"
|
|
42
57
|
},
|
|
43
58
|
"grok-2-vision-latest": {
|
|
44
59
|
"contextWindow": 32768,
|
|
45
60
|
"pricingPerMTok": { "input": 2.0, "output": 10.0 },
|
|
46
|
-
"vision":
|
|
47
|
-
"status": "
|
|
48
|
-
"description": "
|
|
61
|
+
"vision": false,
|
|
62
|
+
"status": "retired",
|
|
63
|
+
"description": "Retired 2026-08 — xAI rejects it as an invalid model; vision moved to the grok-4.x line"
|
|
49
64
|
},
|
|
50
65
|
"grok-beta": {
|
|
51
66
|
"contextWindow": 131072,
|
|
52
67
|
"pricingPerMTok": { "input": 5.0, "output": 15.0 },
|
|
53
68
|
"vision": false,
|
|
54
|
-
"status": "
|
|
55
|
-
"description": "
|
|
69
|
+
"status": "retired",
|
|
70
|
+
"description": "Retired 2026-08 — xAI rejects it as an invalid model"
|
|
56
71
|
}
|
|
57
72
|
},
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
"grok-3-mini",
|
|
61
|
-
"grok-2-vision-latest",
|
|
62
|
-
"grok-2-latest",
|
|
63
|
-
"grok-beta"
|
|
64
|
-
]
|
|
73
|
+
"visionModel": "grok-4.6",
|
|
74
|
+
"topModels": ["grok-4.6", "grok-4.5", "grok-4.3", "grok-3"]
|
|
65
75
|
},
|
|
66
76
|
"capabilities": {
|
|
67
77
|
"text": true,
|
|
@@ -99,10 +109,13 @@
|
|
|
99
109
|
},
|
|
100
110
|
"evidence": {
|
|
101
111
|
"rosterVerified": {
|
|
102
|
-
"date": "2026-08-
|
|
103
|
-
"method": "
|
|
112
|
+
"date": "2026-08-30",
|
|
113
|
+
"method": "GET /models against the live account, cross-checked with a real chat call per id"
|
|
114
|
+
},
|
|
115
|
+
"liveMatrix": {
|
|
116
|
+
"date": "2026-08-30",
|
|
117
|
+
"result": "grok-2-latest, grok-2-vision-latest and grok-beta are rejected as invalid models. The grok-4.x line replaces them: 4.3/4.5/4.6 all answer, and all three read a 64x64 PNG correctly, so vision moved there from the retired grok-2-vision-latest. An earlier probe with an 8x8 PNG reported no vision — that was xAI answering 'Invalid PNG image', a complaint about the file rather than the capability. grok-3 and grok-3-mini are kept because they still serve, even though xAI's /models roster omits them: roster absence is not evidence of death here."
|
|
104
118
|
},
|
|
105
|
-
"liveMatrix": null,
|
|
106
119
|
"addedInPR": "https://github.com/juspay/neurolink/pull/1587"
|
|
107
120
|
}
|
|
108
121
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AIProviderName } from "../constants/enums.js";
|
|
2
|
-
import type { OpenAICompatCatalogEntry, OpenAICompatCredentials } from "../types/index.js";
|
|
2
|
+
import type { OpenAICompatCatalogEntry, OpenAICompatChatRequest, OpenAICompatCredentials } from "../types/index.js";
|
|
3
3
|
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
4
4
|
/**
|
|
5
5
|
* Generic OpenAI-compatible provider driven entirely by an
|
|
@@ -12,6 +12,22 @@ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
|
12
12
|
* adjustBodyAfter400, getChatCompletionsURL, getAuthHeaders,
|
|
13
13
|
* suppressResponseFormatWithTools, ...) it does NOT belong in the catalog —
|
|
14
14
|
* write a dedicated subclass instead (see deepseek.ts, azureOpenai.ts).
|
|
15
|
+
*
|
|
16
|
+
* The exception is a WIRE DIALECT: a vendor that speaks OpenAI for ordinary
|
|
17
|
+
* chat but encodes one part of the request differently. Expressing that as
|
|
18
|
+
* data (the catalog's `messageContentFormat`) keeps the provider a
|
|
19
|
+
* one-JSON-file entry instead of promoting it to a hand-written subclass
|
|
20
|
+
* over a single incompatibility.
|
|
21
|
+
*
|
|
22
|
+
* Today that is Cloudflare Workers AI, whose OpenAI-compatible endpoint
|
|
23
|
+
* accepts `messages[].content` only as a plain string — never the
|
|
24
|
+
* content-parts array OpenAI allows, and never the `null` that OpenAI uses
|
|
25
|
+
* on an assistant message carrying tool_calls. Its schema rejects both with
|
|
26
|
+
* HTTP 400 ("Type mismatch of '/messages/N/content'"). That bites precisely
|
|
27
|
+
* on the second turn of a tool call, so single-turn chat looks healthy while
|
|
28
|
+
* every tool round-trip fails. Normalizing content to a string below is the
|
|
29
|
+
* whole fix: tools, tool_choice, the `tool` role and `tool_calls` are all
|
|
30
|
+
* accepted as-is.
|
|
15
31
|
*/
|
|
16
32
|
export declare class ConfiguredOpenAICompatProvider extends OpenAIChatCompletionsProvider {
|
|
17
33
|
private readonly entry;
|
|
@@ -20,5 +36,6 @@ export declare class ConfiguredOpenAICompatProvider extends OpenAIChatCompletion
|
|
|
20
36
|
protected getDefaultModel(): string;
|
|
21
37
|
protected getFallbackModelName(): string;
|
|
22
38
|
protected getFallbackModels(): string[];
|
|
39
|
+
protected adjustRequestBody(body: OpenAICompatChatRequest, modelId: string): OpenAICompatChatRequest;
|
|
23
40
|
protected formatProviderError(error: unknown): Error;
|
|
24
41
|
}
|
|
@@ -4,6 +4,25 @@ import { getProviderModel, resolveOpenAICompatConfig, } from "../utils/providerC
|
|
|
4
4
|
import { classifyProviderError } from "../utils/errorClassifier.js";
|
|
5
5
|
import { TimeoutError } from "../utils/timeout.js";
|
|
6
6
|
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
7
|
+
/**
|
|
8
|
+
* Collapse OpenAI's `content` union down to the plain string that
|
|
9
|
+
* string-only vendors accept. Image parts carry no string representation and
|
|
10
|
+
* are dropped — a provider that cannot accept a content array cannot accept
|
|
11
|
+
* inline images either.
|
|
12
|
+
*/
|
|
13
|
+
const flattenMessageContent = (content) => {
|
|
14
|
+
if (typeof content === "string") {
|
|
15
|
+
return content;
|
|
16
|
+
}
|
|
17
|
+
// An assistant message with tool_calls legitimately has null content;
|
|
18
|
+
// the empty string is its string-only equivalent.
|
|
19
|
+
if (content === null || content === undefined) {
|
|
20
|
+
return "";
|
|
21
|
+
}
|
|
22
|
+
return content
|
|
23
|
+
.map((part) => (part.type === "text" ? part.text : ""))
|
|
24
|
+
.join("");
|
|
25
|
+
};
|
|
7
26
|
/**
|
|
8
27
|
* Generic OpenAI-compatible provider driven entirely by an
|
|
9
28
|
* OpenAICompatCatalogEntry. Replaces a hand-written subclass for any
|
|
@@ -15,6 +34,22 @@ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
|
15
34
|
* adjustBodyAfter400, getChatCompletionsURL, getAuthHeaders,
|
|
16
35
|
* suppressResponseFormatWithTools, ...) it does NOT belong in the catalog —
|
|
17
36
|
* write a dedicated subclass instead (see deepseek.ts, azureOpenai.ts).
|
|
37
|
+
*
|
|
38
|
+
* The exception is a WIRE DIALECT: a vendor that speaks OpenAI for ordinary
|
|
39
|
+
* chat but encodes one part of the request differently. Expressing that as
|
|
40
|
+
* data (the catalog's `messageContentFormat`) keeps the provider a
|
|
41
|
+
* one-JSON-file entry instead of promoting it to a hand-written subclass
|
|
42
|
+
* over a single incompatibility.
|
|
43
|
+
*
|
|
44
|
+
* Today that is Cloudflare Workers AI, whose OpenAI-compatible endpoint
|
|
45
|
+
* accepts `messages[].content` only as a plain string — never the
|
|
46
|
+
* content-parts array OpenAI allows, and never the `null` that OpenAI uses
|
|
47
|
+
* on an assistant message carrying tool_calls. Its schema rejects both with
|
|
48
|
+
* HTTP 400 ("Type mismatch of '/messages/N/content'"). That bites precisely
|
|
49
|
+
* on the second turn of a tool call, so single-turn chat looks healthy while
|
|
50
|
+
* every tool round-trip fails. Normalizing content to a string below is the
|
|
51
|
+
* whole fix: tools, tool_choice, the `tool` role and `tool_calls` are all
|
|
52
|
+
* accepted as-is.
|
|
18
53
|
*/
|
|
19
54
|
export class ConfiguredOpenAICompatProvider extends OpenAIChatCompletionsProvider {
|
|
20
55
|
entry;
|
|
@@ -51,6 +86,19 @@ export class ConfiguredOpenAICompatProvider extends OpenAIChatCompletionsProvide
|
|
|
51
86
|
getFallbackModels() {
|
|
52
87
|
return this.entry.fallbackModels;
|
|
53
88
|
}
|
|
89
|
+
adjustRequestBody(body, modelId) {
|
|
90
|
+
const adjusted = super.adjustRequestBody(body, modelId);
|
|
91
|
+
if (this.entry.messageContentFormat !== "string") {
|
|
92
|
+
return adjusted;
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
...adjusted,
|
|
96
|
+
messages: adjusted.messages.map((message) => ({
|
|
97
|
+
...message,
|
|
98
|
+
content: flattenMessageContent(message.content),
|
|
99
|
+
})),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
54
102
|
formatProviderError(error) {
|
|
55
103
|
// classifyProviderError hard-codes TimeoutError -> NetworkError ahead
|
|
56
104
|
// of any rule table and does not allow a per-provider override. An
|
|
@@ -45,6 +45,21 @@ export declare abstract class OpenAIChatCompletionsProvider extends BaseProvider
|
|
|
45
45
|
* Hardcoded model names returned from `getAvailableModels()` when the
|
|
46
46
|
* remote `/models` endpoint can't be reached. Default empty.
|
|
47
47
|
*/
|
|
48
|
+
/**
|
|
49
|
+
* Feed the catalog's `fallbacks` to BaseProvider's invalid-model retry, so
|
|
50
|
+
* a default the vendor has retired degrades to the next live model in the
|
|
51
|
+
* entry instead of failing the call outright.
|
|
52
|
+
*/
|
|
53
|
+
protected getModelFallbacks(): string[];
|
|
54
|
+
/**
|
|
55
|
+
* `resolvedModel` memoizes the first id this provider resolved, and
|
|
56
|
+
* getAISDKModel() builds its wire model from that memo rather than from
|
|
57
|
+
* `modelName`. Leaving it stale here silently defeats the invalid-model
|
|
58
|
+
* fallback: modelName advances to the next candidate while every request
|
|
59
|
+
* still carries the retired id, so each retry fails for the same reason
|
|
60
|
+
* the first attempt did.
|
|
61
|
+
*/
|
|
62
|
+
protected refreshHandlersForModel(model: string): void;
|
|
48
63
|
protected getFallbackModels(): string[];
|
|
49
64
|
/**
|
|
50
65
|
* Hook to mutate the `buildBody` options before the wire body is
|
|
@@ -68,6 +68,26 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
68
68
|
* Hardcoded model names returned from `getAvailableModels()` when the
|
|
69
69
|
* remote `/models` endpoint can't be reached. Default empty.
|
|
70
70
|
*/
|
|
71
|
+
/**
|
|
72
|
+
* Feed the catalog's `fallbacks` to BaseProvider's invalid-model retry, so
|
|
73
|
+
* a default the vendor has retired degrades to the next live model in the
|
|
74
|
+
* entry instead of failing the call outright.
|
|
75
|
+
*/
|
|
76
|
+
getModelFallbacks() {
|
|
77
|
+
return this.getFallbackModels();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* `resolvedModel` memoizes the first id this provider resolved, and
|
|
81
|
+
* getAISDKModel() builds its wire model from that memo rather than from
|
|
82
|
+
* `modelName`. Leaving it stale here silently defeats the invalid-model
|
|
83
|
+
* fallback: modelName advances to the next candidate while every request
|
|
84
|
+
* still carries the retired id, so each retry fails for the same reason
|
|
85
|
+
* the first attempt did.
|
|
86
|
+
*/
|
|
87
|
+
refreshHandlersForModel(model) {
|
|
88
|
+
this.resolvedModel = model;
|
|
89
|
+
super.refreshHandlersForModel(model);
|
|
90
|
+
}
|
|
71
91
|
getFallbackModels() {
|
|
72
92
|
return [];
|
|
73
93
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { ProxyActivitySnapshot, ProxyResponseTrackingObserver } from "../types/index.js";
|
|
2
|
+
export declare function registerProxyResponseObserver(metadata: object, observer: ProxyResponseTrackingObserver): void;
|
|
3
|
+
export declare function takeProxyResponseObservers(metadata: object): ProxyResponseTrackingObserver[];
|
|
2
4
|
/** Track one client-facing proxy request until its response body settles. */
|
|
3
5
|
export declare function beginProxyRequest(): () => void;
|
|
4
6
|
export declare function getProxyActivitySnapshot(): ProxyActivitySnapshot;
|
|
@@ -3,6 +3,24 @@ import { logger } from "../utils/logger.js";
|
|
|
3
3
|
const PROXY_RESPONSE_CANCEL_TIMEOUT_MS = 1_000;
|
|
4
4
|
let activeRequests = 0;
|
|
5
5
|
let lastActivityAtMs = null;
|
|
6
|
+
// Route handlers can attach terminal observers to their request context without
|
|
7
|
+
// wrapping the response body a second time. The HTTP runtime drains every
|
|
8
|
+
// response through one tracker, which fans these observers out at the point
|
|
9
|
+
// where bytes actually leave the proxy.
|
|
10
|
+
const responseObserversByMetadata = new WeakMap();
|
|
11
|
+
export function registerProxyResponseObserver(metadata, observer) {
|
|
12
|
+
const existing = responseObserversByMetadata.get(metadata);
|
|
13
|
+
if (existing) {
|
|
14
|
+
existing.push(observer);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
responseObserversByMetadata.set(metadata, [observer]);
|
|
18
|
+
}
|
|
19
|
+
export function takeProxyResponseObservers(metadata) {
|
|
20
|
+
const observers = responseObserversByMetadata.get(metadata) ?? [];
|
|
21
|
+
responseObserversByMetadata.delete(metadata);
|
|
22
|
+
return observers;
|
|
23
|
+
}
|
|
6
24
|
function touchActivity() {
|
|
7
25
|
lastActivityAtMs = Date.now();
|
|
8
26
|
}
|
|
@@ -24,7 +24,7 @@ import { loadAccountQuotas, saveAccountQuota, } from "../../proxy/accountQuota.j
|
|
|
24
24
|
import { createCodexUsageTap } from "../../proxy/codexUsage.js";
|
|
25
25
|
import { CODEX_ACCOUNT_PREFIX, parseCodexRateLimitHeaders, } from "../../proxy/codexAccountUsage.js";
|
|
26
26
|
import { buildClientAttribution } from "../../proxy/clientAttribution.js";
|
|
27
|
-
import {
|
|
27
|
+
import { registerProxyResponseObserver } from "../../proxy/proxyActivity.js";
|
|
28
28
|
import { logRequest, logRequestAttempt } from "../../proxy/requestLogger.js";
|
|
29
29
|
import { parseRetryAfterMs } from "../../proxy/routingPolicy.js";
|
|
30
30
|
import { recordAttempt, recordAttemptError, recordFinalError, recordFinalSuccess, } from "../../proxy/usageStats.js";
|
|
@@ -459,7 +459,7 @@ export async function handleCodexResponsesRequest(ctx) {
|
|
|
459
459
|
status: upstream.status,
|
|
460
460
|
headers,
|
|
461
461
|
});
|
|
462
|
-
|
|
462
|
+
registerProxyResponseObserver(ctx.metadata, {
|
|
463
463
|
onTerminal: ({ outcome }) => {
|
|
464
464
|
void usageSeen
|
|
465
465
|
.then((usage) => {
|
|
@@ -491,6 +491,7 @@ export async function handleCodexResponsesRequest(ctx) {
|
|
|
491
491
|
.catch(() => undefined);
|
|
492
492
|
},
|
|
493
493
|
});
|
|
494
|
+
return relay;
|
|
494
495
|
}
|
|
495
496
|
const errText = await upstream.text().catch(() => "");
|
|
496
497
|
// 401/403 → try a forced token refresh once, then rotate.
|
|
@@ -44,6 +44,12 @@ export type CatalogErrorRuleJson = {
|
|
|
44
44
|
};
|
|
45
45
|
export type CatalogQuirks = {
|
|
46
46
|
timeoutErrorClass?: "provider";
|
|
47
|
+
/** Vendor speaks OpenAI for chat but restricts how message content is
|
|
48
|
+
* encoded. "string": `messages[].content` must be a plain string —
|
|
49
|
+
* the content-parts array and the `null` OpenAI uses on an assistant
|
|
50
|
+
* message with tool_calls are both rejected with HTTP 400. Normalized by
|
|
51
|
+
* ConfiguredOpenAICompatProvider so tool round-trips work. */
|
|
52
|
+
messageContentFormat?: "string";
|
|
47
53
|
registryDefaultIgnoresModelEnvVar?: boolean;
|
|
48
54
|
};
|
|
49
55
|
export type CatalogBillingPolicy = "free-tier" | "free-with-card" | "no-free-tier";
|
|
@@ -693,6 +693,9 @@ export type OpenAICompatCatalogEntry = {
|
|
|
693
693
|
* the classifier's default (six of the seven catalog entries).
|
|
694
694
|
*/
|
|
695
695
|
timeoutErrorClass?: new (message: string, provider?: string) => ProviderError;
|
|
696
|
+
/** See CatalogQuirks.messageContentFormat — a vendor that accepts
|
|
697
|
+
* `messages[].content` only as a plain string. */
|
|
698
|
+
messageContentFormat?: "string";
|
|
696
699
|
};
|
|
697
700
|
/** The subset of OpenAICompatCatalogEntry that resolveOpenAICompatConfig()
|
|
698
701
|
* needs — lets call sites pass a minimal object without the full catalog
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.9.
|
|
3
|
+
"version": "12.9.2",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "TypeScript AI SDK with 24+ LLM providers behind one consistent API. MCP-native (connect any MCP server), voice TTS/STT/realtime, RAG, agents, memory, context compaction. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · DeepSeek · NVIDIA NIM and more.",
|
|
6
6
|
"author": {
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"prepack": "svelte-kit sync && svelte-package && pnpm run build:react-hooks && pnpm run build:cli && pnpm run build:browser && publint",
|
|
42
42
|
"build:react-hooks": "pnpm exec tsc --jsx react-jsx --module nodenext --moduleResolution nodenext --target esnext --esModuleInterop --skipLibCheck --outDir dist --declaration false src/lib/client/reactHooks.tsx",
|
|
43
43
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json && tsc --noEmit --strict",
|
|
44
|
+
"check:models": "tsx tools/check-model-liveness.ts",
|
|
44
45
|
"check:ci-scripts": "svelte-kit sync && tsc -p tsconfig.ci-scripts.json",
|
|
45
46
|
"check:test-parse": "node scripts/parse-check-tests.mjs",
|
|
46
47
|
"check:tools-tests": "svelte-kit sync && tsc -p tsconfig.tools-tests.json",
|