@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/index.js
CHANGED
|
@@ -23584,6 +23584,81 @@ function isUserEndedSessionTurnErrorText(errorText) {
|
|
|
23584
23584
|
// ../types/src/session-kind.ts
|
|
23585
23585
|
var SESSION_KINDS = ["regular", "planning", "planned"];
|
|
23586
23586
|
var SESSION_KIND_SET = new Set(SESSION_KINDS);
|
|
23587
|
+
function parseSessionKind(raw) {
|
|
23588
|
+
if (raw === "todo") return "planned";
|
|
23589
|
+
if (typeof raw === "string" && SESSION_KIND_SET.has(raw)) return raw;
|
|
23590
|
+
return "regular";
|
|
23591
|
+
}
|
|
23592
|
+
|
|
23593
|
+
// ../types/src/planning-todo.ts
|
|
23594
|
+
function planningTodoTitle(item) {
|
|
23595
|
+
return item.content.title;
|
|
23596
|
+
}
|
|
23597
|
+
|
|
23598
|
+
// ../types/src/parse-planning-todo-agent-json.ts
|
|
23599
|
+
function parsePlanningTodoAgentJson(raw) {
|
|
23600
|
+
if (raw == null || raw.trim() === "") return [];
|
|
23601
|
+
let text = raw.trim();
|
|
23602
|
+
const fence = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
23603
|
+
if (fence?.[1]) text = fence[1].trim();
|
|
23604
|
+
let parsed;
|
|
23605
|
+
try {
|
|
23606
|
+
parsed = JSON.parse(text);
|
|
23607
|
+
} catch {
|
|
23608
|
+
const start = text.indexOf("[");
|
|
23609
|
+
const end = text.lastIndexOf("]");
|
|
23610
|
+
if (start < 0 || end <= start) return [];
|
|
23611
|
+
try {
|
|
23612
|
+
parsed = JSON.parse(text.slice(start, end + 1));
|
|
23613
|
+
} catch {
|
|
23614
|
+
return [];
|
|
23615
|
+
}
|
|
23616
|
+
}
|
|
23617
|
+
if (!Array.isArray(parsed)) return [];
|
|
23618
|
+
const rows = [];
|
|
23619
|
+
for (const item of parsed) {
|
|
23620
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
|
|
23621
|
+
const o = item;
|
|
23622
|
+
const title = typeof o.title === "string" ? o.title.trim() : "";
|
|
23623
|
+
const prompt = typeof o.prompt === "string" ? o.prompt.trim() : typeof o.promptText === "string" ? o.promptText.trim() : "";
|
|
23624
|
+
if (!title || !prompt) continue;
|
|
23625
|
+
rows.push({ title, prompt });
|
|
23626
|
+
}
|
|
23627
|
+
return rows;
|
|
23628
|
+
}
|
|
23629
|
+
|
|
23630
|
+
// ../types/src/build-planning-session-agent-prompt.ts
|
|
23631
|
+
var PLANNING_INSTRUCTIONS = [
|
|
23632
|
+
"PLANNING MODE: You must NOT make any changes to the codebase, filesystem, or environment.",
|
|
23633
|
+
"Do not run tools that modify files or execute commands that change state.",
|
|
23634
|
+
"Your only task is to analyze and produce a plan.",
|
|
23635
|
+
"",
|
|
23636
|
+
"Respond with ONLY a single JSON array \u2014 no markdown fences, no other text before or after.",
|
|
23637
|
+
"Each array element must be an object with exactly:",
|
|
23638
|
+
'- "title": a one-line summary of the task',
|
|
23639
|
+
'- "prompt": the full prompt to use when creating a new draft session from this todo',
|
|
23640
|
+
"",
|
|
23641
|
+
"Example:",
|
|
23642
|
+
'[{"title":"Add user login","prompt":"Implement a login form with email and password..."}]'
|
|
23643
|
+
].join("\n");
|
|
23644
|
+
function buildPlanningSessionAgentPrompt(userPrompt) {
|
|
23645
|
+
return [PLANNING_INSTRUCTIONS, "", "User request:", userPrompt.trim()].join("\n");
|
|
23646
|
+
}
|
|
23647
|
+
function buildPlanningSessionFollowUpAgentPrompt(userPrompt, existingTodos) {
|
|
23648
|
+
const todoLines = existingTodos.length > 0 ? existingTodos.map((t) => {
|
|
23649
|
+
const status = t.plannedSessionId ? "DONE (draft session already created)" : "OPEN";
|
|
23650
|
+
return `- [${status}] ${planningTodoTitle(t)}`;
|
|
23651
|
+
}).join("\n") : "(none yet)";
|
|
23652
|
+
return [
|
|
23653
|
+
PLANNING_INSTRUCTIONS,
|
|
23654
|
+
"",
|
|
23655
|
+
"Existing todo items from this planning session (consider these when responding; do not duplicate completed items):",
|
|
23656
|
+
todoLines,
|
|
23657
|
+
"",
|
|
23658
|
+
"User follow-up:",
|
|
23659
|
+
userPrompt.trim()
|
|
23660
|
+
].join("\n");
|
|
23661
|
+
}
|
|
23587
23662
|
|
|
23588
23663
|
// ../types/src/change-summary-path.ts
|
|
23589
23664
|
function normalizeRepoRelativePath(p) {
|
|
@@ -23967,6 +24042,19 @@ function buildCliAutoApprovedPermissionRpcResult(requestParams) {
|
|
|
23967
24042
|
};
|
|
23968
24043
|
}
|
|
23969
24044
|
|
|
24045
|
+
// ../types/src/acp-agent-text-stream-bucket.ts
|
|
24046
|
+
function resolveAgentTextStreamBucket(params) {
|
|
24047
|
+
const k = params.transcriptRowKind;
|
|
24048
|
+
const su = params.sessionUpdate;
|
|
24049
|
+
if (k === "agent_thought_chunk" || su === "agent_thought_chunk" || k === "thinking" || su === "thinking") {
|
|
24050
|
+
return "thought";
|
|
24051
|
+
}
|
|
24052
|
+
if (k === "agent_message_chunk" || su === "agent_message_chunk" || k === "update" || su === "update") {
|
|
24053
|
+
return "message";
|
|
24054
|
+
}
|
|
24055
|
+
return null;
|
|
24056
|
+
}
|
|
24057
|
+
|
|
23970
24058
|
// ../types/src/agent-config.ts
|
|
23971
24059
|
var AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY = "claude_permission_mode";
|
|
23972
24060
|
var AGENT_CONFIG_CLI_PERMISSION_MODE_KEY = "cli_permission_mode";
|
|
@@ -25184,7 +25272,7 @@ function installBridgeProcessResilience() {
|
|
|
25184
25272
|
}
|
|
25185
25273
|
|
|
25186
25274
|
// src/cli-version.ts
|
|
25187
|
-
var CLI_VERSION = "0.1.
|
|
25275
|
+
var CLI_VERSION = "0.1.58".length > 0 ? "0.1.58" : "0.0.0-dev";
|
|
25188
25276
|
|
|
25189
25277
|
// src/connection/heartbeat/constants.ts
|
|
25190
25278
|
var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
|
|
@@ -31057,6 +31145,185 @@ function createBridgeOnRequest(opts) {
|
|
|
31057
31145
|
};
|
|
31058
31146
|
}
|
|
31059
31147
|
|
|
31148
|
+
// src/agents/acp/hooks/bridge-on-session-update/constants.ts
|
|
31149
|
+
var PATH_SNAPSHOT_DEBOUNCE_MS = 500;
|
|
31150
|
+
|
|
31151
|
+
// src/agents/acp/hooks/bridge-on-session-update/tool-key.ts
|
|
31152
|
+
function getToolCallId(params) {
|
|
31153
|
+
if (!params || typeof params !== "object") return "";
|
|
31154
|
+
const u = params;
|
|
31155
|
+
const id = u.toolCallId ?? u.tool_call_id;
|
|
31156
|
+
return typeof id === "string" ? id : "";
|
|
31157
|
+
}
|
|
31158
|
+
function isCompletedToolStatus(status) {
|
|
31159
|
+
if (typeof status !== "string") return false;
|
|
31160
|
+
const s = status.toLowerCase();
|
|
31161
|
+
return s === "completed" || s === "complete" || s === "succeeded" || s === "success";
|
|
31162
|
+
}
|
|
31163
|
+
function accumulateToolPaths(toolKey, paths, acc) {
|
|
31164
|
+
if (!toolKey || paths.length === 0) return;
|
|
31165
|
+
let s = acc.get(toolKey);
|
|
31166
|
+
if (!s) {
|
|
31167
|
+
s = /* @__PURE__ */ new Set();
|
|
31168
|
+
acc.set(toolKey, s);
|
|
31169
|
+
}
|
|
31170
|
+
for (const p of paths) s.add(p);
|
|
31171
|
+
}
|
|
31172
|
+
|
|
31173
|
+
// src/agents/acp/hooks/bridge-on-session-update/path-snapshot-tracker.ts
|
|
31174
|
+
var PathSnapshotTracker = class {
|
|
31175
|
+
lastSeenRunId;
|
|
31176
|
+
anonToolSeq = 0;
|
|
31177
|
+
lastAnonymousToolKey = null;
|
|
31178
|
+
beforeByToolKey = /* @__PURE__ */ new Map();
|
|
31179
|
+
debouncers = /* @__PURE__ */ new Map();
|
|
31180
|
+
accumulatedPathsByToolKey = /* @__PURE__ */ new Map();
|
|
31181
|
+
clearRunState() {
|
|
31182
|
+
for (const t of this.debouncers.values()) clearTimeout(t);
|
|
31183
|
+
this.debouncers.clear();
|
|
31184
|
+
this.beforeByToolKey.clear();
|
|
31185
|
+
this.accumulatedPathsByToolKey.clear();
|
|
31186
|
+
this.lastAnonymousToolKey = null;
|
|
31187
|
+
}
|
|
31188
|
+
onRunIdChanged(runId) {
|
|
31189
|
+
if (runId && runId !== this.lastSeenRunId) {
|
|
31190
|
+
this.lastSeenRunId = runId;
|
|
31191
|
+
this.clearRunState();
|
|
31192
|
+
}
|
|
31193
|
+
}
|
|
31194
|
+
resolveToolKey(params, updateKind) {
|
|
31195
|
+
const id = getToolCallId(params);
|
|
31196
|
+
if (id) return id;
|
|
31197
|
+
if (updateKind === "tool_call") {
|
|
31198
|
+
this.lastAnonymousToolKey = `anon:${++this.anonToolSeq}`;
|
|
31199
|
+
return this.lastAnonymousToolKey;
|
|
31200
|
+
}
|
|
31201
|
+
return this.lastAnonymousToolKey ?? "_unknown";
|
|
31202
|
+
}
|
|
31203
|
+
resetToolSnapshots(toolKey) {
|
|
31204
|
+
const t = this.debouncers.get(toolKey);
|
|
31205
|
+
if (t) clearTimeout(t);
|
|
31206
|
+
this.debouncers.delete(toolKey);
|
|
31207
|
+
this.beforeByToolKey.delete(toolKey);
|
|
31208
|
+
this.accumulatedPathsByToolKey.delete(toolKey);
|
|
31209
|
+
}
|
|
31210
|
+
captureBeforeFromDisk(toolKey, paths, sessionParentPath) {
|
|
31211
|
+
if (paths.length === 0) return;
|
|
31212
|
+
let m = this.beforeByToolKey.get(toolKey);
|
|
31213
|
+
if (!m) {
|
|
31214
|
+
m = /* @__PURE__ */ new Map();
|
|
31215
|
+
this.beforeByToolKey.set(toolKey, m);
|
|
31216
|
+
}
|
|
31217
|
+
for (const p of paths) {
|
|
31218
|
+
if (m.has(p)) continue;
|
|
31219
|
+
m.set(p, readUtf8WorkspaceFile(sessionParentPath, p));
|
|
31220
|
+
}
|
|
31221
|
+
}
|
|
31222
|
+
ensureBeforeFromHeadForMissing(toolKey, paths, sessionParentPath) {
|
|
31223
|
+
let m = this.beforeByToolKey.get(toolKey);
|
|
31224
|
+
if (!m) {
|
|
31225
|
+
m = /* @__PURE__ */ new Map();
|
|
31226
|
+
this.beforeByToolKey.set(toolKey, m);
|
|
31227
|
+
}
|
|
31228
|
+
for (const p of paths) {
|
|
31229
|
+
if (m.has(p)) continue;
|
|
31230
|
+
m.set(p, readGitHeadBlob(sessionParentPath, p));
|
|
31231
|
+
}
|
|
31232
|
+
}
|
|
31233
|
+
flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
|
|
31234
|
+
const t = this.debouncers.get(toolKey);
|
|
31235
|
+
if (t) clearTimeout(t);
|
|
31236
|
+
this.debouncers.delete(toolKey);
|
|
31237
|
+
const beforeMap = this.beforeByToolKey.get(toolKey);
|
|
31238
|
+
if (!beforeMap || beforeMap.size === 0) return;
|
|
31239
|
+
this.beforeByToolKey.delete(toolKey);
|
|
31240
|
+
if (!send || !runId || !sessionId) return;
|
|
31241
|
+
for (const [displayPath, oldText] of beforeMap) {
|
|
31242
|
+
const newText = readUtf8WorkspaceFile(sessionParentPath, displayPath);
|
|
31243
|
+
if (oldText === newText) continue;
|
|
31244
|
+
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
|
|
31245
|
+
const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, displayPath);
|
|
31246
|
+
try {
|
|
31247
|
+
send({
|
|
31248
|
+
type: "session_file_change",
|
|
31249
|
+
sessionId,
|
|
31250
|
+
runId,
|
|
31251
|
+
path: displayPath,
|
|
31252
|
+
oldText,
|
|
31253
|
+
newText,
|
|
31254
|
+
patchContent,
|
|
31255
|
+
isDirectory: dirFlags.isDirectory,
|
|
31256
|
+
directoryRemoved: dirFlags.directoryRemoved
|
|
31257
|
+
});
|
|
31258
|
+
sentPaths.add(displayPath);
|
|
31259
|
+
} catch (err) {
|
|
31260
|
+
log2(`[Bridge service] Session file change failed for ${displayPath}: ${errorMessage(err)}`);
|
|
31261
|
+
}
|
|
31262
|
+
}
|
|
31263
|
+
}
|
|
31264
|
+
scheduleDebouncedFlush(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
|
|
31265
|
+
const prev = this.debouncers.get(toolKey);
|
|
31266
|
+
if (prev) clearTimeout(prev);
|
|
31267
|
+
this.debouncers.set(
|
|
31268
|
+
toolKey,
|
|
31269
|
+
setTimeout(() => {
|
|
31270
|
+
this.debouncers.delete(toolKey);
|
|
31271
|
+
this.flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
|
|
31272
|
+
}, PATH_SNAPSHOT_DEBOUNCE_MS)
|
|
31273
|
+
);
|
|
31274
|
+
}
|
|
31275
|
+
handleToolCallLifecycle(updateKind, toolKey, toolPaths, status, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
|
|
31276
|
+
if (updateKind === "tool_call") {
|
|
31277
|
+
this.resetToolSnapshots(toolKey);
|
|
31278
|
+
}
|
|
31279
|
+
if (updateKind === "tool_call") {
|
|
31280
|
+
this.captureBeforeFromDisk(toolKey, toolPaths, sessionParentPath);
|
|
31281
|
+
} else if (updateKind === "tool_call_update") {
|
|
31282
|
+
if (isCompletedToolStatus(status)) {
|
|
31283
|
+
this.ensureBeforeFromHeadForMissing(toolKey, toolPaths, sessionParentPath);
|
|
31284
|
+
this.flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
|
|
31285
|
+
} else {
|
|
31286
|
+
this.captureBeforeFromDisk(toolKey, toolPaths, sessionParentPath);
|
|
31287
|
+
if (this.beforeByToolKey.has(toolKey)) {
|
|
31288
|
+
this.scheduleDebouncedFlush(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
|
|
31289
|
+
}
|
|
31290
|
+
}
|
|
31291
|
+
}
|
|
31292
|
+
}
|
|
31293
|
+
};
|
|
31294
|
+
|
|
31295
|
+
// src/agents/acp/hooks/bridge-on-session-update/send-session-info-title-update.ts
|
|
31296
|
+
function extractSessionInfoTitle(params) {
|
|
31297
|
+
if (!params || typeof params !== "object") return null;
|
|
31298
|
+
const p = params;
|
|
31299
|
+
const title = typeof p.title === "string" ? p.title.trim() : "";
|
|
31300
|
+
return title ? title : null;
|
|
31301
|
+
}
|
|
31302
|
+
function sendSessionInfoTitleUpdate(params) {
|
|
31303
|
+
const title = extractSessionInfoTitle(params.payload);
|
|
31304
|
+
if (!title || !params.runId || !params.send) return;
|
|
31305
|
+
try {
|
|
31306
|
+
params.send({
|
|
31307
|
+
type: "session_title_update",
|
|
31308
|
+
...params.sessionId ? { sessionId: params.sessionId } : {},
|
|
31309
|
+
runId: params.runId,
|
|
31310
|
+
title
|
|
31311
|
+
});
|
|
31312
|
+
} catch (err) {
|
|
31313
|
+
params.log(`[Bridge service] Session title update send failed: ${errorMessage(err)}`);
|
|
31314
|
+
}
|
|
31315
|
+
}
|
|
31316
|
+
|
|
31317
|
+
// src/agents/acp/hooks/bridge-on-session-update/parse-bridge-session-update.ts
|
|
31318
|
+
function parseBridgeSessionUpdate(params) {
|
|
31319
|
+
const p = params;
|
|
31320
|
+
const updateKind = p.sessionUpdate ?? p.session_update ?? p.type ?? "update";
|
|
31321
|
+
const isCompletedToolCallUpdate = updateKind === "tool_call_update" && isCompletedToolStatus(p.status);
|
|
31322
|
+
const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
|
|
31323
|
+
const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
|
|
31324
|
+
return { updateKind, toolName, isToolUpdate, isCompletedToolCallUpdate };
|
|
31325
|
+
}
|
|
31326
|
+
|
|
31060
31327
|
// src/agents/acp/hooks/extract-acp-file-diffs-from-update/paths-and-text.ts
|
|
31061
31328
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
31062
31329
|
function readOptionalTextField(v) {
|
|
@@ -31227,174 +31494,27 @@ function extractToolTargetDisplayPaths(update, sessionParentPath) {
|
|
|
31227
31494
|
return [...out];
|
|
31228
31495
|
}
|
|
31229
31496
|
|
|
31230
|
-
// src/agents/acp/hooks/bridge-on-session-update/
|
|
31231
|
-
|
|
31232
|
-
|
|
31233
|
-
|
|
31234
|
-
|
|
31235
|
-
|
|
31236
|
-
|
|
31237
|
-
|
|
31238
|
-
|
|
31239
|
-
|
|
31240
|
-
|
|
31241
|
-
|
|
31242
|
-
|
|
31243
|
-
|
|
31244
|
-
|
|
31245
|
-
|
|
31246
|
-
|
|
31247
|
-
|
|
31248
|
-
|
|
31249
|
-
|
|
31250
|
-
|
|
31251
|
-
}
|
|
31252
|
-
for (const p of paths) s.add(p);
|
|
31253
|
-
}
|
|
31254
|
-
|
|
31255
|
-
// src/agents/acp/hooks/bridge-on-session-update/path-snapshot-tracker.ts
|
|
31256
|
-
var PathSnapshotTracker = class {
|
|
31257
|
-
lastSeenRunId;
|
|
31258
|
-
anonToolSeq = 0;
|
|
31259
|
-
lastAnonymousToolKey = null;
|
|
31260
|
-
beforeByToolKey = /* @__PURE__ */ new Map();
|
|
31261
|
-
debouncers = /* @__PURE__ */ new Map();
|
|
31262
|
-
accumulatedPathsByToolKey = /* @__PURE__ */ new Map();
|
|
31263
|
-
clearRunState() {
|
|
31264
|
-
for (const t of this.debouncers.values()) clearTimeout(t);
|
|
31265
|
-
this.debouncers.clear();
|
|
31266
|
-
this.beforeByToolKey.clear();
|
|
31267
|
-
this.accumulatedPathsByToolKey.clear();
|
|
31268
|
-
this.lastAnonymousToolKey = null;
|
|
31269
|
-
}
|
|
31270
|
-
onRunIdChanged(runId) {
|
|
31271
|
-
if (runId && runId !== this.lastSeenRunId) {
|
|
31272
|
-
this.lastSeenRunId = runId;
|
|
31273
|
-
this.clearRunState();
|
|
31274
|
-
}
|
|
31275
|
-
}
|
|
31276
|
-
resolveToolKey(params, updateKind) {
|
|
31277
|
-
const id = getToolCallId(params);
|
|
31278
|
-
if (id) return id;
|
|
31279
|
-
if (updateKind === "tool_call") {
|
|
31280
|
-
this.lastAnonymousToolKey = `anon:${++this.anonToolSeq}`;
|
|
31281
|
-
return this.lastAnonymousToolKey;
|
|
31282
|
-
}
|
|
31283
|
-
return this.lastAnonymousToolKey ?? "_unknown";
|
|
31284
|
-
}
|
|
31285
|
-
resetToolSnapshots(toolKey) {
|
|
31286
|
-
const t = this.debouncers.get(toolKey);
|
|
31287
|
-
if (t) clearTimeout(t);
|
|
31288
|
-
this.debouncers.delete(toolKey);
|
|
31289
|
-
this.beforeByToolKey.delete(toolKey);
|
|
31290
|
-
this.accumulatedPathsByToolKey.delete(toolKey);
|
|
31291
|
-
}
|
|
31292
|
-
captureBeforeFromDisk(toolKey, paths, sessionParentPath) {
|
|
31293
|
-
if (paths.length === 0) return;
|
|
31294
|
-
let m = this.beforeByToolKey.get(toolKey);
|
|
31295
|
-
if (!m) {
|
|
31296
|
-
m = /* @__PURE__ */ new Map();
|
|
31297
|
-
this.beforeByToolKey.set(toolKey, m);
|
|
31298
|
-
}
|
|
31299
|
-
for (const p of paths) {
|
|
31300
|
-
if (m.has(p)) continue;
|
|
31301
|
-
m.set(p, readUtf8WorkspaceFile(sessionParentPath, p));
|
|
31302
|
-
}
|
|
31303
|
-
}
|
|
31304
|
-
ensureBeforeFromHeadForMissing(toolKey, paths, sessionParentPath) {
|
|
31305
|
-
let m = this.beforeByToolKey.get(toolKey);
|
|
31306
|
-
if (!m) {
|
|
31307
|
-
m = /* @__PURE__ */ new Map();
|
|
31308
|
-
this.beforeByToolKey.set(toolKey, m);
|
|
31309
|
-
}
|
|
31310
|
-
for (const p of paths) {
|
|
31311
|
-
if (m.has(p)) continue;
|
|
31312
|
-
m.set(p, readGitHeadBlob(sessionParentPath, p));
|
|
31313
|
-
}
|
|
31314
|
-
}
|
|
31315
|
-
flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
|
|
31316
|
-
const t = this.debouncers.get(toolKey);
|
|
31317
|
-
if (t) clearTimeout(t);
|
|
31318
|
-
this.debouncers.delete(toolKey);
|
|
31319
|
-
const beforeMap = this.beforeByToolKey.get(toolKey);
|
|
31320
|
-
if (!beforeMap || beforeMap.size === 0) return;
|
|
31321
|
-
this.beforeByToolKey.delete(toolKey);
|
|
31322
|
-
if (!send || !runId || !sessionId) return;
|
|
31323
|
-
for (const [displayPath, oldText] of beforeMap) {
|
|
31324
|
-
const newText = readUtf8WorkspaceFile(sessionParentPath, displayPath);
|
|
31325
|
-
if (oldText === newText) continue;
|
|
31326
|
-
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
|
|
31327
|
-
const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, displayPath);
|
|
31328
|
-
try {
|
|
31329
|
-
send({
|
|
31330
|
-
type: "session_file_change",
|
|
31331
|
-
sessionId,
|
|
31332
|
-
runId,
|
|
31333
|
-
path: displayPath,
|
|
31334
|
-
oldText,
|
|
31335
|
-
newText,
|
|
31336
|
-
patchContent,
|
|
31337
|
-
isDirectory: dirFlags.isDirectory,
|
|
31338
|
-
directoryRemoved: dirFlags.directoryRemoved
|
|
31339
|
-
});
|
|
31340
|
-
sentPaths.add(displayPath);
|
|
31341
|
-
} catch (err) {
|
|
31342
|
-
log2(`[Bridge service] Session file change failed for ${displayPath}: ${errorMessage(err)}`);
|
|
31343
|
-
}
|
|
31344
|
-
}
|
|
31345
|
-
}
|
|
31346
|
-
scheduleDebouncedFlush(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
|
|
31347
|
-
const prev = this.debouncers.get(toolKey);
|
|
31348
|
-
if (prev) clearTimeout(prev);
|
|
31349
|
-
this.debouncers.set(
|
|
31350
|
-
toolKey,
|
|
31351
|
-
setTimeout(() => {
|
|
31352
|
-
this.debouncers.delete(toolKey);
|
|
31353
|
-
this.flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
|
|
31354
|
-
}, PATH_SNAPSHOT_DEBOUNCE_MS)
|
|
31355
|
-
);
|
|
31356
|
-
}
|
|
31357
|
-
handleToolCallLifecycle(updateKind, toolKey, toolPaths, status, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
|
|
31358
|
-
if (updateKind === "tool_call") {
|
|
31359
|
-
this.resetToolSnapshots(toolKey);
|
|
31360
|
-
}
|
|
31361
|
-
if (updateKind === "tool_call") {
|
|
31362
|
-
this.captureBeforeFromDisk(toolKey, toolPaths, sessionParentPath);
|
|
31363
|
-
} else if (updateKind === "tool_call_update") {
|
|
31364
|
-
if (isCompletedToolStatus(status)) {
|
|
31365
|
-
this.ensureBeforeFromHeadForMissing(toolKey, toolPaths, sessionParentPath);
|
|
31366
|
-
this.flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
|
|
31367
|
-
} else {
|
|
31368
|
-
this.captureBeforeFromDisk(toolKey, toolPaths, sessionParentPath);
|
|
31369
|
-
if (this.beforeByToolKey.has(toolKey)) {
|
|
31370
|
-
this.scheduleDebouncedFlush(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
|
|
31371
|
-
}
|
|
31372
|
-
}
|
|
31373
|
-
}
|
|
31374
|
-
}
|
|
31375
|
-
};
|
|
31376
|
-
|
|
31377
|
-
// src/agents/acp/hooks/bridge-on-session-update/send-structured-file-changes.ts
|
|
31378
|
-
function sendExtractedDiffsAsSessionFileChanges(diffs, send, sessionParentPath, sessionId, runId, sentPaths, log2) {
|
|
31379
|
-
for (const d of diffs) {
|
|
31380
|
-
try {
|
|
31381
|
-
const patchContent = editSnippetToUnifiedDiff(d.path, d.oldText, d.newText);
|
|
31382
|
-
const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, d.path);
|
|
31383
|
-
send({
|
|
31384
|
-
type: "session_file_change",
|
|
31385
|
-
sessionId,
|
|
31386
|
-
runId,
|
|
31387
|
-
path: d.path,
|
|
31388
|
-
oldText: d.oldText,
|
|
31389
|
-
newText: d.newText,
|
|
31390
|
-
patchContent,
|
|
31391
|
-
isDirectory: dirFlags.isDirectory,
|
|
31392
|
-
directoryRemoved: dirFlags.directoryRemoved
|
|
31393
|
-
});
|
|
31394
|
-
sentPaths.add(d.path);
|
|
31395
|
-
} catch (err) {
|
|
31396
|
-
log2(`[Bridge service] Session file change failed for ${d.path}: ${errorMessage(err)}`);
|
|
31397
|
-
}
|
|
31497
|
+
// src/agents/acp/hooks/bridge-on-session-update/send-structured-file-changes.ts
|
|
31498
|
+
function sendExtractedDiffsAsSessionFileChanges(diffs, send, sessionParentPath, sessionId, runId, sentPaths, log2) {
|
|
31499
|
+
for (const d of diffs) {
|
|
31500
|
+
try {
|
|
31501
|
+
const patchContent = editSnippetToUnifiedDiff(d.path, d.oldText, d.newText);
|
|
31502
|
+
const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, d.path);
|
|
31503
|
+
send({
|
|
31504
|
+
type: "session_file_change",
|
|
31505
|
+
sessionId,
|
|
31506
|
+
runId,
|
|
31507
|
+
path: d.path,
|
|
31508
|
+
oldText: d.oldText,
|
|
31509
|
+
newText: d.newText,
|
|
31510
|
+
patchContent,
|
|
31511
|
+
isDirectory: dirFlags.isDirectory,
|
|
31512
|
+
directoryRemoved: dirFlags.directoryRemoved
|
|
31513
|
+
});
|
|
31514
|
+
sentPaths.add(d.path);
|
|
31515
|
+
} catch (err) {
|
|
31516
|
+
log2(`[Bridge service] Session file change failed for ${d.path}: ${errorMessage(err)}`);
|
|
31517
|
+
}
|
|
31398
31518
|
}
|
|
31399
31519
|
}
|
|
31400
31520
|
function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, sessionParentPath, sessionId, runId, log2) {
|
|
@@ -31424,25 +31544,158 @@ function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, sessio
|
|
|
31424
31544
|
}
|
|
31425
31545
|
}
|
|
31426
31546
|
|
|
31427
|
-
// src/agents/acp/hooks/bridge-on-session-update/
|
|
31428
|
-
function
|
|
31429
|
-
|
|
31430
|
-
|
|
31431
|
-
|
|
31432
|
-
|
|
31547
|
+
// src/agents/acp/hooks/bridge-on-session-update/handle-bridge-tool-session-update.ts
|
|
31548
|
+
function handleBridgeToolSessionUpdate(params) {
|
|
31549
|
+
const {
|
|
31550
|
+
params: updateParams,
|
|
31551
|
+
updateKind,
|
|
31552
|
+
isToolUpdate,
|
|
31553
|
+
isCompletedToolCallUpdate,
|
|
31554
|
+
toolKey,
|
|
31555
|
+
toolPaths,
|
|
31556
|
+
status,
|
|
31557
|
+
sessionParentPath,
|
|
31558
|
+
pathTracker,
|
|
31559
|
+
sentFileChangePaths,
|
|
31560
|
+
send,
|
|
31561
|
+
runId,
|
|
31562
|
+
sessionId,
|
|
31563
|
+
log: log2
|
|
31564
|
+
} = params;
|
|
31565
|
+
if (updateKind === "tool_call") {
|
|
31566
|
+
pathTracker.resetToolSnapshots(toolKey);
|
|
31567
|
+
}
|
|
31568
|
+
if (isToolUpdate) {
|
|
31569
|
+
accumulateToolPaths(toolKey, toolPaths, pathTracker.accumulatedPathsByToolKey);
|
|
31570
|
+
}
|
|
31571
|
+
if (isToolUpdate) {
|
|
31572
|
+
const deliver = send && runId && sessionId ? (msg) => send(msg) : null;
|
|
31573
|
+
pathTracker.handleToolCallLifecycle(
|
|
31574
|
+
updateKind,
|
|
31575
|
+
toolKey,
|
|
31576
|
+
toolPaths,
|
|
31577
|
+
status,
|
|
31578
|
+
sessionParentPath,
|
|
31579
|
+
sentFileChangePaths,
|
|
31580
|
+
deliver,
|
|
31581
|
+
runId,
|
|
31582
|
+
sessionId,
|
|
31583
|
+
log2
|
|
31584
|
+
);
|
|
31585
|
+
}
|
|
31586
|
+
const diffs = extractAcpFileDiffsFromUpdate(updateParams, sessionParentPath);
|
|
31587
|
+
if (diffs.length > 0 && send && runId && sessionId) {
|
|
31588
|
+
sendExtractedDiffsAsSessionFileChanges(
|
|
31589
|
+
diffs,
|
|
31590
|
+
send,
|
|
31591
|
+
sessionParentPath,
|
|
31592
|
+
sessionId,
|
|
31593
|
+
runId,
|
|
31594
|
+
sentFileChangePaths,
|
|
31595
|
+
log2
|
|
31596
|
+
);
|
|
31597
|
+
} else if (diffs.length > 0) {
|
|
31598
|
+
log2(
|
|
31599
|
+
`[Bridge service] Agent file diff(s) not forwarded (${diffs.length}): session or run not wired to the bridge.`
|
|
31600
|
+
);
|
|
31601
|
+
}
|
|
31602
|
+
if (isCompletedToolCallUpdate && send && runId && sessionId) {
|
|
31603
|
+
const acc = pathTracker.accumulatedPathsByToolKey.get(toolKey);
|
|
31604
|
+
const merged = [.../* @__PURE__ */ new Set([...acc ? [...acc] : [], ...toolPaths])];
|
|
31605
|
+
sendGitHeadVsWorkspaceForToolPaths(
|
|
31606
|
+
merged,
|
|
31607
|
+
sentFileChangePaths,
|
|
31608
|
+
send,
|
|
31609
|
+
sessionParentPath,
|
|
31610
|
+
sessionId,
|
|
31611
|
+
runId,
|
|
31612
|
+
log2
|
|
31613
|
+
);
|
|
31614
|
+
pathTracker.accumulatedPathsByToolKey.delete(toolKey);
|
|
31615
|
+
}
|
|
31433
31616
|
}
|
|
31434
|
-
function
|
|
31435
|
-
|
|
31436
|
-
|
|
31617
|
+
function resolveBridgeToolPaths(params, isToolUpdate, sessionParentPath) {
|
|
31618
|
+
return isToolUpdate ? extractToolTargetDisplayPaths(params, sessionParentPath) : [];
|
|
31619
|
+
}
|
|
31620
|
+
|
|
31621
|
+
// src/agents/planning/extract-session-update-message-text.ts
|
|
31622
|
+
function extractSessionUpdateMessageText(params) {
|
|
31623
|
+
if (params == null || typeof params !== "object" || Array.isArray(params)) return null;
|
|
31624
|
+
const o = params;
|
|
31625
|
+
if (typeof o.text === "string" && o.text.length > 0) return o.text;
|
|
31626
|
+
const content = o.content;
|
|
31627
|
+
if (typeof content === "string" && content.length > 0) return content;
|
|
31628
|
+
if (content != null && typeof content === "object" && !Array.isArray(content)) {
|
|
31629
|
+
const c = content;
|
|
31630
|
+
if (typeof c.text === "string" && c.text.length > 0) return c.text;
|
|
31631
|
+
}
|
|
31632
|
+
const update = o.update;
|
|
31633
|
+
if (typeof update === "string" && update.length > 0) return update;
|
|
31634
|
+
if (update != null && typeof update === "object" && !Array.isArray(update)) {
|
|
31635
|
+
const u = update;
|
|
31636
|
+
const innerContent = u.content;
|
|
31637
|
+
if (typeof innerContent === "string" && innerContent.length > 0) return innerContent;
|
|
31638
|
+
if (innerContent != null && typeof innerContent === "object" && !Array.isArray(innerContent)) {
|
|
31639
|
+
const ic = innerContent;
|
|
31640
|
+
if (typeof ic.text === "string" && ic.text.length > 0) return ic.text;
|
|
31641
|
+
}
|
|
31642
|
+
}
|
|
31643
|
+
return null;
|
|
31644
|
+
}
|
|
31645
|
+
|
|
31646
|
+
// src/agents/planning/planning-session-turn-buffer.ts
|
|
31647
|
+
var buffersByRunId = /* @__PURE__ */ new Map();
|
|
31648
|
+
function registerPlanningSessionTurn(runId) {
|
|
31649
|
+
buffersByRunId.set(runId, { messageBuffer: "" });
|
|
31650
|
+
}
|
|
31651
|
+
function clearPlanningSessionTurn(runId) {
|
|
31652
|
+
buffersByRunId.delete(runId);
|
|
31653
|
+
}
|
|
31654
|
+
function capturePlanningSessionUpdate(params) {
|
|
31655
|
+
const state = buffersByRunId.get(params.runId);
|
|
31656
|
+
if (!state) return false;
|
|
31657
|
+
const sessionUpdate = params.payload != null && typeof params.payload === "object" && !Array.isArray(params.payload) ? params.payload.sessionUpdate ?? params.payload.session_update : void 0;
|
|
31658
|
+
const bucket = resolveAgentTextStreamBucket({
|
|
31659
|
+
transcriptRowKind: params.updateKind,
|
|
31660
|
+
sessionUpdate: typeof sessionUpdate === "string" ? sessionUpdate : void 0
|
|
31661
|
+
});
|
|
31662
|
+
if (bucket !== "message") return false;
|
|
31663
|
+
const text = extractSessionUpdateMessageText(params.payload);
|
|
31664
|
+
if (text) state.messageBuffer += text;
|
|
31665
|
+
return true;
|
|
31666
|
+
}
|
|
31667
|
+
function getPlanningSessionTurnOutput(runId) {
|
|
31668
|
+
return buffersByRunId.get(runId)?.messageBuffer ?? "";
|
|
31669
|
+
}
|
|
31670
|
+
function consumePlanningSessionTurnOutput(runId) {
|
|
31671
|
+
const state = buffersByRunId.get(runId);
|
|
31672
|
+
buffersByRunId.delete(runId);
|
|
31673
|
+
return state?.messageBuffer ?? "";
|
|
31674
|
+
}
|
|
31675
|
+
|
|
31676
|
+
// src/agents/acp/hooks/bridge-on-session-update/forward-bridge-session-update.ts
|
|
31677
|
+
function forwardBridgeSessionUpdate(params) {
|
|
31678
|
+
const { runId, sessionId, updateKind, payload, send, nextTranscriptStreamSeq, log: log2 } = params;
|
|
31679
|
+
if (updateKind === "permission") {
|
|
31680
|
+
return;
|
|
31681
|
+
}
|
|
31682
|
+
if (capturePlanningSessionUpdate({ runId, updateKind, payload })) {
|
|
31683
|
+
return;
|
|
31684
|
+
}
|
|
31437
31685
|
try {
|
|
31438
|
-
|
|
31439
|
-
|
|
31440
|
-
|
|
31441
|
-
|
|
31442
|
-
|
|
31686
|
+
const transcriptStreamSeq = nextTranscriptStreamSeq?.(runId);
|
|
31687
|
+
send({
|
|
31688
|
+
type: "session_update",
|
|
31689
|
+
...sessionId ? { sessionId } : {},
|
|
31690
|
+
runId,
|
|
31691
|
+
kind: updateKind,
|
|
31692
|
+
payload,
|
|
31693
|
+
...transcriptStreamSeq != null ? { transcriptStreamSeq } : {}
|
|
31443
31694
|
});
|
|
31444
31695
|
} catch (err) {
|
|
31445
|
-
|
|
31696
|
+
log2(
|
|
31697
|
+
`[Bridge service] Session update send failed (${formatSessionUpdateKindForLog(updateKind)}): ${errorMessage(err)}`
|
|
31698
|
+
);
|
|
31446
31699
|
}
|
|
31447
31700
|
}
|
|
31448
31701
|
|
|
@@ -31457,8 +31710,7 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
31457
31710
|
pathTracker.onRunIdChanged(runId);
|
|
31458
31711
|
const send = getSendSessionUpdate();
|
|
31459
31712
|
const sentFileChangePaths = /* @__PURE__ */ new Set();
|
|
31460
|
-
const
|
|
31461
|
-
const updateKind = p.sessionUpdate ?? p.session_update ?? p.type ?? "update";
|
|
31713
|
+
const { updateKind, isToolUpdate, isCompletedToolCallUpdate } = parseBridgeSessionUpdate(params);
|
|
31462
31714
|
if (updateKind === "config_option_update") {
|
|
31463
31715
|
return;
|
|
31464
31716
|
}
|
|
@@ -31466,81 +31718,35 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
31466
31718
|
sendSessionInfoTitleUpdate({ payload: params, runId, sessionId, send, log: log2 });
|
|
31467
31719
|
return;
|
|
31468
31720
|
}
|
|
31469
|
-
const
|
|
31470
|
-
const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
|
|
31471
|
-
const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
|
|
31472
|
-
const toolPaths = isToolUpdate ? extractToolTargetDisplayPaths(params, sessionParentPath) : [];
|
|
31721
|
+
const toolPaths = resolveBridgeToolPaths(params, isToolUpdate, sessionParentPath);
|
|
31473
31722
|
const toolKey = isToolUpdate ? pathTracker.resolveToolKey(params, updateKind) : "";
|
|
31474
|
-
|
|
31475
|
-
|
|
31476
|
-
|
|
31477
|
-
|
|
31478
|
-
|
|
31479
|
-
|
|
31480
|
-
|
|
31481
|
-
|
|
31482
|
-
|
|
31483
|
-
|
|
31484
|
-
|
|
31485
|
-
|
|
31486
|
-
|
|
31487
|
-
|
|
31488
|
-
|
|
31489
|
-
|
|
31490
|
-
|
|
31491
|
-
|
|
31492
|
-
|
|
31493
|
-
);
|
|
31494
|
-
}
|
|
31495
|
-
const diffs = extractAcpFileDiffsFromUpdate(params, sessionParentPath);
|
|
31496
|
-
if (diffs.length > 0 && send && runId && sessionId) {
|
|
31497
|
-
sendExtractedDiffsAsSessionFileChanges(
|
|
31498
|
-
diffs,
|
|
31499
|
-
send,
|
|
31500
|
-
sessionParentPath,
|
|
31501
|
-
sessionId,
|
|
31723
|
+
const status = params.status;
|
|
31724
|
+
handleBridgeToolSessionUpdate({
|
|
31725
|
+
params,
|
|
31726
|
+
updateKind,
|
|
31727
|
+
isToolUpdate,
|
|
31728
|
+
isCompletedToolCallUpdate,
|
|
31729
|
+
toolKey,
|
|
31730
|
+
toolPaths,
|
|
31731
|
+
status,
|
|
31732
|
+
sessionParentPath,
|
|
31733
|
+
pathTracker,
|
|
31734
|
+
sentFileChangePaths,
|
|
31735
|
+
send,
|
|
31736
|
+
runId: runId ?? "",
|
|
31737
|
+
sessionId: sessionId ?? "",
|
|
31738
|
+
log: log2
|
|
31739
|
+
});
|
|
31740
|
+
if (runId && send) {
|
|
31741
|
+
forwardBridgeSessionUpdate({
|
|
31502
31742
|
runId,
|
|
31503
|
-
sentFileChangePaths,
|
|
31504
|
-
log2
|
|
31505
|
-
);
|
|
31506
|
-
} else if (diffs.length > 0) {
|
|
31507
|
-
log2(
|
|
31508
|
-
`[Bridge service] Agent file diff(s) not forwarded (${diffs.length}): session or run not wired to the bridge.`
|
|
31509
|
-
);
|
|
31510
|
-
}
|
|
31511
|
-
if (isCompletedToolCallUpdate && send && runId && sessionId) {
|
|
31512
|
-
const acc = pathTracker.accumulatedPathsByToolKey.get(toolKey);
|
|
31513
|
-
const merged = [.../* @__PURE__ */ new Set([...acc ? [...acc] : [], ...toolPaths])];
|
|
31514
|
-
sendGitHeadVsWorkspaceForToolPaths(
|
|
31515
|
-
merged,
|
|
31516
|
-
sentFileChangePaths,
|
|
31517
|
-
send,
|
|
31518
|
-
sessionParentPath,
|
|
31519
31743
|
sessionId,
|
|
31520
|
-
|
|
31521
|
-
|
|
31522
|
-
|
|
31523
|
-
|
|
31524
|
-
|
|
31525
|
-
|
|
31526
|
-
if (updateKind === "permission") {
|
|
31527
|
-
return;
|
|
31528
|
-
}
|
|
31529
|
-
try {
|
|
31530
|
-
const transcriptStreamSeq = nextTranscriptStreamSeq?.(runId);
|
|
31531
|
-
send({
|
|
31532
|
-
type: "session_update",
|
|
31533
|
-
...sessionId ? { sessionId } : {},
|
|
31534
|
-
runId,
|
|
31535
|
-
kind: updateKind,
|
|
31536
|
-
payload: params,
|
|
31537
|
-
...transcriptStreamSeq != null ? { transcriptStreamSeq } : {}
|
|
31538
|
-
});
|
|
31539
|
-
} catch (err) {
|
|
31540
|
-
log2(
|
|
31541
|
-
`[Bridge service] Session update send failed (${formatSessionUpdateKindForLog(updateKind)}): ${errorMessage(err)}`
|
|
31542
|
-
);
|
|
31543
|
-
}
|
|
31744
|
+
updateKind,
|
|
31745
|
+
payload: params,
|
|
31746
|
+
send,
|
|
31747
|
+
nextTranscriptStreamSeq,
|
|
31748
|
+
log: log2
|
|
31749
|
+
});
|
|
31544
31750
|
}
|
|
31545
31751
|
};
|
|
31546
31752
|
}
|
|
@@ -31880,14 +32086,48 @@ async function disconnectAll(ctx) {
|
|
|
31880
32086
|
ctx.pendingCancelRunIds.clear();
|
|
31881
32087
|
}
|
|
31882
32088
|
|
|
31883
|
-
// src/
|
|
31884
|
-
|
|
31885
|
-
|
|
31886
|
-
|
|
31887
|
-
|
|
31888
|
-
|
|
31889
|
-
|
|
31890
|
-
|
|
32089
|
+
// src/agents/acp/manager/resolve-prompt-run-context.ts
|
|
32090
|
+
function resolvePromptRunContext(ctx, opts) {
|
|
32091
|
+
const { runId, mode, agentType, agentConfig, sessionId } = opts;
|
|
32092
|
+
const preferredForPrompt = agentType ?? ctx.backendFallbackAgentType ?? null;
|
|
32093
|
+
if (!runId) {
|
|
32094
|
+
ctx.log("[Agent] Prompt ignored: missing runId (cannot route session updates).");
|
|
32095
|
+
return null;
|
|
32096
|
+
}
|
|
32097
|
+
const acpAgentKey = computeAcpAgentKey(preferredForPrompt, mode, agentConfig ?? null);
|
|
32098
|
+
if (!acpAgentKey) {
|
|
32099
|
+
return null;
|
|
32100
|
+
}
|
|
32101
|
+
const activeAcpSessionAgentKey = computeAcpSessionAgentKey(sessionId, acpAgentKey);
|
|
32102
|
+
ctx.pendingCancelRunIds.delete(runId);
|
|
32103
|
+
ctx.promptRouting.registerRun({ sessionId, runId });
|
|
32104
|
+
ctx.runDispatch.set(runId, { acpSessionAgentKey: activeAcpSessionAgentKey });
|
|
32105
|
+
return {
|
|
32106
|
+
activeRunId: runId,
|
|
32107
|
+
activeAcpAgentKey: acpAgentKey,
|
|
32108
|
+
activeAcpSessionAgentKey,
|
|
32109
|
+
preferredForPrompt
|
|
32110
|
+
};
|
|
32111
|
+
}
|
|
32112
|
+
|
|
32113
|
+
// src/agents/acp/send-prompt-result-augment.ts
|
|
32114
|
+
function augmentPromptResultAuthFields(agentType, errorText) {
|
|
32115
|
+
const err = errorText ?? "";
|
|
32116
|
+
const at = agentType ?? null;
|
|
32117
|
+
const evaluated = Boolean(at && err.trim());
|
|
32118
|
+
const suggestsAuth = evaluated && at ? localAgentErrorSuggestsAuth(at, err) : false;
|
|
32119
|
+
if (!suggestsAuth || !agentType) return {};
|
|
32120
|
+
return { agentAuthRequired: true, agentType };
|
|
32121
|
+
}
|
|
32122
|
+
|
|
32123
|
+
// src/git/git-runtime.ts
|
|
32124
|
+
var activeGitChildProcesses = /* @__PURE__ */ new Set();
|
|
32125
|
+
function abortActiveGitChildProcesses() {
|
|
32126
|
+
for (const child of activeGitChildProcesses) {
|
|
32127
|
+
try {
|
|
32128
|
+
child.kill("SIGTERM");
|
|
32129
|
+
} catch {
|
|
32130
|
+
}
|
|
31891
32131
|
}
|
|
31892
32132
|
}
|
|
31893
32133
|
var GitOperationAbortedError = class extends Error {
|
|
@@ -32335,130 +32575,136 @@ async function maybeUploadE2eeSessionChangeSummariesAfterAgentSuccess(params) {
|
|
|
32335
32575
|
}
|
|
32336
32576
|
}
|
|
32337
32577
|
|
|
32338
|
-
// src/agents/
|
|
32339
|
-
function
|
|
32340
|
-
const
|
|
32341
|
-
|
|
32342
|
-
const
|
|
32343
|
-
const
|
|
32344
|
-
|
|
32345
|
-
|
|
32346
|
-
|
|
32347
|
-
|
|
32348
|
-
|
|
32349
|
-
|
|
32350
|
-
|
|
32351
|
-
|
|
32352
|
-
|
|
32353
|
-
|
|
32354
|
-
|
|
32355
|
-
|
|
32356
|
-
|
|
32357
|
-
|
|
32358
|
-
|
|
32359
|
-
|
|
32360
|
-
|
|
32361
|
-
for (let i = 0; i < bytes.length; i += 1) binary += String.fromCharCode(bytes[i]);
|
|
32362
|
-
const b64 = btoa(binary);
|
|
32363
|
-
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
32364
|
-
}
|
|
32365
|
-
function base64UrlDecode(value) {
|
|
32366
|
-
const b64 = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
32367
|
-
const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
|
|
32368
|
-
const binary = atob(padded);
|
|
32369
|
-
const out = new Uint8Array(binary.length);
|
|
32370
|
-
for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);
|
|
32371
|
-
return out;
|
|
32578
|
+
// src/agents/planning/submit-planning-todos-for-turn.ts
|
|
32579
|
+
async function submitPlanningTodosForTurn(params) {
|
|
32580
|
+
const token = params.getCloudAccessToken();
|
|
32581
|
+
if (!token.trim()) return { ok: false, error: "Missing cloud access token" };
|
|
32582
|
+
const base = params.cloudApiBaseUrl.replace(/\/$/, "");
|
|
32583
|
+
const url2 = `${base}/internal/sessions/todos/submit`;
|
|
32584
|
+
const res = await fetch(url2, {
|
|
32585
|
+
method: "POST",
|
|
32586
|
+
headers: {
|
|
32587
|
+
Authorization: `Bearer ${token}`,
|
|
32588
|
+
"Content-Type": "application/json"
|
|
32589
|
+
},
|
|
32590
|
+
body: JSON.stringify({
|
|
32591
|
+
sessionId: params.sessionId,
|
|
32592
|
+
turnId: params.turnId,
|
|
32593
|
+
items: params.items
|
|
32594
|
+
})
|
|
32595
|
+
});
|
|
32596
|
+
if (!res.ok) {
|
|
32597
|
+
const body = await res.json().catch(() => null);
|
|
32598
|
+
return { ok: false, error: body?.error ?? `Planning todo submit failed (${res.status})` };
|
|
32599
|
+
}
|
|
32600
|
+
return { ok: true };
|
|
32372
32601
|
}
|
|
32373
32602
|
|
|
32374
|
-
// src/agents/
|
|
32375
|
-
function
|
|
32376
|
-
|
|
32377
|
-
const
|
|
32378
|
-
|
|
32379
|
-
|
|
32380
|
-
|
|
32381
|
-
|
|
32382
|
-
if (!m.startsWith("image/") || buf.length < 4) return;
|
|
32383
|
-
const b0 = buf[0];
|
|
32384
|
-
const b1 = buf[1];
|
|
32385
|
-
const b2 = buf[2];
|
|
32386
|
-
const b3 = buf[3];
|
|
32387
|
-
let looksOk = false;
|
|
32388
|
-
if (m.includes("png") && b0 === 137 && b1 === 80 && b2 === 78 && b3 === 71) looksOk = true;
|
|
32389
|
-
else if ((m.includes("jpeg") || m.includes("jpg")) && b0 === 255 && b1 === 216 && b2 === 255) looksOk = true;
|
|
32390
|
-
else if (m.includes("gif") && b0 === 71 && b1 === 73 && b2 === 70) looksOk = true;
|
|
32391
|
-
else if (m.includes("webp") && buf.length >= 12 && buf.subarray(0, 4).toString("ascii") === "RIFF" && buf.subarray(8, 12).toString("ascii") === "WEBP")
|
|
32392
|
-
looksOk = true;
|
|
32393
|
-
else if (!/(png|jpe?g|gif|webp)/i.test(m)) looksOk = true;
|
|
32394
|
-
if (!looksOk) {
|
|
32395
|
-
logDebug(
|
|
32396
|
-
`[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")}`
|
|
32397
|
-
);
|
|
32603
|
+
// src/agents/planning/maybe-submit-planning-todos-after-agent-success.ts
|
|
32604
|
+
async function maybeSubmitPlanningTodosAfterAgentSuccess(params) {
|
|
32605
|
+
const { sessionId, runId, resultSuccess, output, cloudApiBaseUrl, getCloudAccessToken, log: log2 } = params;
|
|
32606
|
+
const buffered = runId ? getPlanningSessionTurnOutput(runId) : "";
|
|
32607
|
+
const outputFromResult = typeof output === "string" ? output : "";
|
|
32608
|
+
const outputStr = buffered.trim() !== "" ? buffered : outputFromResult;
|
|
32609
|
+
if (!sessionId || !runId || !resultSuccess || outputStr.trim() === "") {
|
|
32610
|
+
return { submitted: false, suppressOutput: false };
|
|
32398
32611
|
}
|
|
32399
|
-
|
|
32400
|
-
|
|
32401
|
-
const { attachments, sessionId, cloudApiBaseUrl, getCloudAccessToken, e2ee, log: log2 } = params;
|
|
32402
|
-
const token = getCloudAccessToken();
|
|
32403
|
-
if (!token) {
|
|
32404
|
-
return { ok: false, error: "Missing cloud access token; cannot download attachments." };
|
|
32612
|
+
if (!cloudApiBaseUrl || !getCloudAccessToken) {
|
|
32613
|
+
return { submitted: false, suppressOutput: false };
|
|
32405
32614
|
}
|
|
32406
|
-
const
|
|
32407
|
-
if (
|
|
32408
|
-
return {
|
|
32615
|
+
const items = parsePlanningTodoAgentJson(outputStr);
|
|
32616
|
+
if (items.length === 0) {
|
|
32617
|
+
return { submitted: false, suppressOutput: false };
|
|
32409
32618
|
}
|
|
32410
|
-
const
|
|
32411
|
-
|
|
32412
|
-
|
|
32413
|
-
|
|
32414
|
-
|
|
32415
|
-
|
|
32416
|
-
|
|
32417
|
-
|
|
32418
|
-
|
|
32419
|
-
|
|
32420
|
-
|
|
32421
|
-
|
|
32422
|
-
|
|
32423
|
-
|
|
32424
|
-
|
|
32425
|
-
|
|
32426
|
-
|
|
32427
|
-
|
|
32428
|
-
|
|
32429
|
-
|
|
32430
|
-
|
|
32431
|
-
|
|
32432
|
-
|
|
32433
|
-
|
|
32434
|
-
|
|
32435
|
-
|
|
32436
|
-
|
|
32437
|
-
|
|
32438
|
-
|
|
32439
|
-
|
|
32440
|
-
|
|
32441
|
-
|
|
32442
|
-
|
|
32443
|
-
|
|
32444
|
-
|
|
32619
|
+
const result = await submitPlanningTodosForTurn({
|
|
32620
|
+
sessionId,
|
|
32621
|
+
turnId: runId,
|
|
32622
|
+
items,
|
|
32623
|
+
cloudApiBaseUrl,
|
|
32624
|
+
getCloudAccessToken
|
|
32625
|
+
});
|
|
32626
|
+
if (!result.ok) {
|
|
32627
|
+
log2(`[Agent] Planning todo submit failed: ${result.error}`);
|
|
32628
|
+
return { submitted: false, suppressOutput: false };
|
|
32629
|
+
}
|
|
32630
|
+
if (runId) consumePlanningSessionTurnOutput(runId);
|
|
32631
|
+
log2(`[Agent] Planning session: stored ${items.length} todo(s) via internal API`);
|
|
32632
|
+
return { submitted: true, suppressOutput: true };
|
|
32633
|
+
}
|
|
32634
|
+
|
|
32635
|
+
// src/agents/acp/prompts/finalize-and-send-prompt-result.ts
|
|
32636
|
+
async function finalizeAndSendPromptResult(params) {
|
|
32637
|
+
const {
|
|
32638
|
+
result,
|
|
32639
|
+
sessionId,
|
|
32640
|
+
runId,
|
|
32641
|
+
promptId,
|
|
32642
|
+
agentType,
|
|
32643
|
+
agentCwd,
|
|
32644
|
+
isPlanningSession,
|
|
32645
|
+
followUpCatalogPromptId,
|
|
32646
|
+
sessionChangeSummaryFilePaths,
|
|
32647
|
+
cloudApiBaseUrl,
|
|
32648
|
+
getCloudAccessToken,
|
|
32649
|
+
e2ee,
|
|
32650
|
+
sendResult,
|
|
32651
|
+
sendSessionUpdate,
|
|
32652
|
+
log: log2
|
|
32653
|
+
} = params;
|
|
32654
|
+
if (sessionId && runId && sendSessionUpdate && agentCwd && result.success) {
|
|
32655
|
+
await collectTurnGitDiffFromPreTurnSnapshot({
|
|
32656
|
+
sessionId,
|
|
32657
|
+
runId,
|
|
32658
|
+
agentCwd,
|
|
32659
|
+
sendSessionUpdate,
|
|
32660
|
+
log: log2
|
|
32661
|
+
});
|
|
32662
|
+
}
|
|
32663
|
+
await maybeUploadE2eeSessionChangeSummariesAfterAgentSuccess({
|
|
32664
|
+
sessionId,
|
|
32665
|
+
runId,
|
|
32666
|
+
resultSuccess: result.success === true,
|
|
32667
|
+
output: result.output,
|
|
32668
|
+
e2ee,
|
|
32669
|
+
cloudApiBaseUrl,
|
|
32670
|
+
getCloudAccessToken,
|
|
32671
|
+
followUpCatalogPromptId,
|
|
32672
|
+
sessionChangeSummaryFilePaths,
|
|
32673
|
+
log: log2
|
|
32674
|
+
});
|
|
32675
|
+
const planningTodosSubmit = await maybeSubmitPlanningTodosAfterAgentSuccess({
|
|
32676
|
+
sessionId,
|
|
32677
|
+
runId,
|
|
32678
|
+
resultSuccess: result.success === true,
|
|
32679
|
+
output: result.output,
|
|
32680
|
+
cloudApiBaseUrl,
|
|
32681
|
+
getCloudAccessToken,
|
|
32682
|
+
log: log2
|
|
32683
|
+
});
|
|
32684
|
+
const errStr = typeof result.error === "string" ? result.error : void 0;
|
|
32685
|
+
const resultStop = typeof result.stopReason === "string" ? result.stopReason.trim() : "";
|
|
32686
|
+
const cancelledByAgent = resultStop.toLowerCase() === "cancelled" || errStr != null && isUserEndedSessionTurnErrorText(errStr);
|
|
32687
|
+
const planningFallbackOutput = !planningTodosSubmit.suppressOutput && isPlanningSession && runId ? consumePlanningSessionTurnOutput(runId) : "";
|
|
32688
|
+
sendResult({
|
|
32689
|
+
type: "prompt_result",
|
|
32690
|
+
id: promptId,
|
|
32691
|
+
...sessionId ? { sessionId } : {},
|
|
32692
|
+
...runId ? { runId } : {},
|
|
32693
|
+
...result,
|
|
32694
|
+
...planningTodosSubmit.suppressOutput ? { output: void 0 } : planningFallbackOutput.trim() !== "" ? { output: planningFallbackOutput } : {},
|
|
32695
|
+
...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
|
|
32696
|
+
...augmentPromptResultAuthFields(agentType, errStr),
|
|
32697
|
+
...!result.success && cancelledByAgent ? { stopReason: "cancelled" } : {}
|
|
32698
|
+
});
|
|
32699
|
+
if (!result.success) {
|
|
32700
|
+
if (cancelledByAgent) {
|
|
32701
|
+
log2("[Agent] Run ended after stop request (stopped by user).");
|
|
32445
32702
|
} else {
|
|
32446
|
-
|
|
32703
|
+
log2(
|
|
32704
|
+
`[Agent] Prompt did not run successfully on the agent (no successful start/completion): ${result.error ?? "Unknown error"}`
|
|
32705
|
+
);
|
|
32447
32706
|
}
|
|
32448
|
-
warnIfDecodedImageMagicUnexpected(imageBytes, mimeType, id.slice(0, 8));
|
|
32449
|
-
logDebug(
|
|
32450
|
-
`[Agent] Loaded prompt image ${id.slice(0, 8)}\u2026: ${imageBytes.length} bytes, mime=${mimeType}, ${encrypted ? "E2EE decrypted" : "plaintext from storage"}`
|
|
32451
|
-
);
|
|
32452
|
-
const dataBase64 = imageBytes.toString("base64");
|
|
32453
|
-
out.push({ mimeType, dataBase64 });
|
|
32454
|
-
}
|
|
32455
|
-
if (out.length !== wantedCount) {
|
|
32456
|
-
return {
|
|
32457
|
-
ok: false,
|
|
32458
|
-
error: `Expected ${wantedCount} image attachment(s) but only loaded ${out.length} (check attachment ids and empty rows).`
|
|
32459
|
-
};
|
|
32460
32707
|
}
|
|
32461
|
-
return { ok: true, images: out };
|
|
32462
32708
|
}
|
|
32463
32709
|
|
|
32464
32710
|
// src/agents/acp/build-forked-session-agent-prompt.ts
|
|
@@ -32518,6 +32764,32 @@ async function fetchCloudSessionMeta(params) {
|
|
|
32518
32764
|
});
|
|
32519
32765
|
}
|
|
32520
32766
|
|
|
32767
|
+
// ../e2ee/src/constants.ts
|
|
32768
|
+
var E2EE_NONCE_BYTES = 12;
|
|
32769
|
+
|
|
32770
|
+
// ../e2ee/src/types.ts
|
|
32771
|
+
function isE2eeEnvelope(value) {
|
|
32772
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
32773
|
+
const o = value;
|
|
32774
|
+
return typeof o.k === "string" && typeof o.n === "string" && typeof o.c === "string";
|
|
32775
|
+
}
|
|
32776
|
+
|
|
32777
|
+
// ../e2ee/src/encoding.ts
|
|
32778
|
+
function base64UrlEncode(bytes) {
|
|
32779
|
+
let binary = "";
|
|
32780
|
+
for (let i = 0; i < bytes.length; i += 1) binary += String.fromCharCode(bytes[i]);
|
|
32781
|
+
const b64 = btoa(binary);
|
|
32782
|
+
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
32783
|
+
}
|
|
32784
|
+
function base64UrlDecode(value) {
|
|
32785
|
+
const b64 = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
32786
|
+
const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
|
|
32787
|
+
const binary = atob(padded);
|
|
32788
|
+
const out = new Uint8Array(binary.length);
|
|
32789
|
+
for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);
|
|
32790
|
+
return out;
|
|
32791
|
+
}
|
|
32792
|
+
|
|
32521
32793
|
// src/lib/e2ee/decrypt-stored-e2ee-content.ts
|
|
32522
32794
|
function parseJsonObject(raw) {
|
|
32523
32795
|
try {
|
|
@@ -32715,125 +32987,278 @@ function enrichIntegrationContentPromptForAgent(params) {
|
|
|
32715
32987
|
return injectIntegrationContentAgentPromptNote(params.agentPromptText, params.sessionId);
|
|
32716
32988
|
}
|
|
32717
32989
|
|
|
32718
|
-
// src/agents/
|
|
32719
|
-
async function
|
|
32720
|
-
const {
|
|
32721
|
-
|
|
32722
|
-
|
|
32723
|
-
|
|
32724
|
-
|
|
32725
|
-
|
|
32726
|
-
|
|
32727
|
-
|
|
32728
|
-
|
|
32729
|
-
|
|
32730
|
-
|
|
32731
|
-
|
|
32732
|
-
|
|
32733
|
-
|
|
32734
|
-
|
|
32735
|
-
|
|
32736
|
-
|
|
32737
|
-
|
|
32738
|
-
|
|
32739
|
-
|
|
32740
|
-
|
|
32741
|
-
|
|
32742
|
-
|
|
32743
|
-
|
|
32744
|
-
|
|
32745
|
-
|
|
32746
|
-
|
|
32747
|
-
|
|
32748
|
-
|
|
32749
|
-
|
|
32750
|
-
|
|
32751
|
-
|
|
32752
|
-
|
|
32753
|
-
|
|
32754
|
-
|
|
32755
|
-
|
|
32756
|
-
|
|
32757
|
-
|
|
32758
|
-
|
|
32759
|
-
|
|
32760
|
-
|
|
32761
|
-
|
|
32762
|
-
|
|
32763
|
-
|
|
32764
|
-
|
|
32765
|
-
|
|
32766
|
-
|
|
32767
|
-
|
|
32768
|
-
|
|
32769
|
-
|
|
32770
|
-
|
|
32771
|
-
|
|
32772
|
-
|
|
32773
|
-
|
|
32774
|
-
|
|
32775
|
-
|
|
32776
|
-
|
|
32777
|
-
|
|
32778
|
-
|
|
32779
|
-
|
|
32780
|
-
|
|
32781
|
-
|
|
32782
|
-
|
|
32783
|
-
|
|
32784
|
-
|
|
32785
|
-
|
|
32786
|
-
|
|
32787
|
-
|
|
32788
|
-
|
|
32789
|
-
|
|
32790
|
-
|
|
32791
|
-
|
|
32990
|
+
// src/agents/planning/enrich-planning-session-prompt-for-agent.ts
|
|
32991
|
+
async function enrichPlanningSessionPromptForAgent(params) {
|
|
32992
|
+
const meta = await fetchCloudSessionMeta({
|
|
32993
|
+
sessionId: params.sessionId,
|
|
32994
|
+
cloudApiBaseUrl: params.cloudApiBaseUrl,
|
|
32995
|
+
getCloudAccessToken: params.getCloudAccessToken
|
|
32996
|
+
});
|
|
32997
|
+
if (!meta.ok) return { promptText: params.promptText, isPlanningSession: false };
|
|
32998
|
+
const sessionKind = parseSessionKind(meta.data.sessionKind);
|
|
32999
|
+
if (sessionKind !== "planning") return { promptText: params.promptText, isPlanningSession: false };
|
|
33000
|
+
const todos = Array.isArray(meta.data.planningTodos) ? meta.data.planningTodos : [];
|
|
33001
|
+
if (params.isNewSession || todos.length === 0) {
|
|
33002
|
+
return {
|
|
33003
|
+
promptText: buildPlanningSessionAgentPrompt(params.promptText),
|
|
33004
|
+
isPlanningSession: true
|
|
33005
|
+
};
|
|
33006
|
+
}
|
|
33007
|
+
return {
|
|
33008
|
+
promptText: buildPlanningSessionFollowUpAgentPrompt(params.promptText, todos),
|
|
33009
|
+
isPlanningSession: true
|
|
33010
|
+
};
|
|
33011
|
+
}
|
|
33012
|
+
|
|
33013
|
+
// src/agents/acp/prompts/prepare-agent-prompt-text.ts
|
|
33014
|
+
async function prepareAgentPromptText(params) {
|
|
33015
|
+
const { promptText, sessionId, runId, isNewSession, cloudApiBaseUrl, getCloudAccessToken } = params;
|
|
33016
|
+
let agentPromptText = promptText;
|
|
33017
|
+
let isPlanningSession = false;
|
|
33018
|
+
if (sessionId && cloudApiBaseUrl && getCloudAccessToken) {
|
|
33019
|
+
agentPromptText = await enrichForkedSessionPromptForAgent({
|
|
33020
|
+
sessionId,
|
|
33021
|
+
promptText,
|
|
33022
|
+
cloudApiBaseUrl,
|
|
33023
|
+
getCloudAccessToken
|
|
33024
|
+
});
|
|
33025
|
+
const planningEnriched = await enrichPlanningSessionPromptForAgent({
|
|
33026
|
+
sessionId,
|
|
33027
|
+
promptText: agentPromptText,
|
|
33028
|
+
isNewSession,
|
|
33029
|
+
cloudApiBaseUrl,
|
|
33030
|
+
getCloudAccessToken
|
|
33031
|
+
});
|
|
33032
|
+
agentPromptText = planningEnriched.promptText;
|
|
33033
|
+
isPlanningSession = planningEnriched.isPlanningSession;
|
|
33034
|
+
}
|
|
33035
|
+
if (isPlanningSession && runId) {
|
|
33036
|
+
registerPlanningSessionTurn(runId);
|
|
33037
|
+
}
|
|
33038
|
+
if (sessionId) {
|
|
33039
|
+
agentPromptText = enrichIntegrationContentPromptForAgent({
|
|
33040
|
+
sessionId,
|
|
33041
|
+
originalPromptText: promptText,
|
|
33042
|
+
agentPromptText
|
|
33043
|
+
});
|
|
33044
|
+
}
|
|
33045
|
+
return { agentPromptText, isPlanningSession };
|
|
33046
|
+
}
|
|
33047
|
+
|
|
33048
|
+
// src/agents/acp/fetch-session-attachments.ts
|
|
33049
|
+
function metaSaysEncrypted(meta) {
|
|
33050
|
+
if (!meta) return false;
|
|
33051
|
+
const e = meta.encrypted;
|
|
33052
|
+
return e === true || e === "true" || e === 1;
|
|
33053
|
+
}
|
|
33054
|
+
function warnIfDecodedImageMagicUnexpected(buf, mimeType, idShort) {
|
|
33055
|
+
const m = mimeType.toLowerCase();
|
|
33056
|
+
if (!m.startsWith("image/") || buf.length < 4) return;
|
|
33057
|
+
const b0 = buf[0];
|
|
33058
|
+
const b1 = buf[1];
|
|
33059
|
+
const b2 = buf[2];
|
|
33060
|
+
const b3 = buf[3];
|
|
33061
|
+
let looksOk = false;
|
|
33062
|
+
if (m.includes("png") && b0 === 137 && b1 === 80 && b2 === 78 && b3 === 71) looksOk = true;
|
|
33063
|
+
else if ((m.includes("jpeg") || m.includes("jpg")) && b0 === 255 && b1 === 216 && b2 === 255) looksOk = true;
|
|
33064
|
+
else if (m.includes("gif") && b0 === 71 && b1 === 73 && b2 === 70) looksOk = true;
|
|
33065
|
+
else if (m.includes("webp") && buf.length >= 12 && buf.subarray(0, 4).toString("ascii") === "RIFF" && buf.subarray(8, 12).toString("ascii") === "WEBP")
|
|
33066
|
+
looksOk = true;
|
|
33067
|
+
else if (!/(png|jpe?g|gif|webp)/i.test(m)) looksOk = true;
|
|
33068
|
+
if (!looksOk) {
|
|
33069
|
+
logDebug(
|
|
33070
|
+
`[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")}`
|
|
33071
|
+
);
|
|
33072
|
+
}
|
|
33073
|
+
}
|
|
33074
|
+
async function fetchSessionAttachmentPayloadsForAgent(params) {
|
|
33075
|
+
const { attachments, sessionId, cloudApiBaseUrl, getCloudAccessToken, e2ee, log: log2 } = params;
|
|
33076
|
+
const token = getCloudAccessToken();
|
|
33077
|
+
if (!token) {
|
|
33078
|
+
return { ok: false, error: "Missing cloud access token; cannot download attachments." };
|
|
33079
|
+
}
|
|
33080
|
+
const wantedCount = attachments.filter((a) => typeof a.attachmentId === "string" && a.attachmentId.trim() !== "").length;
|
|
33081
|
+
if (wantedCount === 0) {
|
|
33082
|
+
return { ok: false, error: "No valid attachment ids in prompt." };
|
|
33083
|
+
}
|
|
33084
|
+
const base = cloudApiBaseUrl.replace(/\/+$/, "");
|
|
33085
|
+
const out = [];
|
|
33086
|
+
for (const a of attachments) {
|
|
33087
|
+
const id = typeof a.attachmentId === "string" ? a.attachmentId.trim() : "";
|
|
33088
|
+
if (!id) continue;
|
|
33089
|
+
const metaUrl = `${base}/internal/sessions/${encodeURIComponent(sessionId)}/attachments/${encodeURIComponent(id)}/meta`;
|
|
33090
|
+
const blobUrl = `${base}/internal/sessions/${encodeURIComponent(sessionId)}/attachments/${encodeURIComponent(id)}/blob`;
|
|
33091
|
+
const metaRes = await fetch(metaUrl, { headers: { Authorization: `Bearer ${token}` } });
|
|
33092
|
+
if (!metaRes.ok) {
|
|
33093
|
+
const t = await metaRes.text().catch(() => "");
|
|
33094
|
+
log2(`[Agent] Attachment meta fetch failed ${metaRes.status}: ${t.slice(0, 200)}`);
|
|
33095
|
+
return { ok: false, error: `Could not load attachment (${id.slice(0, 8)}\u2026): ${metaRes.status}` };
|
|
32792
33096
|
}
|
|
32793
|
-
const
|
|
32794
|
-
|
|
32795
|
-
|
|
32796
|
-
|
|
32797
|
-
|
|
32798
|
-
|
|
32799
|
-
|
|
32800
|
-
log: log2
|
|
32801
|
-
});
|
|
33097
|
+
const meta = await metaRes.json().catch(() => null);
|
|
33098
|
+
const mimeType = typeof meta?.mimeType === "string" && meta.mimeType.trim() ? meta.mimeType.trim() : a.mimeType;
|
|
33099
|
+
const blobRes = await fetch(blobUrl, { headers: { Authorization: `Bearer ${token}` } });
|
|
33100
|
+
if (!blobRes.ok) {
|
|
33101
|
+
const t = await blobRes.text().catch(() => "");
|
|
33102
|
+
log2(`[Agent] Attachment blob fetch failed ${blobRes.status}: ${t.slice(0, 200)}`);
|
|
33103
|
+
return { ok: false, error: `Could not load attachment data (${id.slice(0, 8)}\u2026): ${blobRes.status}` };
|
|
32802
33104
|
}
|
|
32803
|
-
await
|
|
33105
|
+
const buf = Buffer.from(await blobRes.arrayBuffer());
|
|
33106
|
+
let imageBytes;
|
|
33107
|
+
const encrypted = metaSaysEncrypted(meta);
|
|
33108
|
+
if (encrypted) {
|
|
33109
|
+
if (!e2ee) {
|
|
33110
|
+
return { ok: false, error: "Encrypted attachments require E2EE keys on this bridge." };
|
|
33111
|
+
}
|
|
33112
|
+
const k = typeof meta?.k === "string" ? meta.k : "";
|
|
33113
|
+
const n = typeof meta?.n === "string" ? meta.n : "";
|
|
33114
|
+
if (!k || !n) {
|
|
33115
|
+
return { ok: false, error: "Invalid encrypted attachment metadata (missing key id or nonce)." };
|
|
33116
|
+
}
|
|
33117
|
+
const c = base64UrlEncode(buf);
|
|
33118
|
+
imageBytes = e2ee.decryptEnvelopeToBuffer({ k, n, c });
|
|
33119
|
+
} else {
|
|
33120
|
+
imageBytes = buf;
|
|
33121
|
+
}
|
|
33122
|
+
warnIfDecodedImageMagicUnexpected(imageBytes, mimeType, id.slice(0, 8));
|
|
33123
|
+
logDebug(
|
|
33124
|
+
`[Agent] Loaded prompt image ${id.slice(0, 8)}\u2026: ${imageBytes.length} bytes, mime=${mimeType}, ${encrypted ? "E2EE decrypted" : "plaintext from storage"}`
|
|
33125
|
+
);
|
|
33126
|
+
const dataBase64 = imageBytes.toString("base64");
|
|
33127
|
+
out.push({ mimeType, dataBase64 });
|
|
33128
|
+
}
|
|
33129
|
+
if (out.length !== wantedCount) {
|
|
33130
|
+
return {
|
|
33131
|
+
ok: false,
|
|
33132
|
+
error: `Expected ${wantedCount} image attachment(s) but only loaded ${out.length} (check attachment ids and empty rows).`
|
|
33133
|
+
};
|
|
33134
|
+
}
|
|
33135
|
+
return { ok: true, images: out };
|
|
33136
|
+
}
|
|
33137
|
+
|
|
33138
|
+
// src/agents/acp/prompts/resolve-send-prompt-images.ts
|
|
33139
|
+
async function resolveSendPromptImages(params) {
|
|
33140
|
+
const {
|
|
33141
|
+
attachments,
|
|
33142
|
+
sessionId,
|
|
33143
|
+
promptId,
|
|
33144
|
+
runId,
|
|
33145
|
+
agentType,
|
|
33146
|
+
followUpCatalogPromptId,
|
|
33147
|
+
cloudApiBaseUrl,
|
|
33148
|
+
getCloudAccessToken,
|
|
33149
|
+
e2ee,
|
|
33150
|
+
log: log2
|
|
33151
|
+
} = params;
|
|
33152
|
+
if (!attachments || attachments.length === 0) {
|
|
33153
|
+
return { ok: true, sendOpts: {} };
|
|
33154
|
+
}
|
|
33155
|
+
if (!sessionId || !cloudApiBaseUrl || !getCloudAccessToken) {
|
|
33156
|
+
return {
|
|
33157
|
+
ok: false,
|
|
33158
|
+
errorResult: {
|
|
33159
|
+
type: "prompt_result",
|
|
33160
|
+
id: promptId,
|
|
33161
|
+
...sessionId ? { sessionId } : {},
|
|
33162
|
+
...runId ? { runId } : {},
|
|
33163
|
+
success: false,
|
|
33164
|
+
error: "Prompt includes images but the bridge is not configured with a cloud API URL and token to fetch them.",
|
|
33165
|
+
...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
|
|
33166
|
+
...augmentPromptResultAuthFields(agentType, "missing cloud for images download")
|
|
33167
|
+
}
|
|
33168
|
+
};
|
|
33169
|
+
}
|
|
33170
|
+
const resolved = await fetchSessionAttachmentPayloadsForAgent({
|
|
33171
|
+
attachments,
|
|
33172
|
+
sessionId,
|
|
33173
|
+
cloudApiBaseUrl,
|
|
33174
|
+
getCloudAccessToken,
|
|
33175
|
+
e2ee,
|
|
33176
|
+
log: log2
|
|
33177
|
+
});
|
|
33178
|
+
if (!resolved.ok) {
|
|
33179
|
+
return {
|
|
33180
|
+
ok: false,
|
|
33181
|
+
errorResult: {
|
|
33182
|
+
type: "prompt_result",
|
|
33183
|
+
id: promptId,
|
|
33184
|
+
...sessionId ? { sessionId } : {},
|
|
33185
|
+
...runId ? { runId } : {},
|
|
33186
|
+
success: false,
|
|
33187
|
+
error: resolved.error,
|
|
33188
|
+
...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
|
|
33189
|
+
...augmentPromptResultAuthFields(agentType, resolved.error)
|
|
33190
|
+
}
|
|
33191
|
+
};
|
|
33192
|
+
}
|
|
33193
|
+
return { ok: true, sendOpts: { images: resolved.images } };
|
|
33194
|
+
}
|
|
33195
|
+
|
|
33196
|
+
// src/agents/acp/prompts/send-prompt-to-agent.ts
|
|
33197
|
+
async function sendPromptToAgent(options) {
|
|
33198
|
+
const {
|
|
33199
|
+
handle,
|
|
33200
|
+
promptText,
|
|
33201
|
+
promptId,
|
|
33202
|
+
sessionId,
|
|
33203
|
+
runId,
|
|
33204
|
+
agentType,
|
|
33205
|
+
agentCwd,
|
|
33206
|
+
sendResult,
|
|
33207
|
+
sendSessionUpdate,
|
|
33208
|
+
log: log2,
|
|
33209
|
+
followUpCatalogPromptId,
|
|
33210
|
+
sessionChangeSummaryFilePaths,
|
|
33211
|
+
cloudApiBaseUrl,
|
|
33212
|
+
getCloudAccessToken,
|
|
33213
|
+
e2ee,
|
|
33214
|
+
attachments,
|
|
33215
|
+
isNewSession = false
|
|
33216
|
+
} = options;
|
|
33217
|
+
let isPlanningSession = false;
|
|
33218
|
+
try {
|
|
33219
|
+
const prepared = await prepareAgentPromptText({
|
|
33220
|
+
promptText,
|
|
32804
33221
|
sessionId,
|
|
32805
33222
|
runId,
|
|
32806
|
-
|
|
32807
|
-
|
|
32808
|
-
|
|
33223
|
+
isNewSession,
|
|
33224
|
+
cloudApiBaseUrl,
|
|
33225
|
+
getCloudAccessToken
|
|
33226
|
+
});
|
|
33227
|
+
isPlanningSession = prepared.isPlanningSession;
|
|
33228
|
+
const imagesResolved = await resolveSendPromptImages({
|
|
33229
|
+
attachments,
|
|
33230
|
+
sessionId,
|
|
33231
|
+
promptId,
|
|
33232
|
+
runId,
|
|
33233
|
+
agentType,
|
|
33234
|
+
followUpCatalogPromptId,
|
|
32809
33235
|
cloudApiBaseUrl,
|
|
32810
33236
|
getCloudAccessToken,
|
|
33237
|
+
e2ee,
|
|
33238
|
+
log: log2
|
|
33239
|
+
});
|
|
33240
|
+
if (!imagesResolved.ok) {
|
|
33241
|
+
sendResult(imagesResolved.errorResult);
|
|
33242
|
+
return;
|
|
33243
|
+
}
|
|
33244
|
+
const result = await handle.sendPrompt(prepared.agentPromptText, imagesResolved.sendOpts);
|
|
33245
|
+
await finalizeAndSendPromptResult({
|
|
33246
|
+
result,
|
|
33247
|
+
sessionId,
|
|
33248
|
+
runId,
|
|
33249
|
+
promptId,
|
|
33250
|
+
agentType,
|
|
33251
|
+
agentCwd,
|
|
33252
|
+
isPlanningSession,
|
|
32811
33253
|
followUpCatalogPromptId,
|
|
32812
33254
|
sessionChangeSummaryFilePaths,
|
|
33255
|
+
cloudApiBaseUrl,
|
|
33256
|
+
getCloudAccessToken,
|
|
33257
|
+
e2ee,
|
|
33258
|
+
sendResult,
|
|
33259
|
+
sendSessionUpdate,
|
|
32813
33260
|
log: log2
|
|
32814
33261
|
});
|
|
32815
|
-
const errStr = typeof result.error === "string" ? result.error : void 0;
|
|
32816
|
-
const resultStop = typeof result.stopReason === "string" ? result.stopReason.trim() : "";
|
|
32817
|
-
const cancelledByAgent = resultStop.toLowerCase() === "cancelled" || errStr != null && isUserEndedSessionTurnErrorText(errStr);
|
|
32818
|
-
sendResult({
|
|
32819
|
-
type: "prompt_result",
|
|
32820
|
-
id: promptId,
|
|
32821
|
-
...sessionId ? { sessionId } : {},
|
|
32822
|
-
...runId ? { runId } : {},
|
|
32823
|
-
...result,
|
|
32824
|
-
...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
|
|
32825
|
-
...augmentPromptResultAuthFields(agentType, errStr),
|
|
32826
|
-
...!result.success && cancelledByAgent ? { stopReason: "cancelled" } : {}
|
|
32827
|
-
});
|
|
32828
|
-
if (!result.success) {
|
|
32829
|
-
if (cancelledByAgent) {
|
|
32830
|
-
log2("[Agent] Run ended after stop request (stopped by user).");
|
|
32831
|
-
} else {
|
|
32832
|
-
log2(
|
|
32833
|
-
`[Agent] Prompt did not run successfully on the agent (no successful start/completion): ${result.error ?? "Unknown error"}`
|
|
32834
|
-
);
|
|
32835
|
-
}
|
|
32836
|
-
}
|
|
32837
33262
|
} catch (err) {
|
|
32838
33263
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
32839
33264
|
log2(`[Agent] Send failed: ${errMsg}`);
|
|
@@ -32847,6 +33272,8 @@ async function sendPromptToAgent(options) {
|
|
|
32847
33272
|
...followUpCatalogPromptId != null && followUpCatalogPromptId !== "" ? { followUpCatalogPromptId } : {},
|
|
32848
33273
|
...augmentPromptResultAuthFields(agentType, errMsg)
|
|
32849
33274
|
});
|
|
33275
|
+
} finally {
|
|
33276
|
+
if (runId && isPlanningSession) clearPlanningSessionTurn(runId);
|
|
32850
33277
|
}
|
|
32851
33278
|
}
|
|
32852
33279
|
|
|
@@ -32860,15 +33287,36 @@ function getAcpSessionAgentState(ctx, acpSessionAgentKey) {
|
|
|
32860
33287
|
return state;
|
|
32861
33288
|
}
|
|
32862
33289
|
|
|
32863
|
-
// src/agents/acp/manager/handle-prompt.ts
|
|
32864
|
-
function
|
|
33290
|
+
// src/agents/acp/manager/handle-pending-prompt-cancel.ts
|
|
33291
|
+
async function handlePendingPromptCancel(params) {
|
|
33292
|
+
const { ctx, activeRunId, promptId, sessionId, handle, sendResult } = params;
|
|
33293
|
+
if (!ctx.pendingCancelRunIds.has(activeRunId)) {
|
|
33294
|
+
return false;
|
|
33295
|
+
}
|
|
33296
|
+
ctx.pendingCancelRunIds.delete(activeRunId);
|
|
33297
|
+
try {
|
|
33298
|
+
await handle.cancel?.();
|
|
33299
|
+
} catch {
|
|
33300
|
+
}
|
|
33301
|
+
sendResult({
|
|
33302
|
+
type: "prompt_result",
|
|
33303
|
+
id: promptId,
|
|
33304
|
+
...sessionId ? { sessionId } : {},
|
|
33305
|
+
runId: activeRunId,
|
|
33306
|
+
success: false,
|
|
33307
|
+
error: "Stopped by user",
|
|
33308
|
+
stopReason: "cancelled"
|
|
33309
|
+
});
|
|
33310
|
+
return true;
|
|
33311
|
+
}
|
|
33312
|
+
|
|
33313
|
+
// src/agents/acp/manager/run-acp-prompt.ts
|
|
33314
|
+
async function runAcpPrompt(ctx, runCtx, opts) {
|
|
32865
33315
|
const {
|
|
32866
33316
|
promptText,
|
|
32867
33317
|
promptId,
|
|
32868
33318
|
sessionId,
|
|
32869
|
-
runId,
|
|
32870
33319
|
mode,
|
|
32871
|
-
agentType,
|
|
32872
33320
|
agentConfig,
|
|
32873
33321
|
sessionParentPath,
|
|
32874
33322
|
sendResult,
|
|
@@ -32878,109 +33326,99 @@ function handlePrompt(ctx, opts) {
|
|
|
32878
33326
|
cloudApiBaseUrl,
|
|
32879
33327
|
getCloudAccessToken,
|
|
32880
33328
|
e2ee,
|
|
32881
|
-
attachments
|
|
33329
|
+
attachments,
|
|
33330
|
+
isNewSession
|
|
32882
33331
|
} = opts;
|
|
32883
|
-
const
|
|
32884
|
-
|
|
32885
|
-
|
|
32886
|
-
|
|
32887
|
-
|
|
32888
|
-
|
|
32889
|
-
|
|
32890
|
-
|
|
33332
|
+
const { activeRunId, activeAcpAgentKey, activeAcpSessionAgentKey, preferredForPrompt } = runCtx;
|
|
33333
|
+
const acpAgentState = getAcpSessionAgentState(ctx, activeAcpSessionAgentKey);
|
|
33334
|
+
const handle = await ensureAcpClient({
|
|
33335
|
+
state: acpAgentState,
|
|
33336
|
+
acpAgentKey: activeAcpAgentKey,
|
|
33337
|
+
preferredAgentType: preferredForPrompt,
|
|
33338
|
+
mode,
|
|
33339
|
+
agentConfig: agentConfig ?? null,
|
|
33340
|
+
sessionParentPath,
|
|
33341
|
+
resolveRouting: () => ctx.promptRouting.resolveRouting(activeAcpSessionAgentKey),
|
|
33342
|
+
cloudSessionId: sessionId,
|
|
33343
|
+
bridgeAccessPort: ctx.getBridgeAccessPort(),
|
|
33344
|
+
sendSessionUpdate,
|
|
33345
|
+
sendRequest: sendSessionUpdate,
|
|
33346
|
+
log: ctx.log,
|
|
33347
|
+
reportAgentCapabilities: ctx.reportAgentCapabilities
|
|
33348
|
+
});
|
|
33349
|
+
if (!handle) {
|
|
33350
|
+
const errMsg = acpAgentState.lastAcpStartError || "No agent configured. Register local agents on this bridge in the app.";
|
|
33351
|
+
const evaluated = Boolean(preferredForPrompt && errMsg.trim());
|
|
33352
|
+
const suggestsAuth = evaluated ? localAgentErrorSuggestsAuth(preferredForPrompt, errMsg) : false;
|
|
33353
|
+
const auth = suggestsAuth && preferredForPrompt ? { agentAuthRequired: true, agentType: preferredForPrompt } : {};
|
|
32891
33354
|
sendResult({
|
|
32892
33355
|
type: "prompt_result",
|
|
32893
33356
|
id: promptId,
|
|
32894
33357
|
...sessionId ? { sessionId } : {},
|
|
32895
33358
|
runId: activeRunId,
|
|
32896
33359
|
success: false,
|
|
32897
|
-
error:
|
|
33360
|
+
error: errMsg,
|
|
33361
|
+
...auth
|
|
32898
33362
|
});
|
|
32899
33363
|
return;
|
|
32900
33364
|
}
|
|
32901
|
-
|
|
32902
|
-
|
|
32903
|
-
|
|
32904
|
-
|
|
32905
|
-
|
|
32906
|
-
|
|
32907
|
-
|
|
32908
|
-
|
|
32909
|
-
|
|
32910
|
-
|
|
32911
|
-
|
|
32912
|
-
|
|
32913
|
-
|
|
32914
|
-
|
|
32915
|
-
|
|
32916
|
-
|
|
32917
|
-
|
|
33365
|
+
if (!ctx.promptRouting.isRegisteredRun(activeRunId)) {
|
|
33366
|
+
return;
|
|
33367
|
+
}
|
|
33368
|
+
const cancelled = await handlePendingPromptCancel({
|
|
33369
|
+
ctx,
|
|
33370
|
+
activeRunId,
|
|
33371
|
+
promptId,
|
|
33372
|
+
sessionId,
|
|
33373
|
+
handle,
|
|
33374
|
+
sendResult
|
|
33375
|
+
});
|
|
33376
|
+
if (cancelled) return;
|
|
33377
|
+
ctx.promptRouting.setStreamingRunId(activeAcpSessionAgentKey, activeRunId);
|
|
33378
|
+
try {
|
|
33379
|
+
await sendPromptToAgent({
|
|
33380
|
+
handle,
|
|
33381
|
+
promptText,
|
|
33382
|
+
promptId,
|
|
33383
|
+
sessionId,
|
|
33384
|
+
runId: activeRunId,
|
|
33385
|
+
agentType: preferredForPrompt,
|
|
33386
|
+
agentCwd: resolveSessionParentPathForAgentProcess(sessionParentPath),
|
|
33387
|
+
sendResult,
|
|
32918
33388
|
sendSessionUpdate,
|
|
32919
|
-
sendRequest: sendSessionUpdate,
|
|
32920
33389
|
log: ctx.log,
|
|
32921
|
-
|
|
33390
|
+
followUpCatalogPromptId,
|
|
33391
|
+
sessionChangeSummaryFilePaths,
|
|
33392
|
+
cloudApiBaseUrl,
|
|
33393
|
+
getCloudAccessToken,
|
|
33394
|
+
e2ee,
|
|
33395
|
+
attachments,
|
|
33396
|
+
isNewSession
|
|
32922
33397
|
});
|
|
32923
|
-
|
|
32924
|
-
|
|
32925
|
-
|
|
32926
|
-
|
|
32927
|
-
|
|
32928
|
-
|
|
32929
|
-
|
|
32930
|
-
|
|
32931
|
-
|
|
32932
|
-
|
|
32933
|
-
|
|
32934
|
-
error: errMsg,
|
|
32935
|
-
...auth
|
|
32936
|
-
});
|
|
32937
|
-
return;
|
|
32938
|
-
}
|
|
32939
|
-
if (!ctx.promptRouting.isRegisteredRun(activeRunId)) {
|
|
32940
|
-
return;
|
|
32941
|
-
}
|
|
32942
|
-
if (ctx.pendingCancelRunIds.has(activeRunId)) {
|
|
32943
|
-
ctx.pendingCancelRunIds.delete(activeRunId);
|
|
32944
|
-
try {
|
|
32945
|
-
await handle.cancel?.();
|
|
32946
|
-
} catch {
|
|
32947
|
-
}
|
|
33398
|
+
} finally {
|
|
33399
|
+
ctx.promptRouting.clearStreamingRunId(activeAcpSessionAgentKey, activeRunId);
|
|
33400
|
+
}
|
|
33401
|
+
}
|
|
33402
|
+
|
|
33403
|
+
// src/agents/acp/manager/handle-prompt.ts
|
|
33404
|
+
function handlePrompt(ctx, opts) {
|
|
33405
|
+
const { promptId, sessionId, runId, mode, agentType, agentConfig, sendResult } = opts;
|
|
33406
|
+
const runCtx = resolvePromptRunContext(ctx, { runId, mode, agentType, agentConfig, sessionId });
|
|
33407
|
+
if (!runCtx) {
|
|
33408
|
+
if (runId) {
|
|
32948
33409
|
sendResult({
|
|
32949
33410
|
type: "prompt_result",
|
|
32950
33411
|
id: promptId,
|
|
32951
33412
|
...sessionId ? { sessionId } : {},
|
|
32952
|
-
runId
|
|
33413
|
+
runId,
|
|
32953
33414
|
success: false,
|
|
32954
|
-
error: "
|
|
32955
|
-
stopReason: "cancelled"
|
|
33415
|
+
error: "No agent type: ensure the app sends agentType on prompts or agent_config for this bridge."
|
|
32956
33416
|
});
|
|
32957
|
-
return;
|
|
32958
|
-
}
|
|
32959
|
-
ctx.promptRouting.setStreamingRunId(activeAcpSessionAgentKey, activeRunId);
|
|
32960
|
-
try {
|
|
32961
|
-
await sendPromptToAgent({
|
|
32962
|
-
handle,
|
|
32963
|
-
promptText,
|
|
32964
|
-
promptId,
|
|
32965
|
-
sessionId,
|
|
32966
|
-
runId: activeRunId,
|
|
32967
|
-
agentType: preferredForPrompt,
|
|
32968
|
-
agentCwd: resolveSessionParentPathForAgentProcess(sessionParentPath),
|
|
32969
|
-
sendResult,
|
|
32970
|
-
sendSessionUpdate,
|
|
32971
|
-
log: ctx.log,
|
|
32972
|
-
followUpCatalogPromptId,
|
|
32973
|
-
sessionChangeSummaryFilePaths,
|
|
32974
|
-
cloudApiBaseUrl,
|
|
32975
|
-
getCloudAccessToken,
|
|
32976
|
-
e2ee,
|
|
32977
|
-
attachments
|
|
32978
|
-
});
|
|
32979
|
-
} finally {
|
|
32980
|
-
ctx.promptRouting.clearStreamingRunId(activeAcpSessionAgentKey, activeRunId);
|
|
32981
33417
|
}
|
|
33418
|
+
return;
|
|
32982
33419
|
}
|
|
32983
|
-
|
|
33420
|
+
const { activeRunId } = runCtx;
|
|
33421
|
+
void runAcpPrompt(ctx, runCtx, opts).finally(() => {
|
|
32984
33422
|
ctx.promptRouting.unregisterRun(activeRunId);
|
|
32985
33423
|
ctx.runDispatch.delete(activeRunId);
|
|
32986
33424
|
ctx.pendingCancelRunIds.delete(activeRunId);
|
|
@@ -42278,7 +42716,8 @@ async function runPreambleAndPrompt(params) {
|
|
|
42278
42716
|
cloudApiBaseUrl: deps.cloudApiBaseUrl,
|
|
42279
42717
|
getCloudAccessToken: deps.getCloudAccessToken,
|
|
42280
42718
|
e2ee: deps.e2ee,
|
|
42281
|
-
...attachments.length > 0 ? { attachments } : {}
|
|
42719
|
+
...attachments.length > 0 ? { attachments } : {},
|
|
42720
|
+
isNewSession: msg.isNewSession === true
|
|
42282
42721
|
});
|
|
42283
42722
|
}
|
|
42284
42723
|
|