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.d.cts CHANGED
@@ -175,6 +175,7 @@ interface StatusUpdate {
175
175
  progressPct: number;
176
176
  currentAction: string;
177
177
  status: 'IN_PROGRESS' | 'BLOCKED' | 'ESCALATING';
178
+ output?: string;
178
179
  }
179
180
  interface T2Result {
180
181
  sectionId: string;
@@ -274,6 +275,7 @@ interface RuntimeNode {
274
275
  updatedAt: string;
275
276
  workspacePath?: string;
276
277
  isGlobal?: boolean;
278
+ output?: string;
277
279
  }
278
280
  interface RuntimeNodeLog {
279
281
  id: string;
@@ -287,6 +289,7 @@ interface RuntimeNodeLog {
287
289
  timestamp: string;
288
290
  workspacePath?: string;
289
291
  isGlobal?: boolean;
292
+ output?: string;
290
293
  }
291
294
  type RuntimeScope = 'workspace' | 'global';
292
295
  interface RuntimeSnapshotPayload {
@@ -919,7 +922,7 @@ declare abstract class BaseTier extends EventEmitter {
919
922
  protected signal?: AbortSignal;
920
923
  constructor(role: TierRole, id?: string, parentId?: string);
921
924
  getStatus(): TierStatus;
922
- protected setStatus(status: TierStatus): void;
925
+ protected setStatus(status: TierStatus, output?: string): void;
923
926
  protected setLabel(label: string): void;
924
927
  setSystemPromptOverride(prompt: string): void;
925
928
  setHierarchyContext(context: string): void;
@@ -1581,7 +1584,7 @@ declare class Telemetry {
1581
1584
  shutdown(): Promise<void>;
1582
1585
  }
1583
1586
 
1584
- declare const CASCADE_VERSION = "0.2.11";
1587
+ declare const CASCADE_VERSION = "0.3.0";
1585
1588
  declare const CASCADE_CONFIG_DIR = ".cascade";
1586
1589
  declare const CASCADE_MD_FILE = "CASCADE.md";
1587
1590
  declare const CASCADE_IGNORE_FILE = ".cascadeignore";
package/dist/index.d.ts CHANGED
@@ -175,6 +175,7 @@ interface StatusUpdate {
175
175
  progressPct: number;
176
176
  currentAction: string;
177
177
  status: 'IN_PROGRESS' | 'BLOCKED' | 'ESCALATING';
178
+ output?: string;
178
179
  }
179
180
  interface T2Result {
180
181
  sectionId: string;
@@ -274,6 +275,7 @@ interface RuntimeNode {
274
275
  updatedAt: string;
275
276
  workspacePath?: string;
276
277
  isGlobal?: boolean;
278
+ output?: string;
277
279
  }
278
280
  interface RuntimeNodeLog {
279
281
  id: string;
@@ -287,6 +289,7 @@ interface RuntimeNodeLog {
287
289
  timestamp: string;
288
290
  workspacePath?: string;
289
291
  isGlobal?: boolean;
292
+ output?: string;
290
293
  }
291
294
  type RuntimeScope = 'workspace' | 'global';
292
295
  interface RuntimeSnapshotPayload {
@@ -919,7 +922,7 @@ declare abstract class BaseTier extends EventEmitter {
919
922
  protected signal?: AbortSignal;
920
923
  constructor(role: TierRole, id?: string, parentId?: string);
921
924
  getStatus(): TierStatus;
922
- protected setStatus(status: TierStatus): void;
925
+ protected setStatus(status: TierStatus, output?: string): void;
923
926
  protected setLabel(label: string): void;
924
927
  setSystemPromptOverride(prompt: string): void;
925
928
  setHierarchyContext(context: string): void;
@@ -1581,7 +1584,7 @@ declare class Telemetry {
1581
1584
  shutdown(): Promise<void>;
1582
1585
  }
1583
1586
 
1584
- declare const CASCADE_VERSION = "0.2.11";
1587
+ declare const CASCADE_VERSION = "0.3.0";
1585
1588
  declare const CASCADE_CONFIG_DIR = ".cascade";
1586
1589
  declare const CASCADE_MD_FILE = "CASCADE.md";
1587
1590
  declare const CASCADE_IGNORE_FILE = ".cascadeignore";
package/dist/index.js CHANGED
@@ -124,7 +124,7 @@ var require_keytar2 = __commonJS({
124
124
  });
125
125
 
126
126
  // src/constants.ts
127
- var CASCADE_VERSION = "0.2.11";
127
+ var CASCADE_VERSION = "0.3.0";
128
128
  var CASCADE_CONFIG_DIR = ".cascade";
129
129
  var CASCADE_MD_FILE = "CASCADE.md";
130
130
  var CASCADE_IGNORE_FILE = ".cascadeignore";
@@ -506,17 +506,38 @@ var AnthropicProvider = class extends BaseProvider {
506
506
  messages,
507
507
  tools: tools?.length ? tools : void 0
508
508
  });
509
+ let isThinking = false;
509
510
  for await (const event of stream) {
510
- if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
511
- const text = event.delta.text;
512
- fullContent += text;
513
- onChunk({ text, finishReason: null });
511
+ if (event.type === "content_block_delta") {
512
+ if (event.delta.type === "thinking_delta") {
513
+ if (!isThinking) {
514
+ isThinking = true;
515
+ fullContent += "<think>\n";
516
+ onChunk({ text: "<think>\n", finishReason: null });
517
+ }
518
+ const text = event.delta.thinking;
519
+ fullContent += text;
520
+ onChunk({ text, finishReason: null });
521
+ } else if (event.delta.type === "text_delta") {
522
+ if (isThinking) {
523
+ isThinking = false;
524
+ fullContent += "\n</think>\n\n";
525
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
526
+ }
527
+ const text = event.delta.text;
528
+ fullContent += text;
529
+ onChunk({ text, finishReason: null });
530
+ }
514
531
  } else if (event.type === "message_delta" && event.usage) {
515
532
  outputTokens = event.usage.output_tokens;
516
533
  } else if (event.type === "message_start" && event.message.usage) {
517
534
  inputTokens = event.message.usage.input_tokens;
518
535
  }
519
536
  }
537
+ if (isThinking) {
538
+ fullContent += "\n</think>\n\n";
539
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
540
+ }
520
541
  const finalMessage = await stream.finalMessage();
521
542
  const toolCalls = finalMessage.content.filter((b) => b.type === "tool_use").map((b) => ({
522
543
  id: b.id,
@@ -687,9 +708,25 @@ var OpenAIProvider = class extends BaseProvider {
687
708
  }
688
709
  }
689
710
  const toolCallsMap = {};
711
+ let isThinking = false;
690
712
  for await (const chunk of stream) {
691
713
  const delta = chunk.choices[0]?.delta;
714
+ const reasoningContent = delta?.reasoning_content;
715
+ if (reasoningContent) {
716
+ if (!isThinking) {
717
+ isThinking = true;
718
+ fullContent += "<think>\n";
719
+ onChunk({ text: "<think>\n", finishReason: null });
720
+ }
721
+ fullContent += reasoningContent;
722
+ onChunk({ text: reasoningContent, finishReason: null });
723
+ }
692
724
  if (delta?.content) {
725
+ if (isThinking) {
726
+ isThinking = false;
727
+ fullContent += "\n</think>\n\n";
728
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
729
+ }
693
730
  fullContent += delta.content;
694
731
  onChunk({ text: delta.content, finishReason: null });
695
732
  }
@@ -712,6 +749,10 @@ var OpenAIProvider = class extends BaseProvider {
712
749
  outputTokens = chunk.usage.completion_tokens;
713
750
  }
714
751
  }
752
+ if (isThinking) {
753
+ fullContent += "\n</think>\n\n";
754
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
755
+ }
715
756
  const toolCalls = Object.values(toolCallsMap).map((tc) => {
716
757
  let input = {};
717
758
  try {
@@ -1954,7 +1995,7 @@ var BaseTier = class extends EventEmitter {
1954
1995
  getStatus() {
1955
1996
  return this.status;
1956
1997
  }
1957
- setStatus(status) {
1998
+ setStatus(status, output) {
1958
1999
  this.status = status;
1959
2000
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
1960
2001
  const event = {
@@ -1963,7 +2004,8 @@ var BaseTier = class extends EventEmitter {
1963
2004
  parentId: this.parentId,
1964
2005
  label: this.label,
1965
2006
  status,
1966
- timestamp
2007
+ timestamp,
2008
+ output
1967
2009
  };
1968
2010
  this.emit("status", event);
1969
2011
  this.emit("tier:status", event);
@@ -1989,7 +2031,8 @@ var BaseTier = class extends EventEmitter {
1989
2031
  status: this.status,
1990
2032
  currentAction: update.currentAction,
1991
2033
  progressPct: update.progressPct,
1992
- timestamp
2034
+ timestamp,
2035
+ output: update.output
1993
2036
  });
1994
2037
  }
1995
2038
  buildMessage(type, to, payload) {
@@ -2369,16 +2412,17 @@ Now execute your subtask using this context where relevant.`
2369
2412
  return this.buildResult("ESCALATED", output, { checksRun, passed, failed }, issues, correctionAttempts);
2370
2413
  }
2371
2414
  }
2372
- this.setStatus("COMPLETED");
2373
- this.sendStatusUpdate({ progressPct: 100, currentAction: "Subtask complete", status: "IN_PROGRESS" });
2415
+ this.setStatus("COMPLETED", output);
2416
+ this.sendStatusUpdate({ progressPct: 100, currentAction: "Subtask complete", status: "IN_PROGRESS", output });
2374
2417
  this.peerBus?.publish(this.id, assignment.subtaskId, output, "COMPLETED");
2375
2418
  return this.buildResult("COMPLETED", output, { checksRun, passed, failed }, issues, correctionAttempts);
2376
2419
  } catch (err) {
2377
2420
  const errMsg = err instanceof Error ? err.message : String(err);
2378
2421
  issues.push(`Execution error: ${errMsg}`);
2379
- this.setStatus("FAILED");
2380
- this.peerBus?.publish(this.id, assignment.subtaskId, errMsg, "FAILED");
2381
- return this.buildResult("ESCALATED", output || errMsg, { checksRun, passed, failed }, issues, correctionAttempts);
2422
+ const finalOutput = output || errMsg;
2423
+ this.setStatus("FAILED", finalOutput);
2424
+ this.peerBus?.publish(this.id, assignment.subtaskId, finalOutput, "FAILED");
2425
+ return this.buildResult("ESCALATED", finalOutput, { checksRun, passed, failed }, issues, correctionAttempts);
2382
2426
  }
2383
2427
  }
2384
2428
  sendToPeer(toId, content) {
@@ -3061,8 +3105,9 @@ var T2Manager = class extends BaseTier {
3061
3105
  const summary = await this.aggregateResults(assignment, t3Results);
3062
3106
  const issues = t3Results.filter((r) => r.status !== "COMPLETED").flatMap((r) => r.issues);
3063
3107
  const overallStatus = this.determineStatus(t3Results);
3064
- this.setStatus(overallStatus === "COMPLETED" ? "COMPLETED" : "FAILED");
3065
- this.sendStatusUpdate({ progressPct: 100, currentAction: "Section complete", status: "IN_PROGRESS" });
3108
+ const isOk = overallStatus === "COMPLETED" || overallStatus === "PARTIAL";
3109
+ this.setStatus(isOk ? "COMPLETED" : "FAILED", summary);
3110
+ this.sendStatusUpdate({ progressPct: 100, currentAction: "Section complete", status: "IN_PROGRESS", output: summary });
3066
3111
  const result = {
3067
3112
  sectionId: assignment.sectionId,
3068
3113
  sectionTitle: assignment.sectionTitle,
@@ -3075,7 +3120,7 @@ var T2Manager = class extends BaseTier {
3075
3120
  return result;
3076
3121
  } catch (err) {
3077
3122
  const errMsg = err instanceof Error ? err.message : String(err);
3078
- this.setStatus("FAILED");
3123
+ this.setStatus("FAILED", errMsg);
3079
3124
  const failedResult = {
3080
3125
  sectionId: assignment.sectionId,
3081
3126
  sectionTitle: assignment.sectionTitle,
@@ -3637,8 +3682,8 @@ Create a CORRECTION PLAN that contains only the new sections needed to fix the i
3637
3682
  status: "IN_PROGRESS"
3638
3683
  });
3639
3684
  const output = await this.compileFinalOutput(userPrompt, plan, allT2Results);
3640
- this.setStatus("COMPLETED");
3641
- this.sendStatusUpdate({ progressPct: 100, currentAction: "Task complete", status: "IN_PROGRESS" });
3685
+ this.setStatus("COMPLETED", output);
3686
+ this.sendStatusUpdate({ progressPct: 100, currentAction: "Task complete", status: "IN_PROGRESS", output });
3642
3687
  return { output, t2Results: allT2Results, taskId: this.taskId, complexity: plan.complexity };
3643
3688
  }
3644
3689
  getEscalations() {
@@ -6776,8 +6821,8 @@ Original error: ${err.message}`
6776
6821
  upsertRuntimeNode(node) {
6777
6822
  this.enqueueWrite(() => {
6778
6823
  this.db.prepare(`
6779
- INSERT INTO runtime_nodes (tier_id, session_id, parent_id, role, label, status, current_action, progress_pct, updated_at, workspace_path, is_global)
6780
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6824
+ INSERT INTO runtime_nodes (tier_id, session_id, parent_id, role, label, status, current_action, progress_pct, updated_at, workspace_path, is_global, output)
6825
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6781
6826
  ON CONFLICT(tier_id) DO UPDATE SET
6782
6827
  session_id = excluded.session_id,
6783
6828
  parent_id = excluded.parent_id,
@@ -6788,7 +6833,8 @@ Original error: ${err.message}`
6788
6833
  progress_pct = excluded.progress_pct,
6789
6834
  updated_at = excluded.updated_at,
6790
6835
  workspace_path = excluded.workspace_path,
6791
- is_global = excluded.is_global
6836
+ is_global = excluded.is_global,
6837
+ output = excluded.output
6792
6838
  `).run(
6793
6839
  node.tierId,
6794
6840
  node.sessionId,
@@ -6800,7 +6846,8 @@ Original error: ${err.message}`
6800
6846
  node.progressPct ?? null,
6801
6847
  node.updatedAt,
6802
6848
  node.workspacePath ?? null,
6803
- node.isGlobal ? 1 : 0
6849
+ node.isGlobal ? 1 : 0,
6850
+ node.output ?? null
6804
6851
  );
6805
6852
  });
6806
6853
  }
@@ -6821,14 +6868,15 @@ Original error: ${err.message}`
6821
6868
  progressPct: row.progress_pct ?? void 0,
6822
6869
  updatedAt: row.updated_at,
6823
6870
  workspacePath: row.workspace_path ?? void 0,
6824
- isGlobal: row.is_global === 1
6871
+ isGlobal: row.is_global === 1,
6872
+ output: row.output ?? void 0
6825
6873
  }));
6826
6874
  }
6827
6875
  addRuntimeNodeLog(log) {
6828
6876
  this.enqueueWrite(() => {
6829
6877
  this.db.prepare(`
6830
- INSERT INTO runtime_node_logs (id, session_id, tier_id, role, label, status, current_action, progress_pct, timestamp, workspace_path, is_global)
6831
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6878
+ INSERT INTO runtime_node_logs (id, session_id, tier_id, role, label, status, current_action, progress_pct, timestamp, workspace_path, is_global, output)
6879
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6832
6880
  `).run(
6833
6881
  log.id,
6834
6882
  log.sessionId,
@@ -6840,7 +6888,8 @@ Original error: ${err.message}`
6840
6888
  log.progressPct ?? null,
6841
6889
  log.timestamp,
6842
6890
  log.workspacePath ?? null,
6843
- log.isGlobal ? 1 : 0
6891
+ log.isGlobal ? 1 : 0,
6892
+ log.output ?? null
6844
6893
  );
6845
6894
  this.db.prepare(`
6846
6895
  DELETE FROM runtime_node_logs
@@ -6883,7 +6932,8 @@ Original error: ${err.message}`
6883
6932
  progressPct: row.progress_pct ?? void 0,
6884
6933
  timestamp: row.timestamp,
6885
6934
  workspacePath: row.workspace_path ?? void 0,
6886
- isGlobal: row.is_global === 1
6935
+ isGlobal: row.is_global === 1,
6936
+ output: row.output ?? void 0
6887
6937
  }));
6888
6938
  }
6889
6939
  // ── Messages ──────────────────────────────────
@@ -7210,7 +7260,8 @@ Original error: ${err.message}`
7210
7260
  progress_pct INTEGER,
7211
7261
  updated_at TEXT NOT NULL,
7212
7262
  workspace_path TEXT,
7213
- is_global INTEGER NOT NULL DEFAULT 0
7263
+ is_global INTEGER NOT NULL DEFAULT 0,
7264
+ output TEXT
7214
7265
  );
7215
7266
 
7216
7267
  CREATE INDEX IF NOT EXISTS idx_runtime_nodes_session ON runtime_nodes(session_id);
@@ -7227,7 +7278,8 @@ Original error: ${err.message}`
7227
7278
  progress_pct INTEGER,
7228
7279
  timestamp TEXT NOT NULL,
7229
7280
  workspace_path TEXT,
7230
- is_global INTEGER NOT NULL DEFAULT 0
7281
+ is_global INTEGER NOT NULL DEFAULT 0,
7282
+ output TEXT
7231
7283
  );
7232
7284
 
7233
7285
  CREATE TABLE IF NOT EXISTS model_cache (
@@ -7256,6 +7308,14 @@ Original error: ${err.message}`
7256
7308
 
7257
7309
  CREATE INDEX IF NOT EXISTS idx_file_snapshots_session ON file_snapshots(session_id);
7258
7310
  `);
7311
+ try {
7312
+ this.db.exec("ALTER TABLE runtime_nodes ADD COLUMN output TEXT");
7313
+ } catch {
7314
+ }
7315
+ try {
7316
+ this.db.exec("ALTER TABLE runtime_node_logs ADD COLUMN output TEXT");
7317
+ } catch {
7318
+ }
7259
7319
  }
7260
7320
  // ── Deserializers ─────────────────────────────
7261
7321
  deserializeSession(row, messages) {
@@ -7388,6 +7448,7 @@ var ConfigManager = class {
7388
7448
  }
7389
7449
  }
7390
7450
  async injectEnvKeys() {
7451
+ const isFirstRun = this.config.providers.length === 0;
7391
7452
  const envProviders = [
7392
7453
  { env: "ANTHROPIC_API_KEY", type: "anthropic" },
7393
7454
  { env: "OPENAI_API_KEY", type: "openai" },
@@ -7398,10 +7459,13 @@ var ConfigManager = class {
7398
7459
  const key = process.env[env];
7399
7460
  if (!key) continue;
7400
7461
  const existing = this.config.providers.find((p) => p.type === type);
7401
- if (!existing) this.config.providers.push({ type, apiKey: key });
7402
- else if (!existing.apiKey) existing.apiKey = key;
7462
+ if (!existing && isFirstRun) {
7463
+ this.config.providers.push({ type, apiKey: key });
7464
+ } else if (existing && !existing.apiKey) {
7465
+ existing.apiKey = key;
7466
+ }
7403
7467
  }
7404
- if (!this.config.providers.find((p) => p.type === "ollama")) {
7468
+ if (isFirstRun && !this.config.providers.find((p) => p.type === "ollama")) {
7405
7469
  this.config.providers.push({ type: "ollama" });
7406
7470
  }
7407
7471
  }
@@ -8025,8 +8089,8 @@ var DashboardServer = class {
8025
8089
  void (async () => {
8026
8090
  const cascade = new Cascade(this.config, this.workspacePath, this.store);
8027
8091
  cascade.on("stream:token", (e) => {
8028
- this.socket.broadcast("stream:token", { sessionId, token: e.text });
8029
- this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, token: e.text });
8092
+ this.socket.broadcast("stream:token", { sessionId, tierId: e.tierId, text: e.text });
8093
+ this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, tierId: e.tierId, text: e.text });
8030
8094
  });
8031
8095
  cascade.on("tier:status", (e) => {
8032
8096
  this.socket.broadcast("tier:status", { sessionId, ...e });