cascade-ai 0.45.0 → 0.46.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/cli.cjs CHANGED
@@ -116,7 +116,7 @@ var __export = (target, all) => {
116
116
  var CASCADE_VERSION, CASCADE_CONFIG_FILE, CASCADE_DB_FILE, CASCADE_DASHBOARD_SECRET_FILE, GLOBAL_CONFIG_DIR, GLOBAL_DB_FILE, GLOBAL_KEYSTORE_FILE, GLOBAL_CREDENTIALS_FILE, GLOBAL_RUNTIME_DB_FILE, DEFAULT_DASHBOARD_PORT, DEFAULT_CONTEXT_LIMIT, DEFAULT_AUTO_SUMMARIZE_AT, MODELS, T1_MODEL_PRIORITY, T2_MODEL_PRIORITY, T3_MODEL_PRIORITY, VISION_MODEL_PRIORITY, COMPLEXITY_T2_COUNT, THEME_NAMES, DEFAULT_THEME, OLLAMA_BASE_URL, LM_STUDIO_BASE_URL, AZURE_BASE_URL_TEMPLATE, TOOL_NAMES, DEFAULT_APPROVAL_REQUIRED;
117
117
  var init_constants = __esm({
118
118
  "src/constants.ts"() {
119
- CASCADE_VERSION = "0.45.0";
119
+ CASCADE_VERSION = "0.46.0";
120
120
  CASCADE_CONFIG_FILE = ".cascade/config.json";
121
121
  CASCADE_DB_FILE = ".cascade/memory.db";
122
122
  CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
@@ -3954,12 +3954,21 @@ var ModelSelector = class {
3954
3954
  * Absent for a provider ⇒ no validation ran ⇒ behave exactly as before.
3955
3955
  */
3956
3956
  validatedIds = /* @__PURE__ */ new Map();
3957
+ /**
3958
+ * Normalized ids that were added via discovery/registration but aren't in the
3959
+ * bundled catalog — i.e. genuinely new models the provider reported (a Gemini
3960
+ * flash released after the catalog was last hand-updated, an Ollama tag, etc.).
3961
+ * getCandidatesForTier lets these compete in AUTO ranking so a newer,
3962
+ * better-value model isn't invisible until someone edits constants.ts.
3963
+ */
3964
+ discovered = /* @__PURE__ */ new Set();
3957
3965
  constructor(availableProviders) {
3958
3966
  this.availableProviders = availableProviders;
3959
3967
  this.availableModels = new Map(Object.entries(MODELS));
3960
3968
  }
3961
3969
  addDynamicModel(model) {
3962
3970
  this.availableModels.set(model.id, model);
3971
+ if (!(model.id in MODELS)) this.discovered.add(normalizeModelId(model.id));
3963
3972
  }
3964
3973
  /** Record the ids a provider's API actually serves (discovery). Empty ⇒ ignored. */
3965
3974
  setValidatedModels(provider, ids) {
@@ -4067,6 +4076,19 @@ var ModelSelector = class {
4067
4076
  candidates2.push(model);
4068
4077
  }
4069
4078
  }
4079
+ if (this.discovered.size) {
4080
+ const tierProviders = /* @__PURE__ */ new Set();
4081
+ for (const key of priority) {
4082
+ const m = MODELS[key];
4083
+ if (m) tierProviders.add(m.provider);
4084
+ }
4085
+ const have = new Set(candidates2.map((c) => c.id));
4086
+ for (const model of this.availableModels.values()) {
4087
+ if (have.has(model.id)) continue;
4088
+ if (!this.discovered.has(normalizeModelId(model.id))) continue;
4089
+ if (tierProviders.has(model.provider) && this.isUsable(model)) candidates2.push(model);
4090
+ }
4091
+ }
4070
4092
  const localOnly = this.availableProviders.size > 0 && Array.from(this.availableProviders).every((p) => p === "ollama");
4071
4093
  if (localOnly) {
4072
4094
  for (const model of this.availableModels.values()) {
@@ -4778,6 +4800,14 @@ var FAMILY_MATCHERS = [
4778
4800
  [/gemini-?1\.5-pro/i, "gemini-1.5-pro"],
4779
4801
  [/gemini-?2\.0-flash-lite/i, "gemini-flash-lite"],
4780
4802
  [/gemini-?2\.0-flash/i, "gemini-2.0-flash"],
4803
+ // Generic Gemini fallbacks — a model released after this table was written
4804
+ // (e.g. a Gemini 3.x flash discovered live from the provider) still gets a
4805
+ // sensible score by its class instead of a neutral 0.5, so it can compete in
4806
+ // AUTO ranking. Ordered after the specific rows above; most-specific first.
4807
+ [/gemini.*flash.?lite/i, "gemini-flash-lite"],
4808
+ [/gemini.*pro/i, "gemini-2.5-pro"],
4809
+ [/gemini.*flash/i, "gemini-2.5-flash"],
4810
+ [/gemini/i, "gemini-2.5-flash"],
4781
4811
  [/codellama|code-llama|starcoder|stable-code/i, "codellama"],
4782
4812
  [/deepseek/i, "deepseek"],
4783
4813
  [/qwen/i, "qwen"],
@@ -4869,6 +4899,13 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter__default.default {
4869
4899
  costByFeature: {}
4870
4900
  };
4871
4901
  tierModels = /* @__PURE__ */ new Map();
4902
+ /**
4903
+ * Tiers the user pinned to a specific model in config (`models.tX` !== 'auto').
4904
+ * An explicit pin always wins over Cascade Auto — selectModelForSubtask never
4905
+ * re-selects a pinned tier per subtask. (tierModels is also filled with
4906
+ * auto-picked defaults, so it alone can't distinguish "pinned" from "default".)
4907
+ */
4908
+ explicitTierModels = /* @__PURE__ */ new Set();
4872
4909
  config;
4873
4910
  sessionCostUsd = 0;
4874
4911
  // Per-run accounting for the hard per-task cap. Reset by beginRun() at the
@@ -4946,6 +4983,7 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter__default.default {
4946
4983
  );
4947
4984
  }
4948
4985
  this.tierModels.set(tier, model);
4986
+ this.explicitTierModels.add(tier);
4949
4987
  this.ensureProvider(model, config.providers);
4950
4988
  }
4951
4989
  const azureRanked = [...azureDeployments].sort((a, b) => inferModelCapability(b.id) - inferModelCapability(a.id));
@@ -5386,6 +5424,7 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter__default.default {
5386
5424
  * Pure heuristic — no extra LLM call.
5387
5425
  */
5388
5426
  async selectModelForSubtask(tier, text, opts) {
5427
+ if (this.explicitTierModels.has(tier)) return this.tierModels.get(tier) ?? null;
5389
5428
  if (!this.config?.cascadeAuto || !this.taskAnalyzer || !text.trim()) return null;
5390
5429
  try {
5391
5430
  return await this.taskAnalyzer.selectModel(text, tier, this.selector, opts);