@sideboard-ai/core 0.1.133 → 0.1.136
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/{agents-NHS6P25H.js → agents-ELWR7A2T.js} +5 -5
- package/dist/{agents-SOU5GPWI.js → agents-QNTTLMG2.js} +5 -5
- package/dist/{chunk-Y645NFYN.js → chunk-4XKUHP6G.js} +2 -2
- package/dist/{chunk-4YAVXWFR.js → chunk-CYM5DCHI.js} +39 -5
- package/dist/{chunk-LTP7GHIF.js → chunk-GSKRGF7B.js} +286 -5
- package/dist/{chunk-WEU5M7BW.js → chunk-HQQNLDVC.js} +1 -1
- package/dist/{chunk-IM36S4HZ.js → chunk-IFZ4MOTN.js} +3 -3
- package/dist/{chunk-G6X6UFJO.js → chunk-J5IBSVB3.js} +42 -12
- package/dist/{chunk-AK7SWE2U.js → chunk-JPBRMUM6.js} +9 -5
- package/dist/{chunk-YEIH7P7D.js → chunk-K5YT5GX2.js} +244 -5
- package/dist/{chunk-3UVVWNHF.js → chunk-MDCKV2NF.js} +2 -2
- package/dist/{chunk-HLJUNJBF.js → chunk-PM3C2J6K.js} +42 -12
- package/dist/{chunk-Q6XQXCOM.js → chunk-QAV3HGVS.js} +1 -1
- package/dist/{chunk-TG7YU2KG.js → chunk-TIGKDMIA.js} +144 -271
- package/dist/{chunk-6CRKPD4C.js → chunk-TQ4S5AGJ.js} +3 -3
- package/dist/{chunk-VSON7EJ6.js → chunk-WS5LFFU3.js} +140 -222
- package/dist/{coordinator-prompt-DXHEDRRN.js → coordinator-prompt-2OWSUAUR.js} +3 -3
- package/dist/{coordinator-prompt-XF7LVOUN.js → coordinator-prompt-IPL4Z6SL.js} +3 -3
- package/dist/{global-workspace-2LO5ATOH.js → global-workspace-JDUCUL7S.js} +4 -4
- package/dist/{global-workspace-MLQNULOU.js → global-workspace-NIKZAKOO.js} +4 -4
- package/dist/index.cjs +873 -628
- package/dist/index.d.cts +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +42 -19
- package/dist/mcp/run-stdio.cjs +700 -498
- package/dist/mcp/run-stdio.js +22 -11
- package/dist/{orchestrator-P2SYHVLS.js → orchestrator-6I47JMU2.js} +7 -7
- package/dist/{orchestrator-KR5RA5B7.js → orchestrator-KK3CUW37.js} +7 -7
- package/dist/{thread-store-5MLYY35S.js → thread-store-CRLQJ2HM.js} +3 -1
- package/dist/{thread-store-F6BCARQG.js → thread-store-FADXSMEJ.js} +3 -1
- package/dist/{workspaces-MINB764G.js → workspaces-5EWNNALF.js} +5 -5
- package/dist/{workspaces-ARWPZG6F.js → workspaces-KZA3TCEE.js} +5 -5
- package/dist/{worktree-EBZMUUAL.js → worktree-BC6XDMQK.js} +2 -2
- package/dist/{worktree-S7MKMYAT.js → worktree-MX7XBX6Z.js} +2 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2075,6 +2075,7 @@ __export(thread_store_exports, {
|
|
|
2075
2075
|
createEmptyThread: () => createEmptyThread,
|
|
2076
2076
|
deleteThreadRecord: () => deleteThreadRecord,
|
|
2077
2077
|
findThreadByRef: () => findThreadByRef,
|
|
2078
|
+
invalidateThreadListCache: () => invalidateThreadListCache,
|
|
2078
2079
|
isThreadRecordFile: () => isThreadRecordFile,
|
|
2079
2080
|
listThreads: () => listThreads,
|
|
2080
2081
|
normalizeThread: () => normalizeThread,
|
|
@@ -2172,11 +2173,28 @@ async function withThreadLock(id, fn) {
|
|
|
2172
2173
|
if (release) await release();
|
|
2173
2174
|
}
|
|
2174
2175
|
}
|
|
2176
|
+
function cacheForDir() {
|
|
2177
|
+
const dir = threadsDir();
|
|
2178
|
+
if (!listCache || listCache.dir !== dir) {
|
|
2179
|
+
listCache = { dir, byId: /* @__PURE__ */ new Map(), listed: false };
|
|
2180
|
+
}
|
|
2181
|
+
return listCache;
|
|
2182
|
+
}
|
|
2183
|
+
function invalidateThreadListCache() {
|
|
2184
|
+
listCache = null;
|
|
2185
|
+
}
|
|
2186
|
+
function rememberThread(thread) {
|
|
2187
|
+
cacheForDir().byId.set(thread.id, thread);
|
|
2188
|
+
}
|
|
2175
2189
|
function readThread(id) {
|
|
2190
|
+
const cached = cacheForDir().byId.get(id);
|
|
2191
|
+
if (cached) return cached;
|
|
2176
2192
|
const path2 = threadFilePath(id);
|
|
2177
2193
|
if (!(0, import_node_fs9.existsSync)(path2)) return null;
|
|
2178
2194
|
const raw = (0, import_node_fs9.readFileSync)(path2, "utf8");
|
|
2179
|
-
|
|
2195
|
+
const thread = normalizeThread(JSON.parse(raw));
|
|
2196
|
+
rememberThread(thread);
|
|
2197
|
+
return thread;
|
|
2180
2198
|
}
|
|
2181
2199
|
function writeThread(thread) {
|
|
2182
2200
|
const path2 = threadFilePath(idPath(thread.id));
|
|
@@ -2184,6 +2202,7 @@ function writeThread(thread) {
|
|
|
2184
2202
|
const next = { ...thread, updatedAt: nowIso() };
|
|
2185
2203
|
(0, import_node_fs9.writeFileSync)(tmp, JSON.stringify(next, null, 2), "utf8");
|
|
2186
2204
|
(0, import_node_fs9.renameSync)(tmp, path2);
|
|
2205
|
+
rememberThread(next);
|
|
2187
2206
|
}
|
|
2188
2207
|
function idPath(id) {
|
|
2189
2208
|
return id;
|
|
@@ -2193,22 +2212,32 @@ function isThreadRecordFile(nameOrPath) {
|
|
|
2193
2212
|
return name.endsWith(".json") && !name.endsWith(".live.json");
|
|
2194
2213
|
}
|
|
2195
2214
|
function listThreads(opts) {
|
|
2196
|
-
const
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2215
|
+
const cache = cacheForDir();
|
|
2216
|
+
if (!cache.listed) {
|
|
2217
|
+
const files = (0, import_node_fs9.readdirSync)(threadsDir()).filter(isThreadRecordFile);
|
|
2218
|
+
const byId = /* @__PURE__ */ new Map();
|
|
2219
|
+
for (const f of files) {
|
|
2220
|
+
try {
|
|
2221
|
+
const thread = normalizeThread(
|
|
2222
|
+
JSON.parse((0, import_node_fs9.readFileSync)(threadFilePath(f.replace(/\.json$/, "")), "utf8"))
|
|
2223
|
+
);
|
|
2224
|
+
if (typeof thread.id === "string" && thread.id.length > 0) {
|
|
2225
|
+
byId.set(thread.id, thread);
|
|
2226
|
+
}
|
|
2227
|
+
} catch {
|
|
2228
|
+
}
|
|
2204
2229
|
}
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2230
|
+
cache.byId = byId;
|
|
2231
|
+
cache.listed = true;
|
|
2232
|
+
}
|
|
2233
|
+
const threads = [...cache.byId.values()].sort(
|
|
2234
|
+
(a, b) => b.updatedAt.localeCompare(a.updatedAt)
|
|
2235
|
+
);
|
|
2208
2236
|
if (opts?.includeArchived) return threads;
|
|
2209
2237
|
return threads.filter((t) => t.status !== "archived");
|
|
2210
2238
|
}
|
|
2211
2239
|
function deleteThreadRecord(id) {
|
|
2240
|
+
cacheForDir().byId.delete(id);
|
|
2212
2241
|
const path2 = threadFilePath(id);
|
|
2213
2242
|
if ((0, import_node_fs9.existsSync)(path2)) (0, import_node_fs9.unlinkSync)(path2);
|
|
2214
2243
|
const lock = threadLockPath(id);
|
|
@@ -2240,7 +2269,7 @@ function findThreadByRef(ref) {
|
|
|
2240
2269
|
(t) => t.id === ref || t.id.startsWith(ref) || t.branchName === ref || t.title === ref
|
|
2241
2270
|
) ?? null;
|
|
2242
2271
|
}
|
|
2243
|
-
var import_node_crypto3, import_node_fs9, import_node_path10, import_proper_lockfile;
|
|
2272
|
+
var import_node_crypto3, import_node_fs9, import_node_path10, import_proper_lockfile, listCache;
|
|
2244
2273
|
var init_thread_store = __esm({
|
|
2245
2274
|
"src/store/thread-store.ts"() {
|
|
2246
2275
|
"use strict";
|
|
@@ -2250,6 +2279,7 @@ var init_thread_store = __esm({
|
|
|
2250
2279
|
import_proper_lockfile = __toESM(require("proper-lockfile"), 1);
|
|
2251
2280
|
init_thinking_effort();
|
|
2252
2281
|
init_paths();
|
|
2282
|
+
listCache = null;
|
|
2253
2283
|
}
|
|
2254
2284
|
});
|
|
2255
2285
|
|
|
@@ -2618,6 +2648,300 @@ var init_cloud_connect_constants = __esm({
|
|
|
2618
2648
|
}
|
|
2619
2649
|
});
|
|
2620
2650
|
|
|
2651
|
+
// src/paths/workspace-scratch.ts
|
|
2652
|
+
function attachmentsGitignoreBody() {
|
|
2653
|
+
return ATTACHMENTS_GITIGNORE;
|
|
2654
|
+
}
|
|
2655
|
+
function isWorkspaceScratchPath(relativePath) {
|
|
2656
|
+
const p = relativePath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
|
|
2657
|
+
return p === ATTACHMENTS_DIR || p.startsWith(`${ATTACHMENTS_DIR}/`) || p === LEGACY_ATTACHMENTS_DIR || p.startsWith(`${LEGACY_ATTACHMENTS_DIR}/`) || p === ".context" || p.startsWith(".context/");
|
|
2658
|
+
}
|
|
2659
|
+
var ATTACHMENTS_DIR, LEGACY_ATTACHMENTS_DIR, ATTACHMENTS_GITIGNORE;
|
|
2660
|
+
var init_workspace_scratch = __esm({
|
|
2661
|
+
"src/paths/workspace-scratch.ts"() {
|
|
2662
|
+
"use strict";
|
|
2663
|
+
ATTACHMENTS_DIR = ".context/attachments";
|
|
2664
|
+
LEGACY_ATTACHMENTS_DIR = ".sideboard/attachments";
|
|
2665
|
+
ATTACHMENTS_GITIGNORE = `# Sideboard / workspace attachments (local only)
|
|
2666
|
+
*
|
|
2667
|
+
!.gitignore
|
|
2668
|
+
`;
|
|
2669
|
+
}
|
|
2670
|
+
});
|
|
2671
|
+
|
|
2672
|
+
// src/composer/stage-files.ts
|
|
2673
|
+
function fileExtension(filePath) {
|
|
2674
|
+
const base = (0, import_node_path13.basename)(filePath).toLowerCase();
|
|
2675
|
+
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
2676
|
+
}
|
|
2677
|
+
function isImageFilePath(filePath) {
|
|
2678
|
+
return IMAGE_EXTENSIONS.has(fileExtension(filePath));
|
|
2679
|
+
}
|
|
2680
|
+
function imageMimeType(filePath) {
|
|
2681
|
+
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
2682
|
+
}
|
|
2683
|
+
function ensureAttachmentsDir(worktreePath) {
|
|
2684
|
+
const dir = (0, import_node_path13.join)(worktreePath, ATTACHMENTS_DIR);
|
|
2685
|
+
(0, import_node_fs12.mkdirSync)(dir, { recursive: true });
|
|
2686
|
+
const gi = (0, import_node_path13.join)(dir, ".gitignore");
|
|
2687
|
+
if (!(0, import_node_fs12.existsSync)(gi)) {
|
|
2688
|
+
(0, import_node_fs12.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
2689
|
+
}
|
|
2690
|
+
return dir;
|
|
2691
|
+
}
|
|
2692
|
+
function uniqueAttachmentName(dir, originalName) {
|
|
2693
|
+
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
2694
|
+
if (!(0, import_node_fs12.existsSync)((0, import_node_path13.join)(dir, safe))) return safe;
|
|
2695
|
+
const ext = (0, import_node_path13.extname)(safe);
|
|
2696
|
+
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
2697
|
+
for (let i = 1; i < 1e4; i++) {
|
|
2698
|
+
const candidate = `${stem}-${i}${ext}`;
|
|
2699
|
+
if (!(0, import_node_fs12.existsSync)((0, import_node_path13.join)(dir, candidate))) return candidate;
|
|
2700
|
+
}
|
|
2701
|
+
return `${stem}-${(0, import_node_crypto5.randomUUID)()}${ext}`;
|
|
2702
|
+
}
|
|
2703
|
+
function previewDataUrlFromBuf(filePath, buf) {
|
|
2704
|
+
if (!isImageFilePath(filePath)) return void 0;
|
|
2705
|
+
if (buf.length > MAX_PREVIEW_BYTES) return void 0;
|
|
2706
|
+
return `data:${imageMimeType(filePath)};base64,${buf.toString("base64")}`;
|
|
2707
|
+
}
|
|
2708
|
+
function attachmentFromBuffer(name, buf, opts) {
|
|
2709
|
+
const previewDataUrl = previewDataUrlFromBuf(name, buf);
|
|
2710
|
+
if (isImageFilePath(name)) {
|
|
2711
|
+
const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
|
|
2712
|
+
return {
|
|
2713
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
2714
|
+
name,
|
|
2715
|
+
kind: "file",
|
|
2716
|
+
path: opts.path,
|
|
2717
|
+
previewDataUrl,
|
|
2718
|
+
content: [
|
|
2719
|
+
`Image attached: ${pathHint}`,
|
|
2720
|
+
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."
|
|
2721
|
+
].join("\n")
|
|
2722
|
+
};
|
|
2723
|
+
}
|
|
2724
|
+
if (buf.length > MAX_INLINE_BYTES) {
|
|
2725
|
+
return {
|
|
2726
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
2727
|
+
name,
|
|
2728
|
+
kind: "file",
|
|
2729
|
+
path: opts.path,
|
|
2730
|
+
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)`
|
|
2731
|
+
};
|
|
2732
|
+
}
|
|
2733
|
+
if (buf.includes(0)) {
|
|
2734
|
+
return {
|
|
2735
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
2736
|
+
name,
|
|
2737
|
+
kind: "file",
|
|
2738
|
+
path: opts.path,
|
|
2739
|
+
content: opts.path ? `(binary file at \`${opts.path}\` \u2014 use tools to inspect)` : `(binary file attached by path only: ${opts.sourceLabel || name})`
|
|
2740
|
+
};
|
|
2741
|
+
}
|
|
2742
|
+
return {
|
|
2743
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
2744
|
+
name,
|
|
2745
|
+
kind: "file",
|
|
2746
|
+
path: opts.path,
|
|
2747
|
+
content: buf.toString("utf8")
|
|
2748
|
+
};
|
|
2749
|
+
}
|
|
2750
|
+
function attachmentFromAbsolutePath(absolutePath) {
|
|
2751
|
+
const name = (0, import_node_path13.basename)(absolutePath);
|
|
2752
|
+
try {
|
|
2753
|
+
const st = (0, import_node_fs12.statSync)(absolutePath);
|
|
2754
|
+
if (!st.isFile()) {
|
|
2755
|
+
return {
|
|
2756
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
2757
|
+
name,
|
|
2758
|
+
kind: "file",
|
|
2759
|
+
content: `(not a file: ${absolutePath})`
|
|
2760
|
+
};
|
|
2761
|
+
}
|
|
2762
|
+
const buf = (0, import_node_fs12.readFileSync)(absolutePath);
|
|
2763
|
+
return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
|
|
2764
|
+
} catch (err) {
|
|
2765
|
+
return {
|
|
2766
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
2767
|
+
name,
|
|
2768
|
+
kind: "file",
|
|
2769
|
+
content: `(could not read ${absolutePath}: ${err instanceof Error ? err.message : String(err)})`
|
|
2770
|
+
};
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
2774
|
+
if (absolutePaths.length === 0) return [];
|
|
2775
|
+
const dir = ensureAttachmentsDir(worktreePath);
|
|
2776
|
+
const out = [];
|
|
2777
|
+
for (const abs of absolutePaths) {
|
|
2778
|
+
const originalName = (0, import_node_path13.basename)(abs);
|
|
2779
|
+
try {
|
|
2780
|
+
const st = (0, import_node_fs12.statSync)(abs);
|
|
2781
|
+
if (!st.isFile()) continue;
|
|
2782
|
+
const name = uniqueAttachmentName(dir, originalName);
|
|
2783
|
+
const destAbs = (0, import_node_path13.join)(dir, name);
|
|
2784
|
+
(0, import_node_fs12.copyFileSync)(abs, destAbs);
|
|
2785
|
+
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
2786
|
+
const buf = (0, import_node_fs12.readFileSync)(destAbs);
|
|
2787
|
+
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
2788
|
+
} catch (err) {
|
|
2789
|
+
out.push({
|
|
2790
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
2791
|
+
name: originalName,
|
|
2792
|
+
kind: "file",
|
|
2793
|
+
content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
|
|
2794
|
+
});
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
return out;
|
|
2798
|
+
}
|
|
2799
|
+
function stageBuffersAsAttachments(worktreePath, buffers2) {
|
|
2800
|
+
if (buffers2.length === 0) return [];
|
|
2801
|
+
const dir = ensureAttachmentsDir(worktreePath);
|
|
2802
|
+
const out = [];
|
|
2803
|
+
for (const item of buffers2) {
|
|
2804
|
+
const originalName = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
2805
|
+
try {
|
|
2806
|
+
const buf = Buffer.from(item.dataBase64, "base64");
|
|
2807
|
+
const name = uniqueAttachmentName(dir, originalName);
|
|
2808
|
+
const destAbs = (0, import_node_path13.join)(dir, name);
|
|
2809
|
+
(0, import_node_fs12.writeFileSync)(destAbs, buf);
|
|
2810
|
+
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
2811
|
+
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
2812
|
+
} catch (err) {
|
|
2813
|
+
out.push({
|
|
2814
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
2815
|
+
name: originalName,
|
|
2816
|
+
kind: "file",
|
|
2817
|
+
content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
|
|
2818
|
+
});
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
return out;
|
|
2822
|
+
}
|
|
2823
|
+
function attachmentsFromBuffers(buffers2) {
|
|
2824
|
+
return buffers2.map((item) => {
|
|
2825
|
+
const name = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
2826
|
+
try {
|
|
2827
|
+
const buf = Buffer.from(item.dataBase64, "base64");
|
|
2828
|
+
return attachmentFromBuffer(name, buf, { sourceLabel: name });
|
|
2829
|
+
} catch (err) {
|
|
2830
|
+
return {
|
|
2831
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
2832
|
+
name,
|
|
2833
|
+
kind: "file",
|
|
2834
|
+
content: `(could not attach ${name}: ${err instanceof Error ? err.message : String(err)})`
|
|
2835
|
+
};
|
|
2836
|
+
}
|
|
2837
|
+
});
|
|
2838
|
+
}
|
|
2839
|
+
function isWorktreeRelativePath(p) {
|
|
2840
|
+
if (!p || p.includes("..")) return false;
|
|
2841
|
+
if (p.startsWith("/")) return false;
|
|
2842
|
+
if (/^[A-Za-z]:[\\/]/.test(p)) return false;
|
|
2843
|
+
return true;
|
|
2844
|
+
}
|
|
2845
|
+
function dataUrlToBase64(url) {
|
|
2846
|
+
if (!url) return null;
|
|
2847
|
+
const m = /^data:[^;]+;base64,(.+)$/s.exec(url);
|
|
2848
|
+
return m?.[1] ?? null;
|
|
2849
|
+
}
|
|
2850
|
+
function persistPendingFileAttachments(worktreePath, attachments) {
|
|
2851
|
+
if (attachments.length === 0) return attachments;
|
|
2852
|
+
const keep = [];
|
|
2853
|
+
const buffers2 = [];
|
|
2854
|
+
for (const att of attachments) {
|
|
2855
|
+
if (att.kind !== "file") {
|
|
2856
|
+
keep.push(att);
|
|
2857
|
+
continue;
|
|
2858
|
+
}
|
|
2859
|
+
if (att.path && isWorktreeRelativePath(att.path)) {
|
|
2860
|
+
keep.push(att);
|
|
2861
|
+
continue;
|
|
2862
|
+
}
|
|
2863
|
+
const fromPreview = dataUrlToBase64(att.previewDataUrl);
|
|
2864
|
+
if (fromPreview) {
|
|
2865
|
+
buffers2.push({ name: att.name, dataBase64: fromPreview });
|
|
2866
|
+
continue;
|
|
2867
|
+
}
|
|
2868
|
+
if (att.content && !IMAGE_HINT_RE.test(att.content) && !PLACEHOLDER_CONTENT_RE.test(att.content)) {
|
|
2869
|
+
buffers2.push({
|
|
2870
|
+
name: att.name,
|
|
2871
|
+
dataBase64: Buffer.from(att.content, "utf8").toString("base64")
|
|
2872
|
+
});
|
|
2873
|
+
continue;
|
|
2874
|
+
}
|
|
2875
|
+
keep.push(att);
|
|
2876
|
+
}
|
|
2877
|
+
if (buffers2.length === 0) return attachments;
|
|
2878
|
+
return [...keep, ...stageBuffersAsAttachments(worktreePath, buffers2)];
|
|
2879
|
+
}
|
|
2880
|
+
function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
2881
|
+
const out = [];
|
|
2882
|
+
for (const rel of relativePaths) {
|
|
2883
|
+
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
2884
|
+
out.push({
|
|
2885
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
2886
|
+
name: (0, import_node_path13.basename)(rel) || "file",
|
|
2887
|
+
kind: "file",
|
|
2888
|
+
content: `(invalid path: ${rel})`
|
|
2889
|
+
});
|
|
2890
|
+
continue;
|
|
2891
|
+
}
|
|
2892
|
+
const name = (0, import_node_path13.basename)(rel);
|
|
2893
|
+
try {
|
|
2894
|
+
const abs = (0, import_node_path13.join)(worktreePath, rel);
|
|
2895
|
+
const st = (0, import_node_fs12.statSync)(abs);
|
|
2896
|
+
if (!st.isFile()) continue;
|
|
2897
|
+
const buf = (0, import_node_fs12.readFileSync)(abs);
|
|
2898
|
+
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
2899
|
+
} catch (err) {
|
|
2900
|
+
out.push({
|
|
2901
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
2902
|
+
name,
|
|
2903
|
+
kind: "file",
|
|
2904
|
+
content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
|
|
2905
|
+
});
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
return out;
|
|
2909
|
+
}
|
|
2910
|
+
var import_node_fs12, import_node_path13, import_node_crypto5, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
|
|
2911
|
+
var init_stage_files = __esm({
|
|
2912
|
+
"src/composer/stage-files.ts"() {
|
|
2913
|
+
"use strict";
|
|
2914
|
+
import_node_fs12 = require("fs");
|
|
2915
|
+
import_node_path13 = require("path");
|
|
2916
|
+
import_node_crypto5 = require("crypto");
|
|
2917
|
+
init_workspace_scratch();
|
|
2918
|
+
IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
2919
|
+
"png",
|
|
2920
|
+
"jpg",
|
|
2921
|
+
"jpeg",
|
|
2922
|
+
"gif",
|
|
2923
|
+
"webp",
|
|
2924
|
+
"svg",
|
|
2925
|
+
"bmp",
|
|
2926
|
+
"ico"
|
|
2927
|
+
]);
|
|
2928
|
+
IMAGE_MIME_BY_EXT = {
|
|
2929
|
+
png: "image/png",
|
|
2930
|
+
jpg: "image/jpeg",
|
|
2931
|
+
jpeg: "image/jpeg",
|
|
2932
|
+
gif: "image/gif",
|
|
2933
|
+
webp: "image/webp",
|
|
2934
|
+
svg: "image/svg+xml",
|
|
2935
|
+
bmp: "image/bmp",
|
|
2936
|
+
ico: "image/x-icon"
|
|
2937
|
+
};
|
|
2938
|
+
MAX_INLINE_BYTES = 4e5;
|
|
2939
|
+
MAX_PREVIEW_BYTES = 5e6;
|
|
2940
|
+
IMAGE_HINT_RE = /^Image attached:/;
|
|
2941
|
+
PLACEHOLDER_CONTENT_RE = /^\((could not |file too large|binary file|not a file|invalid path)/;
|
|
2942
|
+
}
|
|
2943
|
+
});
|
|
2944
|
+
|
|
2621
2945
|
// src/git/team-meta.ts
|
|
2622
2946
|
var SOCCER_TEAM_META;
|
|
2623
2947
|
var init_team_meta = __esm({
|
|
@@ -3529,23 +3853,23 @@ var init_gh_errors = __esm({
|
|
|
3529
3853
|
function githubAgentAuthDir() {
|
|
3530
3854
|
const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
|
|
3531
3855
|
if (override) return override;
|
|
3532
|
-
return (0,
|
|
3856
|
+
return (0, import_node_path14.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
|
|
3533
3857
|
}
|
|
3534
3858
|
function githubCredentialStorePath() {
|
|
3535
|
-
return (0,
|
|
3859
|
+
return (0, import_node_path14.join)(githubAgentAuthDir(), "git-credentials");
|
|
3536
3860
|
}
|
|
3537
3861
|
function githubGhConfigDir() {
|
|
3538
|
-
return (0,
|
|
3862
|
+
return (0, import_node_path14.join)(githubAgentAuthDir(), "gh");
|
|
3539
3863
|
}
|
|
3540
3864
|
function writePrivateFile2(file, body) {
|
|
3541
|
-
(0,
|
|
3865
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path14.dirname)(file), { recursive: true, mode: 448 });
|
|
3542
3866
|
try {
|
|
3543
|
-
(0,
|
|
3867
|
+
(0, import_node_fs13.chmodSync)((0, import_node_path14.dirname)(file), 448);
|
|
3544
3868
|
} catch {
|
|
3545
3869
|
}
|
|
3546
|
-
(0,
|
|
3870
|
+
(0, import_node_fs13.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
|
|
3547
3871
|
try {
|
|
3548
|
-
(0,
|
|
3872
|
+
(0, import_node_fs13.chmodSync)(file, 384);
|
|
3549
3873
|
} catch {
|
|
3550
3874
|
}
|
|
3551
3875
|
}
|
|
@@ -3570,19 +3894,19 @@ function materializeGithubAgentAuth(token, user) {
|
|
|
3570
3894
|
const trimmed = token.trim();
|
|
3571
3895
|
if (!trimmed) return;
|
|
3572
3896
|
const root = githubAgentAuthDir();
|
|
3573
|
-
(0,
|
|
3897
|
+
(0, import_node_fs13.mkdirSync)(root, { recursive: true, mode: 448 });
|
|
3574
3898
|
try {
|
|
3575
|
-
(0,
|
|
3899
|
+
(0, import_node_fs13.chmodSync)(root, 448);
|
|
3576
3900
|
} catch {
|
|
3577
3901
|
}
|
|
3578
3902
|
writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
|
|
3579
3903
|
const ghDir = githubGhConfigDir();
|
|
3580
|
-
(0,
|
|
3581
|
-
writePrivateFile2((0,
|
|
3582
|
-
writePrivateFile2((0,
|
|
3904
|
+
(0, import_node_fs13.mkdirSync)(ghDir, { recursive: true, mode: 448 });
|
|
3905
|
+
writePrivateFile2((0, import_node_path14.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
|
|
3906
|
+
writePrivateFile2((0, import_node_path14.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
|
|
3583
3907
|
}
|
|
3584
3908
|
function githubAgentAuthReady() {
|
|
3585
|
-
return (0,
|
|
3909
|
+
return (0, import_node_fs13.existsSync)(githubCredentialStorePath()) && (0, import_node_fs13.existsSync)((0, import_node_path14.join)(githubGhConfigDir(), "hosts.yml"));
|
|
3586
3910
|
}
|
|
3587
3911
|
function githubCredentialHelperGitConfig() {
|
|
3588
3912
|
const file = githubCredentialStorePath();
|
|
@@ -3597,29 +3921,29 @@ function githubGhConfigEnv() {
|
|
|
3597
3921
|
GH_PROMPT_DISABLED: "1"
|
|
3598
3922
|
};
|
|
3599
3923
|
}
|
|
3600
|
-
var
|
|
3924
|
+
var import_node_fs13, import_node_os4, import_node_path14;
|
|
3601
3925
|
var init_github_agent_auth = __esm({
|
|
3602
3926
|
"src/git/github-agent-auth.ts"() {
|
|
3603
3927
|
"use strict";
|
|
3604
|
-
|
|
3928
|
+
import_node_fs13 = require("fs");
|
|
3605
3929
|
import_node_os4 = require("os");
|
|
3606
|
-
|
|
3930
|
+
import_node_path14 = require("path");
|
|
3607
3931
|
}
|
|
3608
3932
|
});
|
|
3609
3933
|
|
|
3610
3934
|
// src/agents/path.ts
|
|
3611
3935
|
function prependPathDir(env, dir) {
|
|
3612
|
-
if (!dir || !(0,
|
|
3936
|
+
if (!dir || !(0, import_node_fs14.existsSync)(dir)) return;
|
|
3613
3937
|
const current = env.PATH ?? "";
|
|
3614
|
-
const parts = current.split(
|
|
3938
|
+
const parts = current.split(import_node_path15.delimiter).filter(Boolean);
|
|
3615
3939
|
if (parts.includes(dir)) {
|
|
3616
3940
|
env.PATH = current;
|
|
3617
3941
|
return;
|
|
3618
3942
|
}
|
|
3619
|
-
env.PATH = [dir, ...parts].join(
|
|
3943
|
+
env.PATH = [dir, ...parts].join(import_node_path15.delimiter);
|
|
3620
3944
|
}
|
|
3621
3945
|
function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os5.homedir)()) {
|
|
3622
|
-
return (0,
|
|
3946
|
+
return (0, import_node_path15.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
|
|
3623
3947
|
}
|
|
3624
3948
|
function isConductorBundledCli(filePath) {
|
|
3625
3949
|
const p = (filePath ?? "").replace(/\\/g, "/");
|
|
@@ -3628,21 +3952,21 @@ function isConductorBundledCli(filePath) {
|
|
|
3628
3952
|
function ensureAgentPath(env = process.env) {
|
|
3629
3953
|
const home = env.HOME || env.USERPROFILE || (0, import_node_os5.homedir)();
|
|
3630
3954
|
const current = env.PATH ?? "";
|
|
3631
|
-
const parts = current.split(
|
|
3955
|
+
const parts = current.split(import_node_path15.delimiter).filter(Boolean);
|
|
3632
3956
|
const seen = new Set(parts);
|
|
3633
3957
|
const extras = [
|
|
3634
|
-
...EXTRA_BIN_DIRS.map((rel) => (0,
|
|
3958
|
+
...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path15.join)(home, rel)),
|
|
3635
3959
|
"/opt/homebrew/bin",
|
|
3636
3960
|
"/usr/local/bin",
|
|
3637
3961
|
// Keep after Homebrew/npm so a user-installed CLI still wins.
|
|
3638
3962
|
conductorBundledBinDir(home)
|
|
3639
3963
|
];
|
|
3640
3964
|
for (const dir of extras.reverse()) {
|
|
3641
|
-
if (!dir || seen.has(dir) || !(0,
|
|
3965
|
+
if (!dir || seen.has(dir) || !(0, import_node_fs14.existsSync)(dir)) continue;
|
|
3642
3966
|
parts.unshift(dir);
|
|
3643
3967
|
seen.add(dir);
|
|
3644
3968
|
}
|
|
3645
|
-
const next = parts.join(
|
|
3969
|
+
const next = parts.join(import_node_path15.delimiter);
|
|
3646
3970
|
env.PATH = next;
|
|
3647
3971
|
return next;
|
|
3648
3972
|
}
|
|
@@ -3656,7 +3980,7 @@ function enrichPathWithNpmGlobalBin(env = process.env) {
|
|
|
3656
3980
|
stdio: ["ignore", "pipe", "ignore"]
|
|
3657
3981
|
}).trim().split(/\r?\n/).find(Boolean);
|
|
3658
3982
|
if (prefix) {
|
|
3659
|
-
const binDir = process.platform === "win32" ? prefix : (0,
|
|
3983
|
+
const binDir = process.platform === "win32" ? prefix : (0, import_node_path15.join)(prefix, "bin");
|
|
3660
3984
|
prependPathDir(env, binDir);
|
|
3661
3985
|
}
|
|
3662
3986
|
} catch {
|
|
@@ -3684,14 +4008,14 @@ function withExportedPath(command, pathValue) {
|
|
|
3684
4008
|
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
3685
4009
|
return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
|
|
3686
4010
|
}
|
|
3687
|
-
var
|
|
4011
|
+
var import_node_fs14, import_node_child_process3, import_node_os5, import_node_path15, EXTRA_BIN_DIRS;
|
|
3688
4012
|
var init_path = __esm({
|
|
3689
4013
|
"src/agents/path.ts"() {
|
|
3690
4014
|
"use strict";
|
|
3691
|
-
|
|
4015
|
+
import_node_fs14 = require("fs");
|
|
3692
4016
|
import_node_child_process3 = require("child_process");
|
|
3693
4017
|
import_node_os5 = require("os");
|
|
3694
|
-
|
|
4018
|
+
import_node_path15 = require("path");
|
|
3695
4019
|
EXTRA_BIN_DIRS = [
|
|
3696
4020
|
".local/bin",
|
|
3697
4021
|
".cargo/bin",
|
|
@@ -3713,11 +4037,11 @@ function isIndexLockError(text5) {
|
|
|
3713
4037
|
return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text5);
|
|
3714
4038
|
}
|
|
3715
4039
|
function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
|
|
3716
|
-
const lockPath = (0,
|
|
4040
|
+
const lockPath = (0, import_node_path16.join)(gitDir, "index.lock");
|
|
3717
4041
|
try {
|
|
3718
|
-
if (!(0,
|
|
3719
|
-
if (now - (0,
|
|
3720
|
-
(0,
|
|
4042
|
+
if (!(0, import_node_fs15.existsSync)(lockPath)) return null;
|
|
4043
|
+
if (now - (0, import_node_fs15.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
|
|
4044
|
+
(0, import_node_fs15.unlinkSync)(lockPath);
|
|
3721
4045
|
return lockPath;
|
|
3722
4046
|
} catch {
|
|
3723
4047
|
return null;
|
|
@@ -3732,12 +4056,12 @@ function clearStaleIndexLocks(gitDirs, maxAgeMs = STALE_INDEX_LOCK_MS) {
|
|
|
3732
4056
|
}
|
|
3733
4057
|
return removed;
|
|
3734
4058
|
}
|
|
3735
|
-
var
|
|
4059
|
+
var import_node_fs15, import_node_path16, STALE_INDEX_LOCK_MS;
|
|
3736
4060
|
var init_stale_lock = __esm({
|
|
3737
4061
|
"src/git/stale-lock.ts"() {
|
|
3738
4062
|
"use strict";
|
|
3739
|
-
|
|
3740
|
-
|
|
4063
|
+
import_node_fs15 = require("fs");
|
|
4064
|
+
import_node_path16 = require("path");
|
|
3741
4065
|
STALE_INDEX_LOCK_MS = 2e4;
|
|
3742
4066
|
}
|
|
3743
4067
|
});
|
|
@@ -3945,7 +4269,7 @@ async function warmGithubAgentAuth(opts) {
|
|
|
3945
4269
|
}
|
|
3946
4270
|
function normalizeWritableRoot(raw) {
|
|
3947
4271
|
const trimmed = raw.trim().replace(/\/+$/, "");
|
|
3948
|
-
return trimmed && (0,
|
|
4272
|
+
return trimmed && (0, import_node_path17.isAbsolute)(trimmed) ? trimmed : null;
|
|
3949
4273
|
}
|
|
3950
4274
|
async function resolveCodexGitWritableRoots(cwd) {
|
|
3951
4275
|
const roots = /* @__PURE__ */ new Set();
|
|
@@ -4022,11 +4346,11 @@ function formatGitAuthModeDirective(mode) {
|
|
|
4022
4346
|
].join("\n");
|
|
4023
4347
|
}
|
|
4024
4348
|
}
|
|
4025
|
-
var
|
|
4349
|
+
var import_node_path17, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
|
|
4026
4350
|
var init_git_auth_mode = __esm({
|
|
4027
4351
|
"src/git/git-auth-mode.ts"() {
|
|
4028
4352
|
"use strict";
|
|
4029
|
-
|
|
4353
|
+
import_node_path17 = require("path");
|
|
4030
4354
|
init_app_settings();
|
|
4031
4355
|
init_github_agent_auth();
|
|
4032
4356
|
init_run();
|
|
@@ -4396,27 +4720,6 @@ var init_stack = __esm({
|
|
|
4396
4720
|
}
|
|
4397
4721
|
});
|
|
4398
4722
|
|
|
4399
|
-
// src/paths/workspace-scratch.ts
|
|
4400
|
-
function attachmentsGitignoreBody() {
|
|
4401
|
-
return ATTACHMENTS_GITIGNORE;
|
|
4402
|
-
}
|
|
4403
|
-
function isWorkspaceScratchPath(relativePath) {
|
|
4404
|
-
const p = relativePath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
|
|
4405
|
-
return p === ATTACHMENTS_DIR || p.startsWith(`${ATTACHMENTS_DIR}/`) || p === LEGACY_ATTACHMENTS_DIR || p.startsWith(`${LEGACY_ATTACHMENTS_DIR}/`) || p === ".context" || p.startsWith(".context/");
|
|
4406
|
-
}
|
|
4407
|
-
var ATTACHMENTS_DIR, LEGACY_ATTACHMENTS_DIR, ATTACHMENTS_GITIGNORE;
|
|
4408
|
-
var init_workspace_scratch = __esm({
|
|
4409
|
-
"src/paths/workspace-scratch.ts"() {
|
|
4410
|
-
"use strict";
|
|
4411
|
-
ATTACHMENTS_DIR = ".context/attachments";
|
|
4412
|
-
LEGACY_ATTACHMENTS_DIR = ".sideboard/attachments";
|
|
4413
|
-
ATTACHMENTS_GITIGNORE = `# Sideboard / workspace attachments (local only)
|
|
4414
|
-
*
|
|
4415
|
-
!.gitignore
|
|
4416
|
-
`;
|
|
4417
|
-
}
|
|
4418
|
-
});
|
|
4419
|
-
|
|
4420
4723
|
// src/git/worktree.ts
|
|
4421
4724
|
var worktree_exports = {};
|
|
4422
4725
|
__export(worktree_exports, {
|
|
@@ -4504,7 +4807,7 @@ async function resolveRepoRoot(cwd) {
|
|
|
4504
4807
|
}
|
|
4505
4808
|
function canonicalizeRepoPath(path2) {
|
|
4506
4809
|
try {
|
|
4507
|
-
return (0,
|
|
4810
|
+
return (0, import_node_fs16.realpathSync)(path2);
|
|
4508
4811
|
} catch {
|
|
4509
4812
|
return path2.replace(/\/+$/, "");
|
|
4510
4813
|
}
|
|
@@ -5232,8 +5535,8 @@ function isLocalPrFetchBranch(ref) {
|
|
|
5232
5535
|
}
|
|
5233
5536
|
async function createThreadWorktree(opts) {
|
|
5234
5537
|
let branchName = `thread/${opts.slug}`;
|
|
5235
|
-
const worktreePath = (0,
|
|
5236
|
-
if ((0,
|
|
5538
|
+
const worktreePath = (0, import_node_path18.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
5539
|
+
if ((0, import_node_fs16.existsSync)(worktreePath)) {
|
|
5237
5540
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
5238
5541
|
}
|
|
5239
5542
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -5300,8 +5603,8 @@ ${add.stdout}`;
|
|
|
5300
5603
|
async function createExistingBranchWorktree(opts) {
|
|
5301
5604
|
const branchName = opts.branchName.trim();
|
|
5302
5605
|
if (!branchName) throw new Error("branch name required");
|
|
5303
|
-
const worktreePath = (0,
|
|
5304
|
-
if ((0,
|
|
5606
|
+
const worktreePath = (0, import_node_path18.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
5607
|
+
if ((0, import_node_fs16.existsSync)(worktreePath)) {
|
|
5305
5608
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
5306
5609
|
}
|
|
5307
5610
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -5592,10 +5895,10 @@ function sameRepoPath(a, b) {
|
|
|
5592
5895
|
return normalizeWorktreePath(a) === normalizeWorktreePath(b);
|
|
5593
5896
|
}
|
|
5594
5897
|
function listLocalThreadBranchSlugs(repoPath) {
|
|
5595
|
-
const refsDir = (0,
|
|
5596
|
-
if (!(0,
|
|
5898
|
+
const refsDir = (0, import_node_path18.join)(repoPath, ".git", "refs", "heads", "thread");
|
|
5899
|
+
if (!(0, import_node_fs16.existsSync)(refsDir)) return [];
|
|
5597
5900
|
try {
|
|
5598
|
-
return (0,
|
|
5901
|
+
return (0, import_node_fs16.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
|
|
5599
5902
|
} catch {
|
|
5600
5903
|
return [];
|
|
5601
5904
|
}
|
|
@@ -5603,8 +5906,8 @@ function listLocalThreadBranchSlugs(repoPath) {
|
|
|
5603
5906
|
function collectTakenTeamSlugs(repoPath) {
|
|
5604
5907
|
const taken = /* @__PURE__ */ new Set();
|
|
5605
5908
|
const root = worktreesRoot(repoPath);
|
|
5606
|
-
if ((0,
|
|
5607
|
-
for (const entry of (0,
|
|
5909
|
+
if ((0, import_node_fs16.existsSync)(root)) {
|
|
5910
|
+
for (const entry of (0, import_node_fs16.readdirSync)(root, { withFileTypes: true })) {
|
|
5608
5911
|
if (entry.isDirectory() && entry.name !== ".DS_Store") {
|
|
5609
5912
|
taken.add(normalizeTakenSlug(entry.name));
|
|
5610
5913
|
}
|
|
@@ -5625,18 +5928,18 @@ function allocateTeamSlug(repoPath) {
|
|
|
5625
5928
|
const taken = collectTakenTeamSlugs(repoPath);
|
|
5626
5929
|
for (let attempt = 0; attempt < 32; attempt++) {
|
|
5627
5930
|
const team = allocateTeamName(taken);
|
|
5628
|
-
const path2 = (0,
|
|
5629
|
-
if (!(0,
|
|
5931
|
+
const path2 = (0, import_node_path18.join)(worktreesRoot(repoPath), team.slug);
|
|
5932
|
+
if (!(0, import_node_fs16.existsSync)(path2)) return team;
|
|
5630
5933
|
taken.add(team.slug);
|
|
5631
5934
|
}
|
|
5632
5935
|
throw new Error("No available soccer team worktree directories left");
|
|
5633
5936
|
}
|
|
5634
|
-
var
|
|
5937
|
+
var import_node_fs16, import_node_path18;
|
|
5635
5938
|
var init_worktree = __esm({
|
|
5636
5939
|
"src/git/worktree.ts"() {
|
|
5637
5940
|
"use strict";
|
|
5638
|
-
|
|
5639
|
-
|
|
5941
|
+
import_node_fs16 = require("fs");
|
|
5942
|
+
import_node_path18 = require("path");
|
|
5640
5943
|
init_paths();
|
|
5641
5944
|
init_thread_store();
|
|
5642
5945
|
init_teams();
|
|
@@ -5707,13 +6010,13 @@ function coordinatorTurnReminder(opts) {
|
|
|
5707
6010
|
`- YOUR orchestration thread id is ${opts.parentId} \u2014 pass parentThreadId="${opts.parentId}" on create_thread, or omit it.`,
|
|
5708
6011
|
goal ? `- Goal / title: ${goal}` : null,
|
|
5709
6012
|
accountDefaultsPlaybookLine(),
|
|
5710
|
-
"- Status: list_board (worktree Kanban: New \u2192 Draft \u2192 Review \u2192 Merged) or list_threads. Link chats as `[Title](sideboard://thread/<id>)`. Merge only if the user asked."
|
|
6013
|
+
"- Status: list_board (worktree Kanban: New \u2192 Draft \u2192 Review \u2192 Merged) or list_threads. Link chats as `[Title](sideboard://thread/<id>)`. Merge only if the user asked. If a child is stopped/error/broken, it did not finish \u2014 resume or tell the user."
|
|
5711
6014
|
].filter(Boolean).join("\n");
|
|
5712
6015
|
}
|
|
5713
6016
|
function ensureGlobalCoordinatorCwd(opts) {
|
|
5714
6017
|
const dir = globalAgentCwd();
|
|
5715
6018
|
try {
|
|
5716
|
-
(0,
|
|
6019
|
+
(0, import_node_fs17.mkdirSync)(dir, { recursive: true });
|
|
5717
6020
|
} catch {
|
|
5718
6021
|
return dir;
|
|
5719
6022
|
}
|
|
@@ -5721,7 +6024,7 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
5721
6024
|
let orchId = opts?.orchestratorThreadId?.trim() || "";
|
|
5722
6025
|
if (!orchId) {
|
|
5723
6026
|
try {
|
|
5724
|
-
const existing = (0,
|
|
6027
|
+
const existing = (0, import_node_fs17.readFileSync)((0, import_node_path19.join)(dir, "AGENTS.md"), "utf8");
|
|
5725
6028
|
const m = existing.match(
|
|
5726
6029
|
/YOUR orchestration thread id is `([0-9a-f-]{36})`/i
|
|
5727
6030
|
);
|
|
@@ -5764,9 +6067,9 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
5764
6067
|
"Always ask worktree agents to commit, push, and open draft PRs (`ask_git` / `send_to_thread`). Tell them to merge only when the user explicitly asked. The worktree agent runs git/gh; never merge from this orchestration cwd."
|
|
5765
6068
|
].join("\n");
|
|
5766
6069
|
try {
|
|
5767
|
-
(0,
|
|
6070
|
+
(0, import_node_fs17.writeFileSync)((0, import_node_path19.join)(dir, "CLAUDE.md"), `${body}
|
|
5768
6071
|
`, "utf8");
|
|
5769
|
-
(0,
|
|
6072
|
+
(0, import_node_fs17.writeFileSync)((0, import_node_path19.join)(dir, "AGENTS.md"), `${body}
|
|
5770
6073
|
`, "utf8");
|
|
5771
6074
|
} catch {
|
|
5772
6075
|
}
|
|
@@ -5798,12 +6101,12 @@ function coordinatorSystemPrompt(opts) {
|
|
|
5798
6101
|
formatWorkspaceInventory(opts.workspaces)
|
|
5799
6102
|
].join("\n");
|
|
5800
6103
|
}
|
|
5801
|
-
var
|
|
6104
|
+
var import_node_fs17, import_node_path19, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
|
|
5802
6105
|
var init_coordinator_prompt = __esm({
|
|
5803
6106
|
"src/orchestrator/coordinator-prompt.ts"() {
|
|
5804
6107
|
"use strict";
|
|
5805
|
-
|
|
5806
|
-
|
|
6108
|
+
import_node_fs17 = require("fs");
|
|
6109
|
+
import_node_path19 = require("path");
|
|
5807
6110
|
init_worktree();
|
|
5808
6111
|
init_app_settings();
|
|
5809
6112
|
init_paths();
|
|
@@ -5832,7 +6135,7 @@ var init_coordinator_prompt = __esm({
|
|
|
5832
6135
|
"- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
|
|
5833
6136
|
"- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
|
|
5834
6137
|
"- send_to_thread \u2014 queue a prompt (start/continue a chat turn); pass force_stop: true to interrupt mid-turn / clear stale queued prompts before replacing with a new request",
|
|
5835
|
-
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success.",
|
|
6138
|
+
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
|
|
5836
6139
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
5837
6140
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
5838
6141
|
"Setup / run:",
|
|
@@ -5952,6 +6255,7 @@ function createGlobalChat(opts) {
|
|
|
5952
6255
|
fast: opts.fast
|
|
5953
6256
|
});
|
|
5954
6257
|
const agent = assertOrchestratorCapableAgent(resolved.agent);
|
|
6258
|
+
const worktreePath = globalAgentCwd();
|
|
5955
6259
|
const thread = createEmptyThread({
|
|
5956
6260
|
title,
|
|
5957
6261
|
// Stick nicknames the same way chat tabs do (avoid later sync overwrites).
|
|
@@ -5959,7 +6263,7 @@ function createGlobalChat(opts) {
|
|
|
5959
6263
|
sourceType: "orchestration",
|
|
5960
6264
|
sourceRef,
|
|
5961
6265
|
branchName: "global",
|
|
5962
|
-
worktreePath
|
|
6266
|
+
worktreePath,
|
|
5963
6267
|
repoPath: GLOBAL_WORKSPACE_ID,
|
|
5964
6268
|
agent,
|
|
5965
6269
|
autonomy: opts.autonomy ?? "default",
|
|
@@ -5967,7 +6271,10 @@ function createGlobalChat(opts) {
|
|
|
5967
6271
|
effort: resolved.effort,
|
|
5968
6272
|
fast: resolved.fast,
|
|
5969
6273
|
planMode: Boolean(opts.planMode),
|
|
5970
|
-
attachments:
|
|
6274
|
+
attachments: persistPendingFileAttachments(
|
|
6275
|
+
worktreePath,
|
|
6276
|
+
opts.attachments ?? []
|
|
6277
|
+
),
|
|
5971
6278
|
parentThreadId: opts.parentThreadId ?? null,
|
|
5972
6279
|
status: "idle"
|
|
5973
6280
|
});
|
|
@@ -6092,6 +6399,7 @@ var init_global_workspace = __esm({
|
|
|
6092
6399
|
"src/store/global-workspace.ts"() {
|
|
6093
6400
|
"use strict";
|
|
6094
6401
|
init_cloud_connect_constants();
|
|
6402
|
+
init_stage_files();
|
|
6095
6403
|
init_orchestrator_capable();
|
|
6096
6404
|
init_teams();
|
|
6097
6405
|
init_coordinator_prompt();
|
|
@@ -6149,13 +6457,13 @@ var init_api = __esm({
|
|
|
6149
6457
|
|
|
6150
6458
|
// src/slack/reply-target.ts
|
|
6151
6459
|
function storePath() {
|
|
6152
|
-
return (0,
|
|
6460
|
+
return (0, import_node_path20.join)(appDataDir(), "slack-reply-to.json");
|
|
6153
6461
|
}
|
|
6154
6462
|
function readStore() {
|
|
6155
6463
|
const path2 = storePath();
|
|
6156
|
-
if (!(0,
|
|
6464
|
+
if (!(0, import_node_fs18.existsSync)(path2)) return {};
|
|
6157
6465
|
try {
|
|
6158
|
-
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0,
|
|
6466
|
+
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs18.readFileSync)(path2, "utf8"));
|
|
6159
6467
|
return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
|
|
6160
6468
|
} catch {
|
|
6161
6469
|
return {};
|
|
@@ -6170,12 +6478,12 @@ function setSlackReplyTarget(target) {
|
|
|
6170
6478
|
function getSlackReplyTarget(threadId) {
|
|
6171
6479
|
return readStore()[threadId] ?? null;
|
|
6172
6480
|
}
|
|
6173
|
-
var
|
|
6481
|
+
var import_node_fs18, import_node_path20;
|
|
6174
6482
|
var init_reply_target = __esm({
|
|
6175
6483
|
"src/slack/reply-target.ts"() {
|
|
6176
6484
|
"use strict";
|
|
6177
|
-
|
|
6178
|
-
|
|
6485
|
+
import_node_fs18 = require("fs");
|
|
6486
|
+
import_node_path20 = require("path");
|
|
6179
6487
|
init_paths();
|
|
6180
6488
|
init_private_file();
|
|
6181
6489
|
init_secure_file();
|
|
@@ -6184,7 +6492,7 @@ var init_reply_target = __esm({
|
|
|
6184
6492
|
|
|
6185
6493
|
// src/slack/workspaces.ts
|
|
6186
6494
|
function storePath2() {
|
|
6187
|
-
return (0,
|
|
6495
|
+
return (0, import_node_path21.join)(appDataDir(), "slack-workspaces.json");
|
|
6188
6496
|
}
|
|
6189
6497
|
function readStore2() {
|
|
6190
6498
|
try {
|
|
@@ -6291,11 +6599,11 @@ function requireSlackWorkspace(teamId) {
|
|
|
6291
6599
|
}
|
|
6292
6600
|
return ws;
|
|
6293
6601
|
}
|
|
6294
|
-
var
|
|
6602
|
+
var import_node_path21;
|
|
6295
6603
|
var init_workspaces = __esm({
|
|
6296
6604
|
"src/slack/workspaces.ts"() {
|
|
6297
6605
|
"use strict";
|
|
6298
|
-
|
|
6606
|
+
import_node_path21 = require("path");
|
|
6299
6607
|
init_paths();
|
|
6300
6608
|
init_secure_file();
|
|
6301
6609
|
init_api();
|
|
@@ -6304,7 +6612,7 @@ var init_workspaces = __esm({
|
|
|
6304
6612
|
|
|
6305
6613
|
// src/slack/outbound-watch.ts
|
|
6306
6614
|
function storePath3() {
|
|
6307
|
-
return (0,
|
|
6615
|
+
return (0, import_node_path22.join)(appDataDir(), "slack-outbound-watch.json");
|
|
6308
6616
|
}
|
|
6309
6617
|
function watchId(teamId, channelId, ts) {
|
|
6310
6618
|
return `${teamId}:${channelId}:${ts}`;
|
|
@@ -6317,9 +6625,9 @@ function tsNewer(a, b) {
|
|
|
6317
6625
|
}
|
|
6318
6626
|
function readStore3() {
|
|
6319
6627
|
const path2 = storePath3();
|
|
6320
|
-
if (!(0,
|
|
6628
|
+
if (!(0, import_node_fs19.existsSync)(path2)) return [];
|
|
6321
6629
|
try {
|
|
6322
|
-
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0,
|
|
6630
|
+
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs19.readFileSync)(path2, "utf8"));
|
|
6323
6631
|
return Array.isArray(parsed?.watches) ? parsed.watches : [];
|
|
6324
6632
|
} catch {
|
|
6325
6633
|
return [];
|
|
@@ -6641,12 +6949,12 @@ async function pollSlackOutboundWatches(opts) {
|
|
|
6641
6949
|
}
|
|
6642
6950
|
if (changed) writeStore2(watches);
|
|
6643
6951
|
}
|
|
6644
|
-
var
|
|
6952
|
+
var import_node_fs19, import_node_path22, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache, continueOnReply;
|
|
6645
6953
|
var init_outbound_watch = __esm({
|
|
6646
6954
|
"src/slack/outbound-watch.ts"() {
|
|
6647
6955
|
"use strict";
|
|
6648
|
-
|
|
6649
|
-
|
|
6956
|
+
import_node_fs19 = require("fs");
|
|
6957
|
+
import_node_path22 = require("path");
|
|
6650
6958
|
init_paths();
|
|
6651
6959
|
init_private_file();
|
|
6652
6960
|
init_secure_file();
|
|
@@ -6927,32 +7235,32 @@ var init_error_detail = __esm({
|
|
|
6927
7235
|
function brightsyConfigPath() {
|
|
6928
7236
|
const override = process.env.BRIGHTSY_CONFIG?.trim();
|
|
6929
7237
|
if (override) return override;
|
|
6930
|
-
return (0,
|
|
7238
|
+
return (0, import_node_path23.join)((0, import_node_os6.homedir)(), ".brightsy", "config.json");
|
|
6931
7239
|
}
|
|
6932
7240
|
function loadBrightsyConfig() {
|
|
6933
7241
|
const path2 = brightsyConfigPath();
|
|
6934
|
-
if (!(0,
|
|
7242
|
+
if (!(0, import_node_fs20.existsSync)(path2)) {
|
|
6935
7243
|
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
6936
7244
|
}
|
|
6937
|
-
const raw = JSON.parse((0,
|
|
7245
|
+
const raw = JSON.parse((0, import_node_fs20.readFileSync)(path2, "utf8"));
|
|
6938
7246
|
if (!raw.access_token || !raw.account_id) {
|
|
6939
7247
|
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
6940
7248
|
}
|
|
6941
7249
|
return raw;
|
|
6942
7250
|
}
|
|
6943
7251
|
function saveBrightsyConfig(cfg) {
|
|
6944
|
-
(0,
|
|
7252
|
+
(0, import_node_fs20.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
6945
7253
|
`, {
|
|
6946
7254
|
mode: 384
|
|
6947
7255
|
});
|
|
6948
7256
|
}
|
|
6949
|
-
var
|
|
7257
|
+
var import_node_fs20, import_node_os6, import_node_path23;
|
|
6950
7258
|
var init_config = __esm({
|
|
6951
7259
|
"src/brightsy/config.ts"() {
|
|
6952
7260
|
"use strict";
|
|
6953
|
-
|
|
7261
|
+
import_node_fs20 = require("fs");
|
|
6954
7262
|
import_node_os6 = require("os");
|
|
6955
|
-
|
|
7263
|
+
import_node_path23 = require("path");
|
|
6956
7264
|
}
|
|
6957
7265
|
});
|
|
6958
7266
|
|
|
@@ -7170,22 +7478,22 @@ __export(connected_teams_exports, {
|
|
|
7170
7478
|
listConnectedBrightsyTeams: () => listConnectedBrightsyTeams
|
|
7171
7479
|
});
|
|
7172
7480
|
function storePath4() {
|
|
7173
|
-
return (0,
|
|
7481
|
+
return (0, import_node_path24.join)(appDataDir(), "brightsy-teams.json");
|
|
7174
7482
|
}
|
|
7175
7483
|
function readStore4() {
|
|
7176
7484
|
const path2 = storePath4();
|
|
7177
|
-
if (!(0,
|
|
7485
|
+
if (!(0, import_node_fs21.existsSync)(path2)) return [];
|
|
7178
7486
|
try {
|
|
7179
|
-
const parsed = JSON.parse((0,
|
|
7487
|
+
const parsed = JSON.parse((0, import_node_fs21.readFileSync)(path2, "utf8"));
|
|
7180
7488
|
return Array.isArray(parsed.teams) ? parsed.teams : [];
|
|
7181
7489
|
} catch {
|
|
7182
7490
|
return [];
|
|
7183
7491
|
}
|
|
7184
7492
|
}
|
|
7185
7493
|
function writeStore3(teams) {
|
|
7186
|
-
(0,
|
|
7494
|
+
(0, import_node_fs21.mkdirSync)(appDataDir(), { recursive: true });
|
|
7187
7495
|
const path2 = storePath4();
|
|
7188
|
-
(0,
|
|
7496
|
+
(0, import_node_fs21.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
|
|
7189
7497
|
`, {
|
|
7190
7498
|
mode: 384
|
|
7191
7499
|
});
|
|
@@ -7341,12 +7649,12 @@ function brightsyMcpServerName(slug) {
|
|
|
7341
7649
|
const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
|
|
7342
7650
|
return `brightsy_${cleaned || "team"}`;
|
|
7343
7651
|
}
|
|
7344
|
-
var
|
|
7652
|
+
var import_node_fs21, import_node_path24;
|
|
7345
7653
|
var init_connected_teams = __esm({
|
|
7346
7654
|
"src/brightsy/connected-teams.ts"() {
|
|
7347
7655
|
"use strict";
|
|
7348
|
-
|
|
7349
|
-
|
|
7656
|
+
import_node_fs21 = require("fs");
|
|
7657
|
+
import_node_path24 = require("path");
|
|
7350
7658
|
init_paths();
|
|
7351
7659
|
init_accounts();
|
|
7352
7660
|
init_config();
|
|
@@ -7765,11 +8073,11 @@ async function syncCliForTarget(accountId) {
|
|
|
7765
8073
|
}
|
|
7766
8074
|
applyConnectedTeamToCli(team);
|
|
7767
8075
|
}
|
|
7768
|
-
var
|
|
8076
|
+
var import_node_fs22, brightsyAdapter;
|
|
7769
8077
|
var init_brightsy = __esm({
|
|
7770
8078
|
"src/agents/brightsy.ts"() {
|
|
7771
8079
|
"use strict";
|
|
7772
|
-
|
|
8080
|
+
import_node_fs22 = require("fs");
|
|
7773
8081
|
init_run();
|
|
7774
8082
|
init_connected_teams();
|
|
7775
8083
|
init_config();
|
|
@@ -7784,7 +8092,7 @@ var init_brightsy = __esm({
|
|
|
7784
8092
|
async detect() {
|
|
7785
8093
|
const brightsy = resolveAgentExecutable("brightsy");
|
|
7786
8094
|
if (brightsy !== "brightsy") {
|
|
7787
|
-
if (!(0,
|
|
8095
|
+
if (!(0, import_node_fs22.existsSync)(brightsy)) {
|
|
7788
8096
|
return {
|
|
7789
8097
|
agent: "brightsy",
|
|
7790
8098
|
installed: false,
|
|
@@ -7915,14 +8223,47 @@ function asRecord(input) {
|
|
|
7915
8223
|
function str2(v) {
|
|
7916
8224
|
return typeof v === "string" && v.trim() ? v : void 0;
|
|
7917
8225
|
}
|
|
8226
|
+
function looksLikeFilePath(value) {
|
|
8227
|
+
if (value.startsWith("/") || value.startsWith("~/")) return true;
|
|
8228
|
+
if (/^[A-Za-z]:[\\/]/.test(value)) return true;
|
|
8229
|
+
return value.includes("/") || value.includes("\\");
|
|
8230
|
+
}
|
|
8231
|
+
function stripWorktreePrefix(path2, worktreePath) {
|
|
8232
|
+
if (!worktreePath) return path2;
|
|
8233
|
+
const prefix = worktreePath.replace(/[/\\]+$/, "");
|
|
8234
|
+
if (path2 === prefix || path2 === `${prefix}/`) return "";
|
|
8235
|
+
if (path2.startsWith(`${prefix}/`)) return path2.slice(prefix.length + 1);
|
|
8236
|
+
return path2;
|
|
8237
|
+
}
|
|
8238
|
+
function visibleToolRowDetail(detail, description, worktreePath) {
|
|
8239
|
+
if (!detail?.trim()) return void 0;
|
|
8240
|
+
const raw = detail.trim();
|
|
8241
|
+
const desc = (description ?? "").trim();
|
|
8242
|
+
if (!looksLikeFilePath(raw)) {
|
|
8243
|
+
if (desc === raw) return void 0;
|
|
8244
|
+
return raw;
|
|
8245
|
+
}
|
|
8246
|
+
const rel = stripWorktreePrefix(raw, worktreePath);
|
|
8247
|
+
if (!rel) return void 0;
|
|
8248
|
+
const base = fileBasename(rel);
|
|
8249
|
+
if (desc && (desc === base || desc.endsWith(` ${base}`))) return void 0;
|
|
8250
|
+
if (rel.length <= 42) return rel;
|
|
8251
|
+
const parts = rel.split(/[/\\]/).filter(Boolean);
|
|
8252
|
+
if (parts.length >= 2) return `\u2026/${parts.slice(-2).join("/")}`;
|
|
8253
|
+
return base;
|
|
8254
|
+
}
|
|
7918
8255
|
function toolDetail(name, input) {
|
|
7919
8256
|
if (!input) return void 0;
|
|
7920
8257
|
const command = str2(input.command) ?? str2(input.cmd);
|
|
7921
8258
|
if (command) return command;
|
|
8259
|
+
const pattern = str2(input.pattern) ?? str2(input.glob) ?? str2(input.glob_pattern);
|
|
8260
|
+
const isSearch = /grep|glob|search|ripgrep|findfiles|semsearch/i.test(name);
|
|
8261
|
+
if (isSearch && pattern) {
|
|
8262
|
+
return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
|
|
8263
|
+
}
|
|
7922
8264
|
const path2 = str2(input.file_path) ?? str2(input.path) ?? str2(input.filePath) ?? str2(input.filename);
|
|
7923
8265
|
if (path2) return path2;
|
|
7924
|
-
|
|
7925
|
-
if (pattern) return pattern;
|
|
8266
|
+
if (pattern) return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
|
|
7926
8267
|
const query = str2(input.query) ?? str2(input.prompt);
|
|
7927
8268
|
if (query) return query.length > 80 ? `${query.slice(0, 77)}\u2026` : query;
|
|
7928
8269
|
try {
|
|
@@ -8441,43 +8782,43 @@ function electronResourcesPath() {
|
|
|
8441
8782
|
function packagedCursorRuntimeDir() {
|
|
8442
8783
|
const resources = electronResourcesPath();
|
|
8443
8784
|
if (!resources) return null;
|
|
8444
|
-
const dir = (0,
|
|
8445
|
-
if (!(0,
|
|
8785
|
+
const dir = (0, import_node_path25.join)(resources, "cursor-runtime");
|
|
8786
|
+
if (!(0, import_node_fs23.existsSync)((0, import_node_path25.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
|
|
8446
8787
|
return dir;
|
|
8447
8788
|
}
|
|
8448
8789
|
function packagedCursorRunnerPath() {
|
|
8449
8790
|
const dir = packagedCursorRuntimeDir();
|
|
8450
|
-
return dir ? (0,
|
|
8791
|
+
return dir ? (0, import_node_path25.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
|
|
8451
8792
|
}
|
|
8452
8793
|
function packagedMcpDir() {
|
|
8453
8794
|
const resources = electronResourcesPath();
|
|
8454
8795
|
if (!resources) return null;
|
|
8455
|
-
const dir = (0,
|
|
8456
|
-
if (!(0,
|
|
8796
|
+
const dir = (0, import_node_path25.join)(resources, "sideboard-mcp");
|
|
8797
|
+
if (!(0, import_node_fs23.existsSync)((0, import_node_path25.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
|
|
8457
8798
|
return dir;
|
|
8458
8799
|
}
|
|
8459
8800
|
function packagedMcpStdioPath() {
|
|
8460
8801
|
const dir = packagedMcpDir();
|
|
8461
|
-
return dir ? (0,
|
|
8802
|
+
return dir ? (0, import_node_path25.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
|
|
8462
8803
|
}
|
|
8463
8804
|
function packagedBundledNodePath() {
|
|
8464
8805
|
const resources = electronResourcesPath();
|
|
8465
8806
|
if (!resources) return null;
|
|
8466
|
-
const bin = (0,
|
|
8467
|
-
if (!(0,
|
|
8807
|
+
const bin = (0, import_node_path25.join)(resources, "node", "bin", "node");
|
|
8808
|
+
if (!(0, import_node_fs23.existsSync)(bin)) return null;
|
|
8468
8809
|
return bin;
|
|
8469
8810
|
}
|
|
8470
8811
|
function packagedCursorRipgrepCandidate(platformPkg, binName) {
|
|
8471
8812
|
const dir = packagedCursorRuntimeDir();
|
|
8472
8813
|
if (!dir) return null;
|
|
8473
|
-
return (0,
|
|
8814
|
+
return (0, import_node_path25.join)(dir, "node_modules", platformPkg, "bin", binName);
|
|
8474
8815
|
}
|
|
8475
|
-
var
|
|
8816
|
+
var import_node_fs23, import_node_path25;
|
|
8476
8817
|
var init_packaged_runtime = __esm({
|
|
8477
8818
|
"src/agents/packaged-runtime.ts"() {
|
|
8478
8819
|
"use strict";
|
|
8479
|
-
|
|
8480
|
-
|
|
8820
|
+
import_node_fs23 = require("fs");
|
|
8821
|
+
import_node_path25 = require("path");
|
|
8481
8822
|
}
|
|
8482
8823
|
});
|
|
8483
8824
|
|
|
@@ -8511,7 +8852,7 @@ function unpackedAsarPath(filePath) {
|
|
|
8511
8852
|
if (!isAsarPath(filePath)) return null;
|
|
8512
8853
|
const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
|
|
8513
8854
|
if (unpacked === filePath) return null;
|
|
8514
|
-
return (0,
|
|
8855
|
+
return (0, import_node_fs24.existsSync)(unpacked) ? unpacked : null;
|
|
8515
8856
|
}
|
|
8516
8857
|
function nodeReadableScriptPath(scriptPath) {
|
|
8517
8858
|
return unpackedAsarPath(scriptPath) ?? scriptPath;
|
|
@@ -8551,37 +8892,37 @@ function pickPreferredNode(candidates) {
|
|
|
8551
8892
|
return best;
|
|
8552
8893
|
}
|
|
8553
8894
|
function versionDirNodeBins(root, toBin) {
|
|
8554
|
-
if (!(0,
|
|
8895
|
+
if (!(0, import_node_fs24.existsSync)(root)) return [];
|
|
8555
8896
|
try {
|
|
8556
|
-
return (0,
|
|
8897
|
+
return (0, import_node_fs24.readdirSync)(root).map(toBin);
|
|
8557
8898
|
} catch {
|
|
8558
8899
|
return [];
|
|
8559
8900
|
}
|
|
8560
8901
|
}
|
|
8561
8902
|
function defaultNodeBinCandidates(home = (0, import_node_os7.homedir)()) {
|
|
8562
8903
|
const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
|
|
8563
|
-
(prefix) => PREFERRED_LTS_MAJORS.map((major) => (0,
|
|
8904
|
+
(prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path26.join)(prefix, "opt", `node@${major}`, "bin", "node"))
|
|
8564
8905
|
);
|
|
8565
8906
|
return [
|
|
8566
8907
|
...kegs,
|
|
8567
8908
|
"/opt/homebrew/bin/node",
|
|
8568
8909
|
"/usr/local/bin/node",
|
|
8569
|
-
(0,
|
|
8570
|
-
(0,
|
|
8571
|
-
(0,
|
|
8572
|
-
(0,
|
|
8573
|
-
(0,
|
|
8910
|
+
(0, import_node_path26.join)(home, ".local/share/fnm/aliases/default/bin/node"),
|
|
8911
|
+
(0, import_node_path26.join)(home, ".nvm/current/bin/node"),
|
|
8912
|
+
(0, import_node_path26.join)(home, ".volta/bin/node"),
|
|
8913
|
+
(0, import_node_path26.join)(home, ".asdf/shims/node"),
|
|
8914
|
+
(0, import_node_path26.join)(home, ".local/share/mise/shims/node"),
|
|
8574
8915
|
...versionDirNodeBins(
|
|
8575
|
-
(0,
|
|
8576
|
-
(name) => (0,
|
|
8916
|
+
(0, import_node_path26.join)(home, ".nvm", "versions", "node"),
|
|
8917
|
+
(name) => (0, import_node_path26.join)(home, ".nvm", "versions", "node", name, "bin", "node")
|
|
8577
8918
|
),
|
|
8578
8919
|
...versionDirNodeBins(
|
|
8579
|
-
(0,
|
|
8580
|
-
(name) => (0,
|
|
8920
|
+
(0, import_node_path26.join)(home, ".local/share/fnm", "node-versions"),
|
|
8921
|
+
(name) => (0, import_node_path26.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
|
|
8581
8922
|
),
|
|
8582
8923
|
...versionDirNodeBins(
|
|
8583
|
-
(0,
|
|
8584
|
-
(name) => (0,
|
|
8924
|
+
(0, import_node_path26.join)(home, ".volta", "tools", "image", "node"),
|
|
8925
|
+
(name) => (0, import_node_path26.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
|
|
8585
8926
|
)
|
|
8586
8927
|
];
|
|
8587
8928
|
}
|
|
@@ -8590,10 +8931,10 @@ function uniqueExistingNodeBins(paths) {
|
|
|
8590
8931
|
const out = [];
|
|
8591
8932
|
for (const raw of paths) {
|
|
8592
8933
|
const p = raw.trim();
|
|
8593
|
-
if (!p || !(0,
|
|
8934
|
+
if (!p || !(0, import_node_fs24.existsSync)(p) || isElectronLikeCommand(p)) continue;
|
|
8594
8935
|
let key = p;
|
|
8595
8936
|
try {
|
|
8596
|
-
key = (0,
|
|
8937
|
+
key = (0, import_node_fs24.realpathSync)(p);
|
|
8597
8938
|
} catch {
|
|
8598
8939
|
continue;
|
|
8599
8940
|
}
|
|
@@ -8673,13 +9014,13 @@ async function resolveNodeLaunch(scriptPath) {
|
|
|
8673
9014
|
env: { ELECTRON_RUN_AS_NODE: "1" }
|
|
8674
9015
|
};
|
|
8675
9016
|
}
|
|
8676
|
-
var
|
|
9017
|
+
var import_node_fs24, import_node_os7, import_node_path26, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
|
|
8677
9018
|
var init_node_launch = __esm({
|
|
8678
9019
|
"src/agents/node-launch.ts"() {
|
|
8679
9020
|
"use strict";
|
|
8680
|
-
|
|
9021
|
+
import_node_fs24 = require("fs");
|
|
8681
9022
|
import_node_os7 = require("os");
|
|
8682
|
-
|
|
9023
|
+
import_node_path26 = require("path");
|
|
8683
9024
|
init_nested_electron_env();
|
|
8684
9025
|
init_run();
|
|
8685
9026
|
init_packaged_runtime();
|
|
@@ -8773,37 +9114,37 @@ function corePackageDir() {
|
|
|
8773
9114
|
try {
|
|
8774
9115
|
const url = import_meta.url;
|
|
8775
9116
|
if (typeof url === "string" && url.length > 0) {
|
|
8776
|
-
return (0,
|
|
9117
|
+
return (0, import_node_path27.dirname)((0, import_node_url.fileURLToPath)(url));
|
|
8777
9118
|
}
|
|
8778
9119
|
} catch {
|
|
8779
9120
|
}
|
|
8780
9121
|
try {
|
|
8781
|
-
const req = (0, import_node_module.createRequire)((0,
|
|
8782
|
-
return (0,
|
|
9122
|
+
const req = (0, import_node_module.createRequire)((0, import_node_path27.join)(process.cwd(), "package.json"));
|
|
9123
|
+
return (0, import_node_path27.dirname)(req.resolve("@sideboard-ai/core"));
|
|
8783
9124
|
} catch {
|
|
8784
9125
|
return process.cwd();
|
|
8785
9126
|
}
|
|
8786
9127
|
}
|
|
8787
9128
|
function findSideboardMcpJsEntry() {
|
|
8788
9129
|
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
8789
|
-
if (override && (0,
|
|
9130
|
+
if (override && (0, import_node_fs25.existsSync)(override)) return override;
|
|
8790
9131
|
const packaged = packagedMcpStdioPath();
|
|
8791
9132
|
if (packaged) return packaged;
|
|
8792
9133
|
let dir = corePackageDir();
|
|
8793
9134
|
for (let i = 0; i < 10; i++) {
|
|
8794
9135
|
const candidates = [
|
|
8795
|
-
(0,
|
|
8796
|
-
(0,
|
|
8797
|
-
(0,
|
|
8798
|
-
(0,
|
|
8799
|
-
(0,
|
|
8800
|
-
(0,
|
|
8801
|
-
(0,
|
|
9136
|
+
(0, import_node_path27.join)(dir, "mcp/run-stdio.js"),
|
|
9137
|
+
(0, import_node_path27.join)(dir, "mcp/run-stdio.cjs"),
|
|
9138
|
+
(0, import_node_path27.join)(dir, "dist/mcp/run-stdio.js"),
|
|
9139
|
+
(0, import_node_path27.join)(dir, "dist/mcp/run-stdio.cjs"),
|
|
9140
|
+
(0, import_node_path27.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
|
|
9141
|
+
(0, import_node_path27.join)(dir, "packages/cli/dist/index.js"),
|
|
9142
|
+
(0, import_node_path27.join)(dir, "cli/dist/index.js")
|
|
8802
9143
|
];
|
|
8803
9144
|
for (const p of candidates) {
|
|
8804
|
-
if ((0,
|
|
9145
|
+
if ((0, import_node_fs25.existsSync)(p) && !isAsarPath(p)) return p;
|
|
8805
9146
|
}
|
|
8806
|
-
const parent = (0,
|
|
9147
|
+
const parent = (0, import_node_path27.dirname)(dir);
|
|
8807
9148
|
if (parent === dir) break;
|
|
8808
9149
|
dir = parent;
|
|
8809
9150
|
}
|
|
@@ -8945,22 +9286,22 @@ function writeMcpServersConfig(servers) {
|
|
|
8945
9286
|
...env ? { env } : {}
|
|
8946
9287
|
};
|
|
8947
9288
|
}
|
|
8948
|
-
const dir = (0,
|
|
8949
|
-
const cfgPath = (0,
|
|
8950
|
-
(0,
|
|
9289
|
+
const dir = (0, import_node_fs25.mkdtempSync)((0, import_node_path27.join)((0, import_node_os8.tmpdir)(), "sideboard-mcp-"));
|
|
9290
|
+
const cfgPath = (0, import_node_path27.join)(dir, "mcp.json");
|
|
9291
|
+
(0, import_node_fs25.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
|
|
8951
9292
|
return cfgPath;
|
|
8952
9293
|
}
|
|
8953
9294
|
async function writeInjectedMcpConfig(opts) {
|
|
8954
9295
|
return writeMcpServersConfig(await buildInjectedMcpServers(opts));
|
|
8955
9296
|
}
|
|
8956
|
-
var
|
|
9297
|
+
var import_node_fs25, import_node_module, import_node_os8, import_node_path27, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
|
|
8957
9298
|
var init_injected_mcp = __esm({
|
|
8958
9299
|
"src/agents/injected-mcp.ts"() {
|
|
8959
9300
|
"use strict";
|
|
8960
|
-
|
|
9301
|
+
import_node_fs25 = require("fs");
|
|
8961
9302
|
import_node_module = require("module");
|
|
8962
9303
|
import_node_os8 = require("os");
|
|
8963
|
-
|
|
9304
|
+
import_node_path27 = require("path");
|
|
8964
9305
|
import_node_url = require("url");
|
|
8965
9306
|
init_run();
|
|
8966
9307
|
init_config();
|
|
@@ -9264,11 +9605,11 @@ function parseIssuesJson(raw) {
|
|
|
9264
9605
|
}
|
|
9265
9606
|
return [];
|
|
9266
9607
|
}
|
|
9267
|
-
var
|
|
9608
|
+
var import_node_fs26, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, mcpListCache, claudeAdapter;
|
|
9268
9609
|
var init_claude = __esm({
|
|
9269
9610
|
"src/agents/claude.ts"() {
|
|
9270
9611
|
"use strict";
|
|
9271
|
-
|
|
9612
|
+
import_node_fs26 = require("fs");
|
|
9272
9613
|
init_run();
|
|
9273
9614
|
init_app_settings();
|
|
9274
9615
|
init_claude_mcp();
|
|
@@ -9308,7 +9649,7 @@ var init_claude = __esm({
|
|
|
9308
9649
|
async detect() {
|
|
9309
9650
|
const claude = resolveClaudeExecutable();
|
|
9310
9651
|
if (claude !== "claude") {
|
|
9311
|
-
if (!(0,
|
|
9652
|
+
if (!(0, import_node_fs26.existsSync)(claude)) {
|
|
9312
9653
|
return {
|
|
9313
9654
|
agent: "claude",
|
|
9314
9655
|
installed: false,
|
|
@@ -9563,7 +9904,7 @@ async function listCodexModels() {
|
|
|
9563
9904
|
if (codex === "codex") {
|
|
9564
9905
|
const which = await run("which", ["codex"], { reject: false });
|
|
9565
9906
|
if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
|
|
9566
|
-
} else if (!(0,
|
|
9907
|
+
} else if (!(0, import_node_fs27.existsSync)(codex)) {
|
|
9567
9908
|
return FALLBACK_CODEX_MODELS;
|
|
9568
9909
|
}
|
|
9569
9910
|
const listed = await run(codex, ["debug", "models"], { reject: false });
|
|
@@ -9598,12 +9939,12 @@ function usageFromCodex(usage) {
|
|
|
9598
9939
|
}
|
|
9599
9940
|
function codexConfigHasNetworkAccess() {
|
|
9600
9941
|
const candidates = [
|
|
9601
|
-
(0,
|
|
9602
|
-
(0,
|
|
9942
|
+
(0, import_node_path28.join)((0, import_node_os9.homedir)(), ".codex", "config.toml"),
|
|
9943
|
+
(0, import_node_path28.join)((0, import_node_os9.homedir)(), ".config", "codex", "config.toml")
|
|
9603
9944
|
];
|
|
9604
9945
|
for (const path2 of candidates) {
|
|
9605
|
-
if (!(0,
|
|
9606
|
-
const text5 = (0,
|
|
9946
|
+
if (!(0, import_node_fs27.existsSync)(path2)) continue;
|
|
9947
|
+
const text5 = (0, import_node_fs27.readFileSync)(path2, "utf8");
|
|
9607
9948
|
if (/network_access\s*=\s*true/.test(text5)) return true;
|
|
9608
9949
|
}
|
|
9609
9950
|
return false;
|
|
@@ -9635,21 +9976,21 @@ function asRecord2(value) {
|
|
|
9635
9976
|
return void 0;
|
|
9636
9977
|
}
|
|
9637
9978
|
function codexLooksAuthenticated() {
|
|
9638
|
-
const authPath = (0,
|
|
9639
|
-
if (!(0,
|
|
9979
|
+
const authPath = (0, import_node_path28.join)((0, import_node_os9.homedir)(), ".codex", "auth.json");
|
|
9980
|
+
if (!(0, import_node_fs27.existsSync)(authPath)) return false;
|
|
9640
9981
|
try {
|
|
9641
|
-
return (0,
|
|
9982
|
+
return (0, import_node_fs27.statSync)(authPath).size > 2;
|
|
9642
9983
|
} catch {
|
|
9643
9984
|
return false;
|
|
9644
9985
|
}
|
|
9645
9986
|
}
|
|
9646
|
-
var
|
|
9987
|
+
var import_node_fs27, import_node_os9, import_node_path28, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
|
|
9647
9988
|
var init_codex = __esm({
|
|
9648
9989
|
"src/agents/codex.ts"() {
|
|
9649
9990
|
"use strict";
|
|
9650
|
-
|
|
9991
|
+
import_node_fs27 = require("fs");
|
|
9651
9992
|
import_node_os9 = require("os");
|
|
9652
|
-
|
|
9993
|
+
import_node_path28 = require("path");
|
|
9653
9994
|
init_run();
|
|
9654
9995
|
init_app_settings();
|
|
9655
9996
|
init_global_workspace();
|
|
@@ -9674,7 +10015,7 @@ var init_codex = __esm({
|
|
|
9674
10015
|
async detect() {
|
|
9675
10016
|
const codex = resolveAgentExecutable("codex");
|
|
9676
10017
|
if (codex !== "codex") {
|
|
9677
|
-
if (!(0,
|
|
10018
|
+
if (!(0, import_node_fs27.existsSync)(codex)) {
|
|
9678
10019
|
return {
|
|
9679
10020
|
agent: "codex",
|
|
9680
10021
|
installed: false,
|
|
@@ -10161,21 +10502,21 @@ function platformRipgrepPackage() {
|
|
|
10161
10502
|
}
|
|
10162
10503
|
function usableRipgrepPath(candidate) {
|
|
10163
10504
|
const raw = candidate?.trim();
|
|
10164
|
-
if (!raw || !(0,
|
|
10505
|
+
if (!raw || !(0, import_node_path29.isAbsolute)(raw)) return null;
|
|
10165
10506
|
const readable = nodeReadableScriptPath(raw);
|
|
10166
|
-
if (!(0,
|
|
10507
|
+
if (!(0, import_node_fs28.existsSync)(readable) || isAsarPath(readable)) return null;
|
|
10167
10508
|
return readable;
|
|
10168
10509
|
}
|
|
10169
10510
|
function walkForBundledRipgrep(startFile) {
|
|
10170
10511
|
if (!startFile) return null;
|
|
10171
10512
|
const pkg = platformRipgrepPackage();
|
|
10172
10513
|
const name = rgBinaryName();
|
|
10173
|
-
let dir = (0,
|
|
10174
|
-
const root = (0,
|
|
10514
|
+
let dir = (0, import_node_path29.dirname)((0, import_node_path29.resolve)(startFile));
|
|
10515
|
+
const root = (0, import_node_path29.parse)(dir).root;
|
|
10175
10516
|
while (dir !== root) {
|
|
10176
|
-
const hit = usableRipgrepPath((0,
|
|
10517
|
+
const hit = usableRipgrepPath((0, import_node_path29.join)(dir, "node_modules", pkg, "bin", name));
|
|
10177
10518
|
if (hit) return hit;
|
|
10178
|
-
const next = (0,
|
|
10519
|
+
const next = (0, import_node_path29.dirname)(dir);
|
|
10179
10520
|
if (next === dir) break;
|
|
10180
10521
|
dir = next;
|
|
10181
10522
|
}
|
|
@@ -10185,7 +10526,7 @@ function requireResolveBundledRipgrep(fromFile) {
|
|
|
10185
10526
|
try {
|
|
10186
10527
|
const req = (0, import_node_module2.createRequire)(fromFile);
|
|
10187
10528
|
const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
|
|
10188
|
-
return usableRipgrepPath((0,
|
|
10529
|
+
return usableRipgrepPath((0, import_node_path29.join)((0, import_node_path29.dirname)(pkgJson), "bin", rgBinaryName()));
|
|
10189
10530
|
} catch {
|
|
10190
10531
|
return null;
|
|
10191
10532
|
}
|
|
@@ -10207,13 +10548,13 @@ function cursorRipgrepEnv(opts) {
|
|
|
10207
10548
|
const path2 = resolveCursorRipgrepPath(opts);
|
|
10208
10549
|
return path2 ? { [RIPGREP_ENV]: path2 } : {};
|
|
10209
10550
|
}
|
|
10210
|
-
var
|
|
10551
|
+
var import_node_fs28, import_node_module2, import_node_path29, RIPGREP_ENV;
|
|
10211
10552
|
var init_cursor_ripgrep = __esm({
|
|
10212
10553
|
"src/agents/cursor-ripgrep.ts"() {
|
|
10213
10554
|
"use strict";
|
|
10214
|
-
|
|
10555
|
+
import_node_fs28 = require("fs");
|
|
10215
10556
|
import_node_module2 = require("module");
|
|
10216
|
-
|
|
10557
|
+
import_node_path29 = require("path");
|
|
10217
10558
|
init_node_launch();
|
|
10218
10559
|
init_packaged_runtime();
|
|
10219
10560
|
RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
|
|
@@ -10259,11 +10600,11 @@ function entryDir() {
|
|
|
10259
10600
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
10260
10601
|
if (cjsDir) return cjsDir;
|
|
10261
10602
|
try {
|
|
10262
|
-
return (0,
|
|
10603
|
+
return (0, import_node_path30.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
|
|
10263
10604
|
} catch {
|
|
10264
10605
|
try {
|
|
10265
10606
|
const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
|
|
10266
|
-
return (0,
|
|
10607
|
+
return (0, import_node_path30.dirname)(req.resolve("@sideboard-ai/core"));
|
|
10267
10608
|
} catch {
|
|
10268
10609
|
return process.cwd();
|
|
10269
10610
|
}
|
|
@@ -10274,27 +10615,27 @@ function cursorRunnerPath() {
|
|
|
10274
10615
|
if (packaged) return packaged;
|
|
10275
10616
|
const root = entryDir();
|
|
10276
10617
|
const candidates = [
|
|
10277
|
-
(0,
|
|
10278
|
-
(0,
|
|
10618
|
+
(0, import_node_path30.join)(root, "agents", "cursor-runner.js"),
|
|
10619
|
+
(0, import_node_path30.join)(root, "agents", "cursor-runner.cjs"),
|
|
10279
10620
|
// If somehow resolved from package root instead of dist/
|
|
10280
|
-
(0,
|
|
10281
|
-
(0,
|
|
10621
|
+
(0, import_node_path30.join)(root, "dist", "agents", "cursor-runner.js"),
|
|
10622
|
+
(0, import_node_path30.join)(root, "dist", "agents", "cursor-runner.cjs"),
|
|
10282
10623
|
// Source tree (dev): packages/core/src/agents/cursor-runner.ts
|
|
10283
|
-
(0,
|
|
10284
|
-
(0,
|
|
10624
|
+
(0, import_node_path30.join)(root, "cursor-runner.ts"),
|
|
10625
|
+
(0, import_node_path30.join)(root, "src", "agents", "cursor-runner.ts")
|
|
10285
10626
|
];
|
|
10286
10627
|
for (const candidate of candidates) {
|
|
10287
|
-
if ((0,
|
|
10628
|
+
if ((0, import_node_fs29.existsSync)(candidate)) return candidate;
|
|
10288
10629
|
}
|
|
10289
10630
|
return candidates[0];
|
|
10290
10631
|
}
|
|
10291
|
-
var
|
|
10632
|
+
var import_node_fs29, import_node_module3, import_node_path30, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
|
|
10292
10633
|
var init_cursor = __esm({
|
|
10293
10634
|
"src/agents/cursor.ts"() {
|
|
10294
10635
|
"use strict";
|
|
10295
|
-
|
|
10636
|
+
import_node_fs29 = require("fs");
|
|
10296
10637
|
import_node_module3 = require("module");
|
|
10297
|
-
|
|
10638
|
+
import_node_path30 = require("path");
|
|
10298
10639
|
import_node_url2 = require("url");
|
|
10299
10640
|
import_sdk = require("@cursor/sdk");
|
|
10300
10641
|
init_run();
|
|
@@ -10445,7 +10786,7 @@ async function listOpencodeModels() {
|
|
|
10445
10786
|
if (opencode === "opencode") {
|
|
10446
10787
|
const which = await run("which", ["opencode"], { reject: false });
|
|
10447
10788
|
if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
|
|
10448
|
-
} else if (!(0,
|
|
10789
|
+
} else if (!(0, import_node_fs30.existsSync)(opencode)) {
|
|
10449
10790
|
return FALLBACK_OPENCODE_MODELS;
|
|
10450
10791
|
}
|
|
10451
10792
|
const listed = await run(opencode, ["models"], { reject: false });
|
|
@@ -10475,11 +10816,11 @@ function usageFromOpencode(tokens) {
|
|
|
10475
10816
|
cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
|
|
10476
10817
|
};
|
|
10477
10818
|
}
|
|
10478
|
-
var
|
|
10819
|
+
var import_node_fs30, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
|
|
10479
10820
|
var init_opencode = __esm({
|
|
10480
10821
|
"src/agents/opencode.ts"() {
|
|
10481
10822
|
"use strict";
|
|
10482
|
-
|
|
10823
|
+
import_node_fs30 = require("fs");
|
|
10483
10824
|
init_run();
|
|
10484
10825
|
init_app_settings();
|
|
10485
10826
|
init_global_workspace();
|
|
@@ -10506,7 +10847,7 @@ var init_opencode = __esm({
|
|
|
10506
10847
|
async detect() {
|
|
10507
10848
|
const opencode = resolveAgentExecutable("opencode");
|
|
10508
10849
|
if (opencode !== "opencode") {
|
|
10509
|
-
if (!(0,
|
|
10850
|
+
if (!(0, import_node_fs30.existsSync)(opencode)) {
|
|
10510
10851
|
return {
|
|
10511
10852
|
agent: "opencode",
|
|
10512
10853
|
installed: false,
|
|
@@ -12009,7 +12350,7 @@ function forkMessageSlice(from, throughIndex) {
|
|
|
12009
12350
|
function buildForkTranscriptAttachment(baseTitle, messages) {
|
|
12010
12351
|
const title = baseTitle || "Chat";
|
|
12011
12352
|
return {
|
|
12012
|
-
id: (0,
|
|
12353
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
12013
12354
|
name: `Transcript of ${title}.md`,
|
|
12014
12355
|
kind: "transcript",
|
|
12015
12356
|
content: formatTranscriptMarkdown(title, messages)
|
|
@@ -12066,11 +12407,11 @@ function forkChatTab(input) {
|
|
|
12066
12407
|
}
|
|
12067
12408
|
return tab;
|
|
12068
12409
|
}
|
|
12069
|
-
var
|
|
12410
|
+
var import_node_crypto6;
|
|
12070
12411
|
var init_chat_tabs = __esm({
|
|
12071
12412
|
"src/threads/chat-tabs.ts"() {
|
|
12072
12413
|
"use strict";
|
|
12073
|
-
|
|
12414
|
+
import_node_crypto6 = require("crypto");
|
|
12074
12415
|
init_context_compact();
|
|
12075
12416
|
init_teams();
|
|
12076
12417
|
init_worktree_labels();
|
|
@@ -12240,21 +12581,21 @@ function shouldRefreshReviewRequestTemplate(content) {
|
|
|
12240
12581
|
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
12241
12582
|
}
|
|
12242
12583
|
function readTextIfPresent(abs) {
|
|
12243
|
-
if (!(0,
|
|
12584
|
+
if (!(0, import_node_fs31.existsSync)(abs)) return null;
|
|
12244
12585
|
try {
|
|
12245
|
-
const content = (0,
|
|
12586
|
+
const content = (0, import_node_fs31.readFileSync)(abs, "utf8");
|
|
12246
12587
|
return content.trim() ? content : null;
|
|
12247
12588
|
} catch {
|
|
12248
12589
|
return null;
|
|
12249
12590
|
}
|
|
12250
12591
|
}
|
|
12251
12592
|
function readLocalGuidelines(worktreePath) {
|
|
12252
|
-
const localAbs = (0,
|
|
12593
|
+
const localAbs = (0, import_node_path31.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
12253
12594
|
const localContent = readTextIfPresent(localAbs);
|
|
12254
12595
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
12255
12596
|
return { path: REVIEW_REQUEST_PATH, content: localContent };
|
|
12256
12597
|
}
|
|
12257
|
-
const legacyAbs = (0,
|
|
12598
|
+
const legacyAbs = (0, import_node_path31.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
|
|
12258
12599
|
const legacyContent = readTextIfPresent(legacyAbs);
|
|
12259
12600
|
if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
|
|
12260
12601
|
return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
|
|
@@ -12270,20 +12611,20 @@ function skillGuidelines(content, source) {
|
|
|
12270
12611
|
};
|
|
12271
12612
|
}
|
|
12272
12613
|
function ensureReviewSkillFile(worktreePath) {
|
|
12273
|
-
const abs = (0,
|
|
12614
|
+
const abs = (0, import_node_path31.join)(worktreePath, REVIEW_SKILL_PATH);
|
|
12274
12615
|
const existing = readTextIfPresent(abs);
|
|
12275
12616
|
if (existing) {
|
|
12276
12617
|
return { path: REVIEW_SKILL_PATH, content: existing, wrote: false };
|
|
12277
12618
|
}
|
|
12278
|
-
const fromRepo = readTextIfPresent((0,
|
|
12619
|
+
const fromRepo = readTextIfPresent((0, import_node_path31.join)(worktreePath, REPO_REVIEW_PATH));
|
|
12279
12620
|
const fromLocal = readLocalGuidelines(worktreePath)?.content ?? null;
|
|
12280
12621
|
const content = wrapReviewSkillMarkdown(fromRepo ?? fromLocal ?? REVIEW_REQUEST_TEMPLATE);
|
|
12281
|
-
(0,
|
|
12282
|
-
(0,
|
|
12622
|
+
(0, import_node_fs31.mkdirSync)((0, import_node_path31.dirname)(abs), { recursive: true });
|
|
12623
|
+
(0, import_node_fs31.writeFileSync)(abs, content, "utf8");
|
|
12283
12624
|
return { path: REVIEW_SKILL_PATH, content, wrote: true };
|
|
12284
12625
|
}
|
|
12285
12626
|
function resolveReviewGuidelines(worktreePath) {
|
|
12286
|
-
const skillContent = readTextIfPresent((0,
|
|
12627
|
+
const skillContent = readTextIfPresent((0, import_node_path31.join)(worktreePath, REVIEW_SKILL_PATH));
|
|
12287
12628
|
if (skillContent) return skillGuidelines(skillContent, "skill");
|
|
12288
12629
|
const local = readLocalGuidelines(worktreePath);
|
|
12289
12630
|
if (local) {
|
|
@@ -12305,7 +12646,7 @@ function buildReviewRequestAttachment(content, opts) {
|
|
|
12305
12646
|
const path2 = opts?.path ?? REVIEW_SKILL_PATH;
|
|
12306
12647
|
const name = opts?.name ?? (path2 === REVIEW_SKILL_PATH ? REVIEW_SKILL_NAME : path2 === REPO_REVIEW_PATH ? REPO_REVIEW_NAME : REVIEW_REQUEST_NAME);
|
|
12307
12648
|
return {
|
|
12308
|
-
id: (0,
|
|
12649
|
+
id: (0, import_node_crypto7.randomUUID)(),
|
|
12309
12650
|
name,
|
|
12310
12651
|
kind: "file",
|
|
12311
12652
|
path: path2,
|
|
@@ -12313,7 +12654,7 @@ function buildReviewRequestAttachment(content, opts) {
|
|
|
12313
12654
|
};
|
|
12314
12655
|
}
|
|
12315
12656
|
function readExistingReviewRequestFile(worktreePath) {
|
|
12316
|
-
return readTextIfPresent((0,
|
|
12657
|
+
return readTextIfPresent((0, import_node_path31.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path31.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path31.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path31.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
|
|
12317
12658
|
}
|
|
12318
12659
|
async function requestReview(threadRef, send2) {
|
|
12319
12660
|
const from = findThreadByRef(threadRef);
|
|
@@ -12340,13 +12681,13 @@ async function requestReview(threadRef, send2) {
|
|
|
12340
12681
|
const started = await send2(tab.id, REVIEW_REQUEST_PREFILL);
|
|
12341
12682
|
return { tab: started, from };
|
|
12342
12683
|
}
|
|
12343
|
-
var
|
|
12684
|
+
var import_node_crypto7, import_node_fs31, import_node_path31, REPO_REVIEW_PATH, REPO_REVIEW_NAME, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
|
|
12344
12685
|
var init_request_review = __esm({
|
|
12345
12686
|
"src/review/request-review.ts"() {
|
|
12346
12687
|
"use strict";
|
|
12347
|
-
|
|
12348
|
-
|
|
12349
|
-
|
|
12688
|
+
import_node_crypto7 = require("crypto");
|
|
12689
|
+
import_node_fs31 = require("fs");
|
|
12690
|
+
import_node_path31 = require("path");
|
|
12350
12691
|
init_global_workspace();
|
|
12351
12692
|
init_chat_tabs();
|
|
12352
12693
|
init_thread_store();
|
|
@@ -12371,9 +12712,9 @@ function matchSimpleGlob(pattern, name) {
|
|
|
12371
12712
|
return new RegExp(`^${escaped}$`).test(name);
|
|
12372
12713
|
}
|
|
12373
12714
|
function readWorktreeInclude(repoPath) {
|
|
12374
|
-
const path2 = (0,
|
|
12375
|
-
if (!(0,
|
|
12376
|
-
return (0,
|
|
12715
|
+
const path2 = (0, import_node_path32.join)(repoPath, ".worktreeinclude");
|
|
12716
|
+
if (!(0, import_node_fs32.existsSync)(path2)) return [];
|
|
12717
|
+
return (0, import_node_fs32.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
12377
12718
|
}
|
|
12378
12719
|
function resolveFilesToCopy(repoPath) {
|
|
12379
12720
|
const fromInclude = readWorktreeInclude(repoPath);
|
|
@@ -12383,10 +12724,10 @@ function resolveFilesToCopy(repoPath) {
|
|
|
12383
12724
|
if (settings?.fileIncludeGlobs?.length) {
|
|
12384
12725
|
const matched = [];
|
|
12385
12726
|
try {
|
|
12386
|
-
for (const entry of (0,
|
|
12727
|
+
for (const entry of (0, import_node_fs32.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
12387
12728
|
if (!entry.isFile()) continue;
|
|
12388
12729
|
for (const glob of settings.fileIncludeGlobs) {
|
|
12389
|
-
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0,
|
|
12730
|
+
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path32.basename)(glob), entry.name)) {
|
|
12390
12731
|
matched.push(entry.name);
|
|
12391
12732
|
break;
|
|
12392
12733
|
}
|
|
@@ -12398,7 +12739,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
12398
12739
|
}
|
|
12399
12740
|
const defaults = [];
|
|
12400
12741
|
try {
|
|
12401
|
-
for (const entry of (0,
|
|
12742
|
+
for (const entry of (0, import_node_fs32.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
12402
12743
|
if (entry.isFile() && entry.name.startsWith(".env")) {
|
|
12403
12744
|
defaults.push(entry.name);
|
|
12404
12745
|
}
|
|
@@ -12412,11 +12753,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
|
|
|
12412
12753
|
const patterns = resolveFilesToCopy(repoPath);
|
|
12413
12754
|
const copied = [];
|
|
12414
12755
|
for (const rel of patterns) {
|
|
12415
|
-
const src = (0,
|
|
12416
|
-
if (!(0,
|
|
12417
|
-
const dest = (0,
|
|
12418
|
-
(0,
|
|
12419
|
-
(0,
|
|
12756
|
+
const src = (0, import_node_path32.join)(repoPath, rel);
|
|
12757
|
+
if (!(0, import_node_fs32.existsSync)(src)) continue;
|
|
12758
|
+
const dest = (0, import_node_path32.join)(worktreePath, rel);
|
|
12759
|
+
(0, import_node_fs32.mkdirSync)((0, import_node_path32.dirname)(dest), { recursive: true });
|
|
12760
|
+
(0, import_node_fs32.copyFileSync)(src, dest);
|
|
12420
12761
|
copied.push(rel);
|
|
12421
12762
|
}
|
|
12422
12763
|
return copied;
|
|
@@ -12451,7 +12792,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
|
|
|
12451
12792
|
const env = stripNestedElectronEnv({
|
|
12452
12793
|
...baseEnv ?? process.env
|
|
12453
12794
|
});
|
|
12454
|
-
const name = opts.workspaceName ?? (0,
|
|
12795
|
+
const name = opts.workspaceName ?? (0, import_node_path32.basename)(opts.worktreePath);
|
|
12455
12796
|
const ports = opts.ports ?? [];
|
|
12456
12797
|
const primary = ports[0];
|
|
12457
12798
|
env.SIDEBOARD_WORKSPACE_NAME = name;
|
|
@@ -12712,13 +13053,13 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
|
12712
13053
|
done: handle.done
|
|
12713
13054
|
};
|
|
12714
13055
|
}
|
|
12715
|
-
var
|
|
13056
|
+
var import_node_fs32, import_node_net, import_node_path32, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
|
|
12716
13057
|
var init_conductor = __esm({
|
|
12717
13058
|
"src/hook/conductor.ts"() {
|
|
12718
13059
|
"use strict";
|
|
12719
|
-
|
|
13060
|
+
import_node_fs32 = require("fs");
|
|
12720
13061
|
import_node_net = require("net");
|
|
12721
|
-
|
|
13062
|
+
import_node_path32 = require("path");
|
|
12722
13063
|
import_execa4 = require("execa");
|
|
12723
13064
|
import_node_readline3 = require("readline");
|
|
12724
13065
|
init_settings();
|
|
@@ -12744,9 +13085,9 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
12744
13085
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
12745
13086
|
);
|
|
12746
13087
|
const homeRoot = sideboardWorkspacesDir();
|
|
12747
|
-
if ((0,
|
|
13088
|
+
if ((0, import_node_fs33.existsSync)(homeRoot)) {
|
|
12748
13089
|
try {
|
|
12749
|
-
for (const entry of (0,
|
|
13090
|
+
for (const entry of (0, import_node_fs33.readdirSync)(homeRoot, { withFileTypes: true })) {
|
|
12750
13091
|
if (!entry.isDirectory()) continue;
|
|
12751
13092
|
void entry;
|
|
12752
13093
|
}
|
|
@@ -12756,7 +13097,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
12756
13097
|
const orphans = [];
|
|
12757
13098
|
const seen = /* @__PURE__ */ new Set();
|
|
12758
13099
|
for (const repoPath of repos) {
|
|
12759
|
-
if (!repoPath || !(0,
|
|
13100
|
+
if (!repoPath || !(0, import_node_fs33.existsSync)(repoPath)) continue;
|
|
12760
13101
|
try {
|
|
12761
13102
|
const wts = await listWorktrees(repoPath);
|
|
12762
13103
|
for (const wt of wts) {
|
|
@@ -12767,7 +13108,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
12767
13108
|
seen.add(path2);
|
|
12768
13109
|
let mtimeMs = 0;
|
|
12769
13110
|
try {
|
|
12770
|
-
mtimeMs = (0,
|
|
13111
|
+
mtimeMs = (0, import_node_fs33.statSync)(path2).mtimeMs;
|
|
12771
13112
|
} catch {
|
|
12772
13113
|
mtimeMs = 0;
|
|
12773
13114
|
}
|
|
@@ -12777,16 +13118,16 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
12777
13118
|
}
|
|
12778
13119
|
try {
|
|
12779
13120
|
const root = worktreesRoot(repoPath);
|
|
12780
|
-
if ((0,
|
|
12781
|
-
for (const entry of (0,
|
|
13121
|
+
if ((0, import_node_fs33.existsSync)(root)) {
|
|
13122
|
+
for (const entry of (0, import_node_fs33.readdirSync)(root, { withFileTypes: true })) {
|
|
12782
13123
|
if (!entry.isDirectory()) continue;
|
|
12783
|
-
const path2 = (0,
|
|
13124
|
+
const path2 = (0, import_node_path33.join)(root, entry.name).replace(/\/$/, "");
|
|
12784
13125
|
if (known.has(path2) || seen.has(path2)) continue;
|
|
12785
|
-
if (!(0,
|
|
13126
|
+
if (!(0, import_node_fs33.existsSync)((0, import_node_path33.join)(path2, ".git"))) continue;
|
|
12786
13127
|
seen.add(path2);
|
|
12787
13128
|
let mtimeMs = 0;
|
|
12788
13129
|
try {
|
|
12789
|
-
mtimeMs = (0,
|
|
13130
|
+
mtimeMs = (0, import_node_fs33.statSync)(path2).mtimeMs;
|
|
12790
13131
|
} catch {
|
|
12791
13132
|
mtimeMs = Date.now();
|
|
12792
13133
|
}
|
|
@@ -12847,12 +13188,12 @@ function worktreeCleanupSettings() {
|
|
|
12847
13188
|
autoCleanupOrphans: a.autoCleanupOrphans
|
|
12848
13189
|
};
|
|
12849
13190
|
}
|
|
12850
|
-
var
|
|
13191
|
+
var import_node_fs33, import_node_path33;
|
|
12851
13192
|
var init_orphan_cleanup = __esm({
|
|
12852
13193
|
"src/git/orphan-cleanup.ts"() {
|
|
12853
13194
|
"use strict";
|
|
12854
|
-
|
|
12855
|
-
|
|
13195
|
+
import_node_fs33 = require("fs");
|
|
13196
|
+
import_node_path33 = require("path");
|
|
12856
13197
|
init_worktree();
|
|
12857
13198
|
init_thread_store();
|
|
12858
13199
|
init_paths();
|
|
@@ -12959,38 +13300,38 @@ __export(workspaces_exports, {
|
|
|
12959
13300
|
syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
|
|
12960
13301
|
});
|
|
12961
13302
|
function workspacesFile() {
|
|
12962
|
-
return (0,
|
|
13303
|
+
return (0, import_node_path34.join)(appDataDir(), "workspaces.json");
|
|
12963
13304
|
}
|
|
12964
13305
|
function removedWorkspacesFile() {
|
|
12965
|
-
return (0,
|
|
13306
|
+
return (0, import_node_path34.join)(appDataDir(), "removed-workspaces.json");
|
|
12966
13307
|
}
|
|
12967
13308
|
function readAll2() {
|
|
12968
13309
|
const path2 = workspacesFile();
|
|
12969
|
-
if (!(0,
|
|
13310
|
+
if (!(0, import_node_fs34.existsSync)(path2)) return [];
|
|
12970
13311
|
try {
|
|
12971
|
-
const raw = JSON.parse((0,
|
|
13312
|
+
const raw = JSON.parse((0, import_node_fs34.readFileSync)(path2, "utf8"));
|
|
12972
13313
|
return Array.isArray(raw) ? raw : [];
|
|
12973
13314
|
} catch {
|
|
12974
13315
|
return [];
|
|
12975
13316
|
}
|
|
12976
13317
|
}
|
|
12977
13318
|
function writeAll2(list) {
|
|
12978
|
-
(0,
|
|
12979
|
-
(0,
|
|
13319
|
+
(0, import_node_fs34.mkdirSync)(appDataDir(), { recursive: true });
|
|
13320
|
+
(0, import_node_fs34.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
|
|
12980
13321
|
}
|
|
12981
13322
|
function readRemoved() {
|
|
12982
13323
|
const path2 = removedWorkspacesFile();
|
|
12983
|
-
if (!(0,
|
|
13324
|
+
if (!(0, import_node_fs34.existsSync)(path2)) return /* @__PURE__ */ new Set();
|
|
12984
13325
|
try {
|
|
12985
|
-
const raw = JSON.parse((0,
|
|
13326
|
+
const raw = JSON.parse((0, import_node_fs34.readFileSync)(path2, "utf8"));
|
|
12986
13327
|
return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
|
|
12987
13328
|
} catch {
|
|
12988
13329
|
return /* @__PURE__ */ new Set();
|
|
12989
13330
|
}
|
|
12990
13331
|
}
|
|
12991
13332
|
function writeRemoved(paths) {
|
|
12992
|
-
(0,
|
|
12993
|
-
(0,
|
|
13333
|
+
(0, import_node_fs34.mkdirSync)(appDataDir(), { recursive: true });
|
|
13334
|
+
(0, import_node_fs34.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
|
|
12994
13335
|
}
|
|
12995
13336
|
function rememberRemoved(repoPath) {
|
|
12996
13337
|
const next = readRemoved();
|
|
@@ -13013,7 +13354,7 @@ function listWorkspaces() {
|
|
|
13013
13354
|
async function addWorkspace(repoPath) {
|
|
13014
13355
|
const root = await resolveRepoRoot(repoPath);
|
|
13015
13356
|
if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
|
|
13016
|
-
if (!(0,
|
|
13357
|
+
if (!(0, import_node_fs34.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
|
|
13017
13358
|
forgetRemoved(root);
|
|
13018
13359
|
await ensureGhPreferOrigin(root);
|
|
13019
13360
|
const current = readAll2();
|
|
@@ -13021,7 +13362,7 @@ async function addWorkspace(repoPath) {
|
|
|
13021
13362
|
if (existing) return existing;
|
|
13022
13363
|
const next = {
|
|
13023
13364
|
path: root,
|
|
13024
|
-
name: (0,
|
|
13365
|
+
name: (0, import_node_path34.basename)(root),
|
|
13025
13366
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13026
13367
|
};
|
|
13027
13368
|
writeAll2([...current, next]);
|
|
@@ -13043,10 +13384,10 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
13043
13384
|
if (!path2 || path2 === "/" || isGlobalRepoPath(path2) || byPath.has(path2) || removed.has(path2)) {
|
|
13044
13385
|
continue;
|
|
13045
13386
|
}
|
|
13046
|
-
if (!(0,
|
|
13387
|
+
if (!(0, import_node_fs34.existsSync)(path2)) continue;
|
|
13047
13388
|
const ws = {
|
|
13048
13389
|
path: path2,
|
|
13049
|
-
name: (0,
|
|
13390
|
+
name: (0, import_node_path34.basename)(path2),
|
|
13050
13391
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13051
13392
|
};
|
|
13052
13393
|
byPath.set(path2, ws);
|
|
@@ -13056,12 +13397,12 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
13056
13397
|
if (dirty) writeAll2(next);
|
|
13057
13398
|
return next.sort((a, b) => a.name.localeCompare(b.name));
|
|
13058
13399
|
}
|
|
13059
|
-
var
|
|
13400
|
+
var import_node_fs34, import_node_path34;
|
|
13060
13401
|
var init_workspaces2 = __esm({
|
|
13061
13402
|
"src/store/workspaces.ts"() {
|
|
13062
13403
|
"use strict";
|
|
13063
|
-
|
|
13064
|
-
|
|
13404
|
+
import_node_fs34 = require("fs");
|
|
13405
|
+
import_node_path34 = require("path");
|
|
13065
13406
|
init_paths();
|
|
13066
13407
|
init_global_workspace();
|
|
13067
13408
|
init_worktree();
|
|
@@ -13074,12 +13415,12 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
13074
13415
|
if (!url) throw new Error("Clone URL is required");
|
|
13075
13416
|
let name = opts.name?.trim();
|
|
13076
13417
|
if (!name) {
|
|
13077
|
-
const leaf = (0,
|
|
13418
|
+
const leaf = (0, import_node_path35.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
|
|
13078
13419
|
name = leaf || "repo";
|
|
13079
13420
|
}
|
|
13080
13421
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
13081
|
-
const dest = (0,
|
|
13082
|
-
if ((0,
|
|
13422
|
+
const dest = (0, import_node_path35.join)(sideboardReposDir(), name);
|
|
13423
|
+
if ((0, import_node_fs35.existsSync)(dest)) {
|
|
13083
13424
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
13084
13425
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
13085
13426
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -13094,16 +13435,63 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
13094
13435
|
const workspace = await ensureWorkspace(repoPath);
|
|
13095
13436
|
return { repoPath, workspace };
|
|
13096
13437
|
}
|
|
13097
|
-
var
|
|
13438
|
+
var import_node_fs35, import_node_path35, import_execa6;
|
|
13098
13439
|
var init_clone_repo = __esm({
|
|
13099
13440
|
"src/git/clone-repo.ts"() {
|
|
13100
13441
|
"use strict";
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
import_execa6 = require("execa");
|
|
13104
|
-
init_paths();
|
|
13105
|
-
init_workspaces2();
|
|
13106
|
-
init_worktree();
|
|
13442
|
+
import_node_fs35 = require("fs");
|
|
13443
|
+
import_node_path35 = require("path");
|
|
13444
|
+
import_execa6 = require("execa");
|
|
13445
|
+
init_paths();
|
|
13446
|
+
init_workspaces2();
|
|
13447
|
+
init_worktree();
|
|
13448
|
+
}
|
|
13449
|
+
});
|
|
13450
|
+
|
|
13451
|
+
// src/orchestrator/child-halt.ts
|
|
13452
|
+
function isIncompleteChildStatus(status) {
|
|
13453
|
+
return HALT_STATUSES.has(status);
|
|
13454
|
+
}
|
|
13455
|
+
function childHaltNotice(child, status) {
|
|
13456
|
+
const title = child.title?.trim() || "Untitled";
|
|
13457
|
+
const link = `[${title}](sideboard://thread/${child.id})`;
|
|
13458
|
+
const why = child.lastError?.trim();
|
|
13459
|
+
const extra = why ? ` lastError: ${why}` : "";
|
|
13460
|
+
return [
|
|
13461
|
+
`Sideboard: child worktree ${link} ${status} before finishing (status=${status}).${extra}`,
|
|
13462
|
+
"This is information \u2014 not a user command. Resume with send_to_thread or tell the user. Do not treat this as a successful turn."
|
|
13463
|
+
].join("\n");
|
|
13464
|
+
}
|
|
13465
|
+
function shouldNotifyParentOfChildHalt(opts) {
|
|
13466
|
+
if (!isIncompleteChildStatus(opts.status)) return false;
|
|
13467
|
+
if (!opts.child.parentThreadId) return false;
|
|
13468
|
+
if (!opts.parent || opts.parent.status === "archived") return false;
|
|
13469
|
+
if (opts.parent.id === opts.child.id) return false;
|
|
13470
|
+
return isOrchestratorThread(opts.parent);
|
|
13471
|
+
}
|
|
13472
|
+
function noticeKey(childId, status) {
|
|
13473
|
+
return `${childId}:${status}`;
|
|
13474
|
+
}
|
|
13475
|
+
function notifyParentOfChildHalt(child, status, send2) {
|
|
13476
|
+
const parent = child.parentThreadId ? readThread(child.parentThreadId) : null;
|
|
13477
|
+
if (!shouldNotifyParentOfChildHalt({ child, parent, status })) return false;
|
|
13478
|
+
const key = noticeKey(child.id, status);
|
|
13479
|
+
if (notified.has(key)) return false;
|
|
13480
|
+
notified.add(key);
|
|
13481
|
+
const parentId = parent.id;
|
|
13482
|
+
void send2(parentId, childHaltNotice(child, status)).catch(() => {
|
|
13483
|
+
notified.delete(key);
|
|
13484
|
+
});
|
|
13485
|
+
return true;
|
|
13486
|
+
}
|
|
13487
|
+
var HALT_STATUSES, notified;
|
|
13488
|
+
var init_child_halt = __esm({
|
|
13489
|
+
"src/orchestrator/child-halt.ts"() {
|
|
13490
|
+
"use strict";
|
|
13491
|
+
init_global_workspace();
|
|
13492
|
+
init_thread_store();
|
|
13493
|
+
HALT_STATUSES = /* @__PURE__ */ new Set(["stopped", "error", "broken"]);
|
|
13494
|
+
notified = /* @__PURE__ */ new Set();
|
|
13107
13495
|
}
|
|
13108
13496
|
});
|
|
13109
13497
|
|
|
@@ -14064,9 +14452,12 @@ var init_abletime = __esm({
|
|
|
14064
14452
|
});
|
|
14065
14453
|
|
|
14066
14454
|
// src/threads/create.ts
|
|
14455
|
+
function persistCreateAttachments(worktreePath, attachments) {
|
|
14456
|
+
return persistPendingFileAttachments(worktreePath, attachments ?? []);
|
|
14457
|
+
}
|
|
14067
14458
|
async function createThread(input, _onSetupLine) {
|
|
14068
14459
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
14069
|
-
if (!(0,
|
|
14460
|
+
if (!(0, import_node_fs36.existsSync)(repoPath)) {
|
|
14070
14461
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
14071
14462
|
}
|
|
14072
14463
|
if (input.reuseExisting !== false) {
|
|
@@ -14083,7 +14474,16 @@ async function createThread(input, _onSetupLine) {
|
|
|
14083
14474
|
repoPath: canonicalizeRepoPath(t.repoPath)
|
|
14084
14475
|
}))
|
|
14085
14476
|
);
|
|
14086
|
-
if (existing)
|
|
14477
|
+
if (existing) {
|
|
14478
|
+
const thread2 = readThread(existing.id) ?? existing;
|
|
14479
|
+
if (!input.attachments?.length) return thread2;
|
|
14480
|
+
return updateThread(thread2.id, {
|
|
14481
|
+
attachments: persistCreateAttachments(thread2.worktreePath, [
|
|
14482
|
+
...thread2.attachments,
|
|
14483
|
+
...input.attachments
|
|
14484
|
+
])
|
|
14485
|
+
});
|
|
14486
|
+
}
|
|
14087
14487
|
}
|
|
14088
14488
|
const resolved = resolveNewThreadOptions({
|
|
14089
14489
|
agent: input.agent,
|
|
@@ -14131,7 +14531,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
14131
14531
|
effort: resolved.effort,
|
|
14132
14532
|
fast: resolved.fast,
|
|
14133
14533
|
planMode: Boolean(input.planMode),
|
|
14134
|
-
attachments: input.attachments
|
|
14534
|
+
attachments: persistCreateAttachments(repoPath, input.attachments),
|
|
14135
14535
|
sourceIsFork: false,
|
|
14136
14536
|
parentThreadId: input.parentThreadId ?? null,
|
|
14137
14537
|
status: "idle",
|
|
@@ -14210,7 +14610,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
14210
14610
|
effort: resolved.effort,
|
|
14211
14611
|
fast: resolved.fast,
|
|
14212
14612
|
planMode: Boolean(input.planMode),
|
|
14213
|
-
attachments,
|
|
14613
|
+
attachments: persistCreateAttachments(worktreePath, attachments),
|
|
14214
14614
|
sourceIsFork,
|
|
14215
14615
|
parentThreadId: input.parentThreadId ?? null,
|
|
14216
14616
|
status: "idle",
|
|
@@ -14230,16 +14630,17 @@ async function listLinearIssues(agent, repoPath) {
|
|
|
14230
14630
|
}
|
|
14231
14631
|
return adapter.listLinearIssues(repoPath);
|
|
14232
14632
|
}
|
|
14233
|
-
var
|
|
14633
|
+
var import_node_fs36;
|
|
14234
14634
|
var init_create = __esm({
|
|
14235
14635
|
"src/threads/create.ts"() {
|
|
14236
14636
|
"use strict";
|
|
14237
|
-
|
|
14637
|
+
import_node_fs36 = require("fs");
|
|
14238
14638
|
init_detect();
|
|
14239
14639
|
init_worktree();
|
|
14240
14640
|
init_home_board();
|
|
14241
14641
|
init_conductor();
|
|
14242
14642
|
init_app_settings();
|
|
14643
|
+
init_stage_files();
|
|
14243
14644
|
init_thread_store();
|
|
14244
14645
|
init_workspaces2();
|
|
14245
14646
|
}
|
|
@@ -14336,20 +14737,20 @@ function writeTurnLive(threadId, progress) {
|
|
|
14336
14737
|
const path2 = threadLivePath(threadId);
|
|
14337
14738
|
const tmp = `${path2}.${process.pid}.tmp`;
|
|
14338
14739
|
try {
|
|
14339
|
-
(0,
|
|
14340
|
-
(0,
|
|
14740
|
+
(0, import_node_fs37.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
|
|
14741
|
+
(0, import_node_fs37.renameSync)(tmp, path2);
|
|
14341
14742
|
} catch {
|
|
14342
14743
|
try {
|
|
14343
|
-
(0,
|
|
14744
|
+
(0, import_node_fs37.unlinkSync)(tmp);
|
|
14344
14745
|
} catch {
|
|
14345
14746
|
}
|
|
14346
14747
|
}
|
|
14347
14748
|
}
|
|
14348
14749
|
function readTurnLive(threadId) {
|
|
14349
14750
|
const path2 = threadLivePath(threadId);
|
|
14350
|
-
if (!(0,
|
|
14751
|
+
if (!(0, import_node_fs37.existsSync)(path2)) return null;
|
|
14351
14752
|
try {
|
|
14352
|
-
const raw = JSON.parse((0,
|
|
14753
|
+
const raw = JSON.parse((0, import_node_fs37.readFileSync)(path2, "utf8"));
|
|
14353
14754
|
if (!raw || typeof raw.summary !== "string") return null;
|
|
14354
14755
|
return raw;
|
|
14355
14756
|
} catch {
|
|
@@ -14361,17 +14762,17 @@ function clearTurnLive(threadId) {
|
|
|
14361
14762
|
if (buf?.timer) clearTimeout(buf.timer);
|
|
14362
14763
|
buffers.delete(threadId);
|
|
14363
14764
|
const path2 = threadLivePath(threadId);
|
|
14364
|
-
if (!(0,
|
|
14765
|
+
if (!(0, import_node_fs37.existsSync)(path2)) return;
|
|
14365
14766
|
try {
|
|
14366
|
-
(0,
|
|
14767
|
+
(0, import_node_fs37.unlinkSync)(path2);
|
|
14367
14768
|
} catch {
|
|
14368
14769
|
}
|
|
14369
14770
|
}
|
|
14370
|
-
var
|
|
14771
|
+
var import_node_fs37, buffers, FLUSH_MS, MAX_PARTS;
|
|
14371
14772
|
var init_turn_live = __esm({
|
|
14372
14773
|
"src/store/turn-live.ts"() {
|
|
14373
14774
|
"use strict";
|
|
14374
|
-
|
|
14775
|
+
import_node_fs37 = require("fs");
|
|
14375
14776
|
init_message_parts();
|
|
14376
14777
|
init_paths();
|
|
14377
14778
|
buffers = /* @__PURE__ */ new Map();
|
|
@@ -14530,7 +14931,7 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
|
|
|
14530
14931
|
`- Do not wait on the limited ${from.agent} account; keep going on ${fallbackAgent}.`
|
|
14531
14932
|
].join("\n");
|
|
14532
14933
|
return {
|
|
14533
|
-
id: (0,
|
|
14934
|
+
id: (0, import_node_crypto8.randomUUID)(),
|
|
14534
14935
|
name: "Orchestration quota handoff.md",
|
|
14535
14936
|
kind: "transcript",
|
|
14536
14937
|
content: body
|
|
@@ -14551,11 +14952,11 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
|
|
|
14551
14952
|
sourceType: "orchestration"
|
|
14552
14953
|
});
|
|
14553
14954
|
}
|
|
14554
|
-
var
|
|
14955
|
+
var import_node_crypto8, QUOTA_CONTINUE_PROMPT, QUOTA_RESUME_PROMPT;
|
|
14555
14956
|
var init_quota_failover = __esm({
|
|
14556
14957
|
"src/orchestrator/quota-failover.ts"() {
|
|
14557
14958
|
"use strict";
|
|
14558
|
-
|
|
14959
|
+
import_node_crypto8 = require("crypto");
|
|
14559
14960
|
init_session_quota();
|
|
14560
14961
|
init_app_settings();
|
|
14561
14962
|
init_global_workspace();
|
|
@@ -14572,7 +14973,7 @@ var init_quota_failover = __esm({
|
|
|
14572
14973
|
// src/threads/adopt.ts
|
|
14573
14974
|
function thisModuleFile() {
|
|
14574
14975
|
const cjsFile = typeof __filename !== "undefined" ? __filename : "";
|
|
14575
|
-
return cjsFile || process.argv[1] || (0,
|
|
14976
|
+
return cjsFile || process.argv[1] || (0, import_node_path36.join)(process.cwd(), "package.json");
|
|
14576
14977
|
}
|
|
14577
14978
|
function openReadonlySqlite(file) {
|
|
14578
14979
|
const req = (0, import_node_module4.createRequire)(thisModuleFile());
|
|
@@ -14590,21 +14991,21 @@ function mapAgentType(raw) {
|
|
|
14590
14991
|
return null;
|
|
14591
14992
|
}
|
|
14592
14993
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
14593
|
-
if (!workspacePath || !(0,
|
|
14994
|
+
if (!workspacePath || !(0, import_node_fs38.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
14594
14995
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
14595
14996
|
let best = null;
|
|
14596
14997
|
let hashes;
|
|
14597
14998
|
try {
|
|
14598
|
-
hashes = (0,
|
|
14999
|
+
hashes = (0, import_node_fs38.readdirSync)(CURSOR_SDK_STORE);
|
|
14599
15000
|
} catch {
|
|
14600
15001
|
return null;
|
|
14601
15002
|
}
|
|
14602
15003
|
for (const hash of hashes) {
|
|
14603
|
-
const agentsFile = (0,
|
|
14604
|
-
if (!(0,
|
|
15004
|
+
const agentsFile = (0, import_node_path36.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
15005
|
+
if (!(0, import_node_fs38.existsSync)(agentsFile)) continue;
|
|
14605
15006
|
let text5;
|
|
14606
15007
|
try {
|
|
14607
|
-
text5 = (0,
|
|
15008
|
+
text5 = (0, import_node_fs38.readFileSync)(agentsFile, "utf8");
|
|
14608
15009
|
} catch {
|
|
14609
15010
|
continue;
|
|
14610
15011
|
}
|
|
@@ -14628,7 +15029,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
14628
15029
|
return best?.agentId ?? null;
|
|
14629
15030
|
}
|
|
14630
15031
|
async function adoptThread(input) {
|
|
14631
|
-
if (!(0,
|
|
15032
|
+
if (!(0, import_node_fs38.existsSync)(input.worktreePath)) {
|
|
14632
15033
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
14633
15034
|
}
|
|
14634
15035
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -14655,18 +15056,18 @@ function conductorDbPath() {
|
|
|
14655
15056
|
return CONDUCTOR_DB;
|
|
14656
15057
|
}
|
|
14657
15058
|
function listConductorWorkspaces() {
|
|
14658
|
-
if (!(0,
|
|
15059
|
+
if (!(0, import_node_fs38.existsSync)(CONDUCTOR_DB)) {
|
|
14659
15060
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
14660
15061
|
}
|
|
14661
|
-
const tmp = (0,
|
|
14662
|
-
const snapshot = (0,
|
|
15062
|
+
const tmp = (0, import_node_fs38.mkdtempSync)((0, import_node_path36.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
|
|
15063
|
+
const snapshot = (0, import_node_path36.join)(tmp, "conductor.db");
|
|
14663
15064
|
try {
|
|
14664
|
-
(0,
|
|
15065
|
+
(0, import_node_fs38.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
14665
15066
|
for (const suffix of ["-wal", "-shm"]) {
|
|
14666
15067
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
14667
|
-
if ((0,
|
|
15068
|
+
if ((0, import_node_fs38.existsSync)(src)) {
|
|
14668
15069
|
try {
|
|
14669
|
-
(0,
|
|
15070
|
+
(0, import_node_fs38.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
14670
15071
|
} catch {
|
|
14671
15072
|
}
|
|
14672
15073
|
}
|
|
@@ -14742,22 +15143,22 @@ function listConductorWorkspaces() {
|
|
|
14742
15143
|
db.close();
|
|
14743
15144
|
}
|
|
14744
15145
|
} finally {
|
|
14745
|
-
(0,
|
|
15146
|
+
(0, import_node_fs38.rmSync)(tmp, { recursive: true, force: true });
|
|
14746
15147
|
}
|
|
14747
15148
|
}
|
|
14748
15149
|
function importConductorWorkspace(workspaceId) {
|
|
14749
|
-
if (!(0,
|
|
15150
|
+
if (!(0, import_node_fs38.existsSync)(CONDUCTOR_DB)) {
|
|
14750
15151
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
14751
15152
|
}
|
|
14752
|
-
const tmp = (0,
|
|
14753
|
-
const snapshot = (0,
|
|
15153
|
+
const tmp = (0, import_node_fs38.mkdtempSync)((0, import_node_path36.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
|
|
15154
|
+
const snapshot = (0, import_node_path36.join)(tmp, "conductor.db");
|
|
14754
15155
|
try {
|
|
14755
|
-
(0,
|
|
15156
|
+
(0, import_node_fs38.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
14756
15157
|
for (const suffix of ["-wal", "-shm"]) {
|
|
14757
15158
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
14758
|
-
if ((0,
|
|
15159
|
+
if ((0, import_node_fs38.existsSync)(src)) {
|
|
14759
15160
|
try {
|
|
14760
|
-
(0,
|
|
15161
|
+
(0, import_node_fs38.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
14761
15162
|
} catch {
|
|
14762
15163
|
}
|
|
14763
15164
|
}
|
|
@@ -14775,7 +15176,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
14775
15176
|
).get(workspaceId);
|
|
14776
15177
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
14777
15178
|
const worktreePath = String(row.workspacePath);
|
|
14778
|
-
if (!(0,
|
|
15179
|
+
if (!(0, import_node_fs38.existsSync)(worktreePath)) {
|
|
14779
15180
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
14780
15181
|
}
|
|
14781
15182
|
let sessionId = null;
|
|
@@ -14838,31 +15239,31 @@ function importConductorWorkspace(workspaceId) {
|
|
|
14838
15239
|
db.close();
|
|
14839
15240
|
}
|
|
14840
15241
|
} finally {
|
|
14841
|
-
(0,
|
|
15242
|
+
(0, import_node_fs38.rmSync)(tmp, { recursive: true, force: true });
|
|
14842
15243
|
}
|
|
14843
15244
|
}
|
|
14844
15245
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
14845
15246
|
return importConductorWorkspace(workspaceId);
|
|
14846
15247
|
}
|
|
14847
|
-
var import_node_child_process4,
|
|
15248
|
+
var import_node_child_process4, import_node_fs38, import_node_os10, import_node_path36, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
|
|
14848
15249
|
var init_adopt = __esm({
|
|
14849
15250
|
"src/threads/adopt.ts"() {
|
|
14850
15251
|
"use strict";
|
|
14851
15252
|
import_node_child_process4 = require("child_process");
|
|
14852
|
-
|
|
15253
|
+
import_node_fs38 = require("fs");
|
|
14853
15254
|
import_node_os10 = require("os");
|
|
14854
|
-
|
|
15255
|
+
import_node_path36 = require("path");
|
|
14855
15256
|
import_node_module4 = require("module");
|
|
14856
15257
|
init_worktree();
|
|
14857
15258
|
init_thread_store();
|
|
14858
|
-
CONDUCTOR_APP_SUPPORT = (0,
|
|
15259
|
+
CONDUCTOR_APP_SUPPORT = (0, import_node_path36.join)(
|
|
14859
15260
|
process.env.HOME ?? "",
|
|
14860
15261
|
"Library",
|
|
14861
15262
|
"Application Support",
|
|
14862
15263
|
"com.conductor.app"
|
|
14863
15264
|
);
|
|
14864
|
-
CONDUCTOR_DB = (0,
|
|
14865
|
-
CURSOR_SDK_STORE = (0,
|
|
15265
|
+
CONDUCTOR_DB = (0, import_node_path36.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
15266
|
+
CURSOR_SDK_STORE = (0, import_node_path36.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
14866
15267
|
}
|
|
14867
15268
|
});
|
|
14868
15269
|
|
|
@@ -14929,7 +15330,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
14929
15330
|
let createdWorktree = false;
|
|
14930
15331
|
const trees = await listWorktrees(repoPath);
|
|
14931
15332
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
14932
|
-
if (checkedOut?.path && (0,
|
|
15333
|
+
if (checkedOut?.path && (0, import_node_fs39.existsSync)(checkedOut.path)) {
|
|
14933
15334
|
if (input.reuseExistingWorktree !== false) {
|
|
14934
15335
|
worktreePath = checkedOut.path;
|
|
14935
15336
|
} else {
|
|
@@ -15071,7 +15472,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
15071
15472
|
async function createPrStack(input, onSetupLine) {
|
|
15072
15473
|
await requireAgent(input.agent);
|
|
15073
15474
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
15074
|
-
if (!(0,
|
|
15475
|
+
if (!(0, import_node_fs39.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
15075
15476
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
15076
15477
|
const status = await detectGhStack(repoPath);
|
|
15077
15478
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -15138,7 +15539,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
15138
15539
|
}
|
|
15139
15540
|
}
|
|
15140
15541
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
15141
|
-
if (!claimed.has(bootstrap.worktreePath) && (0,
|
|
15542
|
+
if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs39.existsSync)(bootstrap.worktreePath)) {
|
|
15142
15543
|
try {
|
|
15143
15544
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
15144
15545
|
deleteBranch: bootstrap.branchName
|
|
@@ -15158,11 +15559,11 @@ function stackAgentDefaultsFrom(input) {
|
|
|
15158
15559
|
planMode: input.planMode
|
|
15159
15560
|
};
|
|
15160
15561
|
}
|
|
15161
|
-
var
|
|
15562
|
+
var import_node_fs39;
|
|
15162
15563
|
var init_stack_layers = __esm({
|
|
15163
15564
|
"src/threads/stack-layers.ts"() {
|
|
15164
15565
|
"use strict";
|
|
15165
|
-
|
|
15566
|
+
import_node_fs39 = require("fs");
|
|
15166
15567
|
init_detect();
|
|
15167
15568
|
init_run();
|
|
15168
15569
|
init_stack();
|
|
@@ -15175,7 +15576,7 @@ var init_stack_layers = __esm({
|
|
|
15175
15576
|
|
|
15176
15577
|
// src/diff/diff.ts
|
|
15177
15578
|
async function inspectGitWorktree(worktreePath) {
|
|
15178
|
-
if (!worktreePath || !(0,
|
|
15579
|
+
if (!worktreePath || !(0, import_node_fs40.existsSync)(worktreePath)) return "missing_worktree";
|
|
15179
15580
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
15180
15581
|
reject: false
|
|
15181
15582
|
});
|
|
@@ -15183,7 +15584,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
15183
15584
|
return "ok";
|
|
15184
15585
|
}
|
|
15185
15586
|
async function initializeGitRepository(worktreePath) {
|
|
15186
|
-
if (!worktreePath || !(0,
|
|
15587
|
+
if (!worktreePath || !(0, import_node_fs40.existsSync)(worktreePath)) {
|
|
15187
15588
|
throw new Error("Worktree not found");
|
|
15188
15589
|
}
|
|
15189
15590
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -15317,11 +15718,11 @@ new file mode 100644
|
|
|
15317
15718
|
};
|
|
15318
15719
|
}
|
|
15319
15720
|
async function untrackedPatch(worktreePath, path2, maxHunk) {
|
|
15320
|
-
const abs = (0,
|
|
15721
|
+
const abs = (0, import_node_path37.join)(worktreePath, path2);
|
|
15321
15722
|
try {
|
|
15322
|
-
const st = (0,
|
|
15723
|
+
const st = (0, import_node_fs40.statSync)(abs);
|
|
15323
15724
|
if (st.isFile() && st.size > maxHunk) {
|
|
15324
|
-
const buf = (0,
|
|
15725
|
+
const buf = (0, import_node_fs40.readFileSync)(abs).subarray(0, maxHunk);
|
|
15325
15726
|
return syntheticAddPatch(path2, buf.toString("utf8"), maxHunk);
|
|
15326
15727
|
}
|
|
15327
15728
|
} catch {
|
|
@@ -15805,13 +16206,13 @@ async function listWorktreeFiles(worktreePath, opts) {
|
|
|
15805
16206
|
function isImageRelativePath(relativePath) {
|
|
15806
16207
|
const base = relativePath.split("/").pop()?.toLowerCase() || "";
|
|
15807
16208
|
const ext = base.includes(".") ? base.split(".").pop() || "" : "";
|
|
15808
|
-
return
|
|
16209
|
+
return IMAGE_EXTENSIONS2.has(ext);
|
|
15809
16210
|
}
|
|
15810
16211
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
15811
16212
|
assertSafeRelativePath(relativePath);
|
|
15812
16213
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
15813
|
-
const abs = (0,
|
|
15814
|
-
const st = (0,
|
|
16214
|
+
const abs = (0, import_node_path37.join)(worktreePath, relativePath);
|
|
16215
|
+
const st = (0, import_node_fs40.statSync)(abs);
|
|
15815
16216
|
if (!st.isFile()) {
|
|
15816
16217
|
throw new Error(`Not a file: ${relativePath}`);
|
|
15817
16218
|
}
|
|
@@ -15820,7 +16221,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
15820
16221
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
15821
16222
|
);
|
|
15822
16223
|
}
|
|
15823
|
-
const buf = (0,
|
|
16224
|
+
const buf = (0, import_node_fs40.readFileSync)(abs);
|
|
15824
16225
|
return {
|
|
15825
16226
|
path: relativePath,
|
|
15826
16227
|
contentBase64: buf.toString("base64"),
|
|
@@ -15830,12 +16231,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
15830
16231
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
15831
16232
|
assertSafeRelativePath(relativePath);
|
|
15832
16233
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
15833
|
-
const abs = (0,
|
|
15834
|
-
const st = (0,
|
|
16234
|
+
const abs = (0, import_node_path37.join)(worktreePath, relativePath);
|
|
16235
|
+
const st = (0, import_node_fs40.statSync)(abs);
|
|
15835
16236
|
if (!st.isFile()) {
|
|
15836
16237
|
throw new Error(`Not a file: ${relativePath}`);
|
|
15837
16238
|
}
|
|
15838
|
-
const buf = (0,
|
|
16239
|
+
const buf = (0, import_node_fs40.readFileSync)(abs);
|
|
15839
16240
|
if (isImageRelativePath(relativePath)) {
|
|
15840
16241
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
15841
16242
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -15878,9 +16279,9 @@ function assertSafeRelativePath(relativePath) {
|
|
|
15878
16279
|
}
|
|
15879
16280
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
15880
16281
|
assertSafeRelativePath(relativePath);
|
|
15881
|
-
const abs = (0,
|
|
15882
|
-
(0,
|
|
15883
|
-
(0,
|
|
16282
|
+
const abs = (0, import_node_path37.join)(worktreePath, relativePath);
|
|
16283
|
+
(0, import_node_fs40.mkdirSync)((0, import_node_path37.dirname)(abs), { recursive: true });
|
|
16284
|
+
(0, import_node_fs40.writeFileSync)(abs, content, "utf8");
|
|
15884
16285
|
return { path: relativePath };
|
|
15885
16286
|
}
|
|
15886
16287
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
@@ -15897,18 +16298,18 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
|
15897
16298
|
truncated: full.files.length > maxFiles
|
|
15898
16299
|
};
|
|
15899
16300
|
}
|
|
15900
|
-
var
|
|
16301
|
+
var import_node_fs40, import_node_path37, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
|
|
15901
16302
|
var init_diff = __esm({
|
|
15902
16303
|
"src/diff/diff.ts"() {
|
|
15903
16304
|
"use strict";
|
|
15904
|
-
|
|
15905
|
-
|
|
16305
|
+
import_node_fs40 = require("fs");
|
|
16306
|
+
import_node_path37 = require("path");
|
|
15906
16307
|
init_run();
|
|
15907
16308
|
init_worktree();
|
|
15908
16309
|
mergeBaseCache = /* @__PURE__ */ new Map();
|
|
15909
16310
|
MERGE_BASE_TTL_MS = 45e3;
|
|
15910
16311
|
SHA_RE = /^[0-9a-f]{7,40}$/i;
|
|
15911
|
-
|
|
16312
|
+
IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
15912
16313
|
"png",
|
|
15913
16314
|
"jpg",
|
|
15914
16315
|
"jpeg",
|
|
@@ -16070,7 +16471,7 @@ function parseFrontmatter(content) {
|
|
|
16070
16471
|
}
|
|
16071
16472
|
function readSkill(skillMd, source) {
|
|
16072
16473
|
try {
|
|
16073
|
-
const content = (0,
|
|
16474
|
+
const content = (0, import_node_fs41.readFileSync)(skillMd, "utf8");
|
|
16074
16475
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
16075
16476
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
16076
16477
|
const name = fmName || dirName;
|
|
@@ -16089,19 +16490,19 @@ function readSkill(skillMd, source) {
|
|
|
16089
16490
|
}
|
|
16090
16491
|
}
|
|
16091
16492
|
function scanSkillsDir(dir, source, out) {
|
|
16092
|
-
if (!(0,
|
|
16493
|
+
if (!(0, import_node_fs41.existsSync)(dir)) return;
|
|
16093
16494
|
let entries;
|
|
16094
16495
|
try {
|
|
16095
|
-
entries = (0,
|
|
16496
|
+
entries = (0, import_node_fs41.readdirSync)(dir);
|
|
16096
16497
|
} catch {
|
|
16097
16498
|
return;
|
|
16098
16499
|
}
|
|
16099
16500
|
for (const entry of entries) {
|
|
16100
16501
|
if (entry.startsWith(".")) continue;
|
|
16101
|
-
const skillMd = (0,
|
|
16102
|
-
if (!(0,
|
|
16502
|
+
const skillMd = (0, import_node_path38.join)(dir, entry, "SKILL.md");
|
|
16503
|
+
if (!(0, import_node_fs41.existsSync)(skillMd)) continue;
|
|
16103
16504
|
try {
|
|
16104
|
-
if (!(0,
|
|
16505
|
+
if (!(0, import_node_fs41.statSync)(skillMd).isFile()) continue;
|
|
16105
16506
|
} catch {
|
|
16106
16507
|
continue;
|
|
16107
16508
|
}
|
|
@@ -16110,24 +16511,24 @@ function scanSkillsDir(dir, source, out) {
|
|
|
16110
16511
|
}
|
|
16111
16512
|
}
|
|
16112
16513
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
16113
|
-
if (!(0,
|
|
16514
|
+
if (!(0, import_node_fs41.existsSync)(pluginsRoot)) return;
|
|
16114
16515
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
16115
16516
|
if (depth > 7) return;
|
|
16116
16517
|
let entries;
|
|
16117
16518
|
try {
|
|
16118
|
-
entries = (0,
|
|
16519
|
+
entries = (0, import_node_fs41.readdirSync)(dir);
|
|
16119
16520
|
} catch {
|
|
16120
16521
|
return;
|
|
16121
16522
|
}
|
|
16122
16523
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
16123
|
-
const skill = readSkill((0,
|
|
16524
|
+
const skill = readSkill((0, import_node_path38.join)(dir, "SKILL.md"), "cli");
|
|
16124
16525
|
if (skill) out.push(skill);
|
|
16125
16526
|
}
|
|
16126
16527
|
for (const entry of entries) {
|
|
16127
16528
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
16128
|
-
const full = (0,
|
|
16529
|
+
const full = (0, import_node_path38.join)(dir, entry);
|
|
16129
16530
|
try {
|
|
16130
|
-
if (!(0,
|
|
16531
|
+
if (!(0, import_node_fs41.statSync)(full).isDirectory()) continue;
|
|
16131
16532
|
} catch {
|
|
16132
16533
|
continue;
|
|
16133
16534
|
}
|
|
@@ -16145,17 +16546,17 @@ function discoverSkills(worktreePath) {
|
|
|
16145
16546
|
const home = (0, import_node_os11.homedir)();
|
|
16146
16547
|
const collected = [];
|
|
16147
16548
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
16148
|
-
scanSkillsDir((0,
|
|
16549
|
+
scanSkillsDir((0, import_node_path38.join)(worktreePath, rel), "workspace", collected);
|
|
16149
16550
|
}
|
|
16150
16551
|
for (const abs of [
|
|
16151
|
-
(0,
|
|
16152
|
-
(0,
|
|
16153
|
-
(0,
|
|
16154
|
-
(0,
|
|
16552
|
+
(0, import_node_path38.join)(home, ".claude/skills"),
|
|
16553
|
+
(0, import_node_path38.join)(home, ".cursor/skills"),
|
|
16554
|
+
(0, import_node_path38.join)(home, ".sideboard/skills"),
|
|
16555
|
+
(0, import_node_path38.join)(home, ".brightsy/skills")
|
|
16155
16556
|
]) {
|
|
16156
16557
|
scanSkillsDir(abs, "user", collected);
|
|
16157
16558
|
}
|
|
16158
|
-
scanClaudePluginSkills((0,
|
|
16559
|
+
scanClaudePluginSkills((0, import_node_path38.join)(home, ".claude/plugins"), collected);
|
|
16159
16560
|
const rank = { workspace: 0, user: 1, cli: 2 };
|
|
16160
16561
|
const byCommand = /* @__PURE__ */ new Map();
|
|
16161
16562
|
for (const skill of collected) {
|
|
@@ -16167,7 +16568,7 @@ function discoverSkills(worktreePath) {
|
|
|
16167
16568
|
return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
|
|
16168
16569
|
}
|
|
16169
16570
|
function readSkillBody(skillPath, maxChars = 12e3) {
|
|
16170
|
-
const raw = (0,
|
|
16571
|
+
const raw = (0, import_node_fs41.readFileSync)(skillPath, "utf8");
|
|
16171
16572
|
if (raw.startsWith("---")) {
|
|
16172
16573
|
const end = raw.indexOf("\n---", 3);
|
|
16173
16574
|
if (end >= 0) {
|
|
@@ -16181,13 +16582,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
|
|
|
16181
16582
|
|
|
16182
16583
|
\u2026(truncated)` : raw;
|
|
16183
16584
|
}
|
|
16184
|
-
var
|
|
16585
|
+
var import_node_fs41, import_node_os11, import_node_path38;
|
|
16185
16586
|
var init_discover = __esm({
|
|
16186
16587
|
"src/skills/discover.ts"() {
|
|
16187
16588
|
"use strict";
|
|
16188
|
-
|
|
16589
|
+
import_node_fs41 = require("fs");
|
|
16189
16590
|
import_node_os11 = require("os");
|
|
16190
|
-
|
|
16591
|
+
import_node_path38 = require("path");
|
|
16191
16592
|
}
|
|
16192
16593
|
});
|
|
16193
16594
|
|
|
@@ -16276,236 +16677,6 @@ var init_expand = __esm({
|
|
|
16276
16677
|
}
|
|
16277
16678
|
});
|
|
16278
16679
|
|
|
16279
|
-
// src/composer/stage-files.ts
|
|
16280
|
-
function fileExtension(filePath) {
|
|
16281
|
-
const base = (0, import_node_path38.basename)(filePath).toLowerCase();
|
|
16282
|
-
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
16283
|
-
}
|
|
16284
|
-
function isImageFilePath(filePath) {
|
|
16285
|
-
return IMAGE_EXTENSIONS2.has(fileExtension(filePath));
|
|
16286
|
-
}
|
|
16287
|
-
function imageMimeType(filePath) {
|
|
16288
|
-
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
16289
|
-
}
|
|
16290
|
-
function ensureAttachmentsDir(worktreePath) {
|
|
16291
|
-
const dir = (0, import_node_path38.join)(worktreePath, ATTACHMENTS_DIR);
|
|
16292
|
-
(0, import_node_fs41.mkdirSync)(dir, { recursive: true });
|
|
16293
|
-
const gi = (0, import_node_path38.join)(dir, ".gitignore");
|
|
16294
|
-
if (!(0, import_node_fs41.existsSync)(gi)) {
|
|
16295
|
-
(0, import_node_fs41.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
16296
|
-
}
|
|
16297
|
-
return dir;
|
|
16298
|
-
}
|
|
16299
|
-
function uniqueAttachmentName(dir, originalName) {
|
|
16300
|
-
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
16301
|
-
if (!(0, import_node_fs41.existsSync)((0, import_node_path38.join)(dir, safe))) return safe;
|
|
16302
|
-
const ext = (0, import_node_path38.extname)(safe);
|
|
16303
|
-
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
16304
|
-
for (let i = 1; i < 1e4; i++) {
|
|
16305
|
-
const candidate = `${stem}-${i}${ext}`;
|
|
16306
|
-
if (!(0, import_node_fs41.existsSync)((0, import_node_path38.join)(dir, candidate))) return candidate;
|
|
16307
|
-
}
|
|
16308
|
-
return `${stem}-${(0, import_node_crypto8.randomUUID)()}${ext}`;
|
|
16309
|
-
}
|
|
16310
|
-
function previewDataUrlFromBuf(filePath, buf) {
|
|
16311
|
-
if (!isImageFilePath(filePath)) return void 0;
|
|
16312
|
-
if (buf.length > MAX_PREVIEW_BYTES) return void 0;
|
|
16313
|
-
return `data:${imageMimeType(filePath)};base64,${buf.toString("base64")}`;
|
|
16314
|
-
}
|
|
16315
|
-
function attachmentFromBuffer(name, buf, opts) {
|
|
16316
|
-
const previewDataUrl = previewDataUrlFromBuf(name, buf);
|
|
16317
|
-
if (isImageFilePath(name)) {
|
|
16318
|
-
const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
|
|
16319
|
-
return {
|
|
16320
|
-
id: (0, import_node_crypto8.randomUUID)(),
|
|
16321
|
-
name,
|
|
16322
|
-
kind: "file",
|
|
16323
|
-
path: opts.path,
|
|
16324
|
-
previewDataUrl,
|
|
16325
|
-
content: [
|
|
16326
|
-
`Image attached: ${pathHint}`,
|
|
16327
|
-
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."
|
|
16328
|
-
].join("\n")
|
|
16329
|
-
};
|
|
16330
|
-
}
|
|
16331
|
-
if (buf.length > MAX_INLINE_BYTES) {
|
|
16332
|
-
return {
|
|
16333
|
-
id: (0, import_node_crypto8.randomUUID)(),
|
|
16334
|
-
name,
|
|
16335
|
-
kind: "file",
|
|
16336
|
-
path: opts.path,
|
|
16337
|
-
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)`
|
|
16338
|
-
};
|
|
16339
|
-
}
|
|
16340
|
-
if (buf.includes(0)) {
|
|
16341
|
-
return {
|
|
16342
|
-
id: (0, import_node_crypto8.randomUUID)(),
|
|
16343
|
-
name,
|
|
16344
|
-
kind: "file",
|
|
16345
|
-
path: opts.path,
|
|
16346
|
-
content: opts.path ? `(binary file at \`${opts.path}\` \u2014 use tools to inspect)` : `(binary file attached by path only: ${opts.sourceLabel || name})`
|
|
16347
|
-
};
|
|
16348
|
-
}
|
|
16349
|
-
return {
|
|
16350
|
-
id: (0, import_node_crypto8.randomUUID)(),
|
|
16351
|
-
name,
|
|
16352
|
-
kind: "file",
|
|
16353
|
-
path: opts.path,
|
|
16354
|
-
content: buf.toString("utf8")
|
|
16355
|
-
};
|
|
16356
|
-
}
|
|
16357
|
-
function attachmentFromAbsolutePath(absolutePath) {
|
|
16358
|
-
const name = (0, import_node_path38.basename)(absolutePath);
|
|
16359
|
-
try {
|
|
16360
|
-
const st = (0, import_node_fs41.statSync)(absolutePath);
|
|
16361
|
-
if (!st.isFile()) {
|
|
16362
|
-
return {
|
|
16363
|
-
id: (0, import_node_crypto8.randomUUID)(),
|
|
16364
|
-
name,
|
|
16365
|
-
kind: "file",
|
|
16366
|
-
content: `(not a file: ${absolutePath})`
|
|
16367
|
-
};
|
|
16368
|
-
}
|
|
16369
|
-
const buf = (0, import_node_fs41.readFileSync)(absolutePath);
|
|
16370
|
-
return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
|
|
16371
|
-
} catch (err) {
|
|
16372
|
-
return {
|
|
16373
|
-
id: (0, import_node_crypto8.randomUUID)(),
|
|
16374
|
-
name,
|
|
16375
|
-
kind: "file",
|
|
16376
|
-
content: `(could not read ${absolutePath}: ${err instanceof Error ? err.message : String(err)})`
|
|
16377
|
-
};
|
|
16378
|
-
}
|
|
16379
|
-
}
|
|
16380
|
-
function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
16381
|
-
if (absolutePaths.length === 0) return [];
|
|
16382
|
-
const dir = ensureAttachmentsDir(worktreePath);
|
|
16383
|
-
const out = [];
|
|
16384
|
-
for (const abs of absolutePaths) {
|
|
16385
|
-
const originalName = (0, import_node_path38.basename)(abs);
|
|
16386
|
-
try {
|
|
16387
|
-
const st = (0, import_node_fs41.statSync)(abs);
|
|
16388
|
-
if (!st.isFile()) continue;
|
|
16389
|
-
const name = uniqueAttachmentName(dir, originalName);
|
|
16390
|
-
const destAbs = (0, import_node_path38.join)(dir, name);
|
|
16391
|
-
(0, import_node_fs41.copyFileSync)(abs, destAbs);
|
|
16392
|
-
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
16393
|
-
const buf = (0, import_node_fs41.readFileSync)(destAbs);
|
|
16394
|
-
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
16395
|
-
} catch (err) {
|
|
16396
|
-
out.push({
|
|
16397
|
-
id: (0, import_node_crypto8.randomUUID)(),
|
|
16398
|
-
name: originalName,
|
|
16399
|
-
kind: "file",
|
|
16400
|
-
content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
|
|
16401
|
-
});
|
|
16402
|
-
}
|
|
16403
|
-
}
|
|
16404
|
-
return out;
|
|
16405
|
-
}
|
|
16406
|
-
function stageBuffersAsAttachments(worktreePath, buffers2) {
|
|
16407
|
-
if (buffers2.length === 0) return [];
|
|
16408
|
-
const dir = ensureAttachmentsDir(worktreePath);
|
|
16409
|
-
const out = [];
|
|
16410
|
-
for (const item of buffers2) {
|
|
16411
|
-
const originalName = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
16412
|
-
try {
|
|
16413
|
-
const buf = Buffer.from(item.dataBase64, "base64");
|
|
16414
|
-
const name = uniqueAttachmentName(dir, originalName);
|
|
16415
|
-
const destAbs = (0, import_node_path38.join)(dir, name);
|
|
16416
|
-
(0, import_node_fs41.writeFileSync)(destAbs, buf);
|
|
16417
|
-
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
16418
|
-
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
16419
|
-
} catch (err) {
|
|
16420
|
-
out.push({
|
|
16421
|
-
id: (0, import_node_crypto8.randomUUID)(),
|
|
16422
|
-
name: originalName,
|
|
16423
|
-
kind: "file",
|
|
16424
|
-
content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
|
|
16425
|
-
});
|
|
16426
|
-
}
|
|
16427
|
-
}
|
|
16428
|
-
return out;
|
|
16429
|
-
}
|
|
16430
|
-
function attachmentsFromBuffers(buffers2) {
|
|
16431
|
-
return buffers2.map((item) => {
|
|
16432
|
-
const name = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
16433
|
-
try {
|
|
16434
|
-
const buf = Buffer.from(item.dataBase64, "base64");
|
|
16435
|
-
return attachmentFromBuffer(name, buf, { sourceLabel: name });
|
|
16436
|
-
} catch (err) {
|
|
16437
|
-
return {
|
|
16438
|
-
id: (0, import_node_crypto8.randomUUID)(),
|
|
16439
|
-
name,
|
|
16440
|
-
kind: "file",
|
|
16441
|
-
content: `(could not attach ${name}: ${err instanceof Error ? err.message : String(err)})`
|
|
16442
|
-
};
|
|
16443
|
-
}
|
|
16444
|
-
});
|
|
16445
|
-
}
|
|
16446
|
-
function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
16447
|
-
const out = [];
|
|
16448
|
-
for (const rel of relativePaths) {
|
|
16449
|
-
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
16450
|
-
out.push({
|
|
16451
|
-
id: (0, import_node_crypto8.randomUUID)(),
|
|
16452
|
-
name: (0, import_node_path38.basename)(rel) || "file",
|
|
16453
|
-
kind: "file",
|
|
16454
|
-
content: `(invalid path: ${rel})`
|
|
16455
|
-
});
|
|
16456
|
-
continue;
|
|
16457
|
-
}
|
|
16458
|
-
const name = (0, import_node_path38.basename)(rel);
|
|
16459
|
-
try {
|
|
16460
|
-
const abs = (0, import_node_path38.join)(worktreePath, rel);
|
|
16461
|
-
const st = (0, import_node_fs41.statSync)(abs);
|
|
16462
|
-
if (!st.isFile()) continue;
|
|
16463
|
-
const buf = (0, import_node_fs41.readFileSync)(abs);
|
|
16464
|
-
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
16465
|
-
} catch (err) {
|
|
16466
|
-
out.push({
|
|
16467
|
-
id: (0, import_node_crypto8.randomUUID)(),
|
|
16468
|
-
name,
|
|
16469
|
-
kind: "file",
|
|
16470
|
-
content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
|
|
16471
|
-
});
|
|
16472
|
-
}
|
|
16473
|
-
}
|
|
16474
|
-
return out;
|
|
16475
|
-
}
|
|
16476
|
-
var import_node_fs41, import_node_path38, import_node_crypto8, IMAGE_EXTENSIONS2, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES;
|
|
16477
|
-
var init_stage_files = __esm({
|
|
16478
|
-
"src/composer/stage-files.ts"() {
|
|
16479
|
-
"use strict";
|
|
16480
|
-
import_node_fs41 = require("fs");
|
|
16481
|
-
import_node_path38 = require("path");
|
|
16482
|
-
import_node_crypto8 = require("crypto");
|
|
16483
|
-
init_workspace_scratch();
|
|
16484
|
-
IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
16485
|
-
"png",
|
|
16486
|
-
"jpg",
|
|
16487
|
-
"jpeg",
|
|
16488
|
-
"gif",
|
|
16489
|
-
"webp",
|
|
16490
|
-
"svg",
|
|
16491
|
-
"bmp",
|
|
16492
|
-
"ico"
|
|
16493
|
-
]);
|
|
16494
|
-
IMAGE_MIME_BY_EXT = {
|
|
16495
|
-
png: "image/png",
|
|
16496
|
-
jpg: "image/jpeg",
|
|
16497
|
-
jpeg: "image/jpeg",
|
|
16498
|
-
gif: "image/gif",
|
|
16499
|
-
webp: "image/webp",
|
|
16500
|
-
svg: "image/svg+xml",
|
|
16501
|
-
bmp: "image/bmp",
|
|
16502
|
-
ico: "image/x-icon"
|
|
16503
|
-
};
|
|
16504
|
-
MAX_INLINE_BYTES = 4e5;
|
|
16505
|
-
MAX_PREVIEW_BYTES = 5e6;
|
|
16506
|
-
}
|
|
16507
|
-
});
|
|
16508
|
-
|
|
16509
16680
|
// src/agents/instructions.ts
|
|
16510
16681
|
function normPath3(p) {
|
|
16511
16682
|
return p.replace(/\/+$/, "");
|
|
@@ -17108,6 +17279,7 @@ var init_orchestrator = __esm({
|
|
|
17108
17279
|
init_usage();
|
|
17109
17280
|
init_thread_store();
|
|
17110
17281
|
init_desktop_host();
|
|
17282
|
+
init_child_halt();
|
|
17111
17283
|
init_create();
|
|
17112
17284
|
init_cowboy();
|
|
17113
17285
|
init_orchestrator_capable();
|
|
@@ -17255,6 +17427,9 @@ var init_orchestrator = __esm({
|
|
|
17255
17427
|
* MCP-created review threads don't stay `queued` after the MCP child exits.
|
|
17256
17428
|
*/
|
|
17257
17429
|
adoptPersistedQueues() {
|
|
17430
|
+
if (thisProcessShouldDrainAgentQueues()) {
|
|
17431
|
+
this.healStaleRunningTurns();
|
|
17432
|
+
}
|
|
17258
17433
|
for (const thread of listThreads()) {
|
|
17259
17434
|
if (thread.status === "stopped" || thread.status === "archived") continue;
|
|
17260
17435
|
const pid = thread.agentPid;
|
|
@@ -17275,6 +17450,32 @@ var init_orchestrator = __esm({
|
|
|
17275
17450
|
}
|
|
17276
17451
|
}
|
|
17277
17452
|
}
|
|
17453
|
+
/**
|
|
17454
|
+
* Mid-session: a worktree can sit at `running` after the agent process dies
|
|
17455
|
+
* (Cursor/CLI crash, OOM) while wait_for_turn still reports stillRunning.
|
|
17456
|
+
* Reclaim those and wake the parent orchestration chat.
|
|
17457
|
+
*/
|
|
17458
|
+
healStaleRunningTurns() {
|
|
17459
|
+
for (const thread of listThreads()) {
|
|
17460
|
+
if (thread.status === "archived") continue;
|
|
17461
|
+
const handle = this.activeTurns.get(thread.id);
|
|
17462
|
+
if (handle) {
|
|
17463
|
+
const pid = thread.agentPid;
|
|
17464
|
+
if (typeof pid === "number" && pid > 0 && !isPidAlive(pid)) {
|
|
17465
|
+
handle.kill();
|
|
17466
|
+
}
|
|
17467
|
+
continue;
|
|
17468
|
+
}
|
|
17469
|
+
if (!this.shouldReclaimRunningThread(thread)) continue;
|
|
17470
|
+
setStatus(thread.id, "stopped", "Process died (agent exited)");
|
|
17471
|
+
this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
|
|
17472
|
+
this.emit({ type: "turn_finished", threadId: thread.id, exitCode: 1 });
|
|
17473
|
+
const latest = readThread(thread.id);
|
|
17474
|
+
if (latest) {
|
|
17475
|
+
notifyParentOfChildHalt(latest, "stopped", (id, prompt) => this.send(id, prompt));
|
|
17476
|
+
}
|
|
17477
|
+
}
|
|
17478
|
+
}
|
|
17278
17479
|
clearQuotaResumeTimer(threadId) {
|
|
17279
17480
|
const timer = this.quotaResumeTimers.get(threadId);
|
|
17280
17481
|
if (timer) clearTimeout(timer);
|
|
@@ -17992,6 +18193,12 @@ var init_orchestrator = __esm({
|
|
|
17992
18193
|
assistantText: chatText,
|
|
17993
18194
|
partsCount: parts.length
|
|
17994
18195
|
});
|
|
18196
|
+
if (!this.crashContinued.has(threadId)) {
|
|
18197
|
+
const failed = readThread(threadId);
|
|
18198
|
+
if (failed) {
|
|
18199
|
+
notifyParentOfChildHalt(failed, "error", (id, prompt2) => this.send(id, prompt2));
|
|
18200
|
+
}
|
|
18201
|
+
}
|
|
17995
18202
|
}
|
|
17996
18203
|
}
|
|
17997
18204
|
} catch (err) {
|
|
@@ -18016,6 +18223,12 @@ var init_orchestrator = __esm({
|
|
|
18016
18223
|
assistantText: "",
|
|
18017
18224
|
partsCount: 0
|
|
18018
18225
|
});
|
|
18226
|
+
if (!this.crashContinued.has(threadId)) {
|
|
18227
|
+
const failed = readThread(threadId);
|
|
18228
|
+
if (failed) {
|
|
18229
|
+
notifyParentOfChildHalt(failed, "error", (id, prompt2) => this.send(id, prompt2));
|
|
18230
|
+
}
|
|
18231
|
+
}
|
|
18019
18232
|
}
|
|
18020
18233
|
} finally {
|
|
18021
18234
|
this.startingTurns.delete(threadId);
|
|
@@ -18071,6 +18284,9 @@ var init_orchestrator = __esm({
|
|
|
18071
18284
|
const stopped = writeLiveStatus(thread.id, "stopped") ?? readThread(thread.id) ?? thread;
|
|
18072
18285
|
if (stopped.status === "stopped") {
|
|
18073
18286
|
this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
|
|
18287
|
+
if (opts?.notifyParent !== false) {
|
|
18288
|
+
notifyParentOfChildHalt(stopped, "stopped", (id, prompt) => this.send(id, prompt));
|
|
18289
|
+
}
|
|
18074
18290
|
}
|
|
18075
18291
|
return stopped;
|
|
18076
18292
|
}
|
|
@@ -18315,21 +18531,25 @@ var init_orchestrator = __esm({
|
|
|
18315
18531
|
fn();
|
|
18316
18532
|
};
|
|
18317
18533
|
const off = this.on((event) => {
|
|
18318
|
-
if (
|
|
18534
|
+
if (!("threadId" in event) || event.threadId !== thread.id) return;
|
|
18535
|
+
if (event.type === "turn_finished" || event.type === "error") {
|
|
18319
18536
|
const latest = readThread(thread.id);
|
|
18320
18537
|
if (!latest) {
|
|
18321
18538
|
finish(() => reject(new Error(`Thread not found: ${thread.id}`)));
|
|
18322
18539
|
return;
|
|
18323
18540
|
}
|
|
18324
18541
|
finish(() => resolve(latest));
|
|
18542
|
+
return;
|
|
18325
18543
|
}
|
|
18326
|
-
if (event.type === "
|
|
18544
|
+
if (event.type === "status_changed") {
|
|
18327
18545
|
const latest = readThread(thread.id);
|
|
18328
18546
|
if (!latest) {
|
|
18329
18547
|
finish(() => reject(new Error(`Thread not found: ${thread.id}`)));
|
|
18330
18548
|
return;
|
|
18331
18549
|
}
|
|
18332
|
-
|
|
18550
|
+
if (!["running", "queued"].includes(latest.status)) {
|
|
18551
|
+
finish(() => resolve(latest));
|
|
18552
|
+
}
|
|
18333
18553
|
}
|
|
18334
18554
|
});
|
|
18335
18555
|
timer = setInterval(() => {
|
|
@@ -18364,7 +18584,7 @@ var init_orchestrator = __esm({
|
|
|
18364
18584
|
const thread = this.requireThread(threadRef);
|
|
18365
18585
|
const lastAgent = [...thread.messages].reverse().find((m) => m.role === "agent");
|
|
18366
18586
|
const lastError = thread.lastError ?? null;
|
|
18367
|
-
const text5 = (lastAgent?.text ?? "").trim() || (thread.status === "error" ? lastError ?? "" : "");
|
|
18587
|
+
const text5 = (lastAgent?.text ?? "").trim() || (thread.status === "error" || thread.status === "stopped" || thread.status === "broken" ? lastError ?? "" : "");
|
|
18368
18588
|
const stillRunning = thread.status === "running" || thread.status === "queued";
|
|
18369
18589
|
const live = stillRunning ? readTurnLive(thread.id) : null;
|
|
18370
18590
|
const queuedHint = thread.status === "queued" && !live?.summary ? "Queued \u2014 waiting for a concurrency slot" : null;
|
|
@@ -19142,6 +19362,7 @@ __export(index_exports, {
|
|
|
19142
19362
|
PLAN_FILE_NAME: () => PLAN_FILE_NAME,
|
|
19143
19363
|
PLAN_FILE_REL: () => PLAN_FILE_REL,
|
|
19144
19364
|
PLAN_MODE_INSTRUCTION: () => PLAN_MODE_INSTRUCTION,
|
|
19365
|
+
PLAN_QUESTION_ANSWERS_PREFIX: () => PLAN_QUESTION_ANSWERS_PREFIX,
|
|
19145
19366
|
REPO_REVIEW_NAME: () => REPO_REVIEW_NAME,
|
|
19146
19367
|
REPO_REVIEW_PATH: () => REPO_REVIEW_PATH,
|
|
19147
19368
|
REVIEW_REQUEST_NAME: () => REVIEW_REQUEST_NAME,
|
|
@@ -19415,6 +19636,7 @@ __export(index_exports, {
|
|
|
19415
19636
|
inspectGitWorktree: () => inspectGitWorktree,
|
|
19416
19637
|
installAgent: () => installAgent,
|
|
19417
19638
|
interruptSlackCoordinatorForInbound: () => interruptSlackCoordinatorForInbound,
|
|
19639
|
+
invalidateThreadListCache: () => invalidateThreadListCache,
|
|
19418
19640
|
isAbleTimeConnected: () => isAbleTimeConnected,
|
|
19419
19641
|
isAskUserToolName: () => isAskUserToolName,
|
|
19420
19642
|
isBrightsyConnected: () => isBrightsyConnected,
|
|
@@ -19440,6 +19662,7 @@ __export(index_exports, {
|
|
|
19440
19662
|
isOrchestratorThread: () => isOrchestratorThread,
|
|
19441
19663
|
isPidAlive: () => isPidAlive,
|
|
19442
19664
|
isPlaceholderBranch: () => isPlaceholderBranch,
|
|
19665
|
+
isPlanQuestionAnswersMessage: () => isPlanQuestionAnswersMessage,
|
|
19443
19666
|
isPollWrapperToolName: () => isPollWrapperToolName,
|
|
19444
19667
|
isPrNotMergeableError: () => isPrNotMergeableError,
|
|
19445
19668
|
isPresentPlanToolName: () => isPresentPlanToolName,
|
|
@@ -19550,6 +19773,7 @@ __export(index_exports, {
|
|
|
19550
19773
|
pastedTextStats: () => pastedTextStats,
|
|
19551
19774
|
pendingSlackExternalReplies: () => pendingSlackExternalReplies,
|
|
19552
19775
|
permissionMode: () => permissionMode,
|
|
19776
|
+
persistPendingFileAttachments: () => persistPendingFileAttachments,
|
|
19553
19777
|
persistVaultKeyInKeychain: () => persistVaultKeyInKeychain,
|
|
19554
19778
|
planFileAbs: () => planFileAbs,
|
|
19555
19779
|
planQuestionsSignature: () => planQuestionsSignature,
|
|
@@ -19719,6 +19943,7 @@ __export(index_exports, {
|
|
|
19719
19943
|
userCursorMcpConfigPath: () => userCursorMcpConfigPath,
|
|
19720
19944
|
validateLinearApiKey: () => validateLinearApiKey,
|
|
19721
19945
|
verifyAbleTimeConnection: () => verifyAbleTimeConnection,
|
|
19946
|
+
visibleToolRowDetail: () => visibleToolRowDetail,
|
|
19722
19947
|
waitForPidExit: () => waitForPidExit,
|
|
19723
19948
|
warmGithubAgentAuth: () => warmGithubAgentAuth,
|
|
19724
19949
|
withAgentInstructions: () => withAgentInstructions,
|
|
@@ -20744,8 +20969,12 @@ function latestPendingPlanQuestions(input) {
|
|
|
20744
20969
|
if (last?.role === "agent") return extractPendingPlanQuestions(last.parts);
|
|
20745
20970
|
return null;
|
|
20746
20971
|
}
|
|
20972
|
+
var PLAN_QUESTION_ANSWERS_PREFIX = "Answers to your questions:";
|
|
20973
|
+
function isPlanQuestionAnswersMessage(text5) {
|
|
20974
|
+
return text5.startsWith(PLAN_QUESTION_ANSWERS_PREFIX);
|
|
20975
|
+
}
|
|
20747
20976
|
function formatPlanQuestionAnswers(questions, answers) {
|
|
20748
|
-
const lines = [
|
|
20977
|
+
const lines = [PLAN_QUESTION_ANSWERS_PREFIX, ""];
|
|
20749
20978
|
for (let i = 0; i < questions.length; i++) {
|
|
20750
20979
|
const q = questions[i];
|
|
20751
20980
|
const a = answers.find((x) => x.questionIndex === i);
|
|
@@ -20754,7 +20983,7 @@ function formatPlanQuestionAnswers(questions, answers) {
|
|
|
20754
20983
|
if (a?.selected.length) parts.push(a.selected.join(", "));
|
|
20755
20984
|
if (a?.other?.trim()) parts.push(a.other.trim());
|
|
20756
20985
|
const body = parts.length ? parts.join(" \xB7 ") : "(no answer)";
|
|
20757
|
-
lines.push(`${i + 1}. ${header}${q.question}`);
|
|
20986
|
+
lines.push(`${i + 1}. ${header}${q.question} `);
|
|
20758
20987
|
lines.push(` \u2192 ${body}`);
|
|
20759
20988
|
}
|
|
20760
20989
|
return lines.join("\n");
|
|
@@ -20822,6 +21051,15 @@ var MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u201
|
|
|
20822
21051
|
function mcpWaitStillRunningHint(status) {
|
|
20823
21052
|
return status === "queued" ? MCP_WAIT_QUEUED_HINT : MCP_WAIT_STILL_RUNNING_HINT;
|
|
20824
21053
|
}
|
|
21054
|
+
var MCP_WAIT_STOPPED_HINT = "Child was stopped before the turn finished. Do not treat this as success. send_to_thread to resume, or tell the user.";
|
|
21055
|
+
var MCP_WAIT_BROKEN_HINT = "Child worktree is broken (missing on disk). Tell the user \u2014 do not treat this as success.";
|
|
21056
|
+
var MCP_WAIT_ERROR_HINT = "Child turn failed. lastError/text is the failure \u2014 switch agent, tell the user, or retry. Do not treat empty text as success.";
|
|
21057
|
+
function mcpWaitFinishedHint(status) {
|
|
21058
|
+
if (status === "stopped") return MCP_WAIT_STOPPED_HINT;
|
|
21059
|
+
if (status === "broken") return MCP_WAIT_BROKEN_HINT;
|
|
21060
|
+
if (status === "error") return MCP_WAIT_ERROR_HINT;
|
|
21061
|
+
return void 0;
|
|
21062
|
+
}
|
|
20825
21063
|
|
|
20826
21064
|
// src/mcp/server.ts
|
|
20827
21065
|
init_turn_live();
|
|
@@ -22600,7 +22838,7 @@ async function startMcpServer() {
|
|
|
22600
22838
|
);
|
|
22601
22839
|
server.tool(
|
|
22602
22840
|
"wait_for_turn",
|
|
22603
|
-
"Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not send a check-in prompt, force_stop, or assume a hang. On status error, lastError/text is the failure. When finished, usage is the last agent turn\u2019s tokens + costUsd (when the provider reported cost).",
|
|
22841
|
+
"Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not send a check-in prompt, force_stop, or assume a hang. On status error, lastError/text is the failure. On status stopped or broken, the child did not finish \u2014 resume with send_to_thread or tell the user; do not treat that as success. When finished, usage is the last agent turn\u2019s tokens + costUsd (when the provider reported cost).",
|
|
22604
22842
|
{
|
|
22605
22843
|
ref: import_zod5.z.string(),
|
|
22606
22844
|
timeoutMs: import_zod5.z.number().optional()
|
|
@@ -22622,7 +22860,8 @@ async function startMcpServer() {
|
|
|
22622
22860
|
stillRunning: result.stillRunning,
|
|
22623
22861
|
progress: result.progress,
|
|
22624
22862
|
lastActivityAt: result.lastActivityAt,
|
|
22625
|
-
hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) :
|
|
22863
|
+
hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) : mcpWaitFinishedHint(result.status),
|
|
22864
|
+
incomplete: !result.stillRunning && Boolean(mcpWaitFinishedHint(result.status))
|
|
22626
22865
|
})
|
|
22627
22866
|
}
|
|
22628
22867
|
]
|
|
@@ -22641,7 +22880,8 @@ async function startMcpServer() {
|
|
|
22641
22880
|
type: "text",
|
|
22642
22881
|
text: JSON.stringify({
|
|
22643
22882
|
...result,
|
|
22644
|
-
hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) :
|
|
22883
|
+
hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) : mcpWaitFinishedHint(result.status),
|
|
22884
|
+
incomplete: !result.stillRunning && Boolean(mcpWaitFinishedHint(result.status))
|
|
22645
22885
|
})
|
|
22646
22886
|
}
|
|
22647
22887
|
]
|
|
@@ -22665,7 +22905,7 @@ async function startMcpServer() {
|
|
|
22665
22905
|
}
|
|
22666
22906
|
const clearQueue = force !== false;
|
|
22667
22907
|
const hadQueued = t.queue.length > 0;
|
|
22668
|
-
const stopped = orch.stop(ref, { clearQueue });
|
|
22908
|
+
const stopped = orch.stop(ref, { clearQueue, notifyParent: false });
|
|
22669
22909
|
return {
|
|
22670
22910
|
content: [
|
|
22671
22911
|
{
|
|
@@ -25600,6 +25840,7 @@ init_outbound_watch();
|
|
|
25600
25840
|
PLAN_FILE_NAME,
|
|
25601
25841
|
PLAN_FILE_REL,
|
|
25602
25842
|
PLAN_MODE_INSTRUCTION,
|
|
25843
|
+
PLAN_QUESTION_ANSWERS_PREFIX,
|
|
25603
25844
|
REPO_REVIEW_NAME,
|
|
25604
25845
|
REPO_REVIEW_PATH,
|
|
25605
25846
|
REVIEW_REQUEST_NAME,
|
|
@@ -25873,6 +26114,7 @@ init_outbound_watch();
|
|
|
25873
26114
|
inspectGitWorktree,
|
|
25874
26115
|
installAgent,
|
|
25875
26116
|
interruptSlackCoordinatorForInbound,
|
|
26117
|
+
invalidateThreadListCache,
|
|
25876
26118
|
isAbleTimeConnected,
|
|
25877
26119
|
isAskUserToolName,
|
|
25878
26120
|
isBrightsyConnected,
|
|
@@ -25898,6 +26140,7 @@ init_outbound_watch();
|
|
|
25898
26140
|
isOrchestratorThread,
|
|
25899
26141
|
isPidAlive,
|
|
25900
26142
|
isPlaceholderBranch,
|
|
26143
|
+
isPlanQuestionAnswersMessage,
|
|
25901
26144
|
isPollWrapperToolName,
|
|
25902
26145
|
isPrNotMergeableError,
|
|
25903
26146
|
isPresentPlanToolName,
|
|
@@ -26008,6 +26251,7 @@ init_outbound_watch();
|
|
|
26008
26251
|
pastedTextStats,
|
|
26009
26252
|
pendingSlackExternalReplies,
|
|
26010
26253
|
permissionMode,
|
|
26254
|
+
persistPendingFileAttachments,
|
|
26011
26255
|
persistVaultKeyInKeychain,
|
|
26012
26256
|
planFileAbs,
|
|
26013
26257
|
planQuestionsSignature,
|
|
@@ -26177,6 +26421,7 @@ init_outbound_watch();
|
|
|
26177
26421
|
userCursorMcpConfigPath,
|
|
26178
26422
|
validateLinearApiKey,
|
|
26179
26423
|
verifyAbleTimeConnection,
|
|
26424
|
+
visibleToolRowDetail,
|
|
26180
26425
|
waitForPidExit,
|
|
26181
26426
|
warmGithubAgentAuth,
|
|
26182
26427
|
withAgentInstructions,
|