@sideboard-ai/core 0.1.149 → 0.1.150
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/{abletime-QEVAE67D.js → abletime-223A3LY6.js} +2 -2
- package/dist/{abletime-DI55AJX3.js → abletime-CLC5UJC2.js} +2 -2
- package/dist/agents/cursor-runner.cjs +40 -35
- package/dist/agents/cursor-runner.js +2 -2
- package/dist/{agents-HSVQ2Z6Y.js → agents-KKXGTEV6.js} +10 -9
- package/dist/{agents-V4MTDWXS.js → agents-YWBQXOA2.js} +10 -9
- package/dist/{app-settings-WJDCJFSY.js → app-settings-3CHCNIMD.js} +5 -1
- package/dist/{app-settings-ZCN632OJ.js → app-settings-J3JBCUOT.js} +5 -1
- package/dist/{chunk-I77RYPOH.js → chunk-4XNSGDXE.js} +12 -0
- package/dist/{chunk-KBWND62T.js → chunk-7F4XE6UG.js} +5 -5
- package/dist/{chunk-R4JP32P5.js → chunk-AF6O55PJ.js} +4 -4
- package/dist/{chunk-BOD5V52W.js → chunk-B7XK37WZ.js} +1 -1
- package/dist/{chunk-BGQBELGJ.js → chunk-CZD4NRDZ.js} +12 -0
- package/dist/{chunk-ZVYLEF72.js → chunk-DMRIZR6M.js} +6 -6
- package/dist/{chunk-TZWO7J4W.js → chunk-DXCNW2JF.js} +113 -52
- package/dist/{chunk-KPIYENTF.js → chunk-FNQNJOHY.js} +89 -5
- package/dist/{chunk-ED4UPEJX.js → chunk-G7SIQFBQ.js} +1 -1
- package/dist/{chunk-3QRGCKYL.js → chunk-HAS5EPBS.js} +2 -2
- package/dist/{chunk-LAFA56WD.js → chunk-HEII7W3Q.js} +1 -1
- package/dist/{chunk-EGDRPA4B.js → chunk-NOTANBYC.js} +6 -6
- package/dist/{chunk-JDYKQ6OI.js → chunk-NUPITVRF.js} +134 -73
- package/dist/{chunk-QTUESPAW.js → chunk-PTOSP4AH.js} +1 -1
- package/dist/{chunk-Q62SDB53.js → chunk-QGJHIJHV.js} +2 -2
- package/dist/{chunk-PTI5H3RK.js → chunk-SDN4ZYQH.js} +24 -13
- package/dist/{chunk-DVM4ID64.js → chunk-UFHNSFAS.js} +89 -5
- package/dist/{chunk-N3VNOFXQ.js → chunk-VO4SPEBS.js} +4 -4
- package/dist/chunk-VSFGPWCQ.js +62 -0
- package/dist/{chunk-N5PM7HGQ.js → chunk-W6N6GQME.js} +1 -1
- package/dist/{chunk-FKOIHGKV.js → chunk-WHU7YGWP.js} +1 -1
- package/dist/{chunk-VZJVKQHH.js → chunk-WLV7TRMR.js} +1 -1
- package/dist/chunk-Y4NAPW5I.js +60 -0
- package/dist/{chunk-B3SJXYIJ.js → chunk-Y7YBWWIG.js} +1 -1
- package/dist/{chunk-Q5DHVMXB.js → chunk-YGGBJY5A.js} +18 -7
- package/dist/{chunk-JTPDWTWJ.js → chunk-Z2PVJKMN.js} +137 -114
- package/dist/{chunk-YP3CSOZ6.js → chunk-ZGFYFVJF.js} +142 -114
- package/dist/{connected-teams-IJUJQ7R6.js → connected-teams-I2WZZZFA.js} +2 -2
- package/dist/{connected-teams-4A2AXDNN.js → connected-teams-XO766HB4.js} +2 -2
- package/dist/{coordinator-prompt-ZWBMAIWA.js → coordinator-prompt-NYR5TPBD.js} +6 -5
- package/dist/{coordinator-prompt-5GXGBGEZ.js → coordinator-prompt-UCQJTFA7.js} +6 -5
- package/dist/{global-workspace-2SIPM4PW.js → global-workspace-4QHDAD2D.js} +7 -6
- package/dist/{global-workspace-OJRXWXEA.js → global-workspace-4SENNWBU.js} +7 -6
- package/dist/index.cjs +998 -574
- package/dist/index.d.cts +91 -10
- package/dist/index.d.ts +91 -10
- package/dist/index.js +268 -93
- package/dist/mcp/run-stdio.cjs +976 -579
- package/dist/mcp/run-stdio.js +196 -43
- package/dist/{orchestrator-6TXQWBXN.js → orchestrator-GZE4X3XV.js} +14 -11
- package/dist/{orchestrator-Z2O5OVJA.js → orchestrator-QSBRWME5.js} +16 -13
- package/dist/{plan-file-6O7G4VPQ.js → plan-file-5S5TUNAW.js} +2 -2
- package/dist/{plan-file-PHVKUAEE.js → plan-file-IBSU2PVW.js} +2 -2
- package/dist/{run-XQKGHQZ2.js → run-CAGKZLHA.js} +1 -1
- package/dist/{run-USF6FRKV.js → run-EBWL2Q4N.js} +1 -1
- package/dist/{workspaces-UUJNOO4T.js → workspaces-7S7QKCUE.js} +8 -7
- package/dist/{workspaces-3NUUZTQK.js → workspaces-RDUSB6FD.js} +8 -7
- package/dist/{worktree-RZRJNHYL.js → worktree-63AGPPLO.js} +5 -4
- package/dist/{worktree-UCWWTVLS.js → worktree-JIZ3QMZX.js} +5 -4
- package/dist/worktree-exclude-6MQWGWV5.js +11 -0
- package/dist/worktree-exclude-TV6EV6BS.js +9 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -837,6 +837,7 @@ var init_issue_source_labels = __esm({
|
|
|
837
837
|
// src/store/app-settings.ts
|
|
838
838
|
var app_settings_exports = {};
|
|
839
839
|
__export(app_settings_exports, {
|
|
840
|
+
FOLLOW_UP_BEHAVIORS: () => FOLLOW_UP_BEHAVIORS,
|
|
840
841
|
GITHUB_GIT_AUTH_MODES: () => GITHUB_GIT_AUTH_MODES,
|
|
841
842
|
HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
|
|
842
843
|
ISSUE_SOURCE_LABELS: () => ISSUE_SOURCE_LABELS,
|
|
@@ -862,6 +863,7 @@ __export(app_settings_exports, {
|
|
|
862
863
|
disconnectLinearConnection: () => disconnectLinearConnection,
|
|
863
864
|
emptyPublicIntegrations: () => emptyPublicIntegrations,
|
|
864
865
|
ensureSlackDeviceIdentity: () => ensureSlackDeviceIdentity,
|
|
866
|
+
followUpBehavior: () => followUpBehavior,
|
|
865
867
|
getAbleTimeAccessToken: () => getAbleTimeAccessToken,
|
|
866
868
|
getAbleTimeHost: () => getAbleTimeHost,
|
|
867
869
|
getDefaultAgent: () => getDefaultAgent,
|
|
@@ -1218,6 +1220,9 @@ function normalizeAdvanced(raw) {
|
|
|
1218
1220
|
if (typeof source.orchestrationQuotaFallbackAgent === "string" && DEFAULT_AGENTS.has(source.orchestrationQuotaFallbackAgent) && source.orchestrationQuotaFallbackAgent !== "brightsy") {
|
|
1219
1221
|
out.orchestrationQuotaFallbackAgent = source.orchestrationQuotaFallbackAgent;
|
|
1220
1222
|
}
|
|
1223
|
+
if (source.followUpBehavior === "queue" || source.followUpBehavior === "steer") {
|
|
1224
|
+
out.followUpBehavior = source.followUpBehavior;
|
|
1225
|
+
}
|
|
1221
1226
|
return out;
|
|
1222
1227
|
}
|
|
1223
1228
|
function normalizeSettings(raw) {
|
|
@@ -1909,6 +1914,9 @@ function updateAdvancedSettings(patch) {
|
|
|
1909
1914
|
if (typeof patch.orchestrationQuotaFallbackAgent === "string" && DEFAULT_AGENTS.has(patch.orchestrationQuotaFallbackAgent) && patch.orchestrationQuotaFallbackAgent !== "brightsy") {
|
|
1910
1915
|
advanced.orchestrationQuotaFallbackAgent = patch.orchestrationQuotaFallbackAgent;
|
|
1911
1916
|
}
|
|
1917
|
+
if (patch.followUpBehavior === "queue" || patch.followUpBehavior === "steer") {
|
|
1918
|
+
advanced.followUpBehavior = patch.followUpBehavior;
|
|
1919
|
+
}
|
|
1912
1920
|
return saveAppSettings({ ...current, advanced });
|
|
1913
1921
|
}
|
|
1914
1922
|
function autoRenameBranchEnabled(settings = loadAppSettings()) {
|
|
@@ -1954,6 +1962,9 @@ function orchestrationQuotaFallbackAgent(settings = loadAppSettings()) {
|
|
|
1954
1962
|
}
|
|
1955
1963
|
return "cursor";
|
|
1956
1964
|
}
|
|
1965
|
+
function followUpBehavior(settings = loadAppSettings()) {
|
|
1966
|
+
return settings.advanced.followUpBehavior === "queue" ? "queue" : "steer";
|
|
1967
|
+
}
|
|
1957
1968
|
function maxConcurrentAgents(settings = loadAppSettings()) {
|
|
1958
1969
|
const n = settings.advanced.maxConcurrent;
|
|
1959
1970
|
if (typeof n === "number" && Number.isFinite(n)) {
|
|
@@ -2041,7 +2052,7 @@ function childEnvWithAppSettings(extra) {
|
|
|
2041
2052
|
function harnessEnvKey(harness) {
|
|
2042
2053
|
return HARNESS_ENV_KEYS[harness];
|
|
2043
2054
|
}
|
|
2044
|
-
var import_node_crypto2, import_node_fs7, import_node_os3, import_node_path8, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, DEFAULT_CLI_BIN;
|
|
2055
|
+
var import_node_crypto2, import_node_fs7, import_node_os3, import_node_path8, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, FOLLOW_UP_BEHAVIORS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, DEFAULT_CLI_BIN;
|
|
2045
2056
|
var init_app_settings = __esm({
|
|
2046
2057
|
"src/store/app-settings.ts"() {
|
|
2047
2058
|
"use strict";
|
|
@@ -2070,6 +2081,7 @@ var init_app_settings = __esm({
|
|
|
2070
2081
|
"cursor"
|
|
2071
2082
|
]);
|
|
2072
2083
|
GITHUB_GIT_AUTH_MODES = ["auto", "gh", "ssh", "token"];
|
|
2084
|
+
FOLLOW_UP_BEHAVIORS = ["steer", "queue"];
|
|
2073
2085
|
CLOUD_CONNECT_AGENTS = /* @__PURE__ */ new Set([
|
|
2074
2086
|
"claude",
|
|
2075
2087
|
"codex",
|
|
@@ -2869,7 +2881,7 @@ function attachmentsGitignoreBody() {
|
|
|
2869
2881
|
}
|
|
2870
2882
|
function isWorkspaceScratchPath(relativePath) {
|
|
2871
2883
|
const p = relativePath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
|
|
2872
|
-
return p === ATTACHMENTS_DIR || p.startsWith(`${ATTACHMENTS_DIR}/`) || p === LEGACY_ATTACHMENTS_DIR || p.startsWith(`${LEGACY_ATTACHMENTS_DIR}/`) || p === ".context" || p.startsWith(".context/");
|
|
2884
|
+
return p === ATTACHMENTS_DIR || p.startsWith(`${ATTACHMENTS_DIR}/`) || p === LEGACY_ATTACHMENTS_DIR || p.startsWith(`${LEGACY_ATTACHMENTS_DIR}/`) || p === ".sideboard" || p.startsWith(".sideboard/") || p === ".context" || p.startsWith(".context/");
|
|
2873
2885
|
}
|
|
2874
2886
|
var ATTACHMENTS_DIR, LEGACY_ATTACHMENTS_DIR, ATTACHMENTS_GITIGNORE;
|
|
2875
2887
|
var init_workspace_scratch = __esm({
|
|
@@ -3991,6 +4003,18 @@ var init_worktree_labels = __esm({
|
|
|
3991
4003
|
function isGhRateLimitError(text5) {
|
|
3992
4004
|
return /API rate limit (already )?exceeded/i.test(text5) || /rate limit exceeded/i.test(text5);
|
|
3993
4005
|
}
|
|
4006
|
+
function isGhPrBodyTooLongError(text5) {
|
|
4007
|
+
return /body is too long|body.{0,20}too long|maximum is 65536|exceeds the maximum allowed size|request (entity |is )?too large|payload too large|413 Request Entity Too Large/i.test(
|
|
4008
|
+
text5
|
|
4009
|
+
);
|
|
4010
|
+
}
|
|
4011
|
+
function clampGithubPrBody(body, max = GITHUB_PR_BODY_SAFE_CHARS) {
|
|
4012
|
+
const t = body.replace(/\s+$/u, "");
|
|
4013
|
+
if (t.length <= max) return t;
|
|
4014
|
+
const note = "\n\n_(truncated to fit GitHub\u2019s PR body limit)_";
|
|
4015
|
+
const keep = Math.max(0, max - note.length);
|
|
4016
|
+
return `${t.slice(0, keep).replace(/\s+$/u, "")}${note}`;
|
|
4017
|
+
}
|
|
3994
4018
|
function formatRateLimitResetHint(resetEpochSec, nowMs = Date.now()) {
|
|
3995
4019
|
const ms = resetEpochSec * 1e3 - nowMs;
|
|
3996
4020
|
if (ms <= 0) return "soon";
|
|
@@ -4001,18 +4025,32 @@ function formatRateLimitResetHint(resetEpochSec, nowMs = Date.now()) {
|
|
|
4001
4025
|
const hours = Math.ceil(mins / 60);
|
|
4002
4026
|
return `in about ${hours} hour${hours === 1 ? "" : "s"}`;
|
|
4003
4027
|
}
|
|
4028
|
+
function omitGhBodyArg(text5) {
|
|
4029
|
+
return text5.replace(
|
|
4030
|
+
/--body(?:-file)?(\s+|=)(?:'[^']*'|"[^"]*"|\S+)/g,
|
|
4031
|
+
"--body <omitted>"
|
|
4032
|
+
);
|
|
4033
|
+
}
|
|
4034
|
+
function capGhErrorText(text5, max = 400) {
|
|
4035
|
+
const t = text5.trim();
|
|
4036
|
+
if (t.length <= max) return t;
|
|
4037
|
+
return `${t.slice(0, max - 1).trimEnd()}\u2026`;
|
|
4038
|
+
}
|
|
4004
4039
|
function extractGhErrorDetail(text5) {
|
|
4005
|
-
const trimmed = text5.trim();
|
|
4040
|
+
const trimmed = omitGhBodyArg(text5.trim());
|
|
4006
4041
|
if (!trimmed) return "";
|
|
4042
|
+
if (isGhPrBodyTooLongError(text5) || isGhPrBodyTooLongError(trimmed)) {
|
|
4043
|
+
return "GraphQL: body is too long (GitHub PR body / request size limit).";
|
|
4044
|
+
}
|
|
4007
4045
|
const graphql = trimmed.match(/\bGraphQL:\s*(.+)$/im);
|
|
4008
|
-
if (graphql?.[1]) return `GraphQL: ${graphql[1].trim()}
|
|
4046
|
+
if (graphql?.[1]) return capGhErrorText(`GraphQL: ${graphql[1].trim()}`);
|
|
4009
4047
|
const http = trimmed.match(/\bHTTP\s+\d{3}:\s*(.+)$/im);
|
|
4010
|
-
if (http?.[1]) return `HTTP: ${http[1].trim()}
|
|
4048
|
+
if (http?.[1]) return capGhErrorText(`HTTP: ${http[1].trim()}`);
|
|
4011
4049
|
const lines = trimmed.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
|
4012
4050
|
if (lines.length > 1 && /^Command failed with exit code/i.test(lines[0])) {
|
|
4013
|
-
return lines.slice(1).join(" ").trim() || lines[0];
|
|
4051
|
+
return capGhErrorText(lines.slice(1).join(" ").trim() || lines[0]);
|
|
4014
4052
|
}
|
|
4015
|
-
return trimmed;
|
|
4053
|
+
return capGhErrorText(trimmed);
|
|
4016
4054
|
}
|
|
4017
4055
|
function formatGhLandError(raw, opts) {
|
|
4018
4056
|
const trimmed = raw.trim();
|
|
@@ -4030,6 +4068,10 @@ function formatGhLandError(raw, opts) {
|
|
|
4030
4068
|
const hint = opts?.targetedRepo ? ` Branch was pushed to origin \u2014 confirm it exists on GitHub and differs from the base branch.${target}${head}.` : " Often `gh` targeted upstream instead of origin. Branch was pushed \u2014 retry in the latest Sideboard, or run: gh pr create -R <owner/name> --base main --head <branch>.";
|
|
4031
4069
|
return `Could not create the pull request.${hint}`;
|
|
4032
4070
|
}
|
|
4071
|
+
if (isGhPrBodyTooLongError(raw) || isGhPrBodyTooLongError(detail)) {
|
|
4072
|
+
const pushNote = opts?.pushed === false ? "" : " Your branch was already pushed.";
|
|
4073
|
+
return `GitHub rejected the pull request: the GraphQL body is too long (PR description / request size, limit ${GITHUB_PR_BODY_MAX_CHARS} characters).${pushNote} Retry with a short title and body via \`gh pr create --body-file\` (or send_to_thread so the worktree agent writes a brief description). Do not paste a changelog or diff into --body.`;
|
|
4074
|
+
}
|
|
4033
4075
|
if (isGhRateLimitError(raw) || isGhRateLimitError(detail)) {
|
|
4034
4076
|
const when = opts?.resetAt ? ` Try again ${formatRateLimitResetHint(opts.resetAt, opts.nowMs)}.` : " Wait a few minutes and try again.";
|
|
4035
4077
|
const pushNote = opts?.pushed === false ? "" : " Your branch was already pushed.";
|
|
@@ -4058,130 +4100,51 @@ function formatIpcInvokeError(err) {
|
|
|
4058
4100
|
if (isPrNotMergeableError(msg)) return formatMergePrError(msg);
|
|
4059
4101
|
return formatGhLandError(msg);
|
|
4060
4102
|
}
|
|
4103
|
+
var GITHUB_PR_BODY_MAX_CHARS, GITHUB_PR_BODY_SAFE_CHARS;
|
|
4061
4104
|
var init_gh_errors = __esm({
|
|
4062
4105
|
"src/git/gh-errors.ts"() {
|
|
4063
4106
|
"use strict";
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
// src/git/github-agent-auth.ts
|
|
4068
|
-
function githubAgentAuthDir() {
|
|
4069
|
-
const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
|
|
4070
|
-
if (override) return override;
|
|
4071
|
-
return (0, import_node_path14.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
|
|
4072
|
-
}
|
|
4073
|
-
function githubCredentialStorePath() {
|
|
4074
|
-
return (0, import_node_path14.join)(githubAgentAuthDir(), "git-credentials");
|
|
4075
|
-
}
|
|
4076
|
-
function githubGhConfigDir() {
|
|
4077
|
-
return (0, import_node_path14.join)(githubAgentAuthDir(), "gh");
|
|
4078
|
-
}
|
|
4079
|
-
function writePrivateFile2(file, body) {
|
|
4080
|
-
(0, import_node_fs13.mkdirSync)((0, import_node_path14.dirname)(file), { recursive: true, mode: 448 });
|
|
4081
|
-
try {
|
|
4082
|
-
(0, import_node_fs13.chmodSync)((0, import_node_path14.dirname)(file), 448);
|
|
4083
|
-
} catch {
|
|
4084
|
-
}
|
|
4085
|
-
(0, import_node_fs13.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
|
|
4086
|
-
try {
|
|
4087
|
-
(0, import_node_fs13.chmodSync)(file, 384);
|
|
4088
|
-
} catch {
|
|
4089
|
-
}
|
|
4090
|
-
}
|
|
4091
|
-
function gitCredentialStoreContents(token) {
|
|
4092
|
-
return `https://x-access-token:${encodeURIComponent(token)}@github.com
|
|
4093
|
-
`;
|
|
4094
|
-
}
|
|
4095
|
-
function ghHostsYml(token, user = "x-access-token") {
|
|
4096
|
-
const u = user.replace(/[^A-Za-z0-9._-]/g, "") || "x-access-token";
|
|
4097
|
-
return [
|
|
4098
|
-
"github.com:",
|
|
4099
|
-
" git_protocol: https",
|
|
4100
|
-
` user: ${u}`,
|
|
4101
|
-
` oauth_token: ${token}`,
|
|
4102
|
-
" users:",
|
|
4103
|
-
` ${u}:`,
|
|
4104
|
-
` oauth_token: ${token}`,
|
|
4105
|
-
""
|
|
4106
|
-
].join("\n");
|
|
4107
|
-
}
|
|
4108
|
-
function materializeGithubAgentAuth(token, user) {
|
|
4109
|
-
const trimmed = token.trim();
|
|
4110
|
-
if (!trimmed) return;
|
|
4111
|
-
const root = githubAgentAuthDir();
|
|
4112
|
-
(0, import_node_fs13.mkdirSync)(root, { recursive: true, mode: 448 });
|
|
4113
|
-
try {
|
|
4114
|
-
(0, import_node_fs13.chmodSync)(root, 448);
|
|
4115
|
-
} catch {
|
|
4116
|
-
}
|
|
4117
|
-
writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
|
|
4118
|
-
const ghDir = githubGhConfigDir();
|
|
4119
|
-
(0, import_node_fs13.mkdirSync)(ghDir, { recursive: true, mode: 448 });
|
|
4120
|
-
writePrivateFile2((0, import_node_path14.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
|
|
4121
|
-
writePrivateFile2((0, import_node_path14.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
|
|
4122
|
-
}
|
|
4123
|
-
function githubAgentAuthReady() {
|
|
4124
|
-
return (0, import_node_fs13.existsSync)(githubCredentialStorePath()) && (0, import_node_fs13.existsSync)((0, import_node_path14.join)(githubGhConfigDir(), "hosts.yml"));
|
|
4125
|
-
}
|
|
4126
|
-
function githubCredentialHelperGitConfig() {
|
|
4127
|
-
const file = githubCredentialStorePath();
|
|
4128
|
-
return [
|
|
4129
|
-
{ key: "credential.helper", value: "" },
|
|
4130
|
-
{ key: "credential.helper", value: `store --file=${file}` }
|
|
4131
|
-
];
|
|
4132
|
-
}
|
|
4133
|
-
function githubGhConfigEnv() {
|
|
4134
|
-
return {
|
|
4135
|
-
GH_CONFIG_DIR: githubGhConfigDir(),
|
|
4136
|
-
GH_PROMPT_DISABLED: "1"
|
|
4137
|
-
};
|
|
4138
|
-
}
|
|
4139
|
-
var import_node_fs13, import_node_os4, import_node_path14;
|
|
4140
|
-
var init_github_agent_auth = __esm({
|
|
4141
|
-
"src/git/github-agent-auth.ts"() {
|
|
4142
|
-
"use strict";
|
|
4143
|
-
import_node_fs13 = require("fs");
|
|
4144
|
-
import_node_os4 = require("os");
|
|
4145
|
-
import_node_path14 = require("path");
|
|
4107
|
+
GITHUB_PR_BODY_MAX_CHARS = 65536;
|
|
4108
|
+
GITHUB_PR_BODY_SAFE_CHARS = 6e4;
|
|
4146
4109
|
}
|
|
4147
4110
|
});
|
|
4148
4111
|
|
|
4149
4112
|
// src/agents/path.ts
|
|
4150
4113
|
function prependPathDir(env, dir) {
|
|
4151
|
-
if (!dir || !(0,
|
|
4114
|
+
if (!dir || !(0, import_node_fs13.existsSync)(dir)) return;
|
|
4152
4115
|
const current = env.PATH ?? "";
|
|
4153
|
-
const parts = current.split(
|
|
4116
|
+
const parts = current.split(import_node_path14.delimiter).filter(Boolean);
|
|
4154
4117
|
if (parts.includes(dir)) {
|
|
4155
4118
|
env.PATH = current;
|
|
4156
4119
|
return;
|
|
4157
4120
|
}
|
|
4158
|
-
env.PATH = [dir, ...parts].join(
|
|
4121
|
+
env.PATH = [dir, ...parts].join(import_node_path14.delimiter);
|
|
4159
4122
|
}
|
|
4160
|
-
function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0,
|
|
4161
|
-
return (0,
|
|
4123
|
+
function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os4.homedir)()) {
|
|
4124
|
+
return (0, import_node_path14.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
|
|
4162
4125
|
}
|
|
4163
4126
|
function isConductorBundledCli(filePath) {
|
|
4164
4127
|
const p = (filePath ?? "").replace(/\\/g, "/");
|
|
4165
4128
|
return p.includes("/com.conductor.app/bin/") || p.endsWith("/com.conductor.app/bin");
|
|
4166
4129
|
}
|
|
4167
4130
|
function ensureAgentPath(env = process.env) {
|
|
4168
|
-
const home = env.HOME || env.USERPROFILE || (0,
|
|
4131
|
+
const home = env.HOME || env.USERPROFILE || (0, import_node_os4.homedir)();
|
|
4169
4132
|
const current = env.PATH ?? "";
|
|
4170
|
-
const parts = current.split(
|
|
4133
|
+
const parts = current.split(import_node_path14.delimiter).filter(Boolean);
|
|
4171
4134
|
const seen = new Set(parts);
|
|
4172
4135
|
const extras = [
|
|
4173
|
-
...EXTRA_BIN_DIRS.map((rel) => (0,
|
|
4136
|
+
...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path14.join)(home, rel)),
|
|
4174
4137
|
"/opt/homebrew/bin",
|
|
4175
4138
|
"/usr/local/bin",
|
|
4176
4139
|
// Keep after Homebrew/npm so a user-installed CLI still wins.
|
|
4177
4140
|
conductorBundledBinDir(home)
|
|
4178
4141
|
];
|
|
4179
4142
|
for (const dir of extras.reverse()) {
|
|
4180
|
-
if (!dir || seen.has(dir) || !(0,
|
|
4143
|
+
if (!dir || seen.has(dir) || !(0, import_node_fs13.existsSync)(dir)) continue;
|
|
4181
4144
|
parts.unshift(dir);
|
|
4182
4145
|
seen.add(dir);
|
|
4183
4146
|
}
|
|
4184
|
-
const next = parts.join(
|
|
4147
|
+
const next = parts.join(import_node_path14.delimiter);
|
|
4185
4148
|
env.PATH = next;
|
|
4186
4149
|
return next;
|
|
4187
4150
|
}
|
|
@@ -4195,7 +4158,7 @@ function enrichPathWithNpmGlobalBin(env = process.env) {
|
|
|
4195
4158
|
stdio: ["ignore", "pipe", "ignore"]
|
|
4196
4159
|
}).trim().split(/\r?\n/).find(Boolean);
|
|
4197
4160
|
if (prefix) {
|
|
4198
|
-
const binDir = process.platform === "win32" ? prefix : (0,
|
|
4161
|
+
const binDir = process.platform === "win32" ? prefix : (0, import_node_path14.join)(prefix, "bin");
|
|
4199
4162
|
prependPathDir(env, binDir);
|
|
4200
4163
|
}
|
|
4201
4164
|
} catch {
|
|
@@ -4223,14 +4186,14 @@ function withExportedPath(command, pathValue) {
|
|
|
4223
4186
|
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
4224
4187
|
return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
|
|
4225
4188
|
}
|
|
4226
|
-
var
|
|
4189
|
+
var import_node_fs13, import_node_child_process3, import_node_os4, import_node_path14, EXTRA_BIN_DIRS;
|
|
4227
4190
|
var init_path = __esm({
|
|
4228
4191
|
"src/agents/path.ts"() {
|
|
4229
4192
|
"use strict";
|
|
4230
|
-
|
|
4193
|
+
import_node_fs13 = require("fs");
|
|
4231
4194
|
import_node_child_process3 = require("child_process");
|
|
4232
|
-
|
|
4233
|
-
|
|
4195
|
+
import_node_os4 = require("os");
|
|
4196
|
+
import_node_path14 = require("path");
|
|
4234
4197
|
EXTRA_BIN_DIRS = [
|
|
4235
4198
|
".local/bin",
|
|
4236
4199
|
".cargo/bin",
|
|
@@ -4247,6 +4210,88 @@ var init_path = __esm({
|
|
|
4247
4210
|
}
|
|
4248
4211
|
});
|
|
4249
4212
|
|
|
4213
|
+
// src/git/github-agent-auth.ts
|
|
4214
|
+
function githubAgentAuthDir() {
|
|
4215
|
+
const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
|
|
4216
|
+
if (override) return override;
|
|
4217
|
+
return (0, import_node_path15.join)((0, import_node_os5.homedir)(), ".sideboard-git-auth");
|
|
4218
|
+
}
|
|
4219
|
+
function githubCredentialStorePath() {
|
|
4220
|
+
return (0, import_node_path15.join)(githubAgentAuthDir(), "git-credentials");
|
|
4221
|
+
}
|
|
4222
|
+
function githubGhConfigDir() {
|
|
4223
|
+
return (0, import_node_path15.join)(githubAgentAuthDir(), "gh");
|
|
4224
|
+
}
|
|
4225
|
+
function writePrivateFile2(file, body) {
|
|
4226
|
+
(0, import_node_fs14.mkdirSync)((0, import_node_path15.dirname)(file), { recursive: true, mode: 448 });
|
|
4227
|
+
try {
|
|
4228
|
+
(0, import_node_fs14.chmodSync)((0, import_node_path15.dirname)(file), 448);
|
|
4229
|
+
} catch {
|
|
4230
|
+
}
|
|
4231
|
+
(0, import_node_fs14.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
|
|
4232
|
+
try {
|
|
4233
|
+
(0, import_node_fs14.chmodSync)(file, 384);
|
|
4234
|
+
} catch {
|
|
4235
|
+
}
|
|
4236
|
+
}
|
|
4237
|
+
function gitCredentialStoreContents(token) {
|
|
4238
|
+
return `https://x-access-token:${encodeURIComponent(token)}@github.com
|
|
4239
|
+
`;
|
|
4240
|
+
}
|
|
4241
|
+
function ghHostsYml(token, user = "x-access-token") {
|
|
4242
|
+
const u = user.replace(/[^A-Za-z0-9._-]/g, "") || "x-access-token";
|
|
4243
|
+
return [
|
|
4244
|
+
"github.com:",
|
|
4245
|
+
" git_protocol: https",
|
|
4246
|
+
` user: ${u}`,
|
|
4247
|
+
` oauth_token: ${token}`,
|
|
4248
|
+
" users:",
|
|
4249
|
+
` ${u}:`,
|
|
4250
|
+
` oauth_token: ${token}`,
|
|
4251
|
+
""
|
|
4252
|
+
].join("\n");
|
|
4253
|
+
}
|
|
4254
|
+
function materializeGithubAgentAuth(token, user) {
|
|
4255
|
+
const trimmed = token.trim();
|
|
4256
|
+
if (!trimmed) return;
|
|
4257
|
+
const root = githubAgentAuthDir();
|
|
4258
|
+
(0, import_node_fs14.mkdirSync)(root, { recursive: true, mode: 448 });
|
|
4259
|
+
try {
|
|
4260
|
+
(0, import_node_fs14.chmodSync)(root, 448);
|
|
4261
|
+
} catch {
|
|
4262
|
+
}
|
|
4263
|
+
writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
|
|
4264
|
+
const ghDir = githubGhConfigDir();
|
|
4265
|
+
(0, import_node_fs14.mkdirSync)(ghDir, { recursive: true, mode: 448 });
|
|
4266
|
+
writePrivateFile2((0, import_node_path15.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
|
|
4267
|
+
writePrivateFile2((0, import_node_path15.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
|
|
4268
|
+
}
|
|
4269
|
+
function githubAgentAuthReady() {
|
|
4270
|
+
return (0, import_node_fs14.existsSync)(githubCredentialStorePath()) && (0, import_node_fs14.existsSync)((0, import_node_path15.join)(githubGhConfigDir(), "hosts.yml"));
|
|
4271
|
+
}
|
|
4272
|
+
function githubCredentialHelperGitConfig() {
|
|
4273
|
+
const file = githubCredentialStorePath();
|
|
4274
|
+
return [
|
|
4275
|
+
{ key: "credential.helper", value: "" },
|
|
4276
|
+
{ key: "credential.helper", value: `store --file=${file}` }
|
|
4277
|
+
];
|
|
4278
|
+
}
|
|
4279
|
+
function githubGhConfigEnv() {
|
|
4280
|
+
return {
|
|
4281
|
+
GH_CONFIG_DIR: githubGhConfigDir(),
|
|
4282
|
+
GH_PROMPT_DISABLED: "1"
|
|
4283
|
+
};
|
|
4284
|
+
}
|
|
4285
|
+
var import_node_fs14, import_node_os5, import_node_path15;
|
|
4286
|
+
var init_github_agent_auth = __esm({
|
|
4287
|
+
"src/git/github-agent-auth.ts"() {
|
|
4288
|
+
"use strict";
|
|
4289
|
+
import_node_fs14 = require("fs");
|
|
4290
|
+
import_node_os5 = require("os");
|
|
4291
|
+
import_node_path15 = require("path");
|
|
4292
|
+
}
|
|
4293
|
+
});
|
|
4294
|
+
|
|
4250
4295
|
// src/git/stale-lock.ts
|
|
4251
4296
|
function isIndexLockError(text5) {
|
|
4252
4297
|
return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text5);
|
|
@@ -4373,7 +4418,10 @@ async function gh(args, cwd, opts) {
|
|
|
4373
4418
|
timeoutMs: opts?.timeoutMs,
|
|
4374
4419
|
env: {
|
|
4375
4420
|
GH_PROMPT_DISABLED: "1",
|
|
4376
|
-
GIT_TERMINAL_PROMPT: "0"
|
|
4421
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
4422
|
+
// Isolated hosts.yml uses git_protocol: https so `gh pr create` does not
|
|
4423
|
+
// shell out over SSH when Settings → Git is SSH (ask_git in Electron).
|
|
4424
|
+
...githubAgentAuthReady() ? githubGhConfigEnv() : {}
|
|
4377
4425
|
}
|
|
4378
4426
|
});
|
|
4379
4427
|
}
|
|
@@ -4389,11 +4437,95 @@ var init_run = __esm({
|
|
|
4389
4437
|
"use strict";
|
|
4390
4438
|
import_execa2 = require("execa");
|
|
4391
4439
|
init_path();
|
|
4440
|
+
init_github_agent_auth();
|
|
4392
4441
|
init_stale_lock();
|
|
4393
4442
|
}
|
|
4394
4443
|
});
|
|
4395
4444
|
|
|
4445
|
+
// src/git/worktree-exclude.ts
|
|
4446
|
+
var worktree_exclude_exports = {};
|
|
4447
|
+
__export(worktree_exclude_exports, {
|
|
4448
|
+
WORKTREE_SIDEBOARD_EXCLUDE: () => WORKTREE_SIDEBOARD_EXCLUDE,
|
|
4449
|
+
ensureWorktreeSideboardIgnored: () => ensureWorktreeSideboardIgnored
|
|
4450
|
+
});
|
|
4451
|
+
function excludeHasSideboard(body) {
|
|
4452
|
+
return body.split(/\r?\n/).some((line) => {
|
|
4453
|
+
const t = line.trim();
|
|
4454
|
+
return t === ".sideboard/" || t === ".sideboard" || t === "/.sideboard/";
|
|
4455
|
+
});
|
|
4456
|
+
}
|
|
4457
|
+
async function ensureWorktreeSideboardIgnored(worktreePath) {
|
|
4458
|
+
if (!worktreePath.trim()) return;
|
|
4459
|
+
const gitDir = await git(["rev-parse", "--absolute-git-dir"], worktreePath, {
|
|
4460
|
+
reject: false,
|
|
4461
|
+
timeoutMs: 5e3
|
|
4462
|
+
});
|
|
4463
|
+
if (gitDir.exitCode !== 0) return;
|
|
4464
|
+
const dir = gitDir.stdout.trim();
|
|
4465
|
+
if (!dir) return;
|
|
4466
|
+
const excludePath = (0, import_node_path17.join)(dir, "info", "exclude");
|
|
4467
|
+
(0, import_node_fs16.mkdirSync)((0, import_node_path17.dirname)(excludePath), { recursive: true });
|
|
4468
|
+
let body = "";
|
|
4469
|
+
try {
|
|
4470
|
+
body = (0, import_node_fs16.readFileSync)(excludePath, "utf8");
|
|
4471
|
+
} catch {
|
|
4472
|
+
body = "";
|
|
4473
|
+
}
|
|
4474
|
+
if (!excludeHasSideboard(body)) {
|
|
4475
|
+
const prefix = body && !body.endsWith("\n") ? `${body}
|
|
4476
|
+
` : body;
|
|
4477
|
+
(0, import_node_fs16.writeFileSync)(
|
|
4478
|
+
excludePath,
|
|
4479
|
+
`${prefix}${EXCLUDE_COMMENT}
|
|
4480
|
+
${WORKTREE_SIDEBOARD_EXCLUDE}
|
|
4481
|
+
`,
|
|
4482
|
+
"utf8"
|
|
4483
|
+
);
|
|
4484
|
+
}
|
|
4485
|
+
const listed = await git(["ls-files", "-z", "--", ".sideboard"], worktreePath, {
|
|
4486
|
+
reject: false,
|
|
4487
|
+
timeoutMs: 5e3
|
|
4488
|
+
});
|
|
4489
|
+
if (listed.exitCode !== 0 || !listed.stdout) return;
|
|
4490
|
+
const files = listed.stdout.split("\0").filter(Boolean);
|
|
4491
|
+
if (files.length === 0) return;
|
|
4492
|
+
await git(["update-index", "--skip-worktree", "--", ...files], worktreePath, {
|
|
4493
|
+
reject: false,
|
|
4494
|
+
timeoutMs: 8e3
|
|
4495
|
+
});
|
|
4496
|
+
}
|
|
4497
|
+
var import_node_fs16, import_node_path17, WORKTREE_SIDEBOARD_EXCLUDE, EXCLUDE_COMMENT;
|
|
4498
|
+
var init_worktree_exclude = __esm({
|
|
4499
|
+
"src/git/worktree-exclude.ts"() {
|
|
4500
|
+
"use strict";
|
|
4501
|
+
import_node_fs16 = require("fs");
|
|
4502
|
+
import_node_path17 = require("path");
|
|
4503
|
+
init_run();
|
|
4504
|
+
WORKTREE_SIDEBOARD_EXCLUDE = ".sideboard/";
|
|
4505
|
+
EXCLUDE_COMMENT = "# Sideboard worktree scratch \u2014 do not commit";
|
|
4506
|
+
}
|
|
4507
|
+
});
|
|
4508
|
+
|
|
4396
4509
|
// src/git/git-auth-mode.ts
|
|
4510
|
+
function githubHttpsInsteadOfEntries(remoteUrl) {
|
|
4511
|
+
const entries = [...HTTPS_REWRITE];
|
|
4512
|
+
const url = remoteUrl?.trim() ?? "";
|
|
4513
|
+
const scpAlias = url.match(/^(git@github\.com-[^:]+):/i);
|
|
4514
|
+
if (scpAlias?.[1]) {
|
|
4515
|
+
entries.push({
|
|
4516
|
+
key: "url.https://github.com/.insteadOf",
|
|
4517
|
+
value: `${scpAlias[1]}:`
|
|
4518
|
+
});
|
|
4519
|
+
}
|
|
4520
|
+
const sshAlias = url.match(/^ssh:\/\/git@(github\.com-[^/]+)\//i);
|
|
4521
|
+
if (sshAlias?.[1]) {
|
|
4522
|
+
entries.push({
|
|
4523
|
+
key: "url.https://github.com/.insteadOf",
|
|
4524
|
+
value: `ssh://git@${sshAlias[1]}/`
|
|
4525
|
+
});
|
|
4526
|
+
}
|
|
4527
|
+
return entries;
|
|
4528
|
+
}
|
|
4397
4529
|
function nonInteractiveGitProcessEnv() {
|
|
4398
4530
|
return {
|
|
4399
4531
|
GIT_TERMINAL_PROMPT: "0",
|
|
@@ -4416,16 +4548,19 @@ function appendIndexedGitConfig(existing, entries) {
|
|
|
4416
4548
|
out.GIT_CONFIG_COUNT = String(count + entries.length);
|
|
4417
4549
|
return out;
|
|
4418
4550
|
}
|
|
4419
|
-
function githubAgentGitEnv(existing) {
|
|
4551
|
+
function githubAgentGitEnv(existing, opts) {
|
|
4420
4552
|
const helpers = githubAgentAuthReady() ? githubCredentialHelperGitConfig() : [{ key: "credential.helper", value: "" }];
|
|
4421
|
-
return appendIndexedGitConfig(existing, [
|
|
4553
|
+
return appendIndexedGitConfig(existing, [
|
|
4554
|
+
...githubHttpsInsteadOfEntries(opts?.remoteUrl),
|
|
4555
|
+
...helpers
|
|
4556
|
+
]);
|
|
4422
4557
|
}
|
|
4423
4558
|
function applyGithubGitAuthEnv(existing, opts) {
|
|
4424
4559
|
const out = { ...nonInteractiveGitProcessEnv() };
|
|
4425
4560
|
const token = opts.token?.trim() || existing?.GH_TOKEN?.trim() || "" || "";
|
|
4426
4561
|
if (token) materializeGithubAgentAuth(token);
|
|
4427
4562
|
Object.assign(out, githubGhConfigEnv());
|
|
4428
|
-
if (opts.mode === "ssh") return out;
|
|
4563
|
+
if (opts.mode === "ssh" && !token) return out;
|
|
4429
4564
|
Object.assign(out, githubAgentGitEnv(existing));
|
|
4430
4565
|
return out;
|
|
4431
4566
|
}
|
|
@@ -4484,7 +4619,7 @@ async function warmGithubAgentAuth(opts) {
|
|
|
4484
4619
|
}
|
|
4485
4620
|
function normalizeWritableRoot(raw) {
|
|
4486
4621
|
const trimmed = raw.trim().replace(/\/+$/, "");
|
|
4487
|
-
return trimmed && (0,
|
|
4622
|
+
return trimmed && (0, import_node_path18.isAbsolute)(trimmed) ? trimmed : null;
|
|
4488
4623
|
}
|
|
4489
4624
|
async function resolveCodexGitWritableRoots(cwd) {
|
|
4490
4625
|
const roots = /* @__PURE__ */ new Set();
|
|
@@ -4541,8 +4676,9 @@ function formatGitAuthModeDirective(mode) {
|
|
|
4541
4676
|
case "ssh":
|
|
4542
4677
|
return [
|
|
4543
4678
|
"Git authentication (Settings \u2192 Git mode: SSH):",
|
|
4544
|
-
"-
|
|
4545
|
-
"-
|
|
4679
|
+
"- Stored remotes stay SSH (`git@github.com:\u2026`). Do not `git remote set-url` or rewrite them to HTTPS.",
|
|
4680
|
+
"- This process may push over HTTPS via `gh` (process-only `insteadOf`) so ask_git / unattended turns work when ssh-agent is missing \u2014 that does not change the stored remote.",
|
|
4681
|
+
"- SSH is batch-mode: it will not prompt for a Keychain password. If both SSH and HTTPS fail, tell the user to unlock ssh-agent or run `gh auth login` (or switch Settings \u2192 Git to Auto).",
|
|
4546
4682
|
"- `gh` already authenticates for PRs/API (no token in the environment). Do not set GitHub token environment variables or run `gh auth login` from this turn.",
|
|
4547
4683
|
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
4548
4684
|
].join("\n");
|
|
@@ -4561,11 +4697,11 @@ function formatGitAuthModeDirective(mode) {
|
|
|
4561
4697
|
].join("\n");
|
|
4562
4698
|
}
|
|
4563
4699
|
}
|
|
4564
|
-
var
|
|
4700
|
+
var import_node_path18, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
|
|
4565
4701
|
var init_git_auth_mode = __esm({
|
|
4566
4702
|
"src/git/git-auth-mode.ts"() {
|
|
4567
4703
|
"use strict";
|
|
4568
|
-
|
|
4704
|
+
import_node_path18 = require("path");
|
|
4569
4705
|
init_app_settings();
|
|
4570
4706
|
init_github_agent_auth();
|
|
4571
4707
|
init_run();
|
|
@@ -5027,7 +5163,7 @@ async function resolveRepoRoot(cwd) {
|
|
|
5027
5163
|
}
|
|
5028
5164
|
function canonicalizeRepoPath(path2) {
|
|
5029
5165
|
try {
|
|
5030
|
-
return (0,
|
|
5166
|
+
return (0, import_node_fs17.realpathSync)(path2);
|
|
5031
5167
|
} catch {
|
|
5032
5168
|
return path2.replace(/\/+$/, "");
|
|
5033
5169
|
}
|
|
@@ -5766,6 +5902,16 @@ function originFetchBranch(sourceRef) {
|
|
|
5766
5902
|
if (ref.startsWith("origin/")) return ref.slice("origin/".length) || null;
|
|
5767
5903
|
return ref;
|
|
5768
5904
|
}
|
|
5905
|
+
async function originRemoteUrl(cwd) {
|
|
5906
|
+
const result = await git(["remote", "get-url", "origin"], cwd, { reject: false });
|
|
5907
|
+
return result.exitCode === 0 ? result.stdout.trim() : "";
|
|
5908
|
+
}
|
|
5909
|
+
function githubHttpsRetryEnv(remoteUrl) {
|
|
5910
|
+
return {
|
|
5911
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
5912
|
+
...githubAgentGitEnv(void 0, { remoteUrl })
|
|
5913
|
+
};
|
|
5914
|
+
}
|
|
5769
5915
|
async function fetchOriginWithAuth(repoPath, args, timeoutMs) {
|
|
5770
5916
|
const first = await git(args, repoPath, { reject: false, timeoutMs });
|
|
5771
5917
|
if (first.exitCode === 0) return true;
|
|
@@ -5775,15 +5921,14 @@ async function fetchOriginWithAuth(repoPath, args, timeoutMs) {
|
|
|
5775
5921
|
} catch {
|
|
5776
5922
|
return false;
|
|
5777
5923
|
}
|
|
5778
|
-
if (mode === "ssh") return false;
|
|
5779
5924
|
const token = await resolveGithubAgentToken(mode, repoPath);
|
|
5780
5925
|
if (!token) return false;
|
|
5926
|
+
const remoteUrl = await originRemoteUrl(repoPath);
|
|
5781
5927
|
const tryHttps = async (header) => git(args, repoPath, {
|
|
5782
5928
|
reject: false,
|
|
5783
5929
|
timeoutMs,
|
|
5784
|
-
env:
|
|
5930
|
+
env: githubHttpsRetryEnv(remoteUrl),
|
|
5785
5931
|
config: {
|
|
5786
|
-
"url.https://github.com/.insteadOf": "git@github.com:",
|
|
5787
5932
|
"http.extraHeader": header
|
|
5788
5933
|
}
|
|
5789
5934
|
});
|
|
@@ -5865,8 +6010,8 @@ async function refreshOriginAndMaybeFastForwardMain(repoPath, sourceRef) {
|
|
|
5865
6010
|
}
|
|
5866
6011
|
async function createThreadWorktree(opts) {
|
|
5867
6012
|
let branchName = `thread/${opts.slug}`;
|
|
5868
|
-
const worktreePath = (0,
|
|
5869
|
-
if ((0,
|
|
6013
|
+
const worktreePath = (0, import_node_path19.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
6014
|
+
if ((0, import_node_fs17.existsSync)(worktreePath)) {
|
|
5870
6015
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
5871
6016
|
}
|
|
5872
6017
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -5901,13 +6046,14 @@ ${add.stdout}`;
|
|
|
5901
6046
|
});
|
|
5902
6047
|
branchName = added;
|
|
5903
6048
|
await ensureGhPreferOrigin(worktreePath);
|
|
6049
|
+
await ensureWorktreeSideboardIgnored(worktreePath);
|
|
5904
6050
|
return { branchName, worktreePath };
|
|
5905
6051
|
}
|
|
5906
6052
|
async function createExistingBranchWorktree(opts) {
|
|
5907
6053
|
const branchName = opts.branchName.trim();
|
|
5908
6054
|
if (!branchName) throw new Error("branch name required");
|
|
5909
|
-
const worktreePath = (0,
|
|
5910
|
-
if ((0,
|
|
6055
|
+
const worktreePath = (0, import_node_path19.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
6056
|
+
if ((0, import_node_fs17.existsSync)(worktreePath)) {
|
|
5911
6057
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
5912
6058
|
}
|
|
5913
6059
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -5945,6 +6091,7 @@ async function createExistingBranchWorktree(opts) {
|
|
|
5945
6091
|
await git(["checkout", "-B", branchName], worktreePath, { reject: false });
|
|
5946
6092
|
}
|
|
5947
6093
|
await ensureGhPreferOrigin(worktreePath);
|
|
6094
|
+
await ensureWorktreeSideboardIgnored(worktreePath);
|
|
5948
6095
|
return { branchName, worktreePath };
|
|
5949
6096
|
}
|
|
5950
6097
|
async function removeWorktree(repoPath, worktreePath, opts) {
|
|
@@ -6033,7 +6180,9 @@ async function currentBranch(worktreePath) {
|
|
|
6033
6180
|
async function commitAll(worktreePath, message) {
|
|
6034
6181
|
const dirty = await isDirty(worktreePath);
|
|
6035
6182
|
if (!dirty) return false;
|
|
6183
|
+
await ensureWorktreeSideboardIgnored(worktreePath);
|
|
6036
6184
|
await git(["add", "-A"], worktreePath);
|
|
6185
|
+
await git(["reset", "-q", "--", ".sideboard"], worktreePath, { reject: false });
|
|
6037
6186
|
await git(["commit", "-m", message], worktreePath);
|
|
6038
6187
|
return true;
|
|
6039
6188
|
}
|
|
@@ -6047,14 +6196,14 @@ async function pushBranch(worktreePath, branchName) {
|
|
|
6047
6196
|
const token = await resolveGithubAgentToken(getGithubGitAuthMode(), worktreePath);
|
|
6048
6197
|
if (!slug || !token) {
|
|
6049
6198
|
throw new Error(
|
|
6050
|
-
sshErr || `git push origin ${branchName} failed` + (!token ? " (
|
|
6199
|
+
sshErr || `git push origin ${branchName} failed` + (!token ? " (SSH remote and gh auth token unavailable \u2014 unlock ssh-agent or run: gh auth login)" : "")
|
|
6051
6200
|
);
|
|
6052
6201
|
}
|
|
6202
|
+
const remoteUrl = await originRemoteUrl(worktreePath);
|
|
6053
6203
|
const tryHttps = async (header) => git(["push", "-u", "origin", branchName], worktreePath, {
|
|
6054
6204
|
reject: false,
|
|
6055
|
-
env:
|
|
6205
|
+
env: githubHttpsRetryEnv(remoteUrl),
|
|
6056
6206
|
config: {
|
|
6057
|
-
"url.https://github.com/.insteadOf": "git@github.com:",
|
|
6058
6207
|
"http.extraHeader": header
|
|
6059
6208
|
}
|
|
6060
6209
|
});
|
|
@@ -6184,6 +6333,32 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
6184
6333
|
const repoArgs = ghRepoSelectArgs(slug);
|
|
6185
6334
|
const headRef = ghHeadRef(slug, opts.head);
|
|
6186
6335
|
const branchOnly = opts.head.trim().replace(/^refs\/heads\//, "");
|
|
6336
|
+
const bodyText = clampGithubPrBody(opts.body ?? opts.title);
|
|
6337
|
+
const bodyFile = (0, import_node_path19.join)(
|
|
6338
|
+
(0, import_node_os6.tmpdir)(),
|
|
6339
|
+
`sideboard-pr-body-${process.pid}-${(0, import_node_crypto6.randomBytes)(6).toString("hex")}.md`
|
|
6340
|
+
);
|
|
6341
|
+
(0, import_node_fs17.writeFileSync)(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
|
|
6342
|
+
`, "utf8");
|
|
6343
|
+
const bodyArgs = ["--body-file", bodyFile];
|
|
6344
|
+
try {
|
|
6345
|
+
return await createOrUpdatePrWithBodyFile(worktreePath, {
|
|
6346
|
+
...opts,
|
|
6347
|
+
slug,
|
|
6348
|
+
repoArgs,
|
|
6349
|
+
headRef,
|
|
6350
|
+
branchOnly,
|
|
6351
|
+
bodyArgs
|
|
6352
|
+
});
|
|
6353
|
+
} finally {
|
|
6354
|
+
try {
|
|
6355
|
+
(0, import_node_fs17.unlinkSync)(bodyFile);
|
|
6356
|
+
} catch {
|
|
6357
|
+
}
|
|
6358
|
+
}
|
|
6359
|
+
}
|
|
6360
|
+
async function createOrUpdatePrWithBodyFile(worktreePath, opts) {
|
|
6361
|
+
const { slug, repoArgs, headRef, branchOnly, bodyArgs } = opts;
|
|
6187
6362
|
const existing = await gh(
|
|
6188
6363
|
[...repoArgs, "pr", "view", branchOnly, "--json", "url", "--jq", ".url"],
|
|
6189
6364
|
worktreePath,
|
|
@@ -6199,8 +6374,7 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
6199
6374
|
branchOnly,
|
|
6200
6375
|
"--title",
|
|
6201
6376
|
opts.title,
|
|
6202
|
-
|
|
6203
|
-
opts.body ?? opts.title
|
|
6377
|
+
...bodyArgs
|
|
6204
6378
|
],
|
|
6205
6379
|
worktreePath,
|
|
6206
6380
|
{ reject: false }
|
|
@@ -6215,8 +6389,7 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
6215
6389
|
"--web",
|
|
6216
6390
|
"--title",
|
|
6217
6391
|
opts.title,
|
|
6218
|
-
|
|
6219
|
-
opts.body ?? opts.title,
|
|
6392
|
+
...bodyArgs,
|
|
6220
6393
|
"--base",
|
|
6221
6394
|
opts.base,
|
|
6222
6395
|
"--head",
|
|
@@ -6237,8 +6410,7 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
6237
6410
|
"create",
|
|
6238
6411
|
"--title",
|
|
6239
6412
|
opts.title,
|
|
6240
|
-
|
|
6241
|
-
opts.body ?? opts.title,
|
|
6413
|
+
...bodyArgs,
|
|
6242
6414
|
"--base",
|
|
6243
6415
|
opts.base,
|
|
6244
6416
|
"--head",
|
|
@@ -6262,10 +6434,10 @@ function sameRepoPath(a, b) {
|
|
|
6262
6434
|
return normalizeWorktreePath(a) === normalizeWorktreePath(b);
|
|
6263
6435
|
}
|
|
6264
6436
|
function listLocalThreadBranchSlugs(repoPath) {
|
|
6265
|
-
const refsDir = (0,
|
|
6266
|
-
if (!(0,
|
|
6437
|
+
const refsDir = (0, import_node_path19.join)(repoPath, ".git", "refs", "heads", "thread");
|
|
6438
|
+
if (!(0, import_node_fs17.existsSync)(refsDir)) return [];
|
|
6267
6439
|
try {
|
|
6268
|
-
return (0,
|
|
6440
|
+
return (0, import_node_fs17.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
|
|
6269
6441
|
} catch {
|
|
6270
6442
|
return [];
|
|
6271
6443
|
}
|
|
@@ -6273,8 +6445,8 @@ function listLocalThreadBranchSlugs(repoPath) {
|
|
|
6273
6445
|
function collectTakenTeamSlugs(repoPath) {
|
|
6274
6446
|
const taken = /* @__PURE__ */ new Set();
|
|
6275
6447
|
const root = worktreesRoot(repoPath);
|
|
6276
|
-
if ((0,
|
|
6277
|
-
for (const entry of (0,
|
|
6448
|
+
if ((0, import_node_fs17.existsSync)(root)) {
|
|
6449
|
+
for (const entry of (0, import_node_fs17.readdirSync)(root, { withFileTypes: true })) {
|
|
6278
6450
|
if (entry.isDirectory() && entry.name !== ".DS_Store") {
|
|
6279
6451
|
taken.add(normalizeTakenSlug(entry.name));
|
|
6280
6452
|
}
|
|
@@ -6295,23 +6467,26 @@ function allocateTeamSlug(repoPath) {
|
|
|
6295
6467
|
const taken = collectTakenTeamSlugs(repoPath);
|
|
6296
6468
|
for (let attempt = 0; attempt < 32; attempt++) {
|
|
6297
6469
|
const team = allocateTeamName(taken);
|
|
6298
|
-
const path2 = (0,
|
|
6299
|
-
if (!(0,
|
|
6470
|
+
const path2 = (0, import_node_path19.join)(worktreesRoot(repoPath), team.slug);
|
|
6471
|
+
if (!(0, import_node_fs17.existsSync)(path2)) return team;
|
|
6300
6472
|
taken.add(team.slug);
|
|
6301
6473
|
}
|
|
6302
6474
|
throw new Error("No available soccer team worktree directories left");
|
|
6303
6475
|
}
|
|
6304
|
-
var
|
|
6476
|
+
var import_node_crypto6, import_node_fs17, import_node_os6, import_node_path19;
|
|
6305
6477
|
var init_worktree = __esm({
|
|
6306
6478
|
"src/git/worktree.ts"() {
|
|
6307
6479
|
"use strict";
|
|
6308
|
-
|
|
6309
|
-
|
|
6480
|
+
import_node_crypto6 = require("crypto");
|
|
6481
|
+
import_node_fs17 = require("fs");
|
|
6482
|
+
import_node_os6 = require("os");
|
|
6483
|
+
import_node_path19 = require("path");
|
|
6310
6484
|
init_paths();
|
|
6311
6485
|
init_thread_store();
|
|
6312
6486
|
init_teams();
|
|
6313
6487
|
init_worktree_labels();
|
|
6314
6488
|
init_gh_errors();
|
|
6489
|
+
init_worktree_exclude();
|
|
6315
6490
|
init_git_auth_mode();
|
|
6316
6491
|
init_run();
|
|
6317
6492
|
init_repo_git_lock();
|
|
@@ -6383,7 +6558,7 @@ function coordinatorTurnReminder(opts) {
|
|
|
6383
6558
|
function ensureGlobalCoordinatorCwd(opts) {
|
|
6384
6559
|
const dir = globalAgentCwd();
|
|
6385
6560
|
try {
|
|
6386
|
-
(0,
|
|
6561
|
+
(0, import_node_fs18.mkdirSync)(dir, { recursive: true });
|
|
6387
6562
|
} catch {
|
|
6388
6563
|
return dir;
|
|
6389
6564
|
}
|
|
@@ -6391,7 +6566,7 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
6391
6566
|
let orchId = opts?.orchestratorThreadId?.trim() || "";
|
|
6392
6567
|
if (!orchId) {
|
|
6393
6568
|
try {
|
|
6394
|
-
const existing = (0,
|
|
6569
|
+
const existing = (0, import_node_fs18.readFileSync)((0, import_node_path20.join)(dir, "AGENTS.md"), "utf8");
|
|
6395
6570
|
const m = existing.match(
|
|
6396
6571
|
/YOUR orchestration thread id is `([0-9a-f-]{36})`/i
|
|
6397
6572
|
);
|
|
@@ -6434,9 +6609,9 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
6434
6609
|
"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."
|
|
6435
6610
|
].join("\n");
|
|
6436
6611
|
try {
|
|
6437
|
-
(0,
|
|
6612
|
+
(0, import_node_fs18.writeFileSync)((0, import_node_path20.join)(dir, "CLAUDE.md"), `${body}
|
|
6438
6613
|
`, "utf8");
|
|
6439
|
-
(0,
|
|
6614
|
+
(0, import_node_fs18.writeFileSync)((0, import_node_path20.join)(dir, "AGENTS.md"), `${body}
|
|
6440
6615
|
`, "utf8");
|
|
6441
6616
|
} catch {
|
|
6442
6617
|
}
|
|
@@ -6468,12 +6643,12 @@ function coordinatorSystemPrompt(opts) {
|
|
|
6468
6643
|
formatWorkspaceInventory(opts.workspaces)
|
|
6469
6644
|
].join("\n");
|
|
6470
6645
|
}
|
|
6471
|
-
var
|
|
6646
|
+
var import_node_fs18, import_node_path20, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
|
|
6472
6647
|
var init_coordinator_prompt = __esm({
|
|
6473
6648
|
"src/orchestrator/coordinator-prompt.ts"() {
|
|
6474
6649
|
"use strict";
|
|
6475
|
-
|
|
6476
|
-
|
|
6650
|
+
import_node_fs18 = require("fs");
|
|
6651
|
+
import_node_path20 = require("path");
|
|
6477
6652
|
init_worktree();
|
|
6478
6653
|
init_app_settings();
|
|
6479
6654
|
init_paths();
|
|
@@ -6483,8 +6658,8 @@ var init_coordinator_prompt = __esm({
|
|
|
6483
6658
|
"Discover:",
|
|
6484
6659
|
"- list_workspaces \u2014 registered repos (path + github slug when known)",
|
|
6485
6660
|
"- list_board \u2014 Home Kanban of worktrees (New / Draft / Review / Merged; one card per checkout). Path to merge: no PR \u2192 draft PR \u2192 open PR \u2192 merged. Archive removes the card to Settings \u2192 History. Queued/running are activity on the card, not columns. Orchestration chats are not on the board. Filters: query, repoPath, kind, column, limit.",
|
|
6486
|
-
"- list_branches / list_prs / list_issues \u2014 pass repoPath from list_workspaces (issues: Linear, AbleTime MCP, or GitHub Issues)",
|
|
6487
|
-
"- linear_list_teams / linear_get_issue / linear_create_issue / linear_update_issue / linear_comment \u2014 Linear Account connection; call linear_list_teams for team key and workflow states; pass ENG-123 or uuid. linear_get_issue returns comments, relations, parent/children, and the rest of the issue metadata. If mutations fail with a scope error, Disconnect and Connect Linear in Account settings.",
|
|
6661
|
+
"- list_branches / list_prs / list_issues \u2014 pass repoPath from list_workspaces (issues: Linear, AbleTime MCP, or GitHub Issues). list_issues accepts query and assignee (me / unassigned / all / user id) so Linear is not limited to tickets assigned to you.",
|
|
6662
|
+
"- linear_list_teams / linear_search_issues / linear_get_issue / linear_create_issue / linear_update_issue / linear_comment \u2014 Linear Account connection; call linear_list_teams for team key and workflow states; pass ENG-123 or uuid. linear_search_issues finds unassigned and other people's open issues (assignee=unassigned|all|me|user). linear_get_issue returns comments, relations, parent/children, and the rest of the issue metadata. If mutations fail with a scope error, Disconnect and Connect Linear in Account settings.",
|
|
6488
6663
|
"- abletime_orientation / abletime_list_projects / abletime_list_tasks / abletime_search_tasks / abletime_get_task / abletime_create_task / abletime_ensure_task \u2014 AbleTime Account personal access token (hosted MCP). Call orientation first. If work has no task yet, abletime_ensure_task creates one to track against (or create_thread from the default branch does that automatically when AbleTime is the preferred issue source).",
|
|
6489
6664
|
"- list_teams / slack_list_channels / slack_list_users / slack_search / slack_read / slack_post / slack_replies \u2014 Slack workspaces from Settings \u2192 Remote; pass team_id from list_teams",
|
|
6490
6665
|
"- Optional connectors (Vercel, Supabase, PostHog, Sentry) in Settings \u2192 Connectors inject tokens into worktree agent env when connected. Prefer official CLIs (`vercel`, `supabase`, `sentry-cli`) with those env vars. PostHog has no first-class CLI \u2014 use the HTTP API (`POSTHOG_PERSONAL_API_KEY`). If a CLI is missing, the user can Install CLI on that row (not auto-installed on Connect). Do not add vendor MCPs or ask the user to paste tokens again. Git (`gh`) stays Settings \u2192 Git; issue tracking stays Settings \u2192 Issues; Slack stays Settings \u2192 Remote (Sideboard MCP).",
|
|
@@ -6503,7 +6678,7 @@ var init_coordinator_prompt = __esm({
|
|
|
6503
6678
|
"- 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.",
|
|
6504
6679
|
"- 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.",
|
|
6505
6680
|
"- send_to_thread \u2014 queue a prompt (start/continue a chat turn). force_stop: true only to replace a wrong in-flight request \u2014 never to check in, resume after a halt notice, or because wait_for_turn returned stillRunning (that kills the child mid-thought)",
|
|
6506
|
-
"- 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.",
|
|
6681
|
+
"- 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). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. 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. If stillRunning stays true across many waits with the same lastActivityAt, the child is stuck \u2014 tell the user; do not invent a gate. 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.",
|
|
6507
6682
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
6508
6683
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
6509
6684
|
"Setup / run:",
|
|
@@ -6512,7 +6687,7 @@ var init_coordinator_prompt = __esm({
|
|
|
6512
6687
|
"Inspect / review / PRs:",
|
|
6513
6688
|
"- get_diff \u2014 compact diff summary",
|
|
6514
6689
|
'- request_review \u2014 open a Review chat tab on a worktree thread (attaches .claude/skills/review/SKILL.md when present, else seeds that skill / local guidelines; sends "Review changes in this workspace."); then wait_for_turn (loop while stillRunning) / get_turn_result on the returned id',
|
|
6515
|
-
"- ask_git \u2014 commit & push, open a draft PR, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing.",
|
|
6690
|
+
"- ask_git \u2014 commit & push, open a draft PR, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error.",
|
|
6516
6691
|
'- Merge (`ask_git` action=merge / send_to_thread "Merge PR.") only when the user explicitly asked to merge that PR. Do not merge because the work looks done, CI is green, or a typical flow includes it.',
|
|
6517
6692
|
'- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Merge the remote branch (main) into your branch and resolve conflicts. Then, commit and push your changes.", "Merge PR." (draft PRs: `gh pr create --draft -R <origin-owner/name>` using the workspace `github:` slug \u2014 never upstream). Never run git/gh from this orchestration cwd, and never merge the PR yourself.',
|
|
6518
6693
|
"Process guides:",
|
|
@@ -6826,13 +7001,13 @@ var init_api = __esm({
|
|
|
6826
7001
|
|
|
6827
7002
|
// src/slack/reply-target.ts
|
|
6828
7003
|
function storePath() {
|
|
6829
|
-
return (0,
|
|
7004
|
+
return (0, import_node_path21.join)(appDataDir(), "slack-reply-to.json");
|
|
6830
7005
|
}
|
|
6831
7006
|
function readStore() {
|
|
6832
7007
|
const path2 = storePath();
|
|
6833
|
-
if (!(0,
|
|
7008
|
+
if (!(0, import_node_fs19.existsSync)(path2)) return {};
|
|
6834
7009
|
try {
|
|
6835
|
-
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0,
|
|
7010
|
+
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs19.readFileSync)(path2, "utf8"));
|
|
6836
7011
|
return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
|
|
6837
7012
|
} catch {
|
|
6838
7013
|
return {};
|
|
@@ -6847,12 +7022,12 @@ function setSlackReplyTarget(target) {
|
|
|
6847
7022
|
function getSlackReplyTarget(threadId) {
|
|
6848
7023
|
return readStore()[threadId] ?? null;
|
|
6849
7024
|
}
|
|
6850
|
-
var
|
|
7025
|
+
var import_node_fs19, import_node_path21;
|
|
6851
7026
|
var init_reply_target = __esm({
|
|
6852
7027
|
"src/slack/reply-target.ts"() {
|
|
6853
7028
|
"use strict";
|
|
6854
|
-
|
|
6855
|
-
|
|
7029
|
+
import_node_fs19 = require("fs");
|
|
7030
|
+
import_node_path21 = require("path");
|
|
6856
7031
|
init_paths();
|
|
6857
7032
|
init_private_file();
|
|
6858
7033
|
init_secure_file();
|
|
@@ -6861,7 +7036,7 @@ var init_reply_target = __esm({
|
|
|
6861
7036
|
|
|
6862
7037
|
// src/slack/workspaces.ts
|
|
6863
7038
|
function storePath2() {
|
|
6864
|
-
return (0,
|
|
7039
|
+
return (0, import_node_path22.join)(appDataDir(), "slack-workspaces.json");
|
|
6865
7040
|
}
|
|
6866
7041
|
function readStore2() {
|
|
6867
7042
|
try {
|
|
@@ -6968,11 +7143,11 @@ function requireSlackWorkspace(teamId) {
|
|
|
6968
7143
|
}
|
|
6969
7144
|
return ws;
|
|
6970
7145
|
}
|
|
6971
|
-
var
|
|
7146
|
+
var import_node_path22;
|
|
6972
7147
|
var init_workspaces = __esm({
|
|
6973
7148
|
"src/slack/workspaces.ts"() {
|
|
6974
7149
|
"use strict";
|
|
6975
|
-
|
|
7150
|
+
import_node_path22 = require("path");
|
|
6976
7151
|
init_paths();
|
|
6977
7152
|
init_secure_file();
|
|
6978
7153
|
init_api();
|
|
@@ -6981,7 +7156,7 @@ var init_workspaces = __esm({
|
|
|
6981
7156
|
|
|
6982
7157
|
// src/slack/outbound-watch.ts
|
|
6983
7158
|
function storePath3() {
|
|
6984
|
-
return (0,
|
|
7159
|
+
return (0, import_node_path23.join)(appDataDir(), "slack-outbound-watch.json");
|
|
6985
7160
|
}
|
|
6986
7161
|
function watchId(teamId, channelId, ts) {
|
|
6987
7162
|
return `${teamId}:${channelId}:${ts}`;
|
|
@@ -6994,9 +7169,9 @@ function tsNewer(a, b) {
|
|
|
6994
7169
|
}
|
|
6995
7170
|
function readStore3() {
|
|
6996
7171
|
const path2 = storePath3();
|
|
6997
|
-
if (!(0,
|
|
7172
|
+
if (!(0, import_node_fs20.existsSync)(path2)) return [];
|
|
6998
7173
|
try {
|
|
6999
|
-
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0,
|
|
7174
|
+
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs20.readFileSync)(path2, "utf8"));
|
|
7000
7175
|
return Array.isArray(parsed?.watches) ? parsed.watches : [];
|
|
7001
7176
|
} catch {
|
|
7002
7177
|
return [];
|
|
@@ -7318,12 +7493,12 @@ async function pollSlackOutboundWatches(opts) {
|
|
|
7318
7493
|
}
|
|
7319
7494
|
if (changed) writeStore2(watches);
|
|
7320
7495
|
}
|
|
7321
|
-
var
|
|
7496
|
+
var import_node_fs20, import_node_path23, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache, continueOnReply;
|
|
7322
7497
|
var init_outbound_watch = __esm({
|
|
7323
7498
|
"src/slack/outbound-watch.ts"() {
|
|
7324
7499
|
"use strict";
|
|
7325
|
-
|
|
7326
|
-
|
|
7500
|
+
import_node_fs20 = require("fs");
|
|
7501
|
+
import_node_path23 = require("path");
|
|
7327
7502
|
init_paths();
|
|
7328
7503
|
init_private_file();
|
|
7329
7504
|
init_secure_file();
|
|
@@ -7607,32 +7782,32 @@ var init_error_detail = __esm({
|
|
|
7607
7782
|
function brightsyConfigPath() {
|
|
7608
7783
|
const override = process.env.BRIGHTSY_CONFIG?.trim();
|
|
7609
7784
|
if (override) return override;
|
|
7610
|
-
return (0,
|
|
7785
|
+
return (0, import_node_path24.join)((0, import_node_os7.homedir)(), ".brightsy", "config.json");
|
|
7611
7786
|
}
|
|
7612
7787
|
function loadBrightsyConfig() {
|
|
7613
7788
|
const path2 = brightsyConfigPath();
|
|
7614
|
-
if (!(0,
|
|
7789
|
+
if (!(0, import_node_fs21.existsSync)(path2)) {
|
|
7615
7790
|
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
7616
7791
|
}
|
|
7617
|
-
const raw = JSON.parse((0,
|
|
7792
|
+
const raw = JSON.parse((0, import_node_fs21.readFileSync)(path2, "utf8"));
|
|
7618
7793
|
if (!raw.access_token || !raw.account_id) {
|
|
7619
7794
|
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
7620
7795
|
}
|
|
7621
7796
|
return raw;
|
|
7622
7797
|
}
|
|
7623
7798
|
function saveBrightsyConfig(cfg) {
|
|
7624
|
-
(0,
|
|
7799
|
+
(0, import_node_fs21.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
7625
7800
|
`, {
|
|
7626
7801
|
mode: 384
|
|
7627
7802
|
});
|
|
7628
7803
|
}
|
|
7629
|
-
var
|
|
7804
|
+
var import_node_fs21, import_node_os7, import_node_path24;
|
|
7630
7805
|
var init_config = __esm({
|
|
7631
7806
|
"src/brightsy/config.ts"() {
|
|
7632
7807
|
"use strict";
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7808
|
+
import_node_fs21 = require("fs");
|
|
7809
|
+
import_node_os7 = require("os");
|
|
7810
|
+
import_node_path24 = require("path");
|
|
7636
7811
|
}
|
|
7637
7812
|
});
|
|
7638
7813
|
|
|
@@ -7850,22 +8025,22 @@ __export(connected_teams_exports, {
|
|
|
7850
8025
|
listConnectedBrightsyTeams: () => listConnectedBrightsyTeams
|
|
7851
8026
|
});
|
|
7852
8027
|
function storePath4() {
|
|
7853
|
-
return (0,
|
|
8028
|
+
return (0, import_node_path25.join)(appDataDir(), "brightsy-teams.json");
|
|
7854
8029
|
}
|
|
7855
8030
|
function readStore4() {
|
|
7856
8031
|
const path2 = storePath4();
|
|
7857
|
-
if (!(0,
|
|
8032
|
+
if (!(0, import_node_fs22.existsSync)(path2)) return [];
|
|
7858
8033
|
try {
|
|
7859
|
-
const parsed = JSON.parse((0,
|
|
8034
|
+
const parsed = JSON.parse((0, import_node_fs22.readFileSync)(path2, "utf8"));
|
|
7860
8035
|
return Array.isArray(parsed.teams) ? parsed.teams : [];
|
|
7861
8036
|
} catch {
|
|
7862
8037
|
return [];
|
|
7863
8038
|
}
|
|
7864
8039
|
}
|
|
7865
8040
|
function writeStore3(teams) {
|
|
7866
|
-
(0,
|
|
8041
|
+
(0, import_node_fs22.mkdirSync)(appDataDir(), { recursive: true });
|
|
7867
8042
|
const path2 = storePath4();
|
|
7868
|
-
(0,
|
|
8043
|
+
(0, import_node_fs22.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
|
|
7869
8044
|
`, {
|
|
7870
8045
|
mode: 384
|
|
7871
8046
|
});
|
|
@@ -8021,12 +8196,12 @@ function brightsyMcpServerName(slug) {
|
|
|
8021
8196
|
const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
|
|
8022
8197
|
return `brightsy_${cleaned || "team"}`;
|
|
8023
8198
|
}
|
|
8024
|
-
var
|
|
8199
|
+
var import_node_fs22, import_node_path25;
|
|
8025
8200
|
var init_connected_teams = __esm({
|
|
8026
8201
|
"src/brightsy/connected-teams.ts"() {
|
|
8027
8202
|
"use strict";
|
|
8028
|
-
|
|
8029
|
-
|
|
8203
|
+
import_node_fs22 = require("fs");
|
|
8204
|
+
import_node_path25 = require("path");
|
|
8030
8205
|
init_paths();
|
|
8031
8206
|
init_accounts();
|
|
8032
8207
|
init_config();
|
|
@@ -8445,11 +8620,11 @@ async function syncCliForTarget(accountId) {
|
|
|
8445
8620
|
}
|
|
8446
8621
|
applyConnectedTeamToCli(team);
|
|
8447
8622
|
}
|
|
8448
|
-
var
|
|
8623
|
+
var import_node_fs23, brightsyAdapter;
|
|
8449
8624
|
var init_brightsy = __esm({
|
|
8450
8625
|
"src/agents/brightsy.ts"() {
|
|
8451
8626
|
"use strict";
|
|
8452
|
-
|
|
8627
|
+
import_node_fs23 = require("fs");
|
|
8453
8628
|
init_run();
|
|
8454
8629
|
init_connected_teams();
|
|
8455
8630
|
init_config();
|
|
@@ -8464,7 +8639,7 @@ var init_brightsy = __esm({
|
|
|
8464
8639
|
async detect() {
|
|
8465
8640
|
const brightsy = resolveAgentExecutable("brightsy");
|
|
8466
8641
|
if (brightsy !== "brightsy") {
|
|
8467
|
-
if (!(0,
|
|
8642
|
+
if (!(0, import_node_fs23.existsSync)(brightsy)) {
|
|
8468
8643
|
return {
|
|
8469
8644
|
agent: "brightsy",
|
|
8470
8645
|
installed: false,
|
|
@@ -8731,6 +8906,13 @@ function isSubagentToolName(name) {
|
|
|
8731
8906
|
if (/^(task|agent|spawn_agent)$/i.test(n)) return true;
|
|
8732
8907
|
return /connectedAgentRequest/i.test(n);
|
|
8733
8908
|
}
|
|
8909
|
+
function isInternalAgentStatusText(text5) {
|
|
8910
|
+
const t = text5.trim();
|
|
8911
|
+
if (!t) return false;
|
|
8912
|
+
if (/waiting for gate to pass/i.test(t)) return true;
|
|
8913
|
+
if (/^agent is running\b/i.test(t) && t.length < 160) return true;
|
|
8914
|
+
return false;
|
|
8915
|
+
}
|
|
8734
8916
|
function isPollWrapperToolName(name) {
|
|
8735
8917
|
const n = (name ?? "").replace(/[_-]/g, "");
|
|
8736
8918
|
return /^(taskoutput|taskstop|sleep)$/i.test(n);
|
|
@@ -8738,7 +8920,10 @@ function isPollWrapperToolName(name) {
|
|
|
8738
8920
|
function lastTextPart(parts, type) {
|
|
8739
8921
|
for (let i = parts.length - 1; i >= 0; i--) {
|
|
8740
8922
|
const p = parts[i];
|
|
8741
|
-
if (p.type
|
|
8923
|
+
if (p.type !== type) continue;
|
|
8924
|
+
const text5 = p.text.trim();
|
|
8925
|
+
if (!text5 || isInternalAgentStatusText(text5)) continue;
|
|
8926
|
+
return text5;
|
|
8742
8927
|
}
|
|
8743
8928
|
return "";
|
|
8744
8929
|
}
|
|
@@ -9154,43 +9339,43 @@ function electronResourcesPath() {
|
|
|
9154
9339
|
function packagedCursorRuntimeDir() {
|
|
9155
9340
|
const resources = electronResourcesPath();
|
|
9156
9341
|
if (!resources) return null;
|
|
9157
|
-
const dir = (0,
|
|
9158
|
-
if (!(0,
|
|
9342
|
+
const dir = (0, import_node_path26.join)(resources, "cursor-runtime");
|
|
9343
|
+
if (!(0, import_node_fs24.existsSync)((0, import_node_path26.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
|
|
9159
9344
|
return dir;
|
|
9160
9345
|
}
|
|
9161
9346
|
function packagedCursorRunnerPath() {
|
|
9162
9347
|
const dir = packagedCursorRuntimeDir();
|
|
9163
|
-
return dir ? (0,
|
|
9348
|
+
return dir ? (0, import_node_path26.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
|
|
9164
9349
|
}
|
|
9165
9350
|
function packagedMcpDir() {
|
|
9166
9351
|
const resources = electronResourcesPath();
|
|
9167
9352
|
if (!resources) return null;
|
|
9168
|
-
const dir = (0,
|
|
9169
|
-
if (!(0,
|
|
9353
|
+
const dir = (0, import_node_path26.join)(resources, "sideboard-mcp");
|
|
9354
|
+
if (!(0, import_node_fs24.existsSync)((0, import_node_path26.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
|
|
9170
9355
|
return dir;
|
|
9171
9356
|
}
|
|
9172
9357
|
function packagedMcpStdioPath() {
|
|
9173
9358
|
const dir = packagedMcpDir();
|
|
9174
|
-
return dir ? (0,
|
|
9359
|
+
return dir ? (0, import_node_path26.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
|
|
9175
9360
|
}
|
|
9176
9361
|
function packagedBundledNodePath() {
|
|
9177
9362
|
const resources = electronResourcesPath();
|
|
9178
9363
|
if (!resources) return null;
|
|
9179
|
-
const bin = (0,
|
|
9180
|
-
if (!(0,
|
|
9364
|
+
const bin = (0, import_node_path26.join)(resources, "node", "bin", "node");
|
|
9365
|
+
if (!(0, import_node_fs24.existsSync)(bin)) return null;
|
|
9181
9366
|
return bin;
|
|
9182
9367
|
}
|
|
9183
9368
|
function packagedCursorRipgrepCandidate(platformPkg, binName) {
|
|
9184
9369
|
const dir = packagedCursorRuntimeDir();
|
|
9185
9370
|
if (!dir) return null;
|
|
9186
|
-
return (0,
|
|
9371
|
+
return (0, import_node_path26.join)(dir, "node_modules", platformPkg, "bin", binName);
|
|
9187
9372
|
}
|
|
9188
|
-
var
|
|
9373
|
+
var import_node_fs24, import_node_path26;
|
|
9189
9374
|
var init_packaged_runtime = __esm({
|
|
9190
9375
|
"src/agents/packaged-runtime.ts"() {
|
|
9191
9376
|
"use strict";
|
|
9192
|
-
|
|
9193
|
-
|
|
9377
|
+
import_node_fs24 = require("fs");
|
|
9378
|
+
import_node_path26 = require("path");
|
|
9194
9379
|
}
|
|
9195
9380
|
});
|
|
9196
9381
|
|
|
@@ -9224,7 +9409,7 @@ function unpackedAsarPath(filePath) {
|
|
|
9224
9409
|
if (!isAsarPath(filePath)) return null;
|
|
9225
9410
|
const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
|
|
9226
9411
|
if (unpacked === filePath) return null;
|
|
9227
|
-
return (0,
|
|
9412
|
+
return (0, import_node_fs25.existsSync)(unpacked) ? unpacked : null;
|
|
9228
9413
|
}
|
|
9229
9414
|
function nodeReadableScriptPath(scriptPath) {
|
|
9230
9415
|
return unpackedAsarPath(scriptPath) ?? scriptPath;
|
|
@@ -9264,37 +9449,37 @@ function pickPreferredNode(candidates) {
|
|
|
9264
9449
|
return best;
|
|
9265
9450
|
}
|
|
9266
9451
|
function versionDirNodeBins(root, toBin) {
|
|
9267
|
-
if (!(0,
|
|
9452
|
+
if (!(0, import_node_fs25.existsSync)(root)) return [];
|
|
9268
9453
|
try {
|
|
9269
|
-
return (0,
|
|
9454
|
+
return (0, import_node_fs25.readdirSync)(root).map(toBin);
|
|
9270
9455
|
} catch {
|
|
9271
9456
|
return [];
|
|
9272
9457
|
}
|
|
9273
9458
|
}
|
|
9274
|
-
function defaultNodeBinCandidates(home = (0,
|
|
9459
|
+
function defaultNodeBinCandidates(home = (0, import_node_os8.homedir)()) {
|
|
9275
9460
|
const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
|
|
9276
|
-
(prefix) => PREFERRED_LTS_MAJORS.map((major) => (0,
|
|
9461
|
+
(prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path27.join)(prefix, "opt", `node@${major}`, "bin", "node"))
|
|
9277
9462
|
);
|
|
9278
9463
|
return [
|
|
9279
9464
|
...kegs,
|
|
9280
9465
|
"/opt/homebrew/bin/node",
|
|
9281
9466
|
"/usr/local/bin/node",
|
|
9282
|
-
(0,
|
|
9283
|
-
(0,
|
|
9284
|
-
(0,
|
|
9285
|
-
(0,
|
|
9286
|
-
(0,
|
|
9467
|
+
(0, import_node_path27.join)(home, ".local/share/fnm/aliases/default/bin/node"),
|
|
9468
|
+
(0, import_node_path27.join)(home, ".nvm/current/bin/node"),
|
|
9469
|
+
(0, import_node_path27.join)(home, ".volta/bin/node"),
|
|
9470
|
+
(0, import_node_path27.join)(home, ".asdf/shims/node"),
|
|
9471
|
+
(0, import_node_path27.join)(home, ".local/share/mise/shims/node"),
|
|
9287
9472
|
...versionDirNodeBins(
|
|
9288
|
-
(0,
|
|
9289
|
-
(name) => (0,
|
|
9473
|
+
(0, import_node_path27.join)(home, ".nvm", "versions", "node"),
|
|
9474
|
+
(name) => (0, import_node_path27.join)(home, ".nvm", "versions", "node", name, "bin", "node")
|
|
9290
9475
|
),
|
|
9291
9476
|
...versionDirNodeBins(
|
|
9292
|
-
(0,
|
|
9293
|
-
(name) => (0,
|
|
9477
|
+
(0, import_node_path27.join)(home, ".local/share/fnm", "node-versions"),
|
|
9478
|
+
(name) => (0, import_node_path27.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
|
|
9294
9479
|
),
|
|
9295
9480
|
...versionDirNodeBins(
|
|
9296
|
-
(0,
|
|
9297
|
-
(name) => (0,
|
|
9481
|
+
(0, import_node_path27.join)(home, ".volta", "tools", "image", "node"),
|
|
9482
|
+
(name) => (0, import_node_path27.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
|
|
9298
9483
|
)
|
|
9299
9484
|
];
|
|
9300
9485
|
}
|
|
@@ -9303,10 +9488,10 @@ function uniqueExistingNodeBins(paths) {
|
|
|
9303
9488
|
const out = [];
|
|
9304
9489
|
for (const raw of paths) {
|
|
9305
9490
|
const p = raw.trim();
|
|
9306
|
-
if (!p || !(0,
|
|
9491
|
+
if (!p || !(0, import_node_fs25.existsSync)(p) || isElectronLikeCommand(p)) continue;
|
|
9307
9492
|
let key = p;
|
|
9308
9493
|
try {
|
|
9309
|
-
key = (0,
|
|
9494
|
+
key = (0, import_node_fs25.realpathSync)(p);
|
|
9310
9495
|
} catch {
|
|
9311
9496
|
continue;
|
|
9312
9497
|
}
|
|
@@ -9386,13 +9571,13 @@ async function resolveNodeLaunch(scriptPath) {
|
|
|
9386
9571
|
env: { ELECTRON_RUN_AS_NODE: "1" }
|
|
9387
9572
|
};
|
|
9388
9573
|
}
|
|
9389
|
-
var
|
|
9574
|
+
var import_node_fs25, import_node_os8, import_node_path27, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
|
|
9390
9575
|
var init_node_launch = __esm({
|
|
9391
9576
|
"src/agents/node-launch.ts"() {
|
|
9392
9577
|
"use strict";
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9578
|
+
import_node_fs25 = require("fs");
|
|
9579
|
+
import_node_os8 = require("os");
|
|
9580
|
+
import_node_path27 = require("path");
|
|
9396
9581
|
init_nested_electron_env();
|
|
9397
9582
|
init_run();
|
|
9398
9583
|
init_packaged_runtime();
|
|
@@ -9486,37 +9671,37 @@ function corePackageDir() {
|
|
|
9486
9671
|
try {
|
|
9487
9672
|
const url = import_meta.url;
|
|
9488
9673
|
if (typeof url === "string" && url.length > 0) {
|
|
9489
|
-
return (0,
|
|
9674
|
+
return (0, import_node_path28.dirname)((0, import_node_url.fileURLToPath)(url));
|
|
9490
9675
|
}
|
|
9491
9676
|
} catch {
|
|
9492
9677
|
}
|
|
9493
9678
|
try {
|
|
9494
|
-
const req = (0, import_node_module.createRequire)((0,
|
|
9495
|
-
return (0,
|
|
9679
|
+
const req = (0, import_node_module.createRequire)((0, import_node_path28.join)(process.cwd(), "package.json"));
|
|
9680
|
+
return (0, import_node_path28.dirname)(req.resolve("@sideboard-ai/core"));
|
|
9496
9681
|
} catch {
|
|
9497
9682
|
return process.cwd();
|
|
9498
9683
|
}
|
|
9499
9684
|
}
|
|
9500
9685
|
function findSideboardMcpJsEntry() {
|
|
9501
9686
|
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
9502
|
-
if (override && (0,
|
|
9687
|
+
if (override && (0, import_node_fs26.existsSync)(override)) return override;
|
|
9503
9688
|
const packaged = packagedMcpStdioPath();
|
|
9504
9689
|
if (packaged) return packaged;
|
|
9505
9690
|
let dir = corePackageDir();
|
|
9506
9691
|
for (let i = 0; i < 10; i++) {
|
|
9507
9692
|
const candidates = [
|
|
9508
|
-
(0,
|
|
9509
|
-
(0,
|
|
9510
|
-
(0,
|
|
9511
|
-
(0,
|
|
9512
|
-
(0,
|
|
9513
|
-
(0,
|
|
9514
|
-
(0,
|
|
9693
|
+
(0, import_node_path28.join)(dir, "mcp/run-stdio.js"),
|
|
9694
|
+
(0, import_node_path28.join)(dir, "mcp/run-stdio.cjs"),
|
|
9695
|
+
(0, import_node_path28.join)(dir, "dist/mcp/run-stdio.js"),
|
|
9696
|
+
(0, import_node_path28.join)(dir, "dist/mcp/run-stdio.cjs"),
|
|
9697
|
+
(0, import_node_path28.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
|
|
9698
|
+
(0, import_node_path28.join)(dir, "packages/cli/dist/index.js"),
|
|
9699
|
+
(0, import_node_path28.join)(dir, "cli/dist/index.js")
|
|
9515
9700
|
];
|
|
9516
9701
|
for (const p of candidates) {
|
|
9517
|
-
if ((0,
|
|
9702
|
+
if ((0, import_node_fs26.existsSync)(p) && !isAsarPath(p)) return p;
|
|
9518
9703
|
}
|
|
9519
|
-
const parent = (0,
|
|
9704
|
+
const parent = (0, import_node_path28.dirname)(dir);
|
|
9520
9705
|
if (parent === dir) break;
|
|
9521
9706
|
dir = parent;
|
|
9522
9707
|
}
|
|
@@ -9658,22 +9843,22 @@ function writeMcpServersConfig(servers) {
|
|
|
9658
9843
|
...env ? { env } : {}
|
|
9659
9844
|
};
|
|
9660
9845
|
}
|
|
9661
|
-
const dir = (0,
|
|
9662
|
-
const cfgPath = (0,
|
|
9663
|
-
(0,
|
|
9846
|
+
const dir = (0, import_node_fs26.mkdtempSync)((0, import_node_path28.join)((0, import_node_os9.tmpdir)(), "sideboard-mcp-"));
|
|
9847
|
+
const cfgPath = (0, import_node_path28.join)(dir, "mcp.json");
|
|
9848
|
+
(0, import_node_fs26.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
|
|
9664
9849
|
return cfgPath;
|
|
9665
9850
|
}
|
|
9666
9851
|
async function writeInjectedMcpConfig(opts) {
|
|
9667
9852
|
return writeMcpServersConfig(await buildInjectedMcpServers(opts));
|
|
9668
9853
|
}
|
|
9669
|
-
var
|
|
9854
|
+
var import_node_fs26, import_node_module, import_node_os9, import_node_path28, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
|
|
9670
9855
|
var init_injected_mcp = __esm({
|
|
9671
9856
|
"src/agents/injected-mcp.ts"() {
|
|
9672
9857
|
"use strict";
|
|
9673
|
-
|
|
9858
|
+
import_node_fs26 = require("fs");
|
|
9674
9859
|
import_node_module = require("module");
|
|
9675
|
-
|
|
9676
|
-
|
|
9860
|
+
import_node_os9 = require("os");
|
|
9861
|
+
import_node_path28 = require("path");
|
|
9677
9862
|
import_node_url = require("url");
|
|
9678
9863
|
init_run();
|
|
9679
9864
|
init_config();
|
|
@@ -10016,11 +10201,11 @@ function parseIssuesJson(raw) {
|
|
|
10016
10201
|
}
|
|
10017
10202
|
return [];
|
|
10018
10203
|
}
|
|
10019
|
-
var
|
|
10204
|
+
var import_node_fs27, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, mcpListCache, claudeAdapter;
|
|
10020
10205
|
var init_claude = __esm({
|
|
10021
10206
|
"src/agents/claude.ts"() {
|
|
10022
10207
|
"use strict";
|
|
10023
|
-
|
|
10208
|
+
import_node_fs27 = require("fs");
|
|
10024
10209
|
init_run();
|
|
10025
10210
|
init_app_settings();
|
|
10026
10211
|
init_claude_mcp();
|
|
@@ -10060,7 +10245,7 @@ var init_claude = __esm({
|
|
|
10060
10245
|
async detect() {
|
|
10061
10246
|
const claude = resolveClaudeExecutable();
|
|
10062
10247
|
if (claude !== "claude") {
|
|
10063
|
-
if (!(0,
|
|
10248
|
+
if (!(0, import_node_fs27.existsSync)(claude)) {
|
|
10064
10249
|
return {
|
|
10065
10250
|
agent: "claude",
|
|
10066
10251
|
installed: false,
|
|
@@ -10315,7 +10500,7 @@ async function listCodexModels() {
|
|
|
10315
10500
|
if (codex === "codex") {
|
|
10316
10501
|
const which = await run("which", ["codex"], { reject: false });
|
|
10317
10502
|
if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
|
|
10318
|
-
} else if (!(0,
|
|
10503
|
+
} else if (!(0, import_node_fs28.existsSync)(codex)) {
|
|
10319
10504
|
return FALLBACK_CODEX_MODELS;
|
|
10320
10505
|
}
|
|
10321
10506
|
const listed = await run(codex, ["debug", "models"], { reject: false });
|
|
@@ -10350,12 +10535,12 @@ function usageFromCodex(usage) {
|
|
|
10350
10535
|
}
|
|
10351
10536
|
function codexConfigHasNetworkAccess() {
|
|
10352
10537
|
const candidates = [
|
|
10353
|
-
(0,
|
|
10354
|
-
(0,
|
|
10538
|
+
(0, import_node_path29.join)((0, import_node_os10.homedir)(), ".codex", "config.toml"),
|
|
10539
|
+
(0, import_node_path29.join)((0, import_node_os10.homedir)(), ".config", "codex", "config.toml")
|
|
10355
10540
|
];
|
|
10356
10541
|
for (const path2 of candidates) {
|
|
10357
|
-
if (!(0,
|
|
10358
|
-
const text5 = (0,
|
|
10542
|
+
if (!(0, import_node_fs28.existsSync)(path2)) continue;
|
|
10543
|
+
const text5 = (0, import_node_fs28.readFileSync)(path2, "utf8");
|
|
10359
10544
|
if (/network_access\s*=\s*true/.test(text5)) return true;
|
|
10360
10545
|
}
|
|
10361
10546
|
return false;
|
|
@@ -10387,21 +10572,21 @@ function asRecord2(value) {
|
|
|
10387
10572
|
return void 0;
|
|
10388
10573
|
}
|
|
10389
10574
|
function codexLooksAuthenticated() {
|
|
10390
|
-
const authPath = (0,
|
|
10391
|
-
if (!(0,
|
|
10575
|
+
const authPath = (0, import_node_path29.join)((0, import_node_os10.homedir)(), ".codex", "auth.json");
|
|
10576
|
+
if (!(0, import_node_fs28.existsSync)(authPath)) return false;
|
|
10392
10577
|
try {
|
|
10393
|
-
return (0,
|
|
10578
|
+
return (0, import_node_fs28.statSync)(authPath).size > 2;
|
|
10394
10579
|
} catch {
|
|
10395
10580
|
return false;
|
|
10396
10581
|
}
|
|
10397
10582
|
}
|
|
10398
|
-
var
|
|
10583
|
+
var import_node_fs28, import_node_os10, import_node_path29, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
|
|
10399
10584
|
var init_codex = __esm({
|
|
10400
10585
|
"src/agents/codex.ts"() {
|
|
10401
10586
|
"use strict";
|
|
10402
|
-
|
|
10403
|
-
|
|
10404
|
-
|
|
10587
|
+
import_node_fs28 = require("fs");
|
|
10588
|
+
import_node_os10 = require("os");
|
|
10589
|
+
import_node_path29 = require("path");
|
|
10405
10590
|
init_run();
|
|
10406
10591
|
init_app_settings();
|
|
10407
10592
|
init_global_workspace();
|
|
@@ -10426,7 +10611,7 @@ var init_codex = __esm({
|
|
|
10426
10611
|
async detect() {
|
|
10427
10612
|
const codex = resolveAgentExecutable("codex");
|
|
10428
10613
|
if (codex !== "codex") {
|
|
10429
|
-
if (!(0,
|
|
10614
|
+
if (!(0, import_node_fs28.existsSync)(codex)) {
|
|
10430
10615
|
return {
|
|
10431
10616
|
agent: "codex",
|
|
10432
10617
|
installed: false,
|
|
@@ -10913,21 +11098,21 @@ function platformRipgrepPackage() {
|
|
|
10913
11098
|
}
|
|
10914
11099
|
function usableRipgrepPath(candidate) {
|
|
10915
11100
|
const raw = candidate?.trim();
|
|
10916
|
-
if (!raw || !(0,
|
|
11101
|
+
if (!raw || !(0, import_node_path30.isAbsolute)(raw)) return null;
|
|
10917
11102
|
const readable = nodeReadableScriptPath(raw);
|
|
10918
|
-
if (!(0,
|
|
11103
|
+
if (!(0, import_node_fs29.existsSync)(readable) || isAsarPath(readable)) return null;
|
|
10919
11104
|
return readable;
|
|
10920
11105
|
}
|
|
10921
11106
|
function walkForBundledRipgrep(startFile) {
|
|
10922
11107
|
if (!startFile) return null;
|
|
10923
11108
|
const pkg = platformRipgrepPackage();
|
|
10924
11109
|
const name = rgBinaryName();
|
|
10925
|
-
let dir = (0,
|
|
10926
|
-
const root = (0,
|
|
11110
|
+
let dir = (0, import_node_path30.dirname)((0, import_node_path30.resolve)(startFile));
|
|
11111
|
+
const root = (0, import_node_path30.parse)(dir).root;
|
|
10927
11112
|
while (dir !== root) {
|
|
10928
|
-
const hit = usableRipgrepPath((0,
|
|
11113
|
+
const hit = usableRipgrepPath((0, import_node_path30.join)(dir, "node_modules", pkg, "bin", name));
|
|
10929
11114
|
if (hit) return hit;
|
|
10930
|
-
const next = (0,
|
|
11115
|
+
const next = (0, import_node_path30.dirname)(dir);
|
|
10931
11116
|
if (next === dir) break;
|
|
10932
11117
|
dir = next;
|
|
10933
11118
|
}
|
|
@@ -10937,7 +11122,7 @@ function requireResolveBundledRipgrep(fromFile) {
|
|
|
10937
11122
|
try {
|
|
10938
11123
|
const req = (0, import_node_module2.createRequire)(fromFile);
|
|
10939
11124
|
const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
|
|
10940
|
-
return usableRipgrepPath((0,
|
|
11125
|
+
return usableRipgrepPath((0, import_node_path30.join)((0, import_node_path30.dirname)(pkgJson), "bin", rgBinaryName()));
|
|
10941
11126
|
} catch {
|
|
10942
11127
|
return null;
|
|
10943
11128
|
}
|
|
@@ -10959,13 +11144,13 @@ function cursorRipgrepEnv(opts) {
|
|
|
10959
11144
|
const path2 = resolveCursorRipgrepPath(opts);
|
|
10960
11145
|
return path2 ? { [RIPGREP_ENV]: path2 } : {};
|
|
10961
11146
|
}
|
|
10962
|
-
var
|
|
11147
|
+
var import_node_fs29, import_node_module2, import_node_path30, RIPGREP_ENV;
|
|
10963
11148
|
var init_cursor_ripgrep = __esm({
|
|
10964
11149
|
"src/agents/cursor-ripgrep.ts"() {
|
|
10965
11150
|
"use strict";
|
|
10966
|
-
|
|
11151
|
+
import_node_fs29 = require("fs");
|
|
10967
11152
|
import_node_module2 = require("module");
|
|
10968
|
-
|
|
11153
|
+
import_node_path30 = require("path");
|
|
10969
11154
|
init_node_launch();
|
|
10970
11155
|
init_packaged_runtime();
|
|
10971
11156
|
RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
|
|
@@ -11011,11 +11196,11 @@ function entryDir() {
|
|
|
11011
11196
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
11012
11197
|
if (cjsDir) return cjsDir;
|
|
11013
11198
|
try {
|
|
11014
|
-
return (0,
|
|
11199
|
+
return (0, import_node_path31.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
|
|
11015
11200
|
} catch {
|
|
11016
11201
|
try {
|
|
11017
11202
|
const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
|
|
11018
|
-
return (0,
|
|
11203
|
+
return (0, import_node_path31.dirname)(req.resolve("@sideboard-ai/core"));
|
|
11019
11204
|
} catch {
|
|
11020
11205
|
return process.cwd();
|
|
11021
11206
|
}
|
|
@@ -11026,27 +11211,27 @@ function cursorRunnerPath() {
|
|
|
11026
11211
|
if (packaged) return packaged;
|
|
11027
11212
|
const root = entryDir();
|
|
11028
11213
|
const candidates = [
|
|
11029
|
-
(0,
|
|
11030
|
-
(0,
|
|
11214
|
+
(0, import_node_path31.join)(root, "agents", "cursor-runner.js"),
|
|
11215
|
+
(0, import_node_path31.join)(root, "agents", "cursor-runner.cjs"),
|
|
11031
11216
|
// If somehow resolved from package root instead of dist/
|
|
11032
|
-
(0,
|
|
11033
|
-
(0,
|
|
11217
|
+
(0, import_node_path31.join)(root, "dist", "agents", "cursor-runner.js"),
|
|
11218
|
+
(0, import_node_path31.join)(root, "dist", "agents", "cursor-runner.cjs"),
|
|
11034
11219
|
// Source tree (dev): packages/core/src/agents/cursor-runner.ts
|
|
11035
|
-
(0,
|
|
11036
|
-
(0,
|
|
11220
|
+
(0, import_node_path31.join)(root, "cursor-runner.ts"),
|
|
11221
|
+
(0, import_node_path31.join)(root, "src", "agents", "cursor-runner.ts")
|
|
11037
11222
|
];
|
|
11038
11223
|
for (const candidate of candidates) {
|
|
11039
|
-
if ((0,
|
|
11224
|
+
if ((0, import_node_fs30.existsSync)(candidate)) return candidate;
|
|
11040
11225
|
}
|
|
11041
11226
|
return candidates[0];
|
|
11042
11227
|
}
|
|
11043
|
-
var
|
|
11228
|
+
var import_node_fs30, import_node_module3, import_node_path31, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
|
|
11044
11229
|
var init_cursor = __esm({
|
|
11045
11230
|
"src/agents/cursor.ts"() {
|
|
11046
11231
|
"use strict";
|
|
11047
|
-
|
|
11232
|
+
import_node_fs30 = require("fs");
|
|
11048
11233
|
import_node_module3 = require("module");
|
|
11049
|
-
|
|
11234
|
+
import_node_path31 = require("path");
|
|
11050
11235
|
import_node_url2 = require("url");
|
|
11051
11236
|
import_sdk = require("@cursor/sdk");
|
|
11052
11237
|
init_run();
|
|
@@ -11197,7 +11382,7 @@ async function listOpencodeModels() {
|
|
|
11197
11382
|
if (opencode === "opencode") {
|
|
11198
11383
|
const which = await run("which", ["opencode"], { reject: false });
|
|
11199
11384
|
if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
|
|
11200
|
-
} else if (!(0,
|
|
11385
|
+
} else if (!(0, import_node_fs31.existsSync)(opencode)) {
|
|
11201
11386
|
return FALLBACK_OPENCODE_MODELS;
|
|
11202
11387
|
}
|
|
11203
11388
|
const listed = await run(opencode, ["models"], { reject: false });
|
|
@@ -11227,11 +11412,11 @@ function usageFromOpencode(tokens) {
|
|
|
11227
11412
|
cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
|
|
11228
11413
|
};
|
|
11229
11414
|
}
|
|
11230
|
-
var
|
|
11415
|
+
var import_node_fs31, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
|
|
11231
11416
|
var init_opencode = __esm({
|
|
11232
11417
|
"src/agents/opencode.ts"() {
|
|
11233
11418
|
"use strict";
|
|
11234
|
-
|
|
11419
|
+
import_node_fs31 = require("fs");
|
|
11235
11420
|
init_run();
|
|
11236
11421
|
init_app_settings();
|
|
11237
11422
|
init_global_workspace();
|
|
@@ -11258,7 +11443,7 @@ var init_opencode = __esm({
|
|
|
11258
11443
|
async detect() {
|
|
11259
11444
|
const opencode = resolveAgentExecutable("opencode");
|
|
11260
11445
|
if (opencode !== "opencode") {
|
|
11261
|
-
if (!(0,
|
|
11446
|
+
if (!(0, import_node_fs31.existsSync)(opencode)) {
|
|
11262
11447
|
return {
|
|
11263
11448
|
agent: "opencode",
|
|
11264
11449
|
installed: false,
|
|
@@ -12884,7 +13069,7 @@ function forkMessageSlice(from, throughIndex) {
|
|
|
12884
13069
|
function buildForkTranscriptAttachment(baseTitle, messages) {
|
|
12885
13070
|
const title = baseTitle || "Chat";
|
|
12886
13071
|
return {
|
|
12887
|
-
id: (0,
|
|
13072
|
+
id: (0, import_node_crypto7.randomUUID)(),
|
|
12888
13073
|
name: `Transcript of ${title}.md`,
|
|
12889
13074
|
kind: "transcript",
|
|
12890
13075
|
content: formatTranscriptMarkdown(title, messages)
|
|
@@ -12941,11 +13126,11 @@ function forkChatTab(input) {
|
|
|
12941
13126
|
}
|
|
12942
13127
|
return tab;
|
|
12943
13128
|
}
|
|
12944
|
-
var
|
|
13129
|
+
var import_node_crypto7;
|
|
12945
13130
|
var init_chat_tabs = __esm({
|
|
12946
13131
|
"src/threads/chat-tabs.ts"() {
|
|
12947
13132
|
"use strict";
|
|
12948
|
-
|
|
13133
|
+
import_node_crypto7 = require("crypto");
|
|
12949
13134
|
init_context_compact();
|
|
12950
13135
|
init_teams();
|
|
12951
13136
|
init_worktree_labels();
|
|
@@ -13115,21 +13300,21 @@ function shouldRefreshReviewRequestTemplate(content) {
|
|
|
13115
13300
|
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
13116
13301
|
}
|
|
13117
13302
|
function readTextIfPresent(abs) {
|
|
13118
|
-
if (!(0,
|
|
13303
|
+
if (!(0, import_node_fs32.existsSync)(abs)) return null;
|
|
13119
13304
|
try {
|
|
13120
|
-
const content = (0,
|
|
13305
|
+
const content = (0, import_node_fs32.readFileSync)(abs, "utf8");
|
|
13121
13306
|
return content.trim() ? content : null;
|
|
13122
13307
|
} catch {
|
|
13123
13308
|
return null;
|
|
13124
13309
|
}
|
|
13125
13310
|
}
|
|
13126
13311
|
function readLocalGuidelines(worktreePath) {
|
|
13127
|
-
const localAbs = (0,
|
|
13312
|
+
const localAbs = (0, import_node_path32.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
13128
13313
|
const localContent = readTextIfPresent(localAbs);
|
|
13129
13314
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
13130
13315
|
return { path: REVIEW_REQUEST_PATH, content: localContent };
|
|
13131
13316
|
}
|
|
13132
|
-
const legacyAbs = (0,
|
|
13317
|
+
const legacyAbs = (0, import_node_path32.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
|
|
13133
13318
|
const legacyContent = readTextIfPresent(legacyAbs);
|
|
13134
13319
|
if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
|
|
13135
13320
|
return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
|
|
@@ -13145,20 +13330,20 @@ function skillGuidelines(content, source) {
|
|
|
13145
13330
|
};
|
|
13146
13331
|
}
|
|
13147
13332
|
function ensureReviewSkillFile(worktreePath) {
|
|
13148
|
-
const abs = (0,
|
|
13333
|
+
const abs = (0, import_node_path32.join)(worktreePath, REVIEW_SKILL_PATH);
|
|
13149
13334
|
const existing = readTextIfPresent(abs);
|
|
13150
13335
|
if (existing) {
|
|
13151
13336
|
return { path: REVIEW_SKILL_PATH, content: existing, wrote: false };
|
|
13152
13337
|
}
|
|
13153
|
-
const fromRepo = readTextIfPresent((0,
|
|
13338
|
+
const fromRepo = readTextIfPresent((0, import_node_path32.join)(worktreePath, REPO_REVIEW_PATH));
|
|
13154
13339
|
const fromLocal = readLocalGuidelines(worktreePath)?.content ?? null;
|
|
13155
13340
|
const content = wrapReviewSkillMarkdown(fromRepo ?? fromLocal ?? REVIEW_REQUEST_TEMPLATE);
|
|
13156
|
-
(0,
|
|
13157
|
-
(0,
|
|
13341
|
+
(0, import_node_fs32.mkdirSync)((0, import_node_path32.dirname)(abs), { recursive: true });
|
|
13342
|
+
(0, import_node_fs32.writeFileSync)(abs, content, "utf8");
|
|
13158
13343
|
return { path: REVIEW_SKILL_PATH, content, wrote: true };
|
|
13159
13344
|
}
|
|
13160
13345
|
function resolveReviewGuidelines(worktreePath) {
|
|
13161
|
-
const skillContent = readTextIfPresent((0,
|
|
13346
|
+
const skillContent = readTextIfPresent((0, import_node_path32.join)(worktreePath, REVIEW_SKILL_PATH));
|
|
13162
13347
|
if (skillContent) return skillGuidelines(skillContent, "skill");
|
|
13163
13348
|
const local = readLocalGuidelines(worktreePath);
|
|
13164
13349
|
if (local) {
|
|
@@ -13180,7 +13365,7 @@ function buildReviewRequestAttachment(content, opts) {
|
|
|
13180
13365
|
const path2 = opts?.path ?? REVIEW_SKILL_PATH;
|
|
13181
13366
|
const name = opts?.name ?? (path2 === REVIEW_SKILL_PATH ? REVIEW_SKILL_NAME : path2 === REPO_REVIEW_PATH ? REPO_REVIEW_NAME : REVIEW_REQUEST_NAME);
|
|
13182
13367
|
return {
|
|
13183
|
-
id: (0,
|
|
13368
|
+
id: (0, import_node_crypto8.randomUUID)(),
|
|
13184
13369
|
name,
|
|
13185
13370
|
kind: "file",
|
|
13186
13371
|
path: path2,
|
|
@@ -13188,7 +13373,7 @@ function buildReviewRequestAttachment(content, opts) {
|
|
|
13188
13373
|
};
|
|
13189
13374
|
}
|
|
13190
13375
|
function readExistingReviewRequestFile(worktreePath) {
|
|
13191
|
-
return readTextIfPresent((0,
|
|
13376
|
+
return readTextIfPresent((0, import_node_path32.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path32.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path32.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path32.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
|
|
13192
13377
|
}
|
|
13193
13378
|
async function requestReview(threadRef, send2) {
|
|
13194
13379
|
const from = findThreadByRef(threadRef);
|
|
@@ -13215,13 +13400,13 @@ async function requestReview(threadRef, send2) {
|
|
|
13215
13400
|
const started = await send2(tab.id, REVIEW_REQUEST_PREFILL);
|
|
13216
13401
|
return { tab: started, from };
|
|
13217
13402
|
}
|
|
13218
|
-
var
|
|
13403
|
+
var import_node_crypto8, import_node_fs32, import_node_path32, REPO_REVIEW_PATH, REPO_REVIEW_NAME, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
|
|
13219
13404
|
var init_request_review = __esm({
|
|
13220
13405
|
"src/review/request-review.ts"() {
|
|
13221
13406
|
"use strict";
|
|
13222
|
-
|
|
13223
|
-
|
|
13224
|
-
|
|
13407
|
+
import_node_crypto8 = require("crypto");
|
|
13408
|
+
import_node_fs32 = require("fs");
|
|
13409
|
+
import_node_path32 = require("path");
|
|
13225
13410
|
init_global_workspace();
|
|
13226
13411
|
init_chat_tabs();
|
|
13227
13412
|
init_thread_store();
|
|
@@ -13246,9 +13431,9 @@ function matchSimpleGlob(pattern, name) {
|
|
|
13246
13431
|
return new RegExp(`^${escaped}$`).test(name);
|
|
13247
13432
|
}
|
|
13248
13433
|
function readWorktreeInclude(repoPath) {
|
|
13249
|
-
const path2 = (0,
|
|
13250
|
-
if (!(0,
|
|
13251
|
-
return (0,
|
|
13434
|
+
const path2 = (0, import_node_path33.join)(repoPath, ".worktreeinclude");
|
|
13435
|
+
if (!(0, import_node_fs33.existsSync)(path2)) return [];
|
|
13436
|
+
return (0, import_node_fs33.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
13252
13437
|
}
|
|
13253
13438
|
function resolveFilesToCopy(repoPath) {
|
|
13254
13439
|
const fromInclude = readWorktreeInclude(repoPath);
|
|
@@ -13258,10 +13443,10 @@ function resolveFilesToCopy(repoPath) {
|
|
|
13258
13443
|
if (settings?.fileIncludeGlobs?.length) {
|
|
13259
13444
|
const matched = [];
|
|
13260
13445
|
try {
|
|
13261
|
-
for (const entry of (0,
|
|
13446
|
+
for (const entry of (0, import_node_fs33.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
13262
13447
|
if (!entry.isFile()) continue;
|
|
13263
13448
|
for (const glob of settings.fileIncludeGlobs) {
|
|
13264
|
-
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0,
|
|
13449
|
+
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path33.basename)(glob), entry.name)) {
|
|
13265
13450
|
matched.push(entry.name);
|
|
13266
13451
|
break;
|
|
13267
13452
|
}
|
|
@@ -13273,7 +13458,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
13273
13458
|
}
|
|
13274
13459
|
const defaults = [];
|
|
13275
13460
|
try {
|
|
13276
|
-
for (const entry of (0,
|
|
13461
|
+
for (const entry of (0, import_node_fs33.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
13277
13462
|
if (entry.isFile() && entry.name.startsWith(".env")) {
|
|
13278
13463
|
defaults.push(entry.name);
|
|
13279
13464
|
}
|
|
@@ -13287,11 +13472,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
|
|
|
13287
13472
|
const patterns = resolveFilesToCopy(repoPath);
|
|
13288
13473
|
const copied = [];
|
|
13289
13474
|
for (const rel of patterns) {
|
|
13290
|
-
const src = (0,
|
|
13291
|
-
if (!(0,
|
|
13292
|
-
const dest = (0,
|
|
13293
|
-
(0,
|
|
13294
|
-
(0,
|
|
13475
|
+
const src = (0, import_node_path33.join)(repoPath, rel);
|
|
13476
|
+
if (!(0, import_node_fs33.existsSync)(src)) continue;
|
|
13477
|
+
const dest = (0, import_node_path33.join)(worktreePath, rel);
|
|
13478
|
+
(0, import_node_fs33.mkdirSync)((0, import_node_path33.dirname)(dest), { recursive: true });
|
|
13479
|
+
(0, import_node_fs33.copyFileSync)(src, dest);
|
|
13295
13480
|
copied.push(rel);
|
|
13296
13481
|
}
|
|
13297
13482
|
return copied;
|
|
@@ -13326,7 +13511,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
|
|
|
13326
13511
|
const env = stripNestedElectronEnv({
|
|
13327
13512
|
...baseEnv ?? process.env
|
|
13328
13513
|
});
|
|
13329
|
-
const name = opts.workspaceName ?? (0,
|
|
13514
|
+
const name = opts.workspaceName ?? (0, import_node_path33.basename)(opts.worktreePath);
|
|
13330
13515
|
const ports = opts.ports ?? [];
|
|
13331
13516
|
const primary = ports[0];
|
|
13332
13517
|
env.SIDEBOARD_WORKSPACE_NAME = name;
|
|
@@ -13481,6 +13666,7 @@ async function runConventionSetup(repoPath, worktreePath, onLine, opts) {
|
|
|
13481
13666
|
};
|
|
13482
13667
|
}
|
|
13483
13668
|
async function runWorkspaceSetup(repoPath, worktreePath, onLine, opts) {
|
|
13669
|
+
await ensureWorktreeSideboardIgnored(worktreePath);
|
|
13484
13670
|
const reviewSkill = ensureReviewSkillFile(worktreePath);
|
|
13485
13671
|
if (reviewSkill.wrote) {
|
|
13486
13672
|
onLine?.(
|
|
@@ -13587,13 +13773,13 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
|
13587
13773
|
done: handle.done
|
|
13588
13774
|
};
|
|
13589
13775
|
}
|
|
13590
|
-
var
|
|
13776
|
+
var import_node_fs33, import_node_net, import_node_path33, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
|
|
13591
13777
|
var init_conductor = __esm({
|
|
13592
13778
|
"src/hook/conductor.ts"() {
|
|
13593
13779
|
"use strict";
|
|
13594
|
-
|
|
13780
|
+
import_node_fs33 = require("fs");
|
|
13595
13781
|
import_node_net = require("net");
|
|
13596
|
-
|
|
13782
|
+
import_node_path33 = require("path");
|
|
13597
13783
|
import_execa4 = require("execa");
|
|
13598
13784
|
import_node_readline3 = require("readline");
|
|
13599
13785
|
init_settings();
|
|
@@ -13602,6 +13788,7 @@ var init_conductor = __esm({
|
|
|
13602
13788
|
init_cursor_worktrees();
|
|
13603
13789
|
init_git_auth_mode();
|
|
13604
13790
|
init_request_review();
|
|
13791
|
+
init_worktree_exclude();
|
|
13605
13792
|
init_nested_electron_env();
|
|
13606
13793
|
PORT_RANGE_SIZE = 10;
|
|
13607
13794
|
cachedLoginEnv = null;
|
|
@@ -13619,9 +13806,9 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
13619
13806
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
13620
13807
|
);
|
|
13621
13808
|
const homeRoot = sideboardWorkspacesDir();
|
|
13622
|
-
if ((0,
|
|
13809
|
+
if ((0, import_node_fs34.existsSync)(homeRoot)) {
|
|
13623
13810
|
try {
|
|
13624
|
-
for (const entry of (0,
|
|
13811
|
+
for (const entry of (0, import_node_fs34.readdirSync)(homeRoot, { withFileTypes: true })) {
|
|
13625
13812
|
if (!entry.isDirectory()) continue;
|
|
13626
13813
|
void entry;
|
|
13627
13814
|
}
|
|
@@ -13631,7 +13818,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
13631
13818
|
const orphans = [];
|
|
13632
13819
|
const seen = /* @__PURE__ */ new Set();
|
|
13633
13820
|
for (const repoPath of repos) {
|
|
13634
|
-
if (!repoPath || !(0,
|
|
13821
|
+
if (!repoPath || !(0, import_node_fs34.existsSync)(repoPath)) continue;
|
|
13635
13822
|
try {
|
|
13636
13823
|
const wts = await listWorktrees(repoPath);
|
|
13637
13824
|
for (const wt of wts) {
|
|
@@ -13642,7 +13829,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
13642
13829
|
seen.add(path2);
|
|
13643
13830
|
let mtimeMs = 0;
|
|
13644
13831
|
try {
|
|
13645
|
-
mtimeMs = (0,
|
|
13832
|
+
mtimeMs = (0, import_node_fs34.statSync)(path2).mtimeMs;
|
|
13646
13833
|
} catch {
|
|
13647
13834
|
mtimeMs = 0;
|
|
13648
13835
|
}
|
|
@@ -13652,16 +13839,16 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
13652
13839
|
}
|
|
13653
13840
|
try {
|
|
13654
13841
|
const root = worktreesRoot(repoPath);
|
|
13655
|
-
if ((0,
|
|
13656
|
-
for (const entry of (0,
|
|
13842
|
+
if ((0, import_node_fs34.existsSync)(root)) {
|
|
13843
|
+
for (const entry of (0, import_node_fs34.readdirSync)(root, { withFileTypes: true })) {
|
|
13657
13844
|
if (!entry.isDirectory()) continue;
|
|
13658
|
-
const path2 = (0,
|
|
13845
|
+
const path2 = (0, import_node_path34.join)(root, entry.name).replace(/\/$/, "");
|
|
13659
13846
|
if (known.has(path2) || seen.has(path2)) continue;
|
|
13660
|
-
if (!(0,
|
|
13847
|
+
if (!(0, import_node_fs34.existsSync)((0, import_node_path34.join)(path2, ".git"))) continue;
|
|
13661
13848
|
seen.add(path2);
|
|
13662
13849
|
let mtimeMs = 0;
|
|
13663
13850
|
try {
|
|
13664
|
-
mtimeMs = (0,
|
|
13851
|
+
mtimeMs = (0, import_node_fs34.statSync)(path2).mtimeMs;
|
|
13665
13852
|
} catch {
|
|
13666
13853
|
mtimeMs = Date.now();
|
|
13667
13854
|
}
|
|
@@ -13722,12 +13909,12 @@ function worktreeCleanupSettings() {
|
|
|
13722
13909
|
autoCleanupOrphans: a.autoCleanupOrphans
|
|
13723
13910
|
};
|
|
13724
13911
|
}
|
|
13725
|
-
var
|
|
13912
|
+
var import_node_fs34, import_node_path34;
|
|
13726
13913
|
var init_orphan_cleanup = __esm({
|
|
13727
13914
|
"src/git/orphan-cleanup.ts"() {
|
|
13728
13915
|
"use strict";
|
|
13729
|
-
|
|
13730
|
-
|
|
13916
|
+
import_node_fs34 = require("fs");
|
|
13917
|
+
import_node_path34 = require("path");
|
|
13731
13918
|
init_worktree();
|
|
13732
13919
|
init_thread_store();
|
|
13733
13920
|
init_paths();
|
|
@@ -13834,38 +14021,38 @@ __export(workspaces_exports, {
|
|
|
13834
14021
|
syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
|
|
13835
14022
|
});
|
|
13836
14023
|
function workspacesFile() {
|
|
13837
|
-
return (0,
|
|
14024
|
+
return (0, import_node_path35.join)(appDataDir(), "workspaces.json");
|
|
13838
14025
|
}
|
|
13839
14026
|
function removedWorkspacesFile() {
|
|
13840
|
-
return (0,
|
|
14027
|
+
return (0, import_node_path35.join)(appDataDir(), "removed-workspaces.json");
|
|
13841
14028
|
}
|
|
13842
14029
|
function readAll2() {
|
|
13843
14030
|
const path2 = workspacesFile();
|
|
13844
|
-
if (!(0,
|
|
14031
|
+
if (!(0, import_node_fs35.existsSync)(path2)) return [];
|
|
13845
14032
|
try {
|
|
13846
|
-
const raw = JSON.parse((0,
|
|
14033
|
+
const raw = JSON.parse((0, import_node_fs35.readFileSync)(path2, "utf8"));
|
|
13847
14034
|
return Array.isArray(raw) ? raw : [];
|
|
13848
14035
|
} catch {
|
|
13849
14036
|
return [];
|
|
13850
14037
|
}
|
|
13851
14038
|
}
|
|
13852
14039
|
function writeAll2(list) {
|
|
13853
|
-
(0,
|
|
13854
|
-
(0,
|
|
14040
|
+
(0, import_node_fs35.mkdirSync)(appDataDir(), { recursive: true });
|
|
14041
|
+
(0, import_node_fs35.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
|
|
13855
14042
|
}
|
|
13856
14043
|
function readRemoved() {
|
|
13857
14044
|
const path2 = removedWorkspacesFile();
|
|
13858
|
-
if (!(0,
|
|
14045
|
+
if (!(0, import_node_fs35.existsSync)(path2)) return /* @__PURE__ */ new Set();
|
|
13859
14046
|
try {
|
|
13860
|
-
const raw = JSON.parse((0,
|
|
14047
|
+
const raw = JSON.parse((0, import_node_fs35.readFileSync)(path2, "utf8"));
|
|
13861
14048
|
return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
|
|
13862
14049
|
} catch {
|
|
13863
14050
|
return /* @__PURE__ */ new Set();
|
|
13864
14051
|
}
|
|
13865
14052
|
}
|
|
13866
14053
|
function writeRemoved(paths) {
|
|
13867
|
-
(0,
|
|
13868
|
-
(0,
|
|
14054
|
+
(0, import_node_fs35.mkdirSync)(appDataDir(), { recursive: true });
|
|
14055
|
+
(0, import_node_fs35.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
|
|
13869
14056
|
}
|
|
13870
14057
|
function rememberRemoved(repoPath) {
|
|
13871
14058
|
const next = readRemoved();
|
|
@@ -13888,7 +14075,7 @@ function listWorkspaces() {
|
|
|
13888
14075
|
async function addWorkspace(repoPath) {
|
|
13889
14076
|
const root = await resolveRepoRoot(repoPath);
|
|
13890
14077
|
if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
|
|
13891
|
-
if (!(0,
|
|
14078
|
+
if (!(0, import_node_fs35.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
|
|
13892
14079
|
forgetRemoved(root);
|
|
13893
14080
|
await ensureGhPreferOrigin(root);
|
|
13894
14081
|
const current = readAll2();
|
|
@@ -13896,7 +14083,7 @@ async function addWorkspace(repoPath) {
|
|
|
13896
14083
|
if (existing) return existing;
|
|
13897
14084
|
const next = {
|
|
13898
14085
|
path: root,
|
|
13899
|
-
name: (0,
|
|
14086
|
+
name: (0, import_node_path35.basename)(root),
|
|
13900
14087
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13901
14088
|
};
|
|
13902
14089
|
writeAll2([...current, next]);
|
|
@@ -13918,10 +14105,10 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
13918
14105
|
if (!path2 || path2 === "/" || isGlobalRepoPath(path2) || byPath.has(path2) || removed.has(path2)) {
|
|
13919
14106
|
continue;
|
|
13920
14107
|
}
|
|
13921
|
-
if (!(0,
|
|
14108
|
+
if (!(0, import_node_fs35.existsSync)(path2)) continue;
|
|
13922
14109
|
const ws = {
|
|
13923
14110
|
path: path2,
|
|
13924
|
-
name: (0,
|
|
14111
|
+
name: (0, import_node_path35.basename)(path2),
|
|
13925
14112
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13926
14113
|
};
|
|
13927
14114
|
byPath.set(path2, ws);
|
|
@@ -13931,12 +14118,12 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
13931
14118
|
if (dirty) writeAll2(next);
|
|
13932
14119
|
return next.sort((a, b) => a.name.localeCompare(b.name));
|
|
13933
14120
|
}
|
|
13934
|
-
var
|
|
14121
|
+
var import_node_fs35, import_node_path35;
|
|
13935
14122
|
var init_workspaces2 = __esm({
|
|
13936
14123
|
"src/store/workspaces.ts"() {
|
|
13937
14124
|
"use strict";
|
|
13938
|
-
|
|
13939
|
-
|
|
14125
|
+
import_node_fs35 = require("fs");
|
|
14126
|
+
import_node_path35 = require("path");
|
|
13940
14127
|
init_paths();
|
|
13941
14128
|
init_global_workspace();
|
|
13942
14129
|
init_worktree();
|
|
@@ -13949,12 +14136,12 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
13949
14136
|
if (!url) throw new Error("Clone URL is required");
|
|
13950
14137
|
let name = opts.name?.trim();
|
|
13951
14138
|
if (!name) {
|
|
13952
|
-
const leaf = (0,
|
|
14139
|
+
const leaf = (0, import_node_path36.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
|
|
13953
14140
|
name = leaf || "repo";
|
|
13954
14141
|
}
|
|
13955
14142
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
13956
|
-
const dest = (0,
|
|
13957
|
-
if ((0,
|
|
14143
|
+
const dest = (0, import_node_path36.join)(sideboardReposDir(), name);
|
|
14144
|
+
if ((0, import_node_fs36.existsSync)(dest)) {
|
|
13958
14145
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
13959
14146
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
13960
14147
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -13969,12 +14156,12 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
13969
14156
|
const workspace = await ensureWorkspace(repoPath);
|
|
13970
14157
|
return { repoPath, workspace };
|
|
13971
14158
|
}
|
|
13972
|
-
var
|
|
14159
|
+
var import_node_fs36, import_node_path36, import_execa6;
|
|
13973
14160
|
var init_clone_repo = __esm({
|
|
13974
14161
|
"src/git/clone-repo.ts"() {
|
|
13975
14162
|
"use strict";
|
|
13976
|
-
|
|
13977
|
-
|
|
14163
|
+
import_node_fs36 = require("fs");
|
|
14164
|
+
import_node_path36 = require("path");
|
|
13978
14165
|
import_execa6 = require("execa");
|
|
13979
14166
|
init_paths();
|
|
13980
14167
|
init_workspaces2();
|
|
@@ -14991,7 +15178,7 @@ function persistCreateAttachments(worktreePath, attachments) {
|
|
|
14991
15178
|
}
|
|
14992
15179
|
async function createThread(input, _onSetupLine) {
|
|
14993
15180
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
14994
|
-
if (!(0,
|
|
15181
|
+
if (!(0, import_node_fs37.existsSync)(repoPath)) {
|
|
14995
15182
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
14996
15183
|
}
|
|
14997
15184
|
if (input.reuseExisting !== false) {
|
|
@@ -15166,11 +15353,11 @@ async function listLinearIssues(agent, repoPath) {
|
|
|
15166
15353
|
}
|
|
15167
15354
|
return adapter.listLinearIssues(repoPath);
|
|
15168
15355
|
}
|
|
15169
|
-
var
|
|
15356
|
+
var import_node_fs37;
|
|
15170
15357
|
var init_create = __esm({
|
|
15171
15358
|
"src/threads/create.ts"() {
|
|
15172
15359
|
"use strict";
|
|
15173
|
-
|
|
15360
|
+
import_node_fs37 = require("fs");
|
|
15174
15361
|
init_detect();
|
|
15175
15362
|
init_worktree();
|
|
15176
15363
|
init_home_board();
|
|
@@ -15273,20 +15460,20 @@ function writeTurnLive(threadId, progress) {
|
|
|
15273
15460
|
const path2 = threadLivePath(threadId);
|
|
15274
15461
|
const tmp = `${path2}.${process.pid}.tmp`;
|
|
15275
15462
|
try {
|
|
15276
|
-
(0,
|
|
15277
|
-
(0,
|
|
15463
|
+
(0, import_node_fs38.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
|
|
15464
|
+
(0, import_node_fs38.renameSync)(tmp, path2);
|
|
15278
15465
|
} catch {
|
|
15279
15466
|
try {
|
|
15280
|
-
(0,
|
|
15467
|
+
(0, import_node_fs38.unlinkSync)(tmp);
|
|
15281
15468
|
} catch {
|
|
15282
15469
|
}
|
|
15283
15470
|
}
|
|
15284
15471
|
}
|
|
15285
15472
|
function readTurnLive(threadId) {
|
|
15286
15473
|
const path2 = threadLivePath(threadId);
|
|
15287
|
-
if (!(0,
|
|
15474
|
+
if (!(0, import_node_fs38.existsSync)(path2)) return null;
|
|
15288
15475
|
try {
|
|
15289
|
-
const raw = JSON.parse((0,
|
|
15476
|
+
const raw = JSON.parse((0, import_node_fs38.readFileSync)(path2, "utf8"));
|
|
15290
15477
|
if (!raw || typeof raw.summary !== "string") return null;
|
|
15291
15478
|
return raw;
|
|
15292
15479
|
} catch {
|
|
@@ -15298,17 +15485,17 @@ function clearTurnLive(threadId) {
|
|
|
15298
15485
|
if (buf?.timer) clearTimeout(buf.timer);
|
|
15299
15486
|
buffers.delete(threadId);
|
|
15300
15487
|
const path2 = threadLivePath(threadId);
|
|
15301
|
-
if (!(0,
|
|
15488
|
+
if (!(0, import_node_fs38.existsSync)(path2)) return;
|
|
15302
15489
|
try {
|
|
15303
|
-
(0,
|
|
15490
|
+
(0, import_node_fs38.unlinkSync)(path2);
|
|
15304
15491
|
} catch {
|
|
15305
15492
|
}
|
|
15306
15493
|
}
|
|
15307
|
-
var
|
|
15494
|
+
var import_node_fs38, buffers, FLUSH_MS, MAX_PARTS;
|
|
15308
15495
|
var init_turn_live = __esm({
|
|
15309
15496
|
"src/store/turn-live.ts"() {
|
|
15310
15497
|
"use strict";
|
|
15311
|
-
|
|
15498
|
+
import_node_fs38 = require("fs");
|
|
15312
15499
|
init_message_parts();
|
|
15313
15500
|
init_paths();
|
|
15314
15501
|
buffers = /* @__PURE__ */ new Map();
|
|
@@ -15482,7 +15669,7 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
|
|
|
15482
15669
|
`- Do not wait on the limited ${from.agent} account; keep going on ${fallbackAgent}.`
|
|
15483
15670
|
].join("\n");
|
|
15484
15671
|
return {
|
|
15485
|
-
id: (0,
|
|
15672
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
15486
15673
|
name: "Orchestration quota handoff.md",
|
|
15487
15674
|
kind: "transcript",
|
|
15488
15675
|
content: body
|
|
@@ -15503,11 +15690,11 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
|
|
|
15503
15690
|
sourceType: "orchestration"
|
|
15504
15691
|
});
|
|
15505
15692
|
}
|
|
15506
|
-
var
|
|
15693
|
+
var import_node_crypto9, QUOTA_CONTINUE_PROMPT, QUOTA_RESUME_PROMPT;
|
|
15507
15694
|
var init_quota_failover = __esm({
|
|
15508
15695
|
"src/orchestrator/quota-failover.ts"() {
|
|
15509
15696
|
"use strict";
|
|
15510
|
-
|
|
15697
|
+
import_node_crypto9 = require("crypto");
|
|
15511
15698
|
init_session_quota();
|
|
15512
15699
|
init_app_settings();
|
|
15513
15700
|
init_global_workspace();
|
|
@@ -15524,7 +15711,7 @@ var init_quota_failover = __esm({
|
|
|
15524
15711
|
// src/threads/adopt.ts
|
|
15525
15712
|
function thisModuleFile() {
|
|
15526
15713
|
const cjsFile = typeof __filename !== "undefined" ? __filename : "";
|
|
15527
|
-
return cjsFile || process.argv[1] || (0,
|
|
15714
|
+
return cjsFile || process.argv[1] || (0, import_node_path37.join)(process.cwd(), "package.json");
|
|
15528
15715
|
}
|
|
15529
15716
|
function openReadonlySqlite(file) {
|
|
15530
15717
|
const req = (0, import_node_module4.createRequire)(thisModuleFile());
|
|
@@ -15542,21 +15729,21 @@ function mapAgentType(raw) {
|
|
|
15542
15729
|
return null;
|
|
15543
15730
|
}
|
|
15544
15731
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
15545
|
-
if (!workspacePath || !(0,
|
|
15732
|
+
if (!workspacePath || !(0, import_node_fs39.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
15546
15733
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
15547
15734
|
let best = null;
|
|
15548
15735
|
let hashes;
|
|
15549
15736
|
try {
|
|
15550
|
-
hashes = (0,
|
|
15737
|
+
hashes = (0, import_node_fs39.readdirSync)(CURSOR_SDK_STORE);
|
|
15551
15738
|
} catch {
|
|
15552
15739
|
return null;
|
|
15553
15740
|
}
|
|
15554
15741
|
for (const hash of hashes) {
|
|
15555
|
-
const agentsFile = (0,
|
|
15556
|
-
if (!(0,
|
|
15742
|
+
const agentsFile = (0, import_node_path37.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
15743
|
+
if (!(0, import_node_fs39.existsSync)(agentsFile)) continue;
|
|
15557
15744
|
let text5;
|
|
15558
15745
|
try {
|
|
15559
|
-
text5 = (0,
|
|
15746
|
+
text5 = (0, import_node_fs39.readFileSync)(agentsFile, "utf8");
|
|
15560
15747
|
} catch {
|
|
15561
15748
|
continue;
|
|
15562
15749
|
}
|
|
@@ -15580,7 +15767,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
15580
15767
|
return best?.agentId ?? null;
|
|
15581
15768
|
}
|
|
15582
15769
|
async function adoptThread(input) {
|
|
15583
|
-
if (!(0,
|
|
15770
|
+
if (!(0, import_node_fs39.existsSync)(input.worktreePath)) {
|
|
15584
15771
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
15585
15772
|
}
|
|
15586
15773
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -15601,24 +15788,26 @@ async function adoptThread(input) {
|
|
|
15601
15788
|
writeThread(thread);
|
|
15602
15789
|
const { ensureWorkspace: ensureWorkspace2 } = await Promise.resolve().then(() => (init_workspaces2(), workspaces_exports));
|
|
15603
15790
|
await ensureWorkspace2(repoPath);
|
|
15791
|
+
const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await Promise.resolve().then(() => (init_worktree_exclude(), worktree_exclude_exports));
|
|
15792
|
+
await ensureWorktreeSideboardIgnored2(input.worktreePath);
|
|
15604
15793
|
return thread;
|
|
15605
15794
|
}
|
|
15606
15795
|
function conductorDbPath() {
|
|
15607
15796
|
return CONDUCTOR_DB;
|
|
15608
15797
|
}
|
|
15609
15798
|
function listConductorWorkspaces() {
|
|
15610
|
-
if (!(0,
|
|
15799
|
+
if (!(0, import_node_fs39.existsSync)(CONDUCTOR_DB)) {
|
|
15611
15800
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
15612
15801
|
}
|
|
15613
|
-
const tmp = (0,
|
|
15614
|
-
const snapshot = (0,
|
|
15802
|
+
const tmp = (0, import_node_fs39.mkdtempSync)((0, import_node_path37.join)((0, import_node_os11.tmpdir)(), "sideboard-conductor-"));
|
|
15803
|
+
const snapshot = (0, import_node_path37.join)(tmp, "conductor.db");
|
|
15615
15804
|
try {
|
|
15616
|
-
(0,
|
|
15805
|
+
(0, import_node_fs39.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
15617
15806
|
for (const suffix of ["-wal", "-shm"]) {
|
|
15618
15807
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
15619
|
-
if ((0,
|
|
15808
|
+
if ((0, import_node_fs39.existsSync)(src)) {
|
|
15620
15809
|
try {
|
|
15621
|
-
(0,
|
|
15810
|
+
(0, import_node_fs39.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
15622
15811
|
} catch {
|
|
15623
15812
|
}
|
|
15624
15813
|
}
|
|
@@ -15694,22 +15883,22 @@ function listConductorWorkspaces() {
|
|
|
15694
15883
|
db.close();
|
|
15695
15884
|
}
|
|
15696
15885
|
} finally {
|
|
15697
|
-
(0,
|
|
15886
|
+
(0, import_node_fs39.rmSync)(tmp, { recursive: true, force: true });
|
|
15698
15887
|
}
|
|
15699
15888
|
}
|
|
15700
15889
|
function importConductorWorkspace(workspaceId) {
|
|
15701
|
-
if (!(0,
|
|
15890
|
+
if (!(0, import_node_fs39.existsSync)(CONDUCTOR_DB)) {
|
|
15702
15891
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
15703
15892
|
}
|
|
15704
|
-
const tmp = (0,
|
|
15705
|
-
const snapshot = (0,
|
|
15893
|
+
const tmp = (0, import_node_fs39.mkdtempSync)((0, import_node_path37.join)((0, import_node_os11.tmpdir)(), "sideboard-conductor-"));
|
|
15894
|
+
const snapshot = (0, import_node_path37.join)(tmp, "conductor.db");
|
|
15706
15895
|
try {
|
|
15707
|
-
(0,
|
|
15896
|
+
(0, import_node_fs39.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
15708
15897
|
for (const suffix of ["-wal", "-shm"]) {
|
|
15709
15898
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
15710
|
-
if ((0,
|
|
15899
|
+
if ((0, import_node_fs39.existsSync)(src)) {
|
|
15711
15900
|
try {
|
|
15712
|
-
(0,
|
|
15901
|
+
(0, import_node_fs39.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
15713
15902
|
} catch {
|
|
15714
15903
|
}
|
|
15715
15904
|
}
|
|
@@ -15727,7 +15916,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
15727
15916
|
).get(workspaceId);
|
|
15728
15917
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
15729
15918
|
const worktreePath = String(row.workspacePath);
|
|
15730
|
-
if (!(0,
|
|
15919
|
+
if (!(0, import_node_fs39.existsSync)(worktreePath)) {
|
|
15731
15920
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
15732
15921
|
}
|
|
15733
15922
|
let sessionId = null;
|
|
@@ -15790,31 +15979,31 @@ function importConductorWorkspace(workspaceId) {
|
|
|
15790
15979
|
db.close();
|
|
15791
15980
|
}
|
|
15792
15981
|
} finally {
|
|
15793
|
-
(0,
|
|
15982
|
+
(0, import_node_fs39.rmSync)(tmp, { recursive: true, force: true });
|
|
15794
15983
|
}
|
|
15795
15984
|
}
|
|
15796
15985
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
15797
15986
|
return importConductorWorkspace(workspaceId);
|
|
15798
15987
|
}
|
|
15799
|
-
var import_node_child_process4,
|
|
15988
|
+
var import_node_child_process4, import_node_fs39, import_node_os11, import_node_path37, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
|
|
15800
15989
|
var init_adopt = __esm({
|
|
15801
15990
|
"src/threads/adopt.ts"() {
|
|
15802
15991
|
"use strict";
|
|
15803
15992
|
import_node_child_process4 = require("child_process");
|
|
15804
|
-
|
|
15805
|
-
|
|
15806
|
-
|
|
15993
|
+
import_node_fs39 = require("fs");
|
|
15994
|
+
import_node_os11 = require("os");
|
|
15995
|
+
import_node_path37 = require("path");
|
|
15807
15996
|
import_node_module4 = require("module");
|
|
15808
15997
|
init_worktree();
|
|
15809
15998
|
init_thread_store();
|
|
15810
|
-
CONDUCTOR_APP_SUPPORT = (0,
|
|
15999
|
+
CONDUCTOR_APP_SUPPORT = (0, import_node_path37.join)(
|
|
15811
16000
|
process.env.HOME ?? "",
|
|
15812
16001
|
"Library",
|
|
15813
16002
|
"Application Support",
|
|
15814
16003
|
"com.conductor.app"
|
|
15815
16004
|
);
|
|
15816
|
-
CONDUCTOR_DB = (0,
|
|
15817
|
-
CURSOR_SDK_STORE = (0,
|
|
16005
|
+
CONDUCTOR_DB = (0, import_node_path37.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
16006
|
+
CURSOR_SDK_STORE = (0, import_node_path37.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
15818
16007
|
}
|
|
15819
16008
|
});
|
|
15820
16009
|
|
|
@@ -15881,7 +16070,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
15881
16070
|
let createdWorktree = false;
|
|
15882
16071
|
const trees = await listWorktrees(repoPath);
|
|
15883
16072
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
15884
|
-
if (checkedOut?.path && (0,
|
|
16073
|
+
if (checkedOut?.path && (0, import_node_fs40.existsSync)(checkedOut.path)) {
|
|
15885
16074
|
if (input.reuseExistingWorktree !== false) {
|
|
15886
16075
|
worktreePath = checkedOut.path;
|
|
15887
16076
|
} else {
|
|
@@ -16023,7 +16212,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
16023
16212
|
async function createPrStack(input, onSetupLine) {
|
|
16024
16213
|
await requireAgent(input.agent);
|
|
16025
16214
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
16026
|
-
if (!(0,
|
|
16215
|
+
if (!(0, import_node_fs40.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
16027
16216
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
16028
16217
|
const status = await detectGhStack(repoPath);
|
|
16029
16218
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -16090,7 +16279,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
16090
16279
|
}
|
|
16091
16280
|
}
|
|
16092
16281
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
16093
|
-
if (!claimed.has(bootstrap.worktreePath) && (0,
|
|
16282
|
+
if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs40.existsSync)(bootstrap.worktreePath)) {
|
|
16094
16283
|
try {
|
|
16095
16284
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
16096
16285
|
deleteBranch: bootstrap.branchName
|
|
@@ -16110,11 +16299,11 @@ function stackAgentDefaultsFrom(input) {
|
|
|
16110
16299
|
planMode: input.planMode
|
|
16111
16300
|
};
|
|
16112
16301
|
}
|
|
16113
|
-
var
|
|
16302
|
+
var import_node_fs40;
|
|
16114
16303
|
var init_stack_layers = __esm({
|
|
16115
16304
|
"src/threads/stack-layers.ts"() {
|
|
16116
16305
|
"use strict";
|
|
16117
|
-
|
|
16306
|
+
import_node_fs40 = require("fs");
|
|
16118
16307
|
init_detect();
|
|
16119
16308
|
init_run();
|
|
16120
16309
|
init_stack();
|
|
@@ -16127,7 +16316,7 @@ var init_stack_layers = __esm({
|
|
|
16127
16316
|
|
|
16128
16317
|
// src/diff/diff.ts
|
|
16129
16318
|
async function inspectGitWorktree(worktreePath) {
|
|
16130
|
-
if (!worktreePath || !(0,
|
|
16319
|
+
if (!worktreePath || !(0, import_node_fs41.existsSync)(worktreePath)) return "missing_worktree";
|
|
16131
16320
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
16132
16321
|
reject: false
|
|
16133
16322
|
});
|
|
@@ -16135,7 +16324,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
16135
16324
|
return "ok";
|
|
16136
16325
|
}
|
|
16137
16326
|
async function initializeGitRepository(worktreePath) {
|
|
16138
|
-
if (!worktreePath || !(0,
|
|
16327
|
+
if (!worktreePath || !(0, import_node_fs41.existsSync)(worktreePath)) {
|
|
16139
16328
|
throw new Error("Worktree not found");
|
|
16140
16329
|
}
|
|
16141
16330
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -16269,11 +16458,11 @@ new file mode 100644
|
|
|
16269
16458
|
};
|
|
16270
16459
|
}
|
|
16271
16460
|
async function untrackedPatch(worktreePath, path2, maxHunk) {
|
|
16272
|
-
const abs = (0,
|
|
16461
|
+
const abs = (0, import_node_path38.join)(worktreePath, path2);
|
|
16273
16462
|
try {
|
|
16274
|
-
const st = (0,
|
|
16463
|
+
const st = (0, import_node_fs41.statSync)(abs);
|
|
16275
16464
|
if (st.isFile() && st.size > maxHunk) {
|
|
16276
|
-
const buf = (0,
|
|
16465
|
+
const buf = (0, import_node_fs41.readFileSync)(abs).subarray(0, maxHunk);
|
|
16277
16466
|
return syntheticAddPatch(path2, buf.toString("utf8"), maxHunk);
|
|
16278
16467
|
}
|
|
16279
16468
|
} catch {
|
|
@@ -16762,8 +16951,8 @@ function isImageRelativePath(relativePath) {
|
|
|
16762
16951
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
16763
16952
|
assertSafeRelativePath(relativePath);
|
|
16764
16953
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
16765
|
-
const abs = (0,
|
|
16766
|
-
const st = (0,
|
|
16954
|
+
const abs = (0, import_node_path38.join)(worktreePath, relativePath);
|
|
16955
|
+
const st = (0, import_node_fs41.statSync)(abs);
|
|
16767
16956
|
if (!st.isFile()) {
|
|
16768
16957
|
throw new Error(`Not a file: ${relativePath}`);
|
|
16769
16958
|
}
|
|
@@ -16772,7 +16961,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
16772
16961
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
16773
16962
|
);
|
|
16774
16963
|
}
|
|
16775
|
-
const buf = (0,
|
|
16964
|
+
const buf = (0, import_node_fs41.readFileSync)(abs);
|
|
16776
16965
|
return {
|
|
16777
16966
|
path: relativePath,
|
|
16778
16967
|
contentBase64: buf.toString("base64"),
|
|
@@ -16782,12 +16971,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
16782
16971
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
16783
16972
|
assertSafeRelativePath(relativePath);
|
|
16784
16973
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
16785
|
-
const abs = (0,
|
|
16786
|
-
const st = (0,
|
|
16974
|
+
const abs = (0, import_node_path38.join)(worktreePath, relativePath);
|
|
16975
|
+
const st = (0, import_node_fs41.statSync)(abs);
|
|
16787
16976
|
if (!st.isFile()) {
|
|
16788
16977
|
throw new Error(`Not a file: ${relativePath}`);
|
|
16789
16978
|
}
|
|
16790
|
-
const buf = (0,
|
|
16979
|
+
const buf = (0, import_node_fs41.readFileSync)(abs);
|
|
16791
16980
|
if (isImageRelativePath(relativePath)) {
|
|
16792
16981
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
16793
16982
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -16830,9 +17019,9 @@ function assertSafeRelativePath(relativePath) {
|
|
|
16830
17019
|
}
|
|
16831
17020
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
16832
17021
|
assertSafeRelativePath(relativePath);
|
|
16833
|
-
const abs = (0,
|
|
16834
|
-
(0,
|
|
16835
|
-
(0,
|
|
17022
|
+
const abs = (0, import_node_path38.join)(worktreePath, relativePath);
|
|
17023
|
+
(0, import_node_fs41.mkdirSync)((0, import_node_path38.dirname)(abs), { recursive: true });
|
|
17024
|
+
(0, import_node_fs41.writeFileSync)(abs, content, "utf8");
|
|
16836
17025
|
return { path: relativePath };
|
|
16837
17026
|
}
|
|
16838
17027
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
@@ -16849,12 +17038,12 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
|
16849
17038
|
truncated: full.files.length > maxFiles
|
|
16850
17039
|
};
|
|
16851
17040
|
}
|
|
16852
|
-
var
|
|
17041
|
+
var import_node_fs41, import_node_path38, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
|
|
16853
17042
|
var init_diff = __esm({
|
|
16854
17043
|
"src/diff/diff.ts"() {
|
|
16855
17044
|
"use strict";
|
|
16856
|
-
|
|
16857
|
-
|
|
17045
|
+
import_node_fs41 = require("fs");
|
|
17046
|
+
import_node_path38 = require("path");
|
|
16858
17047
|
init_run();
|
|
16859
17048
|
init_worktree();
|
|
16860
17049
|
mergeBaseCache = /* @__PURE__ */ new Map();
|
|
@@ -17112,7 +17301,7 @@ function parseFrontmatter(content) {
|
|
|
17112
17301
|
}
|
|
17113
17302
|
function readSkill(skillMd, source) {
|
|
17114
17303
|
try {
|
|
17115
|
-
const content = (0,
|
|
17304
|
+
const content = (0, import_node_fs42.readFileSync)(skillMd, "utf8");
|
|
17116
17305
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
17117
17306
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
17118
17307
|
const name = fmName || dirName;
|
|
@@ -17131,19 +17320,19 @@ function readSkill(skillMd, source) {
|
|
|
17131
17320
|
}
|
|
17132
17321
|
}
|
|
17133
17322
|
function scanSkillsDir(dir, source, out) {
|
|
17134
|
-
if (!(0,
|
|
17323
|
+
if (!(0, import_node_fs42.existsSync)(dir)) return;
|
|
17135
17324
|
let entries;
|
|
17136
17325
|
try {
|
|
17137
|
-
entries = (0,
|
|
17326
|
+
entries = (0, import_node_fs42.readdirSync)(dir);
|
|
17138
17327
|
} catch {
|
|
17139
17328
|
return;
|
|
17140
17329
|
}
|
|
17141
17330
|
for (const entry of entries) {
|
|
17142
17331
|
if (entry.startsWith(".")) continue;
|
|
17143
|
-
const skillMd = (0,
|
|
17144
|
-
if (!(0,
|
|
17332
|
+
const skillMd = (0, import_node_path39.join)(dir, entry, "SKILL.md");
|
|
17333
|
+
if (!(0, import_node_fs42.existsSync)(skillMd)) continue;
|
|
17145
17334
|
try {
|
|
17146
|
-
if (!(0,
|
|
17335
|
+
if (!(0, import_node_fs42.statSync)(skillMd).isFile()) continue;
|
|
17147
17336
|
} catch {
|
|
17148
17337
|
continue;
|
|
17149
17338
|
}
|
|
@@ -17152,24 +17341,24 @@ function scanSkillsDir(dir, source, out) {
|
|
|
17152
17341
|
}
|
|
17153
17342
|
}
|
|
17154
17343
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
17155
|
-
if (!(0,
|
|
17344
|
+
if (!(0, import_node_fs42.existsSync)(pluginsRoot)) return;
|
|
17156
17345
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
17157
17346
|
if (depth > 7) return;
|
|
17158
17347
|
let entries;
|
|
17159
17348
|
try {
|
|
17160
|
-
entries = (0,
|
|
17349
|
+
entries = (0, import_node_fs42.readdirSync)(dir);
|
|
17161
17350
|
} catch {
|
|
17162
17351
|
return;
|
|
17163
17352
|
}
|
|
17164
17353
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
17165
|
-
const skill = readSkill((0,
|
|
17354
|
+
const skill = readSkill((0, import_node_path39.join)(dir, "SKILL.md"), "cli");
|
|
17166
17355
|
if (skill) out.push(skill);
|
|
17167
17356
|
}
|
|
17168
17357
|
for (const entry of entries) {
|
|
17169
17358
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
17170
|
-
const full = (0,
|
|
17359
|
+
const full = (0, import_node_path39.join)(dir, entry);
|
|
17171
17360
|
try {
|
|
17172
|
-
if (!(0,
|
|
17361
|
+
if (!(0, import_node_fs42.statSync)(full).isDirectory()) continue;
|
|
17173
17362
|
} catch {
|
|
17174
17363
|
continue;
|
|
17175
17364
|
}
|
|
@@ -17184,20 +17373,20 @@ function scanClaudePluginSkills(pluginsRoot, out) {
|
|
|
17184
17373
|
walk(pluginsRoot, 0, false);
|
|
17185
17374
|
}
|
|
17186
17375
|
function discoverSkills(worktreePath) {
|
|
17187
|
-
const home = (0,
|
|
17376
|
+
const home = (0, import_node_os12.homedir)();
|
|
17188
17377
|
const collected = [];
|
|
17189
17378
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
17190
|
-
scanSkillsDir((0,
|
|
17379
|
+
scanSkillsDir((0, import_node_path39.join)(worktreePath, rel), "workspace", collected);
|
|
17191
17380
|
}
|
|
17192
17381
|
for (const abs of [
|
|
17193
|
-
(0,
|
|
17194
|
-
(0,
|
|
17195
|
-
(0,
|
|
17196
|
-
(0,
|
|
17382
|
+
(0, import_node_path39.join)(home, ".claude/skills"),
|
|
17383
|
+
(0, import_node_path39.join)(home, ".cursor/skills"),
|
|
17384
|
+
(0, import_node_path39.join)(home, ".sideboard/skills"),
|
|
17385
|
+
(0, import_node_path39.join)(home, ".brightsy/skills")
|
|
17197
17386
|
]) {
|
|
17198
17387
|
scanSkillsDir(abs, "user", collected);
|
|
17199
17388
|
}
|
|
17200
|
-
scanClaudePluginSkills((0,
|
|
17389
|
+
scanClaudePluginSkills((0, import_node_path39.join)(home, ".claude/plugins"), collected);
|
|
17201
17390
|
collected.push(...bundledSkills());
|
|
17202
17391
|
const rank = {
|
|
17203
17392
|
workspace: 0,
|
|
@@ -17223,7 +17412,7 @@ function readSkillBody(skillPath, maxChars = 12e3) {
|
|
|
17223
17412
|
\u2026(truncated)` : body;
|
|
17224
17413
|
}
|
|
17225
17414
|
}
|
|
17226
|
-
const raw = (0,
|
|
17415
|
+
const raw = (0, import_node_fs42.readFileSync)(skillPath, "utf8");
|
|
17227
17416
|
if (raw.startsWith("---")) {
|
|
17228
17417
|
const end = raw.indexOf("\n---", 3);
|
|
17229
17418
|
if (end >= 0) {
|
|
@@ -17237,13 +17426,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
|
|
|
17237
17426
|
|
|
17238
17427
|
\u2026(truncated)` : raw;
|
|
17239
17428
|
}
|
|
17240
|
-
var
|
|
17429
|
+
var import_node_fs42, import_node_os12, import_node_path39, BUNDLED_SKILL_PREFIX;
|
|
17241
17430
|
var init_discover = __esm({
|
|
17242
17431
|
"src/skills/discover.ts"() {
|
|
17243
17432
|
"use strict";
|
|
17244
|
-
|
|
17245
|
-
|
|
17246
|
-
|
|
17433
|
+
import_node_fs42 = require("fs");
|
|
17434
|
+
import_node_os12 = require("os");
|
|
17435
|
+
import_node_path39 = require("path");
|
|
17247
17436
|
init_long_running();
|
|
17248
17437
|
BUNDLED_SKILL_PREFIX = "bundled:";
|
|
17249
17438
|
}
|
|
@@ -17338,17 +17527,17 @@ var init_expand = __esm({
|
|
|
17338
17527
|
function packagedDetachedJobPath() {
|
|
17339
17528
|
const dir = packagedMcpDir();
|
|
17340
17529
|
if (!dir) return null;
|
|
17341
|
-
const script = (0,
|
|
17342
|
-
return (0,
|
|
17530
|
+
const script = (0, import_node_path40.join)(dir, "scripts", "detached-job.js");
|
|
17531
|
+
return (0, import_node_fs43.existsSync)(script) ? script : null;
|
|
17343
17532
|
}
|
|
17344
17533
|
function resolveDetachedJobScript() {
|
|
17345
17534
|
const packaged = packagedDetachedJobPath();
|
|
17346
17535
|
if (packaged) return packaged;
|
|
17347
|
-
let dir = (0,
|
|
17536
|
+
let dir = (0, import_node_path40.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
|
|
17348
17537
|
for (let i = 0; i < 8; i++) {
|
|
17349
|
-
const candidate = (0,
|
|
17350
|
-
if ((0,
|
|
17351
|
-
const parent = (0,
|
|
17538
|
+
const candidate = (0, import_node_path40.join)(dir, "scripts", "detached-job.js");
|
|
17539
|
+
if ((0, import_node_fs43.existsSync)(candidate)) return candidate;
|
|
17540
|
+
const parent = (0, import_node_path40.dirname)(dir);
|
|
17352
17541
|
if (parent === dir) break;
|
|
17353
17542
|
dir = parent;
|
|
17354
17543
|
}
|
|
@@ -17359,12 +17548,12 @@ function formatDetachedJobInvoke(scriptPath) {
|
|
|
17359
17548
|
if (resolved) return `node ${JSON.stringify(resolved)}`;
|
|
17360
17549
|
return "node scripts/detached-job.js";
|
|
17361
17550
|
}
|
|
17362
|
-
var
|
|
17551
|
+
var import_node_fs43, import_node_path40, import_node_url3, import_meta3;
|
|
17363
17552
|
var init_detached_job_path = __esm({
|
|
17364
17553
|
"src/skills/detached-job-path.ts"() {
|
|
17365
17554
|
"use strict";
|
|
17366
|
-
|
|
17367
|
-
|
|
17555
|
+
import_node_fs43 = require("fs");
|
|
17556
|
+
import_node_path40 = require("path");
|
|
17368
17557
|
import_node_url3 = require("url");
|
|
17369
17558
|
init_packaged_runtime();
|
|
17370
17559
|
import_meta3 = {};
|
|
@@ -17437,11 +17626,11 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
17437
17626
|
);
|
|
17438
17627
|
} else if (opts?.githubSlug) {
|
|
17439
17628
|
lines.push(
|
|
17440
|
-
`- Prefer a draft PR first: \`gh pr create --draft -R ${opts.githubSlug}\` (or update via \`gh pr edit -R ${opts.githubSlug}\`) once the change set is coherent. Always pass \`-R ${opts.githubSlug}\` (this worktree's origin). Bare \`gh pr create\` may target upstream instead of origin on dual-remote checkouts. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name
|
|
17629
|
+
`- Prefer a draft PR first: \`gh pr create --draft -R ${opts.githubSlug}\` (or update via \`gh pr edit -R ${opts.githubSlug}\`) once the change set is coherent. Always pass \`-R ${opts.githubSlug}\` (this worktree's origin). Bare \`gh pr create\` may target upstream instead of origin on dual-remote checkouts. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name. If GitHub rejects the GraphQL body as too long, retry with a short \`--body-file\` (limit 65,536 characters) \u2014 do not paste a changelog or diff into \`--body\`.`
|
|
17441
17630
|
);
|
|
17442
17631
|
} else {
|
|
17443
17632
|
lines.push(
|
|
17444
|
-
"- Prefer a draft PR first: `gh pr create --draft -R <origin-owner/name>` (or update via `gh pr edit -R \u2026`) once the change set is coherent. Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree \u2014 never from `upstream`. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name."
|
|
17633
|
+
"- Prefer a draft PR first: `gh pr create --draft -R <origin-owner/name>` (or update via `gh pr edit -R \u2026`) once the change set is coherent. Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree \u2014 never from `upstream`. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name. If GitHub rejects the GraphQL body as too long, retry with a short `--body-file` (limit 65,536 characters) \u2014 do not paste a changelog or diff into `--body`."
|
|
17445
17634
|
);
|
|
17446
17635
|
}
|
|
17447
17636
|
lines.push("");
|
|
@@ -17539,11 +17728,11 @@ function loadAgentInstructions(worktreePath, agent) {
|
|
|
17539
17728
|
const out = [];
|
|
17540
17729
|
for (const rel of candidates) {
|
|
17541
17730
|
if (seenPaths.has(rel)) continue;
|
|
17542
|
-
const abs = (0,
|
|
17543
|
-
if (!(0,
|
|
17731
|
+
const abs = (0, import_node_path41.join)(worktreePath, rel);
|
|
17732
|
+
if (!(0, import_node_fs44.existsSync)(abs)) continue;
|
|
17544
17733
|
try {
|
|
17545
|
-
if (!(0,
|
|
17546
|
-
let content = (0,
|
|
17734
|
+
if (!(0, import_node_fs44.statSync)(abs).isFile()) continue;
|
|
17735
|
+
let content = (0, import_node_fs44.readFileSync)(abs, "utf8");
|
|
17547
17736
|
if (!content.trim()) continue;
|
|
17548
17737
|
if (content.length > MAX_CHARS_PER_FILE) {
|
|
17549
17738
|
content = `${content.slice(0, MAX_CHARS_PER_FILE)}
|
|
@@ -17583,12 +17772,12 @@ function withAgentInstructions(prompt, files) {
|
|
|
17583
17772
|
|
|
17584
17773
|
${prompt}`;
|
|
17585
17774
|
}
|
|
17586
|
-
var
|
|
17775
|
+
var import_node_fs44, import_node_path41, FILES_BY_AGENT, MAX_CHARS_PER_FILE;
|
|
17587
17776
|
var init_instructions = __esm({
|
|
17588
17777
|
"src/agents/instructions.ts"() {
|
|
17589
17778
|
"use strict";
|
|
17590
|
-
|
|
17591
|
-
|
|
17779
|
+
import_node_fs44 = require("fs");
|
|
17780
|
+
import_node_path41 = require("path");
|
|
17592
17781
|
init_git_auth_mode();
|
|
17593
17782
|
init_worktree_labels();
|
|
17594
17783
|
init_detached_job_path();
|
|
@@ -17934,40 +18123,40 @@ __export(plan_file_exports, {
|
|
|
17934
18123
|
writePlanFile: () => writePlanFile
|
|
17935
18124
|
});
|
|
17936
18125
|
function ensureAttachmentsGitignore(worktreePath) {
|
|
17937
|
-
const gitignoreAbs = (0,
|
|
17938
|
-
if ((0,
|
|
17939
|
-
(0,
|
|
17940
|
-
(0,
|
|
18126
|
+
const gitignoreAbs = (0, import_node_path42.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
18127
|
+
if ((0, import_node_fs45.existsSync)(gitignoreAbs)) return;
|
|
18128
|
+
(0, import_node_fs45.mkdirSync)((0, import_node_path42.dirname)(gitignoreAbs), { recursive: true });
|
|
18129
|
+
(0, import_node_fs45.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
17941
18130
|
}
|
|
17942
18131
|
function planFileAbs(worktreePath) {
|
|
17943
|
-
return (0,
|
|
18132
|
+
return (0, import_node_path42.join)(worktreePath, PLAN_FILE_REL);
|
|
17944
18133
|
}
|
|
17945
18134
|
function readTextIfPresent2(abs) {
|
|
17946
|
-
if (!(0,
|
|
18135
|
+
if (!(0, import_node_fs45.existsSync)(abs)) return null;
|
|
17947
18136
|
try {
|
|
17948
|
-
const content = (0,
|
|
18137
|
+
const content = (0, import_node_fs45.readFileSync)(abs, "utf8");
|
|
17949
18138
|
return content.trim() ? content : null;
|
|
17950
18139
|
} catch {
|
|
17951
18140
|
return null;
|
|
17952
18141
|
}
|
|
17953
18142
|
}
|
|
17954
18143
|
function readPlanFile(worktreePath) {
|
|
17955
|
-
return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0,
|
|
18144
|
+
return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path42.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path42.join)(worktreePath, LEGACY_PLAN_FILE_REL));
|
|
17956
18145
|
}
|
|
17957
18146
|
function writePlanFile(worktreePath, content) {
|
|
17958
18147
|
ensureAttachmentsGitignore(worktreePath);
|
|
17959
18148
|
const abs = planFileAbs(worktreePath);
|
|
17960
|
-
(0,
|
|
18149
|
+
(0, import_node_fs45.mkdirSync)((0, import_node_path42.dirname)(abs), { recursive: true });
|
|
17961
18150
|
const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
|
|
17962
|
-
(0,
|
|
18151
|
+
(0, import_node_fs45.writeFileSync)(abs, body, "utf8");
|
|
17963
18152
|
return PLAN_FILE_REL;
|
|
17964
18153
|
}
|
|
17965
|
-
var
|
|
18154
|
+
var import_node_fs45, import_node_path42;
|
|
17966
18155
|
var init_plan_file = __esm({
|
|
17967
18156
|
"src/plan/plan-file.ts"() {
|
|
17968
18157
|
"use strict";
|
|
17969
|
-
|
|
17970
|
-
|
|
18158
|
+
import_node_fs45 = require("fs");
|
|
18159
|
+
import_node_path42 = require("path");
|
|
17971
18160
|
init_workspace_scratch();
|
|
17972
18161
|
init_plan_present();
|
|
17973
18162
|
init_plan_present();
|
|
@@ -18015,13 +18204,13 @@ var init_sync_branch = __esm({
|
|
|
18015
18204
|
|
|
18016
18205
|
// src/agents/cursor-store.ts
|
|
18017
18206
|
function cursorSdkStoreDir(threadId) {
|
|
18018
|
-
const root = (0,
|
|
18207
|
+
const root = (0, import_node_path43.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
|
|
18019
18208
|
const id = sanitizeCursorStoreSegment(threadId);
|
|
18020
18209
|
if (!id) return root;
|
|
18021
|
-
return (0,
|
|
18210
|
+
return (0, import_node_path43.join)(root, "threads", id);
|
|
18022
18211
|
}
|
|
18023
18212
|
function cursorSdkRunsNdjsonPath(threadId) {
|
|
18024
|
-
return (0,
|
|
18213
|
+
return (0, import_node_path43.join)(cursorSdkStoreDir(threadId), "runs.ndjson");
|
|
18025
18214
|
}
|
|
18026
18215
|
function cursorSdkRunsNdjsonSearchPaths(threadId) {
|
|
18027
18216
|
const scoped = cursorSdkRunsNdjsonPath(threadId);
|
|
@@ -18034,11 +18223,11 @@ function cursorSdkRunsNdjsonSearchPaths(threadId) {
|
|
|
18034
18223
|
function sanitizeCursorStoreSegment(threadId) {
|
|
18035
18224
|
return (threadId ?? "").trim().replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
18036
18225
|
}
|
|
18037
|
-
var
|
|
18226
|
+
var import_node_path43, CURSOR_SDK_STORE_DIR;
|
|
18038
18227
|
var init_cursor_store = __esm({
|
|
18039
18228
|
"src/agents/cursor-store.ts"() {
|
|
18040
18229
|
"use strict";
|
|
18041
|
-
|
|
18230
|
+
import_node_path43 = require("path");
|
|
18042
18231
|
init_paths();
|
|
18043
18232
|
CURSOR_SDK_STORE_DIR = "cursor-sdk-store";
|
|
18044
18233
|
}
|
|
@@ -18060,9 +18249,9 @@ function recoverFinishedCursorRun(opts) {
|
|
|
18060
18249
|
return best;
|
|
18061
18250
|
}
|
|
18062
18251
|
function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
|
|
18063
|
-
if (!(0,
|
|
18252
|
+
if (!(0, import_node_fs46.existsSync)(runsPath)) return null;
|
|
18064
18253
|
try {
|
|
18065
|
-
const lines = (0,
|
|
18254
|
+
const lines = (0, import_node_fs46.readFileSync)(runsPath, "utf8").split("\n");
|
|
18066
18255
|
let best = null;
|
|
18067
18256
|
for (const line of lines) {
|
|
18068
18257
|
const trimmed = line.trim();
|
|
@@ -18088,11 +18277,11 @@ function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
|
|
|
18088
18277
|
return null;
|
|
18089
18278
|
}
|
|
18090
18279
|
}
|
|
18091
|
-
var
|
|
18280
|
+
var import_node_fs46;
|
|
18092
18281
|
var init_cursor_recover = __esm({
|
|
18093
18282
|
"src/agents/cursor-recover.ts"() {
|
|
18094
18283
|
"use strict";
|
|
18095
|
-
|
|
18284
|
+
import_node_fs46 = require("fs");
|
|
18096
18285
|
init_cursor_store();
|
|
18097
18286
|
}
|
|
18098
18287
|
});
|
|
@@ -18131,6 +18320,7 @@ var init_title = __esm({
|
|
|
18131
18320
|
// src/orchestrator/orchestrator.ts
|
|
18132
18321
|
var orchestrator_exports = {};
|
|
18133
18322
|
__export(orchestrator_exports, {
|
|
18323
|
+
LIVE_TURN_SPAWN_GRACE_MS: () => LIVE_TURN_SPAWN_GRACE_MS,
|
|
18134
18324
|
Orchestrator: () => Orchestrator,
|
|
18135
18325
|
getOrchestrator: () => getOrchestrator,
|
|
18136
18326
|
isPidAlive: () => isPidAlive,
|
|
@@ -18223,13 +18413,13 @@ async function startOrchestration(opts) {
|
|
|
18223
18413
|
}
|
|
18224
18414
|
return updated;
|
|
18225
18415
|
}
|
|
18226
|
-
var import_node_events,
|
|
18416
|
+
var import_node_events, import_node_fs47, LIVE_TURN_SPAWN_GRACE_MS, STALE_AGENT_PID_WAIT_MS, Orchestrator, singleton;
|
|
18227
18417
|
var init_orchestrator = __esm({
|
|
18228
18418
|
"src/orchestrator/orchestrator.ts"() {
|
|
18229
18419
|
"use strict";
|
|
18230
18420
|
import_node_events = require("events");
|
|
18231
18421
|
init_outbound_watch();
|
|
18232
|
-
|
|
18422
|
+
import_node_fs47 = require("fs");
|
|
18233
18423
|
init_error_detail();
|
|
18234
18424
|
init_run();
|
|
18235
18425
|
init_stale_lock();
|
|
@@ -18244,6 +18434,7 @@ var init_orchestrator = __esm({
|
|
|
18244
18434
|
init_orphan_cleanup();
|
|
18245
18435
|
init_apply_into_main();
|
|
18246
18436
|
init_clone_repo();
|
|
18437
|
+
init_message_parts();
|
|
18247
18438
|
init_usage();
|
|
18248
18439
|
init_thread_store();
|
|
18249
18440
|
init_desktop_host();
|
|
@@ -18281,6 +18472,7 @@ var init_orchestrator = __esm({
|
|
|
18281
18472
|
init_caffeinate_hold();
|
|
18282
18473
|
init_schedule_runner();
|
|
18283
18474
|
init_coordinator_prompt();
|
|
18475
|
+
LIVE_TURN_SPAWN_GRACE_MS = 15e3;
|
|
18284
18476
|
STALE_AGENT_PID_WAIT_MS = 2500;
|
|
18285
18477
|
Orchestrator = class {
|
|
18286
18478
|
events = new import_node_events.EventEmitter();
|
|
@@ -18337,6 +18529,39 @@ var init_orchestrator = __esm({
|
|
|
18337
18529
|
if (typeof pid === "number" && pid > 0 && isPidAlive(pid)) return false;
|
|
18338
18530
|
return true;
|
|
18339
18531
|
}
|
|
18532
|
+
/**
|
|
18533
|
+
* Whether a child is actually turning — not leftover disk `running` after
|
|
18534
|
+
* the process died. Coordinators were telling users “Agent is running.
|
|
18535
|
+
* Waiting for gate to pass” from stale stillRunning.
|
|
18536
|
+
*/
|
|
18537
|
+
threadLooksLive(thread) {
|
|
18538
|
+
if (thread.status === "queued") {
|
|
18539
|
+
if (this.draining.has(thread.id) || this.startingTurns.has(thread.id)) return true;
|
|
18540
|
+
return thread.queue.length > 0;
|
|
18541
|
+
}
|
|
18542
|
+
if (thread.status !== "running") return false;
|
|
18543
|
+
if (this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id)) return true;
|
|
18544
|
+
const pid = thread.agentPid;
|
|
18545
|
+
if (typeof pid === "number" && pid > 0 && isPidAlive(pid)) return true;
|
|
18546
|
+
const updated = Date.parse(thread.updatedAt ?? "");
|
|
18547
|
+
if (Number.isFinite(updated) && Date.now() - updated < LIVE_TURN_SPAWN_GRACE_MS) return true;
|
|
18548
|
+
return false;
|
|
18549
|
+
}
|
|
18550
|
+
/** Desktop-only: persist idle/stopped when MCP would otherwise keep reporting live. */
|
|
18551
|
+
healStaleReportedActivity(thread) {
|
|
18552
|
+
if (!thisProcessShouldDrainAgentQueues()) return thread;
|
|
18553
|
+
if (this.threadLooksLive(thread)) return thread;
|
|
18554
|
+
if (thread.status === "running") {
|
|
18555
|
+
this.healStaleRunningTurns();
|
|
18556
|
+
return readThread(thread.id) ?? thread;
|
|
18557
|
+
}
|
|
18558
|
+
if (thread.status === "queued" && thread.queue.length === 0 && !this.activeTurns.has(thread.id) && !this.startingTurns.has(thread.id) && !this.draining.has(thread.id)) {
|
|
18559
|
+
setStatus(thread.id, "idle");
|
|
18560
|
+
this.emit({ type: "status_changed", threadId: thread.id, status: "idle" });
|
|
18561
|
+
return readThread(thread.id) ?? thread;
|
|
18562
|
+
}
|
|
18563
|
+
return thread;
|
|
18564
|
+
}
|
|
18340
18565
|
async reconcile(repoPath, opts) {
|
|
18341
18566
|
const reclaimStaleTurns = opts?.reclaimStaleTurns === true;
|
|
18342
18567
|
const drainQueues = opts?.drainQueues !== false;
|
|
@@ -18361,7 +18586,7 @@ var init_orchestrator = __esm({
|
|
|
18361
18586
|
}
|
|
18362
18587
|
continue;
|
|
18363
18588
|
}
|
|
18364
|
-
if (!(0,
|
|
18589
|
+
if (!(0, import_node_fs47.existsSync)(thread.worktreePath)) {
|
|
18365
18590
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
18366
18591
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
18367
18592
|
continue;
|
|
@@ -18671,12 +18896,14 @@ var init_orchestrator = __esm({
|
|
|
18671
18896
|
this.emit({ type: "status_changed", threadId: thread.id, status: thread.status });
|
|
18672
18897
|
return thread;
|
|
18673
18898
|
}
|
|
18674
|
-
async send(threadRef, prompt) {
|
|
18899
|
+
async send(threadRef, prompt, opts) {
|
|
18675
18900
|
const thread = this.requireThread(threadRef);
|
|
18676
18901
|
if (thread.status === "archived") {
|
|
18677
18902
|
throw new Error(`Thread is archived: ${thread.id}`);
|
|
18678
18903
|
}
|
|
18679
|
-
|
|
18904
|
+
const followUp = opts?.followUp === "steer" ? "steer" : "queue";
|
|
18905
|
+
let shouldSteer = false;
|
|
18906
|
+
const sent = await withThreadLock(thread.id, async () => {
|
|
18680
18907
|
const current = this.requireThread(thread.id);
|
|
18681
18908
|
if (current.status === "archived") {
|
|
18682
18909
|
throw new Error(`Thread is archived: ${thread.id}`);
|
|
@@ -18685,6 +18912,7 @@ var init_orchestrator = __esm({
|
|
|
18685
18912
|
this.crashContinued.delete(thread.id);
|
|
18686
18913
|
this.haltDrain.delete(thread.id);
|
|
18687
18914
|
const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id) || current.status === "running";
|
|
18915
|
+
shouldSteer = followUp === "steer" && (inFlight || current.queue.length > 0);
|
|
18688
18916
|
const patch = { queue };
|
|
18689
18917
|
if (!inFlight) patch.status = "queued";
|
|
18690
18918
|
const pid = current.agentPid;
|
|
@@ -18696,16 +18924,20 @@ var init_orchestrator = __esm({
|
|
|
18696
18924
|
if (!inFlight) {
|
|
18697
18925
|
this.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
|
|
18698
18926
|
}
|
|
18699
|
-
if (thisProcessShouldDrainAgentQueues()) {
|
|
18927
|
+
if (thisProcessShouldDrainAgentQueues() && !shouldSteer) {
|
|
18700
18928
|
void this.drainQueue(thread.id);
|
|
18701
18929
|
}
|
|
18702
18930
|
return this.requireThread(thread.id);
|
|
18703
18931
|
});
|
|
18932
|
+
if (shouldSteer && sent.queue.length > 0) {
|
|
18933
|
+
return this.sendQueuedMessageNow(sent.id, sent.queue.length - 1);
|
|
18934
|
+
}
|
|
18935
|
+
return sent;
|
|
18704
18936
|
}
|
|
18705
|
-
async fanOut(threadRefs, prompt) {
|
|
18937
|
+
async fanOut(threadRefs, prompt, opts) {
|
|
18706
18938
|
const results = [];
|
|
18707
18939
|
for (const ref of threadRefs) {
|
|
18708
|
-
results.push(await this.send(ref, prompt));
|
|
18940
|
+
results.push(await this.send(ref, prompt, opts));
|
|
18709
18941
|
}
|
|
18710
18942
|
return results;
|
|
18711
18943
|
}
|
|
@@ -19509,8 +19741,8 @@ var init_orchestrator = __esm({
|
|
|
19509
19741
|
return created;
|
|
19510
19742
|
}
|
|
19511
19743
|
async waitForTurn(threadRef, timeoutMs = 6e5, opts) {
|
|
19512
|
-
const thread = this.requireThread(threadRef);
|
|
19513
|
-
if (!
|
|
19744
|
+
const thread = this.healStaleReportedActivity(this.requireThread(threadRef));
|
|
19745
|
+
if (!this.threadLooksLive(thread)) {
|
|
19514
19746
|
return thread;
|
|
19515
19747
|
}
|
|
19516
19748
|
const start = Date.now();
|
|
@@ -19547,12 +19779,13 @@ var init_orchestrator = __esm({
|
|
|
19547
19779
|
}
|
|
19548
19780
|
});
|
|
19549
19781
|
timer = setInterval(() => {
|
|
19550
|
-
const
|
|
19551
|
-
if (!
|
|
19782
|
+
const raw = readThread(thread.id);
|
|
19783
|
+
if (!raw) {
|
|
19552
19784
|
finish(() => reject(new Error(`Thread not found: ${thread.id}`)));
|
|
19553
19785
|
return;
|
|
19554
19786
|
}
|
|
19555
|
-
|
|
19787
|
+
const current = this.healStaleReportedActivity(raw);
|
|
19788
|
+
if (!this.threadLooksLive(current)) {
|
|
19556
19789
|
finish(() => resolve(current));
|
|
19557
19790
|
return;
|
|
19558
19791
|
}
|
|
@@ -19575,20 +19808,22 @@ var init_orchestrator = __esm({
|
|
|
19575
19808
|
};
|
|
19576
19809
|
}
|
|
19577
19810
|
getTurnResult(threadRef) {
|
|
19578
|
-
const thread = this.requireThread(threadRef);
|
|
19811
|
+
const thread = this.healStaleReportedActivity(this.requireThread(threadRef));
|
|
19579
19812
|
const lastAgent = [...thread.messages].reverse().find((m) => m.role === "agent");
|
|
19580
19813
|
const lastError = thread.lastError ?? null;
|
|
19581
|
-
const
|
|
19582
|
-
const
|
|
19814
|
+
const rawText = (lastAgent?.text ?? "").trim();
|
|
19815
|
+
const text5 = (rawText && !isInternalAgentStatusText(rawText) ? rawText : "") || (thread.status === "error" || thread.status === "stopped" || thread.status === "broken" ? lastError ?? "" : "");
|
|
19816
|
+
const stillRunning = this.threadLooksLive(thread);
|
|
19583
19817
|
const live = stillRunning ? readTurnLive(thread.id) : null;
|
|
19584
|
-
const
|
|
19818
|
+
const liveSummary = live?.summary && !isInternalAgentStatusText(live.summary) ? live.summary : null;
|
|
19819
|
+
const queuedHint = stillRunning && thread.status === "queued" && !liveSummary ? "Queued \u2014 waiting for a concurrency slot" : null;
|
|
19585
19820
|
return {
|
|
19586
19821
|
text: text5,
|
|
19587
19822
|
status: thread.status,
|
|
19588
19823
|
sessionId: thread.sessionId,
|
|
19589
19824
|
lastError,
|
|
19590
19825
|
stillRunning,
|
|
19591
|
-
progress:
|
|
19826
|
+
progress: liveSummary ?? queuedHint,
|
|
19592
19827
|
lastActivityAt: live?.updatedAt ?? null,
|
|
19593
19828
|
usage: lastAgent?.usage ?? null
|
|
19594
19829
|
};
|
|
@@ -19936,7 +20171,14 @@ var init_orchestrator = __esm({
|
|
|
19936
20171
|
);
|
|
19937
20172
|
}
|
|
19938
20173
|
if ((action === "commit-push" || action === "create-draft" || action === "create-web") && thread.worktreePath?.trim() && !await isDirty(thread.worktreePath)) {
|
|
19939
|
-
|
|
20174
|
+
try {
|
|
20175
|
+
await this.pushAndMaybeOpenPr(thread, action);
|
|
20176
|
+
} catch (err) {
|
|
20177
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
20178
|
+
updateThread(thread.id, { lastError: message });
|
|
20179
|
+
this.emit({ type: "error", threadId: thread.id, message });
|
|
20180
|
+
throw err;
|
|
20181
|
+
}
|
|
19940
20182
|
return this.requireThread(threadRef);
|
|
19941
20183
|
}
|
|
19942
20184
|
let prBase;
|
|
@@ -20139,7 +20381,7 @@ var init_orchestrator = __esm({
|
|
|
20139
20381
|
this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
|
|
20140
20382
|
return restored2;
|
|
20141
20383
|
}
|
|
20142
|
-
if (!(0,
|
|
20384
|
+
if (!(0, import_node_fs47.existsSync)(thread.worktreePath)) {
|
|
20143
20385
|
if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
|
|
20144
20386
|
throw new Error(
|
|
20145
20387
|
`Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
|
|
@@ -20151,6 +20393,8 @@ var init_orchestrator = __esm({
|
|
|
20151
20393
|
await withRepoGitLock(thread.repoPath, async () => {
|
|
20152
20394
|
await git(["worktree", "add", dest, thread.branchName], thread.repoPath);
|
|
20153
20395
|
});
|
|
20396
|
+
const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await Promise.resolve().then(() => (init_worktree_exclude(), worktree_exclude_exports));
|
|
20397
|
+
await ensureWorktreeSideboardIgnored2(dest);
|
|
20154
20398
|
void createThreadWorktree2;
|
|
20155
20399
|
void slug;
|
|
20156
20400
|
}
|
|
@@ -20365,7 +20609,10 @@ __export(index_exports, {
|
|
|
20365
20609
|
DEFAULT_ABLETIME_HOST: () => DEFAULT_ABLETIME_HOST,
|
|
20366
20610
|
DEFAULT_WORKTREE_SORT: () => DEFAULT_WORKTREE_SORT,
|
|
20367
20611
|
FAMOUS_SOCCER_TEAMS: () => FAMOUS_SOCCER_TEAMS,
|
|
20612
|
+
FOLLOW_UP_BEHAVIORS: () => FOLLOW_UP_BEHAVIORS,
|
|
20368
20613
|
GITHUB_GIT_AUTH_MODES: () => GITHUB_GIT_AUTH_MODES,
|
|
20614
|
+
GITHUB_PR_BODY_MAX_CHARS: () => GITHUB_PR_BODY_MAX_CHARS,
|
|
20615
|
+
GITHUB_PR_BODY_SAFE_CHARS: () => GITHUB_PR_BODY_SAFE_CHARS,
|
|
20369
20616
|
GLOBAL_WORKSPACE_ID: () => GLOBAL_WORKSPACE_ID,
|
|
20370
20617
|
HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
|
|
20371
20618
|
HOME_BOARD_CACHE_TTL_MS: () => HOME_BOARD_CACHE_TTL_MS,
|
|
@@ -20377,6 +20624,7 @@ __export(index_exports, {
|
|
|
20377
20624
|
LINEAR_OAUTH_PORT: () => LINEAR_OAUTH_PORT,
|
|
20378
20625
|
LINEAR_OAUTH_REDIRECT: () => LINEAR_OAUTH_REDIRECT,
|
|
20379
20626
|
LINEAR_OAUTH_SCOPES: () => LINEAR_OAUTH_SCOPES,
|
|
20627
|
+
LIVE_TURN_SPAWN_GRACE_MS: () => LIVE_TURN_SPAWN_GRACE_MS,
|
|
20380
20628
|
LONG_RUNNING_SKILL_COMMAND: () => LONG_RUNNING_SKILL_COMMAND,
|
|
20381
20629
|
LinearOAuthCancelledError: () => LinearOAuthCancelledError,
|
|
20382
20630
|
MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS: () => MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS,
|
|
@@ -20466,6 +20714,7 @@ __export(index_exports, {
|
|
|
20466
20714
|
buildCodeRefAttachment: () => buildCodeRefAttachment,
|
|
20467
20715
|
buildDiffCommentAttachment: () => buildDiffCommentAttachment,
|
|
20468
20716
|
buildForkTranscriptAttachment: () => buildForkTranscriptAttachment,
|
|
20717
|
+
buildLinearIssueFilter: () => buildLinearIssueFilter,
|
|
20469
20718
|
buildPastedTextAttachment: () => buildPastedTextAttachment,
|
|
20470
20719
|
buildPathRefAttachment: () => buildPathRefAttachment,
|
|
20471
20720
|
buildReviewRequestAttachment: () => buildReviewRequestAttachment,
|
|
@@ -20483,6 +20732,7 @@ __export(index_exports, {
|
|
|
20483
20732
|
checkoutPrStackLayer: () => checkoutPrStackLayer,
|
|
20484
20733
|
childEnvWithAppSettings: () => childEnvWithAppSettings,
|
|
20485
20734
|
claimDesktopHost: () => claimDesktopHost,
|
|
20735
|
+
clampGithubPrBody: () => clampGithubPrBody,
|
|
20486
20736
|
classifyWorktreeColumn: () => classifyWorktreeColumn,
|
|
20487
20737
|
claudeAdapter: () => claudeAdapter,
|
|
20488
20738
|
claudeChromeEnabled: () => claudeChromeEnabled,
|
|
@@ -20587,6 +20837,7 @@ __export(index_exports, {
|
|
|
20587
20837
|
fireSchedule: () => fireSchedule,
|
|
20588
20838
|
flattenTurnInput: () => flattenTurnInput,
|
|
20589
20839
|
flipLinearRelationType: () => flipLinearRelationType,
|
|
20840
|
+
followUpBehavior: () => followUpBehavior,
|
|
20590
20841
|
forkChatTab: () => forkChatTab,
|
|
20591
20842
|
forkMessageSlice: () => forkMessageSlice,
|
|
20592
20843
|
forkThreadWorktree: () => forkThreadWorktree,
|
|
@@ -20665,6 +20916,7 @@ __export(index_exports, {
|
|
|
20665
20916
|
ghRepoSelectArgs: () => ghRepoSelectArgs,
|
|
20666
20917
|
git: () => git,
|
|
20667
20918
|
githubAgentGitEnv: () => githubAgentGitEnv,
|
|
20919
|
+
githubHttpsInsteadOfEntries: () => githubHttpsInsteadOfEntries,
|
|
20668
20920
|
globalAgentCwd: () => globalAgentCwd,
|
|
20669
20921
|
groupHomeBoardWorktrees: () => groupHomeBoardWorktrees,
|
|
20670
20922
|
handleSlackInbound: () => handleSlackInbound,
|
|
@@ -20701,6 +20953,7 @@ __export(index_exports, {
|
|
|
20701
20953
|
isDefaultishSourceRef: () => isDefaultishSourceRef,
|
|
20702
20954
|
isDesktopHostAlive: () => isDesktopHostAlive,
|
|
20703
20955
|
isDirty: () => isDirty,
|
|
20956
|
+
isGhPrBodyTooLongError: () => isGhPrBodyTooLongError,
|
|
20704
20957
|
isGhRateLimitError: () => isGhRateLimitError,
|
|
20705
20958
|
isGlobalRepoPath: () => isGlobalRepoPath,
|
|
20706
20959
|
isGlobalThread: () => isGlobalThread,
|
|
@@ -20708,6 +20961,7 @@ __export(index_exports, {
|
|
|
20708
20961
|
isImageFilePath: () => isImageFilePath,
|
|
20709
20962
|
isInPrStack: () => isInPrStack,
|
|
20710
20963
|
isInboundForThisDesktop: () => isInboundForThisDesktop,
|
|
20964
|
+
isInternalAgentStatusText: () => isInternalAgentStatusText,
|
|
20711
20965
|
isIssueSourceConnected: () => isIssueSourceConnected,
|
|
20712
20966
|
isLinearConnected: () => isLinearConnected,
|
|
20713
20967
|
isLinearOAuthCancelled: () => isLinearOAuthCancelled,
|
|
@@ -20734,6 +20988,7 @@ __export(index_exports, {
|
|
|
20734
20988
|
isThreadRecordFile: () => isThreadRecordFile,
|
|
20735
20989
|
isWorkspaceScratchPath: () => isWorkspaceScratchPath,
|
|
20736
20990
|
issueAttachmentForAbleTimeTask: () => issueAttachmentForAbleTimeTask,
|
|
20991
|
+
issueMatchesAssignee: () => issueMatchesAssignee,
|
|
20737
20992
|
issueSourceLabel: () => issueSourceLabel,
|
|
20738
20993
|
lastRequestOccupancy: () => lastRequestOccupancy,
|
|
20739
20994
|
latestPendingPlanQuestions: () => latestPendingPlanQuestions,
|
|
@@ -20761,6 +21016,7 @@ __export(index_exports, {
|
|
|
20761
21016
|
listLinearAssignedIssues: () => listLinearAssignedIssues,
|
|
20762
21017
|
listLinearIssues: () => listLinearIssues,
|
|
20763
21018
|
listLinearIssuesDirect: () => listLinearIssuesDirect,
|
|
21019
|
+
listLinearIssuesFiltered: () => listLinearIssuesFiltered,
|
|
20764
21020
|
listLinearTeams: () => listLinearTeams,
|
|
20765
21021
|
listModelsForAgent: () => listModelsForAgent,
|
|
20766
21022
|
listOpencodeModels: () => listOpencodeModels,
|
|
@@ -21102,7 +21358,7 @@ async function refreshGitHubAuth() {
|
|
|
21102
21358
|
init_fetch();
|
|
21103
21359
|
|
|
21104
21360
|
// src/integrations/linear-oauth.ts
|
|
21105
|
-
var
|
|
21361
|
+
var import_node_crypto10 = require("crypto");
|
|
21106
21362
|
var import_node_http = require("http");
|
|
21107
21363
|
init_app_settings();
|
|
21108
21364
|
init_fetch();
|
|
@@ -21134,8 +21390,8 @@ function linearOAuthCredentials() {
|
|
|
21134
21390
|
return { clientId, clientSecret };
|
|
21135
21391
|
}
|
|
21136
21392
|
function createLinearPkce() {
|
|
21137
|
-
const verifier = (0,
|
|
21138
|
-
const challenge = (0,
|
|
21393
|
+
const verifier = (0, import_node_crypto10.randomBytes)(32).toString("base64url");
|
|
21394
|
+
const challenge = (0, import_node_crypto10.createHash)("sha256").update(verifier).digest("base64url");
|
|
21139
21395
|
return { verifier, challenge };
|
|
21140
21396
|
}
|
|
21141
21397
|
function linearOAuthAuthorizeUrl(clientId, state, codeChallenge) {
|
|
@@ -21266,7 +21522,7 @@ async function startLinearOAuth(opts) {
|
|
|
21266
21522
|
throw new LinearOAuthCancelledError();
|
|
21267
21523
|
}
|
|
21268
21524
|
const { clientId, clientSecret } = linearOAuthCredentials();
|
|
21269
|
-
const state = (0,
|
|
21525
|
+
const state = (0, import_node_crypto10.randomBytes)(16).toString("hex");
|
|
21270
21526
|
const pkce = createLinearPkce();
|
|
21271
21527
|
const authorizeUrl = linearOAuthAuthorizeUrl(clientId, state, pkce.challenge);
|
|
21272
21528
|
const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
|
|
@@ -21454,6 +21710,22 @@ query SideboardAssignedIssues($first: Int!) {
|
|
|
21454
21710
|
}
|
|
21455
21711
|
}
|
|
21456
21712
|
`;
|
|
21713
|
+
var ISSUES_QUERY = `
|
|
21714
|
+
query SideboardIssues($first: Int!, $filter: IssueFilter) {
|
|
21715
|
+
viewer { id name }
|
|
21716
|
+
issues(first: $first, orderBy: updatedAt, filter: $filter) {
|
|
21717
|
+
nodes { ${LIST_ISSUE_FIELDS} }
|
|
21718
|
+
}
|
|
21719
|
+
}
|
|
21720
|
+
`;
|
|
21721
|
+
var SEARCH_ISSUES_QUERY = `
|
|
21722
|
+
query SideboardSearchIssues($term: String!, $first: Int!, $filter: IssueFilter) {
|
|
21723
|
+
viewer { id name }
|
|
21724
|
+
searchIssues(term: $term, first: $first, includeArchived: false, filter: $filter) {
|
|
21725
|
+
nodes { ${LIST_ISSUE_FIELDS} }
|
|
21726
|
+
}
|
|
21727
|
+
}
|
|
21728
|
+
`;
|
|
21457
21729
|
var TEAMS_QUERY = `
|
|
21458
21730
|
query SideboardTeams {
|
|
21459
21731
|
viewer { id name }
|
|
@@ -21737,19 +22009,76 @@ function normalizePriority(priority) {
|
|
|
21737
22009
|
}
|
|
21738
22010
|
return priority;
|
|
21739
22011
|
}
|
|
21740
|
-
|
|
21741
|
-
|
|
21742
|
-
|
|
22012
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
22013
|
+
function assigneeFilterKey(assignee) {
|
|
22014
|
+
return (assignee ?? "").trim();
|
|
22015
|
+
}
|
|
22016
|
+
function buildLinearIssueFilter(input) {
|
|
22017
|
+
const filter = {
|
|
22018
|
+
state: { type: { nin: ["completed", "canceled"] } }
|
|
22019
|
+
};
|
|
22020
|
+
const raw = assigneeFilterKey(input?.assignee) || "me";
|
|
22021
|
+
const key = raw.toLowerCase();
|
|
22022
|
+
if (key === "all" || key === "*") return filter;
|
|
22023
|
+
if (key === "unassigned" || key === "none" || key === "null") {
|
|
22024
|
+
filter.assignee = { null: true };
|
|
22025
|
+
return filter;
|
|
22026
|
+
}
|
|
22027
|
+
if (key === "me" || key === "@me") {
|
|
22028
|
+
filter.assignee = { isMe: true };
|
|
22029
|
+
return filter;
|
|
22030
|
+
}
|
|
22031
|
+
if (UUID_RE.test(raw)) {
|
|
22032
|
+
filter.assignee = { id: { eq: raw } };
|
|
22033
|
+
return filter;
|
|
22034
|
+
}
|
|
22035
|
+
filter.assignee = { name: { eqIgnoreCase: raw } };
|
|
22036
|
+
return filter;
|
|
22037
|
+
}
|
|
22038
|
+
function isAssignedToMe(assignee) {
|
|
22039
|
+
const key = assignee.toLowerCase();
|
|
22040
|
+
return key === "me" || key === "@me";
|
|
22041
|
+
}
|
|
22042
|
+
function listedLinearIssues(json, nodes) {
|
|
21743
22043
|
return {
|
|
21744
22044
|
viewer: {
|
|
21745
22045
|
id: String(json.viewer?.id ?? ""),
|
|
21746
22046
|
name: String(json.viewer?.name ?? "")
|
|
21747
22047
|
},
|
|
21748
|
-
issues: (
|
|
21749
|
-
(node) => toIssueInfo(mapIssue(node))
|
|
21750
|
-
)
|
|
22048
|
+
issues: (nodes ?? []).map((node) => toIssueInfo(mapIssue(node)))
|
|
21751
22049
|
};
|
|
21752
22050
|
}
|
|
22051
|
+
async function listLinearIssuesFiltered(opts) {
|
|
22052
|
+
const first = Math.max(1, Math.min(250, opts?.limit ?? 200));
|
|
22053
|
+
const query = opts?.query?.trim() ?? "";
|
|
22054
|
+
const assignee = assigneeFilterKey(opts?.assignee) || (query ? "all" : "me");
|
|
22055
|
+
const filter = buildLinearIssueFilter({ assignee });
|
|
22056
|
+
if (query) {
|
|
22057
|
+
const json2 = await linearGraphql(
|
|
22058
|
+
SEARCH_ISSUES_QUERY,
|
|
22059
|
+
{ term: query, first, filter },
|
|
22060
|
+
opts
|
|
22061
|
+
);
|
|
22062
|
+
return listedLinearIssues(json2, json2.searchIssues?.nodes);
|
|
22063
|
+
}
|
|
22064
|
+
if (isAssignedToMe(assignee)) {
|
|
22065
|
+
const json2 = await linearGraphql(
|
|
22066
|
+
ASSIGNED_ISSUES_QUERY,
|
|
22067
|
+
{ first },
|
|
22068
|
+
opts
|
|
22069
|
+
);
|
|
22070
|
+
return listedLinearIssues(json2, json2.viewer?.assignedIssues?.nodes);
|
|
22071
|
+
}
|
|
22072
|
+
const json = await linearGraphql(
|
|
22073
|
+
ISSUES_QUERY,
|
|
22074
|
+
{ first, filter },
|
|
22075
|
+
opts
|
|
22076
|
+
);
|
|
22077
|
+
return listedLinearIssues(json, json.issues?.nodes);
|
|
22078
|
+
}
|
|
22079
|
+
async function listLinearAssignedIssues(opts) {
|
|
22080
|
+
return listLinearIssuesFiltered({ ...opts, assignee: "me" });
|
|
22081
|
+
}
|
|
21753
22082
|
async function listLinearIssuesDirect(opts) {
|
|
21754
22083
|
return (await listLinearAssignedIssues(opts)).issues;
|
|
21755
22084
|
}
|
|
@@ -21877,6 +22206,22 @@ init_worktree();
|
|
|
21877
22206
|
init_run();
|
|
21878
22207
|
init_app_settings();
|
|
21879
22208
|
init_abletime();
|
|
22209
|
+
function assigneeKey(assignee) {
|
|
22210
|
+
return (assignee ?? "").trim().toLowerCase();
|
|
22211
|
+
}
|
|
22212
|
+
function issueMatchesAssignee(issue, assignee, viewerName = "") {
|
|
22213
|
+
const key = assigneeKey(assignee);
|
|
22214
|
+
if (!key || key === "all" || key === "*") return true;
|
|
22215
|
+
const names = [...issue.assignees ?? [], issue.assignee ?? ""].map((name) => name.trim().toLowerCase()).filter(Boolean);
|
|
22216
|
+
if (key === "unassigned" || key === "none" || key === "null") {
|
|
22217
|
+
return names.length === 0;
|
|
22218
|
+
}
|
|
22219
|
+
if (key === "me" || key === "@me") {
|
|
22220
|
+
const me = viewerName.trim().toLowerCase();
|
|
22221
|
+
return Boolean(me && names.includes(me));
|
|
22222
|
+
}
|
|
22223
|
+
return names.includes(key);
|
|
22224
|
+
}
|
|
21880
22225
|
async function listGitHubIssues(repoPath, opts) {
|
|
21881
22226
|
const limit = Math.max(1, Math.min(1e3, opts?.limit ?? 200));
|
|
21882
22227
|
const slug = await resolveGithubRepoSlug(repoPath);
|
|
@@ -21890,6 +22235,17 @@ async function listGitHubIssues(repoPath, opts) {
|
|
|
21890
22235
|
"--state",
|
|
21891
22236
|
"open"
|
|
21892
22237
|
];
|
|
22238
|
+
const query = opts?.query?.trim() ?? "";
|
|
22239
|
+
const assignee = opts?.assignee?.trim() ?? "";
|
|
22240
|
+
const key = assignee.toLowerCase();
|
|
22241
|
+
const searchParts = [];
|
|
22242
|
+
if (query) searchParts.push(query);
|
|
22243
|
+
if (key === "unassigned" || key === "none" || key === "null") {
|
|
22244
|
+
searchParts.push("no:assignee");
|
|
22245
|
+
} else if (key && key !== "all" && key !== "*") {
|
|
22246
|
+
args.push("--assignee", key === "me" || key === "@me" ? "@me" : assignee);
|
|
22247
|
+
}
|
|
22248
|
+
if (searchParts.length) args.push("--search", searchParts.join(" "));
|
|
21893
22249
|
if (slug) args.push("--repo", slug);
|
|
21894
22250
|
const { stdout, exitCode } = await gh(args, repoPath, { reject: false });
|
|
21895
22251
|
if (exitCode !== 0 || !stdout.trim()) return [];
|
|
@@ -21927,14 +22283,20 @@ async function githubViewerLogin(repoPath) {
|
|
|
21927
22283
|
if (exitCode !== 0) return "";
|
|
21928
22284
|
return stdout.trim();
|
|
21929
22285
|
}
|
|
21930
|
-
async function listIssues(repoPath) {
|
|
22286
|
+
async function listIssues(repoPath, opts) {
|
|
21931
22287
|
const settings = loadAppSettings();
|
|
21932
22288
|
const preferredSource = settings.integrations.issueSource ?? "github";
|
|
21933
22289
|
const linearConnected = isLinearConnected(settings);
|
|
21934
22290
|
const abletimeConnected = isAbleTimeConnected(settings);
|
|
21935
22291
|
const source = resolveEffectiveIssueSource(settings);
|
|
22292
|
+
const query = opts?.query?.trim() || void 0;
|
|
22293
|
+
const assignee = opts?.assignee?.trim() || void 0;
|
|
21936
22294
|
if (source === "linear") {
|
|
21937
|
-
const listed = await
|
|
22295
|
+
const listed = await listLinearIssuesFiltered({
|
|
22296
|
+
assignee,
|
|
22297
|
+
query,
|
|
22298
|
+
limit: opts?.limit
|
|
22299
|
+
});
|
|
21938
22300
|
return {
|
|
21939
22301
|
source,
|
|
21940
22302
|
preferredSource,
|
|
@@ -21948,13 +22310,20 @@ async function listIssues(repoPath) {
|
|
|
21948
22310
|
};
|
|
21949
22311
|
}
|
|
21950
22312
|
if (source === "abletime") {
|
|
21951
|
-
const listed = await
|
|
22313
|
+
const [listed, searched] = await Promise.all([
|
|
22314
|
+
listAbleTimeAssignedIssues(),
|
|
22315
|
+
query ? searchAbleTimeTasks(query) : Promise.resolve(null)
|
|
22316
|
+
]);
|
|
22317
|
+
const viewerName = listed.viewer.name ?? listed.viewer.id ?? "";
|
|
22318
|
+
const issues2 = (searched ? searched.map(toAbleTimeIssueInfo) : listed.issues).filter(
|
|
22319
|
+
(issue) => issueMatchesAssignee(issue, assignee, viewerName)
|
|
22320
|
+
);
|
|
21952
22321
|
return {
|
|
21953
22322
|
source,
|
|
21954
22323
|
preferredSource,
|
|
21955
22324
|
linearConnected,
|
|
21956
22325
|
abletimeConnected,
|
|
21957
|
-
issues:
|
|
22326
|
+
issues: issues2,
|
|
21958
22327
|
viewer: {
|
|
21959
22328
|
login: listed.viewer.name,
|
|
21960
22329
|
name: listed.viewer.name
|
|
@@ -21962,7 +22331,7 @@ async function listIssues(repoPath) {
|
|
|
21962
22331
|
};
|
|
21963
22332
|
}
|
|
21964
22333
|
const [issues, login] = await Promise.all([
|
|
21965
|
-
listGitHubIssues(repoPath),
|
|
22334
|
+
listGitHubIssues(repoPath, { assignee, query, limit: opts?.limit }),
|
|
21966
22335
|
githubViewerLogin(repoPath)
|
|
21967
22336
|
]);
|
|
21968
22337
|
return {
|
|
@@ -22182,7 +22551,7 @@ function buildPathRefAttachment(input) {
|
|
|
22182
22551
|
init_stage_files();
|
|
22183
22552
|
|
|
22184
22553
|
// src/composer/pasted-text.ts
|
|
22185
|
-
var
|
|
22554
|
+
var import_node_crypto11 = require("crypto");
|
|
22186
22555
|
var PASTE_ATTACH_MIN_CHARS = 1200;
|
|
22187
22556
|
var PASTE_ATTACH_MIN_LINES = 15;
|
|
22188
22557
|
var PASTED_NAME_RE = /^Pasted text #(\d+)\.txt$/i;
|
|
@@ -22209,7 +22578,7 @@ function nextPastedTextName(existing) {
|
|
|
22209
22578
|
}
|
|
22210
22579
|
function buildPastedTextAttachment(text5, opts) {
|
|
22211
22580
|
return {
|
|
22212
|
-
id: opts?.id ?? (0,
|
|
22581
|
+
id: opts?.id ?? (0, import_node_crypto11.randomUUID)(),
|
|
22213
22582
|
name: opts?.name ?? "Pasted text #1.txt",
|
|
22214
22583
|
kind: "file",
|
|
22215
22584
|
path: opts?.path,
|
|
@@ -22361,8 +22730,8 @@ init_orphan_cleanup();
|
|
|
22361
22730
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
22362
22731
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
22363
22732
|
var import_zod5 = require("zod");
|
|
22364
|
-
var
|
|
22365
|
-
var
|
|
22733
|
+
var import_node_crypto13 = require("crypto");
|
|
22734
|
+
var import_node_path46 = require("path");
|
|
22366
22735
|
init_orchestrator();
|
|
22367
22736
|
init_worktree();
|
|
22368
22737
|
init_create();
|
|
@@ -22404,14 +22773,16 @@ function mcpWaitFinishedHint(status) {
|
|
|
22404
22773
|
}
|
|
22405
22774
|
|
|
22406
22775
|
// src/mcp/server.ts
|
|
22776
|
+
init_message_parts();
|
|
22407
22777
|
init_turn_live();
|
|
22408
22778
|
|
|
22409
22779
|
// src/mcp/thread-visibility.ts
|
|
22780
|
+
init_message_parts();
|
|
22410
22781
|
function lastMessagePreview(messages, max = 160) {
|
|
22411
22782
|
if (!messages?.length) return null;
|
|
22412
22783
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
22413
22784
|
const text5 = messages[i]?.text?.trim();
|
|
22414
|
-
if (!text5) continue;
|
|
22785
|
+
if (!text5 || isInternalAgentStatusText(text5)) continue;
|
|
22415
22786
|
const flat = text5.replace(/\s+/g, " ");
|
|
22416
22787
|
return flat.length > max ? `${flat.slice(0, max)}\u2026` : flat;
|
|
22417
22788
|
}
|
|
@@ -23081,6 +23452,22 @@ function registerLinearTools(server) {
|
|
|
23081
23452
|
}
|
|
23082
23453
|
}
|
|
23083
23454
|
);
|
|
23455
|
+
server.tool(
|
|
23456
|
+
"linear_search_issues",
|
|
23457
|
+
"Search or list open Linear issues. Not limited to the current user \u2014 pass assignee=unassigned for issues with no owner, assignee=all (default when query is set) for anyone including unassigned, assignee=me for yours, or a user id / name. Optional query uses Linear search (title, identifier, description).",
|
|
23458
|
+
{
|
|
23459
|
+
query: import_zod3.z.string().optional().describe("Search text (identifier, title, description). Omit to list by assignee only."),
|
|
23460
|
+
assignee: import_zod3.z.string().optional().describe("me, unassigned, all, a Linear user id, or a display name. Default: all when query is set, otherwise me."),
|
|
23461
|
+
limit: import_zod3.z.number().int().positive().max(250).optional()
|
|
23462
|
+
},
|
|
23463
|
+
async ({ query, assignee, limit }) => {
|
|
23464
|
+
try {
|
|
23465
|
+
return text3(await listLinearIssuesFiltered({ query, assignee, limit }));
|
|
23466
|
+
} catch (err) {
|
|
23467
|
+
return fail3(err);
|
|
23468
|
+
}
|
|
23469
|
+
}
|
|
23470
|
+
);
|
|
23084
23471
|
server.tool(
|
|
23085
23472
|
"linear_get_issue",
|
|
23086
23473
|
"Get a Linear issue by uuid or identifier (ENG-123). Returns description, comments, relations (blocks/blockedBy/related/duplicate), parent/children, project, cycle, labels, and other metadata.",
|
|
@@ -23315,30 +23702,31 @@ function registerScheduleTools(server) {
|
|
|
23315
23702
|
|
|
23316
23703
|
// src/mcp/server.ts
|
|
23317
23704
|
init_agent_git_actions();
|
|
23705
|
+
init_gh_errors();
|
|
23318
23706
|
init_git_auth_mode();
|
|
23319
23707
|
|
|
23320
23708
|
// src/board/load-home-board.ts
|
|
23321
|
-
var
|
|
23322
|
-
var
|
|
23709
|
+
var import_node_fs49 = require("fs");
|
|
23710
|
+
var import_node_path45 = require("path");
|
|
23323
23711
|
init_worktree();
|
|
23324
23712
|
init_paths();
|
|
23325
23713
|
|
|
23326
23714
|
// src/board/board-pins.ts
|
|
23327
|
-
var
|
|
23328
|
-
var
|
|
23329
|
-
var
|
|
23715
|
+
var import_node_crypto12 = require("crypto");
|
|
23716
|
+
var import_node_fs48 = require("fs");
|
|
23717
|
+
var import_node_path44 = require("path");
|
|
23330
23718
|
init_paths();
|
|
23331
23719
|
init_home_board();
|
|
23332
23720
|
var FILE = "home-board-pins.json";
|
|
23333
23721
|
var VERSION = 1;
|
|
23334
23722
|
function pinsFile() {
|
|
23335
|
-
return (0,
|
|
23723
|
+
return (0, import_node_path44.join)(appDataDir(), FILE);
|
|
23336
23724
|
}
|
|
23337
23725
|
function readDisk() {
|
|
23338
23726
|
const path2 = pinsFile();
|
|
23339
|
-
if (!(0,
|
|
23727
|
+
if (!(0, import_node_fs48.existsSync)(path2)) return [];
|
|
23340
23728
|
try {
|
|
23341
|
-
const raw = JSON.parse((0,
|
|
23729
|
+
const raw = JSON.parse((0, import_node_fs48.readFileSync)(path2, "utf8"));
|
|
23342
23730
|
if (raw?.version !== VERSION || !Array.isArray(raw.items)) return [];
|
|
23343
23731
|
return raw.items.filter((item) => item?.id && item.kind && item.ref);
|
|
23344
23732
|
} catch {
|
|
@@ -23346,8 +23734,8 @@ function readDisk() {
|
|
|
23346
23734
|
}
|
|
23347
23735
|
}
|
|
23348
23736
|
function writeDisk(items) {
|
|
23349
|
-
(0,
|
|
23350
|
-
(0,
|
|
23737
|
+
(0, import_node_fs48.mkdirSync)(appDataDir(), { recursive: true });
|
|
23738
|
+
(0, import_node_fs48.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
|
|
23351
23739
|
}
|
|
23352
23740
|
function listBoardPins() {
|
|
23353
23741
|
return readDisk();
|
|
@@ -23356,7 +23744,7 @@ function addBoardPin(input) {
|
|
|
23356
23744
|
const ref = input.ref.trim();
|
|
23357
23745
|
if (!ref) throw new Error("Board item needs a ref");
|
|
23358
23746
|
const pin = {
|
|
23359
|
-
id: (0,
|
|
23747
|
+
id: (0, import_node_crypto12.randomUUID)(),
|
|
23360
23748
|
kind: input.kind,
|
|
23361
23749
|
ref,
|
|
23362
23750
|
repoPath: input.repoPath.trim(),
|
|
@@ -23399,7 +23787,7 @@ function replaceBoardPins(items) {
|
|
|
23399
23787
|
}
|
|
23400
23788
|
function clearBoardPins() {
|
|
23401
23789
|
try {
|
|
23402
|
-
(0,
|
|
23790
|
+
(0, import_node_fs48.unlinkSync)(pinsFile());
|
|
23403
23791
|
} catch {
|
|
23404
23792
|
}
|
|
23405
23793
|
}
|
|
@@ -23416,7 +23804,7 @@ function homeBoardWorkspaceKey(workspaces) {
|
|
|
23416
23804
|
return workspaces.map((w) => w.path).filter(Boolean).sort().join("\n");
|
|
23417
23805
|
}
|
|
23418
23806
|
function cacheFile() {
|
|
23419
|
-
return (0,
|
|
23807
|
+
return (0, import_node_path45.join)(appDataDir(), "home-board-cache.json");
|
|
23420
23808
|
}
|
|
23421
23809
|
function emptyInputs() {
|
|
23422
23810
|
return {
|
|
@@ -23442,9 +23830,9 @@ function shouldCacheHomeBoardInputs(inputs) {
|
|
|
23442
23830
|
}
|
|
23443
23831
|
function readDiskCache() {
|
|
23444
23832
|
const path2 = cacheFile();
|
|
23445
|
-
if (!(0,
|
|
23833
|
+
if (!(0, import_node_fs49.existsSync)(path2)) return null;
|
|
23446
23834
|
try {
|
|
23447
|
-
const raw = JSON.parse((0,
|
|
23835
|
+
const raw = JSON.parse((0, import_node_fs49.readFileSync)(path2, "utf8"));
|
|
23448
23836
|
if (raw?.version !== CACHE_VERSION || typeof raw.fetchedAt !== "number") {
|
|
23449
23837
|
return null;
|
|
23450
23838
|
}
|
|
@@ -23458,14 +23846,14 @@ function readDiskCache() {
|
|
|
23458
23846
|
}
|
|
23459
23847
|
function writeDiskCache(entry) {
|
|
23460
23848
|
try {
|
|
23461
|
-
(0,
|
|
23462
|
-
(0,
|
|
23849
|
+
(0, import_node_fs49.mkdirSync)(appDataDir(), { recursive: true });
|
|
23850
|
+
(0, import_node_fs49.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
|
|
23463
23851
|
} catch {
|
|
23464
23852
|
}
|
|
23465
23853
|
}
|
|
23466
23854
|
function deleteDiskCache() {
|
|
23467
23855
|
try {
|
|
23468
|
-
(0,
|
|
23856
|
+
(0, import_node_fs49.unlinkSync)(cacheFile());
|
|
23469
23857
|
} catch {
|
|
23470
23858
|
}
|
|
23471
23859
|
}
|
|
@@ -23762,13 +24150,13 @@ async function startMcpServer() {
|
|
|
23762
24150
|
async () => {
|
|
23763
24151
|
const threads = orch.getThreads(true);
|
|
23764
24152
|
const lines = threads.map((t) => {
|
|
23765
|
-
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0,
|
|
23766
|
-
const live =
|
|
24153
|
+
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path46.basename)(t.repoPath) || t.repoPath;
|
|
24154
|
+
const live = orch.threadLooksLive(t) ? readTurnLive(t.id) : null;
|
|
23767
24155
|
const parent = t.parentThreadId ? ` parent:${t.parentThreadId.slice(0, 8)}` : "";
|
|
23768
24156
|
const preview = lastMessagePreview(t.messages, 80);
|
|
23769
24157
|
const previewBit = preview ? ` ${preview}` : "";
|
|
23770
24158
|
const err = t.lastError ? ` error:${t.lastError.replace(/\s+/g, " ").slice(0, 60)}` : "";
|
|
23771
|
-
const progress = live?.summary ? ` ${live.summary}` : "";
|
|
24159
|
+
const progress = live?.summary && !isInternalAgentStatusText(live.summary) ? ` ${live.summary}` : "";
|
|
23772
24160
|
return `${t.id.slice(0, 8)} ${t.status.padEnd(9)} ${t.agent.padEnd(8)} ${repo} ${t.sourceType}:${t.sourceRef} ${t.title}${parent}${previewBit}${err} sideboard://thread/${t.id}${t.devPort ? ` http://localhost:${t.devPort}` : ""}${progress}`;
|
|
23773
24161
|
});
|
|
23774
24162
|
return {
|
|
@@ -23830,7 +24218,9 @@ async function startMcpServer() {
|
|
|
23830
24218
|
if (!t) {
|
|
23831
24219
|
return { content: [{ type: "text", text: `Thread not found: ${ref}` }], isError: true };
|
|
23832
24220
|
}
|
|
23833
|
-
const
|
|
24221
|
+
const stillRunning = orch.threadLooksLive(t);
|
|
24222
|
+
const live = stillRunning ? readTurnLive(t.id) : null;
|
|
24223
|
+
const liveSummary = live?.summary && !isInternalAgentStatusText(live.summary) ? live.summary : null;
|
|
23834
24224
|
const spend = orch.getThreadUsage(t.id);
|
|
23835
24225
|
const summary = {
|
|
23836
24226
|
id: t.id,
|
|
@@ -23850,8 +24240,8 @@ async function startMcpServer() {
|
|
|
23850
24240
|
devPort: t.devPort,
|
|
23851
24241
|
prUrl: t.prUrl,
|
|
23852
24242
|
lastError: t.lastError ?? null,
|
|
23853
|
-
stillRunning
|
|
23854
|
-
progress:
|
|
24243
|
+
stillRunning,
|
|
24244
|
+
progress: liveSummary ?? (stillRunning && t.status === "queued" ? "Queued \u2014 waiting for a concurrency slot" : null),
|
|
23855
24245
|
lastActivityAt: live?.updatedAt ?? null,
|
|
23856
24246
|
usage: spend.usage,
|
|
23857
24247
|
lastTurnUsage: spend.lastTurnUsage
|
|
@@ -24132,7 +24522,7 @@ async function startMcpServer() {
|
|
|
24132
24522
|
const ident = issue?.identifier ?? ref.trim();
|
|
24133
24523
|
const attachments = issue ? [
|
|
24134
24524
|
{
|
|
24135
|
-
id: (0,
|
|
24525
|
+
id: (0, import_node_crypto13.randomUUID)(),
|
|
24136
24526
|
name: issue.identifier,
|
|
24137
24527
|
kind: "issue",
|
|
24138
24528
|
content: [
|
|
@@ -24208,7 +24598,7 @@ async function startMcpServer() {
|
|
|
24208
24598
|
);
|
|
24209
24599
|
server.tool(
|
|
24210
24600
|
"wait_for_turn",
|
|
24211
|
-
"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).",
|
|
24601
|
+
"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. stillRunning is the source of truth \u2014 if false, the child is not working (do not say it is waiting for a gate). 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).",
|
|
24212
24602
|
{
|
|
24213
24603
|
ref: import_zod5.z.string(),
|
|
24214
24604
|
timeoutMs: import_zod5.z.number().optional()
|
|
@@ -24400,7 +24790,7 @@ async function startMcpServer() {
|
|
|
24400
24790
|
);
|
|
24401
24791
|
server.tool(
|
|
24402
24792
|
"ask_git",
|
|
24403
|
-
"Commit & push, open a draft PR, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh`
|
|
24793
|
+
"Commit & push, open a draft PR, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty, queues the worktree agent to commit; then wait_for_turn (loop while stillRunning). Pass a worktree thread ref (not the orchestrator). action=merge only when the user explicitly asked to merge that PR. Do not run git or gh from the orchestration cwd. If this tool errors that the GraphQL/PR body is too long, the branch is already pushed \u2014 have the worktree agent retry `gh pr create --body-file` with a short description (GitHub limit 65,536 characters). Do not invent SSH/auth failures from that error.",
|
|
24404
24794
|
{
|
|
24405
24795
|
ref: import_zod5.z.string().describe("Worktree thread id/ref"),
|
|
24406
24796
|
action: import_zod5.z.enum(AGENT_GIT_ACTIONS).describe(
|
|
@@ -24425,8 +24815,26 @@ async function startMcpServer() {
|
|
|
24425
24815
|
]
|
|
24426
24816
|
};
|
|
24427
24817
|
} catch (err) {
|
|
24428
|
-
const
|
|
24429
|
-
|
|
24818
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
24819
|
+
const message = formatGhLandError(raw);
|
|
24820
|
+
return {
|
|
24821
|
+
content: [
|
|
24822
|
+
{
|
|
24823
|
+
type: "text",
|
|
24824
|
+
text: JSON.stringify(
|
|
24825
|
+
{
|
|
24826
|
+
error: true,
|
|
24827
|
+
action,
|
|
24828
|
+
lastError: message,
|
|
24829
|
+
hint: /body is too long/i.test(message) ? "Branch is already pushed. send_to_thread so the worktree agent runs gh pr create --draft -R <origin> --body-file <short.md>. Keep the description short." : void 0
|
|
24830
|
+
},
|
|
24831
|
+
null,
|
|
24832
|
+
2
|
|
24833
|
+
)
|
|
24834
|
+
}
|
|
24835
|
+
],
|
|
24836
|
+
isError: true
|
|
24837
|
+
};
|
|
24430
24838
|
}
|
|
24431
24839
|
}
|
|
24432
24840
|
);
|
|
@@ -24821,11 +25229,15 @@ async function startMcpServer() {
|
|
|
24821
25229
|
);
|
|
24822
25230
|
server.tool(
|
|
24823
25231
|
"list_issues",
|
|
24824
|
-
"List issues from Sideboard Account connections (Linear, AbleTime MCP, or GitHub Issues; falls back to GitHub when the preferred tracker is not connected). Linear/AbleTime are account-wide; GitHub Issues are scoped to repoPath from list_workspaces. When AbleTime is the issue source and work has no ticket, call abletime_ensure_task (or create_thread from the default branch \u2014 Sideboard auto-creates a task to track against). Prefer list_board for Home columns. Then create_thread with sourceType=ticket.",
|
|
24825
|
-
{
|
|
24826
|
-
|
|
25232
|
+
"List or search issues from Sideboard Account connections (Linear, AbleTime MCP, or GitHub Issues; falls back to GitHub when the preferred tracker is not connected). Linear defaults to issues assigned to you; pass assignee=unassigned for no owner, assignee=all for everyone (including unassigned), or a user id / GitHub login. Optional query searches title/identifier. Linear/AbleTime are account-wide; GitHub Issues are scoped to repoPath from list_workspaces. Prefer linear_search_issues when Linear is connected and you need unassigned or other people's tickets. When AbleTime is the issue source and work has no ticket, call abletime_ensure_task (or create_thread from the default branch \u2014 Sideboard auto-creates a task to track against). Prefer list_board for Home columns. Then create_thread with sourceType=ticket.",
|
|
25233
|
+
{
|
|
25234
|
+
repoPath: import_zod5.z.string(),
|
|
25235
|
+
query: import_zod5.z.string().optional().describe("Search title, identifier, or description"),
|
|
25236
|
+
assignee: import_zod5.z.string().optional().describe("me (Linear default), unassigned, all, a user id, or a GitHub login")
|
|
25237
|
+
},
|
|
25238
|
+
async ({ repoPath, query, assignee }) => {
|
|
24827
25239
|
const root = await resolveRepoRoot(repoPath);
|
|
24828
|
-
const result = await listIssues(root);
|
|
25240
|
+
const result = await listIssues(root, { query, assignee });
|
|
24829
25241
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
24830
25242
|
}
|
|
24831
25243
|
);
|
|
@@ -25172,16 +25584,16 @@ init_oauth();
|
|
|
25172
25584
|
init_injected_mcp();
|
|
25173
25585
|
|
|
25174
25586
|
// src/agents/user-mcp-config.ts
|
|
25175
|
-
var
|
|
25176
|
-
var
|
|
25177
|
-
var
|
|
25587
|
+
var import_node_fs50 = require("fs");
|
|
25588
|
+
var import_node_os13 = require("os");
|
|
25589
|
+
var import_node_path47 = require("path");
|
|
25178
25590
|
init_paths();
|
|
25179
25591
|
init_injected_mcp();
|
|
25180
25592
|
function userCursorMcpConfigPath() {
|
|
25181
|
-
return (0,
|
|
25593
|
+
return (0, import_node_path47.join)((0, import_node_os13.homedir)(), ".cursor", "mcp.json");
|
|
25182
25594
|
}
|
|
25183
25595
|
function userClaudeMcpConfigPath() {
|
|
25184
|
-
return (0,
|
|
25596
|
+
return (0, import_node_path47.join)((0, import_node_os13.homedir)(), ".claude.json");
|
|
25185
25597
|
}
|
|
25186
25598
|
function asObject(value) {
|
|
25187
25599
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
@@ -25208,16 +25620,16 @@ function mergeSideboardIntoMcpServersJson(existing, sideboard) {
|
|
|
25208
25620
|
}
|
|
25209
25621
|
function writeMergedMcpServersJson(configPath, sideboard) {
|
|
25210
25622
|
let existing = {};
|
|
25211
|
-
if ((0,
|
|
25623
|
+
if ((0, import_node_fs50.existsSync)(configPath)) {
|
|
25212
25624
|
try {
|
|
25213
|
-
existing = JSON.parse((0,
|
|
25625
|
+
existing = JSON.parse((0, import_node_fs50.readFileSync)(configPath, "utf8"));
|
|
25214
25626
|
} catch {
|
|
25215
25627
|
existing = {};
|
|
25216
25628
|
}
|
|
25217
25629
|
}
|
|
25218
25630
|
const next = mergeSideboardIntoMcpServersJson(existing, sideboard);
|
|
25219
|
-
(0,
|
|
25220
|
-
(0,
|
|
25631
|
+
(0, import_node_fs50.mkdirSync)((0, import_node_path47.dirname)(configPath), { recursive: true });
|
|
25632
|
+
(0, import_node_fs50.writeFileSync)(configPath, `${JSON.stringify(next, null, 2)}
|
|
25221
25633
|
`);
|
|
25222
25634
|
}
|
|
25223
25635
|
function launchFromResolved(server) {
|
|
@@ -25235,7 +25647,7 @@ async function registerPackagedUserMcpClients() {
|
|
|
25235
25647
|
const cursor = userCursorMcpConfigPath();
|
|
25236
25648
|
writeMergedMcpServersJson(cursor, launch);
|
|
25237
25649
|
const claude = userClaudeMcpConfigPath();
|
|
25238
|
-
if ((0,
|
|
25650
|
+
if ((0, import_node_fs50.existsSync)(claude)) {
|
|
25239
25651
|
writeMergedMcpServersJson(claude, launch);
|
|
25240
25652
|
return { cursor, claude };
|
|
25241
25653
|
}
|
|
@@ -25246,7 +25658,7 @@ async function registerPackagedUserMcpClients() {
|
|
|
25246
25658
|
init_workspaces();
|
|
25247
25659
|
|
|
25248
25660
|
// src/slack/oauth.ts
|
|
25249
|
-
var
|
|
25661
|
+
var import_node_crypto14 = require("crypto");
|
|
25250
25662
|
init_app_settings();
|
|
25251
25663
|
init_workspaces();
|
|
25252
25664
|
|
|
@@ -25470,7 +25882,7 @@ async function startSlackOAuth(opts) {
|
|
|
25470
25882
|
throw new SlackOAuthCancelledError();
|
|
25471
25883
|
}
|
|
25472
25884
|
const { clientId } = slackOAuthCredentials();
|
|
25473
|
-
const state = (0,
|
|
25885
|
+
const state = (0, import_node_crypto14.randomBytes)(16).toString("hex");
|
|
25474
25886
|
const authorizeUrl = slackOAuthAuthorizeUrl(clientId, state);
|
|
25475
25887
|
const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
|
|
25476
25888
|
const pollIntervalMs = opts?.pollIntervalMs ?? 400;
|
|
@@ -25752,7 +26164,7 @@ init_workspaces();
|
|
|
25752
26164
|
init_reply_target();
|
|
25753
26165
|
|
|
25754
26166
|
// src/slack/relay-protocol.ts
|
|
25755
|
-
var
|
|
26167
|
+
var import_node_crypto15 = require("crypto");
|
|
25756
26168
|
var SLACK_RELAY_PING_INTERVAL_MS = 2e4;
|
|
25757
26169
|
var SLACK_RELAY_PONG_TIMEOUT_MS = 15e3;
|
|
25758
26170
|
function slackRelaySessionKey(teamId, userId, deviceId) {
|
|
@@ -25762,7 +26174,7 @@ function slackRelayUserKey(teamId, userId) {
|
|
|
25762
26174
|
return `${teamId.trim()}:${userId.trim()}`;
|
|
25763
26175
|
}
|
|
25764
26176
|
function newSlackRelayEventId() {
|
|
25765
|
-
return (0,
|
|
26177
|
+
return (0, import_node_crypto15.randomBytes)(12).toString("hex");
|
|
25766
26178
|
}
|
|
25767
26179
|
function parseSlackRelayClientMessage(raw) {
|
|
25768
26180
|
try {
|
|
@@ -26865,9 +27277,9 @@ var import_node_http3 = require("http");
|
|
|
26865
27277
|
var import_ws3 = require("ws");
|
|
26866
27278
|
|
|
26867
27279
|
// src/slack/relay-static.ts
|
|
26868
|
-
var
|
|
27280
|
+
var import_node_fs51 = require("fs");
|
|
26869
27281
|
var import_promises = require("fs/promises");
|
|
26870
|
-
var
|
|
27282
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
26871
27283
|
var TYPES = {
|
|
26872
27284
|
".css": "text/css; charset=utf-8",
|
|
26873
27285
|
".html": "text/html; charset=utf-8",
|
|
@@ -26898,9 +27310,9 @@ function resolveStaticPath(root, requestUrl) {
|
|
|
26898
27310
|
return null;
|
|
26899
27311
|
}
|
|
26900
27312
|
if (!pathname.startsWith("/") || pathname.includes("\0")) return null;
|
|
26901
|
-
const rootResolved =
|
|
26902
|
-
const candidate =
|
|
26903
|
-
if (candidate !== rootResolved && !candidate.startsWith(rootResolved +
|
|
27313
|
+
const rootResolved = import_node_path48.default.resolve(root);
|
|
27314
|
+
const candidate = import_node_path48.default.resolve(rootResolved, `.${pathname}`);
|
|
27315
|
+
if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path48.default.sep)) {
|
|
26904
27316
|
return null;
|
|
26905
27317
|
}
|
|
26906
27318
|
return candidate;
|
|
@@ -26914,7 +27326,7 @@ async function fileSize(file) {
|
|
|
26914
27326
|
}
|
|
26915
27327
|
}
|
|
26916
27328
|
function sendFile(req, res, file, size) {
|
|
26917
|
-
const ext =
|
|
27329
|
+
const ext = import_node_path48.default.extname(file).toLowerCase();
|
|
26918
27330
|
res.writeHead(200, {
|
|
26919
27331
|
"Content-Type": TYPES[ext] ?? "application/octet-stream",
|
|
26920
27332
|
"Content-Length": size,
|
|
@@ -26924,7 +27336,7 @@ function sendFile(req, res, file, size) {
|
|
|
26924
27336
|
res.end();
|
|
26925
27337
|
return true;
|
|
26926
27338
|
}
|
|
26927
|
-
(0,
|
|
27339
|
+
(0, import_node_fs51.createReadStream)(file).pipe(res);
|
|
26928
27340
|
return true;
|
|
26929
27341
|
}
|
|
26930
27342
|
async function tryServeStatic(req, res, root) {
|
|
@@ -26933,7 +27345,7 @@ async function tryServeStatic(req, res, root) {
|
|
|
26933
27345
|
if (!candidate) return false;
|
|
26934
27346
|
const direct = await fileSize(candidate);
|
|
26935
27347
|
if (direct != null) return sendFile(req, res, candidate, direct);
|
|
26936
|
-
const asIndex =
|
|
27348
|
+
const asIndex = import_node_path48.default.join(candidate, "index.html");
|
|
26937
27349
|
const indexSize = await fileSize(asIndex);
|
|
26938
27350
|
if (indexSize != null) return sendFile(req, res, asIndex, indexSize);
|
|
26939
27351
|
return false;
|
|
@@ -27193,7 +27605,10 @@ init_outbound_watch();
|
|
|
27193
27605
|
DEFAULT_ABLETIME_HOST,
|
|
27194
27606
|
DEFAULT_WORKTREE_SORT,
|
|
27195
27607
|
FAMOUS_SOCCER_TEAMS,
|
|
27608
|
+
FOLLOW_UP_BEHAVIORS,
|
|
27196
27609
|
GITHUB_GIT_AUTH_MODES,
|
|
27610
|
+
GITHUB_PR_BODY_MAX_CHARS,
|
|
27611
|
+
GITHUB_PR_BODY_SAFE_CHARS,
|
|
27197
27612
|
GLOBAL_WORKSPACE_ID,
|
|
27198
27613
|
HARNESS_ENV_KEYS,
|
|
27199
27614
|
HOME_BOARD_CACHE_TTL_MS,
|
|
@@ -27205,6 +27620,7 @@ init_outbound_watch();
|
|
|
27205
27620
|
LINEAR_OAUTH_PORT,
|
|
27206
27621
|
LINEAR_OAUTH_REDIRECT,
|
|
27207
27622
|
LINEAR_OAUTH_SCOPES,
|
|
27623
|
+
LIVE_TURN_SPAWN_GRACE_MS,
|
|
27208
27624
|
LONG_RUNNING_SKILL_COMMAND,
|
|
27209
27625
|
LinearOAuthCancelledError,
|
|
27210
27626
|
MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS,
|
|
@@ -27294,6 +27710,7 @@ init_outbound_watch();
|
|
|
27294
27710
|
buildCodeRefAttachment,
|
|
27295
27711
|
buildDiffCommentAttachment,
|
|
27296
27712
|
buildForkTranscriptAttachment,
|
|
27713
|
+
buildLinearIssueFilter,
|
|
27297
27714
|
buildPastedTextAttachment,
|
|
27298
27715
|
buildPathRefAttachment,
|
|
27299
27716
|
buildReviewRequestAttachment,
|
|
@@ -27311,6 +27728,7 @@ init_outbound_watch();
|
|
|
27311
27728
|
checkoutPrStackLayer,
|
|
27312
27729
|
childEnvWithAppSettings,
|
|
27313
27730
|
claimDesktopHost,
|
|
27731
|
+
clampGithubPrBody,
|
|
27314
27732
|
classifyWorktreeColumn,
|
|
27315
27733
|
claudeAdapter,
|
|
27316
27734
|
claudeChromeEnabled,
|
|
@@ -27415,6 +27833,7 @@ init_outbound_watch();
|
|
|
27415
27833
|
fireSchedule,
|
|
27416
27834
|
flattenTurnInput,
|
|
27417
27835
|
flipLinearRelationType,
|
|
27836
|
+
followUpBehavior,
|
|
27418
27837
|
forkChatTab,
|
|
27419
27838
|
forkMessageSlice,
|
|
27420
27839
|
forkThreadWorktree,
|
|
@@ -27493,6 +27912,7 @@ init_outbound_watch();
|
|
|
27493
27912
|
ghRepoSelectArgs,
|
|
27494
27913
|
git,
|
|
27495
27914
|
githubAgentGitEnv,
|
|
27915
|
+
githubHttpsInsteadOfEntries,
|
|
27496
27916
|
globalAgentCwd,
|
|
27497
27917
|
groupHomeBoardWorktrees,
|
|
27498
27918
|
handleSlackInbound,
|
|
@@ -27529,6 +27949,7 @@ init_outbound_watch();
|
|
|
27529
27949
|
isDefaultishSourceRef,
|
|
27530
27950
|
isDesktopHostAlive,
|
|
27531
27951
|
isDirty,
|
|
27952
|
+
isGhPrBodyTooLongError,
|
|
27532
27953
|
isGhRateLimitError,
|
|
27533
27954
|
isGlobalRepoPath,
|
|
27534
27955
|
isGlobalThread,
|
|
@@ -27536,6 +27957,7 @@ init_outbound_watch();
|
|
|
27536
27957
|
isImageFilePath,
|
|
27537
27958
|
isInPrStack,
|
|
27538
27959
|
isInboundForThisDesktop,
|
|
27960
|
+
isInternalAgentStatusText,
|
|
27539
27961
|
isIssueSourceConnected,
|
|
27540
27962
|
isLinearConnected,
|
|
27541
27963
|
isLinearOAuthCancelled,
|
|
@@ -27562,6 +27984,7 @@ init_outbound_watch();
|
|
|
27562
27984
|
isThreadRecordFile,
|
|
27563
27985
|
isWorkspaceScratchPath,
|
|
27564
27986
|
issueAttachmentForAbleTimeTask,
|
|
27987
|
+
issueMatchesAssignee,
|
|
27565
27988
|
issueSourceLabel,
|
|
27566
27989
|
lastRequestOccupancy,
|
|
27567
27990
|
latestPendingPlanQuestions,
|
|
@@ -27589,6 +28012,7 @@ init_outbound_watch();
|
|
|
27589
28012
|
listLinearAssignedIssues,
|
|
27590
28013
|
listLinearIssues,
|
|
27591
28014
|
listLinearIssuesDirect,
|
|
28015
|
+
listLinearIssuesFiltered,
|
|
27592
28016
|
listLinearTeams,
|
|
27593
28017
|
listModelsForAgent,
|
|
27594
28018
|
listOpencodeModels,
|