@shareai-lab/kode-sdk 1.0.0-beta.8 → 2.7.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/LICENSE +21 -0
- package/README.md +115 -273
- package/README.zh-CN.md +114 -0
- package/dist/core/agent/breakpoint-manager.d.ts +16 -0
- package/dist/core/agent/breakpoint-manager.js +36 -0
- package/dist/core/agent/message-queue.d.ts +26 -0
- package/dist/core/agent/message-queue.js +57 -0
- package/dist/core/agent/permission-manager.d.ts +9 -0
- package/dist/core/agent/permission-manager.js +32 -0
- package/dist/core/agent/todo-manager.d.ts +26 -0
- package/dist/core/agent/todo-manager.js +91 -0
- package/dist/core/agent/tool-runner.d.ts +9 -0
- package/dist/core/agent/tool-runner.js +45 -0
- package/dist/core/agent.d.ts +228 -62
- package/dist/core/agent.js +1890 -615
- package/dist/core/config.d.ts +10 -0
- package/dist/core/config.js +2 -0
- package/dist/core/context-manager.d.ts +82 -0
- package/dist/core/context-manager.js +241 -0
- package/dist/core/errors.d.ts +22 -0
- package/dist/core/errors.js +49 -0
- package/dist/core/events.d.ts +41 -10
- package/dist/core/events.js +270 -68
- package/dist/core/file-pool.d.ts +41 -0
- package/dist/core/file-pool.js +102 -0
- package/dist/core/hooks.d.ts +3 -3
- package/dist/core/hooks.js +1 -1
- package/dist/core/permission-modes.d.ts +31 -0
- package/dist/core/permission-modes.js +61 -0
- package/dist/core/pool.d.ts +56 -13
- package/dist/core/pool.js +244 -34
- package/dist/core/room.d.ts +2 -2
- package/dist/core/room.js +10 -10
- package/dist/core/scheduler.d.ts +30 -23
- package/dist/core/scheduler.js +42 -168
- package/dist/core/skills/index.d.ts +10 -0
- package/dist/core/skills/index.js +20 -0
- package/dist/core/skills/management-manager.d.ts +130 -0
- package/dist/core/skills/management-manager.js +557 -0
- package/dist/core/skills/manager.d.ts +47 -0
- package/dist/core/skills/manager.js +243 -0
- package/dist/core/skills/operation-queue.d.ts +87 -0
- package/dist/core/skills/operation-queue.js +113 -0
- package/dist/core/skills/sandbox-file-manager.d.ts +82 -0
- package/dist/core/skills/sandbox-file-manager.js +183 -0
- package/dist/core/skills/types.d.ts +120 -0
- package/dist/core/skills/types.js +9 -0
- package/dist/core/skills/xml-generator.d.ts +13 -0
- package/dist/core/skills/xml-generator.js +70 -0
- package/dist/core/template.d.ts +57 -0
- package/dist/core/template.js +35 -0
- package/dist/core/time-bridge.d.ts +18 -0
- package/dist/core/time-bridge.js +100 -0
- package/dist/core/todo.d.ts +34 -0
- package/dist/core/todo.js +89 -0
- package/dist/core/types.d.ts +311 -114
- package/dist/core/types.js +1 -12
- package/dist/index.d.ts +47 -9
- package/dist/index.js +108 -15
- package/dist/infra/db/postgres/postgres-store.d.ts +97 -0
- package/dist/infra/db/postgres/postgres-store.js +1073 -0
- package/dist/infra/db/sqlite/sqlite-store.d.ts +84 -0
- package/dist/infra/db/sqlite/sqlite-store.js +800 -0
- package/dist/infra/e2b/e2b-fs.d.ts +29 -0
- package/dist/infra/e2b/e2b-fs.js +128 -0
- package/dist/infra/e2b/e2b-sandbox.d.ts +37 -0
- package/dist/infra/e2b/e2b-sandbox.js +156 -0
- package/dist/infra/e2b/e2b-template.d.ts +24 -0
- package/dist/infra/e2b/e2b-template.js +105 -0
- package/dist/infra/e2b/index.d.ts +4 -0
- package/dist/infra/e2b/index.js +9 -0
- package/dist/infra/e2b/types.d.ts +46 -0
- package/dist/infra/e2b/types.js +2 -0
- package/dist/infra/provider.d.ts +17 -58
- package/dist/infra/provider.js +65 -116
- package/dist/infra/providers/anthropic.d.ts +42 -0
- package/dist/infra/providers/anthropic.js +308 -0
- package/dist/infra/providers/core/errors.d.ts +230 -0
- package/dist/infra/providers/core/errors.js +353 -0
- package/dist/infra/providers/core/fork.d.ts +106 -0
- package/dist/infra/providers/core/fork.js +418 -0
- package/dist/infra/providers/core/index.d.ts +10 -0
- package/dist/infra/providers/core/index.js +76 -0
- package/dist/infra/providers/core/logger.d.ts +186 -0
- package/dist/infra/providers/core/logger.js +191 -0
- package/dist/infra/providers/core/retry.d.ts +62 -0
- package/dist/infra/providers/core/retry.js +189 -0
- package/dist/infra/providers/core/usage.d.ts +151 -0
- package/dist/infra/providers/core/usage.js +376 -0
- package/dist/infra/providers/gemini.d.ts +49 -0
- package/dist/infra/providers/gemini.js +493 -0
- package/dist/infra/providers/index.d.ts +25 -0
- package/dist/infra/providers/index.js +83 -0
- package/dist/infra/providers/openai.d.ts +123 -0
- package/dist/infra/providers/openai.js +662 -0
- package/dist/infra/providers/types.d.ts +334 -0
- package/dist/infra/providers/types.js +20 -0
- package/dist/infra/providers/utils.d.ts +53 -0
- package/dist/infra/providers/utils.js +400 -0
- package/dist/infra/sandbox-factory.d.ts +13 -0
- package/dist/infra/sandbox-factory.js +30 -0
- package/dist/infra/sandbox.d.ts +35 -6
- package/dist/infra/sandbox.js +174 -8
- package/dist/infra/store/factory.d.ts +45 -0
- package/dist/infra/store/factory.js +80 -0
- package/dist/infra/store/index.d.ts +3 -0
- package/dist/infra/store/index.js +26 -0
- package/dist/infra/store/json-store.d.ts +67 -0
- package/dist/infra/store/json-store.js +606 -0
- package/dist/infra/store/types.d.ts +342 -0
- package/dist/infra/store/types.js +2 -0
- package/dist/infra/store.d.ts +12 -32
- package/dist/infra/store.js +27 -130
- package/dist/tools/bash_kill/index.d.ts +1 -0
- package/dist/tools/bash_kill/index.js +35 -0
- package/dist/tools/bash_kill/prompt.d.ts +2 -0
- package/dist/tools/bash_kill/prompt.js +14 -0
- package/dist/tools/bash_logs/index.d.ts +1 -0
- package/dist/tools/bash_logs/index.js +40 -0
- package/dist/tools/bash_logs/prompt.d.ts +2 -0
- package/dist/tools/bash_logs/prompt.js +14 -0
- package/dist/tools/bash_run/index.d.ts +16 -0
- package/dist/tools/bash_run/index.js +61 -0
- package/dist/tools/bash_run/prompt.d.ts +2 -0
- package/dist/tools/bash_run/prompt.js +18 -0
- package/dist/tools/builtin.d.ts +7 -13
- package/dist/tools/builtin.js +19 -90
- package/dist/tools/define.d.ts +101 -0
- package/dist/tools/define.js +214 -0
- package/dist/tools/fs_edit/index.d.ts +1 -0
- package/dist/tools/fs_edit/index.js +62 -0
- package/dist/tools/fs_edit/prompt.d.ts +2 -0
- package/dist/tools/fs_edit/prompt.js +15 -0
- package/dist/tools/fs_glob/index.d.ts +1 -0
- package/dist/tools/fs_glob/index.js +40 -0
- package/dist/tools/fs_glob/prompt.d.ts +2 -0
- package/dist/tools/fs_glob/prompt.js +15 -0
- package/dist/tools/fs_grep/index.d.ts +1 -0
- package/dist/tools/fs_grep/index.js +66 -0
- package/dist/tools/fs_grep/prompt.d.ts +2 -0
- package/dist/tools/fs_grep/prompt.js +16 -0
- package/dist/tools/fs_multi_edit/index.d.ts +1 -0
- package/dist/tools/fs_multi_edit/index.js +106 -0
- package/dist/tools/fs_multi_edit/prompt.d.ts +2 -0
- package/dist/tools/fs_multi_edit/prompt.js +16 -0
- package/dist/tools/fs_read/index.d.ts +1 -0
- package/dist/tools/fs_read/index.js +40 -0
- package/dist/tools/fs_read/prompt.d.ts +2 -0
- package/dist/tools/fs_read/prompt.js +16 -0
- package/dist/tools/fs_write/index.d.ts +1 -0
- package/dist/tools/fs_write/index.js +40 -0
- package/dist/tools/fs_write/prompt.d.ts +2 -0
- package/dist/tools/fs_write/prompt.js +15 -0
- package/dist/tools/index.d.ts +11 -0
- package/dist/tools/index.js +61 -0
- package/dist/tools/mcp.d.ts +69 -0
- package/dist/tools/mcp.js +185 -0
- package/dist/tools/registry.d.ts +29 -0
- package/dist/tools/registry.js +26 -0
- package/dist/tools/scripts.d.ts +22 -0
- package/dist/tools/scripts.js +205 -0
- package/dist/tools/skills.d.ts +20 -0
- package/dist/tools/skills.js +115 -0
- package/dist/tools/task_run/index.d.ts +7 -0
- package/dist/tools/task_run/index.js +58 -0
- package/dist/tools/task_run/prompt.d.ts +5 -0
- package/dist/tools/task_run/prompt.js +25 -0
- package/dist/tools/todo_read/index.d.ts +1 -0
- package/dist/tools/todo_read/index.js +29 -0
- package/dist/tools/todo_read/prompt.d.ts +2 -0
- package/dist/tools/todo_read/prompt.js +18 -0
- package/dist/tools/todo_write/index.d.ts +1 -0
- package/dist/tools/todo_write/index.js +42 -0
- package/dist/tools/todo_write/prompt.d.ts +2 -0
- package/dist/tools/todo_write/prompt.js +23 -0
- package/dist/tools/tool.d.ts +43 -0
- package/dist/tools/tool.js +211 -0
- package/dist/tools/toolkit.d.ts +69 -0
- package/dist/tools/toolkit.js +98 -0
- package/dist/tools/type-inference.d.ts +127 -0
- package/dist/tools/type-inference.js +207 -0
- package/dist/utils/agent-id.d.ts +1 -0
- package/dist/utils/agent-id.js +28 -0
- package/dist/utils/logger.d.ts +15 -0
- package/dist/utils/logger.js +44 -0
- package/dist/utils/session-id.js +16 -16
- package/package.json +35 -11
- package/dist/tools/bash.d.ts +0 -63
- package/dist/tools/bash.js +0 -92
- package/dist/tools/fs.d.ts +0 -96
- package/dist/tools/fs.js +0 -100
- package/dist/tools/task.d.ts +0 -38
- package/dist/tools/task.js +0 -45
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage Statistics Module
|
|
3
|
+
*
|
|
4
|
+
* Unified usage tracking, cache metrics, and cost calculation
|
|
5
|
+
* across all supported model providers.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Unified usage statistics for all providers.
|
|
9
|
+
* Normalized from provider-specific usage formats.
|
|
10
|
+
*/
|
|
11
|
+
export interface UsageStatistics {
|
|
12
|
+
inputTokens: number;
|
|
13
|
+
outputTokens: number;
|
|
14
|
+
totalTokens: number;
|
|
15
|
+
reasoningTokens?: number;
|
|
16
|
+
cache: CacheMetrics;
|
|
17
|
+
cost: CostBreakdown;
|
|
18
|
+
request: RequestMetrics;
|
|
19
|
+
raw?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Cache performance metrics.
|
|
23
|
+
*/
|
|
24
|
+
export interface CacheMetrics {
|
|
25
|
+
cacheCreationTokens: number;
|
|
26
|
+
cacheReadTokens: number;
|
|
27
|
+
cacheSavingsEstimate?: number;
|
|
28
|
+
provider: {
|
|
29
|
+
anthropic?: {
|
|
30
|
+
breakpointsUsed: number;
|
|
31
|
+
ttlUsed: '5m' | '1h';
|
|
32
|
+
};
|
|
33
|
+
gemini?: {
|
|
34
|
+
cachedContentName?: string;
|
|
35
|
+
implicitCacheHit: boolean;
|
|
36
|
+
};
|
|
37
|
+
openai?: {
|
|
38
|
+
automaticCacheHit: boolean;
|
|
39
|
+
};
|
|
40
|
+
deepseek?: {
|
|
41
|
+
prefixCacheHit: boolean;
|
|
42
|
+
};
|
|
43
|
+
qwen?: {
|
|
44
|
+
cacheHit: boolean;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Cost breakdown in USD.
|
|
50
|
+
*/
|
|
51
|
+
export interface CostBreakdown {
|
|
52
|
+
inputCost: number;
|
|
53
|
+
outputCost: number;
|
|
54
|
+
cacheWriteCost: number;
|
|
55
|
+
totalCost: number;
|
|
56
|
+
cacheSavings: number;
|
|
57
|
+
currency: 'USD';
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Request performance metrics.
|
|
61
|
+
*/
|
|
62
|
+
export interface RequestMetrics {
|
|
63
|
+
startTime: number;
|
|
64
|
+
endTime: number;
|
|
65
|
+
latencyMs: number;
|
|
66
|
+
timeToFirstTokenMs?: number;
|
|
67
|
+
tokensPerSecond?: number;
|
|
68
|
+
requestId?: string;
|
|
69
|
+
modelUsed: string;
|
|
70
|
+
stopReason?: string;
|
|
71
|
+
retryCount?: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Model pricing information (per 1M tokens in USD).
|
|
75
|
+
*/
|
|
76
|
+
export interface ModelPricing {
|
|
77
|
+
input: number;
|
|
78
|
+
output: number;
|
|
79
|
+
cacheWrite?: number;
|
|
80
|
+
cacheRead?: number;
|
|
81
|
+
reasoning?: number;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Provider pricing table (per 1M tokens).
|
|
85
|
+
*/
|
|
86
|
+
export declare const PROVIDER_PRICING: Record<string, Record<string, ModelPricing>>;
|
|
87
|
+
/**
|
|
88
|
+
* Create empty usage statistics.
|
|
89
|
+
*/
|
|
90
|
+
export declare function createEmptyUsage(): UsageStatistics;
|
|
91
|
+
/**
|
|
92
|
+
* Calculate cost based on usage and pricing.
|
|
93
|
+
*/
|
|
94
|
+
export declare function calculateCost(usage: {
|
|
95
|
+
inputTokens: number;
|
|
96
|
+
outputTokens: number;
|
|
97
|
+
cacheCreationTokens?: number;
|
|
98
|
+
cacheReadTokens?: number;
|
|
99
|
+
reasoningTokens?: number;
|
|
100
|
+
}, pricing: ModelPricing, cacheTtl?: '5m' | '1h'): CostBreakdown;
|
|
101
|
+
/**
|
|
102
|
+
* Normalize Anthropic usage to unified format.
|
|
103
|
+
*/
|
|
104
|
+
export declare function normalizeAnthropicUsage(raw: {
|
|
105
|
+
input_tokens?: number;
|
|
106
|
+
output_tokens?: number;
|
|
107
|
+
cache_creation_input_tokens?: number;
|
|
108
|
+
cache_read_input_tokens?: number;
|
|
109
|
+
}, model: string, startTime: number, requestId?: string, cacheTtl?: '5m' | '1h'): UsageStatistics;
|
|
110
|
+
/**
|
|
111
|
+
* Normalize OpenAI usage to unified format.
|
|
112
|
+
*/
|
|
113
|
+
export declare function normalizeOpenAIUsage(raw: {
|
|
114
|
+
prompt_tokens?: number;
|
|
115
|
+
completion_tokens?: number;
|
|
116
|
+
total_tokens?: number;
|
|
117
|
+
prompt_tokens_details?: {
|
|
118
|
+
cached_tokens?: number;
|
|
119
|
+
};
|
|
120
|
+
completion_tokens_details?: {
|
|
121
|
+
reasoning_tokens?: number;
|
|
122
|
+
};
|
|
123
|
+
}, model: string, api: 'chat' | 'responses', startTime: number, requestId?: string): UsageStatistics;
|
|
124
|
+
/**
|
|
125
|
+
* Normalize Gemini usage to unified format.
|
|
126
|
+
*/
|
|
127
|
+
export declare function normalizeGeminiUsage(raw: {
|
|
128
|
+
promptTokenCount?: number;
|
|
129
|
+
candidatesTokenCount?: number;
|
|
130
|
+
totalTokenCount?: number;
|
|
131
|
+
cachedContentTokenCount?: number;
|
|
132
|
+
thoughtsTokenCount?: number;
|
|
133
|
+
}, model: string, startTime: number, cachedContentName?: string): UsageStatistics;
|
|
134
|
+
/**
|
|
135
|
+
* Normalize DeepSeek usage to unified format.
|
|
136
|
+
*/
|
|
137
|
+
export declare function normalizeDeepSeekUsage(raw: {
|
|
138
|
+
prompt_tokens?: number;
|
|
139
|
+
completion_tokens?: number;
|
|
140
|
+
total_tokens?: number;
|
|
141
|
+
prompt_cache_hit_tokens?: number;
|
|
142
|
+
prompt_cache_miss_tokens?: number;
|
|
143
|
+
}, model: string, startTime: number, requestId?: string): UsageStatistics;
|
|
144
|
+
/**
|
|
145
|
+
* Aggregate multiple usage statistics.
|
|
146
|
+
*/
|
|
147
|
+
export declare function aggregateUsage(usages: UsageStatistics[]): UsageStatistics;
|
|
148
|
+
/**
|
|
149
|
+
* Format usage as human-readable string.
|
|
150
|
+
*/
|
|
151
|
+
export declare function formatUsageString(usage: UsageStatistics): string;
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Usage Statistics Module
|
|
4
|
+
*
|
|
5
|
+
* Unified usage tracking, cache metrics, and cost calculation
|
|
6
|
+
* across all supported model providers.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.PROVIDER_PRICING = void 0;
|
|
10
|
+
exports.createEmptyUsage = createEmptyUsage;
|
|
11
|
+
exports.calculateCost = calculateCost;
|
|
12
|
+
exports.normalizeAnthropicUsage = normalizeAnthropicUsage;
|
|
13
|
+
exports.normalizeOpenAIUsage = normalizeOpenAIUsage;
|
|
14
|
+
exports.normalizeGeminiUsage = normalizeGeminiUsage;
|
|
15
|
+
exports.normalizeDeepSeekUsage = normalizeDeepSeekUsage;
|
|
16
|
+
exports.aggregateUsage = aggregateUsage;
|
|
17
|
+
exports.formatUsageString = formatUsageString;
|
|
18
|
+
/**
|
|
19
|
+
* Provider pricing table (per 1M tokens).
|
|
20
|
+
*/
|
|
21
|
+
exports.PROVIDER_PRICING = {
|
|
22
|
+
anthropic: {
|
|
23
|
+
'claude-opus-4-5': {
|
|
24
|
+
input: 5.0,
|
|
25
|
+
output: 25.0,
|
|
26
|
+
cacheWrite: 6.25, // 5m TTL: 1.25x input
|
|
27
|
+
cacheRead: 0.5, // 10% of input
|
|
28
|
+
},
|
|
29
|
+
'claude-opus-4-5-1h': {
|
|
30
|
+
input: 5.0,
|
|
31
|
+
output: 25.0,
|
|
32
|
+
cacheWrite: 10.0, // 1h TTL: 2x input
|
|
33
|
+
cacheRead: 0.5,
|
|
34
|
+
},
|
|
35
|
+
'claude-sonnet-4-5': {
|
|
36
|
+
input: 3.0,
|
|
37
|
+
output: 15.0,
|
|
38
|
+
cacheWrite: 3.75,
|
|
39
|
+
cacheRead: 0.3,
|
|
40
|
+
},
|
|
41
|
+
'claude-haiku-4-5': {
|
|
42
|
+
input: 1.0,
|
|
43
|
+
output: 5.0,
|
|
44
|
+
cacheWrite: 1.25,
|
|
45
|
+
cacheRead: 0.1,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
openai: {
|
|
49
|
+
'gpt-5.2': {
|
|
50
|
+
input: 5.0,
|
|
51
|
+
output: 15.0,
|
|
52
|
+
cacheRead: 1.25, // 75% discount
|
|
53
|
+
},
|
|
54
|
+
'gpt-4.1': {
|
|
55
|
+
input: 2.0,
|
|
56
|
+
output: 8.0,
|
|
57
|
+
cacheRead: 0.5,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
gemini: {
|
|
61
|
+
'gemini-3-pro': {
|
|
62
|
+
input: 2.5,
|
|
63
|
+
output: 10.0,
|
|
64
|
+
cacheRead: 0.625, // 75% discount
|
|
65
|
+
},
|
|
66
|
+
'gemini-3-flash': {
|
|
67
|
+
input: 0.075,
|
|
68
|
+
output: 0.3,
|
|
69
|
+
cacheRead: 0.01875,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
deepseek: {
|
|
73
|
+
'deepseek-reasoner': {
|
|
74
|
+
input: 0.28,
|
|
75
|
+
output: 1.10,
|
|
76
|
+
cacheRead: 0.028, // 90% discount
|
|
77
|
+
},
|
|
78
|
+
'deepseek-chat': {
|
|
79
|
+
input: 0.14,
|
|
80
|
+
output: 0.28,
|
|
81
|
+
cacheRead: 0.014,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
qwen: {
|
|
85
|
+
'qwen3-max': {
|
|
86
|
+
input: 0.80,
|
|
87
|
+
output: 2.00,
|
|
88
|
+
},
|
|
89
|
+
'qwen3-plus': {
|
|
90
|
+
input: 0.50,
|
|
91
|
+
output: 1.50,
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Create empty usage statistics.
|
|
97
|
+
*/
|
|
98
|
+
function createEmptyUsage() {
|
|
99
|
+
return {
|
|
100
|
+
inputTokens: 0,
|
|
101
|
+
outputTokens: 0,
|
|
102
|
+
totalTokens: 0,
|
|
103
|
+
cache: {
|
|
104
|
+
cacheCreationTokens: 0,
|
|
105
|
+
cacheReadTokens: 0,
|
|
106
|
+
provider: {},
|
|
107
|
+
},
|
|
108
|
+
cost: {
|
|
109
|
+
inputCost: 0,
|
|
110
|
+
outputCost: 0,
|
|
111
|
+
cacheWriteCost: 0,
|
|
112
|
+
totalCost: 0,
|
|
113
|
+
cacheSavings: 0,
|
|
114
|
+
currency: 'USD',
|
|
115
|
+
},
|
|
116
|
+
request: {
|
|
117
|
+
startTime: 0,
|
|
118
|
+
endTime: 0,
|
|
119
|
+
latencyMs: 0,
|
|
120
|
+
modelUsed: '',
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Calculate cost based on usage and pricing.
|
|
126
|
+
*/
|
|
127
|
+
function calculateCost(usage, pricing, cacheTtl) {
|
|
128
|
+
const perMillionFactor = 1000000;
|
|
129
|
+
// Calculate raw input cost (before cache)
|
|
130
|
+
const rawInputCost = (usage.inputTokens / perMillionFactor) * pricing.input;
|
|
131
|
+
// Calculate cache costs
|
|
132
|
+
const cacheReadCost = pricing.cacheRead
|
|
133
|
+
? ((usage.cacheReadTokens || 0) / perMillionFactor) * pricing.cacheRead
|
|
134
|
+
: 0;
|
|
135
|
+
let cacheWriteCost = 0;
|
|
136
|
+
if (usage.cacheCreationTokens && pricing.cacheWrite) {
|
|
137
|
+
const multiplier = cacheTtl === '1h' ? 2.0 : 1.25;
|
|
138
|
+
cacheWriteCost = ((usage.cacheCreationTokens) / perMillionFactor) * pricing.input * multiplier;
|
|
139
|
+
}
|
|
140
|
+
// Actual input cost = raw - cached tokens + cache read cost
|
|
141
|
+
const cachedInputTokens = usage.cacheReadTokens || 0;
|
|
142
|
+
const nonCachedInputTokens = Math.max(0, usage.inputTokens - cachedInputTokens);
|
|
143
|
+
const inputCost = (nonCachedInputTokens / perMillionFactor) * pricing.input + cacheReadCost;
|
|
144
|
+
// Output cost
|
|
145
|
+
const outputCost = (usage.outputTokens / perMillionFactor) * pricing.output;
|
|
146
|
+
// Reasoning cost (if separate pricing)
|
|
147
|
+
const reasoningCost = pricing.reasoning && usage.reasoningTokens
|
|
148
|
+
? (usage.reasoningTokens / perMillionFactor) * pricing.reasoning
|
|
149
|
+
: 0;
|
|
150
|
+
// Total cost
|
|
151
|
+
const totalCost = inputCost + outputCost + cacheWriteCost + reasoningCost;
|
|
152
|
+
// Cache savings = what we would have paid - what we actually paid
|
|
153
|
+
const cacheSavings = cachedInputTokens > 0
|
|
154
|
+
? (cachedInputTokens / perMillionFactor) * pricing.input - cacheReadCost
|
|
155
|
+
: 0;
|
|
156
|
+
return {
|
|
157
|
+
inputCost: Math.round(inputCost * 100000) / 100000, // 5 decimal precision
|
|
158
|
+
outputCost: Math.round((outputCost + reasoningCost) * 100000) / 100000,
|
|
159
|
+
cacheWriteCost: Math.round(cacheWriteCost * 100000) / 100000,
|
|
160
|
+
totalCost: Math.round(totalCost * 100000) / 100000,
|
|
161
|
+
cacheSavings: Math.round(cacheSavings * 100000) / 100000,
|
|
162
|
+
currency: 'USD',
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Normalize Anthropic usage to unified format.
|
|
167
|
+
*/
|
|
168
|
+
function normalizeAnthropicUsage(raw, model, startTime, requestId, cacheTtl) {
|
|
169
|
+
const inputTokens = raw.input_tokens || 0;
|
|
170
|
+
const outputTokens = raw.output_tokens || 0;
|
|
171
|
+
const cacheCreationTokens = raw.cache_creation_input_tokens || 0;
|
|
172
|
+
const cacheReadTokens = raw.cache_read_input_tokens || 0;
|
|
173
|
+
// Determine model key for pricing
|
|
174
|
+
const modelKey = model.includes('opus') ? 'claude-opus-4-5'
|
|
175
|
+
: model.includes('sonnet') ? 'claude-sonnet-4-5'
|
|
176
|
+
: 'claude-haiku-4-5';
|
|
177
|
+
const pricing = cacheTtl === '1h'
|
|
178
|
+
? exports.PROVIDER_PRICING.anthropic[`${modelKey}-1h`] || exports.PROVIDER_PRICING.anthropic[modelKey]
|
|
179
|
+
: exports.PROVIDER_PRICING.anthropic[modelKey];
|
|
180
|
+
const cost = pricing
|
|
181
|
+
? calculateCost({ inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens }, pricing, cacheTtl)
|
|
182
|
+
: createEmptyUsage().cost;
|
|
183
|
+
const endTime = Date.now();
|
|
184
|
+
return {
|
|
185
|
+
inputTokens,
|
|
186
|
+
outputTokens,
|
|
187
|
+
totalTokens: inputTokens + outputTokens + cacheCreationTokens + cacheReadTokens,
|
|
188
|
+
cache: {
|
|
189
|
+
cacheCreationTokens,
|
|
190
|
+
cacheReadTokens,
|
|
191
|
+
cacheSavingsEstimate: cost.cacheSavings,
|
|
192
|
+
provider: {
|
|
193
|
+
anthropic: {
|
|
194
|
+
breakpointsUsed: 0, // Inferred from request
|
|
195
|
+
ttlUsed: cacheTtl || '5m',
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
cost,
|
|
200
|
+
request: {
|
|
201
|
+
startTime,
|
|
202
|
+
endTime,
|
|
203
|
+
latencyMs: endTime - startTime,
|
|
204
|
+
requestId,
|
|
205
|
+
modelUsed: model,
|
|
206
|
+
},
|
|
207
|
+
raw,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Normalize OpenAI usage to unified format.
|
|
212
|
+
*/
|
|
213
|
+
function normalizeOpenAIUsage(raw, model, api, startTime, requestId) {
|
|
214
|
+
const inputTokens = raw.prompt_tokens || 0;
|
|
215
|
+
const outputTokens = raw.completion_tokens || 0;
|
|
216
|
+
const cacheReadTokens = raw.prompt_tokens_details?.cached_tokens || 0;
|
|
217
|
+
const reasoningTokens = raw.completion_tokens_details?.reasoning_tokens || 0;
|
|
218
|
+
const modelKey = model.includes('gpt-5') ? 'gpt-5.2' : 'gpt-4.1';
|
|
219
|
+
const pricing = exports.PROVIDER_PRICING.openai[modelKey];
|
|
220
|
+
const cost = pricing
|
|
221
|
+
? calculateCost({ inputTokens, outputTokens, cacheReadTokens }, pricing)
|
|
222
|
+
: createEmptyUsage().cost;
|
|
223
|
+
const endTime = Date.now();
|
|
224
|
+
return {
|
|
225
|
+
inputTokens,
|
|
226
|
+
outputTokens,
|
|
227
|
+
totalTokens: raw.total_tokens || (inputTokens + outputTokens),
|
|
228
|
+
reasoningTokens: reasoningTokens || undefined,
|
|
229
|
+
cache: {
|
|
230
|
+
cacheCreationTokens: 0,
|
|
231
|
+
cacheReadTokens,
|
|
232
|
+
cacheSavingsEstimate: cost.cacheSavings,
|
|
233
|
+
provider: {
|
|
234
|
+
openai: {
|
|
235
|
+
automaticCacheHit: cacheReadTokens > 0,
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
cost,
|
|
240
|
+
request: {
|
|
241
|
+
startTime,
|
|
242
|
+
endTime,
|
|
243
|
+
latencyMs: endTime - startTime,
|
|
244
|
+
requestId,
|
|
245
|
+
modelUsed: model,
|
|
246
|
+
},
|
|
247
|
+
raw,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Normalize Gemini usage to unified format.
|
|
252
|
+
*/
|
|
253
|
+
function normalizeGeminiUsage(raw, model, startTime, cachedContentName) {
|
|
254
|
+
const inputTokens = raw.promptTokenCount || 0;
|
|
255
|
+
const outputTokens = raw.candidatesTokenCount || 0;
|
|
256
|
+
const cacheReadTokens = raw.cachedContentTokenCount || 0;
|
|
257
|
+
const reasoningTokens = raw.thoughtsTokenCount || 0;
|
|
258
|
+
const modelKey = model.includes('pro') ? 'gemini-3-pro' : 'gemini-3-flash';
|
|
259
|
+
const pricing = exports.PROVIDER_PRICING.gemini[modelKey];
|
|
260
|
+
const cost = pricing
|
|
261
|
+
? calculateCost({ inputTokens, outputTokens, cacheReadTokens }, pricing)
|
|
262
|
+
: createEmptyUsage().cost;
|
|
263
|
+
const endTime = Date.now();
|
|
264
|
+
return {
|
|
265
|
+
inputTokens,
|
|
266
|
+
outputTokens,
|
|
267
|
+
totalTokens: raw.totalTokenCount || (inputTokens + outputTokens),
|
|
268
|
+
reasoningTokens: reasoningTokens || undefined,
|
|
269
|
+
cache: {
|
|
270
|
+
cacheCreationTokens: 0,
|
|
271
|
+
cacheReadTokens,
|
|
272
|
+
cacheSavingsEstimate: cost.cacheSavings,
|
|
273
|
+
provider: {
|
|
274
|
+
gemini: {
|
|
275
|
+
cachedContentName,
|
|
276
|
+
implicitCacheHit: cacheReadTokens > 0 && !cachedContentName,
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
cost,
|
|
281
|
+
request: {
|
|
282
|
+
startTime,
|
|
283
|
+
endTime,
|
|
284
|
+
latencyMs: endTime - startTime,
|
|
285
|
+
modelUsed: model,
|
|
286
|
+
},
|
|
287
|
+
raw,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Normalize DeepSeek usage to unified format.
|
|
292
|
+
*/
|
|
293
|
+
function normalizeDeepSeekUsage(raw, model, startTime, requestId) {
|
|
294
|
+
const inputTokens = raw.prompt_tokens || 0;
|
|
295
|
+
const outputTokens = raw.completion_tokens || 0;
|
|
296
|
+
const cacheReadTokens = raw.prompt_cache_hit_tokens || 0;
|
|
297
|
+
const modelKey = model.includes('reasoner') ? 'deepseek-reasoner' : 'deepseek-chat';
|
|
298
|
+
const pricing = exports.PROVIDER_PRICING.deepseek[modelKey];
|
|
299
|
+
const cost = pricing
|
|
300
|
+
? calculateCost({ inputTokens, outputTokens, cacheReadTokens }, pricing)
|
|
301
|
+
: createEmptyUsage().cost;
|
|
302
|
+
const endTime = Date.now();
|
|
303
|
+
return {
|
|
304
|
+
inputTokens,
|
|
305
|
+
outputTokens,
|
|
306
|
+
totalTokens: raw.total_tokens || (inputTokens + outputTokens),
|
|
307
|
+
cache: {
|
|
308
|
+
cacheCreationTokens: 0,
|
|
309
|
+
cacheReadTokens,
|
|
310
|
+
cacheSavingsEstimate: cost.cacheSavings,
|
|
311
|
+
provider: {
|
|
312
|
+
deepseek: {
|
|
313
|
+
prefixCacheHit: cacheReadTokens > 0,
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
cost,
|
|
318
|
+
request: {
|
|
319
|
+
startTime,
|
|
320
|
+
endTime,
|
|
321
|
+
latencyMs: endTime - startTime,
|
|
322
|
+
requestId,
|
|
323
|
+
modelUsed: model,
|
|
324
|
+
},
|
|
325
|
+
raw,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Aggregate multiple usage statistics.
|
|
330
|
+
*/
|
|
331
|
+
function aggregateUsage(usages) {
|
|
332
|
+
const aggregated = createEmptyUsage();
|
|
333
|
+
for (const usage of usages) {
|
|
334
|
+
aggregated.inputTokens += usage.inputTokens;
|
|
335
|
+
aggregated.outputTokens += usage.outputTokens;
|
|
336
|
+
aggregated.totalTokens += usage.totalTokens;
|
|
337
|
+
aggregated.reasoningTokens = (aggregated.reasoningTokens || 0) + (usage.reasoningTokens || 0);
|
|
338
|
+
aggregated.cache.cacheCreationTokens += usage.cache.cacheCreationTokens;
|
|
339
|
+
aggregated.cache.cacheReadTokens += usage.cache.cacheReadTokens;
|
|
340
|
+
aggregated.cache.cacheSavingsEstimate = (aggregated.cache.cacheSavingsEstimate || 0) +
|
|
341
|
+
(usage.cache.cacheSavingsEstimate || 0);
|
|
342
|
+
aggregated.cost.inputCost += usage.cost.inputCost;
|
|
343
|
+
aggregated.cost.outputCost += usage.cost.outputCost;
|
|
344
|
+
aggregated.cost.cacheWriteCost += usage.cost.cacheWriteCost;
|
|
345
|
+
aggregated.cost.totalCost += usage.cost.totalCost;
|
|
346
|
+
aggregated.cost.cacheSavings += usage.cost.cacheSavings;
|
|
347
|
+
}
|
|
348
|
+
// Average latency
|
|
349
|
+
if (usages.length > 0) {
|
|
350
|
+
aggregated.request.latencyMs = usages.reduce((sum, u) => sum + u.request.latencyMs, 0) / usages.length;
|
|
351
|
+
}
|
|
352
|
+
return aggregated;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Format usage as human-readable string.
|
|
356
|
+
*/
|
|
357
|
+
function formatUsageString(usage) {
|
|
358
|
+
const parts = [];
|
|
359
|
+
parts.push(`Tokens: ${usage.inputTokens} in / ${usage.outputTokens} out`);
|
|
360
|
+
if (usage.reasoningTokens) {
|
|
361
|
+
parts.push(`(${usage.reasoningTokens} reasoning)`);
|
|
362
|
+
}
|
|
363
|
+
if (usage.cache.cacheReadTokens > 0) {
|
|
364
|
+
parts.push(`Cache hit: ${usage.cache.cacheReadTokens} tokens`);
|
|
365
|
+
}
|
|
366
|
+
if (usage.cost.totalCost > 0) {
|
|
367
|
+
parts.push(`Cost: $${usage.cost.totalCost.toFixed(5)}`);
|
|
368
|
+
}
|
|
369
|
+
if (usage.cost.cacheSavings > 0) {
|
|
370
|
+
parts.push(`(saved: $${usage.cost.cacheSavings.toFixed(5)})`);
|
|
371
|
+
}
|
|
372
|
+
if (usage.request.latencyMs > 0) {
|
|
373
|
+
parts.push(`Latency: ${usage.request.latencyMs}ms`);
|
|
374
|
+
}
|
|
375
|
+
return parts.join(' | ');
|
|
376
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gemini Provider Adapter
|
|
3
|
+
*
|
|
4
|
+
* Converts internal Anthropic-style messages to Gemini API format.
|
|
5
|
+
* Supports:
|
|
6
|
+
* - Thinking with thinkingBudget (2.5 models) or thinkingLevel (3.x models)
|
|
7
|
+
* - Files API with GCS URIs
|
|
8
|
+
* - Streaming with SSE
|
|
9
|
+
* - Function calling
|
|
10
|
+
*/
|
|
11
|
+
import { Message } from '../../core/types';
|
|
12
|
+
import { ModelProvider, ModelResponse, ModelStreamChunk, ModelConfig, UploadFileInput, UploadFileResult, CompletionOptions, ReasoningTransport, ThinkingOptions } from './types';
|
|
13
|
+
export interface GeminiProviderOptions {
|
|
14
|
+
reasoningTransport?: ReasoningTransport;
|
|
15
|
+
extraHeaders?: Record<string, string>;
|
|
16
|
+
extraBody?: Record<string, any>;
|
|
17
|
+
providerOptions?: Record<string, any>;
|
|
18
|
+
multimodal?: ModelConfig['multimodal'];
|
|
19
|
+
thinking?: ThinkingOptions;
|
|
20
|
+
}
|
|
21
|
+
export declare class GeminiProvider implements ModelProvider {
|
|
22
|
+
private apiKey;
|
|
23
|
+
readonly maxWindowSize = 1000000;
|
|
24
|
+
readonly maxOutputTokens = 4096;
|
|
25
|
+
readonly temperature = 0.7;
|
|
26
|
+
readonly model: string;
|
|
27
|
+
private readonly baseUrl;
|
|
28
|
+
private readonly dispatcher?;
|
|
29
|
+
private readonly reasoningTransport;
|
|
30
|
+
private readonly extraHeaders?;
|
|
31
|
+
private readonly extraBody?;
|
|
32
|
+
private readonly providerOptions?;
|
|
33
|
+
private readonly multimodal?;
|
|
34
|
+
private readonly thinking?;
|
|
35
|
+
constructor(apiKey: string, model?: string, baseUrl?: string, proxyUrl?: string, options?: GeminiProviderOptions);
|
|
36
|
+
uploadFile(input: UploadFileInput): Promise<UploadFileResult | null>;
|
|
37
|
+
complete(messages: Message[], opts?: CompletionOptions): Promise<ModelResponse>;
|
|
38
|
+
stream(messages: Message[], opts?: CompletionOptions): AsyncIterable<ModelStreamChunk>;
|
|
39
|
+
toConfig(): ModelConfig;
|
|
40
|
+
private buildGeminiUrl;
|
|
41
|
+
private buildGeminiRequestBody;
|
|
42
|
+
private buildGeminiSystemInstruction;
|
|
43
|
+
private buildGeminiContents;
|
|
44
|
+
private buildGeminiTools;
|
|
45
|
+
private normalizeGeminiArgs;
|
|
46
|
+
private formatGeminiToolResult;
|
|
47
|
+
private extractGeminiContentBlocks;
|
|
48
|
+
private parseGeminiChunk;
|
|
49
|
+
}
|