sidekick-shared 0.28.3 → 0.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +86 -0
- package/README.md +188 -27
- package/dist/aggregation/EventAggregator.d.ts +19 -0
- package/dist/aggregation/EventAggregator.js +174 -35
- package/dist/aggregation/snapshot.d.ts +37 -8
- package/dist/aggregation/snapshot.js +31 -9
- package/dist/aggregation/types.d.ts +13 -0
- package/dist/authStatus.d.ts +54 -0
- package/dist/authStatus.js +91 -0
- package/dist/browser.d.ts +16 -6
- package/dist/browser.js +24 -2
- package/dist/codex.d.ts +23 -0
- package/dist/codex.js +44 -0
- package/dist/codexProfiles.d.ts +1 -0
- package/dist/codexProfiles.js +8 -11
- package/dist/context/sessionContext.js +4 -0
- package/dist/esm/aggregation/EventAggregator.js +174 -35
- package/dist/esm/aggregation/snapshot.js +31 -9
- package/dist/esm/authStatus.js +87 -0
- package/dist/esm/browser.js +5 -2
- package/dist/esm/codex.js +18 -0
- package/dist/esm/codexProfiles.js +8 -11
- package/dist/esm/context/sessionContext.js +4 -0
- package/dist/esm/formatters/toolSummary.js +4 -1
- package/dist/esm/formatting.js +10 -1
- package/dist/esm/index.js +11 -6
- package/dist/esm/modelCatalog.js +7 -5
- package/dist/esm/modelContext.js +4 -3
- package/dist/esm/modelInfo.js +425 -47
- package/dist/esm/node.js +9 -3
- package/dist/esm/observedContextWindows.js +2 -1
- package/dist/esm/ownKey.js +26 -0
- package/dist/esm/parsers/codexParser.js +351 -54
- package/dist/esm/parsers/codexRolloutOrigin.js +107 -0
- package/dist/esm/parsers/openCodeParser.js +85 -22
- package/dist/esm/parsers/subagentScanner.js +33 -12
- package/dist/esm/parsers/subagentTraceParser.js +97 -37
- package/dist/esm/pricing.js +18 -0
- package/dist/esm/pricingCatalog.js +17 -9
- package/dist/esm/promptHistory.js +66 -4
- package/dist/esm/providerFailure.js +124 -3
- package/dist/esm/providers/claudeCode.js +10 -2
- package/dist/esm/providers/codex.js +84 -62
- package/dist/esm/providers/codexDatabase.js +3 -19
- package/dist/esm/providers/codexRollouts.js +24 -1
- package/dist/esm/providers/openCode.js +9 -17
- package/dist/esm/report/htmlReportGenerator.js +42 -5
- package/dist/esm/report/transcriptParser.js +13 -11
- package/dist/esm/schemas/providerFailure.js +3 -1
- package/dist/esm/schemas/sessionEvent.js +35 -14
- package/dist/esm/schemas/transcript.js +4 -0
- package/dist/esm/sessionPromptHistory.js +2 -2
- package/dist/esm/statusline/payload.js +9 -0
- package/dist/esm/subagentSpawn.js +163 -0
- package/dist/esm/testing/credentialGuard.js +87 -5
- package/dist/esm/toolCallOrigins.js +310 -0
- package/dist/esm/transcript.js +46 -3
- package/dist/esm/turns/assistantTurn.js +3 -2
- package/dist/esm/usage/claudeUsageDedupe.js +68 -0
- package/dist/esm/usage/usageEvents.js +146 -17
- package/dist/esm/usage/usageReports.js +39 -6
- package/dist/esm/watchers/eventBridge.js +15 -0
- package/dist/esm/watchers/factory.js +5 -3
- package/dist/esm/watchers/jsonlTail.js +442 -58
- package/dist/esm/watchers/jsonlWatcher.js +51 -4
- package/dist/esm/watchers/providerReaderWatcher.js +13 -0
- package/dist/esm/zaiQuota.js +2 -1
- package/dist/formatters/toolSummary.js +4 -1
- package/dist/formatting.d.ts +26 -1
- package/dist/formatting.js +11 -1
- package/dist/index.d.ts +22 -11
- package/dist/index.js +44 -12
- package/dist/modelCatalog.js +7 -5
- package/dist/modelContext.js +4 -3
- package/dist/modelInfo.d.ts +185 -16
- package/dist/modelInfo.js +434 -49
- package/dist/node.d.ts +16 -5
- package/dist/node.js +33 -2
- package/dist/observedContextWindows.js +2 -1
- package/dist/ownKey.d.ts +16 -0
- package/dist/ownKey.js +30 -0
- package/dist/parsers/codexParser.d.ts +118 -0
- package/dist/parsers/codexParser.js +352 -54
- package/dist/parsers/codexRolloutOrigin.d.ts +49 -0
- package/dist/parsers/codexRolloutOrigin.js +111 -0
- package/dist/parsers/openCodeParser.d.ts +38 -0
- package/dist/parsers/openCodeParser.js +88 -22
- package/dist/parsers/subagentScanner.d.ts +19 -6
- package/dist/parsers/subagentScanner.js +33 -12
- package/dist/parsers/subagentTraceParser.d.ts +25 -5
- package/dist/parsers/subagentTraceParser.js +97 -37
- package/dist/pricing.d.ts +22 -0
- package/dist/pricing.js +50 -0
- package/dist/pricingCatalog.d.ts +10 -0
- package/dist/pricingCatalog.js +16 -8
- package/dist/promptHistory.d.ts +65 -4
- package/dist/promptHistory.js +68 -5
- package/dist/providerFailure.d.ts +44 -0
- package/dist/providerFailure.js +126 -4
- package/dist/providers/claudeCode.js +9 -1
- package/dist/providers/codex.d.ts +3 -22
- package/dist/providers/codex.js +85 -64
- package/dist/providers/codexDatabase.d.ts +3 -2
- package/dist/providers/codexDatabase.js +4 -22
- package/dist/providers/codexRollouts.d.ts +22 -0
- package/dist/providers/codexRollouts.js +24 -0
- package/dist/providers/openCode.js +8 -16
- package/dist/providers/types.d.ts +14 -0
- package/dist/report/htmlReportGenerator.js +42 -5
- package/dist/report/transcriptParser.d.ts +10 -1
- package/dist/report/transcriptParser.js +13 -11
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/providerFailure.d.ts +39 -0
- package/dist/schemas/providerFailure.js +2 -0
- package/dist/schemas/sessionEvent.d.ts +27 -10
- package/dist/schemas/sessionEvent.js +35 -14
- package/dist/schemas/transcript.d.ts +2 -0
- package/dist/schemas/transcript.js +4 -0
- package/dist/sessionPromptHistory.d.ts +7 -1
- package/dist/sessionPromptHistory.js +1 -1
- package/dist/statusline/payload.d.ts +10 -0
- package/dist/statusline/payload.js +14 -0
- package/dist/subagentSpawn.d.ts +80 -0
- package/dist/subagentSpawn.js +174 -0
- package/dist/testing/credentialGuard.d.ts +14 -0
- package/dist/testing/credentialGuard.js +87 -5
- package/dist/toolCallOrigins.d.ts +70 -0
- package/dist/toolCallOrigins.js +346 -0
- package/dist/transcript.d.ts +12 -0
- package/dist/transcript.js +46 -3
- package/dist/turns/assistantTurn.d.ts +1 -0
- package/dist/turns/assistantTurn.js +3 -2
- package/dist/types/opencode.d.ts +2 -0
- package/dist/usage/claudeUsageDedupe.d.ts +31 -0
- package/dist/usage/claudeUsageDedupe.js +68 -0
- package/dist/usage/usageEvents.d.ts +54 -6
- package/dist/usage/usageEvents.js +146 -17
- package/dist/usage/usageReports.d.ts +35 -4
- package/dist/usage/usageReports.js +39 -6
- package/dist/watchers/eventBridge.js +15 -0
- package/dist/watchers/factory.d.ts +6 -0
- package/dist/watchers/factory.js +5 -3
- package/dist/watchers/jsonlTail.d.ts +124 -4
- package/dist/watchers/jsonlTail.js +446 -59
- package/dist/watchers/jsonlWatcher.d.ts +18 -1
- package/dist/watchers/jsonlWatcher.js +50 -3
- package/dist/watchers/providerReaderWatcher.d.ts +7 -0
- package/dist/watchers/providerReaderWatcher.js +13 -0
- package/dist/watchers/types.d.ts +12 -0
- package/dist/zaiQuota.js +2 -1
- package/package.json +41 -1
package/dist/esm/modelInfo.js
CHANGED
|
@@ -14,12 +14,18 @@
|
|
|
14
14
|
* baseline without requiring a redeploy when vendor prices change.
|
|
15
15
|
* - Longest-prefix matching handles variants like `claude-opus-4.5-20250514`
|
|
16
16
|
* against a key like `claude-opus-4.5`. Same pattern used in modelContext.ts.
|
|
17
|
+
* - A consumer layer (`registerModelPricing`) sits beside the catalog and
|
|
18
|
+
* imported layers and survives their resets.
|
|
19
|
+
* - Every table-derived value is computed lazily, so a tree-shaken bundle that
|
|
20
|
+
* only uses the parsing/display helpers does not retain the pricing table.
|
|
17
21
|
*
|
|
18
22
|
* @module modelInfo
|
|
19
23
|
*/
|
|
20
24
|
import { getModelContextWindowSize } from './modelContext';
|
|
21
25
|
import { resolveModelAlias } from './modelAliases';
|
|
26
|
+
import { ownValue } from './ownKey';
|
|
22
27
|
export { MODEL_PROVIDER_IDS } from './providerIds';
|
|
28
|
+
export { formatCost } from './formatting';
|
|
23
29
|
// ── Static Pricing Table ──
|
|
24
30
|
/**
|
|
25
31
|
* Static baseline pricing. Keys are model-ID prefixes; lookup uses
|
|
@@ -621,21 +627,38 @@ const PRICING_TABLE = {
|
|
|
621
627
|
cacheReadCostPerMillion: 7.5,
|
|
622
628
|
},
|
|
623
629
|
};
|
|
624
|
-
/**
|
|
625
|
-
|
|
630
|
+
/**
|
|
631
|
+
* Static-table keys sorted longest-first so longest-prefix wins. Computed on
|
|
632
|
+
* first lookup rather than at module load: a top-level call would keep the
|
|
633
|
+
* whole table alive in tree-shaken bundles that never price anything.
|
|
634
|
+
*/
|
|
635
|
+
let staticSortedKeys = null;
|
|
636
|
+
function getStaticSortedKeys() {
|
|
637
|
+
if (!staticSortedKeys) {
|
|
638
|
+
staticSortedKeys = Object.keys(PRICING_TABLE).sort((a, b) => b.length - a.length);
|
|
639
|
+
}
|
|
640
|
+
return staticSortedKeys;
|
|
641
|
+
}
|
|
626
642
|
// ── Override Table (populated at runtime by pricingCatalog) ──
|
|
627
643
|
let overrideTable = {};
|
|
628
644
|
let overrideSortedKeys = [];
|
|
645
|
+
let overrideBasis = null;
|
|
629
646
|
let importedTable = {};
|
|
630
647
|
/**
|
|
631
648
|
* Internal: replace the runtime override map. Called by `pricingCatalog.ts`
|
|
632
649
|
* after a successful LiteLLM hydration. Not part of the stable public API,
|
|
633
650
|
* but exported so the Node-only catalog module can wire itself in without
|
|
634
651
|
* creating a circular import.
|
|
652
|
+
*
|
|
653
|
+
* `basis` records how the map was obtained for `getPricingCatalogInfo()`;
|
|
654
|
+
* omitted, a non-empty map reports as `litellm` with no `fetchedAt`. Every
|
|
655
|
+
* call replaces the previous basis.
|
|
635
656
|
*/
|
|
636
|
-
export function _setPricingOverrides(overrides) {
|
|
657
|
+
export function _setPricingOverrides(overrides, basis) {
|
|
637
658
|
overrideTable = Object.fromEntries(Object.entries(overrides).map(([key, value]) => [key.trim().toLowerCase(), { ...value }]));
|
|
638
659
|
overrideSortedKeys = Object.keys(overrideTable).sort((a, b) => b.length - a.length);
|
|
660
|
+
overrideBasis = basis ? { ...basis } : null;
|
|
661
|
+
invalidatePricingDigest();
|
|
639
662
|
}
|
|
640
663
|
/** Internal: snapshot current overrides (test + diagnostics). */
|
|
641
664
|
export function _getPricingOverrides() {
|
|
@@ -645,6 +668,8 @@ export function _getPricingOverrides() {
|
|
|
645
668
|
export function _clearPricingOverrides() {
|
|
646
669
|
overrideTable = {};
|
|
647
670
|
overrideSortedKeys = [];
|
|
671
|
+
overrideBasis = null;
|
|
672
|
+
invalidatePricingDigest();
|
|
648
673
|
}
|
|
649
674
|
/**
|
|
650
675
|
* Internal: hydrate exact pricing resolutions exported by another realm.
|
|
@@ -653,10 +678,210 @@ export function _clearPricingOverrides() {
|
|
|
653
678
|
*/
|
|
654
679
|
export function _setImportedResolvedPricing(values) {
|
|
655
680
|
importedTable = { ...importedTable, ...values };
|
|
681
|
+
invalidatePricingDigest();
|
|
656
682
|
}
|
|
657
683
|
/** Internal test hook. */
|
|
658
684
|
export function _clearImportedResolvedPricing() {
|
|
659
685
|
importedTable = {};
|
|
686
|
+
invalidatePricingDigest();
|
|
687
|
+
}
|
|
688
|
+
// A Map (created on first registration) so keys such as `__proto__` stay data.
|
|
689
|
+
let registeredTable = null;
|
|
690
|
+
function isValidModelPricing(value) {
|
|
691
|
+
if (!value || typeof value !== 'object')
|
|
692
|
+
return false;
|
|
693
|
+
const pricing = value;
|
|
694
|
+
return [
|
|
695
|
+
pricing.inputCostPerMillion,
|
|
696
|
+
pricing.outputCostPerMillion,
|
|
697
|
+
pricing.cacheWriteCostPerMillion,
|
|
698
|
+
pricing.cacheReadCostPerMillion,
|
|
699
|
+
].every((item) => typeof item === 'number' && Number.isFinite(item) && item >= 0);
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Register consumer pricing for model ids, e.g. negotiated or private-deployment
|
|
703
|
+
* rates. This layer is separate from the runtime catalog and imported layers:
|
|
704
|
+
* `_setPricingOverrides`, `hydratePricingCatalog`, and
|
|
705
|
+
* `importResolvedModelCatalog` never reset it; only
|
|
706
|
+
* `clearRegisteredModelPricing` does.
|
|
707
|
+
*
|
|
708
|
+
* Keys are trimmed, lowercased, and stripped of `[1m]`, like the other tables.
|
|
709
|
+
* Matching is exact, never by prefix, against the looked-up id, its registered
|
|
710
|
+
* alias target, and its `canonicalModelId()` form — so a `claude-opus-5-5`
|
|
711
|
+
* entry also answers `claude-opus-5-5-20261001` and
|
|
712
|
+
* `us.anthropic.claude-opus-5-5-20261001-v1:0`.
|
|
713
|
+
*
|
|
714
|
+
* Successive calls merge; re-registering a key replaces its price and mode.
|
|
715
|
+
* Entries whose four rates are not all finite, nonnegative numbers are
|
|
716
|
+
* skipped. Results carry `provenance.source: 'registered'`.
|
|
717
|
+
*
|
|
718
|
+
* Registered entries are realm-local configuration and are kept out of
|
|
719
|
+
* cross-realm snapshots: they are not listed by the catalog id enumeration,
|
|
720
|
+
* and `resolveModelPricing(id, { includeRegistered: false })` is the
|
|
721
|
+
* resolution a snapshot should carry. An exported price would otherwise be
|
|
722
|
+
* pinned as an exact import in the other realm and outlive
|
|
723
|
+
* `clearRegisteredModelPricing` there. Register in each realm instead.
|
|
724
|
+
*/
|
|
725
|
+
export function registerModelPricing(entries, options) {
|
|
726
|
+
const onlyIfMissing = options?.onlyIfMissing === true;
|
|
727
|
+
let changed = false;
|
|
728
|
+
for (const [key, value] of Object.entries(entries ?? {})) {
|
|
729
|
+
const id = key
|
|
730
|
+
.replace(/\[1m\]/gi, '')
|
|
731
|
+
.trim()
|
|
732
|
+
.toLowerCase();
|
|
733
|
+
if (!id || !isValidModelPricing(value))
|
|
734
|
+
continue;
|
|
735
|
+
registeredTable ??= new Map();
|
|
736
|
+
registeredTable.set(id, {
|
|
737
|
+
pricing: {
|
|
738
|
+
inputCostPerMillion: value.inputCostPerMillion,
|
|
739
|
+
outputCostPerMillion: value.outputCostPerMillion,
|
|
740
|
+
cacheWriteCostPerMillion: value.cacheWriteCostPerMillion,
|
|
741
|
+
cacheReadCostPerMillion: value.cacheReadCostPerMillion,
|
|
742
|
+
},
|
|
743
|
+
onlyIfMissing,
|
|
744
|
+
});
|
|
745
|
+
changed = true;
|
|
746
|
+
}
|
|
747
|
+
if (changed)
|
|
748
|
+
invalidatePricingDigest();
|
|
749
|
+
}
|
|
750
|
+
/** Remove every entry added by `registerModelPricing`. */
|
|
751
|
+
export function clearRegisteredModelPricing() {
|
|
752
|
+
if (registeredTable && registeredTable.size > 0)
|
|
753
|
+
invalidatePricingDigest();
|
|
754
|
+
registeredTable = null;
|
|
755
|
+
}
|
|
756
|
+
function findRegisteredPricing(rawId, aliasId) {
|
|
757
|
+
if (!registeredTable || registeredTable.size === 0)
|
|
758
|
+
return null;
|
|
759
|
+
const canonical = canonicalModelId(rawId);
|
|
760
|
+
for (const id of [rawId, aliasId, canonical, resolveModelAlias(canonical)]) {
|
|
761
|
+
const entry = registeredTable.get(id);
|
|
762
|
+
if (entry)
|
|
763
|
+
return { id, entry };
|
|
764
|
+
}
|
|
765
|
+
return null;
|
|
766
|
+
}
|
|
767
|
+
// ── Pricing Basis ──
|
|
768
|
+
let pricingDigestMemo = null;
|
|
769
|
+
function invalidatePricingDigest() {
|
|
770
|
+
pricingDigestMemo = null;
|
|
771
|
+
}
|
|
772
|
+
/** JSON with object keys sorted at every level; `undefined` members are dropped. */
|
|
773
|
+
function canonicalJson(value) {
|
|
774
|
+
if (value === null || typeof value !== 'object') {
|
|
775
|
+
return JSON.stringify(value) ?? 'null';
|
|
776
|
+
}
|
|
777
|
+
if (Array.isArray(value))
|
|
778
|
+
return `[${value.map(canonicalJson).join(',')}]`;
|
|
779
|
+
const record = value;
|
|
780
|
+
const keys = Object.keys(record)
|
|
781
|
+
.filter((key) => record[key] !== undefined)
|
|
782
|
+
.sort();
|
|
783
|
+
return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(',')}}`;
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* 64-bit FNV-1a over the UTF-8 bytes of `text`, as 16 lowercase hex digits.
|
|
787
|
+
* Uses four 16-bit limbs so it runs on plain numbers in every JS runtime.
|
|
788
|
+
*/
|
|
789
|
+
function fnv1a64Hex(text) {
|
|
790
|
+
// Offset basis 0xcbf29ce484222325, least significant limb first.
|
|
791
|
+
let h0 = 0x2325;
|
|
792
|
+
let h1 = 0x8422;
|
|
793
|
+
let h2 = 0x9ce4;
|
|
794
|
+
let h3 = 0xcbf2;
|
|
795
|
+
const mix = (byte) => {
|
|
796
|
+
h0 ^= byte;
|
|
797
|
+
// Multiply by the FNV prime 0x100000001b3 = 2^40 + 0x1b3, mod 2^64.
|
|
798
|
+
const t0 = h0 * 0x1b3;
|
|
799
|
+
const t1 = h1 * 0x1b3 + (t0 >>> 16);
|
|
800
|
+
const t2 = h2 * 0x1b3 + (h0 << 8) + (t1 >>> 16);
|
|
801
|
+
const t3 = h3 * 0x1b3 + (h1 << 8) + (t2 >>> 16);
|
|
802
|
+
h0 = t0 & 0xffff;
|
|
803
|
+
h1 = t1 & 0xffff;
|
|
804
|
+
h2 = t2 & 0xffff;
|
|
805
|
+
h3 = t3 & 0xffff;
|
|
806
|
+
};
|
|
807
|
+
for (let i = 0; i < text.length; i++) {
|
|
808
|
+
let code = text.charCodeAt(i);
|
|
809
|
+
if (code >= 0xd800 && code <= 0xdfff) {
|
|
810
|
+
const low = code <= 0xdbff && i + 1 < text.length ? text.charCodeAt(i + 1) : 0;
|
|
811
|
+
if (low >= 0xdc00 && low <= 0xdfff) {
|
|
812
|
+
code = 0x10000 + ((code - 0xd800) << 10) + (low - 0xdc00);
|
|
813
|
+
i++;
|
|
814
|
+
}
|
|
815
|
+
else {
|
|
816
|
+
// A lone surrogate encodes as U+FFFD, as TextEncoder does.
|
|
817
|
+
code = 0xfffd;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
if (code < 0x80) {
|
|
821
|
+
mix(code);
|
|
822
|
+
}
|
|
823
|
+
else if (code < 0x800) {
|
|
824
|
+
mix(0xc0 | (code >> 6));
|
|
825
|
+
mix(0x80 | (code & 0x3f));
|
|
826
|
+
}
|
|
827
|
+
else if (code < 0x10000) {
|
|
828
|
+
mix(0xe0 | (code >> 12));
|
|
829
|
+
mix(0x80 | ((code >> 6) & 0x3f));
|
|
830
|
+
mix(0x80 | (code & 0x3f));
|
|
831
|
+
}
|
|
832
|
+
else {
|
|
833
|
+
mix(0xf0 | (code >> 18));
|
|
834
|
+
mix(0x80 | ((code >> 12) & 0x3f));
|
|
835
|
+
mix(0x80 | ((code >> 6) & 0x3f));
|
|
836
|
+
mix(0x80 | (code & 0x3f));
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
return [h3, h2, h1, h0].map((limb) => limb.toString(16).padStart(4, '0')).join('');
|
|
840
|
+
}
|
|
841
|
+
function getPricingDigest() {
|
|
842
|
+
if (pricingDigestMemo === null) {
|
|
843
|
+
const imported = {};
|
|
844
|
+
for (const [id, entry] of Object.entries(importedTable)) {
|
|
845
|
+
imported[id] = { pricing: entry.pricing, provenance: entry.provenance };
|
|
846
|
+
}
|
|
847
|
+
const registered = {};
|
|
848
|
+
for (const [id, entry] of registeredTable ?? []) {
|
|
849
|
+
registered[id] = { pricing: entry.pricing, onlyIfMissing: entry.onlyIfMissing };
|
|
850
|
+
}
|
|
851
|
+
const payload = canonicalJson({
|
|
852
|
+
v: 1,
|
|
853
|
+
static: PRICING_TABLE,
|
|
854
|
+
catalog: overrideTable,
|
|
855
|
+
imported,
|
|
856
|
+
registered,
|
|
857
|
+
});
|
|
858
|
+
pricingDigestMemo = `fnv1a64:${fnv1a64Hex(payload)}`;
|
|
859
|
+
}
|
|
860
|
+
return pricingDigestMemo;
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Describe the pricing basis behind current cost estimates: which layer the
|
|
864
|
+
* prices come from, when the catalog was fetched, and a digest that changes
|
|
865
|
+
* whenever any active price changes. Pure and cheap after the first call (the
|
|
866
|
+
* digest is memoized until a table changes).
|
|
867
|
+
*/
|
|
868
|
+
export function getPricingCatalogInfo() {
|
|
869
|
+
const catalogEntries = overrideSortedKeys.length;
|
|
870
|
+
let source = 'static';
|
|
871
|
+
if (catalogEntries > 0) {
|
|
872
|
+
source = overrideBasis?.source ?? 'litellm';
|
|
873
|
+
}
|
|
874
|
+
else if (Object.keys(importedTable).length > 0) {
|
|
875
|
+
source = 'imported';
|
|
876
|
+
}
|
|
877
|
+
const fetchedAt = catalogEntries > 0 ? overrideBasis?.fetchedAt : undefined;
|
|
878
|
+
return {
|
|
879
|
+
source,
|
|
880
|
+
...(fetchedAt ? { fetchedAt } : {}),
|
|
881
|
+
digest: getPricingDigest(),
|
|
882
|
+
catalogEntries,
|
|
883
|
+
registeredEntries: registeredTable?.size ?? 0,
|
|
884
|
+
};
|
|
660
885
|
}
|
|
661
886
|
/** Internal: list every ID known to the pricing resolver. */
|
|
662
887
|
export function _getModelPricingIds() {
|
|
@@ -666,6 +891,86 @@ export function _getModelPricingIds() {
|
|
|
666
891
|
...Object.keys(importedTable),
|
|
667
892
|
]));
|
|
668
893
|
}
|
|
894
|
+
// ── Model ID Canonicalization ──
|
|
895
|
+
// Bedrock: optional cross-region prefix (`us.`, `eu.`, `apac.`, `global.`, …)
|
|
896
|
+
// then the vendor segment, e.g. `us.anthropic.claude-opus-5-5-20261001-v1:0`.
|
|
897
|
+
const BEDROCK_ANTHROPIC_RE = /^(?:[a-z]{2,6}(?:-[a-z]{2,4})?\.)?anthropic\./;
|
|
898
|
+
// Bedrock revision tag (`-v1:0`, `-v1`), only after a version or date digit so
|
|
899
|
+
// legacy names such as `claude-v2:1` and `claude-instant-v1` keep theirs.
|
|
900
|
+
const BEDROCK_REVISION_RE = /([0-9])-v[0-9]+(?::[0-9]+)?$/;
|
|
901
|
+
const VERTEX_VERSION_RE = /@(?:[0-9]{8}|latest)$/;
|
|
902
|
+
const LATEST_SUFFIX_RE = /-latest$/;
|
|
903
|
+
const DASHED_DATE_SUFFIX_RE = /-[0-9]{4}-[0-9]{2}-[0-9]{2}$/;
|
|
904
|
+
const COMPACT_DATE_SUFFIX_RE = /-[0-9]{8}$/;
|
|
905
|
+
/**
|
|
906
|
+
* Reduce a model id to the bare model name it denotes, for grouping and
|
|
907
|
+
* matching across hosts and snapshots.
|
|
908
|
+
*
|
|
909
|
+
* Trims and lowercases, then removes: `[1m]`; every leading `segment/`
|
|
910
|
+
* provider or region prefix (`azure/us/gpt-6.1-terra` → `gpt-6.1-terra`);
|
|
911
|
+
* Bedrock forms (`us.anthropic.claude-opus-5-5-20261001-v1:0` →
|
|
912
|
+
* `claude-opus-5-5`, also `eu.`/`apac.`/`global.` and bare `anthropic.`);
|
|
913
|
+
* Vertex `@YYYYMMDD`; trailing `-YYYYMMDD` and `-YYYY-MM-DD` dates; `-latest`.
|
|
914
|
+
* Meaningful suffixes (`-mini`, `-codex`, `-sol`, `-terra`, `-high`, …) stay.
|
|
915
|
+
*
|
|
916
|
+
* Pure and syntactic: registered aliases are not applied (see
|
|
917
|
+
* `resolveModelAlias`). Pricing lookups do not use this to reach other
|
|
918
|
+
* models' prices — dated snapshots and deployments can bill differently — only
|
|
919
|
+
* to match `registerModelPricing` entries.
|
|
920
|
+
*/
|
|
921
|
+
export function canonicalModelId(id) {
|
|
922
|
+
let value = String(id ?? '')
|
|
923
|
+
.trim()
|
|
924
|
+
.toLowerCase()
|
|
925
|
+
.replace(/\[1m\]/g, '')
|
|
926
|
+
.trim();
|
|
927
|
+
const slash = value.lastIndexOf('/');
|
|
928
|
+
if (slash >= 0 && slash < value.length - 1)
|
|
929
|
+
value = value.slice(slash + 1);
|
|
930
|
+
const bedrock = BEDROCK_ANTHROPIC_RE.exec(value);
|
|
931
|
+
if (bedrock && value.length > bedrock[0].length) {
|
|
932
|
+
value = value.slice(bedrock[0].length).replace(BEDROCK_REVISION_RE, '$1');
|
|
933
|
+
}
|
|
934
|
+
// Suffixes can stack (`-20250101-latest`), so strip until nothing changes.
|
|
935
|
+
for (;;) {
|
|
936
|
+
const next = value
|
|
937
|
+
.replace(VERTEX_VERSION_RE, '')
|
|
938
|
+
.replace(LATEST_SUFFIX_RE, '')
|
|
939
|
+
.replace(DASHED_DATE_SUFFIX_RE, '')
|
|
940
|
+
.replace(COMPACT_DATE_SUFFIX_RE, '');
|
|
941
|
+
if (next === value || !next)
|
|
942
|
+
break;
|
|
943
|
+
value = next;
|
|
944
|
+
}
|
|
945
|
+
return value;
|
|
946
|
+
}
|
|
947
|
+
// Names an agent CLI re-points at a different concrete model over time.
|
|
948
|
+
// An object literal rather than a Set keeps it free for tree-shaking.
|
|
949
|
+
const MOVING_MODEL_ALIASES = {
|
|
950
|
+
default: true,
|
|
951
|
+
auto: true,
|
|
952
|
+
latest: true,
|
|
953
|
+
sonnet: true,
|
|
954
|
+
opus: true,
|
|
955
|
+
haiku: true,
|
|
956
|
+
fable: true,
|
|
957
|
+
opusplan: true,
|
|
958
|
+
};
|
|
959
|
+
/**
|
|
960
|
+
* True for model names an agent CLI resolves to a different concrete model
|
|
961
|
+
* over time (`default`, `auto`, `latest`, `sonnet`, `opus`, `haiku`, `fable`,
|
|
962
|
+
* and Claude Code's `opusplan`), so a recorded value names a moving target
|
|
963
|
+
* rather than a model. Case-insensitive, trimmed, and `[1m]`-tolerant
|
|
964
|
+
* (`sonnet[1m]`). Dated or versioned ids are never moving aliases.
|
|
965
|
+
*/
|
|
966
|
+
export function isMovingModelAlias(id) {
|
|
967
|
+
const value = String(id ?? '')
|
|
968
|
+
.trim()
|
|
969
|
+
.toLowerCase()
|
|
970
|
+
.replace(/\[1m\]/g, '')
|
|
971
|
+
.trim();
|
|
972
|
+
return Object.prototype.hasOwnProperty.call(MOVING_MODEL_ALIASES, value);
|
|
973
|
+
}
|
|
669
974
|
// ── Model ID Parsing ──
|
|
670
975
|
// Anthropic writes the minor version with a hyphen in modern IDs
|
|
671
976
|
// (`claude-sonnet-4-6-20260321`) and a dot in older ones
|
|
@@ -677,6 +982,14 @@ const LEGACY_CLAUDE_RE = /^claude-([0-9]+(?:[-.][0-9]+)?)-(haiku|sonnet|opus)(?:
|
|
|
677
982
|
const GPT_RE = /^gpt-([0-9][0-9.A-Za-z-]*)/i;
|
|
678
983
|
const O_SERIES_RE = /^o([0-9]+)(-mini|-pro)?/i;
|
|
679
984
|
const GEMINI_RE = /^gemini-([0-9][0-9.A-Za-z-]*)/i;
|
|
985
|
+
// GPT tier names, read from the parsed version (`6.1-sol`, `6-luna-2026-01-01`).
|
|
986
|
+
const GPT_TIER_VARIANT_RE = /^[0-9]+(?:\.[0-9]+)*-(astra|sol|terra|luna)(?=-|$)/;
|
|
987
|
+
const GPT_TIER_VARIANT_RANK = {
|
|
988
|
+
astra: 0,
|
|
989
|
+
sol: 1,
|
|
990
|
+
terra: 2,
|
|
991
|
+
luna: 3,
|
|
992
|
+
};
|
|
680
993
|
/**
|
|
681
994
|
* Parses a model ID into {provider, family, version}.
|
|
682
995
|
*
|
|
@@ -708,7 +1021,13 @@ export function parseModelId(modelId) {
|
|
|
708
1021
|
}
|
|
709
1022
|
const gpt = normalized.match(GPT_RE);
|
|
710
1023
|
if (gpt) {
|
|
711
|
-
|
|
1024
|
+
const version = gpt[1];
|
|
1025
|
+
const variant = GPT_TIER_VARIANT_RE.exec(version)?.[1];
|
|
1026
|
+
// The key is only present when set, so untiered results stay deep-equal
|
|
1027
|
+
// to what earlier releases returned.
|
|
1028
|
+
return variant
|
|
1029
|
+
? { provider: 'openai', family: 'gpt', version, variant }
|
|
1030
|
+
: { provider: 'openai', family: 'gpt', version };
|
|
712
1031
|
}
|
|
713
1032
|
const oSeries = normalized.match(O_SERIES_RE);
|
|
714
1033
|
if (oSeries) {
|
|
@@ -730,24 +1049,45 @@ function findLongestPrefix(keys, modelId) {
|
|
|
730
1049
|
}
|
|
731
1050
|
return null;
|
|
732
1051
|
}
|
|
733
|
-
/**
|
|
734
|
-
|
|
1052
|
+
/**
|
|
1053
|
+
* Resolve pricing and disclose which layer answered and whether the result was
|
|
1054
|
+
* inherited by prefix.
|
|
1055
|
+
*
|
|
1056
|
+
* Order: registered entries (default mode); exact imported, catalog, and
|
|
1057
|
+
* static matches; registered `onlyIfMissing` entries; catalog then static
|
|
1058
|
+
* prefix matches; unpriced.
|
|
1059
|
+
*/
|
|
1060
|
+
export function resolveModelPricing(modelId, options) {
|
|
735
1061
|
const stripped = modelId.replace(/\[1m\]/gi, '');
|
|
736
1062
|
const rawId = stripped.trim().toLowerCase();
|
|
737
|
-
const
|
|
1063
|
+
const aliasId = resolveModelAlias(stripped);
|
|
738
1064
|
// The raw id is tried before its alias target at every step: pricing
|
|
739
1065
|
// recorded for the alias id itself is more specific than the canonical
|
|
740
1066
|
// fallback, so registering an alias never orphans it.
|
|
741
|
-
const candidateIds = rawId ===
|
|
742
|
-
const
|
|
1067
|
+
const candidateIds = rawId === aliasId ? [aliasId] : [rawId, aliasId];
|
|
1068
|
+
const registered = options?.includeRegistered === false ? null : findRegisteredPricing(rawId, aliasId);
|
|
1069
|
+
const registeredResult = (match) => ({
|
|
1070
|
+
modelId,
|
|
1071
|
+
canonicalModelId: aliasId,
|
|
1072
|
+
pricing: { ...match.entry.pricing },
|
|
1073
|
+
provenance: {
|
|
1074
|
+
source: 'registered',
|
|
1075
|
+
match: 'exact',
|
|
1076
|
+
matchedModelId: match.id,
|
|
1077
|
+
inheritedByPrefix: false,
|
|
1078
|
+
},
|
|
1079
|
+
});
|
|
1080
|
+
if (registered && !registered.entry.onlyIfMissing)
|
|
1081
|
+
return registeredResult(registered);
|
|
1082
|
+
const imported = ownValue(importedTable, rawId) ?? ownValue(importedTable, aliasId);
|
|
743
1083
|
if (imported)
|
|
744
|
-
return { ...imported, modelId, canonicalModelId };
|
|
1084
|
+
return { ...imported, modelId, canonicalModelId: aliasId };
|
|
745
1085
|
for (const id of candidateIds) {
|
|
746
|
-
const exactOverride = overrideTable
|
|
1086
|
+
const exactOverride = ownValue(overrideTable, id);
|
|
747
1087
|
if (exactOverride) {
|
|
748
1088
|
return {
|
|
749
1089
|
modelId,
|
|
750
|
-
canonicalModelId,
|
|
1090
|
+
canonicalModelId: aliasId,
|
|
751
1091
|
pricing: exactOverride,
|
|
752
1092
|
provenance: {
|
|
753
1093
|
source: 'catalog',
|
|
@@ -759,11 +1099,11 @@ export function resolveModelPricing(modelId) {
|
|
|
759
1099
|
}
|
|
760
1100
|
}
|
|
761
1101
|
for (const id of candidateIds) {
|
|
762
|
-
const exactStatic = PRICING_TABLE
|
|
1102
|
+
const exactStatic = ownValue(PRICING_TABLE, id);
|
|
763
1103
|
if (exactStatic) {
|
|
764
1104
|
return {
|
|
765
1105
|
modelId,
|
|
766
|
-
canonicalModelId,
|
|
1106
|
+
canonicalModelId: aliasId,
|
|
767
1107
|
pricing: exactStatic,
|
|
768
1108
|
provenance: {
|
|
769
1109
|
source: 'static',
|
|
@@ -774,12 +1114,15 @@ export function resolveModelPricing(modelId) {
|
|
|
774
1114
|
};
|
|
775
1115
|
}
|
|
776
1116
|
}
|
|
1117
|
+
// A gap-filling registration answers once no layer has an exact price.
|
|
1118
|
+
if (registered)
|
|
1119
|
+
return registeredResult(registered);
|
|
777
1120
|
for (const id of candidateIds) {
|
|
778
1121
|
const overridePrefix = findLongestPrefix(overrideSortedKeys, id);
|
|
779
1122
|
if (overridePrefix) {
|
|
780
1123
|
return {
|
|
781
1124
|
modelId,
|
|
782
|
-
canonicalModelId,
|
|
1125
|
+
canonicalModelId: aliasId,
|
|
783
1126
|
pricing: overrideTable[overridePrefix],
|
|
784
1127
|
provenance: {
|
|
785
1128
|
source: 'catalog',
|
|
@@ -791,11 +1134,11 @@ export function resolveModelPricing(modelId) {
|
|
|
791
1134
|
}
|
|
792
1135
|
}
|
|
793
1136
|
for (const id of candidateIds) {
|
|
794
|
-
const staticPrefix = findLongestPrefix(
|
|
1137
|
+
const staticPrefix = findLongestPrefix(getStaticSortedKeys(), id);
|
|
795
1138
|
if (staticPrefix) {
|
|
796
1139
|
return {
|
|
797
1140
|
modelId,
|
|
798
|
-
canonicalModelId,
|
|
1141
|
+
canonicalModelId: aliasId,
|
|
799
1142
|
pricing: PRICING_TABLE[staticPrefix],
|
|
800
1143
|
provenance: {
|
|
801
1144
|
source: 'static',
|
|
@@ -808,7 +1151,7 @@ export function resolveModelPricing(modelId) {
|
|
|
808
1151
|
}
|
|
809
1152
|
return {
|
|
810
1153
|
modelId,
|
|
811
|
-
canonicalModelId,
|
|
1154
|
+
canonicalModelId: aliasId,
|
|
812
1155
|
pricing: null,
|
|
813
1156
|
provenance: { source: 'none', match: 'none', inheritedByPrefix: false },
|
|
814
1157
|
};
|
|
@@ -816,9 +1159,11 @@ export function resolveModelPricing(modelId) {
|
|
|
816
1159
|
/**
|
|
817
1160
|
* Gets pricing for a model ID.
|
|
818
1161
|
*
|
|
819
|
-
* Lookup order:
|
|
820
|
-
* 1.
|
|
821
|
-
* 2.
|
|
1162
|
+
* Lookup order (see `resolveModelPricing` for provenance):
|
|
1163
|
+
* 1. Registered entries (`registerModelPricing`), exact matches only.
|
|
1164
|
+
* 2. Imported resolutions, then the runtime override map (from LiteLLM
|
|
1165
|
+
* catalog hydration), then the static PRICING_TABLE — exact before prefix,
|
|
1166
|
+
* with gap-filling registered entries between the two.
|
|
822
1167
|
* 3. `null` — unknown model. Callers MUST handle this.
|
|
823
1168
|
*
|
|
824
1169
|
* The ID is first looked up verbatim (minus the "[1m]" suffix) — override
|
|
@@ -910,22 +1255,47 @@ export function mergeCostSources(a, b) {
|
|
|
910
1255
|
};
|
|
911
1256
|
return rank[a] >= rank[b] ? a : b;
|
|
912
1257
|
}
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
1258
|
+
/**
|
|
1259
|
+
* Map the provenance `calculateNormalizedUsageCost` reports to the display
|
|
1260
|
+
* cost source: provider-reported costs are `reported`, costs computed from
|
|
1261
|
+
* explicit or catalog pricing are `estimated`, and unpriced stays `unpriced`.
|
|
1262
|
+
*/
|
|
1263
|
+
export function costSourceFromPricingProvenance(provenance) {
|
|
1264
|
+
switch (provenance) {
|
|
1265
|
+
case 'provider-reported':
|
|
1266
|
+
return 'reported';
|
|
1267
|
+
case 'explicit-pricing':
|
|
1268
|
+
case 'model-catalog':
|
|
1269
|
+
return 'estimated';
|
|
1270
|
+
default:
|
|
1271
|
+
return 'unpriced';
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Merge the cost sources of a rollup's components, least certain winning (as
|
|
1276
|
+
* `mergeCostSources`). Components without a `source` have not been seen yet
|
|
1277
|
+
* and are ignored, and an `unpriced` component that contributed no tokens
|
|
1278
|
+
* does not taint the total. Returns `undefined` when nothing counted.
|
|
1279
|
+
*/
|
|
1280
|
+
export function mergeCostComponents(components) {
|
|
1281
|
+
let merged;
|
|
1282
|
+
for (const component of components) {
|
|
1283
|
+
const source = component?.source;
|
|
1284
|
+
if (!source)
|
|
1285
|
+
continue;
|
|
1286
|
+
if (source === 'unpriced' && !(component.tokens > 0))
|
|
1287
|
+
continue;
|
|
1288
|
+
merged = merged ? mergeCostSources(merged, source) : source;
|
|
1289
|
+
}
|
|
1290
|
+
return merged;
|
|
922
1291
|
}
|
|
1292
|
+
// ── Display ──
|
|
923
1293
|
/**
|
|
924
1294
|
* Short display label for model IDs. Keeps historical Claude family labels
|
|
925
1295
|
* compact while normalizing common OpenAI labels.
|
|
926
1296
|
*/
|
|
927
1297
|
export function shortModelName(modelId) {
|
|
928
|
-
const normalized =
|
|
1298
|
+
const normalized = canonicalModelId(modelId);
|
|
929
1299
|
const parsed = parseModelId(normalized);
|
|
930
1300
|
if (normalized.includes('codex'))
|
|
931
1301
|
return 'Codex';
|
|
@@ -964,7 +1334,7 @@ function versionRank(version) {
|
|
|
964
1334
|
*/
|
|
965
1335
|
export function getModelDisplayInfo(modelId) {
|
|
966
1336
|
const parsed = parseModelId(modelId);
|
|
967
|
-
const normalized =
|
|
1337
|
+
const normalized = canonicalModelId(modelId);
|
|
968
1338
|
let rank = 1_000;
|
|
969
1339
|
if (parsed?.provider === 'anthropic') {
|
|
970
1340
|
rank = (CLAUDE_FAMILY_RANK[parsed.family] ?? 9) * 100 + versionRank(parsed.version);
|
|
@@ -990,29 +1360,37 @@ export function getModelDisplayInfo(modelId) {
|
|
|
990
1360
|
rank,
|
|
991
1361
|
};
|
|
992
1362
|
}
|
|
993
|
-
/**
|
|
1363
|
+
/**
|
|
1364
|
+
* Order two GPT tier variants of the same family and numeric version
|
|
1365
|
+
* (astra > sol > terra > luna); 0 for every other pair.
|
|
1366
|
+
*/
|
|
1367
|
+
function compareTierVariants(a, b) {
|
|
1368
|
+
const left = parseModelId(a);
|
|
1369
|
+
const right = parseModelId(b);
|
|
1370
|
+
if (!left?.variant || !right?.variant)
|
|
1371
|
+
return 0;
|
|
1372
|
+
if (left.provider !== right.provider || left.family !== right.family)
|
|
1373
|
+
return 0;
|
|
1374
|
+
if (versionRank(left.version) !== versionRank(right.version))
|
|
1375
|
+
return 0;
|
|
1376
|
+
return ((GPT_TIER_VARIANT_RANK[left.variant] ?? Number.MAX_SAFE_INTEGER) -
|
|
1377
|
+
(GPT_TIER_VARIANT_RANK[right.variant] ?? Number.MAX_SAFE_INTEGER));
|
|
1378
|
+
}
|
|
1379
|
+
/**
|
|
1380
|
+
* Compare two model IDs using shared provider/family ranking rules. Within a
|
|
1381
|
+
* family and numeric version, GPT tiers rank astra > sol > terra > luna.
|
|
1382
|
+
*/
|
|
994
1383
|
export function compareModelIds(a, b) {
|
|
995
1384
|
const left = getModelDisplayInfo(a);
|
|
996
1385
|
const right = getModelDisplayInfo(b);
|
|
997
1386
|
if (left.rank !== right.rank)
|
|
998
1387
|
return left.rank - right.rank;
|
|
1388
|
+
const variantOrder = compareTierVariants(a, b);
|
|
1389
|
+
if (variantOrder !== 0)
|
|
1390
|
+
return variantOrder;
|
|
999
1391
|
return a.localeCompare(b);
|
|
1000
1392
|
}
|
|
1001
1393
|
/** Return a sorted copy of model IDs using shared provider/family ranking rules. */
|
|
1002
1394
|
export function sortModelIds(modelIds) {
|
|
1003
1395
|
return [...modelIds].sort(compareModelIds);
|
|
1004
1396
|
}
|
|
1005
|
-
/**
|
|
1006
|
-
* Formats a USD cost as a currency string.
|
|
1007
|
-
*
|
|
1008
|
-
* - `null` / `undefined` → `"—"` (honest "pricing unavailable").
|
|
1009
|
-
* - `< $0.01` → 4 decimals, so sub-cent costs are still visible.
|
|
1010
|
-
* - otherwise → 2 decimals.
|
|
1011
|
-
*/
|
|
1012
|
-
export function formatCost(cost) {
|
|
1013
|
-
if (cost === null || cost === undefined)
|
|
1014
|
-
return '—';
|
|
1015
|
-
if (cost < 0.01)
|
|
1016
|
-
return `$${cost.toFixed(4)}`;
|
|
1017
|
-
return `$${cost.toFixed(2)}`;
|
|
1018
|
-
}
|
package/dist/esm/node.js
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
export { hydratePricingCatalog, normalizeLiteLlmCatalog, normalizeLiteLlmContextWindows, LITELLM_CATALOG_URL, } from './pricingCatalog';
|
|
9
9
|
export { loadObservedContextWindows, recordObservedContextWindow, getObservedContextWindowPath, } from './observedContextWindows';
|
|
10
10
|
export { listRecentSessions, readSessionTranscript } from './sessionTranscripts';
|
|
11
|
-
export { collectPromptHistory, isPromptHistorySessionSettled, parsePromptHistoryCursor, } from './promptHistory';
|
|
11
|
+
export { collectPromptHistory, isPromptHistorySessionSettled, parsePromptHistoryCursor, PROMPT_HISTORY_ORDINAL_MAX_RECORD_BYTES, } from './promptHistory';
|
|
12
|
+
export { findToolCallOrigins } from './toolCallOrigins';
|
|
12
13
|
export { collectSessionPromptHistory } from './sessionPromptHistory';
|
|
13
14
|
export { HUMAN_CLAUDE_ENTRYPOINTS, HUMAN_CODEX_SOURCES, humanPromptText, isHumanPrompt, } from './humanPrompt';
|
|
14
15
|
export { computeSessionFileStats, firstUserPrompt, providerContextSizeFn, readSessionFileStats, } from './sessionStats';
|
|
@@ -35,7 +36,12 @@ export { CONFIG_DIR_ENV_VAR, getConfigDir, getConfigDirOverride, getDefaultConfi
|
|
|
35
36
|
export { encodeWorkspacePath as encodeClaudeWorkspacePath, getSessionDirectory as getClaudeSessionDirectory, } from './parsers/sessionPathResolver';
|
|
36
37
|
// Provider homes the CLIs read for this process
|
|
37
38
|
export { getLiveClaudeHome, getDefaultClaudeHome, isDefaultClaudeHome, getClaudeProjectsDir, } from './claudePaths';
|
|
38
|
-
export { getSystemCodexHome, getCodexMonitoringHomes, resolveSidekickCodexHome, getCodexExecutionEnv, getCodexSessionsDirs, CODEX_SESSIONS_SUBDIR, CODEX_ARCHIVED_SESSIONS_SUBDIR, } from './codexPaths';
|
|
39
|
+
export { getSystemCodexHome, getCodexMonitoringHomes, resolveSidekickCodexHome, getCodexExecutionEnv, getCodexSessionsDirs, getCodexCredentialStoreMode, forceFileCredentialStore, CODEX_SESSIONS_SUBDIR, CODEX_ARCHIVED_SESSIONS_SUBDIR, } from './codexPaths';
|
|
40
|
+
export { parseAuthJson as parseCodexAuthJson, readAuthIdentityFromRaw as readCodexAuthIdentity, readLastRefresh as readCodexLastRefresh, readAccessTokenExpiry as readCodexAccessTokenExpiry, identitiesMatch as codexIdentitiesMatch, codexRefreshFingerprint, compareCodexAuthFreshness, } from './codexAuth';
|
|
41
|
+
export { atomicWriteJson, atomicWriteJsonSync } from './writers/atomic';
|
|
42
|
+
export { parseClaudeAuthStatus, parseCodexLoginStatus } from './authStatus';
|
|
43
|
+
export { codexRolloutOrigin, codexSpawnParentFromSource } from './parsers/codexRolloutOrigin';
|
|
44
|
+
export { getPricingCatalogInfo, registerModelPricing, clearRegisteredModelPricing, } from './modelInfo';
|
|
39
45
|
export { fetchProviderServiceStatus } from './providerServiceStatus';
|
|
40
46
|
// Tool categories across providers
|
|
41
47
|
export { classifyTool, TOOL_CATEGORIES } from './toolCategory';
|
|
@@ -43,4 +49,4 @@ export { classifyTool, TOOL_CATEGORIES } from './toolCategory';
|
|
|
43
49
|
export { resolveWorkspaceRoots } from './workspaceRoots';
|
|
44
50
|
export { discoverWorktreeSiblings, resolveWorktreeMainRepo } from './parsers/sessionPathResolver';
|
|
45
51
|
// Bounded JSONL tail reader
|
|
46
|
-
export { createJsonlTail, DEFAULT_JSONL_TAIL_MAX_LINE_BYTES, DEFAULT_JSONL_TAIL_READ_BYTES, } from './watchers/jsonlTail';
|
|
52
|
+
export { captureJsonlCheckpoint, createJsonlTail, DEFAULT_JSONL_TAIL_MAX_LINE_BYTES, DEFAULT_JSONL_TAIL_READ_BYTES, JSONL_TAIL_CHECKPOINT_VERSION, JsonlTailSymlinkError, verifyJsonlCheckpoint, } from './watchers/jsonlTail';
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
import { promises as fs } from 'node:fs';
|
|
33
33
|
import * as path from 'node:path';
|
|
34
34
|
import { _setObservedContextWindows, _getObservedContextWindows } from './modelContext';
|
|
35
|
+
import { setOwnValue } from './ownKey';
|
|
35
36
|
import { getConfigDir } from './paths';
|
|
36
37
|
import { updateJsonStoreAtomic } from './writers/atomic';
|
|
37
38
|
// ── Constants ──
|
|
@@ -80,7 +81,7 @@ function toOverrideMap(store, now = Date.now()) {
|
|
|
80
81
|
const observedAt = typeof entry.observedAt === 'string' ? Date.parse(entry.observedAt) : NaN;
|
|
81
82
|
if (Number.isFinite(observedAt) && now - observedAt > OBSERVED_CONTEXT_WINDOW_TTL_MS)
|
|
82
83
|
continue;
|
|
83
|
-
out
|
|
84
|
+
setOwnValue(out, modelId, window);
|
|
84
85
|
}
|
|
85
86
|
return out;
|
|
86
87
|
}
|