@x12i/ai-tools 2.0.0 → 2.0.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.
@@ -0,0 +1,51 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/profiles/resolveProfileForAsk.ts
2
+ var _aiprofiles = require('@x12i/ai-profiles');
3
+ function profileConfigFromResolved(resolved) {
4
+ return {
5
+ provider: resolved.provider,
6
+ model: resolved.modelId,
7
+ instructionTier: resolved.instructionTier,
8
+ backend: resolved.backend,
9
+ profile: resolved.profile,
10
+ choice: resolved.choice,
11
+ temperature: resolved.runtime.temperature,
12
+ outputMode: resolved.runtime.outputMode,
13
+ toolPolicy: resolved.runtime.toolPolicy,
14
+ reasoningEffort: resolved.runtime.reasoningEffort,
15
+ executionMode: resolved.runtime.executionMode,
16
+ requireCitations: resolved.runtime.requireCitations,
17
+ allowWeb: resolved.runtime.allowWeb,
18
+ allowFileSearch: resolved.runtime.allowFileSearch,
19
+ allowCodeExecution: resolved.runtime.allowCodeExecution,
20
+ humanReview: resolved.runtime.humanReview,
21
+ ...resolved.metadata !== void 0 ? { metadata: resolved.metadata } : {},
22
+ ...resolved.pricing !== void 0 ? { pricing: resolved.pricing } : {},
23
+ resolved
24
+ };
25
+ }
26
+ async function resolveProfileForAsk(input) {
27
+ const resolved = await _aiprofiles.resolveAIProfile.call(void 0, input.profile, {
28
+ choice: input.choice,
29
+ source: input.source,
30
+ refresh: input.refresh
31
+ });
32
+ return profileConfigFromResolved(resolved);
33
+ }
34
+
35
+ // src/profiles/index.ts
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+ exports.profileConfigFromResolved = profileConfigFromResolved; exports.resolveProfileForAsk = resolveProfileForAsk; exports.resolveAIProfile = _aiprofiles.resolveAIProfile; exports.listAIProfiles = _aiprofiles.listAIProfiles; exports.listAIShortcuts = _aiprofiles.listAIShortcuts; exports.isKnownProfileOrShortcut = _aiprofiles.isKnownProfileOrShortcut;
51
+ //# sourceMappingURL=chunk-5IZ7PLY2.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-5IZ7PLY2.cjs","../src/profiles/resolveProfileForAsk.ts","../src/profiles/index.ts"],"names":[],"mappings":"AAAA;ACAA,+CAAiC;AAsC1B,SAAS,yBAAA,CACd,QAAA,EACuB;AACvB,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,QAAA,CAAS,QAAA;AAAA,IACnB,KAAA,EAAO,QAAA,CAAS,OAAA;AAAA,IAChB,eAAA,EAAiB,QAAA,CAAS,eAAA;AAAA,IAC1B,OAAA,EAAS,QAAA,CAAS,OAAA;AAAA,IAClB,OAAA,EAAS,QAAA,CAAS,OAAA;AAAA,IAClB,MAAA,EAAQ,QAAA,CAAS,MAAA;AAAA,IACjB,WAAA,EAAa,QAAA,CAAS,OAAA,CAAQ,WAAA;AAAA,IAC9B,UAAA,EAAY,QAAA,CAAS,OAAA,CAAQ,UAAA;AAAA,IAC7B,UAAA,EAAY,QAAA,CAAS,OAAA,CAAQ,UAAA;AAAA,IAC7B,eAAA,EAAiB,QAAA,CAAS,OAAA,CAAQ,eAAA;AAAA,IAClC,aAAA,EAAe,QAAA,CAAS,OAAA,CAAQ,aAAA;AAAA,IAChC,gBAAA,EAAkB,QAAA,CAAS,OAAA,CAAQ,gBAAA;AAAA,IACnC,QAAA,EAAU,QAAA,CAAS,OAAA,CAAQ,QAAA;AAAA,IAC3B,eAAA,EAAiB,QAAA,CAAS,OAAA,CAAQ,eAAA;AAAA,IAClC,kBAAA,EAAoB,QAAA,CAAS,OAAA,CAAQ,kBAAA;AAAA,IACrC,WAAA,EAAa,QAAA,CAAS,OAAA,CAAQ,WAAA;AAAA,IAC9B,GAAI,QAAA,CAAS,SAAA,IAAa,KAAA,EAAA,EAAY,EAAE,QAAA,EAAU,QAAA,CAAS,SAAS,EAAA,EAAI,CAAC,CAAA;AAAA,IACzE,GAAI,QAAA,CAAS,QAAA,IAAY,KAAA,EAAA,EAAY,EAAE,OAAA,EAAS,QAAA,CAAS,QAAQ,EAAA,EAAI,CAAC,CAAA;AAAA,IACtE;AAAA,EACF,CAAA;AACF;AAOA,MAAA,SAAsB,oBAAA,CACpB,KAAA,EACgC;AAChC,EAAA,MAAM,SAAA,EAAW,MAAM,0CAAA,KAAiB,CAAM,OAAA,EAAS;AAAA,IACrD,MAAA,EAAQ,KAAA,CAAM,MAAA;AAAA,IACd,MAAA,EAAQ,KAAA,CAAM,MAAA;AAAA,IACd,OAAA,EAAS,KAAA,CAAM;AAAA,EACjB,CAAC,CAAA;AACD,EAAA,OAAO,yBAAA,CAA0B,QAAQ,CAAA;AAC3C;AD7CA;AACA;AEfA;AACE;AACA;AACA;AACA;AAAA;AFkBF;AACA;AACE;AACA;AACA;AACA;AACA;AACA;AACF,iWAAC","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-5IZ7PLY2.cjs","sourcesContent":[null,"import { resolveAIProfile } from \"@x12i/ai-profiles\";\nimport type {\n AIProfileBackend,\n InstructionTier,\n RegistrySourceMode,\n ResolvedAIProfile,\n} from \"@x12i/ai-profiles\";\n\nexport type ResolveProfileForAskInput = {\n profile: string;\n choice?: string;\n source?: RegistrySourceMode;\n refresh?: boolean;\n};\n\n/** FuncX / ask-node model config derived from {@link ResolvedAIProfile}. */\nexport type AskProfileModelConfig = {\n provider: ResolvedAIProfile[\"provider\"];\n model: string;\n instructionTier: InstructionTier;\n backend: AIProfileBackend;\n profile: string;\n choice: string;\n temperature: number;\n outputMode: ResolvedAIProfile[\"runtime\"][\"outputMode\"];\n toolPolicy: ResolvedAIProfile[\"runtime\"][\"toolPolicy\"];\n reasoningEffort: ResolvedAIProfile[\"runtime\"][\"reasoningEffort\"];\n executionMode: ResolvedAIProfile[\"runtime\"][\"executionMode\"];\n requireCitations: boolean;\n allowWeb: boolean;\n allowFileSearch: boolean;\n allowCodeExecution: boolean;\n humanReview: ResolvedAIProfile[\"runtime\"][\"humanReview\"];\n metadata?: Record<string, unknown>;\n pricing?: ResolvedAIProfile[\"pricing\"];\n resolved: ResolvedAIProfile;\n};\n\nexport function profileConfigFromResolved(\n resolved: ResolvedAIProfile,\n): AskProfileModelConfig {\n return {\n provider: resolved.provider,\n model: resolved.modelId,\n instructionTier: resolved.instructionTier,\n backend: resolved.backend,\n profile: resolved.profile,\n choice: resolved.choice,\n temperature: resolved.runtime.temperature,\n outputMode: resolved.runtime.outputMode,\n toolPolicy: resolved.runtime.toolPolicy,\n reasoningEffort: resolved.runtime.reasoningEffort,\n executionMode: resolved.runtime.executionMode,\n requireCitations: resolved.runtime.requireCitations,\n allowWeb: resolved.runtime.allowWeb,\n allowFileSearch: resolved.runtime.allowFileSearch,\n allowCodeExecution: resolved.runtime.allowCodeExecution,\n humanReview: resolved.runtime.humanReview,\n ...(resolved.metadata !== undefined ? { metadata: resolved.metadata } : {}),\n ...(resolved.pricing !== undefined ? { pricing: resolved.pricing } : {}),\n resolved,\n };\n}\n\n/**\n * Resolve a profile (+ optional choice) into ask-node / FuncX model configuration.\n * Uses {@link ResolvedAIProfile.instructionTier} and {@link ResolvedAIProfile.backend}\n * from `@x12i/ai-profiles` — do not duplicate preset tables locally.\n */\nexport async function resolveProfileForAsk(\n input: ResolveProfileForAskInput,\n): Promise<AskProfileModelConfig> {\n const resolved = await resolveAIProfile(input.profile, {\n choice: input.choice,\n source: input.source,\n refresh: input.refresh,\n });\n return profileConfigFromResolved(resolved);\n}\n","export {\n resolveProfileForAsk,\n profileConfigFromResolved,\n} from \"./resolveProfileForAsk.js\";\nexport type {\n AskProfileModelConfig,\n ResolveProfileForAskInput,\n} from \"./resolveProfileForAsk.js\";\n\nexport type {\n ResolvedAIProfile,\n InstructionTier,\n AIProfileBackend,\n AIProfileSummary,\n AIShortcutSummary,\n ResolveAIProfileOptions,\n RegistrySourceMode,\n} from \"@x12i/ai-profiles\";\n\nexport {\n resolveAIProfile,\n listAIProfiles,\n listAIShortcuts,\n isKnownProfileOrShortcut,\n} from \"@x12i/ai-profiles\";\n"]}
@@ -472,53 +472,22 @@ function indexRegistry(registry) {
472
472
  list.push(entry);
473
473
  byKey.set(k, list);
474
474
  };
