@juspay/neurolink 12.0.4 → 12.0.5

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/dist/neurolink.js CHANGED
@@ -6070,32 +6070,118 @@ Current user's request: ${currentInput}`;
6070
6070
  // oversized case. When the budget check shows the request is
6071
6071
  // over budget but there's nothing to compact (no memory + no
6072
6072
  // inline messages — e.g. a huge prompt or huge tool definitions
6073
- // alone), throw before dispatch instead of wasting a roundtrip.
6073
+ // alone), recover by WINDOWING the prompt when the prompt is what
6074
+ // blew the budget: keep its head and tail around an elision marker
6075
+ // and dispatch. Agentic callers (Yama's session loop) carry their
6076
+ // whole tool transcript in the prompt; the previous
6077
+ // unconditional throw dead-ended every such turn — observed live
6078
+ // as an unbounded retry loop (93K→299K tokens, no verdict, ever).
6079
+ // The throw remains for the truly unrecoverable case: system
6080
+ // prompt + tool definitions alone exceed the budget.
6081
+ let promptWindowRecovered = false;
6074
6082
  if (!budgetCheck.withinBudget && !dpgHasCompactableMessages) {
6075
- try {
6076
- this.emitter.emit("compaction.insufficient", {
6077
- stagesAttempted: ["pre-dispatch hard cap"],
6078
- finalTokens: budgetCheck.estimatedInputTokens,
6079
- budget: budgetCheck.availableInputTokens,
6080
- provider: providerName,
6081
- model: options.model,
6082
- phase: "pre-dispatch-no-recovery",
6083
- timestamp: Date.now(),
6084
- });
6083
+ const fixedOverhead = (budgetCheck.breakdown?.systemPrompt ?? 0) +
6084
+ (budgetCheck.breakdown?.toolDefinitions ?? 0) +
6085
+ (budgetCheck.breakdown?.fileAttachments ?? 0);
6086
+ // 3% margin against estimator drift; 1024-token floor — below
6087
+ // that, a windowed prompt carries too little to answer from.
6088
+ const promptBudget = Math.floor((budgetCheck.availableInputTokens - fixedOverhead) * 0.97);
6089
+ const promptText = typeof options.prompt === "string" ? options.prompt : undefined;
6090
+ if (promptText &&
6091
+ promptBudget >= 1024 &&
6092
+ (budgetCheck.breakdown?.currentPrompt ?? 0) > promptBudget) {
6093
+ const marker = "\n\n[... middle of this prompt elided by NeuroLink to fit the model's context window ...]\n\n";
6094
+ // Proportional char budget from the observed chars-per-token of
6095
+ // THIS text, re-checked and shrunk until the estimator agrees.
6096
+ let charBudget = Math.floor(promptText.length *
6097
+ (promptBudget /
6098
+ Math.max(budgetCheck.breakdown?.currentPrompt ?? 1, 1)));
6099
+ let windowed = promptText;
6100
+ for (let attempt = 0; attempt < 4; attempt++) {
6101
+ const headChars = Math.floor(charBudget * 0.6);
6102
+ const tailChars = Math.max(charBudget - headChars - marker.length, 0);
6103
+ windowed =
6104
+ promptText.slice(0, headChars) +
6105
+ marker +
6106
+ (tailChars > 0 ? promptText.slice(-tailChars) : "");
6107
+ const recheck = checkContextBudget({
6108
+ provider: providerName,
6109
+ model: options.model,
6110
+ maxTokens: options.maxTokens,
6111
+ systemPrompt: options.systemPrompt,
6112
+ conversationMessages: [],
6113
+ currentPrompt: windowed,
6114
+ toolDefinitions: options.tools
6115
+ ? Object.values(options.tools)
6116
+ : undefined,
6117
+ });
6118
+ if (recheck.withinBudget) {
6119
+ break;
6120
+ }
6121
+ charBudget = Math.floor(charBudget * 0.8);
6122
+ if (attempt === 3) {
6123
+ windowed = promptText; // give up — fall through to the throw
6124
+ }
6125
+ }
6126
+ if (windowed !== promptText) {
6127
+ logger.warn("[NeuroLink] Prompt exceeded the model's context budget with nothing to compact — " +
6128
+ "windowed the prompt (head+tail kept, middle elided) to fit.", {
6129
+ provider: providerName,
6130
+ model: options.model,
6131
+ estimatedTokens: budgetCheck.estimatedInputTokens,
6132
+ budget: budgetCheck.availableInputTokens,
6133
+ originalPromptChars: promptText.length,
6134
+ windowedPromptChars: windowed.length,
6135
+ });
6136
+ try {
6137
+ this.emitter.emit("compaction.applied", {
6138
+ stagesAttempted: ["pre-dispatch prompt window"],
6139
+ finalTokens: budgetCheck.availableInputTokens,
6140
+ budget: budgetCheck.availableInputTokens,
6141
+ provider: providerName,
6142
+ model: options.model,
6143
+ phase: "pre-dispatch-prompt-window",
6144
+ timestamp: Date.now(),
6145
+ });
6146
+ }
6147
+ catch {
6148
+ /* listener errors are non-fatal */
6149
+ }
6150
+ options.prompt = windowed;
6151
+ const inputHolder = options
6152
+ .input;
6153
+ if (inputHolder && typeof inputHolder.text === "string") {
6154
+ inputHolder.text = windowed;
6155
+ }
6156
+ promptWindowRecovered = true;
6157
+ }
6085
6158
  }
6086
- catch {
6087
- /* listener errors are non-fatal */
6159
+ if (!promptWindowRecovered) {
6160
+ try {
6161
+ this.emitter.emit("compaction.insufficient", {
6162
+ stagesAttempted: ["pre-dispatch hard cap"],
6163
+ finalTokens: budgetCheck.estimatedInputTokens,
6164
+ budget: budgetCheck.availableInputTokens,
6165
+ provider: providerName,
6166
+ model: options.model,
6167
+ phase: "pre-dispatch-no-recovery",
6168
+ timestamp: Date.now(),
6169
+ });
6170
+ }
6171
+ catch {
6172
+ /* listener errors are non-fatal */
6173
+ }
6174
+ throw new ContextBudgetExceededError(`Context exceeds model budget and no compaction is possible ` +
6175
+ `(no conversationMemory, no inline conversationMessages — only ` +
6176
+ `prompt + tools). Estimated: ${budgetCheck.estimatedInputTokens} ` +
6177
+ `tokens, budget: ${budgetCheck.availableInputTokens} tokens. ` +
6178
+ `Reduce prompt or tool-definition size, or trim the request.`, {
6179
+ estimatedTokens: budgetCheck.estimatedInputTokens,
6180
+ availableTokens: budgetCheck.availableInputTokens,
6181
+ stagesUsed: [],
6182
+ breakdown: budgetCheck.breakdown,
6183
+ });
6088
6184
  }
6089
- throw new ContextBudgetExceededError(`Context exceeds model budget and no compaction is possible ` +
6090
- `(no conversationMemory, no inline conversationMessages — only ` +
6091
- `prompt + tools). Estimated: ${budgetCheck.estimatedInputTokens} ` +
6092
- `tokens, budget: ${budgetCheck.availableInputTokens} tokens. ` +
6093
- `Reduce prompt or tool-definition size, or trim the request.`, {
6094
- estimatedTokens: budgetCheck.estimatedInputTokens,
6095
- availableTokens: budgetCheck.availableInputTokens,
6096
- stagesUsed: [],
6097
- breakdown: budgetCheck.breakdown,
6098
- });
6099
6185
  }
6100
6186
  if (budgetCheck.shouldCompact &&
6101
6187
  (this.conversationMemory || dpgHasInlineMessages) &&
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "12.0.4",
3
+ "version": "12.0.5",
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": {