claudish 8.0.0 → 8.1.0
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 +343 -242
- 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 = "8.
|
|
734
|
+
var VERSION = "8.1.0";
|
|
735
735
|
|
|
736
736
|
// src/logger.ts
|
|
737
737
|
var exports_logger = {};
|
|
@@ -27458,6 +27458,271 @@ var init_stdio2 = __esm(() => {
|
|
|
27458
27458
|
init_stdio();
|
|
27459
27459
|
});
|
|
27460
27460
|
|
|
27461
|
+
// src/providers/all-models-cache.ts
|
|
27462
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
27463
|
+
import { homedir as homedir7 } from "os";
|
|
27464
|
+
import { dirname as dirname4, join as join7 } from "path";
|
|
27465
|
+
function readAllModelsCache(path = ALL_MODELS_CACHE_PATH) {
|
|
27466
|
+
if (!existsSync5(path))
|
|
27467
|
+
return null;
|
|
27468
|
+
let raw;
|
|
27469
|
+
try {
|
|
27470
|
+
raw = JSON.parse(readFileSync5(path, "utf-8"));
|
|
27471
|
+
} catch {
|
|
27472
|
+
return null;
|
|
27473
|
+
}
|
|
27474
|
+
if (!raw || typeof raw !== "object")
|
|
27475
|
+
return null;
|
|
27476
|
+
const data = raw;
|
|
27477
|
+
const lastUpdated = typeof data.lastUpdated === "string" ? data.lastUpdated : new Date(0).toISOString();
|
|
27478
|
+
const models = Array.isArray(data.models) ? data.models : [];
|
|
27479
|
+
const entries = Array.isArray(data.entries) ? data.entries : [];
|
|
27480
|
+
return {
|
|
27481
|
+
version: 2,
|
|
27482
|
+
lastUpdated,
|
|
27483
|
+
entries,
|
|
27484
|
+
models
|
|
27485
|
+
};
|
|
27486
|
+
}
|
|
27487
|
+
function writeAllModelsCache(data, path = ALL_MODELS_CACHE_PATH) {
|
|
27488
|
+
const existing = readAllModelsCache(path);
|
|
27489
|
+
const merged = {
|
|
27490
|
+
version: 2,
|
|
27491
|
+
lastUpdated: data.lastUpdated ?? new Date().toISOString(),
|
|
27492
|
+
entries: data.entries ?? existing?.entries ?? [],
|
|
27493
|
+
models: data.models ?? existing?.models ?? []
|
|
27494
|
+
};
|
|
27495
|
+
mkdirSync5(dirname4(path), { recursive: true });
|
|
27496
|
+
writeFileSync5(path, JSON.stringify(merged), "utf-8");
|
|
27497
|
+
}
|
|
27498
|
+
var ALL_MODELS_CACHE_PATH;
|
|
27499
|
+
var init_all_models_cache = __esm(() => {
|
|
27500
|
+
ALL_MODELS_CACHE_PATH = join7(homedir7(), ".claudish", "all-models.json");
|
|
27501
|
+
});
|
|
27502
|
+
|
|
27503
|
+
// src/providers/model-ordering.ts
|
|
27504
|
+
function extractVersionParts(modelId) {
|
|
27505
|
+
const tokens = modelId.toLowerCase().split(/[\/_-]+/);
|
|
27506
|
+
let started = false;
|
|
27507
|
+
const parts = [];
|
|
27508
|
+
for (const token of tokens) {
|
|
27509
|
+
const match = token.match(/\d+(?:\.\d+)*/);
|
|
27510
|
+
if (!match) {
|
|
27511
|
+
if (started)
|
|
27512
|
+
break;
|
|
27513
|
+
continue;
|
|
27514
|
+
}
|
|
27515
|
+
if (!started && /^\d+b$/.test(token) && Number.parseInt(match[0], 10) > 10) {
|
|
27516
|
+
continue;
|
|
27517
|
+
}
|
|
27518
|
+
if (!started) {
|
|
27519
|
+
started = true;
|
|
27520
|
+
for (const part of match[0].split(".")) {
|
|
27521
|
+
parts.push(Number.parseInt(part, 10));
|
|
27522
|
+
}
|
|
27523
|
+
if (!/^\d+(?:\.\d+)*$/.test(token)) {
|
|
27524
|
+
break;
|
|
27525
|
+
}
|
|
27526
|
+
continue;
|
|
27527
|
+
}
|
|
27528
|
+
if (!/^\d{1,2}(?:\.\d+)?$/.test(token)) {
|
|
27529
|
+
break;
|
|
27530
|
+
}
|
|
27531
|
+
for (const part of token.split(".")) {
|
|
27532
|
+
parts.push(Number.parseInt(part, 10));
|
|
27533
|
+
}
|
|
27534
|
+
}
|
|
27535
|
+
return parts;
|
|
27536
|
+
}
|
|
27537
|
+
function compareVersionPartsDesc(a, b) {
|
|
27538
|
+
const maxLength = Math.max(a.length, b.length);
|
|
27539
|
+
for (let i = 0;i < maxLength; i++) {
|
|
27540
|
+
const aPart = a[i] ?? -1;
|
|
27541
|
+
const bPart = b[i] ?? -1;
|
|
27542
|
+
if (aPart !== bPart) {
|
|
27543
|
+
return bPart - aPart;
|
|
27544
|
+
}
|
|
27545
|
+
}
|
|
27546
|
+
return 0;
|
|
27547
|
+
}
|
|
27548
|
+
function compareByReleaseDateDesc(a, b) {
|
|
27549
|
+
const aReleaseRaw = a.releaseDate ? Date.parse(a.releaseDate) : 0;
|
|
27550
|
+
const bReleaseRaw = b.releaseDate ? Date.parse(b.releaseDate) : 0;
|
|
27551
|
+
const aRelease = Number.isNaN(aReleaseRaw) ? 0 : aReleaseRaw;
|
|
27552
|
+
const bRelease = Number.isNaN(bReleaseRaw) ? 0 : bReleaseRaw;
|
|
27553
|
+
if (aRelease !== bRelease) {
|
|
27554
|
+
return bRelease - aRelease;
|
|
27555
|
+
}
|
|
27556
|
+
const aId = a.id ?? a.modelId ?? "";
|
|
27557
|
+
const bId = b.id ?? b.modelId ?? "";
|
|
27558
|
+
const versionCompare = compareVersionPartsDesc(extractVersionParts(aId), extractVersionParts(bId));
|
|
27559
|
+
if (versionCompare !== 0) {
|
|
27560
|
+
return versionCompare;
|
|
27561
|
+
}
|
|
27562
|
+
return aId.localeCompare(bId);
|
|
27563
|
+
}
|
|
27564
|
+
|
|
27565
|
+
// src/adapters/model-catalog.ts
|
|
27566
|
+
function lookupModel(modelId, cachePath) {
|
|
27567
|
+
const entry = findCacheEntry(modelId, cachePath);
|
|
27568
|
+
if (!entry || entry.contextWindow === undefined)
|
|
27569
|
+
return;
|
|
27570
|
+
return {
|
|
27571
|
+
modelId: entry.modelId,
|
|
27572
|
+
contextWindow: entry.contextWindow,
|
|
27573
|
+
supportsVision: entry.supportsVision,
|
|
27574
|
+
releaseDate: entry.releaseDate
|
|
27575
|
+
};
|
|
27576
|
+
}
|
|
27577
|
+
function lookupModelReasoning(modelId, cachePath) {
|
|
27578
|
+
return findCacheEntry(modelId, cachePath)?.reasoning;
|
|
27579
|
+
}
|
|
27580
|
+
function lookupModelTokenParam(modelId, cachePath) {
|
|
27581
|
+
return findCacheEntry(modelId, cachePath)?.tokenParam;
|
|
27582
|
+
}
|
|
27583
|
+
function lookupRouteReasoningMode(modelId, provider, cachePath) {
|
|
27584
|
+
return findCacheEntry(modelId, cachePath)?.aggregators?.find((aggregator) => aggregator.provider === provider)?.reasoning?.mode;
|
|
27585
|
+
}
|
|
27586
|
+
function lookupFamilyDefaultVariant(familyId, provider, cachePath) {
|
|
27587
|
+
const cache = readAllModelsCache(cachePath);
|
|
27588
|
+
if (!cache)
|
|
27589
|
+
return;
|
|
27590
|
+
for (const entry of cache.entries) {
|
|
27591
|
+
const rv = entry.routeVariant;
|
|
27592
|
+
if (!rv?.isDefault)
|
|
27593
|
+
continue;
|
|
27594
|
+
if (rv.provider !== provider)
|
|
27595
|
+
continue;
|
|
27596
|
+
if (rv.familyId === familyId || rv.baseModelId === familyId)
|
|
27597
|
+
return entry.modelId;
|
|
27598
|
+
}
|
|
27599
|
+
return;
|
|
27600
|
+
}
|
|
27601
|
+
function lookupVariantPresets(baseModelId, provider, cachePath) {
|
|
27602
|
+
const cache = readAllModelsCache(cachePath);
|
|
27603
|
+
if (!cache)
|
|
27604
|
+
return [];
|
|
27605
|
+
const wanted = stripVendorPrefix(baseModelId.toLowerCase());
|
|
27606
|
+
const found = [];
|
|
27607
|
+
for (const entry of cache.entries) {
|
|
27608
|
+
const rv = entry.routeVariant;
|
|
27609
|
+
if (!rv?.preset || !rv.baseModelId)
|
|
27610
|
+
continue;
|
|
27611
|
+
if (stripVendorPrefix(rv.baseModelId.toLowerCase()) !== wanted)
|
|
27612
|
+
continue;
|
|
27613
|
+
if (provider !== undefined && rv.provider !== provider)
|
|
27614
|
+
continue;
|
|
27615
|
+
found.push({ modelId: entry.modelId, preset: rv.preset, provider: rv.provider });
|
|
27616
|
+
}
|
|
27617
|
+
return found;
|
|
27618
|
+
}
|
|
27619
|
+
function lookupModelCapabilities(modelId, cachePath) {
|
|
27620
|
+
const entry = findCacheEntry(modelId, cachePath);
|
|
27621
|
+
if (!entry)
|
|
27622
|
+
return;
|
|
27623
|
+
return { supportsTools: entry.supportsTools, supportsThinking: entry.supportsThinking };
|
|
27624
|
+
}
|
|
27625
|
+
function lookupModelForProvider(modelId, provider, cachePath) {
|
|
27626
|
+
const entry = findCacheEntry(modelId, cachePath);
|
|
27627
|
+
if (!entry)
|
|
27628
|
+
return;
|
|
27629
|
+
return entry.aggregators?.find((a) => a.provider === provider)?.contextWindow ?? entry.contextWindow;
|
|
27630
|
+
}
|
|
27631
|
+
function resolveSubscriptionRouting(modelId, provider, cachePath) {
|
|
27632
|
+
const entry = findCacheEntry(modelId, cachePath);
|
|
27633
|
+
if (!entry)
|
|
27634
|
+
return { kind: "unknown" };
|
|
27635
|
+
if (entry.subscriptionPlans?.includes(provider)) {
|
|
27636
|
+
const agg = entry.aggregators?.find((a) => a.provider === provider);
|
|
27637
|
+
return agg?.externalId ? { kind: "serves", externalId: agg.externalId } : { kind: "unknown" };
|
|
27638
|
+
}
|
|
27639
|
+
return isSubscriptionPlan(provider, cachePath) ? { kind: "not-served" } : { kind: "unknown" };
|
|
27640
|
+
}
|
|
27641
|
+
function isSubscriptionPlan(provider, cachePath) {
|
|
27642
|
+
const cache = readAllModelsCache(cachePath);
|
|
27643
|
+
if (!cache)
|
|
27644
|
+
return false;
|
|
27645
|
+
return cache.entries.some((e) => e.subscriptionPlans?.includes(provider));
|
|
27646
|
+
}
|
|
27647
|
+
function stripVendorPrefix(lowerId) {
|
|
27648
|
+
return lowerId.includes("/") ? lowerId.substring(lowerId.lastIndexOf("/") + 1) : lowerId;
|
|
27649
|
+
}
|
|
27650
|
+
function findCacheEntry(modelId, cachePath) {
|
|
27651
|
+
if (modelId.includes("@")) {
|
|
27652
|
+
throw new Error(`model-catalog lookup received provider-routed ID "${modelId}" \u2014 callers must strip the "@" prefix before calling`);
|
|
27653
|
+
}
|
|
27654
|
+
const cache = readAllModelsCache(cachePath);
|
|
27655
|
+
if (!cache || cache.entries.length === 0)
|
|
27656
|
+
return;
|
|
27657
|
+
const lower = modelId.toLowerCase();
|
|
27658
|
+
const unprefixed = stripVendorPrefix(lower);
|
|
27659
|
+
for (const entry of cache.entries) {
|
|
27660
|
+
const entryId = entry.modelId.toLowerCase();
|
|
27661
|
+
const exactMatch = entryId === unprefixed || entryId === lower;
|
|
27662
|
+
const aliasMatch = entry.aliases?.some((a) => a.toLowerCase() === unprefixed || a.toLowerCase() === lower);
|
|
27663
|
+
if (exactMatch || aliasMatch) {
|
|
27664
|
+
return entry;
|
|
27665
|
+
}
|
|
27666
|
+
}
|
|
27667
|
+
return;
|
|
27668
|
+
}
|
|
27669
|
+
function classifyCatalogHit(entry, q) {
|
|
27670
|
+
const id = entry.modelId.toLowerCase();
|
|
27671
|
+
if (id === q || stripVendorPrefix(id) === q)
|
|
27672
|
+
return { bucket: "exact" };
|
|
27673
|
+
const aliases = entry.aliases ?? [];
|
|
27674
|
+
const exactAlias = aliases.find((a) => a.toLowerCase() === q || stripVendorPrefix(a.toLowerCase()) === q);
|
|
27675
|
+
if (exactAlias)
|
|
27676
|
+
return { bucket: "exact", matchedAlias: exactAlias };
|
|
27677
|
+
if (id.includes(q))
|
|
27678
|
+
return { bucket: "id" };
|
|
27679
|
+
const partialAlias = aliases.find((a) => a.toLowerCase().includes(q));
|
|
27680
|
+
return partialAlias ? { bucket: "alias", matchedAlias: partialAlias } : undefined;
|
|
27681
|
+
}
|
|
27682
|
+
function searchCatalogModels(query, limit = 10, cachePath) {
|
|
27683
|
+
const q = query.trim().toLowerCase();
|
|
27684
|
+
if (!q)
|
|
27685
|
+
return [];
|
|
27686
|
+
const cache = readAllModelsCache(cachePath);
|
|
27687
|
+
if (!cache || cache.entries.length === 0)
|
|
27688
|
+
return [];
|
|
27689
|
+
const exact = [];
|
|
27690
|
+
const idPartial = [];
|
|
27691
|
+
const aliasPartial = [];
|
|
27692
|
+
for (const entry of cache.entries) {
|
|
27693
|
+
const hit = classifyCatalogHit(entry, q);
|
|
27694
|
+
if (!hit)
|
|
27695
|
+
continue;
|
|
27696
|
+
const ranked = {
|
|
27697
|
+
entry,
|
|
27698
|
+
match: {
|
|
27699
|
+
modelId: entry.modelId,
|
|
27700
|
+
aliases: entry.aliases ?? [],
|
|
27701
|
+
subscriptionPlans: entry.subscriptionPlans ?? [],
|
|
27702
|
+
...hit.matchedAlias ? { matchedAlias: hit.matchedAlias } : {}
|
|
27703
|
+
}
|
|
27704
|
+
};
|
|
27705
|
+
if (hit.bucket === "exact")
|
|
27706
|
+
exact.push(ranked);
|
|
27707
|
+
else if (hit.bucket === "id")
|
|
27708
|
+
idPartial.push(ranked);
|
|
27709
|
+
else
|
|
27710
|
+
aliasPartial.push(ranked);
|
|
27711
|
+
}
|
|
27712
|
+
const byRelevance = (a, b) => {
|
|
27713
|
+
const lengthDelta = a.entry.modelId.length - b.entry.modelId.length;
|
|
27714
|
+
if (lengthDelta !== 0)
|
|
27715
|
+
return lengthDelta;
|
|
27716
|
+
return compareByReleaseDateDesc(a.entry, b.entry);
|
|
27717
|
+
};
|
|
27718
|
+
idPartial.sort(byRelevance);
|
|
27719
|
+
aliasPartial.sort(byRelevance);
|
|
27720
|
+
return [...exact, ...idPartial, ...aliasPartial].slice(0, limit).map((r) => r.match);
|
|
27721
|
+
}
|
|
27722
|
+
var init_model_catalog = __esm(() => {
|
|
27723
|
+
init_all_models_cache();
|
|
27724
|
+
});
|
|
27725
|
+
|
|
27461
27726
|
// src/agent-availability.ts
|
|
27462
27727
|
import { spawn } from "child_process";
|
|
27463
27728
|
function parseAvailableAgents(output) {
|
|
@@ -27574,26 +27839,26 @@ __export(exports_profile_config, {
|
|
|
27574
27839
|
setKeychainEnabled: () => setKeychainEnabled,
|
|
27575
27840
|
setProfile: () => setProfile
|
|
27576
27841
|
});
|
|
27577
|
-
import { existsSync as
|
|
27578
|
-
import { homedir as
|
|
27579
|
-
import { dirname as
|
|
27842
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
27843
|
+
import { homedir as homedir8 } from "os";
|
|
27844
|
+
import { dirname as dirname5, join as join8, parse as parse6 } from "path";
|
|
27580
27845
|
function activeConfigFile() {
|
|
27581
27846
|
return activeGlobalConfigFile(CONFIG_FILE);
|
|
27582
27847
|
}
|
|
27583
27848
|
function ensureConfigDir() {
|
|
27584
|
-
if (!
|
|
27585
|
-
|
|
27849
|
+
if (!existsSync6(CONFIG_DIR)) {
|
|
27850
|
+
mkdirSync6(CONFIG_DIR, { recursive: true });
|
|
27586
27851
|
}
|
|
27587
27852
|
}
|
|
27588
27853
|
function loadConfig() {
|
|
27589
27854
|
const activeFile = activeConfigFile();
|
|
27590
27855
|
if (!getConfigFileOverride())
|
|
27591
27856
|
ensureConfigDir();
|
|
27592
|
-
if (!
|
|
27857
|
+
if (!existsSync6(activeFile)) {
|
|
27593
27858
|
return { ...DEFAULT_CONFIG };
|
|
27594
27859
|
}
|
|
27595
27860
|
try {
|
|
27596
|
-
const content =
|
|
27861
|
+
const content = readFileSync6(activeFile, "utf-8");
|
|
27597
27862
|
const config2 = JSON.parse(content);
|
|
27598
27863
|
const merged = {
|
|
27599
27864
|
version: config2.version || DEFAULT_CONFIG.version,
|
|
@@ -27663,39 +27928,39 @@ function loadConfig() {
|
|
|
27663
27928
|
function saveConfig(config2) {
|
|
27664
27929
|
if (!getConfigFileOverride())
|
|
27665
27930
|
ensureConfigDir();
|
|
27666
|
-
|
|
27931
|
+
writeFileSync6(activeConfigFile(), JSON.stringify(config2, null, 2), "utf-8");
|
|
27667
27932
|
}
|
|
27668
27933
|
function configExists() {
|
|
27669
|
-
return
|
|
27934
|
+
return existsSync6(CONFIG_FILE);
|
|
27670
27935
|
}
|
|
27671
27936
|
function getConfigPath() {
|
|
27672
27937
|
return CONFIG_FILE;
|
|
27673
27938
|
}
|
|
27674
27939
|
function getLocalConfigPath() {
|
|
27675
|
-
const home =
|
|
27940
|
+
const home = homedir8();
|
|
27676
27941
|
let dir = process.cwd();
|
|
27677
27942
|
const root = parse6(dir).root;
|
|
27678
27943
|
while (dir !== root && dir !== home) {
|
|
27679
|
-
const candidate =
|
|
27680
|
-
if (
|
|
27944
|
+
const candidate = join8(dir, LOCAL_CONFIG_FILENAME);
|
|
27945
|
+
if (existsSync6(candidate))
|
|
27681
27946
|
return candidate;
|
|
27682
|
-
if (
|
|
27947
|
+
if (existsSync6(join8(dir, ".git"))) {
|
|
27683
27948
|
return candidate;
|
|
27684
27949
|
}
|
|
27685
|
-
dir =
|
|
27950
|
+
dir = dirname5(dir);
|
|
27686
27951
|
}
|
|
27687
|
-
return
|
|
27952
|
+
return join8(process.cwd(), LOCAL_CONFIG_FILENAME);
|
|
27688
27953
|
}
|
|
27689
27954
|
function localConfigExists() {
|
|
27690
|
-
return
|
|
27955
|
+
return existsSync6(getLocalConfigPath());
|
|
27691
27956
|
}
|
|
27692
27957
|
function readProOnUltracode(paths = defaultScopedConfigPaths) {
|
|
27693
27958
|
for (const pathFn of [paths.project, paths.global]) {
|
|
27694
27959
|
try {
|
|
27695
27960
|
const path = pathFn();
|
|
27696
|
-
if (!
|
|
27961
|
+
if (!existsSync6(path))
|
|
27697
27962
|
continue;
|
|
27698
|
-
const parsed = JSON.parse(
|
|
27963
|
+
const parsed = JSON.parse(readFileSync6(path, "utf-8"));
|
|
27699
27964
|
if (typeof parsed?.proOnUltracode === "boolean")
|
|
27700
27965
|
return parsed.proOnUltracode;
|
|
27701
27966
|
} catch {}
|
|
@@ -27704,17 +27969,17 @@ function readProOnUltracode(paths = defaultScopedConfigPaths) {
|
|
|
27704
27969
|
}
|
|
27705
27970
|
function isProjectDirectory() {
|
|
27706
27971
|
const cwd = process.cwd();
|
|
27707
|
-
return [".git", "package.json", "Cargo.toml", "go.mod", "pyproject.toml", ".claudish.json"].some((f) =>
|
|
27972
|
+
return [".git", "package.json", "Cargo.toml", "go.mod", "pyproject.toml", ".claudish.json"].some((f) => existsSync6(join8(cwd, f)));
|
|
27708
27973
|
}
|
|
27709
27974
|
function loadLocalConfig() {
|
|
27710
27975
|
if (getConfigFileOverride())
|
|
27711
27976
|
return null;
|
|
27712
27977
|
const localPath = getLocalConfigPath();
|
|
27713
|
-
if (!
|
|
27978
|
+
if (!existsSync6(localPath)) {
|
|
27714
27979
|
return null;
|
|
27715
27980
|
}
|
|
27716
27981
|
try {
|
|
27717
|
-
const content =
|
|
27982
|
+
const content = readFileSync6(localPath, "utf-8");
|
|
27718
27983
|
const config2 = JSON.parse(content);
|
|
27719
27984
|
return {
|
|
27720
27985
|
...config2,
|
|
@@ -27732,7 +27997,7 @@ function saveLocalConfig(config2) {
|
|
|
27732
27997
|
if (toWrite.routing !== undefined && Object.keys(toWrite.routing).length === 0) {
|
|
27733
27998
|
delete toWrite.routing;
|
|
27734
27999
|
}
|
|
27735
|
-
|
|
28000
|
+
writeFileSync6(getLocalConfigPath(), JSON.stringify(toWrite, null, 2), "utf-8");
|
|
27736
28001
|
}
|
|
27737
28002
|
function loadConfigForScope(scope) {
|
|
27738
28003
|
if (scope === "local") {
|
|
@@ -27987,8 +28252,8 @@ function disableLocalProvider(providerName) {
|
|
|
27987
28252
|
}
|
|
27988
28253
|
var CONFIG_DIR, CONFIG_FILE, LOCAL_CONFIG_FILENAME = ".claudish.json", DEFAULT_CONFIG, defaultScopedConfigPaths;
|
|
27989
28254
|
var init_profile_config = __esm(() => {
|
|
27990
|
-
CONFIG_DIR =
|
|
27991
|
-
CONFIG_FILE =
|
|
28255
|
+
CONFIG_DIR = join8(homedir8(), ".claudish");
|
|
28256
|
+
CONFIG_FILE = join8(CONFIG_DIR, "config.json");
|
|
27992
28257
|
DEFAULT_CONFIG = {
|
|
27993
28258
|
version: "1.0.0",
|
|
27994
28259
|
defaultProfile: "default",
|
|
@@ -28095,153 +28360,6 @@ var init_remote_provider_types = __esm(() => {
|
|
|
28095
28360
|
};
|
|
28096
28361
|
});
|
|
28097
28362
|
|
|
28098
|
-
// src/providers/all-models-cache.ts
|
|
28099
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
28100
|
-
import { homedir as homedir8 } from "os";
|
|
28101
|
-
import { dirname as dirname5, join as join8 } from "path";
|
|
28102
|
-
function readAllModelsCache(path = ALL_MODELS_CACHE_PATH) {
|
|
28103
|
-
if (!existsSync6(path))
|
|
28104
|
-
return null;
|
|
28105
|
-
let raw;
|
|
28106
|
-
try {
|
|
28107
|
-
raw = JSON.parse(readFileSync6(path, "utf-8"));
|
|
28108
|
-
} catch {
|
|
28109
|
-
return null;
|
|
28110
|
-
}
|
|
28111
|
-
if (!raw || typeof raw !== "object")
|
|
28112
|
-
return null;
|
|
28113
|
-
const data = raw;
|
|
28114
|
-
const lastUpdated = typeof data.lastUpdated === "string" ? data.lastUpdated : new Date(0).toISOString();
|
|
28115
|
-
const models = Array.isArray(data.models) ? data.models : [];
|
|
28116
|
-
const entries = Array.isArray(data.entries) ? data.entries : [];
|
|
28117
|
-
return {
|
|
28118
|
-
version: 2,
|
|
28119
|
-
lastUpdated,
|
|
28120
|
-
entries,
|
|
28121
|
-
models
|
|
28122
|
-
};
|
|
28123
|
-
}
|
|
28124
|
-
function writeAllModelsCache(data, path = ALL_MODELS_CACHE_PATH) {
|
|
28125
|
-
const existing = readAllModelsCache(path);
|
|
28126
|
-
const merged = {
|
|
28127
|
-
version: 2,
|
|
28128
|
-
lastUpdated: data.lastUpdated ?? new Date().toISOString(),
|
|
28129
|
-
entries: data.entries ?? existing?.entries ?? [],
|
|
28130
|
-
models: data.models ?? existing?.models ?? []
|
|
28131
|
-
};
|
|
28132
|
-
mkdirSync6(dirname5(path), { recursive: true });
|
|
28133
|
-
writeFileSync6(path, JSON.stringify(merged), "utf-8");
|
|
28134
|
-
}
|
|
28135
|
-
var ALL_MODELS_CACHE_PATH;
|
|
28136
|
-
var init_all_models_cache = __esm(() => {
|
|
28137
|
-
ALL_MODELS_CACHE_PATH = join8(homedir8(), ".claudish", "all-models.json");
|
|
28138
|
-
});
|
|
28139
|
-
|
|
28140
|
-
// src/adapters/model-catalog.ts
|
|
28141
|
-
function lookupModel(modelId, cachePath) {
|
|
28142
|
-
const entry = findCacheEntry(modelId, cachePath);
|
|
28143
|
-
if (!entry || entry.contextWindow === undefined)
|
|
28144
|
-
return;
|
|
28145
|
-
return {
|
|
28146
|
-
modelId: entry.modelId,
|
|
28147
|
-
contextWindow: entry.contextWindow,
|
|
28148
|
-
supportsVision: entry.supportsVision,
|
|
28149
|
-
releaseDate: entry.releaseDate
|
|
28150
|
-
};
|
|
28151
|
-
}
|
|
28152
|
-
function lookupModelReasoning(modelId, cachePath) {
|
|
28153
|
-
return findCacheEntry(modelId, cachePath)?.reasoning;
|
|
28154
|
-
}
|
|
28155
|
-
function lookupModelTokenParam(modelId, cachePath) {
|
|
28156
|
-
return findCacheEntry(modelId, cachePath)?.tokenParam;
|
|
28157
|
-
}
|
|
28158
|
-
function lookupFamilyDefaultVariant(familyId, provider, cachePath) {
|
|
28159
|
-
const cache2 = readAllModelsCache(cachePath);
|
|
28160
|
-
if (!cache2)
|
|
28161
|
-
return;
|
|
28162
|
-
for (const entry of cache2.entries) {
|
|
28163
|
-
const rv = entry.routeVariant;
|
|
28164
|
-
if (!rv?.isDefault)
|
|
28165
|
-
continue;
|
|
28166
|
-
if (rv.provider !== provider)
|
|
28167
|
-
continue;
|
|
28168
|
-
if (rv.familyId === familyId || rv.baseModelId === familyId)
|
|
28169
|
-
return entry.modelId;
|
|
28170
|
-
}
|
|
28171
|
-
return;
|
|
28172
|
-
}
|
|
28173
|
-
function lookupVariantPresets(baseModelId, provider, cachePath) {
|
|
28174
|
-
const cache2 = readAllModelsCache(cachePath);
|
|
28175
|
-
if (!cache2)
|
|
28176
|
-
return [];
|
|
28177
|
-
const wanted = stripVendorPrefix(baseModelId.toLowerCase());
|
|
28178
|
-
const found = [];
|
|
28179
|
-
for (const entry of cache2.entries) {
|
|
28180
|
-
const rv = entry.routeVariant;
|
|
28181
|
-
if (!rv?.preset || !rv.baseModelId)
|
|
28182
|
-
continue;
|
|
28183
|
-
if (stripVendorPrefix(rv.baseModelId.toLowerCase()) !== wanted)
|
|
28184
|
-
continue;
|
|
28185
|
-
if (provider !== undefined && rv.provider !== provider)
|
|
28186
|
-
continue;
|
|
28187
|
-
found.push({ modelId: entry.modelId, preset: rv.preset, provider: rv.provider });
|
|
28188
|
-
}
|
|
28189
|
-
return found;
|
|
28190
|
-
}
|
|
28191
|
-
function lookupModelCapabilities(modelId, cachePath) {
|
|
28192
|
-
const entry = findCacheEntry(modelId, cachePath);
|
|
28193
|
-
if (!entry)
|
|
28194
|
-
return;
|
|
28195
|
-
return { supportsTools: entry.supportsTools, supportsThinking: entry.supportsThinking };
|
|
28196
|
-
}
|
|
28197
|
-
function lookupModelForProvider(modelId, provider, cachePath) {
|
|
28198
|
-
const entry = findCacheEntry(modelId, cachePath);
|
|
28199
|
-
if (!entry)
|
|
28200
|
-
return;
|
|
28201
|
-
return entry.aggregators?.find((a) => a.provider === provider)?.contextWindow ?? entry.contextWindow;
|
|
28202
|
-
}
|
|
28203
|
-
function resolveSubscriptionRouting(modelId, provider, cachePath) {
|
|
28204
|
-
const entry = findCacheEntry(modelId, cachePath);
|
|
28205
|
-
if (!entry)
|
|
28206
|
-
return { kind: "unknown" };
|
|
28207
|
-
if (entry.subscriptionPlans?.includes(provider)) {
|
|
28208
|
-
const agg = entry.aggregators?.find((a) => a.provider === provider);
|
|
28209
|
-
return agg?.externalId ? { kind: "serves", externalId: agg.externalId } : { kind: "unknown" };
|
|
28210
|
-
}
|
|
28211
|
-
return isSubscriptionPlan(provider, cachePath) ? { kind: "not-served" } : { kind: "unknown" };
|
|
28212
|
-
}
|
|
28213
|
-
function isSubscriptionPlan(provider, cachePath) {
|
|
28214
|
-
const cache2 = readAllModelsCache(cachePath);
|
|
28215
|
-
if (!cache2)
|
|
28216
|
-
return false;
|
|
28217
|
-
return cache2.entries.some((e) => e.subscriptionPlans?.includes(provider));
|
|
28218
|
-
}
|
|
28219
|
-
function stripVendorPrefix(lowerId) {
|
|
28220
|
-
return lowerId.includes("/") ? lowerId.substring(lowerId.lastIndexOf("/") + 1) : lowerId;
|
|
28221
|
-
}
|
|
28222
|
-
function findCacheEntry(modelId, cachePath) {
|
|
28223
|
-
if (modelId.includes("@")) {
|
|
28224
|
-
throw new Error(`model-catalog lookup received provider-routed ID "${modelId}" \u2014 callers must strip the "@" prefix before calling`);
|
|
28225
|
-
}
|
|
28226
|
-
const cache2 = readAllModelsCache(cachePath);
|
|
28227
|
-
if (!cache2 || cache2.entries.length === 0)
|
|
28228
|
-
return;
|
|
28229
|
-
const lower = modelId.toLowerCase();
|
|
28230
|
-
const unprefixed = stripVendorPrefix(lower);
|
|
28231
|
-
for (const entry of cache2.entries) {
|
|
28232
|
-
const entryId = entry.modelId.toLowerCase();
|
|
28233
|
-
const exactMatch = entryId === unprefixed || entryId === lower;
|
|
28234
|
-
const aliasMatch = entry.aliases?.some((a) => a.toLowerCase() === unprefixed || a.toLowerCase() === lower);
|
|
28235
|
-
if (exactMatch || aliasMatch) {
|
|
28236
|
-
return entry;
|
|
28237
|
-
}
|
|
28238
|
-
}
|
|
28239
|
-
return;
|
|
28240
|
-
}
|
|
28241
|
-
var init_model_catalog = __esm(() => {
|
|
28242
|
-
init_all_models_cache();
|
|
28243
|
-
});
|
|
28244
|
-
|
|
28245
28363
|
// src/adapters/tool-name-utils.ts
|
|
28246
28364
|
function hashToolName(name) {
|
|
28247
28365
|
let h1 = 3735928559;
|
|
@@ -39642,6 +39760,18 @@ var init_session_events = __esm(() => {
|
|
|
39642
39760
|
|
|
39643
39761
|
// src/session-events/pro-injection.ts
|
|
39644
39762
|
function resolveVariantPreset(bareModelName, provider, cachePath) {
|
|
39763
|
+
const routeMode = lookupRouteReasoningMode(bareModelName, provider, cachePath);
|
|
39764
|
+
if (routeMode) {
|
|
39765
|
+
if (routeMode.status !== "supported" || !routeMode.values.includes("pro")) {
|
|
39766
|
+
return;
|
|
39767
|
+
}
|
|
39768
|
+
return {
|
|
39769
|
+
params: { reasoning: { mode: "pro" } },
|
|
39770
|
+
provider,
|
|
39771
|
+
preset: "reasoning.mode=pro",
|
|
39772
|
+
sourceLabel: `route capability @ ${provider}`
|
|
39773
|
+
};
|
|
39774
|
+
}
|
|
39645
39775
|
for (const variant of lookupVariantPresets(bareModelName, provider, cachePath)) {
|
|
39646
39776
|
try {
|
|
39647
39777
|
const params = parseModelParams(variant.preset);
|
|
@@ -39649,9 +39779,9 @@ function resolveVariantPreset(bareModelName, provider, cachePath) {
|
|
|
39649
39779
|
continue;
|
|
39650
39780
|
return {
|
|
39651
39781
|
params,
|
|
39652
|
-
variantModelId: variant.modelId,
|
|
39653
39782
|
provider: variant.provider,
|
|
39654
|
-
preset: variant.preset
|
|
39783
|
+
preset: variant.preset,
|
|
39784
|
+
sourceLabel: `variant ${variant.modelId} @ ${variant.provider}`
|
|
39655
39785
|
};
|
|
39656
39786
|
} catch {}
|
|
39657
39787
|
}
|
|
@@ -39675,7 +39805,7 @@ function applyProInjection(requestPayload, opts) {
|
|
|
39675
39805
|
if (!resolved)
|
|
39676
39806
|
return false;
|
|
39677
39807
|
deepMergeParams(requestPayload, resolved.params);
|
|
39678
|
-
log(`[SessionEvents] ultracode active \u2192 preset ${resolved.preset} for ${opts.targetModel} ` + `(catalog
|
|
39808
|
+
log(`[SessionEvents] ultracode active \u2192 preset ${resolved.preset} for ${opts.targetModel} ` + `(catalog ${resolved.sourceLabel}, session ${opts.sessionId})`);
|
|
39679
39809
|
return true;
|
|
39680
39810
|
} catch {
|
|
39681
39811
|
return false;
|
|
@@ -51266,68 +51396,6 @@ var init_cache_ttl = __esm(() => {
|
|
|
51266
51396
|
FIREBASE_CACHE_TTL_MS = FIREBASE_CACHE_TTL_HOURS * 60 * 60 * 1000;
|
|
51267
51397
|
});
|
|
51268
51398
|
|
|
51269
|
-
// src/providers/model-ordering.ts
|
|
51270
|
-
function extractVersionParts(modelId) {
|
|
51271
|
-
const tokens = modelId.toLowerCase().split(/[\/_-]+/);
|
|
51272
|
-
let started = false;
|
|
51273
|
-
const parts = [];
|
|
51274
|
-
for (const token of tokens) {
|
|
51275
|
-
const match = token.match(/\d+(?:\.\d+)*/);
|
|
51276
|
-
if (!match) {
|
|
51277
|
-
if (started)
|
|
51278
|
-
break;
|
|
51279
|
-
continue;
|
|
51280
|
-
}
|
|
51281
|
-
if (!started && /^\d+b$/.test(token) && Number.parseInt(match[0], 10) > 10) {
|
|
51282
|
-
continue;
|
|
51283
|
-
}
|
|
51284
|
-
if (!started) {
|
|
51285
|
-
started = true;
|
|
51286
|
-
for (const part of match[0].split(".")) {
|
|
51287
|
-
parts.push(Number.parseInt(part, 10));
|
|
51288
|
-
}
|
|
51289
|
-
if (!/^\d+(?:\.\d+)*$/.test(token)) {
|
|
51290
|
-
break;
|
|
51291
|
-
}
|
|
51292
|
-
continue;
|
|
51293
|
-
}
|
|
51294
|
-
if (!/^\d{1,2}(?:\.\d+)?$/.test(token)) {
|
|
51295
|
-
break;
|
|
51296
|
-
}
|
|
51297
|
-
for (const part of token.split(".")) {
|
|
51298
|
-
parts.push(Number.parseInt(part, 10));
|
|
51299
|
-
}
|
|
51300
|
-
}
|
|
51301
|
-
return parts;
|
|
51302
|
-
}
|
|
51303
|
-
function compareVersionPartsDesc(a, b) {
|
|
51304
|
-
const maxLength = Math.max(a.length, b.length);
|
|
51305
|
-
for (let i = 0;i < maxLength; i++) {
|
|
51306
|
-
const aPart = a[i] ?? -1;
|
|
51307
|
-
const bPart = b[i] ?? -1;
|
|
51308
|
-
if (aPart !== bPart) {
|
|
51309
|
-
return bPart - aPart;
|
|
51310
|
-
}
|
|
51311
|
-
}
|
|
51312
|
-
return 0;
|
|
51313
|
-
}
|
|
51314
|
-
function compareByReleaseDateDesc(a, b) {
|
|
51315
|
-
const aReleaseRaw = a.releaseDate ? Date.parse(a.releaseDate) : 0;
|
|
51316
|
-
const bReleaseRaw = b.releaseDate ? Date.parse(b.releaseDate) : 0;
|
|
51317
|
-
const aRelease = Number.isNaN(aReleaseRaw) ? 0 : aReleaseRaw;
|
|
51318
|
-
const bRelease = Number.isNaN(bReleaseRaw) ? 0 : bReleaseRaw;
|
|
51319
|
-
if (aRelease !== bRelease) {
|
|
51320
|
-
return bRelease - aRelease;
|
|
51321
|
-
}
|
|
51322
|
-
const aId = a.id ?? a.modelId ?? "";
|
|
51323
|
-
const bId = b.id ?? b.modelId ?? "";
|
|
51324
|
-
const versionCompare = compareVersionPartsDesc(extractVersionParts(aId), extractVersionParts(bId));
|
|
51325
|
-
if (versionCompare !== 0) {
|
|
51326
|
-
return versionCompare;
|
|
51327
|
-
}
|
|
51328
|
-
return aId.localeCompare(bId);
|
|
51329
|
-
}
|
|
51330
|
-
|
|
51331
51399
|
// src/model-loader.ts
|
|
51332
51400
|
import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync13 } from "fs";
|
|
51333
51401
|
import { homedir as homedir29 } from "os";
|
|
@@ -56488,7 +56556,7 @@ Tokens: ${result.usage.input} input, ${result.usage.output} output`;
|
|
|
56488
56556
|
});
|
|
56489
56557
|
tools.push({
|
|
56490
56558
|
name: "search_models",
|
|
56491
|
-
description: "Search
|
|
56559
|
+
description: "Search OpenRouter's listing by name, provider, or capability, and cross-reference " + "claudish's own catalog. SCOPE: the listing covers OpenRouter only, so a name's " + "absence from it is NOT evidence the name is unroutable \u2014 subscription wire ids " + "(`k3`) and catalog aliases live outside that namespace and are reported separately " + "here. This tool cannot tell you which provider will serve a model or whether the " + "hop is subscription or metered; call `preflight` for that.",
|
|
56492
56560
|
inputSchema: {
|
|
56493
56561
|
type: "object",
|
|
56494
56562
|
properties: {
|
|
@@ -56523,13 +56591,40 @@ Tokens: ${result.usage.input} input, ${result.usage.output} output`;
|
|
|
56523
56591
|
return b.score - a.score;
|
|
56524
56592
|
return compareByReleaseDateDesc(orderingKey(a.model), orderingKey(b.model));
|
|
56525
56593
|
}).slice(0, maxResults);
|
|
56594
|
+
const catalogMatches = searchCatalogModels(query, Math.max(maxResults, 5));
|
|
56595
|
+
const renderCatalogSection = () => {
|
|
56596
|
+
if (catalogMatches.length === 0)
|
|
56597
|
+
return "";
|
|
56598
|
+
let s = `
|
|
56599
|
+
## Catalog names (what claudish routes)
|
|
56600
|
+
|
|
56601
|
+
`;
|
|
56602
|
+
s += `| Bare name | Matched alias | Subscription plan |
|
|
56603
|
+
`;
|
|
56604
|
+
s += `|-----------|---------------|-------------------|
|
|
56605
|
+
`;
|
|
56606
|
+
for (const m of catalogMatches) {
|
|
56607
|
+
const plans = m.subscriptionPlans.length > 0 ? m.subscriptionPlans.join(", ") : "-";
|
|
56608
|
+
s += `| ${m.modelId} | ${m.matchedAlias ?? "-"} | ${plans} |
|
|
56609
|
+
`;
|
|
56610
|
+
}
|
|
56611
|
+
s += `
|
|
56612
|
+
Pass the **bare name**. Routing puts a subscription ahead of the metered API and ` + "rewrites the model to that plan's wire id for you. An aggregator-qualified id " + "(`moonshotai/...`, `accounts/fireworks/...`) pins that aggregator and bills per token.\n";
|
|
56613
|
+
return s;
|
|
56614
|
+
};
|
|
56526
56615
|
if (results.length === 0) {
|
|
56527
|
-
|
|
56528
|
-
|
|
56529
|
-
|
|
56616
|
+
const catalog = renderCatalogSection();
|
|
56617
|
+
const text = catalog ? `No OpenRouter listing matches "${query}", but claudish's catalog knows these:
|
|
56618
|
+
${catalog}` : `No models found matching "${query}".
|
|
56619
|
+
|
|
56620
|
+
` + "This searched OpenRouter's listing only. Subscription wire ids and catalog " + "aliases are not in it, so this is not proof the name is unroutable. Call " + "`list_models` for the recommended set, or `preflight` to test a specific name " + "against real routing.";
|
|
56621
|
+
return { content: [{ type: "text", text }] };
|
|
56530
56622
|
}
|
|
56531
56623
|
let output = `# Search Results for "${query}"
|
|
56532
56624
|
|
|
56625
|
+
`;
|
|
56626
|
+
output += `## OpenRouter listing
|
|
56627
|
+
|
|
56533
56628
|
`;
|
|
56534
56629
|
output += `| Model | Provider | Pricing | Context |
|
|
56535
56630
|
`;
|
|
@@ -56545,8 +56640,13 @@ Tokens: ${result.usage.input} input, ${result.usage.output} output`;
|
|
|
56545
56640
|
output += `| ${model.id} | ${provider} | ${pricing} | ${context} |
|
|
56546
56641
|
`;
|
|
56547
56642
|
}
|
|
56643
|
+
output += renderCatalogSection();
|
|
56644
|
+
const suggested = catalogMatches[0]?.modelId ?? results[0].model.id;
|
|
56548
56645
|
output += `
|
|
56549
|
-
Use with: run_prompt(model="${
|
|
56646
|
+
Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
|
|
56647
|
+
output += `
|
|
56648
|
+
|
|
56649
|
+
To learn which provider would actually serve \`${suggested}\`, and whether that ` + "hop is covered by a subscription or billed per token, call " + `\`preflight({models: ["${suggested}"]})\`. This listing cannot answer that.`;
|
|
56550
56650
|
return { content: [{ type: "text", text: output }] };
|
|
56551
56651
|
}
|
|
56552
56652
|
});
|
|
@@ -57450,6 +57550,7 @@ var init_mcp_server = __esm(() => {
|
|
|
57450
57550
|
init_server2();
|
|
57451
57551
|
init_stdio2();
|
|
57452
57552
|
init_types();
|
|
57553
|
+
init_model_catalog();
|
|
57453
57554
|
init_agent_availability();
|
|
57454
57555
|
init_prehydrate();
|
|
57455
57556
|
init_diagnostics();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudish",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.1.0",
|
|
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": "8.
|
|
64
|
-
"@claudish/magmux-darwin-x64": "8.
|
|
65
|
-
"@claudish/magmux-linux-arm64": "8.
|
|
66
|
-
"@claudish/magmux-linux-x64": "8.
|
|
63
|
+
"@claudish/magmux-darwin-arm64": "8.1.0",
|
|
64
|
+
"@claudish/magmux-darwin-x64": "8.1.0",
|
|
65
|
+
"@claudish/magmux-linux-arm64": "8.1.0",
|
|
66
|
+
"@claudish/magmux-linux-x64": "8.1.0"
|
|
67
67
|
},
|
|
68
68
|
"author": "Jack Rudenko <i@madappgang.com>",
|
|
69
69
|
"license": "MIT",
|