opencode-usage-insights 0.1.0 → 0.1.1

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/dist/index.js CHANGED
@@ -70,13 +70,9 @@ var TOKEN = /^[A-Za-z0-9][A-Za-z0-9._:/-]*$/;
70
70
  function isToken(value, limit = 64) {
71
71
  return value.length > 0 && value.length <= limit && TOKEN.test(value);
72
72
  }
73
- function normalizeToken(value, limit = 64) {
74
- const trimmed = value.trim().toLowerCase();
75
- return isToken(trimmed, limit) ? trimmed : undefined;
76
- }
77
73
 
78
74
  // src/stats/db.ts
79
- var SCHEMA_VERSION = 8;
75
+ var SCHEMA_VERSION = 9;
80
76
  var LABEL_LIMIT = 4 * TEXT_LIMIT;
81
77
  var SCHEMA = `
82
78
  CREATE TABLE IF NOT EXISTS meta (
@@ -118,13 +114,11 @@ CREATE TABLE IF NOT EXISTS steps (
118
114
  streamed_at INTEGER,
119
115
  completed_at INTEGER,
120
116
  finish TEXT,
121
- router TEXT,
122
117
  recorded_at INTEGER NOT NULL
123
118
  );
124
119
  CREATE INDEX IF NOT EXISTS steps_session ON steps(session_id, created_at);
125
120
  CREATE INDEX IF NOT EXISTS steps_model ON steps(provider_id, model_id, variant);
126
121
  CREATE INDEX IF NOT EXISTS steps_completed ON steps(completed_at);
127
- CREATE INDEX IF NOT EXISTS steps_router ON steps(router);
128
122
  -- Every range filter and every ordering compares the step's own clock, which
129
123
  -- falls back to the recording time for a step that was already in flight when
130
124
  -- the plugin loaded. The index has to cover that expression, or every ranged
@@ -155,10 +149,7 @@ function jsonText(value) {
155
149
  return null;
156
150
  }
157
151
  }
158
- var MIGRATIONS = [
159
- ["router", "ALTER TABLE steps ADD COLUMN router TEXT"]
160
- ];
161
- var REMOVED_COLUMNS = ["provider_state", "upstream", "upstream_source", "upstream_model", "tps"];
152
+ var REMOVED_COLUMNS = ["provider_state", "upstream", "upstream_source", "upstream_model", "tps", "router"];
162
153
  var REMOVED_EVENT_KINDS = ["execution", "step-failed", "model-selected", "usage-recorded"];
163
154
  function dropUnused(db) {
164
155
  const objects = db.query("SELECT name, type FROM sqlite_master WHERE type IN ('table', 'index')").all();
@@ -168,6 +159,8 @@ function dropUnused(db) {
168
159
  db.exec("DROP TABLE http_responses");
169
160
  if (indexes.has("steps_upstream"))
170
161
  db.exec("DROP INDEX steps_upstream");
162
+ if (indexes.has("steps_router"))
163
+ db.exec("DROP INDEX steps_router");
171
164
  const columns = new Set(db.query("PRAGMA table_info(steps)").all().map((column) => column.name));
172
165
  for (const name of REMOVED_COLUMNS) {
173
166
  if (columns.has(name))
@@ -177,30 +170,9 @@ function dropUnused(db) {
177
170
  const kinds = REMOVED_EVENT_KINDS.map((kind) => `'${kind}'`).join(", ");
178
171
  db.exec(`DELETE FROM events WHERE kind IN (${kinds})`);
179
172
  }
180
- db.exec("UPDATE steps SET router = NULL WHERE router IN ('opencode', 'openrouter', 'vercel-ai-gateway')");
181
- }
182
- function schemaVersion(db) {
183
- const row = db.query("SELECT value FROM meta WHERE key = 'schema_version'").get();
184
- const parsed = row === null ? Number.NaN : Number.parseInt(row.value, 10);
185
- return Number.isFinite(parsed) ? parsed : 0;
186
- }
187
- function normalizeRouters(db) {
188
- db.exec("UPDATE steps SET router = lower(router) WHERE router IS NOT NULL AND router <> lower(router)");
189
173
  }
190
174
  function migrate(db) {
191
- const version = schemaVersion(db);
192
- const steps = db.query("PRAGMA table_info(steps)").all();
193
- const existing = new Set(steps.map((column) => column.name));
194
- for (const [name, statement, backfill] of MIGRATIONS) {
195
- if (existing.has(name))
196
- continue;
197
- db.exec(statement);
198
- if (backfill !== undefined)
199
- db.exec(backfill);
200
- }
201
175
  dropUnused(db);
202
- if (version < 7)
203
- normalizeRouters(db);
204
176
  }
205
177
  var POSIX = process.platform !== "win32";
206
178
  function hardenDirectory(path) {
@@ -264,11 +236,11 @@ function recordStep(db, record) {
264
236
  db.query(`INSERT INTO steps (
265
237
  message_id, session_id, parent_id, provider_id, model_id, variant,
266
238
  input_tokens, output_tokens, reasoning_tokens, cache_read, cache_write, cost,
267
- created_at, streamed_at, completed_at, finish, router, recorded_at
239
+ created_at, streamed_at, completed_at, finish, recorded_at
268
240
  ) VALUES (
269
241
  $messageID, $sessionID, $parentID, $providerID, $modelID, $variant,
270
242
  $input, $output, $reasoning, $cacheRead, $cacheWrite, $cost,
271
- $createdAt, $streamedAt, $completedAt, $finish, $router, $recordedAt
243
+ $createdAt, $streamedAt, $completedAt, $finish, $recordedAt
272
244
  )
