cascade-ai 0.12.22 → 0.12.24
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 -7
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +98 -7
- package/dist/cli.js.map +1 -1
- package/dist/desktop-core.cjs +98 -7
- package/dist/index.cjs +98 -7
- 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 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/desktop-core.cjs
CHANGED
|
@@ -222452,7 +222452,7 @@ Anthropic.Models = Models2;
|
|
|
222452
222452
|
Anthropic.Beta = Beta;
|
|
222453
222453
|
|
|
222454
222454
|
// src/constants.ts
|
|
222455
|
-
var CASCADE_VERSION = "0.12.
|
|
222455
|
+
var CASCADE_VERSION = "0.12.24";
|
|
222456
222456
|
var CASCADE_CONFIG_DIR = ".cascade";
|
|
222457
222457
|
var CASCADE_MD_FILE = "CASCADE.md";
|
|
222458
222458
|
var CASCADE_IGNORE_FILE = ".cascadeignore";
|
|
@@ -297978,7 +297978,8 @@ var DashboardSocket = class {
|
|
|
297978
297978
|
this.io.on("connection", (socket) => {
|
|
297979
297979
|
socket.on("cascade:run", (payload) => {
|
|
297980
297980
|
if (typeof payload?.prompt === "string" && payload.prompt.trim()) {
|
|
297981
|
-
|
|
297981
|
+
const sessionId = typeof payload.sessionId === "string" && payload.sessionId.trim() ? payload.sessionId.trim() : void 0;
|
|
297982
|
+
callback(payload.prompt.trim(), payload.model ?? "auto", socket.id, sessionId);
|
|
297982
297983
|
}
|
|
297983
297984
|
});
|
|
297984
297985
|
});
|
|
@@ -298056,8 +298057,10 @@ var DashboardServer = class {
|
|
|
298056
298057
|
}
|
|
298057
298058
|
this.persistConfig();
|
|
298058
298059
|
});
|
|
298059
|
-
this.socket.onCascadeRun(async (prompt, model, socketId) => {
|
|
298060
|
-
const sessionId = crypto2.randomUUID();
|
|
298060
|
+
this.socket.onCascadeRun(async (prompt, model, socketId, requestedSessionId) => {
|
|
298061
|
+
const sessionId = requestedSessionId ?? crypto2.randomUUID();
|
|
298062
|
+
const runPrompt = requestedSessionId ? this.buildContinuationPrompt(sessionId, prompt) : prompt;
|
|
298063
|
+
const title = this.persistRunStart(sessionId, prompt);
|
|
298061
298064
|
const cfg = model !== "auto" ? { ...this.config, models: { ...this.config.models, t1: model } } : this.config;
|
|
298062
298065
|
const cascade = new Cascade(cfg, this.workspacePath, this.store);
|
|
298063
298066
|
this.activeSessions.set(sessionId, cascade);
|
|
@@ -298074,7 +298077,8 @@ var DashboardServer = class {
|
|
|
298074
298077
|
this.socket.emitPeerMessage(e3);
|
|
298075
298078
|
});
|
|
298076
298079
|
try {
|
|
298077
|
-
const result = await cascade.run({ prompt });
|
|
298080
|
+
const result = await cascade.run({ prompt: runPrompt });
|
|
298081
|
+
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
298078
298082
|
this.socket.emitToSocket(socketId, "session:complete", { sessionId, result });
|
|
298079
298083
|
this.socket.broadcast("cost:update", {
|
|
298080
298084
|
sessionId,
|
|
@@ -298083,6 +298087,7 @@ var DashboardServer = class {
|
|
|
298083
298087
|
});
|
|
298084
298088
|
this.throttledBroadcast("workspace");
|
|
298085
298089
|
} catch (err) {
|
|
298090
|
+
this.persistRunEnd(sessionId, title, prompt, void 0, "FAILED");
|
|
298086
298091
|
this.socket.emitToSocket(socketId, "session:error", {
|
|
298087
298092
|
sessionId,
|
|
298088
298093
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -298193,6 +298198,86 @@ var DashboardServer = class {
|
|
|
298193
298198
|
}
|
|
298194
298199
|
return this.globalStore;
|
|
298195
298200
|
}
|
|
298201
|
+
// ── Desktop-run session persistence ─────────
|
|
298202
|
+
// Only the CLI REPL used to persist sessions; runs started from the desktop
|
|
298203
|
+
// (socket `cascade:run` and REST /api/run) wrote nothing to the store, so
|
|
298204
|
+
// they never appeared in the session list and couldn't be resumed. These
|
|
298205
|
+
// helpers give both run paths the same persistence the CLI has.
|
|
298206
|
+
/** Record run start: session row (if new), the user message, and an ACTIVE runtime row. Returns the session title. */
|
|
298207
|
+
persistRunStart(sessionId, prompt) {
|
|
298208
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
298209
|
+
let title = prompt.replace(/\s+/g, " ").trim().slice(0, 40);
|
|
298210
|
+
try {
|
|
298211
|
+
const existing = this.store.getSession(sessionId);
|
|
298212
|
+
if (existing) {
|
|
298213
|
+
title = existing.title;
|
|
298214
|
+
} else {
|
|
298215
|
+
this.store.createSession({
|
|
298216
|
+
id: sessionId,
|
|
298217
|
+
title,
|
|
298218
|
+
createdAt: now,
|
|
298219
|
+
updatedAt: now,
|
|
298220
|
+
identityId: this.config.defaultIdentityId ?? "default",
|
|
298221
|
+
workspacePath: this.workspacePath,
|
|
298222
|
+
messages: [],
|
|
298223
|
+
metadata: { totalTokens: 0, totalCostUsd: 0, modelsUsed: [], toolsUsed: [], taskCount: 0 }
|
|
298224
|
+
});
|
|
298225
|
+
}
|
|
298226
|
+
this.store.addMessage({ id: crypto2.randomUUID(), sessionId, role: "user", content: prompt, timestamp: now });
|
|
298227
|
+
} catch (err) {
|
|
298228
|
+
console.warn("[dashboard] failed to persist run start:", err);
|
|
298229
|
+
}
|
|
298230
|
+
this.persistRuntimeRow(sessionId, title, "ACTIVE", prompt);
|
|
298231
|
+
return title;
|
|
298232
|
+
}
|
|
298233
|
+
/** Record run end: the assistant reply (when there is one) and the runtime row's final status. */
|
|
298234
|
+
persistRunEnd(sessionId, title, latestPrompt, reply, status) {
|
|
298235
|
+
try {
|
|
298236
|
+
if (reply && reply.trim()) {
|
|
298237
|
+
this.store.addMessage({ id: crypto2.randomUUID(), sessionId, role: "assistant", content: reply, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
298238
|
+
}
|
|
298239
|
+
} catch (err) {
|
|
298240
|
+
console.warn("[dashboard] failed to persist run end:", err);
|
|
298241
|
+
}
|
|
298242
|
+
this.persistRuntimeRow(sessionId, title, status, latestPrompt);
|
|
298243
|
+
}
|
|
298244
|
+
persistRuntimeRow(sessionId, title, status, latestPrompt) {
|
|
298245
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
298246
|
+
const row = { sessionId, title, workspacePath: this.workspacePath, status, startedAt: now, updatedAt: now, latestPrompt, isGlobal: false };
|
|
298247
|
+
try {
|
|
298248
|
+
this.store.upsertRuntimeSession(row);
|
|
298249
|
+
} catch (err) {
|
|
298250
|
+
console.warn("[dashboard] runtime upsert failed:", err);
|
|
298251
|
+
}
|
|
298252
|
+
try {
|
|
298253
|
+
this.getGlobalStore().upsertRuntimeSession({ ...row, isGlobal: true });
|
|
298254
|
+
} catch {
|
|
298255
|
+
}
|
|
298256
|
+
this.throttledBroadcast("workspace");
|
|
298257
|
+
}
|
|
298258
|
+
/**
|
|
298259
|
+
* Continuing an existing session: the Cascade orchestrator is per-run and
|
|
298260
|
+
* stateless across runs, so prepend a compact transcript of the stored
|
|
298261
|
+
* conversation to the new prompt. Called BEFORE persistRunStart so the new
|
|
298262
|
+
* prompt isn't duplicated into its own context.
|
|
298263
|
+
*/
|
|
298264
|
+
buildContinuationPrompt(sessionId, prompt) {
|
|
298265
|
+
try {
|
|
298266
|
+
const history = this.store.getSessionMessages(sessionId);
|
|
298267
|
+
if (history.length === 0) return prompt;
|
|
298268
|
+
const lines = history.slice(-10).map((m3) => {
|
|
298269
|
+
const text = typeof m3.content === "string" ? m3.content : JSON.stringify(m3.content);
|
|
298270
|
+
return `${m3.role === "user" ? "User" : "Assistant"}: ${text.slice(0, 2e3)}`;
|
|
298271
|
+
});
|
|
298272
|
+
return `Conversation so far (for context):
|
|
298273
|
+
${lines.join("\n")}
|
|
298274
|
+
|
|
298275
|
+
User's new message:
|
|
298276
|
+
${prompt}`;
|
|
298277
|
+
} catch {
|
|
298278
|
+
return prompt;
|
|
298279
|
+
}
|
|
298280
|
+
}
|
|
298196
298281
|
throttledBroadcast(scope) {
|
|
298197
298282
|
if (this.broadcastTimer) return;
|
|
298198
298283
|
this.broadcastTimer = setTimeout(() => {
|
|
@@ -298554,8 +298639,12 @@ var DashboardServer = class {
|
|
|
298554
298639
|
res.status(400).json({ error: "prompt is required" });
|
|
298555
298640
|
return;
|
|
298556
298641
|
}
|
|
298557
|
-
const
|
|
298642
|
+
const requestedSessionId = typeof body.sessionId === "string" && body.sessionId.trim() ? body.sessionId.trim() : void 0;
|
|
298643
|
+
const sessionId = requestedSessionId ?? crypto2.randomUUID();
|
|
298558
298644
|
res.json({ sessionId, status: "ACTIVE" });
|
|
298645
|
+
const prompt = body.prompt;
|
|
298646
|
+
const runPrompt = requestedSessionId ? this.buildContinuationPrompt(sessionId, prompt) : prompt;
|
|
298647
|
+
const title = this.persistRunStart(sessionId, prompt);
|
|
298559
298648
|
void (async () => {
|
|
298560
298649
|
const cascade = new Cascade(this.config, this.workspacePath, this.store);
|
|
298561
298650
|
this.activeSessions.set(sessionId, cascade);
|
|
@@ -298572,7 +298661,8 @@ var DashboardServer = class {
|
|
|
298572
298661
|
this.socket.emitPeerMessage(e3);
|
|
298573
298662
|
});
|
|
298574
298663
|
try {
|
|
298575
|
-
const result = await cascade.run({ prompt:
|
|
298664
|
+
const result = await cascade.run({ prompt: runPrompt, identityId: body.identityId });
|
|
298665
|
+
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
298576
298666
|
this.socket.broadcast("cost:update", {
|
|
298577
298667
|
sessionId,
|
|
298578
298668
|
totalTokens: result.usage.totalTokens,
|
|
@@ -298581,6 +298671,7 @@ var DashboardServer = class {
|
|
|
298581
298671
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:complete", { sessionId, result });
|
|
298582
298672
|
this.throttledBroadcast("workspace");
|
|
298583
298673
|
} catch (err) {
|
|
298674
|
+
this.persistRunEnd(sessionId, title, prompt, void 0, "FAILED");
|
|
298584
298675
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:error", {
|
|
298585
298676
|
sessionId,
|
|
298586
298677
|
error: err instanceof Error ? err.message : String(err)
|
package/dist/index.cjs
CHANGED
|
@@ -85,7 +85,7 @@ var cron__default = /*#__PURE__*/_interopDefault(cron);
|
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
// src/constants.ts
|
|
88
|
-
var CASCADE_VERSION = "0.12.
|
|
88
|
+
var CASCADE_VERSION = "0.12.24";
|
|
89
89
|
var CASCADE_CONFIG_DIR = ".cascade";
|
|
90
90
|
var CASCADE_MD_FILE = "CASCADE.md";
|
|
91
91
|
var CASCADE_IGNORE_FILE = ".cascadeignore";
|
|
@@ -10748,7 +10748,8 @@ var DashboardSocket = class {
|
|
|
10748
10748
|
this.io.on("connection", (socket) => {
|
|
10749
10749
|
socket.on("cascade:run", (payload) => {
|
|
10750
10750
|
if (typeof payload?.prompt === "string" && payload.prompt.trim()) {
|
|
10751
|
-
|
|
10751
|
+
const sessionId = typeof payload.sessionId === "string" && payload.sessionId.trim() ? payload.sessionId.trim() : void 0;
|
|
10752
|
+
callback(payload.prompt.trim(), payload.model ?? "auto", socket.id, sessionId);
|
|
10752
10753
|
}
|
|
10753
10754
|
});
|
|
10754
10755
|
});
|
|
@@ -10826,8 +10827,10 @@ var DashboardServer = class {
|
|
|
10826
10827
|
}
|
|
10827
10828
|
this.persistConfig();
|
|
10828
10829
|
});
|
|
10829
|
-
this.socket.onCascadeRun(async (prompt, model, socketId) => {
|
|
10830
|
-
const sessionId = crypto.randomUUID();
|
|
10830
|
+
this.socket.onCascadeRun(async (prompt, model, socketId, requestedSessionId) => {
|
|
10831
|
+
const sessionId = requestedSessionId ?? crypto.randomUUID();
|
|
10832
|
+
const runPrompt = requestedSessionId ? this.buildContinuationPrompt(sessionId, prompt) : prompt;
|
|
10833
|
+
const title = this.persistRunStart(sessionId, prompt);
|
|
10831
10834
|
const cfg = model !== "auto" ? { ...this.config, models: { ...this.config.models, t1: model } } : this.config;
|
|
10832
10835
|
const cascade = new Cascade(cfg, this.workspacePath, this.store);
|
|
10833
10836
|
this.activeSessions.set(sessionId, cascade);
|
|
@@ -10844,7 +10847,8 @@ var DashboardServer = class {
|
|
|
10844
10847
|
this.socket.emitPeerMessage(e);
|
|
10845
10848
|
});
|
|
10846
10849
|
try {
|
|
10847
|
-
const result = await cascade.run({ prompt });
|
|
10850
|
+
const result = await cascade.run({ prompt: runPrompt });
|
|
10851
|
+
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
10848
10852
|
this.socket.emitToSocket(socketId, "session:complete", { sessionId, result });
|
|
10849
10853
|
this.socket.broadcast("cost:update", {
|
|
10850
10854
|
sessionId,
|
|
@@ -10853,6 +10857,7 @@ var DashboardServer = class {
|
|
|
10853
10857
|
});
|
|
10854
10858
|
this.throttledBroadcast("workspace");
|
|
10855
10859
|
} catch (err) {
|
|
10860
|
+
this.persistRunEnd(sessionId, title, prompt, void 0, "FAILED");
|
|
10856
10861
|
this.socket.emitToSocket(socketId, "session:error", {
|
|
10857
10862
|
sessionId,
|
|
10858
10863
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -10963,6 +10968,86 @@ var DashboardServer = class {
|
|
|
10963
10968
|
}
|
|
10964
10969
|
return this.globalStore;
|
|
10965
10970
|
}
|
|
10971
|
+
// ── Desktop-run session persistence ─────────
|
|
10972
|
+
// Only the CLI REPL used to persist sessions; runs started from the desktop
|
|
10973
|
+
// (socket `cascade:run` and REST /api/run) wrote nothing to the store, so
|
|
10974
|
+
// they never appeared in the session list and couldn't be resumed. These
|
|
10975
|
+
// helpers give both run paths the same persistence the CLI has.
|
|
10976
|
+
/** Record run start: session row (if new), the user message, and an ACTIVE runtime row. Returns the session title. */
|
|
10977
|
+
persistRunStart(sessionId, prompt) {
|
|
10978
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
10979
|
+
let title = prompt.replace(/\s+/g, " ").trim().slice(0, 40);
|
|
10980
|
+
try {
|
|
10981
|
+
const existing = this.store.getSession(sessionId);
|
|
10982
|
+
if (existing) {
|
|
10983
|
+
title = existing.title;
|
|
10984
|
+
} else {
|
|
10985
|
+
this.store.createSession({
|
|
10986
|
+
id: sessionId,
|
|
10987
|
+
title,
|
|
10988
|
+
createdAt: now,
|
|
10989
|
+
updatedAt: now,
|
|
10990
|
+
identityId: this.config.defaultIdentityId ?? "default",
|
|
10991
|
+
workspacePath: this.workspacePath,
|
|
10992
|
+
messages: [],
|
|
10993
|
+
metadata: { totalTokens: 0, totalCostUsd: 0, modelsUsed: [], toolsUsed: [], taskCount: 0 }
|
|
10994
|
+
});
|
|
10995
|
+
}
|
|
10996
|
+
this.store.addMessage({ id: crypto.randomUUID(), sessionId, role: "user", content: prompt, timestamp: now });
|
|
10997
|
+
} catch (err) {
|
|
10998
|
+
console.warn("[dashboard] failed to persist run start:", err);
|
|
10999
|
+
}
|
|
11000
|
+
this.persistRuntimeRow(sessionId, title, "ACTIVE", prompt);
|
|
11001
|
+
return title;
|
|
11002
|
+
}
|
|
11003
|
+
/** Record run end: the assistant reply (when there is one) and the runtime row's final status. */
|
|
11004
|
+
persistRunEnd(sessionId, title, latestPrompt, reply, status) {
|
|
11005
|
+
try {
|
|
11006
|
+
if (reply && reply.trim()) {
|
|
11007
|
+
this.store.addMessage({ id: crypto.randomUUID(), sessionId, role: "assistant", content: reply, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
11008
|
+
}
|
|
11009
|
+
} catch (err) {
|
|
11010
|
+
console.warn("[dashboard] failed to persist run end:", err);
|
|
11011
|
+
}
|
|
11012
|
+
this.persistRuntimeRow(sessionId, title, status, latestPrompt);
|
|
11013
|
+
}
|
|
11014
|
+
persistRuntimeRow(sessionId, title, status, latestPrompt) {
|
|
11015
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11016
|
+
const row = { sessionId, title, workspacePath: this.workspacePath, status, startedAt: now, updatedAt: now, latestPrompt, isGlobal: false };
|
|
11017
|
+
try {
|
|
11018
|
+
this.store.upsertRuntimeSession(row);
|
|
11019
|
+
} catch (err) {
|
|
11020
|
+
console.warn("[dashboard] runtime upsert failed:", err);
|
|
11021
|
+
}
|
|
11022
|
+
try {
|
|
11023
|
+
this.getGlobalStore().upsertRuntimeSession({ ...row, isGlobal: true });
|
|
11024
|
+
} catch {
|
|
11025
|
+
}
|
|
11026
|
+
this.throttledBroadcast("workspace");
|
|
11027
|
+
}
|
|
11028
|
+
/**
|
|
11029
|
+
* Continuing an existing session: the Cascade orchestrator is per-run and
|
|
11030
|
+
* stateless across runs, so prepend a compact transcript of the stored
|
|
11031
|
+
* conversation to the new prompt. Called BEFORE persistRunStart so the new
|
|
11032
|
+
* prompt isn't duplicated into its own context.
|
|
11033
|
+
*/
|
|
11034
|
+
buildContinuationPrompt(sessionId, prompt) {
|
|
11035
|
+
try {
|
|
11036
|
+
const history = this.store.getSessionMessages(sessionId);
|
|
11037
|
+
if (history.length === 0) return prompt;
|
|
11038
|
+
const lines = history.slice(-10).map((m) => {
|
|
11039
|
+
const text = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
11040
|
+
return `${m.role === "user" ? "User" : "Assistant"}: ${text.slice(0, 2e3)}`;
|
|
11041
|
+
});
|
|
11042
|
+
return `Conversation so far (for context):
|
|
11043
|
+
${lines.join("\n")}
|
|
11044
|
+
|
|
11045
|
+
User's new message:
|
|
11046
|
+
${prompt}`;
|
|
11047
|
+
} catch {
|
|
11048
|
+
return prompt;
|
|
11049
|
+
}
|
|
11050
|
+
}
|
|
10966
11051
|
throttledBroadcast(scope) {
|
|
10967
11052
|
if (this.broadcastTimer) return;
|
|
10968
11053
|
this.broadcastTimer = setTimeout(() => {
|
|
@@ -11324,8 +11409,12 @@ var DashboardServer = class {
|
|
|
11324
11409
|
res.status(400).json({ error: "prompt is required" });
|
|
11325
11410
|
return;
|
|
11326
11411
|
}
|
|
11327
|
-
const
|
|
11412
|
+
const requestedSessionId = typeof body.sessionId === "string" && body.sessionId.trim() ? body.sessionId.trim() : void 0;
|
|
11413
|
+
const sessionId = requestedSessionId ?? crypto.randomUUID();
|
|
11328
11414
|
res.json({ sessionId, status: "ACTIVE" });
|
|
11415
|
+
const prompt = body.prompt;
|
|
11416
|
+
const runPrompt = requestedSessionId ? this.buildContinuationPrompt(sessionId, prompt) : prompt;
|
|
11417
|
+
const title = this.persistRunStart(sessionId, prompt);
|
|
11329
11418
|
void (async () => {
|
|
11330
11419
|
const cascade = new Cascade(this.config, this.workspacePath, this.store);
|
|
11331
11420
|
this.activeSessions.set(sessionId, cascade);
|
|
@@ -11342,7 +11431,8 @@ var DashboardServer = class {
|
|
|
11342
11431
|
this.socket.emitPeerMessage(e);
|
|
11343
11432
|
});
|
|
11344
11433
|
try {
|
|
11345
|
-
const result = await cascade.run({ prompt:
|
|
11434
|
+
const result = await cascade.run({ prompt: runPrompt, identityId: body.identityId });
|
|
11435
|
+
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
11346
11436
|
this.socket.broadcast("cost:update", {
|
|
11347
11437
|
sessionId,
|
|
11348
11438
|
totalTokens: result.usage.totalTokens,
|
|
@@ -11351,6 +11441,7 @@ var DashboardServer = class {
|
|
|
11351
11441
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:complete", { sessionId, result });
|
|
11352
11442
|
this.throttledBroadcast("workspace");
|
|
11353
11443
|
} catch (err) {
|
|
11444
|
+
this.persistRunEnd(sessionId, title, prompt, void 0, "FAILED");
|
|
11354
11445
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:error", {
|
|
11355
11446
|
sessionId,
|
|
11356
11447
|
error: err instanceof Error ? err.message : String(err)
|