@juspay/neurolink 10.9.1 → 10.10.1
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 +400 -398
- package/dist/cli/commands/proxy.js +29 -0
- package/dist/core/modules/GenerationHandler.js +21 -2
- package/dist/core/modules/structuredOutputPolicy.d.ts +8 -0
- package/dist/core/modules/structuredOutputPolicy.js +8 -0
- package/dist/lib/core/modules/GenerationHandler.js +21 -2
- package/dist/lib/core/modules/structuredOutputPolicy.d.ts +8 -0
- package/dist/lib/core/modules/structuredOutputPolicy.js +8 -0
- package/dist/lib/providers/anthropic/client.d.ts +22 -7
- package/dist/lib/providers/anthropic/client.js +188 -61
- package/dist/lib/providers/anthropic/rateLimitCapture.d.ts +82 -0
- package/dist/lib/providers/anthropic/rateLimitCapture.js +375 -0
- package/dist/lib/providers/anthropic/structuredOutput.d.ts +58 -0
- package/dist/lib/providers/anthropic/structuredOutput.js +98 -0
- package/dist/lib/proxy/quotaHeaders.d.ts +73 -0
- package/dist/lib/proxy/quotaHeaders.js +189 -0
- package/dist/lib/server/routes/claudeProxyRoutes.js +132 -17
- package/dist/lib/types/analytics.d.ts +8 -0
- package/dist/lib/types/generate.d.ts +23 -0
- package/dist/lib/types/proxy.d.ts +43 -0
- package/dist/lib/types/subscription.d.ts +77 -0
- package/dist/providers/anthropic/client.d.ts +22 -7
- package/dist/providers/anthropic/client.js +188 -61
- package/dist/providers/anthropic/rateLimitCapture.d.ts +82 -0
- package/dist/providers/anthropic/rateLimitCapture.js +374 -0
- package/dist/providers/anthropic/structuredOutput.d.ts +58 -0
- package/dist/providers/anthropic/structuredOutput.js +97 -0
- package/dist/proxy/quotaHeaders.d.ts +73 -0
- package/dist/proxy/quotaHeaders.js +188 -0
- package/dist/server/routes/claudeProxyRoutes.js +132 -17
- package/dist/types/analytics.d.ts +8 -0
- package/dist/types/generate.d.ts +23 -0
- package/dist/types/proxy.d.ts +43 -0
- package/dist/types/subscription.d.ts +77 -0
- package/package.json +5 -2
|
@@ -1497,9 +1497,34 @@ export async function createProxyStartApp(params) {
|
|
|
1497
1497
|
toolRegistry: params.neurolink.getToolRegistry(),
|
|
1498
1498
|
timestamp: Date.now(),
|
|
1499
1499
|
metadata: {},
|
|
1500
|
+
// Route handlers publish limit/quota headers here. Only the streaming
|
|
1501
|
+
// paths build their own Response (and set headers directly); every
|
|
1502
|
+
// JSON and error path returns a plain object, so without this the
|
|
1503
|
+
// headers had nowhere to go. Applied to each c.json() return below.
|
|
1504
|
+
responseHeaders: {},
|
|
1505
|
+
};
|
|
1506
|
+
/** Copy handler-published headers onto the outgoing response. */
|
|
1507
|
+
const applyResponseHeaders = () => {
|
|
1508
|
+
for (const [key, value] of Object.entries(ctx.responseHeaders)) {
|
|
1509
|
+
c.header(key, value);
|
|
1510
|
+
}
|
|
1500
1511
|
};
|
|
1501
1512
|
const result = await route.handler(ctx);
|
|
1502
1513
|
if (result instanceof Response) {
|
|
1514
|
+
// Streaming responses own their headers; merge in anything the
|
|
1515
|
+
// handler published on the context that the Response lacks. A Response
|
|
1516
|
+
// obtained from fetch() carries immutable headers, so this is
|
|
1517
|
+
// best-effort — the body must still reach the client either way.
|
|
1518
|
+
try {
|
|
1519
|
+
for (const [key, value] of Object.entries(ctx.responseHeaders)) {
|
|
1520
|
+
if (!result.headers.has(key)) {
|
|
1521
|
+
result.headers.set(key, value);
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
catch {
|
|
1526
|
+
// Immutable header guard — skip enrichment, keep the response.
|
|
1527
|
+
}
|
|
1503
1528
|
return result;
|
|
1504
1529
|
}
|
|
1505
1530
|
if (result &&
|
|
@@ -1544,6 +1569,7 @@ export async function createProxyStartApp(params) {
|
|
|
1544
1569
|
});
|
|
1545
1570
|
return new Response(responseStream, {
|
|
1546
1571
|
headers: {
|
|
1572
|
+
...ctx.responseHeaders,
|
|
1547
1573
|
"Content-Type": "text/event-stream",
|
|
1548
1574
|
"Cache-Control": "no-cache",
|
|
1549
1575
|
Connection: "keep-alive",
|
|
@@ -1556,6 +1582,7 @@ export async function createProxyStartApp(params) {
|
|
|
1556
1582
|
const httpResult = result;
|
|
1557
1583
|
const status = httpResult.httpStatus ?? 200;
|
|
1558
1584
|
delete httpResult.httpStatus;
|
|
1585
|
+
applyResponseHeaders();
|
|
1559
1586
|
return c.json(result, status);
|
|
1560
1587
|
}
|
|
1561
1588
|
if (result &&
|
|
@@ -1564,8 +1591,10 @@ export async function createProxyStartApp(params) {
|
|
|
1564
1591
|
result.type === "error") {
|
|
1565
1592
|
const errorResult = result;
|
|
1566
1593
|
const status = mapClaudeErrorTypeToStatus(errorResult.error?.type);
|
|
1594
|
+
applyResponseHeaders();
|
|
1567
1595
|
return c.json(result, status);
|
|
1568
1596
|
}
|
|
1597
|
+
applyResponseHeaders();
|
|
1569
1598
|
return c.json(result ?? {});
|
|
1570
1599
|
});
|
|
1571
1600
|
}
|
|
@@ -26,6 +26,7 @@ import { DEFAULT_MAX_STEPS, DEFAULT_WRAPUP_TIME_LEAD_MS, } from "../constants.js
|
|
|
26
26
|
import { createStepBudgetGuard, estimateFixedOverheadTokens, } from "../../context/stepBudgetGuard.js";
|
|
27
27
|
import { isTemperatureDeprecatedError, isSchemaComplexityError, isToolsSchemaConflictError, isToolsSchemaExclusionInForce, } from "./structuredOutputPolicy.js";
|
|
28
28
|
import { coerceJsonToSchema } from "../../utils/json/coerce.js";
|
|
29
|
+
import { convertZodToJsonSchema } from "../../utils/schemaConversion.js";
|
|
29
30
|
import { NoObjectGeneratedError } from "../../utils/generationErrors.js";
|
|
30
31
|
import { Output, stepCountIs } from "../../utils/tool.js";
|
|
31
32
|
import { generateText } from "../../utils/generation.js";
|
|
@@ -105,11 +106,14 @@ export function resolveTurnBudget(options, turnStartMs) {
|
|
|
105
106
|
* `providerOptions:` spreads in the args literal would silently clobber each
|
|
106
107
|
* other (object spread does not deep-merge).
|
|
107
108
|
*/
|
|
108
|
-
function buildProviderOptions(options, isGoogleProvider, callerTimeoutMs) {
|
|
109
|
+
function buildProviderOptions(options, isGoogleProvider, callerTimeoutMs, finalResultSchema) {
|
|
109
110
|
const providerOptions = {};
|
|
110
111
|
if (callerTimeoutMs !== undefined) {
|
|
111
112
|
providerOptions.neurolink = { timeoutMs: callerTimeoutMs };
|
|
112
113
|
}
|
|
114
|
+
if (finalResultSchema) {
|
|
115
|
+
providerOptions.anthropic = { finalResultSchema };
|
|
116
|
+
}
|
|
113
117
|
if (options.thinkingConfig?.enabled && isGoogleProvider) {
|
|
114
118
|
// Gemini 3 uses thinkingLevel; Gemini 2.5 uses thinkingBudget.
|
|
115
119
|
providerOptions.google = {
|
|
@@ -236,7 +240,22 @@ export class GenerationHandler {
|
|
|
236
240
|
const prepareStep = options.prepareStep;
|
|
237
241
|
const { callerTimeoutMs, turnBudgetMs, wrapupLeadMs, turnDeadline } = resolveTurnBudget(options, turnStartMs);
|
|
238
242
|
let wrapupForced = false;
|
|
239
|
-
|
|
243
|
+
// The native Anthropic Messages surface cannot combine AI-SDK structured
|
|
244
|
+
// output with tools (see structuredOutputPolicy — experimental_output
|
|
245
|
+
// replaces the tools array), so `useStructuredOutput` is false above and
|
|
246
|
+
// the schema would simply be dropped for every agent/MCP turn. Hand the
|
|
247
|
+
// JSON Schema to the provider instead: it appends an additive
|
|
248
|
+
// `final_result` tool and returns the answer as that tool's arguments,
|
|
249
|
+
// keeping the real tools callable. Bedrock is deliberately excluded — it
|
|
250
|
+
// runs on the third-party @ai-sdk/amazon-bedrock model, which has no such
|
|
251
|
+
// handling.
|
|
252
|
+
const finalResultSchema = this.providerName === "anthropic" &&
|
|
253
|
+
!!options.schema &&
|
|
254
|
+
shouldUseTools &&
|
|
255
|
+
Object.keys(tools).length > 0
|
|
256
|
+
? convertZodToJsonSchema(options.schema)
|
|
257
|
+
: undefined;
|
|
258
|
+
const providerOptions = buildProviderOptions(options, isGoogleProvider, callerTimeoutMs, finalResultSchema);
|
|
240
259
|
// Hoist system-role messages into generateText's top-level `system` option
|
|
241
260
|
// rather than passing them inside `messages` (deprecated by the AI SDK,
|
|
242
261
|
// rejected in v7). See extractSystemMessages for the rationale. (#1024)
|
|
@@ -23,6 +23,14 @@ export declare function isGeminiProvider(providerName: string, modelName: string
|
|
|
23
23
|
* experimental_output + tools silently drops tool_use blocks on this surface, so
|
|
24
24
|
* structured output must be disabled when tools are active. Vertex+Claude is NOT
|
|
25
25
|
* matched here (different transport, no conflict).
|
|
26
|
+
*
|
|
27
|
+
* Being excluded here no longer means the schema is LOST for provider
|
|
28
|
+
* "anthropic": GenerationHandler forwards the JSON Schema to the provider via
|
|
29
|
+
* `providerOptions.anthropic.finalResultSchema`, and the provider appends an
|
|
30
|
+
* additive `final_result` tool (see providers/anthropic/structuredOutput.ts) —
|
|
31
|
+
* schema enforcement without giving up tool calling. "bedrock" has no such
|
|
32
|
+
* handling (it runs on the third-party @ai-sdk/amazon-bedrock model) and still
|
|
33
|
+
* falls back to text-mode coercion.
|
|
26
34
|
*/
|
|
27
35
|
export declare function isNativeAnthropicProvider(providerName: string): boolean;
|
|
28
36
|
/**
|
|
@@ -33,6 +33,14 @@ export function isGeminiProvider(providerName, modelName) {
|
|
|
33
33
|
* experimental_output + tools silently drops tool_use blocks on this surface, so
|
|
34
34
|
* structured output must be disabled when tools are active. Vertex+Claude is NOT
|
|
35
35
|
* matched here (different transport, no conflict).
|
|
36
|
+
*
|
|
37
|
+
* Being excluded here no longer means the schema is LOST for provider
|
|
38
|
+
* "anthropic": GenerationHandler forwards the JSON Schema to the provider via
|
|
39
|
+
* `providerOptions.anthropic.finalResultSchema`, and the provider appends an
|
|
40
|
+
* additive `final_result` tool (see providers/anthropic/structuredOutput.ts) —
|
|
41
|
+
* schema enforcement without giving up tool calling. "bedrock" has no such
|
|
42
|
+
* handling (it runs on the third-party @ai-sdk/amazon-bedrock model) and still
|
|
43
|
+
* falls back to text-mode coercion.
|
|
36
44
|
*/
|
|
37
45
|
export function isNativeAnthropicProvider(providerName) {
|
|
38
46
|
return providerName === "anthropic" || providerName === "bedrock";
|
|
@@ -26,6 +26,7 @@ import { DEFAULT_MAX_STEPS, DEFAULT_WRAPUP_TIME_LEAD_MS, } from "../constants.js
|
|
|
26
26
|
import { createStepBudgetGuard, estimateFixedOverheadTokens, } from "../../context/stepBudgetGuard.js";
|
|
27
27
|
import { isTemperatureDeprecatedError, isSchemaComplexityError, isToolsSchemaConflictError, isToolsSchemaExclusionInForce, } from "./structuredOutputPolicy.js";
|
|
28
28
|
import { coerceJsonToSchema } from "../../utils/json/coerce.js";
|
|
29
|
+
import { convertZodToJsonSchema } from "../../utils/schemaConversion.js";
|
|
29
30
|
import { NoObjectGeneratedError } from "../../utils/generationErrors.js";
|
|
30
31
|
import { Output, stepCountIs } from "../../utils/tool.js";
|
|
31
32
|
import { generateText } from "../../utils/generation.js";
|
|
@@ -105,11 +106,14 @@ export function resolveTurnBudget(options, turnStartMs) {
|
|
|
105
106
|
* `providerOptions:` spreads in the args literal would silently clobber each
|
|
106
107
|
* other (object spread does not deep-merge).
|
|
107
108
|
*/
|
|
108
|
-
function buildProviderOptions(options, isGoogleProvider, callerTimeoutMs) {
|
|
109
|
+
function buildProviderOptions(options, isGoogleProvider, callerTimeoutMs, finalResultSchema) {
|
|
109
110
|
const providerOptions = {};
|
|
110
111
|
if (callerTimeoutMs !== undefined) {
|
|
111
112
|
providerOptions.neurolink = { timeoutMs: callerTimeoutMs };
|
|
112
113
|
}
|
|
114
|
+
if (finalResultSchema) {
|
|
115
|
+
providerOptions.anthropic = { finalResultSchema };
|
|
116
|
+
}
|
|
113
117
|
if (options.thinkingConfig?.enabled && isGoogleProvider) {
|
|
114
118
|
// Gemini 3 uses thinkingLevel; Gemini 2.5 uses thinkingBudget.
|
|
115
119
|
providerOptions.google = {
|
|
@@ -236,7 +240,22 @@ export class GenerationHandler {
|
|
|
236
240
|
const prepareStep = options.prepareStep;
|
|
237
241
|
const { callerTimeoutMs, turnBudgetMs, wrapupLeadMs, turnDeadline } = resolveTurnBudget(options, turnStartMs);
|
|
238
242
|
let wrapupForced = false;
|
|
239
|
-
|
|
243
|
+
// The native Anthropic Messages surface cannot combine AI-SDK structured
|
|
244
|
+
// output with tools (see structuredOutputPolicy — experimental_output
|
|
245
|
+
// replaces the tools array), so `useStructuredOutput` is false above and
|
|
246
|
+
// the schema would simply be dropped for every agent/MCP turn. Hand the
|
|
247
|
+
// JSON Schema to the provider instead: it appends an additive
|
|
248
|
+
// `final_result` tool and returns the answer as that tool's arguments,
|
|
249
|
+
// keeping the real tools callable. Bedrock is deliberately excluded — it
|
|
250
|
+
// runs on the third-party @ai-sdk/amazon-bedrock model, which has no such
|
|
251
|
+
// handling.
|
|
252
|
+
const finalResultSchema = this.providerName === "anthropic" &&
|
|
253
|
+
!!options.schema &&
|
|
254
|
+
shouldUseTools &&
|
|
255
|
+
Object.keys(tools).length > 0
|
|
256
|
+
? convertZodToJsonSchema(options.schema)
|
|
257
|
+
: undefined;
|
|
258
|
+
const providerOptions = buildProviderOptions(options, isGoogleProvider, callerTimeoutMs, finalResultSchema);
|
|
240
259
|
// Hoist system-role messages into generateText's top-level `system` option
|
|
241
260
|
// rather than passing them inside `messages` (deprecated by the AI SDK,
|
|
242
261
|
// rejected in v7). See extractSystemMessages for the rationale. (#1024)
|
|
@@ -23,6 +23,14 @@ export declare function isGeminiProvider(providerName: string, modelName: string
|
|
|
23
23
|
* experimental_output + tools silently drops tool_use blocks on this surface, so
|
|
24
24
|
* structured output must be disabled when tools are active. Vertex+Claude is NOT
|
|
25
25
|
* matched here (different transport, no conflict).
|
|
26
|
+
*
|
|
27
|
+
* Being excluded here no longer means the schema is LOST for provider
|
|
28
|
+
* "anthropic": GenerationHandler forwards the JSON Schema to the provider via
|
|
29
|
+
* `providerOptions.anthropic.finalResultSchema`, and the provider appends an
|
|
30
|
+
* additive `final_result` tool (see providers/anthropic/structuredOutput.ts) —
|
|
31
|
+
* schema enforcement without giving up tool calling. "bedrock" has no such
|
|
32
|
+
* handling (it runs on the third-party @ai-sdk/amazon-bedrock model) and still
|
|
33
|
+
* falls back to text-mode coercion.
|
|
26
34
|
*/
|
|
27
35
|
export declare function isNativeAnthropicProvider(providerName: string): boolean;
|
|
28
36
|
/**
|
|
@@ -33,6 +33,14 @@ export function isGeminiProvider(providerName, modelName) {
|
|
|
33
33
|
* experimental_output + tools silently drops tool_use blocks on this surface, so
|
|
34
34
|
* structured output must be disabled when tools are active. Vertex+Claude is NOT
|
|
35
35
|
* matched here (different transport, no conflict).
|
|
36
|
+
*
|
|
37
|
+
* Being excluded here no longer means the schema is LOST for provider
|
|
38
|
+
* "anthropic": GenerationHandler forwards the JSON Schema to the provider via
|
|
39
|
+
* `providerOptions.anthropic.finalResultSchema`, and the provider appends an
|
|
40
|
+
* additive `final_result` tool (see providers/anthropic/structuredOutput.ts) —
|
|
41
|
+
* schema enforcement without giving up tool calling. "bedrock" has no such
|
|
42
|
+
* handling (it runs on the third-party @ai-sdk/amazon-bedrock model) and still
|
|
43
|
+
* falls back to text-mode coercion.
|
|
36
44
|
*/
|
|
37
45
|
export function isNativeAnthropicProvider(providerName) {
|
|
38
46
|
return providerName === "anthropic" || providerName === "bedrock";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type AIProviderName } from "../../constants/enums.js";
|
|
2
2
|
import { BaseProvider } from "../../core/baseProvider.js";
|
|
3
|
-
import type { AnthropicProviderConfig, StreamOptions, StreamResult, ValidationSchema, EnhancedGenerateResult, TextGenerationOptions, AnthropicAuthMethod, AnthropicResponseMetadata, ClaudeSubscriptionTier, ClaudeUsageInfo } from "../../types/index.js";
|
|
3
|
+
import type { AnthropicProviderConfig, StreamOptions, StreamResult, ValidationSchema, EnhancedGenerateResult, TextGenerationOptions, AnthropicAuthMethod, AnthropicRateLimitInfo, AnthropicResponseMetadata, ClaudeSubscriptionTier, ClaudeUsageInfo } from "../../types/index.js";
|
|
4
4
|
import type { LanguageModel } from "../../types/index.js";
|
|
5
5
|
/**
|
|
6
6
|
* Anthropic Provider v2 - BaseProvider Implementation
|
|
@@ -103,12 +103,18 @@ export declare class AnthropicProvider extends BaseProvider {
|
|
|
103
103
|
*/
|
|
104
104
|
getLastResponseMetadata(): AnthropicResponseMetadata | null;
|
|
105
105
|
/**
|
|
106
|
-
* Update response metadata from
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
106
|
+
* Update response metadata from a captured limit snapshot.
|
|
107
|
+
*
|
|
108
|
+
* Takes already-parsed rate-limit info rather than raw headers: parsing now
|
|
109
|
+
* lives in `rateLimitCapture`, which is the only layer that sees the raw
|
|
110
|
+
* response and understands both header families (unified subscription
|
|
111
|
+
* windows and legacy per-tier counters).
|
|
112
|
+
*
|
|
113
|
+
* @param rateLimit - Parsed rate-limit figures
|
|
114
|
+
* @param requestId - Optional Anthropic request ID
|
|
115
|
+
* @param usageUpdate - Optional token counts to fold into usage tracking
|
|
110
116
|
*/
|
|
111
|
-
protected updateResponseMetadata(
|
|
117
|
+
protected updateResponseMetadata(rateLimit: AnthropicRateLimitInfo, requestId?: string, usageUpdate?: {
|
|
112
118
|
inputTokens?: number;
|
|
113
119
|
outputTokens?: number;
|
|
114
120
|
}): void;
|
|
@@ -127,7 +133,16 @@ export declare class AnthropicProvider extends BaseProvider {
|
|
|
127
133
|
* BaseProvider so that expired tokens are renewed automatically.
|
|
128
134
|
*/
|
|
129
135
|
generate(optionsOrPrompt: TextGenerationOptions | string, analysisSchema?: ValidationSchema): Promise<EnhancedGenerateResult | null>;
|
|
130
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Fold a captured snapshot into the provider's usage bookkeeping and log it.
|
|
138
|
+
*
|
|
139
|
+
* `updateResponseMetadata` had no callers before this — the metadata it
|
|
140
|
+
* maintains, and the public `getLastResponseMetadata()` / `getUsageInfo()`
|
|
141
|
+
* that read it, were never populated by anything.
|
|
142
|
+
*/
|
|
143
|
+
private recordLimitSnapshot;
|
|
144
|
+
protected executeStream(options: StreamOptions, analysisSchema?: ValidationSchema): Promise<StreamResult>;
|
|
145
|
+
private executeStreamInCaptureScope;
|
|
131
146
|
isAvailable(): Promise<boolean>;
|
|
132
147
|
getModel(): LanguageModel;
|
|
133
148
|
}
|