273
245
  ON CONFLICT(message_id) DO UPDATE SET
274
246
  session_id = excluded.session_id,
@@ -286,12 +258,11 @@ function recordStep(db, record) {
286
258
  streamed_at = COALESCE(excluded.streamed_at, steps.streamed_at),
287
259
  completed_at = COALESCE(excluded.completed_at, steps.completed_at),
288
260
  finish = COALESCE(excluded.finish, steps.finish),
289
- router = COALESCE(excluded.router, steps.router),
290
261
  recorded_at = excluded.recorded_at`).run({
291
262
  $messageID: record.messageID,
292
263
  $sessionID: record.sessionID,
293
264
  $parentID: record.parentID ?? null,
294
- $providerID: record.providerID ?? null,
265
+ $providerID: record.providerID !== undefined && isToken(record.providerID) ? record.providerID : null,
295
266
  $modelID: record.modelID ?? null,
296
267
  $variant: record.variant ?? null,
297
268
  $input: record.input ?? 0,
@@ -304,7 +275,6 @@ function recordStep(db, record) {
304
275
  $streamedAt: record.streamedAt ?? null,
305
276
  $completedAt: record.completedAt ?? null,
306
277
  $finish: record.finish === undefined ? null : sanitizeLabel(record.finish, 64),
307
- $router: record.router === undefined ? null : normalizeToken(record.router) ?? null,
308
278
  $recordedAt: record.recordedAt ?? Date.now()
309
279
  });
310
280
  }
@@ -344,15 +314,6 @@ function upsertSession(db, record) {
344
314
  $updatedAt: record.updatedAt ?? null
345
315
  });
346
316
  }
347
- function setStepRouterForSessionModel(db, sessionID, modelID, info) {
348
- const router = info.router === undefined ? undefined : normalizeToken(info.router);
349
- if (router === undefined)
350
- return 0;
351
- const result = db.query(`UPDATE steps
352
- SET router = $router
353
- WHERE session_id = $sessionID AND router IS NULL AND ($modelID IS NULL OR model_id = $modelID)`).run({ $router: router, $sessionID: sessionID, $modelID: modelID ?? null });
354
- return result.changes;
355
- }
356
317
 
357
318
  // src/core.ts
358
319
  var PROMPT_BOUNDARIES = new Set(["user", "synthetic", "system"]);
@@ -401,7 +362,7 @@ function totalize(steps) {
401
362
  }
402
363
  return totals;
403
364
  }
404
- function affinityKey(model) {
365
+ function identityKey(model) {
405
366
  if (!model)
406
367
  return;
407
368
  return `${model.providerID}/${model.id}${model.variant ? `#${model.variant}` : ""}`;
@@ -418,14 +379,16 @@ function stepEnd(message) {
418
379
  return;
419
380
  return time.completed ?? time.streamed ?? time.created;
420
381
  }
421
- function cacheDrop(reference, current) {
382
+ function cacheDrop(reference, current, scope = "provider") {
422
383
  if (!reference)
423
384
  return;
424
385
  const before = reference.model;
425
386
  const after = current.model;
426
387
  if (!before || !after)
427
388
  return;
428
- if (before.providerID !== after.providerID || before.id !== after.id || (before.variant ?? "") !== (after.variant ?? "")) {
389
+ if (scope === "provider" && before.providerID !== after.providerID)
390
+ return;
391
+ if (before.id !== after.id || (before.variant ?? "") !== (after.variant ?? "")) {
429
392
  return;
430
393
  }
431
394
  const drop = cacheRead(reference) - cacheRead(current);
@@ -482,8 +445,8 @@ function computeTurn(messages, session) {
482
445
  }
483
446
  const provider = lastStep.model?.providerID;
484
447
  const previousProvider = previousStep?.model?.providerID;
485
- const key = affinityKey(lastStep.model);
486
- const previousKey = affinityKey(previousStep?.model);
448
+ const key = identityKey(lastStep.model);
449
+ const previousKey = identityKey(previousStep?.model);
487
450
  return {
488
451
  endAt: stepEnd(lastStep),
489
452
  startAt: stepCreated(settled[0] ?? lastStep),
@@ -492,9 +455,6 @@ function computeTurn(messages, session) {
492
455
  providerID: provider,
493
456
  modelID: lastStep.model?.id,
494
457
  variant: lastStep.model?.variant,
495
- router: undefined,
496
- identityChanged: false,
497
- affinityKey: key,
498
458
  providerChanged: previousProvider !== undefined && provider !== undefined && previousProvider !== provider,
499
459
  modelChanged: previousKey !== undefined && key !== undefined && previousKey !== key && previousProvider === provider,
500
460
  totals: totalize(settled),
@@ -503,8 +463,7 @@ function computeTurn(messages, session) {
503
463
  drops,
504
464
  cacheDropTokens: drops.reduce((sum, drop) => sum + drop.tokens, 0),
505
465
  cacheExpired: drops.length > 0,
506
- steps: settled.length,
507
- stepIDs: settled.map((step) => step.id)
466
+ steps: settled.length
508
467
  };
509
468
  }
510
469
  function promptGap(current, previous) {
@@ -542,7 +501,7 @@ var DEFAULT_FIELDS = {
542
501
  turn: true,
543
502
  session: true,
544
503
  reasoning: false,
545
- cost: false,
504
+ cost: true,
546
505
  cacheExpiry: true
547
506
  };
548
507
  function formatClock(ms) {
@@ -601,7 +560,7 @@ function displayTotals(totals) {
601
560
  prompt
602
561
  };
603
562
  }
604
- function totalsText(prefix, totals, labels, fields, stepCount = 0) {
563
+ function totalsText(prefix, totals, labels, fields, stepCount = 0, cost = totals.cost) {
605
564
  const display = displayTotals(totals);
606
565
  const input = display.prompt === display.input ? `${labels.input} ${formatTokens(display.input)}` : `${labels.input} ${formatTokens(display.input)} (${formatTokens(display.prompt)})`;
607
566
  const parts = [
@@ -611,8 +570,8 @@ function totalsText(prefix, totals, labels, fields, stepCount = 0) {
611
570
  ];
612
571
  if (fields.reasoning)
613
572
  parts.push(`${labels.reasoning} ${formatTokens(display.reasoning)}`);
614
- if (fields.cost)
615
- parts.push(`${labels.cost} ${formatCost(display.cost)}`);
573
+ if (fields.cost && cost > 0)
574
+ parts.push(`${labels.cost} ${formatCost(cost)}`);
616
575
  const steps = stepCount > 1 ? `${stepCount} ${stepCount === 1 ? labels.step : labels.steps}` : "";
617
576
  const head = [prefix, steps].filter((piece) => piece !== "").join(" ");
618
577
  const numbers = parts.join(", ");
@@ -624,7 +583,6 @@ function formatLineSegments(stats, options) {
624
583
  const labels = { ...DEFAULT_LABELS, ...options?.labels };
625
584
  const fields = { ...DEFAULT_FIELDS, ...options?.fields };
626
585
  const turnTotals = options?.turnTotals ?? "latest";
627
- const identity = options?.identity ?? "endpoint";
628
586
  const segments = [];
629
587
  if (fields.clock && stats.endAt !== undefined) {
630
588
  segments.push({ text: formatClock(stats.endAt), tone: "muted" });
@@ -632,11 +590,7 @@ function formatLineSegments(stats, options) {
632
590
  if (fields.delta && stats.promptGapMs !== undefined) {
633
591
  segments.push({ text: `${labels.delta} ${formatDuration(stats.promptGapMs)}`, tone: "muted" });
634
592
  }
635
- if (identity === "endpoint" && stats.router !== undefined) {
636
- segments.push({ text: stats.router, tone: stats.identityChanged ? "warning" : "base" });
637
- if (stats.identityChanged)
638
- segments.push({ text: labels.providerChanged, tone: "warning" });
639
- } else if (stats.providerID !== undefined) {
593
+ if (stats.providerID !== undefined) {
640
594
  let text = stats.providerID;
641
595
  if (fields.model && stats.modelID !== undefined)
642
596
  text += `/${stats.modelID}`;
@@ -650,10 +604,13 @@ function formatLineSegments(stats, options) {
650
604
  }
651
605
  if (fields.turn && stats.totals.steps > 0) {
652
606
  const totals = turnTotals === "sum" ? stats.totals : stats.latest;
653
- segments.push({ text: totalsText(labels.turn, totals, labels, fields, turnTotals === "sum" ? stats.totals.steps : stats.steps), tone: "base" });
607
+ segments.push({
608
+ text: totalsText(labels.turn, totals, labels, fields, turnTotals === "sum" ? stats.totals.steps : stats.steps, stats.totals.cost),
609
+ tone: "base"
610
+ });
654
611
  }
655
612
  if (fields.session && stats.session) {
656
- segments.push({ text: totalsText(labels.session, stats.session, labels, fields), tone: "muted" });
613
+ segments.push({ text: totalsText(labels.session, stats.session, labels, fields, 0, stats.session.cost), tone: "muted" });
657
614
  }
658
615
  if (fields.cacheExpiry && stats.cacheExpired) {
659
616
  const count = stats.drops.length > 1 ? `\xD7${stats.drops.length}` : "";
@@ -719,9 +676,9 @@ function buildWhere(range, filters, column = STEP_TIME) {
719
676
  clauses.push(`${MODEL_KEY_SQL} = ?`);
720
677
  params.push(filters.modelKey);
721
678
  }
722
- if (filters?.router !== undefined && filters.router !== "") {
723
- clauses.push("router = ?");
724
- params.push(filters.router);
679
+ if (filters?.provider !== undefined && filters.provider !== "") {
680
+ clauses.push("provider_id = ?");
681
+ params.push(filters.provider);
725
682
  }
726
683
  if (filters?.sessionID !== undefined && filters.sessionID !== "") {
727
684
  clauses.push("session_id = ?");
@@ -758,34 +715,32 @@ function overview(db, range, filters) {
758
715
  function models(db, range, filters) {
759
716
  const filter = buildWhere(range, filters);
760
717
  const rows = db.query(`SELECT provider_id, model_id, variant,
761
- GROUP_CONCAT(DISTINCT router) AS router_list,
762
718
  ${USAGE_SELECT},
763
719
  MIN(${STEP_TIME}) AS first_at,
764
720
  MAX(COALESCE(completed_at, recorded_at)) AS last_at
765
721
  FROM steps ${filter.where}
766
722
  GROUP BY provider_id, model_id, variant
767
723
  ORDER BY steps DESC, cached DESC`).all(...filter.params);
768
- const models2 = new Map;
724
+ const models = new Map;
769
725
  for (const row of rows) {
770
726
  const modelID = row.model_id ?? "(unknown)";
771
727
  const variant = row.variant ?? undefined;
772
728
  const key = `${modelID}#${variant ?? ""}`;
773
- let model = models2.get(key);
729
+ let model = models.get(key);
774
730
  if (!model) {
775
731
  model = { modelID, variant, providers: [], totals: emptyUsage() };
776
- models2.set(key, model);
732
+ models.set(key, model);
777
733
  }
778
734
  const usage = usageFrom(row);
779
735
  model.providers.push({
780
736
  ...usage,
781
737
  providerID: row.provider_id ?? "(unknown)",
782
- routers: row.router_list ? row.router_list.split(",").filter(Boolean) : [],
783
738
  firstAt: row.first_at ?? undefined,
784
739
  lastAt: row.last_at ?? undefined
785
740
  });
786
741
  addUsage(model.totals, usage);
787
742
  }
