cascade-ai 0.13.1 → 0.13.2
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/README.md +6 -0
- package/dist/cli.cjs +117 -36
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +117 -36
- package/dist/cli.js.map +1 -1
- package/dist/desktop-core.cjs +117 -36
- package/dist/index.cjs +117 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +59 -2
- package/dist/index.d.ts +59 -2
- package/dist/index.js +117 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/desktop-core.cjs
CHANGED
|
@@ -222595,7 +222595,7 @@ Anthropic.Models = Models2;
|
|
|
222595
222595
|
Anthropic.Beta = Beta;
|
|
222596
222596
|
|
|
222597
222597
|
// src/constants.ts
|
|
222598
|
-
var CASCADE_VERSION = "0.13.
|
|
222598
|
+
var CASCADE_VERSION = "0.13.2";
|
|
222599
222599
|
var CASCADE_CONFIG_DIR = ".cascade";
|
|
222600
222600
|
var CASCADE_MD_FILE = "CASCADE.md";
|
|
222601
222601
|
var CASCADE_IGNORE_FILE = ".cascadeignore";
|
|
@@ -251433,6 +251433,13 @@ var BaseTier = class extends EventEmitter__default.default {
|
|
|
251433
251433
|
hierarchyContext = "";
|
|
251434
251434
|
/** Propagated AbortSignal — set by the tier's `execute()` before work begins. */
|
|
251435
251435
|
signal;
|
|
251436
|
+
/**
|
|
251437
|
+
* True for the run's ROOT tier (T3 for Simple, T2 for Moderate, T1 for
|
|
251438
|
+
* Complex). Its own synthesis stream is the user-facing answer and is
|
|
251439
|
+
* tagged `primary` so the desktop renders it live — background workers,
|
|
251440
|
+
* which would interleave, are not tagged.
|
|
251441
|
+
*/
|
|
251442
|
+
isPresenter = false;
|
|
251436
251443
|
constructor(role, id, parentId) {
|
|
251437
251444
|
super();
|
|
251438
251445
|
this.role = role;
|
|
@@ -251440,6 +251447,10 @@ var BaseTier = class extends EventEmitter__default.default {
|
|
|
251440
251447
|
this.parentId = parentId;
|
|
251441
251448
|
this.label = this.id;
|
|
251442
251449
|
}
|
|
251450
|
+
/** Mark this tier as the run's presenter (root tier). */
|
|
251451
|
+
setPresenter(on = true) {
|
|
251452
|
+
this.isPresenter = on;
|
|
251453
|
+
}
|
|
251443
251454
|
getStatus() {
|
|
251444
251455
|
return this.status;
|
|
251445
251456
|
}
|
|
@@ -252174,7 +252185,7 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : "") + textToolSuffix,
|
|
|
252174
252185
|
"T3",
|
|
252175
252186
|
options,
|
|
252176
252187
|
(chunk) => {
|
|
252177
|
-
this.emit("stream:token", { tierId: this.id, text: chunk.text });
|
|
252188
|
+
this.emit("stream:token", { tierId: this.id, text: chunk.text, primary: this.isPresenter });
|
|
252178
252189
|
}
|
|
252179
252190
|
);
|
|
252180
252191
|
let effectiveToolCalls = result.toolCalls ?? [];
|
|
@@ -253635,6 +253646,7 @@ ${peerOutputs}` : "";
|
|
|
253635
253646
|
chunkEnd++;
|
|
253636
253647
|
}
|
|
253637
253648
|
i4 = chunkEnd;
|
|
253649
|
+
const isLastChunk = chunkEnd >= completed.length;
|
|
253638
253650
|
const prompt = `Summarize these T3 worker outputs for section "${assignment.sectionTitle}" in 2-3 sentences.
|
|
253639
253651
|
${currentSummary ? `
|
|
253640
253652
|
PREVIOUS SUMMARY SO FAR:
|
|
@@ -253644,6 +253656,7 @@ NEW OUTPUTS TO INTEGRATE:
|
|
|
253644
253656
|
` : "\nOUTPUTS:\n"}${chunkText}${peerContext}`;
|
|
253645
253657
|
const messages = [{ role: "user", content: prompt }];
|
|
253646
253658
|
try {
|
|
253659
|
+
const streamFinal = isLastChunk && this.isPresenter ? (chunk) => this.emit("stream:token", { tierId: this.id, text: chunk.text, primary: true }) : void 0;
|
|
253647
253660
|
const result = await this.router.generate("T2", {
|
|
253648
253661
|
messages,
|
|
253649
253662
|
systemPrompt: this.systemPromptOverride + "You are a T2 Manager. Summarize the work of your T3 workers succinctly." + (this.hierarchyContext ? `
|
|
@@ -253651,7 +253664,7 @@ NEW OUTPUTS TO INTEGRATE:
|
|
|
253651
253664
|
HIERARCHY CONTEXT: ${this.hierarchyContext}` : ""),
|
|
253652
253665
|
maxTokens: 500,
|
|
253653
253666
|
...this.sectionModel ? { model: this.sectionModel } : {}
|
|
253654
|
-
});
|
|
253667
|
+
}, streamFinal);
|
|
253655
253668
|
currentSummary = result.content;
|
|
253656
253669
|
} catch (err) {
|
|
253657
253670
|
this.log(`aggregateResults: LLM summarization failed at chunk \u2014 returning raw T3 outputs. Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -253703,14 +253716,11 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : ""),
|
|
|
253703
253716
|
...this.sectionModel ? { model: this.sectionModel } : {}
|
|
253704
253717
|
});
|
|
253705
253718
|
const answer = result.content.trim().toUpperCase();
|
|
253706
|
-
|
|
253707
|
-
|
|
253708
|
-
}
|
|
253709
|
-
if (answer.includes("NO")) {
|
|
253710
|
-
return { requestId: req.id, approved: false, always: true, decidedBy: "T2", reasoning: "T2 LLM evaluated: inconsistent with section goal" };
|
|
253711
|
-
}
|
|
253719
|
+
const verdict = answer.includes("YES") ? "approve" : answer.includes("NO") ? "deny" : "unsure";
|
|
253720
|
+
(req.trail ??= []).push({ tier: "T2", verdict, reason: `T2: ${verdict === "approve" ? "consistent with section goal" : verdict === "deny" ? "inconsistent with section goal" : "unsure"}` });
|
|
253712
253721
|
return null;
|
|
253713
253722
|
} catch {
|
|
253723
|
+
(req.trail ??= []).push({ tier: "T2", verdict: "unsure", reason: "T2 evaluation failed" });
|
|
253714
253724
|
return null;
|
|
253715
253725
|
}
|
|
253716
253726
|
}
|
|
@@ -254389,7 +254399,7 @@ Instructions:
|
|
|
254389
254399
|
systemPrompt: this.systemPromptOverride + "You are a final output compiler. Summarize and format the task results clearly.",
|
|
254390
254400
|
maxTokens: 8e3
|
|
254391
254401
|
}, (chunk) => {
|
|
254392
|
-
this.emit("stream:token", { tierId: this.id, text: chunk.text });
|
|
254402
|
+
this.emit("stream:token", { tierId: this.id, text: chunk.text, primary: this.isPresenter });
|
|
254393
254403
|
});
|
|
254394
254404
|
return result.content;
|
|
254395
254405
|
}
|
|
@@ -254418,14 +254428,11 @@ Reply with exactly one word: YES, NO, or UNSURE.
|
|
|
254418
254428
|
temperature: 0
|
|
254419
254429
|
});
|
|
254420
254430
|
const answer = result.content.trim().toUpperCase();
|
|
254421
|
-
|
|
254422
|
-
|
|
254423
|
-
}
|
|
254424
|
-
if (answer.includes("NO")) {
|
|
254425
|
-
return { requestId: req.id, approved: false, always: true, decidedBy: "T1", reasoning: "T1 evaluated: not consistent with overall task goal" };
|
|
254426
|
-
}
|
|
254431
|
+
const verdict = answer.includes("YES") ? "approve" : answer.includes("NO") ? "deny" : "unsure";
|
|
254432
|
+
(req.trail ??= []).push({ tier: "T1", verdict, reason: `T1: ${verdict === "approve" ? "consistent with overall task goal" : verdict === "deny" ? "not consistent with overall task goal" : "unsure"}` });
|
|
254427
254433
|
return null;
|
|
254428
254434
|
} catch {
|
|
254435
|
+
(req.trail ??= []).push({ tier: "T1", verdict: "unsure", reason: "T1 evaluation failed" });
|
|
254429
254436
|
return null;
|
|
254430
254437
|
}
|
|
254431
254438
|
}
|
|
@@ -294706,6 +294713,8 @@ var CascadeConfigSchema = external_exports.object({
|
|
|
294706
294713
|
privacy: external_exports.object({
|
|
294707
294714
|
paths: external_exports.array(external_exports.object({ pattern: external_exports.string().min(1), policy: external_exports.enum(["local-only"]) })).default([])
|
|
294708
294715
|
}).optional(),
|
|
294716
|
+
/** Routing controls — forceTier pins the root tier, bypassing the classifier. */
|
|
294717
|
+
routing: external_exports.object({ forceTier: external_exports.enum(["auto", "T1", "T2", "T3"]).default("auto") }).optional(),
|
|
294709
294718
|
/**
|
|
294710
294719
|
* T3→T2 reinforcement: when enabled, a worker that discovers its subtask should
|
|
294711
294720
|
* fan out can call the `request_workers` tool to have its T2 manager spawn
|
|
@@ -295983,6 +295992,21 @@ ${last3.partialOutput}` : "");
|
|
|
295983
295992
|
const producesArtifact = /\b(?:create|build|implement|generate|write|refactor|rewrite|add|fix|deploy|install|migrate|scaffold|set up|save (?:a|the)|report|\.(?:pdf|md|txt|json|csv|py|js|ts|tsx|jsx|html|docx?))\b/i.test(p3);
|
|
295984
295993
|
return inquiry && !producesArtifact;
|
|
295985
295994
|
}
|
|
295995
|
+
/**
|
|
295996
|
+
* Strong, explicit signals that a task needs the full hierarchy (planning +
|
|
295997
|
+
* multiple sections/workers). Deliberately conservative: requires a
|
|
295998
|
+
* build/implementation verb AND either an app/system-scale noun or an
|
|
295999
|
+
* explicit multi-part structure, so ordinary single-file asks (handled as
|
|
296000
|
+
* Simple/Moderate) don't get over-escalated.
|
|
296001
|
+
*/
|
|
296002
|
+
looksClearlyComplex(prompt) {
|
|
296003
|
+
const p3 = prompt.trim();
|
|
296004
|
+
if (p3.length < 24) return false;
|
|
296005
|
+
const buildVerb = /\b(?:build|implement|create|develop|design|scaffold|refactor|migrate|architect|set up|integrate)\b/i.test(p3);
|
|
296006
|
+
const scaleNoun = /\b(?:app(?:lication)?|system|platform|service|api|backend|frontend|full[- ]?stack|website|dashboard|pipeline|microservices?|database schema|authentication|end[- ]to[- ]end|codebase|project|multiple files|several (?:files|modules|components)|test suite)\b/i.test(p3);
|
|
296007
|
+
const multiPart = /(?:\b(?:and|then|also|plus|as well as)\b.*\b(?:and|then|also)\b)|(?:^|\n)\s*(?:[-*]|\d+[.)])\s+/i.test(p3);
|
|
296008
|
+
return buildVerb && (scaleNoun || multiPart);
|
|
296009
|
+
}
|
|
295986
296010
|
// Cache glob scan results per workspace path to avoid repeated I/O.
|
|
295987
296011
|
static globCache = /* @__PURE__ */ new Map();
|
|
295988
296012
|
async countWorkspaceFiles(workspacePath) {
|
|
@@ -296066,10 +296090,16 @@ ${prompt}` : prompt;
|
|
|
296066
296090
|
let verdict;
|
|
296067
296091
|
if (match) {
|
|
296068
296092
|
verdict = match[1] === "simple" ? "Simple" : match[1] === "moderate" ? "Moderate" : "Complex";
|
|
296069
|
-
|
|
296093
|
+
if (verdict !== "Complex" && this.looksClearlyComplex(prompt)) {
|
|
296094
|
+
this.recordDecision("complexity", `Complex \u2014 heuristic floor over classifier "${verdict}": explicit multi-step build/implementation signals (T1 engaged)`);
|
|
296095
|
+
verdict = "Complex";
|
|
296096
|
+
} else {
|
|
296097
|
+
this.recordDecision("complexity", `${verdict} \u2014 classifier: ${reason || "no reason given"}`);
|
|
296098
|
+
}
|
|
296070
296099
|
} else {
|
|
296071
|
-
|
|
296072
|
-
|
|
296100
|
+
const words = prompt.trim().split(/\s+/).length;
|
|
296101
|
+
verdict = words <= 12 ? "Simple" : words >= 40 || this.looksClearlyComplex(prompt) ? "Complex" : "Moderate";
|
|
296102
|
+
this.recordDecision("complexity", `${verdict} \u2014 classifier output unparseable; defaulted by length/signals`);
|
|
296073
296103
|
}
|
|
296074
296104
|
return verdict;
|
|
296075
296105
|
} catch {
|
|
@@ -296121,7 +296151,15 @@ ${prompt}` : prompt;
|
|
|
296121
296151
|
}
|
|
296122
296152
|
escalator.resolveUserDecision(req.id, approved, always);
|
|
296123
296153
|
});
|
|
296124
|
-
const
|
|
296154
|
+
const forceTier = this.config.routing?.forceTier;
|
|
296155
|
+
const forced = forceTier === "T1" ? "Complex" : forceTier === "T2" ? "Moderate" : forceTier === "T3" ? "Simple" : void 0;
|
|
296156
|
+
let complexity;
|
|
296157
|
+
if (forced) {
|
|
296158
|
+
complexity = forced;
|
|
296159
|
+
this.recordDecision("complexity", `${forced} \u2014 manually forced via routing.forceTier=${forceTier}`);
|
|
296160
|
+
} else {
|
|
296161
|
+
complexity = await this.determineComplexity(options.prompt, options.workspacePath || process.cwd(), options.conversationHistory);
|
|
296162
|
+
}
|
|
296125
296163
|
this.telemetry.capture("cascade:session_start", {
|
|
296126
296164
|
complexity,
|
|
296127
296165
|
providerCount: this.config.providers.length,
|
|
@@ -296201,6 +296239,7 @@ ${prompt}` : prompt;
|
|
|
296201
296239
|
try {
|
|
296202
296240
|
if (complexity === "Simple") {
|
|
296203
296241
|
const t32 = new T3Worker(this.router, this.toolRegistry, "root");
|
|
296242
|
+
t32.setPresenter(true);
|
|
296204
296243
|
t32.setHierarchyContext("You are the DIRECT worker for this task. There is no T1 Administrator or T2 Manager involved in this run.");
|
|
296205
296244
|
if (identityPrompt) {
|
|
296206
296245
|
t32.setSystemPromptOverride(identityPrompt);
|
|
@@ -296225,6 +296264,7 @@ ${prompt}` : prompt;
|
|
|
296225
296264
|
this.emit("tier:status", { tierId: "t3-root", status: "COMPLETED", role: "T3" });
|
|
296226
296265
|
} else if (complexity === "Moderate") {
|
|
296227
296266
|
const t22 = new T2Manager(this.router, this.toolRegistry, "root");
|
|
296267
|
+
t22.setPresenter(true);
|
|
296228
296268
|
t22.setHierarchyContext("You are the ROOT Manager for this task. There is no T1 Administrator involved in this run. You are responsible for decomposing the task and managing T3 workers directly.");
|
|
296229
296269
|
if (identityPrompt) {
|
|
296230
296270
|
t22.setSystemPromptOverride(identityPrompt);
|
|
@@ -296274,6 +296314,7 @@ ${prompt}` : prompt;
|
|
|
296274
296314
|
}
|
|
296275
296315
|
} else {
|
|
296276
296316
|
const t1 = new T1Administrator(this.router, this.toolRegistry, this.config);
|
|
296317
|
+
t1.setPresenter(true);
|
|
296277
296318
|
t1.setHierarchyContext("You are the top-level Administrator. You are responsible for the overall plan and supervising multiple T2 Managers.");
|
|
296278
296319
|
if (identityPrompt) {
|
|
296279
296320
|
t1.setSystemPromptOverride(identityPrompt);
|
|
@@ -298515,7 +298556,8 @@ var DashboardSocket = class {
|
|
|
298515
298556
|
socket.on("cascade:run", (payload) => {
|
|
298516
298557
|
if (typeof payload?.prompt === "string" && payload.prompt.trim()) {
|
|
298517
298558
|
const sessionId = typeof payload.sessionId === "string" && payload.sessionId.trim() ? payload.sessionId.trim() : void 0;
|
|
298518
|
-
|
|
298559
|
+
const forceTier = ["T1", "T2", "T3"].includes(payload.forceTier) ? payload.forceTier : void 0;
|
|
298560
|
+
callback(payload.prompt.trim(), payload.model ?? "auto", socket.id, sessionId, forceTier);
|
|
298519
298561
|
}
|
|
298520
298562
|
});
|
|
298521
298563
|
});
|
|
@@ -298542,6 +298584,13 @@ var DashboardServer = class {
|
|
|
298542
298584
|
* of runs the session performed in this server's lifetime.
|
|
298543
298585
|
*/
|
|
298544
298586
|
sessionTaskIds = /* @__PURE__ */ new Map();
|
|
298587
|
+
/**
|
|
298588
|
+
* Tool-approval requests awaiting a user decision from a connected client,
|
|
298589
|
+
* keyed by the request's uuid. The desktop shows a modal on
|
|
298590
|
+
* `permission:user-required` and answers with `permission:decision`; this
|
|
298591
|
+
* map is how that answer reaches the run that's blocked on it.
|
|
298592
|
+
*/
|
|
298593
|
+
pendingApprovals = /* @__PURE__ */ new Map();
|
|
298545
298594
|
port;
|
|
298546
298595
|
host;
|
|
298547
298596
|
workspacePath;
|
|
@@ -298600,17 +298649,18 @@ var DashboardServer = class {
|
|
|
298600
298649
|
}
|
|
298601
298650
|
this.persistConfig();
|
|
298602
298651
|
});
|
|
298603
|
-
this.socket.onCascadeRun(async (prompt, model, socketId, requestedSessionId) => {
|
|
298652
|
+
this.socket.onCascadeRun(async (prompt, model, socketId, requestedSessionId, forceTier) => {
|
|
298604
298653
|
const sessionId = requestedSessionId ?? crypto4.randomUUID();
|
|
298605
298654
|
const abortController = new AbortController();
|
|
298606
298655
|
this.activeControllers.set(sessionId, abortController);
|
|
298607
298656
|
const runPrompt = requestedSessionId ? this.buildContinuationPrompt(sessionId, prompt) : prompt;
|
|
298608
298657
|
const title = this.persistRunStart(sessionId, prompt);
|
|
298609
|
-
|
|
298658
|
+
let cfg = model !== "auto" ? { ...this.config, models: { ...this.config.models, t1: model } } : this.config;
|
|
298659
|
+
if (forceTier) cfg = { ...cfg, routing: { ...cfg.routing, forceTier } };
|
|
298610
298660
|
const cascade = new Cascade(cfg, this.workspacePath, this.store);
|
|
298611
298661
|
this.activeSessions.set(sessionId, cascade);
|
|
298612
298662
|
cascade.on("stream:token", (e3) => {
|
|
298613
|
-
this.socket.emitToSocket(socketId, "stream:token", { sessionId, tierId: e3.tierId, text: e3.text });
|
|
298663
|
+
this.socket.emitToSocket(socketId, "stream:token", { sessionId, tierId: e3.tierId, text: e3.text, primary: e3.primary });
|
|
298614
298664
|
});
|
|
298615
298665
|
cascade.on("tier:status", (e3) => {
|
|
298616
298666
|
this.socket.emitToSocket(socketId, "tier:status", { sessionId, ...e3 });
|
|
@@ -298622,7 +298672,11 @@ var DashboardServer = class {
|
|
|
298622
298672
|
this.socket.emitPeerMessage(e3);
|
|
298623
298673
|
});
|
|
298624
298674
|
try {
|
|
298625
|
-
const result = await cascade.run({
|
|
298675
|
+
const result = await cascade.run({
|
|
298676
|
+
prompt: runPrompt,
|
|
298677
|
+
signal: abortController.signal,
|
|
298678
|
+
approvalCallback: this.makeApprovalCallback(sessionId)
|
|
298679
|
+
});
|
|
298626
298680
|
this.recordSessionTask(sessionId, result.taskId);
|
|
298627
298681
|
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
298628
298682
|
this.socket.emitToSocket(socketId, "session:complete", { sessionId, result });
|
|
@@ -298641,10 +298695,18 @@ var DashboardServer = class {
|
|
|
298641
298695
|
} finally {
|
|
298642
298696
|
this.activeSessions.delete(sessionId);
|
|
298643
298697
|
this.activeControllers.delete(sessionId);
|
|
298698
|
+
this.denyPendingApprovals(sessionId);
|
|
298644
298699
|
}
|
|
298645
298700
|
});
|
|
298646
298701
|
this.socket.onSessionHalt((sessionId) => {
|
|
298647
298702
|
this.activeControllers.get(sessionId)?.abort();
|
|
298703
|
+
this.denyPendingApprovals(sessionId);
|
|
298704
|
+
});
|
|
298705
|
+
this.socket.onApprovalResponse(({ requestId, approved, always }) => {
|
|
298706
|
+
const pending = this.pendingApprovals.get(requestId);
|
|
298707
|
+
if (!pending) return;
|
|
298708
|
+
this.pendingApprovals.delete(requestId);
|
|
298709
|
+
pending.resolve({ approved: !!approved, always: !!always });
|
|
298648
298710
|
});
|
|
298649
298711
|
this.socket.onSessionSteer((message, sessionId, nodeId) => {
|
|
298650
298712
|
const steered = this.steerSessions(message, sessionId, nodeId);
|
|
@@ -298812,6 +298874,29 @@ var DashboardServer = class {
|
|
|
298812
298874
|
list.push(taskId);
|
|
298813
298875
|
this.sessionTaskIds.set(sessionId, list);
|
|
298814
298876
|
}
|
|
298877
|
+
/**
|
|
298878
|
+
* Approval bridge: cascade calls this when a dangerous tool escalates to the
|
|
298879
|
+
* user. The request itself was already pushed to the client via the
|
|
298880
|
+
* `permission:user-required` forward; here we just park a resolver keyed by
|
|
298881
|
+
* the request id and wait for the client's `permission:decision` (handled in
|
|
298882
|
+
* onApprovalResponse). Never auto-approves — an unanswered request stays
|
|
298883
|
+
* pending until the client answers, the run ends, or the escalator's own
|
|
298884
|
+
* timeout denies it.
|
|
298885
|
+
*/
|
|
298886
|
+
makeApprovalCallback(sessionId) {
|
|
298887
|
+
return (request) => new Promise((resolve) => {
|
|
298888
|
+
this.pendingApprovals.set(request.id, { resolve, sessionId });
|
|
298889
|
+
});
|
|
298890
|
+
}
|
|
298891
|
+
/** Deny + clear any approvals still pending for a session (run end / abort). */
|
|
298892
|
+
denyPendingApprovals(sessionId) {
|
|
298893
|
+
for (const [id, pending] of this.pendingApprovals) {
|
|
298894
|
+
if (pending.sessionId === sessionId) {
|
|
298895
|
+
this.pendingApprovals.delete(id);
|
|
298896
|
+
pending.resolve({ approved: false, always: false });
|
|
298897
|
+
}
|
|
298898
|
+
}
|
|
298899
|
+
}
|
|
298815
298900
|
persistRuntimeRow(sessionId, title, status, latestPrompt) {
|
|
298816
298901
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
298817
298902
|
const row = { sessionId, title, workspacePath: this.workspacePath, status, startedAt: now, updatedAt: now, latestPrompt, isGlobal: false };
|
|
@@ -299000,15 +299085,6 @@ ${prompt}`;
|
|
|
299000
299085
|
if (sessionId) this.socket.broadcastToRoom(`session:${sessionId}`, "session:halt", payload);
|
|
299001
299086
|
res.json({ success: true, ...payload });
|
|
299002
299087
|
});
|
|
299003
|
-
this.app.post("/api/approve", auth, mutationLimiter, (req, res) => {
|
|
299004
|
-
const body = req.body;
|
|
299005
|
-
const sessionId = typeof body["sessionId"] === "string" ? body["sessionId"] : void 0;
|
|
299006
|
-
const nodeId = typeof body["nodeId"] === "string" ? body["nodeId"] : void 0;
|
|
299007
|
-
const payload = { sessionId, nodeId, requestedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
299008
|
-
this.socket.broadcast("session:approve", payload);
|
|
299009
|
-
if (sessionId) this.socket.broadcastToRoom(`session:${sessionId}`, "session:approve", payload);
|
|
299010
|
-
res.json({ success: true, ...payload });
|
|
299011
|
-
});
|
|
299012
299088
|
this.app.post("/api/inject", auth, mutationLimiter, (req, res) => {
|
|
299013
299089
|
const body = req.body;
|
|
299014
299090
|
const message = typeof body["message"] === "string" ? body["message"] : void 0;
|
|
@@ -299259,7 +299335,7 @@ ${prompt}`;
|
|
|
299259
299335
|
const cascade = new Cascade(this.config, this.workspacePath, this.store);
|
|
299260
299336
|
this.activeSessions.set(sessionId, cascade);
|
|
299261
299337
|
cascade.on("stream:token", (e3) => {
|
|
299262
|
-
this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, tierId: e3.tierId, text: e3.text });
|
|
299338
|
+
this.socket.broadcastToRoom(`session:${sessionId}`, "stream:token", { sessionId, tierId: e3.tierId, text: e3.text, primary: e3.primary });
|
|
299263
299339
|
});
|
|
299264
299340
|
cascade.on("tier:status", (e3) => {
|
|
299265
299341
|
this.socket.broadcastToRoom(`session:${sessionId}`, "tier:status", { sessionId, ...e3 });
|
|
@@ -299271,7 +299347,11 @@ ${prompt}`;
|
|
|
299271
299347
|
this.socket.emitPeerMessage(e3);
|
|
299272
299348
|
});
|
|
299273
299349
|
try {
|
|
299274
|
-
const result = await cascade.run({
|
|
299350
|
+
const result = await cascade.run({
|
|
299351
|
+
prompt: runPrompt,
|
|
299352
|
+
identityId: body.identityId,
|
|
299353
|
+
approvalCallback: this.makeApprovalCallback(sessionId)
|
|
299354
|
+
});
|
|
299275
299355
|
this.recordSessionTask(sessionId, result.taskId);
|
|
299276
299356
|
this.persistRunEnd(sessionId, title, prompt, result.output, "COMPLETED");
|
|
299277
299357
|
this.socket.broadcast("cost:update", {
|
|
@@ -299289,6 +299369,7 @@ ${prompt}`;
|
|
|
299289
299369
|
});
|
|
299290
299370
|
} finally {
|
|
299291
299371
|
this.activeSessions.delete(sessionId);
|
|
299372
|
+
this.denyPendingApprovals(sessionId);
|
|
299292
299373
|
}
|
|
299293
299374
|
})();
|
|
299294
299375
|
});
|