@corsair-dev/studio 0.1.3 → 0.1.4

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.
@@ -349,6 +349,127 @@ import { z } from "zod";
349
349
  // src/server/chat-store.ts
350
350
  import Database from "better-sqlite3";
351
351
  import { Kysely, SqliteDialect } from "kysely";
352
+
353
+ // src/server/model-pricing.ts
354
+ var MODEL_PRICES = {
355
+ "gpt-4o": { input: 2.5, output: 10 },
356
+ "gpt-4o-2024-11-20": { input: 2.5, output: 10 },
357
+ "gpt-4o-2024-08-06": { input: 2.5, output: 10 },
358
+ "gpt-4o-mini": { input: 0.15, output: 0.6 },
359
+ "gpt-4-turbo": { input: 10, output: 30 },
360
+ "gpt-4": { input: 30, output: 60 },
361
+ "gpt-3.5-turbo": { input: 0.5, output: 1.5 },
362
+ "gpt-4.1": { input: 2, output: 8 },
363
+ "gpt-4.1-mini": { input: 0.4, output: 1.6 },
364
+ "gpt-4.1-nano": { input: 0.1, output: 0.4 },
365
+ "gpt-5": { input: 1.25, output: 10 },
366
+ "gpt-5-mini": { input: 0.25, output: 2 },
367
+ "gpt-5-nano": { input: 0.05, output: 0.4 },
368
+ o1: { input: 15, output: 60 },
369
+ "o1-mini": { input: 3, output: 12 },
370
+ "o1-preview": { input: 15, output: 60 },
371
+ "o3-mini": { input: 1.1, output: 4.4 },
372
+ o3: { input: 2, output: 8 },
373
+ "o4-mini": { input: 1.1, output: 4.4 },
374
+ "claude-opus-4-5": { input: 15, output: 75 },
375
+ "claude-opus-4-7": { input: 15, output: 75 },
376
+ "claude-opus-4-1": { input: 15, output: 75 },
377
+ "claude-sonnet-4-5": { input: 3, output: 15 },
378
+ "claude-sonnet-4-6": { input: 3, output: 15 },
379
+ "claude-sonnet-4": { input: 3, output: 15 },
380
+ "claude-haiku-4-5": { input: 1, output: 5 },
381
+ "claude-3-7-sonnet-latest": { input: 3, output: 15 },
382
+ "claude-3-5-sonnet-latest": { input: 3, output: 15 },
383
+ "claude-3-5-sonnet-20241022": { input: 3, output: 15 },
384
+ "claude-3-5-haiku-latest": { input: 0.8, output: 4 },
385
+ "claude-3-5-haiku-20241022": { input: 0.8, output: 4 },
386
+ "claude-3-opus-latest": { input: 15, output: 75 },
387
+ "claude-3-haiku-20240307": { input: 0.25, output: 1.25 },
388
+ "gemini-2.5-pro": { input: 1.25, output: 10 },
389
+ "gemini-2.5-flash": { input: 0.3, output: 2.5 },
390
+ "gemini-2.5-flash-lite": { input: 0.1, output: 0.4 },
391
+ "gemini-2.0-flash": { input: 0.1, output: 0.4 },
392
+ "gemini-2.0-flash-001": { input: 0.1, output: 0.4 },
393
+ "gemini-2.0-flash-lite": { input: 0.075, output: 0.3 },
394
+ "gemini-2.0-pro-exp": { input: 1.25, output: 5 },
395
+ "gemini-1.5-pro": { input: 1.25, output: 5 },
396
+ "gemini-1.5-pro-latest": { input: 1.25, output: 5 },
397
+ "gemini-1.5-flash": { input: 0.075, output: 0.3 },
398
+ "gemini-1.5-flash-latest": { input: 0.075, output: 0.3 },
399
+ "gemini-1.5-flash-8b": { input: 0.0375, output: 0.15 },
400
+ "llama-3.3-70b-versatile": { input: 0.59, output: 0.79 },
401
+ "llama-3.1-70b-versatile": { input: 0.59, output: 0.79 },
402
+ "llama-3.1-8b-instant": { input: 0.05, output: 0.08 },
403
+ "llama-3.2-1b-preview": { input: 0.04, output: 0.04 },
404
+ "llama-3.2-3b-preview": { input: 0.06, output: 0.06 },
405
+ "llama-3.2-11b-vision-preview": { input: 0.18, output: 0.18 },
406
+ "llama-3.2-90b-vision-preview": { input: 0.9, output: 0.9 },
407
+ "mixtral-8x7b-32768": { input: 0.24, output: 0.24 },
408
+ "gemma2-9b-it": { input: 0.2, output: 0.2 },
409
+ "deepseek-r1-distill-llama-70b": { input: 0.75, output: 0.99 },
410
+ "deepseek-chat": { input: 0.27, output: 1.1 },
411
+ "deepseek-reasoner": { input: 0.55, output: 2.19 },
412
+ "mistral-large-latest": { input: 2, output: 6 },
413
+ "mistral-small-latest": { input: 0.2, output: 0.6 },
414
+ "codestral-latest": { input: 0.3, output: 0.9 },
415
+ "grok-2": { input: 2, output: 10 },
416
+ "grok-2-mini": { input: 0.3, output: 0.5 },
417
+ "grok-3": { input: 3, output: 15 },
418
+ "grok-3-mini": { input: 0.3, output: 0.5 },
419
+ "grok-4": { input: 5, output: 25 }
420
+ };
421
+ function normalizeId(id) {
422
+ return id.toLowerCase().replace(/^models\//, "").replace(/^anthropic\//, "").replace(/^openai\//, "").replace(/^google\//, "").replace(/^groq\//, "").trim();
423
+ }
424
+ function candidateIds(modelId) {
425
+ const norm = normalizeId(modelId);
426
+ const variants = /* @__PURE__ */ new Set([modelId, norm]);
427
+ const stripDate = norm.replace(/-\d{8}$/, "").replace(/-\d{4}-\d{2}-\d{2}$/, "");
428
+ if (stripDate !== norm) variants.add(stripDate);
429
+ const stripVersion = norm.replace(/-(?:00\d|0?\d{2,3})$/, "");
430
+ if (stripVersion !== norm) variants.add(stripVersion);
431
+ const stripLatest = norm.replace(/-latest$/, "");
432
+ if (stripLatest !== norm) variants.add(stripLatest);
433
+ const stripPreview = norm.replace(/-preview$/, "").replace(/-exp$/, "");
434
+ if (stripPreview !== norm) variants.add(stripPreview);
435
+ return Array.from(variants);
436
+ }
437
+ var PRICES_NORMALIZED = (() => {
438
+ const map = {};
439
+ for (const [k, v] of Object.entries(MODEL_PRICES)) {
440
+ map[normalizeId(k)] = v;
441
+ }
442
+ return map;
443
+ })();
444
+ function getModelPrice(modelId) {
445
+ if (MODEL_PRICES[modelId]) return MODEL_PRICES[modelId];
446
+ for (const candidate of candidateIds(modelId)) {
447
+ const direct = PRICES_NORMALIZED[candidate];
448
+ if (direct) return direct;
449
+ }
450
+ const norm = normalizeId(modelId);
451
+ let bestMatch = null;
452
+ for (const [key, price] of Object.entries(PRICES_NORMALIZED)) {
453
+ if (norm.startsWith(key) || key.startsWith(norm)) {
454
+ if (!bestMatch || key.length > bestMatch.key.length) {
455
+ bestMatch = { key, price };
456
+ }
457
+ }
458
+ }
459
+ return bestMatch?.price ?? null;
460
+ }
461
+ function computeCost(modelId, usage) {
462
+ const price = getModelPrice(modelId);
463
+ if (!price) {
464
+ console.warn(`[corsair:pricing] no price entry for model "${modelId}"`);
465
+ return null;
466
+ }
467
+ const input = usage.inputTokens / 1e6 * price.input;
468
+ const output = usage.outputTokens / 1e6 * price.output;
469
+ return input + output;
470
+ }
471
+
472
+ // src/server/chat-store.ts
352
473
  var sqlite = new Database(":memory:");
353
474
  var db = new Kysely({
354
475
  dialect: new SqliteDialect({ database: sqlite })
@@ -356,7 +477,7 @@ var db = new Kysely({
356
477
  var schemaReady = initSchema();
357
478
  async function initSchema() {
358
479
  await db.schema.createTable("chats").ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("title", "text", (col) => col.notNull()).addColumn("created_at", "integer", (col) => col.notNull()).execute();
359
- await db.schema.createTable("chat_messages").ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("chat_id", "text", (col) => col.notNull()).addColumn("role", "text", (col) => col.notNull()).addColumn("blocks", "text", (col) => col.notNull()).addColumn("error", "text").addColumn("seq", "integer", (col) => col.notNull()).execute();
480
+ await db.schema.createTable("chat_messages").ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("chat_id", "text", (col) => col.notNull()).addColumn("role", "text", (col) => col.notNull()).addColumn("blocks", "text", (col) => col.notNull()).addColumn("error", "text").addColumn("seq", "integer", (col) => col.notNull()).addColumn("usage", "text").execute();
360
481
  }
361
482
  var _seq = 0;
362
483
  function getTextFromBlocks(blocks) {
@@ -364,19 +485,81 @@ function getTextFromBlocks(blocks) {
364
485
  (block) => block.type === "text"
365
486
  ).map((block) => block.content).join("");
366
487
  }
488
+ function parseRawUsage(raw) {
489
+ if (!raw) return null;
490
+ try {
491
+ const parsed = JSON.parse(raw);
492
+ if (typeof parsed.model !== "string" || typeof parsed.inputTokens !== "number" || typeof parsed.outputTokens !== "number" || typeof parsed.totalTokens !== "number") {
493
+ return null;
494
+ }
495
+ return {
496
+ model: parsed.model,
497
+ inputTokens: parsed.inputTokens,
498
+ outputTokens: parsed.outputTokens,
499
+ totalTokens: parsed.totalTokens
500
+ };
501
+ } catch {
502
+ return null;
503
+ }
504
+ }
505
+ function withCost(raw) {
506
+ return {
507
+ ...raw,
508
+ cost: computeCost(raw.model, raw)
509
+ };
510
+ }
511
+ function aggregateUsage(rows) {
512
+ const total = {
513
+ inputTokens: 0,
514
+ outputTokens: 0,
515
+ totalTokens: 0,
516
+ cost: 0,
517
+ hasUnknownCost: false
518
+ };
519
+ for (const u of rows) {
520
+ if (!u) continue;
521
+ total.inputTokens += u.inputTokens;
522
+ total.outputTokens += u.outputTokens;
523
+ total.totalTokens += u.totalTokens;
524
+ if (u.cost === null) {
525
+ total.hasUnknownCost = true;
526
+ } else {
527
+ total.cost += u.cost;
528
+ }
529
+ }
530
+ return total;
531
+ }
367
532
  async function createChat() {
368
533
  await schemaReady;
369
- const chat = {
370
- id: crypto.randomUUID(),
371
- title: "New chat",
372
- created_at: Date.now()
534
+ const id = crypto.randomUUID();
535
+ const created_at = Date.now();
536
+ const title = "New chat";
537
+ await db.insertInto("chats").values({ id, title, created_at }).execute();
538
+ return {
539
+ id,
540
+ title,
541
+ created_at,
542
+ usage_total: aggregateUsage([])
373
543
  };
374
- await db.insertInto("chats").values(chat).execute();
375
- return chat;
376
544
  }
377
545
  async function listChats() {
378
546
  await schemaReady;
379
- return db.selectFrom("chats").select(["id", "title", "created_at"]).orderBy("created_at", "desc").execute();
547
+ const chats = await db.selectFrom("chats").select(["id", "title", "created_at"]).orderBy("created_at", "desc").execute();
548
+ const messageRows = await db.selectFrom("chat_messages").select(["chat_id", "usage"]).execute();
549
+ const usageByChat = /* @__PURE__ */ new Map();
550
+ for (const row of messageRows) {
551
+ const raw = parseRawUsage(row.usage);
552
+ if (!raw) continue;
553
+ const list = usageByChat.get(row.chat_id) ?? [];
554
+ list.push(withCost(raw));
555
+ usageByChat.set(row.chat_id, list);
556
+ }
557
+ return chats.map((chat) => ({
558
+ id: chat.id,
559
+ title: chat.title,
560
+ created_at: chat.created_at,
561
+ usage_total: aggregateUsage(usageByChat.get(chat.id) ?? [])
562
+ }));
380
563
  }
381
564
  async function chatExists(chatId) {
382
565
  await schemaReady;
@@ -385,24 +568,29 @@ async function chatExists(chatId) {
385
568
  }
386
569
  async function getMessages(chatId) {
387
570
  await schemaReady;
388
- const rows = await db.selectFrom("chat_messages").select(["id", "chat_id", "role", "blocks", "error"]).where("chat_id", "=", chatId).orderBy("seq", "asc").execute();
389
- return rows.map((row) => ({
390
- id: row.id,
391
- chat_id: row.chat_id,
392
- role: row.role,
393
- blocks: JSON.parse(row.blocks),
394
- error: row.error
395
- }));
571
+ const rows = await db.selectFrom("chat_messages").select(["id", "chat_id", "role", "blocks", "error", "usage"]).where("chat_id", "=", chatId).orderBy("seq", "asc").execute();
572
+ return rows.map((row) => {
573
+ const raw = parseRawUsage(row.usage);
574
+ return {
575
+ id: row.id,
576
+ chat_id: row.chat_id,
577
+ role: row.role,
578
+ blocks: JSON.parse(row.blocks),
579
+ error: row.error,
580
+ usage: raw ? withCost(raw) : null
581
+ };
582
+ });
396
583
  }
397
- async function appendMessage(chatId, id, role, blocks, error) {
584
+ async function appendMessage(chatId, id, role, blocks, options = {}) {
398
585
  await schemaReady;
399
586
  await db.insertInto("chat_messages").values({
400
587
  id,
401
588
  chat_id: chatId,
402
589
  role,
403
590
  blocks: JSON.stringify(blocks),
404
- error: error ?? null,
405
- seq: ++_seq
591
+ error: options.error ?? null,
592
+ seq: ++_seq,
593
+ usage: options.usage ? JSON.stringify(options.usage) : null
406
594
  }).execute();
407
595
  if (role === "user") {
408
596
  const row = await db.selectFrom("chats").select("title").where("id", "=", chatId).executeTakeFirst();
@@ -518,35 +706,36 @@ function buildAiTools(corsairClient) {
518
706
  return tools;
519
707
  }
520
708
  async function resolveModel() {
521
- const model = process.env.CORSAIR_CHAT_MODEL;
709
+ const override = process.env.CORSAIR_CHAT_MODEL;
522
710
  console.log(
523
711
  "[corsair:chat] resolving model \u2014 OPENAI_API_KEY:",
524
712
  !!process.env.OPENAI_API_KEY,
525
713
  "| ANTHROPIC_API_KEY:",
526
714
  !!process.env.ANTHROPIC_API_KEY,
527
715
  "| CORSAIR_CHAT_MODEL:",
528
- model ?? "(default)"
716
+ override ?? "(default)"
529
717
  );
530
718
  if (process.env.OPENAI_API_KEY) {
531
719
  const { openai } = await import("@ai-sdk/openai");
532
- console.log("[corsair:chat] using openai:", model ?? "gpt-4o-mini");
533
- return openai(model ?? "gpt-4o-mini");
720
+ const modelId = override ?? "gpt-4o-mini";
721
+ console.log("[corsair:chat] using openai:", modelId);
722
+ return { model: openai(modelId), modelId };
534
723
  }
535
724
  if (process.env.ANTHROPIC_API_KEY) {
536
725
  const { anthropic } = await import("@ai-sdk/anthropic");
537
- console.log(
538
- "[corsair:chat] using anthropic:",
539
- model ?? "claude-sonnet-4-6"
540
- );
541
- return anthropic(model ?? "claude-sonnet-4-6");
726
+ const modelId = override ?? "claude-sonnet-4-6";
727
+ console.log("[corsair:chat] using anthropic:", modelId);
728
+ return { model: anthropic(modelId), modelId };
542
729
  }
543
730
  if (process.env.GOOGLE_GENERATIVE_AI_API_KEY) {
544
731
  const { google } = await import("@ai-sdk/google");
545
- return google(model ?? "gemini-2.0-flash");
732
+ const modelId = override ?? "gemini-2.0-flash";
733
+ return { model: google(modelId), modelId };
546
734
  }
547
735
  if (process.env.GROQ_API_KEY) {
548
736
  const { createGroq } = await import("@ai-sdk/groq");
549
- return createGroq()(model ?? "llama-3.3-70b-versatile");
737
+ const modelId = override ?? "llama-3.3-70b-versatile";
738
+ return { model: createGroq()(modelId), modelId };
550
739
  }
551
740
  throw new Error(
552
741
  "No AI provider configured. Set one of: OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, or GROQ_API_KEY."
@@ -558,20 +747,44 @@ function errorMessage(err) {
558
747
  function isObject(value) {
559
748
  return typeof value === "object" && value !== null;
560
749
  }
750
+ function parseRawUsage2(raw) {
751
+ if (!isObject(raw)) return void 0;
752
+ const usage = {};
753
+ if (typeof raw.promptTokens === "number")
754
+ usage.promptTokens = raw.promptTokens;
755
+ if (typeof raw.completionTokens === "number")
756
+ usage.completionTokens = raw.completionTokens;
757
+ if (typeof raw.totalTokens === "number") usage.totalTokens = raw.totalTokens;
758
+ return usage;
759
+ }
561
760
  function parseStreamPart(raw) {
562
761
  if (!isObject(raw) || typeof raw.type !== "string") {
563
762
  return null;
564
763
  }
565
764
  const textDelta = typeof raw.textDelta === "string" ? raw.textDelta : void 0;
566
765
  const toolName = typeof raw.toolName === "string" ? raw.toolName : void 0;
766
+ let responseModelId;
767
+ if (isObject(raw.response) && typeof raw.response.modelId === "string") {
768
+ responseModelId = raw.response.modelId;
769
+ }
567
770
  return {
568
771
  type: raw.type,
569
772
  textDelta,
570
773
  toolName,
571
774
  args: raw.args,
572
- result: raw.result
775
+ result: raw.result,
776
+ usage: parseRawUsage2(raw.usage),
777
+ responseModelId
573
778
  };
574
779
  }
780
+ function buildRawMessageUsage(modelId, raw) {
781
+ if (!raw) return null;
782
+ const inputTokens = raw.promptTokens ?? 0;
783
+ const outputTokens = raw.completionTokens ?? 0;
784
+ const totalTokens = raw.totalTokens ?? inputTokens + outputTokens;
785
+ if (inputTokens === 0 && outputTokens === 0 && totalTokens === 0) return null;
786
+ return { model: modelId, inputTokens, outputTokens, totalTokens };
787
+ }
575
788
  var chatHandler = async (ctx) => {
576
789
  console.log("[corsair:chat] request received");
577
790
  const body = await readJsonBody(ctx.req);
@@ -593,9 +806,9 @@ var chatHandler = async (ctx) => {
593
806
  "| chatId:",
594
807
  chatId ?? "(none)"
595
808
  );
596
- let model;
809
+ let resolved;
597
810
  try {
598
- model = await resolveModel();
811
+ resolved = await resolveModel();
599
812
  } catch (err) {
600
813
  const message = errorMessage(err);
601
814
  console.error("[corsair:chat] model resolution failed:", message);
@@ -627,10 +840,11 @@ var chatHandler = async (ctx) => {
627
840
  `);
628
841
  };
629
842
  const assistantBlocks = [];
843
+ let finalRawUsage = null;
630
844
  console.log("[corsair:chat] starting stream");
631
845
  try {
632
846
  const result = streamText({
633
- model,
847
+ model: resolved.model,
634
848
  system: "You are a helpful assistant with access to Corsair tools. Use the tools to answer questions about the user's integrations and data. Use list_operations to get the exact endpoint names.",
635
849
  messages,
636
850
  tools,
@@ -664,6 +878,18 @@ var chatHandler = async (ctx) => {
664
878
  block.result = part.result;
665
879
  }
666
880
  } else if (part.type === "finish") {
881
+ const effectiveModelId = part.responseModelId ?? resolved.modelId;
882
+ const raw2 = buildRawMessageUsage(effectiveModelId, part.usage);
883
+ console.log(
884
+ "[corsair:chat] finish \u2014 model:",
885
+ effectiveModelId,
886
+ "| usage:",
887
+ part.usage
888
+ );
889
+ if (raw2) {
890
+ finalRawUsage = raw2;
891
+ send({ type: "usage", usage: withCost(raw2) });
892
+ }
667
893
  send({ type: "done" });
668
894
  }
669
895
  }
@@ -678,7 +904,8 @@ var chatHandler = async (ctx) => {
678
904
  chatId,
679
905
  crypto.randomUUID(),
680
906
  "assistant",
681
- assistantBlocks
907
+ assistantBlocks,
908
+ { usage: finalRawUsage ?? void 0 }
682
909
  );
683
910
  } catch (err) {
684
911
  console.error("[corsair:chat] failed to save assistant message:", err);
@@ -1430,7 +1657,11 @@ var routes = [
1430
1657
  { method: "GET", path: "/api/db/permissions", handler: listPermissions },
1431
1658
  { method: "GET", path: "/api/chats", handler: listChatsHandler },
1432
1659
  { method: "POST", path: "/api/chats", handler: createChatHandler },
1433
- { method: "GET", path: "/api/chats/messages", handler: getChatMessagesHandler },
1660
+ {
1661
+ method: "GET",
1662
+ path: "/api/chats/messages",
1663
+ handler: getChatMessagesHandler
1664
+ },
1434
1665
  { method: "POST", path: "/api/chat", handler: chatHandler }
1435
1666
  ];
1436
1667
  async function handleApi(req, res, baseCtx) {
@@ -2,6 +2,7 @@ export type StoredChat = {
2
2
  id: string;
3
3
  title: string;
4
4
  created_at: number;
5
+ usage_total: ChatUsageTotal;
5
6
  };
6
7
  export type StoredMsgBlock = {
7
8
  type: 'text';
@@ -12,26 +13,38 @@ export type StoredMsgBlock = {
12
13
  args: unknown;
13
14
  result?: unknown;
14
15
  };
16
+ export type RawMessageUsage = {
17
+ model: string;
18
+ inputTokens: number;
19
+ outputTokens: number;
20
+ totalTokens: number;
21
+ };
22
+ export type MessageUsage = RawMessageUsage & {
23
+ cost: number | null;
24
+ };
25
+ export type ChatUsageTotal = {
26
+ inputTokens: number;
27
+ outputTokens: number;
28
+ totalTokens: number;
29
+ cost: number;
30
+ hasUnknownCost: boolean;
31
+ };
15
32
  export type StoredMessage = {
16
33
  id: string;
17
34
  chat_id: string;
18
35
  role: 'user' | 'assistant';
19
36
  blocks: StoredMsgBlock[];
20
37
  error: string | null;
38
+ usage: MessageUsage | null;
21
39
  };
40
+ export declare function withCost(raw: RawMessageUsage): MessageUsage;
41
+ export declare function aggregateUsage(rows: (MessageUsage | null)[]): ChatUsageTotal;
22
42
  export declare function createChat(): Promise<StoredChat>;
23
- export declare function listChats(): Promise<{
24
- id: string;
25
- title: string;
26
- created_at: number;
27
- }[]>;
43
+ export declare function listChats(): Promise<StoredChat[]>;
28
44
  export declare function chatExists(chatId: string): Promise<boolean>;
29
- export declare function getMessages(chatId: string): Promise<{
30
- id: string;
31
- chat_id: string;
32
- role: "user" | "assistant";
33
- blocks: StoredMsgBlock[];
34
- error: string | null;
35
- }[]>;
36
- export declare function appendMessage(chatId: string, id: string, role: 'user' | 'assistant', blocks: StoredMsgBlock[], error?: string): Promise<void>;
45
+ export declare function getMessages(chatId: string): Promise<StoredMessage[]>;
46
+ export declare function appendMessage(chatId: string, id: string, role: 'user' | 'assistant', blocks: StoredMsgBlock[], options?: {
47
+ error?: string;
48
+ usage?: RawMessageUsage;
49
+ }): Promise<void>;
37
50
  //# sourceMappingURL=chat-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-store.d.ts","sourceRoot":"","sources":["../../../src/server/chat-store.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,cAAc,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnE,MAAM,MAAM,aAAa,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CAAC;AA4DF,wBAAsB,UAAU,wBAW/B;AAED,wBAAsB,SAAS;;;;KAQ9B;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,oBAS9C;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM;;;;YAcZ,cAAc,EAAE;;KAGnD;AAED,wBAAsB,aAAa,CAClC,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,GAAG,WAAW,EAC1B,MAAM,EAAE,cAAc,EAAE,EACxB,KAAK,CAAC,EAAE,MAAM,iBAmCd"}
1
+ {"version":3,"file":"chat-store.d.ts","sourceRoot":"","sources":["../../../src/server/chat-store.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,UAAU,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,cAAc,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,cAAc,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnE,MAAM,MAAM,eAAe,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,eAAe,GAAG;IAC5C,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;CAC3B,CAAC;AAsFF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,YAAY,CAK3D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,CAAC,YAAY,GAAG,IAAI,CAAC,EAAE,GAAG,cAAc,CAoB5E;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CActD;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CA6BvD;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,oBAS9C;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAqB1E;AAED,wBAAsB,aAAa,CAClC,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,GAAG,WAAW,EAC1B,MAAM,EAAE,cAAc,EAAE,EACxB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,eAAe,CAAA;CAAO,iBAoCzD"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../../src/server/handlers/chat.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AA6N7C,eAAO,MAAM,WAAW,EAAE,SAgIzB,CAAC"}
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../../src/server/handlers/chat.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAuQ7C,eAAO,MAAM,WAAW,EAAE,SA6IzB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"chats.d.ts","sourceRoot":"","sources":["../../../../src/server/handlers/chats.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,eAAO,MAAM,gBAAgB,EAAE,SAE9B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,SAE/B,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,SAIpC,CAAC"}
1
+ {"version":3,"file":"chats.d.ts","sourceRoot":"","sources":["../../../../src/server/handlers/chats.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,eAAO,MAAM,gBAAgB,EAAE,SAE9B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,SAE/B,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,SAIpC,CAAC"}
@@ -0,0 +1,13 @@
1
+ export type ModelPrice = {
2
+ input: number;
3
+ output: number;
4
+ };
5
+ export declare const MODEL_PRICES: Record<string, ModelPrice>;
6
+ export declare function getModelPrice(modelId: string): ModelPrice | null;
7
+ export type TokenUsage = {
8
+ inputTokens: number;
9
+ outputTokens: number;
10
+ totalTokens: number;
11
+ };
12
+ export declare function computeCost(modelId: string, usage: TokenUsage): number | null;
13
+ //# sourceMappingURL=model-pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-pricing.d.ts","sourceRoot":"","sources":["../../../src/server/model-pricing.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf,CAAC;AAMF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAsEnD,CAAC;AA0CF,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAkBhE;AAED,MAAM,MAAM,UAAU,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAS7E"}
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/server/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAyBjE,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,SAAS,CAAC;AA0CrD,wBAAsB,SAAS,CAC9B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC,GAC9C,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED,wBAAsB,YAAY,CACjC,GAAG,EAAE,eAAe,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAoBlC"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/server/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAyBjE,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,SAAS,CAAC;AA8CrD,wBAAsB,SAAS,CAC9B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC,GAC9C,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED,wBAAsB,YAAY,CACjC,GAAG,EAAE,eAAe,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAoBlC"}