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.js
CHANGED
|
@@ -58,7 +58,7 @@ var __export = (target, all) => {
|
|
|
58
58
|
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;
|
|
59
59
|
var init_constants = __esm({
|
|
60
60
|
"src/constants.ts"() {
|
|
61
|
-
CASCADE_VERSION = "0.12.
|
|
61
|
+
CASCADE_VERSION = "0.12.23";
|
|
62
62
|
CASCADE_CONFIG_FILE = ".cascade/config.json";
|
|
63
63
|
CASCADE_DB_FILE = ".cascade/memory.db";
|
|
64
64
|
CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
|
|
@@ -14780,7 +14780,8 @@ var DashboardSocket = class {
|
|
|
14780
14780
|
this.io.on("connection", (socket) => {
|
|
14781
14781
|
socket.on("cascade:run", (payload) => {
|
|
14782
14782
|
if (typeof payload?.prompt === "string" && payload.prompt.trim()) {
|
|
14783
|
-
|
|
14783
|
+
const sessionId = typeof payload.sessionId === "string" && payload.sessionId.trim() ? payload.sessionId.trim() : void 0;
|
|
14784
|
+
callback(payload.prompt.trim(), payload.model ?? "auto", socket.id, sessionId);
|
|
14784
14785
|
}
|
|
14785
14786
|
});
|
|
14786
14787
|
});
|
|
@@ -14861,18 +14862,18 @@ var DashboardServer = class {
|
|
|
14861
14862
|
}
|
|
14862
14863
|
this.persistConfig();
|
|
14863
14864
|
});
|
|
14864
|
-
this.socket.onCascadeRun(async (prompt, model, socketId) => {
|
|
14865
|
-
const sessionId = randomUUID();
|
|
14865
|
+
this.socket.onCascadeRun(async (prompt, model, socketId, requestedSessionId) => {
|
|
14866
|
+
const sessionId = requestedSessionId ?? randomUUID();
|
|
14867
|
+
const runPrompt = requestedSessionId ? this.buildContinuationPrompt(sessionId, prompt) : prompt;
|
|
14868
|
+
const title = this.persistRunStart(sessionId, prompt);
|
|
14866
14869
|
const cfg = model !== "auto" ? { ...this.config, models: { ...this.config.models, t1: model } } : this.config;
|
|
14867
14870
|
const cascade = new Cascade(cfg, this.workspacePath, this.store);
|
|
14868
14871
|
this.activeSessions.set(sessionId, cascade);
|
|
14869
14872
|
cascade.on("stream:token", (e) => {
|
|
14870
14873
|
this.socket.emitToSocket(socketId, "stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
14871
|
-
this.socket.broadcast("stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
14872
14874
|
});
|
|
14873
14875
|
cascade.on("tier:status", (e) => {
|
|
14874
14876
|
this.socket.emitToSocket(socketId, "tier:status", { sessionId, ...e });
|
|
14875
|
-
this.socket.broadcast("tier:status", { sessionId, ...e });
|
|
14876
14877
|
});
|
|
14877
14878
|
cascade.on("permission:user-required", (e) => {
|
|
14878
14879
|
this.socket.emitToSocket(socketId, "permission:user-required", { sessionId, ...e });
|
|
@@ -14881,7 +14882,8 @@ var DashboardServer = class {
|
|
|
14881
14882
|
this.socket.emitPeerMessage(e);
|
|
14882
14883
|
});
|
|
14883
14884
|
try {
|
|
14884
|
-
const result = await cascade.run({ prompt });
|
|
14885
|
+
const result = await cascade.run({ prompt: runPrompt });
|
|
14886
|
+
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
14885
14887
|
this.socket.emitToSocket(socketId, "session:complete", { sessionId, result });
|
|
14886
14888
|
this.socket.broadcast("cost:update", {
|
|
14887
14889
|
sessionId,
|
|
@@ -14890,6 +14892,7 @@ var DashboardServer = class {
|
|
|
14890
14892
|
});
|
|
14891
14893
|
this.throttledBroadcast("workspace");
|
|
14892
14894
|
} catch (err) {
|
|
14895
|
+
this.persistRunEnd(sessionId, title, prompt, void 0, "FAILED");
|
|
14893
14896
|
this.socket.emitToSocket(socketId, "session:error", {
|
|
14894
14897
|
sessionId,
|
|
14895
14898
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -15000,6 +15003,86 @@ var DashboardServer = class {
|
|
|
15000
15003
|
}
|
|
15001
15004
|
return this.globalStore;
|
|
15002
15005
|
}
|
|
15006
|
+
// ── Desktop-run session persistence ─────────
|
|
15007
|
+
// Only the CLI REPL used to persist sessions; runs started from the desktop
|
|
15008
|
+
// (socket `cascade:run` and REST /api/run) wrote nothing to the store, so
|
|
15009
|
+
// they never appeared in the session list and couldn't be resumed. These
|
|
15010
|
+
// helpers give both run paths the same persistence the CLI has.
|
|
15011
|
+
/** Record run start: session row (if new), the user message, and an ACTIVE runtime row. Returns the session title. */
|
|
15012
|
+
persistRunStart(sessionId, prompt) {
|
|
15013
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
15014
|
+
let title = prompt.replace(/\s+/g, " ").trim().slice(0, 40);
|
|
15015
|
+
try {
|
|
15016
|
+
const existing = this.store.getSession(sessionId);
|
|
15017
|
+
if (existing) {
|
|
15018
|
+
title = existing.title;
|
|
15019
|
+
} else {
|
|
15020
|
+
this.store.createSession({
|
|
15021
|
+
id: sessionId,
|
|
15022
|
+
title,
|
|
15023
|
+
createdAt: now,
|
|
15024
|
+
updatedAt: now,
|
|
15025
|
+
identityId: this.config.defaultIdentityId ?? "default",
|
|
15026
|
+
workspacePath: this.workspacePath,
|
|
15027
|
+
messages: [],
|
|
15028
|
+
metadata: { totalTokens: 0, totalCostUsd: 0, modelsUsed: [], toolsUsed: [], taskCount: 0 }
|
|
15029
|
+
});
|
|
15030
|
+
}
|
|
15031
|
+
this.store.addMessage({ id: randomUUID(), sessionId, role: "user", content: prompt, timestamp: now });
|
|
15032
|
+
} catch (err) {
|
|
15033
|
+
console.warn("[dashboard] failed to persist run start:", err);
|
|
15034
|
+
}
|
|
15035
|
+
this.persistRuntimeRow(sessionId, title, "ACTIVE", prompt);
|
|
15036
|
+
return title;
|
|
15037
|
+
}
|
|
15038
|
+
/** Record run end: the assistant reply (when there is one) and the runtime row's final status. */
|
|
15039
|
+
persistRunEnd(sessionId, title, latestPrompt, reply, status) {
|
|
15040
|
+
try {
|
|
15041
|
+
if (reply && reply.trim()) {
|
|
15042
|
+
this.store.addMessage({ id: randomUUID(), sessionId, role: "assistant", content: reply, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
15043
|
+
}
|
|
15044
|
+
} catch (err) {
|
|
15045
|
+
console.warn("[dashboard] failed to persist run end:", err);
|
|
15046
|
+
}
|
|
15047
|
+
this.persistRuntimeRow(sessionId, title, status, latestPrompt);
|
|
15048
|
+
}
|
|
15049
|
+
persistRuntimeRow(sessionId, title, status, latestPrompt) {
|
|
15050
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
15051
|
+
const row = { sessionId, title, workspacePath: this.workspacePath, status, startedAt: now, updatedAt: now, latestPrompt, isGlobal: false };
|
|
15052
|
+
try {
|
|
15053
|
+
this.store.upsertRuntimeSession(row);
|
|
15054
|
+
} catch (err) {
|
|
15055
|
+
console.warn("[dashboard] runtime upsert failed:", err);
|
|
15056
|
+
}
|
|
15057
|
+
try {
|
|
15058
|
+
this.getGlobalStore().upsertRuntimeSession({ ...row, isGlobal: true });
|
|
15059
|
+
} catch {
|
|
15060
|
+
}
|
|
15061
|
+
this.throttledBroadcast("workspace");
|
|
15062
|
+
}
|
|
15063
|
+
/**
|
|
15064
|
+
* Continuing an existing session: the Cascade orchestrator is per-run and
|
|
15065
|
+
* stateless across runs, so prepend a compact transcript of the stored
|
|
15066
|
+
* conversation to the new prompt. Called BEFORE persistRunStart so the new
|
|
15067
|
+
* prompt isn't duplicated into its own context.
|
|
15068
|
+
*/
|
|
15069
|
+
buildContinuationPrompt(sessionId, prompt) {
|
|
15070
|
+
try {
|
|
15071
|
+
const history = this.store.getSessionMessages(sessionId);
|
|
15072
|
+
if (history.length === 0) return prompt;
|
|
15073
|
+
const lines = history.slice(-10).map((m) => {
|
|
15074
|
+
const text = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
15075
|
+
return `${m.role === "user" ? "User" : "Assistant"}: ${text.slice(0, 2e3)}`;
|
|
15076
|
+
});
|
|
15077
|
+
return `Conversation so far (for context):
|
|
15078
|
+
${lines.join("\n")}
|
|
15079
|
+
|
|
15080
|
+
User's new message:
|
|
15081
|
+
${prompt}`;
|
|
15082
|
+
} catch {
|
|
15083
|
+
return prompt;
|
|
15084
|
+
}
|
|
15085
|
+
}
|
|
15003
15086
|
throttledBroadcast(scope) {
|
|
15004
15087
|
if (this.broadcastTimer) return;
|
|
15005
15088
|
this.broadcastTimer = setTimeout(() => {
|
|
@@ -15361,17 +15444,19 @@ var DashboardServer = class {
|
|
|
15361
15444
|
res.status(400).json({ error: "prompt is required" });
|
|
15362
15445
|
return;
|
|
15363
15446
|
}
|
|
15364
|
-
const
|
|
15447
|
+
const requestedSessionId = typeof body.sessionId === "string" && body.sessionId.trim() ? body.sessionId.trim() : void 0;
|
|
15448
|
+
const sessionId = requestedSessionId ?? randomUUID();
|
|
15365
15449
|
res.json({ sessionId, status: "ACTIVE" });
|
|
15450
|
+
const prompt = body.prompt;
|
|
15451
|
+
const runPrompt = requestedSessionId ? this.buildContinuationPrompt(sessionId, prompt) : prompt;
|
|
15452
|
+
const title = this.persistRunStart(sessionId, prompt);
|
|
15366
15453
|
void (async () => {
|
|
15367
15454
|
const cascade = new Cascade(this.config, this.workspacePath, this.store);
|
|
15368
15455
|
this.activeSessions.set(sessionId, cascade);
|
|
15369
15456
|
cascade.on("stream:token", (e) => {
|
|
15370
|
-
this.socket.broadcast("stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
15371
15457
|
this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, tierId: e.tierId, text: e.text });
|
|
15372
15458
|
});
|
|
15373
15459
|
cascade.on("tier:status", (e) => {
|
|
15374
|
-
this.socket.broadcast("tier:status", { sessionId, ...e });
|
|
15375
15460
|
this.socket.broadcastToRoom(`session:${sessionId}`, "tier:status", { sessionId, ...e });
|
|
15376
15461
|
});
|
|
15377
15462
|
cascade.on("permission:user-required", (e) => {
|
|
@@ -15381,7 +15466,8 @@ var DashboardServer = class {
|
|
|
15381
15466
|
this.socket.emitPeerMessage(e);
|
|
15382
15467
|
});
|
|
15383
15468
|
try {
|
|
15384
|
-
const result = await cascade.run({ prompt:
|
|
15469
|
+
const result = await cascade.run({ prompt: runPrompt, identityId: body.identityId });
|
|
15470
|
+
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
15385
15471
|
this.socket.broadcast("cost:update", {
|
|
15386
15472
|
sessionId,
|
|
15387
15473
|
totalTokens: result.usage.totalTokens,
|
|
@@ -15390,6 +15476,7 @@ var DashboardServer = class {
|
|
|
15390
15476
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:complete", { sessionId, result });
|
|
15391
15477
|
this.throttledBroadcast("workspace");
|
|
15392
15478
|
} catch (err) {
|
|
15479
|
+
this.persistRunEnd(sessionId, title, prompt, void 0, "FAILED");
|
|
15393
15480
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:error", {
|
|
15394
15481
|
sessionId,
|
|
15395
15482
|
error: err instanceof Error ? err.message : String(err)
|