@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.
Files changed (193) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -273
  3. package/README.zh-CN.md +114 -0
  4. package/dist/core/agent/breakpoint-manager.d.ts +16 -0
  5. package/dist/core/agent/breakpoint-manager.js +36 -0
  6. package/dist/core/agent/message-queue.d.ts +26 -0
  7. package/dist/core/agent/message-queue.js +57 -0
  8. package/dist/core/agent/permission-manager.d.ts +9 -0
  9. package/dist/core/agent/permission-manager.js +32 -0
  10. package/dist/core/agent/todo-manager.d.ts +26 -0
  11. package/dist/core/agent/todo-manager.js +91 -0
  12. package/dist/core/agent/tool-runner.d.ts +9 -0
  13. package/dist/core/agent/tool-runner.js +45 -0
  14. package/dist/core/agent.d.ts +228 -62
  15. package/dist/core/agent.js +1890 -615
  16. package/dist/core/config.d.ts +10 -0
  17. package/dist/core/config.js +2 -0
  18. package/dist/core/context-manager.d.ts +82 -0
  19. package/dist/core/context-manager.js +241 -0
  20. package/dist/core/errors.d.ts +22 -0
  21. package/dist/core/errors.js +49 -0
  22. package/dist/core/events.d.ts +41 -10
  23. package/dist/core/events.js +270 -68
  24. package/dist/core/file-pool.d.ts +41 -0
  25. package/dist/core/file-pool.js +102 -0
  26. package/dist/core/hooks.d.ts +3 -3
  27. package/dist/core/hooks.js +1 -1
  28. package/dist/core/permission-modes.d.ts +31 -0
  29. package/dist/core/permission-modes.js +61 -0
  30. package/dist/core/pool.d.ts +56 -13
  31. package/dist/core/pool.js +244 -34
  32. package/dist/core/room.d.ts +2 -2
  33. package/dist/core/room.js +10 -10
  34. package/dist/core/scheduler.d.ts +30 -23
  35. package/dist/core/scheduler.js +42 -168
  36. package/dist/core/skills/index.d.ts +10 -0
  37. package/dist/core/skills/index.js +20 -0
  38. package/dist/core/skills/management-manager.d.ts +130 -0
  39. package/dist/core/skills/management-manager.js +557 -0
  40. package/dist/core/skills/manager.d.ts +47 -0
  41. package/dist/core/skills/manager.js +243 -0
  42. package/dist/core/skills/operation-queue.d.ts +87 -0
  43. package/dist/core/skills/operation-queue.js +113 -0
  44. package/dist/core/skills/sandbox-file-manager.d.ts +82 -0
  45. package/dist/core/skills/sandbox-file-manager.js +183 -0
  46. package/dist/core/skills/types.d.ts +120 -0
  47. package/dist/core/skills/types.js +9 -0
  48. package/dist/core/skills/xml-generator.d.ts +13 -0
  49. package/dist/core/skills/xml-generator.js +70 -0
  50. package/dist/core/template.d.ts +57 -0
  51. package/dist/core/template.js +35 -0
  52. package/dist/core/time-bridge.d.ts +18 -0
  53. package/dist/core/time-bridge.js +100 -0
  54. package/dist/core/todo.d.ts +34 -0
  55. package/dist/core/todo.js +89 -0
  56. package/dist/core/types.d.ts +311 -114
  57. package/dist/core/types.js +1 -12
  58. package/dist/index.d.ts +47 -9
  59. package/dist/index.js +108 -15
  60. package/dist/infra/db/postgres/postgres-store.d.ts +97 -0
  61. package/dist/infra/db/postgres/postgres-store.js +1073 -0
  62. package/dist/infra/db/sqlite/sqlite-store.d.ts +84 -0
  63. package/dist/infra/db/sqlite/sqlite-store.js +800 -0
  64. package/dist/infra/e2b/e2b-fs.d.ts +29 -0
  65. package/dist/infra/e2b/e2b-fs.js +128 -0
  66. package/dist/infra/e2b/e2b-sandbox.d.ts +37 -0
  67. package/dist/infra/e2b/e2b-sandbox.js +156 -0
  68. package/dist/infra/e2b/e2b-template.d.ts +24 -0
  69. package/dist/infra/e2b/e2b-template.js +105 -0
  70. package/dist/infra/e2b/index.d.ts +4 -0
  71. package/dist/infra/e2b/index.js +9 -0
  72. package/dist/infra/e2b/types.d.ts +46 -0
  73. package/dist/infra/e2b/types.js +2 -0
  74. package/dist/infra/provider.d.ts +17 -58
  75. package/dist/infra/provider.js +65 -116
  76. package/dist/infra/providers/anthropic.d.ts +42 -0
  77. package/dist/infra/providers/anthropic.js +308 -0
  78. package/dist/infra/providers/core/errors.d.ts +230 -0
  79. package/dist/infra/providers/core/errors.js +353 -0
  80. package/dist/infra/providers/core/fork.d.ts +106 -0
  81. package/dist/infra/providers/core/fork.js +418 -0
  82. package/dist/infra/providers/core/index.d.ts +10 -0
  83. package/dist/infra/providers/core/index.js +76 -0
  84. package/dist/infra/providers/core/logger.d.ts +186 -0
  85. package/dist/infra/providers/core/logger.js +191 -0
  86. package/dist/infra/providers/core/retry.d.ts +62 -0
  87. package/dist/infra/providers/core/retry.js +189 -0
  88. package/dist/infra/providers/core/usage.d.ts +151 -0
  89. package/dist/infra/providers/core/usage.js +376 -0
  90. package/dist/infra/providers/gemini.d.ts +49 -0
  91. package/dist/infra/providers/gemini.js +493 -0
  92. package/dist/infra/providers/index.d.ts +25 -0
  93. package/dist/infra/providers/index.js +83 -0
  94. package/dist/infra/providers/openai.d.ts +123 -0
  95. package/dist/infra/providers/openai.js +662 -0
  96. package/dist/infra/providers/types.d.ts +334 -0
  97. package/dist/infra/providers/types.js +20 -0
  98. package/dist/infra/providers/utils.d.ts +53 -0
  99. package/dist/infra/providers/utils.js +400 -0
  100. package/dist/infra/sandbox-factory.d.ts +13 -0
  101. package/dist/infra/sandbox-factory.js +30 -0
  102. package/dist/infra/sandbox.d.ts +35 -6
  103. package/dist/infra/sandbox.js +174 -8
  104. package/dist/infra/store/factory.d.ts +45 -0
  105. package/dist/infra/store/factory.js +80 -0
  106. package/dist/infra/store/index.d.ts +3 -0
  107. package/dist/infra/store/index.js +26 -0
  108. package/dist/infra/store/json-store.d.ts +67 -0
  109. package/dist/infra/store/json-store.js +606 -0
  110. package/dist/infra/store/types.d.ts +342 -0
  111. package/dist/infra/store/types.js +2 -0
  112. package/dist/infra/store.d.ts +12 -32
  113. package/dist/infra/store.js +27 -130
  114. package/dist/tools/bash_kill/index.d.ts +1 -0
  115. package/dist/tools/bash_kill/index.js +35 -0
  116. package/dist/tools/bash_kill/prompt.d.ts +2 -0
  117. package/dist/tools/bash_kill/prompt.js +14 -0
  118. package/dist/tools/bash_logs/index.d.ts +1 -0
  119. package/dist/tools/bash_logs/index.js +40 -0
  120. package/dist/tools/bash_logs/prompt.d.ts +2 -0
  121. package/dist/tools/bash_logs/prompt.js +14 -0
  122. package/dist/tools/bash_run/index.d.ts +16 -0
  123. package/dist/tools/bash_run/index.js +61 -0
  124. package/dist/tools/bash_run/prompt.d.ts +2 -0
  125. package/dist/tools/bash_run/prompt.js +18 -0
  126. package/dist/tools/builtin.d.ts +7 -13
  127. package/dist/tools/builtin.js +19 -90
  128. package/dist/tools/define.d.ts +101 -0
  129. package/dist/tools/define.js +214 -0
  130. package/dist/tools/fs_edit/index.d.ts +1 -0
  131. package/dist/tools/fs_edit/index.js +62 -0
  132. package/dist/tools/fs_edit/prompt.d.ts +2 -0
  133. package/dist/tools/fs_edit/prompt.js +15 -0
  134. package/dist/tools/fs_glob/index.d.ts +1 -0
  135. package/dist/tools/fs_glob/index.js +40 -0
  136. package/dist/tools/fs_glob/prompt.d.ts +2 -0
  137. package/dist/tools/fs_glob/prompt.js +15 -0
  138. package/dist/tools/fs_grep/index.d.ts +1 -0
  139. package/dist/tools/fs_grep/index.js +66 -0
  140. package/dist/tools/fs_grep/prompt.d.ts +2 -0
  141. package/dist/tools/fs_grep/prompt.js +16 -0
  142. package/dist/tools/fs_multi_edit/index.d.ts +1 -0
  143. package/dist/tools/fs_multi_edit/index.js +106 -0
  144. package/dist/tools/fs_multi_edit/prompt.d.ts +2 -0
  145. package/dist/tools/fs_multi_edit/prompt.js +16 -0
  146. package/dist/tools/fs_read/index.d.ts +1 -0
  147. package/dist/tools/fs_read/index.js +40 -0
  148. package/dist/tools/fs_read/prompt.d.ts +2 -0
  149. package/dist/tools/fs_read/prompt.js +16 -0
  150. package/dist/tools/fs_write/index.d.ts +1 -0
  151. package/dist/tools/fs_write/index.js +40 -0
  152. package/dist/tools/fs_write/prompt.d.ts +2 -0
  153. package/dist/tools/fs_write/prompt.js +15 -0
  154. package/dist/tools/index.d.ts +11 -0
  155. package/dist/tools/index.js +61 -0
  156. package/dist/tools/mcp.d.ts +69 -0
  157. package/dist/tools/mcp.js +185 -0
  158. package/dist/tools/registry.d.ts +29 -0
  159. package/dist/tools/registry.js +26 -0
  160. package/dist/tools/scripts.d.ts +22 -0
  161. package/dist/tools/scripts.js +205 -0
  162. package/dist/tools/skills.d.ts +20 -0
  163. package/dist/tools/skills.js +115 -0
  164. package/dist/tools/task_run/index.d.ts +7 -0
  165. package/dist/tools/task_run/index.js +58 -0
  166. package/dist/tools/task_run/prompt.d.ts +5 -0
  167. package/dist/tools/task_run/prompt.js +25 -0
  168. package/dist/tools/todo_read/index.d.ts +1 -0
  169. package/dist/tools/todo_read/index.js +29 -0
  170. package/dist/tools/todo_read/prompt.d.ts +2 -0
  171. package/dist/tools/todo_read/prompt.js +18 -0
  172. package/dist/tools/todo_write/index.d.ts +1 -0
  173. package/dist/tools/todo_write/index.js +42 -0
  174. package/dist/tools/todo_write/prompt.d.ts +2 -0
  175. package/dist/tools/todo_write/prompt.js +23 -0
  176. package/dist/tools/tool.d.ts +43 -0
  177. package/dist/tools/tool.js +211 -0
  178. package/dist/tools/toolkit.d.ts +69 -0
  179. package/dist/tools/toolkit.js +98 -0
  180. package/dist/tools/type-inference.d.ts +127 -0
  181. package/dist/tools/type-inference.js +207 -0
  182. package/dist/utils/agent-id.d.ts +1 -0
  183. package/dist/utils/agent-id.js +28 -0
  184. package/dist/utils/logger.d.ts +15 -0
  185. package/dist/utils/logger.js +44 -0
  186. package/dist/utils/session-id.js +16 -16
  187. package/package.json +35 -11
  188. package/dist/tools/bash.d.ts +0 -63
  189. package/dist/tools/bash.js +0 -92
  190. package/dist/tools/fs.d.ts +0 -96
  191. package/dist/tools/fs.js +0 -100
  192. package/dist/tools/task.d.ts +0 -38
  193. 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
+ }