cascade-ai 0.2.11 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +179 -70
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +179 -70
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +98 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +98 -34
- package/dist/index.js.map +1 -1
- package/package.json +8 -5
- 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
|
@@ -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.3.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";
|
|
@@ -522,17 +522,38 @@ var init_anthropic = __esm({
|
|
|
522
522
|
messages,
|
|
523
523
|
tools: tools?.length ? tools : void 0
|
|
524
524
|
});
|
|
525
|
+
let isThinking = false;
|
|
525
526
|
for await (const event of stream) {
|
|
526
|
-
if (event.type === "content_block_delta"
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
527
|
+
if (event.type === "content_block_delta") {
|
|
528
|
+
if (event.delta.type === "thinking_delta") {
|
|
529
|
+
if (!isThinking) {
|
|
530
|
+
isThinking = true;
|
|
531
|
+
fullContent += "<think>\n";
|
|
532
|
+
onChunk({ text: "<think>\n", finishReason: null });
|
|
533
|
+
}
|
|
534
|
+
const text = event.delta.thinking;
|
|
535
|
+
fullContent += text;
|
|
536
|
+
onChunk({ text, finishReason: null });
|
|
537
|
+
} else if (event.delta.type === "text_delta") {
|
|
538
|
+
if (isThinking) {
|
|
539
|
+
isThinking = false;
|
|
540
|
+
fullContent += "\n</think>\n\n";
|
|
541
|
+
onChunk({ text: "\n</think>\n\n", finishReason: null });
|
|
542
|
+
}
|
|
543
|
+
const text = event.delta.text;
|
|
544
|
+
fullContent += text;
|
|
545
|
+
onChunk({ text, finishReason: null });
|
|
546
|
+
}
|
|
530
547
|
} else if (event.type === "message_delta" && event.usage) {
|
|
531
548
|
outputTokens = event.usage.output_tokens;
|
|
532
549
|
} else if (event.type === "message_start" && event.message.usage) {
|
|
533
550
|
inputTokens = event.message.usage.input_tokens;
|
|
534
551
|
}
|
|
535
552
|
}
|
|
553
|
+
if (isThinking) {
|
|
554
|
+
fullContent += "\n</think>\n\n";
|
|
555
|
+
onChunk({ text: "\n</think>\n\n", finishReason: null });
|
|
556
|
+
}
|
|
536
557
|
const finalMessage = await stream.finalMessage();
|
|
537
558
|
const toolCalls = finalMessage.content.filter((b) => b.type === "tool_use").map((b) => ({
|
|
538
559
|
id: b.id,
|
|
@@ -716,9 +737,25 @@ var init_openai = __esm({
|
|
|
716
737
|
}
|
|
717
738
|
}
|
|
718
739
|
const toolCallsMap = {};
|
|
740
|
+
let isThinking = false;
|
|
719
741
|
for await (const chunk of stream) {
|
|
720
742
|
const delta = chunk.choices[0]?.delta;
|
|
743
|
+
const reasoningContent = delta?.reasoning_content;
|
|
744
|
+
if (reasoningContent) {
|
|
745
|
+
if (!isThinking) {
|
|
746
|
+
isThinking = true;
|
|
747
|
+
fullContent += "<think>\n";
|
|
748
|
+
onChunk({ text: "<think>\n", finishReason: null });
|
|
749
|
+
}
|
|
750
|
+
fullContent += reasoningContent;
|
|
751
|
+
onChunk({ text: reasoningContent, finishReason: null });
|
|
752
|
+
}
|
|
721
753
|
if (delta?.content) {
|
|
754
|
+
if (isThinking) {
|
|
755
|
+
isThinking = false;
|
|
756
|
+
fullContent += "\n</think>\n\n";
|
|
757
|
+
onChunk({ text: "\n</think>\n\n", finishReason: null });
|
|
758
|
+
}
|
|
722
759
|
fullContent += delta.content;
|
|
723
760
|
onChunk({ text: delta.content, finishReason: null });
|
|
724
761
|
}
|
|
@@ -741,6 +778,10 @@ var init_openai = __esm({
|
|
|
741
778
|
outputTokens = chunk.usage.completion_tokens;
|
|
742
779
|
}
|
|
743
780
|
}
|
|
781
|
+
if (isThinking) {
|
|
782
|
+
fullContent += "\n</think>\n\n";
|
|
783
|
+
onChunk({ text: "\n</think>\n\n", finishReason: null });
|
|
784
|
+
}
|
|
744
785
|
const toolCalls = Object.values(toolCallsMap).map((tc) => {
|
|
745
786
|
let input = {};
|
|
746
787
|
try {
|
|
@@ -1834,8 +1875,8 @@ Original error: ${err.message}`
|
|
|
1834
1875
|
upsertRuntimeNode(node) {
|
|
1835
1876
|
this.enqueueWrite(() => {
|
|
1836
1877
|
this.db.prepare(`
|
|
1837
|
-
INSERT INTO runtime_nodes (tier_id, session_id, parent_id, role, label, status, current_action, progress_pct, updated_at, workspace_path, is_global)
|
|
1838
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1878
|
+
INSERT INTO runtime_nodes (tier_id, session_id, parent_id, role, label, status, current_action, progress_pct, updated_at, workspace_path, is_global, output)
|
|
1879
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1839
1880
|
ON CONFLICT(tier_id) DO UPDATE SET
|
|
1840
1881
|
session_id = excluded.session_id,
|
|
1841
1882
|
parent_id = excluded.parent_id,
|
|
@@ -1846,7 +1887,8 @@ Original error: ${err.message}`
|
|
|
1846
1887
|
progress_pct = excluded.progress_pct,
|
|
1847
1888
|
updated_at = excluded.updated_at,
|
|
1848
1889
|
workspace_path = excluded.workspace_path,
|
|
1849
|
-
is_global = excluded.is_global
|
|
1890
|
+
is_global = excluded.is_global,
|
|
1891
|
+
output = excluded.output
|
|
1850
1892
|
`).run(
|
|
1851
1893
|
node.tierId,
|
|
1852
1894
|
node.sessionId,
|
|
@@ -1858,7 +1900,8 @@ Original error: ${err.message}`
|
|
|
1858
1900
|
node.progressPct ?? null,
|
|
1859
1901
|
node.updatedAt,
|
|
1860
1902
|
node.workspacePath ?? null,
|
|
1861
|
-
node.isGlobal ? 1 : 0
|
|
1903
|
+
node.isGlobal ? 1 : 0,
|
|
1904
|
+
node.output ?? null
|
|
1862
1905
|
);
|
|
1863
1906
|
});
|
|
1864
1907
|
}
|
|
@@ -1879,14 +1922,15 @@ Original error: ${err.message}`
|
|
|
1879
1922
|
progressPct: row.progress_pct ?? void 0,
|
|
1880
1923
|
updatedAt: row.updated_at,
|
|
1881
1924
|
workspacePath: row.workspace_path ?? void 0,
|
|
1882
|
-
isGlobal: row.is_global === 1
|
|
1925
|
+
isGlobal: row.is_global === 1,
|
|
1926
|
+
output: row.output ?? void 0
|
|
1883
1927
|
}));
|
|
1884
1928
|
}
|
|
1885
1929
|
addRuntimeNodeLog(log) {
|
|
1886
1930
|
this.enqueueWrite(() => {
|
|
1887
1931
|
this.db.prepare(`
|
|
1888
|
-
INSERT INTO runtime_node_logs (id, session_id, tier_id, role, label, status, current_action, progress_pct, timestamp, workspace_path, is_global)
|
|
1889
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1932
|
+
INSERT INTO runtime_node_logs (id, session_id, tier_id, role, label, status, current_action, progress_pct, timestamp, workspace_path, is_global, output)
|
|
1933
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1890
1934
|
`).run(
|
|
1891
1935
|
log.id,
|
|
1892
1936
|
log.sessionId,
|
|
@@ -1898,7 +1942,8 @@ Original error: ${err.message}`
|
|
|
1898
1942
|
log.progressPct ?? null,
|
|
1899
1943
|
log.timestamp,
|
|
1900
1944
|
log.workspacePath ?? null,
|
|
1901
|
-
log.isGlobal ? 1 : 0
|
|
1945
|
+
log.isGlobal ? 1 : 0,
|
|
1946
|
+
log.output ?? null
|
|
1902
1947
|
);
|
|
1903
1948
|
this.db.prepare(`
|
|
1904
1949
|
DELETE FROM runtime_node_logs
|
|
@@ -1941,7 +1986,8 @@ Original error: ${err.message}`
|
|
|
1941
1986
|
progressPct: row.progress_pct ?? void 0,
|
|
1942
1987
|
timestamp: row.timestamp,
|
|
1943
1988
|
workspacePath: row.workspace_path ?? void 0,
|
|
1944
|
-
isGlobal: row.is_global === 1
|
|
1989
|
+
isGlobal: row.is_global === 1,
|
|
1990
|
+
output: row.output ?? void 0
|
|
1945
1991
|
}));
|
|
1946
1992
|
}
|
|
1947
1993
|
// ── Messages ──────────────────────────────────
|
|
@@ -2268,7 +2314,8 @@ Original error: ${err.message}`
|
|
|
2268
2314
|
progress_pct INTEGER,
|
|
2269
2315
|
updated_at TEXT NOT NULL,
|
|
2270
2316
|
workspace_path TEXT,
|
|
2271
|
-
is_global INTEGER NOT NULL DEFAULT 0
|
|
2317
|
+
is_global INTEGER NOT NULL DEFAULT 0,
|
|
2318
|
+
output TEXT
|
|
2272
2319
|
);
|
|
2273
2320
|
|
|
2274
2321
|
CREATE INDEX IF NOT EXISTS idx_runtime_nodes_session ON runtime_nodes(session_id);
|
|
@@ -2285,7 +2332,8 @@ Original error: ${err.message}`
|
|
|
2285
2332
|
progress_pct INTEGER,
|
|
2286
2333
|
timestamp TEXT NOT NULL,
|
|
2287
2334
|
workspace_path TEXT,
|
|
2288
|
-
is_global INTEGER NOT NULL DEFAULT 0
|
|
2335
|
+
is_global INTEGER NOT NULL DEFAULT 0,
|
|
2336
|
+
output TEXT
|
|
2289
2337
|
);
|
|
2290
2338
|
|
|
2291
2339
|
CREATE TABLE IF NOT EXISTS model_cache (
|
|
@@ -2314,6 +2362,14 @@ Original error: ${err.message}`
|
|
|
2314
2362
|
|
|
2315
2363
|
CREATE INDEX IF NOT EXISTS idx_file_snapshots_session ON file_snapshots(session_id);
|
|
2316
2364
|
`);
|
|
2365
|
+
try {
|
|
2366
|
+
this.db.exec("ALTER TABLE runtime_nodes ADD COLUMN output TEXT");
|
|
2367
|
+
} catch {
|
|
2368
|
+
}
|
|
2369
|
+
try {
|
|
2370
|
+
this.db.exec("ALTER TABLE runtime_node_logs ADD COLUMN output TEXT");
|
|
2371
|
+
} catch {
|
|
2372
|
+
}
|
|
2317
2373
|
}
|
|
2318
2374
|
// ── Deserializers ─────────────────────────────
|
|
2319
2375
|
deserializeSession(row, messages) {
|
|
@@ -2576,6 +2632,7 @@ var ConfigManager = class {
|
|
|
2576
2632
|
}
|
|
2577
2633
|
}
|
|
2578
2634
|
async injectEnvKeys() {
|
|
2635
|
+
const isFirstRun = this.config.providers.length === 0;
|
|
2579
2636
|
const envProviders = [
|
|
2580
2637
|
{ env: "ANTHROPIC_API_KEY", type: "anthropic" },
|
|
2581
2638
|
{ env: "OPENAI_API_KEY", type: "openai" },
|
|
@@ -2586,10 +2643,13 @@ var ConfigManager = class {
|
|
|
2586
2643
|
const key = process.env[env];
|
|
2587
2644
|
if (!key) continue;
|
|
2588
2645
|
const existing = this.config.providers.find((p) => p.type === type);
|
|
2589
|
-
if (!existing)
|
|
2590
|
-
|
|
2646
|
+
if (!existing && isFirstRun) {
|
|
2647
|
+
this.config.providers.push({ type, apiKey: key });
|
|
2648
|
+
} else if (existing && !existing.apiKey) {
|
|
2649
|
+
existing.apiKey = key;
|
|
2650
|
+
}
|
|
2591
2651
|
}
|
|
2592
|
-
if (!this.config.providers.find((p) => p.type === "ollama")) {
|
|
2652
|
+
if (isFirstRun && !this.config.providers.find((p) => p.type === "ollama")) {
|
|
2593
2653
|
this.config.providers.push({ type: "ollama" });
|
|
2594
2654
|
}
|
|
2595
2655
|
}
|
|
@@ -3538,7 +3598,7 @@ var BaseTier = class extends EventEmitter {
|
|
|
3538
3598
|
getStatus() {
|
|
3539
3599
|
return this.status;
|
|
3540
3600
|
}
|
|
3541
|
-
setStatus(status) {
|
|
3601
|
+
setStatus(status, output) {
|
|
3542
3602
|
this.status = status;
|
|
3543
3603
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3544
3604
|
const event = {
|
|
@@ -3547,7 +3607,8 @@ var BaseTier = class extends EventEmitter {
|
|
|
3547
3607
|
parentId: this.parentId,
|
|
3548
3608
|
label: this.label,
|
|
3549
3609
|
status,
|
|
3550
|
-
timestamp
|
|
3610
|
+
timestamp,
|
|
3611
|
+
output
|
|
3551
3612
|
};
|
|
3552
3613
|
this.emit("status", event);
|
|
3553
3614
|
this.emit("tier:status", event);
|
|
@@ -3573,7 +3634,8 @@ var BaseTier = class extends EventEmitter {
|
|
|
3573
3634
|
status: this.status,
|
|
3574
3635
|
currentAction: update.currentAction,
|
|
3575
3636
|
progressPct: update.progressPct,
|
|
3576
|
-
timestamp
|
|
3637
|
+
timestamp,
|
|
3638
|
+
output: update.output
|
|
3577
3639
|
});
|
|
3578
3640
|
}
|
|
3579
3641
|
buildMessage(type, to, payload) {
|
|
@@ -3954,16 +4016,17 @@ Now execute your subtask using this context where relevant.`
|
|
|
3954
4016
|
return this.buildResult("ESCALATED", output, { checksRun, passed, failed }, issues, correctionAttempts);
|
|
3955
4017
|
}
|
|
3956
4018
|
}
|
|
3957
|
-
this.setStatus("COMPLETED");
|
|
3958
|
-
this.sendStatusUpdate({ progressPct: 100, currentAction: "Subtask complete", status: "IN_PROGRESS" });
|
|
4019
|
+
this.setStatus("COMPLETED", output);
|
|
4020
|
+
this.sendStatusUpdate({ progressPct: 100, currentAction: "Subtask complete", status: "IN_PROGRESS", output });
|
|
3959
4021
|
this.peerBus?.publish(this.id, assignment.subtaskId, output, "COMPLETED");
|
|
3960
4022
|
return this.buildResult("COMPLETED", output, { checksRun, passed, failed }, issues, correctionAttempts);
|
|
3961
4023
|
} catch (err) {
|
|
3962
4024
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
3963
4025
|
issues.push(`Execution error: ${errMsg}`);
|
|
3964
|
-
|
|
3965
|
-
this.
|
|
3966
|
-
|
|
4026
|
+
const finalOutput = output || errMsg;
|
|
4027
|
+
this.setStatus("FAILED", finalOutput);
|
|
4028
|
+
this.peerBus?.publish(this.id, assignment.subtaskId, finalOutput, "FAILED");
|
|
4029
|
+
return this.buildResult("ESCALATED", finalOutput, { checksRun, passed, failed }, issues, correctionAttempts);
|
|
3967
4030
|
}
|
|
3968
4031
|
}
|
|
3969
4032
|
sendToPeer(toId, content) {
|
|
@@ -4646,8 +4709,9 @@ var T2Manager = class extends BaseTier {
|
|
|
4646
4709
|
const summary = await this.aggregateResults(assignment, t3Results);
|
|
4647
4710
|
const issues = t3Results.filter((r) => r.status !== "COMPLETED").flatMap((r) => r.issues);
|
|
4648
4711
|
const overallStatus = this.determineStatus(t3Results);
|
|
4649
|
-
|
|
4650
|
-
this.
|
|
4712
|
+
const isOk = overallStatus === "COMPLETED" || overallStatus === "PARTIAL";
|
|
4713
|
+
this.setStatus(isOk ? "COMPLETED" : "FAILED", summary);
|
|
4714
|
+
this.sendStatusUpdate({ progressPct: 100, currentAction: "Section complete", status: "IN_PROGRESS", output: summary });
|
|
4651
4715
|
const result = {
|
|
4652
4716
|
sectionId: assignment.sectionId,
|
|
4653
4717
|
sectionTitle: assignment.sectionTitle,
|
|
@@ -4660,7 +4724,7 @@ var T2Manager = class extends BaseTier {
|
|
|
4660
4724
|
return result;
|
|
4661
4725
|
} catch (err) {
|
|
4662
4726
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
4663
|
-
this.setStatus("FAILED");
|
|
4727
|
+
this.setStatus("FAILED", errMsg);
|
|
4664
4728
|
const failedResult = {
|
|
4665
4729
|
sectionId: assignment.sectionId,
|
|
4666
4730
|
sectionTitle: assignment.sectionTitle,
|
|
@@ -5225,8 +5289,8 @@ Create a CORRECTION PLAN that contains only the new sections needed to fix the i
|
|
|
5225
5289
|
status: "IN_PROGRESS"
|
|
5226
5290
|
});
|
|
5227
5291
|
const output = await this.compileFinalOutput(userPrompt, plan, allT2Results);
|
|
5228
|
-
this.setStatus("COMPLETED");
|
|
5229
|
-
this.sendStatusUpdate({ progressPct: 100, currentAction: "Task complete", status: "IN_PROGRESS" });
|
|
5292
|
+
this.setStatus("COMPLETED", output);
|
|
5293
|
+
this.sendStatusUpdate({ progressPct: 100, currentAction: "Task complete", status: "IN_PROGRESS", output });
|
|
5230
5294
|
return { output, t2Results: allT2Results, taskId: this.taskId, complexity: plan.complexity };
|
|
5231
5295
|
}
|
|
5232
5296
|
getEscalations() {
|
|
@@ -8055,11 +8119,6 @@ var SlashCommandRegistry = class {
|
|
|
8055
8119
|
description: "Show active models per tier",
|
|
8056
8120
|
handler: (_args, ctx) => ({ output: ctx.onModelInfo(), handled: true })
|
|
8057
8121
|
});
|
|
8058
|
-
this.register({
|
|
8059
|
-
command: "/models",
|
|
8060
|
-
description: "Browse available models by provider",
|
|
8061
|
-
handler: (_args, ctx) => ({ output: ctx.onModelsInfo(), handled: true })
|
|
8062
|
-
});
|
|
8063
8122
|
this.register({
|
|
8064
8123
|
command: "/providers",
|
|
8065
8124
|
description: "Show configured providers",
|
|
@@ -8188,35 +8247,69 @@ function AgentTree({ root, theme }) {
|
|
|
8188
8247
|
}
|
|
8189
8248
|
function T2Row({ node, theme, isLast }) {
|
|
8190
8249
|
const connector = isLast ? "\u2514\u2500 " : "\u251C\u2500 ";
|
|
8191
|
-
const
|
|
8192
|
-
const
|
|
8193
|
-
const workerSuffix = t3Total > 0 ? ` T3\xD7${t3Total}` : "";
|
|
8250
|
+
const t3Nodes = (node.children ?? []).filter((c) => c.role === "T3");
|
|
8251
|
+
const t3ActiveCount = t3Nodes.filter((c) => c.status === "ACTIVE").length;
|
|
8194
8252
|
const label = stripRolePrefix(node.label, node.role);
|
|
8195
8253
|
const action = node.currentAction ? ` ${node.currentAction.slice(0, 38)}` : "";
|
|
8254
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
8255
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
8256
|
+
/* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
|
|
8257
|
+
" ",
|
|
8258
|
+
connector
|
|
8259
|
+
] }),
|
|
8260
|
+
/* @__PURE__ */ jsx(Text, { color: theme.colors.t2Color, bold: true, children: "[T2]" }),
|
|
8261
|
+
/* @__PURE__ */ jsxs(Text, { color: theme.colors.foreground, children: [
|
|
8262
|
+
" ",
|
|
8263
|
+
label
|
|
8264
|
+
] }),
|
|
8265
|
+
node.status === "ACTIVE" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8266
|
+
action ? /* @__PURE__ */ jsx(Text, { color: theme.colors.muted, children: action }) : null,
|
|
8267
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
8268
|
+
/* @__PURE__ */ jsx(Spinner, { type: "dots" }),
|
|
8269
|
+
t3ActiveCount > 0 ? /* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
|
|
8270
|
+
" (",
|
|
8271
|
+
t3ActiveCount,
|
|
8272
|
+
" running)"
|
|
8273
|
+
] }) : null
|
|
8274
|
+
] }),
|
|
8275
|
+
node.status === "COMPLETED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.success, children: " \u2714" }),
|
|
8276
|
+
node.status === "FAILED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.error, children: " \u2718" }),
|
|
8277
|
+
node.status === "ESCALATED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.warning, children: " \u25B2" })
|
|
8278
|
+
] }),
|
|
8279
|
+
t3Nodes.map((t3, idx) => /* @__PURE__ */ jsx(
|
|
8280
|
+
T3Row,
|
|
8281
|
+
{
|
|
8282
|
+
node: t3,
|
|
8283
|
+
theme,
|
|
8284
|
+
isLast: idx === t3Nodes.length - 1,
|
|
8285
|
+
parentIsLast: isLast
|
|
8286
|
+
},
|
|
8287
|
+
t3.id
|
|
8288
|
+
))
|
|
8289
|
+
] });
|
|
8290
|
+
}
|
|
8291
|
+
function T3Row({ node, theme, isLast, parentIsLast }) {
|
|
8292
|
+
const indent = parentIsLast ? " " : " \u2502 ";
|
|
8293
|
+
const connector = isLast ? "\u2514\u2500 " : "\u251C\u2500 ";
|
|
8294
|
+
const label = stripRolePrefix(node.label, node.role);
|
|
8295
|
+
const action = node.currentAction ? ` ${node.currentAction.slice(0, 42)}` : "";
|
|
8196
8296
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
8197
8297
|
/* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
|
|
8198
|
-
|
|
8298
|
+
indent,
|
|
8199
8299
|
connector
|
|
8200
8300
|
] }),
|
|
8201
|
-
/* @__PURE__ */ jsx(Text, { color: theme.colors.
|
|
8202
|
-
/* @__PURE__ */ jsxs(Text, { color: theme.colors.
|
|
8301
|
+
/* @__PURE__ */ jsx(Text, { color: theme.colors.t3Color, children: "[T3]" }),
|
|
8302
|
+
/* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
|
|
8203
8303
|
" ",
|
|
8204
8304
|
label
|
|
8205
8305
|
] }),
|
|
8206
|
-
workerSuffix ? /* @__PURE__ */ jsx(Text, { color: theme.colors.muted, children: workerSuffix }) : null,
|
|
8207
8306
|
node.status === "ACTIVE" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8208
8307
|
action ? /* @__PURE__ */ jsx(Text, { color: theme.colors.muted, children: action }) : null,
|
|
8209
8308
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
8210
|
-
/* @__PURE__ */ jsx(Spinner, { type: "dots" })
|
|
8211
|
-
t3Active > 0 ? /* @__PURE__ */ jsxs(Text, { color: theme.colors.muted, children: [
|
|
8212
|
-
" (",
|
|
8213
|
-
t3Active,
|
|
8214
|
-
" running)"
|
|
8215
|
-
] }) : null
|
|
8309
|
+
/* @__PURE__ */ jsx(Spinner, { type: "dots" })
|
|
8216
8310
|
] }),
|
|
8217
8311
|
node.status === "COMPLETED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.success, children: " \u2714" }),
|
|
8218
|
-
node.status === "FAILED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.error, children: " \u2718" })
|
|
8219
|
-
node.status === "ESCALATED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.warning, children: " \u25B2" })
|
|
8312
|
+
node.status === "FAILED" && /* @__PURE__ */ jsx(Text, { color: theme.colors.error, children: " \u2718" })
|
|
8220
8313
|
] });
|
|
8221
8314
|
}
|
|
8222
8315
|
function hasActiveOrFailed(node) {
|
|
@@ -8828,7 +8921,7 @@ function Repl({ config, workspacePath, themeName, initialPrompt, identityName })
|
|
|
8828
8921
|
treeNodesRef.current.set(event.tierId, node);
|
|
8829
8922
|
const store = storeRef.current;
|
|
8830
8923
|
if (store) {
|
|
8831
|
-
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 };
|
|
8924
|
+
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 };
|
|
8832
8925
|
store.upsertRuntimeNode(runtimeNode);
|
|
8833
8926
|
globalStoreRef.current?.upsertRuntimeNode({ ...runtimeNode, isGlobal: true });
|
|
8834
8927
|
}
|
|
@@ -8839,7 +8932,6 @@ function Repl({ config, workspacePath, themeName, initialPrompt, identityName })
|
|
|
8839
8932
|
useEffect(() => {
|
|
8840
8933
|
const originalWarn = console.warn;
|
|
8841
8934
|
const originalLog = console.log;
|
|
8842
|
-
process.stdout.write("\x1Bc");
|
|
8843
8935
|
console.warn = (...args) => {
|
|
8844
8936
|
const msg = args.join(" ");
|
|
8845
8937
|
if (msg.includes("non-text parts") || msg.includes("functionCall")) return;
|
|
@@ -9356,8 +9448,8 @@ Use /identity <name|id> to switch.`;
|
|
|
9356
9448
|
const statusHeight = agentTreeHeight + timelineHeight;
|
|
9357
9449
|
const costHeight = state.showCost ? 6 : 0;
|
|
9358
9450
|
const approvalHeight = state.approvalRequest ? 12 : 0;
|
|
9359
|
-
|
|
9360
|
-
const slashHeight =
|
|
9451
|
+
Math.min(SLASH_PAGE_SIZE, slashEntries.length);
|
|
9452
|
+
const slashHeight = isTypingCommand ? SLASH_PAGE_SIZE + 2 : 0;
|
|
9361
9453
|
const chromeHeight = statusHeight + costHeight + approvalHeight + slashHeight + 7;
|
|
9362
9454
|
const availableHeight = Math.max(4, height - chromeHeight);
|
|
9363
9455
|
const allLines = formatToLines(
|
|
@@ -9769,8 +9861,21 @@ function wizardReducer(state, action) {
|
|
|
9769
9861
|
addingAnotherCompat: false
|
|
9770
9862
|
};
|
|
9771
9863
|
}
|
|
9864
|
+
case "ADD_OLLAMA": {
|
|
9865
|
+
const newEntry = {
|
|
9866
|
+
id: randomUUID(),
|
|
9867
|
+
type: "ollama",
|
|
9868
|
+
label: `Ollama endpoint ${state.entries.filter((e) => e.type === "ollama").length + 1}`
|
|
9869
|
+
};
|
|
9870
|
+
return {
|
|
9871
|
+
...state,
|
|
9872
|
+
entries: [...state.entries, newEntry],
|
|
9873
|
+
currentEntryIdx: state.entries.length,
|
|
9874
|
+
addingAnotherOllama: false
|
|
9875
|
+
};
|
|
9876
|
+
}
|
|
9772
9877
|
case "SKIP_MORE":
|
|
9773
|
-
return { ...state, addingAnotherAzure: false, addingAnotherCompat: false, step: "FETCH_MODELS", currentEntryIdx: 0 };
|
|
9878
|
+
return { ...state, addingAnotherAzure: false, addingAnotherCompat: false, addingAnotherOllama: false, step: "FETCH_MODELS", currentEntryIdx: 0 };
|
|
9774
9879
|
case "GO_FETCH":
|
|
9775
9880
|
return { ...state, step: "FETCH_MODELS", fetchLog: [], fetchedModels: [] };
|
|
9776
9881
|
case "SET_FETCH_LOG":
|
|
@@ -9803,6 +9908,7 @@ function SetupWizard({ workspacePath, onComplete }) {
|
|
|
9803
9908
|
currentEntryIdx: 0,
|
|
9804
9909
|
addingAnotherAzure: false,
|
|
9805
9910
|
addingAnotherCompat: false,
|
|
9911
|
+
addingAnotherOllama: false,
|
|
9806
9912
|
fetchedModels: [],
|
|
9807
9913
|
fetchLog: [],
|
|
9808
9914
|
tierT1: "auto",
|
|
@@ -9902,13 +10008,16 @@ function SetupWizard({ workspacePath, onComplete }) {
|
|
|
9902
10008
|
}, [state.step, state.entries, state.tierT1, state.tierT2, state.tierT3, workspacePath, onComplete, exit]);
|
|
9903
10009
|
useInput((_input, key) => {
|
|
9904
10010
|
if (state.step === "PROVIDER_SELECT") {
|
|
9905
|
-
if (key.upArrow) setProviderCursor((p) =>
|
|
9906
|
-
if (key.downArrow) setProviderCursor((p) =>
|
|
10011
|
+
if (key.upArrow) setProviderCursor((p) => p <= 0 ? providerOrder.length - 1 : p - 1);
|
|
10012
|
+
if (key.downArrow) setProviderCursor((p) => p >= providerOrder.length - 1 ? 0 : p + 1);
|
|
9907
10013
|
if (_input === " ") dispatch({ type: "TOGGLE_PROVIDER", provider: providerOrder[providerCursor] });
|
|
9908
10014
|
if (_input === "a") dispatch({ type: "TOGGLE_ALL" });
|
|
9909
10015
|
if (_input === "i") dispatch({ type: "INVERT_SELECTION" });
|
|
9910
10016
|
if (key.return) {
|
|
9911
|
-
if (state.selectedTypes.size === 0)
|
|
10017
|
+
if (state.selectedTypes.size === 0) {
|
|
10018
|
+
dispatch({ type: "SET_ERROR", error: "Please select at least one provider using <space> before pressing <enter>." });
|
|
10019
|
+
return;
|
|
10020
|
+
}
|
|
9912
10021
|
dispatch({ type: "CONFIRM_PROVIDERS" });
|
|
9913
10022
|
const firstType = [...state.selectedTypes][0];
|
|
9914
10023
|
setFieldStage(firstType === "azure" ? "deploymentName" : firstType === "openai-compatible" ? "label" : firstType === "ollama" ? "baseUrl" : "apiKey");
|
|
@@ -9965,11 +10074,7 @@ function SetupWizard({ workspacePath, onComplete }) {
|
|
|
9965
10074
|
} else if (currentEntry.type === "ollama") {
|
|
9966
10075
|
dispatch({ type: "SET_ENTRY_FIELD", field: "baseUrl", value: val || "http://localhost:11434" });
|
|
9967
10076
|
setFieldBuffer("");
|
|
9968
|
-
|
|
9969
|
-
if (nextEntry) {
|
|
9970
|
-
setFieldStage(nextEntry.type === "azure" ? "deploymentName" : nextEntry.type === "openai-compatible" ? "label" : nextEntry.type === "ollama" ? "baseUrl" : "apiKey");
|
|
9971
|
-
}
|
|
9972
|
-
dispatch({ type: "NEXT_ENTRY" });
|
|
10077
|
+
setFieldStage("askMore");
|
|
9973
10078
|
} else {
|
|
9974
10079
|
dispatch({ type: "SET_ENTRY_FIELD", field: "apiKey", value: val });
|
|
9975
10080
|
setFieldBuffer("");
|
|
@@ -10010,7 +10115,7 @@ function SetupWizard({ workspacePath, onComplete }) {
|
|
|
10010
10115
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
|
|
10011
10116
|
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
10012
10117
|
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: "? " }),
|
|
10013
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: isAzure ? "Add another Azure deployment? (y/n)" : "Add another custom endpoint? (y/n)" })
|
|
10118
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: isAzure ? "Add another Azure deployment? (y/n)" : isOllama ? "Add another Ollama endpoint? (y/n)" : "Add another custom endpoint? (y/n)" })
|
|
10014
10119
|
] }),
|
|
10015
10120
|
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
|
|
10016
10121
|
SelectInput,
|
|
@@ -10024,8 +10129,9 @@ function SetupWizard({ workspacePath, onComplete }) {
|
|
|
10024
10129
|
onSelect: (item) => {
|
|
10025
10130
|
if (item.value === "yes") {
|
|
10026
10131
|
if (isAzure) dispatch({ type: "ADD_AZURE" });
|
|
10132
|
+
else if (isOllama) dispatch({ type: "ADD_OLLAMA" });
|
|
10027
10133
|
else dispatch({ type: "ADD_COMPAT" });
|
|
10028
|
-
setFieldStage(isAzure ? "deploymentName" : "label");
|
|
10134
|
+
setFieldStage(isAzure ? "deploymentName" : isOllama ? "baseUrl" : "label");
|
|
10029
10135
|
setFieldBuffer("");
|
|
10030
10136
|
} else {
|
|
10031
10137
|
const nextEntry = state.entries[state.currentEntryIdx + 1];
|
|
@@ -10041,7 +10147,7 @@ function SetupWizard({ workspacePath, onComplete }) {
|
|
|
10041
10147
|
] });
|
|
10042
10148
|
}
|
|
10043
10149
|
const prompt = isAzure && fieldStage === "deploymentName" ? `Azure deployment name (${currentEntry.label})` : isAzure && fieldStage === "baseUrl" ? `Azure endpoint URL` : isCompat && fieldStage === "label" ? `Name for this endpoint (e.g. Groq)` : isCompat && fieldStage === "baseUrl" ? `Base URL (e.g. https://api.groq.com/openai/v1)` : isOllama ? `Ollama URL (Enter for http://localhost:11434)` : `${currentEntry.label} API Key`;
|
|
10044
|
-
const isMasked = fieldStage === "apiKey";
|
|
10150
|
+
const isMasked = fieldStage === "apiKey" && !isOllama;
|
|
10045
10151
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
|
|
10046
10152
|
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
10047
10153
|
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: "? " }),
|
|
@@ -10935,8 +11041,8 @@ var DashboardServer = class {
|
|
|
10935
11041
|
void (async () => {
|
|
10936
11042
|
const cascade = new Cascade(this.config, this.workspacePath, this.store);
|
|
10937
11043
|
cascade.on("stream:token", (e) => {
|
|
10938
|
-
this.socket.broadcast("stream:token", { sessionId,
|
|
10939
|
-
this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId,
|
|
11044
|
+
this.socket.broadcast("stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
11045
|
+
this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
10940
11046
|
});
|
|
10941
11047
|
cascade.on("tier:status", (e) => {
|
|
10942
11048
|
this.socket.broadcast("tier:status", { sessionId, ...e });
|
|
@@ -11372,6 +11478,9 @@ async function startRepl(options) {
|
|
|
11372
11478
|
await cm.load();
|
|
11373
11479
|
config = cm.getConfig();
|
|
11374
11480
|
}
|
|
11481
|
+
if (process.stdout.isTTY) {
|
|
11482
|
+
process.stdout.write("\x1B[2J\x1B[H");
|
|
11483
|
+
}
|
|
11375
11484
|
const { waitUntilExit } = render(
|
|
11376
11485
|
React5.createElement(Repl, {
|
|
11377
11486
|
config,
|