@x12i/ai-tools 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AiModelsCatalogClient-B5FMI9gj.d.cts → AiModelsCatalogClient-C9ZJHhv3.d.ts} +4 -1
- package/dist/{AiModelsCatalogClient-CPPNI6Ry.d.ts → AiModelsCatalogClient-DgBdVFk-.d.cts} +4 -1
- package/dist/aliases/index.d.cts +3 -3
- package/dist/aliases/index.d.ts +3 -3
- package/dist/catalog/index.cjs +6 -5
- package/dist/catalog/index.cjs.map +1 -1
- package/dist/catalog/index.d.cts +4 -4
- package/dist/catalog/index.d.ts +4 -4
- package/dist/catalog/index.js +5 -4
- package/dist/{chunk-EYHMQVAL.js → chunk-54GKLIDW.js} +22 -10
- package/dist/chunk-54GKLIDW.js.map +1 -0
- package/dist/chunk-5IZ7PLY2.cjs +51 -0
- package/dist/chunk-5IZ7PLY2.cjs.map +1 -0
- package/dist/{chunk-XAWBTX3N.cjs → chunk-75ZVXZAV.cjs} +7 -7
- package/dist/{chunk-XAWBTX3N.cjs.map → chunk-75ZVXZAV.cjs.map} +1 -1
- package/dist/{chunk-YQDSN6R6.cjs → chunk-76FHWQH3.cjs} +3 -3
- package/dist/{chunk-YQDSN6R6.cjs.map → chunk-76FHWQH3.cjs.map} +1 -1
- package/dist/{chunk-EDMCKHO6.cjs → chunk-BCX5CLJJ.cjs} +15 -2
- package/dist/chunk-BCX5CLJJ.cjs.map +1 -0
- package/dist/{chunk-OPN6BGNH.js → chunk-D6OIUYNC.js} +117 -5
- package/dist/{chunk-OPN6BGNH.js.map → chunk-D6OIUYNC.js.map} +1 -1
- package/dist/{chunk-NF2SKQR7.cjs → chunk-DDRWORUU.cjs} +30 -298
- package/dist/chunk-DDRWORUU.cjs.map +1 -0
- package/dist/{chunk-5XAAMBDO.cjs → chunk-HBNYVRLZ.cjs} +123 -11
- package/dist/chunk-HBNYVRLZ.cjs.map +1 -0
- package/dist/chunk-HEB73GKJ.js +263 -0
- package/dist/chunk-HEB73GKJ.js.map +1 -0
- package/dist/{chunk-VJHLO2R3.js → chunk-KSJSLKYI.js} +2 -2
- package/dist/{chunk-SIH4GPV4.js → chunk-MOLWV5LV.js} +2 -2
- package/dist/{chunk-U2YDDUVP.js → chunk-PN4FF6YF.js} +10 -275
- package/dist/chunk-PN4FF6YF.js.map +1 -0
- package/dist/{chunk-DXZOL3VN.cjs → chunk-RSHI4OOY.cjs} +46 -34
- package/dist/chunk-RSHI4OOY.cjs.map +1 -0
- package/dist/{chunk-B3V2EHRY.js → chunk-SLSKQRMI.js} +15 -2
- package/dist/{chunk-B3V2EHRY.js.map → chunk-SLSKQRMI.js.map} +1 -1
- package/dist/{chunk-XOKUDUUI.cjs → chunk-TMA6QSNH.cjs} +3 -3
- package/dist/{chunk-XOKUDUUI.cjs.map → chunk-TMA6QSNH.cjs.map} +1 -1
- package/dist/{chunk-6BQBKROR.js → chunk-VBROBIVI.js} +3 -3
- package/dist/{chunk-6BQBKROR.js.map → chunk-VBROBIVI.js.map} +1 -1
- package/dist/chunk-WSUFQR3D.cjs +266 -0
- package/dist/chunk-WSUFQR3D.cjs.map +1 -0
- package/dist/{chunk-PRCICORG.cjs → chunk-X42KFOUO.cjs} +6 -6
- package/dist/{chunk-PRCICORG.cjs.map → chunk-X42KFOUO.cjs.map} +1 -1
- package/dist/chunk-YQVY7CWT.js +51 -0
- package/dist/chunk-YQVY7CWT.js.map +1 -0
- package/dist/{chunk-AB5GNXJ4.js → chunk-ZPUZ7DBO.js} +2 -2
- package/dist/cli/index.cjs +16 -15
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +7 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/cost/index.cjs +4 -3
- package/dist/cost/index.cjs.map +1 -1
- package/dist/cost/index.d.cts +4 -4
- package/dist/cost/index.d.ts +4 -4
- package/dist/cost/index.js +3 -2
- package/dist/index.cjs +28 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -6
- package/dist/index.d.ts +8 -6
- package/dist/index.js +33 -16
- package/dist/{modelCache-CJftI-Ko.d.cts → modelCache-sL3dBfRM.d.cts} +1 -1
- package/dist/{modelCache-BzRn6t_C.d.ts → modelCache-xzoTUue2.d.ts} +1 -1
- package/dist/{modelNameResolver-5XkBMctP.d.ts → modelNameResolver-2WroQlqt.d.ts} +2 -1
- package/dist/{modelNameResolver-C5CSTGFF.d.cts → modelNameResolver-Bxlehrbp.d.cts} +2 -1
- package/dist/models/index.cjs +7 -6
- package/dist/models/index.cjs.map +1 -1
- package/dist/models/index.d.cts +3 -3
- package/dist/models/index.d.ts +3 -3
- package/dist/models/index.js +9 -8
- package/dist/profiles/index.cjs +18 -0
- package/dist/profiles/index.cjs.map +1 -0
- package/dist/profiles/index.d.cts +40 -0
- package/dist/profiles/index.d.ts +40 -0
- package/dist/profiles/index.js +17 -0
- package/dist/profiles/index.js.map +1 -0
- package/dist/{resolveUsageModel-BFwf80Hz.d.ts → resolveUsageModel-DrFuiuIW.d.ts} +2 -2
- package/dist/{resolveUsageModel-C_YmGR1M.d.cts → resolveUsageModel-xKZ2QpHy.d.cts} +2 -2
- package/dist/sync/index.cjs +7 -5
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +3 -3
- package/dist/sync/index.d.ts +3 -3
- package/dist/sync/index.js +6 -4
- package/dist/{types-BrzJWsTU.d.ts → types-BZYGjN2O.d.cts} +21 -2
- package/dist/{types-BrzJWsTU.d.cts → types-BZYGjN2O.d.ts} +21 -2
- package/package.json +7 -2
- package/dist/chunk-5XAAMBDO.cjs.map +0 -1
- package/dist/chunk-DXZOL3VN.cjs.map +0 -1
- package/dist/chunk-EDMCKHO6.cjs.map +0 -1
- package/dist/chunk-EYHMQVAL.js.map +0 -1
- package/dist/chunk-NF2SKQR7.cjs.map +0 -1
- package/dist/chunk-U2YDDUVP.js.map +0 -1
- /package/dist/{chunk-VJHLO2R3.js.map → chunk-KSJSLKYI.js.map} +0 -0
- /package/dist/{chunk-SIH4GPV4.js.map → chunk-MOLWV5LV.js.map} +0 -0
- /package/dist/{chunk-AB5GNXJ4.js.map → chunk-ZPUZ7DBO.js.map} +0 -0
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var _chunkWSUFQR3Dcjs = require('./chunk-WSUFQR3D.cjs');
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
var _chunkBCX5CLJJcjs = require('./chunk-BCX5CLJJ.cjs');
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
var
|
|
15
|
+
var _chunkPADNCGZBcjs = require('./chunk-PADNCGZB.cjs');
|
|
15
16
|
|
|
16
17
|
// src/cost/constants.ts
|
|
17
18
|
var DEFAULT_OPENROUTER_MARKUP_RATE = 0.05;
|
|
@@ -362,275 +363,6 @@ function resolveUsageModel(input) {
|
|
|
362
363
|
return value.trim();
|
|
363
364
|
}
|
|
364
365
|
|
|
365
|
-
// src/cost/aiProfilesMatch.ts
|
|
366
|
-
var _module = require('module');
|
|
367
|
-
var _path = require('path');
|
|
368
|
-
var _aiprofiles = require('@x12i/ai-profiles');
|
|
369
|
-
|
|
370
|
-
// src/cost/costModelResolution.ts
|
|
371
|
-
function isOpenRouterProvider(provider) {
|
|
372
|
-
return _chunkEDMCKHO6cjs.normalizeProvider.call(void 0, provider) === "openrouter";
|
|
373
|
-
}
|
|
374
|
-
function isLocalProvider(provider) {
|
|
375
|
-
const p = _nullishCoalesce(_chunkEDMCKHO6cjs.normalizeProvider.call(void 0, provider), () => ( _chunkEDMCKHO6cjs.normalizeString.call(void 0, _nullishCoalesce(provider, () => ( "")))));
|
|
376
|
-
return _chunkEDMCKHO6cjs.LOCAL_PROVIDERS.has(p);
|
|
377
|
-
}
|
|
378
|
-
function isLocalProviderResolution(resolved, inputProvider) {
|
|
379
|
-
if (!_optionalChain([resolved, 'optionalAccess', _11 => _11.found]) || resolved.record) return false;
|
|
380
|
-
if (resolved.resolvedVia.includes("local-provider-passthrough")) return true;
|
|
381
|
-
return isLocalProvider(inputProvider);
|
|
382
|
-
}
|
|
383
|
-
function underlyingProviderFromModel(model, providerHint) {
|
|
384
|
-
const normalized = _chunkEDMCKHO6cjs.normalizeString.call(void 0, model);
|
|
385
|
-
if (normalized.includes("/")) {
|
|
386
|
-
const prefix = normalized.split("/")[0];
|
|
387
|
-
if (!isOpenRouterProvider(prefix)) return prefix;
|
|
388
|
-
}
|
|
389
|
-
if (providerHint && !isOpenRouterProvider(providerHint)) {
|
|
390
|
-
return _chunkEDMCKHO6cjs.normalizeProvider.call(void 0, providerHint);
|
|
391
|
-
}
|
|
392
|
-
return void 0;
|
|
393
|
-
}
|
|
394
|
-
function providerHintForProfiles(model, provider) {
|
|
395
|
-
if (isOpenRouterProvider(provider)) {
|
|
396
|
-
return underlyingProviderFromModel(model, provider);
|
|
397
|
-
}
|
|
398
|
-
return _chunkEDMCKHO6cjs.normalizeProvider.call(void 0, provider);
|
|
399
|
-
}
|
|
400
|
-
function buildCatalogResolveAttempts(model, provider) {
|
|
401
|
-
const attempts = [];
|
|
402
|
-
const seen = /* @__PURE__ */ new Set();
|
|
403
|
-
const add = (m, p) => {
|
|
404
|
-
const key = `${_nullishCoalesce(p, () => ( ""))}\0${_chunkEDMCKHO6cjs.normalizeString.call(void 0, m)}`;
|
|
405
|
-
if (seen.has(key)) return;
|
|
406
|
-
seen.add(key);
|
|
407
|
-
attempts.push({ model: m, provider: p });
|
|
408
|
-
};
|
|
409
|
-
add(model, provider);
|
|
410
|
-
const underlying = underlyingProviderFromModel(model, provider);
|
|
411
|
-
if (provider) add(model, void 0);
|
|
412
|
-
if (underlying) add(model, underlying);
|
|
413
|
-
if (!isOpenRouterProvider(provider)) {
|
|
414
|
-
add(model, "openrouter");
|
|
415
|
-
}
|
|
416
|
-
return attempts;
|
|
417
|
-
}
|
|
418
|
-
async function resolveFromCatalogAttempts(catalog, attempts, options) {
|
|
419
|
-
let last = null;
|
|
420
|
-
let localPassthrough = null;
|
|
421
|
-
for (const attempt of attempts) {
|
|
422
|
-
const result = await catalog.resolveModel(attempt, options);
|
|
423
|
-
last = result;
|
|
424
|
-
if (result.found && result.record) return result;
|
|
425
|
-
if (result.found && !result.record && isLocalProviderResolution(result, attempt.provider)) {
|
|
426
|
-
localPassthrough = result;
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
return _nullishCoalesce(localPassthrough, () => ( last));
|
|
430
|
-
}
|
|
431
|
-
function resolveRoutedViaOpenRouter(inputProvider, resolved, modelId, routingEnv) {
|
|
432
|
-
const env = _nullishCoalesce(routingEnv, () => ( _chunkEDMCKHO6cjs.loadOpenRouterRoutingEnv.call(void 0, )));
|
|
433
|
-
if (isOpenRouterProvider(inputProvider)) return true;
|
|
434
|
-
if (_optionalChain([resolved, 'optionalAccess', _12 => _12.found])) {
|
|
435
|
-
return resolved.routedViaOpenRouter;
|
|
436
|
-
}
|
|
437
|
-
const vendor = underlyingProviderFromModel(
|
|
438
|
-
_nullishCoalesce(_nullishCoalesce(modelId, () => ( (_optionalChain([resolved, 'optionalAccess', _13 => _13.found]) ? resolved.modelId : ""))), () => ( "")),
|
|
439
|
-
inputProvider
|
|
440
|
-
);
|
|
441
|
-
if (vendor && _chunkEDMCKHO6cjs.shouldDefaultRouteViaOpenRouter.call(void 0, vendor, env)) {
|
|
442
|
-
return true;
|
|
443
|
-
}
|
|
444
|
-
return false;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// src/cost/aiProfilesMatch.ts
|
|
448
|
-
var require2 = _module.createRequire.call(void 0, _chunkGS7T56RPcjs.importMetaUrl);
|
|
449
|
-
function loadProfilesRegistry() {
|
|
450
|
-
const entry = _path.dirname.call(void 0, require2.resolve("@x12i/ai-profiles"));
|
|
451
|
-
const loader = require2(_path.join.call(void 0, entry, "loader/loadAIProfilesRegistry.js"));
|
|
452
|
-
return loader.loadAIProfilesRegistry({ source: "auto" });
|
|
453
|
-
}
|
|
454
|
-
function profileKey(value) {
|
|
455
|
-
return value.trim().toLowerCase();
|
|
456
|
-
}
|
|
457
|
-
function canonicalModelId(provider, modelId) {
|
|
458
|
-
const normalized = _chunkEDMCKHO6cjs.normalizeString.call(void 0, modelId);
|
|
459
|
-
if (normalized.includes("/")) return normalized;
|
|
460
|
-
const p = _nullishCoalesce(_chunkEDMCKHO6cjs.normalizeProvider.call(void 0, provider), () => ( _chunkEDMCKHO6cjs.normalizeString.call(void 0, provider)));
|
|
461
|
-
return `${p}/${normalized}`;
|
|
462
|
-
}
|
|
463
|
-
var cachedIndex = null;
|
|
464
|
-
function indexRegistry(registry) {
|
|
465
|
-
const byKey = /* @__PURE__ */ new Map();
|
|
466
|
-
const add = (key, entry) => {
|
|
467
|
-
const k = profileKey(key);
|
|
468
|
-
if (!k) return;
|
|
469
|
-
const list = _nullishCoalesce(byKey.get(k), () => ( []));
|
|
470
|
-
if (list.some(
|
|
471
|
-
(e) => e.canonicalModelId === entry.canonicalModelId && e.choice === entry.choice && e.profile === entry.profile
|
|
472
|
-
)) {
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
|
-
list.push(entry);
|
|
476
|
-
byKey.set(k, list);
|
|
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
|
-
for (const profile of Object.values(registry.profiles)) {
|
|
489
|
-
for (const [choiceKey, choice] of Object.entries(profile.choices)) {
|
|
490
|
-
const entry = choiceEntry(choice, profile.profile, choiceKey, "model-id");
|
|
491
|
-
add(choice.modelId, entry);
|
|
492
|
-
add(canonicalModelId(choice.provider, choice.modelId), entry);
|
|
493
|
-
}
|
|
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
|
-
}
|
|
515
|
-
return byKey;
|
|
516
|
-
}
|
|
517
|
-
function choiceEntry(choice, profile, choiceKey, matchedVia) {
|
|
518
|
-
const canonical = canonicalModelId(choice.provider, choice.modelId);
|
|
519
|
-
return {
|
|
520
|
-
provider: _nullishCoalesce(_chunkEDMCKHO6cjs.normalizeProvider.call(void 0, choice.provider), () => ( choice.provider)),
|
|
521
|
-
modelId: _chunkEDMCKHO6cjs.normalizeString.call(void 0, choice.modelId),
|
|
522
|
-
canonicalModelId: canonical,
|
|
523
|
-
pricing: choice.pricing,
|
|
524
|
-
matchedVia,
|
|
525
|
-
profile,
|
|
526
|
-
choice: choiceKey
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
|
-
async function getProfileIndex() {
|
|
530
|
-
const registry = await loadProfilesRegistry();
|
|
531
|
-
const cacheKey = `${registry.version}:${_nullishCoalesce(registry.generatedAt, () => ( ""))}:${registry.source}`;
|
|
532
|
-
if (_optionalChain([cachedIndex, 'optionalAccess', _14 => _14.cacheKey]) === cacheKey) {
|
|
533
|
-
return cachedIndex.byKey;
|
|
534
|
-
}
|
|
535
|
-
const byKey = indexRegistry(registry);
|
|
536
|
-
cachedIndex = { cacheKey, byKey };
|
|
537
|
-
return byKey;
|
|
538
|
-
}
|
|
539
|
-
function scoreCandidate(entry, model, providerHint) {
|
|
540
|
-
const normalized = _chunkEDMCKHO6cjs.normalizeString.call(void 0, model);
|
|
541
|
-
let score = 0;
|
|
542
|
-
if (normalized === entry.canonicalModelId) score += 100;
|
|
543
|
-
if (normalized === entry.modelId) score += 80;
|
|
544
|
-
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
|
-
if (entry.pricing) score += 2;
|
|
549
|
-
return score;
|
|
550
|
-
}
|
|
551
|
-
function pickBest(candidates, model, providerHint) {
|
|
552
|
-
if (candidates.length === 0) return null;
|
|
553
|
-
if (candidates.length === 1) return candidates[0];
|
|
554
|
-
let best = candidates[0];
|
|
555
|
-
let bestScore = scoreCandidate(best, model, providerHint);
|
|
556
|
-
for (let i = 1; i < candidates.length; i++) {
|
|
557
|
-
const c = candidates[i];
|
|
558
|
-
const s = scoreCandidate(c, model, providerHint);
|
|
559
|
-
if (s > bestScore) {
|
|
560
|
-
best = c;
|
|
561
|
-
bestScore = s;
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
return best;
|
|
565
|
-
}
|
|
566
|
-
function fromIndexed(entry) {
|
|
567
|
-
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
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
function lookupInIndex(index, model, provider) {
|
|
578
|
-
const providerHint = provider ? _chunkEDMCKHO6cjs.normalizeProvider.call(void 0, provider) : void 0;
|
|
579
|
-
const keys = [
|
|
580
|
-
profileKey(model),
|
|
581
|
-
profileKey(_chunkEDMCKHO6cjs.normalizeString.call(void 0, model))
|
|
582
|
-
];
|
|
583
|
-
if (providerHint) {
|
|
584
|
-
keys.push(profileKey(canonicalModelId(providerHint, model)));
|
|
585
|
-
}
|
|
586
|
-
const pooled = [];
|
|
587
|
-
for (const key of keys) {
|
|
588
|
-
const hits = index.get(key);
|
|
589
|
-
if (hits) pooled.push(...hits);
|
|
590
|
-
}
|
|
591
|
-
const bare = _chunkEDMCKHO6cjs.normalizeString.call(void 0, model);
|
|
592
|
-
if (!bare.includes("/")) {
|
|
593
|
-
for (const list of index.values()) {
|
|
594
|
-
for (const entry of list) {
|
|
595
|
-
if (entry.modelId === bare) pooled.push(entry);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
const unique = /* @__PURE__ */ new Map();
|
|
600
|
-
for (const e of pooled) {
|
|
601
|
-
unique.set(`${e.profile}:${e.choice}:${e.canonicalModelId}`, e);
|
|
602
|
-
}
|
|
603
|
-
const best = pickBest([...unique.values()], model, providerHint);
|
|
604
|
-
return best ? fromIndexed(best) : null;
|
|
605
|
-
}
|
|
606
|
-
async function matchModelInAiProfiles(model, provider) {
|
|
607
|
-
try {
|
|
608
|
-
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
|
-
};
|
|
618
|
-
} catch (err) {
|
|
619
|
-
if (!(err instanceof _aiprofiles.AIProfilesError) || err.code !== "UNKNOWN_PROFILE") {
|
|
620
|
-
throw err;
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
const index = await getProfileIndex();
|
|
624
|
-
const hint = providerHintForProfiles(model, provider);
|
|
625
|
-
const direct = lookupInIndex(index, model, hint);
|
|
626
|
-
if (direct) return direct;
|
|
627
|
-
const stripped = _chunkEDMCKHO6cjs.stripModelVersionSuffix.call(void 0, model);
|
|
628
|
-
if (stripped && stripped !== _chunkEDMCKHO6cjs.normalizeString.call(void 0, model)) {
|
|
629
|
-
return lookupInIndex(index, stripped, providerHintForProfiles(stripped, provider));
|
|
630
|
-
}
|
|
631
|
-
return null;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
366
|
// src/cost/profilePricing.ts
|
|
635
367
|
var TOKENS_PER_UNIT = 1e6;
|
|
636
368
|
function usdPerToken(perMillion) {
|
|
@@ -763,31 +495,31 @@ var CostCalculator = class {
|
|
|
763
495
|
const modelInput = resolveUsageModel(input);
|
|
764
496
|
const resolverOpts = {
|
|
765
497
|
...this.resolverOptions,
|
|
766
|
-
aliasRegistry: _nullishCoalesce(this.aliasRegistry, () => ( _optionalChain([this, 'access',
|
|
498
|
+
aliasRegistry: _nullishCoalesce(this.aliasRegistry, () => ( _optionalChain([this, 'access', _11 => _11.resolverOptions, 'optionalAccess', _12 => _12.aliasRegistry])))
|
|
767
499
|
};
|
|
768
|
-
let resolved = await resolveFromCatalogAttempts(
|
|
500
|
+
let resolved = await _chunkWSUFQR3Dcjs.resolveFromCatalogAttempts.call(void 0,
|
|
769
501
|
this.catalog,
|
|
770
|
-
buildCatalogResolveAttempts(modelInput, input.provider),
|
|
502
|
+
_chunkWSUFQR3Dcjs.buildCatalogResolveAttempts.call(void 0, modelInput, input.provider),
|
|
771
503
|
resolverOpts
|
|
772
504
|
);
|
|
773
|
-
if (isLocalProviderResolution(resolved, input.provider)) {
|
|
505
|
+
if (_chunkWSUFQR3Dcjs.isLocalProviderResolution.call(void 0, resolved, input.provider)) {
|
|
774
506
|
return this.localProviderResult(modelInput, input, resolved);
|
|
775
507
|
}
|
|
776
508
|
let profileMatch = null;
|
|
777
509
|
const warnings = [];
|
|
778
|
-
if (!_optionalChain([resolved, 'optionalAccess',
|
|
779
|
-
if (!isLocalProvider(input.provider)) {
|
|
780
|
-
profileMatch = await matchModelInAiProfiles(modelInput, input.provider);
|
|
510
|
+
if (!_optionalChain([resolved, 'optionalAccess', _13 => _13.found]) || !resolved.record) {
|
|
511
|
+
if (!_chunkWSUFQR3Dcjs.isLocalProvider.call(void 0, input.provider)) {
|
|
512
|
+
profileMatch = await _chunkWSUFQR3Dcjs.matchModelInAiProfiles.call(void 0, modelInput, input.provider);
|
|
781
513
|
}
|
|
782
514
|
if (profileMatch) {
|
|
783
|
-
resolved = await resolveFromCatalogAttempts(
|
|
515
|
+
resolved = await _chunkWSUFQR3Dcjs.resolveFromCatalogAttempts.call(void 0,
|
|
784
516
|
this.catalog,
|
|
785
517
|
mergeAttempts(
|
|
786
|
-
buildCatalogResolveAttempts(
|
|
518
|
+
_chunkWSUFQR3Dcjs.buildCatalogResolveAttempts.call(void 0,
|
|
787
519
|
profileMatch.canonicalModelId,
|
|
788
520
|
_nullishCoalesce(input.provider, () => ( profileMatch.provider))
|
|
789
521
|
),
|
|
790
|
-
buildCatalogResolveAttempts(
|
|
522
|
+
_chunkWSUFQR3Dcjs.buildCatalogResolveAttempts.call(void 0,
|
|
791
523
|
profileMatch.canonicalModelId,
|
|
792
524
|
profileMatch.provider
|
|
793
525
|
)
|
|
@@ -795,15 +527,15 @@ var CostCalculator = class {
|
|
|
795
527
|
resolverOpts
|
|
796
528
|
);
|
|
797
529
|
}
|
|
798
|
-
if (isLocalProviderResolution(resolved, input.provider)) {
|
|
530
|
+
if (_chunkWSUFQR3Dcjs.isLocalProviderResolution.call(void 0, resolved, input.provider)) {
|
|
799
531
|
return this.localProviderResult(modelInput, input, resolved);
|
|
800
532
|
}
|
|
801
|
-
if ((!_optionalChain([resolved, 'optionalAccess',
|
|
802
|
-
const routedViaOpenRouter2 = resolveRoutedViaOpenRouter(
|
|
533
|
+
if ((!_optionalChain([resolved, 'optionalAccess', _14 => _14.found]) || !resolved.record) && _optionalChain([profileMatch, 'optionalAccess', _15 => _15.pricing])) {
|
|
534
|
+
const routedViaOpenRouter2 = _chunkWSUFQR3Dcjs.resolveRoutedViaOpenRouter.call(void 0,
|
|
803
535
|
input.provider,
|
|
804
536
|
resolved,
|
|
805
537
|
profileMatch.canonicalModelId,
|
|
806
|
-
_optionalChain([resolverOpts, 'optionalAccess',
|
|
538
|
+
_optionalChain([resolverOpts, 'optionalAccess', _16 => _16.routingEnv])
|
|
807
539
|
);
|
|
808
540
|
const pricing2 = aiProfilesPricingToCatalogPricing(
|
|
809
541
|
profileMatch.pricing,
|
|
@@ -846,15 +578,15 @@ var CostCalculator = class {
|
|
|
846
578
|
);
|
|
847
579
|
}
|
|
848
580
|
}
|
|
849
|
-
if (!_optionalChain([resolved, 'optionalAccess',
|
|
581
|
+
if (!_optionalChain([resolved, 'optionalAccess', _17 => _17.found]) || !resolved.record) {
|
|
850
582
|
return this.unknownModelResult(modelInput, input, resolved);
|
|
851
583
|
}
|
|
852
584
|
const { record, modelId } = resolved;
|
|
853
|
-
const routedViaOpenRouter = resolveRoutedViaOpenRouter(
|
|
585
|
+
const routedViaOpenRouter = _chunkWSUFQR3Dcjs.resolveRoutedViaOpenRouter.call(void 0,
|
|
854
586
|
input.provider,
|
|
855
587
|
resolved,
|
|
856
588
|
modelId,
|
|
857
|
-
_optionalChain([resolverOpts, 'optionalAccess',
|
|
589
|
+
_optionalChain([resolverOpts, 'optionalAccess', _18 => _18.routingEnv])
|
|
858
590
|
);
|
|
859
591
|
const pricing = record.pricing;
|
|
860
592
|
const { cost, breakdown } = computeCostFromPricing(
|
|
@@ -880,14 +612,14 @@ var CostCalculator = class {
|
|
|
880
612
|
versionSuffixWarnings(input, pricedModelId, resolved) {
|
|
881
613
|
const received = _nullishCoalesce(_nullishCoalesce(input.usedModel, () => ( input.modelUsed)), () => ( input.model));
|
|
882
614
|
if (!received) return [];
|
|
883
|
-
const normalizedReceived =
|
|
884
|
-
const normalizedPriced =
|
|
615
|
+
const normalizedReceived = _chunkBCX5CLJJcjs.normalizeString.call(void 0, received);
|
|
616
|
+
const normalizedPriced = _chunkBCX5CLJJcjs.normalizeString.call(void 0, pricedModelId);
|
|
885
617
|
if (normalizedReceived === normalizedPriced) return [];
|
|
886
|
-
const stripped =
|
|
887
|
-
const viaResolver = _optionalChain([resolved, 'optionalAccess',
|
|
618
|
+
const stripped = _chunkBCX5CLJJcjs.stripModelVersionSuffix.call(void 0, received);
|
|
619
|
+
const viaResolver = _optionalChain([resolved, 'optionalAccess', _19 => _19.found]) === true && resolved.resolvedVia.some(
|
|
888
620
|
(s) => s === "version-suffix-strip" || s === "date-suffix-strip"
|
|
889
621
|
);
|
|
890
|
-
const pricedViaStrip = stripped !== null &&
|
|
622
|
+
const pricedViaStrip = stripped !== null && _chunkBCX5CLJJcjs.normalizeString.call(void 0, stripped) === normalizedPriced;
|
|
891
623
|
if (!viaResolver && !pricedViaStrip) return [];
|
|
892
624
|
return [
|
|
893
625
|
{
|
|
@@ -919,7 +651,7 @@ var CostCalculator = class {
|
|
|
919
651
|
return this.finish(
|
|
920
652
|
{
|
|
921
653
|
cost: 0,
|
|
922
|
-
resolvedModelId: _optionalChain([resolved, 'optionalAccess',
|
|
654
|
+
resolvedModelId: _optionalChain([resolved, 'optionalAccess', _20 => _20.found]) ? resolved.modelId : modelInput,
|
|
923
655
|
routedViaOpenRouter: false,
|
|
924
656
|
isAuthoritative: false,
|
|
925
657
|
pricingSnapshot: emptyPricing(),
|
|
@@ -944,11 +676,11 @@ var CostCalculator = class {
|
|
|
944
676
|
{
|
|
945
677
|
cost: 0,
|
|
946
678
|
resolvedModelId: modelInput,
|
|
947
|
-
routedViaOpenRouter: resolveRoutedViaOpenRouter(
|
|
679
|
+
routedViaOpenRouter: _chunkWSUFQR3Dcjs.resolveRoutedViaOpenRouter.call(void 0,
|
|
948
680
|
input.provider,
|
|
949
681
|
resolved,
|
|
950
682
|
modelInput,
|
|
951
|
-
_optionalChain([this, 'access',
|
|
683
|
+
_optionalChain([this, 'access', _21 => _21.resolverOptions, 'optionalAccess', _22 => _22.routingEnv])
|
|
952
684
|
),
|
|
953
685
|
isAuthoritative: false,
|
|
954
686
|
pricingSnapshot: emptyPricing(),
|
|
@@ -970,4 +702,4 @@ var CostCalculator = class {
|
|
|
970
702
|
|
|
971
703
|
|
|
972
704
|
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-
|
|
705
|
+
//# sourceMappingURL=chunk-DDRWORUU.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-DDRWORUU.cjs","../src/cost/constants.ts","../src/cost/enrichCostResult.ts","../src/cost/extractUsageInput.ts","../src/cost/resolveUsageModel.ts","../src/cost/profilePricing.ts","../src/cost/CostCalculator.ts"],"names":["routedViaOpenRouter","pricing","cost","breakdown"],"mappings":"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","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-DDRWORUU.cjs","sourcesContent":[null,"/** 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 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"]}
|