cascade-ai 0.2.11 → 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/index.cjs CHANGED
@@ -165,7 +165,7 @@ var require_keytar2 = __commonJS({
165
165
  });
166
166
 
167
167
  // src/constants.ts
168
- var CASCADE_VERSION = "0.2.11";
168
+ var CASCADE_VERSION = "0.3.0";
169
169
  var CASCADE_CONFIG_DIR = ".cascade";
170
170
  var CASCADE_MD_FILE = "CASCADE.md";
171
171
  var CASCADE_IGNORE_FILE = ".cascadeignore";
@@ -547,17 +547,38 @@ var AnthropicProvider = class extends BaseProvider {
547
547
  messages,
548
548
  tools: tools?.length ? tools : void 0
549
549
  });
550
+ let isThinking = false;
550
551
  for await (const event of stream) {
551
- if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
552
- const text = event.delta.text;
553
- fullContent += text;
554
- onChunk({ text, finishReason: null });
552
+ if (event.type === "content_block_delta") {
553
+ if (event.delta.type === "thinking_delta") {
554
+ if (!isThinking) {
555
+ isThinking = true;
556
+ fullContent += "<think>\n";
557
+ onChunk({ text: "<think>\n", finishReason: null });
558
+ }
559
+ const text = event.delta.thinking;
560
+ fullContent += text;
561
+ onChunk({ text, finishReason: null });
562
+ } else if (event.delta.type === "text_delta") {
563
+ if (isThinking) {
564
+ isThinking = false;
565
+ fullContent += "\n</think>\n\n";
566
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
567
+ }
568
+ const text = event.delta.text;
569
+ fullContent += text;
570
+ onChunk({ text, finishReason: null });
571
+ }
555
572
  } else if (event.type === "message_delta" && event.usage) {
556
573
  outputTokens = event.usage.output_tokens;
557
574
  } else if (event.type === "message_start" && event.message.usage) {
558
575
  inputTokens = event.message.usage.input_tokens;
559
576
  }
560
577
  }
578
+ if (isThinking) {
579
+ fullContent += "\n</think>\n\n";
580
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
581
+ }
561
582
  const finalMessage = await stream.finalMessage();
