cascade-ai 0.12.2 → 0.12.4

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
@@ -4,7 +4,7 @@ import { GoogleGenAI, HarmBlockThreshold, HarmCategory } from '@google/genai';
4
4
  import { render, Box, Text, useStdout, useApp, useInput, Static } from 'ink';
5
5
  import { Command } from 'commander';
6
6
  import React2, { useState, useReducer, useRef, useCallback, useEffect, useMemo } from 'react';
7
- import chalk11 from 'chalk';
7
+ import chalk9 from 'chalk';
8
8
  import dotenv from 'dotenv';
9
9
  import fs21 from 'fs';
10
10
  import path23 from 'path';
@@ -3189,15 +3189,15 @@ function SafeTextInput(props) {
3189
3189
  const displayValue = mask ? mask.repeat(value.length) : value;
3190
3190
  let rendered;
3191
3191
  if (displayValue.length === 0) {
3192
- rendered = showCursor && focus ? placeholder.length > 0 ? chalk11.inverse(placeholder[0]) + chalk11.grey(placeholder.slice(1)) : chalk11.inverse(" ") : placeholder.length > 0 ? chalk11.grey(placeholder) : "";
3192
+ rendered = showCursor && focus ? placeholder.length > 0 ? chalk9.inverse(placeholder[0]) + chalk9.grey(placeholder.slice(1)) : chalk9.inverse(" ") : placeholder.length > 0 ? chalk9.grey(placeholder) : "";
3193
3193
  } else if (!showCursor || !focus) {
3194
3194
  rendered = displayValue;
3195
3195
  } else {
3196
3196
  let out = "";
3197
3197
  for (let i = 0; i < displayValue.length; i++) {
3198
- out += i === cursorOffset ? chalk11.inverse(displayValue[i]) : displayValue[i];
3198
+ out += i === cursorOffset ? chalk9.inverse(displayValue[i]) : displayValue[i];
3199
3199
  }
3200
- if (cursorOffset >= displayValue.length) out += chalk11.inverse(" ");
3200
+ if (cursorOffset >= displayValue.length) out += chalk9.inverse(" ");
3201
3201
  rendered = out;
3202
3202
  }
3203
3203
  return /* @__PURE__ */ jsx(Text, { children: rendered });
@@ -4047,7 +4047,7 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
4047
4047
  }
4048
4048
  for (const tier of ["T1", "T2", "T3"]) {
4049
4049
  const override = tier === "T1" ? config.models.t1 : tier === "T2" ? config.models.t2 : config.models.t3;
4050
- if (!override) continue;
4050
+ if (!override || override === "auto") continue;
4051
4051
  const model = this.selector.selectForTier(tier, override);
4052
4052
  if (!model) {
4053
4053
  const knownProviders = ["anthropic", "openai", "gemini", "azure", "openai-compatible", "ollama"];
@@ -11450,7 +11450,7 @@ function StatusBarInternal({
11450
11450
  const savedStr = savedUsd > 0 ? ` \xB7 saved $${savedUsd.toFixed(4)}` : "";
11451
11451
  const rightStr = ` ${formatTokens(tokens)} \xB7 $${costUsd.toFixed(4)}${savedStr} ${isExecuting ? "\u26A1" : "\xB7"} `;
11452
11452
  const gap = Math.max(0, width - leftStr.length - rightStr.length);
11453
- const line = chalk11.bgHex(theme.colors.primary).hex(theme.colors.background)(chalk11.bold(leftStr) + " ".repeat(gap) + rightStr);
11453
+ const line = chalk9.bgHex(theme.colors.primary).hex(theme.colors.background)(chalk9.bold(leftStr) + " ".repeat(gap) + rightStr);
11454
11454
  return /* @__PURE__ */ jsx(Text, { children: line });
11455
11455
  }
11456
11456
  function formatTokens(n) {
@@ -11861,7 +11861,7 @@ function renderContent(content, theme) {
11861
11861
  i
11862
11862
  );
11863
11863
  }
11864
- const rendered = part.replace(/\*\*(.*?)\*\*/g, (_, t) => chalk11.bold(t)).replace(/`(.*?)`/g, (_, t) => chalk11.bgHex(theme.colors.border)(t));
11864
+ const rendered = part.replace(/\*\*(.*?)\*\*/g, (_, t) => chalk9.bold(t)).replace(/`(.*?)`/g, (_, t) => chalk9.bgHex(theme.colors.border)(t));
11865
11865
  return /* @__PURE__ */ jsx(Text, { wrap: "wrap", children: rendered }, i);
11866
11866
  });
11867
11867
  }
@@ -14067,20 +14067,20 @@ async function initCommand(workspacePath = process.cwd()) {
14067
14067
  const mdPath = path23.join(workspacePath, "CASCADE.md");
14068
14068
  if (!await fileExists(mdPath)) {
14069
14069
  await createDefaultCascadeMd(workspacePath);
14070
- spin.succeed(chalk11.green("Created CASCADE.md"));
14070
+ spin.succeed(chalk9.green("Created CASCADE.md"));
14071
14071
  }
14072
14072
  const ignorePath = path23.join(workspacePath, ".cascadeignore");
14073
14073
  if (!await fileExists(ignorePath)) {
14074
14074
  await createDefaultIgnoreFile(workspacePath);
14075
- spin.succeed(chalk11.green("Created .cascadeignore"));
14075
+ spin.succeed(chalk9.green("Created .cascadeignore"));
14076
14076
  }
14077
14077
  spin.stop();
14078
14078
  console.log();
14079
- console.log(chalk11.magenta(" \u25C8 Cascade AI \u2014 Project initialized"));
14079
+ console.log(chalk9.magenta(" \u25C8 Cascade AI \u2014 Project initialized"));
14080
14080
  console.log();
14081
14081
  const configPath = path23.join(workspacePath, CASCADE_CONFIG_FILE);
14082
14082
  if (await fileExists(configPath)) {
14083
- console.log(chalk11.yellow(" .cascade/config.json already exists \u2014 launching wizard to reconfigure."));
14083
+ console.log(chalk9.yellow(" .cascade/config.json already exists \u2014 launching wizard to reconfigure."));
14084
14084
  console.log();
14085
14085
  }
14086
14086
  const config = await runSetupWizard(workspacePath);
@@ -14088,10 +14088,10 @@ async function initCommand(workspacePath = process.cwd()) {
14088
14088
  await cm.load();
14089
14089
  await cm.updateConfig(config);
14090
14090
  console.log();
14091
- console.log(chalk11.green(" \u25C8 Setup complete! Run `cascade` to start."));
14091
+ console.log(chalk9.green(" \u25C8 Setup complete! Run `cascade` to start."));
14092
14092
  console.log();
14093
14093
  } catch (err) {
14094
- console.error(chalk11.red(`Init failed: ${err instanceof Error ? err.message : String(err)}`));
14094
+ console.error(chalk9.red(`Init failed: ${err instanceof Error ? err.message : String(err)}`));
14095
14095
  process.exit(1);
14096
14096
  }
14097
14097
  }