788
- return [...models2.values()].sort((a, b) => billedTokens(b.totals) - billedTokens(a.totals));
743
+ return [...models.values()].sort((a, b) => billedTokens(b.totals) - billedTokens(a.totals));
789
744
  }
790
745
  function emptyUsage() {
791
746
  return { steps: 0, input: 0, cached: 0, cacheWrite: 0, output: 0, reasoning: 0, cost: 0 };
@@ -918,7 +873,7 @@ function turns(db, options) {
918
873
  }
919
874
  const steps = db.query(`SELECT message_id, session_id, provider_id, model_id, variant,
920
875
  input_tokens, cache_read, cache_write, output_tokens, reasoning_tokens, cost,
921
- created_at, streamed_at, recorded_at, completed_at, finish, router
876
+ created_at, streamed_at, recorded_at, completed_at, finish
922
877
  FROM steps ${clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : ""}
923
878
  ORDER BY session_id, ${STEP_TIME}`).all(...params);
924
879
  const promptClause = options?.sessionID === undefined ? "" : `WHERE session_id = ?${floor === undefined ? "" : " AND created_at >= ?"}`;
@@ -957,18 +912,9 @@ function turns(db, options) {
957
912
  }
958
913
  reference = message;
959
914
  }
960
- const lastWith = (pick) => {
961
- for (let index = bucket.length - 1;index >= 0; index -= 1) {
962
- const value = pick(bucket[index]);
963
- if (value !== null)
964
- return value;
965
- }
966
- return;
967
- };
968
915
  const providerID = last.provider_id ?? undefined;
