@flame0510/project-aether 1.5.0 → 1.5.2
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/app/agents/ChannelManager.tsx +17 -5
- package/app/agents/PageClient.tsx +13 -3
- package/app/api/agents/download-image/route.ts +8 -0
- package/app/api/update-check/route.ts +26 -15
- package/app/components/VersionBanner.tsx +77 -12
- package/bin/rev4a.js +6 -3
- package/daemon.js +3 -3
- package/docs/ARCHITECTURE.md +25 -3
- package/docs/FRONTEND-ARCHITECTURE.md +3 -2
- package/docs/REV4A.md +17 -0
- package/docs/dev/API-REFERENCE.md +21 -4
- package/docs/rag/REV4A-OVERVIEW.md +7 -1
- package/docs/rag/WHAT-I-CAN-ANSWER.md +2 -1
- package/instrumentation.ts +11 -0
- package/lib/agent-edit-state.ts +25 -66
- package/lib/agent-job-state.ts +145 -0
- package/lib/agent-jobs-maintenance.ts +34 -0
- package/lib/agent-recreate-state.ts +24 -65
- package/lib/agent-restore-state.ts +25 -66
- package/lib/agent-restore.ts +28 -5
- package/lib/agent-update-state.ts +25 -61
- package/lib/channelManager.ts +12 -1
- package/model-pricing.json +258 -22
- package/models.config.json +424 -6
- package/package.json +1 -1
- package/scripts/refresh-model-pricing.mjs +5 -5
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* Persisted state of agent updates: the `agent_upgrades` table (lib/db-bootstrap.mjs).
|
|
3
3
|
*
|
|
4
4
|
* Kept apart from lib/agent-update.ts so the provider sync can ask which agents are
|
|
5
|
-
* being updated without importing the update action, which imports the sync.
|
|
5
|
+
* being updated without importing the update action, which imports the sync. The
|
|
6
|
+
* machinery is lib/agent-job-state.ts; this file holds the table's types and names.
|
|
6
7
|
*/
|
|
7
|
-
import {
|
|
8
|
+
import { createJobState } from '@/lib/agent-job-state';
|
|
8
9
|
|
|
9
10
|
export type UpdateStatus =
|
|
10
11
|
| 'pending'
|
|
@@ -38,65 +39,36 @@ export interface AgentUpdateRow {
|
|
|
38
39
|
|
|
39
40
|
const FINAL: readonly UpdateStatus[] = ['done', 'failed', 'interrupted', 'rolled_back', 'rollback_failed'];
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return Number(info.lastInsertRowid);
|
|
50
|
-
} finally {
|
|
51
|
-
db.close();
|
|
52
|
-
}
|
|
53
|
-
}
|
|
42
|
+
const state = createJobState({
|
|
43
|
+
table: 'agent_upgrades',
|
|
44
|
+
initialStatus: 'pending',
|
|
45
|
+
activeStatuses: ACTIVE_STATUSES,
|
|
46
|
+
finalStatuses: FINAL,
|
|
47
|
+
insertColumns: ['from_version', 'to_version'],
|
|
48
|
+
writableColumns: ['backup_file', 'baseline_json', 'verify_json'],
|
|
49
|
+
});
|
|
54
50
|
|
|
55
51
|
type Writable = Partial<Pick<AgentUpdateRow, 'status' | 'backup_file' | 'baseline_json' | 'verify_json' | 'error'>>;
|
|
56
52
|
|
|
53
|
+
export function insertUpdate(agentId: string, fromVersion: string | null, toVersion: string): number {
|
|
54
|
+
return state.insert(agentId, fromVersion, toVersion);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
57
|
export function updateRow(id: number, fields: Writable): void {
|
|
58
|
-
|
|
59
|
-
const now = Date.now();
|
|
60
|
-
const sets = [...entries.map(([k]) => `${k} = ?`), 'updated_at = ?'];
|
|
61
|
-
const values: unknown[] = [...entries.map(([, v]) => v), now];
|
|
62
|
-
if (fields.status && FINAL.includes(fields.status)) {
|
|
63
|
-
sets.push('finished_at = ?');
|
|
64
|
-
values.push(now);
|
|
65
|
-
} else if (fields.status) {
|
|
66
|
-
sets.push('finished_at = NULL');
|
|
67
|
-
}
|
|
68
|
-
const db = openDb(false);
|
|
69
|
-
try {
|
|
70
|
-
db.prepare(`UPDATE agent_upgrades SET ${sets.join(', ')} WHERE id = ?`).run(...values, id);
|
|
71
|
-
} finally {
|
|
72
|
-
db.close();
|
|
73
|
-
}
|
|
58
|
+
state.update(id, fields);
|
|
74
59
|
}
|
|
75
60
|
|
|
76
61
|
export function latestUpdate(agentId: string): AgentUpdateRow | null {
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
return (db.prepare('SELECT * FROM agent_upgrades WHERE agent_id = ? ORDER BY id DESC LIMIT 1').get(agentId) as AgentUpdateRow | undefined) ?? null;
|
|
80
|
-
} finally {
|
|
81
|
-
db.close();
|
|
82
|
-
}
|
|
62
|
+
return state.latest<AgentUpdateRow>(agentId);
|
|
83
63
|
}
|
|
84
64
|
|
|
85
65
|
export function isUpdateActive(agentId: string): boolean {
|
|
86
|
-
|
|
87
|
-
return !!row && ACTIVE_STATUSES.includes(row.status);
|
|
66
|
+
return state.isActive(agentId);
|
|
88
67
|
}
|
|
89
68
|
|
|
90
69
|
/** AGENT_IDs with an update in an active status. */
|
|
91
70
|
export function activeUpdateAgentIds(): Set<string> {
|
|
92
|
-
|
|
93
|
-
try {
|
|
94
|
-
const placeholders = ACTIVE_STATUSES.map(() => '?').join(', ');
|
|
95
|
-
const rows = db.prepare(`SELECT DISTINCT agent_id FROM agent_upgrades WHERE status IN (${placeholders})`).all(...ACTIVE_STATUSES) as { agent_id: string }[];
|
|
96
|
-
return new Set(rows.map((r) => r.agent_id));
|
|
97
|
-
} finally {
|
|
98
|
-
db.close();
|
|
99
|
-
}
|
|
71
|
+
return state.activeAgentIds();
|
|
100
72
|
}
|
|
101
73
|
|
|
102
74
|
/**
|
|
@@ -105,18 +77,10 @@ export function activeUpdateAgentIds(): Set<string> {
|
|
|
105
77
|
* between Rollback and a new Update.
|
|
106
78
|
*/
|
|
107
79
|
export function markInterruptedUpdates(): number {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
SET error = COALESCE(error, 'Rev4a restarted while this step was running: ' || status),
|
|
115
|
-
status = 'interrupted', updated_at = ?, finished_at = ?
|
|
116
|
-
WHERE status IN (${placeholders})`,
|
|
117
|
-
).run(now, now, ...ACTIVE_STATUSES);
|
|
118
|
-
return info.changes;
|
|
119
|
-
} finally {
|
|
120
|
-
db.close();
|
|
121
|
-
}
|
|
80
|
+
return state.markInterrupted();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Keep the newest `keepPerAgent` updates of each agent; the rest is history. */
|
|
84
|
+
export function pruneUpdates(keepPerAgent: number): number {
|
|
85
|
+
return state.prune(keepPerAgent);
|
|
122
86
|
}
|
package/lib/channelManager.ts
CHANGED
|
@@ -287,6 +287,12 @@ export interface ApprovedPairing {
|
|
|
287
287
|
export interface PairingState {
|
|
288
288
|
pending: PendingPairing[];
|
|
289
289
|
approved: ApprovedPairing[];
|
|
290
|
+
/**
|
|
291
|
+
* Why the approved list is empty, when that is not simply "none": the pairing store
|
|
292
|
+
* could not be read (the writer is not in this OpenClaw build, or the read failed).
|
|
293
|
+
* Callers must show it instead of "No approved senders", which would be a guess.
|
|
294
|
+
*/
|
|
295
|
+
error?: string | null;
|
|
290
296
|
}
|
|
291
297
|
|
|
292
298
|
/**
|
|
@@ -428,8 +434,13 @@ export async function getPairings(agentId: string, channel: string = 'telegram')
|
|
|
428
434
|
if (store.status === 'ok') {
|
|
429
435
|
for (const entry of store.entries ?? []) approved.push({ senderId: String(entry) });
|
|
430
436
|
}
|
|
437
|
+
// 'absent' is a real answer (no store yet, so no approved senders); anything else means
|
|
438
|
+
// the read did not succeed and an empty list must not be presented as "none".
|
|
439
|
+
const error = store.status === 'ok' || store.status === 'absent'
|
|
440
|
+
? null
|
|
441
|
+
: (store.error ?? 'The approved senders could not be read');
|
|
431
442
|
|
|
432
|
-
return { pending, approved };
|
|
443
|
+
return { pending, approved, error };
|
|
433
444
|
}
|
|
434
445
|
|
|
435
446
|
/** Approve a pending pairing code */
|
package/model-pricing.json
CHANGED
|
@@ -103,6 +103,18 @@
|
|
|
103
103
|
"input": 0.9,
|
|
104
104
|
"output": 3.73
|
|
105
105
|
},
|
|
106
|
+
"glm/glm-5.3": {
|
|
107
|
+
"input": 1.4,
|
|
108
|
+
"output": 4.4
|
|
109
|
+
},
|
|
110
|
+
"glm/glm-5.3-flash": {
|
|
111
|
+
"input": 0.15,
|
|
112
|
+
"output": 0.5
|
|
113
|
+
},
|
|
114
|
+
"glm/glm-5.3-flashx": {
|
|
115
|
+
"input": 0.37,
|
|
116
|
+
"output": 1.25
|
|
117
|
+
},
|
|
106
118
|
"glm/glm-5.2": {
|
|
107
119
|
"input": 1.4,
|
|
108
120
|
"output": 4.4
|
|
@@ -164,8 +176,8 @@
|
|
|
164
176
|
"output": 0
|
|
165
177
|
},
|
|
166
178
|
"openrouter/deepseek/deepseek-v4-flash": {
|
|
167
|
-
"input": 0.
|
|
168
|
-
"output": 0.
|
|
179
|
+
"input": 0.08708,
|
|
180
|
+
"output": 0.17416
|
|
169
181
|
},
|
|
170
182
|
"openrouter/google/gemini-2.5-flash": {
|
|
171
183
|
"input": 0.3,
|
|
@@ -180,8 +192,8 @@
|
|
|
180
192
|
"output": 15
|
|
181
193
|
},
|
|
182
194
|
"openrouter/deepseek/deepseek-v4-pro": {
|
|
183
|
-
"input":
|
|
184
|
-
"output":
|
|
195
|
+
"input": 0.95526,
|
|
196
|
+
"output": 1.91052
|
|
185
197
|
},
|
|
186
198
|
"openrouter/qwen/qwen3.7-max": {
|
|
187
199
|
"input": 1.475,
|
|
@@ -204,12 +216,12 @@
|
|
|
204
216
|
"output": 1.125
|
|
205
217
|
},
|
|
206
218
|
"openrouter/qwen/qwen3.6-27b": {
|
|
207
|
-
"input": 0.
|
|
208
|
-
"output": 2
|
|
219
|
+
"input": 0.32,
|
|
220
|
+
"output": 2.7
|
|
209
221
|
},
|
|
210
222
|
"openrouter/qwen/qwen3.6-35b-a3b": {
|
|
211
|
-
"input": 0.
|
|
212
|
-
"output":
|
|
223
|
+
"input": 0.15,
|
|
224
|
+
"output": 1
|
|
213
225
|
},
|
|
214
226
|
"openrouter/qwen/qwen3-coder": {
|
|
215
227
|
"input": 0.3,
|
|
@@ -248,8 +260,8 @@
|
|
|
248
260
|
"output": 1.2
|
|
249
261
|
},
|
|
250
262
|
"openrouter/moonshotai/kimi-k2.7-code": {
|
|
251
|
-
"input": 0.
|
|
252
|
-
"output": 3.
|
|
263
|
+
"input": 0.7062,
|
|
264
|
+
"output": 3.3
|
|
253
265
|
},
|
|
254
266
|
"openrouter/moonshotai/kimi-k2.6": {
|
|
255
267
|
"input": 0.95,
|
|
@@ -264,12 +276,24 @@
|
|
|
264
276
|
"output": 2.5
|
|
265
277
|
},
|
|
266
278
|
"openrouter/moonshotai/kimi-k3": {
|
|
267
|
-
"input":
|
|
268
|
-
"output":
|
|
279
|
+
"input": 3,
|
|
280
|
+
"output": 15
|
|
281
|
+
},
|
|
282
|
+
"openrouter/z-ai/glm-5.3": {
|
|
283
|
+
"input": 0.5614,
|
|
284
|
+
"output": 1.7644
|
|
285
|
+
},
|
|
286
|
+
"openrouter/z-ai/glm-5.3-flash": {
|
|
287
|
+
"input": 0.15,
|
|
288
|
+
"output": 0.5
|
|
289
|
+
},
|
|
290
|
+
"openrouter/z-ai/glm-5.3-flashx": {
|
|
291
|
+
"input": 0.37,
|
|
292
|
+
"output": 1.25
|
|
269
293
|
},
|
|
270
294
|
"openrouter/z-ai/glm-5.2": {
|
|
271
|
-
"input": 0.
|
|
272
|
-
"output": 2
|
|
295
|
+
"input": 0.6496,
|
|
296
|
+
"output": 2.0416
|
|
273
297
|
},
|
|
274
298
|
"openrouter/z-ai/glm-5.1": {
|
|
275
299
|
"input": 0.966,
|
|
@@ -304,8 +328,8 @@
|
|
|
304
328
|
"output": 0.3
|
|
305
329
|
},
|
|
306
330
|
"openrouter/tencent/hy3": {
|
|
307
|
-
"input": 0.
|
|
308
|
-
"output": 0.
|
|
331
|
+
"input": 0.132,
|
|
332
|
+
"output": 0.528
|
|
309
333
|
},
|
|
310
334
|
"openrouter/tencent/hy3-preview": {
|
|
311
335
|
"input": 0.18,
|
|
@@ -344,8 +368,8 @@
|
|
|
344
368
|
"output": 1.9
|
|
345
369
|
},
|
|
346
370
|
"openrouter/meta-llama/llama-4-maverick": {
|
|
347
|
-
"input": 0.
|
|
348
|
-
"output": 0.
|
|
371
|
+
"input": 0.1875,
|
|
372
|
+
"output": 0.6525
|
|
349
373
|
},
|
|
350
374
|
"openrouter/meta-llama/llama-4-scout": {
|
|
351
375
|
"input": 0.1,
|
|
@@ -380,12 +404,12 @@
|
|
|
380
404
|
"output": 3.2
|
|
381
405
|
},
|
|
382
406
|
"openrouter/nvidia/nemotron-3-super-120b-a12b": {
|
|
383
|
-
"input": 0.
|
|
384
|
-
"output": 0.
|
|
407
|
+
"input": 0.08,
|
|
408
|
+
"output": 0.45
|
|
385
409
|
},
|
|
386
410
|
"openrouter/nvidia/nemotron-3-ultra-550b-a55b": {
|
|
387
|
-
"input": 0.
|
|
388
|
-
"output":
|
|
411
|
+
"input": 0.6,
|
|
412
|
+
"output": 2.4
|
|
389
413
|
},
|
|
390
414
|
"openrouter/nousresearch/hermes-4-405b": {
|
|
391
415
|
"input": 1,
|
|
@@ -486,5 +510,217 @@
|
|
|
486
510
|
"openrouter/deepseek/deepseek-v4-flash-vision-exp": {
|
|
487
511
|
"input": 0.22,
|
|
488
512
|
"output": 0.66
|
|
513
|
+
},
|
|
514
|
+
"openrouter/openai/gpt-5-image": {
|
|
515
|
+
"input": 10.0,
|
|
516
|
+
"output": 10.0
|
|
517
|
+
},
|
|
518
|
+
"openrouter/openai/gpt-5-image-mini": {
|
|
519
|
+
"input": 2.5,
|
|
520
|
+
"output": 2.0
|
|
521
|
+
},
|
|
522
|
+
"openrouter/openai/gpt-5-mini": {
|
|
523
|
+
"input": 0.25,
|
|
524
|
+
"output": 2.0
|
|
525
|
+
},
|
|
526
|
+
"openrouter/openai/gpt-5-nano": {
|
|
527
|
+
"input": 0.05,
|
|
528
|
+
"output": 0.4
|
|
529
|
+
},
|
|
530
|
+
"openrouter/openai/gpt-5-pro": {
|
|
531
|
+
"input": 15.0,
|
|
532
|
+
"output": 120.0
|
|
533
|
+
},
|
|
534
|
+
"openrouter/openai/gpt-5.2": {
|
|
535
|
+
"input": 1.75,
|
|
536
|
+
"output": 14.0
|
|
537
|
+
},
|
|
538
|
+
"openrouter/openai/gpt-5.2-chat": {
|
|
539
|
+
"input": 1.75,
|
|
540
|
+
"output": 14.0
|
|
541
|
+
},
|
|
542
|
+
"openrouter/openai/gpt-5.2-codex": {
|
|
543
|
+
"input": 1.75,
|
|
544
|
+
"output": 14.0
|
|
545
|
+
},
|
|
546
|
+
"openrouter/openai/gpt-5.2-pro": {
|
|
547
|
+
"input": 21.0,
|
|
548
|
+
"output": 168.0
|
|
549
|
+
},
|
|
550
|
+
"openrouter/openai/gpt-5.3-codex": {
|
|
551
|
+
"input": 1.75,
|
|
552
|
+
"output": 14.0
|
|
553
|
+
},
|
|
554
|
+
"openrouter/openai/gpt-5.4": {
|
|
555
|
+
"input": 2.5,
|
|
556
|
+
"output": 15.0
|
|
557
|
+
},
|
|
558
|
+
"openrouter/openai/gpt-5.4-image-2": {
|
|
559
|
+
"input": 8.0,
|
|
560
|
+
"output": 15.0
|
|
561
|
+
},
|
|
562
|
+
"openrouter/openai/gpt-5.4-nano": {
|
|
563
|
+
"input": 0.2,
|
|
564
|
+
"output": 1.25
|
|
565
|
+
},
|
|
566
|
+
"openrouter/openai/gpt-5.4-pro": {
|
|
567
|
+
"input": 30.0,
|
|
568
|
+
"output": 180.0
|
|
569
|
+
},
|
|
570
|
+
"openrouter/openai/gpt-5.5": {
|
|
571
|
+
"input": 5.0,
|
|
572
|
+
"output": 30.0
|
|
573
|
+
},
|
|
574
|
+
"openrouter/openai/gpt-5.5-pro": {
|
|
575
|
+
"input": 30.0,
|
|
576
|
+
"output": 180.0
|
|
577
|
+
},
|
|
578
|
+
"openrouter/openai/gpt-5.6-luna-pro": {
|
|
579
|
+
"input": 0.2,
|
|
580
|
+
"output": 1.2
|
|
581
|
+
},
|
|
582
|
+
"openrouter/openai/gpt-5.6-sol-pro": {
|
|
583
|
+
"input": 2.0,
|
|
584
|
+
"output": 10.0
|
|
585
|
+
},
|
|
586
|
+
"openrouter/openai/gpt-5.6-terra": {
|
|
587
|
+
"input": 2.0,
|
|
588
|
+
"output": 12.0
|
|
589
|
+
},
|
|
590
|
+
"openrouter/openai/gpt-5.6-terra-pro": {
|
|
591
|
+
"input": 2.0,
|
|
592
|
+
"output": 12.0
|
|
593
|
+
},
|
|
594
|
+
"openrouter/openai/gpt-6-astra": {
|
|
595
|
+
"input": 10.0,
|
|
596
|
+
"output": 50.0
|
|
597
|
+
},
|
|
598
|
+
"openrouter/openai/gpt-6-astra-pro": {
|
|
599
|
+
"input": 10.0,
|
|
600
|
+
"output": 50.0
|
|
601
|
+
},
|
|
602
|
+
"openrouter/openai/gpt-6-luna": {
|
|
603
|
+
"input": 0.1,
|
|
604
|
+
"output": 0.5
|
|
605
|
+
},
|
|
606
|
+
"openrouter/openai/gpt-6-luna-pro": {
|
|
607
|
+
"input": 0.1,
|
|
608
|
+
"output": 0.5
|
|
609
|
+
},
|
|
610
|
+
"openrouter/openai/gpt-6-sol": {
|
|
611
|
+
"input": 2.0,
|
|
612
|
+
"output": 10.0
|
|
613
|
+
},
|
|
614
|
+
"openrouter/openai/gpt-6-sol-pro": {
|
|
615
|
+
"input": 2.0,
|
|
616
|
+
"output": 10.0
|
|
617
|
+
},
|
|
618
|
+
"openrouter/anthropic/claude-fable-5.1": {
|
|
619
|
+
"input": 10.0,
|
|
620
|
+
"output": 50.0
|
|
621
|
+
},
|
|
622
|
+
"openrouter/anthropic/claude-opus-4.5": {
|
|
623
|
+
"input": 5.0,
|
|
624
|
+
"output": 25.0
|
|
625
|
+
},
|
|
626
|
+
"openrouter/anthropic/claude-opus-4.6": {
|
|
627
|
+
"input": 5.0,
|
|
628
|
+
"output": 25.0
|
|
629
|
+
},
|
|
630
|
+
"openrouter/anthropic/claude-opus-4.8": {
|
|
631
|
+
"input": 5.0,
|
|
632
|
+
"output": 25.0
|
|
633
|
+
},
|
|
634
|
+
"openrouter/anthropic/claude-opus-5.5": {
|
|
635
|
+
"input": 4.0,
|
|
636
|
+
"output": 20.0
|
|
637
|
+
},
|
|
638
|
+
"openrouter/google/gemini-3.5-flash": {
|
|
639
|
+
"input": 1.5,
|
|
640
|
+
"output": 9.0
|
|
641
|
+
},
|
|
642
|
+
"openrouter/google/gemini-3.5-flash-lite": {
|
|
643
|
+
"input": 0.3,
|
|
644
|
+
"output": 2.5
|
|
645
|
+
},
|
|
646
|
+
"openrouter/google/gemini-3.7-flash": {
|
|
647
|
+
"input": 0.75,
|
|
648
|
+
"output": 3.75
|
|
649
|
+
},
|
|
650
|
+
"openrouter/google/gemini-3.8-flash": {
|
|
651
|
+
"input": 0.75,
|
|
652
|
+
"output": 3.75
|
|
653
|
+
},
|
|
654
|
+
"openrouter/qwen/qwen3.5-122b-a10b": {
|
|
655
|
+
"input": 0.26,
|
|
656
|
+
"output": 2.08
|
|
657
|
+
},
|
|
658
|
+
"openrouter/qwen/qwen3.5-27b": {
|
|
659
|
+
"input": 0.195,
|
|
660
|
+
"output": 1.56
|
|
661
|
+
},
|
|
662
|
+
"openrouter/qwen/qwen3.5-35b-a3b": {
|
|
663
|
+
"input": 0.3125,
|
|
664
|
+
"output": 1.25
|
|
665
|
+
},
|
|
666
|
+
"openrouter/qwen/qwen3.5-397b-a17b": {
|
|
667
|
+
"input": 0.55,
|
|
668
|
+
"output": 3.5
|
|
669
|
+
},
|
|
670
|
+
"openrouter/qwen/qwen3.5-9b": {
|
|
671
|
+
"input": 0.1,
|
|
672
|
+
"output": 0.15
|
|
673
|
+
},
|
|
674
|
+
"openrouter/qwen/qwen3.5-flash-02-23": {
|
|
675
|
+
"input": 0.065,
|
|
676
|
+
"output": 0.26
|
|
677
|
+
},
|
|
678
|
+
"openrouter/qwen/qwen3.5-plus-02-15": {
|
|
679
|
+
"input": 0.26,
|
|
680
|
+
"output": 1.56
|
|
681
|
+
},
|
|
682
|
+
"openrouter/qwen/qwen3.5-plus-20260420": {
|
|
683
|
+
"input": 0.3,
|
|
684
|
+
"output": 1.8
|
|
685
|
+
},
|
|
686
|
+
"openrouter/qwen/qwen3.8-2.4t-a95b": {
|
|
687
|
+
"input": 2.0,
|
|
688
|
+
"output": 6.0
|
|
689
|
+
},
|
|
690
|
+
"openrouter/qwen/qwen3.8-27b": {
|
|
691
|
+
"input": 0.42,
|
|
692
|
+
"output": 3.0
|
|
693
|
+
},
|
|
694
|
+
"openrouter/qwen/qwen3.8-flash": {
|
|
695
|
+
"input": 0.15,
|
|
696
|
+
"output": 0.47
|
|
697
|
+
},
|
|
698
|
+
"openrouter/qwen/qwen3.8-max-0902": {
|
|
699
|
+
"input": 2.0,
|
|
700
|
+
"output": 6.0
|
|
701
|
+
},
|
|
702
|
+
"openrouter/qwen/qwen3.8-omni-flash": {
|
|
703
|
+
"input": 0.15,
|
|
704
|
+
"output": 0.47
|
|
705
|
+
},
|
|
706
|
+
"openrouter/deepseek/deepseek-v4-flash-0731": {
|
|
707
|
+
"input": 0.04,
|
|
708
|
+
"output": 0.64
|
|
709
|
+
},
|
|
710
|
+
"openrouter/deepseek/deepseek-v4-pro-0813": {
|
|
711
|
+
"input": 0.462,
|
|
712
|
+
"output": 1.386
|
|
713
|
+
},
|
|
714
|
+
"openrouter/moonshotai/kimi-k2.5": {
|
|
715
|
+
"input": 0.45,
|
|
716
|
+
"output": 2.25
|
|
717
|
+
},
|
|
718
|
+
"openrouter/x-ai/grok-4.6": {
|
|
719
|
+
"input": 2.0,
|
|
720
|
+
"output": 6.0
|
|
721
|
+
},
|
|
722
|
+
"openrouter/x-ai/grok-4.7": {
|
|
723
|
+
"input": 1.6,
|
|
724
|
+
"output": 4.8
|
|
489
725
|
}
|
|
490
726
|
}
|