cascade-ai 0.3.0 → 0.4.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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import Anthropic from '@anthropic-ai/sdk';
2
- import OpenAI from 'openai';
2
+ import OpenAI, { AzureOpenAI } from 'openai';
3
3
  import { GoogleGenAI, HarmBlockThreshold, HarmCategory } from '@google/genai';
4
4
  import axios2 from 'axios';
5
5
  import { render, useApp, useStdout, useInput, Box, Text } from 'ink';
@@ -83,7 +83,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
83
83
  var CASCADE_VERSION, CASCADE_CONFIG_FILE, CASCADE_DB_FILE, CASCADE_DASHBOARD_SECRET_FILE, GLOBAL_CONFIG_DIR, GLOBAL_DB_FILE, GLOBAL_KEYSTORE_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;
84
84
  var init_constants = __esm({
85
85
  "src/constants.ts"() {
86
- CASCADE_VERSION = "0.3.0";
86
+ CASCADE_VERSION = "0.4.0";
87
87
  CASCADE_CONFIG_FILE = ".cascade/config.json";
88
88
  CASCADE_DB_FILE = ".cascade/memory.db";
89
89
  CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
@@ -902,19 +902,21 @@ var init_azure = __esm({
902
902
  init_openai();
903
903
  AzureOpenAIProvider = class extends OpenAIProvider {
904
904
  constructor(config, model) {
905
- const baseUrl = config.baseUrl ?? AZURE_BASE_URL_TEMPLATE.replace("{resource}", "YOUR_RESOURCE");
905
+ const rawUrl = config.baseUrl ?? AZURE_BASE_URL_TEMPLATE.replace("{resource}", "YOUR_RESOURCE");
906
+ const endpoint = rawUrl.replace(/\/+$/, "");
906
907
  super(
907
908
  {
908
909
  ...config,
909
- baseUrl: `${baseUrl}/openai/deployments/${config.deploymentName ?? model.id}`
910
+ baseUrl: endpoint
911
+ // Kept for superclass compatibility if it reads it
910
912
  },
911
913
  model
912
914
  );
913
- this.client = new OpenAI({
915
+ this.client = new AzureOpenAI({
914
916
  apiKey: config.apiKey,
915
- baseURL: `${baseUrl}/openai/deployments/${config.deploymentName ?? model.id}`,
916
- defaultQuery: { "api-version": config.apiVersion ?? "2024-08-01-preview" },
917
- defaultHeaders: { "api-key": config.apiKey ?? "" }
917
+ endpoint,
918
+ deployment: config.deploymentName ?? model.id,
919
+ apiVersion: config.apiVersion ?? "2024-08-01-preview"
918
920
  });
919
921
  }
920
922
  async listModels() {
@@ -3248,7 +3250,7 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
3248
3250
  if (!model) {
3249
3251
  throw new Error(`Configured model "${override}" for ${tier} could not be loaded. Check provider availability and exact model name.`);
3250
3252
  }
3251
- if (model.id !== override) {
3253
+ if (model.id !== override && `${model.provider}:${model.id}` !== override) {
3252
3254
  throw new Error(`Configured model "${override}" for ${tier} resolved to "${model.id}". Use the exact provider model ID or prefix the provider (e.g. gemini:${override}).`);
3253
3255
  }
3254
3256
  this.tierModels.set(tier, model);
@@ -4080,6 +4082,10 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : ""),
4080
4082
  await this.context.addMessage({ role: "assistant", content: result.content, toolCalls: result.toolCalls });
4081
4083
  if (!result.toolCalls?.length) {
4082
4084
  if (requiresArtifact) {
4085
+ const artifactCheck = await this.verifyArtifacts(this.assignment);
4086
+ if (artifactCheck.ok) {
4087
+ return { output: result.content, toolCalls: allToolCalls };
4088
+ }
4083
4089
  stalledArtifactIterations += 1;
4084
4090
  if (stalledArtifactIterations >= 2) {
4085
4091
  if (stalledArtifactIterations === 2) {
@@ -4089,15 +4095,22 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : ""),
4089
4095
  }
4090
4096
  await this.context.addMessage({
4091
4097
  role: "user",
4092
- content: "You have not yet created and verified the required artifact. Use tools to create the file in the workspace, verify it exists, and inspect the result before concluding."
4098
+ content: `You have not yet created and verified the required artifact. Issues: ${artifactCheck.issues.join("; ")}. Use tools to create the file in the workspace, verify it exists, and inspect the result before concluding.`
4093
4099
  });
4094
4100
  continue;
4095
4101
  }
4096
4102
  return { output: result.content, toolCalls: allToolCalls };
4097
4103
  }
4098
4104
  stalledArtifactIterations = 0;
4099
- if (result.finishReason === "stop" && !requiresArtifact) {
4100
- return { output: result.content, toolCalls: allToolCalls };
4105
+ if (result.finishReason === "stop") {
4106
+ if (requiresArtifact) {
4107
+ const artifactCheck = await this.verifyArtifacts(this.assignment);
4108
+ if (artifactCheck.ok) {
4109
+ return { output: result.content, toolCalls: allToolCalls };
4110
+ }
4111
+ } else {
4112
+ return { output: result.content, toolCalls: allToolCalls };
4113
+ }
4101
4114
  }
4102
4115
  for (const tc of result.toolCalls) {
4103
4116
  allToolCalls.push(tc);
@@ -7568,10 +7581,17 @@ var Cascade = class extends EventEmitter {
7568
7581
  throw err;
7569
7582
  }
7570
7583
  }
7584
+ isCasualGreeting(prompt) {
7585
+ const casual = /^(hi|hello|hey|greetings|thanks|thank you|thx|bye|goodbye|cya)$/i.test(prompt.trim().replace(/[!?.]+$/, ""));
7586
+ return casual;
7587
+ }
7571
7588
  looksLikeSimpleArtifactTask(prompt) {
7572
7589
  return /create .*\.(txt|md|json|csv)\b/i.test(prompt) && !/(research|compare|thorough|pdf|report|analy[sz]e|architecture|multi-agent)/i.test(prompt);
7573
7590
  }
7574
7591
  async determineComplexity(prompt, workspacePath, conversationHistory = []) {
7592
+ if (this.isCasualGreeting(prompt)) {
7593
+ return "Simple";
7594
+ }
7575
7595
  if (this.looksLikeSimpleArtifactTask(prompt)) {
7576
7596
  return "Simple";
7577
7597
  }
@@ -8878,7 +8898,7 @@ function Repl({ config, workspacePath, themeName, initialPrompt, identityName })
8878
8898
  if (sel.kind === "auto") {
8879
8899
  delete config.models[tierKey];
8880
8900
  } else {
8881
- config.models[tierKey] = sel.modelId;
8901
+ config.models[tierKey] = `${sel.provider}:${sel.modelId}`;
8882
8902
  }
8883
8903
  try {
8884
8904
  const router = cascadeRef.current?.getRouter();
@@ -9436,9 +9456,15 @@ Use /identity <name|id> to switch.`;
9436
9456
  let agentTreeHeight = 0;
9437
9457
  if (state.agentTree && hasActiveOrFailed2(state.agentTree)) {
9438
9458
  agentTreeHeight = 1;
9439
- const childrenCount = state.agentTree.children?.length ?? 0;
9440
- agentTreeHeight += Math.min(childrenCount, 6);
9441
- if (childrenCount > 6) agentTreeHeight += 1;
9459
+ const visibleT2s = state.agentTree.children?.slice(0, 6) ?? [];
9460
+ agentTreeHeight += visibleT2s.length;
9461
+ for (const t2 of visibleT2s) {
9462
+ const t3Count = (t2.children ?? []).filter((c) => c.role === "T3").length;
9463
+ agentTreeHeight += t3Count;
9464
+ }
9465
+ if ((state.agentTree.children?.length ?? 0) > 6) {
9466
+ agentTreeHeight += 1;
9467
+ }
9442
9468
  }
9443
9469
  let timelineHeight = 0;
9444
9470
  if (state.showDetails && treeNodesRef.current.size > 0) {
@@ -9627,6 +9653,13 @@ async function validateConfiguredModels(config) {
9627
9653
  return problems.length ? `Model warnings: ${problems.join(", ")}` : null;
9628
9654
  }
9629
9655
  function inferProviderFromModelId(id, providers) {
9656
+ if (id.includes(":")) {
9657
+ const prefix = id.split(":")[0].toLowerCase();
9658
+ const validProviders = ["anthropic", "openai", "gemini", "azure", "openai-compatible", "ollama"];
9659
+ if (validProviders.includes(prefix)) {
9660
+ return prefix;
9661
+ }
9662
+ }
9630
9663
  const lower = id.toLowerCase();
9631
9664
  if (lower.includes("gpt")) return "openai";
9632
9665
  if (lower.includes("claude")) return "anthropic";