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/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.23";
|
|
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,18 +10781,18 @@ 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);
|
|
10788
10791
|
cascade.on("stream:token", (e) => {
|
|
10789
10792
|
this.socket.emitToSocket(socketId, "stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
10790
|
-
this.socket.broadcast("stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
10791
10793
|
});
|
|
10792
10794
|
cascade.on("tier:status", (e) => {
|
|
10793
10795
|
this.socket.emitToSocket(socketId, "tier:status", { sessionId, ...e });
|
|
10794
|
-
this.socket.broadcast("tier:status", { sessionId, ...e });
|
|
10795
10796
|
});
|
|
10796
10797
|
cascade.on("permission:user-required", (e) => {
|
|
10797
10798
|
this.socket.emitToSocket(socketId, "permission:user-required", { sessionId, ...e });
|
|
@@ -10800,7 +10801,8 @@ var DashboardServer = class {
|
|
|
10800
10801
|
this.socket.emitPeerMessage(e);
|
|
10801
10802
|
});
|
|
10802
10803
|
try {
|
|
10803
|
-
const result = await cascade.run({ prompt });
|
|
10804
|
+
const result = await cascade.run({ prompt: runPrompt });
|
|
10805
|
+
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
10804
10806
|
this.socket.emitToSocket(socketId, "session:complete", { sessionId, result });
|
|
10805
10807
|
this.socket.broadcast("cost:update", {
|
|
10806
10808
|
sessionId,
|
|
@@ -10809,6 +10811,7 @@ var DashboardServer = class {
|
|
|
10809
10811
|
});
|
|
10810
10812
|
this.throttledBroadcast("workspace");
|
|
10811
10813
|
} catch (err) {
|
|
10814
|
+
this.persistRunEnd(sessionId, title, prompt, void 0, "FAILED");
|
|
10812
10815
|
this.socket.emitToSocket(socketId, "session:error", {
|
|
10813
10816
|
sessionId,
|
|
10814
10817
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -10919,6 +10922,86 @@ var DashboardServer = class {
|
|
|
10919
10922
|
}
|
|
10920
10923
|
return this.globalStore;
|
|
10921
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
|
+
}
|
|
10922
11005
|
throttledBroadcast(scope) {
|
|
10923
11006
|
if (this.broadcastTimer) return;
|
|
10924
11007
|
this.broadcastTimer = setTimeout(() => {
|
|
@@ -11280,17 +11363,19 @@ var DashboardServer = class {
|
|
|
11280
11363
|
res.status(400).json({ error: "prompt is required" });
|
|
11281
11364
|
return;
|
|
11282
11365
|
}
|
|
11283
|
-
const
|
|
11366
|
+
const requestedSessionId = typeof body.sessionId === "string" && body.sessionId.trim() ? body.sessionId.trim() : void 0;
|
|
11367
|
+
const sessionId = requestedSessionId ?? randomUUID();
|
|
11284
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);
|
|
11285
11372
|
void (async () => {
|
|
11286
11373
|
const cascade = new Cascade(this.config, this.workspacePath, this.store);
|
|
11287
11374
|
this.activeSessions.set(sessionId, cascade);
|
|
11288
11375
|
cascade.on("stream:token", (e) => {
|
|
11289
|
-
this.socket.broadcast("stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
11290
11376
|
this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
11291
11377
|
});
|
|
11292
11378
|
cascade.on("tier:status", (e) => {
|
|
11293
|
-
this.socket.broadcast("tier:status", { sessionId, ...e });
|
|
11294
11379
|
this.socket.broadcastToRoom(`session:${sessionId}`, "tier:status", { sessionId, ...e });
|
|
11295
11380
|
});
|
|
11296
11381
|
cascade.on("permission:user-required", (e) => {
|
|
@@ -11300,7 +11385,8 @@ var DashboardServer = class {
|
|
|
11300
11385
|
this.socket.emitPeerMessage(e);
|
|
11301
11386
|
});
|
|
11302
11387
|
try {
|
|
11303
|
-
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");
|
|
11304
11390
|
this.socket.broadcast("cost:update", {
|
|
11305
11391
|
sessionId,
|
|
11306
11392
|
totalTokens: result.usage.totalTokens,
|
|
@@ -11309,6 +11395,7 @@ var DashboardServer = class {
|
|
|
11309
11395
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:complete", { sessionId, result });
|
|
11310
11396
|
this.throttledBroadcast("workspace");
|
|
11311
11397
|
} catch (err) {
|
|
11398
|
+
this.persistRunEnd(sessionId, title, prompt, void 0, "FAILED");
|
|
11312
11399
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:error", {
|
|
11313
11400
|
sessionId,
|
|
11314
11401
|
error: err instanceof Error ? err.message : String(err)
|