cascade-ai 0.2.12 → 0.3.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
@@ -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.2.12";
86
+ CASCADE_VERSION = "0.3.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";
@@ -1875,8 +1875,8 @@ Original error: ${err.message}`
1875
1875
  upsertRuntimeNode(node) {
1876
1876
  this.enqueueWrite(() => {
1877
1877
  this.db.prepare(`
1878
- INSERT INTO runtime_nodes (tier_id, session_id, parent_id, role, label, status, current_action, progress_pct, updated_at, workspace_path, is_global)
1879
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1878
+ INSERT INTO runtime_nodes (tier_id, session_id, parent_id, role, label, status, current_action, progress_pct, updated_at, workspace_path, is_global, output)
1879
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1880
1880
  ON CONFLICT(tier_id) DO UPDATE SET
1881
1881
  session_id = excluded.session_id,
1882
1882
  parent_id = excluded.parent_id,
@@ -1887,7 +1887,8 @@ Original error: ${err.message}`
1887
1887
  progress_pct = excluded.progress_pct,
1888
1888
  updated_at = excluded.updated_at,
1889
1889
  workspace_path = excluded.workspace_path,
1890
- is_global = excluded.is_global
1890
+ is_global = excluded.is_global,
1891
+ output = excluded.output
1891
1892
  `).run(
1892
1893
  node.tierId,
1893
1894
  node.sessionId,
@@ -1899,7 +1900,8 @@ Original error: ${err.message}`
1899
1900
  node.progressPct ?? null,
1900
1901
  node.updatedAt,
1901
1902
  node.workspacePath ?? null,
1902
- node.isGlobal ? 1 : 0
1903
+ node.isGlobal ? 1 : 0,
1904
+ node.output ?? null
1903
1905
  );
1904
1906
  });
1905
1907
  }
@@ -1920,14 +1922,15 @@ Original error: ${err.message}`
1920
1922
  progressPct: row.progress_pct ?? void 0,
1921
1923
  updatedAt: row.updated_at,
1922
1924
  workspacePath: row.workspace_path ?? void 0,
1923
- isGlobal: row.is_global === 1
1925
+ isGlobal: row.is_global === 1,
1926
+ output: row.output ?? void 0
1924
1927
  }));
1925
1928
  }
