claudish 9.0.2 → 9.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +401 -440
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -731,7 +731,7 @@ var init_onepassword_config = __esm(() => {
|
|
|
731
731
|
});
|
|
732
732
|
|
|
733
733
|
// src/version.ts
|
|
734
|
-
var VERSION = "9.0.
|
|
734
|
+
var VERSION = "9.0.4";
|
|
735
735
|
|
|
736
736
|
// src/logger.ts
|
|
737
737
|
var exports_logger = {};
|
|
@@ -27655,6 +27655,10 @@ function resolveSubscriptionRouting(modelId, provider, cachePath) {
|
|
|
27655
27655
|
const hasPublishedProviderRoster = cache.entries.some((candidate) => candidate.subscriptionPlans?.some((planId) => providerPlanIds.has(planId)));
|
|
27656
27656
|
if (!hasPublishedProviderRoster)
|
|
27657
27657
|
return { kind: "unknown" };
|
|
27658
|
+
const vendorsInView = new Set(providerPlans.map((plan) => plan.provider).filter((v) => v !== undefined));
|
|
27659
|
+
const hasUnroutableSiblingPlan = (cache.plans ?? []).some((plan) => plan.provider !== undefined && vendorsInView.has(plan.provider) && plan.routing?.providerUid === undefined);
|
|
27660
|
+
if (hasUnroutableSiblingPlan)
|
|
27661
|
+
return { kind: "unknown" };
|
|
27658
27662
|
return providerPlans.every(isCatalogDiscoveredPlan) ? { kind: "not-served" } : { kind: "unknown" };
|
|
27659
27663
|
}
|
|
27660
27664
|
function isCatalogDiscoveredPlan(plan) {
|
|
@@ -47685,349 +47689,6 @@ var init_routing_hints = __esm(() => {
|
|
|
47685
47689
|
};
|
|
47686
47690
|
});
|
|
47687
47691
|
|
|
47688
|
-
// src/providers/cache-ttl.ts
|
|
47689
|
-
var FIREBASE_CACHE_TTL_HOURS = 24, FIREBASE_CACHE_TTL_MS;
|
|
47690
|
-
var init_cache_ttl = __esm(() => {
|
|
47691
|
-
FIREBASE_CACHE_TTL_MS = FIREBASE_CACHE_TTL_HOURS * 60 * 60 * 1000;
|
|
47692
|
-
});
|
|
47693
|
-
|
|
47694
|
-
// src/model-loader.ts
|
|
47695
|
-
import { existsSync as existsSync19, mkdirSync as mkdirSync11, readFileSync as readFileSync18, writeFileSync as writeFileSync10 } from "fs";
|
|
47696
|
-
import { homedir as homedir27 } from "os";
|
|
47697
|
-
import { join as join27 } from "path";
|
|
47698
|
-
function groupRecommendedModels(entries) {
|
|
47699
|
-
const byId = new Map;
|
|
47700
|
-
const categoryOrder = new Map;
|
|
47701
|
-
for (const entry of entries) {
|
|
47702
|
-
const list = byId.get(entry.id);
|
|
47703
|
-
if (list)
|
|
47704
|
-
list.push(entry);
|
|
47705
|
-
else
|
|
47706
|
-
byId.set(entry.id, [entry]);
|
|
47707
|
-
if (!categoryOrder.has(entry.category))
|
|
47708
|
-
categoryOrder.set(entry.category, categoryOrder.size);
|
|
47709
|
-
}
|
|
47710
|
-
const flagship = [];
|
|
47711
|
-
const fast = [];
|
|
47712
|
-
for (const [id, members] of byId.entries()) {
|
|
47713
|
-
const primary = members.find((m) => m.category !== "subscription") ?? members[0];
|
|
47714
|
-
const subscriptions = members.filter((m) => m.category === "subscription");
|
|
47715
|
-
const bucket = primary.category === "programming" || primary.category === "vision" || primary.category === "reasoning" ? "flagship" : "fast";
|
|
47716
|
-
const group = { id, primary, subscriptions, bucket };
|
|
47717
|
-
if (bucket === "flagship")
|
|
47718
|
-
flagship.push(group);
|
|
47719
|
-
else
|
|
47720
|
-
fast.push(group);
|
|
47721
|
-
}
|
|
47722
|
-
const byCuratedPriorityThenFreshness = (a, b) => {
|
|
47723
|
-
const aCat = categoryOrder.get(a.primary.category) ?? Number.MAX_SAFE_INTEGER;
|
|
47724
|
-
const bCat = categoryOrder.get(b.primary.category) ?? Number.MAX_SAFE_INTEGER;
|
|
47725
|
-
if (aCat !== bCat)
|
|
47726
|
-
return aCat - bCat;
|
|
47727
|
-
if (a.primary.priority !== b.primary.priority)
|
|
47728
|
-
return a.primary.priority - b.primary.priority;
|
|
47729
|
-
return compareByReleaseDateDesc(a.primary, b.primary);
|
|
47730
|
-
};
|
|
47731
|
-
flagship.sort(byCuratedPriorityThenFreshness);
|
|
47732
|
-
fast.sort(byCuratedPriorityThenFreshness);
|
|
47733
|
-
return { flagship, fast };
|
|
47734
|
-
}
|
|
47735
|
-
function collectRoutingPrefixes(group, getNativePrefix) {
|
|
47736
|
-
const slug = (group.primary.provider || "").toLowerCase();
|
|
47737
|
-
const native = getNativePrefix(slug);
|
|
47738
|
-
const seen = new Set;
|
|
47739
|
-
const out = [];
|
|
47740
|
-
if (native) {
|
|
47741
|
-
out.push(native);
|
|
47742
|
-
seen.add(native);
|
|
47743
|
-
}
|
|
47744
|
-
for (const subscriptionRow of group.subscriptions) {
|
|
47745
|
-
const routes = subscriptionRow.subscriptions && subscriptionRow.subscriptions.length > 0 ? subscriptionRow.subscriptions : subscriptionRow.subscription ? [subscriptionRow.subscription] : [];
|
|
47746
|
-
const orderedRoutes = [...routes].sort(compareRecommendedRoutes);
|
|
47747
|
-
for (const route of orderedRoutes) {
|
|
47748
|
-
const p = route?.prefix;
|
|
47749
|
-
if (!p || seen.has(p))
|
|
47750
|
-
continue;
|
|
47751
|
-
seen.add(p);
|
|
47752
|
-
out.push(p);
|
|
47753
|
-
}
|
|
47754
|
-
}
|
|
47755
|
-
return out;
|
|
47756
|
-
}
|
|
47757
|
-
function compareRecommendedRoutes(left, right) {
|
|
47758
|
-
const leftRank = left?.tier && Object.hasOwn(RECOMMENDED_ROUTE_TIER_ORDER, left.tier) ? RECOMMENDED_ROUTE_TIER_ORDER[left.tier] : Number.MAX_SAFE_INTEGER;
|
|
47759
|
-
const rightRank = right?.tier && Object.hasOwn(RECOMMENDED_ROUTE_TIER_ORDER, right.tier) ? RECOMMENDED_ROUTE_TIER_ORDER[right.tier] : Number.MAX_SAFE_INTEGER;
|
|
47760
|
-
return leftRank - rightRank;
|
|
47761
|
-
}
|
|
47762
|
-
function buildCatalogRoutingRules(doc2) {
|
|
47763
|
-
const routesByModel = new Map;
|
|
47764
|
-
let sourceIndex = 0;
|
|
47765
|
-
for (const entry of doc2.models) {
|
|
47766
|
-
const routes = entry.subscriptions && entry.subscriptions.length > 0 ? entry.subscriptions : entry.subscription ? [entry.subscription] : [];
|
|
47767
|
-
for (const route of routes) {
|
|
47768
|
-
routesByModel.set(entry.id, [...routesByModel.get(entry.id) ?? [], { route, sourceIndex }]);
|
|
47769
|
-
sourceIndex += 1;
|
|
47770
|
-
}
|
|
47771
|
-
}
|
|
47772
|
-
const rules = {};
|
|
47773
|
-
for (const [modelId, candidates] of routesByModel) {
|
|
47774
|
-
const seen = new Set;
|
|
47775
|
-
const entries = candidates.filter(({ route }) => typeof route?.routingProvider === "string" && route.routingProvider.length > 0 && typeof route.command === "string" && route.command.length > 0).sort((left, right) => compareRecommendedRoutes(left.route, right.route) || left.sourceIndex - right.sourceIndex).map(({ route }) => {
|
|
47776
|
-
const at = route.command.indexOf("@");
|
|
47777
|
-
const wireId = at >= 0 ? route.command.slice(at + 1) : route.command;
|
|
47778
|
-
return `${route.routingProvider}@${wireId}`;
|
|
47779
|
-
}).filter((entry) => {
|
|
47780
|
-
if (seen.has(entry))
|
|
47781
|
-
return false;
|
|
47782
|
-
seen.add(entry);
|
|
47783
|
-
return true;
|
|
47784
|
-
});
|
|
47785
|
-
if (entries.length > 0)
|
|
47786
|
-
rules[modelId] = entries;
|
|
47787
|
-
}
|
|
47788
|
-
return rules;
|
|
47789
|
-
}
|
|
47790
|
-
function parsePriceAvg(s) {
|
|
47791
|
-
if (!s || s === "N/A")
|
|
47792
|
-
return Number.POSITIVE_INFINITY;
|
|
47793
|
-
if (s === "FREE")
|
|
47794
|
-
return 0;
|
|
47795
|
-
const m = s.match(/\$([\d.]+)/);
|
|
47796
|
-
return m ? Number.parseFloat(m[1]) : Number.POSITIVE_INFINITY;
|
|
47797
|
-
}
|
|
47798
|
-
function parseCtx(s) {
|
|
47799
|
-
if (!s || s === "N/A")
|
|
47800
|
-
return 0;
|
|
47801
|
-
const upper = s.toUpperCase();
|
|
47802
|
-
if (upper.includes("M"))
|
|
47803
|
-
return Number.parseFloat(upper) * 1e6;
|
|
47804
|
-
if (upper.includes("K"))
|
|
47805
|
-
return Number.parseFloat(upper) * 1000;
|
|
47806
|
-
return Number.parseInt(s, 10) || 0;
|
|
47807
|
-
}
|
|
47808
|
-
function normalizePricingDisplay(raw) {
|
|
47809
|
-
const pricing = raw || "N/A";
|
|
47810
|
-
if (pricing.includes("-1000000"))
|
|
47811
|
-
return "varies";
|
|
47812
|
-
if (pricing === "$0.00/1M" || pricing === "FREE")
|
|
47813
|
-
return "FREE";
|
|
47814
|
-
return pricing;
|
|
47815
|
-
}
|
|
47816
|
-
function formatListingPrice(entry, opts) {
|
|
47817
|
-
const rate = normalizePricingDisplay(entry.pricing?.average);
|
|
47818
|
-
if (rate !== "N/A")
|
|
47819
|
-
return rate;
|
|
47820
|
-
const plan = entry.subscription?.plan;
|
|
47821
|
-
if (!plan)
|
|
47822
|
-
return "N/A";
|
|
47823
|
-
return opts?.compact ? "SUB" : `SUB (${plan})`;
|
|
47824
|
-
}
|
|
47825
|
-
function computeQuickPicks(primaries) {
|
|
47826
|
-
if (primaries.length === 0) {
|
|
47827
|
-
return {
|
|
47828
|
-
budget: null,
|
|
47829
|
-
largeContext: null,
|
|
47830
|
-
mostCapable: null,
|
|
47831
|
-
visionCoding: null,
|
|
47832
|
-
agentic: null
|
|
47833
|
-
};
|
|
47834
|
-
}
|
|
47835
|
-
const priced = primaries.filter((m) => {
|
|
47836
|
-
const p = parsePriceAvg(m.pricing?.average);
|
|
47837
|
-
return p > 0 && p !== Number.POSITIVE_INFINITY;
|
|
47838
|
-
}).sort((a, b) => parsePriceAvg(a.pricing?.average) - parsePriceAvg(b.pricing?.average));
|
|
47839
|
-
const budget = priced[0] ?? null;
|
|
47840
|
-
const byCtx = [...primaries].sort((a, b) => parseCtx(b.context) - parseCtx(a.context));
|
|
47841
|
-
const largeContext = byCtx[0] ?? null;
|
|
47842
|
-
const byPrice = [...primaries].sort((a, b) => parsePriceAvg(b.pricing?.average) - parsePriceAvg(a.pricing?.average));
|
|
47843
|
-
const mostCapable = byPrice.find((m) => parsePriceAvg(m.pricing?.average) !== Number.POSITIVE_INFINITY) ?? null;
|
|
47844
|
-
const visionCoding = primaries.find((m) => m.supportsVision === true && m.id !== budget?.id && m.id !== mostCapable?.id) ?? null;
|
|
47845
|
-
const agentic = primaries.find((m) => m.supportsReasoning === true && m.id !== mostCapable?.id) ?? null;
|
|
47846
|
-
return { budget, largeContext, mostCapable, visionCoding, agentic };
|
|
47847
|
-
}
|
|
47848
|
-
async function getRecommendedModels(opts = {}) {
|
|
47849
|
-
const { forceRefresh = false } = opts;
|
|
47850
|
-
if (!forceRefresh && _cachedRecommendedModels) {
|
|
47851
|
-
return _cachedRecommendedModels;
|
|
47852
|
-
}
|
|
47853
|
-
if (!forceRefresh && existsSync19(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
47854
|
-
try {
|
|
47855
|
-
const cacheData = JSON.parse(readFileSync18(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
47856
|
-
if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
|
|
47857
|
-
_cachedRecommendedModels = cacheData;
|
|
47858
|
-
return cacheData;
|
|
47859
|
-
}
|
|
47860
|
-
} catch {}
|
|
47861
|
-
}
|
|
47862
|
-
try {
|
|
47863
|
-
const response = await fetch(FIREBASE_RECOMMENDED_URL, {
|
|
47864
|
-
signal: AbortSignal.timeout(RECOMMENDED_FETCH_TIMEOUT_MS)
|
|
47865
|
-
});
|
|
47866
|
-
if (response.ok) {
|
|
47867
|
-
const data = await response.json();
|
|
47868
|
-
if (data.models && data.models.length > 0) {
|
|
47869
|
-
_cachedRecommendedModels = data;
|
|
47870
|
-
try {
|
|
47871
|
-
const cacheDir = join27(homedir27(), ".claudish");
|
|
47872
|
-
mkdirSync11(cacheDir, { recursive: true });
|
|
47873
|
-
writeFileSync10(RECOMMENDED_MODELS_CACHE_PATH, JSON.stringify(data), "utf-8");
|
|
47874
|
-
} catch {}
|
|
47875
|
-
return data;
|
|
47876
|
-
}
|
|
47877
|
-
}
|
|
47878
|
-
} catch {}
|
|
47879
|
-
throw new Error("Unable to load recommended models: Firebase unreachable and no local cache. " + "Check connectivity.");
|
|
47880
|
-
}
|
|
47881
|
-
function getRecommendedModelsSync() {
|
|
47882
|
-
if (_cachedRecommendedModels)
|
|
47883
|
-
return _cachedRecommendedModels;
|
|
47884
|
-
if (existsSync19(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
47885
|
-
try {
|
|
47886
|
-
const cacheData = JSON.parse(readFileSync18(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
47887
|
-
if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
|
|
47888
|
-
_cachedRecommendedModels = cacheData;
|
|
47889
|
-
return cacheData;
|
|
47890
|
-
}
|
|
47891
|
-
} catch {}
|
|
47892
|
-
}
|
|
47893
|
-
return { version: "0", lastUpdated: "", models: [] };
|
|
47894
|
-
}
|
|
47895
|
-
async function warmRecommendedModels() {
|
|
47896
|
-
try {
|
|
47897
|
-
return await getRecommendedModels({ forceRefresh: true });
|
|
47898
|
-
} catch {
|
|
47899
|
-
return null;
|
|
47900
|
-
}
|
|
47901
|
-
}
|
|
47902
|
-
function isFreshEnough(doc2) {
|
|
47903
|
-
const generatedAt = doc2.generatedAt;
|
|
47904
|
-
if (!generatedAt)
|
|
47905
|
-
return true;
|
|
47906
|
-
const ageHours = (Date.now() - new Date(generatedAt).getTime()) / (1000 * 60 * 60);
|
|
47907
|
-
return ageHours <= FIREBASE_CACHE_TTL_HOURS;
|
|
47908
|
-
}
|
|
47909
|
-
async function searchModels(query, limit = 50) {
|
|
47910
|
-
const url2 = `${FIREBASE_BASE_URL}?search=${encodeURIComponent(query)}&limit=${limit}&status=active`;
|
|
47911
|
-
const response = await fetch(url2, {
|
|
47912
|
-
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
47913
|
-
});
|
|
47914
|
-
if (!response.ok) {
|
|
47915
|
-
throw new Error(`Firebase search returned ${response.status} ${response.statusText}`);
|
|
47916
|
-
}
|
|
47917
|
-
const data = await response.json();
|
|
47918
|
-
return data.models ?? [];
|
|
47919
|
-
}
|
|
47920
|
-
async function getModelByIdFromFirebase(modelId) {
|
|
47921
|
-
const url2 = `${FIREBASE_BASE_URL}?search=${encodeURIComponent(modelId)}&limit=5`;
|
|
47922
|
-
const response = await fetch(url2, {
|
|
47923
|
-
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
47924
|
-
});
|
|
47925
|
-
if (!response.ok) {
|
|
47926
|
-
throw new Error(`Firebase lookup returned ${response.status} ${response.statusText}`);
|
|
47927
|
-
}
|
|
47928
|
-
const data = await response.json();
|
|
47929
|
-
const models = data.models ?? [];
|
|
47930
|
-
for (const m of models) {
|
|
47931
|
-
if (m.modelId === modelId)
|
|
47932
|
-
return m;
|
|
47933
|
-
if (m.aliases?.includes(modelId))
|
|
47934
|
-
return m;
|
|
47935
|
-
}
|
|
47936
|
-
return null;
|
|
47937
|
-
}
|
|
47938
|
-
async function getTop100Models() {
|
|
47939
|
-
const url2 = `${FIREBASE_BASE_URL}?catalog=top100`;
|
|
47940
|
-
const response = await fetch(url2, {
|
|
47941
|
-
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
47942
|
-
});
|
|
47943
|
-
if (!response.ok) {
|
|
47944
|
-
throw new Error(`Firebase top100 fetch failed: ${response.status} ${response.statusText}`);
|
|
47945
|
-
}
|
|
47946
|
-
const data = await response.json();
|
|
47947
|
-
return data;
|
|
47948
|
-
}
|
|
47949
|
-
async function getProviderList() {
|
|
47950
|
-
const url2 = `${FIREBASE_BASE_URL}?catalog=providers`;
|
|
47951
|
-
const response = await fetch(url2, {
|
|
47952
|
-
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
47953
|
-
});
|
|
47954
|
-
if (!response.ok) {
|
|
47955
|
-
throw new Error(`Firebase providers fetch failed: ${response.status} ${response.statusText}`);
|
|
47956
|
-
}
|
|
47957
|
-
const data = await response.json();
|
|
47958
|
-
return data.providers ?? [];
|
|
47959
|
-
}
|
|
47960
|
-
async function getModelsByProvider(provider, limit = 200) {
|
|
47961
|
-
const url2 = `${FIREBASE_BASE_URL}?provider=${encodeURIComponent(provider)}&status=active&limit=${limit}`;
|
|
47962
|
-
const response = await fetch(url2, {
|
|
47963
|
-
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
47964
|
-
});
|
|
47965
|
-
if (!response.ok) {
|
|
47966
|
-
throw new Error(`Firebase provider query returned ${response.status} ${response.statusText}`);
|
|
47967
|
-
}
|
|
47968
|
-
const data = await response.json();
|
|
47969
|
-
if (Array.isArray(data))
|
|
47970
|
-
return data;
|
|
47971
|
-
return data.models ?? [];
|
|
47972
|
-
}
|
|
47973
|
-
function loadModelInfo() {
|
|
47974
|
-
if (_cachedModelInfo) {
|
|
47975
|
-
return _cachedModelInfo;
|
|
47976
|
-
}
|
|
47977
|
-
const data = getRecommendedModelsSync();
|
|
47978
|
-
const modelInfo = {};
|
|
47979
|
-
for (const model of data.models) {
|
|
47980
|
-
modelInfo[model.id] = {
|
|
47981
|
-
name: model.name,
|
|
47982
|
-
description: model.description,
|
|
47983
|
-
priority: model.priority,
|
|
47984
|
-
provider: model.provider
|
|
47985
|
-
};
|
|
47986
|
-
}
|
|
47987
|
-
modelInfo.custom = {
|
|
47988
|
-
name: "Custom Model",
|
|
47989
|
-
description: "Enter any model ID manually",
|
|
47990
|
-
priority: 999,
|
|
47991
|
-
provider: "Custom"
|
|
47992
|
-
};
|
|
47993
|
-
_cachedModelInfo = modelInfo;
|
|
47994
|
-
return modelInfo;
|
|
47995
|
-
}
|
|
47996
|
-
function getAvailableModels() {
|
|
47997
|
-
if (_cachedModelIds) {
|
|
47998
|
-
return _cachedModelIds;
|
|
47999
|
-
}
|
|
48000
|
-
const data = getRecommendedModelsSync();
|
|
48001
|
-
const modelIds = data.models.sort((a, b) => a.priority - b.priority).map((m) => m.id);
|
|
48002
|
-
const result = [...modelIds, "custom"];
|
|
48003
|
-
_cachedModelIds = result;
|
|
48004
|
-
return result;
|
|
48005
|
-
}
|
|
48006
|
-
var _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels = null, FIREBASE_BASE_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/queryModels", FIREBASE_RECOMMENDED_URL, RECOMMENDED_MODELS_CACHE_PATH, RECOMMENDED_FETCH_TIMEOUT_MS = 5000, SEARCH_FETCH_TIMEOUT_MS = 1e4, FIREBASE_SLUG_TO_PROVIDER_NAME, RECOMMENDED_ROUTE_TIER_ORDER;
|
|
48007
|
-
var init_model_loader = __esm(() => {
|
|
48008
|
-
init_cache_ttl();
|
|
48009
|
-
FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
|
|
48010
|
-
RECOMMENDED_MODELS_CACHE_PATH = join27(homedir27(), ".claudish", "recommended-models-cache.json");
|
|
48011
|
-
FIREBASE_SLUG_TO_PROVIDER_NAME = {
|
|
48012
|
-
openai: "openai",
|
|
48013
|
-
google: "google",
|
|
48014
|
-
"x-ai": "x-ai",
|
|
48015
|
-
"z-ai": "z-ai",
|
|
48016
|
-
moonshotai: "kimi",
|
|
48017
|
-
minimax: "minimax",
|
|
48018
|
-
qwen: "qwen",
|
|
48019
|
-
deepseek: "deepseek",
|
|
48020
|
-
mistralai: "mistralai",
|
|
48021
|
-
sakana: "sakana"
|
|
48022
|
-
};
|
|
48023
|
-
RECOMMENDED_ROUTE_TIER_ORDER = {
|
|
48024
|
-
native: 0,
|
|
48025
|
-
general: 1,
|
|
48026
|
-
metered: 2,
|
|
48027
|
-
aggregator: 3
|
|
48028
|
-
};
|
|
48029
|
-
});
|
|
48030
|
-
|
|
48031
47692
|
// src/providers/default-routing-rules.ts
|
|
48032
47693
|
function validateRoutingRulesAgainstProviders(rules) {
|
|
48033
47694
|
const unknown3 = [];
|
|
@@ -48119,26 +47780,12 @@ var init_model_availability = __esm(() => {
|
|
|
48119
47780
|
function mergeRoutingRules(defaults, global_, local) {
|
|
48120
47781
|
return { ...defaults, ...global_, ...local };
|
|
48121
47782
|
}
|
|
48122
|
-
function loadRoutingRules() {
|
|
48123
|
-
const local = loadLocalConfig()?.routing ?? {};
|
|
48124
|
-
const global_ = loadConfig().routing ?? {};
|
|
47783
|
+
function loadRoutingRules(sources) {
|
|
47784
|
+
const local = sources ? sources.localRules : loadLocalConfig()?.routing ?? {};
|
|
47785
|
+
const global_ = sources ? sources.globalRules : loadConfig().routing ?? {};
|
|
48125
47786
|
validateRoutingRules(local);
|
|
48126
47787
|
validateRoutingRules(global_);
|
|
48127
|
-
|
|
48128
|
-
return mergeRoutingRules({ ...DEFAULT_ROUTING_RULES, ...catalogRules }, global_, local);
|
|
48129
|
-
}
|
|
48130
|
-
function retainKnownCatalogRoutingRules(rules) {
|
|
48131
|
-
const retained = {};
|
|
48132
|
-
for (const [modelId, entries] of Object.entries(rules)) {
|
|
48133
|
-
const knownEntries = entries.filter((entry) => {
|
|
48134
|
-
const providerRaw = entry.split("@", 1)[0]?.toLowerCase() ?? "";
|
|
48135
|
-
const provider = PROVIDER_SHORTCUTS[providerRaw] ?? providerRaw;
|
|
48136
|
-
return getProviderByName(provider) !== undefined;
|
|
48137
|
-
});
|
|
48138
|
-
if (knownEntries.length > 0)
|
|
48139
|
-
retained[modelId] = knownEntries;
|
|
48140
|
-
}
|
|
48141
|
-
return retained;
|
|
47788
|
+
return mergeRoutingRules(DEFAULT_ROUTING_RULES, global_, local);
|
|
48142
47789
|
}
|
|
48143
47790
|
function validateRoutingRules(rules) {
|
|
48144
47791
|
const seenLower = new Map;
|
|
@@ -48333,7 +47980,6 @@ var init_routing_rules = __esm(() => {
|
|
|
48333
47980
|
init_authority();
|
|
48334
47981
|
init_remote_provider_types();
|
|
48335
47982
|
init_logger();
|
|
48336
|
-
init_model_loader();
|
|
48337
47983
|
init_profile_config();
|
|
48338
47984
|
init_auto_route();
|
|
48339
47985
|
init_catalog_client();
|
|
@@ -49477,8 +49123,8 @@ __export(exports_session_discovery, {
|
|
|
49477
49123
|
});
|
|
49478
49124
|
import { execFile, execFileSync as execFileSync2 } from "child_process";
|
|
49479
49125
|
import { closeSync as closeSync6, openSync as openSync6, readSync as readSync2, readdirSync as readdirSync4, realpathSync, statSync as statSync5 } from "fs";
|
|
49480
|
-
import { homedir as
|
|
49481
|
-
import { basename, join as
|
|
49126
|
+
import { homedir as homedir27 } from "os";
|
|
49127
|
+
import { basename, join as join27 } from "path";
|
|
49482
49128
|
function slugForPath(absPath) {
|
|
49483
49129
|
return absPath.replace(/[/.]/g, "-");
|
|
49484
49130
|
}
|
|
@@ -49487,7 +49133,7 @@ function transcriptPathFor(cwd, sessionUuid) {
|
|
|
49487
49133
|
try {
|
|
49488
49134
|
real = realpathSync(cwd);
|
|
49489
49135
|
} catch {}
|
|
49490
|
-
return
|
|
49136
|
+
return join27(PROJECTS_DIR, slugForPath(real), `${sessionUuid}.jsonl`);
|
|
49491
49137
|
}
|
|
49492
49138
|
function isAgentSession(row) {
|
|
49493
49139
|
return row.entrypoint !== undefined && row.entrypoint !== "cli";
|
|
@@ -49534,7 +49180,7 @@ function projectDirs() {
|
|
|
49534
49180
|
}
|
|
49535
49181
|
}
|
|
49536
49182
|
function sessionsIn(dirName) {
|
|
49537
|
-
const dir =
|
|
49183
|
+
const dir = join27(PROJECTS_DIR, dirName);
|
|
49538
49184
|
let names;
|
|
49539
49185
|
try {
|
|
49540
49186
|
names = readdirSync4(dir).filter((n) => n.endsWith(".jsonl"));
|
|
@@ -49543,7 +49189,7 @@ function sessionsIn(dirName) {
|
|
|
49543
49189
|
}
|
|
49544
49190
|
const rows = [];
|
|
49545
49191
|
for (const n of names) {
|
|
49546
|
-
const file2 =
|
|
49192
|
+
const file2 = join27(dir, n);
|
|
49547
49193
|
try {
|
|
49548
49194
|
const st = statSync5(file2);
|
|
49549
49195
|
if (st.size === 0)
|
|
@@ -49902,7 +49548,7 @@ function findLatestSessionId(cwd = process.cwd(), sinceMs = 0) {
|
|
|
49902
49548
|
}
|
|
49903
49549
|
var ENTRYPOINT_BYTES = 8192, PROJECTS_DIR, ACTIVE_WINDOW_MS = 120000, HEAD_BYTES, TAIL_BYTES, HARNESS_ENVELOPES, DEEP_TAIL_BYTES, RECENT_AI_TURNS = 5, RECENT_USER_TURNS = 1;
|
|
49904
49550
|
var init_session_discovery = __esm(() => {
|
|
49905
|
-
PROJECTS_DIR =
|
|
49551
|
+
PROJECTS_DIR = join27(homedir27(), ".claude", "projects");
|
|
49906
49552
|
HEAD_BYTES = 64 * 1024;
|
|
49907
49553
|
TAIL_BYTES = 128 * 1024;
|
|
49908
49554
|
HARNESS_ENVELOPES = [
|
|
@@ -49937,19 +49583,19 @@ function newStdioDecoder() {
|
|
|
49937
49583
|
var init_stdio_decode = () => {};
|
|
49938
49584
|
|
|
49939
49585
|
// src/team-stats.ts
|
|
49940
|
-
import { existsSync as
|
|
49941
|
-
import { join as
|
|
49586
|
+
import { existsSync as existsSync19, readFileSync as readFileSync18, writeFileSync as writeFileSync10 } from "fs";
|
|
49587
|
+
import { join as join28 } from "path";
|
|
49942
49588
|
function statsDir(sessionPath) {
|
|
49943
|
-
return
|
|
49589
|
+
return join28(sessionPath, "stats");
|
|
49944
49590
|
}
|
|
49945
49591
|
function tokenFileFor(sessionPath, anonId) {
|
|
49946
|
-
return
|
|
49592
|
+
return join28(statsDir(sessionPath), `${anonId}.json`);
|
|
49947
49593
|
}
|
|
49948
49594
|
function readTokenStatsAt(path) {
|
|
49949
|
-
if (!
|
|
49595
|
+
if (!existsSync19(path))
|
|
49950
49596
|
return null;
|
|
49951
49597
|
try {
|
|
49952
|
-
return JSON.parse(
|
|
49598
|
+
return JSON.parse(readFileSync18(path, "utf-8"));
|
|
49953
49599
|
} catch {
|
|
49954
49600
|
return null;
|
|
49955
49601
|
}
|
|
@@ -50100,7 +49746,7 @@ ${segs.join(" \xB7 ")}`;
|
|
|
50100
49746
|
}
|
|
50101
49747
|
function writeStatusFile(sessionPath, manifest, status, opts) {
|
|
50102
49748
|
try {
|
|
50103
|
-
|
|
49749
|
+
writeFileSync10(join28(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
|
|
50104
49750
|
`, "utf-8");
|
|
50105
49751
|
} catch {}
|
|
50106
49752
|
}
|
|
@@ -50135,13 +49781,13 @@ __export(exports_team_orchestrator, {
|
|
|
50135
49781
|
import { spawn as spawn2 } from "child_process";
|
|
50136
49782
|
import {
|
|
50137
49783
|
createWriteStream,
|
|
50138
|
-
existsSync as
|
|
50139
|
-
mkdirSync as
|
|
50140
|
-
readFileSync as
|
|
49784
|
+
existsSync as existsSync20,
|
|
49785
|
+
mkdirSync as mkdirSync11,
|
|
49786
|
+
readFileSync as readFileSync19,
|
|
50141
49787
|
readdirSync as readdirSync5,
|
|
50142
|
-
writeFileSync as
|
|
49788
|
+
writeFileSync as writeFileSync11
|
|
50143
49789
|
} from "fs";
|
|
50144
|
-
import { basename as basename2, join as
|
|
49790
|
+
import { basename as basename2, join as join29, resolve as resolve3 } from "path";
|
|
50145
49791
|
function resolveCaptureMode(explicit, env = process.env) {
|
|
50146
49792
|
if (explicit)
|
|
50147
49793
|
return explicit;
|
|
@@ -50259,7 +49905,7 @@ function persistErrorLog(errorLogPath, header, stderr, stdoutTail) {
|
|
|
50259
49905
|
parts.push("--- stderr ---", stderr.trim() ? redactSecrets(stderr) : "(empty)", "");
|
|
50260
49906
|
parts.push("--- stdout (tail) ---", stdoutTail.trim() ? redactSecrets(stdoutTail) : "(empty)", "");
|
|
50261
49907
|
try {
|
|
50262
|
-
|
|
49908
|
+
writeFileSync11(errorLogPath, parts.join(`
|
|
50263
49909
|
`), "utf-8");
|
|
50264
49910
|
} catch {}
|
|
50265
49911
|
}
|
|
@@ -50277,10 +49923,10 @@ function readTeamInputFile(inputPath) {
|
|
|
50277
49923
|
if (!resolved.startsWith(`${cwd}/`) && resolved !== cwd) {
|
|
50278
49924
|
throw new Error(`Input file must be within current directory: ${inputPath}`);
|
|
50279
49925
|
}
|
|
50280
|
-
if (!
|
|
49926
|
+
if (!existsSync20(resolved)) {
|
|
50281
49927
|
throw new Error(`Input file not found: ${resolved}`);
|
|
50282
49928
|
}
|
|
50283
|
-
const text =
|
|
49929
|
+
const text = readFileSync19(resolved, "utf-8");
|
|
50284
49930
|
if (text.trim().length === 0) {
|
|
50285
49931
|
throw new Error(`Input file is empty: ${resolved}`);
|
|
50286
49932
|
}
|
|
@@ -50290,14 +49936,14 @@ function setupSession(sessionPath, models, input) {
|
|
|
50290
49936
|
if (models.length === 0) {
|
|
50291
49937
|
throw new Error("At least one model is required");
|
|
50292
49938
|
}
|
|
50293
|
-
if (
|
|
49939
|
+
if (existsSync20(join29(sessionPath, "manifest.json"))) {
|
|
50294
49940
|
throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
|
|
50295
49941
|
}
|
|
50296
|
-
|
|
50297
|
-
|
|
49942
|
+
mkdirSync11(join29(sessionPath, "work"), { recursive: true });
|
|
49943
|
+
mkdirSync11(join29(sessionPath, "errors"), { recursive: true });
|
|
50298
49944
|
if (input !== undefined) {
|
|
50299
|
-
|
|
50300
|
-
} else if (!
|
|
49945
|
+
writeFileSync11(join29(sessionPath, "input.md"), input, "utf-8");
|
|
49946
|
+
} else if (!existsSync20(join29(sessionPath, "input.md"))) {
|
|
50301
49947
|
throw new Error(`No input.md found at ${sessionPath} and no input provided`);
|
|
50302
49948
|
}
|
|
50303
49949
|
const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
|
|
@@ -50314,9 +49960,9 @@ function setupSession(sessionPath, models, input) {
|
|
|
50314
49960
|
model: models[i],
|
|
50315
49961
|
assignedAt: now2
|
|
50316
49962
|
};
|
|
50317
|
-
|
|
49963
|
+
mkdirSync11(join29(sessionPath, "work", anonId), { recursive: true });
|
|
50318
49964
|
}
|
|
50319
|
-
|
|
49965
|
+
writeFileSync11(join29(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
|
|
50320
49966
|
const status = {
|
|
50321
49967
|
startedAt: now2,
|
|
50322
49968
|
models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
|
|
@@ -50330,7 +49976,7 @@ function setupSession(sessionPath, models, input) {
|
|
|
50330
49976
|
}
|
|
50331
49977
|
]))
|
|
50332
49978
|
};
|
|
50333
|
-
|
|
49979
|
+
writeFileSync11(join29(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
|
|
50334
49980
|
return manifest;
|
|
50335
49981
|
}
|
|
50336
49982
|
function assertValidRequirePattern(pattern) {
|
|
@@ -50347,22 +49993,22 @@ function readFullOutputIfNeeded(opts) {
|
|
|
50347
49993
|
if (crashed || !requirePattern || outputSize <= STDOUT_TAIL_LIMIT)
|
|
50348
49994
|
return;
|
|
50349
49995
|
try {
|
|
50350
|
-
return
|
|
49996
|
+
return readFileSync19(outputPath, "utf-8");
|
|
50351
49997
|
} catch {
|
|
50352
49998
|
return;
|
|
50353
49999
|
}
|
|
50354
50000
|
}
|
|
50355
50001
|
async function startModels(sessionPath, opts = {}) {
|
|
50356
50002
|
assertValidRequirePattern(opts.requirePattern);
|
|
50357
|
-
const manifest = JSON.parse(
|
|
50358
|
-
const statusPath =
|
|
50359
|
-
const inputPath =
|
|
50360
|
-
const inputContent =
|
|
50003
|
+
const manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
|
|
50004
|
+
const statusPath = join29(sessionPath, "status.json");
|
|
50005
|
+
const inputPath = join29(sessionPath, "input.md");
|
|
50006
|
+
const inputContent = readFileSync19(inputPath, "utf-8");
|
|
50361
50007
|
const spawnPlan = await (opts.spawnPlanner ?? prehydrateCredentialsForSpawn)(Object.values(manifest.models).map((m) => m.model));
|
|
50362
|
-
const statusCache = JSON.parse(
|
|
50008
|
+
const statusCache = JSON.parse(readFileSync19(statusPath, "utf-8"));
|
|
50363
50009
|
function updateModelStatus(id, update) {
|
|
50364
50010
|
statusCache.models[id] = { ...statusCache.models[id], ...update };
|
|
50365
|
-
|
|
50011
|
+
writeFileSync11(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
|
|
50366
50012
|
}
|
|
50367
50013
|
const minOutputBytes = opts.minOutputBytes ?? DEFAULT_MIN_OUTPUT_BYTES;
|
|
50368
50014
|
const requirePattern = opts.requirePattern;
|
|
@@ -50395,7 +50041,7 @@ async function startModels(sessionPath, opts = {}) {
|
|
|
50395
50041
|
persistErrorLog(rt.errorLogPath, `RECOVERED: ${note}`, stderr, stdoutTail);
|
|
50396
50042
|
opts.onStatusChange?.(id, statusCache.models[id]);
|
|
50397
50043
|
}
|
|
50398
|
-
|
|
50044
|
+
mkdirSync11(statsDir(sessionPath), { recursive: true });
|
|
50399
50045
|
const processes = new Map;
|
|
50400
50046
|
const runtimes = new Map;
|
|
50401
50047
|
const cancelledSlots = new Set;
|
|
@@ -50408,9 +50054,9 @@ async function startModels(sessionPath, opts = {}) {
|
|
|
50408
50054
|
process.on("SIGINT", sigintHandler);
|
|
50409
50055
|
const completionPromises = [];
|
|
50410
50056
|
for (const [anonId, entry] of Object.entries(manifest.models)) {
|
|
50411
|
-
const outputPath =
|
|
50412
|
-
const errorLogPath =
|
|
50413
|
-
const upstreamErrorLogPath =
|
|
50057
|
+
const outputPath = join29(sessionPath, `response-${anonId}.md`);
|
|
50058
|
+
const errorLogPath = join29(sessionPath, "errors", `${anonId}.log`);
|
|
50059
|
+
const upstreamErrorLogPath = join29(sessionPath, "errors", `${anonId}-upstream.jsonl`);
|
|
50414
50060
|
const spawnModel = spawnPlan.pinned.get(entry.model) ?? entry.model;
|
|
50415
50061
|
const args = [
|
|
50416
50062
|
"--model",
|
|
@@ -50550,7 +50196,7 @@ async function startModels(sessionPath, opts = {}) {
|
|
|
50550
50196
|
stderrSnippet: stderr ? redactSecrets(stderr).slice(-2000) : undefined,
|
|
50551
50197
|
stdoutSnippet: stdoutTail ? redactSecrets(stdoutTail).slice(-2000) : undefined,
|
|
50552
50198
|
errorLogPath,
|
|
50553
|
-
upstreamErrorLogPath:
|
|
50199
|
+
upstreamErrorLogPath: existsSync20(upstreamErrorLogPath) ? upstreamErrorLogPath : undefined,
|
|
50554
50200
|
workDir: sessionPath
|
|
50555
50201
|
}
|
|
50556
50202
|
});
|
|
@@ -50570,7 +50216,7 @@ async function startModels(sessionPath, opts = {}) {
|
|
|
50570
50216
|
proc.on("exit", (code) => {
|
|
50571
50217
|
const timedOut = statusCache.models[anonId]?.state === "TIMEOUT";
|
|
50572
50218
|
if (!timedOut && meaningfulStderr(stderr)) {
|
|
50573
|
-
|
|
50219
|
+
writeFileSync11(errorLogPath, redactSecrets(stderr), "utf-8");
|
|
50574
50220
|
}
|
|
50575
50221
|
exitCode = code;
|
|
50576
50222
|
if (outputStream.destroyed) {
|
|
@@ -50650,23 +50296,23 @@ async function judgeResponses(sessionPath, opts = {}) {
|
|
|
50650
50296
|
const responses = {};
|
|
50651
50297
|
for (const file2 of responseFiles) {
|
|
50652
50298
|
const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
|
|
50653
|
-
responses[id] =
|
|
50299
|
+
responses[id] = readFileSync19(join29(sessionPath, file2), "utf-8");
|
|
50654
50300
|
}
|
|
50655
|
-
const input =
|
|
50301
|
+
const input = readFileSync19(join29(sessionPath, "input.md"), "utf-8");
|
|
50656
50302
|
const judgePrompt = buildJudgePrompt(input, responses);
|
|
50657
|
-
|
|
50303
|
+
writeFileSync11(join29(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
|
|
50658
50304
|
const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
|
|
50659
|
-
const judgePath =
|
|
50660
|
-
|
|
50305
|
+
const judgePath = join29(sessionPath, "judging");
|
|
50306
|
+
mkdirSync11(judgePath, { recursive: true });
|
|
50661
50307
|
setupSession(judgePath, judgeModels, judgePrompt);
|
|
50662
50308
|
await runModels(judgePath, { claudeFlags: opts.claudeFlags });
|
|
50663
50309
|
const votes = parseJudgeVotes(judgePath, Object.keys(responses));
|
|
50664
50310
|
const verdict = aggregateVerdict(votes, Object.keys(responses));
|
|
50665
|
-
|
|
50311
|
+
writeFileSync11(join29(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
|
|
50666
50312
|
return verdict;
|
|
50667
50313
|
}
|
|
50668
50314
|
function getStatus(sessionPath) {
|
|
50669
|
-
return JSON.parse(
|
|
50315
|
+
return JSON.parse(readFileSync19(join29(sessionPath, "status.json"), "utf-8"));
|
|
50670
50316
|
}
|
|
50671
50317
|
function fisherYatesShuffle(arr) {
|
|
50672
50318
|
for (let i = arr.length - 1;i > 0; i--) {
|
|
@@ -50676,7 +50322,7 @@ function fisherYatesShuffle(arr) {
|
|
|
50676
50322
|
return arr;
|
|
50677
50323
|
}
|
|
50678
50324
|
function getDefaultJudgeModels(sessionPath) {
|
|
50679
|
-
const manifest = JSON.parse(
|
|
50325
|
+
const manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
|
|
50680
50326
|
return Object.values(manifest.models).map((e) => e.model);
|
|
50681
50327
|
}
|
|
50682
50328
|
function buildJudgePrompt(input, responses) {
|
|
@@ -50739,7 +50385,7 @@ function parseJudgeVotes(judgePath, responseIds) {
|
|
|
50739
50385
|
const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
|
|
50740
50386
|
let content;
|
|
50741
50387
|
try {
|
|
50742
|
-
content =
|
|
50388
|
+
content = readFileSync19(join29(judgePath, file2), "utf-8");
|
|
50743
50389
|
} catch {
|
|
50744
50390
|
continue;
|
|
50745
50391
|
}
|
|
@@ -50791,7 +50437,7 @@ function aggregateVerdict(votes, responseIds) {
|
|
|
50791
50437
|
function formatVerdict(verdict, sessionPath) {
|
|
50792
50438
|
let manifest = null;
|
|
50793
50439
|
try {
|
|
50794
|
-
manifest = JSON.parse(
|
|
50440
|
+
manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
|
|
50795
50441
|
} catch {}
|
|
50796
50442
|
let output = `# Team Verdict
|
|
50797
50443
|
|
|
@@ -50845,15 +50491,15 @@ import {
|
|
|
50845
50491
|
appendFileSync as appendFileSync6,
|
|
50846
50492
|
closeSync as closeSync7,
|
|
50847
50493
|
createWriteStream as createWriteStream2,
|
|
50848
|
-
mkdirSync as
|
|
50494
|
+
mkdirSync as mkdirSync12,
|
|
50849
50495
|
openSync as openSync7,
|
|
50850
|
-
readFileSync as
|
|
50496
|
+
readFileSync as readFileSync20,
|
|
50851
50497
|
readSync as readSync3,
|
|
50852
50498
|
statSync as statSync6,
|
|
50853
|
-
writeFileSync as
|
|
50499
|
+
writeFileSync as writeFileSync12
|
|
50854
50500
|
} from "fs";
|
|
50855
|
-
import { homedir as
|
|
50856
|
-
import { join as
|
|
50501
|
+
import { homedir as homedir28 } from "os";
|
|
50502
|
+
import { join as join30, resolve as resolve4, sep } from "path";
|
|
50857
50503
|
import { StringDecoder as StringDecoder2 } from "string_decoder";
|
|
50858
50504
|
function buildChannelSpawnArgs(opts) {
|
|
50859
50505
|
return [
|
|
@@ -50928,7 +50574,7 @@ function readJsonObject(path, maxBytes) {
|
|
|
50928
50574
|
try {
|
|
50929
50575
|
if (fileSize(path) > maxBytes)
|
|
50930
50576
|
return null;
|
|
50931
|
-
const parsed = JSON.parse(
|
|
50577
|
+
const parsed = JSON.parse(readFileSync20(path, "utf-8"));
|
|
50932
50578
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
50933
50579
|
return null;
|
|
50934
50580
|
return parsed;
|
|
@@ -50944,7 +50590,7 @@ function dropLeadingFragment(tail) {
|
|
|
50944
50590
|
return firstBreak === -1 ? tail.text : tail.text.slice(firstBreak + 1);
|
|
50945
50591
|
}
|
|
50946
50592
|
function diskAccounting(sessionDir) {
|
|
50947
|
-
const stats = readTokenStatsAt(
|
|
50593
|
+
const stats = readTokenStatsAt(join30(sessionDir, "tokens.json"));
|
|
50948
50594
|
return {
|
|
50949
50595
|
tokensUsed: (stats?.total_tokens ?? 0) || (stats?.input_tokens ?? 0) + (stats?.output_tokens ?? 0),
|
|
50950
50596
|
costUsd: stats?.total_cost ?? 0,
|
|
@@ -50984,7 +50630,7 @@ class SessionManager {
|
|
|
50984
50630
|
this.maxSessions = options?.maxSessions ?? DEFAULT_MAX_SESSIONS;
|
|
50985
50631
|
this.scrollbackCapacity = options?.scrollbackCapacity ?? DEFAULT_SCROLLBACK;
|
|
50986
50632
|
this.terminalRetentionMs = options?.terminalRetentionMs ?? TERMINAL_RETENTION_MS;
|
|
50987
|
-
this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ??
|
|
50633
|
+
this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ?? join30(homedir28(), ".claudish", "sessions");
|
|
50988
50634
|
this.stallSeconds = options?.stallSeconds;
|
|
50989
50635
|
this.onStateChange = options?.onStateChange;
|
|
50990
50636
|
}
|
|
@@ -51000,19 +50646,19 @@ class SessionManager {
|
|
|
51000
50646
|
const claudeSessionId = randomUUID4();
|
|
51001
50647
|
const timeout = Math.min(opts.timeoutSeconds ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);
|
|
51002
50648
|
const startedAt = new Date().toISOString();
|
|
51003
|
-
const sessionDir = opts.sessionDir ??
|
|
51004
|
-
|
|
50649
|
+
const sessionDir = opts.sessionDir ?? join30(this.sessionsDir, sessionId2);
|
|
50650
|
+
mkdirSync12(sessionDir, { recursive: true });
|
|
51005
50651
|
if (opts.prompt) {
|
|
51006
|
-
|
|
50652
|
+
writeFileSync12(join30(sessionDir, "prompt.md"), opts.prompt, "utf-8");
|
|
51007
50653
|
}
|
|
51008
50654
|
const args = buildChannelSpawnArgs({
|
|
51009
50655
|
model: opts.spawnModel ?? opts.model,
|
|
51010
50656
|
claudeSessionId,
|
|
51011
50657
|
claudishFlags: opts.claudishFlags
|
|
51012
50658
|
});
|
|
51013
|
-
const tokenFile = opts.tokenFile ??
|
|
51014
|
-
const eventLogPath =
|
|
51015
|
-
const upstreamErrorLogPath =
|
|
50659
|
+
const tokenFile = opts.tokenFile ?? join30(sessionDir, "tokens.json");
|
|
50660
|
+
const eventLogPath = join30(sessionDir, "events.jsonl");
|
|
50661
|
+
const upstreamErrorLogPath = join30(sessionDir, "upstream-errors.jsonl");
|
|
51016
50662
|
const cwd = opts.cwd ?? process.cwd();
|
|
51017
50663
|
const spawnTarget = resolveClaudishSpawn();
|
|
51018
50664
|
const proc = spawn3(spawnTarget.command, [...spawnTarget.prefixArgs, ...args], {
|
|
@@ -51027,7 +50673,7 @@ class SessionManager {
|
|
|
51027
50673
|
}
|
|
51028
50674
|
});
|
|
51029
50675
|
const scrollback = new ScrollbackBuffer(this.scrollbackCapacity);
|
|
51030
|
-
const outputLogStream = createWriteStream2(
|
|
50676
|
+
const outputLogStream = createWriteStream2(join30(sessionDir, "output.log"));
|
|
51031
50677
|
const entry = {
|
|
51032
50678
|
info: {
|
|
51033
50679
|
sessionId: sessionId2,
|
|
@@ -51319,7 +50965,7 @@ class SessionManager {
|
|
|
51319
50965
|
return null;
|
|
51320
50966
|
const root = resolve4(this.sessionsDir);
|
|
51321
50967
|
const dir = resolve4(root, sessionId2);
|
|
51322
|
-
if (dir !==
|
|
50968
|
+
if (dir !== join30(root, sessionId2))
|
|
51323
50969
|
return null;
|
|
51324
50970
|
if (!dir.startsWith(root + sep))
|
|
51325
50971
|
return null;
|
|
@@ -51338,7 +50984,7 @@ class SessionManager {
|
|
|
51338
50984
|
} catch {
|
|
51339
50985
|
return null;
|
|
51340
50986
|
}
|
|
51341
|
-
const meta3 = readJsonObject(
|
|
50987
|
+
const meta3 = readJsonObject(join30(sessionDir, "meta.json"), META_READ_LIMIT);
|
|
51342
50988
|
const partial2 = meta3 === null;
|
|
51343
50989
|
const measured = diskAccounting(sessionDir);
|
|
51344
50990
|
const startedAt = metaString(meta3?.startedAt) ?? new Date(dirMtimeMs).toISOString();
|
|
@@ -51368,7 +51014,7 @@ class SessionManager {
|
|
|
51368
51014
|
};
|
|
51369
51015
|
}
|
|
51370
51016
|
diskOutput(record4, tailLines) {
|
|
51371
|
-
const tail = readTailText(
|
|
51017
|
+
const tail = readTailText(join30(record4.sessionDir, "output.log"), OUTPUT_TAIL_BYTES);
|
|
51372
51018
|
const buffer = new ScrollbackBuffer(this.scrollbackCapacity);
|
|
51373
51019
|
if (tail?.text)
|
|
51374
51020
|
buffer.append(dropLeadingFragment(tail));
|
|
@@ -51387,9 +51033,9 @@ class SessionManager {
|
|
|
51387
51033
|
}
|
|
51388
51034
|
diskDiagnostics(record4, limit) {
|
|
51389
51035
|
const { sessionDir, info } = record4;
|
|
51390
|
-
const eventLogPath =
|
|
51391
|
-
const upstreamErrorLogPath =
|
|
51392
|
-
const outputLogPath =
|
|
51036
|
+
const eventLogPath = join30(sessionDir, "events.jsonl");
|
|
51037
|
+
const upstreamErrorLogPath = join30(sessionDir, "upstream-errors.jsonl");
|
|
51038
|
+
const outputLogPath = join30(sessionDir, "output.log");
|
|
51393
51039
|
const events = readTailLines(eventLogPath, EVENT_TAIL_BYTES);
|
|
51394
51040
|
const outputTail = readTailText(outputLogPath, OUTPUT_TAIL_BYTES);
|
|
51395
51041
|
return {
|
|
@@ -51431,7 +51077,7 @@ class SessionManager {
|
|
|
51431
51077
|
};
|
|
51432
51078
|
}
|
|
51433
51079
|
diskStderrForDiagnostics(record4) {
|
|
51434
|
-
const tail = readTailText(
|
|
51080
|
+
const tail = readTailText(join30(record4.sessionDir, "stderr.log"), STDERR_READ_BYTES);
|
|
51435
51081
|
const raw = tail?.text ?? "";
|
|
51436
51082
|
const filtered = record4.info.status === "completed";
|
|
51437
51083
|
const source = filtered ? meaningfulStderr(raw) : raw;
|
|
@@ -51607,11 +51253,11 @@ ${STDERR_TRUNCATION_MARKER} ${STDERR_SIDE_LIMIT} bytes per end \u2026
|
|
|
51607
51253
|
entry.outputLogStream?.end();
|
|
51608
51254
|
entry.outputLogStream = null;
|
|
51609
51255
|
if (entry.stderr) {
|
|
51610
|
-
|
|
51256
|
+
writeFileSync12(join30(entry.sessionDir, "stderr.log"), redactSecrets(entry.stderr), "utf-8");
|
|
51611
51257
|
}
|
|
51612
51258
|
this.refreshAccounting(entry);
|
|
51613
51259
|
entry.info.claudeSessionId = entry.reducer.claudeSessionId ?? entry.info.claudeSessionId;
|
|
51614
|
-
|
|
51260
|
+
writeFileSync12(join30(entry.sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
|
|
51615
51261
|
}
|
|
51616
51262
|
scheduleEviction(entry) {
|
|
51617
51263
|
if (entry.evictHandle)
|
|
@@ -51671,7 +51317,7 @@ ${STDERR_TRUNCATION_MARKER} ${STDERR_SIDE_LIMIT} bytes per end \u2026
|
|
|
51671
51317
|
return { state: "completed", content: "" };
|
|
51672
51318
|
}
|
|
51673
51319
|
refreshAccounting(entry) {
|
|
51674
|
-
const stats = readTokenStatsAt(
|
|
51320
|
+
const stats = readTokenStatsAt(join30(entry.sessionDir, "tokens.json"));
|
|
51675
51321
|
const fileTokens = (stats?.total_tokens ?? 0) || (stats?.input_tokens ?? 0) + (stats?.output_tokens ?? 0);
|
|
51676
51322
|
entry.info.tokensUsed = fileTokens || entry.reducer.tokens;
|
|
51677
51323
|
entry.info.costUsd = stats?.total_cost ?? 0;
|
|
@@ -51862,6 +51508,321 @@ var init_progress_heartbeat = __esm(() => {
|
|
|
51862
51508
|
});
|
|
51863
51509
|
});
|
|
51864
51510
|
|
|
51511
|
+
// src/providers/cache-ttl.ts
|
|
51512
|
+
var FIREBASE_CACHE_TTL_HOURS = 24, FIREBASE_CACHE_TTL_MS;
|
|
51513
|
+
var init_cache_ttl = __esm(() => {
|
|
51514
|
+
FIREBASE_CACHE_TTL_MS = FIREBASE_CACHE_TTL_HOURS * 60 * 60 * 1000;
|
|
51515
|
+
});
|
|
51516
|
+
|
|
51517
|
+
// src/model-loader.ts
|
|
51518
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync13 } from "fs";
|
|
51519
|
+
import { homedir as homedir29 } from "os";
|
|
51520
|
+
import { join as join31 } from "path";
|
|
51521
|
+
function groupRecommendedModels(entries) {
|
|
51522
|
+
const byId = new Map;
|
|
51523
|
+
const categoryOrder = new Map;
|
|
51524
|
+
for (const entry of entries) {
|
|
51525
|
+
const list = byId.get(entry.id);
|
|
51526
|
+
if (list)
|
|
51527
|
+
list.push(entry);
|
|
51528
|
+
else
|
|
51529
|
+
byId.set(entry.id, [entry]);
|
|
51530
|
+
if (!categoryOrder.has(entry.category))
|
|
51531
|
+
categoryOrder.set(entry.category, categoryOrder.size);
|
|
51532
|
+
}
|
|
51533
|
+
const flagship = [];
|
|
51534
|
+
const fast = [];
|
|
51535
|
+
for (const [id, members] of byId.entries()) {
|
|
51536
|
+
const primary = members.find((m) => m.category !== "subscription") ?? members[0];
|
|
51537
|
+
const subscriptions = members.filter((m) => m.category === "subscription");
|
|
51538
|
+
const bucket = primary.category === "programming" || primary.category === "vision" || primary.category === "reasoning" ? "flagship" : "fast";
|
|
51539
|
+
const group = { id, primary, subscriptions, bucket };
|
|
51540
|
+
if (bucket === "flagship")
|
|
51541
|
+
flagship.push(group);
|
|
51542
|
+
else
|
|
51543
|
+
fast.push(group);
|
|
51544
|
+
}
|
|
51545
|
+
const byCuratedPriorityThenFreshness = (a, b) => {
|
|
51546
|
+
const aCat = categoryOrder.get(a.primary.category) ?? Number.MAX_SAFE_INTEGER;
|
|
51547
|
+
const bCat = categoryOrder.get(b.primary.category) ?? Number.MAX_SAFE_INTEGER;
|
|
51548
|
+
if (aCat !== bCat)
|
|
51549
|
+
return aCat - bCat;
|
|
51550
|
+
if (a.primary.priority !== b.primary.priority)
|
|
51551
|
+
return a.primary.priority - b.primary.priority;
|
|
51552
|
+
return compareByReleaseDateDesc(a.primary, b.primary);
|
|
51553
|
+
};
|
|
51554
|
+
flagship.sort(byCuratedPriorityThenFreshness);
|
|
51555
|
+
fast.sort(byCuratedPriorityThenFreshness);
|
|
51556
|
+
return { flagship, fast };
|
|
51557
|
+
}
|
|
51558
|
+
function collectRoutingPrefixes(group, getNativePrefix) {
|
|
51559
|
+
const slug = (group.primary.provider || "").toLowerCase();
|
|
51560
|
+
const native = getNativePrefix(slug);
|
|
51561
|
+
const seen = new Set;
|
|
51562
|
+
const out = [];
|
|
51563
|
+
if (native) {
|
|
51564
|
+
out.push(native);
|
|
51565
|
+
seen.add(native);
|
|
51566
|
+
}
|
|
51567
|
+
for (const subscriptionRow of group.subscriptions) {
|
|
51568
|
+
const routes = subscriptionRow.subscriptions && subscriptionRow.subscriptions.length > 0 ? subscriptionRow.subscriptions : subscriptionRow.subscription ? [subscriptionRow.subscription] : [];
|
|
51569
|
+
const orderedRoutes = [...routes].sort(compareRecommendedRoutes);
|
|
51570
|
+
for (const route2 of orderedRoutes) {
|
|
51571
|
+
const p = route2?.prefix;
|
|
51572
|
+
if (!p || seen.has(p))
|
|
51573
|
+
continue;
|
|
51574
|
+
seen.add(p);
|
|
51575
|
+
out.push(p);
|
|
51576
|
+
}
|
|
51577
|
+
}
|
|
51578
|
+
return out;
|
|
51579
|
+
}
|
|
51580
|
+
function compareRecommendedRoutes(left, right) {
|
|
51581
|
+
const leftRank = left?.tier && Object.hasOwn(RECOMMENDED_ROUTE_TIER_ORDER, left.tier) ? RECOMMENDED_ROUTE_TIER_ORDER[left.tier] : Number.MAX_SAFE_INTEGER;
|
|
51582
|
+
const rightRank = right?.tier && Object.hasOwn(RECOMMENDED_ROUTE_TIER_ORDER, right.tier) ? RECOMMENDED_ROUTE_TIER_ORDER[right.tier] : Number.MAX_SAFE_INTEGER;
|
|
51583
|
+
return leftRank - rightRank;
|
|
51584
|
+
}
|
|
51585
|
+
function parsePriceAvg(s) {
|
|
51586
|
+
if (!s || s === "N/A")
|
|
51587
|
+
return Number.POSITIVE_INFINITY;
|
|
51588
|
+
if (s === "FREE")
|
|
51589
|
+
return 0;
|
|
51590
|
+
const m = s.match(/\$([\d.]+)/);
|
|
51591
|
+
return m ? Number.parseFloat(m[1]) : Number.POSITIVE_INFINITY;
|
|
51592
|
+
}
|
|
51593
|
+
function parseCtx(s) {
|
|
51594
|
+
if (!s || s === "N/A")
|
|
51595
|
+
return 0;
|
|
51596
|
+
const upper = s.toUpperCase();
|
|
51597
|
+
if (upper.includes("M"))
|
|
51598
|
+
return Number.parseFloat(upper) * 1e6;
|
|
51599
|
+
if (upper.includes("K"))
|
|
51600
|
+
return Number.parseFloat(upper) * 1000;
|
|
51601
|
+
return Number.parseInt(s, 10) || 0;
|
|
51602
|
+
}
|
|
51603
|
+
function normalizePricingDisplay(raw) {
|
|
51604
|
+
const pricing = raw || "N/A";
|
|
51605
|
+
if (pricing.includes("-1000000"))
|
|
51606
|
+
return "varies";
|
|
51607
|
+
if (pricing === "$0.00/1M" || pricing === "FREE")
|
|
51608
|
+
return "FREE";
|
|
51609
|
+
return pricing;
|
|
51610
|
+
}
|
|
51611
|
+
function formatListingPrice(entry, opts) {
|
|
51612
|
+
const rate = normalizePricingDisplay(entry.pricing?.average);
|
|
51613
|
+
if (rate !== "N/A")
|
|
51614
|
+
return rate;
|
|
51615
|
+
const plan = entry.subscription?.plan;
|
|
51616
|
+
if (!plan)
|
|
51617
|
+
return "N/A";
|
|
51618
|
+
return opts?.compact ? "SUB" : `SUB (${plan})`;
|
|
51619
|
+
}
|
|
51620
|
+
function computeQuickPicks(primaries) {
|
|
51621
|
+
if (primaries.length === 0) {
|
|
51622
|
+
return {
|
|
51623
|
+
budget: null,
|
|
51624
|
+
largeContext: null,
|
|
51625
|
+
mostCapable: null,
|
|
51626
|
+
visionCoding: null,
|
|
51627
|
+
agentic: null
|
|
51628
|
+
};
|
|
51629
|
+
}
|
|
51630
|
+
const priced = primaries.filter((m) => {
|
|
51631
|
+
const p = parsePriceAvg(m.pricing?.average);
|
|
51632
|
+
return p > 0 && p !== Number.POSITIVE_INFINITY;
|
|
51633
|
+
}).sort((a, b) => parsePriceAvg(a.pricing?.average) - parsePriceAvg(b.pricing?.average));
|
|
51634
|
+
const budget = priced[0] ?? null;
|
|
51635
|
+
const byCtx = [...primaries].sort((a, b) => parseCtx(b.context) - parseCtx(a.context));
|
|
51636
|
+
const largeContext = byCtx[0] ?? null;
|
|
51637
|
+
const byPrice = [...primaries].sort((a, b) => parsePriceAvg(b.pricing?.average) - parsePriceAvg(a.pricing?.average));
|
|
51638
|
+
const mostCapable = byPrice.find((m) => parsePriceAvg(m.pricing?.average) !== Number.POSITIVE_INFINITY) ?? null;
|
|
51639
|
+
const visionCoding = primaries.find((m) => m.supportsVision === true && m.id !== budget?.id && m.id !== mostCapable?.id) ?? null;
|
|
51640
|
+
const agentic = primaries.find((m) => m.supportsReasoning === true && m.id !== mostCapable?.id) ?? null;
|
|
51641
|
+
return { budget, largeContext, mostCapable, visionCoding, agentic };
|
|
51642
|
+
}
|
|
51643
|
+
async function getRecommendedModels(opts = {}) {
|
|
51644
|
+
const { forceRefresh = false } = opts;
|
|
51645
|
+
if (!forceRefresh && _cachedRecommendedModels) {
|
|
51646
|
+
return _cachedRecommendedModels;
|
|
51647
|
+
}
|
|
51648
|
+
if (!forceRefresh && existsSync21(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
51649
|
+
try {
|
|
51650
|
+
const cacheData = JSON.parse(readFileSync21(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
51651
|
+
if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
|
|
51652
|
+
_cachedRecommendedModels = cacheData;
|
|
51653
|
+
return cacheData;
|
|
51654
|
+
}
|
|
51655
|
+
} catch {}
|
|
51656
|
+
}
|
|
51657
|
+
try {
|
|
51658
|
+
const response = await fetch(FIREBASE_RECOMMENDED_URL, {
|
|
51659
|
+
signal: AbortSignal.timeout(RECOMMENDED_FETCH_TIMEOUT_MS)
|
|
51660
|
+
});
|
|
51661
|
+
if (response.ok) {
|
|
51662
|
+
const data = await response.json();
|
|
51663
|
+
if (data.models && data.models.length > 0) {
|
|
51664
|
+
_cachedRecommendedModels = data;
|
|
51665
|
+
try {
|
|
51666
|
+
const cacheDir = join31(homedir29(), ".claudish");
|
|
51667
|
+
mkdirSync13(cacheDir, { recursive: true });
|
|
51668
|
+
writeFileSync13(RECOMMENDED_MODELS_CACHE_PATH, JSON.stringify(data), "utf-8");
|
|
51669
|
+
} catch {}
|
|
51670
|
+
return data;
|
|
51671
|
+
}
|
|
51672
|
+
}
|
|
51673
|
+
} catch {}
|
|
51674
|
+
throw new Error("Unable to load recommended models: Firebase unreachable and no local cache. " + "Check connectivity.");
|
|
51675
|
+
}
|
|
51676
|
+
function getRecommendedModelsSync() {
|
|
51677
|
+
if (_cachedRecommendedModels)
|
|
51678
|
+
return _cachedRecommendedModels;
|
|
51679
|
+
if (existsSync21(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
51680
|
+
try {
|
|
51681
|
+
const cacheData = JSON.parse(readFileSync21(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
51682
|
+
if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
|
|
51683
|
+
_cachedRecommendedModels = cacheData;
|
|
51684
|
+
return cacheData;
|
|
51685
|
+
}
|
|
51686
|
+
} catch {}
|
|
51687
|
+
}
|
|
51688
|
+
return { version: "0", lastUpdated: "", models: [] };
|
|
51689
|
+
}
|
|
51690
|
+
async function warmRecommendedModels() {
|
|
51691
|
+
try {
|
|
51692
|
+
return await getRecommendedModels({ forceRefresh: true });
|
|
51693
|
+
} catch {
|
|
51694
|
+
return null;
|
|
51695
|
+
}
|
|
51696
|
+
}
|
|
51697
|
+
function isFreshEnough(doc2) {
|
|
51698
|
+
const generatedAt = doc2.generatedAt;
|
|
51699
|
+
if (!generatedAt)
|
|
51700
|
+
return true;
|
|
51701
|
+
const ageHours = (Date.now() - new Date(generatedAt).getTime()) / (1000 * 60 * 60);
|
|
51702
|
+
return ageHours <= FIREBASE_CACHE_TTL_HOURS;
|
|
51703
|
+
}
|
|
51704
|
+
async function searchModels(query, limit = 50) {
|
|
51705
|
+
const url2 = `${FIREBASE_BASE_URL}?search=${encodeURIComponent(query)}&limit=${limit}&status=active`;
|
|
51706
|
+
const response = await fetch(url2, {
|
|
51707
|
+
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
51708
|
+
});
|
|
51709
|
+
if (!response.ok) {
|
|
51710
|
+
throw new Error(`Firebase search returned ${response.status} ${response.statusText}`);
|
|
51711
|
+
}
|
|
51712
|
+
const data = await response.json();
|
|
51713
|
+
return data.models ?? [];
|
|
51714
|
+
}
|
|
51715
|
+
async function getModelByIdFromFirebase(modelId) {
|
|
51716
|
+
const url2 = `${FIREBASE_BASE_URL}?search=${encodeURIComponent(modelId)}&limit=5`;
|
|
51717
|
+
const response = await fetch(url2, {
|
|
51718
|
+
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
51719
|
+
});
|
|
51720
|
+
if (!response.ok) {
|
|
51721
|
+
throw new Error(`Firebase lookup returned ${response.status} ${response.statusText}`);
|
|
51722
|
+
}
|
|
51723
|
+
const data = await response.json();
|
|
51724
|
+
const models = data.models ?? [];
|
|
51725
|
+
for (const m of models) {
|
|
51726
|
+
if (m.modelId === modelId)
|
|
51727
|
+
return m;
|
|
51728
|
+
if (m.aliases?.includes(modelId))
|
|
51729
|
+
return m;
|
|
51730
|
+
}
|
|
51731
|
+
return null;
|
|
51732
|
+
}
|
|
51733
|
+
async function getTop100Models() {
|
|
51734
|
+
const url2 = `${FIREBASE_BASE_URL}?catalog=top100`;
|
|
51735
|
+
const response = await fetch(url2, {
|
|
51736
|
+
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
51737
|
+
});
|
|
51738
|
+
if (!response.ok) {
|
|
51739
|
+
throw new Error(`Firebase top100 fetch failed: ${response.status} ${response.statusText}`);
|
|
51740
|
+
}
|
|
51741
|
+
const data = await response.json();
|
|
51742
|
+
return data;
|
|
51743
|
+
}
|
|
51744
|
+
async function getProviderList() {
|
|
51745
|
+
const url2 = `${FIREBASE_BASE_URL}?catalog=providers`;
|
|
51746
|
+
const response = await fetch(url2, {
|
|
51747
|
+
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
51748
|
+
});
|
|
51749
|
+
if (!response.ok) {
|
|
51750
|
+
throw new Error(`Firebase providers fetch failed: ${response.status} ${response.statusText}`);
|
|
51751
|
+
}
|
|
51752
|
+
const data = await response.json();
|
|
51753
|
+
return data.providers ?? [];
|
|
51754
|
+
}
|
|
51755
|
+
async function getModelsByProvider(provider, limit = 200) {
|
|
51756
|
+
const url2 = `${FIREBASE_BASE_URL}?provider=${encodeURIComponent(provider)}&status=active&limit=${limit}`;
|
|
51757
|
+
const response = await fetch(url2, {
|
|
51758
|
+
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
51759
|
+
});
|
|
51760
|
+
if (!response.ok) {
|
|
51761
|
+
throw new Error(`Firebase provider query returned ${response.status} ${response.statusText}`);
|
|
51762
|
+
}
|
|
51763
|
+
const data = await response.json();
|
|
51764
|
+
if (Array.isArray(data))
|
|
51765
|
+
return data;
|
|
51766
|
+
return data.models ?? [];
|
|
51767
|
+
}
|
|
51768
|
+
function loadModelInfo() {
|
|
51769
|
+
if (_cachedModelInfo) {
|
|
51770
|
+
return _cachedModelInfo;
|
|
51771
|
+
}
|
|
51772
|
+
const data = getRecommendedModelsSync();
|
|
51773
|
+
const modelInfo = {};
|
|
51774
|
+
for (const model of data.models) {
|
|
51775
|
+
modelInfo[model.id] = {
|
|
51776
|
+
name: model.name,
|
|
51777
|
+
description: model.description,
|
|
51778
|
+
priority: model.priority,
|
|
51779
|
+
provider: model.provider
|
|
51780
|
+
};
|
|
51781
|
+
}
|
|
51782
|
+
modelInfo.custom = {
|
|
51783
|
+
name: "Custom Model",
|
|
51784
|
+
description: "Enter any model ID manually",
|
|
51785
|
+
priority: 999,
|
|
51786
|
+
provider: "Custom"
|
|
51787
|
+
};
|
|
51788
|
+
_cachedModelInfo = modelInfo;
|
|
51789
|
+
return modelInfo;
|
|
51790
|
+
}
|
|
51791
|
+
function getAvailableModels() {
|
|
51792
|
+
if (_cachedModelIds) {
|
|
51793
|
+
return _cachedModelIds;
|
|
51794
|
+
}
|
|
51795
|
+
const data = getRecommendedModelsSync();
|
|
51796
|
+
const modelIds = data.models.sort((a, b) => a.priority - b.priority).map((m) => m.id);
|
|
51797
|
+
const result = [...modelIds, "custom"];
|
|
51798
|
+
_cachedModelIds = result;
|
|
51799
|
+
return result;
|
|
51800
|
+
}
|
|
51801
|
+
var _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels = null, FIREBASE_BASE_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/queryModels", FIREBASE_RECOMMENDED_URL, RECOMMENDED_MODELS_CACHE_PATH, RECOMMENDED_FETCH_TIMEOUT_MS = 5000, SEARCH_FETCH_TIMEOUT_MS = 1e4, FIREBASE_SLUG_TO_PROVIDER_NAME, RECOMMENDED_ROUTE_TIER_ORDER;
|
|
51802
|
+
var init_model_loader = __esm(() => {
|
|
51803
|
+
init_cache_ttl();
|
|
51804
|
+
FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
|
|
51805
|
+
RECOMMENDED_MODELS_CACHE_PATH = join31(homedir29(), ".claudish", "recommended-models-cache.json");
|
|
51806
|
+
FIREBASE_SLUG_TO_PROVIDER_NAME = {
|
|
51807
|
+
openai: "openai",
|
|
51808
|
+
google: "google",
|
|
51809
|
+
"x-ai": "x-ai",
|
|
51810
|
+
"z-ai": "z-ai",
|
|
51811
|
+
moonshotai: "kimi",
|
|
51812
|
+
minimax: "minimax",
|
|
51813
|
+
qwen: "qwen",
|
|
51814
|
+
deepseek: "deepseek",
|
|
51815
|
+
mistralai: "mistralai",
|
|
51816
|
+
sakana: "sakana"
|
|
51817
|
+
};
|
|
51818
|
+
RECOMMENDED_ROUTE_TIER_ORDER = {
|
|
51819
|
+
native: 0,
|
|
51820
|
+
general: 1,
|
|
51821
|
+
metered: 2,
|
|
51822
|
+
aggregator: 3
|
|
51823
|
+
};
|
|
51824
|
+
});
|
|
51825
|
+
|
|
51865
51826
|
// src/port-manager.ts
|
|
51866
51827
|
var exports_port_manager = {};
|
|
51867
51828
|
__export(exports_port_manager, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudish",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.4",
|
|
4
4
|
"description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,10 +60,10 @@
|
|
|
60
60
|
"ai"
|
|
61
61
|
],
|
|
62
62
|
"optionalDependencies": {
|
|
63
|
-
"@claudish/magmux-darwin-arm64": "9.0.
|
|
64
|
-
"@claudish/magmux-darwin-x64": "9.0.
|
|
65
|
-
"@claudish/magmux-linux-arm64": "9.0.
|
|
66
|
-
"@claudish/magmux-linux-x64": "9.0.
|
|
63
|
+
"@claudish/magmux-darwin-arm64": "9.0.4",
|
|
64
|
+
"@claudish/magmux-darwin-x64": "9.0.4",
|
|
65
|
+
"@claudish/magmux-linux-arm64": "9.0.4",
|
|
66
|
+
"@claudish/magmux-linux-x64": "9.0.4"
|
|
67
67
|
},
|
|
68
68
|
"author": "Jack Rudenko <i@madappgang.com>",
|
|
69
69
|
"license": "MIT",
|