@@ -14237,7 +14237,7 @@ function maskSecret(secret) {
14237
14237
 
14238
14238
  // src/cli/commands/doctor.ts
14239
14239
  async function doctorCommand() {
14240
- console.log(chalk11.magenta("\n \u25C8 Cascade Doctor \u2014 System Diagnostics\n"));
14240
+ console.log(chalk9.magenta("\n \u25C8 Cascade Doctor \u2014 System Diagnostics\n"));
14241
14241
  const checks = [];
14242
14242
  const nodeVersion = process.versions.node;
14243
14243
  const [major] = nodeVersion.split(".").map(Number);
@@ -14329,22 +14329,22 @@ async function doctorCommand() {
14329
14329
  } catch {
14330
14330
  }
14331
14331
  for (const c of checks) {
14332
- const icon = c.ok ? chalk11.green(" \u2713") : chalk11.yellow(" \u25CB");
14333
- const label = c.ok ? chalk11.white(c.label) : chalk11.gray(c.label);
14334
- const detail = c.detail ? chalk11.gray(` \u2014 ${c.detail}`) : "";
14332
+ const icon = c.ok ? chalk9.green(" \u2713") : chalk9.yellow(" \u25CB");
14333
+ const label = c.ok ? chalk9.white(c.label) : chalk9.gray(c.label);
14334
+ const detail = c.detail ? chalk9.gray(` \u2014 ${c.detail}`) : "";
14335
14335
  console.log(`${icon} ${label}${detail}`);
14336
14336
  }
14337
14337
  const failures = checks.filter((c) => !c.ok);
14338
14338
  console.log();
14339
14339
  if (failures.length === 0) {
14340
- console.log(chalk11.green(" All checks passed!\n"));
14340
+ console.log(chalk9.green(" All checks passed!\n"));
14341
14341
  } else {
14342
14342
  const critical = failures.filter((c) => c.label.includes("Node") || c.label.includes("API key"));
14343
14343
  if (critical.length) {
14344
- console.log(chalk11.yellow(` ${critical.length} issue(s) need attention.
14344
+ console.log(chalk9.yellow(` ${critical.length} issue(s) need attention.
14345
14345
  `));
14346
14346
  } else {
14347
- console.log(chalk11.gray(` ${failures.length} optional item(s) not configured.
14347
+ console.log(chalk9.gray(` ${failures.length} optional item(s) not configured.
14348
14348
  `));
14349
14349
  }
14350
14350
  }
@@ -14371,14 +14371,14 @@ async function updateCommand() {
14371
14371
  const { stdout } = await execAsync2("npm show cascade-ai version", { timeout: 1e4 });
14372
14372
  const latest = stdout.trim().split("\n").filter(Boolean).pop() ?? "";
14373
14373
  if (latest === CASCADE_VERSION) {
14374
- spin.succeed(chalk11.green(`Already up to date (v${CASCADE_VERSION})`));
14374
+ spin.succeed(chalk9.green(`Already up to date (v${CASCADE_VERSION})`));
14375
14375
  return;
14376
14376
  }
14377
14377
  spin.text = `Updating cascade-ai ${CASCADE_VERSION} \u2192 ${latest}\u2026`;
14378
14378
  await execAsync2("npm install -g cascade-ai@latest", { timeout: 6e4 });
14379
- spin.succeed(chalk11.green(`Updated to v${latest}! Restart your terminal.`));
14379
+ spin.succeed(chalk9.green(`Updated to v${latest}! Restart your terminal.`));
14380
14380
  } catch (err) {
14381
- spin.fail(chalk11.red(`Update failed: ${err instanceof Error ? err.message : String(err)}`));
14381
+ spin.fail(chalk9.red(`Update failed: ${err instanceof Error ? err.message : String(err)}`));
14382
14382
  }
14383
14383
  }
14384
14384
  init_constants();
@@ -14543,6 +14543,11 @@ var DashboardSocket = class {
14543
14543
  emitToSocket(socketId, event, data) {
14544
14544
  this.io.sockets.sockets.get(socketId)?.emit(event, data);
14545
14545
  }
14546
+ onConfigGet(callback) {
14547
+ this.io.on("connection", (socket) => {
14548
+ socket.on("config:get", () => callback(socket.id));
14549
+ });
14550
+ }
14546
14551
  onCascadeRun(callback) {
14547
14552
  this.io.on("connection", (socket) => {
14548
14553
  socket.on("cascade:run", (payload) => {
@@ -14592,6 +14597,16 @@ var DashboardServer = class {
14592
14597
  this.socket.onSessionRate((sessionId, rating) => {
14593
14598
  this.activeSessions.get(sessionId)?.rateLastRun(rating);
14594
14599
  });
14600
+ this.socket.onConfigGet((socketId) => {
14601
+ this.socket.emitToSocket(socketId, "config:current", {
14602
+ models: this.config.models ?? {},
14603
+ budget: {
14604
+ maxCostPerRun: this.config.budget?.maxCostPerRunUsd,
14605
+ autoBias: this.config.autoBias
14606
+ },
14607
+ providersWithKey: (this.config.providers ?? []).filter((p) => typeof p.apiKey === "string" && p.apiKey.length > 0).map((p) => p.type)
14608
+ });
14609
+ });
14595
14610
  this.socket.onConfigUpdate((data) => {
14596
14611
  if (data.keys) {
14597
14612
  for (const [type, apiKey] of Object.entries(data.keys)) {
@@ -14602,7 +14617,11 @@ var DashboardServer = class {
14602
14617
  }
14603
14618
  }
14604
14619
  if (data.models) {
14605
- this.config.models = { ...this.config.models, ...data.models };
14620
+ const models = this.config.models;
14621
+ for (const [tier, val] of Object.entries(data.models)) {
14622
+ if (val && val !== "auto") models[tier] = val;
14623
+ else delete models[tier];
14624
+ }
14606
14625
  }
14607
14626
  if (data.budget) {
14608
14627
  if (typeof data.budget.maxCostPerRun === "number") {
@@ -14612,6 +14631,7 @@ var DashboardServer = class {
14612
14631
  this.config.autoBias = data.budget.autoBias;
14613
14632
  }
14614
14633
  }
14634
+ this.persistConfig();
14615
14635
  });
14616
14636
  this.socket.onCascadeRun(async (prompt, model, socketId) => {
14617
14637
  const sessionId = randomUUID();
@@ -14688,6 +14708,20 @@ var DashboardServer = class {
14688
14708
  getSocket() {
14689
14709
  return this.socket;
14690
14710
  }
14711
+ /**
14712
+ * Write the in-memory config back to the workspace config file so mutations
14713
+ * made over the socket (Settings → Save) persist across restarts. Best-effort:
14714
+ * a write failure is logged but never crashes the running dashboard.
14715
+ */
14716
+ persistConfig() {
14717
+ try {
14718
+ const configPath = path23.join(this.workspacePath, CASCADE_CONFIG_FILE);
14719
+ fs21.mkdirSync(path23.dirname(configPath), { recursive: true });
14720
+ fs21.writeFileSync(configPath, JSON.stringify(this.config, null, 2), "utf-8");
14721
+ } catch (err) {
14722
+ console.warn(`[dashboard] Failed to persist config: ${err instanceof Error ? err.message : String(err)}`);
14723
+ }
14724
+ }
14691
14725
  /**
14692
14726
  * Produce a stable dashboard JWT signing secret.
14693
14727
  *
@@ -15187,10 +15221,10 @@ async function dashboardCommand(config, workspacePath = process.cwd()) {
15187
15221
  process.once("exit", onExit);
15188
15222
  try {
15189
15223
  await server.start();
15190
- spin.succeed(chalk11.green(`Dashboard running at http://localhost:${port}`));
15224
+ spin.succeed(chalk9.green(`Dashboard running at http://localhost:${port}`));
15191
15225
  server.refreshRuntime("workspace");
15192
15226
  server.refreshRuntime("global");
15193
- console.log(chalk11.gray(` Press Ctrl+C to stop
15227
+ console.log(chalk9.gray(` Press Ctrl+C to stop
15194
15228
  `));
15195
15229
  await new Promise(() => {
15196
15230
  });
@@ -15199,7 +15233,7 @@ async function dashboardCommand(config, workspacePath = process.cwd()) {
15199
15233
  await server.stop().catch(() => {
15200
15234
  });
15201
15235
  onExit();
15202
- spin.fail(chalk11.red(`Dashboard failed: ${err instanceof Error ? err.message : String(err)}`));
15236
+ spin.fail(chalk9.red(`Dashboard failed: ${err instanceof Error ? err.message : String(err)}`));
15203
15237
  process.exit(1);
15204
15238
  }
15205
15239
  }
@@ -15210,15 +15244,15 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
15210
15244
  const store = new MemoryStore(path23.join(workspacePath, CASCADE_DB_FILE));
15211
15245
  try {
15212
15246
  const identities = store.listIdentities();
15213
- console.log(chalk11.bold("\n Identities:"));
15247
+ console.log(chalk9.bold("\n Identities:"));
15214
15248
  if (identities.length === 0) {
15215
- console.log(chalk11.gray(" No identities found."));
15249
+ console.log(chalk9.gray(" No identities found."));
15216
15250
  } else {
15217
15251
  identities.forEach((id) => {
15218
- const defaultLabel = id.isDefault ? chalk11.green(" [Default]") : "";
15219
- console.log(` - ${chalk11.cyan(id.name)}${defaultLabel}`);
15220
- console.log(chalk11.gray(` ID: ${id.id}`));
15221
- if (id.description) console.log(chalk11.gray(` ${id.description}`));
15252
+ const defaultLabel = id.isDefault ? chalk9.green(" [Default]") : "";
15253
+ console.log(` - ${chalk9.cyan(id.name)}${defaultLabel}`);
15254
+ console.log(chalk9.gray(` ID: ${id.id}`));
15255
+ if (id.description) console.log(chalk9.gray(` ${id.description}`));
15222
15256
  });
15223
15257
  }
15224
15258
  console.log();
@@ -15244,9 +15278,9 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
15244
15278
  isDefault: !!options.default,
15245
15279
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
15246
15280
  });
15247
- console.log(chalk11.green(`
15281
+ console.log(chalk9.green(`
15248
15282
  Successfully created identity: ${name} (${id})`));
15249
- if (options.default) console.log(chalk11.green(" Set as default."));
15283
+ if (options.default) console.log(chalk9.green(" Set as default."));
15250
15284
  console.log();
15251
15285
  } finally {
15252
15286
  store.close();
@@ -15258,7 +15292,7 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
15258
15292
  const identities = store.listIdentities();
15259
15293
  const match = identities.find((i) => i.id === query || i.name.toLowerCase() === query.toLowerCase());
15260
15294
  if (!match) {
15261
- console.error(chalk11.red(`
15295
+ console.error(chalk9.red(`
15262
15296
  Identity '${query}' not found.
15263
15297
  `));
15264
15298
  process.exit(1);
@@ -15268,7 +15302,7 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
15268
15302
  store.updateIdentity(existingDefault.id, { isDefault: false });
15269
15303
  }
15270
15304
  store.updateIdentity(match.id, { isDefault: true });
15271
- console.log(chalk11.green(`
15305
+ console.log(chalk9.green(`
15272
15306
  Identity ${match.name} is now the default.
15273
15307
  `));
15274
15308
  } finally {
@@ -15278,7 +15312,7 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
15278
15312
  return identity;
15279
15313
  }
15280
15314
  async function modelsCommand(options = {}) {
15281
- console.log(chalk11.magenta("\n \u25C8 Cascade Models\n"));
15315
+ console.log(chalk9.magenta("\n \u25C8 Cascade Models\n"));
15282
15316
  const cm = new ConfigManager(process.cwd());
15283
15317
  await cm.load();
15284
15318
  const config = cm.getConfig();
@@ -15286,16 +15320,16 @@ async function modelsCommand(options = {}) {
15286
15320
  try {
15287
15321
  await router.init(config);
15288
15322
  } catch (err) {
15289
- console.error(chalk11.red(` Failed to initialize router: ${err instanceof Error ? err.message : String(err)}`));
15323
+ console.error(chalk9.red(` Failed to initialize router: ${err instanceof Error ? err.message : String(err)}`));
15290
15324
  process.exit(1);
15291
15325
  }
15292
15326
  await withTimeout(router.refreshLiveData(), 6e3, "live data timeout").catch(() => {
15293
15327
  });
15294
15328
  const liveData = router.getLiveData();
15295
15329
  const tiers = [
15296
- { tier: "T1", label: "T1 Administrator", color: chalk11.hex("#7C6AF7") },
15297
- { tier: "T2", label: "T2 Manager", color: chalk11.hex("#5AB4E8") },
15298
- { tier: "T3", label: "T3 Worker", color: chalk11.hex("#5AE8A4") }
15330
+ { tier: "T1", label: "T1 Administrator", color: chalk9.hex("#7C6AF7") },
15331
+ { tier: "T2", label: "T2 Manager", color: chalk9.hex("#5AB4E8") },
15332
+ { tier: "T3", label: "T3 Worker", color: chalk9.hex("#5AE8A4") }
15299
15333
  ];
15300
15334
  let anyMissing = false;
15301
15335
  for (const { tier, label, color } of tiers) {
@@ -15304,48 +15338,72 @@ async function modelsCommand(options = {}) {
15304
15338
  const costIn = model.inputCostPer1kTokens === 0 ? "free" : `$${model.inputCostPer1kTokens.toFixed(4)}/1K in`;
15305
15339
  const costOut = model.outputCostPer1kTokens === 0 ? "free" : `$${model.outputCostPer1kTokens.toFixed(4)}/1K out`;
15306
15340
  const ctx = model.contextWindow >= 1e6 ? `${(model.contextWindow / 1e6).toFixed(1)}M ctx` : `${(model.contextWindow / 1e3).toFixed(0)}K ctx`;
15307
- const local = model.isLocal ? chalk11.gray(" [local]") : "";
15308
- const vision = model.isVisionCapable ? chalk11.gray(" \u{1F441}") : "";
15341
+ const local = model.isLocal ? chalk9.gray(" [local]") : "";
15342
+ const vision = model.isVisionCapable ? chalk9.gray(" \u{1F441}") : "";
15309
15343
  const bench = Math.round(benchmarkScore01(model, "mixed") * 100);
15310
15344
  console.log(
15311
- ` ${color.bold(tier)} ${chalk11.white(col(model.name, 24))}${chalk11.gray(col(model.provider, 16))}` + (options.verbose ? `${chalk11.gray(col(ctx, 12))}${chalk11.gray(col(`bench ${bench}/100`, 14))}${chalk11.gray(`${costIn}, ${costOut}`)}` : `${chalk11.gray(col(ctx, 10))}${chalk11.gray(`bench ${bench}/100`)}`) + local + vision
15345
+ ` ${color.bold(tier)} ${chalk9.white(col(model.name, 24))}${chalk9.gray(col(model.provider, 16))}` + (options.verbose ? `${chalk9.gray(col(ctx, 12))}${chalk9.gray(col(`bench ${bench}/100`, 14))}${chalk9.gray(`${costIn}, ${costOut}`)}` : `${chalk9.gray(col(ctx, 10))}${chalk9.gray(`bench ${bench}/100`)}`) + local + vision
15312
15346
  );
15313
15347
  } else {
15314
- console.log(` ${color.bold(tier)} ${chalk11.red("No model available")} ${chalk11.gray(`(check provider config for ${label})`)}`);
15348
+ console.log(` ${color.bold(tier)} ${chalk9.red("No model available")} ${chalk9.gray(`(check provider config for ${label})`)}`);
15315
15349
  anyMissing = true;
15316
15350
  }
15317
15351
  }
15318
15352
  console.log();
15319
15353
  const providers = config.providers.map((p) => p.type).join(", ") || "(none)";
15320
- console.log(chalk11.gray(` Configured providers: ${providers}`));
15354
+ console.log(chalk9.gray(` Configured providers: ${providers}`));
15321
15355
  if (liveData) {
15322
15356
  const src = liveData.getDataSource();
15323
15357
  const gen = liveData.getGeneratedAt();
15324
15358
  const srcLabel = src === "live" ? "live (just fetched)" : src === "cache" ? "cached" : "bundled";
15325
- console.log(chalk11.gray(
15359
+ console.log(chalk9.gray(
15326
15360
  ` Benchmark data: ${srcLabel}` + (gen ? ` \xB7 updated ${gen.slice(0, 10)}` : "") + ` \xB7 pricing: ${liveData.hasLivePricing() ? "live (OpenRouter)" : "catalog"}`
15327
15361
  ));
15328
15362
  }
15329
15363
  if (options.verbose) {
15330
15364
  console.log();
15331
- console.log(chalk11.white(" Available models by provider:\n"));
15365
+ console.log(chalk9.white(" Available models by provider:\n"));
15332
15366
  const allProviderTypes = [...new Set(config.providers.map((p) => p.type))];
15333
15367
  for (const providerType of allProviderTypes) {
15334
15368
  const available = router.getModelsForProvider(providerType);
15335
15369
  if (available.length === 0) continue;
15336
- console.log(chalk11.gray(` ${providerType}:`));
15370
+ console.log(chalk9.gray(` ${providerType}:`));
15337
15371
  for (const m of available) {
15338
15372
  const override = config.models.t1 === m.id ? " \u2190 T1" : config.models.t2 === m.id ? " \u2190 T2" : config.models.t3 === m.id ? " \u2190 T3" : "";
15339
- console.log(` ${chalk11.white(col(m.name, 28))}${chalk11.gray(m.id)}${chalk11.yellow(override)}`);
15373
+ console.log(` ${chalk9.white(col(m.name, 28))}${chalk9.gray(m.id)}${chalk9.yellow(override)}`);
15340
15374
  }
15341
15375
  console.log();
15342
15376
  }
15343
15377
  }
15344
15378
  if (anyMissing) {
15345
- console.log(chalk11.yellow(" Some tiers have no available model. Run `cascade doctor` for details.\n"));
15379
+ console.log(chalk9.yellow(" Some tiers have no available model. Run `cascade doctor` for details.\n"));
15346
15380
  } else {
15347
- console.log(chalk11.green(" All tiers are configured.\n"));
15381
+ console.log(chalk9.green(" All tiers are configured.\n"));
15382
+ }
15383
+ }
15384
+ async function setModelCommand(action, tierArg, value) {
15385
+ const tier = (tierArg ?? "").toLowerCase();
15386
+ if (!["t1", "t2", "t3"].includes(tier)) {
15387
+ console.error(chalk9.red(` Invalid tier "${tierArg ?? ""}". Use t1, t2, or t3.`));
15388
+ console.log(chalk9.gray(" e.g. cascade models set t1 anthropic:claude-opus-4-8"));
15389
+ process.exit(1);
15390
+ }
15391
+ const override = action === "unset" ? "auto" : (value ?? "").trim();
15392
+ if (action === "set" && !override) {
15393
+ console.error(chalk9.red(' Missing value. e.g. cascade models set t3 openai:gpt-4o-mini (or "auto")'));
15394
+ process.exit(1);
15348
15395
  }
15396
+ const cm = new ConfigManager(process.cwd());
15397
+ await cm.load();
15398
+ const config = cm.getConfig();
15399
+ const models = { ...config.models };
15400
+ if (override === "auto") delete models[tier];
15401
+ else models[tier] = override;
15402
+ await cm.updateConfig({ models });
15403
+ const label = override === "auto" ? chalk9.gray("auto (routing decides)") : chalk9.white(override);
15404
+ console.log(chalk9.green(`
15405
+ \u2713 ${tier.toUpperCase()} model set to ${label}
15406
+ `));
15349
15407
  }
15350
15408
  function col(s, width) {
15351
15409
  return s.length < width ? s.padEnd(width) : `${s} `;
@@ -15367,7 +15425,7 @@ async function exportCommand(options = {}) {
15367
15425
  }
15368
15426
  store = new MemoryStore(dbPath);
15369
15427
  } catch (err) {
15370
- spin.fail(chalk11.red(`Cannot open memory store: ${err instanceof Error ? err.message : String(err)}`));
15428
+ spin.fail(chalk9.red(`Cannot open memory store: ${err instanceof Error ? err.message : String(err)}`));
15371
15429
  process.exit(1);
15372
15430
  }
15373
15431
  try {
@@ -15375,7 +15433,7 @@ async function exportCommand(options = {}) {
15375
15433
  if (options.sessionId) {
15376
15434
  const session2 = store.getSession(options.sessionId);
15377
15435
  if (!session2) {
15378
- spin.fail(chalk11.red(`Session "${options.sessionId}" not found.`));
15436
+ spin.fail(chalk9.red(`Session "${options.sessionId}" not found.`));
15379
15437
  process.exit(1);
15380
15438
  }
15381
15439
  sessions = [session2];
@@ -15383,14 +15441,14 @@ async function exportCommand(options = {}) {
15383
15441
  const limit = options.last ?? 10;
15384
15442
  sessions = store.listSessions(void 0, limit);
15385
15443
  if (sessions.length === 0) {
15386
- spin.warn(chalk11.yellow("No sessions found."));
15444
+ spin.warn(chalk9.yellow("No sessions found."));
15387
15445
  return;
15388
15446
  }
15389
15447
  const latest = sessions[0];
15390
15448
  const full = store.getSession(latest.id);
15391
15449
  sessions = full ? [full] : [];
15392
15450
  if (sessions.length === 0) {
15393
- spin.fail(chalk11.red("Could not load latest session."));
15451
+ spin.fail(chalk9.red("Could not load latest session."));
15394
15452
  process.exit(1);
15395
15453
  }
15396
15454
  }
@@ -15402,15 +15460,15 @@ async function exportCommand(options = {}) {
15402
15460
  const defaultFile = `cascade-export-${safeName}${ext}`;
15403
15461
  const outPath = options.output ? path23.resolve(options.output) : path23.join(process.cwd(), defaultFile);
15404
15462
  await fs9.writeFile(outPath, content, "utf-8");
15405
- spin.succeed(chalk11.green(`Exported to ${chalk11.white(outPath)}`));
15463
+ spin.succeed(chalk9.green(`Exported to ${chalk9.white(outPath)}`));
15406
15464
  const messageCount = Array.isArray(session.messages) ? session.messages.length : 0;
15407
15465
  console.log();
15408
- console.log(chalk11.gray(` Session: ${session.title}`));
15409
- console.log(chalk11.gray(` Messages: ${messageCount}`));
15410
- console.log(chalk11.gray(` Format: ${format}`));
15466
+ console.log(chalk9.gray(` Session: ${session.title}`));
15467
+ console.log(chalk9.gray(` Messages: ${messageCount}`));
15468
+ console.log(chalk9.gray(` Format: ${format}`));
15411
15469
  console.log();
15412
15470
  } catch (err) {
15413
- spin.fail(chalk11.red(`Export failed: ${err instanceof Error ? err.message : String(err)}`));
15471
+ spin.fail(chalk9.red(`Export failed: ${err instanceof Error ? err.message : String(err)}`));
15414
15472
  process.exit(1);
15415
15473
  }
15416
15474
  }
@@ -15467,9 +15525,9 @@ function buildJsonExport(session) {
15467
15525
  async function linkCommand(target, options = {}) {
15468
15526
  const found = await discoverCredentials();
15469
15527
  if (found.length === 0) {
15470
- console.log(chalk11.yellow("\n No reusable credentials found.\n"));
15471
- console.log(chalk11.gray(" Cascade looks for Claude Code, Codex, Gemini CLI, and GitHub Copilot logins,"));
15472
- console.log(chalk11.gray(" plus ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY in your environment.\n"));
15528
+ console.log(chalk9.yellow("\n No reusable credentials found.\n"));
15529
+ console.log(chalk9.gray(" Cascade looks for Claude Code, Codex, Gemini CLI, and GitHub Copilot logins,"));
15530
+ console.log(chalk9.gray(" plus ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY in your environment.\n"));
15473
15531
  return;
15474
15532
  }
15475
15533
  if (!target) {
@@ -15478,7 +15536,7 @@ async function linkCommand(target, options = {}) {
15478
15536
  }
15479
15537
  const provider = normalizeProvider(target);
15480
15538
  if (!provider) {
15481
- console.log(chalk11.red(`
15539
+ console.log(chalk9.red(`
15482
15540
  Unknown provider "${target}". Use one of: anthropic, openai, gemini.
15483
15541
  `));
15484
15542
  return;
@@ -15486,46 +15544,46 @@ async function linkCommand(target, options = {}) {
15486
15544
  const candidates2 = found.filter((c) => c.provider === provider);
15487
15545
  const chosen = candidates2.find((c) => c.directlyUsable) ?? candidates2[0];
15488
15546
  if (!chosen) {
15489
- console.log(chalk11.yellow(`
15547
+ console.log(chalk9.yellow(`
15490
15548
  No detected credential maps to "${provider}".
15491
15549
  `));
15492
15550
  return;
15493
15551
  }
15494
15552
  if (!chosen.directlyUsable) {
15495
- console.log(chalk11.yellow(`
15553
+ console.log(chalk9.yellow(`
15496
15554
  Found a ${chosen.sourceTool} credential, but it can't be used against the standard ${provider} API.`));
15497
- if (chosen.warning) console.log(chalk11.gray(` ${chosen.warning}`));
15498
- console.log(chalk11.gray(" Cascade won't adopt it because it would create a non-working provider.\n"));
15555
+ if (chosen.warning) console.log(chalk9.gray(` ${chosen.warning}`));
15556
+ console.log(chalk9.gray(" Cascade won't adopt it because it would create a non-working provider.\n"));
15499
15557
  return;
15500
15558
  }
15501
15559
  if (chosen.kind === "oauth" && !options.acceptRisk) {
15502
- console.log(chalk11.yellow(`
15560
+ console.log(chalk9.yellow(`
15503
15561
  ${chosen.sourceTool} provides a subscription OAuth token, not an API key.`));
15504
- if (chosen.warning) console.log(chalk11.gray(` ${chosen.warning}`));
15505
- console.log(chalk11.gray(" Re-run with --accept-risk to adopt it anyway:\n"));
15506
- console.log(chalk11.cyan(` cascade link ${provider} --accept-risk
15562
+ if (chosen.warning) console.log(chalk9.gray(` ${chosen.warning}`));
15563
+ console.log(chalk9.gray(" Re-run with --accept-risk to adopt it anyway:\n"));
15564
+ console.log(chalk9.cyan(` cascade link ${provider} --accept-risk
15507
15565
  `));
15508
15566
  return;
15509
15567
  }
15510
15568
  await adoptCredential(chosen, options.workspace ?? process.cwd());
15511
- console.log(chalk11.green(`
15569
+ console.log(chalk9.green(`
15512
15570
  \u2713 Linked ${provider} using your ${chosen.sourceTool} credential (${maskSecret(chosen.secret)}).`));
15513
15571
  if (chosen.kind === "oauth") {
15514
- console.log(chalk11.gray(" Adopted as an OAuth bearer token \u2014 revoke it in the source tool to disable."));
15572
+ console.log(chalk9.gray(" Adopted as an OAuth bearer token \u2014 revoke it in the source tool to disable."));
15515
15573
  }
15516
- console.log(chalk11.gray(" Run `cascade doctor` to verify, or `cascade` to start.\n"));
15574
+ console.log(chalk9.gray(" Run `cascade doctor` to verify, or `cascade` to start.\n"));
15517
15575
  }
15518
15576
  function printDiscovered(found) {
15519
- console.log(chalk11.magenta("\n \u25C8 Detected credentials\n"));
15577
+ console.log(chalk9.magenta("\n \u25C8 Detected credentials\n"));
15520
15578
  for (const c of found) {
15521
- const usable = c.directlyUsable ? chalk11.green("usable") : chalk11.yellow("needs vendor backend");
15522
- const kind = c.kind === "oauth" ? chalk11.yellow("oauth") : chalk11.gray("api-key");
15523
- console.log(` ${chalk11.white(c.provider.padEnd(18))} ${chalk11.gray(maskSecret(c.secret).padEnd(12))} ${kind} ${usable}`);
15524
- console.log(chalk11.gray(` from ${c.sourceTool}`));
15525
- if (c.warning) console.log(chalk11.yellow(` \u26A0 ${c.warning}`));
15579
+ const usable = c.directlyUsable ? chalk9.green("usable") : chalk9.yellow("needs vendor backend");
15580
+ const kind = c.kind === "oauth" ? chalk9.yellow("oauth") : chalk9.gray("api-key");
15581
+ console.log(` ${chalk9.white(c.provider.padEnd(18))} ${chalk9.gray(maskSecret(c.secret).padEnd(12))} ${kind} ${usable}`);
15582
+ console.log(chalk9.gray(` from ${c.sourceTool}`));
15583
+ if (c.warning) console.log(chalk9.yellow(` \u26A0 ${c.warning}`));
15526
15584
  }
15527
- console.log(chalk11.gray("\n Adopt one with: ") + chalk11.cyan("cascade link <provider> [--accept-risk]"));
15528
- console.log(chalk11.gray(" --accept-risk is required for subscription OAuth tokens.\n"));
15585
+ console.log(chalk9.gray("\n Adopt one with: ") + chalk9.cyan("cascade link <provider> [--accept-risk]"));
15586
+ console.log(chalk9.gray(" --accept-risk is required for subscription OAuth tokens.\n"));
15529
15587
  }
15530
15588
  function normalizeProvider(target) {
15531
15589
  const t = target.toLowerCase();
@@ -15558,12 +15616,12 @@ async function telemetryCommand(action) {
15558
15616
  if (action === "status") {
15559
15617
  const state = config.telemetry?.enabled ? "ON" : "OFF";
15560
15618
  console.log();
15561
- console.log(chalk11.magenta(" \u25C8 Cascade Telemetry"));
15619
+ console.log(chalk9.magenta(" \u25C8 Cascade Telemetry"));
15562
15620
  console.log();
15563
- console.log(` Status: ${config.telemetry?.enabled ? chalk11.green(state) : chalk11.gray(state)}`);
15564
- console.log(chalk11.gray(" Scope: anonymous session metadata only (no prompts/outputs)"));
15621
+ console.log(` Status: ${config.telemetry?.enabled ? chalk9.green(state) : chalk9.gray(state)}`);
15622
+ console.log(chalk9.gray(" Scope: anonymous session metadata only (no prompts/outputs)"));
15565
15623
  console.log();
15566
- console.log(chalk11.gray(" Toggle with: cascade telemetry on | cascade telemetry off"));
15624
+ console.log(chalk9.gray(" Toggle with: cascade telemetry on | cascade telemetry off"));
15567
15625
  console.log();
15568
15626
  return;
15569
15627
  }
@@ -15577,11 +15635,11 @@ async function telemetryCommand(action) {
15577
15635
  });
15578
15636
  console.log();
15579
15637
  if (enabled) {
15580
- console.log(chalk11.green(` \u2713 Telemetry enabled.`));
15581
- console.log(chalk11.gray(" Anonymous session metadata (no prompts, no outputs) will be sent."));
15638
+ console.log(chalk9.green(` \u2713 Telemetry enabled.`));
15639
+ console.log(chalk9.gray(" Anonymous session metadata (no prompts, no outputs) will be sent."));
15582
15640
  } else {
15583
- console.log(chalk11.yellow(` \u2713 Telemetry disabled.`));
15584
- console.log(chalk11.gray(" No events will be transmitted from this workspace."));
15641
+ console.log(chalk9.yellow(` \u2713 Telemetry disabled.`));
15642
+ console.log(chalk9.gray(" No events will be transmitted from this workspace."));
15585
15643
  }
15586
15644
  console.log();
15587
15645
  }
@@ -15591,11 +15649,11 @@ async function statsCommand() {
15591
15649
  await tracker.load();
15592
15650
  const all = tracker.getAll();
15593
15651
  if (all.size === 0) {
15594
- console.log(chalk11.dim("\n No routing history yet \u2014 run some tasks first.\n"));
15652
+ console.log(chalk9.dim("\n No routing history yet \u2014 run some tasks first.\n"));
15595
15653
  return;
15596
15654
  }
15597
- console.log(chalk11.magenta("\n \u25C8 Auto-Routing History\n"));
15598
- console.log(chalk11.dim(" Per-task-type model performance learned from past runs.\n"));
15655
+ console.log(chalk9.magenta("\n \u25C8 Auto-Routing History\n"));
15656
+ console.log(chalk9.dim(" Per-task-type model performance learned from past runs.\n"));
15599
15657
  for (const taskType of TASK_TYPES) {
15600
15658
  const entries = [];
15601
15659
  for (const [key, stat] of all) {
@@ -15607,21 +15665,21 @@ async function statsCommand() {
15607
15665
  }
15608
15666
  if (entries.length === 0) continue;
15609
15667
  entries.sort((a, b) => b.successRate - a.successRate || b.samples - a.samples);
15610
- console.log(chalk11.bold(` ${taskType.toUpperCase()}`));
15668
+ console.log(chalk9.bold(` ${taskType.toUpperCase()}`));
15611
15669
  const header = ` ${"Model".padEnd(36)} ${"Success".padEnd(9)} ${"Samples".padEnd(9)} Avg cost`;
15612
- console.log(chalk11.dim(header));
15613
- console.log(chalk11.dim(" " + "\u2500".repeat(62)));
15670
+ console.log(chalk9.dim(header));
15671
+ console.log(chalk9.dim(" " + "\u2500".repeat(62)));
15614
15672
  for (const e of entries) {
15615
15673
  const pct = `${Math.round(e.successRate * 100)}%`;
15616
15674
  const cost = e.avgCostUsd < 1e-4 ? "<$0.0001" : `$${e.avgCostUsd.toFixed(4)}`;
15617
- const color = e.successRate >= 0.8 ? chalk11.green : e.successRate >= 0.5 ? chalk11.yellow : chalk11.red;
15675
+ const color = e.successRate >= 0.8 ? chalk9.green : e.successRate >= 0.5 ? chalk9.yellow : chalk9.red;
15618
15676
  console.log(
15619
- ` ${e.modelId.padEnd(36)} ${color(pct.padEnd(9))} ${String(e.samples).padEnd(9)} ${chalk11.dim(cost)}`
15677
+ ` ${e.modelId.padEnd(36)} ${color(pct.padEnd(9))} ${String(e.samples).padEnd(9)} ${chalk9.dim(cost)}`
15620
15678
  );
15621
15679
  }
15622
15680
  console.log();
15623
15681
  }
15624
- console.log(chalk11.dim(" tip: use /rate good | bad after a task to improve these scores.\n"));
15682
+ console.log(chalk9.dim(" tip: use /rate good | bad after a task to improve these scores.\n"));
15625
15683
  }
15626
15684
 
15627
15685
  // src/cli/index.ts
@@ -15636,7 +15694,7 @@ function warnIfBuildIsStale() {
15636
15694
  if (pkg.name !== "cascade-ai") continue;
15637
15695
  if (pkg.version && pkg.version !== CASCADE_VERSION) {
15638
15696
  console.error(
15639
- chalk11.yellow(
15697
+ chalk9.yellow(
15640
15698
  `\u26A0 Stale build: compiled output is v${CASCADE_VERSION} but the source tree is v${pkg.version}.
15641
15699
  Run: npm install && npm run build`
15642
15700
  )
@@ -15704,13 +15762,17 @@ program.command("dashboard").description("Launch the web dashboard").option("-p,
15704
15762
  program.command("run <prompt>").description("Run a single prompt and exit").option("-t, --theme <name>", "Color theme", DEFAULT_THEME).option("-i, --identity <name>", "Identity name or ID").action(async (prompt, opts) => {
15705
15763
  await runHeadless(prompt, { theme: opts.theme, workspace: process.cwd(), identity: opts.identity });
15706
15764
  });
15707
- program.command("models").description("List available AI models for each tier").option("-v, --verbose", "Show all models per provider with pricing").action(async (opts) => {
15708
- await modelsCommand({ verbose: opts.verbose });
15765
+ program.command("models [action] [tier] [value]").description("List AI models per tier, or set/unset a tier provider+model (e.g. models set t1 anthropic:claude-opus-4-8)").option("-v, --verbose", "Show all models per provider with pricing").action(async (action, tier, value, opts) => {
15766
+ if (action === "set" || action === "unset") {
15767
+ await setModelCommand(action, tier, value);
15768
+ } else {
15769
+ await modelsCommand({ verbose: opts.verbose });
15770
+ }
15709
15771
  });
15710
15772
  program.command("telemetry [action]").description("Toggle anonymous usage telemetry (on | off | status). Default: status").action(async (action) => {
15711
15773
  const normalized = (action ?? "status").toLowerCase();
15712
15774
  if (normalized !== "on" && normalized !== "off" && normalized !== "status") {
15713
- console.error(chalk11.red(`Unknown action: ${action}. Use: on | off | status`));
15775
+ console.error(chalk9.red(`Unknown action: ${action}. Use: on | off | status`));
15714
15776
  process.exit(1);
15715
15777
  }
15716
15778
  await telemetryCommand(normalized);
@@ -15732,14 +15794,14 @@ async function startRepl(options) {
15732
15794
  try {
15733
15795
  await cm.load();
15734
15796
  } catch (err) {
15735
- console.error(chalk11.red(`Config error: ${err instanceof Error ? err.message : String(err)}`));
15736
- console.error(chalk11.gray("Run `cascade init` to set up this directory."));
15797
+ console.error(chalk9.red(`Config error: ${err instanceof Error ? err.message : String(err)}`));
15798
+ console.error(chalk9.gray("Run `cascade init` to set up this directory."));
15737
15799
  process.exit(1);
15738
15800
  }
15739
15801
  let config = cm.getConfig();
15740
15802
  const needsSetup = !config.providers?.length || config.providers.every((p) => p.type !== "ollama" && !p.apiKey);
15741
15803
  if (needsSetup) {
15742
- console.log(chalk11.magenta(" \u25C8 No providers configured \u2014 launching setup wizard\u2026"));
15804
+ console.log(chalk9.magenta(" \u25C8 No providers configured \u2014 launching setup wizard\u2026"));
15743
15805
  console.log();
15744
15806
  config = await runSetupWizard(workspacePath);
15745
15807
  await cm.updateConfig(config);
@@ -15773,24 +15835,24 @@ async function runHeadless(prompt, options) {
15773
15835
  try {
15774
15836
  await cm.load();
15775
15837
  } catch (err) {
15776
- console.error(chalk11.red(`Config error: ${err instanceof Error ? err.message : String(err)}`));
15777
- console.error(chalk11.gray("Run `cascade init` to set up this directory."));
15838
+ console.error(chalk9.red(`Config error: ${err instanceof Error ? err.message : String(err)}`));
15839
+ console.error(chalk9.gray("Run `cascade init` to set up this directory."));
15778
15840
  process.exit(1);
15779
15841
  }
15780
15842
  const config = cm.getConfig();
15781
15843
  const needsSetup = !config.providers?.length || config.providers.every((p) => p.type !== "ollama" && !p.apiKey);
15782
15844
  if (needsSetup) {
15783
- console.error(chalk11.red("No providers configured. Run `cascade init` first."));
15845
+ console.error(chalk9.red("No providers configured. Run `cascade init` first."));
15784
15846
  process.exit(1);
15785
15847
  }
15786
15848
  const cascade = new Cascade(config, workspacePath);
15787
15849
  try {
15788
15850
  await cascade.init();
15789
15851
  } catch (err) {
15790
- console.error(chalk11.red(`Initialization failed: ${err instanceof Error ? err.message : String(err)}`));
15852
+ console.error(chalk9.red(`Initialization failed: ${err instanceof Error ? err.message : String(err)}`));
15791
15853
  process.exit(1);
15792
15854
  }
15793
- console.error(chalk11.gray(" \u25C8 Running headlessly \u2014 tool approvals are auto-granted."));
15855
+ console.error(chalk9.gray(" \u25C8 Running headlessly \u2014 tool approvals are auto-granted."));
15794
15856
  let lastProgress = "";
15795
15857
  cascade.on("tier:status", (ev) => {
15796
15858
  const action = ev?.currentAction?.trim();
@@ -15798,7 +15860,7 @@ async function runHeadless(prompt, options) {
15798
15860
  const line = ` \xB7 ${ev.role ?? ""} ${action}`.trimEnd();
15799
15861
  if (line === lastProgress) return;
15800
15862
  lastProgress = line;
15801
- console.error(chalk11.gray(line));
15863
+ console.error(chalk9.gray(line));
15802
15864
  });
15803
15865
  try {
15804
15866
  const result = await cascade.run({
@@ -15809,7 +15871,7 @@ async function runHeadless(prompt, options) {
15809
15871
  });
15810
15872
  process.stdout.write(result.output.trimEnd() + "\n");
15811
15873
  } catch (err) {
15812
- console.error(chalk11.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
15874
+ console.error(chalk9.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
15813
15875
  await cascade.close().catch(() => {
15814
15876
  });
15815
15877
  process.exit(1);
@@ -15821,10 +15883,10 @@ async function runHeadless(prompt, options) {
15821
15883
  function printBanner() {
15822
15884
  if (process.stdout.columns < 60) return;
15823
15885
  console.log();
15824
- console.log(chalk11.hex("#7C6AF7").bold(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
15825
- console.log(chalk11.hex("#7C6AF7").bold(" \u2551") + chalk11.white.bold(" \u25C8 CASCADE AI") + chalk11.gray(" v" + CASCADE_VERSION + " ") + chalk11.hex("#7C6AF7").bold("\u2551"));
15826
- console.log(chalk11.hex("#7C6AF7").bold(" \u2551") + chalk11.gray(" Multi-Tier Orchestration ") + chalk11.hex("#7C6AF7").bold("\u2551"));
15827
- console.log(chalk11.hex("#7C6AF7").bold(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
15886
+ console.log(chalk9.hex("#7C6AF7").bold(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
15887
+ console.log(chalk9.hex("#7C6AF7").bold(" \u2551") + chalk9.white.bold(" \u25C8 CASCADE AI") + chalk9.gray(" v" + CASCADE_VERSION + " ") + chalk9.hex("#7C6AF7").bold("\u2551"));
15888
+ console.log(chalk9.hex("#7C6AF7").bold(" \u2551") + chalk9.gray(" Multi-Tier Orchestration ") + chalk9.hex("#7C6AF7").bold("\u2551"));
15889
+ console.log(chalk9.hex("#7C6AF7").bold(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
15828
15890
  console.log();
15829
15891
  }
15830
15892
  program.parse(process.argv);