562
583
  const toolCalls = finalMessage.content.filter((b) => b.type === "tool_use").map((b) => ({
563
584
  id: b.id,
@@ -728,9 +749,25 @@ var OpenAIProvider = class extends BaseProvider {
728
749
  }
729
750
  }
730
751
  const toolCallsMap = {};
752
+ let isThinking = false;
731
753
  for await (const chunk of stream) {
732
754
  const delta = chunk.choices[0]?.delta;
755
+ const reasoningContent = delta?.reasoning_content;
756
+ if (reasoningContent) {
757
+ if (!isThinking) {
758
+ isThinking = true;
759
+ fullContent += "<think>\n";
760
+ onChunk({ text: "<think>\n", finishReason: null });
761
+ }
762
+ fullContent += reasoningContent;
763
+ onChunk({ text: reasoningContent, finishReason: null });
764
+ }
733
765
  if (delta?.content) {
766
+ if (isThinking) {
767
+ isThinking = false;
768
+ fullContent += "\n</think>\n\n";
769
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
770
+ }
734
771
  fullContent += delta.content;
735
772
  onChunk({ text: delta.content, finishReason: null });
736
773
  }
@@ -753,6 +790,10 @@ var OpenAIProvider = class extends BaseProvider {
753
790
  outputTokens = chunk.usage.completion_tokens;
754
791
  }
755
792
  }
793
+ if (isThinking) {
794
+ fullContent += "\n</think>\n\n";
795
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
796
+ }
756
797
  const toolCalls = Object.values(toolCallsMap).map((tc) => {
757
798
  let input = {};
758
799
  try {
@@ -1995,7 +2036,7 @@ var BaseTier = class extends EventEmitter__default.default {
1995
2036
  getStatus() {
1996
2037
  return this.status;
1997
2038
  }
1998
- setStatus(status) {
2039
+ setStatus(status, output) {
1999
2040
  this.status = status;
2000
2041
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2001
2042
  const event = {
@@ -2004,7 +2045,8 @@ var BaseTier = class extends EventEmitter__default.default {
2004
2045
  parentId: this.parentId,
2005
2046
  label: this.label,
2006
2047
  status,
2007
- timestamp
2048
+ timestamp,
2049
+ output
2008
2050
  };
2009
2051
  this.emit("status", event);
2010
2052
  this.emit("tier:status", event);
@@ -2030,7 +2072,8 @@ var BaseTier = class extends EventEmitter__default.default {
2030
2072
  status: this.status,
2031
2073
  currentAction: update.currentAction,
2032
2074
  progressPct: update.progressPct,
2033
- timestamp
2075
+ timestamp,
2076
+ output: update.output
2034
2077
  });
2035
2078
  }
2036
2079
  buildMessage(type, to, payload) {
@@ -2410,16 +2453,17 @@ Now execute your subtask using this context where relevant.`
2410
2453
  return this.buildResult("ESCALATED", output, { checksRun, passed, failed }, issues, correctionAttempts);
2411
2454
  }
2412
2455
  }
2413
- this.setStatus("COMPLETED");
2414
- this.sendStatusUpdate({ progressPct: 100, currentAction: "Subtask complete", status: "IN_PROGRESS" });
2456
+ this.setStatus("COMPLETED", output);
2457
+ this.sendStatusUpdate({ progressPct: 100, currentAction: "Subtask complete", status: "IN_PROGRESS", output });
2415
2458
  this.peerBus?.publish(this.id, assignment.subtaskId, output, "COMPLETED");
2416
2459
  return this.buildResult("COMPLETED", output, { checksRun, passed, failed }, issues, correctionAttempts);
2417
2460
  } catch (err) {
2418
2461
  const errMsg = err instanceof Error ? err.message : String(err);
2419
2462
  issues.push(`Execution error: ${errMsg}`);
2420
- this.setStatus("FAILED");
2421
- this.peerBus?.publish(this.id, assignment.subtaskId, errMsg, "FAILED");
2422
- return this.buildResult("ESCALATED", output || errMsg, { checksRun, passed, failed }, issues, correctionAttempts);
2463
+ const finalOutput = output || errMsg;
2464
+ this.setStatus("FAILED", finalOutput);
2465
+ this.peerBus?.publish(this.id, assignment.subtaskId, finalOutput, "FAILED");
2466
+ return this.buildResult("ESCALATED", finalOutput, { checksRun, passed, failed }, issues, correctionAttempts);
2423
2467
  }
2424
2468
  }
2425
2469
  sendToPeer(toId, content) {
@@ -3102,8 +3146,9 @@ var T2Manager = class extends BaseTier {
3102
3146
  const summary = await this.aggregateResults(assignment, t3Results);
3103
3147
  const issues = t3Results.filter((r) => r.status !== "COMPLETED").flatMap((r) => r.issues);
3104
3148
  const overallStatus = this.determineStatus(t3Results);
3105
- this.setStatus(overallStatus === "COMPLETED" ? "COMPLETED" : "FAILED");
3106
- this.sendStatusUpdate({ progressPct: 100, currentAction: "Section complete", status: "IN_PROGRESS" });
3149
+ const isOk = overallStatus === "COMPLETED" || overallStatus === "PARTIAL";
3150
+ this.setStatus(isOk ? "COMPLETED" : "FAILED", summary);
3151
+ this.sendStatusUpdate({ progressPct: 100, currentAction: "Section complete", status: "IN_PROGRESS", output: summary });
3107
3152
  const result = {
3108
3153
  sectionId: assignment.sectionId,
3109
3154
  sectionTitle: assignment.sectionTitle,
@@ -3116,7 +3161,7 @@ var T2Manager = class extends BaseTier {
3116
3161
  return result;
3117
3162
  } catch (err) {
3118
3163
  const errMsg = err instanceof Error ? err.message : String(err);
3119
- this.setStatus("FAILED");
3164
+ this.setStatus("FAILED", errMsg);
3120
3165
  const failedResult = {
3121
3166
  sectionId: assignment.sectionId,
3122
3167
  sectionTitle: assignment.sectionTitle,
@@ -3678,8 +3723,8 @@ Create a CORRECTION PLAN that contains only the new sections needed to fix the i
3678
3723
  status: "IN_PROGRESS"
3679
3724
  });
3680
3725
  const output = await this.compileFinalOutput(userPrompt, plan, allT2Results);
3681
- this.setStatus("COMPLETED");
3682
- this.sendStatusUpdate({ progressPct: 100, currentAction: "Task complete", status: "IN_PROGRESS" });
3726
+ this.setStatus("COMPLETED", output);
3727
+ this.sendStatusUpdate({ progressPct: 100, currentAction: "Task complete", status: "IN_PROGRESS", output });
3683
3728
  return { output, t2Results: allT2Results, taskId: this.taskId, complexity: plan.complexity };
3684
3729
  }
3685
3730
  getEscalations() {
@@ -6817,8 +6862,8 @@ Original error: ${err.message}`
6817
6862
  upsertRuntimeNode(node) {
6818
6863
  this.enqueueWrite(() => {
6819
6864
  this.db.prepare(`
6820
- INSERT INTO runtime_nodes (tier_id, session_id, parent_id, role, label, status, current_action, progress_pct, updated_at, workspace_path, is_global)
6821
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6865
+ INSERT INTO runtime_nodes (tier_id, session_id, parent_id, role, label, status, current_action, progress_pct, updated_at, workspace_path, is_global, output)
6866
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6822
6867
  ON CONFLICT(tier_id) DO UPDATE SET
6823
6868
  session_id = excluded.session_id,
6824
6869
  parent_id = excluded.parent_id,
@@ -6829,7 +6874,8 @@ Original error: ${err.message}`
6829
6874
  progress_pct = excluded.progress_pct,
6830
6875
  updated_at = excluded.updated_at,
6831
6876
  workspace_path = excluded.workspace_path,
6832
- is_global = excluded.is_global
6877
+ is_global = excluded.is_global,
6878
+ output = excluded.output
6833
6879
  `).run(
6834
6880
  node.tierId,
6835
6881
  node.sessionId,
@@ -6841,7 +6887,8 @@ Original error: ${err.message}`
6841
6887
  node.progressPct ?? null,
6842
6888
  node.updatedAt,
6843
6889
  node.workspacePath ?? null,
6844
- node.isGlobal ? 1 : 0
6890
+ node.isGlobal ? 1 : 0,
6891
+ node.output ?? null
6845
6892
  );
6846
6893
  });
6847
6894
  }
@@ -6862,14 +6909,15 @@ Original error: ${err.message}`
6862
6909
  progressPct: row.progress_pct ?? void 0,
6863
6910
  updatedAt: row.updated_at,
6864
6911
  workspacePath: row.workspace_path ?? void 0,
6865
- isGlobal: row.is_global === 1
6912
+ isGlobal: row.is_global === 1,
6913
+ output: row.output ?? void 0
6866
6914
  }));
6867
6915
  }
6868
6916
  addRuntimeNodeLog(log) {
6869
6917
  this.enqueueWrite(() => {
6870
6918
  this.db.prepare(`
6871
- INSERT INTO runtime_node_logs (id, session_id, tier_id, role, label, status, current_action, progress_pct, timestamp, workspace_path, is_global)
6872
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6919
+ INSERT INTO runtime_node_logs (id, session_id, tier_id, role, label, status, current_action, progress_pct, timestamp, workspace_path, is_global, output)
6920
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6873
6921
  `).run(
6874
6922
  log.id,
6875
6923
  log.sessionId,
@@ -6881,7 +6929,8 @@ Original error: ${err.message}`
6881
6929
  log.progressPct ?? null,
6882
6930
  log.timestamp,
6883
6931
  log.workspacePath ?? null,
6884
- log.isGlobal ? 1 : 0
6932
+ log.isGlobal ? 1 : 0,
6933
+ log.output ?? null
6885
6934
  );
6886
6935
  this.db.prepare(`
6887
6936
  DELETE FROM runtime_node_logs
@@ -6924,7 +6973,8 @@ Original error: ${err.message}`
6924
6973
  progressPct: row.progress_pct ?? void 0,
6925
6974
  timestamp: row.timestamp,
6926
6975
  workspacePath: row.workspace_path ?? void 0,
6927
- isGlobal: row.is_global === 1
6976
+ isGlobal: row.is_global === 1,
6977
+ output: row.output ?? void 0
6928
6978
  }));
6929
6979
  }
6930
6980
  // ── Messages ──────────────────────────────────
@@ -7251,7 +7301,8 @@ Original error: ${err.message}`
7251
7301
  progress_pct INTEGER,
7252
7302
  updated_at TEXT NOT NULL,
7253
7303
  workspace_path TEXT,
7254
- is_global INTEGER NOT NULL DEFAULT 0
7304
+ is_global INTEGER NOT NULL DEFAULT 0,
7305
+ output TEXT
7255
7306
  );
7256
7307
 
7257
7308
  CREATE INDEX IF NOT EXISTS idx_runtime_nodes_session ON runtime_nodes(session_id);
@@ -7268,7 +7319,8 @@ Original error: ${err.message}`
7268
7319
  progress_pct INTEGER,
7269
7320
  timestamp TEXT NOT NULL,
7270
7321
  workspace_path TEXT,
7271
- is_global INTEGER NOT NULL DEFAULT 0
7322
+ is_global INTEGER NOT NULL DEFAULT 0,
7323
+ output TEXT
7272
7324
  );
7273
7325
 
7274
7326
  CREATE TABLE IF NOT EXISTS model_cache (
@@ -7297,6 +7349,14 @@ Original error: ${err.message}`
7297
7349
 
7298
7350
  CREATE INDEX IF NOT EXISTS idx_file_snapshots_session ON file_snapshots(session_id);
7299
7351
  `);
7352
+ try {
7353
+ this.db.exec("ALTER TABLE runtime_nodes ADD COLUMN output TEXT");
7354
+ } catch {
7355
+ }
7356
+ try {
7357
+ this.db.exec("ALTER TABLE runtime_node_logs ADD COLUMN output TEXT");
7358
+ } catch {
7359
+ }
7300
7360
  }
7301
7361
  // ── Deserializers ─────────────────────────────
7302
7362
  deserializeSession(row, messages) {
@@ -7429,6 +7489,7 @@ var ConfigManager = class {
7429
7489
  }
7430
7490
  }
7431
7491
  async injectEnvKeys() {
7492
+ const isFirstRun = this.config.providers.length === 0;
7432
7493
  const envProviders = [
7433
7494
  { env: "ANTHROPIC_API_KEY", type: "anthropic" },
7434
7495
  { env: "OPENAI_API_KEY", type: "openai" },
@@ -7439,10 +7500,13 @@ var ConfigManager = class {
7439
7500
  const key = process.env[env];
7440
7501
  if (!key) continue;
7441
7502
  const existing = this.config.providers.find((p) => p.type === type);
7442
- if (!existing) this.config.providers.push({ type, apiKey: key });
7443
- else if (!existing.apiKey) existing.apiKey = key;
7503
+ if (!existing && isFirstRun) {
7504
+ this.config.providers.push({ type, apiKey: key });
7505
+ } else if (existing && !existing.apiKey) {
7506
+ existing.apiKey = key;
7507
+ }
7444
7508
  }
7445
- if (!this.config.providers.find((p) => p.type === "ollama")) {
7509
+ if (isFirstRun && !this.config.providers.find((p) => p.type === "ollama")) {
7446
7510
  this.config.providers.push({ type: "ollama" });
7447
7511
  }
7448
7512
  }
@@ -8066,8 +8130,8 @@ var DashboardServer = class {
8066
8130
  void (async () => {
8067
8131
  const cascade = new Cascade(this.config, this.workspacePath, this.store);
8068
8132
  cascade.on("stream:token", (e) => {
8069
- this.socket.broadcast("stream:token", { sessionId, token: e.text });
8070
- this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, token: e.text });
8133
+ this.socket.broadcast("stream:token", { sessionId, tierId: e.tierId, text: e.text });
8134
+ this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, tierId: e.tierId, text: e.text });
8071
8135
  });
8072
8136
  cascade.on("tier:status", (e) => {
8073
8137
  this.socket.broadcast("tier:status", { sessionId, ...e });