@sideboard-ai/core 0.1.23 → 0.1.30
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/{chunk-JNMLRJ3D.js → chunk-RPSHBKLW.js} +308 -50
- package/dist/index.cjs +318 -53
- package/dist/index.d.cts +73 -3
- package/dist/index.d.ts +73 -3
- package/dist/index.js +14 -1
- package/dist/mcp/run-stdio.cjs +225 -12
- package/dist/mcp/run-stdio.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5241,6 +5241,9 @@ __export(index_exports, {
|
|
|
5241
5241
|
applyAppEnvironment: () => applyAppEnvironment,
|
|
5242
5242
|
applyCompaction: () => applyCompaction,
|
|
5243
5243
|
applyThreadIntoMain: () => applyThreadIntoMain,
|
|
5244
|
+
attachmentFromAbsolutePath: () => attachmentFromAbsolutePath,
|
|
5245
|
+
attachmentsFromBuffers: () => attachmentsFromBuffers,
|
|
5246
|
+
attachmentsFromWorktreePaths: () => attachmentsFromWorktreePaths,
|
|
5244
5247
|
autoCleanupOrphansEnabled: () => autoCleanupOrphansEnabled,
|
|
5245
5248
|
autoRenameBranchEnabled: () => autoRenameBranchEnabled,
|
|
5246
5249
|
autoRunAfterSetupEnabled: () => autoRunAfterSetupEnabled,
|
|
@@ -5363,6 +5366,7 @@ __export(index_exports, {
|
|
|
5363
5366
|
isGhRateLimitError: () => isGhRateLimitError,
|
|
5364
5367
|
isGlobalRepoPath: () => isGlobalRepoPath,
|
|
5365
5368
|
isGlobalThread: () => isGlobalThread,
|
|
5369
|
+
isImageFilePath: () => isImageFilePath,
|
|
5366
5370
|
isLinearConnected: () => isLinearConnected,
|
|
5367
5371
|
isOrchestratorThread: () => isOrchestratorThread,
|
|
5368
5372
|
isPlaceholderBranch: () => isPlaceholderBranch,
|
|
@@ -5451,6 +5455,8 @@ __export(index_exports, {
|
|
|
5451
5455
|
slugify: () => slugify,
|
|
5452
5456
|
spawnAgentTurn: () => spawnAgentTurn,
|
|
5453
5457
|
splitForCompaction: () => splitForCompaction,
|
|
5458
|
+
stageAbsolutePathsAsAttachments: () => stageAbsolutePathsAsAttachments,
|
|
5459
|
+
stageBuffersAsAttachments: () => stageBuffersAsAttachments,
|
|
5454
5460
|
startDevServer: () => startDevServer,
|
|
5455
5461
|
startMcpServer: () => startMcpServer,
|
|
5456
5462
|
startOrchestration: () => startOrchestration,
|
|
@@ -7257,6 +7263,9 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
|
|
|
7257
7263
|
parts.push("");
|
|
7258
7264
|
parts.push(`## Attachment: ${att.name}`);
|
|
7259
7265
|
parts.push(`Kind: ${att.kind}`);
|
|
7266
|
+
if (att.path) {
|
|
7267
|
+
parts.push(`Path in worktree: \`${att.path}\``);
|
|
7268
|
+
}
|
|
7260
7269
|
parts.push("");
|
|
7261
7270
|
parts.push(att.content);
|
|
7262
7271
|
}
|
|
@@ -7342,10 +7351,239 @@ function buildDiffCommentAttachment(input) {
|
|
|
7342
7351
|
id: input.id ?? `diff-comment-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
7343
7352
|
name,
|
|
7344
7353
|
kind: "diff-comment",
|
|
7354
|
+
path: input.path.trim(),
|
|
7345
7355
|
content
|
|
7346
7356
|
};
|
|
7347
7357
|
}
|
|
7348
7358
|
|
|
7359
|
+
// src/composer/stage-files.ts
|
|
7360
|
+
var import_node_fs19 = require("fs");
|
|
7361
|
+
var import_node_path19 = require("path");
|
|
7362
|
+
var import_node_crypto2 = require("crypto");
|
|
7363
|
+
var IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
7364
|
+
"png",
|
|
7365
|
+
"jpg",
|
|
7366
|
+
"jpeg",
|
|
7367
|
+
"gif",
|
|
7368
|
+
"webp",
|
|
7369
|
+
"svg",
|
|
7370
|
+
"bmp",
|
|
7371
|
+
"ico"
|
|
7372
|
+
]);
|
|
7373
|
+
var IMAGE_MIME_BY_EXT = {
|
|
7374
|
+
png: "image/png",
|
|
7375
|
+
jpg: "image/jpeg",
|
|
7376
|
+
jpeg: "image/jpeg",
|
|
7377
|
+
gif: "image/gif",
|
|
7378
|
+
webp: "image/webp",
|
|
7379
|
+
svg: "image/svg+xml",
|
|
7380
|
+
bmp: "image/bmp",
|
|
7381
|
+
ico: "image/x-icon"
|
|
7382
|
+
};
|
|
7383
|
+
var ATTACHMENTS_DIR = ".sideboard/attachments";
|
|
7384
|
+
var ATTACHMENTS_GITIGNORE = `# Sideboard review / composer attachments (local only)
|
|
7385
|
+
*
|
|
7386
|
+
!.gitignore
|
|
7387
|
+
`;
|
|
7388
|
+
var MAX_INLINE_BYTES = 4e5;
|
|
7389
|
+
var MAX_PREVIEW_BYTES = 5e6;
|
|
7390
|
+
function fileExtension(filePath) {
|
|
7391
|
+
const base = (0, import_node_path19.basename)(filePath).toLowerCase();
|
|
7392
|
+
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
7393
|
+
}
|
|
7394
|
+
function isImageFilePath(filePath) {
|
|
7395
|
+
return IMAGE_EXTENSIONS2.has(fileExtension(filePath));
|
|
7396
|
+
}
|
|
7397
|
+
function imageMimeType(filePath) {
|
|
7398
|
+
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
7399
|
+
}
|
|
7400
|
+
function ensureAttachmentsDir(worktreePath) {
|
|
7401
|
+
const dir = (0, import_node_path19.join)(worktreePath, ATTACHMENTS_DIR);
|
|
7402
|
+
(0, import_node_fs19.mkdirSync)(dir, { recursive: true });
|
|
7403
|
+
const gi = (0, import_node_path19.join)(dir, ".gitignore");
|
|
7404
|
+
if (!(0, import_node_fs19.existsSync)(gi)) {
|
|
7405
|
+
(0, import_node_fs19.writeFileSync)(gi, ATTACHMENTS_GITIGNORE, "utf8");
|
|
7406
|
+
}
|
|
7407
|
+
return dir;
|
|
7408
|
+
}
|
|
7409
|
+
function uniqueAttachmentName(dir, originalName) {
|
|
7410
|
+
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
7411
|
+
if (!(0, import_node_fs19.existsSync)((0, import_node_path19.join)(dir, safe))) return safe;
|
|
7412
|
+
const ext = (0, import_node_path19.extname)(safe);
|
|
7413
|
+
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
7414
|
+
for (let i = 1; i < 1e4; i++) {
|
|
7415
|
+
const candidate = `${stem}-${i}${ext}`;
|
|
7416
|
+
if (!(0, import_node_fs19.existsSync)((0, import_node_path19.join)(dir, candidate))) return candidate;
|
|
7417
|
+
}
|
|
7418
|
+
return `${stem}-${(0, import_node_crypto2.randomUUID)()}${ext}`;
|
|
7419
|
+
}
|
|
7420
|
+
function previewDataUrlFromBuf(filePath, buf) {
|
|
7421
|
+
if (!isImageFilePath(filePath)) return void 0;
|
|
7422
|
+
if (buf.length > MAX_PREVIEW_BYTES) return void 0;
|
|
7423
|
+
return `data:${imageMimeType(filePath)};base64,${buf.toString("base64")}`;
|
|
7424
|
+
}
|
|
7425
|
+
function attachmentFromBuffer(name, buf, opts) {
|
|
7426
|
+
const previewDataUrl = previewDataUrlFromBuf(name, buf);
|
|
7427
|
+
if (isImageFilePath(name)) {
|
|
7428
|
+
const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
|
|
7429
|
+
return {
|
|
7430
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
7431
|
+
name,
|
|
7432
|
+
kind: "file",
|
|
7433
|
+
path: opts.path,
|
|
7434
|
+
previewDataUrl,
|
|
7435
|
+
content: [
|
|
7436
|
+
`Image attached: ${pathHint}`,
|
|
7437
|
+
opts.path ? `Use the Read tool on \`${opts.path}\` to view this image.` : "The image is shown in the composer; copy it into the worktree if you need to inspect pixels."
|
|
7438
|
+
].join("\n")
|
|
7439
|
+
};
|
|
7440
|
+
}
|
|
7441
|
+
if (buf.length > MAX_INLINE_BYTES) {
|
|
7442
|
+
return {
|
|
7443
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
7444
|
+
name,
|
|
7445
|
+
kind: "file",
|
|
7446
|
+
path: opts.path,
|
|
7447
|
+
content: opts.path ? `(file too large to attach inline: \`${opts.path}\`, ${buf.length} bytes \u2014 use the Read tool)` : `(file too large to attach inline: ${opts.sourceLabel || name}, ${buf.length} bytes)`
|
|
7448
|
+
};
|
|
7449
|
+
}
|
|
7450
|
+
if (buf.includes(0)) {
|
|
7451
|
+
return {
|
|
7452
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
7453
|
+
name,
|
|
7454
|
+
kind: "file",
|
|
7455
|
+
path: opts.path,
|
|
7456
|
+
content: opts.path ? `(binary file at \`${opts.path}\` \u2014 use tools to inspect)` : `(binary file attached by path only: ${opts.sourceLabel || name})`
|
|
7457
|
+
};
|
|
7458
|
+
}
|
|
7459
|
+
return {
|
|
7460
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
7461
|
+
name,
|
|
7462
|
+
kind: "file",
|
|
7463
|
+
path: opts.path,
|
|
7464
|
+
content: buf.toString("utf8")
|
|
7465
|
+
};
|
|
7466
|
+
}
|
|
7467
|
+
function attachmentFromAbsolutePath(absolutePath) {
|
|
7468
|
+
const name = (0, import_node_path19.basename)(absolutePath);
|
|
7469
|
+
try {
|
|
7470
|
+
const st = (0, import_node_fs19.statSync)(absolutePath);
|
|
7471
|
+
if (!st.isFile()) {
|
|
7472
|
+
return {
|
|
7473
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
7474
|
+
name,
|
|
7475
|
+
kind: "file",
|
|
7476
|
+
content: `(not a file: ${absolutePath})`
|
|
7477
|
+
};
|
|
7478
|
+
}
|
|
7479
|
+
const buf = (0, import_node_fs19.readFileSync)(absolutePath);
|
|
7480
|
+
return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
|
|
7481
|
+
} catch (err) {
|
|
7482
|
+
return {
|
|
7483
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
7484
|
+
name,
|
|
7485
|
+
kind: "file",
|
|
7486
|
+
content: `(could not read ${absolutePath}: ${err instanceof Error ? err.message : String(err)})`
|
|
7487
|
+
};
|
|
7488
|
+
}
|
|
7489
|
+
}
|
|
7490
|
+
function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
7491
|
+
if (absolutePaths.length === 0) return [];
|
|
7492
|
+
const dir = ensureAttachmentsDir(worktreePath);
|
|
7493
|
+
const out = [];
|
|
7494
|
+
for (const abs of absolutePaths) {
|
|
7495
|
+
const originalName = (0, import_node_path19.basename)(abs);
|
|
7496
|
+
try {
|
|
7497
|
+
const st = (0, import_node_fs19.statSync)(abs);
|
|
7498
|
+
if (!st.isFile()) continue;
|
|
7499
|
+
const name = uniqueAttachmentName(dir, originalName);
|
|
7500
|
+
const destAbs = (0, import_node_path19.join)(dir, name);
|
|
7501
|
+
(0, import_node_fs19.copyFileSync)(abs, destAbs);
|
|
7502
|
+
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
7503
|
+
const buf = (0, import_node_fs19.readFileSync)(destAbs);
|
|
7504
|
+
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
7505
|
+
} catch (err) {
|
|
7506
|
+
out.push({
|
|
7507
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
7508
|
+
name: originalName,
|
|
7509
|
+
kind: "file",
|
|
7510
|
+
content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
|
|
7511
|
+
});
|
|
7512
|
+
}
|
|
7513
|
+
}
|
|
7514
|
+
return out;
|
|
7515
|
+
}
|
|
7516
|
+
function stageBuffersAsAttachments(worktreePath, buffers) {
|
|
7517
|
+
if (buffers.length === 0) return [];
|
|
7518
|
+
const dir = ensureAttachmentsDir(worktreePath);
|
|
7519
|
+
const out = [];
|
|
7520
|
+
for (const item of buffers) {
|
|
7521
|
+
const originalName = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
7522
|
+
try {
|
|
7523
|
+
const buf = Buffer.from(item.dataBase64, "base64");
|
|
7524
|
+
const name = uniqueAttachmentName(dir, originalName);
|
|
7525
|
+
const destAbs = (0, import_node_path19.join)(dir, name);
|
|
7526
|
+
(0, import_node_fs19.writeFileSync)(destAbs, buf);
|
|
7527
|
+
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
7528
|
+
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
7529
|
+
} catch (err) {
|
|
7530
|
+
out.push({
|
|
7531
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
7532
|
+
name: originalName,
|
|
7533
|
+
kind: "file",
|
|
7534
|
+
content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
|
|
7535
|
+
});
|
|
7536
|
+
}
|
|
7537
|
+
}
|
|
7538
|
+
return out;
|
|
7539
|
+
}
|
|
7540
|
+
function attachmentsFromBuffers(buffers) {
|
|
7541
|
+
return buffers.map((item) => {
|
|
7542
|
+
const name = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
7543
|
+
try {
|
|
7544
|
+
const buf = Buffer.from(item.dataBase64, "base64");
|
|
7545
|
+
return attachmentFromBuffer(name, buf, { sourceLabel: name });
|
|
7546
|
+
} catch (err) {
|
|
7547
|
+
return {
|
|
7548
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
7549
|
+
name,
|
|
7550
|
+
kind: "file",
|
|
7551
|
+
content: `(could not attach ${name}: ${err instanceof Error ? err.message : String(err)})`
|
|
7552
|
+
};
|
|
7553
|
+
}
|
|
7554
|
+
});
|
|
7555
|
+
}
|
|
7556
|
+
function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
7557
|
+
const out = [];
|
|
7558
|
+
for (const rel of relativePaths) {
|
|
7559
|
+
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
7560
|
+
out.push({
|
|
7561
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
7562
|
+
name: (0, import_node_path19.basename)(rel) || "file",
|
|
7563
|
+
kind: "file",
|
|
7564
|
+
content: `(invalid path: ${rel})`
|
|
7565
|
+
});
|
|
7566
|
+
continue;
|
|
7567
|
+
}
|
|
7568
|
+
const name = (0, import_node_path19.basename)(rel);
|
|
7569
|
+
try {
|
|
7570
|
+
const abs = (0, import_node_path19.join)(worktreePath, rel);
|
|
7571
|
+
const st = (0, import_node_fs19.statSync)(abs);
|
|
7572
|
+
if (!st.isFile()) continue;
|
|
7573
|
+
const buf = (0, import_node_fs19.readFileSync)(abs);
|
|
7574
|
+
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
7575
|
+
} catch (err) {
|
|
7576
|
+
out.push({
|
|
7577
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
7578
|
+
name,
|
|
7579
|
+
kind: "file",
|
|
7580
|
+
content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
|
|
7581
|
+
});
|
|
7582
|
+
}
|
|
7583
|
+
}
|
|
7584
|
+
return out;
|
|
7585
|
+
}
|
|
7586
|
+
|
|
7349
7587
|
// src/composer/summarize.ts
|
|
7350
7588
|
init_run();
|
|
7351
7589
|
init_path();
|
|
@@ -7784,14 +8022,14 @@ async function confirmLand(thread, opts) {
|
|
|
7784
8022
|
}
|
|
7785
8023
|
|
|
7786
8024
|
// src/threads/create.ts
|
|
7787
|
-
var
|
|
8025
|
+
var import_node_fs20 = require("fs");
|
|
7788
8026
|
init_worktree();
|
|
7789
8027
|
init_thread_store();
|
|
7790
8028
|
init_workspaces();
|
|
7791
8029
|
async function createThread(input, onSetupLine) {
|
|
7792
8030
|
await requireAgent(input.agent);
|
|
7793
8031
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
7794
|
-
if (!(0,
|
|
8032
|
+
if (!(0, import_node_fs20.existsSync)(repoPath)) {
|
|
7795
8033
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
7796
8034
|
}
|
|
7797
8035
|
let sourceRef = input.sourceRef;
|
|
@@ -7874,7 +8112,7 @@ async function listLinearIssues(agent, repoPath) {
|
|
|
7874
8112
|
}
|
|
7875
8113
|
|
|
7876
8114
|
// src/threads/chat-tabs.ts
|
|
7877
|
-
var
|
|
8115
|
+
var import_node_crypto3 = require("crypto");
|
|
7878
8116
|
init_teams();
|
|
7879
8117
|
init_worktree_labels();
|
|
7880
8118
|
init_global_workspace();
|
|
@@ -7930,7 +8168,7 @@ function forkMessageSlice(from, throughIndex) {
|
|
|
7930
8168
|
function buildForkTranscriptAttachment(baseTitle, messages) {
|
|
7931
8169
|
const title = baseTitle || "Chat";
|
|
7932
8170
|
return {
|
|
7933
|
-
id: (0,
|
|
8171
|
+
id: (0, import_node_crypto3.randomUUID)(),
|
|
7934
8172
|
name: `Transcript of ${title}.md`,
|
|
7935
8173
|
kind: "transcript",
|
|
7936
8174
|
content: formatTranscriptMarkdown(title, messages)
|
|
@@ -7989,30 +8227,34 @@ async function forkThreadWorktree(input, onSetupLine) {
|
|
|
7989
8227
|
repoPath: from.repoPath,
|
|
7990
8228
|
agent: input.agent ?? from.agent,
|
|
7991
8229
|
autonomy: from.autonomy,
|
|
8230
|
+
model: from.model,
|
|
8231
|
+
fast: from.fast,
|
|
8232
|
+
planMode: from.planMode,
|
|
7992
8233
|
title: input.title?.trim() || void 0,
|
|
7993
|
-
parentThreadId: from.id
|
|
8234
|
+
parentThreadId: from.id,
|
|
8235
|
+
attachments: [attachment]
|
|
7994
8236
|
},
|
|
7995
8237
|
onSetupLine
|
|
7996
8238
|
);
|
|
7997
|
-
return
|
|
8239
|
+
return thread;
|
|
7998
8240
|
}
|
|
7999
8241
|
|
|
8000
8242
|
// src/threads/adopt.ts
|
|
8001
8243
|
var import_node_child_process = require("child_process");
|
|
8002
|
-
var
|
|
8244
|
+
var import_node_fs21 = require("fs");
|
|
8003
8245
|
var import_node_os9 = require("os");
|
|
8004
|
-
var
|
|
8246
|
+
var import_node_path20 = require("path");
|
|
8005
8247
|
var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
8006
8248
|
init_worktree();
|
|
8007
8249
|
init_thread_store();
|
|
8008
|
-
var CONDUCTOR_APP_SUPPORT = (0,
|
|
8250
|
+
var CONDUCTOR_APP_SUPPORT = (0, import_node_path20.join)(
|
|
8009
8251
|
process.env.HOME ?? "",
|
|
8010
8252
|
"Library",
|
|
8011
8253
|
"Application Support",
|
|
8012
8254
|
"com.conductor.app"
|
|
8013
8255
|
);
|
|
8014
|
-
var CONDUCTOR_DB = (0,
|
|
8015
|
-
var CURSOR_SDK_STORE = (0,
|
|
8256
|
+
var CONDUCTOR_DB = (0, import_node_path20.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
8257
|
+
var CURSOR_SDK_STORE = (0, import_node_path20.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
8016
8258
|
function mapAgentType(raw) {
|
|
8017
8259
|
if (!raw) return null;
|
|
8018
8260
|
const v = raw.toLowerCase();
|
|
@@ -8024,21 +8266,21 @@ function mapAgentType(raw) {
|
|
|
8024
8266
|
return null;
|
|
8025
8267
|
}
|
|
8026
8268
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
8027
|
-
if (!workspacePath || !(0,
|
|
8269
|
+
if (!workspacePath || !(0, import_node_fs21.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
8028
8270
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
8029
8271
|
let best = null;
|
|
8030
8272
|
let hashes;
|
|
8031
8273
|
try {
|
|
8032
|
-
hashes = (0,
|
|
8274
|
+
hashes = (0, import_node_fs21.readdirSync)(CURSOR_SDK_STORE);
|
|
8033
8275
|
} catch {
|
|
8034
8276
|
return null;
|
|
8035
8277
|
}
|
|
8036
8278
|
for (const hash of hashes) {
|
|
8037
|
-
const agentsFile = (0,
|
|
8038
|
-
if (!(0,
|
|
8279
|
+
const agentsFile = (0, import_node_path20.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
8280
|
+
if (!(0, import_node_fs21.existsSync)(agentsFile)) continue;
|
|
8039
8281
|
let text;
|
|
8040
8282
|
try {
|
|
8041
|
-
text = (0,
|
|
8283
|
+
text = (0, import_node_fs21.readFileSync)(agentsFile, "utf8");
|
|
8042
8284
|
} catch {
|
|
8043
8285
|
continue;
|
|
8044
8286
|
}
|
|
@@ -8062,7 +8304,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
8062
8304
|
return best?.agentId ?? null;
|
|
8063
8305
|
}
|
|
8064
8306
|
async function adoptThread(input) {
|
|
8065
|
-
if (!(0,
|
|
8307
|
+
if (!(0, import_node_fs21.existsSync)(input.worktreePath)) {
|
|
8066
8308
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
8067
8309
|
}
|
|
8068
8310
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -8089,18 +8331,18 @@ function conductorDbPath() {
|
|
|
8089
8331
|
return CONDUCTOR_DB;
|
|
8090
8332
|
}
|
|
8091
8333
|
function listConductorWorkspaces() {
|
|
8092
|
-
if (!(0,
|
|
8334
|
+
if (!(0, import_node_fs21.existsSync)(CONDUCTOR_DB)) {
|
|
8093
8335
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
8094
8336
|
}
|
|
8095
|
-
const tmp = (0,
|
|
8096
|
-
const snapshot = (0,
|
|
8337
|
+
const tmp = (0, import_node_fs21.mkdtempSync)((0, import_node_path20.join)((0, import_node_os9.tmpdir)(), "sideboard-conductor-"));
|
|
8338
|
+
const snapshot = (0, import_node_path20.join)(tmp, "conductor.db");
|
|
8097
8339
|
try {
|
|
8098
|
-
(0,
|
|
8340
|
+
(0, import_node_fs21.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
8099
8341
|
for (const suffix of ["-wal", "-shm"]) {
|
|
8100
8342
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
8101
|
-
if ((0,
|
|
8343
|
+
if ((0, import_node_fs21.existsSync)(src)) {
|
|
8102
8344
|
try {
|
|
8103
|
-
(0,
|
|
8345
|
+
(0, import_node_fs21.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
8104
8346
|
} catch {
|
|
8105
8347
|
}
|
|
8106
8348
|
}
|
|
@@ -8176,22 +8418,22 @@ function listConductorWorkspaces() {
|
|
|
8176
8418
|
db.close();
|
|
8177
8419
|
}
|
|
8178
8420
|
} finally {
|
|
8179
|
-
(0,
|
|
8421
|
+
(0, import_node_fs21.rmSync)(tmp, { recursive: true, force: true });
|
|
8180
8422
|
}
|
|
8181
8423
|
}
|
|
8182
8424
|
function importConductorWorkspace(workspaceId) {
|
|
8183
|
-
if (!(0,
|
|
8425
|
+
if (!(0, import_node_fs21.existsSync)(CONDUCTOR_DB)) {
|
|
8184
8426
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
8185
8427
|
}
|
|
8186
|
-
const tmp = (0,
|
|
8187
|
-
const snapshot = (0,
|
|
8428
|
+
const tmp = (0, import_node_fs21.mkdtempSync)((0, import_node_path20.join)((0, import_node_os9.tmpdir)(), "sideboard-conductor-"));
|
|
8429
|
+
const snapshot = (0, import_node_path20.join)(tmp, "conductor.db");
|
|
8188
8430
|
try {
|
|
8189
|
-
(0,
|
|
8431
|
+
(0, import_node_fs21.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
8190
8432
|
for (const suffix of ["-wal", "-shm"]) {
|
|
8191
8433
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
8192
|
-
if ((0,
|
|
8434
|
+
if ((0, import_node_fs21.existsSync)(src)) {
|
|
8193
8435
|
try {
|
|
8194
|
-
(0,
|
|
8436
|
+
(0, import_node_fs21.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
8195
8437
|
} catch {
|
|
8196
8438
|
}
|
|
8197
8439
|
}
|
|
@@ -8209,7 +8451,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
8209
8451
|
).get(workspaceId);
|
|
8210
8452
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
8211
8453
|
const worktreePath = String(row.workspacePath);
|
|
8212
|
-
if (!(0,
|
|
8454
|
+
if (!(0, import_node_fs21.existsSync)(worktreePath)) {
|
|
8213
8455
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
8214
8456
|
}
|
|
8215
8457
|
let sessionId = null;
|
|
@@ -8272,7 +8514,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
8272
8514
|
db.close();
|
|
8273
8515
|
}
|
|
8274
8516
|
} finally {
|
|
8275
|
-
(0,
|
|
8517
|
+
(0, import_node_fs21.rmSync)(tmp, { recursive: true, force: true });
|
|
8276
8518
|
}
|
|
8277
8519
|
}
|
|
8278
8520
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
@@ -8281,13 +8523,13 @@ async function importConductorWorkspaceAsync(workspaceId) {
|
|
|
8281
8523
|
|
|
8282
8524
|
// src/orchestrator/orchestrator.ts
|
|
8283
8525
|
var import_node_events = require("events");
|
|
8284
|
-
var
|
|
8526
|
+
var import_node_fs24 = require("fs");
|
|
8285
8527
|
init_agents();
|
|
8286
8528
|
init_worktree();
|
|
8287
8529
|
|
|
8288
8530
|
// src/git/orphan-cleanup.ts
|
|
8289
|
-
var
|
|
8290
|
-
var
|
|
8531
|
+
var import_node_fs22 = require("fs");
|
|
8532
|
+
var import_node_path21 = require("path");
|
|
8291
8533
|
init_worktree();
|
|
8292
8534
|
init_thread_store();
|
|
8293
8535
|
init_paths();
|
|
@@ -8302,9 +8544,9 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
8302
8544
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
8303
8545
|
);
|
|
8304
8546
|
const homeRoot = sideboardWorkspacesDir();
|
|
8305
|
-
if ((0,
|
|
8547
|
+
if ((0, import_node_fs22.existsSync)(homeRoot)) {
|
|
8306
8548
|
try {
|
|
8307
|
-
for (const entry of (0,
|
|
8549
|
+
for (const entry of (0, import_node_fs22.readdirSync)(homeRoot, { withFileTypes: true })) {
|
|
8308
8550
|
if (!entry.isDirectory()) continue;
|
|
8309
8551
|
void entry;
|
|
8310
8552
|
}
|
|
@@ -8314,7 +8556,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
8314
8556
|
const orphans = [];
|
|
8315
8557
|
const seen = /* @__PURE__ */ new Set();
|
|
8316
8558
|
for (const repoPath of repos) {
|
|
8317
|
-
if (!repoPath || !(0,
|
|
8559
|
+
if (!repoPath || !(0, import_node_fs22.existsSync)(repoPath)) continue;
|
|
8318
8560
|
try {
|
|
8319
8561
|
const wts = await listWorktrees(repoPath);
|
|
8320
8562
|
for (const wt of wts) {
|
|
@@ -8325,7 +8567,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
8325
8567
|
seen.add(path);
|
|
8326
8568
|
let mtimeMs = 0;
|
|
8327
8569
|
try {
|
|
8328
|
-
mtimeMs = (0,
|
|
8570
|
+
mtimeMs = (0, import_node_fs22.statSync)(path).mtimeMs;
|
|
8329
8571
|
} catch {
|
|
8330
8572
|
mtimeMs = 0;
|
|
8331
8573
|
}
|
|
@@ -8335,16 +8577,16 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
8335
8577
|
}
|
|
8336
8578
|
try {
|
|
8337
8579
|
const root = worktreesRoot(repoPath);
|
|
8338
|
-
if ((0,
|
|
8339
|
-
for (const entry of (0,
|
|
8580
|
+
if ((0, import_node_fs22.existsSync)(root)) {
|
|
8581
|
+
for (const entry of (0, import_node_fs22.readdirSync)(root, { withFileTypes: true })) {
|
|
8340
8582
|
if (!entry.isDirectory()) continue;
|
|
8341
|
-
const path = (0,
|
|
8583
|
+
const path = (0, import_node_path21.join)(root, entry.name).replace(/\/$/, "");
|
|
8342
8584
|
if (known.has(path) || seen.has(path)) continue;
|
|
8343
|
-
if (!(0,
|
|
8585
|
+
if (!(0, import_node_fs22.existsSync)((0, import_node_path21.join)(path, ".git"))) continue;
|
|
8344
8586
|
seen.add(path);
|
|
8345
8587
|
let mtimeMs = 0;
|
|
8346
8588
|
try {
|
|
8347
|
-
mtimeMs = (0,
|
|
8589
|
+
mtimeMs = (0, import_node_fs22.statSync)(path).mtimeMs;
|
|
8348
8590
|
} catch {
|
|
8349
8591
|
mtimeMs = Date.now();
|
|
8350
8592
|
}
|
|
@@ -8490,8 +8732,8 @@ async function applyThreadIntoMain(thread, opts) {
|
|
|
8490
8732
|
}
|
|
8491
8733
|
|
|
8492
8734
|
// src/git/clone-repo.ts
|
|
8493
|
-
var
|
|
8494
|
-
var
|
|
8735
|
+
var import_node_fs23 = require("fs");
|
|
8736
|
+
var import_node_path22 = require("path");
|
|
8495
8737
|
var import_execa6 = require("execa");
|
|
8496
8738
|
init_paths();
|
|
8497
8739
|
init_workspaces();
|
|
@@ -8501,12 +8743,12 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
8501
8743
|
if (!url) throw new Error("Clone URL is required");
|
|
8502
8744
|
let name = opts.name?.trim();
|
|
8503
8745
|
if (!name) {
|
|
8504
|
-
const leaf = (0,
|
|
8746
|
+
const leaf = (0, import_node_path22.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
|
|
8505
8747
|
name = leaf || "repo";
|
|
8506
8748
|
}
|
|
8507
8749
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
8508
|
-
const dest = (0,
|
|
8509
|
-
if ((0,
|
|
8750
|
+
const dest = (0, import_node_path22.join)(sideboardReposDir(), name);
|
|
8751
|
+
if ((0, import_node_fs23.existsSync)(dest)) {
|
|
8510
8752
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
8511
8753
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
8512
8754
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -8618,7 +8860,7 @@ var Orchestrator = class {
|
|
|
8618
8860
|
}
|
|
8619
8861
|
continue;
|
|
8620
8862
|
}
|
|
8621
|
-
if (!(0,
|
|
8863
|
+
if (!(0, import_node_fs24.existsSync)(thread.worktreePath)) {
|
|
8622
8864
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
8623
8865
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
8624
8866
|
continue;
|
|
@@ -9430,6 +9672,23 @@ var Orchestrator = class {
|
|
|
9430
9672
|
setAttachments(threadRef, attachments) {
|
|
9431
9673
|
return updateThread(this.requireThread(threadRef).id, { attachments });
|
|
9432
9674
|
}
|
|
9675
|
+
/**
|
|
9676
|
+
* Stage OS / worktree files into composer attachments (copies external files
|
|
9677
|
+
* into `.sideboard/attachments/` so agents can Read images and binaries).
|
|
9678
|
+
*/
|
|
9679
|
+
attachComposerFiles(threadRef, opts) {
|
|
9680
|
+
const thread = this.requireThread(threadRef);
|
|
9681
|
+
const fromAbs = stageAbsolutePathsAsAttachments(
|
|
9682
|
+
thread.worktreePath,
|
|
9683
|
+
opts.absolutePaths ?? []
|
|
9684
|
+
);
|
|
9685
|
+
const fromRel = attachmentsFromWorktreePaths(
|
|
9686
|
+
thread.worktreePath,
|
|
9687
|
+
opts.relativePaths ?? []
|
|
9688
|
+
);
|
|
9689
|
+
const fromBuf = stageBuffersAsAttachments(thread.worktreePath, opts.buffers ?? []);
|
|
9690
|
+
return [...fromAbs, ...fromRel, ...fromBuf];
|
|
9691
|
+
}
|
|
9433
9692
|
listWorktreeChats(threadRef) {
|
|
9434
9693
|
const thread = this.requireThread(threadRef);
|
|
9435
9694
|
return threadsSharingWorktree(thread.worktreePath);
|
|
@@ -9489,7 +9748,7 @@ var Orchestrator = class {
|
|
|
9489
9748
|
updateThread(thread.id, { worktreePath: globalAgentCwd2() });
|
|
9490
9749
|
return setStatus(thread.id, "idle");
|
|
9491
9750
|
}
|
|
9492
|
-
if (!(0,
|
|
9751
|
+
if (!(0, import_node_fs24.existsSync)(thread.worktreePath)) {
|
|
9493
9752
|
const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
|
|
9494
9753
|
const { execa: execa7 } = await import("execa");
|
|
9495
9754
|
const slug = thread.worktreePath.split("/").pop();
|
|
@@ -9591,7 +9850,7 @@ init_coordinator_prompt();
|
|
|
9591
9850
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
9592
9851
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
9593
9852
|
var import_zod = require("zod");
|
|
9594
|
-
var
|
|
9853
|
+
var import_node_path23 = require("path");
|
|
9595
9854
|
init_worktree();
|
|
9596
9855
|
init_global_workspace();
|
|
9597
9856
|
|
|
@@ -9639,7 +9898,7 @@ async function startMcpServer() {
|
|
|
9639
9898
|
async () => {
|
|
9640
9899
|
const threads = orch.getThreads(true);
|
|
9641
9900
|
const lines = threads.map((t) => {
|
|
9642
|
-
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0,
|
|
9901
|
+
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path23.basename)(t.repoPath) || t.repoPath;
|
|
9643
9902
|
return `${t.id.slice(0, 8)} ${t.status.padEnd(9)} ${t.agent.padEnd(8)} ${repo} ${t.sourceType}:${t.sourceRef} ${t.title} sideboard://thread/${t.id}${t.devPort ? ` http://localhost:${t.devPort}` : ""}`;
|
|
9644
9903
|
});
|
|
9645
9904
|
return {
|
|
@@ -10535,6 +10794,9 @@ init_injected_mcp();
|
|
|
10535
10794
|
applyAppEnvironment,
|
|
10536
10795
|
applyCompaction,
|
|
10537
10796
|
applyThreadIntoMain,
|
|
10797
|
+
attachmentFromAbsolutePath,
|
|
10798
|
+
attachmentsFromBuffers,
|
|
10799
|
+
attachmentsFromWorktreePaths,
|
|
10538
10800
|
autoCleanupOrphansEnabled,
|
|
10539
10801
|
autoRenameBranchEnabled,
|
|
10540
10802
|
autoRunAfterSetupEnabled,
|
|
@@ -10657,6 +10919,7 @@ init_injected_mcp();
|
|
|
10657
10919
|
isGhRateLimitError,
|
|
10658
10920
|
isGlobalRepoPath,
|
|
10659
10921
|
isGlobalThread,
|
|
10922
|
+
isImageFilePath,
|
|
10660
10923
|
isLinearConnected,
|
|
10661
10924
|
isOrchestratorThread,
|
|
10662
10925
|
isPlaceholderBranch,
|
|
@@ -10745,6 +11008,8 @@ init_injected_mcp();
|
|
|
10745
11008
|
slugify,
|
|
10746
11009
|
spawnAgentTurn,
|
|
10747
11010
|
splitForCompaction,
|
|
11011
|
+
stageAbsolutePathsAsAttachments,
|
|
11012
|
+
stageBuffersAsAttachments,
|
|
10748
11013
|
startDevServer,
|
|
10749
11014
|
startMcpServer,
|
|
10750
11015
|
startOrchestration,
|