cascade-ai 0.12.3 → 0.12.5
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.cjs +186 -210
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +185 -209
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +38 -94
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +38 -94
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/keytar-VMICNFEJ.node +0 -0
package/dist/cli.cjs
CHANGED
|
@@ -6,7 +6,7 @@ var genai = require('@google/genai');
|
|
|
6
6
|
var ink = require('ink');
|
|
7
7
|
var commander = require('commander');
|
|
8
8
|
var React2 = require('react');
|
|
9
|
-
var
|
|
9
|
+
var chalk9 = require('chalk');
|
|
10
10
|
var dotenv = require('dotenv');
|
|
11
11
|
var fs21 = require('fs');
|
|
12
12
|
var path23 = require('path');
|
|
@@ -64,7 +64,7 @@ function _interopNamespace(e) {
|
|
|
64
64
|
var Anthropic__default = /*#__PURE__*/_interopDefault(Anthropic);
|
|
65
65
|
var OpenAI__default = /*#__PURE__*/_interopDefault(OpenAI);
|
|
66
66
|
var React2__default = /*#__PURE__*/_interopDefault(React2);
|
|
67
|
-
var
|
|
67
|
+
var chalk9__default = /*#__PURE__*/_interopDefault(chalk9);
|
|
68
68
|
var dotenv__default = /*#__PURE__*/_interopDefault(dotenv);
|
|
69
69
|
var fs21__default = /*#__PURE__*/_interopDefault(fs21);
|
|
70
70
|
var path23__default = /*#__PURE__*/_interopDefault(path23);
|
|
@@ -87,50 +87,21 @@ var parser__default = /*#__PURE__*/_interopDefault(parser);
|
|
|
87
87
|
var jwt__default = /*#__PURE__*/_interopDefault(jwt);
|
|
88
88
|
|
|
89
89
|
// Cascade AI — Multi-tier AI Orchestration System
|
|
90
|
-
var __create = Object.create;
|
|
91
90
|
var __defProp = Object.defineProperty;
|
|
92
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
93
91
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
94
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
95
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
96
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
97
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
98
|
-
}) : x)(function(x) {
|
|
99
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
100
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
101
|
-
});
|
|
102
92
|
var __esm = (fn, res) => function __init() {
|
|
103
93
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
104
94
|
};
|
|
105
|
-
var __commonJS = (cb, mod) => function __require2() {
|
|
106
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
107
|
-
};
|
|
108
95
|
var __export = (target, all) => {
|
|
109
96
|
for (var name in all)
|
|
110
97
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
111
98
|
};
|
|
112
|
-
var __copyProps = (to, from, except, desc) => {
|
|
113
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
114
|
-
for (let key of __getOwnPropNames(from))
|
|
115
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
116
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
117
|
-
}
|
|
118
|
-
return to;
|
|
119
|
-
};
|
|
120
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
121
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
122
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
123
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
124
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
125
|
-
__defProp(target, "default", { value: mod, enumerable: true }) ,
|
|
126
|
-
mod
|
|
127
|
-
));
|
|
128
99
|
|
|
129
100
|
// src/constants.ts
|
|
130
101
|
var CASCADE_VERSION, CASCADE_CONFIG_FILE, CASCADE_DB_FILE, CASCADE_DASHBOARD_SECRET_FILE, GLOBAL_CONFIG_DIR, GLOBAL_DB_FILE, GLOBAL_KEYSTORE_FILE, GLOBAL_RUNTIME_DB_FILE, DEFAULT_DASHBOARD_PORT, DEFAULT_CONTEXT_LIMIT, DEFAULT_AUTO_SUMMARIZE_AT, MODELS, T1_MODEL_PRIORITY, T2_MODEL_PRIORITY, T3_MODEL_PRIORITY, VISION_MODEL_PRIORITY, COMPLEXITY_T2_COUNT, THEME_NAMES, DEFAULT_THEME, OLLAMA_BASE_URL, LM_STUDIO_BASE_URL, AZURE_BASE_URL_TEMPLATE, TOOL_NAMES, DEFAULT_APPROVAL_REQUIRED;
|
|
131
102
|
var init_constants = __esm({
|
|
132
103
|
"src/constants.ts"() {
|
|
133
|
-
CASCADE_VERSION = "0.
|
|
104
|
+
CASCADE_VERSION = "0.12.5";
|
|
134
105
|
CASCADE_CONFIG_FILE = ".cascade/config.json";
|
|
135
106
|
CASCADE_DB_FILE = ".cascade/memory.db";
|
|
136
107
|
CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
|
|
@@ -446,63 +417,6 @@ var init_constants = __esm({
|
|
|
446
417
|
}
|
|
447
418
|
});
|
|
448
419
|
|
|
449
|
-
// node_modules/keytar/build/Release/keytar.node
|
|
450
|
-
var keytar_default;
|
|
451
|
-
var init_keytar = __esm({
|
|
452
|
-
"node_modules/keytar/build/Release/keytar.node"() {
|
|
453
|
-
keytar_default = "./keytar-VMICNFEJ.node";
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
|
|
457
|
-
// node-file:/home/runner/work/Cascade-AI/Cascade-AI/node_modules/keytar/build/Release/keytar.node
|
|
458
|
-
var require_keytar = __commonJS({
|
|
459
|
-
"node-file:/home/runner/work/Cascade-AI/Cascade-AI/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
460
|
-
init_keytar();
|
|
461
|
-
try {
|
|
462
|
-
module.exports = __require(keytar_default);
|
|
463
|
-
} catch {
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
// node_modules/keytar/lib/keytar.js
|
|
469
|
-
var require_keytar2 = __commonJS({
|
|
470
|
-
"node_modules/keytar/lib/keytar.js"(exports, module) {
|
|
471
|
-
var keytar = require_keytar();
|
|
472
|
-
function checkRequired(val, name) {
|
|
473
|
-
if (!val || val.length <= 0) {
|
|
474
|
-
throw new Error(name + " is required.");
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
module.exports = {
|
|
478
|
-
getPassword: function(service, account) {
|
|
479
|
-
checkRequired(service, "Service");
|
|
480
|
-
checkRequired(account, "Account");
|
|
481
|
-
return keytar.getPassword(service, account);
|
|
482
|
-
},
|
|
483
|
-
setPassword: function(service, account, password) {
|
|
484
|
-
checkRequired(service, "Service");
|
|
485
|
-
checkRequired(account, "Account");
|
|
486
|
-
checkRequired(password, "Password");
|
|
487
|
-
return keytar.setPassword(service, account, password);
|
|
488
|
-
},
|
|
489
|
-
deletePassword: function(service, account) {
|
|
490
|
-
checkRequired(service, "Service");
|
|
491
|
-
checkRequired(account, "Account");
|
|
492
|
-
return keytar.deletePassword(service, account);
|
|
493
|
-
},
|
|
494
|
-
findPassword: function(service) {
|
|
495
|
-
checkRequired(service, "Service");
|
|
496
|
-
return keytar.findPassword(service);
|
|
497
|
-
},
|
|
498
|
-
findCredentials: function(service) {
|
|
499
|
-
checkRequired(service, "Service");
|
|
500
|
-
return keytar.findCredentials(service);
|
|
501
|
-
}
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
|
-
});
|
|
505
|
-
|
|
506
420
|
// src/providers/base.ts
|
|
507
421
|
var BaseProvider;
|
|
508
422
|
var init_base = __esm({
|
|
@@ -1512,7 +1426,7 @@ var PBKDF2_ITERATIONS = 1e5;
|
|
|
1512
1426
|
var KEYTAR_SERVICE = "cascade-ai";
|
|
1513
1427
|
async function loadKeytar() {
|
|
1514
1428
|
try {
|
|
1515
|
-
const mod = await
|
|
1429
|
+
const mod = await import('keytar');
|
|
1516
1430
|
const candidate = mod.default ?? mod;
|
|
1517
1431
|
if (typeof candidate.getPassword !== "function") return null;
|
|
1518
1432
|
return candidate;
|
|
@@ -3236,15 +3150,15 @@ function SafeTextInput(props) {
|
|
|
3236
3150
|
const displayValue = mask ? mask.repeat(value.length) : value;
|
|
3237
3151
|
let rendered;
|
|
3238
3152
|
if (displayValue.length === 0) {
|
|
3239
|
-
rendered = showCursor && focus ? placeholder.length > 0 ?
|
|
3153
|
+
rendered = showCursor && focus ? placeholder.length > 0 ? chalk9__default.default.inverse(placeholder[0]) + chalk9__default.default.grey(placeholder.slice(1)) : chalk9__default.default.inverse(" ") : placeholder.length > 0 ? chalk9__default.default.grey(placeholder) : "";
|
|
3240
3154
|
} else if (!showCursor || !focus) {
|
|
3241
3155
|
rendered = displayValue;
|
|
3242
3156
|
} else {
|
|
3243
3157
|
let out = "";
|
|
3244
3158
|
for (let i = 0; i < displayValue.length; i++) {
|
|
3245
|
-
out += i === cursorOffset ?
|
|
3159
|
+
out += i === cursorOffset ? chalk9__default.default.inverse(displayValue[i]) : displayValue[i];
|
|
3246
3160
|
}
|
|
3247
|
-
if (cursorOffset >= displayValue.length) out +=
|
|
3161
|
+
if (cursorOffset >= displayValue.length) out += chalk9__default.default.inverse(" ");
|
|
3248
3162
|
rendered = out;
|
|
3249
3163
|
}
|
|
3250
3164
|
return /* @__PURE__ */ jsxRuntime.jsx(ink.Text, { children: rendered });
|
|
@@ -4094,7 +4008,7 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter__default.default {
|
|
|
4094
4008
|
}
|
|
4095
4009
|
for (const tier of ["T1", "T2", "T3"]) {
|
|
4096
4010
|
const override = tier === "T1" ? config.models.t1 : tier === "T2" ? config.models.t2 : config.models.t3;
|
|
4097
|
-
if (!override) continue;
|
|
4011
|
+
if (!override || override === "auto") continue;
|
|
4098
4012
|
const model = this.selector.selectForTier(tier, override);
|
|
4099
4013
|
if (!model) {
|
|
4100
4014
|
const knownProviders = ["anthropic", "openai", "gemini", "azure", "openai-compatible", "ollama"];
|
|
@@ -11497,7 +11411,7 @@ function StatusBarInternal({
|
|
|
11497
11411
|
const savedStr = savedUsd > 0 ? ` \xB7 saved $${savedUsd.toFixed(4)}` : "";
|
|
11498
11412
|
const rightStr = ` ${formatTokens(tokens)} \xB7 $${costUsd.toFixed(4)}${savedStr} ${isExecuting ? "\u26A1" : "\xB7"} `;
|
|
11499
11413
|
const gap = Math.max(0, width - leftStr.length - rightStr.length);
|
|
11500
|
-
const line =
|
|
11414
|
+
const line = chalk9__default.default.bgHex(theme.colors.primary).hex(theme.colors.background)(chalk9__default.default.bold(leftStr) + " ".repeat(gap) + rightStr);
|
|
11501
11415
|
return /* @__PURE__ */ jsxRuntime.jsx(ink.Text, { children: line });
|
|
11502
11416
|
}
|
|
11503
11417
|
function formatTokens(n) {
|
|
@@ -11908,7 +11822,7 @@ function renderContent(content, theme) {
|
|
|
11908
11822
|
i
|
|
11909
11823
|
);
|
|
11910
11824
|
}
|
|
11911
|
-
const rendered = part.replace(/\*\*(.*?)\*\*/g, (_, t) =>
|
|
11825
|
+
const rendered = part.replace(/\*\*(.*?)\*\*/g, (_, t) => chalk9__default.default.bold(t)).replace(/`(.*?)`/g, (_, t) => chalk9__default.default.bgHex(theme.colors.border)(t));
|
|
11912
11826
|
return /* @__PURE__ */ jsxRuntime.jsx(ink.Text, { wrap: "wrap", children: rendered }, i);
|
|
11913
11827
|
});
|
|
11914
11828
|
}
|
|
@@ -14114,20 +14028,20 @@ async function initCommand(workspacePath = process.cwd()) {
|
|
|
14114
14028
|
const mdPath = path23__default.default.join(workspacePath, "CASCADE.md");
|
|
14115
14029
|
if (!await fileExists(mdPath)) {
|
|
14116
14030
|
await createDefaultCascadeMd(workspacePath);
|
|
14117
|
-
spin.succeed(
|
|
14031
|
+
spin.succeed(chalk9__default.default.green("Created CASCADE.md"));
|
|
14118
14032
|
}
|
|
14119
14033
|
const ignorePath = path23__default.default.join(workspacePath, ".cascadeignore");
|
|
14120
14034
|
if (!await fileExists(ignorePath)) {
|
|
14121
14035
|
await createDefaultIgnoreFile(workspacePath);
|
|
14122
|
-
spin.succeed(
|
|
14036
|
+
spin.succeed(chalk9__default.default.green("Created .cascadeignore"));
|
|
14123
14037
|
}
|
|
14124
14038
|
spin.stop();
|
|
14125
14039
|
console.log();
|
|
14126
|
-
console.log(
|
|
14040
|
+
console.log(chalk9__default.default.magenta(" \u25C8 Cascade AI \u2014 Project initialized"));
|
|
14127
14041
|
console.log();
|
|
14128
14042
|
const configPath = path23__default.default.join(workspacePath, CASCADE_CONFIG_FILE);
|
|
14129
14043
|
if (await fileExists(configPath)) {
|
|
14130
|
-
console.log(
|
|
14044
|
+
console.log(chalk9__default.default.yellow(" .cascade/config.json already exists \u2014 launching wizard to reconfigure."));
|
|
14131
14045
|
console.log();
|
|
14132
14046
|
}
|
|
14133
14047
|
const config = await runSetupWizard(workspacePath);
|
|
@@ -14135,10 +14049,10 @@ async function initCommand(workspacePath = process.cwd()) {
|
|
|
14135
14049
|
await cm.load();
|
|
14136
14050
|
await cm.updateConfig(config);
|
|
14137
14051
|
console.log();
|
|
14138
|
-
console.log(
|
|
14052
|
+
console.log(chalk9__default.default.green(" \u25C8 Setup complete! Run `cascade` to start."));
|
|
14139
14053
|
console.log();
|
|
14140
14054
|
} catch (err) {
|
|
14141
|
-
console.error(
|
|
14055
|
+
console.error(chalk9__default.default.red(`Init failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
14142
14056
|
process.exit(1);
|
|
14143
14057
|
}
|
|
14144
14058
|
}
|
|
@@ -14284,7 +14198,7 @@ function maskSecret(secret) {
|
|
|
14284
14198
|
|
|
14285
14199
|
// src/cli/commands/doctor.ts
|
|
14286
14200
|
async function doctorCommand() {
|
|
14287
|
-
console.log(
|
|
14201
|
+
console.log(chalk9__default.default.magenta("\n \u25C8 Cascade Doctor \u2014 System Diagnostics\n"));
|
|
14288
14202
|
const checks = [];
|
|
14289
14203
|
const nodeVersion = process.versions.node;
|
|
14290
14204
|
const [major] = nodeVersion.split(".").map(Number);
|
|
@@ -14348,7 +14262,7 @@ async function doctorCommand() {
|
|
|
14348
14262
|
});
|
|
14349
14263
|
let keystoreBackend = "file (AES-256-GCM)";
|
|
14350
14264
|
try {
|
|
14351
|
-
await
|
|
14265
|
+
await import('keytar');
|
|
14352
14266
|
keystoreBackend = "keytar (OS keychain)";
|
|
14353
14267
|
} catch {
|
|
14354
14268
|
}
|
|
@@ -14376,22 +14290,22 @@ async function doctorCommand() {
|
|
|
14376
14290
|
} catch {
|
|
14377
14291
|
}
|
|
14378
14292
|
for (const c of checks) {
|
|
14379
|
-
const icon = c.ok ?
|
|
14380
|
-
const label = c.ok ?
|
|
14381
|
-
const detail = c.detail ?
|
|
14293
|
+
const icon = c.ok ? chalk9__default.default.green(" \u2713") : chalk9__default.default.yellow(" \u25CB");
|
|
14294
|
+
const label = c.ok ? chalk9__default.default.white(c.label) : chalk9__default.default.gray(c.label);
|
|
14295
|
+
const detail = c.detail ? chalk9__default.default.gray(` \u2014 ${c.detail}`) : "";
|
|
14382
14296
|
console.log(`${icon} ${label}${detail}`);
|
|
14383
14297
|
}
|
|
14384
14298
|
const failures = checks.filter((c) => !c.ok);
|
|
14385
14299
|
console.log();
|
|
14386
14300
|
if (failures.length === 0) {
|
|
14387
|
-
console.log(
|
|
14301
|
+
console.log(chalk9__default.default.green(" All checks passed!\n"));
|
|
14388
14302
|
} else {
|
|
14389
14303
|
const critical = failures.filter((c) => c.label.includes("Node") || c.label.includes("API key"));
|
|
14390
14304
|
if (critical.length) {
|
|
14391
|
-
console.log(
|
|
14305
|
+
console.log(chalk9__default.default.yellow(` ${critical.length} issue(s) need attention.
|
|
14392
14306
|
`));
|
|
14393
14307
|
} else {
|
|
14394
|
-
console.log(
|
|
14308
|
+
console.log(chalk9__default.default.gray(` ${failures.length} optional item(s) not configured.
|
|
14395
14309
|
`));
|
|
14396
14310
|
}
|
|
14397
14311
|
}
|
|
@@ -14418,14 +14332,14 @@ async function updateCommand() {
|
|
|
14418
14332
|
const { stdout } = await execAsync2("npm show cascade-ai version", { timeout: 1e4 });
|
|
14419
14333
|
const latest = stdout.trim().split("\n").filter(Boolean).pop() ?? "";
|
|
14420
14334
|
if (latest === CASCADE_VERSION) {
|
|
14421
|
-
spin.succeed(
|
|
14335
|
+
spin.succeed(chalk9__default.default.green(`Already up to date (v${CASCADE_VERSION})`));
|
|
14422
14336
|
return;
|
|
14423
14337
|
}
|
|
14424
14338
|
spin.text = `Updating cascade-ai ${CASCADE_VERSION} \u2192 ${latest}\u2026`;
|
|
14425
14339
|
await execAsync2("npm install -g cascade-ai@latest", { timeout: 6e4 });
|
|
14426
|
-
spin.succeed(
|
|
14340
|
+
spin.succeed(chalk9__default.default.green(`Updated to v${latest}! Restart your terminal.`));
|
|
14427
14341
|
} catch (err) {
|
|
14428
|
-
spin.fail(
|
|
14342
|
+
spin.fail(chalk9__default.default.red(`Update failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
14429
14343
|
}
|
|
14430
14344
|
}
|
|
14431
14345
|
init_constants();
|
|
@@ -14590,6 +14504,11 @@ var DashboardSocket = class {
|
|
|
14590
14504
|
emitToSocket(socketId, event, data) {
|
|
14591
14505
|
this.io.sockets.sockets.get(socketId)?.emit(event, data);
|
|
14592
14506
|
}
|
|
14507
|
+
onConfigGet(callback) {
|
|
14508
|
+
this.io.on("connection", (socket) => {
|
|
14509
|
+
socket.on("config:get", () => callback(socket.id));
|
|
14510
|
+
});
|
|
14511
|
+
}
|
|
14593
14512
|
onCascadeRun(callback) {
|
|
14594
14513
|
this.io.on("connection", (socket) => {
|
|
14595
14514
|
socket.on("cascade:run", (payload) => {
|
|
@@ -14639,6 +14558,16 @@ var DashboardServer = class {
|
|
|
14639
14558
|
this.socket.onSessionRate((sessionId, rating) => {
|
|
14640
14559
|
this.activeSessions.get(sessionId)?.rateLastRun(rating);
|
|
14641
14560
|
});
|
|
14561
|
+
this.socket.onConfigGet((socketId) => {
|
|
14562
|
+
this.socket.emitToSocket(socketId, "config:current", {
|
|
14563
|
+
models: this.config.models ?? {},
|
|
14564
|
+
budget: {
|
|
14565
|
+
maxCostPerRun: this.config.budget?.maxCostPerRunUsd,
|
|
14566
|
+
autoBias: this.config.autoBias
|
|
14567
|
+
},
|
|
14568
|
+
providersWithKey: (this.config.providers ?? []).filter((p) => typeof p.apiKey === "string" && p.apiKey.length > 0).map((p) => p.type)
|
|
14569
|
+
});
|
|
14570
|
+
});
|
|
14642
14571
|
this.socket.onConfigUpdate((data) => {
|
|
14643
14572
|
if (data.keys) {
|
|
14644
14573
|
for (const [type, apiKey] of Object.entries(data.keys)) {
|
|
@@ -14649,7 +14578,11 @@ var DashboardServer = class {
|
|
|
14649
14578
|
}
|
|
14650
14579
|
}
|
|
14651
14580
|
if (data.models) {
|
|
14652
|
-
|
|
14581
|
+
const models = this.config.models;
|
|
14582
|
+
for (const [tier, val] of Object.entries(data.models)) {
|
|
14583
|
+
if (val && val !== "auto") models[tier] = val;
|
|
14584
|
+
else delete models[tier];
|
|
14585
|
+
}
|
|
14653
14586
|
}
|
|
14654
14587
|
if (data.budget) {
|
|
14655
14588
|
if (typeof data.budget.maxCostPerRun === "number") {
|
|
@@ -14659,6 +14592,7 @@ var DashboardServer = class {
|
|
|
14659
14592
|
this.config.autoBias = data.budget.autoBias;
|
|
14660
14593
|
}
|
|
14661
14594
|
}
|
|
14595
|
+
this.persistConfig();
|
|
14662
14596
|
});
|
|
14663
14597
|
this.socket.onCascadeRun(async (prompt, model, socketId) => {
|
|
14664
14598
|
const sessionId = crypto.randomUUID();
|
|
@@ -14735,6 +14669,20 @@ var DashboardServer = class {
|
|
|
14735
14669
|
getSocket() {
|
|
14736
14670
|
return this.socket;
|
|
14737
14671
|
}
|
|
14672
|
+
/**
|
|
14673
|
+
* Write the in-memory config back to the workspace config file so mutations
|
|
14674
|
+
* made over the socket (Settings → Save) persist across restarts. Best-effort:
|
|
14675
|
+
* a write failure is logged but never crashes the running dashboard.
|
|
14676
|
+
*/
|
|
14677
|
+
persistConfig() {
|
|
14678
|
+
try {
|
|
14679
|
+
const configPath = path23__default.default.join(this.workspacePath, CASCADE_CONFIG_FILE);
|
|
14680
|
+
fs21__default.default.mkdirSync(path23__default.default.dirname(configPath), { recursive: true });
|
|
14681
|
+
fs21__default.default.writeFileSync(configPath, JSON.stringify(this.config, null, 2), "utf-8");
|
|
14682
|
+
} catch (err) {
|
|
14683
|
+
console.warn(`[dashboard] Failed to persist config: ${err instanceof Error ? err.message : String(err)}`);
|
|
14684
|
+
}
|
|
14685
|
+
}
|
|
14738
14686
|
/**
|
|
14739
14687
|
* Produce a stable dashboard JWT signing secret.
|
|
14740
14688
|
*
|
|
@@ -15234,10 +15182,10 @@ async function dashboardCommand(config, workspacePath = process.cwd()) {
|
|
|
15234
15182
|
process.once("exit", onExit);
|
|
15235
15183
|
try {
|
|
15236
15184
|
await server.start();
|
|
15237
|
-
spin.succeed(
|
|
15185
|
+
spin.succeed(chalk9__default.default.green(`Dashboard running at http://localhost:${port}`));
|
|
15238
15186
|
server.refreshRuntime("workspace");
|
|
15239
15187
|
server.refreshRuntime("global");
|
|
15240
|
-
console.log(
|
|
15188
|
+
console.log(chalk9__default.default.gray(` Press Ctrl+C to stop
|
|
15241
15189
|
`));
|
|
15242
15190
|
await new Promise(() => {
|
|
15243
15191
|
});
|
|
@@ -15246,7 +15194,7 @@ async function dashboardCommand(config, workspacePath = process.cwd()) {
|
|
|
15246
15194
|
await server.stop().catch(() => {
|
|
15247
15195
|
});
|
|
15248
15196
|
onExit();
|
|
15249
|
-
spin.fail(
|
|
15197
|
+
spin.fail(chalk9__default.default.red(`Dashboard failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
15250
15198
|
process.exit(1);
|
|
15251
15199
|
}
|
|
15252
15200
|
}
|
|
@@ -15257,15 +15205,15 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
|
|
|
15257
15205
|
const store = new MemoryStore(path23__default.default.join(workspacePath, CASCADE_DB_FILE));
|
|
15258
15206
|
try {
|
|
15259
15207
|
const identities = store.listIdentities();
|
|
15260
|
-
console.log(
|
|
15208
|
+
console.log(chalk9__default.default.bold("\n Identities:"));
|
|
15261
15209
|
if (identities.length === 0) {
|
|
15262
|
-
console.log(
|
|
15210
|
+
console.log(chalk9__default.default.gray(" No identities found."));
|
|
15263
15211
|
} else {
|
|
15264
15212
|
identities.forEach((id) => {
|
|
15265
|
-
const defaultLabel = id.isDefault ?
|
|
15266
|
-
console.log(` - ${
|
|
15267
|
-
console.log(
|
|
15268
|
-
if (id.description) console.log(
|
|
15213
|
+
const defaultLabel = id.isDefault ? chalk9__default.default.green(" [Default]") : "";
|
|
15214
|
+
console.log(` - ${chalk9__default.default.cyan(id.name)}${defaultLabel}`);
|
|
15215
|
+
console.log(chalk9__default.default.gray(` ID: ${id.id}`));
|
|
15216
|
+
if (id.description) console.log(chalk9__default.default.gray(` ${id.description}`));
|
|
15269
15217
|
});
|
|
15270
15218
|
}
|
|
15271
15219
|
console.log();
|
|
@@ -15291,9 +15239,9 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
|
|
|
15291
15239
|
isDefault: !!options.default,
|
|
15292
15240
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
15293
15241
|
});
|
|
15294
|
-
console.log(
|
|
15242
|
+
console.log(chalk9__default.default.green(`
|
|
15295
15243
|
Successfully created identity: ${name} (${id})`));
|
|
15296
|
-
if (options.default) console.log(
|
|
15244
|
+
if (options.default) console.log(chalk9__default.default.green(" Set as default."));
|
|
15297
15245
|
console.log();
|
|
15298
15246
|
} finally {
|
|
15299
15247
|
store.close();
|
|
@@ -15305,7 +15253,7 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
|
|
|
15305
15253
|
const identities = store.listIdentities();
|
|
15306
15254
|
const match = identities.find((i) => i.id === query || i.name.toLowerCase() === query.toLowerCase());
|
|
15307
15255
|
if (!match) {
|
|
15308
|
-
console.error(
|
|
15256
|
+
console.error(chalk9__default.default.red(`
|
|
15309
15257
|
Identity '${query}' not found.
|
|
15310
15258
|
`));
|
|
15311
15259
|
process.exit(1);
|
|
@@ -15315,7 +15263,7 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
|
|
|
15315
15263
|
store.updateIdentity(existingDefault.id, { isDefault: false });
|
|
15316
15264
|
}
|
|
15317
15265
|
store.updateIdentity(match.id, { isDefault: true });
|
|
15318
|
-
console.log(
|
|
15266
|
+
console.log(chalk9__default.default.green(`
|
|
15319
15267
|
Identity ${match.name} is now the default.
|
|
15320
15268
|
`));
|
|
15321
15269
|
} finally {
|
|
@@ -15325,7 +15273,7 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
|
|
|
15325
15273
|
return identity;
|
|
15326
15274
|
}
|
|
15327
15275
|
async function modelsCommand(options = {}) {
|
|
15328
|
-
console.log(
|
|
15276
|
+
console.log(chalk9__default.default.magenta("\n \u25C8 Cascade Models\n"));
|
|
15329
15277
|
const cm = new ConfigManager(process.cwd());
|
|
15330
15278
|
await cm.load();
|
|
15331
15279
|
const config = cm.getConfig();
|
|
@@ -15333,16 +15281,16 @@ async function modelsCommand(options = {}) {
|
|
|
15333
15281
|
try {
|
|
15334
15282
|
await router.init(config);
|
|
15335
15283
|
} catch (err) {
|
|
15336
|
-
console.error(
|
|
15284
|
+
console.error(chalk9__default.default.red(` Failed to initialize router: ${err instanceof Error ? err.message : String(err)}`));
|
|
15337
15285
|
process.exit(1);
|
|
15338
15286
|
}
|
|
15339
15287
|
await withTimeout(router.refreshLiveData(), 6e3, "live data timeout").catch(() => {
|
|
15340
15288
|
});
|
|
15341
15289
|
const liveData = router.getLiveData();
|
|
15342
15290
|
const tiers = [
|
|
15343
|
-
{ tier: "T1", label: "T1 Administrator", color:
|
|
15344
|
-
{ tier: "T2", label: "T2 Manager", color:
|
|
15345
|
-
{ tier: "T3", label: "T3 Worker", color:
|
|
15291
|
+
{ tier: "T1", label: "T1 Administrator", color: chalk9__default.default.hex("#7C6AF7") },
|
|
15292
|
+
{ tier: "T2", label: "T2 Manager", color: chalk9__default.default.hex("#5AB4E8") },
|
|
15293
|
+
{ tier: "T3", label: "T3 Worker", color: chalk9__default.default.hex("#5AE8A4") }
|
|
15346
15294
|
];
|
|
15347
15295
|
let anyMissing = false;
|
|
15348
15296
|
for (const { tier, label, color } of tiers) {
|
|
@@ -15351,48 +15299,72 @@ async function modelsCommand(options = {}) {
|
|
|
15351
15299
|
const costIn = model.inputCostPer1kTokens === 0 ? "free" : `$${model.inputCostPer1kTokens.toFixed(4)}/1K in`;
|
|
15352
15300
|
const costOut = model.outputCostPer1kTokens === 0 ? "free" : `$${model.outputCostPer1kTokens.toFixed(4)}/1K out`;
|
|
15353
15301
|
const ctx = model.contextWindow >= 1e6 ? `${(model.contextWindow / 1e6).toFixed(1)}M ctx` : `${(model.contextWindow / 1e3).toFixed(0)}K ctx`;
|
|
15354
|
-
const local = model.isLocal ?
|
|
15355
|
-
const vision = model.isVisionCapable ?
|
|
15302
|
+
const local = model.isLocal ? chalk9__default.default.gray(" [local]") : "";
|
|
15303
|
+
const vision = model.isVisionCapable ? chalk9__default.default.gray(" \u{1F441}") : "";
|
|
15356
15304
|
const bench = Math.round(benchmarkScore01(model, "mixed") * 100);
|
|
15357
15305
|
console.log(
|
|
15358
|
-
` ${color.bold(tier)} ${
|
|
15306
|
+
` ${color.bold(tier)} ${chalk9__default.default.white(col(model.name, 24))}${chalk9__default.default.gray(col(model.provider, 16))}` + (options.verbose ? `${chalk9__default.default.gray(col(ctx, 12))}${chalk9__default.default.gray(col(`bench ${bench}/100`, 14))}${chalk9__default.default.gray(`${costIn}, ${costOut}`)}` : `${chalk9__default.default.gray(col(ctx, 10))}${chalk9__default.default.gray(`bench ${bench}/100`)}`) + local + vision
|
|
15359
15307
|
);
|
|
15360
15308
|
} else {
|
|
15361
|
-
console.log(` ${color.bold(tier)} ${
|
|
15309
|
+
console.log(` ${color.bold(tier)} ${chalk9__default.default.red("No model available")} ${chalk9__default.default.gray(`(check provider config for ${label})`)}`);
|
|
15362
15310
|
anyMissing = true;
|
|
15363
15311
|
}
|
|
15364
15312
|
}
|
|
15365
15313
|
console.log();
|
|
15366
15314
|
const providers = config.providers.map((p) => p.type).join(", ") || "(none)";
|
|
15367
|
-
console.log(
|
|
15315
|
+
console.log(chalk9__default.default.gray(` Configured providers: ${providers}`));
|
|
15368
15316
|
if (liveData) {
|
|
15369
15317
|
const src = liveData.getDataSource();
|
|
15370
15318
|
const gen = liveData.getGeneratedAt();
|
|
15371
15319
|
const srcLabel = src === "live" ? "live (just fetched)" : src === "cache" ? "cached" : "bundled";
|
|
15372
|
-
console.log(
|
|
15320
|
+
console.log(chalk9__default.default.gray(
|
|
15373
15321
|
` Benchmark data: ${srcLabel}` + (gen ? ` \xB7 updated ${gen.slice(0, 10)}` : "") + ` \xB7 pricing: ${liveData.hasLivePricing() ? "live (OpenRouter)" : "catalog"}`
|
|
15374
15322
|
));
|
|
15375
15323
|
}
|
|
15376
15324
|
if (options.verbose) {
|
|
15377
15325
|
console.log();
|
|
15378
|
-
console.log(
|
|
15326
|
+
console.log(chalk9__default.default.white(" Available models by provider:\n"));
|
|
15379
15327
|
const allProviderTypes = [...new Set(config.providers.map((p) => p.type))];
|
|
15380
15328
|
for (const providerType of allProviderTypes) {
|
|
15381
15329
|
const available = router.getModelsForProvider(providerType);
|
|
15382
15330
|
if (available.length === 0) continue;
|
|
15383
|
-
console.log(
|
|
15331
|
+
console.log(chalk9__default.default.gray(` ${providerType}:`));
|
|
15384
15332
|
for (const m of available) {
|
|
15385
15333
|
const override = config.models.t1 === m.id ? " \u2190 T1" : config.models.t2 === m.id ? " \u2190 T2" : config.models.t3 === m.id ? " \u2190 T3" : "";
|
|
15386
|
-
console.log(` ${
|
|
15334
|
+
console.log(` ${chalk9__default.default.white(col(m.name, 28))}${chalk9__default.default.gray(m.id)}${chalk9__default.default.yellow(override)}`);
|
|
15387
15335
|
}
|
|
15388
15336
|
console.log();
|
|
15389
15337
|
}
|
|
15390
15338
|
}
|
|
15391
15339
|
if (anyMissing) {
|
|
15392
|
-
console.log(
|
|
15340
|
+
console.log(chalk9__default.default.yellow(" Some tiers have no available model. Run `cascade doctor` for details.\n"));
|
|
15393
15341
|
} else {
|
|
15394
|
-
console.log(
|
|
15342
|
+
console.log(chalk9__default.default.green(" All tiers are configured.\n"));
|
|
15343
|
+
}
|
|
15344
|
+
}
|
|
15345
|
+
async function setModelCommand(action, tierArg, value) {
|
|
15346
|
+
const tier = (tierArg ?? "").toLowerCase();
|
|
15347
|
+
if (!["t1", "t2", "t3"].includes(tier)) {
|
|
15348
|
+
console.error(chalk9__default.default.red(` Invalid tier "${tierArg ?? ""}". Use t1, t2, or t3.`));
|
|
15349
|
+
console.log(chalk9__default.default.gray(" e.g. cascade models set t1 anthropic:claude-opus-4-8"));
|
|
15350
|
+
process.exit(1);
|
|
15351
|
+
}
|
|
15352
|
+
const override = action === "unset" ? "auto" : (value ?? "").trim();
|
|
15353
|
+
if (action === "set" && !override) {
|
|
15354
|
+
console.error(chalk9__default.default.red(' Missing value. e.g. cascade models set t3 openai:gpt-4o-mini (or "auto")'));
|
|
15355
|
+
process.exit(1);
|
|
15395
15356
|
}
|
|
15357
|
+
const cm = new ConfigManager(process.cwd());
|
|
15358
|
+
await cm.load();
|
|
15359
|
+
const config = cm.getConfig();
|
|
15360
|
+
const models = { ...config.models };
|
|
15361
|
+
if (override === "auto") delete models[tier];
|
|
15362
|
+
else models[tier] = override;
|
|
15363
|
+
await cm.updateConfig({ models });
|
|
15364
|
+
const label = override === "auto" ? chalk9__default.default.gray("auto (routing decides)") : chalk9__default.default.white(override);
|
|
15365
|
+
console.log(chalk9__default.default.green(`
|
|
15366
|
+
\u2713 ${tier.toUpperCase()} model set to ${label}
|
|
15367
|
+
`));
|
|
15396
15368
|
}
|
|
15397
15369
|
function col(s, width) {
|
|
15398
15370
|
return s.length < width ? s.padEnd(width) : `${s} `;
|
|
@@ -15414,7 +15386,7 @@ async function exportCommand(options = {}) {
|
|
|
15414
15386
|
}
|
|
15415
15387
|
store = new MemoryStore(dbPath);
|
|
15416
15388
|
} catch (err) {
|
|
15417
|
-
spin.fail(
|
|
15389
|
+
spin.fail(chalk9__default.default.red(`Cannot open memory store: ${err instanceof Error ? err.message : String(err)}`));
|
|
15418
15390
|
process.exit(1);
|
|
15419
15391
|
}
|
|
15420
15392
|
try {
|
|
@@ -15422,7 +15394,7 @@ async function exportCommand(options = {}) {
|
|
|
15422
15394
|
if (options.sessionId) {
|
|
15423
15395
|
const session2 = store.getSession(options.sessionId);
|
|
15424
15396
|
if (!session2) {
|
|
15425
|
-
spin.fail(
|
|
15397
|
+
spin.fail(chalk9__default.default.red(`Session "${options.sessionId}" not found.`));
|
|
15426
15398
|
process.exit(1);
|
|
15427
15399
|
}
|
|
15428
15400
|
sessions = [session2];
|
|
@@ -15430,14 +15402,14 @@ async function exportCommand(options = {}) {
|
|
|
15430
15402
|
const limit = options.last ?? 10;
|
|
15431
15403
|
sessions = store.listSessions(void 0, limit);
|
|
15432
15404
|
if (sessions.length === 0) {
|
|
15433
|
-
spin.warn(
|
|
15405
|
+
spin.warn(chalk9__default.default.yellow("No sessions found."));
|
|
15434
15406
|
return;
|
|
15435
15407
|
}
|
|
15436
15408
|
const latest = sessions[0];
|
|
15437
15409
|
const full = store.getSession(latest.id);
|
|
15438
15410
|
sessions = full ? [full] : [];
|
|
15439
15411
|
if (sessions.length === 0) {
|
|
15440
|
-
spin.fail(
|
|
15412
|
+
spin.fail(chalk9__default.default.red("Could not load latest session."));
|
|
15441
15413
|
process.exit(1);
|
|
15442
15414
|
}
|
|
15443
15415
|
}
|
|
@@ -15449,15 +15421,15 @@ async function exportCommand(options = {}) {
|
|
|
15449
15421
|
const defaultFile = `cascade-export-${safeName}${ext}`;
|
|
15450
15422
|
const outPath = options.output ? path23__default.default.resolve(options.output) : path23__default.default.join(process.cwd(), defaultFile);
|
|
15451
15423
|
await fs9__default.default.writeFile(outPath, content, "utf-8");
|
|
15452
|
-
spin.succeed(
|
|
15424
|
+
spin.succeed(chalk9__default.default.green(`Exported to ${chalk9__default.default.white(outPath)}`));
|
|
15453
15425
|
const messageCount = Array.isArray(session.messages) ? session.messages.length : 0;
|
|
15454
15426
|
console.log();
|
|
15455
|
-
console.log(
|
|
15456
|
-
console.log(
|
|
15457
|
-
console.log(
|
|
15427
|
+
console.log(chalk9__default.default.gray(` Session: ${session.title}`));
|
|
15428
|
+
console.log(chalk9__default.default.gray(` Messages: ${messageCount}`));
|
|
15429
|
+
console.log(chalk9__default.default.gray(` Format: ${format}`));
|
|
15458
15430
|
console.log();
|
|
15459
15431
|
} catch (err) {
|
|
15460
|
-
spin.fail(
|
|
15432
|
+
spin.fail(chalk9__default.default.red(`Export failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
15461
15433
|
process.exit(1);
|
|
15462
15434
|
}
|
|
15463
15435
|
}
|
|
@@ -15514,9 +15486,9 @@ function buildJsonExport(session) {
|
|
|
15514
15486
|
async function linkCommand(target, options = {}) {
|
|
15515
15487
|
const found = await discoverCredentials();
|
|
15516
15488
|
if (found.length === 0) {
|
|
15517
|
-
console.log(
|
|
15518
|
-
console.log(
|
|
15519
|
-
console.log(
|
|
15489
|
+
console.log(chalk9__default.default.yellow("\n No reusable credentials found.\n"));
|
|
15490
|
+
console.log(chalk9__default.default.gray(" Cascade looks for Claude Code, Codex, Gemini CLI, and GitHub Copilot logins,"));
|
|
15491
|
+
console.log(chalk9__default.default.gray(" plus ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY in your environment.\n"));
|
|
15520
15492
|
return;
|
|
15521
15493
|
}
|
|
15522
15494
|
if (!target) {
|
|
@@ -15525,7 +15497,7 @@ async function linkCommand(target, options = {}) {
|
|
|
15525
15497
|
}
|
|
15526
15498
|
const provider = normalizeProvider(target);
|
|
15527
15499
|
if (!provider) {
|
|
15528
|
-
console.log(
|
|
15500
|
+
console.log(chalk9__default.default.red(`
|
|
15529
15501
|
Unknown provider "${target}". Use one of: anthropic, openai, gemini.
|
|
15530
15502
|
`));
|
|
15531
15503
|
return;
|
|
@@ -15533,46 +15505,46 @@ async function linkCommand(target, options = {}) {
|
|
|
15533
15505
|
const candidates2 = found.filter((c) => c.provider === provider);
|
|
15534
15506
|
const chosen = candidates2.find((c) => c.directlyUsable) ?? candidates2[0];
|
|
15535
15507
|
if (!chosen) {
|
|
15536
|
-
console.log(
|
|
15508
|
+
console.log(chalk9__default.default.yellow(`
|
|
15537
15509
|
No detected credential maps to "${provider}".
|
|
15538
15510
|
`));
|
|
15539
15511
|
return;
|
|
15540
15512
|
}
|
|
15541
15513
|
if (!chosen.directlyUsable) {
|
|
15542
|
-
console.log(
|
|
15514
|
+
console.log(chalk9__default.default.yellow(`
|
|
15543
15515
|
Found a ${chosen.sourceTool} credential, but it can't be used against the standard ${provider} API.`));
|
|
15544
|
-
if (chosen.warning) console.log(
|
|
15545
|
-
console.log(
|
|
15516
|
+
if (chosen.warning) console.log(chalk9__default.default.gray(` ${chosen.warning}`));
|
|
15517
|
+
console.log(chalk9__default.default.gray(" Cascade won't adopt it because it would create a non-working provider.\n"));
|
|
15546
15518
|
return;
|
|
15547
15519
|
}
|
|
15548
15520
|
if (chosen.kind === "oauth" && !options.acceptRisk) {
|
|
15549
|
-
console.log(
|
|
15521
|
+
console.log(chalk9__default.default.yellow(`
|
|
15550
15522
|
${chosen.sourceTool} provides a subscription OAuth token, not an API key.`));
|
|
15551
|
-
if (chosen.warning) console.log(
|
|
15552
|
-
console.log(
|
|
15553
|
-
console.log(
|
|
15523
|
+
if (chosen.warning) console.log(chalk9__default.default.gray(` ${chosen.warning}`));
|
|
15524
|
+
console.log(chalk9__default.default.gray(" Re-run with --accept-risk to adopt it anyway:\n"));
|
|
15525
|
+
console.log(chalk9__default.default.cyan(` cascade link ${provider} --accept-risk
|
|
15554
15526
|
`));
|
|
15555
15527
|
return;
|
|
15556
15528
|
}
|
|
15557
15529
|
await adoptCredential(chosen, options.workspace ?? process.cwd());
|
|
15558
|
-
console.log(
|
|
15530
|
+
console.log(chalk9__default.default.green(`
|
|
15559
15531
|
\u2713 Linked ${provider} using your ${chosen.sourceTool} credential (${maskSecret(chosen.secret)}).`));
|
|
15560
15532
|
if (chosen.kind === "oauth") {
|
|
15561
|
-
console.log(
|
|
15533
|
+
console.log(chalk9__default.default.gray(" Adopted as an OAuth bearer token \u2014 revoke it in the source tool to disable."));
|
|
15562
15534
|
}
|
|
15563
|
-
console.log(
|
|
15535
|
+
console.log(chalk9__default.default.gray(" Run `cascade doctor` to verify, or `cascade` to start.\n"));
|
|
15564
15536
|
}
|
|
15565
15537
|
function printDiscovered(found) {
|
|
15566
|
-
console.log(
|
|
15538
|
+
console.log(chalk9__default.default.magenta("\n \u25C8 Detected credentials\n"));
|
|
15567
15539
|
for (const c of found) {
|
|
15568
|
-
const usable = c.directlyUsable ?
|
|
15569
|
-
const kind = c.kind === "oauth" ?
|
|
15570
|
-
console.log(` ${
|
|
15571
|
-
console.log(
|
|
15572
|
-
if (c.warning) console.log(
|
|
15540
|
+
const usable = c.directlyUsable ? chalk9__default.default.green("usable") : chalk9__default.default.yellow("needs vendor backend");
|
|
15541
|
+
const kind = c.kind === "oauth" ? chalk9__default.default.yellow("oauth") : chalk9__default.default.gray("api-key");
|
|
15542
|
+
console.log(` ${chalk9__default.default.white(c.provider.padEnd(18))} ${chalk9__default.default.gray(maskSecret(c.secret).padEnd(12))} ${kind} ${usable}`);
|
|
15543
|
+
console.log(chalk9__default.default.gray(` from ${c.sourceTool}`));
|
|
15544
|
+
if (c.warning) console.log(chalk9__default.default.yellow(` \u26A0 ${c.warning}`));
|
|
15573
15545
|
}
|
|
15574
|
-
console.log(
|
|
15575
|
-
console.log(
|
|
15546
|
+
console.log(chalk9__default.default.gray("\n Adopt one with: ") + chalk9__default.default.cyan("cascade link <provider> [--accept-risk]"));
|
|
15547
|
+
console.log(chalk9__default.default.gray(" --accept-risk is required for subscription OAuth tokens.\n"));
|
|
15576
15548
|
}
|
|
15577
15549
|
function normalizeProvider(target) {
|
|
15578
15550
|
const t = target.toLowerCase();
|
|
@@ -15605,12 +15577,12 @@ async function telemetryCommand(action) {
|
|
|
15605
15577
|
if (action === "status") {
|
|
15606
15578
|
const state = config.telemetry?.enabled ? "ON" : "OFF";
|
|
15607
15579
|
console.log();
|
|
15608
|
-
console.log(
|
|
15580
|
+
console.log(chalk9__default.default.magenta(" \u25C8 Cascade Telemetry"));
|
|
15609
15581
|
console.log();
|
|
15610
|
-
console.log(` Status: ${config.telemetry?.enabled ?
|
|
15611
|
-
console.log(
|
|
15582
|
+
console.log(` Status: ${config.telemetry?.enabled ? chalk9__default.default.green(state) : chalk9__default.default.gray(state)}`);
|
|
15583
|
+
console.log(chalk9__default.default.gray(" Scope: anonymous session metadata only (no prompts/outputs)"));
|
|
15612
15584
|
console.log();
|
|
15613
|
-
console.log(
|
|
15585
|
+
console.log(chalk9__default.default.gray(" Toggle with: cascade telemetry on | cascade telemetry off"));
|
|
15614
15586
|
console.log();
|
|
15615
15587
|
return;
|
|
15616
15588
|
}
|
|
@@ -15624,11 +15596,11 @@ async function telemetryCommand(action) {
|
|
|
15624
15596
|
});
|
|
15625
15597
|
console.log();
|
|
15626
15598
|
if (enabled) {
|
|
15627
|
-
console.log(
|
|
15628
|
-
console.log(
|
|
15599
|
+
console.log(chalk9__default.default.green(` \u2713 Telemetry enabled.`));
|
|
15600
|
+
console.log(chalk9__default.default.gray(" Anonymous session metadata (no prompts, no outputs) will be sent."));
|
|
15629
15601
|
} else {
|
|
15630
|
-
console.log(
|
|
15631
|
-
console.log(
|
|
15602
|
+
console.log(chalk9__default.default.yellow(` \u2713 Telemetry disabled.`));
|
|
15603
|
+
console.log(chalk9__default.default.gray(" No events will be transmitted from this workspace."));
|
|
15632
15604
|
}
|
|
15633
15605
|
console.log();
|
|
15634
15606
|
}
|
|
@@ -15638,11 +15610,11 @@ async function statsCommand() {
|
|
|
15638
15610
|
await tracker.load();
|
|
15639
15611
|
const all = tracker.getAll();
|
|
15640
15612
|
if (all.size === 0) {
|
|
15641
|
-
console.log(
|
|
15613
|
+
console.log(chalk9__default.default.dim("\n No routing history yet \u2014 run some tasks first.\n"));
|
|
15642
15614
|
return;
|
|
15643
15615
|
}
|
|
15644
|
-
console.log(
|
|
15645
|
-
console.log(
|
|
15616
|
+
console.log(chalk9__default.default.magenta("\n \u25C8 Auto-Routing History\n"));
|
|
15617
|
+
console.log(chalk9__default.default.dim(" Per-task-type model performance learned from past runs.\n"));
|
|
15646
15618
|
for (const taskType of TASK_TYPES) {
|
|
15647
15619
|
const entries = [];
|
|
15648
15620
|
for (const [key, stat] of all) {
|
|
@@ -15654,21 +15626,21 @@ async function statsCommand() {
|
|
|
15654
15626
|
}
|
|
15655
15627
|
if (entries.length === 0) continue;
|
|
15656
15628
|
entries.sort((a, b) => b.successRate - a.successRate || b.samples - a.samples);
|
|
15657
|
-
console.log(
|
|
15629
|
+
console.log(chalk9__default.default.bold(` ${taskType.toUpperCase()}`));
|
|
15658
15630
|
const header = ` ${"Model".padEnd(36)} ${"Success".padEnd(9)} ${"Samples".padEnd(9)} Avg cost`;
|
|
15659
|
-
console.log(
|
|
15660
|
-
console.log(
|
|
15631
|
+
console.log(chalk9__default.default.dim(header));
|
|
15632
|
+
console.log(chalk9__default.default.dim(" " + "\u2500".repeat(62)));
|
|
15661
15633
|
for (const e of entries) {
|
|
15662
15634
|
const pct = `${Math.round(e.successRate * 100)}%`;
|
|
15663
15635
|
const cost = e.avgCostUsd < 1e-4 ? "<$0.0001" : `$${e.avgCostUsd.toFixed(4)}`;
|
|
15664
|
-
const color = e.successRate >= 0.8 ?
|
|
15636
|
+
const color = e.successRate >= 0.8 ? chalk9__default.default.green : e.successRate >= 0.5 ? chalk9__default.default.yellow : chalk9__default.default.red;
|
|
15665
15637
|
console.log(
|
|
15666
|
-
` ${e.modelId.padEnd(36)} ${color(pct.padEnd(9))} ${String(e.samples).padEnd(9)} ${
|
|
15638
|
+
` ${e.modelId.padEnd(36)} ${color(pct.padEnd(9))} ${String(e.samples).padEnd(9)} ${chalk9__default.default.dim(cost)}`
|
|
15667
15639
|
);
|
|
15668
15640
|
}
|
|
15669
15641
|
console.log();
|
|
15670
15642
|
}
|
|
15671
|
-
console.log(
|
|
15643
|
+
console.log(chalk9__default.default.dim(" tip: use /rate good | bad after a task to improve these scores.\n"));
|
|
15672
15644
|
}
|
|
15673
15645
|
|
|
15674
15646
|
// src/cli/index.ts
|
|
@@ -15683,7 +15655,7 @@ function warnIfBuildIsStale() {
|
|
|
15683
15655
|
if (pkg.name !== "cascade-ai") continue;
|
|
15684
15656
|
if (pkg.version && pkg.version !== CASCADE_VERSION) {
|
|
15685
15657
|
console.error(
|
|
15686
|
-
|
|
15658
|
+
chalk9__default.default.yellow(
|
|
15687
15659
|
`\u26A0 Stale build: compiled output is v${CASCADE_VERSION} but the source tree is v${pkg.version}.
|
|
15688
15660
|
Run: npm install && npm run build`
|
|
15689
15661
|
)
|
|
@@ -15751,13 +15723,17 @@ program.command("dashboard").description("Launch the web dashboard").option("-p,
|
|
|
15751
15723
|
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) => {
|
|
15752
15724
|
await runHeadless(prompt, { theme: opts.theme, workspace: process.cwd(), identity: opts.identity });
|
|
15753
15725
|
});
|
|
15754
|
-
program.command("models").description("List
|
|
15755
|
-
|
|
15726
|
+
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) => {
|
|
15727
|
+
if (action === "set" || action === "unset") {
|
|
15728
|
+
await setModelCommand(action, tier, value);
|
|
15729
|
+
} else {
|
|
15730
|
+
await modelsCommand({ verbose: opts.verbose });
|
|
15731
|
+
}
|
|
15756
15732
|
});
|
|
15757
15733
|
program.command("telemetry [action]").description("Toggle anonymous usage telemetry (on | off | status). Default: status").action(async (action) => {
|
|
15758
15734
|
const normalized = (action ?? "status").toLowerCase();
|
|
15759
15735
|
if (normalized !== "on" && normalized !== "off" && normalized !== "status") {
|
|
15760
|
-
console.error(
|
|
15736
|
+
console.error(chalk9__default.default.red(`Unknown action: ${action}. Use: on | off | status`));
|
|
15761
15737
|
process.exit(1);
|
|
15762
15738
|
}
|
|
15763
15739
|
await telemetryCommand(normalized);
|
|
@@ -15779,14 +15755,14 @@ async function startRepl(options) {
|
|
|
15779
15755
|
try {
|
|
15780
15756
|
await cm.load();
|
|
15781
15757
|
} catch (err) {
|
|
15782
|
-
console.error(
|
|
15783
|
-
console.error(
|
|
15758
|
+
console.error(chalk9__default.default.red(`Config error: ${err instanceof Error ? err.message : String(err)}`));
|
|
15759
|
+
console.error(chalk9__default.default.gray("Run `cascade init` to set up this directory."));
|
|
15784
15760
|
process.exit(1);
|
|
15785
15761
|
}
|
|
15786
15762
|
let config = cm.getConfig();
|
|
15787
15763
|
const needsSetup = !config.providers?.length || config.providers.every((p) => p.type !== "ollama" && !p.apiKey);
|
|
15788
15764
|
if (needsSetup) {
|
|
15789
|
-
console.log(
|
|
15765
|
+
console.log(chalk9__default.default.magenta(" \u25C8 No providers configured \u2014 launching setup wizard\u2026"));
|
|
15790
15766
|
console.log();
|
|
15791
15767
|
config = await runSetupWizard(workspacePath);
|
|
15792
15768
|
await cm.updateConfig(config);
|
|
@@ -15820,24 +15796,24 @@ async function runHeadless(prompt, options) {
|
|
|
15820
15796
|
try {
|
|
15821
15797
|
await cm.load();
|
|
15822
15798
|
} catch (err) {
|
|
15823
|
-
console.error(
|
|
15824
|
-
console.error(
|
|
15799
|
+
console.error(chalk9__default.default.red(`Config error: ${err instanceof Error ? err.message : String(err)}`));
|
|
15800
|
+
console.error(chalk9__default.default.gray("Run `cascade init` to set up this directory."));
|
|
15825
15801
|
process.exit(1);
|
|
15826
15802
|
}
|
|
15827
15803
|
const config = cm.getConfig();
|
|
15828
15804
|
const needsSetup = !config.providers?.length || config.providers.every((p) => p.type !== "ollama" && !p.apiKey);
|
|
15829
15805
|
if (needsSetup) {
|
|
15830
|
-
console.error(
|
|
15806
|
+
console.error(chalk9__default.default.red("No providers configured. Run `cascade init` first."));
|
|
15831
15807
|
process.exit(1);
|
|
15832
15808
|
}
|
|
15833
15809
|
const cascade = new Cascade(config, workspacePath);
|
|
15834
15810
|
try {
|
|
15835
15811
|
await cascade.init();
|
|
15836
15812
|
} catch (err) {
|
|
15837
|
-
console.error(
|
|
15813
|
+
console.error(chalk9__default.default.red(`Initialization failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
15838
15814
|
process.exit(1);
|
|
15839
15815
|
}
|
|
15840
|
-
console.error(
|
|
15816
|
+
console.error(chalk9__default.default.gray(" \u25C8 Running headlessly \u2014 tool approvals are auto-granted."));
|
|
15841
15817
|
let lastProgress = "";
|
|
15842
15818
|
cascade.on("tier:status", (ev) => {
|
|
15843
15819
|
const action = ev?.currentAction?.trim();
|
|
@@ -15845,7 +15821,7 @@ async function runHeadless(prompt, options) {
|
|
|
15845
15821
|
const line = ` \xB7 ${ev.role ?? ""} ${action}`.trimEnd();
|
|
15846
15822
|
if (line === lastProgress) return;
|
|
15847
15823
|
lastProgress = line;
|
|
15848
|
-
console.error(
|
|
15824
|
+
console.error(chalk9__default.default.gray(line));
|
|
15849
15825
|
});
|
|
15850
15826
|
try {
|
|
15851
15827
|
const result = await cascade.run({
|
|
@@ -15856,7 +15832,7 @@ async function runHeadless(prompt, options) {
|
|
|
15856
15832
|
});
|
|
15857
15833
|
process.stdout.write(result.output.trimEnd() + "\n");
|
|
15858
15834
|
} catch (err) {
|
|
15859
|
-
console.error(
|
|
15835
|
+
console.error(chalk9__default.default.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
15860
15836
|
await cascade.close().catch(() => {
|
|
15861
15837
|
});
|
|
15862
15838
|
process.exit(1);
|
|
@@ -15868,10 +15844,10 @@ async function runHeadless(prompt, options) {
|
|
|
15868
15844
|
function printBanner() {
|
|
15869
15845
|
if (process.stdout.columns < 60) return;
|
|
15870
15846
|
console.log();
|
|
15871
|
-
console.log(
|
|
15872
|
-
console.log(
|
|
15873
|
-
console.log(
|
|
15874
|
-
console.log(
|
|
15847
|
+
console.log(chalk9__default.default.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"));
|
|
15848
|
+
console.log(chalk9__default.default.hex("#7C6AF7").bold(" \u2551") + chalk9__default.default.white.bold(" \u25C8 CASCADE AI") + chalk9__default.default.gray(" v" + CASCADE_VERSION + " ") + chalk9__default.default.hex("#7C6AF7").bold("\u2551"));
|
|
15849
|
+
console.log(chalk9__default.default.hex("#7C6AF7").bold(" \u2551") + chalk9__default.default.gray(" Multi-Tier Orchestration ") + chalk9__default.default.hex("#7C6AF7").bold("\u2551"));
|
|
15850
|
+
console.log(chalk9__default.default.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"));
|
|
15875
15851
|
console.log();
|
|
15876
15852
|
}
|
|
15877
15853
|
program.parse(process.argv);
|