cascade-ai 0.2.12 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +146 -58
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +147 -59
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +76 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +77 -38
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/web/dist/assets/{index-BdaS_Mbj.js → index-BvxaBI9b.js} +34 -34
- package/web/dist/index.html +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Anthropic from '@anthropic-ai/sdk';
|
|
2
|
-
import OpenAI from 'openai';
|
|
2
|
+
import OpenAI, { AzureOpenAI } from 'openai';
|
|
3
3
|
import { GoogleGenAI, HarmBlockThreshold, HarmCategory } from '@google/genai';
|
|
4
4
|
import axios2 from 'axios';
|
|
5
5
|
import { render, useApp, useStdout, useInput, Box, Text } from 'ink';
|
|
@@ -83,7 +83,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
83
83
|
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;
|
|
84
84
|
var init_constants = __esm({
|
|
85
85
|
"src/constants.ts"() {
|
|
86
|
-
CASCADE_VERSION = "0.
|
|
86
|
+
CASCADE_VERSION = "0.4.0";
|
|
87
87
|
CASCADE_CONFIG_FILE = ".cascade/config.json";
|
|
88
88
|
CASCADE_DB_FILE = ".cascade/memory.db";
|
|
89
89
|
CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
|
|
@@ -902,19 +902,21 @@ var init_azure = __esm({
|
|
|
902
902
|
init_openai();
|
|
903
903
|
AzureOpenAIProvider = class extends OpenAIProvider {
|
|
904
904
|
constructor(config, model) {
|
|
905
|
-
const
|
|
905
|
+
const rawUrl = config.baseUrl ?? AZURE_BASE_URL_TEMPLATE.replace("{resource}", "YOUR_RESOURCE");
|
|
906
|
+
const endpoint = rawUrl.replace(/\/+$/, "");
|
|
906
907
|
super(
|
|
907
908
|
{
|
|
908
909
|
...config,
|
|
909
|
-
baseUrl:
|
|
910
|
+
baseUrl: endpoint
|
|
911
|
+
// Kept for superclass compatibility if it reads it
|
|
910
912
|
},
|
|
911
913
|
model
|
|
912
914
|
);
|
|
913
|
-
this.client = new
|
|
915
|
+
this.client = new AzureOpenAI({
|
|
914
916
|
apiKey: config.apiKey,
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
917
|
+
endpoint,
|
|
918
|
+
deployment: config.deploymentName ?? model.id,
|
|
919
|
+
apiVersion: config.apiVersion ?? "2024-08-01-preview"
|
|
918
920
|
});
|
|
919
921
|
}
|
|
920
922
|
async listModels() {
|
|
@@ -1875,8 +1877,8 @@ Original error: ${err.message}`
|
|
|
1875
1877
|
upsertRuntimeNode(node) {
|
|
1876
1878
|
this.enqueueWrite(() => {
|
|
1877
1879
|
this.db.prepare(`
|
|
1878
|
-
INSERT INTO runtime_nodes (tier_id, session_id, parent_id, role, label, status, current_action, progress_pct, updated_at, workspace_path, is_global)
|
|
1879
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1880
|
+
INSERT INTO runtime_nodes (tier_id, session_id, parent_id, role, label, status, current_action, progress_pct, updated_at, workspace_path, is_global, output)
|
|
1881
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1880
1882
|
ON CONFLICT(tier_id) DO UPDATE SET
|
|
1881
1883
|
session_id = excluded.session_id,
|
|
1882
1884
|
parent_id = excluded.parent_id,
|
|
@@ -1887,7 +1889,8 @@ Original error: ${err.message}`
|
|
|
1887
1889
|
progress_pct = excluded.progress_pct,
|
|
1888
1890
|
updated_at = excluded.updated_at,
|
|
1889
1891
|
workspace_path = excluded.workspace_path,
|
|
1890
|
-
is_global = excluded.is_global
|
|
1892
|
+
is_global = excluded.is_global,
|
|
1893
|
+
output = excluded.output
|
|
1891
1894
|
`).run(
|
|
1892
1895
|
node.tierId,
|
|
1893
1896
|
node.sessionId,
|
|
@@ -1899,7 +1902,8 @@ Original error: ${err.message}`
|
|
|
1899
1902
|
node.progressPct ?? null,
|
|
1900
1903
|
node.updatedAt,
|
|
1901
1904
|
node.workspacePath ?? null,
|
|
1902
|
-
node.isGlobal ? 1 : 0
|
|
1905
|
+
node.isGlobal ? 1 : 0,
|
|
1906
|
+
node.output ?? null
|
|
1903
1907
|
);
|
|
1904
1908
|
});
|
|
1905
1909
|
}
|
|
@@ -1920,14 +1924,15 @@ Original error: ${err.message}`
|
|
|
1920
1924
|
progressPct: row.progress_pct ?? void 0,
|
|
1921
1925
|
updatedAt: row.updated_at,
|
|
1922
1926
|
workspacePath: row.workspace_path ?? void 0,
|
|
1923
|
-
isGlobal: row.is_global === 1
|
|
1927
|
+
isGlobal: row.is_global === 1,
|
|
1928
|
+
output: row.output ?? void 0
|
|
1924
1929
|
}));
|
|
1925
1930
|
}
|
|
1926
1931
|
addRuntimeNodeLog(log) {
|
|
1927
1932
|
this.enqueueWrite(() => {
|
|
1928
1933
|
this.db.prepare(`
|
|
1929
|
-
INSERT INTO runtime_node_logs (id, session_id, tier_id, role, label, status, current_action, progress_pct, timestamp, workspace_path, is_global)
|
|
1930
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1934
|
+
INSERT INTO runtime_node_logs (id, session_id, tier_id, role, label, status, current_action, progress_pct, timestamp, workspace_path, is_global, output)
|
|
1935
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1931
1936
|
`).run(
|
|
1932
1937
|
log.id,
|
|
1933
1938
|
log.sessionId,
|
|
@@ -1939,7 +1944,8 @@ Original error: ${err.message}`
|
|
|
1939
1944
|
log.progressPct ?? null,
|
|
1940
1945
|
log.timestamp,
|
|
1941
1946
|
log.workspacePath ?? null,
|
|
1942
|
-
log.isGlobal ? 1 : 0
|
|
1947
|
+
log.isGlobal ? 1 : 0,
|
|
1948
|
+
log.output ?? null
|
|
1943
1949
|
);
|
|
1944
1950
|
this.db.prepare(`
|
|
1945
1951
|
DELETE FROM runtime_node_logs
|
|
@@ -1982,7 +1988,8 @@ Original error: ${err.message}`
|
|
|
1982
1988
|
progressPct: row.progress_pct ?? void 0,
|
|
1983
1989
|
timestamp: row.timestamp,
|
|
1984
1990
|
workspacePath: row.workspace_path ?? void 0,
|
|
1985
|
-
isGlobal: row.is_global === 1
|
|
1991
|
+
isGlobal: row.is_global === 1,
|
|
1992
|
+
output: row.output ?? void 0
|
|
1986
1993
|
}));
|
|
1987
1994
|
}
|
|
1988
1995
|
// ── Messages ──────────────────────────────────
|
|
@@ -2309,7 +2316,8 @@ Original error: ${err.message}`
|
|
|
2309
2316
|
progress_pct INTEGER,
|
|
2310
2317
|
updated_at TEXT NOT NULL,
|
|
2311
2318
|
workspace_path TEXT,
|
|
2312
|
-
is_global INTEGER NOT NULL DEFAULT 0
|
|
2319
|
+
is_global INTEGER NOT NULL DEFAULT 0,
|
|
2320
|
+
output TEXT
|
|
2313
2321
|
);
|
|
2314
2322
|
|
|
2315
2323
|
CREATE INDEX IF NOT EXISTS idx_runtime_nodes_session ON runtime_nodes(session_id);
|
|
@@ -2326,7 +2334,8 @@ Original error: ${err.message}`
|
|
|
2326
2334
|
progress_pct INTEGER,
|
|
2327
2335
|
timestamp TEXT NOT NULL,
|
|
2328
2336
|
workspace_path TEXT,
|
|
2329
|
-
is_global INTEGER NOT NULL DEFAULT 0
|
|
2337
|
+
is_global INTEGER NOT NULL DEFAULT 0,
|
|
2338
|
+
output TEXT
|
|
2330
2339
|
);
|
|
2331
2340
|
|
|
2332
2341
|
CREATE TABLE IF NOT EXISTS model_cache (
|
|
@@ -2355,6 +2364,14 @@ Original error: ${err.message}`
|
|
|
2355
2364
|
|
|
2356
2365
|
CREATE INDEX IF NOT EXISTS idx_file_snapshots_session ON file_snapshots(session_id);
|
|
2357
2366
|
`);
|
|
2367
|
+
try {
|
|
2368
|
+
this.db.exec("ALTER TABLE runtime_nodes ADD COLUMN output TEXT");
|
|
2369
|
+
} catch {
|
|
2370
|
+
}
|
|
2371
|
+
try {
|
|
2372
|
+
this.db.exec("ALTER TABLE runtime_node_logs ADD COLUMN output TEXT");
|
|
2373
|
+
} catch {
|
|
2374
|
+
}
|
|
2358
2375
|
}
|
|
2359
2376
|
// ── Deserializers ─────────────────────────────
|
|
2360
2377
|
deserializeSession(row, messages) {
|
|
@@ -3233,7 +3250,7 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
|
|
|
3233
3250
|
if (!model) {
|
|
3234
3251
|
throw new Error(`Configured model "${override}" for ${tier} could not be loaded. Check provider availability and exact model name.`);
|
|
3235
3252
|
}
|
|
3236
|
-
if (model.id !== override) {
|
|
3253
|
+
if (model.id !== override && `${model.provider}:${model.id}` !== override) {
|
|
3237
3254
|
throw new Error(`Configured model "${override}" for ${tier} resolved to "${model.id}". Use the exact provider model ID or prefix the provider (e.g. gemini:${override}).`);
|
|
3238
3255
|
}
|
|
3239
3256
|
this.tierModels.set(tier, model);
|
|
@@ -3583,7 +3600,7 @@ var BaseTier = class extends EventEmitter {
|
|
|
3583
3600
|
getStatus() {
|
|
3584
3601
|
return this.status;
|
|
3585
3602
|
}
|
|
3586
|
-
setStatus(status) {
|
|
3603
|
+
setStatus(status, output) {
|
|
3587
3604
|
this.status = status;
|
|
3588
3605
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3589
3606
|
const event = {
|
|
@@ -3592,7 +3609,8 @@ var BaseTier = class extends EventEmitter {
|
|
|
3592
3609
|
parentId: this.parentId,
|
|
3593
3610
|
label: this.label,
|
|
3594
3611
|
status,
|
|
3595
|
-
timestamp
|
|
3612
|
+
timestamp,
|
|
3613
|
+
output
|
|
3596
3614
|
};
|
|
3597
3615
|
this.emit("status", event);
|
|
3598
3616
|
this.emit("tier:status", event);
|
|
@@ -3618,7 +3636,8 @@ var BaseTier = class extends EventEmitter {
|
|
|
3618
3636
|
status: this.status,
|
|
3619
3637
|
currentAction: update.currentAction,
|
|
3620
3638
|
progressPct: update.progressPct,
|
|
3621
|
-
timestamp
|
|
3639
|
+
timestamp,
|
|
3640
|
+
output: update.output
|
|
3622
3641
|
});
|
|
3623
3642
|
}
|
|
3624
3643
|
buildMessage(type, to, payload) {
|
|
@@ -3999,16 +4018,17 @@ Now execute your subtask using this context where relevant.`
|
|
|
3999
4018
|
return this.buildResult("ESCALATED", output, { checksRun, passed, failed }, issues, correctionAttempts);
|
|
4000
4019
|
}
|
|
4001
4020
|
}
|
|
4002
|
-
this.setStatus("COMPLETED");
|
|
4003
|
-
this.sendStatusUpdate({ progressPct: 100, currentAction: "Subtask complete", status: "IN_PROGRESS" });
|
|
4021
|
+
this.setStatus("COMPLETED", output);
|
|
4022
|
+
this.sendStatusUpdate({ progressPct: 100, currentAction: "Subtask complete", status: "IN_PROGRESS", output });
|
|
4004
4023
|
this.peerBus?.publish(this.id, assignment.subtaskId, output, "COMPLETED");
|
|
4005
4024
|
return this.buildResult("COMPLETED", output, { checksRun, passed, failed }, issues, correctionAttempts);
|
|
4006
4025
|
} catch (err) {
|
|
4007
4026
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
4008
4027
|
issues.push(`Execution error: ${errMsg}`);
|
|
4009
|
-
|
|
4010
|
-
this.
|
|
4011
|
-
|
|
4028
|
+
const finalOutput = output || errMsg;
|
|
4029
|
+
this.setStatus("FAILED", finalOutput);
|
|
4030
|
+
this.peerBus?.publish(this.id, assignment.subtaskId, finalOutput, "FAILED");
|
|
4031
|
+
return this.buildResult("ESCALATED", finalOutput, { checksRun, passed, failed }, issues, correctionAttempts);
|
|
4012
4032
|
}
|
|
4013
4033
|
}
|
|
4014
4034
|
sendToPeer(toId, content) {
|
|
@@ -4062,6 +4082,10 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : ""),
|
|
|
4062
4082
|
await this.context.addMessage({ role: "assistant", content: result.content, toolCalls: result.toolCalls });
|
|
4063
4083
|
if (!result.toolCalls?.length) {
|
|
4064
4084
|
if (requiresArtifact) {
|
|
4085
|
+
const artifactCheck = await this.verifyArtifacts(this.assignment);
|
|
4086
|
+
if (artifactCheck.ok) {
|
|
4087
|
+
return { output: result.content, toolCalls: allToolCalls };
|
|
4088
|
+
}
|
|
4065
4089
|
stalledArtifactIterations += 1;
|
|
4066
4090
|
if (stalledArtifactIterations >= 2) {
|
|
4067
4091
|
if (stalledArtifactIterations === 2) {
|
|
@@ -4071,15 +4095,22 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : ""),
|
|
|
4071
4095
|
}
|
|
4072
4096
|
await this.context.addMessage({
|
|
4073
4097
|
role: "user",
|
|
4074
|
-
content:
|
|
4098
|
+
content: `You have not yet created and verified the required artifact. Issues: ${artifactCheck.issues.join("; ")}. Use tools to create the file in the workspace, verify it exists, and inspect the result before concluding.`
|
|
4075
4099
|
});
|
|
4076
4100
|
continue;
|
|
4077
4101
|
}
|
|
4078
4102
|
return { output: result.content, toolCalls: allToolCalls };
|
|
4079
4103
|
}
|
|
4080
4104
|
stalledArtifactIterations = 0;
|
|
4081
|
-
if (result.finishReason === "stop"
|
|
4082
|
-
|
|
4105
|
+
if (result.finishReason === "stop") {
|
|
4106
|
+
if (requiresArtifact) {
|
|
4107
|
+
const artifactCheck = await this.verifyArtifacts(this.assignment);
|
|
4108
|
+
if (artifactCheck.ok) {
|
|
4109
|
+
return { output: result.content, toolCalls: allToolCalls };
|
|
4110
|
+
}
|
|
4111
|
+
} else {
|
|
4112
|
+
return { output: result.content, toolCalls: allToolCalls };
|
|
4113
|
+
}
|
|
4083
4114
|
}
|
|
4084
4115
|
for (const tc of result.toolCalls) {
|
|
4085
4116
|
allToolCalls.push(tc);
|
|
@@ -4691,8 +4722,9 @@ var T2Manager = class extends BaseTier {
|
|
|
4691
4722
|
const summary = await this.aggregateResults(assignment, t3Results);
|
|
4692
4723
|
const issues = t3Results.filter((r) => r.status !== "COMPLETED").flatMap((r) => r.issues);
|
|
4693
4724
|
const overallStatus = this.determineStatus(t3Results);
|
|
4694
|
-
|
|
4695
|
-
this.
|
|
4725
|
+
const isOk = overallStatus === "COMPLETED" || overallStatus === "PARTIAL";
|
|
4726
|
+
this.setStatus(isOk ? "COMPLETED" : "FAILED", summary);
|
|
4727
|
+
this.sendStatusUpdate({ progressPct: 100, currentAction: "Section complete", status: "IN_PROGRESS", output: summary });
|
|
4696
4728
|
const result = {
|
|
4697
4729
|
sectionId: assignment.sectionId,
|
|
4698
4730
|
sectionTitle: assignment.sectionTitle,
|
|
@@ -4705,7 +4737,7 @@ var T2Manager = class extends BaseTier {
|
|
|
4705
4737
|
return result;
|
|
4706
4738
|
} catch (err) {
|
|
4707
4739
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
4708
|
-
this.setStatus("FAILED");
|
|
4740
|
+
this.setStatus("FAILED", errMsg);
|
|
4709
4741
|
const failedResult = {
|
|
4710
4742
|
sectionId: assignment.sectionId,
|
|
4711
4743
|
sectionTitle: assignment.sectionTitle,
|
|
@@ -5270,8 +5302,8 @@ Create a CORRECTION PLAN that contains only the new sections needed to fix the i
|
|
|
5270
5302
|
status: "IN_PROGRESS"
|
|
5271
5303
|
});
|
|
5272
5304
|
const output = await this.compileFinalOutput(userPrompt, plan, allT2Results);
|
|
5273
|
-
this.setStatus("COMPLETED");
|
|
5274
|
-
this.sendStatusUpdate({ progressPct: 100, currentAction: "Task complete", status: "IN_PROGRESS" });
|
|
5305
|
+
this.setStatus("COMPLETED", output);
|
|
5306
|
+
this.sendStatusUpdate({ progressPct: 100, currentAction: "Task complete", status: "IN_PROGRESS", output });
|
|
5275
5307
|
return { output, t2Results: allT2Results, taskId: this.taskId, complexity: plan.complexity };
|
|
5276
5308
|
}
|
|
5277
5309
|
getEscalations() {
|
|
@@ -7549,10 +7581,17 @@ var Cascade = class extends EventEmitter {
|
|
|
7549
7581
|
throw err;
|
|
7550
7582
|
}
|
|
7551
7583
|
}
|
|
7584
|
+
isCasualGreeting(prompt) {
|
|
7585
|
+
const casual = /^(hi|hello|hey|greetings|thanks|thank you|thx|bye|goodbye|cya)$/i.test(prompt.trim().replace(/[!?.]+$/, ""));
|
|
7586
|
+
return casual;
|
|
7587
|
+
}
|
|
7552
7588
|
looksLikeSimpleArtifactTask(prompt) {
|
|
7553
7589
|
return /create .*\.(txt|md|json|csv)\b/i.test(prompt) && !/(research|compare|thorough|pdf|report|analy[sz]e|architecture|multi-agent)/i.test(prompt);
|
|
7554
7590
|
}
|
|
7555
7591
|
async determineComplexity(prompt, workspacePath, conversationHistory = []) {
|
|
7592
|
+
if (this.isCasualGreeting(prompt)) {
|
|
7593
|
+
return "Simple";
|
|
7594
|
+
}
|
|
7556
7595
|
if (this.looksLikeSimpleArtifactTask(prompt)) {
|
|
7557
7596
|
return "Simple";
|
|
7558
7597
|
}
|
|
@@ -8228,35 +8267,69 @@ function AgentTree({ root, theme }) {
|
|
|
8228
8267
|
}
|
|
8229
8268
|
function T2Row({ node, theme, isLast }) {
|
|
8230
8269
|
const connector = isLast ? "\u2514\u2500 " : "\u251C\u2500 ";
|
|
8231
|
-
const
|
|
8232
|
-
const
|
|
8233
|
-
const workerSuffix = t3Total > 0 ? ` T3\xD7${t3Total}` : "";
|
|
8270
|
+
const t3Nodes = (node.children ?? []).filter((c) => c.role === "T3");
|
|
8271
|
+
const t3ActiveCount = t3Nodes.filter((c) => c.status === "ACTIVE").length;
|
|
8234
8272
|
const label = stripRolePrefix(node.label, node.role);
|
|
8235
8273
|
const action = node.currentAction ? ` ${node.currentAction.slice(0, 38)}` : "";
|
|
8274
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
8275
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
8276
|
+
/* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
|
|
8277
|
+
" ",
|
|
8278
|
+
connector
|
|
8279
|
+
] }),
|
|
8280
|
+
/* @__PURE__ */ jsx(Text, { color: theme.colors.t2Color, bold: true, children: "[T2]" }),
|
|
8281
|
+
/* @__PURE__ */ jsxs(Text, { color: theme.colors.foreground, children: [
|
|
8282
|
+
" ",
|
|
8283
|
+
label
|
|
8284
|
+
] }),
|
|
8285
|
+
node.status === "ACTIVE" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8286
|
+
action ? /* @__PURE__ */ jsx(Text, { color: theme.colors.muted, children: action }) : null,
|
|
8287
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
8288
|
+
/* @__PURE__ */ jsx(Spinner, { type: "dots" }),
|
|
8289
|
+
t3ActiveCount > 0 ? /* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
|
|
8290
|
+
" (",
|
|
8291
|
+
t3ActiveCount,
|
|
8292
|
+
" running)"
|
|
8293
|
+
] }) : null
|
|
8294
|
+
] }),
|
|
8295
|
+
node.status === "COMPLETED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.success, children: " \u2714" }),
|
|
8296
|
+
node.status === "FAILED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.error, children: " \u2718" }),
|
|
8297
|
+
node.status === "ESCALATED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.warning, children: " \u25B2" })
|
|
8298
|
+
] }),
|
|
8299
|
+
t3Nodes.map((t3, idx) => /* @__PURE__ */ jsx(
|
|
8300
|
+
T3Row,
|
|
8301
|
+
{
|
|
8302
|
+
node: t3,
|
|
8303
|
+
theme,
|
|
8304
|
+
isLast: idx === t3Nodes.length - 1,
|
|
8305
|
+
parentIsLast: isLast
|
|
8306
|
+
},
|
|
8307
|
+
t3.id
|
|
8308
|
+
))
|
|
8309
|
+
] });
|
|
8310
|
+
}
|
|
8311
|
+
function T3Row({ node, theme, isLast, parentIsLast }) {
|
|
8312
|
+
const indent = parentIsLast ? " " : " \u2502 ";
|
|
8313
|
+
const connector = isLast ? "\u2514\u2500 " : "\u251C\u2500 ";
|
|
8314
|
+
const label = stripRolePrefix(node.label, node.role);
|
|
8315
|
+
const action = node.currentAction ? ` ${node.currentAction.slice(0, 42)}` : "";
|
|
8236
8316
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
8237
8317
|
/* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
|
|
8238
|
-
|
|
8318
|
+
indent,
|
|
8239
8319
|
connector
|
|
8240
8320
|
] }),
|
|
8241
|
-
/* @__PURE__ */ jsx(Text, { color: theme.colors.
|
|
8242
|
-
/* @__PURE__ */ jsxs(Text, { color: theme.colors.
|
|
8321
|
+
/* @__PURE__ */ jsx(Text, { color: theme.colors.t3Color, children: "[T3]" }),
|
|
8322
|
+
/* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
|
|
8243
8323
|
" ",
|
|
8244
8324
|
label
|
|
8245
8325
|
] }),
|
|
8246
|
-
workerSuffix ? /* @__PURE__ */ jsx(Text, { color: theme.colors.muted, children: workerSuffix }) : null,
|
|
8247
8326
|
node.status === "ACTIVE" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8248
8327
|
action ? /* @__PURE__ */ jsx(Text, { color: theme.colors.muted, children: action }) : null,
|
|
8249
8328
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
8250
|
-
/* @__PURE__ */ jsx(Spinner, { type: "dots" })
|
|
8251
|
-
t3Active > 0 ? /* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
|
|
8252
|
-
" (",
|
|
8253
|
-
t3Active,
|
|
8254
|
-
" running)"
|
|
8255
|
-
] }) : null
|
|
8329
|
+
/* @__PURE__ */ jsx(Spinner, { type: "dots" })
|
|
8256
8330
|
] }),
|
|
8257
8331
|
node.status === "COMPLETED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.success, children: " \u2714" }),
|
|
8258
|
-
node.status === "FAILED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.error, children: " \u2718" })
|
|
8259
|
-
node.status === "ESCALATED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.warning, children: " \u25B2" })
|
|
8332
|
+
node.status === "FAILED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.error, children: " \u2718" })
|
|
8260
8333
|
] });
|
|
8261
8334
|
}
|
|
8262
8335
|
function hasActiveOrFailed(node) {
|
|
@@ -8825,7 +8898,7 @@ function Repl({ config, workspacePath, themeName, initialPrompt, identityName })
|
|
|
8825
8898
|
if (sel.kind === "auto") {
|
|
8826
8899
|
delete config.models[tierKey];
|
|
8827
8900
|
} else {
|
|
8828
|
-
config.models[tierKey] = sel.modelId
|
|
8901
|
+
config.models[tierKey] = `${sel.provider}:${sel.modelId}`;
|
|
8829
8902
|
}
|
|
8830
8903
|
try {
|
|
8831
8904
|
const router = cascadeRef.current?.getRouter();
|
|
@@ -8868,7 +8941,7 @@ function Repl({ config, workspacePath, themeName, initialPrompt, identityName })
|
|
|
8868
8941
|
treeNodesRef.current.set(event.tierId, node);
|
|
8869
8942
|
const store = storeRef.current;
|
|
8870
8943
|
if (store) {
|
|
8871
|
-
const runtimeNode = { tierId: node.id, sessionId: sessionIdRef.current, parentId: node.parentId, role: node.role, label: node.label, status: node.status, currentAction: node.currentAction, progressPct: node.progressPct, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), workspacePath, isGlobal: false };
|
|
8944
|
+
const runtimeNode = { tierId: node.id, sessionId: sessionIdRef.current, parentId: node.parentId, role: node.role, label: node.label, status: node.status, currentAction: node.currentAction, progressPct: node.progressPct, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), workspacePath, isGlobal: false, output: event.output };
|
|
8872
8945
|
store.upsertRuntimeNode(runtimeNode);
|
|
8873
8946
|
globalStoreRef.current?.upsertRuntimeNode({ ...runtimeNode, isGlobal: true });
|
|
8874
8947
|
}
|
|
@@ -8879,7 +8952,6 @@ function Repl({ config, workspacePath, themeName, initialPrompt, identityName })
|
|
|
8879
8952
|
useEffect(() => {
|
|
8880
8953
|
const originalWarn = console.warn;
|
|
8881
8954
|
const originalLog = console.log;
|
|
8882
|
-
process.stdout.write("\x1Bc");
|
|
8883
8955
|
console.warn = (...args) => {
|
|
8884
8956
|
const msg = args.join(" ");
|
|
8885
8957
|
if (msg.includes("non-text parts") || msg.includes("functionCall")) return;
|
|
@@ -9384,9 +9456,15 @@ Use /identity <name|id> to switch.`;
|
|
|
9384
9456
|
let agentTreeHeight = 0;
|
|
9385
9457
|
if (state.agentTree && hasActiveOrFailed2(state.agentTree)) {
|
|
9386
9458
|
agentTreeHeight = 1;
|
|
9387
|
-
const
|
|
9388
|
-
agentTreeHeight +=
|
|
9389
|
-
|
|
9459
|
+
const visibleT2s = state.agentTree.children?.slice(0, 6) ?? [];
|
|
9460
|
+
agentTreeHeight += visibleT2s.length;
|
|
9461
|
+
for (const t2 of visibleT2s) {
|
|
9462
|
+
const t3Count = (t2.children ?? []).filter((c) => c.role === "T3").length;
|
|
9463
|
+
agentTreeHeight += t3Count;
|
|
9464
|
+
}
|
|
9465
|
+
if ((state.agentTree.children?.length ?? 0) > 6) {
|
|
9466
|
+
agentTreeHeight += 1;
|
|
9467
|
+
}
|
|
9390
9468
|
}
|
|
9391
9469
|
let timelineHeight = 0;
|
|
9392
9470
|
if (state.showDetails && treeNodesRef.current.size > 0) {
|
|
@@ -9575,6 +9653,13 @@ async function validateConfiguredModels(config) {
|
|
|
9575
9653
|
return problems.length ? `Model warnings: ${problems.join(", ")}` : null;
|
|
9576
9654
|
}
|
|
9577
9655
|
function inferProviderFromModelId(id, providers) {
|
|
9656
|
+
if (id.includes(":")) {
|
|
9657
|
+
const prefix = id.split(":")[0].toLowerCase();
|
|
9658
|
+
const validProviders = ["anthropic", "openai", "gemini", "azure", "openai-compatible", "ollama"];
|
|
9659
|
+
if (validProviders.includes(prefix)) {
|
|
9660
|
+
return prefix;
|
|
9661
|
+
}
|
|
9662
|
+
}
|
|
9578
9663
|
const lower = id.toLowerCase();
|
|
9579
9664
|
if (lower.includes("gpt")) return "openai";
|
|
9580
9665
|
if (lower.includes("claude")) return "anthropic";
|
|
@@ -10989,8 +11074,8 @@ var DashboardServer = class {
|
|
|
10989
11074
|
void (async () => {
|
|
10990
11075
|
const cascade = new Cascade(this.config, this.workspacePath, this.store);
|
|
10991
11076
|
cascade.on("stream:token", (e) => {
|
|
10992
|
-
this.socket.broadcast("stream:token", { sessionId,
|
|
10993
|
-
this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId,
|
|
11077
|
+
this.socket.broadcast("stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
11078
|
+
this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
10994
11079
|
});
|
|
10995
11080
|
cascade.on("tier:status", (e) => {
|
|
10996
11081
|
this.socket.broadcast("tier:status", { sessionId, ...e });
|
|
@@ -11426,6 +11511,9 @@ async function startRepl(options) {
|
|
|
11426
11511
|
await cm.load();
|
|
11427
11512
|
config = cm.getConfig();
|
|
11428
11513
|
}
|
|
11514
|
+
if (process.stdout.isTTY) {
|
|
11515
|
+
process.stdout.write("\x1B[2J\x1B[H");
|
|
11516
|
+
}
|
|
11429
11517
|
const { waitUntilExit } = render(
|
|
11430
11518
|
React5.createElement(Repl, {
|
|
11431
11519
|
config,
|