cascade-ai 0.17.0 → 0.18.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.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import Database from 'better-sqlite3';
2
- import path20 from 'path';
3
- import fs19 from 'fs';
2
+ import path21 from 'path';
3
+ import fs20 from 'fs';
4
4
  import os6 from 'os';
5
5
  import crypto3, { randomUUID, timingSafeEqual } from 'crypto';
6
6
  import EventEmitter from 'events';
@@ -58,12 +58,12 @@ var init_audit_logger = __esm({
58
58
  constructor(workspacePath, debugMode = false) {
59
59
  this.workspacePath = workspacePath;
60
60
  this.debugMode = debugMode;
61
- const cascadeDir = path20.join(workspacePath, ".cascade");
62
- if (!fs19.existsSync(cascadeDir)) {
63
- fs19.mkdirSync(cascadeDir, { recursive: true });
61
+ const cascadeDir = path21.join(workspacePath, ".cascade");
62
+ if (!fs20.existsSync(cascadeDir)) {
63
+ fs20.mkdirSync(cascadeDir, { recursive: true });
64
64
  }
65
- this.keyPath = path20.join(cascadeDir, "audit_log.key");
66
- this.dbPath = path20.join(cascadeDir, "audit_log.db");
65
+ this.keyPath = path21.join(cascadeDir, "audit_log.key");
66
+ this.dbPath = path21.join(cascadeDir, "audit_log.db");
67
67
  this.initEncryptionKey();
68
68
  this.db = new Database(this.dbPath);
69
69
  this.db.pragma("journal_mode = WAL");
@@ -93,11 +93,11 @@ var init_audit_logger = __esm({
93
93
  return crypto3.createHash("sha256").update(`${prevHash}|${timestamp}|${eventType}|${tierId}|${encryptedPayload}`).digest("hex");
94
94
  }
95
95
  initEncryptionKey() {
96
- if (fs19.existsSync(this.keyPath)) {
97
- this.encryptionKey = fs19.readFileSync(this.keyPath);
96
+ if (fs20.existsSync(this.keyPath)) {
97
+ this.encryptionKey = fs20.readFileSync(this.keyPath);
98
98
  } else {
99
99
  this.encryptionKey = crypto3.randomBytes(32);
100
- fs19.writeFileSync(this.keyPath, this.encryptionKey);
100
+ fs20.writeFileSync(this.keyPath, this.encryptionKey);
101
101
  }
102
102
  }
103
103
  encrypt(text) {
@@ -175,9 +175,9 @@ var init_audit_logger = __esm({
175
175
  dumpDebugIfNeeded() {
176
176
  if (!this.debugMode) return;
177
177
  try {
178
- const dumpPath = path20.join(os6.tmpdir(), "cascade_audit_logs_debug.json");
178
+ const dumpPath = path21.join(os6.tmpdir(), "cascade_audit_logs_debug.json");
179
179
  const entries = this.getAllLogs();
180
- fs19.writeFileSync(dumpPath, JSON.stringify(entries, null, 2), "utf-8");
180
+ fs20.writeFileSync(dumpPath, JSON.stringify(entries, null, 2), "utf-8");
181
181
  } catch (err) {
182
182
  console.error("Failed to dump debug audit logs", err);
183
183
  }
@@ -190,7 +190,7 @@ var init_audit_logger = __esm({
190
190
  });
191
191
 
192
192
  // src/constants.ts
193
- var CASCADE_VERSION = "0.17.0";
193
+ var CASCADE_VERSION = "0.18.0";
194
194
  var CASCADE_CONFIG_DIR = ".cascade";
195
195
  var CASCADE_MD_FILE = "CASCADE.md";
196
196
  var CASCADE_IGNORE_FILE = ".cascadeignore";
@@ -202,6 +202,7 @@ var CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
202
202
  var GLOBAL_CONFIG_DIR = ".cascade-ai";
203
203
  var GLOBAL_DB_FILE = "memory.db";
204
204
  var GLOBAL_KEYSTORE_FILE = "keystore.enc";
205
+ var GLOBAL_CREDENTIALS_FILE = "credentials.json";
205
206
  var GLOBAL_RUNTIME_DB_FILE = "runtime.db";
206
207
  var DEFAULT_DASHBOARD_PORT = 4891;
207
208
  var DEFAULT_API_PORT = 4892;
@@ -2164,7 +2165,7 @@ function computeDelegationSavings(stats, t1Model) {
2164
2165
  var DEFAULT_SNAPSHOT_URL = "https://raw.githubusercontent.com/Varun-SV/Cascade-AI/main/src/core/router/benchmark-data.json";
2165
2166
  var OPENROUTER_MODELS_URL = "https://openrouter.ai/api/v1/models";
2166
2167
  var FETCH_TIMEOUT_MS = 8e3;
2167
- var DEFAULT_CACHE_FILE = path20.join(os6.homedir(), GLOBAL_CONFIG_DIR, "benchmarks-cache.json");
2168
+ var DEFAULT_CACHE_FILE = path21.join(os6.homedir(), GLOBAL_CONFIG_DIR, "benchmarks-cache.json");
2168
2169
  function normalizeModelId(id) {
2169
2170
  let s = id.toLowerCase();
2170
2171
  const slash = s.lastIndexOf("/");
@@ -2309,7 +2310,7 @@ var LiveDataProvider = class {
2309
2310
  }
2310
2311
  async saveCache() {
2311
2312
  try {
2312
- await fs4.mkdir(path20.dirname(this.opts.cacheFile), { recursive: true });
2313
+ await fs4.mkdir(path21.dirname(this.opts.cacheFile), { recursive: true });
2313
2314
  const cache = {
2314
2315
  fetchedAt: this.fetchedAt,
2315
2316
  snapshot: this.snapshot ?? void 0,
@@ -4212,8 +4213,8 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : "") + textToolSuffix,
4212
4213
  tierId: this.id,
4213
4214
  sessionId: this.taskId,
4214
4215
  requireApproval: false,
4215
- saveSnapshot: async (path21, content) => {
4216
- this.store?.addFileSnapshot(this.taskId, path21, content);
4216
+ saveSnapshot: async (path22, content) => {
4217
+ this.store?.addFileSnapshot(this.taskId, path22, content);
4217
4218
  },
4218
4219
  sendPeerSync: (to, syncType, content) => {
4219
4220
  this.peerBus?.send(this.id, to, syncType, this.assignment?.subtaskId ?? "", content);
@@ -4383,7 +4384,7 @@ ${assignment.expectedOutput}`;
4383
4384
  const { promisify: promisify4 } = await import('util');
4384
4385
  const execAsync2 = promisify4(exec2);
4385
4386
  for (const artifactPath of artifactPaths) {
4386
- const absolutePath = path20.resolve(process.cwd(), artifactPath);
4387
+ const absolutePath = path21.resolve(process.cwd(), artifactPath);
4387
4388
  try {
4388
4389
  const stat = await fs4.stat(absolutePath);
4389
4390
  if (!stat.isFile()) {
@@ -4404,7 +4405,7 @@ ${assignment.expectedOutput}`;
4404
4405
  issues.push(`PDF artifact looks too small to be valid: ${artifactPath}`);
4405
4406
  continue;
4406
4407
  }
4407
- const ext = path20.extname(absolutePath).toLowerCase();
4408
+ const ext = path21.extname(absolutePath).toLowerCase();
4408
4409
  try {
4409
4410
  if (ext === ".ts" || ext === ".tsx") {
4410
4411
  await execAsync2(`npx tsc --noEmit ${absolutePath}`, { timeout: 1e4 });
@@ -6486,16 +6487,16 @@ function resolveInWorkspace(workspaceRoot, input) {
6486
6487
  if (typeof input !== "string" || input.length === 0) {
6487
6488
  throw new WorkspaceSandboxError(String(input), workspaceRoot);
6488
6489
  }
6489
- const root = path20.resolve(workspaceRoot);
6490
- const abs = path20.isAbsolute(input) ? path20.resolve(input) : path20.resolve(root, input);
6491
- const rel = path20.relative(root, abs);
6492
- if (rel === "" || rel === ".") ; else if (rel.startsWith("..") || path20.isAbsolute(rel)) {
6490
+ const root = path21.resolve(workspaceRoot);
6491
+ const abs = path21.isAbsolute(input) ? path21.resolve(input) : path21.resolve(root, input);
6492
+ const rel = path21.relative(root, abs);
6493
+ if (rel === "" || rel === ".") ; else if (rel.startsWith("..") || path21.isAbsolute(rel)) {
6493
6494
  throw new WorkspaceSandboxError(input, root);
6494
6495
  }
6495
6496
  try {
6496
- const real = fs19.realpathSync(abs);
6497
- const realRel = path20.relative(root, real);
6498
- if (realRel !== "" && realRel !== "." && (realRel.startsWith("..") || path20.isAbsolute(realRel))) {
6497
+ const real = fs20.realpathSync(abs);
6498
+ const realRel = path21.relative(root, real);
6499
+ if (realRel !== "" && realRel !== "." && (realRel.startsWith("..") || path21.isAbsolute(realRel))) {
6499
6500
  throw new WorkspaceSandboxError(input, root);
6500
6501
  }
6501
6502
  } catch (e) {
@@ -6556,7 +6557,7 @@ var FileWriteTool = class extends BaseTool {
6556
6557
  } catch {
6557
6558
  }
6558
6559
  }
6559
- await fs4.mkdir(path20.dirname(absPath), { recursive: true });
6560
+ await fs4.mkdir(path21.dirname(absPath), { recursive: true });
6560
6561
  await fs4.writeFile(absPath, content, "utf-8");
6561
6562
  return `Written ${content.length} characters to ${filePath}`;
6562
6563
  }
@@ -7054,7 +7055,7 @@ var ImageAnalyzeTool = class extends BaseTool {
7054
7055
  };
7055
7056
  async function fileToImageAttachment(filePath) {
7056
7057
  const data = await fs4.readFile(filePath);
7057
- const ext = path20.extname(filePath).toLowerCase();
7058
+ const ext = path21.extname(filePath).toLowerCase();
7058
7059
  const mimeMap = {
7059
7060
  ".jpg": "image/jpeg",
7060
7061
  ".jpeg": "image/jpeg",
@@ -7088,14 +7089,14 @@ var PDFCreateTool = class extends BaseTool {
7088
7089
  const filePath = input["path"];
7089
7090
  const content = input["content"];
7090
7091
  const title = input["title"];
7091
- const dir = path20.dirname(filePath);
7092
- if (!fs19.existsSync(dir)) {
7093
- fs19.mkdirSync(dir, { recursive: true });
7092
+ const dir = path21.dirname(filePath);
7093
+ if (!fs20.existsSync(dir)) {
7094
+ fs20.mkdirSync(dir, { recursive: true });
7094
7095
  }
7095
7096
  return new Promise((resolve, reject) => {
7096
7097
  try {
7097
7098
  const doc = new PDFDocument({ margin: 50 });
7098
- const stream = fs19.createWriteStream(filePath);
7099
+ const stream = fs20.createWriteStream(filePath);
7099
7100
  doc.pipe(stream);
7100
7101
  if (title) {
7101
7102
  doc.info["Title"] = title;
@@ -7173,22 +7174,22 @@ var CodeInterpreterTool = class extends BaseTool {
7173
7174
  }
7174
7175
  cmdPrefix = NODE_CMD;
7175
7176
  }
7176
- const tmpDir = path20.join(this.workspaceRoot, ".cascade", "tmp");
7177
- if (!fs19.existsSync(tmpDir)) {
7178
- fs19.mkdirSync(tmpDir, { recursive: true });
7177
+ const tmpDir = path21.join(this.workspaceRoot, ".cascade", "tmp");
7178
+ if (!fs20.existsSync(tmpDir)) {
7179
+ fs20.mkdirSync(tmpDir, { recursive: true });
7179
7180
  }
7180
7181
  const extension = language === "python" ? "py" : "js";
7181
7182
  const fileName = `intp_${randomUUID().slice(0, 8)}.${extension}`;
7182
- const filePath = path20.join(tmpDir, fileName);
7183
- fs19.writeFileSync(filePath, code, "utf-8");
7183
+ const filePath = path21.join(tmpDir, fileName);
7184
+ fs20.writeFileSync(filePath, code, "utf-8");
7184
7185
  const execArgs = [filePath, ...args];
7185
7186
  return new Promise((resolve) => {
7186
7187
  const startMs = Date.now();
7187
7188
  execFile(cmdPrefix, execArgs, { cwd: this.workspaceRoot, timeout: 3e4 }, (error, stdout, stderr) => {
7188
7189
  const duration = Date.now() - startMs;
7189
7190
  try {
7190
- if (fs19.existsSync(filePath)) {
7191
- fs19.unlinkSync(filePath);
7191
+ if (fs20.existsSync(filePath)) {
7192
+ fs20.unlinkSync(filePath);
7192
7193
  }
7193
7194
  } catch (cleanupErr) {
7194
7195
  console.error(`Failed to cleanup interpreter script ${filePath}:`, cleanupErr);
@@ -7467,7 +7468,7 @@ var GlobTool = class extends BaseTool {
7467
7468
  };
7468
7469
  async execute(input, _options) {
7469
7470
  const pattern = input["pattern"];
7470
- const searchPath = input["path"] ? path20.resolve(this.workspaceRoot, input["path"]) : this.workspaceRoot;
7471
+ const searchPath = input["path"] ? path21.resolve(this.workspaceRoot, input["path"]) : this.workspaceRoot;
7471
7472
  const matches = await glob(pattern, {
7472
7473
  cwd: searchPath,
7473
7474
  ignore: ["node_modules/**", ".git/**", "dist/**", "build/**"],
@@ -7480,7 +7481,7 @@ var GlobTool = class extends BaseTool {
7480
7481
  const withMtime = await Promise.all(
7481
7482
  matches.map(async (rel) => {
7482
7483
  try {
7483
- const stat = await fs4.stat(path20.join(searchPath, rel));
7484
+ const stat = await fs4.stat(path21.join(searchPath, rel));
7484
7485
  return { rel, mtime: stat.mtimeMs };
7485
7486
  } catch {
7486
7487
  return { rel, mtime: 0 };
@@ -7529,7 +7530,7 @@ var GrepTool = class extends BaseTool {
7529
7530
  };
7530
7531
  async execute(input, _options) {
7531
7532
  const pattern = input["pattern"];
7532
- const searchPath = input["path"] ? path20.resolve(this.workspaceRoot, input["path"]) : this.workspaceRoot;
7533
+ const searchPath = input["path"] ? path21.resolve(this.workspaceRoot, input["path"]) : this.workspaceRoot;
7533
7534
  const globPattern = input["glob"];
7534
7535
  const outputMode = input["output_mode"] ?? "content";
7535
7536
  const context = input["context"] ?? 0;
@@ -7583,12 +7584,12 @@ var GrepTool = class extends BaseTool {
7583
7584
  nodir: true
7584
7585
  });
7585
7586
  } catch {
7586
- files = [path20.relative(searchPath, searchPath) || "."];
7587
+ files = [path21.relative(searchPath, searchPath) || "."];
7587
7588
  }
7588
7589
  const results = [];
7589
7590
  let totalCount = 0;
7590
7591
  for (const rel of files) {
7591
- const abs = path20.join(searchPath, rel);
7592
+ const abs = path21.join(searchPath, rel);
7592
7593
  let content;
7593
7594
  try {
7594
7595
  content = await fs4.readFile(abs, "utf-8");
@@ -7950,10 +7951,10 @@ var ToolRegistry = class extends EventEmitter {
7950
7951
  }
7951
7952
  isIgnored(filePath) {
7952
7953
  if (!filePath) return false;
7953
- const abs = path20.resolve(this.workspaceRoot, filePath);
7954
- const rel = path20.relative(this.workspaceRoot, abs);
7955
- if (!rel || rel.startsWith("..") || path20.isAbsolute(rel)) return true;
7956
- const posixRel = rel.split(path20.sep).join("/");
7954
+ const abs = path21.resolve(this.workspaceRoot, filePath);
7955
+ const rel = path21.relative(this.workspaceRoot, abs);
7956
+ if (!rel || rel.startsWith("..") || path21.isAbsolute(rel)) return true;
7957
+ const posixRel = rel.split(path21.sep).join("/");
7957
7958
  return this.ignoreMatcher.ignores(posixRel);
7958
7959
  }
7959
7960
  };
@@ -8787,7 +8788,7 @@ var TaskAnalyzer = class {
8787
8788
  analysisCache.clear();
8788
8789
  }
8789
8790
  };
8790
- var DEFAULT_STATS_FILE = path20.join(os6.homedir(), ".cascade", "model-perf.json");
8791
+ var DEFAULT_STATS_FILE = path21.join(os6.homedir(), ".cascade", "model-perf.json");
8791
8792
  var ModelPerformanceTracker = class {
8792
8793
  stats = /* @__PURE__ */ new Map();
8793
8794
  featureStats = /* @__PURE__ */ new Map();
@@ -8819,7 +8820,7 @@ var ModelPerformanceTracker = class {
8819
8820
  }
8820
8821
  async save() {
8821
8822
  try {
8822
- await fs4.mkdir(path20.dirname(this.statsFile), { recursive: true });
8823
+ await fs4.mkdir(path21.dirname(this.statsFile), { recursive: true });
8823
8824
  const modelsObj = {};
8824
8825
  const featuresObj = {};
8825
8826
  for (const [key, stat] of this.stats) modelsObj[key] = stat;
@@ -9358,7 +9359,7 @@ Required capability: ${description.slice(0, 300)}`;
9358
9359
  * any dangerous action, so a silently-reloaded tool can't act without approval. */
9359
9360
  async loadPersistedTools() {
9360
9361
  if (!this.workspacePath || !this.persistEnabled) return;
9361
- const file = path20.join(this.workspacePath, ".cascade", DYNAMIC_TOOLS_FILE);
9362
+ const file = path21.join(this.workspacePath, ".cascade", DYNAMIC_TOOLS_FILE);
9362
9363
  try {
9363
9364
  const raw = await fs4.readFile(file, "utf-8");
9364
9365
  const specs = JSON.parse(raw);
@@ -9382,8 +9383,8 @@ Required capability: ${description.slice(0, 300)}`;
9382
9383
  }
9383
9384
  async persist() {
9384
9385
  if (!this.workspacePath || !this.persistEnabled) return;
9385
- const dir = path20.join(this.workspacePath, ".cascade");
9386
- const file = path20.join(dir, DYNAMIC_TOOLS_FILE);
9386
+ const dir = path21.join(this.workspacePath, ".cascade");
9387
+ const file = path21.join(dir, DYNAMIC_TOOLS_FILE);
9387
9388
  try {
9388
9389
  await fs4.mkdir(dir, { recursive: true });
9389
9390
  await fs4.writeFile(file, JSON.stringify(Array.from(this.specs.values()), null, 2), "utf-8");
@@ -9403,12 +9404,12 @@ var WorldStateDB = class {
9403
9404
  constructor(workspacePath, debugMode = false) {
9404
9405
  this.workspacePath = workspacePath;
9405
9406
  this.debugMode = debugMode;
9406
- const cascadeDir = path20.join(workspacePath, ".cascade");
9407
- if (!fs19.existsSync(cascadeDir)) {
9408
- fs19.mkdirSync(cascadeDir, { recursive: true });
9407
+ const cascadeDir = path21.join(workspacePath, ".cascade");
9408
+ if (!fs20.existsSync(cascadeDir)) {
9409
+ fs20.mkdirSync(cascadeDir, { recursive: true });
9409
9410
  }
9410
- this.keyPath = path20.join(cascadeDir, "world_state.key");
9411
- this.dbPath = path20.join(cascadeDir, "world_state.db");
9411
+ this.keyPath = path21.join(cascadeDir, "world_state.key");
9412
+ this.dbPath = path21.join(cascadeDir, "world_state.db");
9412
9413
  this.initEncryptionKey();
9413
9414
  this.db = new Database(this.dbPath);
9414
9415
  this.db.pragma("journal_mode = WAL");
@@ -9438,11 +9439,11 @@ var WorldStateDB = class {
9438
9439
  dbPath;
9439
9440
  encryptionKey;
9440
9441
  initEncryptionKey() {
9441
- if (fs19.existsSync(this.keyPath)) {
9442
- this.encryptionKey = fs19.readFileSync(this.keyPath);
9442
+ if (fs20.existsSync(this.keyPath)) {
9443
+ this.encryptionKey = fs20.readFileSync(this.keyPath);
9443
9444
  } else {
9444
9445
  this.encryptionKey = crypto3.randomBytes(32);
9445
- fs19.writeFileSync(this.keyPath, this.encryptionKey);
9446
+ fs20.writeFileSync(this.keyPath, this.encryptionKey);
9446
9447
  }
9447
9448
  }
9448
9449
  encrypt(text) {
@@ -9583,6 +9584,22 @@ var WorldStateDB = class {
9583
9584
  }
9584
9585
  return selected.slice(0, limit).map((f) => `- ${f.entity} ${f.relation} ${f.value}`).join("\n");
9585
9586
  }
9587
+ /**
9588
+ * Delete one fact by its (normalized) entity + relation key. Returns whether
9589
+ * a row was actually removed. Powers the desktop Knowledge tab's per-fact
9590
+ * delete — users can prune what the planner remembers about their project.
9591
+ */
9592
+ deleteFact(entity, relation) {
9593
+ const e = normalizeKey(entity);
9594
+ const r = normalizeKey(relation);
9595
+ if (!e || !r) return false;
9596
+ const result = this.db.prepare("DELETE FROM facts WHERE entity = ? AND relation = ?").run(e, r);
9597
+ return result.changes > 0;
9598
+ }
9599
+ /** Delete every fact. Returns how many were removed. */
9600
+ clearFacts() {
9601
+ return this.db.prepare("DELETE FROM facts").run().changes;
9602
+ }
9586
9603
  // ── Export / Import ──────────────────────────
9587
9604
  //
9588
9605
  // Knowledge travels DECRYPTED in the export bundle (a portable plaintext
@@ -9631,9 +9648,9 @@ var WorldStateDB = class {
9631
9648
  dumpDebugIfNeeded() {
9632
9649
  if (!this.debugMode) return;
9633
9650
  try {
9634
- const dumpPath = path20.join(os6.tmpdir(), "cascade_world_state_debug.json");
9651
+ const dumpPath = path21.join(os6.tmpdir(), "cascade_world_state_debug.json");
9635
9652
  const entries = this.getAllEntries();
9636
- fs19.writeFileSync(dumpPath, JSON.stringify(entries, null, 2), "utf-8");
9653
+ fs20.writeFileSync(dumpPath, JSON.stringify(entries, null, 2), "utf-8");
9637
9654
  } catch (err) {
9638
9655
  console.error("Failed to dump debug world state", err);
9639
9656
  }
@@ -10543,7 +10560,7 @@ var Keystore = class {
10543
10560
  const creds = await this.keytar.findCredentials(KEYTAR_SERVICE);
10544
10561
  this.cache = Object.fromEntries(creds.map((c) => [c.account, c.password]));
10545
10562
  this.backend = "keytar";
10546
- if (password && fs19.existsSync(this.storePath)) {
10563
+ if (password && fs20.existsSync(this.storePath)) {
10547
10564
  try {
10548
10565
  const fileEntries = this.decryptFile(password);
10549
10566
  for (const [k, v] of Object.entries(fileEntries)) {
@@ -10562,7 +10579,7 @@ var Keystore = class {
10562
10579
  "Keystore unlock requires a password because the OS keychain (keytar) is not available on this system."
10563
10580
  );
10564
10581
  }
10565
- if (!fs19.existsSync(this.storePath)) {
10582
+ if (!fs20.existsSync(this.storePath)) {
10566
10583
  const salt = crypto3.randomBytes(SALT_LEN);
10567
10584
  this.masterKey = this.deriveKey(password, salt);
10568
10585
  this.writeWithSalt({}, salt);
@@ -10576,7 +10593,7 @@ var Keystore = class {
10576
10593
  }
10577
10594
  /** Synchronous legacy unlock kept for AES-only environments. */
10578
10595
  unlockSync(password) {
10579
- if (!fs19.existsSync(this.storePath)) {
10596
+ if (!fs20.existsSync(this.storePath)) {
10580
10597
  const salt = crypto3.randomBytes(SALT_LEN);
10581
10598
  this.masterKey = this.deriveKey(password, salt);
10582
10599
  this.writeWithSalt({}, salt);
@@ -10634,7 +10651,7 @@ var Keystore = class {
10634
10651
  }
10635
10652
  }
10636
10653
  decryptFile(password, knownSalt) {
10637
- if (!fs19.existsSync(this.storePath)) return {};
10654
+ if (!fs20.existsSync(this.storePath)) return {};
10638
10655
  try {
10639
10656
  const { salt, ciphertext, iv, tag } = this.readRaw();
10640
10657
  const useSalt = knownSalt ?? salt;
@@ -10656,8 +10673,8 @@ var Keystore = class {
10656
10673
  const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
10657
10674
  const tag = cipher.getAuthTag();
10658
10675
  const out = Buffer.concat([raw.salt, iv, tag, ciphertext]);
10659
- fs19.mkdirSync(path20.dirname(this.storePath), { recursive: true });
10660
- fs19.writeFileSync(this.storePath, out, { mode: 384 });
10676
+ fs20.mkdirSync(path21.dirname(this.storePath), { recursive: true });
10677
+ fs20.writeFileSync(this.storePath, out, { mode: 384 });
10661
10678
  }
10662
10679
  writeWithSalt(data, salt) {
10663
10680
  if (!this.masterKey) throw new Error("writeWithSalt called before masterKey was set");
@@ -10667,11 +10684,11 @@ var Keystore = class {
10667
10684
  const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
10668
10685
  const tag = cipher.getAuthTag();
10669
10686
  const out = Buffer.concat([salt, iv, tag, ciphertext]);
10670
- fs19.mkdirSync(path20.dirname(this.storePath), { recursive: true });
10671
- fs19.writeFileSync(this.storePath, out, { mode: 384 });
10687
+ fs20.mkdirSync(path21.dirname(this.storePath), { recursive: true });
10688
+ fs20.writeFileSync(this.storePath, out, { mode: 384 });
10672
10689
  }
10673
10690
  readRaw() {
10674
- const buf = fs19.readFileSync(this.storePath);
10691
+ const buf = fs20.readFileSync(this.storePath);
10675
10692
  let offset = 0;
10676
10693
  const salt = buf.subarray(offset, offset + SALT_LEN);
10677
10694
  offset += SALT_LEN;
@@ -10704,7 +10721,7 @@ var CascadeIgnore = class {
10704
10721
  ]);
10705
10722
  }
10706
10723
  async load(workspacePath) {
10707
- const filePath = path20.join(workspacePath, ".cascadeignore");
10724
+ const filePath = path21.join(workspacePath, ".cascadeignore");
10708
10725
  try {
10709
10726
  const content = await fs4.readFile(filePath, "utf-8");
10710
10727
  const lines = content.split("\n").filter((l) => l.trim() && !l.startsWith("#"));
@@ -10715,7 +10732,7 @@ var CascadeIgnore = class {
10715
10732
  }
10716
10733
  isIgnored(filePath, workspacePath) {
10717
10734
  try {
10718
- const relative = workspacePath ? path20.relative(workspacePath, filePath) : filePath;
10735
+ const relative = workspacePath ? path21.relative(workspacePath, filePath) : filePath;
10719
10736
  return this.ig.ignores(relative);
10720
10737
  } catch {
10721
10738
  return false;
@@ -10726,7 +10743,7 @@ var CascadeIgnore = class {
10726
10743
  }
10727
10744
  };
10728
10745
  async function loadCascadeMd(workspacePath) {
10729
- const filePath = path20.join(workspacePath, "CASCADE.md");
10746
+ const filePath = path21.join(workspacePath, "CASCADE.md");
10730
10747
  try {
10731
10748
  const raw = await fs4.readFile(filePath, "utf-8");
10732
10749
  return parseCascadeMd(raw);
@@ -10757,7 +10774,7 @@ ${raw.trim()}`;
10757
10774
  var MemoryStore = class _MemoryStore {
10758
10775
  db;
10759
10776
  constructor(dbPath) {
10760
- fs19.mkdirSync(path20.dirname(dbPath), { recursive: true });
10777
+ fs20.mkdirSync(path21.dirname(dbPath), { recursive: true });
10761
10778
  try {
10762
10779
  this.db = new Database(dbPath, { timeout: 5e3 });
10763
10780
  this.db.pragma("journal_mode = WAL");
@@ -11592,6 +11609,60 @@ Original error: ${err.message}`
11592
11609
  };
11593
11610
  }
11594
11611
  };
11612
+ function credentialsPath(globalDir) {
11613
+ return path21.join(globalDir, GLOBAL_CREDENTIALS_FILE);
11614
+ }
11615
+ function providerKey(p) {
11616
+ if (p.type === "azure") {
11617
+ return `azure:${p.deploymentName ?? p.baseUrl ?? p.label ?? ""}`;
11618
+ }
11619
+ return p.type;
11620
+ }
11621
+ function isPersistable(p) {
11622
+ return Boolean(p.apiKey || p.authToken || p.type === "azure" || p.baseUrl);
11623
+ }
11624
+ function loadGlobalCredentials(globalDir) {
11625
+ try {
11626
+ const raw = fs20.readFileSync(credentialsPath(globalDir), "utf-8");
11627
+ const parsed = JSON.parse(raw);
11628
+ if (!Array.isArray(parsed.providers)) return [];
11629
+ return parsed.providers.filter(
11630
+ (p) => Boolean(p) && typeof p.type === "string"
11631
+ );
11632
+ } catch {
11633
+ return [];
11634
+ }
11635
+ }
11636
+ function saveGlobalCredentials(globalDir, providers) {
11637
+ const filePath = credentialsPath(globalDir);
11638
+ fs20.mkdirSync(globalDir, { recursive: true, mode: 448 });
11639
+ const body = { version: 1, providers: providers.filter(isPersistable) };
11640
+ const tmp = `${filePath}.tmp`;
11641
+ fs20.writeFileSync(tmp, JSON.stringify(body, null, 2), { encoding: "utf-8", mode: 384 });
11642
+ fs20.renameSync(tmp, filePath);
11643
+ try {
11644
+ fs20.chmodSync(filePath, 384);
11645
+ } catch {
11646
+ }
11647
+ }
11648
+ function mergeGlobalCredentials(workspaceProviders, globalProviders) {
11649
+ const merged = [...workspaceProviders];
11650
+ const byKey = new Map(merged.map((p) => [providerKey(p), p]));
11651
+ for (const g of globalProviders) {
11652
+ const existing = byKey.get(providerKey(g));
11653
+ if (!existing) {
11654
+ merged.push({ ...g });
11655
+ byKey.set(providerKey(g), merged[merged.length - 1]);
11656
+ continue;
11657
+ }
11658
+ if (!existing.apiKey && g.apiKey) existing.apiKey = g.apiKey;
11659
+ if (!existing.authToken && g.authToken) existing.authToken = g.authToken;
11660
+ if (!existing.baseUrl && g.baseUrl) existing.baseUrl = g.baseUrl;
11661
+ if (!existing.apiVersion && g.apiVersion) existing.apiVersion = g.apiVersion;
11662
+ if (!existing.label && g.label) existing.label = g.label;
11663
+ }
11664
+ return merged;
11665
+ }
11595
11666
 
11596
11667
  // src/config/index.ts
11597
11668
  var ConfigManager = class {
@@ -11602,18 +11673,20 @@ var ConfigManager = class {
11602
11673
  cascadeMd = null;
11603
11674
  workspacePath;
11604
11675
  globalDir;
11605
- constructor(workspacePath = process.cwd()) {
11676
+ /** `globalDirOverride` exists for tests — never point it at the real home dir there. */
11677
+ constructor(workspacePath = process.cwd(), globalDirOverride) {
11606
11678
  this.workspacePath = workspacePath;
11607
- this.globalDir = path20.join(os6.homedir(), GLOBAL_CONFIG_DIR);
11679
+ this.globalDir = globalDirOverride ?? path21.join(os6.homedir(), GLOBAL_CONFIG_DIR);
11608
11680
  }
11609
11681
  async load() {
11610
11682
  this.config = await this.loadConfig();
11611
11683
  this.ignore = new CascadeIgnore();
11612
11684
  await this.ignore.load(this.workspacePath);
11613
11685
  this.cascadeMd = await loadCascadeMd(this.workspacePath);
11614
- this.keystore = new Keystore(path20.join(this.globalDir, GLOBAL_KEYSTORE_FILE));
11615
- this.store = new MemoryStore(path20.join(this.workspacePath, CASCADE_DB_FILE));
11686
+ this.keystore = new Keystore(path21.join(this.globalDir, GLOBAL_KEYSTORE_FILE));
11687
+ this.store = new MemoryStore(path21.join(this.workspacePath, CASCADE_DB_FILE));
11616
11688
  await this.injectEnvKeys();
11689
+ this.config.providers = mergeGlobalCredentials(this.config.providers, loadGlobalCredentials(this.globalDir));
11617
11690
  await this.ensureDefaultIdentity();
11618
11691
  }
11619
11692
  getConfig() {
@@ -11635,9 +11708,14 @@ var ConfigManager = class {
11635
11708
  return this.workspacePath;
11636
11709
  }
11637
11710
  async save() {
11638
- const configPath = path20.join(this.workspacePath, CASCADE_CONFIG_FILE);
11639
- await fs4.mkdir(path20.dirname(configPath), { recursive: true });
11711
+ const configPath = path21.join(this.workspacePath, CASCADE_CONFIG_FILE);
11712
+ await fs4.mkdir(path21.dirname(configPath), { recursive: true });
11640
11713
  await fs4.writeFile(configPath, JSON.stringify(this.config, null, 2), "utf-8");
11714
+ try {
11715
+ saveGlobalCredentials(this.globalDir, this.config.providers);
11716
+ } catch (err) {
11717
+ console.warn(`Failed to sync credentials to global store: ${err instanceof Error ? err.message : String(err)}`);
11718
+ }
11641
11719
  }
11642
11720
  async updateConfig(updates) {
11643
11721
  this.config = validateConfig({ ...this.config, ...updates });
@@ -11660,7 +11738,7 @@ var ConfigManager = class {
11660
11738
  return configProvider?.apiKey;
11661
11739
  }
11662
11740
  async loadConfig() {
11663
- const configPath = path20.join(this.workspacePath, CASCADE_CONFIG_FILE);
11741
+ const configPath = path21.join(this.workspacePath, CASCADE_CONFIG_FILE);
11664
11742
  try {
11665
11743
  const raw = await fs4.readFile(configPath, "utf-8");
11666
11744
  return validateConfig(JSON.parse(raw));
@@ -11767,6 +11845,11 @@ function authMiddleware(secret, required = true) {
11767
11845
  }
11768
11846
  const user = verifyToken(token, secret);
11769
11847
  if (!user) {
11848
+ if (!required) {
11849
+ req.user = void 0;
11850
+ next();
11851
+ return;
11852
+ }
11770
11853
  res.status(401).json({ error: "Invalid or expired token" });
11771
11854
  return;
11772
11855
  }
@@ -12075,7 +12158,7 @@ function aggregateCostStats(sessions, opts = {}) {
12075
12158
  }
12076
12159
 
12077
12160
  // src/dashboard/server.ts
12078
- var __dirname$1 = path20.dirname(fileURLToPath(import.meta.url));
12161
+ var __dirname$1 = path21.dirname(fileURLToPath(import.meta.url));
12079
12162
  var DashboardServer = class {
12080
12163
  app;
12081
12164
  httpServer;
@@ -12309,12 +12392,17 @@ var DashboardServer = class {
12309
12392
  */
12310
12393
  persistConfig() {
12311
12394
  try {
12312
- const configPath = path20.join(this.workspacePath, CASCADE_CONFIG_FILE);
12313
- fs19.mkdirSync(path20.dirname(configPath), { recursive: true });
12314
- fs19.writeFileSync(configPath, JSON.stringify(this.config, null, 2), "utf-8");
12395
+ const configPath = path21.join(this.workspacePath, CASCADE_CONFIG_FILE);
12396
+ fs20.mkdirSync(path21.dirname(configPath), { recursive: true });
12397
+ fs20.writeFileSync(configPath, JSON.stringify(this.config, null, 2), "utf-8");
12315
12398
  } catch (err) {
12316
12399
  console.warn(`[dashboard] Failed to persist config: ${err instanceof Error ? err.message : String(err)}`);
12317
12400
  }
12401
+ try {
12402
+ saveGlobalCredentials(path21.join(os6.homedir(), GLOBAL_CONFIG_DIR), this.config.providers ?? []);
12403
+ } catch (err) {
12404
+ console.warn(`[dashboard] Failed to sync global credentials: ${err instanceof Error ? err.message : String(err)}`);
12405
+ }
12318
12406
  }
12319
12407
  /**
12320
12408
  * Produce a stable dashboard JWT signing secret.
@@ -12326,15 +12414,15 @@ var DashboardServer = class {
12326
12414
  resolveDashboardSecret() {
12327
12415
  const fromConfig = this.config.dashboard.secret ?? process.env["CASCADE_DASHBOARD_SECRET"];
12328
12416
  if (fromConfig) return fromConfig;
12329
- const secretPath = path20.join(this.workspacePath, CASCADE_DASHBOARD_SECRET_FILE);
12417
+ const secretPath = path21.join(this.workspacePath, CASCADE_DASHBOARD_SECRET_FILE);
12330
12418
  try {
12331
- if (fs19.existsSync(secretPath)) {
12332
- const existing = fs19.readFileSync(secretPath, "utf-8").trim();
12419
+ if (fs20.existsSync(secretPath)) {
12420
+ const existing = fs20.readFileSync(secretPath, "utf-8").trim();
12333
12421
  if (existing.length >= 16) return existing;
12334
12422
  }
12335
12423
  const generated = randomUUID();
12336
- fs19.mkdirSync(path20.dirname(secretPath), { recursive: true });
12337
- fs19.writeFileSync(secretPath, generated, { encoding: "utf-8", mode: 384 });
12424
+ fs20.mkdirSync(path21.dirname(secretPath), { recursive: true });
12425
+ fs20.writeFileSync(secretPath, generated, { encoding: "utf-8", mode: 384 });
12338
12426
  if (this.config.dashboard.auth) {
12339
12427
  console.warn(
12340
12428
  `Dashboard auth enabled with no secret configured; persisted a generated secret to ${secretPath}. Set CASCADE_DASHBOARD_SECRET or config.dashboard.secret to override.`
@@ -12361,7 +12449,7 @@ var DashboardServer = class {
12361
12449
  // ── Setup ─────────────────────────────────────
12362
12450
  getGlobalStore() {
12363
12451
  if (!this.globalStore) {
12364
- const globalDbPath = path20.join(os6.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
12452
+ const globalDbPath = path21.join(os6.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
12365
12453
  this.globalStore = new MemoryStore(globalDbPath);
12366
12454
  }
12367
12455
  return this.globalStore;
@@ -12630,12 +12718,12 @@ ${prompt}`;
12630
12718
  }
12631
12719
  }
12632
12720
  watchRuntimeChanges() {
12633
- const workspaceDbPath = path20.join(this.workspacePath, CASCADE_DB_FILE);
12634
- const globalDbPath = path20.join(os6.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
12721
+ const workspaceDbPath = path21.join(this.workspacePath, CASCADE_DB_FILE);
12722
+ const globalDbPath = path21.join(os6.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
12635
12723
  const watchPaths = [workspaceDbPath, globalDbPath].filter((p, index, arr) => arr.indexOf(p) === index);
12636
12724
  for (const watchPath of watchPaths) {
12637
- if (!fs19.existsSync(watchPath)) continue;
12638
- fs19.watchFile(watchPath, { interval: 3e3 }, () => {
12725
+ if (!fs20.existsSync(watchPath)) continue;
12726
+ fs20.watchFile(watchPath, { interval: 3e3 }, () => {
12639
12727
  this.throttledBroadcast(watchPath === globalDbPath ? "global" : "workspace");
12640
12728
  });
12641
12729
  }
@@ -12757,7 +12845,7 @@ ${prompt}`;
12757
12845
  const sessionId = req.params.id;
12758
12846
  this.store.deleteSession(sessionId);
12759
12847
  this.store.deleteRuntimeSession(sessionId);
12760
- const globalDbPath = path20.join(os6.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
12848
+ const globalDbPath = path21.join(os6.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
12761
12849
  const globalStore = new MemoryStore(globalDbPath);
12762
12850
  try {
12763
12851
  globalStore.deleteRuntimeSession(sessionId);
@@ -12850,7 +12938,7 @@ ${prompt}`;
12850
12938
  });
12851
12939
  this.app.delete("/api/sessions", auth, (req, res) => {
12852
12940
  const body = req.body;
12853
- const globalDbPath = path20.join(os6.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
12941
+ const globalDbPath = path21.join(os6.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
12854
12942
  if (body?.ids && Array.isArray(body.ids) && body.ids.length > 0) {
12855
12943
  const globalStore = new MemoryStore(globalDbPath);
12856
12944
  try {
@@ -12873,7 +12961,7 @@ ${prompt}`;
12873
12961
  });
12874
12962
  this.app.delete("/api/runtime", auth, (_req, res) => {
12875
12963
  this.store.deleteAllRuntimeNodes();
12876
- const globalDbPath = path20.join(os6.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
12964
+ const globalDbPath = path21.join(os6.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
12877
12965
  const globalStore = new MemoryStore(globalDbPath);
12878
12966
  try {
12879
12967
  globalStore.deleteAllRuntimeNodes();
@@ -12959,12 +13047,12 @@ ${prompt}`;
12959
13047
  if (body["tierLimits"]) this.config.tierLimits = { ...this.config.tierLimits, ...body["tierLimits"] };
12960
13048
  if (body["budget"]) this.config.budget = { ...this.config.budget, ...body["budget"] };
12961
13049
  try {
12962
- const configPath = path20.join(this.workspacePath, CASCADE_CONFIG_FILE);
12963
- const existing = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf-8")) : {};
13050
+ const configPath = path21.join(this.workspacePath, CASCADE_CONFIG_FILE);
13051
+ const existing = fs20.existsSync(configPath) ? JSON.parse(fs20.readFileSync(configPath, "utf-8")) : {};
12964
13052
  const updated = { ...existing, tierLimits: this.config.tierLimits, budget: this.config.budget };
12965
13053
  const tmp = configPath + ".tmp";
12966
- fs19.writeFileSync(tmp, JSON.stringify(updated, null, 2), "utf-8");
12967
- fs19.renameSync(tmp, configPath);
13054
+ fs20.writeFileSync(tmp, JSON.stringify(updated, null, 2), "utf-8");
13055
+ fs20.renameSync(tmp, configPath);
12968
13056
  res.json({ ok: true });
12969
13057
  } catch (err) {
12970
13058
  res.status(500).json({ error: `Failed to save config: ${err instanceof Error ? err.message : String(err)}` });
@@ -12992,7 +13080,7 @@ ${prompt}`;
12992
13080
  this.app.get("/api/runtime", auth, (req, res) => {
12993
13081
  const scope = req.query["scope"] ?? "workspace";
12994
13082
  if (scope === "global") {
12995
- const globalDbPath = path20.join(os6.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
13083
+ const globalDbPath = path21.join(os6.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
12996
13084
  const globalStore = new MemoryStore(globalDbPath);
12997
13085
  try {
12998
13086
  res.json({
@@ -13227,6 +13315,48 @@ ${prompt}`;
13227
13315
  res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
13228
13316
  }
13229
13317
  });
13318
+ this.app.get("/api/knowledge", auth, (_req, res) => {
13319
+ try {
13320
+ const ws = new WorldStateDB(this.workspacePath);
13321
+ try {
13322
+ const facts = ws.getAllFacts();
13323
+ res.json({ total: facts.length, facts });
13324
+ } finally {
13325
+ ws.close();
13326
+ }
13327
+ } catch (err) {
13328
+ res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
13329
+ }
13330
+ });
13331
+ this.app.delete("/api/knowledge/fact", auth, mutationLimiter, (req, res) => {
13332
+ const body = req.body;
13333
+ if (!body.entity || !body.relation) {
13334
+ res.status(400).json({ error: "entity and relation are required" });
13335
+ return;
13336
+ }
13337
+ try {
13338
+ const ws = new WorldStateDB(this.workspacePath);
13339
+ try {
13340
+ res.json({ ok: true, deleted: ws.deleteFact(body.entity, body.relation) });
13341
+ } finally {
13342
+ ws.close();
13343
+ }
13344
+ } catch (err) {
13345
+ res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
13346
+ }
13347
+ });
13348
+ this.app.delete("/api/knowledge", auth, mutationLimiter, (_req, res) => {
13349
+ try {
13350
+ const ws = new WorldStateDB(this.workspacePath);
13351
+ try {
13352
+ res.json({ ok: true, deleted: ws.clearFacts() });
13353
+ } finally {
13354
+ ws.close();
13355
+ }
13356
+ } catch (err) {
13357
+ res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
13358
+ }
13359
+ });
13230
13360
  this.app.get("/api/audit-chain", auth, async (req, res) => {
13231
13361
  try {
13232
13362
  const limit = Math.min(500, Math.max(1, parseInt(req.query["limit"] || "200", 10) || 200));
@@ -13245,13 +13375,13 @@ ${prompt}`;
13245
13375
  res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
13246
13376
  }
13247
13377
  });
13248
- const prodPath = path20.resolve(__dirname$1, "../web/dist");
13249
- const devPath = path20.resolve(__dirname$1, "../../web/dist");
13250
- const webDistPath = fs19.existsSync(prodPath) ? prodPath : devPath;
13251
- if (fs19.existsSync(webDistPath)) {
13378
+ const prodPath = path21.resolve(__dirname$1, "../web/dist");
13379
+ const devPath = path21.resolve(__dirname$1, "../../web/dist");
13380
+ const webDistPath = fs20.existsSync(prodPath) ? prodPath : devPath;
13381
+ if (fs20.existsSync(webDistPath)) {
13252
13382
  this.app.use(express.static(webDistPath));
13253
13383
  this.app.get("*", (_req, res) => {
13254
- res.sendFile(path20.join(webDistPath, "index.html"));
13384
+ res.sendFile(path21.join(webDistPath, "index.html"));
13255
13385
  });
13256
13386
  } else {
13257
13387
  this.app.get("/", (_req, res) => {
@@ -13324,6 +13454,6 @@ var HooksRunner = class {
13324
13454
  }
13325
13455
  };
13326
13456
 
13327
- export { AZURE_BASE_URL_TEMPLATE, AuditLogger, CASCADE_AUDIT_FILE, CASCADE_CONFIG_DIR, CASCADE_CONFIG_FILE, CASCADE_DASHBOARD_SECRET_FILE, CASCADE_DB_FILE, CASCADE_IGNORE_FILE, CASCADE_KEYSTORE_FILE, CASCADE_MD_FILE, CASCADE_VERSION, COMPLEXITY_T2_COUNT, Cascade, CascadeCancelledError, CascadeIgnore, CascadeRouter, CascadeToolError, ConfigManager, DEFAULT_API_PORT, DEFAULT_APPROVAL_REQUIRED, DEFAULT_AUTO_SUMMARIZE_AT, DEFAULT_CONTEXT_LIMIT, DEFAULT_DASHBOARD_PORT, DEFAULT_MAX_SESSION_MESSAGES, DEFAULT_RETENTION_DAYS, DEFAULT_THEME, DashboardServer, GLOBAL_CONFIG_DIR, GLOBAL_DB_FILE, GLOBAL_KEYSTORE_FILE, GLOBAL_RUNTIME_DB_FILE, HooksRunner, Keystore, LM_STUDIO_BASE_URL, MODELS, McpClient, MemoryStore, OLLAMA_BASE_URL, PROVIDER_DISPLAY_NAMES, T1Administrator, T1_MODEL_PRIORITY, T2Manager, T2_MODEL_PRIORITY, T3Worker, T3_MODEL_PRIORITY, THEME_NAMES, TOOL_NAMES, TaskScheduler, Telemetry, ToolRegistry, VISION_MODEL_PRIORITY, createCascade, nodeHttpFetch, preferIpv4Host, runCascade, streamCascade };
13457
+ export { AZURE_BASE_URL_TEMPLATE, AuditLogger, CASCADE_AUDIT_FILE, CASCADE_CONFIG_DIR, CASCADE_CONFIG_FILE, CASCADE_DASHBOARD_SECRET_FILE, CASCADE_DB_FILE, CASCADE_IGNORE_FILE, CASCADE_KEYSTORE_FILE, CASCADE_MD_FILE, CASCADE_VERSION, COMPLEXITY_T2_COUNT, Cascade, CascadeCancelledError, CascadeIgnore, CascadeRouter, CascadeToolError, ConfigManager, DEFAULT_API_PORT, DEFAULT_APPROVAL_REQUIRED, DEFAULT_AUTO_SUMMARIZE_AT, DEFAULT_CONTEXT_LIMIT, DEFAULT_DASHBOARD_PORT, DEFAULT_MAX_SESSION_MESSAGES, DEFAULT_RETENTION_DAYS, DEFAULT_THEME, DashboardServer, GLOBAL_CONFIG_DIR, GLOBAL_CREDENTIALS_FILE, GLOBAL_DB_FILE, GLOBAL_KEYSTORE_FILE, GLOBAL_RUNTIME_DB_FILE, HooksRunner, Keystore, LM_STUDIO_BASE_URL, MODELS, McpClient, MemoryStore, OLLAMA_BASE_URL, PROVIDER_DISPLAY_NAMES, T1Administrator, T1_MODEL_PRIORITY, T2Manager, T2_MODEL_PRIORITY, T3Worker, T3_MODEL_PRIORITY, THEME_NAMES, TOOL_NAMES, TaskScheduler, Telemetry, ToolRegistry, VISION_MODEL_PRIORITY, createCascade, nodeHttpFetch, preferIpv4Host, runCascade, streamCascade };
13328
13458
  //# sourceMappingURL=index.js.map
13329
13459
  //# sourceMappingURL=index.js.map