475
- for (const shortcutKey of Object.keys(registry.shortcuts)) {
476
- const shortcut = registry.shortcuts[shortcutKey];
477
- const profile = registry.profiles[shortcut.profile];
478
- if (!profile) continue;
479
- const choiceKey = shortcut.choice ?? profile.defaultChoice;
480
- const choice = profile.choices[choiceKey];
481
- if (!choice) continue;
482
- const entry = choiceEntry(choice, profile.profile, choiceKey, "shortcut");
483
- add(shortcutKey, entry);
484
- }
485
475
  for (const profile of Object.values(registry.profiles)) {
486
476
  for (const [choiceKey, choice] of Object.entries(profile.choices)) {
487
- const entry = choiceEntry(choice, profile.profile, choiceKey, "model-id");
477
+ const entry = choiceEntry(choice, profile.profile, choiceKey);
488
478
  add(choice.modelId, entry);
489
479
  add(canonicalModelId(choice.provider, choice.modelId), entry);
490
480
  }
491
- const defaultChoice = profile.choices[profile.defaultChoice];
492
- if (defaultChoice) {
493
- add(
494
- profile.profile,
495
- choiceEntry(defaultChoice, profile.profile, profile.defaultChoice, "profile")
496
- );
497
- }
498
- for (const alias of profile.aliases ?? []) {
499
- if (defaultChoice) {
500
- add(
501
- alias,
502
- choiceEntry(
503
- defaultChoice,
504
- profile.profile,
505
- profile.defaultChoice,
506
- "profile-alias"
507
- )
508
- );
509
- }
510
- }
511
481
  }
512
482
  return byKey;
513
483
  }
