@juspay/neurolink 10.2.1 → 10.3.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 +12 -0
- package/dist/browser/neurolink.min.js +371 -371
- package/dist/constants/contextWindows.d.ts +12 -0
- package/dist/constants/contextWindows.js +38 -0
- package/dist/context/stepBudgetGuard.d.ts +47 -0
- package/dist/context/stepBudgetGuard.js +289 -0
- package/dist/core/modules/GenerationHandler.js +53 -5
- package/dist/lib/constants/contextWindows.d.ts +12 -0
- package/dist/lib/constants/contextWindows.js +38 -0
- package/dist/lib/context/stepBudgetGuard.d.ts +47 -0
- package/dist/lib/context/stepBudgetGuard.js +290 -0
- package/dist/lib/core/modules/GenerationHandler.js +53 -5
- package/dist/lib/providers/litellm.d.ts +19 -0
- package/dist/lib/providers/litellm.js +92 -0
- package/dist/lib/types/context.d.ts +22 -0
- package/dist/providers/litellm.d.ts +19 -0
- package/dist/providers/litellm.js +92 -0
- package/dist/types/context.d.ts +22 -0
- package/package.json +5 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
2
|
+
import { registerRuntimeContextWindow } from "../constants/contextWindows.js";
|
|
2
3
|
import { createProxyFetch } from "../proxy/proxyFetch.js";
|
|
3
4
|
import { AuthenticationError, InvalidModelError, ModelAccessDeniedError, NetworkError, ProviderError, RateLimitError, isModelAccessDeniedMessage, parseAllowedModels, } from "../types/index.js";
|
|
4
5
|
import { isAbortError } from "../utils/errorHandling.js";
|
|
@@ -45,12 +46,24 @@ export class LiteLLMProvider extends OpenAIChatCompletionsProvider {
|
|
|
45
46
|
static modelsCache = [];
|
|
46
47
|
static modelsCacheTime = 0;
|
|
47
48
|
static MODELS_CACHE_DURATION = 10 * 60 * 1000; // 10 minutes
|
|
49
|
+
/**
|
|
50
|
+
* Dedupes the fire-and-forget `/model/info` discovery per base URL, so a
|
|
51
|
+
* process constructing many LiteLLM providers fetches each proxy's limits
|
|
52
|
+
* once per cache period.
|
|
53
|
+
*/
|
|
54
|
+
static modelInfoFetchTime = new Map();
|
|
48
55
|
constructor(modelName, sdk, _region, credentials) {
|
|
49
56
|
const envConfig = getLiteLLMConfig();
|
|
50
57
|
super("litellm", modelName, sdk, {
|
|
51
58
|
baseURL: credentials?.baseURL ?? envConfig.baseURL,
|
|
52
59
|
apiKey: credentials?.apiKey ?? envConfig.apiKey,
|
|
53
60
|
});
|
|
61
|
+
// Fire-and-forget: discover real per-model context windows from the
|
|
62
|
+
// proxy's /model/info. The static table only has a one-size litellm
|
|
63
|
+
// `_default` (128K), while proxied models range from 8K to 2M — budget
|
|
64
|
+
// checks and compaction need the real window. Failures degrade cleanly
|
|
65
|
+
// to the static default.
|
|
66
|
+
this.discoverModelContextWindows();
|
|
54
67
|
logger.debug("LiteLLM Provider initialized", {
|
|
55
68
|
modelName: this.modelName,
|
|
56
69
|
provider: this.providerName,
|
|
@@ -208,6 +221,85 @@ export class LiteLLMProvider extends OpenAIChatCompletionsProvider {
|
|
|
208
221
|
}
|
|
209
222
|
return this.getFallbackModels();
|
|
210
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Discover real per-model context windows from the LiteLLM proxy's
|
|
226
|
+
* `GET /model/info` (`data[].model_info.max_input_tokens`) and register
|
|
227
|
+
* them with the context-window resolver. Fire-and-forget with the same
|
|
228
|
+
* cache period as the models list; any failure (endpoint absent, auth,
|
|
229
|
+
* timeout) is logged at debug and leaves the static `_default` in force.
|
|
230
|
+
*/
|
|
231
|
+
discoverModelContextWindows() {
|
|
232
|
+
const baseURL = stripTrailingSlash(this.config.baseURL);
|
|
233
|
+
const now = Date.now();
|
|
234
|
+
const lastFetch = LiteLLMProvider.modelInfoFetchTime.get(baseURL) ?? 0;
|
|
235
|
+
if (now - lastFetch < LiteLLMProvider.MODELS_CACHE_DURATION) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
LiteLLMProvider.modelInfoFetchTime.set(baseURL, now);
|
|
239
|
+
void this.fetchModelInfoFromAPI()
|
|
240
|
+
.then((windows) => {
|
|
241
|
+
for (const [model, contextWindow] of windows) {
|
|
242
|
+
registerRuntimeContextWindow("litellm", model, contextWindow);
|
|
243
|
+
}
|
|
244
|
+
if (windows.size > 0) {
|
|
245
|
+
logger.debug("[LiteLLMProvider] Registered runtime context windows from /model/info", { baseURL: redactUrlCredentials(baseURL), models: windows.size });
|
|
246
|
+
}
|
|
247
|
+
})
|
|
248
|
+
.catch((error) => {
|
|
249
|
+
// Allow a retry before the cache period when discovery failed.
|
|
250
|
+
LiteLLMProvider.modelInfoFetchTime.delete(baseURL);
|
|
251
|
+
logger.debug("[LiteLLMProvider] /model/info discovery failed; static context-window defaults remain in force", { error: error instanceof Error ? error.message : String(error) });
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Fetch `GET /model/info` and map model group name → max_input_tokens.
|
|
256
|
+
* Same fetch/auth/abort scaffolding as {@link fetchModelsFromAPI}.
|
|
257
|
+
*/
|
|
258
|
+
async fetchModelInfoFromAPI() {
|
|
259
|
+
const infoUrl = `${stripTrailingSlash(this.config.baseURL)}/model/info`;
|
|
260
|
+
const proxyFetch = createProxyFetch();
|
|
261
|
+
const controller = new AbortController();
|
|
262
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
263
|
+
try {
|
|
264
|
+
const response = await proxyFetch(infoUrl, {
|
|
265
|
+
method: "GET",
|
|
266
|
+
headers: {
|
|
267
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
268
|
+
"Content-Type": "application/json",
|
|
269
|
+
},
|
|
270
|
+
signal: controller.signal,
|
|
271
|
+
});
|
|
272
|
+
if (!response.ok) {
|
|
273
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
274
|
+
}
|
|
275
|
+
const data = (await response.json());
|
|
276
|
+
const windows = new Map();
|
|
277
|
+
for (const entry of data.data ?? []) {
|
|
278
|
+
const model = entry?.model_name;
|
|
279
|
+
const maxInput = entry?.model_info?.max_input_tokens;
|
|
280
|
+
if (typeof model === "string" &&
|
|
281
|
+
model.length > 0 &&
|
|
282
|
+
typeof maxInput === "number" &&
|
|
283
|
+
Number.isFinite(maxInput) &&
|
|
284
|
+
maxInput > 0) {
|
|
285
|
+
// A model group can appear once per underlying deployment; keep the
|
|
286
|
+
// smallest advertised window so budgets are safe for every replica.
|
|
287
|
+
const existing = windows.get(model);
|
|
288
|
+
windows.set(model, existing === undefined ? maxInput : Math.min(existing, maxInput));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return windows;
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
if (isAbortError(error)) {
|
|
295
|
+
throw new NetworkError("Request timed out after 5 seconds", this.providerName);
|
|
296
|
+
}
|
|
297
|
+
throw error;
|
|
298
|
+
}
|
|
299
|
+
finally {
|
|
300
|
+
clearTimeout(timeoutId);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
211
303
|
async fetchModelsFromAPI() {
|
|
212
304
|
const modelsUrl = `${stripTrailingSlash(this.config.baseURL)}/v1/models`;
|
|
213
305
|
const proxyFetch = createProxyFetch();
|
package/dist/types/context.d.ts
CHANGED
|
@@ -219,6 +219,28 @@ export type BudgetCheckResult = {
|
|
|
219
219
|
fileAttachments: number;
|
|
220
220
|
};
|
|
221
221
|
};
|
|
222
|
+
/**
|
|
223
|
+
* Configuration for the per-step context budget guard that compacts the
|
|
224
|
+
* AI-SDK tool loop's messages before they overflow the model window
|
|
225
|
+
* (context/stepBudgetGuard.ts).
|
|
226
|
+
*/
|
|
227
|
+
export type StepBudgetGuardConfig = {
|
|
228
|
+
provider: string;
|
|
229
|
+
model?: string;
|
|
230
|
+
/** The caller's requested output budget (reserved out of the window). */
|
|
231
|
+
maxTokens?: number;
|
|
232
|
+
/** Static token cost of the hoisted system prompt + tool definitions. */
|
|
233
|
+
fixedOverheadTokens?: number;
|
|
234
|
+
/**
|
|
235
|
+
* Dynamic overhead resolver, re-evaluated on EVERY guard invocation. Takes
|
|
236
|
+
* precedence over `fixedOverheadTokens`. Use when the tool set can grow
|
|
237
|
+
* mid-loop (search_tools hydration) so newly added definitions count toward
|
|
238
|
+
* the budget.
|
|
239
|
+
*/
|
|
240
|
+
getFixedOverheadTokens?: () => number;
|
|
241
|
+
/** Override the trigger ratio; defaults to DEFAULT_CONTEXT_GUARD_RATIO. */
|
|
242
|
+
thresholdRatio?: number;
|
|
243
|
+
};
|
|
222
244
|
/** Parameters for budget checking. */
|
|
223
245
|
export type BudgetCheckParams = {
|
|
224
246
|
provider: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.3.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": {
|
|
@@ -147,7 +147,7 @@
|
|
|
147
147
|
"test:system-messages:vitest": "pnpm exec vitest run test/systemMessages.test.ts",
|
|
148
148
|
"test:tool-routing-semantic:vitest": "pnpm exec vitest run test/toolRoutingSemantic.test.ts",
|
|
149
149
|
"test:tool-routing-semantic": "pnpm run test:tool-routing-semantic:vitest && npx tsx test/continuous-test-suite-tool-routing-semantic.ts",
|
|
150
|
-
"test:unit": "pnpm run test:envguard && pnpm run test:bugfixes && pnpm run test:file-detector-extension && 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: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",
|
|
150
|
+
"test:unit": "pnpm run test:envguard && pnpm run test:bugfixes && pnpm run test:file-detector-extension && 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",
|
|
151
151
|
"// 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)": "",
|
|
152
152
|
"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",
|
|
153
153
|
"// CI tier — product output (image/video/TTS/PPT) — costs $$ per run": "",
|
|
@@ -208,7 +208,9 @@
|
|
|
208
208
|
"quality:report": "pnpm run quality:metrics && echo 'Quality metrics saved to quality-metrics.json'",
|
|
209
209
|
"pre-commit": "lint-staged",
|
|
210
210
|
"pre-push": "pnpm run validate:commit && pnpm run validate:env && pnpm run validate && pnpm run test:ci",
|
|
211
|
-
"check:all": "pnpm run lint && pnpm run format --check && pnpm run validate && pnpm run validate:commit"
|
|
211
|
+
"check:all": "pnpm run lint && pnpm run format --check && pnpm run validate && pnpm run validate:commit",
|
|
212
|
+
"test:litellm-context:vitest": "pnpm exec vitest run test/litellmContextWindows.test.ts",
|
|
213
|
+
"test:step-budget-guard:vitest": "pnpm exec vitest run test/stepBudgetGuard.test.ts"
|
|
212
214
|
},
|
|
213
215
|
"files": [
|
|
214
216
|
"dist",
|