@sideboard-ai/core 0.1.135 → 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-O3AJMI2Y.js → agents-ELWR7A2T.js} +3 -3
- package/dist/{agents-RTQFF7PY.js → agents-QNTTLMG2.js} +3 -3
- package/dist/{chunk-RDULVW3E.js → chunk-4XKUHP6G.js} +1 -1
- package/dist/{chunk-N62K3KXX.js → chunk-CYM5DCHI.js} +38 -4
- package/dist/{chunk-XUEI4GCF.js → chunk-GSKRGF7B.js} +284 -3
- package/dist/{chunk-57GIFU3X.js → chunk-IFZ4MOTN.js} +2 -2
- package/dist/{chunk-KBBXNS2V.js → chunk-JPBRMUM6.js} +8 -4
- package/dist/{chunk-2ESCEK2Q.js → chunk-K5YT5GX2.js} +242 -3
- package/dist/{chunk-LOKXPQ4U.js → chunk-MDCKV2NF.js} +1 -1
- package/dist/{chunk-XIKEUCNC.js → chunk-TIGKDMIA.js} +139 -266
- package/dist/{chunk-K7EX47QG.js → chunk-TQ4S5AGJ.js} +2 -2
- package/dist/{chunk-Z5LYMW7M.js → chunk-WS5LFFU3.js} +135 -217
- package/dist/{coordinator-prompt-Y737IIFR.js → coordinator-prompt-2OWSUAUR.js} +1 -1
- package/dist/{coordinator-prompt-FYMWE33S.js → coordinator-prompt-IPL4Z6SL.js} +1 -1
- package/dist/{global-workspace-6KH6BSKL.js → global-workspace-JDUCUL7S.js} +2 -2
- package/dist/{global-workspace-ZFKNLBZA.js → global-workspace-NIKZAKOO.js} +2 -2
- package/dist/index.cjs +828 -615
- package/dist/index.d.cts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +38 -17
- package/dist/mcp/run-stdio.cjs +657 -485
- package/dist/mcp/run-stdio.js +20 -9
- package/dist/{orchestrator-3YDPPZHZ.js → orchestrator-6I47JMU2.js} +5 -5
- package/dist/{orchestrator-2BRAPJ47.js → orchestrator-KK3CUW37.js} +5 -5
- package/dist/{workspaces-3RRF3LVF.js → workspaces-5EWNNALF.js} +3 -3
- package/dist/{workspaces-AYI5DHK4.js → workspaces-KZA3TCEE.js} +3 -3
- package/package.json +1 -1
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -5825,6 +5825,240 @@ var init_cloud_connect_constants = __esm({
|
|
|
5825
5825
|
}
|
|
5826
5826
|
});
|
|
5827
5827
|
|
|
5828
|
+
// src/composer/stage-files.ts
|
|
5829
|
+
function fileExtension(filePath) {
|
|
5830
|
+
const base = (0, import_node_path18.basename)(filePath).toLowerCase();
|
|
5831
|
+
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
5832
|
+
}
|
|
5833
|
+
function isImageFilePath(filePath) {
|
|
5834
|
+
return IMAGE_EXTENSIONS.has(fileExtension(filePath));
|
|
5835
|
+
}
|
|
5836
|
+
function imageMimeType(filePath) {
|
|
5837
|
+
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
5838
|
+
}
|
|
5839
|
+
function ensureAttachmentsDir(worktreePath) {
|
|
5840
|
+
const dir = (0, import_node_path18.join)(worktreePath, ATTACHMENTS_DIR);
|
|
5841
|
+
(0, import_node_fs15.mkdirSync)(dir, { recursive: true });
|
|
5842
|
+
const gi = (0, import_node_path18.join)(dir, ".gitignore");
|
|
5843
|
+
if (!(0, import_node_fs15.existsSync)(gi)) {
|
|
5844
|
+
(0, import_node_fs15.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
5845
|
+
}
|
|
5846
|
+
return dir;
|
|
5847
|
+
}
|
|
5848
|
+
function uniqueAttachmentName(dir, originalName) {
|
|
5849
|
+
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
5850
|
+
if (!(0, import_node_fs15.existsSync)((0, import_node_path18.join)(dir, safe))) return safe;
|
|
5851
|
+
const ext = (0, import_node_path18.extname)(safe);
|
|
5852
|
+
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
5853
|
+
for (let i = 1; i < 1e4; i++) {
|
|
5854
|
+
const candidate = `${stem}-${i}${ext}`;
|
|
5855
|
+
if (!(0, import_node_fs15.existsSync)((0, import_node_path18.join)(dir, candidate))) return candidate;
|
|
5856
|
+
}
|
|
5857
|
+
return `${stem}-${(0, import_node_crypto4.randomUUID)()}${ext}`;
|
|
5858
|
+
}
|
|
5859
|
+
function previewDataUrlFromBuf(filePath, buf) {
|
|
5860
|
+
if (!isImageFilePath(filePath)) return void 0;
|
|
5861
|
+
if (buf.length > MAX_PREVIEW_BYTES) return void 0;
|
|
5862
|
+
return `data:${imageMimeType(filePath)};base64,${buf.toString("base64")}`;
|
|
5863
|
+
}
|
|
5864
|
+
function attachmentFromBuffer(name, buf, opts) {
|
|
5865
|
+
const previewDataUrl = previewDataUrlFromBuf(name, buf);
|
|
5866
|
+
if (isImageFilePath(name)) {
|
|
5867
|
+
const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
|
|
5868
|
+
return {
|
|
5869
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
5870
|
+
name,
|
|
5871
|
+
kind: "file",
|
|
5872
|
+
path: opts.path,
|
|
5873
|
+
previewDataUrl,
|
|
5874
|
+
content: [
|
|
5875
|
+
`Image attached: ${pathHint}`,
|
|
5876
|
+
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."
|
|
5877
|
+
].join("\n")
|
|
5878
|
+
};
|
|
5879
|
+
}
|
|
5880
|
+
if (buf.length > MAX_INLINE_BYTES) {
|
|
5881
|
+
return {
|
|
5882
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
5883
|
+
name,
|
|
5884
|
+
kind: "file",
|
|
5885
|
+
path: opts.path,
|
|
5886
|
+
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)`
|
|
5887
|
+
};
|
|
5888
|
+
}
|
|
5889
|
+
if (buf.includes(0)) {
|
|
5890
|
+
return {
|
|
5891
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
5892
|
+
name,
|
|
5893
|
+
kind: "file",
|
|
5894
|
+
path: opts.path,
|
|
5895
|
+
content: opts.path ? `(binary file at \`${opts.path}\` \u2014 use tools to inspect)` : `(binary file attached by path only: ${opts.sourceLabel || name})`
|
|
5896
|
+
};
|
|
5897
|
+
}
|
|
5898
|
+
return {
|
|
5899
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
5900
|
+
name,
|
|
5901
|
+
kind: "file",
|
|
5902
|
+
path: opts.path,
|
|
5903
|
+
content: buf.toString("utf8")
|
|
5904
|
+
};
|
|
5905
|
+
}
|
|
5906
|
+
function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
5907
|
+
if (absolutePaths.length === 0) return [];
|
|
5908
|
+
const dir = ensureAttachmentsDir(worktreePath);
|
|
5909
|
+
const out = [];
|
|
5910
|
+
for (const abs of absolutePaths) {
|
|
5911
|
+
const originalName = (0, import_node_path18.basename)(abs);
|
|
5912
|
+
try {
|
|
5913
|
+
const st = (0, import_node_fs15.statSync)(abs);
|
|
5914
|
+
if (!st.isFile()) continue;
|
|
5915
|
+
const name = uniqueAttachmentName(dir, originalName);
|
|
5916
|
+
const destAbs = (0, import_node_path18.join)(dir, name);
|
|
5917
|
+
(0, import_node_fs15.copyFileSync)(abs, destAbs);
|
|
5918
|
+
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
5919
|
+
const buf = (0, import_node_fs15.readFileSync)(destAbs);
|
|
5920
|
+
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
5921
|
+
} catch (err) {
|
|
5922
|
+
out.push({
|
|
5923
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
5924
|
+
name: originalName,
|
|
5925
|
+
kind: "file",
|
|
5926
|
+
content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
|
|
5927
|
+
});
|
|
5928
|
+
}
|
|
5929
|
+
}
|
|
5930
|
+
return out;
|
|
5931
|
+
}
|
|
5932
|
+
function stageBuffersAsAttachments(worktreePath, buffers2) {
|
|
5933
|
+
if (buffers2.length === 0) return [];
|
|
5934
|
+
const dir = ensureAttachmentsDir(worktreePath);
|
|
5935
|
+
const out = [];
|
|
5936
|
+
for (const item of buffers2) {
|
|
5937
|
+
const originalName = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
5938
|
+
try {
|
|
5939
|
+
const buf = Buffer.from(item.dataBase64, "base64");
|
|
5940
|
+
const name = uniqueAttachmentName(dir, originalName);
|
|
5941
|
+
const destAbs = (0, import_node_path18.join)(dir, name);
|
|
5942
|
+
(0, import_node_fs15.writeFileSync)(destAbs, buf);
|
|
5943
|
+
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
5944
|
+
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
5945
|
+
} catch (err) {
|
|
5946
|
+
out.push({
|
|
5947
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
5948
|
+
name: originalName,
|
|
5949
|
+
kind: "file",
|
|
5950
|
+
content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
|
|
5951
|
+
});
|
|
5952
|
+
}
|
|
5953
|
+
}
|
|
5954
|
+
return out;
|
|
5955
|
+
}
|
|
5956
|
+
function isWorktreeRelativePath(p) {
|
|
5957
|
+
if (!p || p.includes("..")) return false;
|
|
5958
|
+
if (p.startsWith("/")) return false;
|
|
5959
|
+
if (/^[A-Za-z]:[\\/]/.test(p)) return false;
|
|
5960
|
+
return true;
|
|
5961
|
+
}
|
|
5962
|
+
function dataUrlToBase64(url) {
|
|
5963
|
+
if (!url) return null;
|
|
5964
|
+
const m = /^data:[^;]+;base64,(.+)$/s.exec(url);
|
|
5965
|
+
return m?.[1] ?? null;
|
|
5966
|
+
}
|
|
5967
|
+
function persistPendingFileAttachments(worktreePath, attachments) {
|
|
5968
|
+
if (attachments.length === 0) return attachments;
|
|
5969
|
+
const keep = [];
|
|
5970
|
+
const buffers2 = [];
|
|
5971
|
+
for (const att of attachments) {
|
|
5972
|
+
if (att.kind !== "file") {
|
|
5973
|
+
keep.push(att);
|
|
5974
|
+
continue;
|
|
5975
|
+
}
|
|
5976
|
+
if (att.path && isWorktreeRelativePath(att.path)) {
|
|
5977
|
+
keep.push(att);
|
|
5978
|
+
continue;
|
|
5979
|
+
}
|
|
5980
|
+
const fromPreview = dataUrlToBase64(att.previewDataUrl);
|
|
5981
|
+
if (fromPreview) {
|
|
5982
|
+
buffers2.push({ name: att.name, dataBase64: fromPreview });
|
|
5983
|
+
continue;
|
|
5984
|
+
}
|
|
5985
|
+
if (att.content && !IMAGE_HINT_RE.test(att.content) && !PLACEHOLDER_CONTENT_RE.test(att.content)) {
|
|
5986
|
+
buffers2.push({
|
|
5987
|
+
name: att.name,
|
|
5988
|
+
dataBase64: Buffer.from(att.content, "utf8").toString("base64")
|
|
5989
|
+
});
|
|
5990
|
+
continue;
|
|
5991
|
+
}
|
|
5992
|
+
keep.push(att);
|
|
5993
|
+
}
|
|
5994
|
+
if (buffers2.length === 0) return attachments;
|
|
5995
|
+
return [...keep, ...stageBuffersAsAttachments(worktreePath, buffers2)];
|
|
5996
|
+
}
|
|
5997
|
+
function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
5998
|
+
const out = [];
|
|
5999
|
+
for (const rel of relativePaths) {
|
|
6000
|
+
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
6001
|
+
out.push({
|
|
6002
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
6003
|
+
name: (0, import_node_path18.basename)(rel) || "file",
|
|
6004
|
+
kind: "file",
|
|
6005
|
+
content: `(invalid path: ${rel})`
|
|
6006
|
+
});
|
|
6007
|
+
continue;
|
|
6008
|
+
}
|
|
6009
|
+
const name = (0, import_node_path18.basename)(rel);
|
|
6010
|
+
try {
|
|
6011
|
+
const abs = (0, import_node_path18.join)(worktreePath, rel);
|
|
6012
|
+
const st = (0, import_node_fs15.statSync)(abs);
|
|
6013
|
+
if (!st.isFile()) continue;
|
|
6014
|
+
const buf = (0, import_node_fs15.readFileSync)(abs);
|
|
6015
|
+
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
6016
|
+
} catch (err) {
|
|
6017
|
+
out.push({
|
|
6018
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
6019
|
+
name,
|
|
6020
|
+
kind: "file",
|
|
6021
|
+
content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
|
|
6022
|
+
});
|
|
6023
|
+
}
|
|
6024
|
+
}
|
|
6025
|
+
return out;
|
|
6026
|
+
}
|
|
6027
|
+
var import_node_fs15, import_node_path18, import_node_crypto4, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
|
|
6028
|
+
var init_stage_files = __esm({
|
|
6029
|
+
"src/composer/stage-files.ts"() {
|
|
6030
|
+
"use strict";
|
|
6031
|
+
import_node_fs15 = require("fs");
|
|
6032
|
+
import_node_path18 = require("path");
|
|
6033
|
+
import_node_crypto4 = require("crypto");
|
|
6034
|
+
init_workspace_scratch();
|
|
6035
|
+
IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
6036
|
+
"png",
|
|
6037
|
+
"jpg",
|
|
6038
|
+
"jpeg",
|
|
6039
|
+
"gif",
|
|
6040
|
+
"webp",
|
|
6041
|
+
"svg",
|
|
6042
|
+
"bmp",
|
|
6043
|
+
"ico"
|
|
6044
|
+
]);
|
|
6045
|
+
IMAGE_MIME_BY_EXT = {
|
|
6046
|
+
png: "image/png",
|
|
6047
|
+
jpg: "image/jpeg",
|
|
6048
|
+
jpeg: "image/jpeg",
|
|
6049
|
+
gif: "image/gif",
|
|
6050
|
+
webp: "image/webp",
|
|
6051
|
+
svg: "image/svg+xml",
|
|
6052
|
+
bmp: "image/bmp",
|
|
6053
|
+
ico: "image/x-icon"
|
|
6054
|
+
};
|
|
6055
|
+
MAX_INLINE_BYTES = 4e5;
|
|
6056
|
+
MAX_PREVIEW_BYTES = 5e6;
|
|
6057
|
+
IMAGE_HINT_RE = /^Image attached:/;
|
|
6058
|
+
PLACEHOLDER_CONTENT_RE = /^\((could not |file too large|binary file|not a file|invalid path)/;
|
|
6059
|
+
}
|
|
6060
|
+
});
|
|
6061
|
+
|
|
5828
6062
|
// src/agents/orchestrator-capable.ts
|
|
5829
6063
|
function isOrchestratorCapableAgent(agent) {
|
|
5830
6064
|
return Boolean(
|
|
@@ -5907,13 +6141,13 @@ function coordinatorTurnReminder(opts) {
|
|
|
5907
6141
|
`- YOUR orchestration thread id is ${opts.parentId} \u2014 pass parentThreadId="${opts.parentId}" on create_thread, or omit it.`,
|
|
5908
6142
|
goal ? `- Goal / title: ${goal}` : null,
|
|
5909
6143
|
accountDefaultsPlaybookLine(),
|
|
5910
|
-
"- 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."
|
|
6144
|
+
"- 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."
|
|
5911
6145
|
].filter(Boolean).join("\n");
|
|
5912
6146
|
}
|
|
5913
6147
|
function ensureGlobalCoordinatorCwd(opts) {
|
|
5914
6148
|
const dir = globalAgentCwd();
|
|
5915
6149
|
try {
|
|
5916
|
-
(0,
|
|
6150
|
+
(0, import_node_fs16.mkdirSync)(dir, { recursive: true });
|
|
5917
6151
|
} catch {
|
|
5918
6152
|
return dir;
|
|
5919
6153
|
}
|
|
@@ -5921,7 +6155,7 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
5921
6155
|
let orchId = opts?.orchestratorThreadId?.trim() || "";
|
|
5922
6156
|
if (!orchId) {
|
|
5923
6157
|
try {
|
|
5924
|
-
const existing = (0,
|
|
6158
|
+
const existing = (0, import_node_fs16.readFileSync)((0, import_node_path19.join)(dir, "AGENTS.md"), "utf8");
|
|
5925
6159
|
const m = existing.match(
|
|
5926
6160
|
/YOUR orchestration thread id is `([0-9a-f-]{36})`/i
|
|
5927
6161
|
);
|
|
@@ -5964,9 +6198,9 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
5964
6198
|
"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."
|
|
5965
6199
|
].join("\n");
|
|
5966
6200
|
try {
|
|
5967
|
-
(0,
|
|
6201
|
+
(0, import_node_fs16.writeFileSync)((0, import_node_path19.join)(dir, "CLAUDE.md"), `${body}
|
|
5968
6202
|
`, "utf8");
|
|
5969
|
-
(0,
|
|
6203
|
+
(0, import_node_fs16.writeFileSync)((0, import_node_path19.join)(dir, "AGENTS.md"), `${body}
|
|
5970
6204
|
`, "utf8");
|
|
5971
6205
|
} catch {
|
|
5972
6206
|
}
|
|
@@ -5998,12 +6232,12 @@ function coordinatorSystemPrompt(opts) {
|
|
|
5998
6232
|
formatWorkspaceInventory(opts.workspaces)
|
|
5999
6233
|
].join("\n");
|
|
6000
6234
|
}
|
|
6001
|
-
var
|
|
6235
|
+
var import_node_fs16, import_node_path19, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
|
|
6002
6236
|
var init_coordinator_prompt = __esm({
|
|
6003
6237
|
"src/orchestrator/coordinator-prompt.ts"() {
|
|
6004
6238
|
"use strict";
|
|
6005
|
-
|
|
6006
|
-
|
|
6239
|
+
import_node_fs16 = require("fs");
|
|
6240
|
+
import_node_path19 = require("path");
|
|
6007
6241
|
init_worktree();
|
|
6008
6242
|
init_app_settings();
|
|
6009
6243
|
init_paths();
|
|
@@ -6032,7 +6266,7 @@ var init_coordinator_prompt = __esm({
|
|
|
6032
6266
|
"- 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.",
|
|
6033
6267
|
"- 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.",
|
|
6034
6268
|
"- 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",
|
|
6035
|
-
"- 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.",
|
|
6269
|
+
"- 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.",
|
|
6036
6270
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
6037
6271
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
6038
6272
|
"Setup / run:",
|
|
@@ -6152,6 +6386,7 @@ function createGlobalChat(opts) {
|
|
|
6152
6386
|
fast: opts.fast
|
|
6153
6387
|
});
|
|
6154
6388
|
const agent = assertOrchestratorCapableAgent(resolved.agent);
|
|
6389
|
+
const worktreePath = globalAgentCwd();
|
|
6155
6390
|
const thread = createEmptyThread({
|
|
6156
6391
|
title,
|
|
6157
6392
|
// Stick nicknames the same way chat tabs do (avoid later sync overwrites).
|
|
@@ -6159,7 +6394,7 @@ function createGlobalChat(opts) {
|
|
|
6159
6394
|
sourceType: "orchestration",
|
|
6160
6395
|
sourceRef,
|
|
6161
6396
|
branchName: "global",
|
|
6162
|
-
worktreePath
|
|
6397
|
+
worktreePath,
|
|
6163
6398
|
repoPath: GLOBAL_WORKSPACE_ID,
|
|
6164
6399
|
agent,
|
|
6165
6400
|
autonomy: opts.autonomy ?? "default",
|
|
@@ -6167,7 +6402,10 @@ function createGlobalChat(opts) {
|
|
|
6167
6402
|
effort: resolved.effort,
|
|
6168
6403
|
fast: resolved.fast,
|
|
6169
6404
|
planMode: Boolean(opts.planMode),
|
|
6170
|
-
attachments:
|
|
6405
|
+
attachments: persistPendingFileAttachments(
|
|
6406
|
+
worktreePath,
|
|
6407
|
+
opts.attachments ?? []
|
|
6408
|
+
),
|
|
6171
6409
|
parentThreadId: opts.parentThreadId ?? null,
|
|
6172
6410
|
status: "idle"
|
|
6173
6411
|
});
|
|
@@ -6292,6 +6530,7 @@ var init_global_workspace = __esm({
|
|
|
6292
6530
|
"src/store/global-workspace.ts"() {
|
|
6293
6531
|
"use strict";
|
|
6294
6532
|
init_cloud_connect_constants();
|
|
6533
|
+
init_stage_files();
|
|
6295
6534
|
init_orchestrator_capable();
|
|
6296
6535
|
init_teams();
|
|
6297
6536
|
init_coordinator_prompt();
|
|
@@ -6306,32 +6545,32 @@ var init_global_workspace = __esm({
|
|
|
6306
6545
|
function brightsyConfigPath() {
|
|
6307
6546
|
const override = process.env.BRIGHTSY_CONFIG?.trim();
|
|
6308
6547
|
if (override) return override;
|
|
6309
|
-
return (0,
|
|
6548
|
+
return (0, import_node_path20.join)((0, import_node_os6.homedir)(), ".brightsy", "config.json");
|
|
6310
6549
|
}
|
|
6311
6550
|
function loadBrightsyConfig() {
|
|
6312
6551
|
const path = brightsyConfigPath();
|
|
6313
|
-
if (!(0,
|
|
6552
|
+
if (!(0, import_node_fs17.existsSync)(path)) {
|
|
6314
6553
|
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
6315
6554
|
}
|
|
6316
|
-
const raw = JSON.parse((0,
|
|
6555
|
+
const raw = JSON.parse((0, import_node_fs17.readFileSync)(path, "utf8"));
|
|
6317
6556
|
if (!raw.access_token || !raw.account_id) {
|
|
6318
6557
|
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
6319
6558
|
}
|
|
6320
6559
|
return raw;
|
|
6321
6560
|
}
|
|
6322
6561
|
function saveBrightsyConfig(cfg) {
|
|
6323
|
-
(0,
|
|
6562
|
+
(0, import_node_fs17.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
6324
6563
|
`, {
|
|
6325
6564
|
mode: 384
|
|
6326
6565
|
});
|
|
6327
6566
|
}
|
|
6328
|
-
var
|
|
6567
|
+
var import_node_fs17, import_node_os6, import_node_path20;
|
|
6329
6568
|
var init_config = __esm({
|
|
6330
6569
|
"src/brightsy/config.ts"() {
|
|
6331
6570
|
"use strict";
|
|
6332
|
-
|
|
6571
|
+
import_node_fs17 = require("fs");
|
|
6333
6572
|
import_node_os6 = require("os");
|
|
6334
|
-
|
|
6573
|
+
import_node_path20 = require("path");
|
|
6335
6574
|
}
|
|
6336
6575
|
});
|
|
6337
6576
|
|
|
@@ -6448,22 +6687,22 @@ var init_oauth = __esm({
|
|
|
6448
6687
|
|
|
6449
6688
|
// src/brightsy/connected-teams.ts
|
|
6450
6689
|
function storePath4() {
|
|
6451
|
-
return (0,
|
|
6690
|
+
return (0, import_node_path21.join)(appDataDir(), "brightsy-teams.json");
|
|
6452
6691
|
}
|
|
6453
6692
|
function readStore4() {
|
|
6454
6693
|
const path = storePath4();
|
|
6455
|
-
if (!(0,
|
|
6694
|
+
if (!(0, import_node_fs18.existsSync)(path)) return [];
|
|
6456
6695
|
try {
|
|
6457
|
-
const parsed = JSON.parse((0,
|
|
6696
|
+
const parsed = JSON.parse((0, import_node_fs18.readFileSync)(path, "utf8"));
|
|
6458
6697
|
return Array.isArray(parsed.teams) ? parsed.teams : [];
|
|
6459
6698
|
} catch {
|
|
6460
6699
|
return [];
|
|
6461
6700
|
}
|
|
6462
6701
|
}
|
|
6463
6702
|
function writeStore2(teams) {
|
|
6464
|
-
(0,
|
|
6703
|
+
(0, import_node_fs18.mkdirSync)(appDataDir(), { recursive: true });
|
|
6465
6704
|
const path = storePath4();
|
|
6466
|
-
(0,
|
|
6705
|
+
(0, import_node_fs18.writeFileSync)(path, `${JSON.stringify({ teams }, null, 2)}
|
|
6467
6706
|
`, {
|
|
6468
6707
|
mode: 384
|
|
6469
6708
|
});
|
|
@@ -6569,12 +6808,12 @@ function brightsyMcpServerName(slug) {
|
|
|
6569
6808
|
const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
|
|
6570
6809
|
return `brightsy_${cleaned || "team"}`;
|
|
6571
6810
|
}
|
|
6572
|
-
var
|
|
6811
|
+
var import_node_fs18, import_node_path21;
|
|
6573
6812
|
var init_connected_teams = __esm({
|
|
6574
6813
|
"src/brightsy/connected-teams.ts"() {
|
|
6575
6814
|
"use strict";
|
|
6576
|
-
|
|
6577
|
-
|
|
6815
|
+
import_node_fs18 = require("fs");
|
|
6816
|
+
import_node_path21 = require("path");
|
|
6578
6817
|
init_paths();
|
|
6579
6818
|
init_accounts();
|
|
6580
6819
|
init_config();
|
|
@@ -6946,11 +7185,11 @@ async function syncCliForTarget(accountId) {
|
|
|
6946
7185
|
}
|
|
6947
7186
|
applyConnectedTeamToCli(team);
|
|
6948
7187
|
}
|
|
6949
|
-
var
|
|
7188
|
+
var import_node_fs19, brightsyAdapter;
|
|
6950
7189
|
var init_brightsy = __esm({
|
|
6951
7190
|
"src/agents/brightsy.ts"() {
|
|
6952
7191
|
"use strict";
|
|
6953
|
-
|
|
7192
|
+
import_node_fs19 = require("fs");
|
|
6954
7193
|
init_run();
|
|
6955
7194
|
init_connected_teams();
|
|
6956
7195
|
init_config();
|
|
@@ -6965,7 +7204,7 @@ var init_brightsy = __esm({
|
|
|
6965
7204
|
async detect() {
|
|
6966
7205
|
const brightsy = resolveAgentExecutable("brightsy");
|
|
6967
7206
|
if (brightsy !== "brightsy") {
|
|
6968
|
-
if (!(0,
|
|
7207
|
+
if (!(0, import_node_fs19.existsSync)(brightsy)) {
|
|
6969
7208
|
return {
|
|
6970
7209
|
agent: "brightsy",
|
|
6971
7210
|
installed: false,
|
|
@@ -7093,10 +7332,14 @@ function toolDetail(name, input) {
|
|
|
7093
7332
|
if (!input) return void 0;
|
|
7094
7333
|
const command = str2(input.command) ?? str2(input.cmd);
|
|
7095
7334
|
if (command) return command;
|
|
7335
|
+
const pattern = str2(input.pattern) ?? str2(input.glob) ?? str2(input.glob_pattern);
|
|
7336
|
+
const isSearch = /grep|glob|search|ripgrep|findfiles|semsearch/i.test(name);
|
|
7337
|
+
if (isSearch && pattern) {
|
|
7338
|
+
return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
|
|
7339
|
+
}
|
|
7096
7340
|
const path = str2(input.file_path) ?? str2(input.path) ?? str2(input.filePath) ?? str2(input.filename);
|
|
7097
7341
|
if (path) return path;
|
|
7098
|
-
|
|
7099
|
-
if (pattern) return pattern;
|
|
7342
|
+
if (pattern) return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
|
|
7100
7343
|
const query = str2(input.query) ?? str2(input.prompt);
|
|
7101
7344
|
if (query) return query.length > 80 ? `${query.slice(0, 77)}\u2026` : query;
|
|
7102
7345
|
try {
|
|
@@ -7536,43 +7779,43 @@ function electronResourcesPath() {
|
|
|
7536
7779
|
function packagedCursorRuntimeDir() {
|
|
7537
7780
|
const resources = electronResourcesPath();
|
|
7538
7781
|
if (!resources) return null;
|
|
7539
|
-
const dir = (0,
|
|
7540
|
-
if (!(0,
|
|
7782
|
+
const dir = (0, import_node_path22.join)(resources, "cursor-runtime");
|
|
7783
|
+
if (!(0, import_node_fs20.existsSync)((0, import_node_path22.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
|
|
7541
7784
|
return dir;
|
|
7542
7785
|
}
|
|
7543
7786
|
function packagedCursorRunnerPath() {
|
|
7544
7787
|
const dir = packagedCursorRuntimeDir();
|
|
7545
|
-
return dir ? (0,
|
|
7788
|
+
return dir ? (0, import_node_path22.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
|
|
7546
7789
|
}
|
|
7547
7790
|
function packagedMcpDir() {
|
|
7548
7791
|
const resources = electronResourcesPath();
|
|
7549
7792
|
if (!resources) return null;
|
|
7550
|
-
const dir = (0,
|
|
7551
|
-
if (!(0,
|
|
7793
|
+
const dir = (0, import_node_path22.join)(resources, "sideboard-mcp");
|
|
7794
|
+
if (!(0, import_node_fs20.existsSync)((0, import_node_path22.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
|
|
7552
7795
|
return dir;
|
|
7553
7796
|
}
|
|
7554
7797
|
function packagedMcpStdioPath() {
|
|
7555
7798
|
const dir = packagedMcpDir();
|
|
7556
|
-
return dir ? (0,
|
|
7799
|
+
return dir ? (0, import_node_path22.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
|
|
7557
7800
|
}
|
|
7558
7801
|
function packagedBundledNodePath() {
|
|
7559
7802
|
const resources = electronResourcesPath();
|
|
7560
7803
|
if (!resources) return null;
|
|
7561
|
-
const bin = (0,
|
|
7562
|
-
if (!(0,
|
|
7804
|
+
const bin = (0, import_node_path22.join)(resources, "node", "bin", "node");
|
|
7805
|
+
if (!(0, import_node_fs20.existsSync)(bin)) return null;
|
|
7563
7806
|
return bin;
|
|
7564
7807
|
}
|
|
7565
7808
|
function packagedCursorRipgrepCandidate(platformPkg, binName) {
|
|
7566
7809
|
const dir = packagedCursorRuntimeDir();
|
|
7567
7810
|
if (!dir) return null;
|
|
7568
|
-
return (0,
|
|
7811
|
+
return (0, import_node_path22.join)(dir, "node_modules", platformPkg, "bin", binName);
|
|
7569
7812
|
}
|
|
7570
|
-
var
|
|
7813
|
+
var import_node_fs20, import_node_path22;
|
|
7571
7814
|
var init_packaged_runtime = __esm({
|
|
7572
7815
|
"src/agents/packaged-runtime.ts"() {
|
|
7573
7816
|
"use strict";
|
|
7574
|
-
|
|
7575
|
-
|
|
7817
|
+
import_node_fs20 = require("fs");
|
|
7818
|
+
import_node_path22 = require("path");
|
|
7576
7819
|
}
|
|
7577
7820
|
});
|
|
7578
7821
|
|
|
@@ -7606,7 +7849,7 @@ function unpackedAsarPath(filePath) {
|
|
|
7606
7849
|
if (!isAsarPath(filePath)) return null;
|
|
7607
7850
|
const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
|
|
7608
7851
|
if (unpacked === filePath) return null;
|
|
7609
|
-
return (0,
|
|
7852
|
+
return (0, import_node_fs21.existsSync)(unpacked) ? unpacked : null;
|
|
7610
7853
|
}
|
|
7611
7854
|
function nodeReadableScriptPath(scriptPath) {
|
|
7612
7855
|
return unpackedAsarPath(scriptPath) ?? scriptPath;
|
|
@@ -7646,37 +7889,37 @@ function pickPreferredNode(candidates) {
|
|
|
7646
7889
|
return best;
|
|
7647
7890
|
}
|
|
7648
7891
|
function versionDirNodeBins(root, toBin) {
|
|
7649
|
-
if (!(0,
|
|
7892
|
+
if (!(0, import_node_fs21.existsSync)(root)) return [];
|
|
7650
7893
|
try {
|
|
7651
|
-
return (0,
|
|
7894
|
+
return (0, import_node_fs21.readdirSync)(root).map(toBin);
|
|
7652
7895
|
} catch {
|
|
7653
7896
|
return [];
|
|
7654
7897
|
}
|
|
7655
7898
|
}
|
|
7656
7899
|
function defaultNodeBinCandidates(home = (0, import_node_os7.homedir)()) {
|
|
7657
7900
|
const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
|
|
7658
|
-
(prefix) => PREFERRED_LTS_MAJORS.map((major) => (0,
|
|
7901
|
+
(prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path23.join)(prefix, "opt", `node@${major}`, "bin", "node"))
|
|
7659
7902
|
);
|
|
7660
7903
|
return [
|
|
7661
7904
|
...kegs,
|
|
7662
7905
|
"/opt/homebrew/bin/node",
|
|
7663
7906
|
"/usr/local/bin/node",
|
|
7664
|
-
(0,
|
|
7665
|
-
(0,
|
|
7666
|
-
(0,
|
|
7667
|
-
(0,
|
|
7668
|
-
(0,
|
|
7907
|
+
(0, import_node_path23.join)(home, ".local/share/fnm/aliases/default/bin/node"),
|
|
7908
|
+
(0, import_node_path23.join)(home, ".nvm/current/bin/node"),
|
|
7909
|
+
(0, import_node_path23.join)(home, ".volta/bin/node"),
|
|
7910
|
+
(0, import_node_path23.join)(home, ".asdf/shims/node"),
|
|
7911
|
+
(0, import_node_path23.join)(home, ".local/share/mise/shims/node"),
|
|
7669
7912
|
...versionDirNodeBins(
|
|
7670
|
-
(0,
|
|
7671
|
-
(name) => (0,
|
|
7913
|
+
(0, import_node_path23.join)(home, ".nvm", "versions", "node"),
|
|
7914
|
+
(name) => (0, import_node_path23.join)(home, ".nvm", "versions", "node", name, "bin", "node")
|
|
7672
7915
|
),
|
|
7673
7916
|
...versionDirNodeBins(
|
|
7674
|
-
(0,
|
|
7675
|
-
(name) => (0,
|
|
7917
|
+
(0, import_node_path23.join)(home, ".local/share/fnm", "node-versions"),
|
|
7918
|
+
(name) => (0, import_node_path23.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
|
|
7676
7919
|
),
|
|
7677
7920
|
...versionDirNodeBins(
|
|
7678
|
-
(0,
|
|
7679
|
-
(name) => (0,
|
|
7921
|
+
(0, import_node_path23.join)(home, ".volta", "tools", "image", "node"),
|
|
7922
|
+
(name) => (0, import_node_path23.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
|
|
7680
7923
|
)
|
|
7681
7924
|
];
|
|
7682
7925
|
}
|
|
@@ -7685,10 +7928,10 @@ function uniqueExistingNodeBins(paths) {
|
|
|
7685
7928
|
const out = [];
|
|
7686
7929
|
for (const raw of paths) {
|
|
7687
7930
|
const p = raw.trim();
|
|
7688
|
-
if (!p || !(0,
|
|
7931
|
+
if (!p || !(0, import_node_fs21.existsSync)(p) || isElectronLikeCommand(p)) continue;
|
|
7689
7932
|
let key = p;
|
|
7690
7933
|
try {
|
|
7691
|
-
key = (0,
|
|
7934
|
+
key = (0, import_node_fs21.realpathSync)(p);
|
|
7692
7935
|
} catch {
|
|
7693
7936
|
continue;
|
|
7694
7937
|
}
|
|
@@ -7768,13 +8011,13 @@ async function resolveNodeLaunch(scriptPath) {
|
|
|
7768
8011
|
env: { ELECTRON_RUN_AS_NODE: "1" }
|
|
7769
8012
|
};
|
|
7770
8013
|
}
|
|
7771
|
-
var
|
|
8014
|
+
var import_node_fs21, import_node_os7, import_node_path23, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
|
|
7772
8015
|
var init_node_launch = __esm({
|
|
7773
8016
|
"src/agents/node-launch.ts"() {
|
|
7774
8017
|
"use strict";
|
|
7775
|
-
|
|
8018
|
+
import_node_fs21 = require("fs");
|
|
7776
8019
|
import_node_os7 = require("os");
|
|
7777
|
-
|
|
8020
|
+
import_node_path23 = require("path");
|
|
7778
8021
|
init_nested_electron_env();
|
|
7779
8022
|
init_run();
|
|
7780
8023
|
init_packaged_runtime();
|
|
@@ -7868,37 +8111,37 @@ function corePackageDir() {
|
|
|
7868
8111
|
try {
|
|
7869
8112
|
const url = import_meta.url;
|
|
7870
8113
|
if (typeof url === "string" && url.length > 0) {
|
|
7871
|
-
return (0,
|
|
8114
|
+
return (0, import_node_path24.dirname)((0, import_node_url.fileURLToPath)(url));
|
|
7872
8115
|
}
|
|
7873
8116
|
} catch {
|
|
7874
8117
|
}
|
|
7875
8118
|
try {
|
|
7876
|
-
const req = (0, import_node_module.createRequire)((0,
|
|
7877
|
-
return (0,
|
|
8119
|
+
const req = (0, import_node_module.createRequire)((0, import_node_path24.join)(process.cwd(), "package.json"));
|
|
8120
|
+
return (0, import_node_path24.dirname)(req.resolve("@sideboard-ai/core"));
|
|
7878
8121
|
} catch {
|
|
7879
8122
|
return process.cwd();
|
|
7880
8123
|
}
|
|
7881
8124
|
}
|
|
7882
8125
|
function findSideboardMcpJsEntry() {
|
|
7883
8126
|
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
7884
|
-
if (override && (0,
|
|
8127
|
+
if (override && (0, import_node_fs22.existsSync)(override)) return override;
|
|
7885
8128
|
const packaged = packagedMcpStdioPath();
|
|
7886
8129
|
if (packaged) return packaged;
|
|
7887
8130
|
let dir = corePackageDir();
|
|
7888
8131
|
for (let i = 0; i < 10; i++) {
|
|
7889
8132
|
const candidates = [
|
|
7890
|
-
(0,
|
|
7891
|
-
(0,
|
|
7892
|
-
(0,
|
|
7893
|
-
(0,
|
|
7894
|
-
(0,
|
|
7895
|
-
(0,
|
|
7896
|
-
(0,
|
|
8133
|
+
(0, import_node_path24.join)(dir, "mcp/run-stdio.js"),
|
|
8134
|
+
(0, import_node_path24.join)(dir, "mcp/run-stdio.cjs"),
|
|
8135
|
+
(0, import_node_path24.join)(dir, "dist/mcp/run-stdio.js"),
|
|
8136
|
+
(0, import_node_path24.join)(dir, "dist/mcp/run-stdio.cjs"),
|
|
8137
|
+
(0, import_node_path24.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
|
|
8138
|
+
(0, import_node_path24.join)(dir, "packages/cli/dist/index.js"),
|
|
8139
|
+
(0, import_node_path24.join)(dir, "cli/dist/index.js")
|
|
7897
8140
|
];
|
|
7898
8141
|
for (const p of candidates) {
|
|
7899
|
-
if ((0,
|
|
8142
|
+
if ((0, import_node_fs22.existsSync)(p) && !isAsarPath(p)) return p;
|
|
7900
8143
|
}
|
|
7901
|
-
const parent = (0,
|
|
8144
|
+
const parent = (0, import_node_path24.dirname)(dir);
|
|
7902
8145
|
if (parent === dir) break;
|
|
7903
8146
|
dir = parent;
|
|
7904
8147
|
}
|
|
@@ -8040,19 +8283,19 @@ function writeMcpServersConfig(servers) {
|
|
|
8040
8283
|
...env ? { env } : {}
|
|
8041
8284
|
};
|
|
8042
8285
|
}
|
|
8043
|
-
const dir = (0,
|
|
8044
|
-
const cfgPath = (0,
|
|
8045
|
-
(0,
|
|
8286
|
+
const dir = (0, import_node_fs22.mkdtempSync)((0, import_node_path24.join)((0, import_node_os8.tmpdir)(), "sideboard-mcp-"));
|
|
8287
|
+
const cfgPath = (0, import_node_path24.join)(dir, "mcp.json");
|
|
8288
|
+
(0, import_node_fs22.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
|
|
8046
8289
|
return cfgPath;
|
|
8047
8290
|
}
|
|
8048
|
-
var
|
|
8291
|
+
var import_node_fs22, import_node_module, import_node_os8, import_node_path24, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
|
|
8049
8292
|
var init_injected_mcp = __esm({
|
|
8050
8293
|
"src/agents/injected-mcp.ts"() {
|
|
8051
8294
|
"use strict";
|
|
8052
|
-
|
|
8295
|
+
import_node_fs22 = require("fs");
|
|
8053
8296
|
import_node_module = require("module");
|
|
8054
8297
|
import_node_os8 = require("os");
|
|
8055
|
-
|
|
8298
|
+
import_node_path24 = require("path");
|
|
8056
8299
|
import_node_url = require("url");
|
|
8057
8300
|
init_run();
|
|
8058
8301
|
init_config();
|
|
@@ -8352,11 +8595,11 @@ function parseIssuesJson(raw) {
|
|
|
8352
8595
|
}
|
|
8353
8596
|
return [];
|
|
8354
8597
|
}
|
|
8355
|
-
var
|
|
8598
|
+
var import_node_fs23, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, mcpListCache, claudeAdapter;
|
|
8356
8599
|
var init_claude = __esm({
|
|
8357
8600
|
"src/agents/claude.ts"() {
|
|
8358
8601
|
"use strict";
|
|
8359
|
-
|
|
8602
|
+
import_node_fs23 = require("fs");
|
|
8360
8603
|
init_run();
|
|
8361
8604
|
init_app_settings();
|
|
8362
8605
|
init_claude_mcp();
|
|
@@ -8396,7 +8639,7 @@ var init_claude = __esm({
|
|
|
8396
8639
|
async detect() {
|
|
8397
8640
|
const claude = resolveClaudeExecutable();
|
|
8398
8641
|
if (claude !== "claude") {
|
|
8399
|
-
if (!(0,
|
|
8642
|
+
if (!(0, import_node_fs23.existsSync)(claude)) {
|
|
8400
8643
|
return {
|
|
8401
8644
|
agent: "claude",
|
|
8402
8645
|
installed: false,
|
|
@@ -8651,7 +8894,7 @@ async function listCodexModels() {
|
|
|
8651
8894
|
if (codex === "codex") {
|
|
8652
8895
|
const which = await run("which", ["codex"], { reject: false });
|
|
8653
8896
|
if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
|
|
8654
|
-
} else if (!(0,
|
|
8897
|
+
} else if (!(0, import_node_fs24.existsSync)(codex)) {
|
|
8655
8898
|
return FALLBACK_CODEX_MODELS;
|
|
8656
8899
|
}
|
|
8657
8900
|
const listed = await run(codex, ["debug", "models"], { reject: false });
|
|
@@ -8686,12 +8929,12 @@ function usageFromCodex(usage) {
|
|
|
8686
8929
|
}
|
|
8687
8930
|
function codexConfigHasNetworkAccess() {
|
|
8688
8931
|
const candidates = [
|
|
8689
|
-
(0,
|
|
8690
|
-
(0,
|
|
8932
|
+
(0, import_node_path25.join)((0, import_node_os9.homedir)(), ".codex", "config.toml"),
|
|
8933
|
+
(0, import_node_path25.join)((0, import_node_os9.homedir)(), ".config", "codex", "config.toml")
|
|
8691
8934
|
];
|
|
8692
8935
|
for (const path of candidates) {
|
|
8693
|
-
if (!(0,
|
|
8694
|
-
const text5 = (0,
|
|
8936
|
+
if (!(0, import_node_fs24.existsSync)(path)) continue;
|
|
8937
|
+
const text5 = (0, import_node_fs24.readFileSync)(path, "utf8");
|
|
8695
8938
|
if (/network_access\s*=\s*true/.test(text5)) return true;
|
|
8696
8939
|
}
|
|
8697
8940
|
return false;
|
|
@@ -8723,21 +8966,21 @@ function asRecord2(value) {
|
|
|
8723
8966
|
return void 0;
|
|
8724
8967
|
}
|
|
8725
8968
|
function codexLooksAuthenticated() {
|
|
8726
|
-
const authPath = (0,
|
|
8727
|
-
if (!(0,
|
|
8969
|
+
const authPath = (0, import_node_path25.join)((0, import_node_os9.homedir)(), ".codex", "auth.json");
|
|
8970
|
+
if (!(0, import_node_fs24.existsSync)(authPath)) return false;
|
|
8728
8971
|
try {
|
|
8729
|
-
return (0,
|
|
8972
|
+
return (0, import_node_fs24.statSync)(authPath).size > 2;
|
|
8730
8973
|
} catch {
|
|
8731
8974
|
return false;
|
|
8732
8975
|
}
|
|
8733
8976
|
}
|
|
8734
|
-
var
|
|
8977
|
+
var import_node_fs24, import_node_os9, import_node_path25, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
|
|
8735
8978
|
var init_codex = __esm({
|
|
8736
8979
|
"src/agents/codex.ts"() {
|
|
8737
8980
|
"use strict";
|
|
8738
|
-
|
|
8981
|
+
import_node_fs24 = require("fs");
|
|
8739
8982
|
import_node_os9 = require("os");
|
|
8740
|
-
|
|
8983
|
+
import_node_path25 = require("path");
|
|
8741
8984
|
init_run();
|
|
8742
8985
|
init_app_settings();
|
|
8743
8986
|
init_global_workspace();
|
|
@@ -8762,7 +9005,7 @@ var init_codex = __esm({
|
|
|
8762
9005
|
async detect() {
|
|
8763
9006
|
const codex = resolveAgentExecutable("codex");
|
|
8764
9007
|
if (codex !== "codex") {
|
|
8765
|
-
if (!(0,
|
|
9008
|
+
if (!(0, import_node_fs24.existsSync)(codex)) {
|
|
8766
9009
|
return {
|
|
8767
9010
|
agent: "codex",
|
|
8768
9011
|
installed: false,
|
|
@@ -9249,21 +9492,21 @@ function platformRipgrepPackage() {
|
|
|
9249
9492
|
}
|
|
9250
9493
|
function usableRipgrepPath(candidate) {
|
|
9251
9494
|
const raw = candidate?.trim();
|
|
9252
|
-
if (!raw || !(0,
|
|
9495
|
+
if (!raw || !(0, import_node_path26.isAbsolute)(raw)) return null;
|
|
9253
9496
|
const readable = nodeReadableScriptPath(raw);
|
|
9254
|
-
if (!(0,
|
|
9497
|
+
if (!(0, import_node_fs25.existsSync)(readable) || isAsarPath(readable)) return null;
|
|
9255
9498
|
return readable;
|
|
9256
9499
|
}
|
|
9257
9500
|
function walkForBundledRipgrep(startFile) {
|
|
9258
9501
|
if (!startFile) return null;
|
|
9259
9502
|
const pkg = platformRipgrepPackage();
|
|
9260
9503
|
const name = rgBinaryName();
|
|
9261
|
-
let dir = (0,
|
|
9262
|
-
const root = (0,
|
|
9504
|
+
let dir = (0, import_node_path26.dirname)((0, import_node_path26.resolve)(startFile));
|
|
9505
|
+
const root = (0, import_node_path26.parse)(dir).root;
|
|
9263
9506
|
while (dir !== root) {
|
|
9264
|
-
const hit = usableRipgrepPath((0,
|
|
9507
|
+
const hit = usableRipgrepPath((0, import_node_path26.join)(dir, "node_modules", pkg, "bin", name));
|
|
9265
9508
|
if (hit) return hit;
|
|
9266
|
-
const next = (0,
|
|
9509
|
+
const next = (0, import_node_path26.dirname)(dir);
|
|
9267
9510
|
if (next === dir) break;
|
|
9268
9511
|
dir = next;
|
|
9269
9512
|
}
|
|
@@ -9273,7 +9516,7 @@ function requireResolveBundledRipgrep(fromFile) {
|
|
|
9273
9516
|
try {
|
|
9274
9517
|
const req = (0, import_node_module2.createRequire)(fromFile);
|
|
9275
9518
|
const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
|
|
9276
|
-
return usableRipgrepPath((0,
|
|
9519
|
+
return usableRipgrepPath((0, import_node_path26.join)((0, import_node_path26.dirname)(pkgJson), "bin", rgBinaryName()));
|
|
9277
9520
|
} catch {
|
|
9278
9521
|
return null;
|
|
9279
9522
|
}
|
|
@@ -9295,13 +9538,13 @@ function cursorRipgrepEnv(opts) {
|
|
|
9295
9538
|
const path = resolveCursorRipgrepPath(opts);
|
|
9296
9539
|
return path ? { [RIPGREP_ENV]: path } : {};
|
|
9297
9540
|
}
|
|
9298
|
-
var
|
|
9541
|
+
var import_node_fs25, import_node_module2, import_node_path26, RIPGREP_ENV;
|
|
9299
9542
|
var init_cursor_ripgrep = __esm({
|
|
9300
9543
|
"src/agents/cursor-ripgrep.ts"() {
|
|
9301
9544
|
"use strict";
|
|
9302
|
-
|
|
9545
|
+
import_node_fs25 = require("fs");
|
|
9303
9546
|
import_node_module2 = require("module");
|
|
9304
|
-
|
|
9547
|
+
import_node_path26 = require("path");
|
|
9305
9548
|
init_node_launch();
|
|
9306
9549
|
init_packaged_runtime();
|
|
9307
9550
|
RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
|
|
@@ -9347,11 +9590,11 @@ function entryDir() {
|
|
|
9347
9590
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
9348
9591
|
if (cjsDir) return cjsDir;
|
|
9349
9592
|
try {
|
|
9350
|
-
return (0,
|
|
9593
|
+
return (0, import_node_path27.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
|
|
9351
9594
|
} catch {
|
|
9352
9595
|
try {
|
|
9353
9596
|
const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
|
|
9354
|
-
return (0,
|
|
9597
|
+
return (0, import_node_path27.dirname)(req.resolve("@sideboard-ai/core"));
|
|
9355
9598
|
} catch {
|
|
9356
9599
|
return process.cwd();
|
|
9357
9600
|
}
|
|
@@ -9362,27 +9605,27 @@ function cursorRunnerPath() {
|
|
|
9362
9605
|
if (packaged) return packaged;
|
|
9363
9606
|
const root = entryDir();
|
|
9364
9607
|
const candidates = [
|
|
9365
|
-
(0,
|
|
9366
|
-
(0,
|
|
9608
|
+
(0, import_node_path27.join)(root, "agents", "cursor-runner.js"),
|
|
9609
|
+
(0, import_node_path27.join)(root, "agents", "cursor-runner.cjs"),
|
|
9367
9610
|
// If somehow resolved from package root instead of dist/
|
|
9368
|
-
(0,
|
|
9369
|
-
(0,
|
|
9611
|
+
(0, import_node_path27.join)(root, "dist", "agents", "cursor-runner.js"),
|
|
9612
|
+
(0, import_node_path27.join)(root, "dist", "agents", "cursor-runner.cjs"),
|
|
9370
9613
|
// Source tree (dev): packages/core/src/agents/cursor-runner.ts
|
|
9371
|
-
(0,
|
|
9372
|
-
(0,
|
|
9614
|
+
(0, import_node_path27.join)(root, "cursor-runner.ts"),
|
|
9615
|
+
(0, import_node_path27.join)(root, "src", "agents", "cursor-runner.ts")
|
|
9373
9616
|
];
|
|
9374
9617
|
for (const candidate of candidates) {
|
|
9375
|
-
if ((0,
|
|
9618
|
+
if ((0, import_node_fs26.existsSync)(candidate)) return candidate;
|
|
9376
9619
|
}
|
|
9377
9620
|
return candidates[0];
|
|
9378
9621
|
}
|
|
9379
|
-
var
|
|
9622
|
+
var import_node_fs26, import_node_module3, import_node_path27, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
|
|
9380
9623
|
var init_cursor = __esm({
|
|
9381
9624
|
"src/agents/cursor.ts"() {
|
|
9382
9625
|
"use strict";
|
|
9383
|
-
|
|
9626
|
+
import_node_fs26 = require("fs");
|
|
9384
9627
|
import_node_module3 = require("module");
|
|
9385
|
-
|
|
9628
|
+
import_node_path27 = require("path");
|
|
9386
9629
|
import_node_url2 = require("url");
|
|
9387
9630
|
import_sdk = require("@cursor/sdk");
|
|
9388
9631
|
init_run();
|
|
@@ -9533,7 +9776,7 @@ async function listOpencodeModels() {
|
|
|
9533
9776
|
if (opencode === "opencode") {
|
|
9534
9777
|
const which = await run("which", ["opencode"], { reject: false });
|
|
9535
9778
|
if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
|
|
9536
|
-
} else if (!(0,
|
|
9779
|
+
} else if (!(0, import_node_fs27.existsSync)(opencode)) {
|
|
9537
9780
|
return FALLBACK_OPENCODE_MODELS;
|
|
9538
9781
|
}
|
|
9539
9782
|
const listed = await run(opencode, ["models"], { reject: false });
|
|
@@ -9563,11 +9806,11 @@ function usageFromOpencode(tokens) {
|
|
|
9563
9806
|
cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
|
|
9564
9807
|
};
|
|
9565
9808
|
}
|
|
9566
|
-
var
|
|
9809
|
+
var import_node_fs27, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
|
|
9567
9810
|
var init_opencode = __esm({
|
|
9568
9811
|
"src/agents/opencode.ts"() {
|
|
9569
9812
|
"use strict";
|
|
9570
|
-
|
|
9813
|
+
import_node_fs27 = require("fs");
|
|
9571
9814
|
init_run();
|
|
9572
9815
|
init_app_settings();
|
|
9573
9816
|
init_global_workspace();
|
|
@@ -9594,7 +9837,7 @@ var init_opencode = __esm({
|
|
|
9594
9837
|
async detect() {
|
|
9595
9838
|
const opencode = resolveAgentExecutable("opencode");
|
|
9596
9839
|
if (opencode !== "opencode") {
|
|
9597
|
-
if (!(0,
|
|
9840
|
+
if (!(0, import_node_fs27.existsSync)(opencode)) {
|
|
9598
9841
|
return {
|
|
9599
9842
|
agent: "opencode",
|
|
9600
9843
|
installed: false,
|
|
@@ -11097,7 +11340,7 @@ function forkMessageSlice(from, throughIndex) {
|
|
|
11097
11340
|
function buildForkTranscriptAttachment(baseTitle, messages) {
|
|
11098
11341
|
const title = baseTitle || "Chat";
|
|
11099
11342
|
return {
|
|
11100
|
-
id: (0,
|
|
11343
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
11101
11344
|
name: `Transcript of ${title}.md`,
|
|
11102
11345
|
kind: "transcript",
|
|
11103
11346
|
content: formatTranscriptMarkdown(title, messages)
|
|
@@ -11154,11 +11397,11 @@ function forkChatTab(input) {
|
|
|
11154
11397
|
}
|
|
11155
11398
|
return tab;
|
|
11156
11399
|
}
|
|
11157
|
-
var
|
|
11400
|
+
var import_node_crypto5;
|
|
11158
11401
|
var init_chat_tabs = __esm({
|
|
11159
11402
|
"src/threads/chat-tabs.ts"() {
|
|
11160
11403
|
"use strict";
|
|
11161
|
-
|
|
11404
|
+
import_node_crypto5 = require("crypto");
|
|
11162
11405
|
init_context_compact();
|
|
11163
11406
|
init_teams();
|
|
11164
11407
|
init_worktree_labels();
|
|
@@ -11328,21 +11571,21 @@ function shouldRefreshReviewRequestTemplate(content) {
|
|
|
11328
11571
|
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
11329
11572
|
}
|
|
11330
11573
|
function readTextIfPresent(abs) {
|
|
11331
|
-
if (!(0,
|
|
11574
|
+
if (!(0, import_node_fs28.existsSync)(abs)) return null;
|
|
11332
11575
|
try {
|
|
11333
|
-
const content = (0,
|
|
11576
|
+
const content = (0, import_node_fs28.readFileSync)(abs, "utf8");
|
|
11334
11577
|
return content.trim() ? content : null;
|
|
11335
11578
|
} catch {
|
|
11336
11579
|
return null;
|
|
11337
11580
|
}
|
|
11338
11581
|
}
|
|
11339
11582
|
function readLocalGuidelines(worktreePath) {
|
|
11340
|
-
const localAbs = (0,
|
|
11583
|
+
const localAbs = (0, import_node_path28.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
11341
11584
|
const localContent = readTextIfPresent(localAbs);
|
|
11342
11585
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
11343
11586
|
return { path: REVIEW_REQUEST_PATH, content: localContent };
|
|
11344
11587
|
}
|
|
11345
|
-
const legacyAbs = (0,
|
|
11588
|
+
const legacyAbs = (0, import_node_path28.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
|
|
11346
11589
|
const legacyContent = readTextIfPresent(legacyAbs);
|
|
11347
11590
|
if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
|
|
11348
11591
|
return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
|
|
@@ -11358,20 +11601,20 @@ function skillGuidelines(content, source) {
|
|
|
11358
11601
|
};
|
|
11359
11602
|
}
|
|
11360
11603
|
function ensureReviewSkillFile(worktreePath) {
|
|
11361
|
-
const abs = (0,
|
|
11604
|
+
const abs = (0, import_node_path28.join)(worktreePath, REVIEW_SKILL_PATH);
|
|
11362
11605
|
const existing = readTextIfPresent(abs);
|
|
11363
11606
|
if (existing) {
|
|
11364
11607
|
return { path: REVIEW_SKILL_PATH, content: existing, wrote: false };
|
|
11365
11608
|
}
|
|
11366
|
-
const fromRepo = readTextIfPresent((0,
|
|
11609
|
+
const fromRepo = readTextIfPresent((0, import_node_path28.join)(worktreePath, REPO_REVIEW_PATH));
|
|
11367
11610
|
const fromLocal = readLocalGuidelines(worktreePath)?.content ?? null;
|
|
11368
11611
|
const content = wrapReviewSkillMarkdown(fromRepo ?? fromLocal ?? REVIEW_REQUEST_TEMPLATE);
|
|
11369
|
-
(0,
|
|
11370
|
-
(0,
|
|
11612
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path28.dirname)(abs), { recursive: true });
|
|
11613
|
+
(0, import_node_fs28.writeFileSync)(abs, content, "utf8");
|
|
11371
11614
|
return { path: REVIEW_SKILL_PATH, content, wrote: true };
|
|
11372
11615
|
}
|
|
11373
11616
|
function resolveReviewGuidelines(worktreePath) {
|
|
11374
|
-
const skillContent = readTextIfPresent((0,
|
|
11617
|
+
const skillContent = readTextIfPresent((0, import_node_path28.join)(worktreePath, REVIEW_SKILL_PATH));
|
|
11375
11618
|
if (skillContent) return skillGuidelines(skillContent, "skill");
|
|
11376
11619
|
const local = readLocalGuidelines(worktreePath);
|
|
11377
11620
|
if (local) {
|
|
@@ -11389,7 +11632,7 @@ function buildReviewRequestAttachment(content, opts) {
|
|
|
11389
11632
|
const path = opts?.path ?? REVIEW_SKILL_PATH;
|
|
11390
11633
|
const name = opts?.name ?? (path === REVIEW_SKILL_PATH ? REVIEW_SKILL_NAME : path === REPO_REVIEW_PATH ? REPO_REVIEW_NAME : REVIEW_REQUEST_NAME);
|
|
11391
11634
|
return {
|
|
11392
|
-
id: (0,
|
|
11635
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
11393
11636
|
name,
|
|
11394
11637
|
kind: "file",
|
|
11395
11638
|
path,
|
|
@@ -11421,13 +11664,13 @@ async function requestReview(threadRef, send) {
|
|
|
11421
11664
|
const started = await send(tab.id, REVIEW_REQUEST_PREFILL);
|
|
11422
11665
|
return { tab: started, from };
|
|
11423
11666
|
}
|
|
11424
|
-
var
|
|
11667
|
+
var import_node_crypto6, import_node_fs28, import_node_path28, REPO_REVIEW_PATH, REPO_REVIEW_NAME, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
|
|
11425
11668
|
var init_request_review = __esm({
|
|
11426
11669
|
"src/review/request-review.ts"() {
|
|
11427
11670
|
"use strict";
|
|
11428
|
-
|
|
11429
|
-
|
|
11430
|
-
|
|
11671
|
+
import_node_crypto6 = require("crypto");
|
|
11672
|
+
import_node_fs28 = require("fs");
|
|
11673
|
+
import_node_path28 = require("path");
|
|
11431
11674
|
init_global_workspace();
|
|
11432
11675
|
init_chat_tabs();
|
|
11433
11676
|
init_thread_store();
|
|
@@ -11452,9 +11695,9 @@ function matchSimpleGlob(pattern, name) {
|
|
|
11452
11695
|
return new RegExp(`^${escaped}$`).test(name);
|
|
11453
11696
|
}
|
|
11454
11697
|
function readWorktreeInclude(repoPath) {
|
|
11455
|
-
const path = (0,
|
|
11456
|
-
if (!(0,
|
|
11457
|
-
return (0,
|
|
11698
|
+
const path = (0, import_node_path29.join)(repoPath, ".worktreeinclude");
|
|
11699
|
+
if (!(0, import_node_fs29.existsSync)(path)) return [];
|
|
11700
|
+
return (0, import_node_fs29.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
11458
11701
|
}
|
|
11459
11702
|
function resolveFilesToCopy(repoPath) {
|
|
11460
11703
|
const fromInclude = readWorktreeInclude(repoPath);
|
|
@@ -11464,10 +11707,10 @@ function resolveFilesToCopy(repoPath) {
|
|
|
11464
11707
|
if (settings?.fileIncludeGlobs?.length) {
|
|
11465
11708
|
const matched = [];
|
|
11466
11709
|
try {
|
|
11467
|
-
for (const entry of (0,
|
|
11710
|
+
for (const entry of (0, import_node_fs29.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
11468
11711
|
if (!entry.isFile()) continue;
|
|
11469
11712
|
for (const glob of settings.fileIncludeGlobs) {
|
|
11470
|
-
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0,
|
|
11713
|
+
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path29.basename)(glob), entry.name)) {
|
|
11471
11714
|
matched.push(entry.name);
|
|
11472
11715
|
break;
|
|
11473
11716
|
}
|
|
@@ -11479,7 +11722,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
11479
11722
|
}
|
|
11480
11723
|
const defaults = [];
|
|
11481
11724
|
try {
|
|
11482
|
-
for (const entry of (0,
|
|
11725
|
+
for (const entry of (0, import_node_fs29.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
11483
11726
|
if (entry.isFile() && entry.name.startsWith(".env")) {
|
|
11484
11727
|
defaults.push(entry.name);
|
|
11485
11728
|
}
|
|
@@ -11493,11 +11736,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
|
|
|
11493
11736
|
const patterns = resolveFilesToCopy(repoPath);
|
|
11494
11737
|
const copied = [];
|
|
11495
11738
|
for (const rel of patterns) {
|
|
11496
|
-
const src = (0,
|
|
11497
|
-
if (!(0,
|
|
11498
|
-
const dest = (0,
|
|
11499
|
-
(0,
|
|
11500
|
-
(0,
|
|
11739
|
+
const src = (0, import_node_path29.join)(repoPath, rel);
|
|
11740
|
+
if (!(0, import_node_fs29.existsSync)(src)) continue;
|
|
11741
|
+
const dest = (0, import_node_path29.join)(worktreePath, rel);
|
|
11742
|
+
(0, import_node_fs29.mkdirSync)((0, import_node_path29.dirname)(dest), { recursive: true });
|
|
11743
|
+
(0, import_node_fs29.copyFileSync)(src, dest);
|
|
11501
11744
|
copied.push(rel);
|
|
11502
11745
|
}
|
|
11503
11746
|
return copied;
|
|
@@ -11532,7 +11775,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
|
|
|
11532
11775
|
const env = stripNestedElectronEnv({
|
|
11533
11776
|
...baseEnv ?? process.env
|
|
11534
11777
|
});
|
|
11535
|
-
const name = opts.workspaceName ?? (0,
|
|
11778
|
+
const name = opts.workspaceName ?? (0, import_node_path29.basename)(opts.worktreePath);
|
|
11536
11779
|
const ports = opts.ports ?? [];
|
|
11537
11780
|
const primary = ports[0];
|
|
11538
11781
|
env.SIDEBOARD_WORKSPACE_NAME = name;
|
|
@@ -11793,13 +12036,13 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
|
11793
12036
|
done: handle.done
|
|
11794
12037
|
};
|
|
11795
12038
|
}
|
|
11796
|
-
var
|
|
12039
|
+
var import_node_fs29, import_node_net, import_node_path29, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
|
|
11797
12040
|
var init_conductor = __esm({
|
|
11798
12041
|
"src/hook/conductor.ts"() {
|
|
11799
12042
|
"use strict";
|
|
11800
|
-
|
|
12043
|
+
import_node_fs29 = require("fs");
|
|
11801
12044
|
import_node_net = require("net");
|
|
11802
|
-
|
|
12045
|
+
import_node_path29 = require("path");
|
|
11803
12046
|
import_execa4 = require("execa");
|
|
11804
12047
|
import_node_readline3 = require("readline");
|
|
11805
12048
|
init_settings();
|
|
@@ -11825,9 +12068,9 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11825
12068
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
11826
12069
|
);
|
|
11827
12070
|
const homeRoot = sideboardWorkspacesDir();
|
|
11828
|
-
if ((0,
|
|
12071
|
+
if ((0, import_node_fs30.existsSync)(homeRoot)) {
|
|
11829
12072
|
try {
|
|
11830
|
-
for (const entry of (0,
|
|
12073
|
+
for (const entry of (0, import_node_fs30.readdirSync)(homeRoot, { withFileTypes: true })) {
|
|
11831
12074
|
if (!entry.isDirectory()) continue;
|
|
11832
12075
|
void entry;
|
|
11833
12076
|
}
|
|
@@ -11837,7 +12080,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11837
12080
|
const orphans = [];
|
|
11838
12081
|
const seen = /* @__PURE__ */ new Set();
|
|
11839
12082
|
for (const repoPath of repos) {
|
|
11840
|
-
if (!repoPath || !(0,
|
|
12083
|
+
if (!repoPath || !(0, import_node_fs30.existsSync)(repoPath)) continue;
|
|
11841
12084
|
try {
|
|
11842
12085
|
const wts = await listWorktrees(repoPath);
|
|
11843
12086
|
for (const wt of wts) {
|
|
@@ -11848,7 +12091,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11848
12091
|
seen.add(path);
|
|
11849
12092
|
let mtimeMs = 0;
|
|
11850
12093
|
try {
|
|
11851
|
-
mtimeMs = (0,
|
|
12094
|
+
mtimeMs = (0, import_node_fs30.statSync)(path).mtimeMs;
|
|
11852
12095
|
} catch {
|
|
11853
12096
|
mtimeMs = 0;
|
|
11854
12097
|
}
|
|
@@ -11858,16 +12101,16 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11858
12101
|
}
|
|
11859
12102
|
try {
|
|
11860
12103
|
const root = worktreesRoot(repoPath);
|
|
11861
|
-
if ((0,
|
|
11862
|
-
for (const entry of (0,
|
|
12104
|
+
if ((0, import_node_fs30.existsSync)(root)) {
|
|
12105
|
+
for (const entry of (0, import_node_fs30.readdirSync)(root, { withFileTypes: true })) {
|
|
11863
12106
|
if (!entry.isDirectory()) continue;
|
|
11864
|
-
const path = (0,
|
|
12107
|
+
const path = (0, import_node_path30.join)(root, entry.name).replace(/\/$/, "");
|
|
11865
12108
|
if (known.has(path) || seen.has(path)) continue;
|
|
11866
|
-
if (!(0,
|
|
12109
|
+
if (!(0, import_node_fs30.existsSync)((0, import_node_path30.join)(path, ".git"))) continue;
|
|
11867
12110
|
seen.add(path);
|
|
11868
12111
|
let mtimeMs = 0;
|
|
11869
12112
|
try {
|
|
11870
|
-
mtimeMs = (0,
|
|
12113
|
+
mtimeMs = (0, import_node_fs30.statSync)(path).mtimeMs;
|
|
11871
12114
|
} catch {
|
|
11872
12115
|
mtimeMs = Date.now();
|
|
11873
12116
|
}
|
|
@@ -11919,12 +12162,12 @@ function shouldRunWorktreeCleanup(settings = loadAppSettings()) {
|
|
|
11919
12162
|
const elapsed = Date.now() - Date.parse(last);
|
|
11920
12163
|
return elapsed >= intervalHours * 36e5;
|
|
11921
12164
|
}
|
|
11922
|
-
var
|
|
12165
|
+
var import_node_fs30, import_node_path30;
|
|
11923
12166
|
var init_orphan_cleanup = __esm({
|
|
11924
12167
|
"src/git/orphan-cleanup.ts"() {
|
|
11925
12168
|
"use strict";
|
|
11926
|
-
|
|
11927
|
-
|
|
12169
|
+
import_node_fs30 = require("fs");
|
|
12170
|
+
import_node_path30 = require("path");
|
|
11928
12171
|
init_worktree();
|
|
11929
12172
|
init_thread_store();
|
|
11930
12173
|
init_paths();
|
|
@@ -12031,38 +12274,38 @@ __export(workspaces_exports, {
|
|
|
12031
12274
|
syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
|
|
12032
12275
|
});
|
|
12033
12276
|
function workspacesFile() {
|
|
12034
|
-
return (0,
|
|
12277
|
+
return (0, import_node_path31.join)(appDataDir(), "workspaces.json");
|
|
12035
12278
|
}
|
|
12036
12279
|
function removedWorkspacesFile() {
|
|
12037
|
-
return (0,
|
|
12280
|
+
return (0, import_node_path31.join)(appDataDir(), "removed-workspaces.json");
|
|
12038
12281
|
}
|
|
12039
12282
|
function readAll() {
|
|
12040
12283
|
const path = workspacesFile();
|
|
12041
|
-
if (!(0,
|
|
12284
|
+
if (!(0, import_node_fs31.existsSync)(path)) return [];
|
|
12042
12285
|
try {
|
|
12043
|
-
const raw = JSON.parse((0,
|
|
12286
|
+
const raw = JSON.parse((0, import_node_fs31.readFileSync)(path, "utf8"));
|
|
12044
12287
|
return Array.isArray(raw) ? raw : [];
|
|
12045
12288
|
} catch {
|
|
12046
12289
|
return [];
|
|
12047
12290
|
}
|
|
12048
12291
|
}
|
|
12049
12292
|
function writeAll(list) {
|
|
12050
|
-
(0,
|
|
12051
|
-
(0,
|
|
12293
|
+
(0, import_node_fs31.mkdirSync)(appDataDir(), { recursive: true });
|
|
12294
|
+
(0, import_node_fs31.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
|
|
12052
12295
|
}
|
|
12053
12296
|
function readRemoved() {
|
|
12054
12297
|
const path = removedWorkspacesFile();
|
|
12055
|
-
if (!(0,
|
|
12298
|
+
if (!(0, import_node_fs31.existsSync)(path)) return /* @__PURE__ */ new Set();
|
|
12056
12299
|
try {
|
|
12057
|
-
const raw = JSON.parse((0,
|
|
12300
|
+
const raw = JSON.parse((0, import_node_fs31.readFileSync)(path, "utf8"));
|
|
12058
12301
|
return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
|
|
12059
12302
|
} catch {
|
|
12060
12303
|
return /* @__PURE__ */ new Set();
|
|
12061
12304
|
}
|
|
12062
12305
|
}
|
|
12063
12306
|
function writeRemoved(paths) {
|
|
12064
|
-
(0,
|
|
12065
|
-
(0,
|
|
12307
|
+
(0, import_node_fs31.mkdirSync)(appDataDir(), { recursive: true });
|
|
12308
|
+
(0, import_node_fs31.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
|
|
12066
12309
|
}
|
|
12067
12310
|
function rememberRemoved(repoPath) {
|
|
12068
12311
|
const next = readRemoved();
|
|
@@ -12085,7 +12328,7 @@ function listWorkspaces() {
|
|
|
12085
12328
|
async function addWorkspace(repoPath) {
|
|
12086
12329
|
const root = await resolveRepoRoot(repoPath);
|
|
12087
12330
|
if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
|
|
12088
|
-
if (!(0,
|
|
12331
|
+
if (!(0, import_node_fs31.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
|
|
12089
12332
|
forgetRemoved(root);
|
|
12090
12333
|
await ensureGhPreferOrigin(root);
|
|
12091
12334
|
const current = readAll();
|
|
@@ -12093,7 +12336,7 @@ async function addWorkspace(repoPath) {
|
|
|
12093
12336
|
if (existing) return existing;
|
|
12094
12337
|
const next = {
|
|
12095
12338
|
path: root,
|
|
12096
|
-
name: (0,
|
|
12339
|
+
name: (0, import_node_path31.basename)(root),
|
|
12097
12340
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12098
12341
|
};
|
|
12099
12342
|
writeAll([...current, next]);
|
|
@@ -12115,10 +12358,10 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
12115
12358
|
if (!path || path === "/" || isGlobalRepoPath(path) || byPath.has(path) || removed.has(path)) {
|
|
12116
12359
|
continue;
|
|
12117
12360
|
}
|
|
12118
|
-
if (!(0,
|
|
12361
|
+
if (!(0, import_node_fs31.existsSync)(path)) continue;
|
|
12119
12362
|
const ws = {
|
|
12120
12363
|
path,
|
|
12121
|
-
name: (0,
|
|
12364
|
+
name: (0, import_node_path31.basename)(path),
|
|
12122
12365
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12123
12366
|
};
|
|
12124
12367
|
byPath.set(path, ws);
|
|
@@ -12128,12 +12371,12 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
12128
12371
|
if (dirty) writeAll(next);
|
|
12129
12372
|
return next.sort((a, b) => a.name.localeCompare(b.name));
|
|
12130
12373
|
}
|
|
12131
|
-
var
|
|
12374
|
+
var import_node_fs31, import_node_path31;
|
|
12132
12375
|
var init_workspaces2 = __esm({
|
|
12133
12376
|
"src/store/workspaces.ts"() {
|
|
12134
12377
|
"use strict";
|
|
12135
|
-
|
|
12136
|
-
|
|
12378
|
+
import_node_fs31 = require("fs");
|
|
12379
|
+
import_node_path31 = require("path");
|
|
12137
12380
|
init_paths();
|
|
12138
12381
|
init_global_workspace();
|
|
12139
12382
|
init_worktree();
|
|
@@ -12146,12 +12389,12 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
12146
12389
|
if (!url) throw new Error("Clone URL is required");
|
|
12147
12390
|
let name = opts.name?.trim();
|
|
12148
12391
|
if (!name) {
|
|
12149
|
-
const leaf = (0,
|
|
12392
|
+
const leaf = (0, import_node_path32.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
|
|
12150
12393
|
name = leaf || "repo";
|
|
12151
12394
|
}
|
|
12152
12395
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
12153
|
-
const dest = (0,
|
|
12154
|
-
if ((0,
|
|
12396
|
+
const dest = (0, import_node_path32.join)(sideboardReposDir(), name);
|
|
12397
|
+
if ((0, import_node_fs32.existsSync)(dest)) {
|
|
12155
12398
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
12156
12399
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
12157
12400
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -12166,12 +12409,12 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
12166
12409
|
const workspace = await ensureWorkspace(repoPath);
|
|
12167
12410
|
return { repoPath, workspace };
|
|
12168
12411
|
}
|
|
12169
|
-
var
|
|
12412
|
+
var import_node_fs32, import_node_path32, import_execa6;
|
|
12170
12413
|
var init_clone_repo = __esm({
|
|
12171
12414
|
"src/git/clone-repo.ts"() {
|
|
12172
12415
|
"use strict";
|
|
12173
|
-
|
|
12174
|
-
|
|
12416
|
+
import_node_fs32 = require("fs");
|
|
12417
|
+
import_node_path32 = require("path");
|
|
12175
12418
|
import_execa6 = require("execa");
|
|
12176
12419
|
init_paths();
|
|
12177
12420
|
init_workspaces2();
|
|
@@ -12181,11 +12424,11 @@ var init_clone_repo = __esm({
|
|
|
12181
12424
|
|
|
12182
12425
|
// src/store/desktop-host.ts
|
|
12183
12426
|
function desktopHostPidPath() {
|
|
12184
|
-
return (0,
|
|
12427
|
+
return (0, import_node_path33.join)(appDataDir(), "desktop-host.pid");
|
|
12185
12428
|
}
|
|
12186
12429
|
function readDesktopHostPid() {
|
|
12187
12430
|
try {
|
|
12188
|
-
const pid = Number.parseInt((0,
|
|
12431
|
+
const pid = Number.parseInt((0, import_node_fs33.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
|
|
12189
12432
|
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
12190
12433
|
return pid;
|
|
12191
12434
|
} catch {
|
|
@@ -12211,16 +12454,63 @@ function thisProcessShouldDrainAgentQueues() {
|
|
|
12211
12454
|
if (isThisProcessDesktopHost()) return true;
|
|
12212
12455
|
return !isDesktopHostAlive();
|
|
12213
12456
|
}
|
|
12214
|
-
var
|
|
12457
|
+
var import_node_fs33, import_node_path33;
|
|
12215
12458
|
var init_desktop_host = __esm({
|
|
12216
12459
|
"src/store/desktop-host.ts"() {
|
|
12217
12460
|
"use strict";
|
|
12218
|
-
|
|
12219
|
-
|
|
12461
|
+
import_node_fs33 = require("fs");
|
|
12462
|
+
import_node_path33 = require("path");
|
|
12220
12463
|
init_paths();
|
|
12221
12464
|
}
|
|
12222
12465
|
});
|
|
12223
12466
|
|
|
12467
|
+
// src/orchestrator/child-halt.ts
|
|
12468
|
+
function isIncompleteChildStatus(status) {
|
|
12469
|
+
return HALT_STATUSES.has(status);
|
|
12470
|
+
}
|
|
12471
|
+
function childHaltNotice(child, status) {
|
|
12472
|
+
const title = child.title?.trim() || "Untitled";
|
|
12473
|
+
const link = `[${title}](sideboard://thread/${child.id})`;
|
|
12474
|
+
const why = child.lastError?.trim();
|
|
12475
|
+
const extra = why ? ` lastError: ${why}` : "";
|
|
12476
|
+
return [
|
|
12477
|
+
`Sideboard: child worktree ${link} ${status} before finishing (status=${status}).${extra}`,
|
|
12478
|
+
"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."
|
|
12479
|
+
].join("\n");
|
|
12480
|
+
}
|
|
12481
|
+
function shouldNotifyParentOfChildHalt(opts) {
|
|
12482
|
+
if (!isIncompleteChildStatus(opts.status)) return false;
|
|
12483
|
+
if (!opts.child.parentThreadId) return false;
|
|
12484
|
+
if (!opts.parent || opts.parent.status === "archived") return false;
|
|
12485
|
+
if (opts.parent.id === opts.child.id) return false;
|
|
12486
|
+
return isOrchestratorThread(opts.parent);
|
|
12487
|
+
}
|
|
12488
|
+
function noticeKey(childId, status) {
|
|
12489
|
+
return `${childId}:${status}`;
|
|
12490
|
+
}
|
|
12491
|
+
function notifyParentOfChildHalt(child, status, send) {
|
|
12492
|
+
const parent = child.parentThreadId ? readThread(child.parentThreadId) : null;
|
|
12493
|
+
if (!shouldNotifyParentOfChildHalt({ child, parent, status })) return false;
|
|
12494
|
+
const key = noticeKey(child.id, status);
|
|
12495
|
+
if (notified.has(key)) return false;
|
|
12496
|
+
notified.add(key);
|
|
12497
|
+
const parentId = parent.id;
|
|
12498
|
+
void send(parentId, childHaltNotice(child, status)).catch(() => {
|
|
12499
|
+
notified.delete(key);
|
|
12500
|
+
});
|
|
12501
|
+
return true;
|
|
12502
|
+
}
|
|
12503
|
+
var HALT_STATUSES, notified;
|
|
12504
|
+
var init_child_halt = __esm({
|
|
12505
|
+
"src/orchestrator/child-halt.ts"() {
|
|
12506
|
+
"use strict";
|
|
12507
|
+
init_global_workspace();
|
|
12508
|
+
init_thread_store();
|
|
12509
|
+
HALT_STATUSES = /* @__PURE__ */ new Set(["stopped", "error", "broken"]);
|
|
12510
|
+
notified = /* @__PURE__ */ new Set();
|
|
12511
|
+
}
|
|
12512
|
+
});
|
|
12513
|
+
|
|
12224
12514
|
// src/detect/detect.ts
|
|
12225
12515
|
async function requireAgent(agent, opts) {
|
|
12226
12516
|
ensureAgentPath();
|
|
@@ -13166,9 +13456,12 @@ var init_abletime = __esm({
|
|
|
13166
13456
|
});
|
|
13167
13457
|
|
|
13168
13458
|
// src/threads/create.ts
|
|
13459
|
+
function persistCreateAttachments(worktreePath, attachments) {
|
|
13460
|
+
return persistPendingFileAttachments(worktreePath, attachments ?? []);
|
|
13461
|
+
}
|
|
13169
13462
|
async function createThread(input, _onSetupLine) {
|
|
13170
13463
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
13171
|
-
if (!(0,
|
|
13464
|
+
if (!(0, import_node_fs34.existsSync)(repoPath)) {
|
|
13172
13465
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
13173
13466
|
}
|
|
13174
13467
|
if (input.reuseExisting !== false) {
|
|
@@ -13185,7 +13478,16 @@ async function createThread(input, _onSetupLine) {
|
|
|
13185
13478
|
repoPath: canonicalizeRepoPath(t.repoPath)
|
|
13186
13479
|
}))
|
|
13187
13480
|
);
|
|
13188
|
-
if (existing)
|
|
13481
|
+
if (existing) {
|
|
13482
|
+
const thread2 = readThread(existing.id) ?? existing;
|
|
13483
|
+
if (!input.attachments?.length) return thread2;
|
|
13484
|
+
return updateThread(thread2.id, {
|
|
13485
|
+
attachments: persistCreateAttachments(thread2.worktreePath, [
|
|
13486
|
+
...thread2.attachments,
|
|
13487
|
+
...input.attachments
|
|
13488
|
+
])
|
|
13489
|
+
});
|
|
13490
|
+
}
|
|
13189
13491
|
}
|
|
13190
13492
|
const resolved = resolveNewThreadOptions({
|
|
13191
13493
|
agent: input.agent,
|
|
@@ -13233,7 +13535,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
13233
13535
|
effort: resolved.effort,
|
|
13234
13536
|
fast: resolved.fast,
|
|
13235
13537
|
planMode: Boolean(input.planMode),
|
|
13236
|
-
attachments: input.attachments
|
|
13538
|
+
attachments: persistCreateAttachments(repoPath, input.attachments),
|
|
13237
13539
|
sourceIsFork: false,
|
|
13238
13540
|
parentThreadId: input.parentThreadId ?? null,
|
|
13239
13541
|
status: "idle",
|
|
@@ -13312,7 +13614,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
13312
13614
|
effort: resolved.effort,
|
|
13313
13615
|
fast: resolved.fast,
|
|
13314
13616
|
planMode: Boolean(input.planMode),
|
|
13315
|
-
attachments,
|
|
13617
|
+
attachments: persistCreateAttachments(worktreePath, attachments),
|
|
13316
13618
|
sourceIsFork,
|
|
13317
13619
|
parentThreadId: input.parentThreadId ?? null,
|
|
13318
13620
|
status: "idle",
|
|
@@ -13332,16 +13634,17 @@ async function listLinearIssues(agent, repoPath) {
|
|
|
13332
13634
|
}
|
|
13333
13635
|
return adapter.listLinearIssues(repoPath);
|
|
13334
13636
|
}
|
|
13335
|
-
var
|
|
13637
|
+
var import_node_fs34;
|
|
13336
13638
|
var init_create = __esm({
|
|
13337
13639
|
"src/threads/create.ts"() {
|
|
13338
13640
|
"use strict";
|
|
13339
|
-
|
|
13641
|
+
import_node_fs34 = require("fs");
|
|
13340
13642
|
init_detect();
|
|
13341
13643
|
init_worktree();
|
|
13342
13644
|
init_home_board();
|
|
13343
13645
|
init_conductor();
|
|
13344
13646
|
init_app_settings();
|
|
13647
|
+
init_stage_files();
|
|
13345
13648
|
init_thread_store();
|
|
13346
13649
|
init_workspaces2();
|
|
13347
13650
|
}
|
|
@@ -13438,20 +13741,20 @@ function writeTurnLive(threadId, progress) {
|
|
|
13438
13741
|
const path = threadLivePath(threadId);
|
|
13439
13742
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
13440
13743
|
try {
|
|
13441
|
-
(0,
|
|
13442
|
-
(0,
|
|
13744
|
+
(0, import_node_fs35.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
|
|
13745
|
+
(0, import_node_fs35.renameSync)(tmp, path);
|
|
13443
13746
|
} catch {
|
|
13444
13747
|
try {
|
|
13445
|
-
(0,
|
|
13748
|
+
(0, import_node_fs35.unlinkSync)(tmp);
|
|
13446
13749
|
} catch {
|
|
13447
13750
|
}
|
|
13448
13751
|
}
|
|
13449
13752
|
}
|
|
13450
13753
|
function readTurnLive(threadId) {
|
|
13451
13754
|
const path = threadLivePath(threadId);
|
|
13452
|
-
if (!(0,
|
|
13755
|
+
if (!(0, import_node_fs35.existsSync)(path)) return null;
|
|
13453
13756
|
try {
|
|
13454
|
-
const raw = JSON.parse((0,
|
|
13757
|
+
const raw = JSON.parse((0, import_node_fs35.readFileSync)(path, "utf8"));
|
|
13455
13758
|
if (!raw || typeof raw.summary !== "string") return null;
|
|
13456
13759
|
return raw;
|
|
13457
13760
|
} catch {
|
|
@@ -13463,17 +13766,17 @@ function clearTurnLive(threadId) {
|
|
|
13463
13766
|
if (buf?.timer) clearTimeout(buf.timer);
|
|
13464
13767
|
buffers.delete(threadId);
|
|
13465
13768
|
const path = threadLivePath(threadId);
|
|
13466
|
-
if (!(0,
|
|
13769
|
+
if (!(0, import_node_fs35.existsSync)(path)) return;
|
|
13467
13770
|
try {
|
|
13468
|
-
(0,
|
|
13771
|
+
(0, import_node_fs35.unlinkSync)(path);
|
|
13469
13772
|
} catch {
|
|
13470
13773
|
}
|
|
13471
13774
|
}
|
|
13472
|
-
var
|
|
13775
|
+
var import_node_fs35, buffers, FLUSH_MS, MAX_PARTS;
|
|
13473
13776
|
var init_turn_live = __esm({
|
|
13474
13777
|
"src/store/turn-live.ts"() {
|
|
13475
13778
|
"use strict";
|
|
13476
|
-
|
|
13779
|
+
import_node_fs35 = require("fs");
|
|
13477
13780
|
init_message_parts();
|
|
13478
13781
|
init_paths();
|
|
13479
13782
|
buffers = /* @__PURE__ */ new Map();
|
|
@@ -13632,7 +13935,7 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
|
|
|
13632
13935
|
`- Do not wait on the limited ${from.agent} account; keep going on ${fallbackAgent}.`
|
|
13633
13936
|
].join("\n");
|
|
13634
13937
|
return {
|
|
13635
|
-
id: (0,
|
|
13938
|
+
id: (0, import_node_crypto7.randomUUID)(),
|
|
13636
13939
|
name: "Orchestration quota handoff.md",
|
|
13637
13940
|
kind: "transcript",
|
|
13638
13941
|
content: body
|
|
@@ -13653,11 +13956,11 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
|
|
|
13653
13956
|
sourceType: "orchestration"
|
|
13654
13957
|
});
|
|
13655
13958
|
}
|
|
13656
|
-
var
|
|
13959
|
+
var import_node_crypto7, QUOTA_CONTINUE_PROMPT, QUOTA_RESUME_PROMPT;
|
|
13657
13960
|
var init_quota_failover = __esm({
|
|
13658
13961
|
"src/orchestrator/quota-failover.ts"() {
|
|
13659
13962
|
"use strict";
|
|
13660
|
-
|
|
13963
|
+
import_node_crypto7 = require("crypto");
|
|
13661
13964
|
init_session_quota();
|
|
13662
13965
|
init_app_settings();
|
|
13663
13966
|
init_global_workspace();
|
|
@@ -13674,7 +13977,7 @@ var init_quota_failover = __esm({
|
|
|
13674
13977
|
// src/threads/adopt.ts
|
|
13675
13978
|
function thisModuleFile() {
|
|
13676
13979
|
const cjsFile = typeof __filename !== "undefined" ? __filename : "";
|
|
13677
|
-
return cjsFile || process.argv[1] || (0,
|
|
13980
|
+
return cjsFile || process.argv[1] || (0, import_node_path34.join)(process.cwd(), "package.json");
|
|
13678
13981
|
}
|
|
13679
13982
|
function openReadonlySqlite(file) {
|
|
13680
13983
|
const req = (0, import_node_module4.createRequire)(thisModuleFile());
|
|
@@ -13692,21 +13995,21 @@ function mapAgentType(raw) {
|
|
|
13692
13995
|
return null;
|
|
13693
13996
|
}
|
|
13694
13997
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
13695
|
-
if (!workspacePath || !(0,
|
|
13998
|
+
if (!workspacePath || !(0, import_node_fs36.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
13696
13999
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
13697
14000
|
let best = null;
|
|
13698
14001
|
let hashes;
|
|
13699
14002
|
try {
|
|
13700
|
-
hashes = (0,
|
|
14003
|
+
hashes = (0, import_node_fs36.readdirSync)(CURSOR_SDK_STORE);
|
|
13701
14004
|
} catch {
|
|
13702
14005
|
return null;
|
|
13703
14006
|
}
|
|
13704
14007
|
for (const hash of hashes) {
|
|
13705
|
-
const agentsFile = (0,
|
|
13706
|
-
if (!(0,
|
|
14008
|
+
const agentsFile = (0, import_node_path34.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
14009
|
+
if (!(0, import_node_fs36.existsSync)(agentsFile)) continue;
|
|
13707
14010
|
let text5;
|
|
13708
14011
|
try {
|
|
13709
|
-
text5 = (0,
|
|
14012
|
+
text5 = (0, import_node_fs36.readFileSync)(agentsFile, "utf8");
|
|
13710
14013
|
} catch {
|
|
13711
14014
|
continue;
|
|
13712
14015
|
}
|
|
@@ -13730,7 +14033,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
13730
14033
|
return best?.agentId ?? null;
|
|
13731
14034
|
}
|
|
13732
14035
|
async function adoptThread(input) {
|
|
13733
|
-
if (!(0,
|
|
14036
|
+
if (!(0, import_node_fs36.existsSync)(input.worktreePath)) {
|
|
13734
14037
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
13735
14038
|
}
|
|
13736
14039
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -13754,18 +14057,18 @@ async function adoptThread(input) {
|
|
|
13754
14057
|
return thread;
|
|
13755
14058
|
}
|
|
13756
14059
|
function listConductorWorkspaces() {
|
|
13757
|
-
if (!(0,
|
|
14060
|
+
if (!(0, import_node_fs36.existsSync)(CONDUCTOR_DB)) {
|
|
13758
14061
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
13759
14062
|
}
|
|
13760
|
-
const tmp = (0,
|
|
13761
|
-
const snapshot = (0,
|
|
14063
|
+
const tmp = (0, import_node_fs36.mkdtempSync)((0, import_node_path34.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
|
|
14064
|
+
const snapshot = (0, import_node_path34.join)(tmp, "conductor.db");
|
|
13762
14065
|
try {
|
|
13763
|
-
(0,
|
|
14066
|
+
(0, import_node_fs36.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
13764
14067
|
for (const suffix of ["-wal", "-shm"]) {
|
|
13765
14068
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
13766
|
-
if ((0,
|
|
14069
|
+
if ((0, import_node_fs36.existsSync)(src)) {
|
|
13767
14070
|
try {
|
|
13768
|
-
(0,
|
|
14071
|
+
(0, import_node_fs36.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
13769
14072
|
} catch {
|
|
13770
14073
|
}
|
|
13771
14074
|
}
|
|
@@ -13841,22 +14144,22 @@ function listConductorWorkspaces() {
|
|
|
13841
14144
|
db.close();
|
|
13842
14145
|
}
|
|
13843
14146
|
} finally {
|
|
13844
|
-
(0,
|
|
14147
|
+
(0, import_node_fs36.rmSync)(tmp, { recursive: true, force: true });
|
|
13845
14148
|
}
|
|
13846
14149
|
}
|
|
13847
14150
|
function importConductorWorkspace(workspaceId) {
|
|
13848
|
-
if (!(0,
|
|
14151
|
+
if (!(0, import_node_fs36.existsSync)(CONDUCTOR_DB)) {
|
|
13849
14152
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
13850
14153
|
}
|
|
13851
|
-
const tmp = (0,
|
|
13852
|
-
const snapshot = (0,
|
|
14154
|
+
const tmp = (0, import_node_fs36.mkdtempSync)((0, import_node_path34.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
|
|
14155
|
+
const snapshot = (0, import_node_path34.join)(tmp, "conductor.db");
|
|
13853
14156
|
try {
|
|
13854
|
-
(0,
|
|
14157
|
+
(0, import_node_fs36.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
13855
14158
|
for (const suffix of ["-wal", "-shm"]) {
|
|
13856
14159
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
13857
|
-
if ((0,
|
|
14160
|
+
if ((0, import_node_fs36.existsSync)(src)) {
|
|
13858
14161
|
try {
|
|
13859
|
-
(0,
|
|
14162
|
+
(0, import_node_fs36.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
13860
14163
|
} catch {
|
|
13861
14164
|
}
|
|
13862
14165
|
}
|
|
@@ -13874,7 +14177,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
13874
14177
|
).get(workspaceId);
|
|
13875
14178
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
13876
14179
|
const worktreePath = String(row.workspacePath);
|
|
13877
|
-
if (!(0,
|
|
14180
|
+
if (!(0, import_node_fs36.existsSync)(worktreePath)) {
|
|
13878
14181
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
13879
14182
|
}
|
|
13880
14183
|
let sessionId = null;
|
|
@@ -13937,31 +14240,31 @@ function importConductorWorkspace(workspaceId) {
|
|
|
13937
14240
|
db.close();
|
|
13938
14241
|
}
|
|
13939
14242
|
} finally {
|
|
13940
|
-
(0,
|
|
14243
|
+
(0, import_node_fs36.rmSync)(tmp, { recursive: true, force: true });
|
|
13941
14244
|
}
|
|
13942
14245
|
}
|
|
13943
14246
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
13944
14247
|
return importConductorWorkspace(workspaceId);
|
|
13945
14248
|
}
|
|
13946
|
-
var import_node_child_process3,
|
|
14249
|
+
var import_node_child_process3, import_node_fs36, import_node_os10, import_node_path34, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
|
|
13947
14250
|
var init_adopt = __esm({
|
|
13948
14251
|
"src/threads/adopt.ts"() {
|
|
13949
14252
|
"use strict";
|
|
13950
14253
|
import_node_child_process3 = require("child_process");
|
|
13951
|
-
|
|
14254
|
+
import_node_fs36 = require("fs");
|
|
13952
14255
|
import_node_os10 = require("os");
|
|
13953
|
-
|
|
14256
|
+
import_node_path34 = require("path");
|
|
13954
14257
|
import_node_module4 = require("module");
|
|
13955
14258
|
init_worktree();
|
|
13956
14259
|
init_thread_store();
|
|
13957
|
-
CONDUCTOR_APP_SUPPORT = (0,
|
|
14260
|
+
CONDUCTOR_APP_SUPPORT = (0, import_node_path34.join)(
|
|
13958
14261
|
process.env.HOME ?? "",
|
|
13959
14262
|
"Library",
|
|
13960
14263
|
"Application Support",
|
|
13961
14264
|
"com.conductor.app"
|
|
13962
14265
|
);
|
|
13963
|
-
CONDUCTOR_DB = (0,
|
|
13964
|
-
CURSOR_SDK_STORE = (0,
|
|
14266
|
+
CONDUCTOR_DB = (0, import_node_path34.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
14267
|
+
CURSOR_SDK_STORE = (0, import_node_path34.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
13965
14268
|
}
|
|
13966
14269
|
});
|
|
13967
14270
|
|
|
@@ -14028,7 +14331,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
14028
14331
|
let createdWorktree = false;
|
|
14029
14332
|
const trees = await listWorktrees(repoPath);
|
|
14030
14333
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
14031
|
-
if (checkedOut?.path && (0,
|
|
14334
|
+
if (checkedOut?.path && (0, import_node_fs37.existsSync)(checkedOut.path)) {
|
|
14032
14335
|
if (input.reuseExistingWorktree !== false) {
|
|
14033
14336
|
worktreePath = checkedOut.path;
|
|
14034
14337
|
} else {
|
|
@@ -14170,7 +14473,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
14170
14473
|
async function createPrStack(input, onSetupLine) {
|
|
14171
14474
|
await requireAgent(input.agent);
|
|
14172
14475
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
14173
|
-
if (!(0,
|
|
14476
|
+
if (!(0, import_node_fs37.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
14174
14477
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
14175
14478
|
const status = await detectGhStack(repoPath);
|
|
14176
14479
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -14237,7 +14540,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
14237
14540
|
}
|
|
14238
14541
|
}
|
|
14239
14542
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
14240
|
-
if (!claimed.has(bootstrap.worktreePath) && (0,
|
|
14543
|
+
if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs37.existsSync)(bootstrap.worktreePath)) {
|
|
14241
14544
|
try {
|
|
14242
14545
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
14243
14546
|
deleteBranch: bootstrap.branchName
|
|
@@ -14247,11 +14550,11 @@ async function createPrStack(input, onSetupLine) {
|
|
|
14247
14550
|
}
|
|
14248
14551
|
return { stack, threads, createdThreadIds };
|
|
14249
14552
|
}
|
|
14250
|
-
var
|
|
14553
|
+
var import_node_fs37;
|
|
14251
14554
|
var init_stack_layers = __esm({
|
|
14252
14555
|
"src/threads/stack-layers.ts"() {
|
|
14253
14556
|
"use strict";
|
|
14254
|
-
|
|
14557
|
+
import_node_fs37 = require("fs");
|
|
14255
14558
|
init_detect();
|
|
14256
14559
|
init_run();
|
|
14257
14560
|
init_stack();
|
|
@@ -14264,7 +14567,7 @@ var init_stack_layers = __esm({
|
|
|
14264
14567
|
|
|
14265
14568
|
// src/diff/diff.ts
|
|
14266
14569
|
async function inspectGitWorktree(worktreePath) {
|
|
14267
|
-
if (!worktreePath || !(0,
|
|
14570
|
+
if (!worktreePath || !(0, import_node_fs38.existsSync)(worktreePath)) return "missing_worktree";
|
|
14268
14571
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
14269
14572
|
reject: false
|
|
14270
14573
|
});
|
|
@@ -14272,7 +14575,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
14272
14575
|
return "ok";
|
|
14273
14576
|
}
|
|
14274
14577
|
async function initializeGitRepository(worktreePath) {
|
|
14275
|
-
if (!worktreePath || !(0,
|
|
14578
|
+
if (!worktreePath || !(0, import_node_fs38.existsSync)(worktreePath)) {
|
|
14276
14579
|
throw new Error("Worktree not found");
|
|
14277
14580
|
}
|
|
14278
14581
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -14406,11 +14709,11 @@ new file mode 100644
|
|
|
14406
14709
|
};
|
|
14407
14710
|
}
|
|
14408
14711
|
async function untrackedPatch(worktreePath, path, maxHunk) {
|
|
14409
|
-
const abs = (0,
|
|
14712
|
+
const abs = (0, import_node_path35.join)(worktreePath, path);
|
|
14410
14713
|
try {
|
|
14411
|
-
const st = (0,
|
|
14714
|
+
const st = (0, import_node_fs38.statSync)(abs);
|
|
14412
14715
|
if (st.isFile() && st.size > maxHunk) {
|
|
14413
|
-
const buf = (0,
|
|
14716
|
+
const buf = (0, import_node_fs38.readFileSync)(abs).subarray(0, maxHunk);
|
|
14414
14717
|
return syntheticAddPatch(path, buf.toString("utf8"), maxHunk);
|
|
14415
14718
|
}
|
|
14416
14719
|
} catch {
|
|
@@ -14894,13 +15197,13 @@ async function listWorktreeFiles(worktreePath, opts) {
|
|
|
14894
15197
|
function isImageRelativePath(relativePath) {
|
|
14895
15198
|
const base = relativePath.split("/").pop()?.toLowerCase() || "";
|
|
14896
15199
|
const ext = base.includes(".") ? base.split(".").pop() || "" : "";
|
|
14897
|
-
return
|
|
15200
|
+
return IMAGE_EXTENSIONS2.has(ext);
|
|
14898
15201
|
}
|
|
14899
15202
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
14900
15203
|
assertSafeRelativePath(relativePath);
|
|
14901
15204
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
14902
|
-
const abs = (0,
|
|
14903
|
-
const st = (0,
|
|
15205
|
+
const abs = (0, import_node_path35.join)(worktreePath, relativePath);
|
|
15206
|
+
const st = (0, import_node_fs38.statSync)(abs);
|
|
14904
15207
|
if (!st.isFile()) {
|
|
14905
15208
|
throw new Error(`Not a file: ${relativePath}`);
|
|
14906
15209
|
}
|
|
@@ -14909,7 +15212,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
14909
15212
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
14910
15213
|
);
|
|
14911
15214
|
}
|
|
14912
|
-
const buf = (0,
|
|
15215
|
+
const buf = (0, import_node_fs38.readFileSync)(abs);
|
|
14913
15216
|
return {
|
|
14914
15217
|
path: relativePath,
|
|
14915
15218
|
contentBase64: buf.toString("base64"),
|
|
@@ -14919,12 +15222,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
14919
15222
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
14920
15223
|
assertSafeRelativePath(relativePath);
|
|
14921
15224
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
14922
|
-
const abs = (0,
|
|
14923
|
-
const st = (0,
|
|
15225
|
+
const abs = (0, import_node_path35.join)(worktreePath, relativePath);
|
|
15226
|
+
const st = (0, import_node_fs38.statSync)(abs);
|
|
14924
15227
|
if (!st.isFile()) {
|
|
14925
15228
|
throw new Error(`Not a file: ${relativePath}`);
|
|
14926
15229
|
}
|
|
14927
|
-
const buf = (0,
|
|
15230
|
+
const buf = (0, import_node_fs38.readFileSync)(abs);
|
|
14928
15231
|
if (isImageRelativePath(relativePath)) {
|
|
14929
15232
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
14930
15233
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -14967,9 +15270,9 @@ function assertSafeRelativePath(relativePath) {
|
|
|
14967
15270
|
}
|
|
14968
15271
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
14969
15272
|
assertSafeRelativePath(relativePath);
|
|
14970
|
-
const abs = (0,
|
|
14971
|
-
(0,
|
|
14972
|
-
(0,
|
|
15273
|
+
const abs = (0, import_node_path35.join)(worktreePath, relativePath);
|
|
15274
|
+
(0, import_node_fs38.mkdirSync)((0, import_node_path35.dirname)(abs), { recursive: true });
|
|
15275
|
+
(0, import_node_fs38.writeFileSync)(abs, content, "utf8");
|
|
14973
15276
|
return { path: relativePath };
|
|
14974
15277
|
}
|
|
14975
15278
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
@@ -14986,18 +15289,18 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
|
14986
15289
|
truncated: full.files.length > maxFiles
|
|
14987
15290
|
};
|
|
14988
15291
|
}
|
|
14989
|
-
var
|
|
15292
|
+
var import_node_fs38, import_node_path35, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
|
|
14990
15293
|
var init_diff = __esm({
|
|
14991
15294
|
"src/diff/diff.ts"() {
|
|
14992
15295
|
"use strict";
|
|
14993
|
-
|
|
14994
|
-
|
|
15296
|
+
import_node_fs38 = require("fs");
|
|
15297
|
+
import_node_path35 = require("path");
|
|
14995
15298
|
init_run();
|
|
14996
15299
|
init_worktree();
|
|
14997
15300
|
mergeBaseCache = /* @__PURE__ */ new Map();
|
|
14998
15301
|
MERGE_BASE_TTL_MS = 45e3;
|
|
14999
15302
|
SHA_RE = /^[0-9a-f]{7,40}$/i;
|
|
15000
|
-
|
|
15303
|
+
IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
15001
15304
|
"png",
|
|
15002
15305
|
"jpg",
|
|
15003
15306
|
"jpeg",
|
|
@@ -15159,7 +15462,7 @@ function parseFrontmatter(content) {
|
|
|
15159
15462
|
}
|
|
15160
15463
|
function readSkill(skillMd, source) {
|
|
15161
15464
|
try {
|
|
15162
|
-
const content = (0,
|
|
15465
|
+
const content = (0, import_node_fs39.readFileSync)(skillMd, "utf8");
|
|
15163
15466
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
15164
15467
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
15165
15468
|
const name = fmName || dirName;
|
|
@@ -15178,19 +15481,19 @@ function readSkill(skillMd, source) {
|
|
|
15178
15481
|
}
|
|
15179
15482
|
}
|
|
15180
15483
|
function scanSkillsDir(dir, source, out) {
|
|
15181
|
-
if (!(0,
|
|
15484
|
+
if (!(0, import_node_fs39.existsSync)(dir)) return;
|
|
15182
15485
|
let entries;
|
|
15183
15486
|
try {
|
|
15184
|
-
entries = (0,
|
|
15487
|
+
entries = (0, import_node_fs39.readdirSync)(dir);
|
|
15185
15488
|
} catch {
|
|
15186
15489
|
return;
|
|
15187
15490
|
}
|
|
15188
15491
|
for (const entry of entries) {
|
|
15189
15492
|
if (entry.startsWith(".")) continue;
|
|
15190
|
-
const skillMd = (0,
|
|
15191
|
-
if (!(0,
|
|
15493
|
+
const skillMd = (0, import_node_path36.join)(dir, entry, "SKILL.md");
|
|
15494
|
+
if (!(0, import_node_fs39.existsSync)(skillMd)) continue;
|
|
15192
15495
|
try {
|
|
15193
|
-
if (!(0,
|
|
15496
|
+
if (!(0, import_node_fs39.statSync)(skillMd).isFile()) continue;
|
|
15194
15497
|
} catch {
|
|
15195
15498
|
continue;
|
|
15196
15499
|
}
|
|
@@ -15199,24 +15502,24 @@ function scanSkillsDir(dir, source, out) {
|
|
|
15199
15502
|
}
|
|
15200
15503
|
}
|
|
15201
15504
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
15202
|
-
if (!(0,
|
|
15505
|
+
if (!(0, import_node_fs39.existsSync)(pluginsRoot)) return;
|
|
15203
15506
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
15204
15507
|
if (depth > 7) return;
|
|
15205
15508
|
let entries;
|
|
15206
15509
|
try {
|
|
15207
|
-
entries = (0,
|
|
15510
|
+
entries = (0, import_node_fs39.readdirSync)(dir);
|
|
15208
15511
|
} catch {
|
|
15209
15512
|
return;
|
|
15210
15513
|
}
|
|
15211
15514
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
15212
|
-
const skill = readSkill((0,
|
|
15515
|
+
const skill = readSkill((0, import_node_path36.join)(dir, "SKILL.md"), "cli");
|
|
15213
15516
|
if (skill) out.push(skill);
|
|
15214
15517
|
}
|
|
15215
15518
|
for (const entry of entries) {
|
|
15216
15519
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
15217
|
-
const full = (0,
|
|
15520
|
+
const full = (0, import_node_path36.join)(dir, entry);
|
|
15218
15521
|
try {
|
|
15219
|
-
if (!(0,
|
|
15522
|
+
if (!(0, import_node_fs39.statSync)(full).isDirectory()) continue;
|
|
15220
15523
|
} catch {
|
|
15221
15524
|
continue;
|
|
15222
15525
|
}
|
|
@@ -15234,17 +15537,17 @@ function discoverSkills(worktreePath) {
|
|
|
15234
15537
|
const home = (0, import_node_os11.homedir)();
|
|
15235
15538
|
const collected = [];
|
|
15236
15539
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
15237
|
-
scanSkillsDir((0,
|
|
15540
|
+
scanSkillsDir((0, import_node_path36.join)(worktreePath, rel), "workspace", collected);
|
|
15238
15541
|
}
|
|
15239
15542
|
for (const abs of [
|
|
15240
|
-
(0,
|
|
15241
|
-
(0,
|
|
15242
|
-
(0,
|
|
15243
|
-
(0,
|
|
15543
|
+
(0, import_node_path36.join)(home, ".claude/skills"),
|
|
15544
|
+
(0, import_node_path36.join)(home, ".cursor/skills"),
|
|
15545
|
+
(0, import_node_path36.join)(home, ".sideboard/skills"),
|
|
15546
|
+
(0, import_node_path36.join)(home, ".brightsy/skills")
|
|
15244
15547
|
]) {
|
|
15245
15548
|
scanSkillsDir(abs, "user", collected);
|
|
15246
15549
|
}
|
|
15247
|
-
scanClaudePluginSkills((0,
|
|
15550
|
+
scanClaudePluginSkills((0, import_node_path36.join)(home, ".claude/plugins"), collected);
|
|
15248
15551
|
const rank = { workspace: 0, user: 1, cli: 2 };
|
|
15249
15552
|
const byCommand = /* @__PURE__ */ new Map();
|
|
15250
15553
|
for (const skill of collected) {
|
|
@@ -15256,7 +15559,7 @@ function discoverSkills(worktreePath) {
|
|
|
15256
15559
|
return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
|
|
15257
15560
|
}
|
|
15258
15561
|
function readSkillBody(skillPath, maxChars = 12e3) {
|
|
15259
|
-
const raw = (0,
|
|
15562
|
+
const raw = (0, import_node_fs39.readFileSync)(skillPath, "utf8");
|
|
15260
15563
|
if (raw.startsWith("---")) {
|
|
15261
15564
|
const end = raw.indexOf("\n---", 3);
|
|
15262
15565
|
if (end >= 0) {
|
|
@@ -15270,13 +15573,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
|
|
|
15270
15573
|
|
|
15271
15574
|
\u2026(truncated)` : raw;
|
|
15272
15575
|
}
|
|
15273
|
-
var
|
|
15576
|
+
var import_node_fs39, import_node_os11, import_node_path36;
|
|
15274
15577
|
var init_discover = __esm({
|
|
15275
15578
|
"src/skills/discover.ts"() {
|
|
15276
15579
|
"use strict";
|
|
15277
|
-
|
|
15580
|
+
import_node_fs39 = require("fs");
|
|
15278
15581
|
import_node_os11 = require("os");
|
|
15279
|
-
|
|
15582
|
+
import_node_path36 = require("path");
|
|
15280
15583
|
}
|
|
15281
15584
|
});
|
|
15282
15585
|
|
|
@@ -15365,197 +15668,6 @@ var init_expand = __esm({
|
|
|
15365
15668
|
}
|
|
15366
15669
|
});
|
|
15367
15670
|
|
|
15368
|
-
// src/composer/stage-files.ts
|
|
15369
|
-
function fileExtension(filePath) {
|
|
15370
|
-
const base = (0, import_node_path36.basename)(filePath).toLowerCase();
|
|
15371
|
-
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
15372
|
-
}
|
|
15373
|
-
function isImageFilePath(filePath) {
|
|
15374
|
-
return IMAGE_EXTENSIONS2.has(fileExtension(filePath));
|
|
15375
|
-
}
|
|
15376
|
-
function imageMimeType(filePath) {
|
|
15377
|
-
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
15378
|
-
}
|
|
15379
|
-
function ensureAttachmentsDir(worktreePath) {
|
|
15380
|
-
const dir = (0, import_node_path36.join)(worktreePath, ATTACHMENTS_DIR);
|
|
15381
|
-
(0, import_node_fs39.mkdirSync)(dir, { recursive: true });
|
|
15382
|
-
const gi = (0, import_node_path36.join)(dir, ".gitignore");
|
|
15383
|
-
if (!(0, import_node_fs39.existsSync)(gi)) {
|
|
15384
|
-
(0, import_node_fs39.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
15385
|
-
}
|
|
15386
|
-
return dir;
|
|
15387
|
-
}
|
|
15388
|
-
function uniqueAttachmentName(dir, originalName) {
|
|
15389
|
-
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
15390
|
-
if (!(0, import_node_fs39.existsSync)((0, import_node_path36.join)(dir, safe))) return safe;
|
|
15391
|
-
const ext = (0, import_node_path36.extname)(safe);
|
|
15392
|
-
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
15393
|
-
for (let i = 1; i < 1e4; i++) {
|
|
15394
|
-
const candidate = `${stem}-${i}${ext}`;
|
|
15395
|
-
if (!(0, import_node_fs39.existsSync)((0, import_node_path36.join)(dir, candidate))) return candidate;
|
|
15396
|
-
}
|
|
15397
|
-
return `${stem}-${(0, import_node_crypto7.randomUUID)()}${ext}`;
|
|
15398
|
-
}
|
|
15399
|
-
function previewDataUrlFromBuf(filePath, buf) {
|
|
15400
|
-
if (!isImageFilePath(filePath)) return void 0;
|
|
15401
|
-
if (buf.length > MAX_PREVIEW_BYTES) return void 0;
|
|
15402
|
-
return `data:${imageMimeType(filePath)};base64,${buf.toString("base64")}`;
|
|
15403
|
-
}
|
|
15404
|
-
function attachmentFromBuffer(name, buf, opts) {
|
|
15405
|
-
const previewDataUrl = previewDataUrlFromBuf(name, buf);
|
|
15406
|
-
if (isImageFilePath(name)) {
|
|
15407
|
-
const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
|
|
15408
|
-
return {
|
|
15409
|
-
id: (0, import_node_crypto7.randomUUID)(),
|
|
15410
|
-
name,
|
|
15411
|
-
kind: "file",
|
|
15412
|
-
path: opts.path,
|
|
15413
|
-
previewDataUrl,
|
|
15414
|
-
content: [
|
|
15415
|
-
`Image attached: ${pathHint}`,
|
|
15416
|
-
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."
|
|
15417
|
-
].join("\n")
|
|
15418
|
-
};
|
|
15419
|
-
}
|
|
15420
|
-
if (buf.length > MAX_INLINE_BYTES) {
|
|
15421
|
-
return {
|
|
15422
|
-
id: (0, import_node_crypto7.randomUUID)(),
|
|
15423
|
-
name,
|
|
15424
|
-
kind: "file",
|
|
15425
|
-
path: opts.path,
|
|
15426
|
-
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)`
|
|
15427
|
-
};
|
|
15428
|
-
}
|
|
15429
|
-
if (buf.includes(0)) {
|
|
15430
|
-
return {
|
|
15431
|
-
id: (0, import_node_crypto7.randomUUID)(),
|
|
15432
|
-
name,
|
|
15433
|
-
kind: "file",
|
|
15434
|
-
path: opts.path,
|
|
15435
|
-
content: opts.path ? `(binary file at \`${opts.path}\` \u2014 use tools to inspect)` : `(binary file attached by path only: ${opts.sourceLabel || name})`
|
|
15436
|
-
};
|
|
15437
|
-
}
|
|
15438
|
-
return {
|
|
15439
|
-
id: (0, import_node_crypto7.randomUUID)(),
|
|
15440
|
-
name,
|
|
15441
|
-
kind: "file",
|
|
15442
|
-
path: opts.path,
|
|
15443
|
-
content: buf.toString("utf8")
|
|
15444
|
-
};
|
|
15445
|
-
}
|
|
15446
|
-
function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
15447
|
-
if (absolutePaths.length === 0) return [];
|
|
15448
|
-
const dir = ensureAttachmentsDir(worktreePath);
|
|
15449
|
-
const out = [];
|
|
15450
|
-
for (const abs of absolutePaths) {
|
|
15451
|
-
const originalName = (0, import_node_path36.basename)(abs);
|
|
15452
|
-
try {
|
|
15453
|
-
const st = (0, import_node_fs39.statSync)(abs);
|
|
15454
|
-
if (!st.isFile()) continue;
|
|
15455
|
-
const name = uniqueAttachmentName(dir, originalName);
|
|
15456
|
-
const destAbs = (0, import_node_path36.join)(dir, name);
|
|
15457
|
-
(0, import_node_fs39.copyFileSync)(abs, destAbs);
|
|
15458
|
-
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
15459
|
-
const buf = (0, import_node_fs39.readFileSync)(destAbs);
|
|
15460
|
-
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
15461
|
-
} catch (err) {
|
|
15462
|
-
out.push({
|
|
15463
|
-
id: (0, import_node_crypto7.randomUUID)(),
|
|
15464
|
-
name: originalName,
|
|
15465
|
-
kind: "file",
|
|
15466
|
-
content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
|
|
15467
|
-
});
|
|
15468
|
-
}
|
|
15469
|
-
}
|
|
15470
|
-
return out;
|
|
15471
|
-
}
|
|
15472
|
-
function stageBuffersAsAttachments(worktreePath, buffers2) {
|
|
15473
|
-
if (buffers2.length === 0) return [];
|
|
15474
|
-
const dir = ensureAttachmentsDir(worktreePath);
|
|
15475
|
-
const out = [];
|
|
15476
|
-
for (const item of buffers2) {
|
|
15477
|
-
const originalName = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
15478
|
-
try {
|
|
15479
|
-
const buf = Buffer.from(item.dataBase64, "base64");
|
|
15480
|
-
const name = uniqueAttachmentName(dir, originalName);
|
|
15481
|
-
const destAbs = (0, import_node_path36.join)(dir, name);
|
|
15482
|
-
(0, import_node_fs39.writeFileSync)(destAbs, buf);
|
|
15483
|
-
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
15484
|
-
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
15485
|
-
} catch (err) {
|
|
15486
|
-
out.push({
|
|
15487
|
-
id: (0, import_node_crypto7.randomUUID)(),
|
|
15488
|
-
name: originalName,
|
|
15489
|
-
kind: "file",
|
|
15490
|
-
content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
|
|
15491
|
-
});
|
|
15492
|
-
}
|
|
15493
|
-
}
|
|
15494
|
-
return out;
|
|
15495
|
-
}
|
|
15496
|
-
function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
15497
|
-
const out = [];
|
|
15498
|
-
for (const rel of relativePaths) {
|
|
15499
|
-
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
15500
|
-
out.push({
|
|
15501
|
-
id: (0, import_node_crypto7.randomUUID)(),
|
|
15502
|
-
name: (0, import_node_path36.basename)(rel) || "file",
|
|
15503
|
-
kind: "file",
|
|
15504
|
-
content: `(invalid path: ${rel})`
|
|
15505
|
-
});
|
|
15506
|
-
continue;
|
|
15507
|
-
}
|
|
15508
|
-
const name = (0, import_node_path36.basename)(rel);
|
|
15509
|
-
try {
|
|
15510
|
-
const abs = (0, import_node_path36.join)(worktreePath, rel);
|
|
15511
|
-
const st = (0, import_node_fs39.statSync)(abs);
|
|
15512
|
-
if (!st.isFile()) continue;
|
|
15513
|
-
const buf = (0, import_node_fs39.readFileSync)(abs);
|
|
15514
|
-
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
15515
|
-
} catch (err) {
|
|
15516
|
-
out.push({
|
|
15517
|
-
id: (0, import_node_crypto7.randomUUID)(),
|
|
15518
|
-
name,
|
|
15519
|
-
kind: "file",
|
|
15520
|
-
content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
|
|
15521
|
-
});
|
|
15522
|
-
}
|
|
15523
|
-
}
|
|
15524
|
-
return out;
|
|
15525
|
-
}
|
|
15526
|
-
var import_node_fs39, import_node_path36, import_node_crypto7, IMAGE_EXTENSIONS2, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES;
|
|
15527
|
-
var init_stage_files = __esm({
|
|
15528
|
-
"src/composer/stage-files.ts"() {
|
|
15529
|
-
"use strict";
|
|
15530
|
-
import_node_fs39 = require("fs");
|
|
15531
|
-
import_node_path36 = require("path");
|
|
15532
|
-
import_node_crypto7 = require("crypto");
|
|
15533
|
-
init_workspace_scratch();
|
|
15534
|
-
IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
15535
|
-
"png",
|
|
15536
|
-
"jpg",
|
|
15537
|
-
"jpeg",
|
|
15538
|
-
"gif",
|
|
15539
|
-
"webp",
|
|
15540
|
-
"svg",
|
|
15541
|
-
"bmp",
|
|
15542
|
-
"ico"
|
|
15543
|
-
]);
|
|
15544
|
-
IMAGE_MIME_BY_EXT = {
|
|
15545
|
-
png: "image/png",
|
|
15546
|
-
jpg: "image/jpeg",
|
|
15547
|
-
jpeg: "image/jpeg",
|
|
15548
|
-
gif: "image/gif",
|
|
15549
|
-
webp: "image/webp",
|
|
15550
|
-
svg: "image/svg+xml",
|
|
15551
|
-
bmp: "image/bmp",
|
|
15552
|
-
ico: "image/x-icon"
|
|
15553
|
-
};
|
|
15554
|
-
MAX_INLINE_BYTES = 4e5;
|
|
15555
|
-
MAX_PREVIEW_BYTES = 5e6;
|
|
15556
|
-
}
|
|
15557
|
-
});
|
|
15558
|
-
|
|
15559
15671
|
// src/agents/instructions.ts
|
|
15560
15672
|
function normPath3(p) {
|
|
15561
15673
|
return p.replace(/\/+$/, "");
|
|
@@ -16625,6 +16737,7 @@ var init_orchestrator = __esm({
|
|
|
16625
16737
|
init_usage();
|
|
16626
16738
|
init_thread_store();
|
|
16627
16739
|
init_desktop_host();
|
|
16740
|
+
init_child_halt();
|
|
16628
16741
|
init_create();
|
|
16629
16742
|
init_cowboy();
|
|
16630
16743
|
init_orchestrator_capable();
|
|
@@ -16772,6 +16885,9 @@ var init_orchestrator = __esm({
|
|
|
16772
16885
|
* MCP-created review threads don't stay `queued` after the MCP child exits.
|
|
16773
16886
|
*/
|
|
16774
16887
|
adoptPersistedQueues() {
|
|
16888
|
+
if (thisProcessShouldDrainAgentQueues()) {
|
|
16889
|
+
this.healStaleRunningTurns();
|
|
16890
|
+
}
|
|
16775
16891
|
for (const thread of listThreads()) {
|
|
16776
16892
|
if (thread.status === "stopped" || thread.status === "archived") continue;
|
|
16777
16893
|
const pid = thread.agentPid;
|
|
@@ -16792,6 +16908,32 @@ var init_orchestrator = __esm({
|
|
|
16792
16908
|
}
|
|
16793
16909
|
}
|
|
16794
16910
|
}
|
|
16911
|
+
/**
|
|
16912
|
+
* Mid-session: a worktree can sit at `running` after the agent process dies
|
|
16913
|
+
* (Cursor/CLI crash, OOM) while wait_for_turn still reports stillRunning.
|
|
16914
|
+
* Reclaim those and wake the parent orchestration chat.
|
|
16915
|
+
*/
|
|
16916
|
+
healStaleRunningTurns() {
|
|
16917
|
+
for (const thread of listThreads()) {
|
|
16918
|
+
if (thread.status === "archived") continue;
|
|
16919
|
+
const handle = this.activeTurns.get(thread.id);
|
|
16920
|
+
if (handle) {
|
|
16921
|
+
const pid = thread.agentPid;
|
|
16922
|
+
if (typeof pid === "number" && pid > 0 && !isPidAlive(pid)) {
|
|
16923
|
+
handle.kill();
|
|
16924
|
+
}
|
|
16925
|
+
continue;
|
|
16926
|
+
}
|
|
16927
|
+
if (!this.shouldReclaimRunningThread(thread)) continue;
|
|
16928
|
+
setStatus(thread.id, "stopped", "Process died (agent exited)");
|
|
16929
|
+
this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
|
|
16930
|
+
this.emit({ type: "turn_finished", threadId: thread.id, exitCode: 1 });
|
|
16931
|
+
const latest = readThread(thread.id);
|
|
16932
|
+
if (latest) {
|
|
16933
|
+
notifyParentOfChildHalt(latest, "stopped", (id, prompt) => this.send(id, prompt));
|
|
16934
|
+
}
|
|
16935
|
+
}
|
|
16936
|
+
}
|
|
16795
16937
|
clearQuotaResumeTimer(threadId) {
|
|
16796
16938
|
const timer = this.quotaResumeTimers.get(threadId);
|
|
16797
16939
|
if (timer) clearTimeout(timer);
|
|
@@ -17509,6 +17651,12 @@ var init_orchestrator = __esm({
|
|
|
17509
17651
|
assistantText: chatText,
|
|
17510
17652
|
partsCount: parts.length
|
|
17511
17653
|
});
|
|
17654
|
+
if (!this.crashContinued.has(threadId)) {
|
|
17655
|
+
const failed = readThread(threadId);
|
|
17656
|
+
if (failed) {
|
|
17657
|
+
notifyParentOfChildHalt(failed, "error", (id, prompt2) => this.send(id, prompt2));
|
|
17658
|
+
}
|
|
17659
|
+
}
|
|
17512
17660
|
}
|
|
17513
17661
|
}
|
|
17514
17662
|
} catch (err) {
|
|
@@ -17533,6 +17681,12 @@ var init_orchestrator = __esm({
|
|
|
17533
17681
|
assistantText: "",
|
|
17534
17682
|
partsCount: 0
|
|
17535
17683
|
});
|
|
17684
|
+
if (!this.crashContinued.has(threadId)) {
|
|
17685
|
+
const failed = readThread(threadId);
|
|
17686
|
+
if (failed) {
|
|
17687
|
+
notifyParentOfChildHalt(failed, "error", (id, prompt2) => this.send(id, prompt2));
|
|
17688
|
+
}
|
|
17689
|
+
}
|
|
17536
17690
|
}
|
|
17537
17691
|
} finally {
|
|
17538
17692
|
this.startingTurns.delete(threadId);
|
|
@@ -17588,6 +17742,9 @@ var init_orchestrator = __esm({
|
|
|
17588
17742
|
const stopped = writeLiveStatus(thread.id, "stopped") ?? readThread(thread.id) ?? thread;
|
|
17589
17743
|
if (stopped.status === "stopped") {
|
|
17590
17744
|
this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
|
|
17745
|
+
if (opts?.notifyParent !== false) {
|
|
17746
|
+
notifyParentOfChildHalt(stopped, "stopped", (id, prompt) => this.send(id, prompt));
|
|
17747
|
+
}
|
|
17591
17748
|
}
|
|
17592
17749
|
return stopped;
|
|
17593
17750
|
}
|
|
@@ -17832,21 +17989,25 @@ var init_orchestrator = __esm({
|
|
|
17832
17989
|
fn();
|
|
17833
17990
|
};
|
|
17834
17991
|
const off = this.on((event) => {
|
|
17835
|
-
if (
|
|
17992
|
+
if (!("threadId" in event) || event.threadId !== thread.id) return;
|
|
17993
|
+
if (event.type === "turn_finished" || event.type === "error") {
|
|
17836
17994
|
const latest = readThread(thread.id);
|
|
17837
17995
|
if (!latest) {
|
|
17838
17996
|
finish(() => reject(new Error(`Thread not found: ${thread.id}`)));
|
|
17839
17997
|
return;
|
|
17840
17998
|
}
|
|
17841
17999
|
finish(() => resolve(latest));
|
|
18000
|
+
return;
|
|
17842
18001
|
}
|
|
17843
|
-
if (event.type === "
|
|
18002
|
+
if (event.type === "status_changed") {
|
|
17844
18003
|
const latest = readThread(thread.id);
|
|
17845
18004
|
if (!latest) {
|
|
17846
18005
|
finish(() => reject(new Error(`Thread not found: ${thread.id}`)));
|
|
17847
18006
|
return;
|
|
17848
18007
|
}
|
|
17849
|
-
|
|
18008
|
+
if (!["running", "queued"].includes(latest.status)) {
|
|
18009
|
+
finish(() => resolve(latest));
|
|
18010
|
+
}
|
|
17850
18011
|
}
|
|
17851
18012
|
});
|
|
17852
18013
|
timer = setInterval(() => {
|
|
@@ -17881,7 +18042,7 @@ var init_orchestrator = __esm({
|
|
|
17881
18042
|
const thread = this.requireThread(threadRef);
|
|
17882
18043
|
const lastAgent = [...thread.messages].reverse().find((m) => m.role === "agent");
|
|
17883
18044
|
const lastError = thread.lastError ?? null;
|
|
17884
|
-
const text5 = (lastAgent?.text ?? "").trim() || (thread.status === "error" ? lastError ?? "" : "");
|
|
18045
|
+
const text5 = (lastAgent?.text ?? "").trim() || (thread.status === "error" || thread.status === "stopped" || thread.status === "broken" ? lastError ?? "" : "");
|
|
17885
18046
|
const stillRunning = thread.status === "running" || thread.status === "queued";
|
|
17886
18047
|
const live = stillRunning ? readTurnLive(thread.id) : null;
|
|
17887
18048
|
const queuedHint = thread.status === "queued" && !live?.summary ? "Queued \u2014 waiting for a concurrency slot" : null;
|
|
@@ -19079,6 +19240,15 @@ var MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u201
|
|
|
19079
19240
|
function mcpWaitStillRunningHint(status) {
|
|
19080
19241
|
return status === "queued" ? MCP_WAIT_QUEUED_HINT : MCP_WAIT_STILL_RUNNING_HINT;
|
|
19081
19242
|
}
|
|
19243
|
+
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.";
|
|
19244
|
+
var MCP_WAIT_BROKEN_HINT = "Child worktree is broken (missing on disk). Tell the user \u2014 do not treat this as success.";
|
|
19245
|
+
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.";
|
|
19246
|
+
function mcpWaitFinishedHint(status) {
|
|
19247
|
+
if (status === "stopped") return MCP_WAIT_STOPPED_HINT;
|
|
19248
|
+
if (status === "broken") return MCP_WAIT_BROKEN_HINT;
|
|
19249
|
+
if (status === "error") return MCP_WAIT_ERROR_HINT;
|
|
19250
|
+
return void 0;
|
|
19251
|
+
}
|
|
19082
19252
|
|
|
19083
19253
|
// src/mcp/server.ts
|
|
19084
19254
|
init_turn_live();
|
|
@@ -20795,7 +20965,7 @@ async function startMcpServer() {
|
|
|
20795
20965
|
);
|
|
20796
20966
|
server.tool(
|
|
20797
20967
|
"wait_for_turn",
|
|
20798
|
-
"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).",
|
|
20968
|
+
"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).",
|
|
20799
20969
|
{
|
|
20800
20970
|
ref: import_zod5.z.string(),
|
|
20801
20971
|
timeoutMs: import_zod5.z.number().optional()
|
|
@@ -20817,7 +20987,8 @@ async function startMcpServer() {
|
|
|
20817
20987
|
stillRunning: result.stillRunning,
|
|
20818
20988
|
progress: result.progress,
|
|
20819
20989
|
lastActivityAt: result.lastActivityAt,
|
|
20820
|
-
hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) :
|
|
20990
|
+
hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) : mcpWaitFinishedHint(result.status),
|
|
20991
|
+
incomplete: !result.stillRunning && Boolean(mcpWaitFinishedHint(result.status))
|
|
20821
20992
|
})
|
|
20822
20993
|
}
|
|
20823
20994
|
]
|
|
@@ -20836,7 +21007,8 @@ async function startMcpServer() {
|
|
|
20836
21007
|
type: "text",
|
|
20837
21008
|
text: JSON.stringify({
|
|
20838
21009
|
...result,
|
|
20839
|
-
hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) :
|
|
21010
|
+
hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) : mcpWaitFinishedHint(result.status),
|
|
21011
|
+
incomplete: !result.stillRunning && Boolean(mcpWaitFinishedHint(result.status))
|
|
20840
21012
|
})
|
|
20841
21013
|
}
|
|
20842
21014
|
]
|
|
@@ -20860,7 +21032,7 @@ async function startMcpServer() {
|
|
|
20860
21032
|
}
|
|
20861
21033
|
const clearQueue = force !== false;
|
|
20862
21034
|
const hadQueued = t.queue.length > 0;
|
|
20863
|
-
const stopped = orch.stop(ref, { clearQueue });
|
|
21035
|
+
const stopped = orch.stop(ref, { clearQueue, notifyParent: false });
|
|
20864
21036
|
return {
|
|
20865
21037
|
content: [
|
|
20866
21038
|
{
|