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/index.cjs CHANGED
@@ -77,7 +77,7 @@ var cron__default = /*#__PURE__*/_interopDefault(cron);
77
77
 
78
78
 
79
79
  // src/constants.ts
80
- var CASCADE_VERSION = "0.12.5";
80
+ var CASCADE_VERSION = "0.12.7";
81
81
  var CASCADE_CONFIG_DIR = ".cascade";
82
82
  var CASCADE_MD_FILE = "CASCADE.md";
83
83
  var CASCADE_IGNORE_FILE = ".cascadeignore";
@@ -146,6 +146,30 @@ var MODELS = {
146
146
  supportsStreaming: true,
147
147
  isLocal: false
148
148
  },
149
+ "claude-opus-4-8": {
150
+ id: "claude-opus-4-8",
151
+ name: "Claude Opus 4.8",
152
+ provider: "anthropic",
153
+ contextWindow: 2e5,
154
+ isVisionCapable: true,
155
+ inputCostPer1kTokens: 0.015,
156
+ outputCostPer1kTokens: 0.075,
157
+ maxOutputTokens: 32e3,
158
+ supportsStreaming: true,
159
+ isLocal: false
160
+ },
161
+ "claude-sonnet-4-6": {
162
+ id: "claude-sonnet-4-6",
163
+ name: "Claude Sonnet 4.6",
164
+ provider: "anthropic",
165
+ contextWindow: 2e5,
166
+ isVisionCapable: true,
167
+ inputCostPer1kTokens: 3e-3,
168
+ outputCostPer1kTokens: 0.015,
169
+ maxOutputTokens: 16e3,
170
+ supportsStreaming: true,
171
+ isLocal: false
172
+ },
149
173
  // OpenAI