514
- function choiceEntry(choice, profile, choiceKey, matchedVia) {
484
+ function choiceEntry(choice, profile, choiceKey) {
515
485
  const canonical = canonicalModelId(choice.provider, choice.modelId);
516
486
  return {
517
487
  provider: normalizeProvider(choice.provider) ?? choice.provider,
518
488
  modelId: normalizeString(choice.modelId),
519
489
  canonicalModelId: canonical,
520
490
  pricing: choice.pricing,
521
- matchedVia,
522
491
  profile,
523
492
  choice: choiceKey
524
493
  };
@@ -539,9 +508,6 @@ function scoreCandidate(entry, model, providerHint) {
539
508
  if (normalized === entry.canonicalModelId) score += 100;
540
509
  if (normalized === entry.modelId) score += 80;
541
510
  if (providerHint && entry.provider === providerHint) score += 50;
542
- if (entry.matchedVia === "model-id") score += 10;
543
- if (entry.matchedVia === "shortcut") score += 5;
544
- if (entry.matchedVia === "profile") score += 3;
545
511
  if (entry.pricing) score += 2;
546
512
  return score;
547
513
  }
@@ -560,18 +526,34 @@ function pickBest(candidates, model, providerHint) {
560
526
  }
561
527
  return best;
562
528
  }
563
- function fromIndexed(entry) {
529
+ function resolvedToMatch(resolved) {
564
530
  return {
565
- provider: entry.provider,
566
- modelId: entry.modelId,
567
- canonicalModelId: entry.canonicalModelId,
568
- pricing: entry.pricing,
569
- matchedVia: entry.matchedVia,
570
- profile: entry.profile,
571
- choice: entry.choice
531
+ provider: normalizeProvider(resolved.provider) ?? resolved.provider,
532
+ modelId: normalizeString(resolved.modelId),
533
+ canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),
534
+ pricing: resolved.pricing,
535
+ instructionTier: resolved.instructionTier,
536
+ backend: resolved.backend,
537
+ matchedVia: resolved.shortcut ? "shortcut" : "profile",
538
+ profile: resolved.profile,
539
+ choice: resolved.choice
572
540
  };
573
541
  }
574
- function lookupInIndex(index, model, provider) {
542
+ async function fromIndexed(entry) {
543
+ const resolved = await resolveAIProfile(entry.profile, { choice: entry.choice });
544
+ return {
545
+ provider: normalizeProvider(resolved.provider) ?? resolved.provider,
546
+ modelId: normalizeString(resolved.modelId),
547
+ canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),
548
+ pricing: resolved.pricing ?? entry.pricing,
549
+ instructionTier: resolved.instructionTier,
550
+ backend: resolved.backend,
551
+ matchedVia: "model-id",
552
+ profile: resolved.profile,
553
+ choice: resolved.choice
554
+ };
555
+ }
556
+ async function lookupInIndex(index, model, provider) {
575
557
  const providerHint = provider ? normalizeProvider(provider) : void 0;
576
558
  const keys = [
577
559
  profileKey(model),
@@ -603,15 +585,7 @@ function lookupInIndex(index, model, provider) {
603
585
  async function matchModelInAiProfiles(model, provider) {
604
586
  try {
605
587
  const resolved = await resolveAIProfile(model);
606
- return {
607
- provider: normalizeProvider(resolved.provider) ?? resolved.provider,
608
- modelId: normalizeString(resolved.modelId),
609
- canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),
610
- pricing: resolved.pricing,
611
- matchedVia: resolved.shortcut ? "shortcut" : "profile",
612
- profile: resolved.profile,
613
- choice: resolved.choice
614
- };
588
+ return resolvedToMatch(resolved);
615
589
  } catch (err) {
616
590
  if (!(err instanceof AIProfilesError) || err.code !== "UNKNOWN_PROFILE") {
617
591
  throw err;
@@ -619,11 +593,15 @@ async function matchModelInAiProfiles(model, provider) {
619
593
  }
620
594
  const index = await getProfileIndex();
621
595
  const hint = providerHintForProfiles(model, provider);
622
- const direct = lookupInIndex(index, model, hint);
596
+ const direct = await lookupInIndex(index, model, hint);
623
597
  if (direct) return direct;
624
598
  const stripped = stripModelVersionSuffix(model);
625
599
  if (stripped && stripped !== normalizeString(model)) {
626
- return lookupInIndex(index, stripped, providerHintForProfiles(stripped, provider));
600
+ return lookupInIndex(
601
+ index,
602
+ stripped,
603
+ providerHintForProfiles(stripped, provider)
604
+ );
627
605
  }
628
606
  return null;
629
607
  }
@@ -967,4 +945,4 @@ export {
967
945
  resolveUsageModel,
968
946
  CostCalculator
969
947
  };
970
- //# sourceMappingURL=chunk-U2YDDUVP.js.map
948
+ //# sourceMappingURL=chunk-CTM35DMA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cost/constants.ts","../src/cost/enrichCostResult.ts","../src/cost/extractUsageInput.ts","../src/cost/resolveUsageModel.ts","../src/cost/aiProfilesMatch.ts","../src/cost/costModelResolution.ts","../src/cost/profilePricing.ts","../src/cost/CostCalculator.ts"],"sourcesContent":["/** Default OpenRouter platform surcharge when catalog markup fields are absent (5%). */\nexport const DEFAULT_OPENROUTER_MARKUP_RATE = 0.05;\n\n/** ai-profiles tiered pricing threshold (tokens). */\nexport const PROFILE_TIERED_CONTEXT_THRESHOLD = 200_000;\n","import type { ExtractUsageInputResult } from \"./extractUsageInput.js\";\nimport type { AiCostExtraction, AiCostResult, AiUsageInput } from \"./types.js\";\n\nexport function toCostExtraction(\n provenance: ExtractUsageInputResult[\"provenance\"],\n): AiCostExtraction {\n return {\n model: { field: provenance.model.field, path: provenance.model.path },\n tokens: {\n source: provenance.tokens.source,\n path: provenance.tokens.path,\n estimated: provenance.tokens.estimated,\n },\n ...(provenance.modelUsed\n ? {\n modelUsed: {\n field: provenance.modelUsed.field,\n path: provenance.modelUsed.path,\n },\n }\n : {}),\n ...(provenance.provider\n ? {\n provider: {\n field: provenance.provider.field,\n path: provenance.provider.path,\n },\n }\n : {}),\n };\n}\n\n/** Attach usage, provider, and model fields callers expect on every cost response. */\nexport function enrichCostResult(\n result: Omit<\n AiCostResult,\n \"usage\" | \"provider\" | \"usedModel\" | \"model\" | \"extraction\"\n >,\n input: AiUsageInput,\n extraction?: AiCostExtraction,\n): AiCostResult {\n /** Original model id from the caller — never replaced by catalog resolution. */\n const receivedModelId = input.usedModel ?? input.modelUsed ?? input.model;\n\n return {\n ...result,\n provider: input.provider,\n usage: { ...input.tokens },\n ...(receivedModelId ? { usedModel: receivedModelId } : {}),\n ...(input.model && input.model !== receivedModelId ? { model: input.model } : {}),\n ...(extraction ? { extraction } : {}),\n };\n}\n","import type { AiUsageInput } from \"./types.js\";\n\n/** Model id field priority (higher wins). Runtime ids beat request/config aliases. */\nexport const MODEL_FIELD_PRIORITY: readonly { key: string; score: number }[] = [\n { key: \"usedModel\", score: 1000 },\n { key: \"modelUsed\", score: 990 },\n { key: \"resolvedModel\", score: 980 },\n { key: \"model\", score: 500 },\n { key: \"xynthesisModel\", score: 120 },\n { key: \"skillModel\", score: 110 },\n] as const;\n\n/** Path segments that boost or penalize a model candidate. */\nconst MODEL_PATH_BONUS: readonly { pattern: RegExp; bonus: number }[] = [\n { pattern: /(^|\\.)response(\\.|$)/i, bonus: 40 },\n { pattern: /(^|\\.)outer\\.input(\\.|$)/i, bonus: 35 },\n { pattern: /(^|\\.)config(?!\\.rawConfig)(\\.|$)/i, bonus: 30 },\n { pattern: /(^|\\.)outer\\.input\\.config(\\.|$)/i, bonus: 28 },\n { pattern: /(^|\\.)usage(\\.|$)/i, bonus: 15 },\n { pattern: /(^|\\.)rawConfig(\\.|$)/i, bonus: -40 },\n { pattern: /workingMemory/i, bonus: -50 },\n { pattern: /requestExample/i, bonus: -80 },\n { pattern: /graphsStudio/i, bonus: -80 },\n];\n\nconst PROVIDER_FIELD_PRIORITY: readonly { key: string; score: number }[] = [\n { key: \"provider\", score: 500 },\n { key: \"providerId\", score: 480 },\n] as const;\n\nconst PROVIDER_PATH_BONUS: readonly { pattern: RegExp; bonus: number }[] = [\n { pattern: /(^|\\.)config(?!\\.rawConfig)(\\.|$)/i, bonus: 30 },\n { pattern: /(^|\\.)outer\\.input(\\.|$)/i, bonus: 20 },\n { pattern: /(^|\\.)rawConfig(\\.|$)/i, bonus: -20 },\n];\n\nconst PROMPT_TOKEN_KEYS = new Set([\n \"prompt\",\n \"prompt_tokens\",\n \"promptTokens\",\n \"input_tokens\",\n \"inputTokens\",\n \"estimatedInputTokens\",\n \"input\",\n]);\n\nconst COMPLETION_TOKEN_KEYS = new Set([\n \"completion\",\n \"completion_tokens\",\n \"completionTokens\",\n \"output_tokens\",\n \"outputTokens\",\n \"estimatedOutputTokens\",\n \"output\",\n]);\n\nconst OPTIONAL_TOKEN_KEYS: Record<string, keyof AiUsageInput[\"tokens\"]> = {\n total: \"total\",\n total_tokens: \"total\",\n totalTokens: \"total\",\n cached: \"cached\",\n cached_tokens: \"cached\",\n cache_read_tokens: \"cached\",\n cacheReadTokens: \"cached\",\n cacheWrite: \"cacheWrite\",\n cache_write_tokens: \"cacheWrite\",\n cacheWriteTokens: \"cacheWrite\",\n reasoning: \"reasoning\",\n reasoning_tokens: \"reasoning\",\n reasoningTokens: \"reasoning\",\n audio: \"audio\",\n audio_tokens: \"audio\",\n image: \"image\",\n image_tokens: \"image\",\n};\n\nexport type FieldProvenance = {\n field: string;\n path: string;\n score: number;\n};\n\nexport type TokenExtractionProvenance = {\n source: \"usage\" | \"tokens\" | \"diagnostics\" | \"estimated\";\n path: string;\n estimated?: boolean;\n};\n\nexport type ExtractUsageInputResult = {\n input: AiUsageInput;\n provenance: {\n model: FieldProvenance;\n modelUsed?: FieldProvenance;\n provider?: FieldProvenance;\n tokens: TokenExtractionProvenance;\n };\n};\n\nexport type ExtractUsageInputOptions = {\n /** Default when no provider field is found (default: `openrouter`). */\n defaultProvider?: string;\n};\n\ntype ModelCandidate = FieldProvenance & { value: string };\ntype ProviderCandidate = FieldProvenance & { value: string };\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === \"object\" && !Array.isArray(v);\n}\n\nfunction modelKeyScore(key: string): number {\n return MODEL_FIELD_PRIORITY.find((e) => e.key === key)?.score ?? 0;\n}\n\nfunction providerKeyScore(key: string): number {\n return PROVIDER_FIELD_PRIORITY.find((e) => e.key === key)?.score ?? 0;\n}\n\nfunction pathBonus(path: string, rules: readonly { pattern: RegExp; bonus: number }[]): number {\n let bonus = 0;\n for (const { pattern, bonus: b } of rules) {\n if (pattern.test(path)) bonus += b;\n }\n return bonus;\n}\n\nfunction normalizeModelValue(v: unknown): string | undefined {\n if (typeof v !== \"string\") return undefined;\n const t = v.trim();\n return t.length > 0 ? t : undefined;\n}\n\nfunction normalizeProviderValue(v: unknown): string | undefined {\n if (typeof v !== \"string\") return undefined;\n const t = v.trim().toLowerCase();\n if (!t || t === \"null\") return undefined;\n return t;\n}\n\nfunction collectModelCandidates(\n node: unknown,\n path: string,\n out: ModelCandidate[],\n depth: number,\n maxDepth: number,\n): void {\n if (depth > maxDepth || node === null || node === undefined) return;\n\n if (isPlainObject(node)) {\n for (const [key, value] of Object.entries(node)) {\n const childPath = path ? `${path}.${key}` : key;\n const base = modelKeyScore(key);\n if (base > 0) {\n const model = normalizeModelValue(value);\n if (model) {\n out.push({\n field: key,\n path: childPath,\n value: model,\n score: base + pathBonus(childPath, MODEL_PATH_BONUS),\n });\n }\n }\n collectModelCandidates(value, childPath, out, depth + 1, maxDepth);\n }\n return;\n }\n\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) {\n collectModelCandidates(node[i], `${path}[${i}]`, out, depth + 1, maxDepth);\n }\n }\n}\n\nfunction collectProviderCandidates(\n node: unknown,\n path: string,\n out: ProviderCandidate[],\n depth: number,\n maxDepth: number,\n): void {\n if (depth > maxDepth || node === null || node === undefined) return;\n\n if (isPlainObject(node)) {\n for (const [key, value] of Object.entries(node)) {\n const childPath = path ? `${path}.${key}` : key;\n const base = providerKeyScore(key);\n if (base > 0) {\n const provider = normalizeProviderValue(value);\n if (provider) {\n out.push({\n field: key,\n path: childPath,\n value: provider,\n score: base + pathBonus(childPath, PROVIDER_PATH_BONUS),\n });\n }\n }\n collectProviderCandidates(value, childPath, out, depth + 1, maxDepth);\n }\n return;\n }\n\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) {\n collectProviderCandidates(node[i], `${path}[${i}]`, out, depth + 1, maxDepth);\n }\n }\n}\n\nfunction readNumber(obj: Record<string, unknown>, keys: Set<string>): number | undefined {\n for (const [k, v] of Object.entries(obj)) {\n if (!keys.has(k)) continue;\n if (typeof v === \"number\" && Number.isFinite(v) && v >= 0) return v;\n }\n return undefined;\n}\n\nfunction readOptionalNumbers(\n obj: Record<string, unknown>,\n): Partial<AiUsageInput[\"tokens\"]> {\n const extra: Partial<AiUsageInput[\"tokens\"]> = {};\n for (const [k, v] of Object.entries(obj)) {\n const target = OPTIONAL_TOKEN_KEYS[k];\n if (!target || typeof v !== \"number\" || !Number.isFinite(v) || v < 0) continue;\n extra[target] = v;\n }\n return extra;\n}\n\nfunction looksLikeUsageObject(obj: Record<string, unknown>): boolean {\n const hasPrompt = readNumber(obj, PROMPT_TOKEN_KEYS) !== undefined;\n const hasCompletion = readNumber(obj, COMPLETION_TOKEN_KEYS) !== undefined;\n return hasPrompt && hasCompletion;\n}\n\nfunction looksLikeDiagnosticsObject(obj: Record<string, unknown>): boolean {\n return (\n typeof obj.estimatedInputTokens === \"number\" &&\n typeof obj.estimatedOutputTokens === \"number\"\n );\n}\n\ntype TokenCandidate = {\n tokens: AiUsageInput[\"tokens\"];\n provenance: TokenExtractionProvenance;\n score: number;\n};\n\nfunction tokensFromObject(\n obj: Record<string, unknown>,\n source: TokenExtractionProvenance[\"source\"],\n path: string,\n estimated: boolean,\n score: number,\n): TokenCandidate | null {\n const prompt = readNumber(obj, PROMPT_TOKEN_KEYS);\n const completion = readNumber(obj, COMPLETION_TOKEN_KEYS);\n if (prompt === undefined || completion === undefined) return null;\n\n const extra = readOptionalNumbers(obj);\n const total =\n typeof extra.total === \"number\" ? extra.total : prompt + completion;\n\n return {\n tokens: {\n prompt,\n completion,\n total,\n ...extra,\n },\n provenance: { source, path, estimated },\n score,\n };\n}\n\nfunction collectTokenCandidates(\n node: unknown,\n path: string,\n out: TokenCandidate[],\n depth: number,\n maxDepth: number,\n): void {\n if (depth > maxDepth || node === null || node === undefined) return;\n\n if (isPlainObject(node)) {\n if (path.endsWith(\"diagnostics\") || looksLikeDiagnosticsObject(node)) {\n const cand = tokensFromObject(node, \"diagnostics\", path, true, 200);\n if (cand) out.push(cand);\n } else if (path.endsWith(\"usage\") || path.endsWith(\"tokens\") || looksLikeUsageObject(node)) {\n const source = path.endsWith(\"tokens\") ? \"tokens\" : \"usage\";\n const estimated = false;\n const score = path.endsWith(\"usage\") ? 500 : 450;\n const cand = tokensFromObject(node, source, path, estimated, score);\n if (cand) out.push(cand);\n }\n\n for (const [key, value] of Object.entries(node)) {\n const childPath = path ? `${path}.${key}` : key;\n if (key === \"usage\" || key === \"tokens\" || key === \"diagnostics\") {\n if (isPlainObject(value)) {\n collectTokenCandidates(value, childPath, out, depth + 1, maxDepth);\n }\n } else {\n collectTokenCandidates(value, childPath, out, depth + 1, maxDepth);\n }\n }\n return;\n }\n\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) {\n collectTokenCandidates(node[i], `${path}[${i}]`, out, depth + 1, maxDepth);\n }\n }\n}\n\nfunction pickBestModel(candidates: ModelCandidate[]): ModelCandidate | null {\n if (candidates.length === 0) return null;\n return [...candidates].sort((a, b) => b.score - a.score)[0]!;\n}\n\nfunction pickBestProvider(candidates: ProviderCandidate[]): ProviderCandidate | null {\n if (candidates.length === 0) return null;\n return [...candidates].sort((a, b) => b.score - a.score)[0]!;\n}\n\nfunction pickBestTokens(candidates: TokenCandidate[]): TokenCandidate | null {\n if (candidates.length === 0) return null;\n return [...candidates].sort((a, b) => b.score - a.score)[0]!;\n}\n\nfunction inferProviderFromModel(model: string, fallback: string): string {\n const slash = model.indexOf(\"/\");\n if (slash > 0) {\n const prefix = model.slice(0, slash).toLowerCase();\n if (prefix !== \"openrouter\") return prefix;\n }\n return fallback;\n}\n\n/**\n * Extract {@link AiUsageInput} from activity logs, gateway records, MongoDB exports,\n * or any nested JSON shape (e.g. `outer.input`, `config`, `metadata.diagnostics`).\n */\nexport function extractUsageInput(\n record: unknown,\n options: ExtractUsageInputOptions = {},\n): ExtractUsageInputResult {\n const defaultProvider = options.defaultProvider ?? \"openrouter\";\n const maxDepth = 24;\n\n const modelCandidates: ModelCandidate[] = [];\n const providerCandidates: ProviderCandidate[] = [];\n const tokenCandidates: TokenCandidate[] = [];\n\n collectModelCandidates(record, \"\", modelCandidates, 0, maxDepth);\n collectProviderCandidates(record, \"\", providerCandidates, 0, maxDepth);\n collectTokenCandidates(record, \"\", tokenCandidates, 0, maxDepth);\n\n const bestModel = pickBestModel(modelCandidates);\n if (!bestModel) {\n throw new Error(\n \"[ai-tools] Could not extract a model from the record (looked for usedModel, modelUsed, model, …).\",\n );\n }\n\n const runtimeFields = new Set([\"usedModel\", \"modelUsed\", \"resolvedModel\"]);\n const isRuntimeModel = runtimeFields.has(bestModel.field);\n const requestModel = modelCandidates.find(\n (c) => c.field === \"model\" && c.path !== bestModel.path,\n );\n\n const bestProvider = pickBestProvider(providerCandidates);\n const provider =\n bestProvider?.value ??\n inferProviderFromModel(bestModel.value, defaultProvider);\n\n const bestTokens = pickBestTokens(tokenCandidates);\n if (!bestTokens) {\n throw new Error(\n \"[ai-tools] Could not extract token usage from the record (usage, tokens, or metadata.diagnostics).\",\n );\n }\n\n const input: AiUsageInput = {\n tokens: bestTokens.tokens,\n provider,\n ...(isRuntimeModel\n ? { modelUsed: bestModel.value, model: requestModel?.value }\n : { model: bestModel.value }),\n };\n\n const provenance: ExtractUsageInputResult[\"provenance\"] = {\n model: {\n field: bestModel.field,\n path: bestModel.path,\n score: bestModel.score,\n },\n tokens: bestTokens.provenance,\n };\n\n if (bestProvider) {\n provenance.provider = {\n field: bestProvider.field,\n path: bestProvider.path,\n score: bestProvider.score,\n };\n }\n\n if (isRuntimeModel && requestModel) {\n provenance.modelUsed = {\n field: bestModel.field,\n path: bestModel.path,\n score: bestModel.score,\n };\n } else if (input.modelUsed) {\n provenance.modelUsed = provenance.model;\n }\n\n return { input, provenance };\n}\n","import type { AiUsageInput } from \"./types.js\";\n\n/** Prefer runtime id (`usedModel` / `modelUsed`); fall back to `model`. */\nexport function resolveUsageModel(input: AiUsageInput): string {\n const value = input.usedModel ?? input.modelUsed ?? input.model;\n if (!value?.trim()) {\n throw new Error(\n \"[ai-tools] Cost calculation requires `usedModel`, `modelUsed`, or `model` on usage input.\",\n );\n }\n return value.trim();\n}\n","import { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\nimport { AIProfilesError, resolveAIProfile } from \"@x12i/ai-profiles\";\nimport type {\n AIProfileBackend,\n AIProfileChoice,\n AIModelPricing,\n AIProfilesRegistry,\n InstructionTier,\n ResolvedAIProfile,\n} from \"@x12i/ai-profiles\";\nimport { providerHintForProfiles } from \"./costModelResolution.js\";\nimport { normalizeProvider, normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport { stripModelVersionSuffix } from \"../sync/modelNameResolver/stripVersionSuffix.js\";\n\nconst require = createRequire(import.meta.url);\n\ntype LoadRegistryFn = (options?: {\n source?: \"auto\" | \"remote\" | \"bundled\";\n refresh?: boolean;\n}) => Promise<AIProfilesRegistry>;\n\nfunction loadProfilesRegistry(): Promise<AIProfilesRegistry> {\n const entry = dirname(require.resolve(\"@x12i/ai-profiles\"));\n const loader = require(join(entry, \"loader/loadAIProfilesRegistry.js\")) as {\n loadAIProfilesRegistry: LoadRegistryFn;\n };\n return loader.loadAIProfilesRegistry({ source: \"auto\" });\n}\n\nexport type AiProfilesModelMatch = {\n provider: string;\n modelId: string;\n canonicalModelId: string;\n pricing?: AIModelPricing;\n instructionTier: InstructionTier;\n backend: AIProfileBackend;\n matchedVia: \"profile\" | \"shortcut\" | \"profile-alias\" | \"model-id\";\n profile?: string;\n choice?: string;\n};\n\nfunction profileKey(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction canonicalModelId(provider: string, modelId: string): string {\n const normalized = normalizeString(modelId);\n if (normalized.includes(\"/\")) return normalized;\n const p = normalizeProvider(provider) ?? normalizeString(provider);\n return `${p}/${normalized}`;\n}\n\ntype IndexedChoice = {\n provider: string;\n modelId: string;\n canonicalModelId: string;\n pricing?: AIModelPricing;\n profile: string;\n choice: string;\n};\n\nlet cachedIndex: {\n cacheKey: string;\n byKey: Map<string, IndexedChoice[]>;\n} | null = null;\n\n/** Index bare model ids only — profile/shortcut names resolve via {@link resolveAIProfile}. */\nfunction indexRegistry(registry: AIProfilesRegistry): Map<string, IndexedChoice[]> {\n const byKey = new Map<string, IndexedChoice[]>();\n\n const add = (key: string, entry: IndexedChoice) => {\n const k = profileKey(key);\n if (!k) return;\n const list = byKey.get(k) ?? [];\n if (\n list.some(\n (e) =>\n e.canonicalModelId === entry.canonicalModelId &&\n e.choice === entry.choice &&\n e.profile === entry.profile,\n )\n ) {\n return;\n }\n list.push(entry);\n byKey.set(k, list);\n };\n\n for (const profile of Object.values(registry.profiles)) {\n for (const [choiceKey, choice] of Object.entries(profile.choices)) {\n const entry = choiceEntry(choice, profile.profile, choiceKey);\n add(choice.modelId, entry);\n add(canonicalModelId(choice.provider, choice.modelId), entry);\n }\n }\n\n return byKey;\n}\n\nfunction choiceEntry(\n choice: AIProfileChoice,\n profile: string,\n choiceKey: string,\n): IndexedChoice {\n const canonical = canonicalModelId(choice.provider, choice.modelId);\n return {\n provider: normalizeProvider(choice.provider) ?? choice.provider,\n modelId: normalizeString(choice.modelId),\n canonicalModelId: canonical,\n pricing: choice.pricing,\n profile,\n choice: choiceKey,\n };\n}\n\nasync function getProfileIndex(): Promise<Map<string, IndexedChoice[]>> {\n const registry = await loadProfilesRegistry();\n const cacheKey = `${registry.version}:${registry.generatedAt ?? \"\"}:${registry.source}`;\n if (cachedIndex?.cacheKey === cacheKey) {\n return cachedIndex.byKey;\n }\n const byKey = indexRegistry(registry);\n cachedIndex = { cacheKey, byKey };\n return byKey;\n}\n\nfunction scoreCandidate(\n entry: IndexedChoice,\n model: string,\n providerHint?: string,\n): number {\n const normalized = normalizeString(model);\n let score = 0;\n\n if (normalized === entry.canonicalModelId) score += 100;\n if (normalized === entry.modelId) score += 80;\n if (providerHint && entry.provider === providerHint) score += 50;\n if (entry.pricing) score += 2;\n\n return score;\n}\n\nfunction pickBest(\n candidates: IndexedChoice[],\n model: string,\n providerHint?: string,\n): IndexedChoice | null {\n if (candidates.length === 0) return null;\n if (candidates.length === 1) return candidates[0]!;\n\n let best = candidates[0]!;\n let bestScore = scoreCandidate(best, model, providerHint);\n for (let i = 1; i < candidates.length; i++) {\n const c = candidates[i]!;\n const s = scoreCandidate(c, model, providerHint);\n if (s > bestScore) {\n best = c;\n bestScore = s;\n }\n }\n return best;\n}\n\nfunction resolvedToMatch(resolved: ResolvedAIProfile): AiProfilesModelMatch {\n return {\n provider: normalizeProvider(resolved.provider) ?? resolved.provider,\n modelId: normalizeString(resolved.modelId),\n canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),\n pricing: resolved.pricing,\n instructionTier: resolved.instructionTier,\n backend: resolved.backend,\n matchedVia: resolved.shortcut ? \"shortcut\" : \"profile\",\n profile: resolved.profile,\n choice: resolved.choice,\n };\n}\n\nasync function fromIndexed(entry: IndexedChoice): Promise<AiProfilesModelMatch> {\n const resolved = await resolveAIProfile(entry.profile, { choice: entry.choice });\n return {\n provider: normalizeProvider(resolved.provider) ?? resolved.provider,\n modelId: normalizeString(resolved.modelId),\n canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),\n pricing: resolved.pricing ?? entry.pricing,\n instructionTier: resolved.instructionTier,\n backend: resolved.backend,\n matchedVia: \"model-id\",\n profile: resolved.profile,\n choice: resolved.choice,\n };\n}\n\nasync function lookupInIndex(\n index: Map<string, IndexedChoice[]>,\n model: string,\n provider?: string,\n): Promise<AiProfilesModelMatch | null> {\n const providerHint = provider ? normalizeProvider(provider) : undefined;\n const keys = [\n profileKey(model),\n profileKey(normalizeString(model)),\n ];\n if (providerHint) {\n keys.push(profileKey(canonicalModelId(providerHint, model)));\n }\n\n const pooled: IndexedChoice[] = [];\n for (const key of keys) {\n const hits = index.get(key);\n if (hits) pooled.push(...hits);\n }\n\n const bare = normalizeString(model);\n if (!bare.includes(\"/\")) {\n for (const list of index.values()) {\n for (const entry of list) {\n if (entry.modelId === bare) pooled.push(entry);\n }\n }\n }\n\n const unique = new Map<string, IndexedChoice>();\n for (const e of pooled) {\n unique.set(`${e.profile}:${e.choice}:${e.canonicalModelId}`, e);\n }\n\n const best = pickBest([...unique.values()], model, providerHint);\n return best ? fromIndexed(best) : null;\n}\n\n/**\n * Resolve a model string via @x12i/ai-profiles — profile/shortcut names, aliases,\n * or a concrete model id that appears on a profile choice.\n */\nexport async function matchModelInAiProfiles(\n model: string,\n provider?: string,\n): Promise<AiProfilesModelMatch | null> {\n try {\n const resolved = await resolveAIProfile(model);\n return resolvedToMatch(resolved);\n } catch (err) {\n if (!(err instanceof AIProfilesError) || err.code !== \"UNKNOWN_PROFILE\") {\n throw err;\n }\n }\n\n const index = await getProfileIndex();\n const hint = providerHintForProfiles(model, provider);\n const direct = await lookupInIndex(index, model, hint);\n if (direct) return direct;\n\n const stripped = stripModelVersionSuffix(model);\n if (stripped && stripped !== normalizeString(model)) {\n return lookupInIndex(\n index,\n stripped,\n providerHintForProfiles(stripped, provider),\n );\n }\n\n return null;\n}\n\n/** @internal Test-only — reset module cache between tests. */\nexport function resetAiProfilesMatchCacheForTests(): void {\n cachedIndex = null;\n}\n","import type { AiModelsCatalogClient } from \"../catalog/AiModelsCatalogClient.js\";\nimport { LOCAL_PROVIDERS } from \"../sync/modelNameResolver/constants.js\";\nimport {\n loadOpenRouterRoutingEnv,\n shouldDefaultRouteViaOpenRouter,\n} from \"../sync/openRouterRoutingEnv.js\";\nimport { normalizeProvider, normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport type {\n ModelResolutionInput,\n ModelResolutionResult,\n ModelResolverOptions,\n} from \"../sync/modelNameResolver/types.js\";\nimport type { OpenRouterRoutingConfig } from \"../sync/openRouterRoutingEnv.js\";\n\nexport function isOpenRouterProvider(provider?: string): boolean {\n return normalizeProvider(provider) === \"openrouter\";\n}\n\nexport function isLocalProvider(provider?: string): boolean {\n const p = normalizeProvider(provider) ?? normalizeString(provider ?? \"\");\n return LOCAL_PROVIDERS.has(p);\n}\n\n/** Catalog resolver returned success without a priced record (Ollama, LM Studio, …). */\nexport function isLocalProviderResolution(\n resolved: ModelResolutionResult | null,\n inputProvider?: string,\n): boolean {\n if (!resolved?.found || resolved.record) return false;\n if (resolved.resolvedVia.includes(\"local-provider-passthrough\")) return true;\n return isLocalProvider(inputProvider);\n}\n\n/**\n * Vendor id for a model slug (`openai/gpt-4o` → `openai`).\n * Ignores `openrouter` as a provider hint — it is a routing layer, not the model owner.\n */\nexport function underlyingProviderFromModel(\n model: string,\n providerHint?: string,\n): string | undefined {\n const normalized = normalizeString(model);\n if (normalized.includes(\"/\")) {\n const prefix = normalized.split(\"/\")[0]!;\n if (!isOpenRouterProvider(prefix)) return prefix;\n }\n if (providerHint && !isOpenRouterProvider(providerHint)) {\n return normalizeProvider(providerHint);\n }\n return undefined;\n}\n\n/** Provider hint for ai-profiles index lookup (openrouter → underlying vendor). */\nexport function providerHintForProfiles(\n model: string,\n provider?: string,\n): string | undefined {\n if (isOpenRouterProvider(provider)) {\n return underlyingProviderFromModel(model, provider);\n }\n return normalizeProvider(provider);\n}\n\n/**\n * Catalog resolve attempts for direct API and OpenRouter usage.\n * Tries the caller hint, inferred vendor, no hint, and openrouter routing.\n */\nexport function buildCatalogResolveAttempts(\n model: string,\n provider?: string,\n): ModelResolutionInput[] {\n const attempts: ModelResolutionInput[] = [];\n const seen = new Set<string>();\n const add = (m: string, p?: string) => {\n const key = `${p ?? \"\"}\\0${normalizeString(m)}`;\n if (seen.has(key)) return;\n seen.add(key);\n attempts.push({ model: m, provider: p });\n };\n\n add(model, provider);\n\n const underlying = underlyingProviderFromModel(model, provider);\n if (provider) add(model, undefined);\n if (underlying) add(model, underlying);\n if (!isOpenRouterProvider(provider)) {\n add(model, \"openrouter\");\n }\n\n return attempts;\n}\n\nexport async function resolveFromCatalogAttempts(\n catalog: AiModelsCatalogClient,\n attempts: ModelResolutionInput[],\n options?: ModelResolverOptions,\n): Promise<ModelResolutionResult | null> {\n let last: ModelResolutionResult | null = null;\n let localPassthrough: ModelResolutionResult | null = null;\n\n for (const attempt of attempts) {\n const result = await catalog.resolveModel(attempt, options);\n last = result;\n if (result.found && result.record) return result;\n if (\n result.found &&\n !result.record &&\n isLocalProviderResolution(result, attempt.provider)\n ) {\n localPassthrough = result;\n }\n }\n\n return localPassthrough ?? last;\n}\n\nexport function resolveRoutedViaOpenRouter(\n inputProvider: string | undefined,\n resolved: ModelResolutionResult | null,\n modelId?: string,\n routingEnv?: OpenRouterRoutingConfig,\n): boolean {\n const env = routingEnv ?? loadOpenRouterRoutingEnv();\n\n if (isOpenRouterProvider(inputProvider)) return true;\n\n if (resolved?.found) {\n return resolved.routedViaOpenRouter;\n }\n\n const vendor = underlyingProviderFromModel(\n modelId ?? (resolved?.found ? resolved.modelId : \"\") ?? \"\",\n inputProvider,\n );\n if (vendor && shouldDefaultRouteViaOpenRouter(vendor, env)) {\n return true;\n }\n\n return false;\n}\n","import type { AIModelPricing } from \"@x12i/ai-profiles\";\nimport {\n DEFAULT_OPENROUTER_MARKUP_RATE,\n PROFILE_TIERED_CONTEXT_THRESHOLD,\n} from \"./constants.js\";\nimport type { AiModelPricing, AiUsageInput } from \"./types.js\";\n\nconst TOKENS_PER_UNIT = 1_000_000;\n\nfunction usdPerToken(perMillion?: number): number {\n return (perMillion ?? 0) / TOKENS_PER_UNIT;\n}\n\nfunction pickInputRatePerMillion(\n pricing: AIModelPricing,\n promptTokens: number,\n): number | undefined {\n if (\n pricing.inputBelow200k !== undefined &&\n pricing.inputAbove200k !== undefined\n ) {\n return promptTokens <= PROFILE_TIERED_CONTEXT_THRESHOLD\n ? pricing.inputBelow200k\n : pricing.inputAbove200k;\n }\n return pricing.input ?? pricing.inputBelow200k ?? pricing.inputAbove200k;\n}\n\nfunction pickOutputRatePerMillion(\n pricing: AIModelPricing,\n promptTokens: number,\n): number | undefined {\n if (\n pricing.outputBelow200k !== undefined &&\n pricing.outputAbove200k !== undefined\n ) {\n return promptTokens <= PROFILE_TIERED_CONTEXT_THRESHOLD\n ? pricing.outputBelow200k\n : pricing.outputAbove200k;\n }\n return pricing.output ?? pricing.outputBelow200k ?? pricing.outputAbove200k;\n}\n\nexport type AiProfilesPricingOptions = {\n promptTokens?: number;\n routedViaOpenRouter?: boolean;\n};\n\nexport function aiProfilesPricingToCatalogPricing(\n pricing: AIModelPricing,\n pricedAt: string,\n options: AiProfilesPricingOptions = {},\n): AiModelPricing {\n const promptTokens = options.promptTokens ?? 0;\n const promptUsdPerToken = usdPerToken(pickInputRatePerMillion(pricing, promptTokens));\n const completionUsdPerToken = usdPerToken(\n pickOutputRatePerMillion(pricing, promptTokens),\n );\n\n const snapshot: AiModelPricing = {\n promptUsdPerToken,\n completionUsdPerToken,\n cacheReadUsdPerToken: usdPerToken(pricing.cachedInput ?? pricing.cacheHit),\n cacheWriteUsdPerToken: usdPerToken(pricing.cacheWrite5m ?? pricing.cacheWrite1h),\n imageUsdPerUnit: 0,\n requestUsdPerRequest: 0,\n pricedAt,\n source: \"manual\",\n };\n\n if (options.routedViaOpenRouter) {\n snapshot.openRouterMarkupUsdPerInputToken =\n promptUsdPerToken * DEFAULT_OPENROUTER_MARKUP_RATE;\n snapshot.openRouterMarkupUsdPerOutputToken =\n completionUsdPerToken * DEFAULT_OPENROUTER_MARKUP_RATE;\n }\n\n return snapshot;\n}\n\nexport function computeCostFromPricing(\n input: AiUsageInput,\n pricing: AiModelPricing,\n routedViaOpenRouter: boolean,\n includeBreakdown: boolean,\n): { cost: number; breakdown?: import(\"./types.js\").AiCostResult[\"breakdown\"] } {\n const { tokens } = input;\n\n let promptCost = tokens.prompt * pricing.promptUsdPerToken;\n let completionCost = tokens.completion * pricing.completionUsdPerToken;\n\n const cachingCost =\n (tokens.cacheWrite ?? 0) * (pricing.cacheWriteUsdPerToken ?? 0) +\n (tokens.cached ?? 0) * (pricing.cacheReadUsdPerToken ?? 0);\n\n const reasoningCost =\n (tokens.reasoning ?? 0) *\n (pricing.reasoningUsdPerToken ?? pricing.promptUsdPerToken);\n\n const audioCost = (tokens.audio ?? 0) * pricing.promptUsdPerToken;\n const imageCost = (tokens.image ?? 0) * (pricing.imageUsdPerUnit ?? 0);\n const requestFlat = pricing.requestUsdPerRequest;\n\n if (routedViaOpenRouter) {\n promptCost +=\n tokens.prompt * (pricing.openRouterMarkupUsdPerInputToken ?? 0);\n completionCost +=\n tokens.completion * (pricing.openRouterMarkupUsdPerOutputToken ?? 0);\n }\n\n const cost =\n promptCost +\n completionCost +\n cachingCost +\n reasoningCost +\n audioCost +\n imageCost +\n requestFlat;\n\n if (!includeBreakdown) {\n return { cost };\n }\n\n return {\n cost,\n breakdown: {\n promptCostUsd: promptCost,\n completionCostUsd: completionCost,\n cachingCostUsd: cachingCost || undefined,\n reasoningCostUsd: reasoningCost || undefined,\n audioCostUsd: audioCost || undefined,\n imageCostUsd: imageCost || undefined,\n requestFlatCostUsd: requestFlat || undefined,\n },\n };\n}\n","import type { AliasRegistry } from \"../aliases/AliasRegistry.js\";\nimport type { AiModelsCatalogClient } from \"../catalog/AiModelsCatalogClient.js\";\nimport { UnknownModelCostError } from \"../errors.js\";\nimport { normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport { stripModelVersionSuffix } from \"../sync/modelNameResolver/stripVersionSuffix.js\";\nimport type {\n ModelResolutionResult,\n ModelResolverOptions,\n} from \"../sync/modelNameResolver/types.js\";\nimport { matchModelInAiProfiles } from \"./aiProfilesMatch.js\";\nimport {\n buildCatalogResolveAttempts,\n isLocalProvider,\n isLocalProviderResolution,\n resolveFromCatalogAttempts,\n resolveRoutedViaOpenRouter,\n} from \"./costModelResolution.js\";\nimport {\n aiProfilesPricingToCatalogPricing,\n computeCostFromPricing,\n} from \"./profilePricing.js\";\nimport { enrichCostResult, toCostExtraction } from \"./enrichCostResult.js\";\nimport {\n extractUsageInput,\n type ExtractUsageInputOptions,\n} from \"./extractUsageInput.js\";\nimport { resolveUsageModel } from \"./resolveUsageModel.js\";\nimport type { AiCostResult, AiCostWarning, AiModelPricing, AiUsageInput } from \"./types.js\";\n\nexport type CostCalculatorOptions = {\n aliasRegistry?: AliasRegistry;\n includeBreakdown?: boolean;\n resolverOptions?: ModelResolverOptions;\n /** When true, throw {@link UnknownModelCostError} instead of zero-cost fallback. */\n throwOnUnknownModel?: boolean;\n};\n\nfunction emptyPricing(): AiModelPricing {\n return {\n promptUsdPerToken: 0,\n completionUsdPerToken: 0,\n imageUsdPerUnit: 0,\n requestUsdPerRequest: 0,\n pricedAt: new Date().toISOString(),\n source: \"manual\",\n };\n}\n\nfunction mergeAttempts(\n ...groups: ReturnType<typeof buildCatalogResolveAttempts>[]\n): ReturnType<typeof buildCatalogResolveAttempts> {\n const seen = new Set<string>();\n const out: ReturnType<typeof buildCatalogResolveAttempts> = [];\n for (const group of groups) {\n for (const a of group) {\n const key = `${a.provider ?? \"\"}\\0${a.model}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(a);\n }\n }\n return out;\n}\n\nexport class CostCalculator {\n private readonly aliasRegistry?: AliasRegistry;\n private readonly includeBreakdown: boolean;\n private readonly resolverOptions?: ModelResolverOptions;\n private readonly throwOnUnknownModel: boolean;\n\n constructor(\n private readonly catalog: AiModelsCatalogClient,\n options: CostCalculatorOptions = {},\n ) {\n this.aliasRegistry = options.aliasRegistry;\n this.includeBreakdown = options.includeBreakdown ?? true;\n this.resolverOptions = options.resolverOptions;\n this.throwOnUnknownModel = options.throwOnUnknownModel ?? false;\n }\n\n /**\n * Extract model, provider, and token usage from an activity / gateway record\n * (MongoDB export, nested `outer`, `config`, `metadata.diagnostics`, etc.)\n * then run {@link calculate}.\n */\n async calculateFromRecord(\n record: unknown,\n extractOptions?: ExtractUsageInputOptions,\n ): Promise<AiCostResult> {\n const { input, provenance } = extractUsageInput(record, extractOptions);\n const warnings: AiCostWarning[] = [];\n if (provenance.tokens.estimated) {\n warnings.push({\n code: \"ESTIMATED_TOKEN_USAGE\",\n message: `Token counts are estimates from ${provenance.tokens.path} (not billed usage).`,\n });\n }\n const result = await this.calculate(input);\n const enriched = enrichCostResult(result, input, toCostExtraction(provenance));\n if (warnings.length > 0) {\n enriched.warnings = [...(enriched.warnings ?? []), ...warnings];\n }\n return enriched;\n }\n\n async calculate(input: AiUsageInput): Promise<AiCostResult> {\n const modelInput = resolveUsageModel(input);\n const resolverOpts = {\n ...this.resolverOptions,\n aliasRegistry: this.aliasRegistry ?? this.resolverOptions?.aliasRegistry,\n };\n\n let resolved = await resolveFromCatalogAttempts(\n this.catalog,\n buildCatalogResolveAttempts(modelInput, input.provider),\n resolverOpts,\n );\n\n if (isLocalProviderResolution(resolved, input.provider)) {\n return this.localProviderResult(modelInput, input, resolved);\n }\n\n let profileMatch = null as Awaited<ReturnType<typeof matchModelInAiProfiles>>;\n const warnings: AiCostWarning[] = [];\n\n if (!resolved?.found || !resolved.record) {\n if (!isLocalProvider(input.provider)) {\n profileMatch = await matchModelInAiProfiles(modelInput, input.provider);\n }\n if (profileMatch) {\n resolved = await resolveFromCatalogAttempts(\n this.catalog,\n mergeAttempts(\n buildCatalogResolveAttempts(\n profileMatch.canonicalModelId,\n input.provider ?? profileMatch.provider,\n ),\n buildCatalogResolveAttempts(\n profileMatch.canonicalModelId,\n profileMatch.provider,\n ),\n ),\n resolverOpts,\n );\n }\n\n if (isLocalProviderResolution(resolved, input.provider)) {\n return this.localProviderResult(modelInput, input, resolved);\n }\n\n if ((!resolved?.found || !resolved.record) && profileMatch?.pricing) {\n const routedViaOpenRouter = resolveRoutedViaOpenRouter(\n input.provider,\n resolved,\n profileMatch.canonicalModelId,\n resolverOpts?.routingEnv,\n );\n const pricing = aiProfilesPricingToCatalogPricing(\n profileMatch.pricing,\n new Date().toISOString(),\n {\n promptTokens: input.tokens.prompt,\n routedViaOpenRouter,\n },\n );\n const { cost, breakdown } = computeCostFromPricing(\n input,\n pricing,\n routedViaOpenRouter,\n this.includeBreakdown,\n );\n\n warnings.push({\n code: \"AI_PROFILES_ESTIMATE\",\n message: `Catalog has no pricing for \"${modelInput}\"; estimated from ai-profiles (${profileMatch.matchedVia} → ${profileMatch.canonicalModelId}).`,\n });\n if (\n routedViaOpenRouter &&\n pricing.openRouterMarkupUsdPerInputToken !== undefined\n ) {\n warnings.push({\n code: \"OPENROUTER_MARKUP_ESTIMATED\",\n message:\n \"OpenRouter markup estimated at 5% of base token rates (catalog markup fields absent).\",\n });\n }\n\n console.warn(`[ai-tools] ${warnings.map((w) => w.message).join(\" \")}`);\n\n return this.finish(\n {\n cost,\n breakdown,\n resolvedModelId: profileMatch.canonicalModelId,\n routedViaOpenRouter,\n isAuthoritative: false,\n pricingSnapshot: pricing,\n source: \"ai-profiles\",\n warnings,\n },\n input,\n resolved,\n );\n }\n }\n\n if (!resolved?.found || !resolved.record) {\n return this.unknownModelResult(modelInput, input, resolved);\n }\n\n const { record, modelId } = resolved;\n const routedViaOpenRouter = resolveRoutedViaOpenRouter(\n input.provider,\n resolved,\n modelId,\n resolverOpts?.routingEnv,\n );\n const pricing = record.pricing;\n const { cost, breakdown } = computeCostFromPricing(\n input,\n pricing,\n routedViaOpenRouter,\n this.includeBreakdown,\n );\n\n return this.finish(\n {\n cost,\n breakdown,\n resolvedModelId: modelId,\n routedViaOpenRouter,\n isAuthoritative: true,\n pricingSnapshot: pricing,\n source: \"catalog\",\n },\n input,\n resolved,\n );\n }\n\n private versionSuffixWarnings(\n input: AiUsageInput,\n pricedModelId: string,\n resolved?: ModelResolutionResult | null,\n ): AiCostWarning[] {\n const received = input.usedModel ?? input.modelUsed ?? input.model;\n if (!received) return [];\n\n const normalizedReceived = normalizeString(received);\n const normalizedPriced = normalizeString(pricedModelId);\n if (normalizedReceived === normalizedPriced) return [];\n\n const stripped = stripModelVersionSuffix(received);\n const viaResolver =\n resolved?.found === true &&\n resolved.resolvedVia.some(\n (s) => s === \"version-suffix-strip\" || s === \"date-suffix-strip\",\n );\n const pricedViaStrip =\n stripped !== null && normalizeString(stripped) === normalizedPriced;\n\n if (!viaResolver && !pricedViaStrip) return [];\n\n return [\n {\n code: \"VERSION_SUFFIX_PRICING\",\n message: `Priced using catalog model \"${pricedModelId}\" (no exact pricing for \"${received}\").`,\n },\n ];\n }\n\n private finish(\n partial: Omit<\n AiCostResult,\n \"usage\" | \"provider\" | \"usedModel\" | \"model\" | \"extraction\"\n >,\n input: AiUsageInput,\n resolved?: ModelResolutionResult | null,\n ): AiCostResult {\n const enriched = enrichCostResult(partial, input);\n const suffixWarnings = this.versionSuffixWarnings(\n input,\n partial.resolvedModelId,\n resolved,\n );\n if (suffixWarnings.length > 0) {\n enriched.warnings = [...(enriched.warnings ?? []), ...suffixWarnings];\n }\n return enriched;\n }\n\n private localProviderResult(\n modelInput: string,\n input: AiUsageInput,\n resolved: Awaited<ReturnType<typeof resolveFromCatalogAttempts>>,\n ): AiCostResult {\n const warnings: AiCostWarning[] = [\n {\n code: \"LOCAL_PROVIDER_NO_PRICING\",\n message: `Local provider \"${input.provider}\" has no catalog pricing for \"${modelInput}\".`,\n },\n ];\n console.warn(`[ai-tools] ${warnings[0]!.message}`);\n return this.finish(\n {\n cost: 0,\n resolvedModelId: resolved?.found ? resolved.modelId : modelInput,\n routedViaOpenRouter: false,\n isAuthoritative: false,\n pricingSnapshot: emptyPricing(),\n source: \"local\",\n warnings,\n },\n input,\n );\n }\n\n private unknownModelResult(\n modelInput: string,\n input: AiUsageInput,\n resolved: Awaited<ReturnType<typeof resolveFromCatalogAttempts>>,\n ): AiCostResult {\n if (this.throwOnUnknownModel) {\n throw new UnknownModelCostError(modelInput, input.provider);\n }\n\n const warnings: AiCostWarning[] = [\n {\n code: \"UNKNOWN_MODEL\",\n message: `Unknown model \"${modelInput}\" (provider: \"${input.provider}\") — returning zero-cost fallback.`,\n },\n ];\n console.warn(`[ai-tools] ${warnings[0]!.message}`);\n\n return this.finish(\n {\n cost: 0,\n resolvedModelId: modelInput,\n routedViaOpenRouter: resolveRoutedViaOpenRouter(\n input.provider,\n resolved,\n modelInput,\n this.resolverOptions?.routingEnv,\n ),\n isAuthoritative: false,\n pricingSnapshot: emptyPricing(),\n source: \"estimate-fallback\",\n unknownModel: true,\n warnings,\n },\n input,\n );\n }\n}\n"],"mappings":"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","names":["require","routedViaOpenRouter","pricing","cost","breakdown"]}
@@ -475,53 +475,22 @@ function indexRegistry(registry) {
475
475
  list.push(entry);
476
476
  byKey.set(k, list);
477
477
  };
478
- for (const shortcutKey of Object.keys(registry.shortcuts)) {
479
- const shortcut = registry.shortcuts[shortcutKey];
480
- const profile = registry.profiles[shortcut.profile];
481
- if (!profile) continue;
482
- const choiceKey = _nullishCoalesce(shortcut.choice, () => ( profile.defaultChoice));
483
- const choice = profile.choices[choiceKey];
484
- if (!choice) continue;
485
- const entry = choiceEntry(choice, profile.profile, choiceKey, "shortcut");
486
- add(shortcutKey, entry);
487
- }
488
478
  for (const profile of Object.values(registry.profiles)) {
489
479
  for (const [choiceKey, choice] of Object.entries(profile.choices)) {
490
- const entry = choiceEntry(choice, profile.profile, choiceKey, "model-id");
480
+ const entry = choiceEntry(choice, profile.profile, choiceKey);
491
481
  add(choice.modelId, entry);
492
482
  add(canonicalModelId(choice.provider, choice.modelId), entry);
493
483
  }
494
- const defaultChoice = profile.choices[profile.defaultChoice];
495
- if (defaultChoice) {
496
- add(
497
- profile.profile,
498
- choiceEntry(defaultChoice, profile.profile, profile.defaultChoice, "profile")
499
- );
500
- }
501
- for (const alias of _nullishCoalesce(profile.aliases, () => ( []))) {
502
- if (defaultChoice) {
503
- add(
504
- alias,
505
- choiceEntry(
506
- defaultChoice,
507
- profile.profile,
508
- profile.defaultChoice,
509
- "profile-alias"
510
- )
511
- );
512
- }
513
- }
514
484
  }
515
485
  return byKey;
516
486
  }
517
- function choiceEntry(choice, profile, choiceKey, matchedVia) {
487
+ function choiceEntry(choice, profile, choiceKey) {
518
488
  const canonical = canonicalModelId(choice.provider, choice.modelId);
519
489
  return {
520
490
  provider: _nullishCoalesce(_chunkEDMCKHO6cjs.normalizeProvider.call(void 0, choice.provider), () => ( choice.provider)),
521
491
  modelId: _chunkEDMCKHO6cjs.normalizeString.call(void 0, choice.modelId),
522
492
  canonicalModelId: canonical,
523
493
  pricing: choice.pricing,
524
- matchedVia,
525
494
  profile,
526
495
  choice: choiceKey
527
496
  };
@@ -542,9 +511,6 @@ function scoreCandidate(entry, model, providerHint) {
542
511
  if (normalized === entry.canonicalModelId) score += 100;
543
512
  if (normalized === entry.modelId) score += 80;
544
513
  if (providerHint && entry.provider === providerHint) score += 50;
545
- if (entry.matchedVia === "model-id") score += 10;
546
- if (entry.matchedVia === "shortcut") score += 5;
547
- if (entry.matchedVia === "profile") score += 3;
548
514
  if (entry.pricing) score += 2;
549
515
  return score;
550
516
  }
@@ -563,18 +529,34 @@ function pickBest(candidates, model, providerHint) {
563
529
  }
564
530
  return best;
565
531
  }
566
- function fromIndexed(entry) {
532
+ function resolvedToMatch(resolved) {
567
533
  return {
568
- provider: entry.provider,
569
- modelId: entry.modelId,
570
- canonicalModelId: entry.canonicalModelId,
571
- pricing: entry.pricing,
572
- matchedVia: entry.matchedVia,
573
- profile: entry.profile,
574
- choice: entry.choice
534
+ provider: _nullishCoalesce(_chunkEDMCKHO6cjs.normalizeProvider.call(void 0, resolved.provider), () => ( resolved.provider)),
535
+ modelId: _chunkEDMCKHO6cjs.normalizeString.call(void 0, resolved.modelId),
536
+ canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),
537
+ pricing: resolved.pricing,
538
+ instructionTier: resolved.instructionTier,
539
+ backend: resolved.backend,
540
+ matchedVia: resolved.shortcut ? "shortcut" : "profile",
541
+ profile: resolved.profile,
542
+ choice: resolved.choice
575
543
  };
576
544
  }
577
- function lookupInIndex(index, model, provider) {
545
+ async function fromIndexed(entry) {
546
+ const resolved = await _aiprofiles.resolveAIProfile.call(void 0, entry.profile, { choice: entry.choice });
547
+ return {
548
+ provider: _nullishCoalesce(_chunkEDMCKHO6cjs.normalizeProvider.call(void 0, resolved.provider), () => ( resolved.provider)),
549
+ modelId: _chunkEDMCKHO6cjs.normalizeString.call(void 0, resolved.modelId),
550
+ canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),
551
+ pricing: _nullishCoalesce(resolved.pricing, () => ( entry.pricing)),
552
+ instructionTier: resolved.instructionTier,
553
+ backend: resolved.backend,
554
+ matchedVia: "model-id",
555
+ profile: resolved.profile,
556
+ choice: resolved.choice
557
+ };
558
+ }
559
+ async function lookupInIndex(index, model, provider) {
578
560
  const providerHint = provider ? _chunkEDMCKHO6cjs.normalizeProvider.call(void 0, provider) : void 0;
579
561
  const keys = [
580
562
  profileKey(model),
@@ -606,15 +588,7 @@ function lookupInIndex(index, model, provider) {
606
588
  async function matchModelInAiProfiles(model, provider) {
607
589
  try {
608
590
  const resolved = await _aiprofiles.resolveAIProfile.call(void 0, model);
609
- return {
610
- provider: _nullishCoalesce(_chunkEDMCKHO6cjs.normalizeProvider.call(void 0, resolved.provider), () => ( resolved.provider)),
611
- modelId: _chunkEDMCKHO6cjs.normalizeString.call(void 0, resolved.modelId),
612
- canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),
613
- pricing: resolved.pricing,
614
- matchedVia: resolved.shortcut ? "shortcut" : "profile",
615
- profile: resolved.profile,
616
- choice: resolved.choice
617
- };
591
+ return resolvedToMatch(resolved);
618
592
  } catch (err) {
619
593
  if (!(err instanceof _aiprofiles.AIProfilesError) || err.code !== "UNKNOWN_PROFILE") {
620
594
  throw err;
@@ -622,11 +596,15 @@ async function matchModelInAiProfiles(model, provider) {
622
596
  }
623
597
  const index = await getProfileIndex();
624
598
  const hint = providerHintForProfiles(model, provider);
625
- const direct = lookupInIndex(index, model, hint);
599
+ const direct = await lookupInIndex(index, model, hint);
626
600
  if (direct) return direct;
627
601
  const stripped = _chunkEDMCKHO6cjs.stripModelVersionSuffix.call(void 0, model);
628
602
  if (stripped && stripped !== _chunkEDMCKHO6cjs.normalizeString.call(void 0, model)) {
629
- return lookupInIndex(index, stripped, providerHintForProfiles(stripped, provider));
603
+ return lookupInIndex(
604
+ index,
605
+ stripped,
606
+ providerHintForProfiles(stripped, provider)
607
+ );
630
608
  }
631
609
  return null;
632
610
  }
@@ -970,4 +948,4 @@ var CostCalculator = class {
970
948
 
971
949
 
972
950
  exports.DEFAULT_OPENROUTER_MARKUP_RATE = DEFAULT_OPENROUTER_MARKUP_RATE; exports.toCostExtraction = toCostExtraction; exports.enrichCostResult = enrichCostResult; exports.MODEL_FIELD_PRIORITY = MODEL_FIELD_PRIORITY; exports.extractUsageInput = extractUsageInput; exports.resolveUsageModel = resolveUsageModel; exports.CostCalculator = CostCalculator;
973
- //# sourceMappingURL=chunk-NF2SKQR7.cjs.map
951
+ //# sourceMappingURL=chunk-WOHMHXRZ.cjs.map