cascade-ai 0.12.5 → 0.12.7

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
@@ -54,7 +54,7 @@ var __export = (target, all) => {
54
54
  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;
55
55
  var init_constants = __esm({
56
56
  "src/constants.ts"() {
57
- CASCADE_VERSION = "0.12.5";
57
+ CASCADE_VERSION = "0.12.7";
58
58
  CASCADE_CONFIG_FILE = ".cascade/config.json";
59
59
  CASCADE_DB_FILE = ".cascade/memory.db";
60
60
  CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
@@ -115,6 +115,30 @@ var init_constants = __esm({
115
115
  supportsStreaming: true,
116
116
  isLocal: false
117
117
  },
118
+ "claude-opus-4-8": {
119
+ id: "claude-opus-4-8",
120
+ name: "Claude Opus 4.8",
121
+ provider: "anthropic",
122
+ contextWindow: 2e5,
123
+ isVisionCapable: true,
124
+ inputCostPer1kTokens: 0.015,
125
+ outputCostPer1kTokens: 0.075,
126
+ maxOutputTokens: 32e3,
127
+ supportsStreaming: true,
128
+ isLocal: false
129
+ },
130
+ "claude-sonnet-4-6": {
131
+ id: "claude-sonnet-4-6",
132
+ name: "Claude Sonnet 4.6",
133
+ provider: "anthropic",
134
+ contextWindow: 2e5,
135
+ isVisionCapable: true,
136
+ inputCostPer1kTokens: 3e-3,
137
+ outputCostPer1kTokens: 0.015,
138
+ maxOutputTokens: 16e3,
139
+ supportsStreaming: true,
140
+ isLocal: false
141
+ },
118
142
  // OpenAI
119
143
  "gpt-4o": {
120
144
  id: "gpt-4o",
@@ -370,10 +394,34 @@ var init_constants = __esm({
370
394
  }
371
395
  });
372
396
 
397
+ // src/utils/cost.ts
398
+ function resolveModelPricing(model) {
399
+ let input = model.inputCostPer1kTokens;
400
+ let output = model.outputCostPer1kTokens;
401
+ if (input === 0 && output === 0 && model.id && !model.isLocal) {
402
+ const known = Object.values(MODELS).find((m) => m.id === model.id && !m.isLocal);
403
+ if (known) {
404
+ input = known.inputCostPer1kTokens;
405
+ output = known.outputCostPer1kTokens;
406
+ }
407
+ }
408
+ return { input, output };
409
+ }
410
+ function calculateCost(inputTokens, outputTokens, model) {
411
+ const { input, output } = resolveModelPricing(model);
412
+ return inputTokens / 1e3 * input + outputTokens / 1e3 * output;
413
+ }
414
+ var init_cost = __esm({
415
+ "src/utils/cost.ts"() {
416
+ init_constants();
417
+ }
418
+ });
419
+
373
420
  // src/providers/base.ts
374
421
  var BaseProvider;
375
422
  var init_base = __esm({
376
423
  "src/providers/base.ts"() {
424
+ init_cost();
377
425
  BaseProvider = class {
378
426
  config;
379
427
  model;
@@ -388,7 +436,7 @@ var init_base = __esm({
388
436
  return this.model.isVisionCapable;
389
437
  }
390
438
  estimateCost(inputTokens, outputTokens) {
391
- return inputTokens / 1e3 * this.model.inputCostPer1kTokens + outputTokens / 1e3 * this.model.outputCostPer1kTokens;
439
+ return calculateCost(inputTokens, outputTokens, this.model);
392
440
  }
393
441
  makeUsage(inputTokens, outputTokens) {
394
442
  return {
@@ -3513,11 +3561,7 @@ var LocalRequestQueue = class {
3513
3561
 
3514
3562
  // src/core/router/index.ts
3515
3563
  init_constants();
3516
-
3517
- // src/utils/cost.ts
3518
- function calculateCost(inputTokens, outputTokens, model) {
3519
- return inputTokens / 1e3 * model.inputCostPer1kTokens + outputTokens / 1e3 * model.outputCostPer1kTokens;
3520
- }
3564
+ init_cost();
3521
3565
 
3522
3566
  // src/utils/retry.ts
3523
3567
  var CascadeCancelledError = class extends Error {
@@ -3635,6 +3679,7 @@ var ModelProfiler = class {
3635
3679
  };
3636
3680
 
3637
3681
  // src/core/router/savings.ts
3682
+ init_cost();
3638
3683
  var NO_SAVINGS = { savedUsd: 0, savedPct: 0, counterfactualUsd: 0 };
3639
3684
  function computeDelegationSavings(stats, t1Model) {
3640
3685
  if (!t1Model) return NO_SAVINGS;
@@ -5088,8 +5133,9 @@ var T3Worker = class extends BaseTier {
5088
5133
  const depOutputs = [];
5089
5134
  for (const depId of assignment.dependsOn) {
5090
5135
  try {
5091
- const dep = await this.peerBus.waitFor(depId);
5136
+ const dep = await this.peerBus.waitFor(depId, 6e4);
5092
5137
  if (dep.status === "FAILED" || dep.status === "ESCALATED") {
5138
+ this.peerBus.publish(this.id, assignment.subtaskId, `Blocked by failed dependency: ${depId}`, "FAILED");
5093
5139
  return this.buildResult(
5094
5140
  "ESCALATED",
5095
5141
  `Dependency ${depId} failed \u2014 cannot proceed`,
@@ -5101,6 +5147,7 @@ var T3Worker = class extends BaseTier {
5101
5147
  depOutputs.push(`[From ${dep.fromId} - ${dep.subtaskId}]:
5102
5148
  ${dep.output}`);
5103
5149
  } catch (err) {
5150
+ this.peerBus.publish(this.id, assignment.subtaskId, `Dependency timeout: ${depId}`, "FAILED");
5104
5151
  return this.buildResult(
5105
5152
  "ESCALATED",
5106
5153
  `Dependency timeout: ${depId}`,
@@ -6802,6 +6849,16 @@ function parseFirstJsonObject(input) {
6802
6849
  }
6803
6850
 
6804
6851
  // src/core/tiers/t1-administrator.ts
6852
+ function sharedKeywords(a = [], b = []) {
6853
+ const setB = new Set(b.map((k) => k.toLowerCase().trim()).filter(Boolean));
6854
+ return [...new Set(a.map((k) => k.toLowerCase().trim()).filter(Boolean))].filter((k) => setB.has(k));
6855
+ }
6856
+ function isStrongKeywordOverlap(a = [], b = []) {
6857
+ if (!a.length || !b.length) return false;
6858
+ const shared = sharedKeywords(a, b);
6859
+ const ratio = shared.length / Math.min(a.length, b.length);
6860
+ return shared.length >= 3 && ratio >= 0.6;
6861
+ }
6805
6862
  var T1_SYSTEM_PROMPT = `You are T1, the Administrator in the Cascade AI orchestration system.
6806
6863
 
6807
6864
  Your responsibilities:
@@ -7226,17 +7283,27 @@ Leave dependsOn empty for sections that can run immediately in parallel.`;
7226
7283
  siblingKeywords.set(payload.sectionId, [...new Set(existing)]);
7227
7284
  }
7228
7285
  }
7229
- const overlapSections = /* @__PURE__ */ new Set();
7230
- for (let i = 0; i < announcements.length; i++) {
7231
- for (let j = i + 1; j < announcements.length; j++) {
7232
- const a = announcements[i].payload;
7233
- const b = announcements[j].payload;
7234
- if (!a.keywords || !b.keywords || !a.sectionId || !b.sectionId) continue;
7235
- const shared = a.keywords.filter((k) => b.keywords.includes(k));
7236
- if (shared.length > 0) {
7237
- overlapSections.add(a.sectionId);
7238
- overlapSections.add(b.sectionId);
7239
- this.log(`T2 overlap detected between sections: ${a.sectionId} \u2194 ${b.sectionId} (shared: ${shared.join(", ")})`);
7286
+ const payloads = announcements.map((ann) => ann.payload).filter((p) => p?.type === "T2_PLAN_ANNOUNCEMENT" && !!p.sectionId);
7287
+ const softOverlap = /* @__PURE__ */ new Set();
7288
+ const orderOf = new Map(sections.map((s, i) => [s.sectionId, i]));
7289
+ for (let i = 0; i < payloads.length; i++) {
7290
+ for (let j = i + 1; j < payloads.length; j++) {
7291
+ const a = payloads[i];
7292
+ const b = payloads[j];
7293
+ const shared = sharedKeywords(a.keywords ?? [], b.keywords ?? []);
7294
+ if (shared.length === 0) continue;
7295
+ softOverlap.add(a.sectionId);
7296
+ softOverlap.add(b.sectionId);
7297
+ if (isStrongKeywordOverlap(a.keywords ?? [], b.keywords ?? [])) {
7298
+ const ai = orderOf.get(a.sectionId) ?? 0;
7299
+ const bi = orderOf.get(b.sectionId) ?? 0;
7300
+ const earlier = ai <= bi ? a.sectionId : b.sectionId;
7301
+ const later = ai <= bi ? b.sectionId : a.sectionId;
7302
+ const laterSection = sections.find((s) => s.sectionId === later);
7303
+ if (laterSection && earlier !== later && !(laterSection.dependsOn ?? []).includes(earlier)) {
7304
+ laterSection.dependsOn = [...laterSection.dependsOn || [], earlier];
7305
+ this.log(`Strong overlap ${earlier} \u2194 ${later} (shared: ${shared.slice(0, 5).join(", ")}) \u2014 serializing ${later} after ${earlier}`);
7306
+ }
7240
7307
  }
7241
7308
  }
7242
7309
  }
@@ -7248,20 +7315,10 @@ Leave dependsOn empty for sections that can run immediately in parallel.`;
7248
7315
  `You are T2 Manager for section: "${section.sectionTitle}".`,
7249
7316
  `Sibling sections being worked on in parallel: ${otherTitles.join(", ") || "none"}.`,
7250
7317
  myKeywords.length > 0 ? `Watch for overlap with: ${[...new Set(myKeywords)].slice(0, 10).join(", ")}.` : "",
7251
- overlapSections.has(section.sectionId) ? "NOTE: Potential overlap detected with a sibling section \u2014 be careful not to duplicate work." : ""
7318
+ softOverlap.has(section.sectionId) ? "NOTE: Potential overlap detected with a sibling section \u2014 be careful not to duplicate work." : ""
7252
7319
  ].filter(Boolean).join(" ");
7253
7320
  m.setHierarchyContext(context);
7254
7321
  });
7255
- if (overlapSections.size > 0) {
7256
- this.log("Overlap detected \u2014 adding sequential dependencies for conflicting sections to prevent race conditions");
7257
- const overlapArray = Array.from(overlapSections);
7258
- for (let i = 1; i < overlapArray.length; i++) {
7259
- const section = sections.find((s) => s.sectionId === overlapArray[i]);
7260
- if (section) {
7261
- section.dependsOn = [...section.dependsOn || [], overlapArray[i - 1]];
7262
- }
7263
- }
7264
- }
7265
7322
  const t2Results = [];
7266
7323
  try {
7267
7324
  t2Results.push(...await this.runT2sWithDependencies(sections, managers, this.taskId));
@@ -7456,6 +7513,9 @@ Reply with exactly one word: YES, NO, or UNSURE.
7456
7513
  }
7457
7514
  };
7458
7515
 
7516
+ // src/core/cascade.ts
7517
+ init_cost();
7518
+
7459
7519
  // src/tools/registry.ts
7460
7520
  init_constants();
7461
7521