@juspay/neurolink 8.26.0 → 8.26.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 +6 -0
- package/README.md +47 -25
- package/dist/adapters/providerImageAdapter.js +11 -0
- package/dist/cli/commands/config.js +16 -23
- package/dist/cli/commands/setup-anthropic.js +3 -26
- package/dist/cli/commands/setup-azure.js +3 -22
- package/dist/cli/commands/setup-bedrock.js +3 -26
- package/dist/cli/commands/setup-google-ai.js +3 -22
- package/dist/cli/commands/setup-mistral.js +3 -31
- package/dist/cli/commands/setup-openai.js +3 -22
- package/dist/cli/factories/commandFactory.js +32 -0
- package/dist/cli/factories/ollamaCommandFactory.js +5 -17
- package/dist/cli/loop/optionsSchema.d.ts +1 -1
- package/dist/cli/loop/optionsSchema.js +13 -0
- package/dist/config/modelSpecificPrompts.d.ts +9 -0
- package/dist/config/modelSpecificPrompts.js +38 -0
- package/dist/constants/enums.d.ts +8 -0
- package/dist/constants/enums.js +8 -0
- package/dist/constants/tokens.d.ts +25 -0
- package/dist/constants/tokens.js +18 -0
- package/dist/core/analytics.js +7 -28
- package/dist/core/baseProvider.js +1 -0
- package/dist/core/constants.d.ts +1 -0
- package/dist/core/constants.js +1 -0
- package/dist/core/modules/GenerationHandler.js +43 -5
- package/dist/core/streamAnalytics.d.ts +1 -0
- package/dist/core/streamAnalytics.js +8 -16
- package/dist/lib/adapters/providerImageAdapter.js +11 -0
- package/dist/lib/config/modelSpecificPrompts.d.ts +9 -0
- package/dist/lib/config/modelSpecificPrompts.js +39 -0
- package/dist/lib/constants/enums.d.ts +8 -0
- package/dist/lib/constants/enums.js +8 -0
- package/dist/lib/constants/tokens.d.ts +25 -0
- package/dist/lib/constants/tokens.js +18 -0
- package/dist/lib/core/analytics.js +7 -28
- package/dist/lib/core/baseProvider.js +1 -0
- package/dist/lib/core/constants.d.ts +1 -0
- package/dist/lib/core/constants.js +1 -0
- package/dist/lib/core/modules/GenerationHandler.js +43 -5
- package/dist/lib/core/streamAnalytics.d.ts +1 -0
- package/dist/lib/core/streamAnalytics.js +8 -16
- package/dist/lib/providers/googleAiStudio.d.ts +15 -0
- package/dist/lib/providers/googleAiStudio.js +659 -3
- package/dist/lib/providers/googleVertex.d.ts +25 -0
- package/dist/lib/providers/googleVertex.js +978 -3
- package/dist/lib/types/analytics.d.ts +4 -0
- package/dist/lib/types/cli.d.ts +16 -0
- package/dist/lib/types/conversation.d.ts +72 -4
- package/dist/lib/types/conversation.js +30 -0
- package/dist/lib/types/generateTypes.d.ts +135 -0
- package/dist/lib/types/groundingTypes.d.ts +231 -0
- package/dist/lib/types/groundingTypes.js +12 -0
- package/dist/lib/types/providers.d.ts +29 -0
- package/dist/lib/types/streamTypes.d.ts +54 -0
- package/dist/lib/utils/analyticsUtils.js +22 -2
- package/dist/lib/utils/modelChoices.d.ts +82 -0
- package/dist/lib/utils/modelChoices.js +402 -0
- package/dist/lib/utils/modelDetection.d.ts +9 -0
- package/dist/lib/utils/modelDetection.js +81 -0
- package/dist/lib/utils/schemaConversion.d.ts +12 -0
- package/dist/lib/utils/schemaConversion.js +90 -0
- package/dist/lib/utils/thinkingConfig.d.ts +108 -0
- package/dist/lib/utils/thinkingConfig.js +105 -0
- package/dist/lib/utils/tokenUtils.d.ts +124 -0
- package/dist/lib/utils/tokenUtils.js +240 -0
- package/dist/lib/utils/transformationUtils.js +15 -26
- package/dist/providers/googleAiStudio.d.ts +15 -0
- package/dist/providers/googleAiStudio.js +659 -3
- package/dist/providers/googleVertex.d.ts +25 -0
- package/dist/providers/googleVertex.js +978 -3
- package/dist/types/analytics.d.ts +4 -0
- package/dist/types/cli.d.ts +16 -0
- package/dist/types/conversation.d.ts +72 -4
- package/dist/types/conversation.js +30 -0
- package/dist/types/generateTypes.d.ts +135 -0
- package/dist/types/groundingTypes.d.ts +231 -0
- package/dist/types/groundingTypes.js +11 -0
- package/dist/types/providers.d.ts +29 -0
- package/dist/types/streamTypes.d.ts +54 -0
- package/dist/utils/analyticsUtils.js +22 -2
- package/dist/utils/modelChoices.d.ts +82 -0
- package/dist/utils/modelChoices.js +401 -0
- package/dist/utils/modelDetection.d.ts +9 -0
- package/dist/utils/modelDetection.js +80 -0
- package/dist/utils/schemaConversion.d.ts +12 -0
- package/dist/utils/schemaConversion.js +90 -0
- package/dist/utils/thinkingConfig.d.ts +108 -0
- package/dist/utils/thinkingConfig.js +104 -0
- package/dist/utils/tokenUtils.d.ts +124 -0
- package/dist/utils/tokenUtils.js +239 -0
- package/dist/utils/transformationUtils.js +15 -26
- package/package.json +4 -3
|
@@ -2,6 +2,96 @@ import { zodToJsonSchema } from "zod-to-json-schema";
|
|
|
2
2
|
import { jsonSchemaToZod } from "json-schema-to-zod";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { logger } from "./logger.js";
|
|
5
|
+
/**
|
|
6
|
+
* Inline a JSON Schema by recursively resolving all $ref references.
|
|
7
|
+
* zodToJsonSchema with 'name' option produces schemas with $ref pointing to definitions.
|
|
8
|
+
* Some SDKs (like @google/genai) expect flat schemas without $ref.
|
|
9
|
+
*
|
|
10
|
+
* This function handles:
|
|
11
|
+
* - Top-level $ref resolution
|
|
12
|
+
* - Nested $ref within properties, items, additionalProperties
|
|
13
|
+
* - $ref within allOf, anyOf, oneOf arrays
|
|
14
|
+
* - Circular reference detection to prevent infinite loops
|
|
15
|
+
*/
|
|
16
|
+
export function inlineJsonSchema(schema, definitions, visited = new Set()) {
|
|
17
|
+
// Use definitions from schema if not provided
|
|
18
|
+
const defs = definitions ||
|
|
19
|
+
schema.definitions;
|
|
20
|
+
// Handle $ref at current level
|
|
21
|
+
if (typeof schema.$ref === "string" &&
|
|
22
|
+
schema.$ref.startsWith("#/definitions/")) {
|
|
23
|
+
const defName = schema.$ref.replace("#/definitions/", "");
|
|
24
|
+
// Prevent circular reference infinite loops
|
|
25
|
+
if (visited.has(defName)) {
|
|
26
|
+
logger.debug(`[SCHEMA-INLINE] Circular reference detected for: ${defName}`);
|
|
27
|
+
// Return a simple object placeholder for circular refs
|
|
28
|
+
return { type: "object" };
|
|
29
|
+
}
|
|
30
|
+
if (defs && defs[defName]) {
|
|
31
|
+
visited.add(defName);
|
|
32
|
+
// Recursively inline the resolved definition
|
|
33
|
+
const resolved = inlineJsonSchema({ ...defs[defName] }, defs, visited);
|
|
34
|
+
visited.delete(defName);
|
|
35
|
+
return resolved;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Create result without $ref and definitions
|
|
39
|
+
const result = {};
|
|
40
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
41
|
+
// Skip $ref and definitions keys
|
|
42
|
+
if (key === "$ref" || key === "definitions") {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
// Recursively process nested schemas
|
|
46
|
+
if (key === "properties" && value && typeof value === "object") {
|
|
47
|
+
const properties = {};
|
|
48
|
+
for (const [propName, propSchema] of Object.entries(value)) {
|
|
49
|
+
if (propSchema && typeof propSchema === "object") {
|
|
50
|
+
properties[propName] = inlineJsonSchema(propSchema, defs, visited);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
properties[propName] = propSchema;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
result[key] = properties;
|
|
57
|
+
}
|
|
58
|
+
else if (key === "items" && value && typeof value === "object") {
|
|
59
|
+
// Handle array items schema
|
|
60
|
+
if (Array.isArray(value)) {
|
|
61
|
+
result[key] = value.map((item) => item && typeof item === "object"
|
|
62
|
+
? inlineJsonSchema(item, defs, visited)
|
|
63
|
+
: item);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
result[key] = inlineJsonSchema(value, defs, visited);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if (key === "additionalProperties" &&
|
|
70
|
+
value &&
|
|
71
|
+
typeof value === "object") {
|
|
72
|
+
result[key] = inlineJsonSchema(value, defs, visited);
|
|
73
|
+
}
|
|
74
|
+
else if ((key === "allOf" || key === "anyOf" || key === "oneOf") &&
|
|
75
|
+
Array.isArray(value)) {
|
|
76
|
+
// Handle composition schemas
|
|
77
|
+
result[key] = value.map((item) => item && typeof item === "object"
|
|
78
|
+
? inlineJsonSchema(item, defs, visited)
|
|
79
|
+
: item);
|
|
80
|
+
}
|
|
81
|
+
else if (key === "not" && value && typeof value === "object") {
|
|
82
|
+
result[key] = inlineJsonSchema(value, defs, visited);
|
|
83
|
+
}
|
|
84
|
+
else if ((key === "if" || key === "then" || key === "else") &&
|
|
85
|
+
value &&
|
|
86
|
+
typeof value === "object") {
|
|
87
|
+
result[key] = inlineJsonSchema(value, defs, visited);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
result[key] = value;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
5
95
|
/**
|
|
6
96
|
* Convert Zod schema to JSON Schema format for Claude AI
|
|
7
97
|
*/
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThinkingConfig utility functions for constructing thinking configuration objects.
|
|
3
|
+
*
|
|
4
|
+
* This module provides helper functions to create thinkingConfig objects consistently
|
|
5
|
+
* across the codebase, reducing duplication in CLI and providers.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* ThinkingLevel type for Gemini 3 models
|
|
9
|
+
*/
|
|
10
|
+
export type ThinkingLevel = "minimal" | "low" | "medium" | "high";
|
|
11
|
+
/**
|
|
12
|
+
* ThinkingConfig interface matching the SDK's expected structure
|
|
13
|
+
*/
|
|
14
|
+
export interface ThinkingConfig {
|
|
15
|
+
enabled?: boolean;
|
|
16
|
+
type?: "enabled" | "disabled";
|
|
17
|
+
/** Token budget for thinking (Anthropic models: 5000-100000) */
|
|
18
|
+
budgetTokens?: number;
|
|
19
|
+
/** Thinking level for Gemini 3 models */
|
|
20
|
+
thinkingLevel?: ThinkingLevel;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Options for creating a thinkingConfig from CLI-style options
|
|
24
|
+
*/
|
|
25
|
+
export interface CreateThinkingConfigOptions {
|
|
26
|
+
/** Enable thinking mode */
|
|
27
|
+
thinking?: boolean;
|
|
28
|
+
/** Token budget for thinking (defaults to 10000) */
|
|
29
|
+
thinkingBudget?: number;
|
|
30
|
+
/** Thinking level for Gemini 3 models */
|
|
31
|
+
thinkingLevel?: ThinkingLevel;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Native SDK thinkingConfig structure for Gemini native SDK.
|
|
35
|
+
*/
|
|
36
|
+
export interface NativeThinkingConfig {
|
|
37
|
+
includeThoughts: boolean;
|
|
38
|
+
thinkingLevel: ThinkingLevel;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Default token budget for thinking operations
|
|
42
|
+
*/
|
|
43
|
+
export declare const DEFAULT_THINKING_BUDGET_TOKENS = 10000;
|
|
44
|
+
/**
|
|
45
|
+
* Default thinking level for Gemini 3 models
|
|
46
|
+
*/
|
|
47
|
+
export declare const DEFAULT_THINKING_LEVEL: ThinkingLevel;
|
|
48
|
+
/**
|
|
49
|
+
* Creates a thinkingConfig object from CLI-style options.
|
|
50
|
+
*
|
|
51
|
+
* This helper consolidates the pattern used in CLI command handlers
|
|
52
|
+
* to convert simple CLI flags into the full thinkingConfig structure.
|
|
53
|
+
*
|
|
54
|
+
* @param options - CLI-style options with thinking, thinkingBudget, thinkingLevel
|
|
55
|
+
* @returns ThinkingConfig object or undefined if thinking is not enabled
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* // From CLI options
|
|
60
|
+
* const config = createThinkingConfig({
|
|
61
|
+
* thinking: true,
|
|
62
|
+
* thinkingBudget: 15000,
|
|
63
|
+
* thinkingLevel: "high"
|
|
64
|
+
* });
|
|
65
|
+
* // Returns: { enabled: true, budgetTokens: 15000, thinkingLevel: "high" }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function createThinkingConfig(options: CreateThinkingConfigOptions): ThinkingConfig | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* Creates a thinkingConfig from record-style options (useful for CLI handlers).
|
|
71
|
+
*
|
|
72
|
+
* This handles the type casting that's commonly needed when working with
|
|
73
|
+
* CLI argument records.
|
|
74
|
+
*
|
|
75
|
+
* @param options - Record-style options from CLI argv
|
|
76
|
+
* @returns ThinkingConfig object or undefined if thinking is not enabled
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const config = createThinkingConfigFromRecord(argv as Record<string, unknown>);
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function createThinkingConfigFromRecord(options: Record<string, unknown>): ThinkingConfig | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Creates thinkingConfig for native Gemini SDK (not AI SDK).
|
|
86
|
+
*
|
|
87
|
+
* This is used for direct calls to the Gemini SDK where the config
|
|
88
|
+
* structure is different from the AI SDK providerOptions.
|
|
89
|
+
*
|
|
90
|
+
* @param config - The thinkingConfig from options
|
|
91
|
+
* @returns NativeThinkingConfig object or undefined
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const nativeConfig = createNativeThinkingConfig(options.thinkingConfig);
|
|
96
|
+
* if (nativeConfig) {
|
|
97
|
+
* sdkConfig.thinkingConfig = nativeConfig;
|
|
98
|
+
* }
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export declare function createNativeThinkingConfig(config: ThinkingConfig | undefined): NativeThinkingConfig | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Checks if thinkingConfig should be applied based on options.
|
|
104
|
+
*
|
|
105
|
+
* @param config - The thinkingConfig from options
|
|
106
|
+
* @returns true if thinking should be enabled
|
|
107
|
+
*/
|
|
108
|
+
export declare function shouldEnableThinking(config: ThinkingConfig | undefined): boolean;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThinkingConfig utility functions for constructing thinking configuration objects.
|
|
3
|
+
*
|
|
4
|
+
* This module provides helper functions to create thinkingConfig objects consistently
|
|
5
|
+
* across the codebase, reducing duplication in CLI and providers.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Default token budget for thinking operations
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_THINKING_BUDGET_TOKENS = 10000;
|
|
11
|
+
/**
|
|
12
|
+
* Default thinking level for Gemini 3 models
|
|
13
|
+
*/
|
|
14
|
+
export const DEFAULT_THINKING_LEVEL = "high";
|
|
15
|
+
/**
|
|
16
|
+
* Creates a thinkingConfig object from CLI-style options.
|
|
17
|
+
*
|
|
18
|
+
* This helper consolidates the pattern used in CLI command handlers
|
|
19
|
+
* to convert simple CLI flags into the full thinkingConfig structure.
|
|
20
|
+
*
|
|
21
|
+
* @param options - CLI-style options with thinking, thinkingBudget, thinkingLevel
|
|
22
|
+
* @returns ThinkingConfig object or undefined if thinking is not enabled
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* // From CLI options
|
|
27
|
+
* const config = createThinkingConfig({
|
|
28
|
+
* thinking: true,
|
|
29
|
+
* thinkingBudget: 15000,
|
|
30
|
+
* thinkingLevel: "high"
|
|
31
|
+
* });
|
|
32
|
+
* // Returns: { enabled: true, budgetTokens: 15000, thinkingLevel: "high" }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export function createThinkingConfig(options) {
|
|
36
|
+
// Only create config if thinking is explicitly enabled or thinkingLevel is set
|
|
37
|
+
if (!options.thinking && !options.thinkingLevel) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
enabled: true,
|
|
42
|
+
budgetTokens: options.thinkingBudget ?? DEFAULT_THINKING_BUDGET_TOKENS,
|
|
43
|
+
thinkingLevel: options.thinkingLevel,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Creates a thinkingConfig from record-style options (useful for CLI handlers).
|
|
48
|
+
*
|
|
49
|
+
* This handles the type casting that's commonly needed when working with
|
|
50
|
+
* CLI argument records.
|
|
51
|
+
*
|
|
52
|
+
* @param options - Record-style options from CLI argv
|
|
53
|
+
* @returns ThinkingConfig object or undefined if thinking is not enabled
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const config = createThinkingConfigFromRecord(argv as Record<string, unknown>);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function createThinkingConfigFromRecord(options) {
|
|
61
|
+
const thinking = options.thinking;
|
|
62
|
+
const thinkingLevel = options.thinkingLevel;
|
|
63
|
+
const thinkingBudget = options.thinkingBudget;
|
|
64
|
+
return createThinkingConfig({
|
|
65
|
+
thinking,
|
|
66
|
+
thinkingLevel,
|
|
67
|
+
thinkingBudget,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Creates thinkingConfig for native Gemini SDK (not AI SDK).
|
|
72
|
+
*
|
|
73
|
+
* This is used for direct calls to the Gemini SDK where the config
|
|
74
|
+
* structure is different from the AI SDK providerOptions.
|
|
75
|
+
*
|
|
76
|
+
* @param config - The thinkingConfig from options
|
|
77
|
+
* @returns NativeThinkingConfig object or undefined
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const nativeConfig = createNativeThinkingConfig(options.thinkingConfig);
|
|
82
|
+
* if (nativeConfig) {
|
|
83
|
+
* sdkConfig.thinkingConfig = nativeConfig;
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export function createNativeThinkingConfig(config) {
|
|
88
|
+
if (!config?.enabled && !config?.thinkingLevel) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
includeThoughts: true,
|
|
93
|
+
thinkingLevel: config.thinkingLevel ?? DEFAULT_THINKING_LEVEL,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Checks if thinkingConfig should be applied based on options.
|
|
98
|
+
*
|
|
99
|
+
* @param config - The thinkingConfig from options
|
|
100
|
+
* @returns true if thinking should be enabled
|
|
101
|
+
*/
|
|
102
|
+
export function shouldEnableThinking(config) {
|
|
103
|
+
return Boolean(config?.enabled || config?.thinkingLevel);
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=thinkingConfig.js.map
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized token usage extraction utilities
|
|
3
|
+
* Handles multiple provider formats and optional fields
|
|
4
|
+
*
|
|
5
|
+
* Consolidates token extraction logic from:
|
|
6
|
+
* - GenerationHandler.ts
|
|
7
|
+
* - analytics.ts
|
|
8
|
+
* - streamAnalytics.ts
|
|
9
|
+
*/
|
|
10
|
+
import type { TokenUsage } from "../types/analytics.js";
|
|
11
|
+
/**
|
|
12
|
+
* Raw usage object that may come from various AI providers
|
|
13
|
+
* Supports multiple naming conventions and nested structures
|
|
14
|
+
*/
|
|
15
|
+
export interface RawUsageObject {
|
|
16
|
+
input?: number;
|
|
17
|
+
output?: number;
|
|
18
|
+
total?: number;
|
|
19
|
+
inputTokens?: number;
|
|
20
|
+
outputTokens?: number;
|
|
21
|
+
totalTokens?: number;
|
|
22
|
+
promptTokens?: number;
|
|
23
|
+
completionTokens?: number;
|
|
24
|
+
cacheCreationInputTokens?: number;
|
|
25
|
+
cacheReadInputTokens?: number;
|
|
26
|
+
cacheCreationTokens?: number;
|
|
27
|
+
cacheReadTokens?: number;
|
|
28
|
+
reasoningTokens?: number;
|
|
29
|
+
reasoning?: number;
|
|
30
|
+
reasoning_tokens?: number;
|
|
31
|
+
thinkingTokens?: number;
|
|
32
|
+
usage?: RawUsageObject;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Options for token extraction behavior
|
|
36
|
+
*/
|
|
37
|
+
export interface TokenExtractionOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Whether to calculate cache savings percentage
|
|
40
|
+
* @default true
|
|
41
|
+
*/
|
|
42
|
+
calculateCacheSavings?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* How to handle missing optional fields
|
|
45
|
+
* - "zero": Return 0 for missing optional fields
|
|
46
|
+
* - "undefined": Return undefined for missing optional fields (default)
|
|
47
|
+
*/
|
|
48
|
+
missingOptionalBehavior?: "zero" | "undefined";
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Extract input token count from various provider formats
|
|
52
|
+
* Priority: input > inputTokens > promptTokens
|
|
53
|
+
*/
|
|
54
|
+
export declare function extractInputTokens(usage: RawUsageObject): number;
|
|
55
|
+
/**
|
|
56
|
+
* Extract output token count from various provider formats
|
|
57
|
+
* Priority: output > outputTokens > completionTokens
|
|
58
|
+
*/
|
|
59
|
+
export declare function extractOutputTokens(usage: RawUsageObject): number;
|
|
60
|
+
/**
|
|
61
|
+
* Extract total token count from various provider formats
|
|
62
|
+
* Falls back to input + output if total is not provided
|
|
63
|
+
*/
|
|
64
|
+
export declare function extractTotalTokens(usage: RawUsageObject, input: number, output: number): number;
|
|
65
|
+
/**
|
|
66
|
+
* Extract reasoning/thinking token count from various provider formats
|
|
67
|
+
* Supports: reasoningTokens, thinkingTokens, reasoning_tokens, reasoning
|
|
68
|
+
*/
|
|
69
|
+
export declare function extractReasoningTokens(usage: RawUsageObject): number | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Extract cache creation token count from various provider formats
|
|
72
|
+
* Supports: cacheCreationInputTokens, cacheCreationTokens
|
|
73
|
+
*/
|
|
74
|
+
export declare function extractCacheCreationTokens(usage: RawUsageObject): number | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Extract cache read token count from various provider formats
|
|
77
|
+
* Supports: cacheReadInputTokens, cacheReadTokens
|
|
78
|
+
*/
|
|
79
|
+
export declare function extractCacheReadTokens(usage: RawUsageObject): number | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Calculate cache savings percentage
|
|
82
|
+
*
|
|
83
|
+
* This represents the percentage of input tokens served from cache.
|
|
84
|
+
* For Anthropic, cache read tokens cost 0.1x, so actual cost savings = cacheSavingsPercent * 0.9
|
|
85
|
+
* For other providers, cost savings may vary based on their cache pricing.
|
|
86
|
+
*
|
|
87
|
+
* @param cacheReadTokens Number of tokens read from cache
|
|
88
|
+
* @param inputTokens Number of non-cached input tokens
|
|
89
|
+
* @returns Percentage of tokens served from cache (0-100), or undefined if no cache usage
|
|
90
|
+
*/
|
|
91
|
+
export declare function calculateCacheSavingsPercent(cacheReadTokens: number | undefined, inputTokens: number): number | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* Extract token usage from various provider response formats
|
|
94
|
+
*
|
|
95
|
+
* Handles multiple input formats:
|
|
96
|
+
* - BaseProvider normalized format (input/output/total)
|
|
97
|
+
* - AI SDK format (inputTokens/outputTokens/totalTokens)
|
|
98
|
+
* - OpenAI/Mistral format (promptTokens/completionTokens)
|
|
99
|
+
* - Nested usage objects
|
|
100
|
+
*
|
|
101
|
+
* Also extracts optional fields:
|
|
102
|
+
* - Cache creation and read tokens (Anthropic-style)
|
|
103
|
+
* - Reasoning/thinking tokens (OpenAI o1, Anthropic, Google)
|
|
104
|
+
* - Cache savings percentage
|
|
105
|
+
*
|
|
106
|
+
* @param result Raw usage object from provider response
|
|
107
|
+
* @param options Extraction options
|
|
108
|
+
* @returns Normalized TokenUsage object
|
|
109
|
+
*/
|
|
110
|
+
export declare function extractTokenUsage(result: RawUsageObject | undefined | null, options?: TokenExtractionOptions): TokenUsage;
|
|
111
|
+
/**
|
|
112
|
+
* Create a default/empty TokenUsage object
|
|
113
|
+
* Useful for error handling and fallback scenarios
|
|
114
|
+
*/
|
|
115
|
+
export declare function createEmptyTokenUsage(): TokenUsage;
|
|
116
|
+
/**
|
|
117
|
+
* Check if a TokenUsage object has any non-zero values
|
|
118
|
+
*/
|
|
119
|
+
export declare function hasTokenUsage(usage: TokenUsage): boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Merge two TokenUsage objects by summing their values
|
|
122
|
+
* Useful for aggregating usage across multiple calls
|
|
123
|
+
*/
|
|
124
|
+
export declare function mergeTokenUsage(a: TokenUsage, b: TokenUsage): TokenUsage;
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized token usage extraction utilities
|
|
3
|
+
* Handles multiple provider formats and optional fields
|
|
4
|
+
*
|
|
5
|
+
* Consolidates token extraction logic from:
|
|
6
|
+
* - GenerationHandler.ts
|
|
7
|
+
* - analytics.ts
|
|
8
|
+
* - streamAnalytics.ts
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Extract input token count from various provider formats
|
|
12
|
+
* Priority: input > inputTokens > promptTokens
|
|
13
|
+
*/
|
|
14
|
+
export function extractInputTokens(usage) {
|
|
15
|
+
if (typeof usage.input === "number") {
|
|
16
|
+
return usage.input;
|
|
17
|
+
}
|
|
18
|
+
if (typeof usage.inputTokens === "number") {
|
|
19
|
+
return usage.inputTokens;
|
|
20
|
+
}
|
|
21
|
+
if (typeof usage.promptTokens === "number") {
|
|
22
|
+
return usage.promptTokens;
|
|
23
|
+
}
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Extract output token count from various provider formats
|
|
28
|
+
* Priority: output > outputTokens > completionTokens
|
|
29
|
+
*/
|
|
30
|
+
export function extractOutputTokens(usage) {
|
|
31
|
+
if (typeof usage.output === "number") {
|
|
32
|
+
return usage.output;
|
|
33
|
+
}
|
|
34
|
+
if (typeof usage.outputTokens === "number") {
|
|
35
|
+
return usage.outputTokens;
|
|
36
|
+
}
|
|
37
|
+
if (typeof usage.completionTokens === "number") {
|
|
38
|
+
return usage.completionTokens;
|
|
39
|
+
}
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Extract total token count from various provider formats
|
|
44
|
+
* Falls back to input + output if total is not provided
|
|
45
|
+
*/
|
|
46
|
+
export function extractTotalTokens(usage, input, output) {
|
|
47
|
+
if (typeof usage.total === "number") {
|
|
48
|
+
return usage.total;
|
|
49
|
+
}
|
|
50
|
+
if (typeof usage.totalTokens === "number") {
|
|
51
|
+
return usage.totalTokens;
|
|
52
|
+
}
|
|
53
|
+
return input + output;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Extract reasoning/thinking token count from various provider formats
|
|
57
|
+
* Supports: reasoningTokens, thinkingTokens, reasoning_tokens, reasoning
|
|
58
|
+
*/
|
|
59
|
+
export function extractReasoningTokens(usage) {
|
|
60
|
+
if (typeof usage.reasoningTokens === "number" && usage.reasoningTokens > 0) {
|
|
61
|
+
return usage.reasoningTokens;
|
|
62
|
+
}
|
|
63
|
+
if (typeof usage.thinkingTokens === "number" && usage.thinkingTokens > 0) {
|
|
64
|
+
return usage.thinkingTokens;
|
|
65
|
+
}
|
|
66
|
+
if (typeof usage.reasoning_tokens === "number" &&
|
|
67
|
+
usage.reasoning_tokens > 0) {
|
|
68
|
+
return usage.reasoning_tokens;
|
|
69
|
+
}
|
|
70
|
+
if (typeof usage.reasoning === "number" && usage.reasoning > 0) {
|
|
71
|
+
return usage.reasoning;
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Extract cache creation token count from various provider formats
|
|
77
|
+
* Supports: cacheCreationInputTokens, cacheCreationTokens
|
|
78
|
+
*/
|
|
79
|
+
export function extractCacheCreationTokens(usage) {
|
|
80
|
+
if (typeof usage.cacheCreationInputTokens === "number" &&
|
|
81
|
+
usage.cacheCreationInputTokens > 0) {
|
|
82
|
+
return usage.cacheCreationInputTokens;
|
|
83
|
+
}
|
|
84
|
+
if (typeof usage.cacheCreationTokens === "number" &&
|
|
85
|
+
usage.cacheCreationTokens > 0) {
|
|
86
|
+
return usage.cacheCreationTokens;
|
|
87
|
+
}
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Extract cache read token count from various provider formats
|
|
92
|
+
* Supports: cacheReadInputTokens, cacheReadTokens
|
|
93
|
+
*/
|
|
94
|
+
export function extractCacheReadTokens(usage) {
|
|
95
|
+
if (typeof usage.cacheReadInputTokens === "number" &&
|
|
96
|
+
usage.cacheReadInputTokens > 0) {
|
|
97
|
+
return usage.cacheReadInputTokens;
|
|
98
|
+
}
|
|
99
|
+
if (typeof usage.cacheReadTokens === "number" && usage.cacheReadTokens > 0) {
|
|
100
|
+
return usage.cacheReadTokens;
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Calculate cache savings percentage
|
|
106
|
+
*
|
|
107
|
+
* This represents the percentage of input tokens served from cache.
|
|
108
|
+
* For Anthropic, cache read tokens cost 0.1x, so actual cost savings = cacheSavingsPercent * 0.9
|
|
109
|
+
* For other providers, cost savings may vary based on their cache pricing.
|
|
110
|
+
*
|
|
111
|
+
* @param cacheReadTokens Number of tokens read from cache
|
|
112
|
+
* @param inputTokens Number of non-cached input tokens
|
|
113
|
+
* @returns Percentage of tokens served from cache (0-100), or undefined if no cache usage
|
|
114
|
+
*/
|
|
115
|
+
export function calculateCacheSavingsPercent(cacheReadTokens, inputTokens) {
|
|
116
|
+
if (cacheReadTokens === undefined || cacheReadTokens <= 0) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
const totalInputWithCache = inputTokens + cacheReadTokens;
|
|
120
|
+
if (totalInputWithCache <= 0) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
return Math.round((cacheReadTokens / totalInputWithCache) * 100);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Extract token usage from various provider response formats
|
|
127
|
+
*
|
|
128
|
+
* Handles multiple input formats:
|
|
129
|
+
* - BaseProvider normalized format (input/output/total)
|
|
130
|
+
* - AI SDK format (inputTokens/outputTokens/totalTokens)
|
|
131
|
+
* - OpenAI/Mistral format (promptTokens/completionTokens)
|
|
132
|
+
* - Nested usage objects
|
|
133
|
+
*
|
|
134
|
+
* Also extracts optional fields:
|
|
135
|
+
* - Cache creation and read tokens (Anthropic-style)
|
|
136
|
+
* - Reasoning/thinking tokens (OpenAI o1, Anthropic, Google)
|
|
137
|
+
* - Cache savings percentage
|
|
138
|
+
*
|
|
139
|
+
* @param result Raw usage object from provider response
|
|
140
|
+
* @param options Extraction options
|
|
141
|
+
* @returns Normalized TokenUsage object
|
|
142
|
+
*/
|
|
143
|
+
export function extractTokenUsage(result, options = {}) {
|
|
144
|
+
const { calculateCacheSavings = true, missingOptionalBehavior = "undefined", } = options;
|
|
145
|
+
// Handle null/undefined input
|
|
146
|
+
if (!result) {
|
|
147
|
+
return { input: 0, output: 0, total: 0 };
|
|
148
|
+
}
|
|
149
|
+
// Handle nested usage object (some providers wrap usage in a usage property)
|
|
150
|
+
const usage = result.usage && typeof result.usage === "object" ? result.usage : result;
|
|
151
|
+
// Extract base token counts
|
|
152
|
+
const input = extractInputTokens(usage);
|
|
153
|
+
const output = extractOutputTokens(usage);
|
|
154
|
+
const total = extractTotalTokens(usage, input, output);
|
|
155
|
+
// Extract optional token fields
|
|
156
|
+
const reasoning = extractReasoningTokens(usage);
|
|
157
|
+
const cacheCreationTokens = extractCacheCreationTokens(usage);
|
|
158
|
+
const cacheReadTokens = extractCacheReadTokens(usage);
|
|
159
|
+
// Calculate cache savings if enabled
|
|
160
|
+
const cacheSavingsPercent = calculateCacheSavings
|
|
161
|
+
? calculateCacheSavingsPercent(cacheReadTokens, input)
|
|
162
|
+
: undefined;
|
|
163
|
+
// Build result object
|
|
164
|
+
const tokenUsage = {
|
|
165
|
+
input,
|
|
166
|
+
output,
|
|
167
|
+
total,
|
|
168
|
+
};
|
|
169
|
+
// Add optional fields based on behavior setting
|
|
170
|
+
if (missingOptionalBehavior === "zero") {
|
|
171
|
+
tokenUsage.cacheCreationTokens = cacheCreationTokens ?? 0;
|
|
172
|
+
tokenUsage.cacheReadTokens = cacheReadTokens ?? 0;
|
|
173
|
+
tokenUsage.reasoning = reasoning ?? 0;
|
|
174
|
+
tokenUsage.cacheSavingsPercent = cacheSavingsPercent ?? 0;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
// Only include optional fields if they have values
|
|
178
|
+
if (cacheCreationTokens !== undefined) {
|
|
179
|
+
tokenUsage.cacheCreationTokens = cacheCreationTokens;
|
|
180
|
+
}
|
|
181
|
+
if (cacheReadTokens !== undefined) {
|
|
182
|
+
tokenUsage.cacheReadTokens = cacheReadTokens;
|
|
183
|
+
}
|
|
184
|
+
if (reasoning !== undefined) {
|
|
185
|
+
tokenUsage.reasoning = reasoning;
|
|
186
|
+
}
|
|
187
|
+
if (cacheSavingsPercent !== undefined) {
|
|
188
|
+
tokenUsage.cacheSavingsPercent = cacheSavingsPercent;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return tokenUsage;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Create a default/empty TokenUsage object
|
|
195
|
+
* Useful for error handling and fallback scenarios
|
|
196
|
+
*/
|
|
197
|
+
export function createEmptyTokenUsage() {
|
|
198
|
+
return {
|
|
199
|
+
input: 0,
|
|
200
|
+
output: 0,
|
|
201
|
+
total: 0,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Check if a TokenUsage object has any non-zero values
|
|
206
|
+
*/
|
|
207
|
+
export function hasTokenUsage(usage) {
|
|
208
|
+
return usage.input > 0 || usage.output > 0 || usage.total > 0;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Merge two TokenUsage objects by summing their values
|
|
212
|
+
* Useful for aggregating usage across multiple calls
|
|
213
|
+
*/
|
|
214
|
+
export function mergeTokenUsage(a, b) {
|
|
215
|
+
const merged = {
|
|
216
|
+
input: a.input + b.input,
|
|
217
|
+
output: a.output + b.output,
|
|
218
|
+
total: a.total + b.total,
|
|
219
|
+
};
|
|
220
|
+
// Merge optional fields if present in either
|
|
221
|
+
const cacheCreationTokens = (a.cacheCreationTokens ?? 0) + (b.cacheCreationTokens ?? 0);
|
|
222
|
+
const cacheReadTokens = (a.cacheReadTokens ?? 0) + (b.cacheReadTokens ?? 0);
|
|
223
|
+
const reasoning = (a.reasoning ?? 0) + (b.reasoning ?? 0);
|
|
224
|
+
if (cacheCreationTokens > 0) {
|
|
225
|
+
merged.cacheCreationTokens = cacheCreationTokens;
|
|
226
|
+
}
|
|
227
|
+
if (cacheReadTokens > 0) {
|
|
228
|
+
merged.cacheReadTokens = cacheReadTokens;
|
|
229
|
+
}
|
|
230
|
+
if (reasoning > 0) {
|
|
231
|
+
merged.reasoning = reasoning;
|
|
232
|
+
}
|
|
233
|
+
// Recalculate cache savings for merged usage
|
|
234
|
+
const cacheSavingsPercent = calculateCacheSavingsPercent(merged.cacheReadTokens, merged.input);
|
|
235
|
+
if (cacheSavingsPercent !== undefined) {
|
|
236
|
+
merged.cacheSavingsPercent = cacheSavingsPercent;
|
|
237
|
+
}
|
|
238
|
+
return merged;
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=tokenUtils.js.map
|