@buildautomaton/cli 0.1.69 → 0.1.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +954 -729
- package/dist/cli.js.map +4 -4
- package/dist/index.js +794 -569
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -29341,6 +29341,18 @@ function getAgentModelFromAgentConfig(config2) {
|
|
|
29341
29341
|
return t !== "" ? t : null;
|
|
29342
29342
|
}
|
|
29343
29343
|
|
|
29344
|
+
// ../types/src/overview/heatmap/constants.ts
|
|
29345
|
+
var HOUR_MS = 36e5;
|
|
29346
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
29347
|
+
|
|
29348
|
+
// ../types/src/bridges/agents/types.ts
|
|
29349
|
+
var INSTALLABLE_BRIDGE_AGENTS = [
|
|
29350
|
+
{ value: "claude-code", label: "Anthropic Claude Code", tokenLabel: "Anthropic API key", tokenEnvVar: "ANTHROPIC_API_KEY" },
|
|
29351
|
+
{ value: "codex-acp", label: "Codex", tokenLabel: "OpenAI API key", tokenEnvVar: "OPENAI_API_KEY" },
|
|
29352
|
+
{ value: "cursor-cli", label: "Cursor CLI agent", tokenLabel: "Cursor API key", tokenEnvVar: "CURSOR_API_KEY" },
|
|
29353
|
+
{ value: "opencode", label: "OpenCode agent", tokenLabel: "Provider API key", tokenEnvVar: "OPENCODE_API_KEY" }
|
|
29354
|
+
];
|
|
29355
|
+
|
|
29344
29356
|
// src/agents/acp/safe-fs-path.ts
|
|
29345
29357
|
import * as path2 from "node:path";
|
|
29346
29358
|
function resolveSafePathUnderCwd(cwd, filePath) {
|
|
@@ -30574,7 +30586,7 @@ function installBridgeProcessResilience() {
|
|
|
30574
30586
|
}
|
|
30575
30587
|
|
|
30576
30588
|
// src/cli-version.ts
|
|
30577
|
-
var CLI_VERSION = "0.1.
|
|
30589
|
+
var CLI_VERSION = "0.1.70".length > 0 ? "0.1.70" : "0.0.0-dev";
|
|
30578
30590
|
|
|
30579
30591
|
// src/connection/heartbeat/constants.ts
|
|
30580
30592
|
var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
|
|
@@ -48443,6 +48455,7 @@ var API_TO_BRIDGE_MESSAGE_TYPES = [
|
|
|
48443
48455
|
"code_nav",
|
|
48444
48456
|
"skill_layout_request",
|
|
48445
48457
|
"install_skills",
|
|
48458
|
+
"install_agent",
|
|
48446
48459
|
"refresh_local_skills",
|
|
48447
48460
|
"bridge_git_context_request",
|
|
48448
48461
|
"list_repo_branches_request"
|
|
@@ -48518,6 +48531,100 @@ var handleBridgeHeartbeatAck = (msg, deps) => {
|
|
|
48518
48531
|
deps.onBridgeHeartbeatAck?.(Math.trunc(raw));
|
|
48519
48532
|
};
|
|
48520
48533
|
|
|
48534
|
+
// src/routing/dispatch/connection.ts
|
|
48535
|
+
function dispatchBridgeConnectionMessage(msg, deps) {
|
|
48536
|
+
switch (msg.type) {
|
|
48537
|
+
case "auth_token":
|
|
48538
|
+
handleAuthToken(msg, deps);
|
|
48539
|
+
break;
|
|
48540
|
+
case "bridge_identified":
|
|
48541
|
+
handleBridgeIdentified(msg, deps);
|
|
48542
|
+
break;
|
|
48543
|
+
case "ha":
|
|
48544
|
+
handleBridgeHeartbeatAck(msg, deps);
|
|
48545
|
+
break;
|
|
48546
|
+
}
|
|
48547
|
+
}
|
|
48548
|
+
|
|
48549
|
+
// src/routing/handlers/preview-environment-control.ts
|
|
48550
|
+
var handlePreviewEnvironmentControl = (msg, deps) => {
|
|
48551
|
+
let wire;
|
|
48552
|
+
try {
|
|
48553
|
+
wire = deps.e2ee ? deps.e2ee.decryptMessage(msg) : msg;
|
|
48554
|
+
} catch (e) {
|
|
48555
|
+
deps.log(`[E2EE] Could not decrypt preview environment command: ${e instanceof Error ? e.message : String(e)}`);
|
|
48556
|
+
return;
|
|
48557
|
+
}
|
|
48558
|
+
const environmentId = typeof wire.environmentId === "string" ? wire.environmentId : "";
|
|
48559
|
+
const action = wire.action === "start" || wire.action === "stop" ? wire.action : null;
|
|
48560
|
+
if (!environmentId || !action) return;
|
|
48561
|
+
deps.previewEnvironmentManager?.handleControl(environmentId, action);
|
|
48562
|
+
};
|
|
48563
|
+
|
|
48564
|
+
// src/routing/handlers/preview-environments-config.ts
|
|
48565
|
+
var VALID_PORT = (p) => typeof p === "number" && Number.isInteger(p) && p > 0 && p < 65536;
|
|
48566
|
+
var handlePreviewEnvironmentsConfig = (msg, deps) => {
|
|
48567
|
+
const previewEnvironments = msg.previewEnvironments;
|
|
48568
|
+
const proxyPorts = Array.isArray(msg.proxyPorts) ? msg.proxyPorts.filter(VALID_PORT) : void 0;
|
|
48569
|
+
setImmediate(() => {
|
|
48570
|
+
deps.previewEnvironmentManager?.applyConfig(previewEnvironments ?? []);
|
|
48571
|
+
const environmentIds = parsePreviewEnvironmentDefs(previewEnvironments ?? []).map((d) => d.environmentId);
|
|
48572
|
+
void deps.previewWorktreeManager?.syncConfiguredEnvironments(environmentIds);
|
|
48573
|
+
if (proxyPorts !== void 0) {
|
|
48574
|
+
deps.updateFirehoseProxyPorts?.(proxyPorts);
|
|
48575
|
+
}
|
|
48576
|
+
});
|
|
48577
|
+
};
|
|
48578
|
+
|
|
48579
|
+
// src/routing/handlers/send-deploy-session-to-preview-result.ts
|
|
48580
|
+
function sendDeploySessionToPreviewResult(ws, id, payload) {
|
|
48581
|
+
if (!ws) return;
|
|
48582
|
+
sendWsMessage(ws, { type: "deploy_session_to_preview_result", id, ...payload });
|
|
48583
|
+
}
|
|
48584
|
+
|
|
48585
|
+
// src/routing/handlers/deploy-session-to-preview.ts
|
|
48586
|
+
var handleDeploySessionToPreviewMessage = (msg, deps) => {
|
|
48587
|
+
if (typeof msg.id !== "string") return;
|
|
48588
|
+
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
48589
|
+
const environmentId = typeof msg.environmentId === "string" ? msg.environmentId : "";
|
|
48590
|
+
if (!sessionId || !environmentId) return;
|
|
48591
|
+
void (async () => {
|
|
48592
|
+
const ws = deps.getWs();
|
|
48593
|
+
const reply = (payload) => sendDeploySessionToPreviewResult(ws, msg.id, payload);
|
|
48594
|
+
try {
|
|
48595
|
+
if (!deps.previewWorktreeManager) {
|
|
48596
|
+
reply({ ok: false, error: "Preview worktree manager unavailable" });
|
|
48597
|
+
return;
|
|
48598
|
+
}
|
|
48599
|
+
const result = await deploySessionToPreviewEnvironment({
|
|
48600
|
+
sessionWorktreeManager: deps.sessionWorktreeManager,
|
|
48601
|
+
previewWorktreeManager: deps.previewWorktreeManager,
|
|
48602
|
+
sessionId,
|
|
48603
|
+
environmentId,
|
|
48604
|
+
log: deps.log
|
|
48605
|
+
});
|
|
48606
|
+
reply(result);
|
|
48607
|
+
} catch (e) {
|
|
48608
|
+
reply({ ok: false, error: e instanceof Error ? e.message : String(e) });
|
|
48609
|
+
}
|
|
48610
|
+
})();
|
|
48611
|
+
};
|
|
48612
|
+
|
|
48613
|
+
// src/routing/dispatch/preview.ts
|
|
48614
|
+
function dispatchBridgePreviewMessage(msg, deps) {
|
|
48615
|
+
switch (msg.type) {
|
|
48616
|
+
case "preview_environments_config":
|
|
48617
|
+
handlePreviewEnvironmentsConfig(msg, deps);
|
|
48618
|
+
break;
|
|
48619
|
+
case "preview_environment_control":
|
|
48620
|
+
handlePreviewEnvironmentControl(msg, deps);
|
|
48621
|
+
break;
|
|
48622
|
+
case "deploy_session_to_preview":
|
|
48623
|
+
handleDeploySessionToPreviewMessage(msg, deps);
|
|
48624
|
+
break;
|
|
48625
|
+
}
|
|
48626
|
+
}
|
|
48627
|
+
|
|
48521
48628
|
// src/agents/acp/from-bridge/handle-bridge-agent-config.ts
|
|
48522
48629
|
function handleBridgeAgentConfig(msg, { acpManager }) {
|
|
48523
48630
|
if (!Array.isArray(msg.agents) || msg.agents.length === 0) return;
|
|
@@ -49156,193 +49263,331 @@ var handleSessionRequestResponseMessage = (msg, deps) => {
|
|
|
49156
49263
|
handleBridgeSessionRequestResponse(msg, deps);
|
|
49157
49264
|
};
|
|
49158
49265
|
|
|
49159
|
-
// src/
|
|
49160
|
-
function
|
|
49161
|
-
|
|
49162
|
-
|
|
49163
|
-
|
|
49164
|
-
|
|
49165
|
-
|
|
49266
|
+
// src/routing/handlers/git/handle-session-git-commit.ts
|
|
49267
|
+
async function handleSessionGitCommitAction(deps, sessionId, msg, reply) {
|
|
49268
|
+
const branch = typeof msg.branch === "string" ? msg.branch : "";
|
|
49269
|
+
const message = typeof msg.message === "string" ? msg.message : "";
|
|
49270
|
+
const pushAfterCommit = msg.pushAfterCommit === true;
|
|
49271
|
+
if (!branch.trim() || !message.trim()) {
|
|
49272
|
+
reply({ ok: false, error: "branch and message are required for commit" });
|
|
49273
|
+
return;
|
|
49274
|
+
}
|
|
49275
|
+
const commitRes = await deps.sessionWorktreeManager.commitSession({
|
|
49276
|
+
sessionId,
|
|
49277
|
+
branch: branch.trim(),
|
|
49278
|
+
message: message.trim(),
|
|
49279
|
+
push: pushAfterCommit
|
|
49280
|
+
});
|
|
49281
|
+
if (!commitRes.ok) {
|
|
49282
|
+
reply({ ok: false, error: commitRes.error ?? "Commit failed" });
|
|
49283
|
+
return;
|
|
49284
|
+
}
|
|
49285
|
+
const st = await deps.sessionWorktreeManager.getSessionWorkingTreeStatus(sessionId);
|
|
49286
|
+
reply({
|
|
49287
|
+
ok: true,
|
|
49288
|
+
hasUncommittedChanges: st.hasUncommittedChanges,
|
|
49289
|
+
hasUnpushedCommits: st.hasUnpushedCommits,
|
|
49290
|
+
uncommittedFileCount: st.uncommittedFileCount
|
|
49166
49291
|
});
|
|
49167
49292
|
}
|
|
49168
49293
|
|
|
49169
|
-
// src/routing/handlers/
|
|
49170
|
-
|
|
49171
|
-
|
|
49172
|
-
|
|
49173
|
-
|
|
49174
|
-
const
|
|
49175
|
-
if (!
|
|
49176
|
-
|
|
49177
|
-
|
|
49178
|
-
|
|
49179
|
-
|
|
49180
|
-
);
|
|
49181
|
-
|
|
49182
|
-
|
|
49183
|
-
|
|
49184
|
-
|
|
49185
|
-
|
|
49294
|
+
// src/routing/handlers/git/session-git-changes-params.ts
|
|
49295
|
+
function readString(value) {
|
|
49296
|
+
return typeof value === "string" ? value.trim() : "";
|
|
49297
|
+
}
|
|
49298
|
+
function readChangesObject(msg) {
|
|
49299
|
+
const changes = msg.changes;
|
|
49300
|
+
if (!changes || typeof changes !== "object" || Array.isArray(changes)) return null;
|
|
49301
|
+
return changes;
|
|
49302
|
+
}
|
|
49303
|
+
function parseSessionGitChangesParams(msg) {
|
|
49304
|
+
const nested = readChangesObject(msg);
|
|
49305
|
+
const file2 = nested?.file && typeof nested.file === "object" && !Array.isArray(nested.file) ? nested.file : null;
|
|
49306
|
+
const repoRelPath = readString(nested?.repoRelPath) || readString(msg.changesRepoRelPath);
|
|
49307
|
+
const viewRaw = nested?.view ?? msg.changesView;
|
|
49308
|
+
const view = viewRaw === "commit" ? "commit" : "working";
|
|
49309
|
+
const commitSha = readString(nested?.commitSha) || readString(msg.changesCommitSha);
|
|
49310
|
+
const recentCommitsLimit = nested?.recentCommitsLimit ?? msg.changesRecentCommitsLimit;
|
|
49311
|
+
return {
|
|
49312
|
+
repoRelPath,
|
|
49313
|
+
view,
|
|
49314
|
+
commitSha,
|
|
49315
|
+
recentCommitsLimit: typeof recentCommitsLimit === "number" || typeof recentCommitsLimit === "string" ? recentCommitsLimit : void 0,
|
|
49316
|
+
fileWorkspaceRelPath: readString(file2?.workspaceRelPath),
|
|
49317
|
+
fileChange: readString(file2?.change),
|
|
49318
|
+
fileMovedFromWorkspaceRelPath: readString(file2?.movedFromWorkspaceRelPath)
|
|
49319
|
+
};
|
|
49186
49320
|
}
|
|
49187
49321
|
|
|
49188
|
-
// src/
|
|
49189
|
-
async function
|
|
49190
|
-
const
|
|
49191
|
-
|
|
49192
|
-
|
|
49322
|
+
// src/routing/handlers/git/handle-session-git-get-change-file-patch.ts
|
|
49323
|
+
async function handleSessionGitGetChangeFilePatchAction(deps, msg, reply) {
|
|
49324
|
+
const changes = parseSessionGitChangesParams(msg);
|
|
49325
|
+
const { repoRelPath: repoRel, view, commitSha, fileWorkspaceRelPath, fileChange, fileMovedFromWorkspaceRelPath } = changes;
|
|
49326
|
+
const change = parseWorkingTreeChangeKind(fileChange);
|
|
49327
|
+
if (!repoRel || !fileWorkspaceRelPath || !change) {
|
|
49328
|
+
reply({
|
|
49329
|
+
ok: false,
|
|
49330
|
+
error: "changes.repoRelPath, changes.file.workspaceRelPath, and changes.file.change are required"
|
|
49331
|
+
});
|
|
49193
49332
|
return;
|
|
49194
49333
|
}
|
|
49195
|
-
|
|
49196
|
-
}
|
|
49197
|
-
|
|
49198
|
-
// src/files/browser/handle-file-browser-read.ts
|
|
49199
|
-
async function handleFileBrowserRead(socket, e2ee, msg, reqPath, sessionParentPath, gitScope) {
|
|
49200
|
-
const result = await executeFileBrowserRead({ msg, reqPath, sessionParentPath, gitScope });
|
|
49201
|
-
if ("error" in result) {
|
|
49202
|
-
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
|
|
49334
|
+
if (view === "commit" && !commitSha) {
|
|
49335
|
+
reply({ ok: false, error: "changes.commitSha is required for commit file patch" });
|
|
49203
49336
|
return;
|
|
49204
49337
|
}
|
|
49205
|
-
const
|
|
49206
|
-
|
|
49207
|
-
|
|
49208
|
-
|
|
49209
|
-
|
|
49210
|
-
|
|
49211
|
-
};
|
|
49212
|
-
|
|
49213
|
-
|
|
49214
|
-
|
|
49215
|
-
|
|
49338
|
+
const patch = await deps.sessionWorktreeManager.getSessionWorkingTreeChangeFilePatch(msg.sessionId, {
|
|
49339
|
+
repoRelPath: repoRel,
|
|
49340
|
+
workspaceRelPath: fileWorkspaceRelPath,
|
|
49341
|
+
change,
|
|
49342
|
+
movedFromWorkspaceRelPath: fileMovedFromWorkspaceRelPath || null,
|
|
49343
|
+
basis: view === "commit" ? { kind: "commit", sha: commitSha } : { kind: "working" }
|
|
49344
|
+
});
|
|
49345
|
+
reply(
|
|
49346
|
+
{
|
|
49347
|
+
ok: true,
|
|
49348
|
+
patchContent: patch.patchContent ?? null,
|
|
49349
|
+
totalLines: patch.totalLines
|
|
49350
|
+
},
|
|
49351
|
+
["patchContent"]
|
|
49352
|
+
);
|
|
49216
49353
|
}
|
|
49217
49354
|
|
|
49218
|
-
// src/
|
|
49219
|
-
|
|
49220
|
-
function
|
|
49221
|
-
|
|
49222
|
-
|
|
49223
|
-
try {
|
|
49224
|
-
const reqPath = msg.path.replace(/^\/+/, "") || ".";
|
|
49225
|
-
const sessionParentPath = sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : void 0;
|
|
49226
|
-
const gitScope = resolveGitBranchScope(msg);
|
|
49227
|
-
if (msg.source === "git_branch" && typeof msg.repoRelPath === "string" && typeof msg.branch === "string" && msg.branch.trim().length > 0 && !gitScope) {
|
|
49228
|
-
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: "Invalid repository path" });
|
|
49229
|
-
return;
|
|
49230
|
-
}
|
|
49231
|
-
if (msg.op === "read") {
|
|
49232
|
-
await handleFileBrowserRead(socket, e2ee, msg, reqPath, sessionParentPath, gitScope);
|
|
49233
|
-
} else {
|
|
49234
|
-
await handleFileBrowserList(socket, e2ee, msg.id, reqPath, sessionParentPath, gitScope);
|
|
49235
|
-
}
|
|
49236
|
-
} finally {
|
|
49237
|
-
endFileBrowserRequest();
|
|
49238
|
-
}
|
|
49239
|
-
})();
|
|
49355
|
+
// src/routing/handlers/git/coalesce-list-changes.ts
|
|
49356
|
+
var listChangesInflight = /* @__PURE__ */ new Map();
|
|
49357
|
+
function normalizeListChangesRepoPathRelativeToWorkspaceRoot(repoRelPath) {
|
|
49358
|
+
if (!repoRelPath?.trim()) return "";
|
|
49359
|
+
return normalizeRepoPathRelativeToWorkspaceRoot(repoRelPath.trim());
|
|
49240
49360
|
}
|
|
49241
|
-
|
|
49242
|
-
|
|
49243
|
-
|
|
49244
|
-
|
|
49245
|
-
|
|
49246
|
-
|
|
49247
|
-
|
|
49248
|
-
|
|
49249
|
-
|
|
49250
|
-
|
|
49251
|
-
|
|
49252
|
-
|
|
49253
|
-
|
|
49254
|
-
|
|
49255
|
-
|
|
49256
|
-
|
|
49257
|
-
|
|
49258
|
-
|
|
49259
|
-
|
|
49260
|
-
|
|
49261
|
-
|
|
49361
|
+
function listChangesInflightKey(sessionId, opts) {
|
|
49362
|
+
const basis = opts?.basis;
|
|
49363
|
+
return [
|
|
49364
|
+
sessionId,
|
|
49365
|
+
normalizeListChangesRepoPathRelativeToWorkspaceRoot(opts?.repoRelPath),
|
|
49366
|
+
basis?.kind === "commit" ? `commit:${basis.sha}` : "working",
|
|
49367
|
+
String(opts?.recentCommitsLimit ?? "")
|
|
49368
|
+
].join("|");
|
|
49369
|
+
}
|
|
49370
|
+
function getSessionWorkingTreeChangeDetailsCoalesced(sessionWorktreeManager, sessionId, opts) {
|
|
49371
|
+
const key = listChangesInflightKey(sessionId, opts);
|
|
49372
|
+
const existing = listChangesInflight.get(key);
|
|
49373
|
+
if (existing) return existing;
|
|
49374
|
+
const promise2 = sessionWorktreeManager.getSessionWorkingTreeChangeDetails(sessionId, opts).finally(() => {
|
|
49375
|
+
if (listChangesInflight.get(key) === promise2) listChangesInflight.delete(key);
|
|
49376
|
+
});
|
|
49377
|
+
listChangesInflight.set(key, promise2);
|
|
49378
|
+
return promise2;
|
|
49379
|
+
}
|
|
49380
|
+
|
|
49381
|
+
// src/routing/handlers/git/handle-session-git-list-changes.ts
|
|
49382
|
+
async function handleSessionGitListChangesAction(deps, msg, reply) {
|
|
49383
|
+
const changes = parseSessionGitChangesParams(msg);
|
|
49384
|
+
const { repoRelPath: repoRel, view, commitSha, recentCommitsLimit } = changes;
|
|
49385
|
+
if (view === "commit") {
|
|
49386
|
+
if (!repoRel || !commitSha) {
|
|
49387
|
+
reply({
|
|
49388
|
+
ok: false,
|
|
49389
|
+
error: "changes.repoRelPath and changes.commitSha are required for commit view"
|
|
49390
|
+
});
|
|
49262
49391
|
return;
|
|
49263
49392
|
}
|
|
49264
|
-
|
|
49265
|
-
|
|
49266
|
-
|
|
49267
|
-
|
|
49268
|
-
|
|
49269
|
-
|
|
49270
|
-
|
|
49271
|
-
|
|
49272
|
-
|
|
49393
|
+
}
|
|
49394
|
+
const opts = repoRel && view === "commit" && commitSha ? {
|
|
49395
|
+
repoRelPath: repoRel,
|
|
49396
|
+
basis: { kind: "commit", sha: commitSha },
|
|
49397
|
+
recentCommitsLimit
|
|
49398
|
+
} : repoRel ? { repoRelPath: repoRel, basis: { kind: "working" }, recentCommitsLimit } : recentCommitsLimit !== void 0 ? { recentCommitsLimit } : void 0;
|
|
49399
|
+
const repos = await getSessionWorkingTreeChangeDetailsCoalesced(
|
|
49400
|
+
deps.sessionWorktreeManager,
|
|
49401
|
+
msg.sessionId,
|
|
49402
|
+
opts
|
|
49403
|
+
);
|
|
49404
|
+
reply({ ok: true, repos }, ["repos"]);
|
|
49273
49405
|
}
|
|
49274
|
-
|
|
49275
|
-
|
|
49276
|
-
|
|
49277
|
-
|
|
49278
|
-
|
|
49406
|
+
|
|
49407
|
+
// src/routing/handlers/git/handle-session-git-push.ts
|
|
49408
|
+
async function handleSessionGitPushAction(deps, sessionId, reply) {
|
|
49409
|
+
const pushRes = await deps.sessionWorktreeManager.pushSessionUpstream(sessionId);
|
|
49410
|
+
if (!pushRes.ok) {
|
|
49411
|
+
reply({ ok: false, error: pushRes.error ?? "Push failed" });
|
|
49412
|
+
return;
|
|
49413
|
+
}
|
|
49414
|
+
const st = await deps.sessionWorktreeManager.getSessionWorkingTreeStatus(sessionId);
|
|
49415
|
+
reply({
|
|
49416
|
+
ok: true,
|
|
49417
|
+
hasUncommittedChanges: st.hasUncommittedChanges,
|
|
49418
|
+
hasUnpushedCommits: st.hasUnpushedCommits,
|
|
49419
|
+
uncommittedFileCount: st.uncommittedFileCount
|
|
49279
49420
|
});
|
|
49280
49421
|
}
|
|
49281
49422
|
|
|
49282
|
-
// src/routing/handlers/
|
|
49283
|
-
function
|
|
49284
|
-
|
|
49285
|
-
|
|
49286
|
-
|
|
49287
|
-
|
|
49288
|
-
|
|
49289
|
-
|
|
49290
|
-
|
|
49291
|
-
const socket = getWs();
|
|
49292
|
-
if (!socket) return;
|
|
49293
|
-
handleFileBrowserSearch(
|
|
49294
|
-
msg,
|
|
49295
|
-
socket,
|
|
49296
|
-
e2ee,
|
|
49297
|
-
sessionWorktreeManager
|
|
49298
|
-
);
|
|
49423
|
+
// src/routing/handlers/git/handle-session-git-status.ts
|
|
49424
|
+
async function handleSessionGitStatusAction(deps, sessionId, reply) {
|
|
49425
|
+
const r = await deps.sessionWorktreeManager.getSessionWorkingTreeStatus(sessionId);
|
|
49426
|
+
reply({
|
|
49427
|
+
ok: true,
|
|
49428
|
+
hasUncommittedChanges: r.hasUncommittedChanges,
|
|
49429
|
+
hasUnpushedCommits: r.hasUnpushedCommits,
|
|
49430
|
+
uncommittedFileCount: r.uncommittedFileCount
|
|
49431
|
+
});
|
|
49299
49432
|
}
|
|
49300
49433
|
|
|
49301
|
-
// src/
|
|
49302
|
-
|
|
49303
|
-
|
|
49304
|
-
const
|
|
49305
|
-
|
|
49306
|
-
|
|
49307
|
-
|
|
49308
|
-
|
|
49434
|
+
// src/routing/handlers/git/send-session-git-result.ts
|
|
49435
|
+
function sendSessionGitResult(ws, id, payload, e2ee, encryptedFields = []) {
|
|
49436
|
+
if (!ws) return;
|
|
49437
|
+
const message = { type: "session_git_result", id, ...payload };
|
|
49438
|
+
let wire = message;
|
|
49439
|
+
if (e2ee && encryptedFields.length > 0) {
|
|
49440
|
+
wire = e2ee.encryptFields(message, encryptedFields);
|
|
49441
|
+
}
|
|
49442
|
+
sendWsMessage(ws, wire);
|
|
49309
49443
|
}
|
|
49310
49444
|
|
|
49311
|
-
// src/
|
|
49312
|
-
|
|
49445
|
+
// src/routing/handlers/git/session-git-request.ts
|
|
49446
|
+
var handleSessionGitRequestMessage = (msg, deps) => {
|
|
49447
|
+
if (typeof msg.id !== "string") return;
|
|
49448
|
+
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
49449
|
+
const action = msg.action;
|
|
49450
|
+
if (!sessionId || action !== "status" && action !== "push" && action !== "commit" && action !== "list_changes" && action !== "file_diff")
|
|
49451
|
+
return;
|
|
49313
49452
|
void (async () => {
|
|
49314
|
-
const
|
|
49315
|
-
|
|
49316
|
-
|
|
49317
|
-
|
|
49318
|
-
|
|
49453
|
+
const ws = deps.getWs();
|
|
49454
|
+
const reply = (payload, encryptedFields = []) => sendSessionGitResult(ws, msg.id, payload, deps.e2ee, encryptedFields);
|
|
49455
|
+
try {
|
|
49456
|
+
if (action === "status") {
|
|
49457
|
+
await handleSessionGitStatusAction(deps, sessionId, reply);
|
|
49458
|
+
return;
|
|
49459
|
+
}
|
|
49460
|
+
if (action === "list_changes") {
|
|
49461
|
+
await handleSessionGitListChangesAction(deps, { ...msg, sessionId }, reply);
|
|
49462
|
+
return;
|
|
49463
|
+
}
|
|
49464
|
+
if (action === "file_diff") {
|
|
49465
|
+
await handleSessionGitGetChangeFilePatchAction(deps, { ...msg, sessionId }, reply);
|
|
49466
|
+
return;
|
|
49467
|
+
}
|
|
49468
|
+
if (action === "push") {
|
|
49469
|
+
await handleSessionGitPushAction(deps, sessionId, reply);
|
|
49470
|
+
return;
|
|
49471
|
+
}
|
|
49472
|
+
await handleSessionGitCommitAction(deps, sessionId, msg, reply);
|
|
49473
|
+
} catch (e) {
|
|
49474
|
+
reply({ ok: false, error: e instanceof Error ? e.message : String(e) });
|
|
49475
|
+
}
|
|
49476
|
+
})();
|
|
49477
|
+
};
|
|
49478
|
+
|
|
49479
|
+
// src/routing/handlers/rename-session-branch.ts
|
|
49480
|
+
var handleRenameSessionBranchMessage = (msg, deps) => {
|
|
49481
|
+
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
49482
|
+
const newBranch = typeof msg.newBranch === "string" ? msg.newBranch : "";
|
|
49483
|
+
if (!sessionId || !newBranch) return;
|
|
49484
|
+
void deps.sessionWorktreeManager.renameSessionBranch(sessionId, newBranch);
|
|
49485
|
+
};
|
|
49486
|
+
|
|
49487
|
+
// src/routing/handlers/session-archived.ts
|
|
49488
|
+
var handleSessionArchivedMessage = (msg, deps) => {
|
|
49489
|
+
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
49490
|
+
if (!sessionId) return;
|
|
49491
|
+
void deps.sessionWorktreeManager.removeSessionWorktrees(sessionId);
|
|
49492
|
+
};
|
|
49493
|
+
|
|
49494
|
+
// src/routing/handlers/session-discarded.ts
|
|
49495
|
+
var handleSessionDiscardedMessage = (msg, deps) => {
|
|
49496
|
+
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
49497
|
+
if (!sessionId) return;
|
|
49498
|
+
void deps.sessionWorktreeManager.removeSessionWorktrees(sessionId);
|
|
49499
|
+
};
|
|
49500
|
+
|
|
49501
|
+
// src/routing/handlers/revert-turn-snapshot.ts
|
|
49502
|
+
import * as fs59 from "node:fs";
|
|
49503
|
+
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
49504
|
+
const id = typeof msg.id === "string" ? msg.id : "";
|
|
49505
|
+
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
49506
|
+
const turnId = typeof msg.turnId === "string" ? msg.turnId : "";
|
|
49507
|
+
if (!id || !sessionId || !turnId) return;
|
|
49508
|
+
const { getWs, log: log2, sessionWorktreeManager } = deps;
|
|
49509
|
+
void (async () => {
|
|
49510
|
+
const s = getWs();
|
|
49511
|
+
if (!s) return;
|
|
49512
|
+
const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
|
|
49513
|
+
const file2 = snapshotFilePath(agentBase, turnId);
|
|
49514
|
+
try {
|
|
49515
|
+
await fs59.promises.access(file2, fs59.constants.F_OK);
|
|
49516
|
+
} catch {
|
|
49517
|
+
sendWsMessage(s, {
|
|
49518
|
+
type: "revert_turn_snapshot_result",
|
|
49519
|
+
id,
|
|
49520
|
+
ok: false,
|
|
49521
|
+
error: "No snapshot found for this turn (git state may be unavailable)."
|
|
49522
|
+
});
|
|
49523
|
+
return;
|
|
49524
|
+
}
|
|
49525
|
+
const res = await applyPreTurnSnapshot(file2, log2);
|
|
49526
|
+
sendWsMessage(s, {
|
|
49527
|
+
type: "revert_turn_snapshot_result",
|
|
49528
|
+
id,
|
|
49529
|
+
ok: res.ok,
|
|
49530
|
+
...res.error ? { error: res.error } : {}
|
|
49319
49531
|
});
|
|
49320
49532
|
})();
|
|
49533
|
+
};
|
|
49534
|
+
|
|
49535
|
+
// src/routing/dispatch/session.ts
|
|
49536
|
+
function dispatchBridgeSessionMessage(msg, deps) {
|
|
49537
|
+
switch (msg.type) {
|
|
49538
|
+
case "agent_config":
|
|
49539
|
+
handleAgentConfigMessage(msg, deps);
|
|
49540
|
+
break;
|
|
49541
|
+
case "prompt_queue_state":
|
|
49542
|
+
handlePromptQueueStateMessage(msg, deps);
|
|
49543
|
+
break;
|
|
49544
|
+
case "prompt":
|
|
49545
|
+
handlePromptMessage(msg, deps);
|
|
49546
|
+
break;
|
|
49547
|
+
case "session_git_request":
|
|
49548
|
+
handleSessionGitRequestMessage(msg, deps);
|
|
49549
|
+
break;
|
|
49550
|
+
case "rename_session_branch":
|
|
49551
|
+
handleRenameSessionBranchMessage(msg, deps);
|
|
49552
|
+
break;
|
|
49553
|
+
case "session_archived":
|
|
49554
|
+
handleSessionArchivedMessage(msg, deps);
|
|
49555
|
+
break;
|
|
49556
|
+
case "session_discarded":
|
|
49557
|
+
handleSessionDiscardedMessage(msg, deps);
|
|
49558
|
+
break;
|
|
49559
|
+
case "revert_turn_snapshot":
|
|
49560
|
+
handleRevertTurnSnapshotMessage(msg, deps);
|
|
49561
|
+
break;
|
|
49562
|
+
case "cursor_request_response":
|
|
49563
|
+
handleSessionRequestResponseMessage(msg, deps);
|
|
49564
|
+
break;
|
|
49565
|
+
}
|
|
49321
49566
|
}
|
|
49322
49567
|
|
|
49323
|
-
// src/
|
|
49324
|
-
|
|
49568
|
+
// src/skills/handle-skill-call.ts
|
|
49569
|
+
function handleSkillCall(msg, socket, log2) {
|
|
49570
|
+
callSkill(msg.skillId, msg.operationId, msg.params ?? {}).then((result) => {
|
|
49571
|
+
sendWsMessage(socket, { type: "skill_result", id: msg.id, result });
|
|
49572
|
+
}).catch((err) => {
|
|
49573
|
+
sendWsMessage(socket, { type: "skill_result", id: msg.id, error: String(err) });
|
|
49574
|
+
log2(`[Bridge service] Skill invocation failed (${msg.skillId}/${msg.operationId}): ${err}`);
|
|
49575
|
+
});
|
|
49576
|
+
}
|
|
49325
49577
|
|
|
49326
|
-
// src/routing/handlers/
|
|
49327
|
-
|
|
49328
|
-
|
|
49578
|
+
// src/routing/handlers/skill-call.ts
|
|
49579
|
+
var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
49580
|
+
const skillId = typeof msg.skillId === "string" ? msg.skillId : "";
|
|
49581
|
+
const operationId = typeof msg.operationId === "string" ? msg.operationId : "";
|
|
49582
|
+
if (!skillId || !operationId) return;
|
|
49329
49583
|
const socket = getWs();
|
|
49330
49584
|
if (!socket) return;
|
|
49331
|
-
|
|
49332
|
-
{
|
|
49333
|
-
id: msg.id,
|
|
49334
|
-
type: "code_nav",
|
|
49335
|
-
op: msg.op === "references" ? "references" : msg.op === "symbols" ? "symbols" : msg.op === "definitions" ? "definitions" : "definition",
|
|
49336
|
-
path: msg.path,
|
|
49337
|
-
line: typeof msg.line === "number" ? msg.line : 1,
|
|
49338
|
-
column: typeof msg.column === "number" ? msg.column : 0,
|
|
49339
|
-
sessionId: msg.sessionId
|
|
49340
|
-
},
|
|
49585
|
+
handleSkillCall(
|
|
49586
|
+
{ id: msg.id, skillId, operationId, params: msg.params },
|
|
49341
49587
|
socket,
|
|
49342
|
-
|
|
49343
|
-
sessionWorktreeManager
|
|
49588
|
+
log2
|
|
49344
49589
|
);
|
|
49345
|
-
}
|
|
49590
|
+
};
|
|
49346
49591
|
|
|
49347
49592
|
// src/routing/handlers/skill-layout-request.ts
|
|
49348
49593
|
function handleSkillLayoutRequest(msg, deps) {
|
|
@@ -49365,413 +49610,409 @@ function isValidRemoteSkillInstallItem(item) {
|
|
|
49365
49610
|
|
|
49366
49611
|
// src/skills/install/install-remote-skills-async.ts
|
|
49367
49612
|
init_yield_to_event_loop();
|
|
49368
|
-
import
|
|
49369
|
-
import
|
|
49613
|
+
import fs60 from "node:fs";
|
|
49614
|
+
import path79 from "node:path";
|
|
49370
49615
|
|
|
49371
49616
|
// src/skills/install/constants.ts
|
|
49372
49617
|
var INSTALL_SKILLS_YIELD_EVERY = 16;
|
|
49373
49618
|
|
|
49374
49619
|
// src/skills/install/install-remote-skills-async.ts
|
|
49375
49620
|
async function writeInstallFileAsync(skillDir, f, filesWritten) {
|
|
49376
|
-
if (typeof f.path !== "string" || !f.text && !f.base64) return;
|
|
49377
|
-
if (++filesWritten.count % INSTALL_SKILLS_YIELD_EVERY === 0) {
|
|
49378
|
-
await yieldToEventLoop();
|
|
49379
|
-
}
|
|
49380
|
-
const dest =
|
|
49381
|
-
await
|
|
49382
|
-
if (f.text !== void 0) {
|
|
49383
|
-
await
|
|
49384
|
-
} else if (f.base64) {
|
|
49385
|
-
await
|
|
49386
|
-
}
|
|
49387
|
-
}
|
|
49388
|
-
async function installRemoteSkillsAsync(cwd, targetDir, items) {
|
|
49389
|
-
const installed2 = [];
|
|
49390
|
-
if (!Array.isArray(items)) {
|
|
49391
|
-
return { success: false, error: "Invalid items" };
|
|
49392
|
-
}
|
|
49393
|
-
const filesWritten = { count: 0 };
|
|
49394
|
-
try {
|
|
49395
|
-
for (const item of items) {
|
|
49396
|
-
if (!isValidRemoteSkillInstallItem(item)) continue;
|
|
49397
|
-
const skillDir = path80.join(cwd, targetDir, item.skillName);
|
|
49398
|
-
for (const f of item.files) {
|
|
49399
|
-
await writeInstallFileAsync(skillDir, f, filesWritten);
|
|
49400
|
-
}
|
|
49401
|
-
installed2.push({
|
|
49402
|
-
sourceId: item.sourceId,
|
|
49403
|
-
skillName: item.skillName,
|
|
49404
|
-
versionHash: item.versionHash
|
|
49405
|
-
});
|
|
49406
|
-
}
|
|
49407
|
-
return { success: true, installed: installed2 };
|
|
49408
|
-
} catch (e) {
|
|
49409
|
-
return { success: false, error: e instanceof Error ? e.message : String(e) };
|
|
49410
|
-
}
|
|
49411
|
-
}
|
|
49412
|
-
|
|
49413
|
-
// src/routing/handlers/install-skills.ts
|
|
49414
|
-
var handleInstallSkillsMessage = (msg, deps) => {
|
|
49415
|
-
const id = typeof msg.id === "string" ? msg.id : "";
|
|
49416
|
-
const targetDir = typeof msg.targetDir === "string" && msg.targetDir.trim() ? msg.targetDir.trim() : ".agents/skills";
|
|
49417
|
-
const rawItems = msg.items;
|
|
49418
|
-
const cwd = getBridgeRoot();
|
|
49419
|
-
void (async () => {
|
|
49420
|
-
const socket = deps.getWs();
|
|
49421
|
-
const result = await installRemoteSkillsAsync(cwd, targetDir, rawItems);
|
|
49422
|
-
if (!result.success) {
|
|
49423
|
-
const err = result.error ?? "Invalid items";
|
|
49424
|
-
deps.log(`[Bridge service] Install skills failed: ${err}`);
|
|
49425
|
-
if (socket) {
|
|
49426
|
-
sendWsMessage(socket, { type: "install_skills_result", id, success: false, error: err });
|
|
49427
|
-
}
|
|
49428
|
-
return;
|
|
49429
|
-
}
|
|
49430
|
-
if (socket) {
|
|
49431
|
-
sendWsMessage(socket, { type: "install_skills_result", id, success: true, installed: result.installed });
|
|
49432
|
-
}
|
|
49433
|
-
})();
|
|
49434
|
-
};
|
|
49435
|
-
|
|
49436
|
-
// src/routing/handlers/refresh-local-skills.ts
|
|
49437
|
-
var handleRefreshLocalSkills = (_msg, deps) => {
|
|
49438
|
-
setImmediate(() => {
|
|
49439
|
-
deps.sendLocalSkillsReport?.();
|
|
49440
|
-
});
|
|
49441
|
-
};
|
|
49442
|
-
|
|
49443
|
-
// src/routing/handlers/git/handle-session-git-commit.ts
|
|
49444
|
-
async function handleSessionGitCommitAction(deps, sessionId, msg, reply) {
|
|
49445
|
-
const branch = typeof msg.branch === "string" ? msg.branch : "";
|
|
49446
|
-
const message = typeof msg.message === "string" ? msg.message : "";
|
|
49447
|
-
const pushAfterCommit = msg.pushAfterCommit === true;
|
|
49448
|
-
if (!branch.trim() || !message.trim()) {
|
|
49449
|
-
reply({ ok: false, error: "branch and message are required for commit" });
|
|
49450
|
-
return;
|
|
49451
|
-
}
|
|
49452
|
-
const commitRes = await deps.sessionWorktreeManager.commitSession({
|
|
49453
|
-
sessionId,
|
|
49454
|
-
branch: branch.trim(),
|
|
49455
|
-
message: message.trim(),
|
|
49456
|
-
push: pushAfterCommit
|
|
49457
|
-
});
|
|
49458
|
-
if (!commitRes.ok) {
|
|
49459
|
-
reply({ ok: false, error: commitRes.error ?? "Commit failed" });
|
|
49460
|
-
return;
|
|
49461
|
-
}
|
|
49462
|
-
const st = await deps.sessionWorktreeManager.getSessionWorkingTreeStatus(sessionId);
|
|
49463
|
-
reply({
|
|
49464
|
-
ok: true,
|
|
49465
|
-
hasUncommittedChanges: st.hasUncommittedChanges,
|
|
49466
|
-
hasUnpushedCommits: st.hasUnpushedCommits,
|
|
49467
|
-
uncommittedFileCount: st.uncommittedFileCount
|
|
49468
|
-
});
|
|
49469
|
-
}
|
|
49470
|
-
|
|
49471
|
-
// src/routing/handlers/git/session-git-changes-params.ts
|
|
49472
|
-
function readString(value) {
|
|
49473
|
-
return typeof value === "string" ? value.trim() : "";
|
|
49474
|
-
}
|
|
49475
|
-
function readChangesObject(msg) {
|
|
49476
|
-
const changes = msg.changes;
|
|
49477
|
-
if (!changes || typeof changes !== "object" || Array.isArray(changes)) return null;
|
|
49478
|
-
return changes;
|
|
49479
|
-
}
|
|
49480
|
-
function parseSessionGitChangesParams(msg) {
|
|
49481
|
-
const nested = readChangesObject(msg);
|
|
49482
|
-
const file2 = nested?.file && typeof nested.file === "object" && !Array.isArray(nested.file) ? nested.file : null;
|
|
49483
|
-
const repoRelPath = readString(nested?.repoRelPath) || readString(msg.changesRepoRelPath);
|
|
49484
|
-
const viewRaw = nested?.view ?? msg.changesView;
|
|
49485
|
-
const view = viewRaw === "commit" ? "commit" : "working";
|
|
49486
|
-
const commitSha = readString(nested?.commitSha) || readString(msg.changesCommitSha);
|
|
49487
|
-
const recentCommitsLimit = nested?.recentCommitsLimit ?? msg.changesRecentCommitsLimit;
|
|
49488
|
-
return {
|
|
49489
|
-
repoRelPath,
|
|
49490
|
-
view,
|
|
49491
|
-
commitSha,
|
|
49492
|
-
recentCommitsLimit: typeof recentCommitsLimit === "number" || typeof recentCommitsLimit === "string" ? recentCommitsLimit : void 0,
|
|
49493
|
-
fileWorkspaceRelPath: readString(file2?.workspaceRelPath),
|
|
49494
|
-
fileChange: readString(file2?.change),
|
|
49495
|
-
fileMovedFromWorkspaceRelPath: readString(file2?.movedFromWorkspaceRelPath)
|
|
49496
|
-
};
|
|
49497
|
-
}
|
|
49498
|
-
|
|
49499
|
-
// src/routing/handlers/git/handle-session-git-get-change-file-patch.ts
|
|
49500
|
-
async function handleSessionGitGetChangeFilePatchAction(deps, msg, reply) {
|
|
49501
|
-
const changes = parseSessionGitChangesParams(msg);
|
|
49502
|
-
const { repoRelPath: repoRel, view, commitSha, fileWorkspaceRelPath, fileChange, fileMovedFromWorkspaceRelPath } = changes;
|
|
49503
|
-
const change = parseWorkingTreeChangeKind(fileChange);
|
|
49504
|
-
if (!repoRel || !fileWorkspaceRelPath || !change) {
|
|
49505
|
-
reply({
|
|
49506
|
-
ok: false,
|
|
49507
|
-
error: "changes.repoRelPath, changes.file.workspaceRelPath, and changes.file.change are required"
|
|
49508
|
-
});
|
|
49509
|
-
return;
|
|
49510
|
-
}
|
|
49511
|
-
if (view === "commit" && !commitSha) {
|
|
49512
|
-
reply({ ok: false, error: "changes.commitSha is required for commit file patch" });
|
|
49513
|
-
return;
|
|
49514
|
-
}
|
|
49515
|
-
const patch = await deps.sessionWorktreeManager.getSessionWorkingTreeChangeFilePatch(msg.sessionId, {
|
|
49516
|
-
repoRelPath: repoRel,
|
|
49517
|
-
workspaceRelPath: fileWorkspaceRelPath,
|
|
49518
|
-
change,
|
|
49519
|
-
movedFromWorkspaceRelPath: fileMovedFromWorkspaceRelPath || null,
|
|
49520
|
-
basis: view === "commit" ? { kind: "commit", sha: commitSha } : { kind: "working" }
|
|
49521
|
-
});
|
|
49522
|
-
reply(
|
|
49523
|
-
{
|
|
49524
|
-
ok: true,
|
|
49525
|
-
patchContent: patch.patchContent ?? null,
|
|
49526
|
-
totalLines: patch.totalLines
|
|
49527
|
-
},
|
|
49528
|
-
["patchContent"]
|
|
49529
|
-
);
|
|
49530
|
-
}
|
|
49531
|
-
|
|
49532
|
-
// src/routing/handlers/git/coalesce-list-changes.ts
|
|
49533
|
-
var listChangesInflight = /* @__PURE__ */ new Map();
|
|
49534
|
-
function normalizeListChangesRepoPathRelativeToWorkspaceRoot(repoRelPath) {
|
|
49535
|
-
if (!repoRelPath?.trim()) return "";
|
|
49536
|
-
return normalizeRepoPathRelativeToWorkspaceRoot(repoRelPath.trim());
|
|
49537
|
-
}
|
|
49538
|
-
function listChangesInflightKey(sessionId, opts) {
|
|
49539
|
-
const basis = opts?.basis;
|
|
49540
|
-
return [
|
|
49541
|
-
sessionId,
|
|
49542
|
-
normalizeListChangesRepoPathRelativeToWorkspaceRoot(opts?.repoRelPath),
|
|
49543
|
-
basis?.kind === "commit" ? `commit:${basis.sha}` : "working",
|
|
49544
|
-
String(opts?.recentCommitsLimit ?? "")
|
|
49545
|
-
].join("|");
|
|
49621
|
+
if (typeof f.path !== "string" || !f.text && !f.base64) return;
|
|
49622
|
+
if (++filesWritten.count % INSTALL_SKILLS_YIELD_EVERY === 0) {
|
|
49623
|
+
await yieldToEventLoop();
|
|
49624
|
+
}
|
|
49625
|
+
const dest = path79.join(skillDir, f.path);
|
|
49626
|
+
await fs60.promises.mkdir(path79.dirname(dest), { recursive: true });
|
|
49627
|
+
if (f.text !== void 0) {
|
|
49628
|
+
await fs60.promises.writeFile(dest, f.text, "utf8");
|
|
49629
|
+
} else if (f.base64) {
|
|
49630
|
+
await fs60.promises.writeFile(dest, Buffer.from(f.base64, "base64"));
|
|
49631
|
+
}
|
|
49546
49632
|
}
|
|
49547
|
-
function
|
|
49548
|
-
const
|
|
49549
|
-
|
|
49550
|
-
|
|
49551
|
-
|
|
49552
|
-
|
|
49553
|
-
|
|
49554
|
-
|
|
49555
|
-
|
|
49633
|
+
async function installRemoteSkillsAsync(cwd, targetDir, items) {
|
|
49634
|
+
const installed2 = [];
|
|
49635
|
+
if (!Array.isArray(items)) {
|
|
49636
|
+
return { success: false, error: "Invalid items" };
|
|
49637
|
+
}
|
|
49638
|
+
const filesWritten = { count: 0 };
|
|
49639
|
+
try {
|
|
49640
|
+
for (const item of items) {
|
|
49641
|
+
if (!isValidRemoteSkillInstallItem(item)) continue;
|
|
49642
|
+
const skillDir = path79.join(cwd, targetDir, item.skillName);
|
|
49643
|
+
for (const f of item.files) {
|
|
49644
|
+
await writeInstallFileAsync(skillDir, f, filesWritten);
|
|
49645
|
+
}
|
|
49646
|
+
installed2.push({
|
|
49647
|
+
sourceId: item.sourceId,
|
|
49648
|
+
skillName: item.skillName,
|
|
49649
|
+
versionHash: item.versionHash
|
|
49650
|
+
});
|
|
49651
|
+
}
|
|
49652
|
+
return { success: true, installed: installed2 };
|
|
49653
|
+
} catch (e) {
|
|
49654
|
+
return { success: false, error: e instanceof Error ? e.message : String(e) };
|
|
49655
|
+
}
|
|
49556
49656
|
}
|
|
49557
49657
|
|
|
49558
|
-
// src/routing/handlers/
|
|
49559
|
-
|
|
49560
|
-
const
|
|
49561
|
-
const
|
|
49562
|
-
|
|
49563
|
-
|
|
49564
|
-
|
|
49565
|
-
|
|
49566
|
-
|
|
49567
|
-
|
|
49658
|
+
// src/routing/handlers/install-skills.ts
|
|
49659
|
+
var handleInstallSkillsMessage = (msg, deps) => {
|
|
49660
|
+
const id = typeof msg.id === "string" ? msg.id : "";
|
|
49661
|
+
const targetDir = typeof msg.targetDir === "string" && msg.targetDir.trim() ? msg.targetDir.trim() : ".agents/skills";
|
|
49662
|
+
const rawItems = msg.items;
|
|
49663
|
+
const cwd = getBridgeRoot();
|
|
49664
|
+
void (async () => {
|
|
49665
|
+
const socket = deps.getWs();
|
|
49666
|
+
const result = await installRemoteSkillsAsync(cwd, targetDir, rawItems);
|
|
49667
|
+
if (!result.success) {
|
|
49668
|
+
const err = result.error ?? "Invalid items";
|
|
49669
|
+
deps.log(`[Bridge service] Install skills failed: ${err}`);
|
|
49670
|
+
if (socket) {
|
|
49671
|
+
sendWsMessage(socket, { type: "install_skills_result", id, success: false, error: err });
|
|
49672
|
+
}
|
|
49568
49673
|
return;
|
|
49569
49674
|
}
|
|
49570
|
-
|
|
49571
|
-
|
|
49572
|
-
|
|
49573
|
-
|
|
49574
|
-
|
|
49575
|
-
|
|
49576
|
-
|
|
49577
|
-
|
|
49578
|
-
|
|
49579
|
-
|
|
49580
|
-
|
|
49581
|
-
|
|
49675
|
+
if (socket) {
|
|
49676
|
+
sendWsMessage(socket, { type: "install_skills_result", id, success: true, installed: result.installed });
|
|
49677
|
+
}
|
|
49678
|
+
})();
|
|
49679
|
+
};
|
|
49680
|
+
|
|
49681
|
+
// src/agents/install/commands/run-npm-global-install.ts
|
|
49682
|
+
import { execFile as execFile9 } from "node:child_process";
|
|
49683
|
+
import { promisify as promisify10 } from "node:util";
|
|
49684
|
+
var execFileAsync8 = promisify10(execFile9);
|
|
49685
|
+
async function runNpmGlobalInstall(packageName, env, timeoutMs = 3e5) {
|
|
49686
|
+
await execFileAsync8("npm", ["install", "-g", packageName], { timeout: timeoutMs, env });
|
|
49582
49687
|
}
|
|
49583
49688
|
|
|
49584
|
-
// src/
|
|
49585
|
-
|
|
49586
|
-
|
|
49587
|
-
|
|
49588
|
-
|
|
49589
|
-
|
|
49689
|
+
// src/agents/install/commands/claude-code.ts
|
|
49690
|
+
var claudeCodeInstallCommand = {
|
|
49691
|
+
agentType: "claude-code",
|
|
49692
|
+
detectCommand: "claude",
|
|
49693
|
+
async install(ctx) {
|
|
49694
|
+
ctx.onProgress?.("Installing Anthropic Claude Code");
|
|
49695
|
+
await runNpmGlobalInstall("@anthropic-ai/claude-code", {
|
|
49696
|
+
...ctx.env,
|
|
49697
|
+
ANTHROPIC_API_KEY: ctx.authToken
|
|
49698
|
+
});
|
|
49590
49699
|
}
|
|
49591
|
-
|
|
49592
|
-
reply({
|
|
49593
|
-
ok: true,
|
|
49594
|
-
hasUncommittedChanges: st.hasUncommittedChanges,
|
|
49595
|
-
hasUnpushedCommits: st.hasUnpushedCommits,
|
|
49596
|
-
uncommittedFileCount: st.uncommittedFileCount
|
|
49597
|
-
});
|
|
49598
|
-
}
|
|
49700
|
+
};
|
|
49599
49701
|
|
|
49600
|
-
// src/
|
|
49601
|
-
|
|
49602
|
-
|
|
49603
|
-
|
|
49604
|
-
|
|
49605
|
-
|
|
49606
|
-
|
|
49607
|
-
|
|
49608
|
-
|
|
49609
|
-
}
|
|
49702
|
+
// src/agents/install/commands/codex-acp.ts
|
|
49703
|
+
var codexAcpInstallCommand = {
|
|
49704
|
+
agentType: "codex-acp",
|
|
49705
|
+
detectCommand: "codex",
|
|
49706
|
+
async install(ctx) {
|
|
49707
|
+
ctx.onProgress?.("Installing Codex");
|
|
49708
|
+
await runNpmGlobalInstall("@openai/codex", {
|
|
49709
|
+
...ctx.env,
|
|
49710
|
+
OPENAI_API_KEY: ctx.authToken
|
|
49711
|
+
});
|
|
49712
|
+
}
|
|
49713
|
+
};
|
|
49610
49714
|
|
|
49611
|
-
// src/
|
|
49612
|
-
|
|
49613
|
-
|
|
49614
|
-
|
|
49615
|
-
|
|
49616
|
-
|
|
49617
|
-
|
|
49715
|
+
// src/agents/install/commands/cursor-cli.ts
|
|
49716
|
+
import { execFile as execFile10 } from "node:child_process";
|
|
49717
|
+
import { promisify as promisify11 } from "node:util";
|
|
49718
|
+
var execFileAsync9 = promisify11(execFile10);
|
|
49719
|
+
var cursorCliInstallCommand = {
|
|
49720
|
+
agentType: "cursor-cli",
|
|
49721
|
+
detectCommand: "agent",
|
|
49722
|
+
async install(ctx) {
|
|
49723
|
+
ctx.onProgress?.("Installing Cursor CLI");
|
|
49724
|
+
await execFileAsync9("bash", ["-lc", "curl -fsSL https://cursor.com/install | bash"], {
|
|
49725
|
+
timeout: 3e5,
|
|
49726
|
+
env: { ...ctx.env, CURSOR_API_KEY: ctx.authToken }
|
|
49727
|
+
});
|
|
49618
49728
|
}
|
|
49619
|
-
|
|
49729
|
+
};
|
|
49730
|
+
|
|
49731
|
+
// src/agents/install/commands/opencode.ts
|
|
49732
|
+
var opencodeInstallCommand = {
|
|
49733
|
+
agentType: "opencode",
|
|
49734
|
+
detectCommand: "opencode",
|
|
49735
|
+
async install(ctx) {
|
|
49736
|
+
ctx.onProgress?.("Installing OpenCode");
|
|
49737
|
+
await runNpmGlobalInstall("opencode-ai", {
|
|
49738
|
+
...ctx.env,
|
|
49739
|
+
OPENCODE_API_KEY: ctx.authToken
|
|
49740
|
+
});
|
|
49741
|
+
}
|
|
49742
|
+
};
|
|
49743
|
+
|
|
49744
|
+
// src/agents/install/commands/index.ts
|
|
49745
|
+
var COMMANDS = [
|
|
49746
|
+
claudeCodeInstallCommand,
|
|
49747
|
+
codexAcpInstallCommand,
|
|
49748
|
+
cursorCliInstallCommand,
|
|
49749
|
+
opencodeInstallCommand
|
|
49750
|
+
];
|
|
49751
|
+
var byType = new Map(COMMANDS.map((c) => [c.agentType, c]));
|
|
49752
|
+
function getAgentInstallCommand(agentType) {
|
|
49753
|
+
return byType.get(agentType);
|
|
49754
|
+
}
|
|
49755
|
+
|
|
49756
|
+
// src/agents/install/install-local-agent.ts
|
|
49757
|
+
async function installLocalAgentOnBridge(params) {
|
|
49758
|
+
const spec = INSTALLABLE_BRIDGE_AGENTS.find((a) => a.value === params.agentType);
|
|
49759
|
+
if (!spec) return { success: false, error: `Unsupported agent type: ${params.agentType}` };
|
|
49760
|
+
const command = getAgentInstallCommand(params.agentType);
|
|
49761
|
+
if (!command) return { success: false, error: `No install command for ${params.agentType}` };
|
|
49762
|
+
params.onProgress?.(`Configuring ${spec.label} credentials`);
|
|
49763
|
+
try {
|
|
49764
|
+
await command.install({
|
|
49765
|
+
authToken: params.authToken,
|
|
49766
|
+
onProgress: params.onProgress,
|
|
49767
|
+
env: { ...process.env, [spec.tokenEnvVar]: params.authToken }
|
|
49768
|
+
});
|
|
49769
|
+
} catch (e) {
|
|
49770
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
49771
|
+
return { success: false, error: msg };
|
|
49772
|
+
}
|
|
49773
|
+
const found = await isCommandOnPath(command.detectCommand);
|
|
49774
|
+
if (!found) {
|
|
49775
|
+
return { success: false, error: `${command.detectCommand} not found on PATH after install` };
|
|
49776
|
+
}
|
|
49777
|
+
return { success: true };
|
|
49620
49778
|
}
|
|
49621
49779
|
|
|
49622
|
-
// src/routing/handlers/
|
|
49623
|
-
var
|
|
49624
|
-
|
|
49625
|
-
const
|
|
49626
|
-
const
|
|
49627
|
-
|
|
49628
|
-
|
|
49780
|
+
// src/routing/handlers/install-agent.ts
|
|
49781
|
+
var handleInstallAgentMessage = (msg, deps) => {
|
|
49782
|
+
const processId = typeof msg.processId === "string" ? msg.processId : "";
|
|
49783
|
+
const agentId = typeof msg.agentId === "string" ? msg.agentId : "";
|
|
49784
|
+
const tokenId = typeof msg.tokenId === "string" ? msg.tokenId : "";
|
|
49785
|
+
const agentType = typeof msg.agentType === "string" ? msg.agentType : "";
|
|
49786
|
+
const authToken = typeof msg.authToken === "string" ? msg.authToken : "";
|
|
49787
|
+
if (!processId || !agentId || !tokenId || !agentType || !authToken) return;
|
|
49629
49788
|
void (async () => {
|
|
49630
|
-
const
|
|
49631
|
-
const
|
|
49632
|
-
|
|
49633
|
-
|
|
49634
|
-
|
|
49635
|
-
|
|
49636
|
-
|
|
49637
|
-
|
|
49638
|
-
|
|
49639
|
-
|
|
49640
|
-
|
|
49641
|
-
|
|
49642
|
-
await handleSessionGitGetChangeFilePatchAction(deps, { ...msg, sessionId }, reply);
|
|
49643
|
-
return;
|
|
49644
|
-
}
|
|
49645
|
-
if (action === "push") {
|
|
49646
|
-
await handleSessionGitPushAction(deps, sessionId, reply);
|
|
49647
|
-
return;
|
|
49789
|
+
const socket = deps.getWs();
|
|
49790
|
+
const report = (step, message) => {
|
|
49791
|
+
if (socket) {
|
|
49792
|
+
sendWsMessage(socket, {
|
|
49793
|
+
type: "install_agent_progress",
|
|
49794
|
+
processId,
|
|
49795
|
+
agentId,
|
|
49796
|
+
tokenId,
|
|
49797
|
+
agentType,
|
|
49798
|
+
step,
|
|
49799
|
+
message
|
|
49800
|
+
});
|
|
49648
49801
|
}
|
|
49649
|
-
|
|
49650
|
-
|
|
49651
|
-
|
|
49802
|
+
};
|
|
49803
|
+
const result = await installLocalAgentOnBridge({
|
|
49804
|
+
agentType,
|
|
49805
|
+
authToken,
|
|
49806
|
+
onProgress: (message) => report("agent_install_package", message)
|
|
49807
|
+
});
|
|
49808
|
+
if (socket) {
|
|
49809
|
+
sendWsMessage(socket, {
|
|
49810
|
+
type: "install_agent_result",
|
|
49811
|
+
processId,
|
|
49812
|
+
agentId,
|
|
49813
|
+
tokenId,
|
|
49814
|
+
agentType,
|
|
49815
|
+
success: result.success,
|
|
49816
|
+
error: result.error
|
|
49817
|
+
});
|
|
49818
|
+
}
|
|
49819
|
+
if (!result.success) {
|
|
49820
|
+
deps.log(`[Bridge service] Install agent failed: ${result.error ?? "unknown"}`);
|
|
49652
49821
|
}
|
|
49653
49822
|
})();
|
|
49654
49823
|
};
|
|
49655
49824
|
|
|
49656
|
-
// src/routing/handlers/
|
|
49657
|
-
var
|
|
49658
|
-
|
|
49659
|
-
|
|
49660
|
-
|
|
49661
|
-
void deps.sessionWorktreeManager.renameSessionBranch(sessionId, newBranch);
|
|
49825
|
+
// src/routing/handlers/refresh-local-skills.ts
|
|
49826
|
+
var handleRefreshLocalSkills = (_msg, deps) => {
|
|
49827
|
+
setImmediate(() => {
|
|
49828
|
+
deps.sendLocalSkillsReport?.();
|
|
49829
|
+
});
|
|
49662
49830
|
};
|
|
49663
49831
|
|
|
49664
|
-
// src/routing/
|
|
49665
|
-
|
|
49666
|
-
|
|
49667
|
-
|
|
49668
|
-
|
|
49669
|
-
|
|
49832
|
+
// src/routing/dispatch/skills.ts
|
|
49833
|
+
function dispatchBridgeSkillsMessage(msg, deps) {
|
|
49834
|
+
switch (msg.type) {
|
|
49835
|
+
case "skill_call":
|
|
49836
|
+
handleSkillCallMessage(msg, deps);
|
|
49837
|
+
break;
|
|
49838
|
+
case "skill_layout_request":
|
|
49839
|
+
handleSkillLayoutRequest(msg, deps);
|
|
49840
|
+
break;
|
|
49841
|
+
case "install_skills":
|
|
49842
|
+
handleInstallSkillsMessage(msg, deps);
|
|
49843
|
+
break;
|
|
49844
|
+
case "install_agent":
|
|
49845
|
+
handleInstallAgentMessage(msg, deps);
|
|
49846
|
+
break;
|
|
49847
|
+
case "refresh_local_skills":
|
|
49848
|
+
handleRefreshLocalSkills(msg, deps);
|
|
49849
|
+
break;
|
|
49850
|
+
}
|
|
49851
|
+
}
|
|
49670
49852
|
|
|
49671
|
-
// src/
|
|
49672
|
-
|
|
49673
|
-
|
|
49674
|
-
|
|
49675
|
-
void deps.sessionWorktreeManager.removeSessionWorktrees(sessionId);
|
|
49676
|
-
};
|
|
49853
|
+
// src/files/browser/send-file-browser-message.ts
|
|
49854
|
+
function sendFileBrowserMessage(socket, e2ee, payload) {
|
|
49855
|
+
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["entries", "content", "totalLines", "size", "lineOffset"]) : payload);
|
|
49856
|
+
}
|
|
49677
49857
|
|
|
49678
|
-
// src/
|
|
49679
|
-
|
|
49680
|
-
|
|
49681
|
-
|
|
49682
|
-
|
|
49683
|
-
|
|
49684
|
-
|
|
49685
|
-
|
|
49858
|
+
// src/files/browser/handle-file-browser-list.ts
|
|
49859
|
+
async function handleFileBrowserList(socket, e2ee, id, reqPath, sessionParentPath, gitScope) {
|
|
49860
|
+
const result = await executeFileBrowserList({ reqPath, sessionParentPath, gitScope });
|
|
49861
|
+
if ("error" in result) {
|
|
49862
|
+
sendWsMessage(socket, { type: "file_browser_response", id, error: result.error });
|
|
49863
|
+
return;
|
|
49864
|
+
}
|
|
49865
|
+
sendFileBrowserMessage(socket, e2ee, { type: "file_browser_response", id, entries: result.entries });
|
|
49866
|
+
}
|
|
49867
|
+
|
|
49868
|
+
// src/files/browser/handle-file-browser-read.ts
|
|
49869
|
+
async function handleFileBrowserRead(socket, e2ee, msg, reqPath, sessionParentPath, gitScope) {
|
|
49870
|
+
const result = await executeFileBrowserRead({ msg, reqPath, sessionParentPath, gitScope });
|
|
49871
|
+
if ("error" in result) {
|
|
49872
|
+
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
|
|
49873
|
+
return;
|
|
49874
|
+
}
|
|
49875
|
+
const payload = {
|
|
49876
|
+
type: "file_browser_response",
|
|
49877
|
+
id: msg.id,
|
|
49878
|
+
content: result.content,
|
|
49879
|
+
totalLines: result.totalLines,
|
|
49880
|
+
size: result.size
|
|
49881
|
+
};
|
|
49882
|
+
if (result.lineOffset != null) payload.lineOffset = result.lineOffset;
|
|
49883
|
+
if (result.mimeType != null) payload.mimeType = result.mimeType;
|
|
49884
|
+
if (result.resolvedPath != null) payload.resolvedPath = result.resolvedPath;
|
|
49885
|
+
sendFileBrowserMessage(socket, e2ee, payload);
|
|
49886
|
+
}
|
|
49887
|
+
|
|
49888
|
+
// src/files/browser/index.ts
|
|
49889
|
+
init_in_flight();
|
|
49890
|
+
function handleFileBrowserRequest(msg, socket, e2ee, sessionWorktreeManager) {
|
|
49891
|
+
beginFileBrowserRequest();
|
|
49686
49892
|
void (async () => {
|
|
49687
|
-
const s = getWs();
|
|
49688
|
-
if (!s) return;
|
|
49689
|
-
const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
|
|
49690
|
-
const file2 = snapshotFilePath(agentBase, turnId);
|
|
49691
49893
|
try {
|
|
49692
|
-
|
|
49693
|
-
|
|
49694
|
-
|
|
49695
|
-
|
|
49696
|
-
id,
|
|
49697
|
-
|
|
49698
|
-
|
|
49699
|
-
|
|
49700
|
-
|
|
49894
|
+
const reqPath = msg.path.replace(/^\/+/, "") || ".";
|
|
49895
|
+
const sessionParentPath = sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : void 0;
|
|
49896
|
+
const gitScope = resolveGitBranchScope(msg);
|
|
49897
|
+
if (msg.source === "git_branch" && typeof msg.repoRelPath === "string" && typeof msg.branch === "string" && msg.branch.trim().length > 0 && !gitScope) {
|
|
49898
|
+
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: "Invalid repository path" });
|
|
49899
|
+
return;
|
|
49900
|
+
}
|
|
49901
|
+
if (msg.op === "read") {
|
|
49902
|
+
await handleFileBrowserRead(socket, e2ee, msg, reqPath, sessionParentPath, gitScope);
|
|
49903
|
+
} else {
|
|
49904
|
+
await handleFileBrowserList(socket, e2ee, msg.id, reqPath, sessionParentPath, gitScope);
|
|
49905
|
+
}
|
|
49906
|
+
} finally {
|
|
49907
|
+
endFileBrowserRequest();
|
|
49701
49908
|
}
|
|
49702
|
-
const res = await applyPreTurnSnapshot(file2, log2);
|
|
49703
|
-
sendWsMessage(s, {
|
|
49704
|
-
type: "revert_turn_snapshot_result",
|
|
49705
|
-
id,
|
|
49706
|
-
ok: res.ok,
|
|
49707
|
-
...res.error ? { error: res.error } : {}
|
|
49708
|
-
});
|
|
49709
49909
|
})();
|
|
49710
|
-
}
|
|
49711
|
-
|
|
49712
|
-
// src/routing/handlers/preview-environment-control.ts
|
|
49713
|
-
var handlePreviewEnvironmentControl = (msg, deps) => {
|
|
49714
|
-
let wire;
|
|
49715
|
-
try {
|
|
49716
|
-
wire = deps.e2ee ? deps.e2ee.decryptMessage(msg) : msg;
|
|
49717
|
-
} catch (e) {
|
|
49718
|
-
deps.log(`[E2EE] Could not decrypt preview environment command: ${e instanceof Error ? e.message : String(e)}`);
|
|
49719
|
-
return;
|
|
49720
|
-
}
|
|
49721
|
-
const environmentId = typeof wire.environmentId === "string" ? wire.environmentId : "";
|
|
49722
|
-
const action = wire.action === "start" || wire.action === "stop" ? wire.action : null;
|
|
49723
|
-
if (!environmentId || !action) return;
|
|
49724
|
-
deps.previewEnvironmentManager?.handleControl(environmentId, action);
|
|
49725
|
-
};
|
|
49910
|
+
}
|
|
49726
49911
|
|
|
49727
|
-
// src/
|
|
49728
|
-
|
|
49729
|
-
|
|
49730
|
-
|
|
49731
|
-
|
|
49732
|
-
|
|
49733
|
-
|
|
49734
|
-
const
|
|
49735
|
-
|
|
49736
|
-
|
|
49737
|
-
|
|
49912
|
+
// src/files/handle-file-browser-search.ts
|
|
49913
|
+
init_yield_to_event_loop();
|
|
49914
|
+
import path80 from "node:path";
|
|
49915
|
+
var SEARCH_LIMIT = 100;
|
|
49916
|
+
function handleFileBrowserSearch(msg, socket, e2ee, sessionWorktreeManager) {
|
|
49917
|
+
void (async () => {
|
|
49918
|
+
await yieldToEventLoop();
|
|
49919
|
+
const q = typeof msg.q === "string" ? msg.q : "";
|
|
49920
|
+
const sessionParentPath = path80.resolve(
|
|
49921
|
+
sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : getBridgeRoot()
|
|
49922
|
+
);
|
|
49923
|
+
if (!await bridgeFileIndexIsPopulated(sessionParentPath)) {
|
|
49924
|
+
triggerFileIndexBuild(sessionParentPath);
|
|
49925
|
+
const payload2 = {
|
|
49926
|
+
type: "file_browser_search_response",
|
|
49927
|
+
id: msg.id,
|
|
49928
|
+
paths: [],
|
|
49929
|
+
indexReady: false
|
|
49930
|
+
};
|
|
49931
|
+
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload2, ["paths"]) : payload2);
|
|
49932
|
+
return;
|
|
49738
49933
|
}
|
|
49934
|
+
const results = await searchBridgeFilePathsAsync(sessionParentPath, q, SEARCH_LIMIT);
|
|
49935
|
+
const payload = {
|
|
49936
|
+
type: "file_browser_search_response",
|
|
49937
|
+
id: msg.id,
|
|
49938
|
+
paths: results,
|
|
49939
|
+
indexReady: true
|
|
49940
|
+
};
|
|
49941
|
+
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["paths"]) : payload);
|
|
49942
|
+
})();
|
|
49943
|
+
}
|
|
49944
|
+
function triggerFileIndexBuild(sessionParentPath = getBridgeRoot()) {
|
|
49945
|
+
setImmediate(() => {
|
|
49946
|
+
void ensureFileIndexAsync(sessionParentPath).catch((e) => {
|
|
49947
|
+
console.error("[file-index] Background build failed:", e);
|
|
49948
|
+
});
|
|
49739
49949
|
});
|
|
49740
|
-
};
|
|
49741
|
-
|
|
49742
|
-
// src/routing/handlers/send-deploy-session-to-preview-result.ts
|
|
49743
|
-
function sendDeploySessionToPreviewResult(ws, id, payload) {
|
|
49744
|
-
if (!ws) return;
|
|
49745
|
-
sendWsMessage(ws, { type: "deploy_session_to_preview_result", id, ...payload });
|
|
49746
49950
|
}
|
|
49747
49951
|
|
|
49748
|
-
// src/routing/handlers/
|
|
49749
|
-
|
|
49952
|
+
// src/routing/handlers/file-browser-messages.ts
|
|
49953
|
+
function handleFileBrowserRequestMessage(msg, { getWs, e2ee, sessionWorktreeManager }) {
|
|
49954
|
+
if (typeof msg.id !== "string" || typeof msg.path !== "string") return;
|
|
49955
|
+
const socket = getWs();
|
|
49956
|
+
if (!socket) return;
|
|
49957
|
+
handleFileBrowserRequest(msg, socket, e2ee, sessionWorktreeManager);
|
|
49958
|
+
}
|
|
49959
|
+
function handleFileBrowserSearchMessage(msg, { getWs, e2ee, sessionWorktreeManager }) {
|
|
49750
49960
|
if (typeof msg.id !== "string") return;
|
|
49751
|
-
const
|
|
49752
|
-
|
|
49753
|
-
|
|
49961
|
+
const socket = getWs();
|
|
49962
|
+
if (!socket) return;
|
|
49963
|
+
handleFileBrowserSearch(
|
|
49964
|
+
msg,
|
|
49965
|
+
socket,
|
|
49966
|
+
e2ee,
|
|
49967
|
+
sessionWorktreeManager
|
|
49968
|
+
);
|
|
49969
|
+
}
|
|
49970
|
+
|
|
49971
|
+
// src/code-nav/handlers/send-code-nav-response.ts
|
|
49972
|
+
var ENCRYPTED_FIELDS = ["definition", "definitions", "references", "symbols", "confidentTarget"];
|
|
49973
|
+
function sendCodeNavResponse(socket, e2ee, payload) {
|
|
49974
|
+
const fieldsToEncrypt = ENCRYPTED_FIELDS.filter((field) => field in payload && payload[field] !== void 0);
|
|
49975
|
+
sendWsMessage(
|
|
49976
|
+
socket,
|
|
49977
|
+
e2ee && fieldsToEncrypt.length > 0 ? e2ee.encryptFields(payload, [...fieldsToEncrypt]) : payload
|
|
49978
|
+
);
|
|
49979
|
+
}
|
|
49980
|
+
|
|
49981
|
+
// src/code-nav/handlers/handle-code-nav-request.ts
|
|
49982
|
+
function handleCodeNavRequest(msg, socket, e2ee, sessionWorktreeManager) {
|
|
49754
49983
|
void (async () => {
|
|
49755
|
-
const
|
|
49756
|
-
|
|
49757
|
-
|
|
49758
|
-
|
|
49759
|
-
|
|
49760
|
-
|
|
49761
|
-
}
|
|
49762
|
-
const result = await deploySessionToPreviewEnvironment({
|
|
49763
|
-
sessionWorktreeManager: deps.sessionWorktreeManager,
|
|
49764
|
-
previewWorktreeManager: deps.previewWorktreeManager,
|
|
49765
|
-
sessionId,
|
|
49766
|
-
environmentId,
|
|
49767
|
-
log: deps.log
|
|
49768
|
-
});
|
|
49769
|
-
reply(result);
|
|
49770
|
-
} catch (e) {
|
|
49771
|
-
reply({ ok: false, error: e instanceof Error ? e.message : String(e) });
|
|
49772
|
-
}
|
|
49984
|
+
const body = await executeCodeNavRequest(msg, sessionWorktreeManager);
|
|
49985
|
+
sendCodeNavResponse(socket, e2ee, {
|
|
49986
|
+
type: "code_nav_response",
|
|
49987
|
+
id: msg.id,
|
|
49988
|
+
...body
|
|
49989
|
+
});
|
|
49773
49990
|
})();
|
|
49774
|
-
}
|
|
49991
|
+
}
|
|
49992
|
+
|
|
49993
|
+
// src/code-nav/handlers/trigger-symbol-index-build.ts
|
|
49994
|
+
init_normalize_resolved_path();
|
|
49995
|
+
|
|
49996
|
+
// src/routing/handlers/code-nav-messages.ts
|
|
49997
|
+
function handleFileBrowserCodeNavMessage(msg, { getWs, e2ee, sessionWorktreeManager }) {
|
|
49998
|
+
if (typeof msg.id !== "string" || typeof msg.path !== "string") return;
|
|
49999
|
+
const socket = getWs();
|
|
50000
|
+
if (!socket) return;
|
|
50001
|
+
handleCodeNavRequest(
|
|
50002
|
+
{
|
|
50003
|
+
id: msg.id,
|
|
50004
|
+
type: "code_nav",
|
|
50005
|
+
op: msg.op === "references" ? "references" : msg.op === "symbols" ? "symbols" : msg.op === "definitions" ? "definitions" : "definition",
|
|
50006
|
+
path: msg.path,
|
|
50007
|
+
line: typeof msg.line === "number" ? msg.line : 1,
|
|
50008
|
+
column: typeof msg.column === "number" ? msg.column : 0,
|
|
50009
|
+
sessionId: msg.sessionId
|
|
50010
|
+
},
|
|
50011
|
+
socket,
|
|
50012
|
+
e2ee,
|
|
50013
|
+
sessionWorktreeManager
|
|
50014
|
+
);
|
|
50015
|
+
}
|
|
49775
50016
|
|
|
49776
50017
|
// src/git/bridge-git-context.ts
|
|
49777
50018
|
import * as path81 from "node:path";
|
|
@@ -49918,80 +50159,64 @@ function handleListRepoBranchesRequestMessage(msg, getWs) {
|
|
|
49918
50159
|
})();
|
|
49919
50160
|
}
|
|
49920
50161
|
|
|
49921
|
-
// src/routing/dispatch-
|
|
50162
|
+
// src/routing/dispatch/file-browser.ts
|
|
50163
|
+
function dispatchBridgeFileBrowserMessage(msg, deps) {
|
|
50164
|
+
switch (msg.type) {
|
|
50165
|
+
case "file_browser_request":
|
|
50166
|
+
handleFileBrowserRequestMessage(msg, deps);
|
|
50167
|
+
break;
|
|
50168
|
+
case "file_browser_search":
|
|
50169
|
+
handleFileBrowserSearchMessage(msg, deps);
|
|
50170
|
+
break;
|
|
50171
|
+
case "code_nav":
|
|
50172
|
+
handleFileBrowserCodeNavMessage(msg, deps);
|
|
50173
|
+
break;
|
|
50174
|
+
case "bridge_git_context_request":
|
|
50175
|
+
handleBridgeGitContextRequestMessage(msg, deps.getWs);
|
|
50176
|
+
break;
|
|
50177
|
+
case "list_repo_branches_request":
|
|
50178
|
+
handleListRepoBranchesRequestMessage(msg, deps.getWs);
|
|
50179
|
+
break;
|
|
50180
|
+
}
|
|
50181
|
+
}
|
|
50182
|
+
|
|
50183
|
+
// src/routing/dispatch/index.ts
|
|
49922
50184
|
function dispatchBridgeMessage(msg, deps) {
|
|
49923
50185
|
switch (msg.type) {
|
|
49924
50186
|
case "auth_token":
|
|
49925
|
-
handleAuthToken(msg, deps);
|
|
49926
|
-
break;
|
|
49927
50187
|
case "bridge_identified":
|
|
49928
|
-
handleBridgeIdentified(msg, deps);
|
|
49929
|
-
break;
|
|
49930
50188
|
case "ha":
|
|
49931
|
-
|
|
50189
|
+
dispatchBridgeConnectionMessage(msg, deps);
|
|
49932
50190
|
break;
|
|
49933
50191
|
case "preview_environments_config":
|
|
49934
|
-
handlePreviewEnvironmentsConfig(msg, deps);
|
|
49935
|
-
break;
|
|
49936
50192
|
case "preview_environment_control":
|
|
49937
|
-
handlePreviewEnvironmentControl(msg, deps);
|
|
49938
|
-
break;
|
|
49939
50193
|
case "deploy_session_to_preview":
|
|
49940
|
-
|
|
50194
|
+
dispatchBridgePreviewMessage(msg, deps);
|
|
49941
50195
|
break;
|
|
49942
50196
|
case "agent_config":
|
|
49943
|
-
handleAgentConfigMessage(msg, deps);
|
|
49944
|
-
break;
|
|
49945
50197
|
case "prompt_queue_state":
|
|
49946
|
-
handlePromptQueueStateMessage(msg, deps);
|
|
49947
|
-
break;
|
|
49948
50198
|
case "prompt":
|
|
49949
|
-
handlePromptMessage(msg, deps);
|
|
49950
|
-
break;
|
|
49951
50199
|
case "session_git_request":
|
|
49952
|
-
handleSessionGitRequestMessage(msg, deps);
|
|
49953
|
-
break;
|
|
49954
50200
|
case "rename_session_branch":
|
|
49955
|
-
handleRenameSessionBranchMessage(msg, deps);
|
|
49956
|
-
break;
|
|
49957
50201
|
case "session_archived":
|
|
49958
|
-
handleSessionArchivedMessage(msg, deps);
|
|
49959
|
-
break;
|
|
49960
50202
|
case "session_discarded":
|
|
49961
|
-
handleSessionDiscardedMessage(msg, deps);
|
|
49962
|
-
break;
|
|
49963
50203
|
case "revert_turn_snapshot":
|
|
49964
|
-
handleRevertTurnSnapshotMessage(msg, deps);
|
|
49965
|
-
break;
|
|
49966
50204
|
case "cursor_request_response":
|
|
49967
|
-
|
|
50205
|
+
dispatchBridgeSessionMessage(msg, deps);
|
|
49968
50206
|
break;
|
|
49969
50207
|
case "skill_call":
|
|
49970
|
-
handleSkillCallMessage(msg, deps);
|
|
49971
|
-
break;
|
|
49972
|
-
case "file_browser_request":
|
|
49973
|
-
handleFileBrowserRequestMessage(msg, deps);
|
|
49974
|
-
break;
|
|
49975
|
-
case "file_browser_search":
|
|
49976
|
-
handleFileBrowserSearchMessage(msg, deps);
|
|
49977
|
-
break;
|
|
49978
|
-
case "code_nav":
|
|
49979
|
-
handleFileBrowserCodeNavMessage(msg, deps);
|
|
49980
|
-
break;
|
|
49981
50208
|
case "skill_layout_request":
|
|
49982
|
-
handleSkillLayoutRequest(msg, deps);
|
|
49983
|
-
break;
|
|
49984
50209
|
case "install_skills":
|
|
49985
|
-
|
|
49986
|
-
break;
|
|
50210
|
+
case "install_agent":
|
|
49987
50211
|
case "refresh_local_skills":
|
|
49988
|
-
|
|
50212
|
+
dispatchBridgeSkillsMessage(msg, deps);
|
|
49989
50213
|
break;
|
|
50214
|
+
case "file_browser_request":
|
|
50215
|
+
case "file_browser_search":
|
|
50216
|
+
case "code_nav":
|
|
49990
50217
|
case "bridge_git_context_request":
|
|
49991
|
-
handleBridgeGitContextRequestMessage(msg, deps.getWs);
|
|
49992
|
-
break;
|
|
49993
50218
|
case "list_repo_branches_request":
|
|
49994
|
-
|
|
50219
|
+
dispatchBridgeFileBrowserMessage(msg, deps);
|
|
49995
50220
|
break;
|
|
49996
50221
|
}
|
|
49997
50222
|
}
|