969
916
  const modelID = last.model_id ?? undefined;
970
917
  const variant = last.variant ?? undefined;
971
- const router = lastWith((row) => row.router);
972
918
  let produced = 0;
973
919
  let window = 0;
974
920
  for (const row of bucket) {
@@ -986,8 +932,6 @@ function turns(db, options) {
986
932
  providerID,
987
933
  modelID,
988
934
  variant,
989
- router,
990
- routerChanged: previous?.router !== undefined && router !== undefined && previous.router !== router,
991
935
  providerChanged: previous?.providerID !== undefined && providerID !== undefined && previous.providerID !== providerID,
992
936
  modelChanged: previous !== undefined && previous.providerID === providerID && `${previous.modelID ?? ""}#${previous.variant ?? ""}` !== `${modelID ?? ""}#${variant ?? ""}`,
993
937
  steps: bucket.length,
@@ -1031,127 +975,9 @@ function promptFloor(db, sessionID, count) {
1031
975
  const rows = db.query("SELECT created_at FROM prompts WHERE session_id = ? AND created_at IS NOT NULL ORDER BY created_at DESC LIMIT ?").all(sessionID, count);
1032
976
  return rows.length === count ? rows[count - 1].created_at : undefined;
1033
977
  }
1034
- function routerBefore(db, sessionID, at) {
1035
- if (at === undefined)
1036
- return;
1037
- const row = db.query(`SELECT router FROM steps
1038
- WHERE session_id = $sessionID AND router IS NOT NULL AND COALESCE(created_at, recorded_at) < $at
1039
- ORDER BY COALESCE(created_at, recorded_at) DESC LIMIT 1`).get({ $sessionID: sessionID, $at: at });
1040
- return row?.router ?? undefined;
1041
- }
1042
- function routerForSteps(db, sessionID, messageIDs) {
1043
- if (messageIDs.length === 0)
1044
- return;
1045
- const placeholders = messageIDs.map(() => "?").join(", ");
1046
- const row = db.query(`SELECT router FROM steps
1047
- WHERE session_id = ? AND message_id IN (${placeholders}) AND router IS NOT NULL
1048
- ORDER BY recorded_at DESC LIMIT 1`).get(sessionID, ...messageIDs);
1049
- return row?.router ?? undefined;
1050
- }
1051
978
  function filterOptions(db) {
1052
979
  const pick = (column) => db.query(`SELECT ${column} AS value, COUNT(*) AS steps FROM steps WHERE ${column} IS NOT NULL GROUP BY ${column} ORDER BY steps DESC`).all().map((row) => ({ value: row.value, steps: row.steps }));
1053
- return { models: pick("model_id"), endpoints: pick("router") };
1054
- }
1055
-
1056
- // src/endpoint.ts
1057
- var ENDPOINT_HEADER = "x-opencode-endpoint-id";
1058
- var ENDPOINT_MAX = 64;
1059
- var KNOWN_ENDPOINT_HOSTS = [
1060
- ["api.fireworks.ai", "fireworks"],
1061
- ["api.deepseek.com", "deepseek"],
1062
- ["api.together.xyz", "together"],
1063
- ["api.groq.com", "groq"],
1064
- ["api.cerebras.ai", "cerebras"],
1065
- ["api.sambanova.ai", "sambanova"],
1066
- ["api.hyperbolic.xyz", "hyperbolic"],
1067
- ["api.deepinfra.com", "deepinfra"],
1068
- ["api.baseten.co", "baseten"],
1069
- ["api.novita.ai", "novita"],
1070
- ["api.parasail.io", "parasail"],
1071
- ["api.moonshot.ai", "moonshot"],
1072
- ["api.moonshot.cn", "moonshot"],
1073
- ["api.z.ai", "zhipu"],
1074
- ["open.bigmodel.cn", "zhipu"],
1075
- ["api.minimax.chat", "minimax"],
1076
- ["dashscope.aliyuncs.com", "alibaba"],
1077
- ["api.x.ai", "xai"],
1078
- ["api.anthropic.com", "anthropic"],
1079
- ["api.openai.com", "openai"],
1080
- ["openai.azure.com", "azure"],
1081
- ["bedrock-runtime.*.amazonaws.com", "bedrock"],
1082
- ["generativelanguage.googleapis.com", "google"],
1083
- ["aiplatform.googleapis.com", "vertex"],
1084
- ["api.nvidia.com", "nvidia"],
1085
- ["api.mistral.ai", "mistral"],
1086
- ["api.cloudflare.com", "cloudflare"]
1087
- ];
1088
- function readHeader(headers, name) {
1089
- const get = headers.get;
1090
- if (typeof get === "function") {
1091
- const value = get.call(headers, name);
1092
- return value === null || value === "" ? undefined : value;
1093
- }
1094
- for (const key of Object.keys(headers)) {
1095
- if (key.toLowerCase() !== name)
1096
- continue;
1097
- const value = headers[key];
1098
- return value ? value : undefined;
1099
- }
1100
- return;
1101
- }
1102
- function inferFromHeaders(headers) {
1103
- if (!headers)
1104
- return;
1105
- const value = readHeader(headers, ENDPOINT_HEADER);
1106
- if (value === undefined)
1107
- return;
1108
- const router = normalizeToken(value, ENDPOINT_MAX);
1109
- if (router === undefined)
1110
- return;
1111
- return { router, source: `header:${ENDPOINT_HEADER}` };
1112
- }
1113
- function hostMatches(host, pattern) {
1114
- const hostLabels = host.split(".");
1115
- const patternLabels = pattern.split(".");
1116
- if (patternLabels.includes("*")) {
1117
- if (hostLabels.length !== patternLabels.length)
1118
- return false;
1119
- return patternLabels.every((label, index) => label === "*" || label === hostLabels[index]);
1120
- }
1121
- if (host === pattern)
1122
- return true;
1123
- if (host.endsWith(`.${pattern}`))
1124
- return true;
1125
- return host.endsWith(`-${pattern}`);
1126
- }
1127
- function inferFromUrl(url) {
1128
- if (url === undefined)
1129
- return;
1130
- let host;
1131
- try {
1132
- host = new URL(url).hostname.toLowerCase();
1133
- } catch {
1134
- return;
1135
- }
1136
- if (host === "")
1137
- return;
1138
- for (const [suffix, router] of KNOWN_ENDPOINT_HOSTS) {
1139
- if (hostMatches(host, suffix))
1140
- return { router, source: `endpoint:${host}` };
1141
- }
1142
- return;
1143
- }
1144
- function mergeEndpoint(...candidates) {
1145
- const merged = {};
1146
- for (const candidate of candidates) {
1147
- if (candidate === undefined)
1148
- continue;
1149
- if (merged.router === undefined && candidate.router !== undefined)
1150
- merged.router = candidate.router;
1151
- if (merged.source === undefined && candidate.source !== undefined)
1152
- merged.source = candidate.source;
1153
- }
1154
- return merged.router === undefined ? undefined : merged;
980
+ return { models: pick("model_id"), providers: pick("provider_id") };
1155
981
  }
1156
982
 
1157
983
  // src/recorder.ts
@@ -1160,7 +986,6 @@ function createRecorder(db, options) {
1160
986
  const MAX_PENDING = 256;
1161
987
  const pending = new Map;
1162
988
  const lastModel = new Map;
1163
- const known = new Map;
1164
989
  const now = options?.now ?? (() => Date.now());
1165
990
  const MAX_DEFERRED = 256;
1166
991
  const deferred = [];
@@ -1211,26 +1036,11 @@ function createRecorder(db, options) {
1211
1036
  }
1212
1037
  function forget(sessionID) {
1213
1038
  lastModel.delete(sessionID);
1214
- known.delete(sessionID);
1215
1039
  for (const [messageID, step] of pending) {
1216
1040
  if (step.sessionID === sessionID)
1217
1041
  pending.delete(messageID);
1218
1042
  }
1219
1043
  }
1220
- function strength(info) {
1221
- if (info?.router === undefined)
1222
- return 0;
1223
- return info.source?.startsWith("header:") === true ? 2 : 1;
1224
- }
1225
- function noteRouter(sessionID, modelID, info) {
1226
- const previous = known.get(sessionID);
1227
- const merged = strength(previous?.info) > strength(info) ? previous.info : mergeEndpoint(info, previous?.info);
1228
- const info2 = merged ?? info;
1229
- const settled = previous !== undefined && previous.modelID === modelID && previous.info.router === info2.router;
1230
- remember(known, sessionID, { modelID, info: info2 }, MAX_TRACKED_SESSIONS);
1231
- if (!settled)
1232
- write(() => setStepRouterForSessionModel(db, sessionID, modelID, info2));
1233
- }
1234
1044
  function recordPendingStep(messageID, data, finish, at) {
1235
1045
  const sessionID = data.sessionID;
1236
1046
  if (typeof sessionID !== "string")
@@ -1238,8 +1048,6 @@ function createRecorder(db, options) {
1238
1048
  const info = pending.get(messageID);
1239
1049
  pending.delete(messageID);
1240
1050
  const model = info?.model ?? lastModel.get(sessionID);
1241
- const learned = known.get(sessionID);
1242
- const matched = learned !== undefined && (learned.modelID === undefined || learned.modelID === model?.id) ? learned.info : undefined;
1243
1051
  write(() => recordStep(db, {
1244
1052
  messageID,
1245
1053
  sessionID,
@@ -1256,7 +1064,6 @@ function createRecorder(db, options) {
1256
1064
  streamedAt: info?.streamed,
1257
1065
  completedAt: at,
1258
1066
  finish,
1259
- router: matched?.router,
1260
1067
  recordedAt: now()
1261
1068
  }));
1262
1069
  }
@@ -1372,16 +1179,7 @@ function createRecorder(db, options) {
1372
1179
  }
1373
1180
  return found;
1374
1181
  }
1375
- function handleHttpResponse(event) {
1376
- const sessionID = event.sessionID;
1377
- if (typeof sessionID !== "string")
1378
- return;
1379
- const inferred = mergeEndpoint(inferFromHeaders(event.response?.headers), inferFromUrl(event.request?.url));
1380
- if (inferred === undefined)
1381
- return;
1382
- noteRouter(sessionID, event.model?.id, inferred);
1383
- }
1384
- return { handleEvent, handleHttpResponse, pendingFor };
1182
+ return { handleEvent, pendingFor };
1385
1183
  }
1386
1184
 
1387
1185
  // src/index.ts
@@ -1415,18 +1213,7 @@ var src_default = Plugin.define({
1415
1213
  }
1416
1214
  } catch {}
1417
1215
  })();
1418
- let hook;
1419
- try {
1420
- hook = await ctx.session.hook("http.response", (event) => {
1421
- try {
1422
- recorder.handleHttpResponse(event);
1423
- } catch {}
1424
- });
1425
- } catch {
1426
- hook = undefined;
1427
- }
1428
1216
  return async () => {
1429
- await hook?.dispose();
1430
1217
  abort.abort();
1431
1218
  await stream;
1432
1219
  db.close();
@@ -1437,4 +1224,4 @@ export {
1437
1224
  src_default as default
1438
1225
  };
1439
1226
 
1440
- //# debugId=B7051C41CF32481164756E2164756E21
1227
+ //# debugId=CB2A8AAFDC0E182864756E2164756E21