@tyvm/knowhow 0.0.100 → 0.0.102

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 (62) hide show
  1. package/jest.manual.config.js +19 -0
  2. package/package.json +2 -1
  3. package/src/agents/base/base.ts +61 -4
  4. package/src/cli.ts +22 -1
  5. package/src/clients/contextLimits.ts +0 -2
  6. package/src/clients/pricing/anthropic.ts +0 -6
  7. package/src/clients/pricing/google.ts +0 -4
  8. package/src/clients/pricing/xai.ts +11 -0
  9. package/src/cloudWorker.ts +48 -30
  10. package/src/fileSync.ts +153 -9
  11. package/src/hashes.ts +52 -0
  12. package/src/login.ts +1 -4
  13. package/src/services/KnowhowClient.ts +8 -3
  14. package/src/services/Mcp.ts +17 -3
  15. package/src/services/S3.ts +15 -5
  16. package/src/types.ts +17 -17
  17. package/tests/manual/clients/completions.json +454 -0
  18. package/tests/manual/clients/completions.test.ts +166 -0
  19. package/ts_build/package.json +2 -1
  20. package/ts_build/src/agents/base/base.d.ts +1 -0
  21. package/ts_build/src/agents/base/base.js +37 -4
  22. package/ts_build/src/agents/base/base.js.map +1 -1
  23. package/ts_build/src/cli.js +11 -1
  24. package/ts_build/src/cli.js.map +1 -1
  25. package/ts_build/src/clients/anthropic.d.ts +0 -6
  26. package/ts_build/src/clients/contextLimits.js +0 -2
  27. package/ts_build/src/clients/contextLimits.js.map +1 -1
  28. package/ts_build/src/clients/pricing/anthropic.d.ts +0 -6
  29. package/ts_build/src/clients/pricing/anthropic.js +0 -6
  30. package/ts_build/src/clients/pricing/anthropic.js.map +1 -1
  31. package/ts_build/src/clients/pricing/google.js +0 -4
  32. package/ts_build/src/clients/pricing/google.js.map +1 -1
  33. package/ts_build/src/clients/pricing/xai.d.ts +10 -0
  34. package/ts_build/src/clients/pricing/xai.js +10 -0
  35. package/ts_build/src/clients/pricing/xai.js.map +1 -1
  36. package/ts_build/src/clients/xai.d.ts +13 -4
  37. package/ts_build/src/cloudWorker.js +38 -25
  38. package/ts_build/src/cloudWorker.js.map +1 -1
  39. package/ts_build/src/fileSync.d.ts +3 -0
  40. package/ts_build/src/fileSync.js +104 -6
  41. package/ts_build/src/fileSync.js.map +1 -1
  42. package/ts_build/src/hashes.d.ts +4 -0
  43. package/ts_build/src/hashes.js +34 -0
  44. package/ts_build/src/hashes.js.map +1 -1
  45. package/ts_build/src/login.js +1 -4
  46. package/ts_build/src/login.js.map +1 -1
  47. package/ts_build/src/services/KnowhowClient.d.ts +4 -1
  48. package/ts_build/src/services/KnowhowClient.js +4 -1
  49. package/ts_build/src/services/KnowhowClient.js.map +1 -1
  50. package/ts_build/src/services/Mcp.js +11 -3
  51. package/ts_build/src/services/Mcp.js.map +1 -1
  52. package/ts_build/src/services/S3.js +14 -4
  53. package/ts_build/src/services/S3.js.map +1 -1
  54. package/ts_build/src/types.d.ts +2 -2
  55. package/ts_build/src/types.js +12 -13
  56. package/ts_build/src/types.js.map +1 -1
  57. package/ts_build/tests/manual/clients/completions.test.d.ts +1 -0
  58. package/ts_build/tests/manual/clients/completions.test.js +135 -0
  59. package/ts_build/tests/manual/clients/completions.test.js.map +1 -0
  60. package/test-ai-completion.ts +0 -39
  61. package/test-mcp-args.ts +0 -71
  62. package/test-tools-service.ts +0 -45
