cascade-ai 0.12.21 → 0.12.23
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 +98 -11
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +98 -11
- package/dist/cli.js.map +1 -1
- package/dist/desktop-core.cjs +98 -11
- package/dist/index.cjs +98 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +98 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -109,7 +109,7 @@ var __export = (target, all) => {
|
|
|
109
109
|
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;
|
|
110
110
|
var init_constants = __esm({
|
|
111
111
|
"src/constants.ts"() {
|
|
112
|
-
CASCADE_VERSION = "0.12.
|
|
112
|
+
CASCADE_VERSION = "0.12.23";
|
|
113
113
|
CASCADE_CONFIG_FILE = ".cascade/config.json";
|
|
114
114
|
CASCADE_DB_FILE = ".cascade/memory.db";
|
|
115
115
|
CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
|
|
@@ -14831,7 +14831,8 @@ var DashboardSocket = class {
|
|
|
14831
14831
|
this.io.on("connection", (socket) => {
|
|
14832
14832
|
socket.on("cascade:run", (payload) => {
|
|
14833
14833
|
if (typeof payload?.prompt === "string" && payload.prompt.trim()) {
|
|
14834
|
-
|
|
14834
|
+
const sessionId = typeof payload.sessionId === "string" && payload.sessionId.trim() ? payload.sessionId.trim() : void 0;
|
|
14835
|
+
callback(payload.prompt.trim(), payload.model ?? "auto", socket.id, sessionId);
|
|
14835
14836
|
}
|
|
14836
14837
|
});
|
|
14837
14838
|
});
|
|
@@ -14912,18 +14913,18 @@ var DashboardServer = class {
|
|
|
14912
14913
|
}
|
|
14913
14914
|
this.persistConfig();
|
|
14914
14915
|
});
|
|
14915
|
-
this.socket.onCascadeRun(async (prompt, model, socketId) => {
|
|
14916
|
-
const sessionId = crypto.randomUUID();
|
|
14916
|
+
this.socket.onCascadeRun(async (prompt, model, socketId, requestedSessionId) => {
|
|
14917
|
+
const sessionId = requestedSessionId ?? crypto.randomUUID();
|
|
14918
|
+
const runPrompt = requestedSessionId ? this.buildContinuationPrompt(sessionId, prompt) : prompt;
|
|
14919
|
+
const title = this.persistRunStart(sessionId, prompt);
|
|
14917
14920
|
const cfg = model !== "auto" ? { ...this.config, models: { ...this.config.models, t1: model } } : this.config;
|
|
14918
14921
|
const cascade = new Cascade(cfg, this.workspacePath, this.store);
|
|
14919
14922
|
this.activeSessions.set(sessionId, cascade);
|
|
14920
14923
|
cascade.on("stream:token", (e) => {
|
|
14921
14924
|
this.socket.emitToSocket(socketId, "stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
14922
|
-
this.socket.broadcast("stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
14923
14925
|
});
|
|
14924
14926
|
cascade.on("tier:status", (e) => {
|
|
14925
14927
|
this.socket.emitToSocket(socketId, "tier:status", { sessionId, ...e });
|
|
14926
|
-
this.socket.broadcast("tier:status", { sessionId, ...e });
|
|
14927
14928
|
});
|
|
14928
14929
|
cascade.on("permission:user-required", (e) => {
|
|
14929
14930
|
this.socket.emitToSocket(socketId, "permission:user-required", { sessionId, ...e });
|
|
@@ -14932,7 +14933,8 @@ var DashboardServer = class {
|
|
|
14932
14933
|
this.socket.emitPeerMessage(e);
|
|
14933
14934
|
});
|
|
14934
14935
|
try {
|
|
14935
|
-
const result = await cascade.run({ prompt });
|
|
14936
|
+
const result = await cascade.run({ prompt: runPrompt });
|
|
14937
|
+
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
14936
14938
|
this.socket.emitToSocket(socketId, "session:complete", { sessionId, result });
|
|
14937
14939
|
this.socket.broadcast("cost:update", {
|
|
14938
14940
|
sessionId,
|
|
@@ -14941,6 +14943,7 @@ var DashboardServer = class {
|
|
|
14941
14943
|
});
|
|
14942
14944
|
this.throttledBroadcast("workspace");
|
|
14943
14945
|
} catch (err) {
|
|
14946
|
+
this.persistRunEnd(sessionId, title, prompt, void 0, "FAILED");
|
|
14944
14947
|
this.socket.emitToSocket(socketId, "session:error", {
|
|
14945
14948
|
sessionId,
|
|
14946
14949
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -15051,6 +15054,86 @@ var DashboardServer = class {
|
|
|
15051
15054
|
}
|
|
15052
15055
|
return this.globalStore;
|
|
15053
15056
|
}
|
|
15057
|
+
// ── Desktop-run session persistence ─────────
|
|
15058
|
+
// Only the CLI REPL used to persist sessions; runs started from the desktop
|
|
15059
|
+
// (socket `cascade:run` and REST /api/run) wrote nothing to the store, so
|
|
15060
|
+
// they never appeared in the session list and couldn't be resumed. These
|
|
15061
|
+
// helpers give both run paths the same persistence the CLI has.
|
|
15062
|
+
/** Record run start: session row (if new), the user message, and an ACTIVE runtime row. Returns the session title. */
|
|
15063
|
+
persistRunStart(sessionId, prompt) {
|
|
15064
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
15065
|
+
let title = prompt.replace(/\s+/g, " ").trim().slice(0, 40);
|
|
15066
|
+
try {
|
|
15067
|
+
const existing = this.store.getSession(sessionId);
|
|
15068
|
+
if (existing) {
|
|
15069
|
+
title = existing.title;
|
|
15070
|
+
} else {
|
|
15071
|
+
this.store.createSession({
|
|
15072
|
+
id: sessionId,
|
|
15073
|
+
title,
|
|
15074
|
+
createdAt: now,
|
|
15075
|
+
updatedAt: now,
|
|
15076
|
+
identityId: this.config.defaultIdentityId ?? "default",
|
|
15077
|
+
workspacePath: this.workspacePath,
|
|
15078
|
+
messages: [],
|
|
15079
|
+
metadata: { totalTokens: 0, totalCostUsd: 0, modelsUsed: [], toolsUsed: [], taskCount: 0 }
|
|
15080
|
+
});
|
|
15081
|
+
}
|
|
15082
|
+
this.store.addMessage({ id: crypto.randomUUID(), sessionId, role: "user", content: prompt, timestamp: now });
|
|
15083
|
+
} catch (err) {
|
|
15084
|
+
console.warn("[dashboard] failed to persist run start:", err);
|
|
15085
|
+
}
|
|
15086
|
+
this.persistRuntimeRow(sessionId, title, "ACTIVE", prompt);
|
|
15087
|
+
return title;
|
|
15088
|
+
}
|
|
15089
|
+
/** Record run end: the assistant reply (when there is one) and the runtime row's final status. */
|
|
15090
|
+
persistRunEnd(sessionId, title, latestPrompt, reply, status) {
|
|
15091
|
+
try {
|
|
15092
|
+
if (reply && reply.trim()) {
|
|
15093
|
+
this.store.addMessage({ id: crypto.randomUUID(), sessionId, role: "assistant", content: reply, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
15094
|
+
}
|
|
15095
|
+
} catch (err) {
|
|
15096
|
+
console.warn("[dashboard] failed to persist run end:", err);
|
|
15097
|
+
}
|
|
15098
|
+
this.persistRuntimeRow(sessionId, title, status, latestPrompt);
|
|
15099
|
+
}
|
|
15100
|
+
persistRuntimeRow(sessionId, title, status, latestPrompt) {
|
|
15101
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
15102
|
+
const row = { sessionId, title, workspacePath: this.workspacePath, status, startedAt: now, updatedAt: now, latestPrompt, isGlobal: false };
|
|
15103
|
+
try {
|
|
15104
|
+
this.store.upsertRuntimeSession(row);
|
|
15105
|
+
} catch (err) {
|
|
15106
|
+
console.warn("[dashboard] runtime upsert failed:", err);
|
|
15107
|
+
}
|
|
15108
|
+
try {
|
|
15109
|
+
this.getGlobalStore().upsertRuntimeSession({ ...row, isGlobal: true });
|
|
15110
|
+
} catch {
|
|
15111
|
+
}
|
|
15112
|
+
this.throttledBroadcast("workspace");
|
|
15113
|
+
}
|
|
15114
|
+
/**
|
|
15115
|
+
* Continuing an existing session: the Cascade orchestrator is per-run and
|
|
15116
|
+
* stateless across runs, so prepend a compact transcript of the stored
|
|
15117
|
+
* conversation to the new prompt. Called BEFORE persistRunStart so the new
|
|
15118
|
+
* prompt isn't duplicated into its own context.
|
|
15119
|
+
*/
|
|
15120
|
+
buildContinuationPrompt(sessionId, prompt) {
|
|
15121
|
+
try {
|
|
15122
|
+
const history = this.store.getSessionMessages(sessionId);
|
|
15123
|
+
if (history.length === 0) return prompt;
|
|
15124
|
+
const lines = history.slice(-10).map((m) => {
|
|
15125
|
+
const text = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
15126
|
+
return `${m.role === "user" ? "User" : "Assistant"}: ${text.slice(0, 2e3)}`;
|
|
15127
|
+
});
|
|
15128
|
+
return `Conversation so far (for context):
|
|
15129
|
+
${lines.join("\n")}
|
|
15130
|
+
|
|
15131
|
+
User's new message:
|
|
15132
|
+
${prompt}`;
|
|
15133
|
+
} catch {
|
|
15134
|
+
return prompt;
|
|
15135
|
+
}
|
|
15136
|
+
}
|
|
15054
15137
|
throttledBroadcast(scope) {
|
|
15055
15138
|
if (this.broadcastTimer) return;
|
|
15056
15139
|
this.broadcastTimer = setTimeout(() => {
|
|
@@ -15412,17 +15495,19 @@ var DashboardServer = class {
|
|
|
15412
15495
|
res.status(400).json({ error: "prompt is required" });
|
|
15413
15496
|
return;
|
|
15414
15497
|
}
|
|
15415
|
-
const
|
|
15498
|
+
const requestedSessionId = typeof body.sessionId === "string" && body.sessionId.trim() ? body.sessionId.trim() : void 0;
|
|
15499
|
+
const sessionId = requestedSessionId ?? crypto.randomUUID();
|
|
15416
15500
|
res.json({ sessionId, status: "ACTIVE" });
|
|
15501
|
+
const prompt = body.prompt;
|
|
15502
|
+
const runPrompt = requestedSessionId ? this.buildContinuationPrompt(sessionId, prompt) : prompt;
|
|
15503
|
+
const title = this.persistRunStart(sessionId, prompt);
|
|
15417
15504
|
void (async () => {
|
|
15418
15505
|
const cascade = new Cascade(this.config, this.workspacePath, this.store);
|
|
15419
15506
|
this.activeSessions.set(sessionId, cascade);
|
|
15420
15507
|
cascade.on("stream:token", (e) => {
|
|
15421
|
-
this.socket.broadcast("stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
15422
15508
|
this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
15423
15509
|
});
|
|
15424
15510
|
cascade.on("tier:status", (e) => {
|
|
15425
|
-
this.socket.broadcast("tier:status", { sessionId, ...e });
|
|
15426
15511
|
this.socket.broadcastToRoom(`session:${sessionId}`, "tier:status", { sessionId, ...e });
|
|
15427
15512
|
});
|
|
15428
15513
|
cascade.on("permission:user-required", (e) => {
|
|
@@ -15432,7 +15517,8 @@ var DashboardServer = class {
|
|
|
15432
15517
|
this.socket.emitPeerMessage(e);
|
|
15433
15518
|
});
|
|
15434
15519
|
try {
|
|
15435
|
-
const result = await cascade.run({ prompt:
|
|
15520
|
+
const result = await cascade.run({ prompt: runPrompt, identityId: body.identityId });
|
|
15521
|
+
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
15436
15522
|
this.socket.broadcast("cost:update", {
|
|
15437
15523
|
sessionId,
|
|
15438
15524
|
totalTokens: result.usage.totalTokens,
|
|
@@ -15441,6 +15527,7 @@ var DashboardServer = class {
|
|
|
15441
15527
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:complete", { sessionId, result });
|
|
15442
15528
|
this.throttledBroadcast("workspace");
|
|
15443
15529
|
} catch (err) {
|
|
15530
|
+
this.persistRunEnd(sessionId, title, prompt, void 0, "FAILED");
|
|
15444
15531
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:error", {
|
|
15445
15532
|
sessionId,
|
|
15446
15533
|
error: err instanceof Error ? err.message : String(err)
|