claudish 8.0.0 → 9.0.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 +438 -272
- 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 = "
|
|
734
|
+
var VERSION = "9.0.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",
|
|
@@ -28040,17 +28305,24 @@ var init_runtime_providers = __esm(() => {
|
|
|
28040
28305
|
});
|
|
28041
28306
|
|
|
28042
28307
|
// src/handlers/shared/remote-provider-types.ts
|
|
28308
|
+
function registerSubscriptionCredentialProbe(fn) {
|
|
28309
|
+
const previous = _subscriptionCredentialProbe;
|
|
28310
|
+
_subscriptionCredentialProbe = fn;
|
|
28311
|
+
return previous;
|
|
28312
|
+
}
|
|
28043
28313
|
function isSubscriptionProvider(provider) {
|
|
28044
|
-
|
|
28314
|
+
const p = provider.toLowerCase();
|
|
28315
|
+
if (SUBSCRIPTION_PROVIDERS.has(p))
|
|
28316
|
+
return true;
|
|
28317
|
+
if (!CREDENTIAL_DECIDED_PROVIDERS.has(p))
|
|
28318
|
+
return false;
|
|
28319
|
+
return _subscriptionCredentialProbe?.(p) === true;
|
|
28045
28320
|
}
|
|
28046
28321
|
function registerDynamicPricingLookup(fn) {
|
|
28047
28322
|
_dynamicLookup = fn;
|
|
28048
28323
|
}
|
|
28049
28324
|
function getModelPricing(provider, modelName) {
|
|
28050
28325
|
const p = provider.toLowerCase();
|
|
28051
|
-
if (FREE_PROVIDERS.has(p)) {
|
|
28052
|
-
return { inputCostPer1M: 0, outputCostPer1M: 0, isFree: true };
|
|
28053
|
-
}
|
|
28054
28326
|
if (isSubscriptionProvider(p)) {
|
|
28055
28327
|
return { inputCostPer1M: 0, outputCostPer1M: 0, isSubscription: true };
|
|
28056
28328
|
}
|
|
@@ -28062,7 +28334,7 @@ function getModelPricing(provider, modelName) {
|
|
|
28062
28334
|
const canonical = PROVIDER_ALIAS[p] || p;
|
|
28063
28335
|
return PROVIDER_DEFAULTS[canonical] || { inputCostPer1M: 1, outputCostPer1M: 4, isEstimate: true };
|
|
28064
28336
|
}
|
|
28065
|
-
var PROVIDER_DEFAULTS,
|
|
28337
|
+
var PROVIDER_DEFAULTS, SUBSCRIPTION_PROVIDERS, CREDENTIAL_DECIDED_PROVIDERS, _subscriptionCredentialProbe = null, PROVIDER_ALIAS, _dynamicLookup = null;
|
|
28066
28338
|
var init_remote_provider_types = __esm(() => {
|
|
28067
28339
|
PROVIDER_DEFAULTS = {
|
|
28068
28340
|
gemini: { inputCostPer1M: 0.5, outputCostPer1M: 2, isEstimate: true },
|
|
@@ -28072,7 +28344,6 @@ var init_remote_provider_types = __esm(() => {
|
|
|
28072
28344
|
glm: { inputCostPer1M: 0.16, outputCostPer1M: 0.8, isEstimate: true },
|
|
28073
28345
|
ollamacloud: { inputCostPer1M: 1, outputCostPer1M: 4, isEstimate: true }
|
|
28074
28346
|
};
|
|
28075
|
-
FREE_PROVIDERS = new Set(["opencode-zen", "zen"]);
|
|
28076
28347
|
SUBSCRIPTION_PROVIDERS = new Set([
|
|
28077
28348
|
"minimax-coding",
|
|
28078
28349
|
"kimi-coding",
|
|
@@ -28081,8 +28352,10 @@ var init_remote_provider_types = __esm(() => {
|
|
|
28081
28352
|
"devin",
|
|
28082
28353
|
"antigravity",
|
|
28083
28354
|
"sakana-subscription",
|
|
28084
|
-
"grok-subscription"
|
|
28355
|
+
"grok-subscription",
|
|
28356
|
+
"opencode-zen-go"
|
|
28085
28357
|
]);
|
|
28358
|
+
CREDENTIAL_DECIDED_PROVIDERS = new Set(["openai-codex"]);
|
|
28086
28359
|
PROVIDER_ALIAS = {
|
|
28087
28360
|
google: "gemini",
|
|
28088
28361
|
oai: "openai",
|
|
@@ -28095,153 +28368,6 @@ var init_remote_provider_types = __esm(() => {
|
|
|
28095
28368
|
};
|
|
28096
28369
|
});
|
|
28097
28370
|
|
|
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
28371
|
// src/adapters/tool-name-utils.ts
|
|
28246
28372
|
function hashToolName(name) {
|
|
28247
28373
|
let h1 = 3735928559;
|
|
@@ -36430,7 +36556,7 @@ class ApiKeyCredentialProvider {
|
|
|
36430
36556
|
} else {
|
|
36431
36557
|
headers = { ...this.staticHeaders };
|
|
36432
36558
|
}
|
|
36433
|
-
return { headers };
|
|
36559
|
+
return { arm: "api-key", headers };
|
|
36434
36560
|
}
|
|
36435
36561
|
}
|
|
36436
36562
|
var init_api_key_credential = __esm(() => {
|
|
@@ -36809,6 +36935,34 @@ var init_codex_oauth = __esm(() => {
|
|
|
36809
36935
|
};
|
|
36810
36936
|
});
|
|
36811
36937
|
|
|
36938
|
+
// src/auth/credentials/billing-probe.ts
|
|
36939
|
+
function recordSignedArm(provider, arm) {
|
|
36940
|
+
signedArm.set(provider.toLowerCase(), arm);
|
|
36941
|
+
}
|
|
36942
|
+
function clearSignedArm(provider) {
|
|
36943
|
+
if (provider)
|
|
36944
|
+
signedArm.delete(provider.toLowerCase());
|
|
36945
|
+
else
|
|
36946
|
+
signedArm.clear();
|
|
36947
|
+
}
|
|
36948
|
+
function installBillingProbes() {
|
|
36949
|
+
return registerSubscriptionCredentialProbe((p) => {
|
|
36950
|
+
const recorded = signedArm.get(p);
|
|
36951
|
+
if (recorded)
|
|
36952
|
+
return recorded === "subscription";
|
|
36953
|
+
return PROBES[p]?.() === true;
|
|
36954
|
+
});
|
|
36955
|
+
}
|
|
36956
|
+
var signedArm, PROBES;
|
|
36957
|
+
var init_billing_probe = __esm(() => {
|
|
36958
|
+
init_remote_provider_types();
|
|
36959
|
+
init_codex_oauth();
|
|
36960
|
+
signedArm = new Map;
|
|
36961
|
+
PROBES = {
|
|
36962
|
+
"openai-codex": () => CodexOAuth.getInstance().hasCredentials()
|
|
36963
|
+
};
|
|
36964
|
+
});
|
|
36965
|
+
|
|
36812
36966
|
// src/auth/credentials/composite-credential.ts
|
|
36813
36967
|
class CompositeCredentialProvider {
|
|
36814
36968
|
catalogName;
|
|
@@ -36876,6 +37030,7 @@ class CodexOAuthHalf {
|
|
|
36876
37030
|
const token = await this.oauth.getAccessToken();
|
|
36877
37031
|
const accountId = this.oauth.getAccountId();
|
|
36878
37032
|
return {
|
|
37033
|
+
arm: "oauth",
|
|
36879
37034
|
headers: buildOAuthHeaders(token, accountId),
|
|
36880
37035
|
endpoint: CODEX_RESPONSES_ENDPOINT,
|
|
36881
37036
|
transformPayload: (p) => ({
|
|
@@ -37365,6 +37520,17 @@ var init_kimi_oauth = __esm(() => {
|
|
|
37365
37520
|
import { existsSync as existsSync15, readFileSync as readFileSync14 } from "fs";
|
|
37366
37521
|
import { homedir as homedir22 } from "os";
|
|
37367
37522
|
import { join as join22 } from "path";
|
|
37523
|
+
function credentialSatisfies(descriptor, data) {
|
|
37524
|
+
if (!data?.access_token)
|
|
37525
|
+
return false;
|
|
37526
|
+
if (data.refresh_token)
|
|
37527
|
+
return true;
|
|
37528
|
+
if (descriptor.expiresAtField && data[descriptor.expiresAtField]) {
|
|
37529
|
+
const buffer = descriptor.expiryBufferMs ?? 0;
|
|
37530
|
+
return data[descriptor.expiresAtField] > Date.now() + buffer;
|
|
37531
|
+
}
|
|
37532
|
+
return true;
|
|
37533
|
+
}
|
|
37368
37534
|
function hasValidOAuthCredentials(descriptor) {
|
|
37369
37535
|
const credPath = join22(homedir22(), ".claudish", descriptor.credentialFile);
|
|
37370
37536
|
if (!existsSync15(credPath))
|
|
@@ -37373,16 +37539,7 @@ function hasValidOAuthCredentials(descriptor) {
|
|
|
37373
37539
|
return true;
|
|
37374
37540
|
}
|
|
37375
37541
|
try {
|
|
37376
|
-
|
|
37377
|
-
if (!data.access_token)
|
|
37378
|
-
return false;
|
|
37379
|
-
if (data.refresh_token)
|
|
37380
|
-
return true;
|
|
37381
|
-
if (descriptor.expiresAtField && data[descriptor.expiresAtField]) {
|
|
37382
|
-
const buffer = descriptor.expiryBufferMs ?? 0;
|
|
37383
|
-
return data[descriptor.expiresAtField] > Date.now() + buffer;
|
|
37384
|
-
}
|
|
37385
|
-
return true;
|
|
37542
|
+
return credentialSatisfies(descriptor, JSON.parse(readFileSync14(credPath, "utf-8")));
|
|
37386
37543
|
} catch {
|
|
37387
37544
|
return false;
|
|
37388
37545
|
}
|
|
@@ -37433,6 +37590,7 @@ class KimiOAuthHalf {
|
|
|
37433
37590
|
async getRequestAuth(_ctx) {
|
|
37434
37591
|
const token = await this.oauth.getAccessToken();
|
|
37435
37592
|
return {
|
|
37593
|
+
arm: "oauth",
|
|
37436
37594
|
headers: {
|
|
37437
37595
|
"anthropic-version": "2023-06-01",
|
|
37438
37596
|
Authorization: `Bearer ${token}`,
|
|
@@ -37632,6 +37790,7 @@ class CredentialAuthority {
|
|
|
37632
37790
|
return p.getRequestAuth(ctx);
|
|
37633
37791
|
}
|
|
37634
37792
|
invalidate(name) {
|
|
37793
|
+
clearSignedArm(name);
|
|
37635
37794
|
if (name) {
|
|
37636
37795
|
this.registry.get(name)?.invalidate?.();
|
|
37637
37796
|
return;
|
|
@@ -37646,9 +37805,11 @@ class CredentialAuthority {
|
|
|
37646
37805
|
}
|
|
37647
37806
|
async login(name) {
|
|
37648
37807
|
await this.registry.get(name)?.login?.();
|
|
37808
|
+
clearSignedArm(name);
|
|
37649
37809
|
}
|
|
37650
37810
|
async logout(name) {
|
|
37651
37811
|
await this.registry.get(name)?.logout?.();
|
|
37812
|
+
clearSignedArm(name);
|
|
37652
37813
|
}
|
|
37653
37814
|
get(name) {
|
|
37654
37815
|
return this.registry.get(name);
|
|
@@ -37699,6 +37860,7 @@ var init_authority = __esm(() => {
|
|
|
37699
37860
|
init_provider_definitions();
|
|
37700
37861
|
init_antigravity_credential();
|
|
37701
37862
|
init_api_key_credential();
|
|
37863
|
+
init_billing_probe();
|
|
37702
37864
|
init_codex_credential();
|
|
37703
37865
|
init_devin_credential();
|
|
37704
37866
|
init_grok_credential();
|
|
@@ -37711,6 +37873,7 @@ var init_authority = __esm(() => {
|
|
|
37711
37873
|
google: ["gemini"]
|
|
37712
37874
|
};
|
|
37713
37875
|
credentials = CredentialAuthority.buildDefault();
|
|
37876
|
+
installBillingProbes();
|
|
37714
37877
|
});
|
|
37715
37878
|
|
|
37716
37879
|
// src/providers/devin/proto-codec.ts
|
|
@@ -39642,6 +39805,18 @@ var init_session_events = __esm(() => {
|
|
|
39642
39805
|
|
|
39643
39806
|
// src/session-events/pro-injection.ts
|
|
39644
39807
|
function resolveVariantPreset(bareModelName, provider, cachePath) {
|
|
39808
|
+
const routeMode = lookupRouteReasoningMode(bareModelName, provider, cachePath);
|
|
39809
|
+
if (routeMode) {
|
|
39810
|
+
if (routeMode.status !== "supported" || !routeMode.values.includes("pro")) {
|
|
39811
|
+
return;
|
|
39812
|
+
}
|
|
39813
|
+
return {
|
|
39814
|
+
params: { reasoning: { mode: "pro" } },
|
|
39815
|
+
provider,
|
|
39816
|
+
preset: "reasoning.mode=pro",
|
|
39817
|
+
sourceLabel: `route capability @ ${provider}`
|
|
39818
|
+
};
|
|
39819
|
+
}
|
|
39645
39820
|
for (const variant of lookupVariantPresets(bareModelName, provider, cachePath)) {
|
|
39646
39821
|
try {
|
|
39647
39822
|
const params = parseModelParams(variant.preset);
|
|
@@ -39649,9 +39824,9 @@ function resolveVariantPreset(bareModelName, provider, cachePath) {
|
|
|
39649
39824
|
continue;
|
|
39650
39825
|
return {
|
|
39651
39826
|
params,
|
|
39652
|
-
variantModelId: variant.modelId,
|
|
39653
39827
|
provider: variant.provider,
|
|
39654
|
-
preset: variant.preset
|
|
39828
|
+
preset: variant.preset,
|
|
39829
|
+
sourceLabel: `variant ${variant.modelId} @ ${variant.provider}`
|
|
39655
39830
|
};
|
|
39656
39831
|
} catch {}
|
|
39657
39832
|
}
|
|
@@ -39675,7 +39850,7 @@ function applyProInjection(requestPayload, opts) {
|
|
|
39675
39850
|
if (!resolved)
|
|
39676
39851
|
return false;
|
|
39677
39852
|
deepMergeParams(requestPayload, resolved.params);
|
|
39678
|
-
log(`[SessionEvents] ultracode active \u2192 preset ${resolved.preset} for ${opts.targetModel} ` + `(catalog
|
|
39853
|
+
log(`[SessionEvents] ultracode active \u2192 preset ${resolved.preset} for ${opts.targetModel} ` + `(catalog ${resolved.sourceLabel}, session ${opts.sessionId})`);
|
|
39679
39854
|
return true;
|
|
39680
39855
|
} catch {
|
|
39681
39856
|
return false;
|
|
@@ -44846,6 +45021,7 @@ var init_openai_codex = __esm(() => {
|
|
|
44846
45021
|
init_codex_api_format();
|
|
44847
45022
|
init_model_catalog();
|
|
44848
45023
|
init_authority();
|
|
45024
|
+
init_billing_probe();
|
|
44849
45025
|
init_harness();
|
|
44850
45026
|
init_openai();
|
|
44851
45027
|
FALLBACK_CONVERSATION_KEY = randomBytes6(16).toString("hex");
|
|
@@ -44859,6 +45035,8 @@ var init_openai_codex = __esm(() => {
|
|
|
44859
45035
|
} catch {
|
|
44860
45036
|
this.cachedAuth = null;
|
|
44861
45037
|
}
|
|
45038
|
+
const signedWithOAuth = this.cachedAuth?.arm === "oauth";
|
|
45039
|
+
recordSignedArm("openai-codex", signedWithOAuth ? "subscription" : "metered");
|
|
44862
45040
|
}
|
|
44863
45041
|
getEndpoint(_targetModel) {
|
|
44864
45042
|
return this.cachedAuth?.endpoint ?? super.getEndpoint();
|
|
@@ -45347,16 +45525,28 @@ function describeMissingCredential(providerName) {
|
|
|
45347
45525
|
const keyNames = info?.envVar ? [info.envVar, ...info.aliases ?? []].join(" or ") : undefined;
|
|
45348
45526
|
const signup = info?.url ? ` Get one at ${info.url}.` : "";
|
|
45349
45527
|
const def = getProviderByName(providerName);
|
|
45528
|
+
const sibling = describeSiblingKeys(def);
|
|
45350
45529
|
if (isLocalTransport(providerName)) {
|
|
45351
45530
|
const where = def ? ` Claudish will use ${getEffectiveBaseUrl(def)}.` : "";
|
|
45352
45531
|
const keyClause = keyNames ? ` (Only set ${keyNames} if your local server requires a bearer token.)` : "";
|
|
45353
|
-
return `Provider "${providerName}" is a LOCAL server and is not enabled. Enable it in \`claudish config\` (Providers tab), or add "localProviders": ["${providerName}"] to ~/.claudish/config.json.${where}${keyClause}`;
|
|
45532
|
+
return `Provider "${providerName}" is a LOCAL server and is not enabled. Enable it in \`claudish config\` (Providers tab), or add "localProviders": ["${providerName}"] to ~/.claudish/config.json.${where}${keyClause}${sibling}`;
|
|
45354
45533
|
}
|
|
45355
45534
|
if (def?.oauthFallback) {
|
|
45356
45535
|
const keyClause = keyNames ? ` Or set ${keyNames} (env, config, or 1Password import) to use a metered API key instead.${signup}` : "";
|
|
45357
|
-
return `No credential for provider "${providerName}". Sign in with \`claudish login ${providerName}\` to use your existing subscription.${keyClause}`;
|
|
45536
|
+
return `No credential for provider "${providerName}". Sign in with \`claudish login ${providerName}\` to use your existing subscription.${keyClause}${sibling}`;
|
|
45358
45537
|
}
|
|
45359
|
-
return keyNames ? `No API key for provider "${providerName}". Set ${keyNames} (env, config, or 1Password import).${signup}` : `No API key for provider "${providerName}"
|
|
45538
|
+
return keyNames ? `No API key for provider "${providerName}". Set ${keyNames} (env, config, or 1Password import).${signup}${sibling}` : `No API key for provider "${providerName}".${sibling}`;
|
|
45539
|
+
}
|
|
45540
|
+
function describeSiblingKeys(def) {
|
|
45541
|
+
const vars = def?.siblingKeyEnvVars ?? [];
|
|
45542
|
+
if (vars.length === 0)
|
|
45543
|
+
return "";
|
|
45544
|
+
const all = getAllProviders();
|
|
45545
|
+
const named = vars.map((v) => {
|
|
45546
|
+
const owner = all.find((p) => p.name !== def?.name && p.apiKeyEnvVar === v);
|
|
45547
|
+
return owner ? `${v} (${owner.name})` : v;
|
|
45548
|
+
});
|
|
45549
|
+
return ` Note: ${named.join(" or ")} is a DIFFERENT plan's key and is not accepted here.`;
|
|
45360
45550
|
}
|
|
45361
45551
|
function getDisplayName(providerName) {
|
|
45362
45552
|
const def = getProviderByName(providerName);
|
|
@@ -45822,7 +46012,7 @@ var init_provider_definitions = __esm(() => {
|
|
|
45822
46012
|
apiPath: "/v1/chat/completions",
|
|
45823
46013
|
modelDiscovery: { path: "/v1/models", format: "openai-models-list" },
|
|
45824
46014
|
apiKeyEnvVar: "OPENCODE_GO_API_KEY",
|
|
45825
|
-
|
|
46015
|
+
siblingKeyEnvVars: ["OPENCODE_API_KEY"],
|
|
45826
46016
|
apiKeyDescription: "OpenCode Zen Go (Lite Plan) API Key",
|
|
45827
46017
|
apiKeyUrl: "https://opencode.ai/",
|
|
45828
46018
|
shortcuts: ["zengo", "zgo"],
|
|
@@ -47438,7 +47628,8 @@ var init_routing_hints = __esm(() => {
|
|
|
47438
47628
|
openrouter: { apiKeyEnvVar: "OPENROUTER_API_KEY" },
|
|
47439
47629
|
"x-ai": { apiKeyEnvVar: "XAI_API_KEY" },
|
|
47440
47630
|
"z-ai": { apiKeyEnvVar: "ZAI_API_KEY" },
|
|
47441
|
-
"opencode-zen": { apiKeyEnvVar: "OPENCODE_API_KEY" }
|
|
47631
|
+
"opencode-zen": { apiKeyEnvVar: "OPENCODE_API_KEY" },
|
|
47632
|
+
"opencode-zen-go": { apiKeyEnvVar: "OPENCODE_GO_API_KEY" }
|
|
47442
47633
|
};
|
|
47443
47634
|
});
|
|
47444
47635
|
|
|
@@ -51266,68 +51457,6 @@ var init_cache_ttl = __esm(() => {
|
|
|
51266
51457
|
FIREBASE_CACHE_TTL_MS = FIREBASE_CACHE_TTL_HOURS * 60 * 60 * 1000;
|
|
51267
51458
|
});
|
|
51268
51459
|
|
|
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
51460
|
// src/model-loader.ts
|
|
51332
51461
|
import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync13 } from "fs";
|
|
51333
51462
|
import { homedir as homedir29 } from "os";
|
|
@@ -51378,12 +51507,15 @@ function collectRoutingPrefixes(group, getNativePrefix) {
|
|
|
51378
51507
|
out.push(native);
|
|
51379
51508
|
seen.add(native);
|
|
51380
51509
|
}
|
|
51381
|
-
for (const
|
|
51382
|
-
const
|
|
51383
|
-
|
|
51384
|
-
|
|
51385
|
-
|
|
51386
|
-
|
|
51510
|
+
for (const subscriptionRow of group.subscriptions) {
|
|
51511
|
+
const routes = subscriptionRow.subscriptions && subscriptionRow.subscriptions.length > 0 ? subscriptionRow.subscriptions : subscriptionRow.subscription ? [subscriptionRow.subscription] : [];
|
|
51512
|
+
for (const route2 of routes) {
|
|
51513
|
+
const p = route2?.prefix;
|
|
51514
|
+
if (!p || seen.has(p))
|
|
51515
|
+
continue;
|
|
51516
|
+
seen.add(p);
|
|
51517
|
+
out.push(p);
|
|
51518
|
+
}
|
|
51387
51519
|
}
|
|
51388
51520
|
return out;
|
|
51389
51521
|
}
|
|
@@ -56488,7 +56620,7 @@ Tokens: ${result.usage.input} input, ${result.usage.output} output`;
|
|
|
56488
56620
|
});
|
|
56489
56621
|
tools.push({
|
|
56490
56622
|
name: "search_models",
|
|
56491
|
-
description: "Search
|
|
56623
|
+
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
56624
|
inputSchema: {
|
|
56493
56625
|
type: "object",
|
|
56494
56626
|
properties: {
|
|
@@ -56523,13 +56655,40 @@ Tokens: ${result.usage.input} input, ${result.usage.output} output`;
|
|
|
56523
56655
|
return b.score - a.score;
|
|
56524
56656
|
return compareByReleaseDateDesc(orderingKey(a.model), orderingKey(b.model));
|
|
56525
56657
|
}).slice(0, maxResults);
|
|
56658
|
+
const catalogMatches = searchCatalogModels(query, Math.max(maxResults, 5));
|
|
56659
|
+
const renderCatalogSection = () => {
|
|
56660
|
+
if (catalogMatches.length === 0)
|
|
56661
|
+
return "";
|
|
56662
|
+
let s = `
|
|
56663
|
+
## Catalog names (what claudish routes)
|
|
56664
|
+
|
|
56665
|
+
`;
|
|
56666
|
+
s += `| Bare name | Matched alias | Subscription plan |
|
|
56667
|
+
`;
|
|
56668
|
+
s += `|-----------|---------------|-------------------|
|
|
56669
|
+
`;
|
|
56670
|
+
for (const m of catalogMatches) {
|
|
56671
|
+
const plans = m.subscriptionPlans.length > 0 ? m.subscriptionPlans.join(", ") : "-";
|
|
56672
|
+
s += `| ${m.modelId} | ${m.matchedAlias ?? "-"} | ${plans} |
|
|
56673
|
+
`;
|
|
56674
|
+
}
|
|
56675
|
+
s += `
|
|
56676
|
+
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";
|
|
56677
|
+
return s;
|
|
56678
|
+
};
|
|
56526
56679
|
if (results.length === 0) {
|
|
56527
|
-
|
|
56528
|
-
|
|
56529
|
-
|
|
56680
|
+
const catalog = renderCatalogSection();
|
|
56681
|
+
const text = catalog ? `No OpenRouter listing matches "${query}", but claudish's catalog knows these:
|
|
56682
|
+
${catalog}` : `No models found matching "${query}".
|
|
56683
|
+
|
|
56684
|
+
` + "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.";
|
|
56685
|
+
return { content: [{ type: "text", text }] };
|
|
56530
56686
|
}
|
|
56531
56687
|
let output = `# Search Results for "${query}"
|
|
56532
56688
|
|
|
56689
|
+
`;
|
|
56690
|
+
output += `## OpenRouter listing
|
|
56691
|
+
|
|
56533
56692
|
`;
|
|
56534
56693
|
output += `| Model | Provider | Pricing | Context |
|
|
56535
56694
|
`;
|
|
@@ -56545,8 +56704,13 @@ Tokens: ${result.usage.input} input, ${result.usage.output} output`;
|
|
|
56545
56704
|
output += `| ${model.id} | ${provider} | ${pricing} | ${context} |
|
|
56546
56705
|
`;
|
|
56547
56706
|
}
|
|
56707
|
+
output += renderCatalogSection();
|
|
56708
|
+
const suggested = catalogMatches[0]?.modelId ?? results[0].model.id;
|
|
56548
56709
|
output += `
|
|
56549
|
-
Use with: run_prompt(model="${
|
|
56710
|
+
Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
|
|
56711
|
+
output += `
|
|
56712
|
+
|
|
56713
|
+
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
56714
|
return { content: [{ type: "text", text: output }] };
|
|
56551
56715
|
}
|
|
56552
56716
|
});
|
|
@@ -57450,6 +57614,7 @@ var init_mcp_server = __esm(() => {
|
|
|
57450
57614
|
init_server2();
|
|
57451
57615
|
init_stdio2();
|
|
57452
57616
|
init_types();
|
|
57617
|
+
init_model_catalog();
|
|
57453
57618
|
init_agent_availability();
|
|
57454
57619
|
init_prehydrate();
|
|
57455
57620
|
init_diagnostics();
|
|
@@ -75349,7 +75514,7 @@ var init_api_key_map = __esm(() => {
|
|
|
75349
75514
|
"qwen-payg": { envVar: "DASHSCOPE_API_KEY", aliases: ["QWEN_API_KEY"] },
|
|
75350
75515
|
ollamacloud: { envVar: "OLLAMA_API_KEY" },
|
|
75351
75516
|
"opencode-zen": { envVar: "OPENCODE_API_KEY" },
|
|
75352
|
-
"opencode-zen-go": { envVar: "OPENCODE_GO_API_KEY"
|
|
75517
|
+
"opencode-zen-go": { envVar: "OPENCODE_GO_API_KEY" },
|
|
75353
75518
|
vertex: { envVar: "VERTEX_API_KEY", aliases: ["VERTEX_PROJECT"] },
|
|
75354
75519
|
poe: { envVar: "POE_API_KEY" }
|
|
75355
75520
|
};
|
|
@@ -76922,6 +77087,7 @@ ${h("ENVIRONMENT VARIABLES")}
|
|
|
76922
77087
|
${blue("SAKANA_SUBSCRIPTION_API_KEY")} Sakana Fugu Subscription ${dim4("(sc@; separate subscription key)")}
|
|
76923
77088
|
${blue("OLLAMA_API_KEY")} OllamaCloud ${dim4("(oc@, llama@)")}
|
|
76924
77089
|
${blue("OPENCODE_API_KEY")} OpenCode Zen ${dim4("(zen@)")}
|
|
77090
|
+
${blue("OPENCODE_GO_API_KEY")} OpenCode Zen Go plan ${dim4("(zgo@, zengo@; separate plan key)")}
|
|
76925
77091
|
${blue("POE_API_KEY")} Poe ${dim4("(poe@)")}
|
|
76926
77092
|
${blue("LITELLM_API_KEY")} LiteLLM ${dim4("(litellm@, ll@; needs LITELLM_BASE_URL)")}
|
|
76927
77093
|
${blue("VERTEX_API_KEY")} Vertex AI Express ${dim4("(v@)")}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudish",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.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": "
|
|
64
|
-
"@claudish/magmux-darwin-x64": "
|
|
65
|
-
"@claudish/magmux-linux-arm64": "
|
|
66
|
-
"@claudish/magmux-linux-x64": "
|
|
63
|
+
"@claudish/magmux-darwin-arm64": "9.0.0",
|
|
64
|
+
"@claudish/magmux-darwin-x64": "9.0.0",
|
|
65
|
+
"@claudish/magmux-linux-arm64": "9.0.0",
|
|
66
|
+
"@claudish/magmux-linux-x64": "9.0.0"
|
|
67
67
|
},
|
|
68
68
|
"author": "Jack Rudenko <i@madappgang.com>",
|
|
69
69
|
"license": "MIT",
|