1926
1929
  addRuntimeNodeLog(log) {
1927
1930
  this.enqueueWrite(() => {
1928
1931
  this.db.prepare(`
1929
- INSERT INTO runtime_node_logs (id, session_id, tier_id, role, label, status, current_action, progress_pct, timestamp, workspace_path, is_global)
1930
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1932
+ INSERT INTO runtime_node_logs (id, session_id, tier_id, role, label, status, current_action, progress_pct, timestamp, workspace_path, is_global, output)
1933
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1931
1934
  `).run(
1932
1935
  log.id,
1933
1936
  log.sessionId,
@@ -1939,7 +1942,8 @@ Original error: ${err.message}`
1939
1942
  log.progressPct ?? null,
1940
1943
  log.timestamp,
1941
1944
  log.workspacePath ?? null,
1942
- log.isGlobal ? 1 : 0
1945
+ log.isGlobal ? 1 : 0,
1946
+ log.output ?? null
1943
1947
  );
1944
1948
  this.db.prepare(`
1945
1949
  DELETE FROM runtime_node_logs
@@ -1982,7 +1986,8 @@ Original error: ${err.message}`
1982
1986
  progressPct: row.progress_pct ?? void 0,
1983
1987
  timestamp: row.timestamp,
1984
1988
  workspacePath: row.workspace_path ?? void 0,
1985
- isGlobal: row.is_global === 1
1989
+ isGlobal: row.is_global === 1,
1990
+ output: row.output ?? void 0
1986
1991
  }));
1987
1992
  }
1988
1993
  // ── Messages ──────────────────────────────────
@@ -2309,7 +2314,8 @@ Original error: ${err.message}`
2309
2314
  progress_pct INTEGER,
2310
2315
  updated_at TEXT NOT NULL,
2311
2316
  workspace_path TEXT,
2312
- is_global INTEGER NOT NULL DEFAULT 0
2317
+ is_global INTEGER NOT NULL DEFAULT 0,
2318
+ output TEXT
2313
2319
  );
2314
2320
 
2315
2321
  CREATE INDEX IF NOT EXISTS idx_runtime_nodes_session ON runtime_nodes(session_id);
@@ -2326,7 +2332,8 @@ Original error: ${err.message}`
2326
2332
  progress_pct INTEGER,
2327
2333
  timestamp TEXT NOT NULL,
2328
2334
  workspace_path TEXT,
2329
- is_global INTEGER NOT NULL DEFAULT 0
2335
+ is_global INTEGER NOT NULL DEFAULT 0,
2336
+ output TEXT
2330
2337
  );
2331
2338
 
2332
2339
  CREATE TABLE IF NOT EXISTS model_cache (
@@ -2355,6 +2362,14 @@ Original error: ${err.message}`
2355
2362
 
2356
2363
  CREATE INDEX IF NOT EXISTS idx_file_snapshots_session ON file_snapshots(session_id);
2357
2364
  `);
2365
+ try {
2366
+ this.db.exec("ALTER TABLE runtime_nodes ADD COLUMN output TEXT");
2367
+ } catch {
2368
+ }
2369
+ try {
2370
+ this.db.exec("ALTER TABLE runtime_node_logs ADD COLUMN output TEXT");
2371
+ } catch {
2372
+ }
2358
2373
  }
2359
2374
  // ── Deserializers ─────────────────────────────
2360
2375
  deserializeSession(row, messages) {
@@ -3583,7 +3598,7 @@ var BaseTier = class extends EventEmitter {
3583
3598
  getStatus() {
3584
3599
  return this.status;
3585
3600
  }
3586
- setStatus(status) {
3601
+ setStatus(status, output) {
3587
3602
  this.status = status;
3588
3603
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
3589
3604
  const event = {
@@ -3592,7 +3607,8 @@ var BaseTier = class extends EventEmitter {
3592
3607
  parentId: this.parentId,
3593
3608
  label: this.label,
3594
3609
  status,
3595
- timestamp
3610
+ timestamp,
3611
+ output
3596
3612
  };
3597
3613
  this.emit("status", event);
3598
3614
  this.emit("tier:status", event);
@@ -3618,7 +3634,8 @@ var BaseTier = class extends EventEmitter {
3618
3634
  status: this.status,
3619
3635
  currentAction: update.currentAction,
3620
3636
  progressPct: update.progressPct,
3621
- timestamp
3637
+ timestamp,
3638
+ output: update.output
3622
3639
  });
3623
3640
  }
3624
3641
  buildMessage(type, to, payload) {
@@ -3999,16 +4016,17 @@ Now execute your subtask using this context where relevant.`
3999
4016
  return this.buildResult("ESCALATED", output, { checksRun, passed, failed }, issues, correctionAttempts);
4000
4017
  }
4001
4018
  }
4002
- this.setStatus("COMPLETED");
4003
- this.sendStatusUpdate({ progressPct: 100, currentAction: "Subtask complete", status: "IN_PROGRESS" });
4019
+ this.setStatus("COMPLETED", output);
4020
+ this.sendStatusUpdate({ progressPct: 100, currentAction: "Subtask complete", status: "IN_PROGRESS", output });
4004
4021
  this.peerBus?.publish(this.id, assignment.subtaskId, output, "COMPLETED");
4005
4022
  return this.buildResult("COMPLETED", output, { checksRun, passed, failed }, issues, correctionAttempts);
4006
4023
  } catch (err) {
4007
4024
  const errMsg = err instanceof Error ? err.message : String(err);
4008
4025
  issues.push(`Execution error: ${errMsg}`);
4009
- this.setStatus("FAILED");
4010
- this.peerBus?.publish(this.id, assignment.subtaskId, errMsg, "FAILED");
4011
- return this.buildResult("ESCALATED", output || errMsg, { checksRun, passed, failed }, issues, correctionAttempts);
4026
+ const finalOutput = output || errMsg;
4027
+ this.setStatus("FAILED", finalOutput);
4028
+ this.peerBus?.publish(this.id, assignment.subtaskId, finalOutput, "FAILED");
4029
+ return this.buildResult("ESCALATED", finalOutput, { checksRun, passed, failed }, issues, correctionAttempts);
4012
4030
  }
4013
4031
  }
