claudish 9.0.2 → 9.0.3
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 +397 -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.3";
|
|
735
735
|
|
|
736
736
|
// src/logger.ts
|
|
737
737
|
var exports_logger = {};
|
|
@@ -47685,349 +47685,6 @@ var init_routing_hints = __esm(() => {
|
|
|
47685
47685
|
};
|
|
47686
47686
|
});
|
|
47687
47687
|
|
|
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
47688
|
// src/providers/default-routing-rules.ts
|
|
48032
47689
|
function validateRoutingRulesAgainstProviders(rules) {
|
|
48033
47690
|
const unknown3 = [];
|
|
@@ -48119,26 +47776,12 @@ var init_model_availability = __esm(() => {
|
|
|
48119
47776
|
function mergeRoutingRules(defaults, global_, local) {
|
|
48120
47777
|
return { ...defaults, ...global_, ...local };
|
|
48121
47778
|
}
|
|
48122
|
-
function loadRoutingRules() {
|
|
48123
|
-
const local = loadLocalConfig()?.routing ?? {};
|
|
48124
|
-
const global_ = loadConfig().routing ?? {};
|
|
47779
|
+
function loadRoutingRules(sources) {
|
|
47780
|
+
const local = sources ? sources.localRules : loadLocalConfig()?.routing ?? {};
|
|
47781
|
+
const global_ = sources ? sources.globalRules : loadConfig().routing ?? {};
|
|
48125
47782
|
validateRoutingRules(local);
|
|
48126
47783
|
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;
|
|
47784
|
+
return mergeRoutingRules(DEFAULT_ROUTING_RULES, global_, local);
|
|
48142
47785
|
}
|
|
48143
47786
|
function validateRoutingRules(rules) {
|
|
48144
47787
|
const seenLower = new Map;
|
|
@@ -48333,7 +47976,6 @@ var init_routing_rules = __esm(() => {
|
|
|
48333
47976
|
init_authority();
|
|
48334
47977
|
init_remote_provider_types();
|
|
48335
47978
|
init_logger();
|
|
48336
|
-
init_model_loader();
|
|
48337
47979
|
init_profile_config();
|
|
48338
47980
|
init_auto_route();
|
|
48339
47981
|
init_catalog_client();
|
|
@@ -49477,8 +49119,8 @@ __export(exports_session_discovery, {
|
|
|
49477
49119
|
});
|
|
49478
49120
|
import { execFile, execFileSync as execFileSync2 } from "child_process";
|
|
49479
49121
|
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
|
|
49122
|
+
import { homedir as homedir27 } from "os";
|
|
49123
|
+
import { basename, join as join27 } from "path";
|
|
49482
49124
|
function slugForPath(absPath) {
|
|
49483
49125
|
return absPath.replace(/[/.]/g, "-");
|
|
49484
49126
|
}
|
|
@@ -49487,7 +49129,7 @@ function transcriptPathFor(cwd, sessionUuid) {
|
|
|
49487
49129
|
try {
|
|
49488
49130
|
real = realpathSync(cwd);
|
|
49489
49131
|
} catch {}
|
|
49490
|
-
return
|
|
49132
|
+
return join27(PROJECTS_DIR, slugForPath(real), `${sessionUuid}.jsonl`);
|
|
49491
49133
|
}
|
|
49492
49134
|
function isAgentSession(row) {
|
|
49493
49135
|
return row.entrypoint !== undefined && row.entrypoint !== "cli";
|
|
@@ -49534,7 +49176,7 @@ function projectDirs() {
|
|
|
49534
49176
|
}
|
|
49535
49177
|
}
|
|
49536
49178
|
function sessionsIn(dirName) {
|
|
49537
|
-
const dir =
|
|
49179
|
+
const dir = join27(PROJECTS_DIR, dirName);
|
|
49538
49180
|
let names;
|
|
49539
49181
|
try {
|
|
49540
49182
|
names = readdirSync4(dir).filter((n) => n.endsWith(".jsonl"));
|
|
@@ -49543,7 +49185,7 @@ function sessionsIn(dirName) {
|
|
|
49543
49185
|
}
|
|
49544
49186
|
const rows = [];
|
|
49545
49187
|
for (const n of names) {
|
|
49546
|
-
const file2 =
|
|
49188
|
+
const file2 = join27(dir, n);
|
|
49547
49189
|
try {
|
|
49548
49190
|
const st = statSync5(file2);
|
|
49549
49191
|
if (st.size === 0)
|
|
@@ -49902,7 +49544,7 @@ function findLatestSessionId(cwd = process.cwd(), sinceMs = 0) {
|
|
|
49902
49544
|
}
|
|
49903
49545
|
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
49546
|
var init_session_discovery = __esm(() => {
|
|
49905
|
-
PROJECTS_DIR =
|
|
49547
|
+
PROJECTS_DIR = join27(homedir27(), ".claude", "projects");
|
|
49906
49548
|
HEAD_BYTES = 64 * 1024;
|
|
49907
49549
|
TAIL_BYTES = 128 * 1024;
|
|
49908
49550
|
HARNESS_ENVELOPES = [
|
|
@@ -49937,19 +49579,19 @@ function newStdioDecoder() {
|
|
|
49937
49579
|
var init_stdio_decode = () => {};
|
|
49938
49580
|
|
|
49939
49581
|
// src/team-stats.ts
|
|
49940
|
-
import { existsSync as
|
|
49941
|
-
import { join as
|
|
49582
|
+
import { existsSync as existsSync19, readFileSync as readFileSync18, writeFileSync as writeFileSync10 } from "fs";
|
|
49583
|
+
import { join as join28 } from "path";
|
|
49942
49584
|
function statsDir(sessionPath) {
|
|
49943
|
-
return
|
|
49585
|
+
return join28(sessionPath, "stats");
|
|
49944
49586
|
}
|
|
49945
49587
|
function tokenFileFor(sessionPath, anonId) {
|
|
49946
|
-
return
|
|
49588
|
+
return join28(statsDir(sessionPath), `${anonId}.json`);
|
|
49947
49589
|
}
|
|
49948
49590
|
function readTokenStatsAt(path) {
|
|
49949
|
-
if (!
|
|
49591
|
+
if (!existsSync19(path))
|
|
49950
49592
|
return null;
|
|
49951
49593
|
try {
|
|
49952
|
-
return JSON.parse(
|
|
49594
|
+
return JSON.parse(readFileSync18(path, "utf-8"));
|
|
49953
49595
|
} catch {
|
|
49954
49596
|
return null;
|
|
49955
49597
|
}
|
|
@@ -50100,7 +49742,7 @@ ${segs.join(" \xB7 ")}`;
|
|
|
50100
49742
|
}
|
|
50101
49743
|
function writeStatusFile(sessionPath, manifest, status, opts) {
|
|
50102
49744
|
try {
|
|
50103
|
-
|
|
49745
|
+
writeFileSync10(join28(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
|
|
50104
49746
|
`, "utf-8");
|
|
50105
49747
|
} catch {}
|
|
50106
49748
|
}
|
|
@@ -50135,13 +49777,13 @@ __export(exports_team_orchestrator, {
|
|
|
50135
49777
|
import { spawn as spawn2 } from "child_process";
|
|
50136
49778
|
import {
|
|
50137
49779
|
createWriteStream,
|
|
50138
|
-
existsSync as
|
|
50139
|
-
mkdirSync as
|
|
50140
|
-
readFileSync as
|
|
49780
|
+
existsSync as existsSync20,
|
|
49781
|
+
mkdirSync as mkdirSync11,
|
|
49782
|
+
readFileSync as readFileSync19,
|
|
50141
49783
|
readdirSync as readdirSync5,
|
|
50142
|
-
writeFileSync as
|
|
49784
|
+
writeFileSync as writeFileSync11
|
|
50143
49785
|
} from "fs";
|
|
50144
|
-
import { basename as basename2, join as
|
|
49786
|
+
import { basename as basename2, join as join29, resolve as resolve3 } from "path";
|
|
50145
49787
|
function resolveCaptureMode(explicit, env = process.env) {
|
|
50146
49788
|
if (explicit)
|
|
50147
49789
|
return explicit;
|
|
@@ -50259,7 +49901,7 @@ function persistErrorLog(errorLogPath, header, stderr, stdoutTail) {
|
|
|
50259
49901
|
parts.push("--- stderr ---", stderr.trim() ? redactSecrets(stderr) : "(empty)", "");
|
|
50260
49902
|
parts.push("--- stdout (tail) ---", stdoutTail.trim() ? redactSecrets(stdoutTail) : "(empty)", "");
|
|
50261
49903
|
try {
|
|
50262
|
-
|
|
49904
|
+
writeFileSync11(errorLogPath, parts.join(`
|
|
50263
49905
|
`), "utf-8");
|
|
50264
49906
|
} catch {}
|
|
50265
49907
|
}
|
|
@@ -50277,10 +49919,10 @@ function readTeamInputFile(inputPath) {
|
|
|
50277
49919
|
if (!resolved.startsWith(`${cwd}/`) && resolved !== cwd) {
|
|
50278
49920
|
throw new Error(`Input file must be within current directory: ${inputPath}`);
|
|
50279
49921
|
}
|
|
50280
|
-
if (!
|
|
49922
|
+
if (!existsSync20(resolved)) {
|
|
50281
49923
|
throw new Error(`Input file not found: ${resolved}`);
|
|
50282
49924
|
}
|
|
50283
|
-
const text =
|
|
49925
|
+
const text = readFileSync19(resolved, "utf-8");
|
|
50284
49926
|
if (text.trim().length === 0) {
|
|
50285
49927
|
throw new Error(`Input file is empty: ${resolved}`);
|
|
50286
49928
|
}
|
|
@@ -50290,14 +49932,14 @@ function setupSession(sessionPath, models, input) {
|
|
|
50290
49932
|
if (models.length === 0) {
|
|
50291
49933
|
throw new Error("At least one model is required");
|
|
50292
49934
|
}
|
|
50293
|
-
if (
|
|
49935
|
+
if (existsSync20(join29(sessionPath, "manifest.json"))) {
|
|
50294
49936
|
throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
|
|
50295
49937
|
}
|
|
50296
|
-
|
|
50297
|
-
|
|
49938
|
+
mkdirSync11(join29(sessionPath, "work"), { recursive: true });
|
|
49939
|
+
mkdirSync11(join29(sessionPath, "errors"), { recursive: true });
|
|
50298
49940
|
if (input !== undefined) {
|
|
50299
|
-
|
|
50300
|
-
} else if (!
|
|
49941
|
+
writeFileSync11(join29(sessionPath, "input.md"), input, "utf-8");
|
|
49942
|
+
} else if (!existsSync20(join29(sessionPath, "input.md"))) {
|
|
50301
49943
|
throw new Error(`No input.md found at ${sessionPath} and no input provided`);
|
|
50302
49944
|
}
|
|
50303
49945
|
const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
|
|
@@ -50314,9 +49956,9 @@ function setupSession(sessionPath, models, input) {
|
|
|
50314
49956
|
model: models[i],
|
|
50315
49957
|
assignedAt: now2
|
|
50316
49958
|
};
|
|
50317
|
-
|
|
49959
|
+
mkdirSync11(join29(sessionPath, "work", anonId), { recursive: true });
|
|
50318
49960
|
}
|
|
50319
|
-
|
|
49961
|
+
writeFileSync11(join29(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
|
|
50320
49962
|
const status = {
|
|
50321
49963
|
startedAt: now2,
|
|
50322
49964
|
models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
|
|
@@ -50330,7 +49972,7 @@ function setupSession(sessionPath, models, input) {
|
|
|
50330
49972
|
}
|
|
50331
49973
|
]))
|
|
50332
49974
|
};
|
|
50333
|
-
|
|
49975
|
+
writeFileSync11(join29(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
|
|
50334
49976
|
return manifest;
|
|
50335
49977
|
}
|
|
50336
49978
|
function assertValidRequirePattern(pattern) {
|
|
@@ -50347,22 +49989,22 @@ function readFullOutputIfNeeded(opts) {
|
|
|
50347
49989
|
if (crashed || !requirePattern || outputSize <= STDOUT_TAIL_LIMIT)
|
|
50348
49990
|
return;
|
|
50349
49991
|
try {
|
|
50350
|
-
return
|
|
49992
|
+
return readFileSync19(outputPath, "utf-8");
|
|
50351
49993
|
} catch {
|
|
50352
49994
|
return;
|
|
50353
49995
|
}
|
|
50354
49996
|
}
|
|
50355
49997
|
async function startModels(sessionPath, opts = {}) {
|
|
50356
49998
|
assertValidRequirePattern(opts.requirePattern);
|
|
50357
|
-
const manifest = JSON.parse(
|
|
50358
|
-
const statusPath =
|
|
50359
|
-
const inputPath =
|
|
50360
|
-
const inputContent =
|
|
49999
|
+
const manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
|
|
50000
|
+
const statusPath = join29(sessionPath, "status.json");
|
|
50001
|
+
const inputPath = join29(sessionPath, "input.md");
|
|
50002
|
+
const inputContent = readFileSync19(inputPath, "utf-8");
|
|
50361
50003
|
const spawnPlan = await (opts.spawnPlanner ?? prehydrateCredentialsForSpawn)(Object.values(manifest.models).map((m) => m.model));
|
|
50362
|
-
const statusCache = JSON.parse(
|
|
50004
|
+
const statusCache = JSON.parse(readFileSync19(statusPath, "utf-8"));
|
|
50363
50005
|
function updateModelStatus(id, update) {
|
|
50364
50006
|
statusCache.models[id] = { ...statusCache.models[id], ...update };
|
|
50365
|
-
|
|
50007
|
+
writeFileSync11(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
|
|
50366
50008
|
}
|
|
50367
50009
|
const minOutputBytes = opts.minOutputBytes ?? DEFAULT_MIN_OUTPUT_BYTES;
|
|
50368
50010
|
const requirePattern = opts.requirePattern;
|
|
@@ -50395,7 +50037,7 @@ async function startModels(sessionPath, opts = {}) {
|
|
|
50395
50037
|
persistErrorLog(rt.errorLogPath, `RECOVERED: ${note}`, stderr, stdoutTail);
|
|
50396
50038
|
opts.onStatusChange?.(id, statusCache.models[id]);
|
|
50397
50039
|
}
|
|
50398
|
-
|
|
50040
|
+
mkdirSync11(statsDir(sessionPath), { recursive: true });
|
|
50399
50041
|
const processes = new Map;
|
|
50400
50042
|
const runtimes = new Map;
|
|
50401
50043
|
const cancelledSlots = new Set;
|
|
@@ -50408,9 +50050,9 @@ async function startModels(sessionPath, opts = {}) {
|
|
|
50408
50050
|
process.on("SIGINT", sigintHandler);
|
|
50409
50051
|
const completionPromises = [];
|
|
50410
50052
|
for (const [anonId, entry] of Object.entries(manifest.models)) {
|
|
50411
|
-
const outputPath =
|
|
50412
|
-
const errorLogPath =
|
|
50413
|
-
const upstreamErrorLogPath =
|
|
50053
|
+
const outputPath = join29(sessionPath, `response-${anonId}.md`);
|
|
50054
|
+
const errorLogPath = join29(sessionPath, "errors", `${anonId}.log`);
|
|
50055
|
+
const upstreamErrorLogPath = join29(sessionPath, "errors", `${anonId}-upstream.jsonl`);
|
|
50414
50056
|
const spawnModel = spawnPlan.pinned.get(entry.model) ?? entry.model;
|
|
50415
50057
|
const args = [
|
|
50416
50058
|
"--model",
|
|
@@ -50550,7 +50192,7 @@ async function startModels(sessionPath, opts = {}) {
|
|
|
50550
50192
|
stderrSnippet: stderr ? redactSecrets(stderr).slice(-2000) : undefined,
|
|
50551
50193
|
stdoutSnippet: stdoutTail ? redactSecrets(stdoutTail).slice(-2000) : undefined,
|
|
50552
50194
|
errorLogPath,
|
|
50553
|
-
upstreamErrorLogPath:
|
|
50195
|
+
upstreamErrorLogPath: existsSync20(upstreamErrorLogPath) ? upstreamErrorLogPath : undefined,
|
|
50554
50196
|
workDir: sessionPath
|
|
50555
50197
|
}
|
|
50556
50198
|
});
|
|
@@ -50570,7 +50212,7 @@ async function startModels(sessionPath, opts = {}) {
|
|
|
50570
50212
|
proc.on("exit", (code) => {
|
|
50571
50213
|
const timedOut = statusCache.models[anonId]?.state === "TIMEOUT";
|
|
50572
50214
|
if (!timedOut && meaningfulStderr(stderr)) {
|
|
50573
|
-
|
|
50215
|
+
writeFileSync11(errorLogPath, redactSecrets(stderr), "utf-8");
|
|
50574
50216
|
}
|
|
50575
50217
|
exitCode = code;
|
|
50576
50218
|
if (outputStream.destroyed) {
|
|
@@ -50650,23 +50292,23 @@ async function judgeResponses(sessionPath, opts = {}) {
|
|
|
50650
50292
|
const responses = {};
|
|
50651
50293
|
for (const file2 of responseFiles) {
|
|
50652
50294
|
const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
|
|
50653
|
-
responses[id] =
|
|
50295
|
+
responses[id] = readFileSync19(join29(sessionPath, file2), "utf-8");
|
|
50654
50296
|
}
|
|
50655
|
-
const input =
|
|
50297
|
+
const input = readFileSync19(join29(sessionPath, "input.md"), "utf-8");
|
|
50656
50298
|
const judgePrompt = buildJudgePrompt(input, responses);
|
|
50657
|
-
|
|
50299
|
+
writeFileSync11(join29(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
|
|
50658
50300
|
const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
|
|
50659
|
-
const judgePath =
|
|
50660
|
-
|
|
50301
|
+
const judgePath = join29(sessionPath, "judging");
|
|
50302
|
+
mkdirSync11(judgePath, { recursive: true });
|
|
50661
50303
|
setupSession(judgePath, judgeModels, judgePrompt);
|
|
50662
50304
|
await runModels(judgePath, { claudeFlags: opts.claudeFlags });
|
|
50663
50305
|
const votes = parseJudgeVotes(judgePath, Object.keys(responses));
|
|
50664
50306
|
const verdict = aggregateVerdict(votes, Object.keys(responses));
|
|
50665
|
-
|
|
50307
|
+
writeFileSync11(join29(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
|
|
50666
50308
|
return verdict;
|
|
50667
50309
|
}
|
|
50668
50310
|
function getStatus(sessionPath) {
|
|
50669
|
-
return JSON.parse(
|
|
50311
|
+
return JSON.parse(readFileSync19(join29(sessionPath, "status.json"), "utf-8"));
|
|
50670
50312
|
}
|
|
50671
50313
|
function fisherYatesShuffle(arr) {
|
|
50672
50314
|
for (let i = arr.length - 1;i > 0; i--) {
|
|
@@ -50676,7 +50318,7 @@ function fisherYatesShuffle(arr) {
|
|
|
50676
50318
|
return arr;
|
|
50677
50319
|
}
|
|
50678
50320
|
function getDefaultJudgeModels(sessionPath) {
|
|
50679
|
-
const manifest = JSON.parse(
|
|
50321
|
+
const manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
|
|
50680
50322
|
return Object.values(manifest.models).map((e) => e.model);
|
|
50681
50323
|
}
|
|
50682
50324
|
function buildJudgePrompt(input, responses) {
|
|
@@ -50739,7 +50381,7 @@ function parseJudgeVotes(judgePath, responseIds) {
|
|
|
50739
50381
|
const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
|
|
50740
50382
|
let content;
|
|
50741
50383
|
try {
|
|
50742
|
-
content =
|
|
50384
|
+
content = readFileSync19(join29(judgePath, file2), "utf-8");
|
|
50743
50385
|
} catch {
|
|
50744
50386
|
continue;
|
|
50745
50387
|
}
|
|
@@ -50791,7 +50433,7 @@ function aggregateVerdict(votes, responseIds) {
|
|
|
50791
50433
|
function formatVerdict(verdict, sessionPath) {
|
|
50792
50434
|
let manifest = null;
|
|
50793
50435
|
try {
|
|
50794
|
-
manifest = JSON.parse(
|
|
50436
|
+
manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
|
|
50795
50437
|
} catch {}
|
|
50796
50438
|
let output = `# Team Verdict
|
|
50797
50439
|
|
|
@@ -50845,15 +50487,15 @@ import {
|
|
|
50845
50487
|
appendFileSync as appendFileSync6,
|
|
50846
50488
|
closeSync as closeSync7,
|
|
50847
50489
|
createWriteStream as createWriteStream2,
|
|
50848
|
-
mkdirSync as
|
|
50490
|
+
mkdirSync as mkdirSync12,
|
|
50849
50491
|
openSync as openSync7,
|
|
50850
|
-
readFileSync as
|
|
50492
|
+
readFileSync as readFileSync20,
|
|
50851
50493
|
readSync as readSync3,
|
|
50852
50494
|
statSync as statSync6,
|
|
50853
|
-
writeFileSync as
|
|
50495
|
+
writeFileSync as writeFileSync12
|
|
50854
50496
|
} from "fs";
|
|
50855
|
-
import { homedir as
|
|
50856
|
-
import { join as
|
|
50497
|
+
import { homedir as homedir28 } from "os";
|
|
50498
|
+
import { join as join30, resolve as resolve4, sep } from "path";
|
|
50857
50499
|
import { StringDecoder as StringDecoder2 } from "string_decoder";
|
|
50858
50500
|
function buildChannelSpawnArgs(opts) {
|
|
50859
50501
|
return [
|
|
@@ -50928,7 +50570,7 @@ function readJsonObject(path, maxBytes) {
|
|
|
50928
50570
|
try {
|
|
50929
50571
|
if (fileSize(path) > maxBytes)
|
|
50930
50572
|
return null;
|
|
50931
|
-
const parsed = JSON.parse(
|
|
50573
|
+
const parsed = JSON.parse(readFileSync20(path, "utf-8"));
|
|
50932
50574
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
50933
50575
|
return null;
|
|
50934
50576
|
return parsed;
|
|
@@ -50944,7 +50586,7 @@ function dropLeadingFragment(tail) {
|
|
|
50944
50586
|
return firstBreak === -1 ? tail.text : tail.text.slice(firstBreak + 1);
|
|
50945
50587
|
}
|
|
50946
50588
|
function diskAccounting(sessionDir) {
|
|
50947
|
-
const stats = readTokenStatsAt(
|
|
50589
|
+
const stats = readTokenStatsAt(join30(sessionDir, "tokens.json"));
|
|
50948
50590
|
return {
|
|
50949
50591
|
tokensUsed: (stats?.total_tokens ?? 0) || (stats?.input_tokens ?? 0) + (stats?.output_tokens ?? 0),
|
|
50950
50592
|
costUsd: stats?.total_cost ?? 0,
|
|
@@ -50984,7 +50626,7 @@ class SessionManager {
|
|
|
50984
50626
|
this.maxSessions = options?.maxSessions ?? DEFAULT_MAX_SESSIONS;
|
|
50985
50627
|
this.scrollbackCapacity = options?.scrollbackCapacity ?? DEFAULT_SCROLLBACK;
|
|
50986
50628
|
this.terminalRetentionMs = options?.terminalRetentionMs ?? TERMINAL_RETENTION_MS;
|
|
50987
|
-
this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ??
|
|
50629
|
+
this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ?? join30(homedir28(), ".claudish", "sessions");
|
|
50988
50630
|
this.stallSeconds = options?.stallSeconds;
|
|
50989
50631
|
this.onStateChange = options?.onStateChange;
|
|
50990
50632
|
}
|
|
@@ -51000,19 +50642,19 @@ class SessionManager {
|
|
|
51000
50642
|
const claudeSessionId = randomUUID4();
|
|
51001
50643
|
const timeout = Math.min(opts.timeoutSeconds ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);
|
|
51002
50644
|
const startedAt = new Date().toISOString();
|
|
51003
|
-
const sessionDir = opts.sessionDir ??
|
|
51004
|
-
|
|
50645
|
+
const sessionDir = opts.sessionDir ?? join30(this.sessionsDir, sessionId2);
|
|
50646
|
+
mkdirSync12(sessionDir, { recursive: true });
|
|
51005
50647
|
if (opts.prompt) {
|
|
51006
|
-
|
|
50648
|
+
writeFileSync12(join30(sessionDir, "prompt.md"), opts.prompt, "utf-8");
|
|
51007
50649
|
}
|
|
51008
50650
|
const args = buildChannelSpawnArgs({
|
|
51009
50651
|
model: opts.spawnModel ?? opts.model,
|
|
51010
50652
|
claudeSessionId,
|
|
51011
50653
|
claudishFlags: opts.claudishFlags
|
|
51012
50654
|
});
|
|
51013
|
-
const tokenFile = opts.tokenFile ??
|
|
51014
|
-
const eventLogPath =
|
|
51015
|
-
const upstreamErrorLogPath =
|
|
50655
|
+
const tokenFile = opts.tokenFile ?? join30(sessionDir, "tokens.json");
|
|
50656
|
+
const eventLogPath = join30(sessionDir, "events.jsonl");
|
|
50657
|
+
const upstreamErrorLogPath = join30(sessionDir, "upstream-errors.jsonl");
|
|
51016
50658
|
const cwd = opts.cwd ?? process.cwd();
|
|
51017
50659
|
const spawnTarget = resolveClaudishSpawn();
|
|
51018
50660
|
const proc = spawn3(spawnTarget.command, [...spawnTarget.prefixArgs, ...args], {
|
|
@@ -51027,7 +50669,7 @@ class SessionManager {
|
|
|
51027
50669
|
}
|
|
51028
50670
|
});
|
|
51029
50671
|
const scrollback = new ScrollbackBuffer(this.scrollbackCapacity);
|
|
51030
|
-
const outputLogStream = createWriteStream2(
|
|
50672
|
+
const outputLogStream = createWriteStream2(join30(sessionDir, "output.log"));
|
|
51031
50673
|
const entry = {
|
|
51032
50674
|
info: {
|
|
51033
50675
|
sessionId: sessionId2,
|
|
@@ -51319,7 +50961,7 @@ class SessionManager {
|
|
|
51319
50961
|
return null;
|
|
51320
50962
|
const root = resolve4(this.sessionsDir);
|
|
51321
50963
|
const dir = resolve4(root, sessionId2);
|
|
51322
|
-
if (dir !==
|
|
50964
|
+
if (dir !== join30(root, sessionId2))
|
|
51323
50965
|
return null;
|
|
51324
50966
|
if (!dir.startsWith(root + sep))
|
|
51325
50967
|
return null;
|
|
@@ -51338,7 +50980,7 @@ class SessionManager {
|
|
|
51338
50980
|
} catch {
|
|
51339
50981
|
return null;
|
|
51340
50982
|
}
|
|
51341
|
-
const meta3 = readJsonObject(
|
|
50983
|
+
const meta3 = readJsonObject(join30(sessionDir, "meta.json"), META_READ_LIMIT);
|
|
51342
50984
|
const partial2 = meta3 === null;
|
|
51343
50985
|
const measured = diskAccounting(sessionDir);
|
|
51344
50986
|
const startedAt = metaString(meta3?.startedAt) ?? new Date(dirMtimeMs).toISOString();
|
|
@@ -51368,7 +51010,7 @@ class SessionManager {
|
|
|
51368
51010
|
};
|
|
51369
51011
|
}
|
|
51370
51012
|
diskOutput(record4, tailLines) {
|
|
51371
|
-
const tail = readTailText(
|
|
51013
|
+
const tail = readTailText(join30(record4.sessionDir, "output.log"), OUTPUT_TAIL_BYTES);
|
|
51372
51014
|
const buffer = new ScrollbackBuffer(this.scrollbackCapacity);
|
|
51373
51015
|
if (tail?.text)
|
|
51374
51016
|
buffer.append(dropLeadingFragment(tail));
|
|
@@ -51387,9 +51029,9 @@ class SessionManager {
|
|
|
51387
51029
|
}
|
|
51388
51030
|
diskDiagnostics(record4, limit) {
|
|
51389
51031
|
const { sessionDir, info } = record4;
|
|
51390
|
-
const eventLogPath =
|
|
51391
|
-
const upstreamErrorLogPath =
|
|
51392
|
-
const outputLogPath =
|
|
51032
|
+
const eventLogPath = join30(sessionDir, "events.jsonl");
|
|
51033
|
+
const upstreamErrorLogPath = join30(sessionDir, "upstream-errors.jsonl");
|
|
51034
|
+
const outputLogPath = join30(sessionDir, "output.log");
|
|
51393
51035
|
const events = readTailLines(eventLogPath, EVENT_TAIL_BYTES);
|
|
51394
51036
|
const outputTail = readTailText(outputLogPath, OUTPUT_TAIL_BYTES);
|
|
51395
51037
|
return {
|
|
@@ -51431,7 +51073,7 @@ class SessionManager {
|
|
|
51431
51073
|
};
|
|
51432
51074
|
}
|
|
51433
51075
|
diskStderrForDiagnostics(record4) {
|
|
51434
|
-
const tail = readTailText(
|
|
51076
|
+
const tail = readTailText(join30(record4.sessionDir, "stderr.log"), STDERR_READ_BYTES);
|
|
51435
51077
|
const raw = tail?.text ?? "";
|
|
51436
51078
|
const filtered = record4.info.status === "completed";
|
|
51437
51079
|
const source = filtered ? meaningfulStderr(raw) : raw;
|
|
@@ -51607,11 +51249,11 @@ ${STDERR_TRUNCATION_MARKER} ${STDERR_SIDE_LIMIT} bytes per end \u2026
|
|
|
51607
51249
|
entry.outputLogStream?.end();
|
|
51608
51250
|
entry.outputLogStream = null;
|
|
51609
51251
|
if (entry.stderr) {
|
|
51610
|
-
|
|
51252
|
+
writeFileSync12(join30(entry.sessionDir, "stderr.log"), redactSecrets(entry.stderr), "utf-8");
|
|
51611
51253
|
}
|
|
51612
51254
|
this.refreshAccounting(entry);
|
|
51613
51255
|
entry.info.claudeSessionId = entry.reducer.claudeSessionId ?? entry.info.claudeSessionId;
|
|
51614
|
-
|
|
51256
|
+
writeFileSync12(join30(entry.sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
|
|
51615
51257
|
}
|
|
51616
51258
|
scheduleEviction(entry) {
|
|
51617
51259
|
if (entry.evictHandle)
|
|
@@ -51671,7 +51313,7 @@ ${STDERR_TRUNCATION_MARKER} ${STDERR_SIDE_LIMIT} bytes per end \u2026
|
|
|
51671
51313
|
return { state: "completed", content: "" };
|
|
51672
51314
|
}
|
|
51673
51315
|
refreshAccounting(entry) {
|
|
51674
|
-
const stats = readTokenStatsAt(
|
|
51316
|
+
const stats = readTokenStatsAt(join30(entry.sessionDir, "tokens.json"));
|
|
51675
51317
|
const fileTokens = (stats?.total_tokens ?? 0) || (stats?.input_tokens ?? 0) + (stats?.output_tokens ?? 0);
|
|
51676
51318
|
entry.info.tokensUsed = fileTokens || entry.reducer.tokens;
|
|
51677
51319
|
entry.info.costUsd = stats?.total_cost ?? 0;
|
|
@@ -51862,6 +51504,321 @@ var init_progress_heartbeat = __esm(() => {
|
|
|
51862
51504
|
});
|
|
51863
51505
|
});
|
|
51864
51506
|
|
|
51507
|
+
// src/providers/cache-ttl.ts
|
|
51508
|
+
var FIREBASE_CACHE_TTL_HOURS = 24, FIREBASE_CACHE_TTL_MS;
|
|
51509
|
+
var init_cache_ttl = __esm(() => {
|
|
51510
|
+
FIREBASE_CACHE_TTL_MS = FIREBASE_CACHE_TTL_HOURS * 60 * 60 * 1000;
|
|
51511
|
+
});
|
|
51512
|
+
|
|
51513
|
+
// src/model-loader.ts
|
|
51514
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync13 } from "fs";
|
|
51515
|
+
import { homedir as homedir29 } from "os";
|
|
51516
|
+
import { join as join31 } from "path";
|
|
51517
|
+
function groupRecommendedModels(entries) {
|
|
51518
|
+
const byId = new Map;
|
|
51519
|
+
const categoryOrder = new Map;
|
|
51520
|
+
for (const entry of entries) {
|
|
51521
|
+
const list = byId.get(entry.id);
|
|
51522
|
+
if (list)
|
|
51523
|
+
list.push(entry);
|
|
51524
|
+
else
|
|
51525
|
+
byId.set(entry.id, [entry]);
|
|
51526
|
+
if (!categoryOrder.has(entry.category))
|
|
51527
|
+
categoryOrder.set(entry.category, categoryOrder.size);
|
|
51528
|
+
}
|
|
51529
|
+
const flagship = [];
|
|
51530
|
+
const fast = [];
|
|
51531
|
+
for (const [id, members] of byId.entries()) {
|
|
51532
|
+
const primary = members.find((m) => m.category !== "subscription") ?? members[0];
|
|
51533
|
+
const subscriptions = members.filter((m) => m.category === "subscription");
|
|
51534
|
+
const bucket = primary.category === "programming" || primary.category === "vision" || primary.category === "reasoning" ? "flagship" : "fast";
|
|
51535
|
+
const group = { id, primary, subscriptions, bucket };
|
|
51536
|
+
if (bucket === "flagship")
|
|
51537
|
+
flagship.push(group);
|
|
51538
|
+
else
|
|
51539
|
+
fast.push(group);
|
|
51540
|
+
}
|
|
51541
|
+
const byCuratedPriorityThenFreshness = (a, b) => {
|
|
51542
|
+
const aCat = categoryOrder.get(a.primary.category) ?? Number.MAX_SAFE_INTEGER;
|
|
51543
|
+
const bCat = categoryOrder.get(b.primary.category) ?? Number.MAX_SAFE_INTEGER;
|
|
51544
|
+
if (aCat !== bCat)
|
|
51545
|
+
return aCat - bCat;
|
|
51546
|
+
if (a.primary.priority !== b.primary.priority)
|
|
51547
|
+
return a.primary.priority - b.primary.priority;
|
|
51548
|
+
return compareByReleaseDateDesc(a.primary, b.primary);
|
|
51549
|
+
};
|
|
51550
|
+
flagship.sort(byCuratedPriorityThenFreshness);
|
|
51551
|
+
fast.sort(byCuratedPriorityThenFreshness);
|
|
51552
|
+
return { flagship, fast };
|
|
51553
|
+
}
|
|
51554
|
+
function collectRoutingPrefixes(group, getNativePrefix) {
|
|
51555
|
+
const slug = (group.primary.provider || "").toLowerCase();
|
|
51556
|
+
const native = getNativePrefix(slug);
|
|
51557
|
+
const seen = new Set;
|
|
51558
|
+
const out = [];
|
|
51559
|
+
if (native) {
|
|
51560
|
+
out.push(native);
|
|
51561
|
+
seen.add(native);
|
|
51562
|
+
}
|
|
51563
|
+
for (const subscriptionRow of group.subscriptions) {
|
|
51564
|
+
const routes = subscriptionRow.subscriptions && subscriptionRow.subscriptions.length > 0 ? subscriptionRow.subscriptions : subscriptionRow.subscription ? [subscriptionRow.subscription] : [];
|
|
51565
|
+
const orderedRoutes = [...routes].sort(compareRecommendedRoutes);
|
|
51566
|
+
for (const route2 of orderedRoutes) {
|
|
51567
|
+
const p = route2?.prefix;
|
|
51568
|
+
if (!p || seen.has(p))
|
|
51569
|
+
continue;
|
|
51570
|
+
seen.add(p);
|
|
51571
|
+
out.push(p);
|
|
51572
|
+
}
|
|
51573
|
+
}
|
|
51574
|
+
return out;
|
|
51575
|
+
}
|
|
51576
|
+
function compareRecommendedRoutes(left, right) {
|
|
51577
|
+
const leftRank = left?.tier && Object.hasOwn(RECOMMENDED_ROUTE_TIER_ORDER, left.tier) ? RECOMMENDED_ROUTE_TIER_ORDER[left.tier] : Number.MAX_SAFE_INTEGER;
|
|
51578
|
+
const rightRank = right?.tier && Object.hasOwn(RECOMMENDED_ROUTE_TIER_ORDER, right.tier) ? RECOMMENDED_ROUTE_TIER_ORDER[right.tier] : Number.MAX_SAFE_INTEGER;
|
|
51579
|
+
return leftRank - rightRank;
|
|
51580
|
+
}
|
|
51581
|
+
function parsePriceAvg(s) {
|
|
51582
|
+
if (!s || s === "N/A")
|
|
51583
|
+
return Number.POSITIVE_INFINITY;
|
|
51584
|
+
if (s === "FREE")
|
|
51585
|
+
return 0;
|
|
51586
|
+
const m = s.match(/\$([\d.]+)/);
|
|
51587
|
+
return m ? Number.parseFloat(m[1]) : Number.POSITIVE_INFINITY;
|
|
51588
|
+
}
|
|
51589
|
+
function parseCtx(s) {
|
|
51590
|
+
if (!s || s === "N/A")
|
|
51591
|
+
return 0;
|
|
51592
|
+
const upper = s.toUpperCase();
|
|
51593
|
+
if (upper.includes("M"))
|
|
51594
|
+
return Number.parseFloat(upper) * 1e6;
|
|
51595
|
+
if (upper.includes("K"))
|
|
51596
|
+
return Number.parseFloat(upper) * 1000;
|
|
51597
|
+
return Number.parseInt(s, 10) || 0;
|
|
51598
|
+
}
|
|
51599
|
+
function normalizePricingDisplay(raw) {
|
|
51600
|
+
const pricing = raw || "N/A";
|
|
51601
|
+
if (pricing.includes("-1000000"))
|
|
51602
|
+
return "varies";
|
|
51603
|
+
if (pricing === "$0.00/1M" || pricing === "FREE")
|
|
51604
|
+
return "FREE";
|
|
51605
|
+
return pricing;
|
|
51606
|
+
}
|
|
51607
|
+
function formatListingPrice(entry, opts) {
|
|
51608
|
+
const rate = normalizePricingDisplay(entry.pricing?.average);
|
|
51609
|
+
if (rate !== "N/A")
|
|
51610
|
+
return rate;
|
|
51611
|
+
const plan = entry.subscription?.plan;
|
|
51612
|
+
if (!plan)
|
|
51613
|
+
return "N/A";
|
|
51614
|
+
return opts?.compact ? "SUB" : `SUB (${plan})`;
|
|
51615
|
+
}
|
|
51616
|
+
function computeQuickPicks(primaries) {
|
|
51617
|
+
if (primaries.length === 0) {
|
|
51618
|
+
return {
|
|
51619
|
+
budget: null,
|
|
51620
|
+
largeContext: null,
|
|
51621
|
+
mostCapable: null,
|
|
51622
|
+
visionCoding: null,
|
|
51623
|
+
agentic: null
|
|
51624
|
+
};
|
|
51625
|
+
}
|
|
51626
|
+
const priced = primaries.filter((m) => {
|
|
51627
|
+
const p = parsePriceAvg(m.pricing?.average);
|
|
51628
|
+
return p > 0 && p !== Number.POSITIVE_INFINITY;
|
|
51629
|
+
}).sort((a, b) => parsePriceAvg(a.pricing?.average) - parsePriceAvg(b.pricing?.average));
|
|
51630
|
+
const budget = priced[0] ?? null;
|
|
51631
|
+
const byCtx = [...primaries].sort((a, b) => parseCtx(b.context) - parseCtx(a.context));
|
|
51632
|
+
const largeContext = byCtx[0] ?? null;
|
|
51633
|
+
const byPrice = [...primaries].sort((a, b) => parsePriceAvg(b.pricing?.average) - parsePriceAvg(a.pricing?.average));
|
|
51634
|
+
const mostCapable = byPrice.find((m) => parsePriceAvg(m.pricing?.average) !== Number.POSITIVE_INFINITY) ?? null;
|
|
51635
|
+
const visionCoding = primaries.find((m) => m.supportsVision === true && m.id !== budget?.id && m.id !== mostCapable?.id) ?? null;
|
|
51636
|
+
const agentic = primaries.find((m) => m.supportsReasoning === true && m.id !== mostCapable?.id) ?? null;
|
|
51637
|
+
return { budget, largeContext, mostCapable, visionCoding, agentic };
|
|
51638
|
+
}
|
|
51639
|
+
async function getRecommendedModels(opts = {}) {
|
|
51640
|
+
const { forceRefresh = false } = opts;
|
|
51641
|
+
if (!forceRefresh && _cachedRecommendedModels) {
|
|
51642
|
+
return _cachedRecommendedModels;
|
|
51643
|
+
}
|
|
51644
|
+
if (!forceRefresh && existsSync21(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
51645
|
+
try {
|
|
51646
|
+
const cacheData = JSON.parse(readFileSync21(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
51647
|
+
if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
|
|
51648
|
+
_cachedRecommendedModels = cacheData;
|
|
51649
|
+
return cacheData;
|
|
51650
|
+
}
|
|
51651
|
+
} catch {}
|
|
51652
|
+
}
|
|
51653
|
+
try {
|
|
51654
|
+
const response = await fetch(FIREBASE_RECOMMENDED_URL, {
|
|
51655
|
+
signal: AbortSignal.timeout(RECOMMENDED_FETCH_TIMEOUT_MS)
|
|
51656
|
+
});
|
|
51657
|
+
if (response.ok) {
|
|
51658
|
+
const data = await response.json();
|
|
51659
|
+
if (data.models && data.models.length > 0) {
|
|
51660
|
+
_cachedRecommendedModels = data;
|
|
51661
|
+
try {
|
|
51662
|
+
const cacheDir = join31(homedir29(), ".claudish");
|
|
51663
|
+
mkdirSync13(cacheDir, { recursive: true });
|
|
51664
|
+
writeFileSync13(RECOMMENDED_MODELS_CACHE_PATH, JSON.stringify(data), "utf-8");
|
|
51665
|
+
} catch {}
|
|
51666
|
+
return data;
|
|
51667
|
+
}
|
|
51668
|
+
}
|
|
51669
|
+
} catch {}
|
|
51670
|
+
throw new Error("Unable to load recommended models: Firebase unreachable and no local cache. " + "Check connectivity.");
|
|
51671
|
+
}
|
|
51672
|
+
function getRecommendedModelsSync() {
|
|
51673
|
+
if (_cachedRecommendedModels)
|
|
51674
|
+
return _cachedRecommendedModels;
|
|
51675
|
+
if (existsSync21(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
51676
|
+
try {
|
|
51677
|
+
const cacheData = JSON.parse(readFileSync21(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
51678
|
+
if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
|
|
51679
|
+
_cachedRecommendedModels = cacheData;
|
|
51680
|
+
return cacheData;
|
|
51681
|
+
}
|
|
51682
|
+
} catch {}
|
|
51683
|
+
}
|
|
51684
|
+
return { version: "0", lastUpdated: "", models: [] };
|
|
51685
|
+
}
|
|
51686
|
+
async function warmRecommendedModels() {
|
|
51687
|
+
try {
|
|
51688
|
+
return await getRecommendedModels({ forceRefresh: true });
|
|
51689
|
+
} catch {
|
|
51690
|
+
return null;
|
|
51691
|
+
}
|
|
51692
|
+
}
|
|
51693
|
+
function isFreshEnough(doc2) {
|
|
51694
|
+
const generatedAt = doc2.generatedAt;
|
|
51695
|
+
if (!generatedAt)
|
|
51696
|
+
return true;
|
|
51697
|
+
const ageHours = (Date.now() - new Date(generatedAt).getTime()) / (1000 * 60 * 60);
|
|
51698
|
+
return ageHours <= FIREBASE_CACHE_TTL_HOURS;
|
|
51699
|
+
}
|
|
51700
|
+
async function searchModels(query, limit = 50) {
|
|
51701
|
+
const url2 = `${FIREBASE_BASE_URL}?search=${encodeURIComponent(query)}&limit=${limit}&status=active`;
|
|
51702
|
+
const response = await fetch(url2, {
|
|
51703
|
+
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
51704
|
+
});
|
|
51705
|
+
if (!response.ok) {
|
|
51706
|
+
throw new Error(`Firebase search returned ${response.status} ${response.statusText}`);
|
|
51707
|
+
}
|
|
51708
|
+
const data = await response.json();
|
|
51709
|
+
return data.models ?? [];
|
|
51710
|
+
}
|
|
51711
|
+
async function getModelByIdFromFirebase(modelId) {
|
|
51712
|
+
const url2 = `${FIREBASE_BASE_URL}?search=${encodeURIComponent(modelId)}&limit=5`;
|
|
51713
|
+
const response = await fetch(url2, {
|
|
51714
|
+
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
51715
|
+
});
|
|
51716
|
+
if (!response.ok) {
|
|
51717
|
+
throw new Error(`Firebase lookup returned ${response.status} ${response.statusText}`);
|
|
51718
|
+
}
|
|
51719
|
+
const data = await response.json();
|
|
51720
|
+
const models = data.models ?? [];
|
|
51721
|
+
for (const m of models) {
|
|
51722
|
+
if (m.modelId === modelId)
|
|
51723
|
+
return m;
|
|
51724
|
+
if (m.aliases?.includes(modelId))
|
|
51725
|
+
return m;
|
|
51726
|
+
}
|
|
51727
|
+
return null;
|
|
51728
|
+
}
|
|
51729
|
+
async function getTop100Models() {
|
|
51730
|
+
const url2 = `${FIREBASE_BASE_URL}?catalog=top100`;
|
|
51731
|
+
const response = await fetch(url2, {
|
|
51732
|
+
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
51733
|
+
});
|
|
51734
|
+
if (!response.ok) {
|
|
51735
|
+
throw new Error(`Firebase top100 fetch failed: ${response.status} ${response.statusText}`);
|
|
51736
|
+
}
|
|
51737
|
+
const data = await response.json();
|
|
51738
|
+
return data;
|
|
51739
|
+
}
|
|
51740
|
+
async function getProviderList() {
|
|
51741
|
+
const url2 = `${FIREBASE_BASE_URL}?catalog=providers`;
|
|
51742
|
+
const response = await fetch(url2, {
|
|
51743
|
+
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
51744
|
+
});
|
|
51745
|
+
if (!response.ok) {
|
|
51746
|
+
throw new Error(`Firebase providers fetch failed: ${response.status} ${response.statusText}`);
|
|
51747
|
+
}
|
|
51748
|
+
const data = await response.json();
|
|
51749
|
+
return data.providers ?? [];
|
|
51750
|
+
}
|
|
51751
|
+
async function getModelsByProvider(provider, limit = 200) {
|
|
51752
|
+
const url2 = `${FIREBASE_BASE_URL}?provider=${encodeURIComponent(provider)}&status=active&limit=${limit}`;
|
|
51753
|
+
const response = await fetch(url2, {
|
|
51754
|
+
signal: AbortSignal.timeout(SEARCH_FETCH_TIMEOUT_MS)
|
|
51755
|
+
});
|
|
51756
|
+
if (!response.ok) {
|
|
51757
|
+
throw new Error(`Firebase provider query returned ${response.status} ${response.statusText}`);
|
|
51758
|
+
}
|
|
51759
|
+
const data = await response.json();
|
|
51760
|
+
if (Array.isArray(data))
|
|
51761
|
+
return data;
|
|
51762
|
+
return data.models ?? [];
|
|
51763
|
+
}
|
|
51764
|
+
function loadModelInfo() {
|
|
51765
|
+
if (_cachedModelInfo) {
|
|
51766
|
+
return _cachedModelInfo;
|
|
51767
|
+
}
|
|
51768
|
+
const data = getRecommendedModelsSync();
|
|
51769
|
+
const modelInfo = {};
|
|
51770
|
+
for (const model of data.models) {
|
|
51771
|
+
modelInfo[model.id] = {
|
|
51772
|
+
name: model.name,
|
|
51773
|
+
description: model.description,
|
|
51774
|
+
priority: model.priority,
|
|
51775
|
+
provider: model.provider
|
|
51776
|
+
};
|
|
51777
|
+
}
|
|
51778
|
+
modelInfo.custom = {
|
|
51779
|
+
name: "Custom Model",
|
|
51780
|
+
description: "Enter any model ID manually",
|
|
51781
|
+
priority: 999,
|
|
51782
|
+
provider: "Custom"
|
|
51783
|
+
};
|
|
51784
|
+
_cachedModelInfo = modelInfo;
|
|
51785
|
+
return modelInfo;
|
|
51786
|
+
}
|
|
51787
|
+
function getAvailableModels() {
|
|
51788
|
+
if (_cachedModelIds) {
|
|
51789
|
+
return _cachedModelIds;
|
|
51790
|
+
}
|
|
51791
|
+
const data = getRecommendedModelsSync();
|
|
51792
|
+
const modelIds = data.models.sort((a, b) => a.priority - b.priority).map((m) => m.id);
|
|
51793
|
+
const result = [...modelIds, "custom"];
|
|
51794
|
+
_cachedModelIds = result;
|
|
51795
|
+
return result;
|
|
51796
|
+
}
|
|
51797
|
+
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;
|
|
51798
|
+
var init_model_loader = __esm(() => {
|
|
51799
|
+
init_cache_ttl();
|
|
51800
|
+
FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
|
|
51801
|
+
RECOMMENDED_MODELS_CACHE_PATH = join31(homedir29(), ".claudish", "recommended-models-cache.json");
|
|
51802
|
+
FIREBASE_SLUG_TO_PROVIDER_NAME = {
|
|
51803
|
+
openai: "openai",
|
|
51804
|
+
google: "google",
|
|
51805
|
+
"x-ai": "x-ai",
|
|
51806
|
+
"z-ai": "z-ai",
|
|
51807
|
+
moonshotai: "kimi",
|
|
51808
|
+
minimax: "minimax",
|
|
51809
|
+
qwen: "qwen",
|
|
51810
|
+
deepseek: "deepseek",
|
|
51811
|
+
mistralai: "mistralai",
|
|
51812
|
+
sakana: "sakana"
|
|
51813
|
+
};
|
|
51814
|
+
RECOMMENDED_ROUTE_TIER_ORDER = {
|
|
51815
|
+
native: 0,
|
|
51816
|
+
general: 1,
|
|
51817
|
+
metered: 2,
|
|
51818
|
+
aggregator: 3
|
|
51819
|
+
};
|
|
51820
|
+
});
|
|
51821
|
+
|
|
51865
51822
|
// src/port-manager.ts
|
|
51866
51823
|
var exports_port_manager = {};
|
|
51867
51824
|
__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.3",
|
|
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.3",
|
|
64
|
+
"@claudish/magmux-darwin-x64": "9.0.3",
|
|
65
|
+
"@claudish/magmux-linux-arm64": "9.0.3",
|
|
66
|
+
"@claudish/magmux-linux-x64": "9.0.3"
|
|
67
67
|
},
|
|
68
68
|
"author": "Jack Rudenko <i@madappgang.com>",
|
|
69
69
|
"license": "MIT",
|