@@ -575,7 +575,9 @@ export class KnowhowSimpleClient {
575
575
  * Get presigned S3 URL for downloading a file from Knowhow FS.
576
576
  * First finds or creates the file by path, then gets its download URL.
577
577
  */
578
- async getOrgFilePresignedDownloadUrl(filePath: string): Promise<string> {
578
+ async getOrgFilePresignedDownloadUrl(
579
+ filePath: string
580
+ ): Promise<{ downloadUrl: string; checksumSHA256: string | null }> {
579
581
  await this.checkJwt();
580
582
 
581
583
  // Find the file by path
@@ -585,12 +587,15 @@ export class KnowhowSimpleClient {
585
587
  }
586
588
 
587
589
  // Get download URL using the file ID
588
- const response = await http.post<{ downloadUrl: string }>(
590
+ const response = await http.post<{ downloadUrl: string; checksumSHA256: string | null }>(
589
591
  `${this.baseUrl}/api/org-files/download/${file.id}`,
590
592
  {},
591
593
  { headers: this.headers }
592
594
  );
593
- return response.data.downloadUrl;
595
+ return {
596
+ downloadUrl: response.data.downloadUrl,
597
+ checksumSHA256: response.data.checksumSHA256 ?? null,
598
+ };
594
599
  }
595
600
 
596
601
  /**
@@ -136,13 +136,24 @@ export class McpService {
136
136
  if (shouldAutoConnect && !this.connected[index]) {
137
137
  console.log(`Connecting to MCP server: ${config.name}`);
138
138
  try {
139
- await client.connect(this.transports[index]);
139
+ // Wrap connect in a race with a timeout to prevent hanging,
140
+ // and use a wrapping Promise to catch errors that may come
141
+ // from event-emitter callbacks (unhandled rejection pattern in MCP SDK)
142
+ await new Promise<void>(async (resolve, reject) => {
143
+ try {
144
+ await client.connect(this.transports[index]);
145
+ resolve();
146
+ } catch (err) {
147
+ reject(err);
148
+ }
149
+ });
140
150
  } catch (error) {
141
151
  console.error(
142
152
  `Failed to connect to MCP server '${config.name}':`,
143
153
  error.message || error
144
154
  );
145
- throw error; // Re-throw to mark as rejected in Promise.allSettled
155
+ // Don't re-throw just log and continue so other servers can still connect
156
+ return;
146
157
  }
147
158
  this.connected[index] = true;
148
159
  } else if (!shouldAutoConnect) {
@@ -155,7 +166,10 @@ export class McpService {
155
166
 
156
167
  // Log summary of auto-connection results
157
168
  const successful = results.filter((r) => r.status === "fulfilled").length;
158
- const failed = results.filter((r) => r.status === "rejected").length;
169
+ // Since we no longer re-throw, count servers that are NOT connected after the attempt
170
+ const failed = this.clients.filter(
171
+ (_, i) => this.config[i]?.autoConnect !== false && !this.connected[i]
172
+ ).length;
159
173
  if (failed > 0) {
160
174
  console.warn(
161
175
  `Auto-connected ${successful}/${this.clients.length} MCP servers (${failed} failed)`
@@ -1,4 +1,5 @@
1
1
  import * as fs from "fs";
2
+ import * as crypto from "crypto";
2
3
  import { createWriteStream, createReadStream } from "fs";
3
4
  import { pipeline, Readable } from "stream";
4
5
  import * as util from "util";
@@ -11,19 +12,28 @@ export class S3Service {
11
12
  filePath: string
12
13
  ): Promise<void> {
13
14
  try {
14
- const fileStream = createReadStream(filePath);
15
+ const fileContent = fs.readFileSync(filePath);
15
16
  const fileStats = await fs.promises.stat(filePath);
17
+ const sha256Base64 = crypto
18
+ .createHash("sha256")
19
+ .update(fileContent)
20
+ .digest("base64");
16
21
 
17
22
  const response = await fetch(presignedUrl, {
18
23
  method: "PUT",
19
- headers: { "Content-Length": String(fileStats.size) },
20
- body: fileStream as any,
21
- // @ts-ignore - Node 18+ supports ReadableStream body with duplex
24
+ headers: {
25
+ "Content-Length": String(fileStats.size),
26
+ "x-amz-checksum-sha256": sha256Base64,
27
+ "x-amz-sdk-checksum-algorithm": "SHA256",
28
+ },
29
+ body: fileContent,
30
+ // @ts-ignore
22
31
  duplex: "half",
23
32
  });
24
33
 
25
34
  if (!response.ok) {
26
- throw new Error(`Upload failed with status code: ${response.status}`);
35
+ const text = await response.text();
36
+ throw new Error(`Upload failed with status code: ${response.status} - ${text}`);
27
37
  }
28
38
 
29
39
  console.log("File uploaded successfully to pre-signed URL");
package/src/types.ts CHANGED
@@ -89,9 +89,9 @@ export type Config = {
89
89
  auth?: {
90
90
  required?: boolean;
91
91
  passkey?: {
92
- publicKey?: string; // base64-encoded public key
93
- credentialId?: string; // base64-encoded credential ID
94
- algorithm?: string; // e.g. "ES256"
92
+ publicKey?: string; // base64-encoded public key
93
+ credentialId?: string; // base64-encoded credential ID
94
+ algorithm?: string; // e.g. "ES256"
95
95
  };
96
96
  sessionDurationHours?: number;
97
97
  };
@@ -187,19 +187,20 @@ export const Models = {
187
187
  anthropic: {
188
188
  Opus4_6: "claude-opus-4-6",
189
189
  Sonnet4_6: "claude-sonnet-4-6",
190
- Opus4_5: "claude-opus-4-5-20251101",
191
- Opus4: "claude-opus-4-20250514",
192
- Opus4_1: "claude-opus-4-1-20250805",
193
- Sonnet4_5: "claude-sonnet-4-5-20250929",
194
- Haiku4_5: "claude-haiku-4-5-20251001",
195
- Sonnet4: "claude-sonnet-4-20250514",
196
- Sonnet3_7: "claude-3-7-sonnet-20250219",
197
- Sonnet3_5: "claude-3-5-sonnet-20241022",
198
- Haiku3_5: "claude-3-5-haiku-20241022",
199
- Opus3: "claude-3-opus-20240229",
200
- Haiku3: "claude-3-haiku-20240307",
190
+ Opus4_5: "claude-opus-4-5",
191
+ Opus4: "claude-opus-4",
192
+ Opus4_1: "claude-opus-4-1",
193
+ Sonnet4_5: "claude-sonnet-4-5",
194
+ Haiku4_5: "claude-haiku-4-5",
195
+ Sonnet4: "claude-sonnet-4",
196
+ Sonnet3_7: "claude-3-7-sonnet",
197
+ Sonnet3_5: "claude-3-5-sonnet",
198
+ Opus3: "claude-3-opus",
199
+ Haiku3: "claude-3-haiku",
201
200
  },
202
201
  xai: {
202
+ Grok_4_20_Reasoning: "grok-4.20-0309-reasoning",
203
+ Grok_4_20_NonReasoning: "grok-4.20-0309-non-reasoning",
203
204
  Grok4_1_Fast_Reasoning: "grok-4-1-fast-reasoning",
204
205
  Grok4_1_Fast_NonReasoning: "grok-4-1-fast-non-reasoning",
205
206
  GrokCodeFast: "grok-code-fast-1",
@@ -277,13 +278,13 @@ export const Models = {
277
278
  Gemini_25_Pro_Preview: "gemini-2.5-pro-preview-05-06",
278
279
  Gemini_25_Flash_Image: "gemini-2.5-flash-image",
279
280
  Gemini_25_Flash_Live: "gemini-2.5-flash-live-preview",
280
- Gemini_25_Flash_Native_Audio: "gemini-2.5-flash-native-audio-preview-12-2025",
281
+ Gemini_25_Flash_Native_Audio:
282
+ "gemini-2.5-flash-native-audio-preview-12-2025",
281
283
  Gemini_25_Pro_TTS: "gemini-2.5-pro-preview-tts",
282
284
  // Gemini 2.0 (deprecated)
283
285
  Gemini_20_Flash: "gemini-2.0-flash",
284
286
  Gemini_20_Flash_Preview_Image_Generation:
285
287
  "gemini-2.0-flash-exp-image-generation",
286
- Gemini_20_Flash_Lite: "gemini-2.0-flash-lite",
287
288
  // Gemini 1.5 (legacy)
288
289
  Gemini_15_Flash: "gemini-1.5-flash",
289
290
  Gemini_15_Flash_8B: "gemini-1.5-flash-8b",
@@ -380,7 +381,6 @@ export const GoogleReasoningModels = [
380
381
  Models.google.Gemini_25_Flash_Preview,
381
382
  Models.google.Gemini_25_Pro_Preview,
382
383
  Models.google.Gemini_20_Flash,
383
- Models.google.Gemini_20_Flash_Lite,
384
384
  Models.google.Gemini_15_Flash,
385
385
  Models.google.Gemini_15_Flash_8B,
386
386
  Models.google.Gemini_15_Pro,
@@ -0,0 +1,454 @@
1
+ {
2
+ "anthropic::claude-haiku-4-5-20251001": {
3
+ "provider": "anthropic",
4
+ "model": "claude-haiku-4-5-20251001",
5
+ "prompt": "Say hello in 5 words.",
6
+ "response": "Hello, how are you today?",
7
+ "usage": {
8
+ "input_tokens": 15,
9
+ "cache_creation_input_tokens": 0,
10
+ "cache_read_input_tokens": 0,
11
+ "cache_creation": {
12
+ "ephemeral_5m_input_tokens": 0,
13
+ "ephemeral_1h_input_tokens": 0
14
+ },
15
+ "output_tokens": 10,
16
+ "service_tier": "standard",
17
+ "inference_geo": "not_available"
18
+ },
19
+ "usd_cost": 0.00006500000000000001,
20
+ "testedAt": "2026-04-14T19:18:23.775Z"
21
+ },
22
+ "anthropic::claude-sonnet-4-6": {
23
+ "provider": "anthropic",
24
+ "model": "claude-sonnet-4-6",
25
+ "prompt": "Say hello in 5 words.",
26
+ "response": "\"Hello there, how are you?\"",
27
+ "usage": {
28
+ "input_tokens": 15,
29
+ "cache_creation_input_tokens": 0,
30
+ "cache_read_input_tokens": 0,
31
+ "cache_creation": {
32
+ "ephemeral_5m_input_tokens": 0,
33
+ "ephemeral_1h_input_tokens": 0
34
+ },
35
+ "output_tokens": 11,
36
+ "service_tier": "standard",
37
+ "inference_geo": "global"
38
+ },
39
+ "usd_cost": 0.00021,
40
+ "testedAt": "2026-04-14T19:18:24.981Z"
41
+ },
42
+ "anthropic::claude-opus-4-6": {
43
+ "provider": "anthropic",
44
+ "model": "claude-opus-4-6",
45
+ "prompt": "Say hello in 5 words.",
46
+ "response": "Hello there, how are you?",
47
+ "usage": {
48
+ "input_tokens": 15,
49
+ "cache_creation_input_tokens": 0,
50
+ "cache_read_input_tokens": 0,
51
+ "cache_creation": {
52
+ "ephemeral_5m_input_tokens": 0,
53
+ "ephemeral_1h_input_tokens": 0
54
+ },
55
+ "output_tokens": 10,
56
+ "service_tier": "standard",
57
+ "inference_geo": "global"
58
+ },
59
+ "usd_cost": 0.000325,
60
+ "testedAt": "2026-04-14T19:18:27.010Z"
61
+ },
62
+ "google::gemini-3.1-flash-lite-preview": {
63
+ "provider": "google",
64
+ "model": "gemini-3.1-flash-lite-preview",
65
+ "prompt": "Say hello in 5 words.",
66
+ "response": "Hello, it is nice meeting.",
67
+ "usage": {
68
+ "promptTokenCount": 8,
69
+ "candidatesTokenCount": 7,
70
+ "totalTokenCount": 15,
71
+ "promptTokensDetails": [
72
+ {
73
+ "modality": "TEXT",
74
+ "tokenCount": 8
75
+ }
76
+ ]
77
+ },
78
+ "usd_cost": 0.000002,
79
+ "testedAt": "2026-04-14T19:18:35.317Z"
80
+ },
81
+ "google::gemini-3.1-flash-image-preview": {
82
+ "provider": "google",
83
+ "model": "gemini-3.1-flash-image-preview",
84
+ "prompt": "Say hello in 5 words.",
85
+ "response": "Hello there, welcome everyone, goodbye. \n",
86
+ "usage": {
87
+ "promptTokenCount": 8,
88
+ "candidatesTokenCount": 10,
89
+ "totalTokenCount": 18,
90
+ "promptTokensDetails": [
91
+ {
92
+ "modality": "TEXT",
93
+ "tokenCount": 8
94
+ }
95
+ ]
96
+ },
97
+ "usd_cost": 0.000004,
98
+ "testedAt": "2026-04-14T19:18:38.564Z"
99
+ },
100
+ "xai::grok-3-mini-fast-beta": {
101
+ "provider": "xai",
102
+ "model": "grok-3-mini-fast-beta",
103
+ "prompt": "Say hello in 5 words.",
104
+ "response": "Hello, this is Grok here.",
105
+ "usage": {
106
+ "prompt_tokens": 14,
107
+ "completion_tokens": 8,
108
+ "total_tokens": 554,
109
+ "prompt_tokens_details": {
110
+ "text_tokens": 14,
111
+ "audio_tokens": 0,
112
+ "image_tokens": 0,
113
+ "cached_tokens": 5
114
+ },
115
+ "completion_tokens_details": {
116
+ "reasoning_tokens": 532,
117
+ "audio_tokens": 0,
118
+ "accepted_prediction_tokens": 0,
119
+ "rejected_prediction_tokens": 0
120
+ },
121
+ "num_sources_used": 0,
122
+ "cost_in_usd_ticks": 2730750
123
+ },
124
+ "usd_cost": 0.0000404,
125
+ "testedAt": "2026-04-14T19:18:52.696Z"
126
+ },
127
+ "xai::grok-3-mini-beta": {
128
+ "provider": "xai",
129
+ "model": "grok-3-mini-beta",
130
+ "prompt": "Say hello in 5 words.",
131
+ "response": "Hello, I am Grok here.",
132
+ "usage": {
133
+ "prompt_tokens": 14,
134
+ "completion_tokens": 8,
135
+ "total_tokens": 549,
136
+ "prompt_tokens_details": {
137
+ "text_tokens": 14,
138
+ "audio_tokens": 0,
139
+ "image_tokens": 0,
140
+ "cached_tokens": 3
141
+ },
142
+ "completion_tokens_details": {
143
+ "reasoning_tokens": 527,
144
+ "audio_tokens": 0,
145
+ "accepted_prediction_tokens": 0,
146
+ "rejected_prediction_tokens": 0
147
+ },
148
+ "num_sources_used": 0,
149
+ "cost_in_usd_ticks": 2710250
150
+ },
151
+ "usd_cost": 0.0000082,
152
+ "testedAt": "2026-04-14T19:19:03.041Z"
153
+ },
154
+ "xai::grok-4-0709": {
155
+ "provider": "xai",
156
+ "model": "grok-4-0709",
157
+ "prompt": "Say hello in 5 words.",
158
+ "response": "Hello, how are you today?",
159
+ "usage": {
160
+ "prompt_tokens": 691,
161
+ "completion_tokens": 7,
162
+ "total_tokens": 849,
163
+ "prompt_tokens_details": {
164
+ "text_tokens": 691,
165
+ "audio_tokens": 0,
166
+ "image_tokens": 0,
167
+ "cached_tokens": 679
168
+ },
169
+ "completion_tokens_details": {
170
+ "reasoning_tokens": 151,
171
+ "audio_tokens": 0,
172
+ "accepted_prediction_tokens": 0,
173
+ "rejected_prediction_tokens": 0
174
+ },
175
+ "num_sources_used": 0,
176
+ "cost_in_usd_ticks": 29152500
177
+ },
178
+ "usd_cost": 0.0021780000000000002,
179
+ "testedAt": "2026-04-14T19:19:06.403Z"
180
+ },
181
+ "xai::grok-4-1-fast-non-reasoning": {
182
+ "provider": "xai",
183
+ "model": "grok-4-1-fast-non-reasoning",
184
+ "prompt": "Say hello in 5 words.",
185
+ "response": "Hello, world! How are you today?",
186
+ "usage": {
187
+ "prompt_tokens": 175,
188
+ "completion_tokens": 9,
189
+ "total_tokens": 184,
190
+ "prompt_tokens_details": {
191
+ "text_tokens": 175,
192
+ "audio_tokens": 0,
193
+ "image_tokens": 0,
194
+ "cached_tokens": 161
195
+ },
196
+ "completion_tokens_details": {
197
+ "reasoning_tokens": 0,
198
+ "audio_tokens": 0,
199
+ "accepted_prediction_tokens": 0,
200
+ "rejected_prediction_tokens": 0
201
+ },
202
+ "num_sources_used": 0,
203
+ "cost_in_usd_ticks": 153500
204
+ },
205
+ "usd_cost": 0.00004755,
206
+ "testedAt": "2026-04-14T19:19:06.825Z"
207
+ },
208
+ "openai::gpt-4o-mini-2024-07-18": {
209
+ "provider": "openai",
210
+ "model": "gpt-4o-mini-2024-07-18",
211
+ "prompt": "Say hello in 5 words.",
212
+ "response": "Hello! How are you today?",
213
+ "usage": {
214
+ "prompt_tokens": 14,
215
+ "completion_tokens": 7,
216
+ "total_tokens": 21,
217
+ "prompt_tokens_details": {
218
+ "cached_tokens": 0,
219
+ "audio_tokens": 0
220
+ },
221
+ "completion_tokens_details": {
222
+ "reasoning_tokens": 0,
223
+ "audio_tokens": 0,
224
+ "accepted_prediction_tokens": 0,
225
+ "rejected_prediction_tokens": 0
226
+ }
227
+ },
228
+ "usd_cost": 0.000006300000000000001,
229
+ "testedAt": "2026-04-14T19:20:03.349Z"
230
+ },
231
+ "openai::gpt-4.1-nano-2025-04-14": {
232
+ "provider": "openai",
233
+ "model": "gpt-4.1-nano-2025-04-14",
234
+ "prompt": "Say hello in 5 words.",
235
+ "response": "Hello! How are you today?",
236
+ "usage": {
237
+ "prompt_tokens": 14,
238
+ "completion_tokens": 7,
239
+ "total_tokens": 21,
240
+ "prompt_tokens_details": {
241
+ "cached_tokens": 0,
242
+ "audio_tokens": 0
243
+ },
244
+ "completion_tokens_details": {
245
+ "reasoning_tokens": 0,
246
+ "audio_tokens": 0,
247
+ "accepted_prediction_tokens": 0,
248
+ "rejected_prediction_tokens": 0
249
+ }
250
+ },
251
+ "usd_cost": 0.0000042000000000000004,
252
+ "testedAt": "2026-04-14T19:20:04.374Z"
253
+ },
254
+ "openai::gpt-5.4": {
255
+ "provider": "openai",
256
+ "model": "gpt-5.4",
257
+ "prompt": "Say hello in 5 words.",
258
+ "response": "Hello! Hope you're doing well.",
259
+ "usage": {
260
+ "prompt_tokens": 13,
261
+ "completion_tokens": 111,
262
+ "total_tokens": 124
263
+ },
264
+ "usd_cost": 0.0016975,
265
+ "testedAt": "2026-04-14T19:20:06.964Z"
266
+ },
267
+ "openai::gpt-5.4-pro": {
268
+ "provider": "openai",
269
+ "model": "gpt-5.4-pro",
270
+ "prompt": "Say hello in 5 words.",
271
+ "response": "Hello, have a wonderful day!",
272
+ "usage": {
273
+ "prompt_tokens": 13,
274
+ "completion_tokens": 157,
275
+ "total_tokens": 170
276
+ },
277
+ "usd_cost": 0.028650000000000002,
278
+ "testedAt": "2026-04-14T19:20:26.803Z"
279
+ },
280
+ "openai::gpt-5.4-mini": {
281
+ "provider": "openai",
282
+ "model": "gpt-5.4-mini",
283
+ "prompt": "Say hello in 5 words.",
284
+ "response": "Hello, how are you today?",
285
+ "usage": {
286
+ "prompt_tokens": 13,
287
+ "completion_tokens": 46,
288
+ "total_tokens": 59
289
+ },
290
+ "usd_cost": 0.00021674999999999998,
291
+ "testedAt": "2026-04-14T19:20:27.900Z"
292
+ },
293
+ "openai::gpt-5.4-nano": {
294
+ "provider": "openai",
295
+ "model": "gpt-5.4-nano",
296
+ "prompt": "Say hello in 5 words.",
297
+ "response": "Hello! How are you doing?",
298
+ "usage": {
299
+ "prompt_tokens": 13,
300
+ "completion_tokens": 11,
301
+ "total_tokens": 24
302
+ },
303
+ "usd_cost": 0.00001635,
304
+ "testedAt": "2026-04-14T19:20:28.644Z"
305
+ },
306
+ "openai::gpt-5.3-chat-latest": {
307
+ "provider": "openai",
308
+ "model": "gpt-5.3-chat-latest",
309
+ "prompt": "Say hello in 5 words.",
310
+ "response": "Hello there, nice to meet.",
311
+ "usage": {
312
+ "prompt_tokens": 13,
313
+ "completion_tokens": 16,
314
+ "total_tokens": 29,
315
+ "prompt_tokens_details": {
316
+ "cached_tokens": 0,
317
+ "audio_tokens": 0
318
+ },
319
+ "completion_tokens_details": {
320
+ "reasoning_tokens": 0,
321
+ "audio_tokens": 0,
322
+ "accepted_prediction_tokens": 0,
323
+ "rejected_prediction_tokens": 0
324
+ }
325
+ },
326
+ "usd_cost": 0.00024675,
327
+ "testedAt": "2026-04-14T19:20:30.469Z"
328
+ },
329
+ "openai::gpt-5.3-codex": {
330
+ "provider": "openai",
331
+ "model": "gpt-5.3-codex",
332
+ "prompt": "Say hello in 5 words.",
333
+ "response": "Hello there, hope you're doing great!",
334
+ "usage": {
335
+ "prompt_tokens": 13,
336
+ "completion_tokens": 12,
337
+ "total_tokens": 25
338
+ },
339
+ "usd_cost": 0.00019075,
340
+ "testedAt": "2026-04-14T19:20:31.376Z"
341
+ },
342
+ "google::gemini-3.1-pro-preview": {
343
+ "provider": "google",
344
+ "model": "gemini-3.1-pro-preview",
345
+ "prompt": "Say hello in 5 words.",
346
+ "response": "Hello,",
347
+ "usage": {
348
+ "promptTokenCount": 8,
349
+ "candidatesTokenCount": 2,
350
+ "totalTokenCount": 54,
351
+ "promptTokensDetails": [
352
+ {
353
+ "modality": "TEXT",
354
+ "tokenCount": 8
355
+ }
356
+ ],
357
+ "thoughtsTokenCount": 44
358
+ },
359
+ "usd_cost": 0.000016,
360
+ "testedAt": "2026-04-14T19:20:41.040Z"
361
+ },
362
+ "anthropic::claude-haiku-4-5": {
363
+ "provider": "anthropic",
364
+ "model": "claude-haiku-4-5",
365
+ "prompt": "Say hello in 5 words.",
366
+ "response": "Hello, how are you today?",
367
+ "usage": {
368
+ "input_tokens": 15,
369
+ "cache_creation_input_tokens": 0,
370
+ "cache_read_input_tokens": 0,
371
+ "cache_creation": {
372
+ "ephemeral_5m_input_tokens": 0,
373
+ "ephemeral_1h_input_tokens": 0
374
+ },
375
+ "output_tokens": 10,
376
+ "service_tier": "standard",
377
+ "inference_geo": "not_available"
378
+ },
379
+ "usd_cost": 0.00006500000000000001,
380
+ "testedAt": "2026-04-14T19:21:44.319Z"
381
+ },
382
+ "google::gemini-2.5-flash": {
383
+ "provider": "google",
384
+ "model": "gemini-2.5-flash",
385
+ "prompt": "Say hello in 5 words.",
386
+ "response": "Hello there",
387
+ "usage": {
388
+ "promptTokenCount": 8,
389
+ "candidatesTokenCount": 2,
390
+ "totalTokenCount": 54,
391
+ "promptTokensDetails": [
392
+ {
393
+ "modality": "TEXT",
394
+ "tokenCount": 8
395
+ }
396
+ ],
397
+ "thoughtsTokenCount": 44
398
+ },
399
+ "usd_cost": 0.0000024,
400
+ "testedAt": "2026-04-14T19:21:50.097Z"
401
+ },
402
+ "xai::grok-4.20-0309-non-reasoning": {
403
+ "provider": "xai",
404
+ "model": "grok-4.20-0309-non-reasoning",
405
+ "prompt": "Say hello in 5 words.",
406
+ "response": "Hello there, how are you?",
407
+ "usage": {
408
+ "prompt_tokens": 129,
409
+ "completion_tokens": 7,
410
+ "total_tokens": 136,
411
+ "prompt_tokens_details": {
412
+ "text_tokens": 129,
413
+ "audio_tokens": 0,
414
+ "image_tokens": 0,
415
+ "cached_tokens": 64
416
+ },
417
+ "completion_tokens_details": {
418
+ "reasoning_tokens": 0,
419
+ "audio_tokens": 0,
420
+ "accepted_prediction_tokens": 0,
421
+ "rejected_prediction_tokens": 0
422
+ },
423
+ "num_sources_used": 0,
424
+ "cost_in_usd_ticks": 1848000
425
+ },
426
+ "testedAt": "2026-04-14T19:28:47.420Z"
427
+ },
428
+ "xai::grok-4.20-0309-reasoning": {
429
+ "provider": "xai",
430
+ "model": "grok-4.20-0309-reasoning",
431
+ "prompt": "Say hello in 5 words.",
432
+ "response": "Hello there how are you?",
433
+ "usage": {
434
+ "prompt_tokens": 131,
435
+ "completion_tokens": 6,
436
+ "total_tokens": 1170,
437
+ "prompt_tokens_details": {
438
+ "text_tokens": 131,
439
+ "audio_tokens": 0,
440
+ "image_tokens": 0,
441
+ "cached_tokens": 64
442
+ },
443
+ "completion_tokens_details": {
444
+ "reasoning_tokens": 1033,
445
+ "audio_tokens": 0,
446
+ "accepted_prediction_tokens": 0,
447
+ "rejected_prediction_tokens": 0
448
+ },
449
+ "num_sources_used": 0,
450
+ "cost_in_usd_ticks": 63808000
451
+ },
452
+ "testedAt": "2026-04-14T19:28:53.889Z"
453
+ }
454
+ }