cascade-ai 0.12.6 → 0.12.8
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/cli.cjs +72 -9
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +72 -9
- package/dist/cli.js.map +1 -1
- package/dist/desktop-core.cjs +299101 -0
- package/dist/index.cjs +68 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +68 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1084,8 +1084,15 @@ declare class CascadeRouter extends EventEmitter {
|
|
|
1084
1084
|
* Useful for listing configured/usable models per provider.
|
|
1085
1085
|
*/
|
|
1086
1086
|
getModelsForProvider(provider: ProviderType): ModelInfo[];
|
|
1087
|
+
/**
|
|
1088
|
+
* Every model available across the configured + reachable providers, after
|
|
1089
|
+
* discovery (Ollama tags, OpenAI-compatible/llama.cpp models, cloud catalog).
|
|
1090
|
+
* Used to populate the desktop model pickers with the user's real models.
|
|
1091
|
+
*/
|
|
1092
|
+
getAvailableModels(): ModelInfo[];
|
|
1087
1093
|
private detectAvailableProviders;
|
|
1088
1094
|
private discoverOllamaModels;
|
|
1095
|
+
private discoverOpenAICompatibleModels;
|
|
1089
1096
|
private ensureProvider;
|
|
1090
1097
|
private getProvider;
|
|
1091
1098
|
private createProvider;
|
package/dist/index.d.ts
CHANGED
|
@@ -1084,8 +1084,15 @@ declare class CascadeRouter extends EventEmitter {
|
|
|
1084
1084
|
* Useful for listing configured/usable models per provider.
|
|
1085
1085
|
*/
|
|
1086
1086
|
getModelsForProvider(provider: ProviderType): ModelInfo[];
|
|
1087
|
+
/**
|
|
1088
|
+
* Every model available across the configured + reachable providers, after
|
|
1089
|
+
* discovery (Ollama tags, OpenAI-compatible/llama.cpp models, cloud catalog).
|
|
1090
|
+
* Used to populate the desktop model pickers with the user's real models.
|
|
1091
|
+
*/
|
|
1092
|
+
getAvailableModels(): ModelInfo[];
|
|
1087
1093
|
private detectAvailableProviders;
|
|
1088
1094
|
private discoverOllamaModels;
|
|
1095
|
+
private discoverOpenAICompatibleModels;
|
|
1089
1096
|
private ensureProvider;
|
|
1090
1097
|
private getProvider;
|
|
1091
1098
|
private createProvider;
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ import cron from 'node-cron';
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
// src/constants.ts
|
|
38
|
-
var CASCADE_VERSION = "0.12.
|
|
38
|
+
var CASCADE_VERSION = "0.12.8";
|
|
39
39
|
var CASCADE_CONFIG_DIR = ".cascade";
|
|
40
40
|
var CASCADE_MD_FILE = "CASCADE.md";
|
|
41
41
|
var CASCADE_IGNORE_FILE = ".cascadeignore";
|
|
@@ -1474,6 +1474,7 @@ var ModelSelector = class {
|
|
|
1474
1474
|
if (lower.includes("claude")) providerStr = "anthropic";
|
|
1475
1475
|
else if (lower.startsWith("gpt") || lower.startsWith("o1") || lower.startsWith("o3")) providerStr = "openai";
|
|
1476
1476
|
else if (lower.includes("gemini")) providerStr = "gemini";
|
|
1477
|
+
else if ((lower.endsWith(".gguf") || actualId.includes("/") || actualId.includes("\\")) && this.availableProviders.has("openai-compatible")) providerStr = "openai-compatible";
|
|
1477
1478
|
else if (this.availableProviders.has("ollama")) providerStr = "ollama";
|
|
1478
1479
|
else if (this.availableProviders.has("openai-compatible")) providerStr = "openai-compatible";
|
|
1479
1480
|
else if (this.availableProviders.size === 1) providerStr = Array.from(this.availableProviders)[0];
|
|
@@ -2161,6 +2162,11 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
|
|
|
2161
2162
|
if (availableProviders.has("ollama")) {
|
|
2162
2163
|
await this.discoverOllamaModels(ollamaCfg);
|
|
2163
2164
|
}
|
|
2165
|
+
if (availableProviders.has("openai-compatible")) {
|
|
2166
|
+
await Promise.all(
|
|
2167
|
+
config.providers.filter((p) => p.type === "openai-compatible").map((cfg) => this.discoverOpenAICompatibleModels(cfg))
|
|
2168
|
+
);
|
|
2169
|
+
}
|
|
2164
2170
|
for (const tier of ["T1", "T2", "T3"]) {
|
|
2165
2171
|
const override = tier === "T1" ? config.models.t1 : tier === "T2" ? config.models.t2 : config.models.t3;
|
|
2166
2172
|
if (!override || override === "auto") continue;
|
|
@@ -2592,6 +2598,14 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
|
|
|
2592
2598
|
getModelsForProvider(provider) {
|
|
2593
2599
|
return this.selector.getAvailableModelsForProvider(provider);
|
|
2594
2600
|
}
|
|
2601
|
+
/**
|
|
2602
|
+
* Every model available across the configured + reachable providers, after
|
|
2603
|
+
* discovery (Ollama tags, OpenAI-compatible/llama.cpp models, cloud catalog).
|
|
2604
|
+
* Used to populate the desktop model pickers with the user's real models.
|
|
2605
|
+
*/
|
|
2606
|
+
getAvailableModels() {
|
|
2607
|
+
return this.selector?.getAllAvailableModels() ?? [];
|
|
2608
|
+
}
|
|
2595
2609
|
// ── Private ──────────────────────────────────
|
|
2596
2610
|
async detectAvailableProviders(configs) {
|
|
2597
2611
|
const available = /* @__PURE__ */ new Set();
|
|
@@ -2622,6 +2636,28 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
|
|
|
2622
2636
|
} catch {
|
|
2623
2637
|
}
|
|
2624
2638
|
}
|
|
2639
|
+
async discoverOpenAICompatibleModels(cfg) {
|
|
2640
|
+
try {
|
|
2641
|
+
const seed = {
|
|
2642
|
+
id: "openai-compatible",
|
|
2643
|
+
name: "openai-compatible",
|
|
2644
|
+
provider: "openai-compatible",
|
|
2645
|
+
contextWindow: 32e3,
|
|
2646
|
+
isVisionCapable: false,
|
|
2647
|
+
inputCostPer1kTokens: 0,
|
|
2648
|
+
outputCostPer1kTokens: 0,
|
|
2649
|
+
maxOutputTokens: 4e3,
|
|
2650
|
+
supportsStreaming: true,
|
|
2651
|
+
isLocal: false
|
|
2652
|
+
};
|
|
2653
|
+
const provider = new OpenAICompatibleProvider(cfg, seed);
|
|
2654
|
+
const models = await provider.listModels();
|
|
2655
|
+
for (const m of models) {
|
|
2656
|
+
this.selector.addDynamicModel(m);
|
|
2657
|
+
}
|
|
2658
|
+
} catch {
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2625
2661
|
ensureProvider(model, configs) {
|
|
2626
2662
|
const key = `${model.provider}:${model.id}`;
|
|
2627
2663
|
if (this.providers.has(key)) return;
|
|
@@ -2651,7 +2687,23 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
|
|
|
2651
2687
|
}
|
|
2652
2688
|
}
|
|
2653
2689
|
getAnyModelForProvider(type) {
|
|
2654
|
-
|
|
2690
|
+
const fromCatalog = Object.values(MODELS).find((m) => m.provider === type);
|
|
2691
|
+
if (fromCatalog) return fromCatalog;
|
|
2692
|
+
if (type === "openai-compatible" || type === "azure") {
|
|
2693
|
+
return {
|
|
2694
|
+
id: type,
|
|
2695
|
+
name: type,
|
|
2696
|
+
provider: type,
|
|
2697
|
+
contextWindow: 32e3,
|
|
2698
|
+
isVisionCapable: false,
|
|
2699
|
+
inputCostPer1kTokens: 0,
|
|
2700
|
+
outputCostPer1kTokens: 0,
|
|
2701
|
+
maxOutputTokens: 4e3,
|
|
2702
|
+
supportsStreaming: true,
|
|
2703
|
+
isLocal: false
|
|
2704
|
+
};
|
|
2705
|
+
}
|
|
2706
|
+
return void 0;
|
|
2655
2707
|
}
|
|
2656
2708
|
recordStats(tier, model, usage) {
|
|
2657
2709
|
this.stats.totalTokens += usage.totalTokens;
|
|
@@ -8792,7 +8844,11 @@ ${last.partialOutput}` : "");
|
|
|
8792
8844
|
looksLikeConversational(prompt) {
|
|
8793
8845
|
const LOW_COMPLEXITY = [
|
|
8794
8846
|
/^(?:hi|hello|hey|thanks|thank you|ok|okay|yes|no|sure|got it|sounds good)\b/i,
|
|
8795
|
-
/^(?:what is|what are|list|show me|tell me|who is|where is|when is|how do i)\b/i,
|
|
8847
|
+
/^(?:what is|what are|what'?s|list|show me|tell me|who is|who are|who'?re|where is|when is|how do i)\b/i,
|
|
8848
|
+
// Self-identity / capability questions ("who are you", "what can you do",
|
|
8849
|
+
// "who made you") are pure conversation — never a multi-agent build.
|
|
8850
|
+
/^(?:who|what)\b.*\byou\b/i,
|
|
8851
|
+
/^what can you\b/i,
|
|
8796
8852
|
/\b(?:simple|quick|brief|small|single|one-line|typo|rename)\b/i
|
|
8797
8853
|
];
|
|
8798
8854
|
const wordCount = prompt.trim().split(/\s+/).length;
|
|
@@ -8890,10 +8946,16 @@ ${prompt}` : prompt;
|
|
|
8890
8946
|
temperature: 0
|
|
8891
8947
|
});
|
|
8892
8948
|
const content = result.content.trim();
|
|
8893
|
-
const
|
|
8949
|
+
const match = content.toLowerCase().match(/\b(simple|moderate|complex)\b/);
|
|
8894
8950
|
const reason = content.replace(/^\S+\s*[—–-]*\s*/, "").trim();
|
|
8895
|
-
|
|
8896
|
-
|
|
8951
|
+
let verdict;
|
|
8952
|
+
if (match) {
|
|
8953
|
+
verdict = match[1] === "simple" ? "Simple" : match[1] === "moderate" ? "Moderate" : "Complex";
|
|
8954
|
+
this.recordDecision("complexity", `${verdict} \u2014 classifier: ${reason || "no reason given"}`);
|
|
8955
|
+
} else {
|
|
8956
|
+
verdict = prompt.trim().split(/\s+/).length <= 12 ? "Simple" : "Moderate";
|
|
8957
|
+
this.recordDecision("complexity", `${verdict} \u2014 classifier output unparseable; defaulted by length`);
|
|
8958
|
+
}
|
|
8897
8959
|
return verdict;
|
|
8898
8960
|
} catch {
|
|
8899
8961
|
const followUpPrompt = /^(proceed|continue|go ahead|do it|yes|yep|ok|okay|carry on)$/i.test(prompt.trim());
|