@buildautomaton/cli 0.1.57 → 0.1.58
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 +1 -1
- package/dist/cli.js +974 -535
- package/dist/cli.js.map +4 -4
- package/dist/index.js +1017 -578
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -25631,7 +25631,7 @@ var {
|
|
|
25631
25631
|
} = import_index.default;
|
|
25632
25632
|
|
|
25633
25633
|
// src/cli-version.ts
|
|
25634
|
-
var CLI_VERSION = "0.1.
|
|
25634
|
+
var CLI_VERSION = "0.1.58".length > 0 ? "0.1.58" : "0.0.0-dev";
|
|
25635
25635
|
|
|
25636
25636
|
// src/cli/defaults.ts
|
|
25637
25637
|
var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
|
|
@@ -28757,6 +28757,81 @@ function isUserEndedSessionTurnErrorText(errorText) {
|
|
|
28757
28757
|
// ../types/src/session-kind.ts
|
|
28758
28758
|
var SESSION_KINDS = ["regular", "planning", "planned"];
|
|
28759
28759
|
var SESSION_KIND_SET = new Set(SESSION_KINDS);
|
|
28760
|
+
function parseSessionKind(raw) {
|
|
28761
|
+
if (raw === "todo") return "planned";
|
|
28762
|
+
if (typeof raw === "string" && SESSION_KIND_SET.has(raw)) return raw;
|
|
28763
|
+
return "regular";
|
|
28764
|
+
}
|
|
28765
|
+
|
|
28766
|
+
// ../types/src/planning-todo.ts
|
|
28767
|
+
function planningTodoTitle(item) {
|
|
28768
|
+
return item.content.title;
|
|
28769
|
+
}
|
|
28770
|
+
|
|
28771
|
+
// ../types/src/parse-planning-todo-agent-json.ts
|
|
28772
|
+
function parsePlanningTodoAgentJson(raw) {
|
|
28773
|
+
if (raw == null || raw.trim() === "") return [];
|
|
28774
|
+
let text = raw.trim();
|
|
28775
|
+
const fence = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
28776
|
+
if (fence?.[1]) text = fence[1].trim();
|
|
28777
|
+
let parsed;
|
|
28778
|
+
try {
|
|
28779
|
+
parsed = JSON.parse(text);
|
|
28780
|
+
} catch {
|
|
28781
|
+
const start = text.indexOf("[");
|
|
28782
|
+
const end = text.lastIndexOf("]");
|
|
28783
|
+
if (start < 0 || end <= start) return [];
|
|
28784
|
+
try {
|
|
28785
|
+
parsed = JSON.parse(text.slice(start, end + 1));
|
|
28786
|
+
} catch {
|
|
28787
|
+
return [];
|
|
28788
|
+
}
|
|
28789
|
+
}
|
|
28790
|
+
if (!Array.isArray(parsed)) return [];
|
|
28791
|
+
const rows = [];
|
|
28792
|
+
for (const item of parsed) {
|
|
28793
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
|
|
28794
|
+
const o = item;
|
|
28795
|
+
const title = typeof o.title === "string" ? o.title.trim() : "";
|
|
28796
|
+
const prompt = typeof o.prompt === "string" ? o.prompt.trim() : typeof o.promptText === "string" ? o.promptText.trim() : "";
|
|
28797
|
+
if (!title || !prompt) continue;
|
|
28798
|
+
rows.push({ title, prompt });
|
|
28799
|
+
}
|
|
28800
|
+
return rows;
|
|
28801
|
+
}
|
|
28802
|
+
|
|
28803
|
+
// ../types/src/build-planning-session-agent-prompt.ts
|
|
28804
|
+
var PLANNING_INSTRUCTIONS = [
|
|
28805
|
+
"PLANNING MODE: You must NOT make any changes to the codebase, filesystem, or environment.",
|
|
28806
|
+
"Do not run tools that modify files or execute commands that change state.",
|
|
28807
|
+
"Your only task is to analyze and produce a plan.",
|
|
28808
|
+
"",
|
|
28809
|
+
"Respond with ONLY a single JSON array \u2014 no markdown fences, no other text before or after.",
|
|
28810
|
+
"Each array element must be an object with exactly:",
|
|
28811
|
+
'- "title": a one-line summary of the task',
|
|
28812
|
+
'- "prompt": the full prompt to use when creating a new draft session from this todo',
|
|
28813
|
+
"",
|
|
28814
|
+
"Example:",
|
|
28815
|
+
'[{"title":"Add user login","prompt":"Implement a login form with email and password..."}]'
|
|
28816
|
+
].join("\n");
|
|
28817
|
+
function buildPlanningSessionAgentPrompt(userPrompt) {
|
|
28818
|
+
return [PLANNING_INSTRUCTIONS, "", "User request:", userPrompt.trim()].join("\n");
|
|
28819
|
+
}
|
|
28820
|
+
function buildPlanningSessionFollowUpAgentPrompt(userPrompt, existingTodos) {
|
|
28821
|
+
const todoLines = existingTodos.length > 0 ? existingTodos.map((t) => {
|
|
28822
|
+
const status = t.plannedSessionId ? "DONE (draft session already created)" : "OPEN";
|
|
28823
|
+
return `- [${status}] ${planningTodoTitle(t)}`;
|
|
28824
|
+
}).join("\n") : "(none yet)";
|
|
28825
|
+
return [
|
|
28826
|
+
PLANNING_INSTRUCTIONS,
|
|
28827
|
+
"",
|
|
28828
|
+
"Existing todo items from this planning session (consider these when responding; do not duplicate completed items):",
|
|
28829
|
+
todoLines,
|
|
28830
|
+
"",
|
|
28831
|
+
"User follow-up:",
|
|
28832
|
+
userPrompt.trim()
|
|
28833
|
+
].join("\n");
|
|
28834
|
+
}
|
|
28760
28835
|
|
|
28761
28836
|
// ../types/src/change-summary-path.ts
|
|
28762
28837
|
function normalizeRepoRelativePath(p) {
|
|
@@ -29140,6 +29215,19 @@ function buildCliAutoApprovedPermissionRpcResult(requestParams) {
|
|
|
29140
29215
|
};
|
|
29141
29216
|
}
|
|
29142
29217
|
|
|
29218
|
+
// ../types/src/acp-agent-text-stream-bucket.ts
|
|
29219
|
+
function resolveAgentTextStreamBucket(params) {
|
|
29220
|
+
const k = params.transcriptRowKind;
|
|
29221
|
+
const su = params.sessionUpdate;
|
|
29222
|
+
if (k === "agent_thought_chunk" || su === "agent_thought_chunk" || k === "thinking" || su === "thinking") {
|
|
29223
|
+
return "thought";
|
|
29224
|
+
}
|
|
29225
|
+
if (k === "agent_message_chunk" || su === "agent_message_chunk" || k === "update" || su === "update") {
|
|
29226
|
+
return "message";
|
|
29227
|
+
}
|
|
29228
|
+
return null;
|
|
29229
|
+
}
|
|
29230
|
+
|
|
29143
29231
|
// ../types/src/agent-config.ts
|
|
29144
29232
|
var AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY = "claude_permission_mode";
|
|
29145
29233
|
var AGENT_CONFIG_CLI_PERMISSION_MODE_KEY = "cli_permission_mode";
|
|
@@ -34109,6 +34197,185 @@ function createBridgeOnRequest(opts) {
|
|
|
34109
34197
|
};
|
|
34110
34198
|
}
|
|
34111
34199
|
|
|
34200
|
+
// src/agents/acp/hooks/bridge-on-session-update/constants.ts
|
|
34201
|
+
var PATH_SNAPSHOT_DEBOUNCE_MS = 500;
|
|
34202
|
+
|
|
34203
|
+
// src/agents/acp/hooks/bridge-on-session-update/tool-key.ts
|
|
34204
|
+
function getToolCallId(params) {
|
|
34205
|
+
if (!params || typeof params !== "object") return "";
|
|
34206
|
+
const u = params;
|
|
34207
|
+
const id = u.toolCallId ?? u.tool_call_id;
|
|
34208
|
+
return typeof id === "string" ? id : "";
|
|
34209
|
+
}
|
|
34210
|
+
function isCompletedToolStatus(status) {
|
|
34211
|
+
if (typeof status !== "string") return false;
|
|
34212
|
+
const s = status.toLowerCase();
|
|
34213
|
+
return s === "completed" || s === "complete" || s === "succeeded" || s === "success";
|
|
34214
|
+
}
|
|
34215
|
+
function accumulateToolPaths(toolKey, paths, acc) {
|
|
34216
|
+
if (!toolKey || paths.length === 0) return;
|
|
34217
|
+
let s = acc.get(toolKey);
|
|
34218
|
+
if (!s) {
|
|
34219
|
+
s = /* @__PURE__ */ new Set();
|
|
34220
|
+
acc.set(toolKey, s);
|
|
34221
|
+
}
|
|
34222
|
+
for (const p of paths) s.add(p);
|
|
34223
|
+
}
|
|
34224
|
+
|
|
34225
|
+
// src/agents/acp/hooks/bridge-on-session-update/path-snapshot-tracker.ts
|
|
34226
|
+
var PathSnapshotTracker = class {
|
|
34227
|
+
lastSeenRunId;
|
|
34228
|
+
anonToolSeq = 0;
|
|
34229
|
+
lastAnonymousToolKey = null;
|
|
34230
|
+
beforeByToolKey = /* @__PURE__ */ new Map();
|
|
34231
|
+
debouncers = /* @__PURE__ */ new Map();
|
|
34232
|
+
accumulatedPathsByToolKey = /* @__PURE__ */ new Map();
|
|
34233
|
+
clearRunState() {
|
|
34234
|
+
for (const t of this.debouncers.values()) clearTimeout(t);
|
|
34235
|
+
this.debouncers.clear();
|
|
34236
|
+
this.beforeByToolKey.clear();
|
|
34237
|
+
this.accumulatedPathsByToolKey.clear();
|
|
34238
|
+
this.lastAnonymousToolKey = null;
|
|
34239
|
+
}
|
|
34240
|
+
onRunIdChanged(runId) {
|
|
34241
|
+
if (runId && runId !== this.lastSeenRunId) {
|
|
34242
|
+
this.lastSeenRunId = runId;
|
|
34243
|
+
this.clearRunState();
|
|
34244
|
+
}
|
|
34245
|
+
}
|
|
34246
|
+
resolveToolKey(params, updateKind) {
|
|
34247
|
+
const id = getToolCallId(params);
|
|
34248
|
+
if (id) return id;
|
|
34249
|
+
if (updateKind === "tool_call") {
|
|
34250
|
+
this.lastAnonymousToolKey = `anon:${++this.anonToolSeq}`;
|
|
34251
|
+
return this.lastAnonymousToolKey;
|
|
34252
|
+
}
|
|
34253
|
+
return this.lastAnonymousToolKey ?? "_unknown";
|
|
34254
|
+
}
|
|
34255
|
+
resetToolSnapshots(toolKey) {
|
|
34256
|
+
const t = this.debouncers.get(toolKey);
|
|
34257
|
+
if (t) clearTimeout(t);
|
|
34258
|
+
this.debouncers.delete(toolKey);
|
|
34259
|
+
this.beforeByToolKey.delete(toolKey);
|
|
34260
|
+
this.accumulatedPathsByToolKey.delete(toolKey);
|
|
34261
|
+
}
|
|
34262
|
+
captureBeforeFromDisk(toolKey, paths, sessionParentPath) {
|
|
34263
|
+
if (paths.length === 0) return;
|
|
34264
|
+
let m = this.beforeByToolKey.get(toolKey);
|
|
34265
|
+
if (!m) {
|
|
34266
|
+
m = /* @__PURE__ */ new Map();
|
|
34267
|
+
this.beforeByToolKey.set(toolKey, m);
|
|
34268
|
+
}
|
|
34269
|
+
for (const p of paths) {
|
|
34270
|
+
if (m.has(p)) continue;
|
|
34271
|
+
m.set(p, readUtf8WorkspaceFile(sessionParentPath, p));
|
|
34272
|
+
}
|
|
34273
|
+
}
|
|
34274
|
+
ensureBeforeFromHeadForMissing(toolKey, paths, sessionParentPath) {
|
|
34275
|
+
let m = this.beforeByToolKey.get(toolKey);
|
|
34276
|
+
if (!m) {
|
|
34277
|
+
m = /* @__PURE__ */ new Map();
|
|
34278
|
+
this.beforeByToolKey.set(toolKey, m);
|
|
34279
|
+
}
|
|
34280
|
+
for (const p of paths) {
|
|
34281
|
+
if (m.has(p)) continue;
|
|
34282
|
+
m.set(p, readGitHeadBlob(sessionParentPath, p));
|
|
34283
|
+
}
|
|
34284
|
+
}
|
|
34285
|
+
flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
|
|
34286
|
+
const t = this.debouncers.get(toolKey);
|
|
34287
|
+
if (t) clearTimeout(t);
|
|
34288
|
+
this.debouncers.delete(toolKey);
|
|
34289
|
+
const beforeMap = this.beforeByToolKey.get(toolKey);
|
|
34290
|
+
if (!beforeMap || beforeMap.size === 0) return;
|
|
34291
|
+
this.beforeByToolKey.delete(toolKey);
|
|
34292
|
+
if (!send || !runId || !sessionId) return;
|
|
34293
|
+
for (const [displayPath, oldText] of beforeMap) {
|
|
34294
|
+
const newText = readUtf8WorkspaceFile(sessionParentPath, displayPath);
|
|
34295
|
+
if (oldText === newText) continue;
|
|
34296
|
+
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
|
|
34297
|
+
const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, displayPath);
|
|
34298
|
+
try {
|
|
34299
|
+
send({
|
|
34300
|
+
type: "session_file_change",
|
|
34301
|
+
sessionId,
|
|
34302
|
+
runId,
|
|
34303
|
+
path: displayPath,
|
|
34304
|
+
oldText,
|
|
34305
|
+
newText,
|
|
34306
|
+
patchContent,
|
|
34307
|
+
isDirectory: dirFlags.isDirectory,
|
|
34308
|
+
directoryRemoved: dirFlags.directoryRemoved
|
|
34309
|
+
});
|
|
34310
|
+
sentPaths.add(displayPath);
|
|
34311
|
+
} catch (err) {
|
|
34312
|
+
log2(`[Bridge service] Session file change failed for ${displayPath}: ${errorMessage(err)}`);
|
|
34313
|
+
}
|
|
34314
|
+
}
|
|
34315
|
+
}
|
|
34316
|
+
scheduleDebouncedFlush(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
|
|
34317
|
+
const prev = this.debouncers.get(toolKey);
|
|
34318
|
+
if (prev) clearTimeout(prev);
|
|
34319
|
+
this.debouncers.set(
|
|
34320
|
+
toolKey,
|
|
34321
|
+
setTimeout(() => {
|
|
34322
|
+
this.debouncers.delete(toolKey);
|
|
34323
|
+
this.flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
|
|
34324
|
+
}, PATH_SNAPSHOT_DEBOUNCE_MS)
|
|
34325
|
+
);
|
|
34326
|
+
}
|
|
34327
|
+
handleToolCallLifecycle(updateKind, toolKey, toolPaths, status, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
|
|
34328
|
+
if (updateKind === "tool_call") {
|
|
34329
|
+
this.resetToolSnapshots(toolKey);
|
|
34330
|
+
}
|
|
34331
|
+
if (updateKind === "tool_call") {
|
|
34332
|
+
this.captureBeforeFromDisk(toolKey, toolPaths, sessionParentPath);
|
|
34333
|
+
} else if (updateKind === "tool_call_update") {
|
|
34334
|
+
if (isCompletedToolStatus(status)) {
|
|
34335
|
+
this.ensureBeforeFromHeadForMissing(toolKey, toolPaths, sessionParentPath);
|
|
34336
|
+
this.flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
|
|
34337
|
+
} else {
|
|
34338
|
+
this.captureBeforeFromDisk(toolKey, toolPaths, sessionParentPath);
|
|
34339
|
+
if (this.beforeByToolKey.has(toolKey)) {
|
|
34340
|
+
this.scheduleDebouncedFlush(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
|
|
34341
|
+
}
|
|
34342
|
+
}
|
|
34343
|
+
}
|
|
34344
|
+
}
|
|
34345
|
+
};
|
|
34346
|
+
|
|
34347
|
+
// src/agents/acp/hooks/bridge-on-session-update/send-session-info-title-update.ts
|
|
34348
|
+
function extractSessionInfoTitle(params) {
|
|
34349
|
+
if (!params || typeof params !== "object") return null;
|
|
34350
|
+
const p = params;
|
|
34351
|
+
const title = typeof p.title === "string" ? p.title.trim() : "";
|
|
34352
|
+
return title ? title : null;
|
|
34353
|
+
}
|
|
34354
|
+
function sendSessionInfoTitleUpdate(params) {
|
|
34355
|
+
const title = extractSessionInfoTitle(params.payload);
|
|
34356
|
+
if (!title || !params.runId || !params.send) return;
|
|
34357
|
+
try {
|
|
34358
|
+
params.send({
|
|
34359
|
+
type: "session_title_update",
|
|
34360
|
+
...params.sessionId ? { sessionId: params.sessionId } : {},
|
|
34361
|
+
runId: params.runId,
|
|
34362
|
+
title
|
|
34363
|
+
});
|
|
34364
|
+
} catch (err) {
|
|
34365
|
+
params.log(`[Bridge service] Session title update send failed: ${errorMessage(err)}`);
|
|
34366
|
+
}
|
|
34367
|
+
}
|
|
34368
|
+
|
|
34369
|
+
// src/agents/acp/hooks/bridge-on-session-update/parse-bridge-session-update.ts
|
|
34370
|
+
function parseBridgeSessionUpdate(params) {
|
|
34371
|
+
const p = params;
|
|
34372
|
+
const updateKind = p.sessionUpdate ?? p.session_update ?? p.type ?? "update";
|
|
34373
|
+
const isCompletedToolCallUpdate = updateKind === "tool_call_update" && isCompletedToolStatus(p.status);
|
|
34374
|
+
const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
|
|
34375
|
+
const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
|
|
34376
|
+
return { updateKind, toolName, isToolUpdate, isCompletedToolCallUpdate };
|
|
34377
|
+
}
|
|
34378
|
+
|
|
34112
34379
|
// src/agents/acp/hooks/extract-acp-file-diffs-from-update/paths-and-text.ts
|
|
34113
34380
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
34114
34381
|
function readOptionalTextField(v) {
|
|
@@ -34279,174 +34546,27 @@ function extractToolTargetDisplayPaths(update, sessionParentPath) {
|
|
|
34279
34546
|
return [...out];
|
|
34280
34547
|
}
|
|
34281
34548
|
|
|
34282
|
-
// src/agents/acp/hooks/bridge-on-session-update/
|
|
34283
|
-
|
|
34284
|
-
|
|
34285
|
-
|
|
34286
|
-
|
|
34287
|
-
|
|
34288
|
-
|
|
34289
|
-
|
|
34290
|
-
|
|
34291
|
-
|
|
34292
|
-
|
|
34293
|
-
|
|
34294
|
-
|
|
34295
|
-
|
|
34296
|
-
|
|
34297
|
-
|
|
34298
|
-
|
|
34299
|
-
|
|
34300
|
-
|
|
34301
|
-
|
|
34302
|
-
|
|
34303
|
-
}
|
|
34304
|
-
for (const p of paths) s.add(p);
|
|
34305
|
-
}
|
|
34306
|
-
|
|
34307
|
-
// src/agents/acp/hooks/bridge-on-session-update/path-snapshot-tracker.ts
|
|
34308
|
-
var PathSnapshotTracker = class {
|
|
34309
|
-
lastSeenRunId;
|
|
34310
|
-
anonToolSeq = 0;
|
|
34311
|
-
lastAnonymousToolKey = null;
|
|
34312
|
-
beforeByToolKey = /* @__PURE__ */ new Map();
|
|
34313
|
-
debouncers = /* @__PURE__ */ new Map();
|
|
34314
|
-
accumulatedPathsByToolKey = /* @__PURE__ */ new Map();
|
|
34315
|
-
clearRunState() {
|
|
34316
|
-
for (const t of this.debouncers.values()) clearTimeout(t);
|
|
34317
|
-
this.debouncers.clear();
|
|
34318
|
-
this.beforeByToolKey.clear();
|
|
34319
|
-
this.accumulatedPathsByToolKey.clear();
|
|
34320
|
-
this.lastAnonymousToolKey = null;
|
|
34321
|
-
}
|
|
34322
|
-
onRunIdChanged(runId) {
|
|
34323
|
-
if (runId && runId !== this.lastSeenRunId) {
|
|
34324
|
-
this.lastSeenRunId = runId;
|
|
34325
|
-
this.clearRunState();
|
|
34326
|
-
}
|
|
34327
|
-
}
|
|
34328
|
-
resolveToolKey(params, updateKind) {
|
|
34329
|
-
const id = getToolCallId(params);
|
|
34330
|
-
if (id) return id;
|
|
34331
|
-
if (updateKind === "tool_call") {
|
|
34332
|
-
this.lastAnonymousToolKey = `anon:${++this.anonToolSeq}`;
|
|
34333
|
-
return this.lastAnonymousToolKey;
|
|
34334
|
-
}
|
|
34335
|
-
return this.lastAnonymousToolKey ?? "_unknown";
|
|
34336
|
-
}
|
|
34337
|
-
resetToolSnapshots(toolKey) {
|
|
34338
|
-
const t = this.debouncers.get(toolKey);
|
|
34339
|
-
if (t) clearTimeout(t);
|
|
34340
|
-
this.debouncers.delete(toolKey);
|
|
34341
|
-
this.beforeByToolKey.delete(toolKey);
|
|
34342
|
-
this.accumulatedPathsByToolKey.delete(toolKey);
|
|
34343
|
-
}
|
|
34344
|
-
captureBeforeFromDisk(toolKey, paths, sessionParentPath) {
|
|
34345
|
-
if (paths.length === 0) return;
|
|
34346
|
-
let m = this.beforeByToolKey.get(toolKey);
|
|
34347
|
-
if (!m) {
|
|
34348
|
-
m = /* @__PURE__ */ new Map();
|
|
34349
|
-
this.beforeByToolKey.set(toolKey, m);
|
|
34350
|
-
}
|
|
34351
|
-
for (const p of paths) {
|
|
34352
|
-
if (m.has(p)) continue;
|
|
34353
|
-
m.set(p, readUtf8WorkspaceFile(sessionParentPath, p));
|
|
34354
|
-
}
|
|
34355
|
-
}
|
|
34356
|
-
ensureBeforeFromHeadForMissing(toolKey, paths, sessionParentPath) {
|
|
34357
|
-
let m = this.beforeByToolKey.get(toolKey);
|
|
34358
|
-
if (!m) {
|
|
34359
|
-
m = /* @__PURE__ */ new Map();
|
|
34360
|
-
this.beforeByToolKey.set(toolKey, m);
|
|
34361
|
-
}
|
|
34362
|
-
for (const p of paths) {
|
|
34363
|
-
if (m.has(p)) continue;
|
|
34364
|
-
m.set(p, readGitHeadBlob(sessionParentPath, p));
|
|
34365
|
-
}
|
|
34366
|
-
}
|
|
34367
|
-
flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
|
|
34368
|
-
const t = this.debouncers.get(toolKey);
|
|
34369
|
-
if (t) clearTimeout(t);
|
|
34370
|
-
this.debouncers.delete(toolKey);
|
|
34371
|
-
const beforeMap = this.beforeByToolKey.get(toolKey);
|
|
34372
|
-
if (!beforeMap || beforeMap.size === 0) return;
|
|
34373
|
-
this.beforeByToolKey.delete(toolKey);
|
|
34374
|
-
if (!send || !runId || !sessionId) return;
|
|
34375
|
-
for (const [displayPath, oldText] of beforeMap) {
|
|
34376
|
-
const newText = readUtf8WorkspaceFile(sessionParentPath, displayPath);
|
|
34377
|
-
if (oldText === newText) continue;
|
|
34378
|
-
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
|
|
34379
|
-
const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, displayPath);
|
|
34380
|
-
try {
|
|
34381
|
-
send({
|
|
34382
|
-
type: "session_file_change",
|
|
34383
|
-
sessionId,
|
|
34384
|
-
runId,
|
|
34385
|
-
path: displayPath,
|
|
34386
|
-
oldText,
|
|
34387
|
-
newText,
|
|
34388
|
-
patchContent,
|
|
34389
|
-
isDirectory: dirFlags.isDirectory,
|
|
34390
|
-
directoryRemoved: dirFlags.directoryRemoved
|
|
34391
|
-
});
|
|
34392
|
-
sentPaths.add(displayPath);
|
|
34393
|
-
} catch (err) {
|
|
34394
|
-
log2(`[Bridge service] Session file change failed for ${displayPath}: ${errorMessage(err)}`);
|
|
34395
|
-
}
|
|
34396
|
-
}
|
|
34397
|
-
}
|
|
34398
|
-
scheduleDebouncedFlush(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
|
|
34399
|
-
const prev = this.debouncers.get(toolKey);
|
|
34400
|
-
if (prev) clearTimeout(prev);
|
|
34401
|
-
this.debouncers.set(
|
|
34402
|
-
toolKey,
|
|
34403
|
-
setTimeout(() => {
|
|
34404
|
-
this.debouncers.delete(toolKey);
|
|
34405
|
-
this.flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
|
|
34406
|
-
}, PATH_SNAPSHOT_DEBOUNCE_MS)
|
|
34407
|
-
);
|
|
34408
|
-
}
|
|
34409
|
-
handleToolCallLifecycle(updateKind, toolKey, toolPaths, status, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
|
|
34410
|
-
if (updateKind === "tool_call") {
|
|
34411
|
-
this.resetToolSnapshots(toolKey);
|
|
34412
|
-
}
|
|
34413
|
-
if (updateKind === "tool_call") {
|
|
34414
|
-
this.captureBeforeFromDisk(toolKey, toolPaths, sessionParentPath);
|
|
34415
|
-
} else if (updateKind === "tool_call_update") {
|
|
34416
|
-
if (isCompletedToolStatus(status)) {
|
|
34417
|
-
this.ensureBeforeFromHeadForMissing(toolKey, toolPaths, sessionParentPath);
|
|
34418
|
-
this.flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
|
|
34419
|
-
} else {
|
|
34420
|
-
this.captureBeforeFromDisk(toolKey, toolPaths, sessionParentPath);
|
|
34421
|
-
if (this.beforeByToolKey.has(toolKey)) {
|
|
34422
|
-
this.scheduleDebouncedFlush(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
|
|
34423
|
-
}
|
|
34424
|
-
}
|
|
34425
|
-
}
|
|
34426
|
-
}
|
|
34427
|
-
};
|
|
34428
|
-
|
|
34429
|
-
// src/agents/acp/hooks/bridge-on-session-update/send-structured-file-changes.ts
|
|
34430
|
-
function sendExtractedDiffsAsSessionFileChanges(diffs, send, sessionParentPath, sessionId, runId, sentPaths, log2) {
|
|
34431
|
-
for (const d of diffs) {
|
|
34432
|
-
try {
|
|
34433
|
-
const patchContent = editSnippetToUnifiedDiff(d.path, d.oldText, d.newText);
|
|
34434
|
-
const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, d.path);
|
|
34435
|
-
send({
|
|
34436
|
-
type: "session_file_change",
|
|
34437
|
-
sessionId,
|
|
34438
|
-
runId,
|
|
34439
|
-
path: d.path,
|
|
34440
|
-
oldText: d.oldText,
|
|
34441
|
-
newText: d.newText,
|
|
34442
|
-
patchContent,
|
|
34443
|
-
isDirectory: dirFlags.isDirectory,
|
|
34444
|
-
directoryRemoved: dirFlags.directoryRemoved
|
|
34445
|
-
});
|
|
34446
|
-
sentPaths.add(d.path);
|
|
34447
|
-
} catch (err) {
|
|
34448
|
-
log2(`[Bridge service] Session file change failed for ${d.path}: ${errorMessage(err)}`);
|
|
34449
|
-
}
|
|
34549
|
+
// src/agents/acp/hooks/bridge-on-session-update/send-structured-file-changes.ts
|
|
34550
|
+
function sendExtractedDiffsAsSessionFileChanges(diffs, send, sessionParentPath, sessionId, runId, sentPaths, log2) {
|
|
34551
|
+
for (const d of diffs) {
|
|
34552
|
+
try {
|
|
34553
|
+
const patchContent = editSnippetToUnifiedDiff(d.path, d.oldText, d.newText);
|
|
34554
|
+
const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, d.path);
|
|
34555
|
+
send({
|
|
34556
|
+
type: "session_file_change",
|
|
34557
|
+
sessionId,
|
|
34558
|
+
runId,
|
|
34559
|
+
path: d.path,
|
|
34560
|
+
oldText: d.oldText,
|
|
34561
|
+
newText: d.newText,
|
|
34562
|
+
patchContent,
|
|
34563
|
+
isDirectory: dirFlags.isDirectory,
|
|
34564
|
+
directoryRemoved: dirFlags.directoryRemoved
|
|
34565
|
+
});
|
|
34566
|
+
sentPaths.add(d.path);
|
|
34567
|
+
} catch (err) {
|
|
34568
|
+
log2(`[Bridge service] Session file change failed for ${d.path}: ${errorMessage(err)}`);
|
|
34569
|
+
}
|
|
34450
34570
|
}
|
|
34451
34571
|
}
|
|
34452
34572
|
function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, sessionParentPath, sessionId, runId, log2) {
|
|
@@ -34476,25 +34596,158 @@ function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, sessio
|
|
|
34476
34596
|
}
|
|
34477
34597
|
}
|
|
34478
34598
|
|
|
34479
|
-
// src/agents/acp/hooks/bridge-on-session-update/
|
|
34480
|
-
function
|
|
34481
|
-
|
|
34482
|
-
|
|
34483
|
-
|
|
34484
|
-
|
|
34599
|
+
// src/agents/acp/hooks/bridge-on-session-update/handle-bridge-tool-session-update.ts
|
|
34600
|
+
function handleBridgeToolSessionUpdate(params) {
|
|
34601
|
+
const {
|
|
34602
|
+
params: updateParams,
|
|
34603
|
+
updateKind,
|
|
34604
|
+
isToolUpdate,
|
|
34605
|
+
isCompletedToolCallUpdate,
|
|
34606
|
+
toolKey,
|
|
34607
|
+
toolPaths,
|
|
34608
|
+
status,
|
|
34609
|
+
sessionParentPath,
|
|
34610
|
+
pathTracker,
|
|
34611
|
+
sentFileChangePaths,
|
|
34612
|
+
send,
|
|
34613
|
+
runId,
|
|
34614
|
+
sessionId,
|
|
34615
|
+
log: log2
|
|
34616
|
+
} = params;
|
|
34617
|
+
if (updateKind === "tool_call") {
|
|
34618
|
+
pathTracker.resetToolSnapshots(toolKey);
|
|
34619
|
+
}
|
|
34620
|
+
if (isToolUpdate) {
|
|
34621
|
+
accumulateToolPaths(toolKey, toolPaths, pathTracker.accumulatedPathsByToolKey);
|
|
34622
|
+
}
|
|
34623
|
+
if (isToolUpdate) {
|
|
34624
|
+
const deliver = send && runId && sessionId ? (msg) => send(msg) : null;
|
|
34625
|
+
pathTracker.handleToolCallLifecycle(
|
|
34626
|
+
updateKind,
|
|
34627
|
+
toolKey,
|
|
34628
|
+
toolPaths,
|
|
34629
|
+
status,
|
|
34630
|
+
sessionParentPath,
|
|
34631
|
+
sentFileChangePaths,
|
|
34632
|
+
deliver,
|
|
34633
|
+
runId,
|
|
34634
|
+
sessionId,
|
|
34635
|
+
log2
|
|
34636
|
+
);
|
|
34637
|
+
}
|
|
34638
|
+
const diffs = extractAcpFileDiffsFromUpdate(updateParams, sessionParentPath);
|
|
34639
|
+
if (diffs.length > 0 && send && runId && sessionId) {
|
|
34640
|
+
sendExtractedDiffsAsSessionFileChanges(
|
|
34641
|
+
diffs,
|
|
34642
|
+
send,
|
|
34643
|
+
sessionParentPath,
|
|
34644
|
+
sessionId,
|
|
34645
|
+
runId,
|
|
34646
|
+
sentFileChangePaths,
|
|
34647
|
+
log2
|
|
34648
|
+
);
|
|
34649
|
+
} else if (diffs.length > 0) {
|
|
34650
|
+
log2(
|
|
34651
|
+
`[Bridge service] Agent file diff(s) not forwarded (${diffs.length}): session or run not wired to the bridge.`
|
|
34652
|
+
);
|
|
34653
|
+
}
|
|
34654
|
+
if (isCompletedToolCallUpdate && send && runId && sessionId) {
|
|
34655
|
+
const acc = pathTracker.accumulatedPathsByToolKey.get(toolKey);
|
|
34656
|
+
const merged = [.../* @__PURE__ */ new Set([...acc ? [...acc] : [], ...toolPaths])];
|
|
34657
|
+
sendGitHeadVsWorkspaceForToolPaths(
|
|
34658
|
+
merged,
|
|
34659
|
+
sentFileChangePaths,
|
|
34660
|
+
send,
|
|
34661
|
+
sessionParentPath,
|
|
34662
|
+
sessionId,
|
|
34663
|
+
runId,
|
|
34664
|
+
log2
|
|
34665
|
+
);
|
|
34666
|
+
pathTracker.accumulatedPathsByToolKey.delete(toolKey);
|
|
34667
|
+
}
|
|
34485
34668
|
}
|
|
34486
|
-
function
|
|
34487
|
-
|
|
34488
|
-
|
|
34669
|
+
function resolveBridgeToolPaths(params, isToolUpdate, sessionParentPath) {
|
|
34670
|
+
return isToolUpdate ? extractToolTargetDisplayPaths(params, sessionParentPath) : [];
|
|
34671
|
+
}
|
|
34672
|
+
|
|
34673
|
+
// src/agents/planning/extract-session-update-message-text.ts
|
|
34674
|
+
function extractSessionUpdateMessageText(params) {
|
|
34675
|
+
if (params == null || typeof params !== "object" || Array.isArray(params)) return null;
|
|
34676
|
+
const o = params;
|
|
34677
|
+
if (typeof o.text === "string" && o.text.length > 0) return o.text;
|
|
34678
|
+
const content = o.content;
|
|
34679
|
+
if (typeof content === "string" && content.length > 0) return content;
|
|
34680
|
+
if (content != null && typeof content === "object" && !Array.isArray(content)) {
|
|
34681
|
+
const c = content;
|
|
34682
|
+
if (typeof c.text === "string" && c.text.length > 0) return c.text;
|
|
34683
|
+
}
|
|
34684
|
+
const update = o.update;
|
|
34685
|
+
if (typeof update === "string" && update.length > 0) return update;
|
|
34686
|
+
if (update != null && typeof update === "object" && !Array.isArray(update)) {
|
|
34687
|
+
const u = update;
|
|
34688
|
+
const innerContent = u.content;
|
|
34689
|
+
if (typeof innerContent === "string" && innerContent.length > 0) return innerContent;
|
|
34690
|
+
if (innerContent != null && typeof innerContent === "object" && !Array.isArray(innerContent)) {
|
|
34691
|
+
const ic = innerContent;
|
|
34692
|
+
if (typeof ic.text === "string" && ic.text.length > 0) return ic.text;
|
|
34693
|
+
}
|
|
34694
|
+
}
|
|
34695
|
+
return null;
|
|
34696
|
+
}
|
|
34697
|
+
|
|
34698
|
+
// src/agents/planning/planning-session-turn-buffer.ts
|
|
34699
|
+
var buffersByRunId = /* @__PURE__ */ new Map();
|
|
34700
|
+
function registerPlanningSessionTurn(runId) {
|
|
34701
|
+
buffersByRunId.set(runId, { messageBuffer: "" });
|
|
34702
|
+
}
|
|
34703
|
+
function clearPlanningSessionTurn(runId) {
|
|
34704
|
+
buffersByRunId.delete(runId);
|
|
34705
|
+
}
|
|
34706
|
+
function capturePlanningSessionUpdate(params) {
|
|
34707
|
+
const state = buffersByRunId.get(params.runId);
|
|
34708
|
+
if (!state) return false;
|
|
34709
|
+
const sessionUpdate = params.payload != null && typeof params.payload === "object" && !Array.isArray(params.payload) ? params.payload.sessionUpdate ?? params.payload.session_update : void 0;
|
|
34710
|
+
const bucket = resolveAgentTextStreamBucket({
|
|
34711
|
+
transcriptRowKind: params.updateKind,
|
|
34712
|
+
sessionUpdate: typeof sessionUpdate === "string" ? sessionUpdate : void 0
|
|
34713
|
+
});
|
|
34714
|
+
if (bucket !== "message") return false;
|
|
34715
|
+
const text = extractSessionUpdateMessageText(params.payload);
|
|
34716
|
+
if (text) state.messageBuffer += text;
|
|
34717
|
+
return true;
|
|
34718
|
+
}
|
|
34719
|
+
function getPlanningSessionTurnOutput(runId) {
|
|
34720
|
+
return buffersByRunId.get(runId)?.messageBuffer ?? "";
|
|
34721
|
+
}
|
|
34722
|
+
function consumePlanningSessionTurnOutput(runId) {
|
|
34723
|
+
const state = buffersByRunId.get(runId);
|
|
34724
|
+
buffersByRunId.delete(runId);
|
|
34725
|
+
return state?.messageBuffer ?? "";
|
|
34726
|
+
}
|
|
34727
|
+
|
|
34728
|
+
// src/agents/acp/hooks/bridge-on-session-update/forward-bridge-session-update.ts
|
|
34729
|
+
function forwardBridgeSessionUpdate(params) {
|
|
34730
|
+
const { runId, sessionId, updateKind, payload, send, nextTranscriptStreamSeq, log: log2 } = params;
|
|
34731
|
+
if (updateKind === "permission") {
|
|
34732
|
+
return;
|
|
34733
|
+
}
|
|
34734
|
+
if (capturePlanningSessionUpdate({ runId, updateKind, payload })) {
|
|
34735
|
+
return;
|
|
34736
|
+
}
|
|
34489
34737
|
try {
|
|
34490
|
-
|
|
34491
|
-
|
|
34492
|
-
|
|
34493
|
-
|
|
34494
|
-
|
|
34738
|
+
const transcriptStreamSeq = nextTranscriptStreamSeq?.(runId);
|
|
34739
|
+
send({
|
|
34740
|
+
type: "session_update",
|
|
34741
|
+
...sessionId ? { sessionId } : {},
|
|
34742
|
+
runId,
|
|
34743
|
+
kind: updateKind,
|
|
34744
|
+
payload,
|
|
34745
|
+
...transcriptStreamSeq != null ? { transcriptStreamSeq } : {}
|
|
34495
34746
|
});
|
|
34496
34747
|
} catch (err) {
|
|
34497
|
-
|
|
34748
|
+
log2(
|
|
34749
|
+
`[Bridge service] Session update send failed (${formatSessionUpdateKindForLog(updateKind)}): ${errorMessage(err)}`
|
|
34750
|
+
);
|
|
34498
34751
|
}
|
|
34499
34752
|
}
|
|
34500
34753
|
|
|
@@ -34509,8 +34762,7 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
34509
34762
|
pathTracker.onRunIdChanged(runId);
|
|
34510
34763
|
const send = getSendSessionUpdate();
|
|
34511
34764
|
const sentFileChangePaths = /* @__PURE__ */ new Set();
|
|
34512
|
-
const
|
|
34513
|
-
const updateKind = p.sessionUpdate ?? p.session_update ?? p.type ?? "update";
|
|
34765
|
+
const { updateKind, isToolUpdate, isCompletedToolCallUpdate } = parseBridgeSessionUpdate(params);
|
|
34514
34766
|
if (updateKind === "config_option_update") {
|
|
34515
34767
|
return;
|
|
34516
34768
|
}
|
|
@@ -34518,81 +34770,35 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
34518
34770
|
sendSessionInfoTitleUpdate({ payload: params, runId, sessionId, send, log: log2 });
|
|
34519
34771
|
return;
|
|
34520
34772
|
}
|
|
34521
|
-
const
|
|
34522
|
-
const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
|
|
34523
|
-
const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
|
|
34524
|
-
const toolPaths = isToolUpdate ? extractToolTargetDisplayPaths(params, sessionParentPath) : [];
|
|
34773
|
+
const toolPaths = resolveBridgeToolPaths(params, isToolUpdate, sessionParentPath);
|
|
34525
34774
|
const toolKey = isToolUpdate ? pathTracker.resolveToolKey(params, updateKind) : "";
|
|
34526
|
-
|
|
34527
|
-
|
|
34528
|
-
|
|
34529
|
-
|
|
34530
|
-
|
|
34531
|
-
|
|
34532
|
-
|
|
34533
|
-
|
|
34534
|
-
|
|
34535
|
-
|
|
34536
|
-
|
|
34537
|
-
|
|
34538
|
-
|
|
34539
|
-
|
|
34540
|
-
|
|
34541
|
-
|
|
34542
|
-
|
|
34543
|
-
|
|
34544
|
-
|
|
34545
|
-
);
|
|
34546
|
-
}
|
|
34547
|
-
const diffs = extractAcpFileDiffsFromUpdate(params, sessionParentPath);
|
|
34548
|
-
if (diffs.length > 0 && send && runId && sessionId) {
|
|
34549
|
-
sendExtractedDiffsAsSessionFileChanges(
|
|
34550
|
-
diffs,
|
|
34551
|
-
send,
|
|
34552
|
-
sessionParentPath,
|
|
34553
|
-
sessionId,
|
|
34775
|
+
const status = params.status;
|
|
34776
|
+
handleBridgeToolSessionUpdate({
|
|
34777
|
+
params,
|
|
34778
|
+
updateKind,
|
|
34779
|
+
isToolUpdate,
|
|
34780
|
+
isCompletedToolCallUpdate,
|
|
34781
|
+
toolKey,
|
|
34782
|
+
toolPaths,
|
|
34783
|
+
status,
|
|
34784
|
+
sessionParentPath,
|
|
34785
|
+
pathTracker,
|
|
34786
|
+
sentFileChangePaths,
|
|
34787
|
+
send,
|
|
34788
|
+
runId: runId ?? "",
|
|
34789
|
+
sessionId: sessionId ?? "",
|
|
34790
|
+
log: log2
|
|
34791
|
+
});
|
|
34792
|
+
if (runId && send) {
|
|
34793
|
+
forwardBridgeSessionUpdate({
|
|
34554
34794
|
runId,
|
|
34555
|
-
sentFileChangePaths,
|
|
34556
|
-
log2
|
|
34557
|
-
);
|
|
34558
|
-
} else if (diffs.length > 0) {
|
|
34559
|
-
log2(
|
|
34560
|
-
`[Bridge service] Agent file diff(s) not forwarded (${diffs.length}): session or run not wired to the bridge.`
|
|
34561
|
-
);
|
|
34562
|
-
}
|
|
34563
|
-
if (isCompletedToolCallUpdate && send && runId && sessionId) {
|
|
34564
|
-
const acc = pathTracker.accumulatedPathsByToolKey.get(toolKey);
|
|
34565
|
-
const merged = [.../* @__PURE__ */ new Set([...acc ? [...acc] : [], ...toolPaths])];
|
|
34566
|
-
sendGitHeadVsWorkspaceForToolPaths(
|
|
34567
|
-
merged,
|
|
34568
|
-
sentFileChangePaths,
|
|
34569
|
-
send,
|
|
34570
|
-
sessionParentPath,
|
|
34571
34795
|
sessionId,
|
|
34572
|
-
|
|
34573
|
-
|
|
34574
|
-
|
|
34575
|
-
|
|
34576
|
-
|
|
34577
|
-
|
|
34578
|
-
if (updateKind === "permission") {
|
|
34579
|
-
return;
|
|
34580
|
-
}
|
|
34581
|
-
try {
|
|
34582
|
-
const transcriptStreamSeq = nextTranscriptStreamSeq?.(runId);
|
|
34583
|
-
send({
|
|
34584
|
-
type: "session_update",
|
|
34585
|
-
...sessionId ? { sessionId } : {},
|
|
34586
|
-
runId,
|
|
34587
|
-
kind: updateKind,
|
|
34588
|
-
payload: params,
|
|
34589
|
-
...transcriptStreamSeq != null ? { transcriptStreamSeq } : {}
|
|
34590
|
-
});
|
|
34591
|
-
} catch (err) {
|
|
34592
|
-
log2(
|
|
34593
|
-
`[Bridge service] Session update send failed (${formatSessionUpdateKindForLog(updateKind)}): ${errorMessage(err)}`
|
|
34594
|
-
);
|
|
34595
|
-
}
|
|
34796
|
+
updateKind,
|
|
34797
|
+
payload: params,
|
|
34798
|
+
send,
|
|
34799
|
+
nextTranscriptStreamSeq,
|
|
34800
|
+
log: log2
|
|
34801
|
+
});
|
|
34596
34802
|
}
|
|
34597
34803
|
};
|
|
34598
34804
|
}
|
|
@@ -34932,14 +35138,48 @@ async function disconnectAll(ctx) {
|
|
|
34932
35138
|
ctx.pendingCancelRunIds.clear();
|
|
34933
35139
|
}
|
|
34934
35140
|
|
|
34935
|
-
// src/
|
|
34936
|
-
|
|
34937
|
-
|
|
34938
|
-
|
|
34939
|
-
|
|
34940
|
-
|
|
34941
|
-
|
|
34942
|
-
|
|
35141
|
+
// src/agents/acp/manager/resolve-prompt-run-context.ts
|
|
35142
|
+
function resolvePromptRunContext(ctx, opts) {
|
|
35143
|
+
const { runId, mode, agentType, agentConfig, sessionId } = opts;
|
|
35144
|
+
const preferredForPrompt = agentType ?? ctx.backendFallbackAgentType ?? null;
|
|
35145
|
+
if (!runId) {
|
|
35146
|
+
ctx.log("[Agent] Prompt ignored: missing runId (cannot route session updates).");
|
|
35147
|
+
return null;
|
|
35148
|
+
}
|
|
35149
|
+
const acpAgentKey = computeAcpAgentKey(preferredForPrompt, mode, agentConfig ?? null);
|
|
35150
|
+
if (!acpAgentKey) {
|
|
35151
|
+
return null;
|
|
35152
|
+
}
|
|
35153
|
+
const activeAcpSessionAgentKey = computeAcpSessionAgentKey(sessionId, acpAgentKey);
|
|
35154
|
+
ctx.pendingCancelRunIds.delete(runId);
|
|
35155
|
+
ctx.promptRouting.registerRun({ sessionId, runId });
|
|
35156
|
+
ctx.runDispatch.set(runId, { acpSessionAgentKey: activeAcpSessionAgentKey });
|
|
35157
|
+
return {
|
|
35158
|
+
activeRunId: runId,
|
|
35159
|
+
activeAcpAgentKey: acpAgentKey,
|
|
35160
|
+
activeAcpSessionAgentKey,
|
|
35161
|
+
preferredForPrompt
|
|
35162
|
+
};
|
|
35163
|
+
}
|
|
35164
|
+
|
|
35165
|
+
// src/agents/acp/send-prompt-result-augment.ts
|
|
35166
|
+
function augmentPromptResultAuthFields(agentType, errorText) {
|
|
35167
|
+
const err = errorText ?? "";
|
|
35168
|
+
const at = agentType ?? null;
|
|
35169
|
+
const evaluated = Boolean(at && err.trim());
|
|
35170
|
+
const suggestsAuth = evaluated && at ? localAgentErrorSuggestsAuth(at, err) : false;
|
|
35171
|
+
if (!suggestsAuth || !agentType) return {};
|
|
35172
|
+
return { agentAuthRequired: true, agentType };
|
|
35173
|
+
}
|
|
35174
|
+
|
|
35175
|
+
// src/git/git-runtime.ts
|
|
35176
|
+
var activeGitChildProcesses = /* @__PURE__ */ new Set();
|
|
35177
|
+
function abortActiveGitChildProcesses() {
|
|
35178
|
+
for (const child of activeGitChildProcesses) {
|
|
35179
|
+
try {
|
|
35180
|
+
child.kill("SIGTERM");
|
|
35181
|
+
} catch {
|
|
35182
|
+
}
|
|
34943
35183
|
}
|
|
34944
35184
|
}
|
|
34945
35185
|
var GitOperationAbortedError = class extends Error {
|
|
@@ -35387,104 +35627,136 @@ async function maybeUploadE2eeSessionChangeSummariesAfterAgentSuccess(params) {
|
|
|
35387
35627
|
}
|
|
35388
35628
|
}
|
|
35389
35629
|
|
|
35390
|
-
// src/agents/
|
|
35391
|
-
function
|
|
35392
|
-
const
|
|
35393
|
-
|
|
35394
|
-
const
|
|
35395
|
-
const
|
|
35396
|
-
|
|
35397
|
-
|
|
35630
|
+
// src/agents/planning/submit-planning-todos-for-turn.ts
|
|
35631
|
+
async function submitPlanningTodosForTurn(params) {
|
|
35632
|
+
const token = params.getCloudAccessToken();
|
|
35633
|
+
if (!token.trim()) return { ok: false, error: "Missing cloud access token" };
|
|
35634
|
+
const base = params.cloudApiBaseUrl.replace(/\/$/, "");
|
|
35635
|
+
const url2 = `${base}/internal/sessions/todos/submit`;
|
|
35636
|
+
const res = await fetch(url2, {
|
|
35637
|
+
method: "POST",
|
|
35638
|
+
headers: {
|
|
35639
|
+
Authorization: `Bearer ${token}`,
|
|
35640
|
+
"Content-Type": "application/json"
|
|
35641
|
+
},
|
|
35642
|
+
body: JSON.stringify({
|
|
35643
|
+
sessionId: params.sessionId,
|
|
35644
|
+
turnId: params.turnId,
|
|
35645
|
+
items: params.items
|
|
35646
|
+
})
|
|
35647
|
+
});
|
|
35648
|
+
if (!res.ok) {
|
|
35649
|
+
const body = await res.json().catch(() => null);
|
|
35650
|
+
return { ok: false, error: body?.error ?? `Planning todo submit failed (${res.status})` };
|
|
35651
|
+
}
|
|
35652
|
+
return { ok: true };
|
|
35398
35653
|
}
|
|
35399
35654
|
|
|
35400
|
-
// src/agents/
|
|
35401
|
-
function
|
|
35402
|
-
|
|
35403
|
-
const
|
|
35404
|
-
|
|
35405
|
-
|
|
35406
|
-
|
|
35407
|
-
|
|
35408
|
-
if (!m.startsWith("image/") || buf.length < 4) return;
|
|
35409
|
-
const b0 = buf[0];
|
|
35410
|
-
const b1 = buf[1];
|
|
35411
|
-
const b2 = buf[2];
|
|
35412
|
-
const b3 = buf[3];
|
|
35413
|
-
let looksOk = false;
|
|
35414
|
-
if (m.includes("png") && b0 === 137 && b1 === 80 && b2 === 78 && b3 === 71) looksOk = true;
|
|
35415
|
-
else if ((m.includes("jpeg") || m.includes("jpg")) && b0 === 255 && b1 === 216 && b2 === 255) looksOk = true;
|
|
35416
|
-
else if (m.includes("gif") && b0 === 71 && b1 === 73 && b2 === 70) looksOk = true;
|
|
35417
|
-
else if (m.includes("webp") && buf.length >= 12 && buf.subarray(0, 4).toString("ascii") === "RIFF" && buf.subarray(8, 12).toString("ascii") === "WEBP")
|
|
35418
|
-
looksOk = true;
|
|
35419
|
-
else if (!/(png|jpe?g|gif|webp)/i.test(m)) looksOk = true;
|
|
35420
|
-
if (!looksOk) {
|
|
35421
|
-
logDebug(
|
|
35422
|
-
`[Agent] Attachment ${idShort} (${mimeType}): decoded bytes do not match common image signatures \u2014 wrong E2EE key, corrupt blob, or metadata mismatch. First 12 bytes (hex): ${buf.subarray(0, Math.min(12, buf.length)).toString("hex")}`
|
|
35423
|
-
);
|
|
35655
|
+
// src/agents/planning/maybe-submit-planning-todos-after-agent-success.ts
|
|
35656
|
+
async function maybeSubmitPlanningTodosAfterAgentSuccess(params) {
|
|
35657
|
+
const { sessionId, runId, resultSuccess, output, cloudApiBaseUrl, getCloudAccessToken, log: log2 } = params;
|
|
35658
|
+
const buffered = runId ? getPlanningSessionTurnOutput(runId) : "";
|
|
35659
|
+
const outputFromResult = typeof output === "string" ? output : "";
|
|
35660
|
+
const outputStr = buffered.trim() !== "" ? buffered : outputFromResult;
|
|
35661
|
+
if (!sessionId || !runId || !resultSuccess || outputStr.trim() === "") {
|
|
35662
|
+
return { submitted: false, suppressOutput: false };
|
|
35424
35663
|
}
|
|
35425
|
-
|
|
35426
|
-
|
|
35427
|
-
const { attachments, sessionId, cloudApiBaseUrl, getCloudAccessToken, e2ee, log: log2 } = params;
|
|
35428
|
-
const token = getCloudAccessToken();
|
|
35429
|
-
if (!token) {
|
|
35430
|
-
return { ok: false, error: "Missing cloud access token; cannot download attachments." };
|
|
35664
|
+
if (!cloudApiBaseUrl || !getCloudAccessToken) {
|
|
35665
|
+
return { submitted: false, suppressOutput: false };
|
|
35431
35666
|
}
|
|
35432
|
-
const
|
|
35433
|
-
if (
|
|
35434
|
-
return {
|
|
35667
|
+
const items = parsePlanningTodoAgentJson(outputStr);
|
|
35668
|
+
if (items.length === 0) {
|
|
35669
|
+
return { submitted: false, suppressOutput: false };
|
|
35435
35670
|
}
|
|
35436
|
-
const
|
|
35437
|
-
|
|
35438
|
-
|
|
35439
|
-
|
|
35440
|
-
|
|
35441
|
-
|
|
35442
|
-
|
|
35443
|
-
|
|
35444
|
-
|
|
35445
|
-
|
|
35446
|
-
|
|
35447
|
-
|
|
35448
|
-
|
|
35449
|
-
|
|
35450
|
-
|
|
35451
|
-
|
|
35452
|
-
|
|
35453
|
-
|
|
35454
|
-
|
|
35455
|
-
|
|
35456
|
-
|
|
35457
|
-
|
|
35458
|
-
|
|
35459
|
-
|
|
35460
|
-
|
|
35461
|
-
|
|
35462
|
-
|
|
35463
|
-
|
|
35464
|
-
|
|
35465
|
-
|
|
35466
|
-
|
|
35467
|
-
|
|
35468
|
-
|
|
35469
|
-
|
|
35470
|
-
|
|
35671
|
+
const result = await submitPlanningTodosForTurn({
|
|
35672
|
+
sessionId,
|
|
35673
|
+
turnId: runId,
|
|
35674
|
+
items,
|
|
35675
|
+
cloudApiBaseUrl,
|
|
35676
|
+
getCloudAccessToken
|
|
35677
|
+
});
|
|
35678
|
+
if (!result.ok) {
|
|
35679
|
+
log2(`[Agent] Planning todo submit failed: ${result.error}`);
|
|
35680
|
+
return { submitted: false, suppressOutput: false };
|
|
35681
|
+
}
|
|
35682
|
+
if (runId) consumePlanningSessionTurnOutput(runId);
|
|
35683
|
+
log2(`[Agent] Planning session: stored ${items.length} todo(s) via internal API`);
|
|
35684
|
+
return { submitted: true, suppressOutput: true };
|
|
35685
|
+
}
|
|
35686
|
+
|
|
35687
|
+
// src/agents/acp/prompts/finalize-and-send-prompt-result.ts
|
|
35688
|
+
async function finalizeAndSendPromptResult(params) {
|
|
35689
|
+
const {
|
|
35690
|
+
result,
|
|
35691
|
+
sessionId,
|
|
35692
|
+
runId,
|
|
35693
|
+
promptId,
|
|
35694
|
+
agentType,
|
|
35695
|
+
agentCwd,
|
|
35696
|
+
isPlanningSession,
|
|
35697
|
+
followUpCatalogPromptId,
|
|
35698
|
+
sessionChangeSummaryFilePaths,
|
|
35699
|
+
cloudApiBaseUrl,
|
|
35700
|
+
getCloudAccessToken,
|
|
35701
|
+
e2ee,
|
|
35702
|
+
sendResult,
|
|
35703
|
+
sendSessionUpdate,
|
|
35704
|
+
log: log2
|
|
35705
|
+
} = params;
|
|
35706
|
+
if (sessionId && runId && sendSessionUpdate && agentCwd && result.success) {
|
|
35707
|
+
await collectTurnGitDiffFromPreTurnSnapshot({
|
|
35708
|
+
sessionId,
|
|
35709
|
+
runId,
|
|
35710
|
+
agentCwd,
|
|
35711
|
+
sendSessionUpdate,
|
|
35712
|
+
log: log2
|
|
35713
|
+
});
|
|
35714
|
+
}
|
|
35715
|
+
await maybeUploadE2eeSessionChangeSummariesAfterAgentSuccess({
|
|
35716
|
+
sessionId,
|
|
35717
|
+
runId,
|
|
35718
|
+
resultSuccess: result.success === true,
|
|
35719
|
+
output: result.output,
|
|
35720
|
+
e2ee,
|
|
35721
|
+
cloudApiBaseUrl,
|
|
35722
|
+
getCloudAccessToken,
|
|
35723
|
+
followUpCatalogPromptId,
|
|
35724
|
+
sessionChangeSummaryFilePaths,
|
|
35725
|
+
log: log2
|
|
35726
|
+
});
|
|
35727
|
+
const planningTodosSubmit = await maybeSubmitPlanningTodosAfterAgentSuccess({
|
|
35728
|
+
sessionId,
|
|
35729
|
+
runId,
|
|
35730
|
+
resultSuccess: result.success === true,
|
|
35731
|
+
output: result.output,
|
|
35732
|
+
cloudApiBaseUrl,
|
|
35733
|
+
getCloudAccessToken,
|
|
35734
|
+
log: log2
|
|
35735
|
+
});
|
|
35736
|
+
const errStr = typeof result.error === "string" ? result.error : void 0;
|
|
35737
|
+
const resultStop = typeof result.stopReason === "string" ? result.stopReason.trim() : "";
|
|
35738
|
+
const cancelledByAgent = resultStop.toLowerCase() === "cancelled" || errStr != null && isUserEndedSessionTurnErrorText(errStr);
|
|
35739
|
+
const planningFallbackOutput = !planningTodosSubmit.suppressOutput && isPlanningSession && runId ? consumePlanningSessionTurnOutput(runId) : "";
|
|
35740
|
+
sendResult({
|
|
35741
|
+
type: "prompt_result",
|
|
35742
|
+
id: promptId,
|
|
35743
|
+
...sessionId ? { sessionId } : {},
|
|
35744
|
+
...runId ? { runId } : {},
|
|
35745
|
+
...result,
|
|
35746
|
+
...planningTodosSubmit.suppressOutput ? { output: void 0 } : planningFallbackOutput.trim() !== "" ? { output: planningFallbackOutput } : {},
|
|
35747
|
+
...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
|
|
35748
|
+
...augmentPromptResultAuthFields(agentType, errStr),
|
|
35749
|
+
...!result.success && cancelledByAgent ? { stopReason: "cancelled" } : {}
|
|
35750
|
+
});
|
|
35751
|
+
if (!result.success) {
|
|
35752
|
+
if (cancelledByAgent) {
|
|
35753
|
+
log2("[Agent] Run ended after stop request (stopped by user).");
|
|
35471
35754
|
} else {
|
|
35472
|
-
|
|
35755
|
+
log2(
|
|
35756
|
+
`[Agent] Prompt did not run successfully on the agent (no successful start/completion): ${result.error ?? "Unknown error"}`
|
|
35757
|
+
);
|
|
35473
35758
|
}
|
|
35474
|
-
warnIfDecodedImageMagicUnexpected(imageBytes, mimeType, id.slice(0, 8));
|
|
35475
|
-
logDebug(
|
|
35476
|
-
`[Agent] Loaded prompt image ${id.slice(0, 8)}\u2026: ${imageBytes.length} bytes, mime=${mimeType}, ${encrypted ? "E2EE decrypted" : "plaintext from storage"}`
|
|
35477
|
-
);
|
|
35478
|
-
const dataBase64 = imageBytes.toString("base64");
|
|
35479
|
-
out.push({ mimeType, dataBase64 });
|
|
35480
35759
|
}
|
|
35481
|
-
if (out.length !== wantedCount) {
|
|
35482
|
-
return {
|
|
35483
|
-
ok: false,
|
|
35484
|
-
error: `Expected ${wantedCount} image attachment(s) but only loaded ${out.length} (check attachment ids and empty rows).`
|
|
35485
|
-
};
|
|
35486
|
-
}
|
|
35487
|
-
return { ok: true, images: out };
|
|
35488
35760
|
}
|
|
35489
35761
|
|
|
35490
35762
|
// src/agents/acp/build-forked-session-agent-prompt.ts
|
|
@@ -35675,7 +35947,213 @@ function enrichIntegrationContentPromptForAgent(params) {
|
|
|
35675
35947
|
return injectIntegrationContentAgentPromptNote(params.agentPromptText, params.sessionId);
|
|
35676
35948
|
}
|
|
35677
35949
|
|
|
35678
|
-
// src/agents/
|
|
35950
|
+
// src/agents/planning/enrich-planning-session-prompt-for-agent.ts
|
|
35951
|
+
async function enrichPlanningSessionPromptForAgent(params) {
|
|
35952
|
+
const meta = await fetchCloudSessionMeta({
|
|
35953
|
+
sessionId: params.sessionId,
|
|
35954
|
+
cloudApiBaseUrl: params.cloudApiBaseUrl,
|
|
35955
|
+
getCloudAccessToken: params.getCloudAccessToken
|
|
35956
|
+
});
|
|
35957
|
+
if (!meta.ok) return { promptText: params.promptText, isPlanningSession: false };
|
|
35958
|
+
const sessionKind = parseSessionKind(meta.data.sessionKind);
|
|
35959
|
+
if (sessionKind !== "planning") return { promptText: params.promptText, isPlanningSession: false };
|
|
35960
|
+
const todos = Array.isArray(meta.data.planningTodos) ? meta.data.planningTodos : [];
|
|
35961
|
+
if (params.isNewSession || todos.length === 0) {
|
|
35962
|
+
return {
|
|
35963
|
+
promptText: buildPlanningSessionAgentPrompt(params.promptText),
|
|
35964
|
+
isPlanningSession: true
|
|
35965
|
+
};
|
|
35966
|
+
}
|
|
35967
|
+
return {
|
|
35968
|
+
promptText: buildPlanningSessionFollowUpAgentPrompt(params.promptText, todos),
|
|
35969
|
+
isPlanningSession: true
|
|
35970
|
+
};
|
|
35971
|
+
}
|
|
35972
|
+
|
|
35973
|
+
// src/agents/acp/prompts/prepare-agent-prompt-text.ts
|
|
35974
|
+
async function prepareAgentPromptText(params) {
|
|
35975
|
+
const { promptText, sessionId, runId, isNewSession, cloudApiBaseUrl, getCloudAccessToken } = params;
|
|
35976
|
+
let agentPromptText = promptText;
|
|
35977
|
+
let isPlanningSession = false;
|
|
35978
|
+
if (sessionId && cloudApiBaseUrl && getCloudAccessToken) {
|
|
35979
|
+
agentPromptText = await enrichForkedSessionPromptForAgent({
|
|
35980
|
+
sessionId,
|
|
35981
|
+
promptText,
|
|
35982
|
+
cloudApiBaseUrl,
|
|
35983
|
+
getCloudAccessToken
|
|
35984
|
+
});
|
|
35985
|
+
const planningEnriched = await enrichPlanningSessionPromptForAgent({
|
|
35986
|
+
sessionId,
|
|
35987
|
+
promptText: agentPromptText,
|
|
35988
|
+
isNewSession,
|
|
35989
|
+
cloudApiBaseUrl,
|
|
35990
|
+
getCloudAccessToken
|
|
35991
|
+
});
|
|
35992
|
+
agentPromptText = planningEnriched.promptText;
|
|
35993
|
+
isPlanningSession = planningEnriched.isPlanningSession;
|
|
35994
|
+
}
|
|
35995
|
+
if (isPlanningSession && runId) {
|
|
35996
|
+
registerPlanningSessionTurn(runId);
|
|
35997
|
+
}
|
|
35998
|
+
if (sessionId) {
|
|
35999
|
+
agentPromptText = enrichIntegrationContentPromptForAgent({
|
|
36000
|
+
sessionId,
|
|
36001
|
+
originalPromptText: promptText,
|
|
36002
|
+
agentPromptText
|
|
36003
|
+
});
|
|
36004
|
+
}
|
|
36005
|
+
return { agentPromptText, isPlanningSession };
|
|
36006
|
+
}
|
|
36007
|
+
|
|
36008
|
+
// src/agents/acp/fetch-session-attachments.ts
|
|
36009
|
+
function metaSaysEncrypted(meta) {
|
|
36010
|
+
if (!meta) return false;
|
|
36011
|
+
const e = meta.encrypted;
|
|
36012
|
+
return e === true || e === "true" || e === 1;
|
|
36013
|
+
}
|
|
36014
|
+
function warnIfDecodedImageMagicUnexpected(buf, mimeType, idShort) {
|
|
36015
|
+
const m = mimeType.toLowerCase();
|
|
36016
|
+
if (!m.startsWith("image/") || buf.length < 4) return;
|
|
36017
|
+
const b0 = buf[0];
|
|
36018
|
+
const b1 = buf[1];
|
|
36019
|
+
const b2 = buf[2];
|
|
36020
|
+
const b3 = buf[3];
|
|
36021
|
+
let looksOk = false;
|
|
36022
|
+
if (m.includes("png") && b0 === 137 && b1 === 80 && b2 === 78 && b3 === 71) looksOk = true;
|
|
36023
|
+
else if ((m.includes("jpeg") || m.includes("jpg")) && b0 === 255 && b1 === 216 && b2 === 255) looksOk = true;
|
|
36024
|
+
else if (m.includes("gif") && b0 === 71 && b1 === 73 && b2 === 70) looksOk = true;
|
|
36025
|
+
else if (m.includes("webp") && buf.length >= 12 && buf.subarray(0, 4).toString("ascii") === "RIFF" && buf.subarray(8, 12).toString("ascii") === "WEBP")
|
|
36026
|
+
looksOk = true;
|
|
36027
|
+
else if (!/(png|jpe?g|gif|webp)/i.test(m)) looksOk = true;
|
|
36028
|
+
if (!looksOk) {
|
|
36029
|
+
logDebug(
|
|
36030
|
+
`[Agent] Attachment ${idShort} (${mimeType}): decoded bytes do not match common image signatures \u2014 wrong E2EE key, corrupt blob, or metadata mismatch. First 12 bytes (hex): ${buf.subarray(0, Math.min(12, buf.length)).toString("hex")}`
|
|
36031
|
+
);
|
|
36032
|
+
}
|
|
36033
|
+
}
|
|
36034
|
+
async function fetchSessionAttachmentPayloadsForAgent(params) {
|
|
36035
|
+
const { attachments, sessionId, cloudApiBaseUrl, getCloudAccessToken, e2ee, log: log2 } = params;
|
|
36036
|
+
const token = getCloudAccessToken();
|
|
36037
|
+
if (!token) {
|
|
36038
|
+
return { ok: false, error: "Missing cloud access token; cannot download attachments." };
|
|
36039
|
+
}
|
|
36040
|
+
const wantedCount = attachments.filter((a) => typeof a.attachmentId === "string" && a.attachmentId.trim() !== "").length;
|
|
36041
|
+
if (wantedCount === 0) {
|
|
36042
|
+
return { ok: false, error: "No valid attachment ids in prompt." };
|
|
36043
|
+
}
|
|
36044
|
+
const base = cloudApiBaseUrl.replace(/\/+$/, "");
|
|
36045
|
+
const out = [];
|
|
36046
|
+
for (const a of attachments) {
|
|
36047
|
+
const id = typeof a.attachmentId === "string" ? a.attachmentId.trim() : "";
|
|
36048
|
+
if (!id) continue;
|
|
36049
|
+
const metaUrl = `${base}/internal/sessions/${encodeURIComponent(sessionId)}/attachments/${encodeURIComponent(id)}/meta`;
|
|
36050
|
+
const blobUrl = `${base}/internal/sessions/${encodeURIComponent(sessionId)}/attachments/${encodeURIComponent(id)}/blob`;
|
|
36051
|
+
const metaRes = await fetch(metaUrl, { headers: { Authorization: `Bearer ${token}` } });
|
|
36052
|
+
if (!metaRes.ok) {
|
|
36053
|
+
const t = await metaRes.text().catch(() => "");
|
|
36054
|
+
log2(`[Agent] Attachment meta fetch failed ${metaRes.status}: ${t.slice(0, 200)}`);
|
|
36055
|
+
return { ok: false, error: `Could not load attachment (${id.slice(0, 8)}\u2026): ${metaRes.status}` };
|
|
36056
|
+
}
|
|
36057
|
+
const meta = await metaRes.json().catch(() => null);
|
|
36058
|
+
const mimeType = typeof meta?.mimeType === "string" && meta.mimeType.trim() ? meta.mimeType.trim() : a.mimeType;
|
|
36059
|
+
const blobRes = await fetch(blobUrl, { headers: { Authorization: `Bearer ${token}` } });
|
|
36060
|
+
if (!blobRes.ok) {
|
|
36061
|
+
const t = await blobRes.text().catch(() => "");
|
|
36062
|
+
log2(`[Agent] Attachment blob fetch failed ${blobRes.status}: ${t.slice(0, 200)}`);
|
|
36063
|
+
return { ok: false, error: `Could not load attachment data (${id.slice(0, 8)}\u2026): ${blobRes.status}` };
|
|
36064
|
+
}
|
|
36065
|
+
const buf = Buffer.from(await blobRes.arrayBuffer());
|
|
36066
|
+
let imageBytes;
|
|
36067
|
+
const encrypted = metaSaysEncrypted(meta);
|
|
36068
|
+
if (encrypted) {
|
|
36069
|
+
if (!e2ee) {
|
|
36070
|
+
return { ok: false, error: "Encrypted attachments require E2EE keys on this bridge." };
|
|
36071
|
+
}
|
|
36072
|
+
const k = typeof meta?.k === "string" ? meta.k : "";
|
|
36073
|
+
const n = typeof meta?.n === "string" ? meta.n : "";
|
|
36074
|
+
if (!k || !n) {
|
|
36075
|
+
return { ok: false, error: "Invalid encrypted attachment metadata (missing key id or nonce)." };
|
|
36076
|
+
}
|
|
36077
|
+
const c = base64UrlEncode(buf);
|
|
36078
|
+
imageBytes = e2ee.decryptEnvelopeToBuffer({ k, n, c });
|
|
36079
|
+
} else {
|
|
36080
|
+
imageBytes = buf;
|
|
36081
|
+
}
|
|
36082
|
+
warnIfDecodedImageMagicUnexpected(imageBytes, mimeType, id.slice(0, 8));
|
|
36083
|
+
logDebug(
|
|
36084
|
+
`[Agent] Loaded prompt image ${id.slice(0, 8)}\u2026: ${imageBytes.length} bytes, mime=${mimeType}, ${encrypted ? "E2EE decrypted" : "plaintext from storage"}`
|
|
36085
|
+
);
|
|
36086
|
+
const dataBase64 = imageBytes.toString("base64");
|
|
36087
|
+
out.push({ mimeType, dataBase64 });
|
|
36088
|
+
}
|
|
36089
|
+
if (out.length !== wantedCount) {
|
|
36090
|
+
return {
|
|
36091
|
+
ok: false,
|
|
36092
|
+
error: `Expected ${wantedCount} image attachment(s) but only loaded ${out.length} (check attachment ids and empty rows).`
|
|
36093
|
+
};
|
|
36094
|
+
}
|
|
36095
|
+
return { ok: true, images: out };
|
|
36096
|
+
}
|
|
36097
|
+
|
|
36098
|
+
// src/agents/acp/prompts/resolve-send-prompt-images.ts
|
|
36099
|
+
async function resolveSendPromptImages(params) {
|
|
36100
|
+
const {
|
|
36101
|
+
attachments,
|
|
36102
|
+
sessionId,
|
|
36103
|
+
promptId,
|
|
36104
|
+
runId,
|
|
36105
|
+
agentType,
|
|
36106
|
+
followUpCatalogPromptId,
|
|
36107
|
+
cloudApiBaseUrl,
|
|
36108
|
+
getCloudAccessToken,
|
|
36109
|
+
e2ee,
|
|
36110
|
+
log: log2
|
|
36111
|
+
} = params;
|
|
36112
|
+
if (!attachments || attachments.length === 0) {
|
|
36113
|
+
return { ok: true, sendOpts: {} };
|
|
36114
|
+
}
|
|
36115
|
+
if (!sessionId || !cloudApiBaseUrl || !getCloudAccessToken) {
|
|
36116
|
+
return {
|
|
36117
|
+
ok: false,
|
|
36118
|
+
errorResult: {
|
|
36119
|
+
type: "prompt_result",
|
|
36120
|
+
id: promptId,
|
|
36121
|
+
...sessionId ? { sessionId } : {},
|
|
36122
|
+
...runId ? { runId } : {},
|
|
36123
|
+
success: false,
|
|
36124
|
+
error: "Prompt includes images but the bridge is not configured with a cloud API URL and token to fetch them.",
|
|
36125
|
+
...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
|
|
36126
|
+
...augmentPromptResultAuthFields(agentType, "missing cloud for images download")
|
|
36127
|
+
}
|
|
36128
|
+
};
|
|
36129
|
+
}
|
|
36130
|
+
const resolved = await fetchSessionAttachmentPayloadsForAgent({
|
|
36131
|
+
attachments,
|
|
36132
|
+
sessionId,
|
|
36133
|
+
cloudApiBaseUrl,
|
|
36134
|
+
getCloudAccessToken,
|
|
36135
|
+
e2ee,
|
|
36136
|
+
log: log2
|
|
36137
|
+
});
|
|
36138
|
+
if (!resolved.ok) {
|
|
36139
|
+
return {
|
|
36140
|
+
ok: false,
|
|
36141
|
+
errorResult: {
|
|
36142
|
+
type: "prompt_result",
|
|
36143
|
+
id: promptId,
|
|
36144
|
+
...sessionId ? { sessionId } : {},
|
|
36145
|
+
...runId ? { runId } : {},
|
|
36146
|
+
success: false,
|
|
36147
|
+
error: resolved.error,
|
|
36148
|
+
...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
|
|
36149
|
+
...augmentPromptResultAuthFields(agentType, resolved.error)
|
|
36150
|
+
}
|
|
36151
|
+
};
|
|
36152
|
+
}
|
|
36153
|
+
return { ok: true, sendOpts: { images: resolved.images } };
|
|
36154
|
+
}
|
|
36155
|
+
|
|
36156
|
+
// src/agents/acp/prompts/send-prompt-to-agent.ts
|
|
35679
36157
|
async function sendPromptToAgent(options) {
|
|
35680
36158
|
const {
|
|
35681
36159
|
handle,
|
|
@@ -35693,107 +36171,54 @@ async function sendPromptToAgent(options) {
|
|
|
35693
36171
|
cloudApiBaseUrl,
|
|
35694
36172
|
getCloudAccessToken,
|
|
35695
36173
|
e2ee,
|
|
35696
|
-
attachments
|
|
36174
|
+
attachments,
|
|
36175
|
+
isNewSession = false
|
|
35697
36176
|
} = options;
|
|
36177
|
+
let isPlanningSession = false;
|
|
35698
36178
|
try {
|
|
35699
|
-
|
|
35700
|
-
|
|
35701
|
-
agentPromptText = await enrichForkedSessionPromptForAgent({
|
|
35702
|
-
sessionId,
|
|
35703
|
-
promptText,
|
|
35704
|
-
cloudApiBaseUrl,
|
|
35705
|
-
getCloudAccessToken
|
|
35706
|
-
});
|
|
35707
|
-
}
|
|
35708
|
-
if (sessionId) {
|
|
35709
|
-
agentPromptText = enrichIntegrationContentPromptForAgent({
|
|
35710
|
-
sessionId,
|
|
35711
|
-
originalPromptText: promptText,
|
|
35712
|
-
agentPromptText
|
|
35713
|
-
});
|
|
35714
|
-
}
|
|
35715
|
-
let sendOpts = {};
|
|
35716
|
-
if (attachments && attachments.length > 0) {
|
|
35717
|
-
if (!sessionId || !cloudApiBaseUrl || !getCloudAccessToken) {
|
|
35718
|
-
sendResult({
|
|
35719
|
-
type: "prompt_result",
|
|
35720
|
-
id: promptId,
|
|
35721
|
-
...sessionId ? { sessionId } : {},
|
|
35722
|
-
...runId ? { runId } : {},
|
|
35723
|
-
success: false,
|
|
35724
|
-
error: "Prompt includes images but the bridge is not configured with a cloud API URL and token to fetch them.",
|
|
35725
|
-
...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
|
|
35726
|
-
...augmentPromptResultAuthFields(agentType, "missing cloud for images download")
|
|
35727
|
-
});
|
|
35728
|
-
return;
|
|
35729
|
-
}
|
|
35730
|
-
const resolved = await fetchSessionAttachmentPayloadsForAgent({
|
|
35731
|
-
attachments,
|
|
35732
|
-
sessionId,
|
|
35733
|
-
cloudApiBaseUrl,
|
|
35734
|
-
getCloudAccessToken,
|
|
35735
|
-
e2ee,
|
|
35736
|
-
log: log2
|
|
35737
|
-
});
|
|
35738
|
-
if (!resolved.ok) {
|
|
35739
|
-
sendResult({
|
|
35740
|
-
type: "prompt_result",
|
|
35741
|
-
id: promptId,
|
|
35742
|
-
...sessionId ? { sessionId } : {},
|
|
35743
|
-
...runId ? { runId } : {},
|
|
35744
|
-
success: false,
|
|
35745
|
-
error: resolved.error,
|
|
35746
|
-
...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
|
|
35747
|
-
...augmentPromptResultAuthFields(agentType, resolved.error)
|
|
35748
|
-
});
|
|
35749
|
-
return;
|
|
35750
|
-
}
|
|
35751
|
-
sendOpts = { images: resolved.images };
|
|
35752
|
-
}
|
|
35753
|
-
const result = await handle.sendPrompt(agentPromptText, sendOpts);
|
|
35754
|
-
if (sessionId && runId && sendSessionUpdate && agentCwd && result.success) {
|
|
35755
|
-
await collectTurnGitDiffFromPreTurnSnapshot({
|
|
35756
|
-
sessionId,
|
|
35757
|
-
runId,
|
|
35758
|
-
agentCwd,
|
|
35759
|
-
sendSessionUpdate,
|
|
35760
|
-
log: log2
|
|
35761
|
-
});
|
|
35762
|
-
}
|
|
35763
|
-
await maybeUploadE2eeSessionChangeSummariesAfterAgentSuccess({
|
|
36179
|
+
const prepared = await prepareAgentPromptText({
|
|
36180
|
+
promptText,
|
|
35764
36181
|
sessionId,
|
|
35765
36182
|
runId,
|
|
35766
|
-
|
|
35767
|
-
|
|
35768
|
-
|
|
36183
|
+
isNewSession,
|
|
36184
|
+
cloudApiBaseUrl,
|
|
36185
|
+
getCloudAccessToken
|
|
36186
|
+
});
|
|
36187
|
+
isPlanningSession = prepared.isPlanningSession;
|
|
36188
|
+
const imagesResolved = await resolveSendPromptImages({
|
|
36189
|
+
attachments,
|
|
36190
|
+
sessionId,
|
|
36191
|
+
promptId,
|
|
36192
|
+
runId,
|
|
36193
|
+
agentType,
|
|
36194
|
+
followUpCatalogPromptId,
|
|
35769
36195
|
cloudApiBaseUrl,
|
|
35770
36196
|
getCloudAccessToken,
|
|
36197
|
+
e2ee,
|
|
36198
|
+
log: log2
|
|
36199
|
+
});
|
|
36200
|
+
if (!imagesResolved.ok) {
|
|
36201
|
+
sendResult(imagesResolved.errorResult);
|
|
36202
|
+
return;
|
|
36203
|
+
}
|
|
36204
|
+
const result = await handle.sendPrompt(prepared.agentPromptText, imagesResolved.sendOpts);
|
|
36205
|
+
await finalizeAndSendPromptResult({
|
|
36206
|
+
result,
|
|
36207
|
+
sessionId,
|
|
36208
|
+
runId,
|
|
36209
|
+
promptId,
|
|
36210
|
+
agentType,
|
|
36211
|
+
agentCwd,
|
|
36212
|
+
isPlanningSession,
|
|
35771
36213
|
followUpCatalogPromptId,
|
|
35772
36214
|
sessionChangeSummaryFilePaths,
|
|
36215
|
+
cloudApiBaseUrl,
|
|
36216
|
+
getCloudAccessToken,
|
|
36217
|
+
e2ee,
|
|
36218
|
+
sendResult,
|
|
36219
|
+
sendSessionUpdate,
|
|
35773
36220
|
log: log2
|
|
35774
36221
|
});
|
|
35775
|
-
const errStr = typeof result.error === "string" ? result.error : void 0;
|
|
35776
|
-
const resultStop = typeof result.stopReason === "string" ? result.stopReason.trim() : "";
|
|
35777
|
-
const cancelledByAgent = resultStop.toLowerCase() === "cancelled" || errStr != null && isUserEndedSessionTurnErrorText(errStr);
|
|
35778
|
-
sendResult({
|
|
35779
|
-
type: "prompt_result",
|
|
35780
|
-
id: promptId,
|
|
35781
|
-
...sessionId ? { sessionId } : {},
|
|
35782
|
-
...runId ? { runId } : {},
|
|
35783
|
-
...result,
|
|
35784
|
-
...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
|
|
35785
|
-
...augmentPromptResultAuthFields(agentType, errStr),
|
|
35786
|
-
...!result.success && cancelledByAgent ? { stopReason: "cancelled" } : {}
|
|
35787
|
-
});
|
|
35788
|
-
if (!result.success) {
|
|
35789
|
-
if (cancelledByAgent) {
|
|
35790
|
-
log2("[Agent] Run ended after stop request (stopped by user).");
|
|
35791
|
-
} else {
|
|
35792
|
-
log2(
|
|
35793
|
-
`[Agent] Prompt did not run successfully on the agent (no successful start/completion): ${result.error ?? "Unknown error"}`
|
|
35794
|
-
);
|
|
35795
|
-
}
|
|
35796
|
-
}
|
|
35797
36222
|
} catch (err) {
|
|
35798
36223
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
35799
36224
|
log2(`[Agent] Send failed: ${errMsg}`);
|
|
@@ -35807,6 +36232,8 @@ async function sendPromptToAgent(options) {
|
|
|
35807
36232
|
...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
|
|
35808
36233
|
...augmentPromptResultAuthFields(agentType, errMsg)
|
|
35809
36234
|
});
|
|
36235
|
+
} finally {
|
|
36236
|
+
if (runId && isPlanningSession) clearPlanningSessionTurn(runId);
|
|
35810
36237
|
}
|
|
35811
36238
|
}
|
|
35812
36239
|
|
|
@@ -35820,15 +36247,36 @@ function getAcpSessionAgentState(ctx, acpSessionAgentKey) {
|
|
|
35820
36247
|
return state;
|
|
35821
36248
|
}
|
|
35822
36249
|
|
|
35823
|
-
// src/agents/acp/manager/handle-prompt.ts
|
|
35824
|
-
function
|
|
36250
|
+
// src/agents/acp/manager/handle-pending-prompt-cancel.ts
|
|
36251
|
+
async function handlePendingPromptCancel(params) {
|
|
36252
|
+
const { ctx, activeRunId, promptId, sessionId, handle, sendResult } = params;
|
|
36253
|
+
if (!ctx.pendingCancelRunIds.has(activeRunId)) {
|
|
36254
|
+
return false;
|
|
36255
|
+
}
|
|
36256
|
+
ctx.pendingCancelRunIds.delete(activeRunId);
|
|
36257
|
+
try {
|
|
36258
|
+
await handle.cancel?.();
|
|
36259
|
+
} catch {
|
|
36260
|
+
}
|
|
36261
|
+
sendResult({
|
|
36262
|
+
type: "prompt_result",
|
|
36263
|
+
id: promptId,
|
|
36264
|
+
...sessionId ? { sessionId } : {},
|
|
36265
|
+
runId: activeRunId,
|
|
36266
|
+
success: false,
|
|
36267
|
+
error: "Stopped by user",
|
|
36268
|
+
stopReason: "cancelled"
|
|
36269
|
+
});
|
|
36270
|
+
return true;
|
|
36271
|
+
}
|
|
36272
|
+
|
|
36273
|
+
// src/agents/acp/manager/run-acp-prompt.ts
|
|
36274
|
+
async function runAcpPrompt(ctx, runCtx, opts) {
|
|
35825
36275
|
const {
|
|
35826
36276
|
promptText,
|
|
35827
36277
|
promptId,
|
|
35828
36278
|
sessionId,
|
|
35829
|
-
runId,
|
|
35830
36279
|
mode,
|
|
35831
|
-
agentType,
|
|
35832
36280
|
agentConfig,
|
|
35833
36281
|
sessionParentPath,
|
|
35834
36282
|
sendResult,
|
|
@@ -35838,109 +36286,99 @@ function handlePrompt(ctx, opts) {
|
|
|
35838
36286
|
cloudApiBaseUrl,
|
|
35839
36287
|
getCloudAccessToken,
|
|
35840
36288
|
e2ee,
|
|
35841
|
-
attachments
|
|
36289
|
+
attachments,
|
|
36290
|
+
isNewSession
|
|
35842
36291
|
} = opts;
|
|
35843
|
-
const
|
|
35844
|
-
|
|
35845
|
-
|
|
35846
|
-
|
|
35847
|
-
|
|
35848
|
-
|
|
35849
|
-
|
|
35850
|
-
|
|
36292
|
+
const { activeRunId, activeAcpAgentKey, activeAcpSessionAgentKey, preferredForPrompt } = runCtx;
|
|
36293
|
+
const acpAgentState = getAcpSessionAgentState(ctx, activeAcpSessionAgentKey);
|
|
36294
|
+
const handle = await ensureAcpClient({
|
|
36295
|
+
state: acpAgentState,
|
|
36296
|
+
acpAgentKey: activeAcpAgentKey,
|
|
36297
|
+
preferredAgentType: preferredForPrompt,
|
|
36298
|
+
mode,
|
|
36299
|
+
agentConfig: agentConfig ?? null,
|
|
36300
|
+
sessionParentPath,
|
|
36301
|
+
resolveRouting: () => ctx.promptRouting.resolveRouting(activeAcpSessionAgentKey),
|
|
36302
|
+
cloudSessionId: sessionId,
|
|
36303
|
+
bridgeAccessPort: ctx.getBridgeAccessPort(),
|
|
36304
|
+
sendSessionUpdate,
|
|
36305
|
+
sendRequest: sendSessionUpdate,
|
|
36306
|
+
log: ctx.log,
|
|
36307
|
+
reportAgentCapabilities: ctx.reportAgentCapabilities
|
|
36308
|
+
});
|
|
36309
|
+
if (!handle) {
|
|
36310
|
+
const errMsg = acpAgentState.lastAcpStartError || "No agent configured. Register local agents on this bridge in the app.";
|
|
36311
|
+
const evaluated = Boolean(preferredForPrompt && errMsg.trim());
|
|
36312
|
+
const suggestsAuth = evaluated ? localAgentErrorSuggestsAuth(preferredForPrompt, errMsg) : false;
|
|
36313
|
+
const auth = suggestsAuth && preferredForPrompt ? { agentAuthRequired: true, agentType: preferredForPrompt } : {};
|
|
35851
36314
|
sendResult({
|
|
35852
36315
|
type: "prompt_result",
|
|
35853
36316
|
id: promptId,
|
|
35854
36317
|
...sessionId ? { sessionId } : {},
|
|
35855
36318
|
runId: activeRunId,
|
|
35856
36319
|
success: false,
|
|
35857
|
-
error:
|
|
36320
|
+
error: errMsg,
|
|
36321
|
+
...auth
|
|
35858
36322
|
});
|
|
35859
36323
|
return;
|
|
35860
36324
|
}
|
|
35861
|
-
|
|
35862
|
-
|
|
35863
|
-
|
|
35864
|
-
|
|
35865
|
-
|
|
35866
|
-
|
|
35867
|
-
|
|
35868
|
-
|
|
35869
|
-
|
|
35870
|
-
|
|
35871
|
-
|
|
35872
|
-
|
|
35873
|
-
|
|
35874
|
-
|
|
35875
|
-
|
|
35876
|
-
|
|
35877
|
-
|
|
36325
|
+
if (!ctx.promptRouting.isRegisteredRun(activeRunId)) {
|
|
36326
|
+
return;
|
|
36327
|
+
}
|
|
36328
|
+
const cancelled = await handlePendingPromptCancel({
|
|
36329
|
+
ctx,
|
|
36330
|
+
activeRunId,
|
|
36331
|
+
promptId,
|
|
36332
|
+
sessionId,
|
|
36333
|
+
handle,
|
|
36334
|
+
sendResult
|
|
36335
|
+
});
|
|
36336
|
+
if (cancelled) return;
|
|
36337
|
+
ctx.promptRouting.setStreamingRunId(activeAcpSessionAgentKey, activeRunId);
|
|
36338
|
+
try {
|
|
36339
|
+
await sendPromptToAgent({
|
|
36340
|
+
handle,
|
|
36341
|
+
promptText,
|
|
36342
|
+
promptId,
|
|
36343
|
+
sessionId,
|
|
36344
|
+
runId: activeRunId,
|
|
36345
|
+
agentType: preferredForPrompt,
|
|
36346
|
+
agentCwd: resolveSessionParentPathForAgentProcess(sessionParentPath),
|
|
36347
|
+
sendResult,
|
|
35878
36348
|
sendSessionUpdate,
|
|
35879
|
-
sendRequest: sendSessionUpdate,
|
|
35880
36349
|
log: ctx.log,
|
|
35881
|
-
|
|
36350
|
+
followUpCatalogPromptId,
|
|
36351
|
+
sessionChangeSummaryFilePaths,
|
|
36352
|
+
cloudApiBaseUrl,
|
|
36353
|
+
getCloudAccessToken,
|
|
36354
|
+
e2ee,
|
|
36355
|
+
attachments,
|
|
36356
|
+
isNewSession
|
|
35882
36357
|
});
|
|
35883
|
-
|
|
35884
|
-
|
|
35885
|
-
|
|
35886
|
-
|
|
35887
|
-
|
|
35888
|
-
|
|
35889
|
-
|
|
35890
|
-
|
|
35891
|
-
|
|
35892
|
-
|
|
35893
|
-
|
|
35894
|
-
error: errMsg,
|
|
35895
|
-
...auth
|
|
35896
|
-
});
|
|
35897
|
-
return;
|
|
35898
|
-
}
|
|
35899
|
-
if (!ctx.promptRouting.isRegisteredRun(activeRunId)) {
|
|
35900
|
-
return;
|
|
35901
|
-
}
|
|
35902
|
-
if (ctx.pendingCancelRunIds.has(activeRunId)) {
|
|
35903
|
-
ctx.pendingCancelRunIds.delete(activeRunId);
|
|
35904
|
-
try {
|
|
35905
|
-
await handle.cancel?.();
|
|
35906
|
-
} catch {
|
|
35907
|
-
}
|
|
36358
|
+
} finally {
|
|
36359
|
+
ctx.promptRouting.clearStreamingRunId(activeAcpSessionAgentKey, activeRunId);
|
|
36360
|
+
}
|
|
36361
|
+
}
|
|
36362
|
+
|
|
36363
|
+
// src/agents/acp/manager/handle-prompt.ts
|
|
36364
|
+
function handlePrompt(ctx, opts) {
|
|
36365
|
+
const { promptId, sessionId, runId, mode, agentType, agentConfig, sendResult } = opts;
|
|
36366
|
+
const runCtx = resolvePromptRunContext(ctx, { runId, mode, agentType, agentConfig, sessionId });
|
|
36367
|
+
if (!runCtx) {
|
|
36368
|
+
if (runId) {
|
|
35908
36369
|
sendResult({
|
|
35909
36370
|
type: "prompt_result",
|
|
35910
36371
|
id: promptId,
|
|
35911
36372
|
...sessionId ? { sessionId } : {},
|
|
35912
|
-
runId
|
|
36373
|
+
runId,
|
|
35913
36374
|
success: false,
|
|
35914
|
-
error: "
|
|
35915
|
-
stopReason: "cancelled"
|
|
35916
|
-
});
|
|
35917
|
-
return;
|
|
35918
|
-
}
|
|
35919
|
-
ctx.promptRouting.setStreamingRunId(activeAcpSessionAgentKey, activeRunId);
|
|
35920
|
-
try {
|
|
35921
|
-
await sendPromptToAgent({
|
|
35922
|
-
handle,
|
|
35923
|
-
promptText,
|
|
35924
|
-
promptId,
|
|
35925
|
-
sessionId,
|
|
35926
|
-
runId: activeRunId,
|
|
35927
|
-
agentType: preferredForPrompt,
|
|
35928
|
-
agentCwd: resolveSessionParentPathForAgentProcess(sessionParentPath),
|
|
35929
|
-
sendResult,
|
|
35930
|
-
sendSessionUpdate,
|
|
35931
|
-
log: ctx.log,
|
|
35932
|
-
followUpCatalogPromptId,
|
|
35933
|
-
sessionChangeSummaryFilePaths,
|
|
35934
|
-
cloudApiBaseUrl,
|
|
35935
|
-
getCloudAccessToken,
|
|
35936
|
-
e2ee,
|
|
35937
|
-
attachments
|
|
36375
|
+
error: "No agent type: ensure the app sends agentType on prompts or agent_config for this bridge."
|
|
35938
36376
|
});
|
|
35939
|
-
} finally {
|
|
35940
|
-
ctx.promptRouting.clearStreamingRunId(activeAcpSessionAgentKey, activeRunId);
|
|
35941
36377
|
}
|
|
36378
|
+
return;
|
|
35942
36379
|
}
|
|
35943
|
-
|
|
36380
|
+
const { activeRunId } = runCtx;
|
|
36381
|
+
void runAcpPrompt(ctx, runCtx, opts).finally(() => {
|
|
35944
36382
|
ctx.promptRouting.unregisterRun(activeRunId);
|
|
35945
36383
|
ctx.runDispatch.delete(activeRunId);
|
|
35946
36384
|
ctx.pendingCancelRunIds.delete(activeRunId);
|
|
@@ -45406,7 +45844,8 @@ async function runPreambleAndPrompt(params) {
|
|
|
45406
45844
|
cloudApiBaseUrl: deps.cloudApiBaseUrl,
|
|
45407
45845
|
getCloudAccessToken: deps.getCloudAccessToken,
|
|
45408
45846
|
e2ee: deps.e2ee,
|
|
45409
|
-
...attachments.length > 0 ? { attachments } : {}
|
|
45847
|
+
...attachments.length > 0 ? { attachments } : {},
|
|
45848
|
+
isNewSession: msg.isNewSession === true
|
|
45410
45849
|
});
|
|
45411
45850
|
}
|
|
45412
45851
|
|