150
174
  "gpt-4o": {
151
175
  id: "gpt-4o",
@@ -407,6 +431,24 @@ var PROVIDER_DISPLAY_NAMES = {
407
431
  ollama: "Ollama (Local)"
408
432
  };
409
433
 
434
+ // src/utils/cost.ts
435
+ function resolveModelPricing(model) {
436
+ let input = model.inputCostPer1kTokens;
437
+ let output = model.outputCostPer1kTokens;
438
+ if (input === 0 && output === 0 && model.id && !model.isLocal) {
439
+ const known = Object.values(MODELS).find((m) => m.id === model.id && !m.isLocal);
440
+ if (known) {
441
+ input = known.inputCostPer1kTokens;
442
+ output = known.outputCostPer1kTokens;
443
+ }
444
+ }
445
+ return { input, output };
446
+ }
447
+ function calculateCost(inputTokens, outputTokens, model) {
448
+ const { input, output } = resolveModelPricing(model);
449
+ return inputTokens / 1e3 * input + outputTokens / 1e3 * output;
450
+ }
451
+
410
452
  // src/providers/base.ts
411
453
  var BaseProvider = class {
412
454
  config;
@@ -422,7 +464,7 @@ var BaseProvider = class {
422
464
  return this.model.isVisionCapable;
423
465
  }
424
466
  estimateCost(inputTokens, outputTokens) {
425
- return inputTokens / 1e3 * this.model.inputCostPer1kTokens + outputTokens / 1e3 * this.model.outputCostPer1kTokens;
467
+ return calculateCost(inputTokens, outputTokens, this.model);
426
468
  }
427
469
  makeUsage(inputTokens, outputTokens) {
428
470
  return {
@@ -1711,11 +1753,6 @@ var LocalRequestQueue = class {
1711
1753
  }
1712
1754
  };
1713
1755
 
1714
- // src/utils/cost.ts
1715
- function calculateCost(inputTokens, outputTokens, model) {
1716
- return inputTokens / 1e3 * model.inputCostPer1kTokens + outputTokens / 1e3 * model.outputCostPer1kTokens;
1717
- }
1718
-
1719
1756
  // src/utils/retry.ts
1720
1757
  var CascadeCancelledError = class extends Error {
1721
1758
  constructor(reason) {
@@ -3294,8 +3331,9 @@ var T3Worker = class extends BaseTier {
3294
3331
  const depOutputs = [];
3295
3332
  for (const depId of assignment.dependsOn) {
3296
3333
  try {
3297
- const dep = await this.peerBus.waitFor(depId);
3334
+ const dep = await this.peerBus.waitFor(depId, 6e4);
3298
3335
  if (dep.status === "FAILED" || dep.status === "ESCALATED") {
3336
+ this.peerBus.publish(this.id, assignment.subtaskId, `Blocked by failed dependency: ${depId}`, "FAILED");
3299
3337
  return this.buildResult(
3300
3338
  "ESCALATED",
3301
3339
  `Dependency ${depId} failed \u2014 cannot proceed`,
@@ -3307,6 +3345,7 @@ var T3Worker = class extends BaseTier {
3307
3345
  depOutputs.push(`[From ${dep.fromId} - ${dep.subtaskId}]:
3308
3346
  ${dep.output}`);
3309
3347
  } catch (err) {
3348
+ this.peerBus.publish(this.id, assignment.subtaskId, `Dependency timeout: ${depId}`, "FAILED");
3310
3349
  return this.buildResult(
3311
3350
  "ESCALATED",
3312
3351
  `Dependency timeout: ${depId}`,
@@ -5005,6 +5044,16 @@ function parseFirstJsonObject(input) {
5005
5044
  }
5006
5045
 
5007
5046
  // src/core/tiers/t1-administrator.ts
5047
+ function sharedKeywords(a = [], b = []) {
5048
+ const setB = new Set(b.map((k) => k.toLowerCase().trim()).filter(Boolean));
5049
+ return [...new Set(a.map((k) => k.toLowerCase().trim()).filter(Boolean))].filter((k) => setB.has(k));
5050
+ }
5051
+ function isStrongKeywordOverlap(a = [], b = []) {
5052
+ if (!a.length || !b.length) return false;
5053
+ const shared = sharedKeywords(a, b);
5054
+ const ratio = shared.length / Math.min(a.length, b.length);
5055
+ return shared.length >= 3 && ratio >= 0.6;
5056
+ }
5008
5057
  var T1_SYSTEM_PROMPT = `You are T1, the Administrator in the Cascade AI orchestration system.
5009
5058
 
5010
5059
  Your responsibilities:
@@ -5429,17 +5478,27 @@ Leave dependsOn empty for sections that can run immediately in parallel.`;
5429
5478
  siblingKeywords.set(payload.sectionId, [...new Set(existing)]);
5430
5479
  }
5431
5480
  }
5432
- const overlapSections = /* @__PURE__ */ new Set();
5433
- for (let i = 0; i < announcements.length; i++) {
5434
- for (let j = i + 1; j < announcements.length; j++) {
5435
- const a = announcements[i].payload;
5436
- const b = announcements[j].payload;
5437
- if (!a.keywords || !b.keywords || !a.sectionId || !b.sectionId) continue;
5438
- const shared = a.keywords.filter((k) => b.keywords.includes(k));
5439
- if (shared.length > 0) {
5440
- overlapSections.add(a.sectionId);
5441
- overlapSections.add(b.sectionId);
5442
- this.log(`T2 overlap detected between sections: ${a.sectionId} \u2194 ${b.sectionId} (shared: ${shared.join(", ")})`);
5481
+ const payloads = announcements.map((ann) => ann.payload).filter((p) => p?.type === "T2_PLAN_ANNOUNCEMENT" && !!p.sectionId);
5482
+ const softOverlap = /* @__PURE__ */ new Set();
5483
+ const orderOf = new Map(sections.map((s, i) => [s.sectionId, i]));
5484
+ for (let i = 0; i < payloads.length; i++) {
5485
+ for (let j = i + 1; j < payloads.length; j++) {
5486
+ const a = payloads[i];
5487
+ const b = payloads[j];
5488
+ const shared = sharedKeywords(a.keywords ?? [], b.keywords ?? []);
5489
+ if (shared.length === 0) continue;
5490
+ softOverlap.add(a.sectionId);
5491
+ softOverlap.add(b.sectionId);
5492
+ if (isStrongKeywordOverlap(a.keywords ?? [], b.keywords ?? [])) {
5493
+ const ai = orderOf.get(a.sectionId) ?? 0;
5494
+ const bi = orderOf.get(b.sectionId) ?? 0;
5495
+ const earlier = ai <= bi ? a.sectionId : b.sectionId;
5496
+ const later = ai <= bi ? b.sectionId : a.sectionId;
5497
+ const laterSection = sections.find((s) => s.sectionId === later);
5498
+ if (laterSection && earlier !== later && !(laterSection.dependsOn ?? []).includes(earlier)) {
5499
+ laterSection.dependsOn = [...laterSection.dependsOn || [], earlier];
5500
+ this.log(`Strong overlap ${earlier} \u2194 ${later} (shared: ${shared.slice(0, 5).join(", ")}) \u2014 serializing ${later} after ${earlier}`);
5501
+ }
5443
5502
  }
5444
5503
  }
5445
5504
  }
@@ -5451,20 +5510,10 @@ Leave dependsOn empty for sections that can run immediately in parallel.`;
5451
5510
  `You are T2 Manager for section: "${section.sectionTitle}".`,
5452
5511
  `Sibling sections being worked on in parallel: ${otherTitles.join(", ") || "none"}.`,
5453
5512
  myKeywords.length > 0 ? `Watch for overlap with: ${[...new Set(myKeywords)].slice(0, 10).join(", ")}.` : "",
5454
- overlapSections.has(section.sectionId) ? "NOTE: Potential overlap detected with a sibling section \u2014 be careful not to duplicate work." : ""
5513
+ softOverlap.has(section.sectionId) ? "NOTE: Potential overlap detected with a sibling section \u2014 be careful not to duplicate work." : ""
5455
5514
  ].filter(Boolean).join(" ");
5456
5515
  m.setHierarchyContext(context);
5457
5516
  });
5458
- if (overlapSections.size > 0) {
5459
- this.log("Overlap detected \u2014 adding sequential dependencies for conflicting sections to prevent race conditions");
5460
- const overlapArray = Array.from(overlapSections);
5461
- for (let i = 1; i < overlapArray.length; i++) {
5462
- const section = sections.find((s) => s.sectionId === overlapArray[i]);
5463
- if (section) {
5464
- section.dependsOn = [...section.dependsOn || [], overlapArray[i - 1]];
5465
- }
5466
- }
5467
- }
5468
5517
  const t2Results = [];
5469
5518
  try {
5470
5519
  t2Results.push(...await this.runT2sWithDependencies(sections, managers, this.taskId));