4014
4032
  sendToPeer(toId, content) {
@@ -4691,8 +4709,9 @@ var T2Manager = class extends BaseTier {
4691
4709
  const summary = await this.aggregateResults(assignment, t3Results);
4692
4710
  const issues = t3Results.filter((r) => r.status !== "COMPLETED").flatMap((r) => r.issues);
4693
4711
  const overallStatus = this.determineStatus(t3Results);
4694
- this.setStatus(overallStatus === "COMPLETED" ? "COMPLETED" : "FAILED");
4695
- this.sendStatusUpdate({ progressPct: 100, currentAction: "Section complete", status: "IN_PROGRESS" });
4712
+ const isOk = overallStatus === "COMPLETED" || overallStatus === "PARTIAL";
4713
+ this.setStatus(isOk ? "COMPLETED" : "FAILED", summary);
4714
+ this.sendStatusUpdate({ progressPct: 100, currentAction: "Section complete", status: "IN_PROGRESS", output: summary });
4696
4715
  const result = {
4697
4716
  sectionId: assignment.sectionId,
4698
4717
  sectionTitle: assignment.sectionTitle,
@@ -4705,7 +4724,7 @@ var T2Manager = class extends BaseTier {
4705
4724
  return result;
4706
4725
  } catch (err) {
4707
4726
  const errMsg = err instanceof Error ? err.message : String(err);
4708
- this.setStatus("FAILED");
4727
+ this.setStatus("FAILED", errMsg);
4709
4728
  const failedResult = {
4710
4729
  sectionId: assignment.sectionId,
4711
4730
  sectionTitle: assignment.sectionTitle,
@@ -5270,8 +5289,8 @@ Create a CORRECTION PLAN that contains only the new sections needed to fix the i
5270
5289
  status: "IN_PROGRESS"
5271
5290
  });
5272
5291
  const output = await this.compileFinalOutput(userPrompt, plan, allT2Results);
5273
- this.setStatus("COMPLETED");
5274
- this.sendStatusUpdate({ progressPct: 100, currentAction: "Task complete", status: "IN_PROGRESS" });
5292
+ this.setStatus("COMPLETED", output);
5293
+ this.sendStatusUpdate({ progressPct: 100, currentAction: "Task complete", status: "IN_PROGRESS", output });
5275
5294
  return { output, t2Results: allT2Results, taskId: this.taskId, complexity: plan.complexity };
5276
5295
  }
5277
5296
  getEscalations() {
@@ -8228,35 +8247,69 @@ function AgentTree({ root, theme }) {
8228
8247
  }
8229
8248
  function T2Row({ node, theme, isLast }) {
8230
8249
  const connector = isLast ? "\u2514\u2500 " : "\u251C\u2500 ";
8231
- const t3Active = countByRoleAndStatus(node, "T3", "ACTIVE");
8232
- const t3Total = countByRole(node, "T3");
8233
- const workerSuffix = t3Total > 0 ? ` T3\xD7${t3Total}` : "";
8250
+ const t3Nodes = (node.children ?? []).filter((c) => c.role === "T3");
8251
+ const t3ActiveCount = t3Nodes.filter((c) => c.status === "ACTIVE").length;
8234
8252
  const label = stripRolePrefix(node.label, node.role);
8235
8253
  const action = node.currentAction ? ` ${node.currentAction.slice(0, 38)}` : "";
8254
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
8255
+ /* @__PURE__ */ jsxs(Box, { children: [
8256
+ /* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
8257
+ " ",
8258
+ connector
8259
+ ] }),
8260
+ /* @__PURE__ */ jsx(Text, { color: theme.colors.t2Color, bold: true, children: "[T2]" }),
8261
+ /* @__PURE__ */ jsxs(Text, { color: theme.colors.foreground, children: [
8262
+ " ",
8263
+ label
8264
+ ] }),
8265
+ node.status === "ACTIVE" && /* @__PURE__ */ jsxs(Fragment, { children: [
8266
+ action ? /* @__PURE__ */ jsx(Text, { color: theme.colors.muted, children: action }) : null,
8267
+ /* @__PURE__ */ jsx(Text, { children: " " }),
8268
+ /* @__PURE__ */ jsx(Spinner, { type: "dots" }),
8269
+ t3ActiveCount > 0 ? /* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
8270
+ " (",
8271
+ t3ActiveCount,
8272
+ " running)"
8273
+ ] }) : null
8274
+ ] }),
8275
+ node.status === "COMPLETED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.success, children: " \u2714" }),
8276
+ node.status === "FAILED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.error, children: " \u2718" }),
8277
+ node.status === "ESCALATED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.warning, children: " \u25B2" })
8278
+ ] }),
8279
+ t3Nodes.map((t3, idx) => /* @__PURE__ */ jsx(
8280
+ T3Row,
8281
+ {
8282
+ node: t3,
8283
+ theme,
8284
+ isLast: idx === t3Nodes.length - 1,
8285
+ parentIsLast: isLast
8286
+ },
8287
+ t3.id
8288
+ ))
8289
+ ] });
8290
+ }
8291
+ function T3Row({ node, theme, isLast, parentIsLast }) {
8292
+ const indent = parentIsLast ? " " : " \u2502 ";
8293
+ const connector = isLast ? "\u2514\u2500 " : "\u251C\u2500 ";
8294
+ const label = stripRolePrefix(node.label, node.role);
8295
+ const action = node.currentAction ? ` ${node.currentAction.slice(0, 42)}` : "";
8236
8296
  return /* @__PURE__ */ jsxs(Box, { children: [
8237
8297
  /* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
8238
- " ",
8298
+ indent,
8239
8299
  connector
8240
8300
  ] }),
8241
- /* @__PURE__ */ jsx(Text, { color: theme.colors.t2Color, bold: true, children: "[T2]" }),
8242
- /* @__PURE__ */ jsxs(Text, { color: theme.colors.foreground, children: [
8301
+ /* @__PURE__ */ jsx(Text, { color: theme.colors.t3Color, children: "[T3]" }),
8302
+ /* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
8243
8303
  " ",
8244
8304
  label
8245
8305
  ] }),
8246
- workerSuffix ? /* @__PURE__ */ jsx(Text, { color: theme.colors.muted, children: workerSuffix }) : null,
8247
8306
  node.status === "ACTIVE" && /* @__PURE__ */ jsxs(Fragment, { children: [
8248
8307
  action ? /* @__PURE__ */ jsx(Text, { color: theme.colors.muted, children: action }) : null,
8249
8308
  /* @__PURE__ */ jsx(Text, { children: " " }),
8250
- /* @__PURE__ */ jsx(Spinner, { type: "dots" }),
8251
- t3Active > 0 ? /* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
8252
- " (",
8253
- t3Active,
8254
- " running)"
8255
- ] }) : null
8309
+ /* @__PURE__ */ jsx(Spinner, { type: "dots" })
8256
8310
  ] }),
8257
8311
  node.status === "COMPLETED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.success, children: " \u2714" }),
8258
- node.status === "FAILED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.error, children: " \u2718" }),
8259
- node.status === "ESCALATED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.warning, children: " \u25B2" })
8312
+ node.status === "FAILED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.error, children: " \u2718" })
8260
8313
  ] });
8261
8314
  }
8262
8315
  function hasActiveOrFailed(node) {
@@ -8868,7 +8921,7 @@ function Repl({ config, workspacePath, themeName, initialPrompt, identityName })
8868
8921
  treeNodesRef.current.set(event.tierId, node);
8869
8922
  const store = storeRef.current;
8870
8923
  if (store) {
8871
- const runtimeNode = { tierId: node.id, sessionId: sessionIdRef.current, parentId: node.parentId, role: node.role, label: node.label, status: node.status, currentAction: node.currentAction, progressPct: node.progressPct, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), workspacePath, isGlobal: false };
8924
+ const runtimeNode = { tierId: node.id, sessionId: sessionIdRef.current, parentId: node.parentId, role: node.role, label: node.label, status: node.status, currentAction: node.currentAction, progressPct: node.progressPct, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), workspacePath, isGlobal: false, output: event.output };
8872
8925
  store.upsertRuntimeNode(runtimeNode);
8873
8926
  globalStoreRef.current?.upsertRuntimeNode({ ...runtimeNode, isGlobal: true });
8874
8927
  }
@@ -8879,7 +8932,6 @@ function Repl({ config, workspacePath, themeName, initialPrompt, identityName })
8879
8932
  useEffect(() => {
8880
8933
  const originalWarn = console.warn;
8881
8934
  const originalLog = console.log;
8882
- process.stdout.write("\x1Bc");
8883
8935
  console.warn = (...args) => {
8884
8936
  const msg = args.join(" ");
8885
8937
  if (msg.includes("non-text parts") || msg.includes("functionCall")) return;
@@ -10989,8 +11041,8 @@ var DashboardServer = class {
10989
11041
  void (async () => {
10990
11042
  const cascade = new Cascade(this.config, this.workspacePath, this.store);
10991
11043
  cascade.on("stream:token", (e) => {
10992
- this.socket.broadcast("stream:token", { sessionId, token: e.text });
10993
- this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, token: e.text });
11044
+ this.socket.broadcast("stream:token", { sessionId, tierId: e.tierId, text: e.text });
11045
+ this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, tierId: e.tierId, text: e.text });
10994
11046
  });
10995
11047
  cascade.on("tier:status", (e) => {
10996
11048
  this.socket.broadcast("tier:status", { sessionId, ...e });
@@ -11426,6 +11478,9 @@ async function startRepl(options) {
11426
11478
  await cm.load();
11427
11479
  config = cm.getConfig();
11428
11480
  }
11481
+ if (process.stdout.isTTY) {
11482
+ process.stdout.write("\x1B[2J\x1B[H");
11483
+ }
11429
11484
  const { waitUntilExit } = render(
11430
11485
  React5.createElement(Repl, {
11431
11486
  config,