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/index.d.cts
CHANGED
|
@@ -2036,7 +2036,7 @@ declare class DashboardSocket {
|
|
|
2036
2036
|
}) => void): void;
|
|
2037
2037
|
emitToSocket(socketId: string, event: string, data: unknown): void;
|
|
2038
2038
|
onConfigGet(callback: (socketId: string) => void): void;
|
|
2039
|
-
onCascadeRun(callback: (prompt: string, model: string, socketId: string) => void): void;
|
|
2039
|
+
onCascadeRun(callback: (prompt: string, model: string, socketId: string, sessionId?: string) => void): void;
|
|
2040
2040
|
close(): void;
|
|
2041
2041
|
}
|
|
2042
2042
|
|
|
@@ -2078,6 +2078,18 @@ declare class DashboardServer {
|
|
|
2078
2078
|
*/
|
|
2079
2079
|
private resolvePasswordHash;
|
|
2080
2080
|
private getGlobalStore;
|
|
2081
|
+
/** Record run start: session row (if new), the user message, and an ACTIVE runtime row. Returns the session title. */
|
|
2082
|
+
private persistRunStart;
|
|
2083
|
+
/** Record run end: the assistant reply (when there is one) and the runtime row's final status. */
|
|
2084
|
+
private persistRunEnd;
|
|
2085
|
+
private persistRuntimeRow;
|
|
2086
|
+
/**
|
|
2087
|
+
* Continuing an existing session: the Cascade orchestrator is per-run and
|
|
2088
|
+
* stateless across runs, so prepend a compact transcript of the stored
|
|
2089
|
+
* conversation to the new prompt. Called BEFORE persistRunStart so the new
|
|
2090
|
+
* prompt isn't duplicated into its own context.
|
|
2091
|
+
*/
|
|
2092
|
+
private buildContinuationPrompt;
|
|
2081
2093
|
private throttledBroadcast;
|
|
2082
2094
|
private broadcastRuntime;
|
|
2083
2095
|
private broadcastSessionDetails;
|
package/dist/index.d.ts
CHANGED
|
@@ -2036,7 +2036,7 @@ declare class DashboardSocket {
|
|
|
2036
2036
|
}) => void): void;
|
|
2037
2037
|
emitToSocket(socketId: string, event: string, data: unknown): void;
|
|
2038
2038
|
onConfigGet(callback: (socketId: string) => void): void;
|
|
2039
|
-
onCascadeRun(callback: (prompt: string, model: string, socketId: string) => void): void;
|
|
2039
|
+
onCascadeRun(callback: (prompt: string, model: string, socketId: string, sessionId?: string) => void): void;
|
|
2040
2040
|
close(): void;
|
|
2041
2041
|
}
|
|
2042
2042
|
|
|
@@ -2078,6 +2078,18 @@ declare class DashboardServer {
|
|
|
2078
2078
|
*/
|
|
2079
2079
|
private resolvePasswordHash;
|
|
2080
2080
|
private getGlobalStore;
|
|
2081
|
+
/** Record run start: session row (if new), the user message, and an ACTIVE runtime row. Returns the session title. */
|
|
2082
|
+
private persistRunStart;
|
|
2083
|
+
/** Record run end: the assistant reply (when there is one) and the runtime row's final status. */
|
|
2084
|
+
private persistRunEnd;
|
|
2085
|
+
private persistRuntimeRow;
|
|
2086
|
+
/**
|
|
2087
|
+
* Continuing an existing session: the Cascade orchestrator is per-run and
|
|
2088
|
+
* stateless across runs, so prepend a compact transcript of the stored
|
|
2089
|
+
* conversation to the new prompt. Called BEFORE persistRunStart so the new
|
|
2090
|
+
* prompt isn't duplicated into its own context.
|
|
2091
|
+
*/
|
|
2092
|
+
private buildContinuationPrompt;
|
|
2081
2093
|
private throttledBroadcast;
|
|
2082
2094
|
private broadcastRuntime;
|
|
2083
2095
|
private broadcastSessionDetails;
|
package/dist/index.js
CHANGED
|
@@ -39,7 +39,7 @@ import cron from 'node-cron';
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
// src/constants.ts
|
|
42
|
-
var CASCADE_VERSION = "0.12.
|
|
42
|
+
var CASCADE_VERSION = "0.12.24";
|
|
43
43
|
var CASCADE_CONFIG_DIR = ".cascade";
|
|
44
44
|
var CASCADE_MD_FILE = "CASCADE.md";
|
|
45
45
|
var CASCADE_IGNORE_FILE = ".cascadeignore";
|
|
@@ -10702,7 +10702,8 @@ var DashboardSocket = class {
|
|
|
10702
10702
|
this.io.on("connection", (socket) => {
|
|
10703
10703
|
socket.on("cascade:run", (payload) => {
|
|
10704
10704
|
if (typeof payload?.prompt === "string" && payload.prompt.trim()) {
|
|
10705
|
-
|
|
10705
|
+
const sessionId = typeof payload.sessionId === "string" && payload.sessionId.trim() ? payload.sessionId.trim() : void 0;
|
|
10706
|
+
callback(payload.prompt.trim(), payload.model ?? "auto", socket.id, sessionId);
|
|
10706
10707
|
}
|
|
10707
10708
|
});
|
|
10708
10709
|
});
|
|
@@ -10780,8 +10781,10 @@ var DashboardServer = class {
|
|
|
10780
10781
|
}
|
|
10781
10782
|
this.persistConfig();
|
|
10782
10783
|
});
|
|
10783
|
-
this.socket.onCascadeRun(async (prompt, model, socketId) => {
|
|
10784
|
-
const sessionId = randomUUID();
|
|
10784
|
+
this.socket.onCascadeRun(async (prompt, model, socketId, requestedSessionId) => {
|
|
10785
|
+
const sessionId = requestedSessionId ?? randomUUID();
|
|
10786
|
+
const runPrompt = requestedSessionId ? this.buildContinuationPrompt(sessionId, prompt) : prompt;
|
|
10787
|
+
const title = this.persistRunStart(sessionId, prompt);
|
|
10785
10788
|
const cfg = model !== "auto" ? { ...this.config, models: { ...this.config.models, t1: model } } : this.config;
|
|
10786
10789
|
const cascade = new Cascade(cfg, this.workspacePath, this.store);
|
|
10787
10790
|
this.activeSessions.set(sessionId, cascade);
|
|
@@ -10798,7 +10801,8 @@ var DashboardServer = class {
|
|
|
10798
10801
|
this.socket.emitPeerMessage(e);
|
|
10799
10802
|
});
|
|
10800
10803
|
try {
|
|
10801
|
-
const result = await cascade.run({ prompt });
|
|
10804
|
+
const result = await cascade.run({ prompt: runPrompt });
|
|
10805
|
+
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
10802
10806
|
this.socket.emitToSocket(socketId, "session:complete", { sessionId, result });
|
|
10803
10807
|
this.socket.broadcast("cost:update", {
|
|
10804
10808
|
sessionId,
|
|
@@ -10807,6 +10811,7 @@ var DashboardServer = class {
|
|
|
10807
10811
|
});
|
|
10808
10812
|
this.throttledBroadcast("workspace");
|
|
10809
10813
|
} catch (err) {
|
|
10814
|
+
this.persistRunEnd(sessionId, title, prompt, void 0, "FAILED");
|
|
10810
10815
|
this.socket.emitToSocket(socketId, "session:error", {
|
|
10811
10816
|
sessionId,
|
|
10812
10817
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -10917,6 +10922,86 @@ var DashboardServer = class {
|
|
|
10917
10922
|
}
|
|
10918
10923
|
return this.globalStore;
|
|
10919
10924
|
}
|
|
10925
|
+
// ── Desktop-run session persistence ─────────
|
|
10926
|
+
// Only the CLI REPL used to persist sessions; runs started from the desktop
|
|
10927
|
+
// (socket `cascade:run` and REST /api/run) wrote nothing to the store, so
|
|
10928
|
+
// they never appeared in the session list and couldn't be resumed. These
|
|
10929
|
+
// helpers give both run paths the same persistence the CLI has.
|
|
10930
|
+
/** Record run start: session row (if new), the user message, and an ACTIVE runtime row. Returns the session title. */
|
|
10931
|
+
persistRunStart(sessionId, prompt) {
|
|
10932
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
10933
|
+
let title = prompt.replace(/\s+/g, " ").trim().slice(0, 40);
|
|
10934
|
+
try {
|
|
10935
|
+
const existing = this.store.getSession(sessionId);
|
|
10936
|
+
if (existing) {
|
|
10937
|
+
title = existing.title;
|
|
10938
|
+
} else {
|
|
10939
|
+
this.store.createSession({
|
|
10940
|
+
id: sessionId,
|
|
10941
|
+
title,
|
|
10942
|
+
createdAt: now,
|
|
10943
|
+
updatedAt: now,
|
|
10944
|
+
identityId: this.config.defaultIdentityId ?? "default",
|
|
10945
|
+
workspacePath: this.workspacePath,
|
|
10946
|
+
messages: [],
|
|
10947
|
+
metadata: { totalTokens: 0, totalCostUsd: 0, modelsUsed: [], toolsUsed: [], taskCount: 0 }
|
|
10948
|
+
});
|
|
10949
|
+
}
|
|
10950
|
+
this.store.addMessage({ id: randomUUID(), sessionId, role: "user", content: prompt, timestamp: now });
|
|
10951
|
+
} catch (err) {
|
|
10952
|
+
console.warn("[dashboard] failed to persist run start:", err);
|
|
10953
|
+
}
|
|
10954
|
+
this.persistRuntimeRow(sessionId, title, "ACTIVE", prompt);
|
|
10955
|
+
return title;
|
|
10956
|
+
}
|
|
10957
|
+
/** Record run end: the assistant reply (when there is one) and the runtime row's final status. */
|
|
10958
|
+
persistRunEnd(sessionId, title, latestPrompt, reply, status) {
|
|
10959
|
+
try {
|
|
10960
|
+
if (reply && reply.trim()) {
|
|
10961
|
+
this.store.addMessage({ id: randomUUID(), sessionId, role: "assistant", content: reply, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
10962
|
+
}
|
|
10963
|
+
} catch (err) {
|
|
10964
|
+
console.warn("[dashboard] failed to persist run end:", err);
|
|
10965
|
+
}
|
|
10966
|
+
this.persistRuntimeRow(sessionId, title, status, latestPrompt);
|
|
10967
|
+
}
|
|
10968
|
+
persistRuntimeRow(sessionId, title, status, latestPrompt) {
|
|
10969
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
10970
|
+
const row = { sessionId, title, workspacePath: this.workspacePath, status, startedAt: now, updatedAt: now, latestPrompt, isGlobal: false };
|
|
10971
|
+
try {
|
|
10972
|
+
this.store.upsertRuntimeSession(row);
|
|
10973
|
+
} catch (err) {
|
|
10974
|
+
console.warn("[dashboard] runtime upsert failed:", err);
|
|
10975
|
+
}
|
|
10976
|
+
try {
|
|
10977
|
+
this.getGlobalStore().upsertRuntimeSession({ ...row, isGlobal: true });
|
|
10978
|
+
} catch {
|
|
10979
|
+
}
|
|
10980
|
+
this.throttledBroadcast("workspace");
|
|
10981
|
+
}
|
|
10982
|
+
/**
|
|
10983
|
+
* Continuing an existing session: the Cascade orchestrator is per-run and
|
|
10984
|
+
* stateless across runs, so prepend a compact transcript of the stored
|
|
10985
|
+
* conversation to the new prompt. Called BEFORE persistRunStart so the new
|
|
10986
|
+
* prompt isn't duplicated into its own context.
|
|
10987
|
+
*/
|
|
10988
|
+
buildContinuationPrompt(sessionId, prompt) {
|
|
10989
|
+
try {
|
|
10990
|
+
const history = this.store.getSessionMessages(sessionId);
|
|
10991
|
+
if (history.length === 0) return prompt;
|
|
10992
|
+
const lines = history.slice(-10).map((m) => {
|
|
10993
|
+
const text = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
10994
|
+
return `${m.role === "user" ? "User" : "Assistant"}: ${text.slice(0, 2e3)}`;
|
|
10995
|
+
});
|
|
10996
|
+
return `Conversation so far (for context):
|
|
10997
|
+
${lines.join("\n")}
|
|
10998
|
+
|
|
10999
|
+
User's new message:
|
|
11000
|
+
${prompt}`;
|
|
11001
|
+
} catch {
|
|
11002
|
+
return prompt;
|
|
11003
|
+
}
|
|
11004
|
+
}
|
|
10920
11005
|
throttledBroadcast(scope) {
|
|
10921
11006
|
if (this.broadcastTimer) return;
|
|
10922
11007
|
this.broadcastTimer = setTimeout(() => {
|
|
@@ -11278,8 +11363,12 @@ var DashboardServer = class {
|
|
|
11278
11363
|
res.status(400).json({ error: "prompt is required" });
|
|
11279
11364
|
return;
|
|
11280
11365
|
}
|
|
11281
|
-
const
|
|
11366
|
+
const requestedSessionId = typeof body.sessionId === "string" && body.sessionId.trim() ? body.sessionId.trim() : void 0;
|
|
11367
|
+
const sessionId = requestedSessionId ?? randomUUID();
|
|
11282
11368
|
res.json({ sessionId, status: "ACTIVE" });
|
|
11369
|
+
const prompt = body.prompt;
|
|
11370
|
+
const runPrompt = requestedSessionId ? this.buildContinuationPrompt(sessionId, prompt) : prompt;
|
|
11371
|
+
const title = this.persistRunStart(sessionId, prompt);
|
|
11283
11372
|
void (async () => {
|
|
11284
11373
|
const cascade = new Cascade(this.config, this.workspacePath, this.store);
|
|
11285
11374
|
this.activeSessions.set(sessionId, cascade);
|
|
@@ -11296,7 +11385,8 @@ var DashboardServer = class {
|
|
|
11296
11385
|
this.socket.emitPeerMessage(e);
|
|
11297
11386
|
});
|
|
11298
11387
|
try {
|
|
11299
|
-
const result = await cascade.run({ prompt:
|
|
11388
|
+
const result = await cascade.run({ prompt: runPrompt, identityId: body.identityId });
|
|
11389
|
+
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
11300
11390
|
this.socket.broadcast("cost:update", {
|
|
11301
11391
|
sessionId,
|
|
11302
11392
|
totalTokens: result.usage.totalTokens,
|
|
@@ -11305,6 +11395,7 @@ var DashboardServer = class {
|
|
|
11305
11395
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:complete", { sessionId, result });
|
|
11306
11396
|
this.throttledBroadcast("workspace");
|
|
11307
11397
|
} catch (err) {
|
|
11398
|
+
this.persistRunEnd(sessionId, title, prompt, void 0, "FAILED");
|
|
11308
11399
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:error", {
|
|
11309
11400
|
sessionId,
|
|
11310
11401
|
error: err instanceof Error ? err.message : String(err)
|