@sideboard-ai/core 0.1.149 → 0.1.151
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-V4MTDWXS.js → agents-JAOMXDXN.js} +10 -9
- package/dist/{agents-HSVQ2Z6Y.js → agents-U2JCFXW4.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-N5PM7HGQ.js → chunk-2SDMENAL.js} +1 -1
- package/dist/{chunk-JTPDWTWJ.js → chunk-3JBMACYX.js} +137 -114
- package/dist/{chunk-I77RYPOH.js → chunk-4XNSGDXE.js} +12 -0
- package/dist/{chunk-JDYKQ6OI.js → chunk-6H4TJ5TA.js} +136 -75
- package/dist/{chunk-EGDRPA4B.js → chunk-77MP647F.js} +6 -6
- package/dist/{chunk-KBWND62T.js → chunk-7F4XE6UG.js} +5 -5
- package/dist/{chunk-R4JP32P5.js → chunk-ADCEGG4A.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-KPIYENTF.js → chunk-FNQNJOHY.js} +89 -5
- package/dist/{chunk-ED4UPEJX.js → chunk-G7SIQFBQ.js} +1 -1
- package/dist/{chunk-TZWO7J4W.js → chunk-GCWAAPJ5.js} +115 -54
- package/dist/{chunk-YP3CSOZ6.js → chunk-GE7M3QTE.js} +142 -114
- package/dist/{chunk-LAFA56WD.js → chunk-HEII7W3Q.js} +1 -1
- package/dist/{chunk-3QRGCKYL.js → chunk-HWZWBJWL.js} +2 -2
- package/dist/{chunk-FKOIHGKV.js → chunk-JRH62XC4.js} +5 -1
- package/dist/{chunk-Q5DHVMXB.js → chunk-LZAOX76N.js} +18 -7
- package/dist/{chunk-B3SJXYIJ.js → chunk-NVXVEGGM.js} +1 -1
- package/dist/{chunk-ZVYLEF72.js → chunk-OXOU2FRS.js} +6 -6
- package/dist/chunk-QQKDGPUI.js +63 -0
- package/dist/{chunk-QTUESPAW.js → chunk-RFMQY56R.js} +1 -1
- package/dist/chunk-SYFVUF2C.js +65 -0
- package/dist/{chunk-Q62SDB53.js → chunk-TSCWSAQL.js} +2 -2
- package/dist/{chunk-DVM4ID64.js → chunk-UFHNSFAS.js} +89 -5
- package/dist/{chunk-PTI5H3RK.js → chunk-UIS7BVCX.js} +24 -13
- package/dist/{chunk-VZJVKQHH.js → chunk-WLV7TRMR.js} +1 -1
- package/dist/{chunk-N3VNOFXQ.js → chunk-Y2FNDKHF.js} +4 -4
- 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-LWYUZAXR.js} +6 -5
- package/dist/{coordinator-prompt-5GXGBGEZ.js → coordinator-prompt-ZK5MII7W.js} +6 -5
- package/dist/{global-workspace-OJRXWXEA.js → global-workspace-IB2CCEJF.js} +7 -6
- package/dist/{global-workspace-2SIPM4PW.js → global-workspace-T7RL3XEC.js} +7 -6
- package/dist/index.cjs +1010 -577
- package/dist/index.d.cts +96 -11
- package/dist/index.d.ts +96 -11
- package/dist/index.js +272 -93
- package/dist/mcp/run-stdio.cjs +981 -581
- package/dist/mcp/run-stdio.js +196 -43
- package/dist/{orchestrator-Z2O5OVJA.js → orchestrator-DPTRBKEH.js} +16 -13
- package/dist/{orchestrator-6TXQWBXN.js → orchestrator-Y5MWUU7C.js} +14 -11
- package/dist/{plan-file-6O7G4VPQ.js → plan-file-LSSSQGTQ.js} +2 -2
- package/dist/{plan-file-PHVKUAEE.js → plan-file-OZEBFSGQ.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-VICQYI2N.js} +8 -7
- package/dist/{workspaces-3NUUZTQK.js → workspaces-ZXCUVCZC.js} +8 -7
- package/dist/{worktree-RZRJNHYL.js → worktree-DPIREDFR.js} +5 -4
- package/dist/{worktree-UCWWTVLS.js → worktree-HTUM35NT.js} +5 -4
- package/dist/worktree-exclude-N5X5I422.js +13 -0
- package/dist/worktree-exclude-X54WSOXM.js +11 -0
- package/package.json +1 -1
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -1764,16 +1764,98 @@ var init_path = __esm({
|
|
|
1764
1764
|
}
|
|
1765
1765
|
});
|
|
1766
1766
|
|
|
1767
|
+
// src/git/github-agent-auth.ts
|
|
1768
|
+
function githubAgentAuthDir() {
|
|
1769
|
+
const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
|
|
1770
|
+
if (override) return override;
|
|
1771
|
+
return (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
|
|
1772
|
+
}
|
|
1773
|
+
function githubCredentialStorePath() {
|
|
1774
|
+
return (0, import_node_path12.join)(githubAgentAuthDir(), "git-credentials");
|
|
1775
|
+
}
|
|
1776
|
+
function githubGhConfigDir() {
|
|
1777
|
+
return (0, import_node_path12.join)(githubAgentAuthDir(), "gh");
|
|
1778
|
+
}
|
|
1779
|
+
function writePrivateFile2(file, body) {
|
|
1780
|
+
(0, import_node_fs11.mkdirSync)((0, import_node_path12.dirname)(file), { recursive: true, mode: 448 });
|
|
1781
|
+
try {
|
|
1782
|
+
(0, import_node_fs11.chmodSync)((0, import_node_path12.dirname)(file), 448);
|
|
1783
|
+
} catch {
|
|
1784
|
+
}
|
|
1785
|
+
(0, import_node_fs11.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
|
|
1786
|
+
try {
|
|
1787
|
+
(0, import_node_fs11.chmodSync)(file, 384);
|
|
1788
|
+
} catch {
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
function gitCredentialStoreContents(token) {
|
|
1792
|
+
return `https://x-access-token:${encodeURIComponent(token)}@github.com
|
|
1793
|
+
`;
|
|
1794
|
+
}
|
|
1795
|
+
function ghHostsYml(token, user = "x-access-token") {
|
|
1796
|
+
const u = user.replace(/[^A-Za-z0-9._-]/g, "") || "x-access-token";
|
|
1797
|
+
return [
|
|
1798
|
+
"github.com:",
|
|
1799
|
+
" git_protocol: https",
|
|
1800
|
+
` user: ${u}`,
|
|
1801
|
+
` oauth_token: ${token}`,
|
|
1802
|
+
" users:",
|
|
1803
|
+
` ${u}:`,
|
|
1804
|
+
` oauth_token: ${token}`,
|
|
1805
|
+
""
|
|
1806
|
+
].join("\n");
|
|
1807
|
+
}
|
|
1808
|
+
function materializeGithubAgentAuth(token, user) {
|
|
1809
|
+
const trimmed = token.trim();
|
|
1810
|
+
if (!trimmed) return;
|
|
1811
|
+
const root = githubAgentAuthDir();
|
|
1812
|
+
(0, import_node_fs11.mkdirSync)(root, { recursive: true, mode: 448 });
|
|
1813
|
+
try {
|
|
1814
|
+
(0, import_node_fs11.chmodSync)(root, 448);
|
|
1815
|
+
} catch {
|
|
1816
|
+
}
|
|
1817
|
+
writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
|
|
1818
|
+
const ghDir = githubGhConfigDir();
|
|
1819
|
+
(0, import_node_fs11.mkdirSync)(ghDir, { recursive: true, mode: 448 });
|
|
1820
|
+
writePrivateFile2((0, import_node_path12.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
|
|
1821
|
+
writePrivateFile2((0, import_node_path12.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
|
|
1822
|
+
}
|
|
1823
|
+
function githubAgentAuthReady() {
|
|
1824
|
+
return (0, import_node_fs11.existsSync)(githubCredentialStorePath()) && (0, import_node_fs11.existsSync)((0, import_node_path12.join)(githubGhConfigDir(), "hosts.yml"));
|
|
1825
|
+
}
|
|
1826
|
+
function githubCredentialHelperGitConfig() {
|
|
1827
|
+
const file = githubCredentialStorePath();
|
|
1828
|
+
return [
|
|
1829
|
+
{ key: "credential.helper", value: "" },
|
|
1830
|
+
{ key: "credential.helper", value: `store --file=${file}` }
|
|
1831
|
+
];
|
|
1832
|
+
}
|
|
1833
|
+
function githubGhConfigEnv() {
|
|
1834
|
+
return {
|
|
1835
|
+
GH_CONFIG_DIR: githubGhConfigDir(),
|
|
1836
|
+
GH_PROMPT_DISABLED: "1"
|
|
1837
|
+
};
|
|
1838
|
+
}
|
|
1839
|
+
var import_node_fs11, import_node_os4, import_node_path12;
|
|
1840
|
+
var init_github_agent_auth = __esm({
|
|
1841
|
+
"src/git/github-agent-auth.ts"() {
|
|
1842
|
+
"use strict";
|
|
1843
|
+
import_node_fs11 = require("fs");
|
|
1844
|
+
import_node_os4 = require("os");
|
|
1845
|
+
import_node_path12 = require("path");
|
|
1846
|
+
}
|
|
1847
|
+
});
|
|
1848
|
+
|
|
1767
1849
|
// src/git/stale-lock.ts
|
|
1768
1850
|
function isIndexLockError(text5) {
|
|
1769
1851
|
return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text5);
|
|
1770
1852
|
}
|
|
1771
1853
|
function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
|
|
1772
|
-
const lockPath = (0,
|
|
1854
|
+
const lockPath = (0, import_node_path13.join)(gitDir, "index.lock");
|
|
1773
1855
|
try {
|
|
1774
|
-
if (!(0,
|
|
1775
|
-
if (now - (0,
|
|
1776
|
-
(0,
|
|
1856
|
+
if (!(0, import_node_fs12.existsSync)(lockPath)) return null;
|
|
1857
|
+
if (now - (0, import_node_fs12.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
|
|
1858
|
+
(0, import_node_fs12.unlinkSync)(lockPath);
|
|
1777
1859
|
return lockPath;
|
|
1778
1860
|
} catch {
|
|
1779
1861
|
return null;
|
|
@@ -1788,12 +1870,12 @@ function clearStaleIndexLocks(gitDirs, maxAgeMs = STALE_INDEX_LOCK_MS) {
|
|
|
1788
1870
|
}
|
|
1789
1871
|
return removed;
|
|
1790
1872
|
}
|
|
1791
|
-
var
|
|
1873
|
+
var import_node_fs12, import_node_path13, STALE_INDEX_LOCK_MS;
|
|
1792
1874
|
var init_stale_lock = __esm({
|
|
1793
1875
|
"src/git/stale-lock.ts"() {
|
|
1794
1876
|
"use strict";
|
|
1795
|
-
|
|
1796
|
-
|
|
1877
|
+
import_node_fs12 = require("fs");
|
|
1878
|
+
import_node_path13 = require("path");
|
|
1797
1879
|
STALE_INDEX_LOCK_MS = 2e4;
|
|
1798
1880
|
}
|
|
1799
1881
|
});
|
|
@@ -1890,7 +1972,10 @@ async function gh(args, cwd, opts) {
|
|
|
1890
1972
|
timeoutMs: opts?.timeoutMs,
|
|
1891
1973
|
env: {
|
|
1892
1974
|
GH_PROMPT_DISABLED: "1",
|
|
1893
|
-
GIT_TERMINAL_PROMPT: "0"
|
|
1975
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
1976
|
+
// Isolated hosts.yml uses git_protocol: https so `gh pr create` does not
|
|
1977
|
+
// shell out over SSH when Settings → Git is SSH (ask_git in Electron).
|
|
1978
|
+
...githubAgentAuthReady() ? githubGhConfigEnv() : {}
|
|
1894
1979
|
}
|
|
1895
1980
|
});
|
|
1896
1981
|
}
|
|
@@ -1906,6 +1991,7 @@ var init_run = __esm({
|
|
|
1906
1991
|
"use strict";
|
|
1907
1992
|
import_execa2 = require("execa");
|
|
1908
1993
|
init_path();
|
|
1994
|
+
init_github_agent_auth();
|
|
1909
1995
|
init_stale_lock();
|
|
1910
1996
|
}
|
|
1911
1997
|
});
|
|
@@ -2744,6 +2830,18 @@ var init_worktree_labels = __esm({
|
|
|
2744
2830
|
function isGhRateLimitError(text5) {
|
|
2745
2831
|
return /API rate limit (already )?exceeded/i.test(text5) || /rate limit exceeded/i.test(text5);
|
|
2746
2832
|
}
|
|
2833
|
+
function isGhPrBodyTooLongError(text5) {
|
|
2834
|
+
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(
|
|
2835
|
+
text5
|
|
2836
|
+
);
|
|
2837
|
+
}
|
|
2838
|
+
function clampGithubPrBody(body, max = GITHUB_PR_BODY_SAFE_CHARS) {
|
|
2839
|
+
const t = body.replace(/\s+$/u, "");
|
|
2840
|
+
if (t.length <= max) return t;
|
|
2841
|
+
const note = "\n\n_(truncated to fit GitHub\u2019s PR body limit)_";
|
|
2842
|
+
const keep = Math.max(0, max - note.length);
|
|
2843
|
+
return `${t.slice(0, keep).replace(/\s+$/u, "")}${note}`;
|
|
2844
|
+
}
|
|
2747
2845
|
function formatRateLimitResetHint(resetEpochSec, nowMs = Date.now()) {
|
|
2748
2846
|
const ms = resetEpochSec * 1e3 - nowMs;
|
|
2749
2847
|
if (ms <= 0) return "soon";
|
|
@@ -2754,18 +2852,32 @@ function formatRateLimitResetHint(resetEpochSec, nowMs = Date.now()) {
|
|
|
2754
2852
|
const hours = Math.ceil(mins / 60);
|
|
2755
2853
|
return `in about ${hours} hour${hours === 1 ? "" : "s"}`;
|
|
2756
2854
|
}
|
|
2855
|
+
function omitGhBodyArg(text5) {
|
|
2856
|
+
return text5.replace(
|
|
2857
|
+
/--body(?:-file)?(\s+|=)(?:'[^']*'|"[^"]*"|\S+)/g,
|
|
2858
|
+
"--body <omitted>"
|
|
2859
|
+
);
|
|
2860
|
+
}
|
|
2861
|
+
function capGhErrorText(text5, max = 400) {
|
|
2862
|
+
const t = text5.trim();
|
|
2863
|
+
if (t.length <= max) return t;
|
|
2864
|
+
return `${t.slice(0, max - 1).trimEnd()}\u2026`;
|
|
2865
|
+
}
|
|
2757
2866
|
function extractGhErrorDetail(text5) {
|
|
2758
|
-
const trimmed = text5.trim();
|
|
2867
|
+
const trimmed = omitGhBodyArg(text5.trim());
|
|
2759
2868
|
if (!trimmed) return "";
|
|
2869
|
+
if (isGhPrBodyTooLongError(text5) || isGhPrBodyTooLongError(trimmed)) {
|
|
2870
|
+
return "GraphQL: body is too long (GitHub PR body / request size limit).";
|
|
2871
|
+
}
|
|
2760
2872
|
const graphql = trimmed.match(/\bGraphQL:\s*(.+)$/im);
|
|
2761
|
-
if (graphql?.[1]) return `GraphQL: ${graphql[1].trim()}
|
|
2873
|
+
if (graphql?.[1]) return capGhErrorText(`GraphQL: ${graphql[1].trim()}`);
|
|
2762
2874
|
const http = trimmed.match(/\bHTTP\s+\d{3}:\s*(.+)$/im);
|
|
2763
|
-
if (http?.[1]) return `HTTP: ${http[1].trim()}
|
|
2875
|
+
if (http?.[1]) return capGhErrorText(`HTTP: ${http[1].trim()}`);
|
|
2764
2876
|
const lines = trimmed.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
|
2765
2877
|
if (lines.length > 1 && /^Command failed with exit code/i.test(lines[0])) {
|
|
2766
|
-
return lines.slice(1).join(" ").trim() || lines[0];
|
|
2878
|
+
return capGhErrorText(lines.slice(1).join(" ").trim() || lines[0]);
|
|
2767
2879
|
}
|
|
2768
|
-
return trimmed;
|
|
2880
|
+
return capGhErrorText(trimmed);
|
|
2769
2881
|
}
|
|
2770
2882
|
function formatGhLandError(raw, opts) {
|
|
2771
2883
|
const trimmed = raw.trim();
|
|
@@ -2783,6 +2895,10 @@ function formatGhLandError(raw, opts) {
|
|
|
2783
2895
|
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>.";
|
|
2784
2896
|
return `Could not create the pull request.${hint}`;
|
|
2785
2897
|
}
|
|
2898
|
+
if (isGhPrBodyTooLongError(raw) || isGhPrBodyTooLongError(detail)) {
|
|
2899
|
+
const pushNote = opts?.pushed === false ? "" : " Your branch was already pushed.";
|
|
2900
|
+
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.`;
|
|
2901
|
+
}
|
|
2786
2902
|
if (isGhRateLimitError(raw) || isGhRateLimitError(detail)) {
|
|
2787
2903
|
const when = opts?.resetAt ? ` Try again ${formatRateLimitResetHint(opts.resetAt, opts.nowMs)}.` : " Wait a few minutes and try again.";
|
|
2788
2904
|
const pushNote = opts?.pushed === false ? "" : " Your branch was already pushed.";
|
|
@@ -2803,15 +2919,85 @@ function formatMergePrError(raw) {
|
|
|
2803
2919
|
}
|
|
2804
2920
|
return extractGhErrorDetail(trimmed) || trimmed;
|
|
2805
2921
|
}
|
|
2922
|
+
var GITHUB_PR_BODY_MAX_CHARS, GITHUB_PR_BODY_SAFE_CHARS;
|
|
2806
2923
|
var init_gh_errors = __esm({
|
|
2807
2924
|
"src/git/gh-errors.ts"() {
|
|
2808
2925
|
"use strict";
|
|
2926
|
+
GITHUB_PR_BODY_MAX_CHARS = 65536;
|
|
2927
|
+
GITHUB_PR_BODY_SAFE_CHARS = 6e4;
|
|
2928
|
+
}
|
|
2929
|
+
});
|
|
2930
|
+
|
|
2931
|
+
// src/git/worktree-exclude.ts
|
|
2932
|
+
var worktree_exclude_exports = {};
|
|
2933
|
+
__export(worktree_exclude_exports, {
|
|
2934
|
+
WORKTREE_CONTEXT_EXCLUDE: () => WORKTREE_CONTEXT_EXCLUDE,
|
|
2935
|
+
WORKTREE_SIDEBOARD_EXCLUDE: () => WORKTREE_SIDEBOARD_EXCLUDE,
|
|
2936
|
+
ensureWorktreeSideboardIgnored: () => ensureWorktreeSideboardIgnored
|
|
2937
|
+
});
|
|
2938
|
+
function excludeHasLine(body, ...needles) {
|
|
2939
|
+
return body.split(/\r?\n/).some((line) => needles.includes(line.trim()));
|
|
2940
|
+
}
|
|
2941
|
+
async function ensureWorktreeSideboardIgnored(worktreePath) {
|
|
2942
|
+
if (!worktreePath.trim()) return;
|
|
2943
|
+
const gitDir = await git(["rev-parse", "--absolute-git-dir"], worktreePath, {
|
|
2944
|
+
reject: false,
|
|
2945
|
+
timeoutMs: 5e3
|
|
2946
|
+
});
|
|
2947
|
+
if (gitDir.exitCode !== 0) return;
|
|
2948
|
+
const dir = gitDir.stdout.trim();
|
|
2949
|
+
if (!dir) return;
|
|
2950
|
+
const excludePath = (0, import_node_path14.join)(dir, "info", "exclude");
|
|
2951
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path14.dirname)(excludePath), { recursive: true });
|
|
2952
|
+
let body = "";
|
|
2953
|
+
try {
|
|
2954
|
+
body = (0, import_node_fs13.readFileSync)(excludePath, "utf8");
|
|
2955
|
+
} catch {
|
|
2956
|
+
body = "";
|
|
2957
|
+
}
|
|
2958
|
+
const missing = [];
|
|
2959
|
+
if (!excludeHasLine(body, ".sideboard/", ".sideboard", "/.sideboard/")) {
|
|
2960
|
+
missing.push(WORKTREE_SIDEBOARD_EXCLUDE);
|
|
2961
|
+
}
|
|
2962
|
+
if (!excludeHasLine(body, ".context/", ".context", "/.context/")) {
|
|
2963
|
+
missing.push(WORKTREE_CONTEXT_EXCLUDE);
|
|
2964
|
+
}
|
|
2965
|
+
if (missing.length > 0) {
|
|
2966
|
+
const prefix = body && !body.endsWith("\n") ? `${body}
|
|
2967
|
+
` : body;
|
|
2968
|
+
const header = body.includes(EXCLUDE_COMMENT) ? "" : `${EXCLUDE_COMMENT}
|
|
2969
|
+
`;
|
|
2970
|
+
(0, import_node_fs13.writeFileSync)(excludePath, `${prefix}${header}${missing.join("\n")}
|
|
2971
|
+
`, "utf8");
|
|
2972
|
+
}
|
|
2973
|
+
const listed = await git(["ls-files", "-z", "--", ".sideboard"], worktreePath, {
|
|
2974
|
+
reject: false,
|
|
2975
|
+
timeoutMs: 5e3
|
|
2976
|
+
});
|
|
2977
|
+
if (listed.exitCode !== 0 || !listed.stdout) return;
|
|
2978
|
+
const files = listed.stdout.split("\0").filter(Boolean);
|
|
2979
|
+
if (files.length === 0) return;
|
|
2980
|
+
await git(["update-index", "--skip-worktree", "--", ...files], worktreePath, {
|
|
2981
|
+
reject: false,
|
|
2982
|
+
timeoutMs: 8e3
|
|
2983
|
+
});
|
|
2984
|
+
}
|
|
2985
|
+
var import_node_fs13, import_node_path14, WORKTREE_SIDEBOARD_EXCLUDE, WORKTREE_CONTEXT_EXCLUDE, EXCLUDE_COMMENT;
|
|
2986
|
+
var init_worktree_exclude = __esm({
|
|
2987
|
+
"src/git/worktree-exclude.ts"() {
|
|
2988
|
+
"use strict";
|
|
2989
|
+
import_node_fs13 = require("fs");
|
|
2990
|
+
import_node_path14 = require("path");
|
|
2991
|
+
init_run();
|
|
2992
|
+
WORKTREE_SIDEBOARD_EXCLUDE = ".sideboard/";
|
|
2993
|
+
WORKTREE_CONTEXT_EXCLUDE = ".context/";
|
|
2994
|
+
EXCLUDE_COMMENT = "# Sideboard worktree scratch \u2014 do not commit";
|
|
2809
2995
|
}
|
|
2810
2996
|
});
|
|
2811
2997
|
|
|
2812
2998
|
// src/store/secret-vault.ts
|
|
2813
2999
|
function secretVaultPath() {
|
|
2814
|
-
return (0,
|
|
3000
|
+
return (0, import_node_path15.join)(appDataDir(), "secrets.json");
|
|
2815
3001
|
}
|
|
2816
3002
|
function loadSecretVault() {
|
|
2817
3003
|
const parsed = readSecureJson(secretVaultPath());
|
|
@@ -2870,11 +3056,11 @@ function normalizeVault(raw) {
|
|
|
2870
3056
|
}
|
|
2871
3057
|
return out;
|
|
2872
3058
|
}
|
|
2873
|
-
var
|
|
3059
|
+
var import_node_path15;
|
|
2874
3060
|
var init_secret_vault = __esm({
|
|
2875
3061
|
"src/store/secret-vault.ts"() {
|
|
2876
3062
|
"use strict";
|
|
2877
|
-
|
|
3063
|
+
import_node_path15 = require("path");
|
|
2878
3064
|
init_paths();
|
|
2879
3065
|
init_secure_file();
|
|
2880
3066
|
}
|
|
@@ -2903,6 +3089,7 @@ var init_issue_source_labels = __esm({
|
|
|
2903
3089
|
// src/store/app-settings.ts
|
|
2904
3090
|
var app_settings_exports = {};
|
|
2905
3091
|
__export(app_settings_exports, {
|
|
3092
|
+
FOLLOW_UP_BEHAVIORS: () => FOLLOW_UP_BEHAVIORS,
|
|
2906
3093
|
GITHUB_GIT_AUTH_MODES: () => GITHUB_GIT_AUTH_MODES,
|
|
2907
3094
|
HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
|
|
2908
3095
|
ISSUE_SOURCE_LABELS: () => ISSUE_SOURCE_LABELS,
|
|
@@ -2928,6 +3115,7 @@ __export(app_settings_exports, {
|
|
|
2928
3115
|
disconnectLinearConnection: () => disconnectLinearConnection,
|
|
2929
3116
|
emptyPublicIntegrations: () => emptyPublicIntegrations,
|
|
2930
3117
|
ensureSlackDeviceIdentity: () => ensureSlackDeviceIdentity,
|
|
3118
|
+
followUpBehavior: () => followUpBehavior,
|
|
2931
3119
|
getAbleTimeAccessToken: () => getAbleTimeAccessToken,
|
|
2932
3120
|
getAbleTimeHost: () => getAbleTimeHost,
|
|
2933
3121
|
getDefaultAgent: () => getDefaultAgent,
|
|
@@ -3036,10 +3224,10 @@ function toPublicAppSettings(settings) {
|
|
|
3036
3224
|
};
|
|
3037
3225
|
}
|
|
3038
3226
|
function appSettingsPath() {
|
|
3039
|
-
return (0,
|
|
3227
|
+
return (0, import_node_path16.join)(appDataDir(), "settings.json");
|
|
3040
3228
|
}
|
|
3041
3229
|
function claudeUserSettingsPath() {
|
|
3042
|
-
return (0,
|
|
3230
|
+
return (0, import_node_path16.join)((0, import_node_os5.homedir)(), ".claude", "settings.json");
|
|
3043
3231
|
}
|
|
3044
3232
|
function normalizeClaude(raw) {
|
|
3045
3233
|
if (!raw || typeof raw !== "object") return {};
|
|
@@ -3284,6 +3472,9 @@ function normalizeAdvanced(raw) {
|
|
|
3284
3472
|
if (typeof source.orchestrationQuotaFallbackAgent === "string" && DEFAULT_AGENTS.has(source.orchestrationQuotaFallbackAgent) && source.orchestrationQuotaFallbackAgent !== "brightsy") {
|
|
3285
3473
|
out.orchestrationQuotaFallbackAgent = source.orchestrationQuotaFallbackAgent;
|
|
3286
3474
|
}
|
|
3475
|
+
if (source.followUpBehavior === "queue" || source.followUpBehavior === "steer") {
|
|
3476
|
+
out.followUpBehavior = source.followUpBehavior;
|
|
3477
|
+
}
|
|
3287
3478
|
return out;
|
|
3288
3479
|
}
|
|
3289
3480
|
function normalizeSettings(raw) {
|
|
@@ -3343,10 +3534,10 @@ function normalizeSettings(raw) {
|
|
|
3343
3534
|
}
|
|
3344
3535
|
function readSettingsFile() {
|
|
3345
3536
|
const path = appSettingsPath();
|
|
3346
|
-
if (!(0,
|
|
3537
|
+
if (!(0, import_node_fs14.existsSync)(path)) return { ...EMPTY_SETTINGS };
|
|
3347
3538
|
try {
|
|
3348
3539
|
chmodOwnerOnly(path);
|
|
3349
|
-
const parsed = JSON.parse((0,
|
|
3540
|
+
const parsed = JSON.parse((0, import_node_fs14.readFileSync)(path, "utf8"));
|
|
3350
3541
|
return normalizeSettings(parsed);
|
|
3351
3542
|
} catch {
|
|
3352
3543
|
return { ...EMPTY_SETTINGS };
|
|
@@ -3892,7 +4083,7 @@ function ensureSlackDeviceIdentity(settings = loadAppSettings()) {
|
|
|
3892
4083
|
}
|
|
3893
4084
|
if (!deviceLabel) {
|
|
3894
4085
|
try {
|
|
3895
|
-
deviceLabel = (0,
|
|
4086
|
+
deviceLabel = (0, import_node_os5.hostname)().split(".")[0]?.trim() || "This Mac";
|
|
3896
4087
|
} catch {
|
|
3897
4088
|
deviceLabel = "This Mac";
|
|
3898
4089
|
}
|
|
@@ -3975,6 +4166,9 @@ function updateAdvancedSettings(patch) {
|
|
|
3975
4166
|
if (typeof patch.orchestrationQuotaFallbackAgent === "string" && DEFAULT_AGENTS.has(patch.orchestrationQuotaFallbackAgent) && patch.orchestrationQuotaFallbackAgent !== "brightsy") {
|
|
3976
4167
|
advanced.orchestrationQuotaFallbackAgent = patch.orchestrationQuotaFallbackAgent;
|
|
3977
4168
|
}
|
|
4169
|
+
if (patch.followUpBehavior === "queue" || patch.followUpBehavior === "steer") {
|
|
4170
|
+
advanced.followUpBehavior = patch.followUpBehavior;
|
|
4171
|
+
}
|
|
3978
4172
|
return saveAppSettings({ ...current, advanced });
|
|
3979
4173
|
}
|
|
3980
4174
|
function autoRenameBranchEnabled(settings = loadAppSettings()) {
|
|
@@ -4020,6 +4214,9 @@ function orchestrationQuotaFallbackAgent(settings = loadAppSettings()) {
|
|
|
4020
4214
|
}
|
|
4021
4215
|
return "cursor";
|
|
4022
4216
|
}
|
|
4217
|
+
function followUpBehavior(settings = loadAppSettings()) {
|
|
4218
|
+
return settings.advanced.followUpBehavior === "queue" ? "queue" : "steer";
|
|
4219
|
+
}
|
|
4023
4220
|
function maxConcurrentAgents(settings = loadAppSettings()) {
|
|
4024
4221
|
const n = settings.advanced.maxConcurrent;
|
|
4025
4222
|
if (typeof n === "number" && Number.isFinite(n)) {
|
|
@@ -4107,14 +4304,14 @@ function childEnvWithAppSettings(extra) {
|
|
|
4107
4304
|
function harnessEnvKey(harness) {
|
|
4108
4305
|
return HARNESS_ENV_KEYS[harness];
|
|
4109
4306
|
}
|
|
4110
|
-
var import_node_crypto3,
|
|
4307
|
+
var import_node_crypto3, import_node_fs14, import_node_os5, import_node_path16, 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;
|
|
4111
4308
|
var init_app_settings = __esm({
|
|
4112
4309
|
"src/store/app-settings.ts"() {
|
|
4113
4310
|
"use strict";
|
|
4114
4311
|
import_node_crypto3 = require("crypto");
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4312
|
+
import_node_fs14 = require("fs");
|
|
4313
|
+
import_node_os5 = require("os");
|
|
4314
|
+
import_node_path16 = require("path");
|
|
4118
4315
|
init_thinking_effort();
|
|
4119
4316
|
init_nested_electron_env();
|
|
4120
4317
|
init_paths();
|
|
@@ -4136,6 +4333,7 @@ var init_app_settings = __esm({
|
|
|
4136
4333
|
"cursor"
|
|
4137
4334
|
]);
|
|
4138
4335
|
GITHUB_GIT_AUTH_MODES = ["auto", "gh", "ssh", "token"];
|
|
4336
|
+
FOLLOW_UP_BEHAVIORS = ["steer", "queue"];
|
|
4139
4337
|
CLOUD_CONNECT_AGENTS = /* @__PURE__ */ new Set([
|
|
4140
4338
|
"claude",
|
|
4141
4339
|
"codex",
|
|
@@ -4163,89 +4361,26 @@ var init_app_settings = __esm({
|
|
|
4163
4361
|
}
|
|
4164
4362
|
});
|
|
4165
4363
|
|
|
4166
|
-
// src/git/
|
|
4167
|
-
function
|
|
4168
|
-
const
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
}
|
|
4175
|
-
|
|
4176
|
-
return (0, import_node_path15.join)(githubAgentAuthDir(), "gh");
|
|
4177
|
-
}
|
|
4178
|
-
function writePrivateFile2(file, body) {
|
|
4179
|
-
(0, import_node_fs13.mkdirSync)((0, import_node_path15.dirname)(file), { recursive: true, mode: 448 });
|
|
4180
|
-
try {
|
|
4181
|
-
(0, import_node_fs13.chmodSync)((0, import_node_path15.dirname)(file), 448);
|
|
4182
|
-
} catch {
|
|
4183
|
-
}
|
|
4184
|
-
(0, import_node_fs13.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
|
|
4185
|
-
try {
|
|
4186
|
-
(0, import_node_fs13.chmodSync)(file, 384);
|
|
4187
|
-
} catch {
|
|
4364
|
+
// src/git/git-auth-mode.ts
|
|
4365
|
+
function githubHttpsInsteadOfEntries(remoteUrl) {
|
|
4366
|
+
const entries = [...HTTPS_REWRITE];
|
|
4367
|
+
const url = remoteUrl?.trim() ?? "";
|
|
4368
|
+
const scpAlias = url.match(/^(git@github\.com-[^:]+):/i);
|
|
4369
|
+
if (scpAlias?.[1]) {
|
|
4370
|
+
entries.push({
|
|
4371
|
+
key: "url.https://github.com/.insteadOf",
|
|
4372
|
+
value: `${scpAlias[1]}:`
|
|
4373
|
+
});
|
|
4188
4374
|
}
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
}
|
|
4194
|
-
|
|
4195
|
-
const u = user.replace(/[^A-Za-z0-9._-]/g, "") || "x-access-token";
|
|
4196
|
-
return [
|
|
4197
|
-
"github.com:",
|
|
4198
|
-
" git_protocol: https",
|
|
4199
|
-
` user: ${u}`,
|
|
4200
|
-
` oauth_token: ${token}`,
|
|
4201
|
-
" users:",
|
|
4202
|
-
` ${u}:`,
|
|
4203
|
-
` oauth_token: ${token}`,
|
|
4204
|
-
""
|
|
4205
|
-
].join("\n");
|
|
4206
|
-
}
|
|
4207
|
-
function materializeGithubAgentAuth(token, user) {
|
|
4208
|
-
const trimmed = token.trim();
|
|
4209
|
-
if (!trimmed) return;
|
|
4210
|
-
const root = githubAgentAuthDir();
|
|
4211
|
-
(0, import_node_fs13.mkdirSync)(root, { recursive: true, mode: 448 });
|
|
4212
|
-
try {
|
|
4213
|
-
(0, import_node_fs13.chmodSync)(root, 448);
|
|
4214
|
-
} catch {
|
|
4375
|
+
const sshAlias = url.match(/^ssh:\/\/git@(github\.com-[^/]+)\//i);
|
|
4376
|
+
if (sshAlias?.[1]) {
|
|
4377
|
+
entries.push({
|
|
4378
|
+
key: "url.https://github.com/.insteadOf",
|
|
4379
|
+
value: `ssh://git@${sshAlias[1]}/`
|
|
4380
|
+
});
|
|
4215
4381
|
}
|
|
4216
|
-
|
|
4217
|
-
const ghDir = githubGhConfigDir();
|
|
4218
|
-
(0, import_node_fs13.mkdirSync)(ghDir, { recursive: true, mode: 448 });
|
|
4219
|
-
writePrivateFile2((0, import_node_path15.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
|
|
4220
|
-
writePrivateFile2((0, import_node_path15.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
|
|
4221
|
-
}
|
|
4222
|
-
function githubAgentAuthReady() {
|
|
4223
|
-
return (0, import_node_fs13.existsSync)(githubCredentialStorePath()) && (0, import_node_fs13.existsSync)((0, import_node_path15.join)(githubGhConfigDir(), "hosts.yml"));
|
|
4224
|
-
}
|
|
4225
|
-
function githubCredentialHelperGitConfig() {
|
|
4226
|
-
const file = githubCredentialStorePath();
|
|
4227
|
-
return [
|
|
4228
|
-
{ key: "credential.helper", value: "" },
|
|
4229
|
-
{ key: "credential.helper", value: `store --file=${file}` }
|
|
4230
|
-
];
|
|
4231
|
-
}
|
|
4232
|
-
function githubGhConfigEnv() {
|
|
4233
|
-
return {
|
|
4234
|
-
GH_CONFIG_DIR: githubGhConfigDir(),
|
|
4235
|
-
GH_PROMPT_DISABLED: "1"
|
|
4236
|
-
};
|
|
4382
|
+
return entries;
|
|
4237
4383
|
}
|
|
4238
|
-
var import_node_fs13, import_node_os5, import_node_path15;
|
|
4239
|
-
var init_github_agent_auth = __esm({
|
|
4240
|
-
"src/git/github-agent-auth.ts"() {
|
|
4241
|
-
"use strict";
|
|
4242
|
-
import_node_fs13 = require("fs");
|
|
4243
|
-
import_node_os5 = require("os");
|
|
4244
|
-
import_node_path15 = require("path");
|
|
4245
|
-
}
|
|
4246
|
-
});
|
|
4247
|
-
|
|
4248
|
-
// src/git/git-auth-mode.ts
|
|
4249
4384
|
function nonInteractiveGitProcessEnv() {
|
|
4250
4385
|
return {
|
|
4251
4386
|
GIT_TERMINAL_PROMPT: "0",
|
|
@@ -4268,16 +4403,19 @@ function appendIndexedGitConfig(existing, entries) {
|
|
|
4268
4403
|
out.GIT_CONFIG_COUNT = String(count + entries.length);
|
|
4269
4404
|
return out;
|
|
4270
4405
|
}
|
|
4271
|
-
function githubAgentGitEnv(existing) {
|
|
4406
|
+
function githubAgentGitEnv(existing, opts) {
|
|
4272
4407
|
const helpers = githubAgentAuthReady() ? githubCredentialHelperGitConfig() : [{ key: "credential.helper", value: "" }];
|
|
4273
|
-
return appendIndexedGitConfig(existing, [
|
|
4408
|
+
return appendIndexedGitConfig(existing, [
|
|
4409
|
+
...githubHttpsInsteadOfEntries(opts?.remoteUrl),
|
|
4410
|
+
...helpers
|
|
4411
|
+
]);
|
|
4274
4412
|
}
|
|
4275
4413
|
function applyGithubGitAuthEnv(existing, opts) {
|
|
4276
4414
|
const out = { ...nonInteractiveGitProcessEnv() };
|
|
4277
4415
|
const token = opts.token?.trim() || existing?.GH_TOKEN?.trim() || "" || "";
|
|
4278
4416
|
if (token) materializeGithubAgentAuth(token);
|
|
4279
4417
|
Object.assign(out, githubGhConfigEnv());
|
|
4280
|
-
if (opts.mode === "ssh") return out;
|
|
4418
|
+
if (opts.mode === "ssh" && !token) return out;
|
|
4281
4419
|
Object.assign(out, githubAgentGitEnv(existing));
|
|
4282
4420
|
return out;
|
|
4283
4421
|
}
|
|
@@ -4333,7 +4471,7 @@ async function warmGithubAgentAuth(opts) {
|
|
|
4333
4471
|
}
|
|
4334
4472
|
function normalizeWritableRoot(raw) {
|
|
4335
4473
|
const trimmed = raw.trim().replace(/\/+$/, "");
|
|
4336
|
-
return trimmed && (0,
|
|
4474
|
+
return trimmed && (0, import_node_path17.isAbsolute)(trimmed) ? trimmed : null;
|
|
4337
4475
|
}
|
|
4338
4476
|
async function resolveCodexGitWritableRoots(cwd) {
|
|
4339
4477
|
const roots = /* @__PURE__ */ new Set();
|
|
@@ -4390,8 +4528,9 @@ function formatGitAuthModeDirective(mode) {
|
|
|
4390
4528
|
case "ssh":
|
|
4391
4529
|
return [
|
|
4392
4530
|
"Git authentication (Settings \u2192 Git mode: SSH):",
|
|
4393
|
-
"-
|
|
4394
|
-
"-
|
|
4531
|
+
"- Stored remotes stay SSH (`git@github.com:\u2026`). Do not `git remote set-url` or rewrite them to HTTPS.",
|
|
4532
|
+
"- 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.",
|
|
4533
|
+
"- 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).",
|
|
4395
4534
|
"- `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.",
|
|
4396
4535
|
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
4397
4536
|
].join("\n");
|
|
@@ -4410,11 +4549,11 @@ function formatGitAuthModeDirective(mode) {
|
|
|
4410
4549
|
].join("\n");
|
|
4411
4550
|
}
|
|
4412
4551
|
}
|
|
4413
|
-
var
|
|
4552
|
+
var import_node_path17, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
|
|
4414
4553
|
var init_git_auth_mode = __esm({
|
|
4415
4554
|
"src/git/git-auth-mode.ts"() {
|
|
4416
4555
|
"use strict";
|
|
4417
|
-
|
|
4556
|
+
import_node_path17 = require("path");
|
|
4418
4557
|
init_app_settings();
|
|
4419
4558
|
init_github_agent_auth();
|
|
4420
4559
|
init_run();
|
|
@@ -4762,7 +4901,7 @@ function attachmentsGitignoreBody() {
|
|
|
4762
4901
|
}
|
|
4763
4902
|
function isWorkspaceScratchPath(relativePath) {
|
|
4764
4903
|
const p = relativePath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
|
|
4765
|
-
return p === ATTACHMENTS_DIR || p.startsWith(`${ATTACHMENTS_DIR}/`) || p === LEGACY_ATTACHMENTS_DIR || p.startsWith(`${LEGACY_ATTACHMENTS_DIR}/`) || p === ".context" || p.startsWith(".context/");
|
|
4904
|
+
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/");
|
|
4766
4905
|
}
|
|
4767
4906
|
var ATTACHMENTS_DIR, LEGACY_ATTACHMENTS_DIR, ATTACHMENTS_GITIGNORE;
|
|
4768
4907
|
var init_workspace_scratch = __esm({
|
|
@@ -4869,7 +5008,7 @@ async function resolveRepoRoot(cwd) {
|
|
|
4869
5008
|
}
|
|
4870
5009
|
function canonicalizeRepoPath(path) {
|
|
4871
5010
|
try {
|
|
4872
|
-
return (0,
|
|
5011
|
+
return (0, import_node_fs15.realpathSync)(path);
|
|
4873
5012
|
} catch {
|
|
4874
5013
|
return path.replace(/\/+$/, "");
|
|
4875
5014
|
}
|
|
@@ -5608,6 +5747,16 @@ function originFetchBranch(sourceRef) {
|
|
|
5608
5747
|
if (ref.startsWith("origin/")) return ref.slice("origin/".length) || null;
|
|
5609
5748
|
return ref;
|
|
5610
5749
|
}
|
|
5750
|
+
async function originRemoteUrl(cwd) {
|
|
5751
|
+
const result = await git(["remote", "get-url", "origin"], cwd, { reject: false });
|
|
5752
|
+
return result.exitCode === 0 ? result.stdout.trim() : "";
|
|
5753
|
+
}
|
|
5754
|
+
function githubHttpsRetryEnv(remoteUrl) {
|
|
5755
|
+
return {
|
|
5756
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
5757
|
+
...githubAgentGitEnv(void 0, { remoteUrl })
|
|
5758
|
+
};
|
|
5759
|
+
}
|
|
5611
5760
|
async function fetchOriginWithAuth(repoPath, args, timeoutMs) {
|
|
5612
5761
|
const first = await git(args, repoPath, { reject: false, timeoutMs });
|
|
5613
5762
|
if (first.exitCode === 0) return true;
|
|
@@ -5617,15 +5766,14 @@ async function fetchOriginWithAuth(repoPath, args, timeoutMs) {
|
|
|
5617
5766
|
} catch {
|
|
5618
5767
|
return false;
|
|
5619
5768
|
}
|
|
5620
|
-
if (mode === "ssh") return false;
|
|
5621
5769
|
const token = await resolveGithubAgentToken(mode, repoPath);
|
|
5622
5770
|
if (!token) return false;
|
|
5771
|
+
const remoteUrl = await originRemoteUrl(repoPath);
|
|
5623
5772
|
const tryHttps = async (header) => git(args, repoPath, {
|
|
5624
5773
|
reject: false,
|
|
5625
5774
|
timeoutMs,
|
|
5626
|
-
env:
|
|
5775
|
+
env: githubHttpsRetryEnv(remoteUrl),
|
|
5627
5776
|
config: {
|
|
5628
|
-
"url.https://github.com/.insteadOf": "git@github.com:",
|
|
5629
5777
|
"http.extraHeader": header
|
|
5630
5778
|
}
|
|
5631
5779
|
});
|
|
@@ -5707,8 +5855,8 @@ async function refreshOriginAndMaybeFastForwardMain(repoPath, sourceRef) {
|
|
|
5707
5855
|
}
|
|
5708
5856
|
async function createThreadWorktree(opts) {
|
|
5709
5857
|
let branchName = `thread/${opts.slug}`;
|
|
5710
|
-
const worktreePath = (0,
|
|
5711
|
-
if ((0,
|
|
5858
|
+
const worktreePath = (0, import_node_path18.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
5859
|
+
if ((0, import_node_fs15.existsSync)(worktreePath)) {
|
|
5712
5860
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
5713
5861
|
}
|
|
5714
5862
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -5743,13 +5891,14 @@ ${add.stdout}`;
|
|
|
5743
5891
|
});
|
|
5744
5892
|
branchName = added;
|
|
5745
5893
|
await ensureGhPreferOrigin(worktreePath);
|
|
5894
|
+
await ensureWorktreeSideboardIgnored(worktreePath);
|
|
5746
5895
|
return { branchName, worktreePath };
|
|
5747
5896
|
}
|
|
5748
5897
|
async function createExistingBranchWorktree(opts) {
|
|
5749
5898
|
const branchName = opts.branchName.trim();
|
|
5750
5899
|
if (!branchName) throw new Error("branch name required");
|
|
5751
|
-
const worktreePath = (0,
|
|
5752
|
-
if ((0,
|
|
5900
|
+
const worktreePath = (0, import_node_path18.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
5901
|
+
if ((0, import_node_fs15.existsSync)(worktreePath)) {
|
|
5753
5902
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
5754
5903
|
}
|
|
5755
5904
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -5787,6 +5936,7 @@ async function createExistingBranchWorktree(opts) {
|
|
|
5787
5936
|
await git(["checkout", "-B", branchName], worktreePath, { reject: false });
|
|
5788
5937
|
}
|
|
5789
5938
|
await ensureGhPreferOrigin(worktreePath);
|
|
5939
|
+
await ensureWorktreeSideboardIgnored(worktreePath);
|
|
5790
5940
|
return { branchName, worktreePath };
|
|
5791
5941
|
}
|
|
5792
5942
|
async function removeWorktree(repoPath, worktreePath, opts) {
|
|
@@ -5875,7 +6025,9 @@ async function currentBranch(worktreePath) {
|
|
|
5875
6025
|
async function commitAll(worktreePath, message) {
|
|
5876
6026
|
const dirty = await isDirty(worktreePath);
|
|
5877
6027
|
if (!dirty) return false;
|
|
6028
|
+
await ensureWorktreeSideboardIgnored(worktreePath);
|
|
5878
6029
|
await git(["add", "-A"], worktreePath);
|
|
6030
|
+
await git(["reset", "-q", "--", ".sideboard"], worktreePath, { reject: false });
|
|
5879
6031
|
await git(["commit", "-m", message], worktreePath);
|
|
5880
6032
|
return true;
|
|
5881
6033
|
}
|
|
@@ -5889,14 +6041,14 @@ async function pushBranch(worktreePath, branchName) {
|
|
|
5889
6041
|
const token = await resolveGithubAgentToken(getGithubGitAuthMode(), worktreePath);
|
|
5890
6042
|
if (!slug || !token) {
|
|
5891
6043
|
throw new Error(
|
|
5892
|
-
sshErr || `git push origin ${branchName} failed` + (!token ? " (
|
|
6044
|
+
sshErr || `git push origin ${branchName} failed` + (!token ? " (SSH remote and gh auth token unavailable \u2014 unlock ssh-agent or run: gh auth login)" : "")
|
|
5893
6045
|
);
|
|
5894
6046
|
}
|
|
6047
|
+
const remoteUrl = await originRemoteUrl(worktreePath);
|
|
5895
6048
|
const tryHttps = async (header) => git(["push", "-u", "origin", branchName], worktreePath, {
|
|
5896
6049
|
reject: false,
|
|
5897
|
-
env:
|
|
6050
|
+
env: githubHttpsRetryEnv(remoteUrl),
|
|
5898
6051
|
config: {
|
|
5899
|
-
"url.https://github.com/.insteadOf": "git@github.com:",
|
|
5900
6052
|
"http.extraHeader": header
|
|
5901
6053
|
}
|
|
5902
6054
|
});
|
|
@@ -6026,6 +6178,32 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
6026
6178
|
const repoArgs = ghRepoSelectArgs(slug);
|
|
6027
6179
|
const headRef = ghHeadRef(slug, opts.head);
|
|
6028
6180
|
const branchOnly = opts.head.trim().replace(/^refs\/heads\//, "");
|
|
6181
|
+
const bodyText = clampGithubPrBody(opts.body ?? opts.title);
|
|
6182
|
+
const bodyFile = (0, import_node_path18.join)(
|
|
6183
|
+
(0, import_node_os6.tmpdir)(),
|
|
6184
|
+
`sideboard-pr-body-${process.pid}-${(0, import_node_crypto4.randomBytes)(6).toString("hex")}.md`
|
|
6185
|
+
);
|
|
6186
|
+
(0, import_node_fs15.writeFileSync)(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
|
|
6187
|
+
`, "utf8");
|
|
6188
|
+
const bodyArgs = ["--body-file", bodyFile];
|
|
6189
|
+
try {
|
|
6190
|
+
return await createOrUpdatePrWithBodyFile(worktreePath, {
|
|
6191
|
+
...opts,
|
|
6192
|
+
slug,
|
|
6193
|
+
repoArgs,
|
|
6194
|
+
headRef,
|
|
6195
|
+
branchOnly,
|
|
6196
|
+
bodyArgs
|
|
6197
|
+
});
|
|
6198
|
+
} finally {
|
|
6199
|
+
try {
|
|
6200
|
+
(0, import_node_fs15.unlinkSync)(bodyFile);
|
|
6201
|
+
} catch {
|
|
6202
|
+
}
|
|
6203
|
+
}
|
|
6204
|
+
}
|
|
6205
|
+
async function createOrUpdatePrWithBodyFile(worktreePath, opts) {
|
|
6206
|
+
const { slug, repoArgs, headRef, branchOnly, bodyArgs } = opts;
|
|
6029
6207
|
const existing = await gh(
|
|
6030
6208
|
[...repoArgs, "pr", "view", branchOnly, "--json", "url", "--jq", ".url"],
|
|
6031
6209
|
worktreePath,
|
|
@@ -6041,8 +6219,7 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
6041
6219
|
branchOnly,
|
|
6042
6220
|
"--title",
|
|
6043
6221
|
opts.title,
|
|
6044
|
-
|
|
6045
|
-
opts.body ?? opts.title
|
|
6222
|
+
...bodyArgs
|
|
6046
6223
|
],
|
|
6047
6224
|
worktreePath,
|
|
6048
6225
|
{ reject: false }
|
|
@@ -6057,8 +6234,7 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
6057
6234
|
"--web",
|
|
6058
6235
|
"--title",
|
|
6059
6236
|
opts.title,
|
|
6060
|
-
|
|
6061
|
-
opts.body ?? opts.title,
|
|
6237
|
+
...bodyArgs,
|
|
6062
6238
|
"--base",
|
|
6063
6239
|
opts.base,
|
|
6064
6240
|
"--head",
|
|
@@ -6079,8 +6255,7 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
6079
6255
|
"create",
|
|
6080
6256
|
"--title",
|
|
6081
6257
|
opts.title,
|
|
6082
|
-
|
|
6083
|
-
opts.body ?? opts.title,
|
|
6258
|
+
...bodyArgs,
|
|
6084
6259
|
"--base",
|
|
6085
6260
|
opts.base,
|
|
6086
6261
|
"--head",
|
|
@@ -6104,10 +6279,10 @@ function sameRepoPath(a, b) {
|
|
|
6104
6279
|
return normalizeWorktreePath(a) === normalizeWorktreePath(b);
|
|
6105
6280
|
}
|
|
6106
6281
|
function listLocalThreadBranchSlugs(repoPath) {
|
|
6107
|
-
const refsDir = (0,
|
|
6108
|
-
if (!(0,
|
|
6282
|
+
const refsDir = (0, import_node_path18.join)(repoPath, ".git", "refs", "heads", "thread");
|
|
6283
|
+
if (!(0, import_node_fs15.existsSync)(refsDir)) return [];
|
|
6109
6284
|
try {
|
|
6110
|
-
return (0,
|
|
6285
|
+
return (0, import_node_fs15.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
|
|
6111
6286
|
} catch {
|
|
6112
6287
|
return [];
|
|
6113
6288
|
}
|
|
@@ -6115,8 +6290,8 @@ function listLocalThreadBranchSlugs(repoPath) {
|
|
|
6115
6290
|
function collectTakenTeamSlugs(repoPath) {
|
|
6116
6291
|
const taken = /* @__PURE__ */ new Set();
|
|
6117
6292
|
const root = worktreesRoot(repoPath);
|
|
6118
|
-
if ((0,
|
|
6119
|
-
for (const entry of (0,
|
|
6293
|
+
if ((0, import_node_fs15.existsSync)(root)) {
|
|
6294
|
+
for (const entry of (0, import_node_fs15.readdirSync)(root, { withFileTypes: true })) {
|
|
6120
6295
|
if (entry.isDirectory() && entry.name !== ".DS_Store") {
|
|
6121
6296
|
taken.add(normalizeTakenSlug(entry.name));
|
|
6122
6297
|
}
|
|
@@ -6137,23 +6312,26 @@ function allocateTeamSlug(repoPath) {
|
|
|
6137
6312
|
const taken = collectTakenTeamSlugs(repoPath);
|
|
6138
6313
|
for (let attempt = 0; attempt < 32; attempt++) {
|
|
6139
6314
|
const team = allocateTeamName(taken);
|
|
6140
|
-
const path = (0,
|
|
6141
|
-
if (!(0,
|
|
6315
|
+
const path = (0, import_node_path18.join)(worktreesRoot(repoPath), team.slug);
|
|
6316
|
+
if (!(0, import_node_fs15.existsSync)(path)) return team;
|
|
6142
6317
|
taken.add(team.slug);
|
|
6143
6318
|
}
|
|
6144
6319
|
throw new Error("No available soccer team worktree directories left");
|
|
6145
6320
|
}
|
|
6146
|
-
var
|
|
6321
|
+
var import_node_crypto4, import_node_fs15, import_node_os6, import_node_path18;
|
|
6147
6322
|
var init_worktree = __esm({
|
|
6148
6323
|
"src/git/worktree.ts"() {
|
|
6149
6324
|
"use strict";
|
|
6150
|
-
|
|
6151
|
-
|
|
6325
|
+
import_node_crypto4 = require("crypto");
|
|
6326
|
+
import_node_fs15 = require("fs");
|
|
6327
|
+
import_node_os6 = require("os");
|
|
6328
|
+
import_node_path18 = require("path");
|
|
6152
6329
|
init_paths();
|
|
6153
6330
|
init_thread_store();
|
|
6154
6331
|
init_teams();
|
|
6155
6332
|
init_worktree_labels();
|
|
6156
6333
|
init_gh_errors();
|
|
6334
|
+
init_worktree_exclude();
|
|
6157
6335
|
init_git_auth_mode();
|
|
6158
6336
|
init_run();
|
|
6159
6337
|
init_repo_git_lock();
|
|
@@ -6197,7 +6375,7 @@ var init_cloud_connect_constants = __esm({
|
|
|
6197
6375
|
|
|
6198
6376
|
// src/composer/stage-files.ts
|
|
6199
6377
|
function fileExtension(filePath) {
|
|
6200
|
-
const base = (0,
|
|
6378
|
+
const base = (0, import_node_path19.basename)(filePath).toLowerCase();
|
|
6201
6379
|
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
6202
6380
|
}
|
|
6203
6381
|
function isImageFilePath(filePath) {
|
|
@@ -6207,24 +6385,24 @@ function imageMimeType(filePath) {
|
|
|
6207
6385
|
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
6208
6386
|
}
|
|
6209
6387
|
function ensureAttachmentsDir(worktreePath) {
|
|
6210
|
-
const dir = (0,
|
|
6211
|
-
(0,
|
|
6212
|
-
const gi = (0,
|
|
6213
|
-
if (!(0,
|
|
6214
|
-
(0,
|
|
6388
|
+
const dir = (0, import_node_path19.join)(worktreePath, ATTACHMENTS_DIR);
|
|
6389
|
+
(0, import_node_fs16.mkdirSync)(dir, { recursive: true });
|
|
6390
|
+
const gi = (0, import_node_path19.join)(dir, ".gitignore");
|
|
6391
|
+
if (!(0, import_node_fs16.existsSync)(gi)) {
|
|
6392
|
+
(0, import_node_fs16.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
6215
6393
|
}
|
|
6216
6394
|
return dir;
|
|
6217
6395
|
}
|
|
6218
6396
|
function uniqueAttachmentName(dir, originalName) {
|
|
6219
6397
|
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
6220
|
-
if (!(0,
|
|
6221
|
-
const ext = (0,
|
|
6398
|
+
if (!(0, import_node_fs16.existsSync)((0, import_node_path19.join)(dir, safe))) return safe;
|
|
6399
|
+
const ext = (0, import_node_path19.extname)(safe);
|
|
6222
6400
|
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
6223
6401
|
for (let i = 1; i < 1e4; i++) {
|
|
6224
6402
|
const candidate = `${stem}-${i}${ext}`;
|
|
6225
|
-
if (!(0,
|
|
6403
|
+
if (!(0, import_node_fs16.existsSync)((0, import_node_path19.join)(dir, candidate))) return candidate;
|
|
6226
6404
|
}
|
|
6227
|
-
return `${stem}-${(0,
|
|
6405
|
+
return `${stem}-${(0, import_node_crypto5.randomUUID)()}${ext}`;
|
|
6228
6406
|
}
|
|
6229
6407
|
function previewDataUrlFromBuf(filePath, buf) {
|
|
6230
6408
|
if (!isImageFilePath(filePath)) return void 0;
|
|
@@ -6236,7 +6414,7 @@ function attachmentFromBuffer(name, buf, opts) {
|
|
|
6236
6414
|
if (isImageFilePath(name)) {
|
|
6237
6415
|
const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
|
|
6238
6416
|
return {
|
|
6239
|
-
id: (0,
|
|
6417
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
6240
6418
|
name,
|
|
6241
6419
|
kind: "file",
|
|
6242
6420
|
path: opts.path,
|
|
@@ -6249,7 +6427,7 @@ function attachmentFromBuffer(name, buf, opts) {
|
|
|
6249
6427
|
}
|
|
6250
6428
|
if (buf.length > MAX_INLINE_BYTES) {
|
|
6251
6429
|
return {
|
|
6252
|
-
id: (0,
|
|
6430
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
6253
6431
|
name,
|
|
6254
6432
|
kind: "file",
|
|
6255
6433
|
path: opts.path,
|
|
@@ -6258,7 +6436,7 @@ function attachmentFromBuffer(name, buf, opts) {
|
|
|
6258
6436
|
}
|
|
6259
6437
|
if (buf.includes(0)) {
|
|
6260
6438
|
return {
|
|
6261
|
-
id: (0,
|
|
6439
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
6262
6440
|
name,
|
|
6263
6441
|
kind: "file",
|
|
6264
6442
|
path: opts.path,
|
|
@@ -6266,7 +6444,7 @@ function attachmentFromBuffer(name, buf, opts) {
|
|
|
6266
6444
|
};
|
|
6267
6445
|
}
|
|
6268
6446
|
return {
|
|
6269
|
-
id: (0,
|
|
6447
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
6270
6448
|
name,
|
|
6271
6449
|
kind: "file",
|
|
6272
6450
|
path: opts.path,
|
|
@@ -6278,19 +6456,19 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
|
6278
6456
|
const dir = ensureAttachmentsDir(worktreePath);
|
|
6279
6457
|
const out = [];
|
|
6280
6458
|
for (const abs of absolutePaths) {
|
|
6281
|
-
const originalName = (0,
|
|
6459
|
+
const originalName = (0, import_node_path19.basename)(abs);
|
|
6282
6460
|
try {
|
|
6283
|
-
const st = (0,
|
|
6461
|
+
const st = (0, import_node_fs16.statSync)(abs);
|
|
6284
6462
|
if (!st.isFile()) continue;
|
|
6285
6463
|
const name = uniqueAttachmentName(dir, originalName);
|
|
6286
|
-
const destAbs = (0,
|
|
6287
|
-
(0,
|
|
6464
|
+
const destAbs = (0, import_node_path19.join)(dir, name);
|
|
6465
|
+
(0, import_node_fs16.copyFileSync)(abs, destAbs);
|
|
6288
6466
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
6289
|
-
const buf = (0,
|
|
6467
|
+
const buf = (0, import_node_fs16.readFileSync)(destAbs);
|
|
6290
6468
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
6291
6469
|
} catch (err) {
|
|
6292
6470
|
out.push({
|
|
6293
|
-
id: (0,
|
|
6471
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
6294
6472
|
name: originalName,
|
|
6295
6473
|
kind: "file",
|
|
6296
6474
|
content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
|
|
@@ -6308,13 +6486,13 @@ function stageBuffersAsAttachments(worktreePath, buffers2) {
|
|
|
6308
6486
|
try {
|
|
6309
6487
|
const buf = Buffer.from(item.dataBase64, "base64");
|
|
6310
6488
|
const name = uniqueAttachmentName(dir, originalName);
|
|
6311
|
-
const destAbs = (0,
|
|
6312
|
-
(0,
|
|
6489
|
+
const destAbs = (0, import_node_path19.join)(dir, name);
|
|
6490
|
+
(0, import_node_fs16.writeFileSync)(destAbs, buf);
|
|
6313
6491
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
6314
6492
|
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
6315
6493
|
} catch (err) {
|
|
6316
6494
|
out.push({
|
|
6317
|
-
id: (0,
|
|
6495
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
6318
6496
|
name: originalName,
|
|
6319
6497
|
kind: "file",
|
|
6320
6498
|
content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
|
|
@@ -6369,23 +6547,23 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
|
6369
6547
|
for (const rel of relativePaths) {
|
|
6370
6548
|
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
6371
6549
|
out.push({
|
|
6372
|
-
id: (0,
|
|
6373
|
-
name: (0,
|
|
6550
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
6551
|
+
name: (0, import_node_path19.basename)(rel) || "file",
|
|
6374
6552
|
kind: "file",
|
|
6375
6553
|
content: `(invalid path: ${rel})`
|
|
6376
6554
|
});
|
|
6377
6555
|
continue;
|
|
6378
6556
|
}
|
|
6379
|
-
const name = (0,
|
|
6557
|
+
const name = (0, import_node_path19.basename)(rel);
|
|
6380
6558
|
try {
|
|
6381
|
-
const abs = (0,
|
|
6382
|
-
const st = (0,
|
|
6559
|
+
const abs = (0, import_node_path19.join)(worktreePath, rel);
|
|
6560
|
+
const st = (0, import_node_fs16.statSync)(abs);
|
|
6383
6561
|
if (!st.isFile()) continue;
|
|
6384
|
-
const buf = (0,
|
|
6562
|
+
const buf = (0, import_node_fs16.readFileSync)(abs);
|
|
6385
6563
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
6386
6564
|
} catch (err) {
|
|
6387
6565
|
out.push({
|
|
6388
|
-
id: (0,
|
|
6566
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
6389
6567
|
name,
|
|
6390
6568
|
kind: "file",
|
|
6391
6569
|
content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
|
|
@@ -6394,13 +6572,13 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
|
6394
6572
|
}
|
|
6395
6573
|
return out;
|
|
6396
6574
|
}
|
|
6397
|
-
var
|
|
6575
|
+
var import_node_fs16, import_node_path19, import_node_crypto5, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
|
|
6398
6576
|
var init_stage_files = __esm({
|
|
6399
6577
|
"src/composer/stage-files.ts"() {
|
|
6400
6578
|
"use strict";
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6579
|
+
import_node_fs16 = require("fs");
|
|
6580
|
+
import_node_path19 = require("path");
|
|
6581
|
+
import_node_crypto5 = require("crypto");
|
|
6404
6582
|
init_workspace_scratch();
|
|
6405
6583
|
IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
6406
6584
|
"png",
|
|
@@ -6517,7 +6695,7 @@ function coordinatorTurnReminder(opts) {
|
|
|
6517
6695
|
function ensureGlobalCoordinatorCwd(opts) {
|
|
6518
6696
|
const dir = globalAgentCwd();
|
|
6519
6697
|
try {
|
|
6520
|
-
(0,
|
|
6698
|
+
(0, import_node_fs17.mkdirSync)(dir, { recursive: true });
|
|
6521
6699
|
} catch {
|
|
6522
6700
|
return dir;
|
|
6523
6701
|
}
|
|
@@ -6525,7 +6703,7 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
6525
6703
|
let orchId = opts?.orchestratorThreadId?.trim() || "";
|
|
6526
6704
|
if (!orchId) {
|
|
6527
6705
|
try {
|
|
6528
|
-
const existing = (0,
|
|
6706
|
+
const existing = (0, import_node_fs17.readFileSync)((0, import_node_path20.join)(dir, "AGENTS.md"), "utf8");
|
|
6529
6707
|
const m = existing.match(
|
|
6530
6708
|
/YOUR orchestration thread id is `([0-9a-f-]{36})`/i
|
|
6531
6709
|
);
|
|
@@ -6568,9 +6746,9 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
6568
6746
|
"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."
|
|
6569
6747
|
].join("\n");
|
|
6570
6748
|
try {
|
|
6571
|
-
(0,
|
|
6749
|
+
(0, import_node_fs17.writeFileSync)((0, import_node_path20.join)(dir, "CLAUDE.md"), `${body}
|
|
6572
6750
|
`, "utf8");
|
|
6573
|
-
(0,
|
|
6751
|
+
(0, import_node_fs17.writeFileSync)((0, import_node_path20.join)(dir, "AGENTS.md"), `${body}
|
|
6574
6752
|
`, "utf8");
|
|
6575
6753
|
} catch {
|
|
6576
6754
|
}
|
|
@@ -6602,12 +6780,12 @@ function coordinatorSystemPrompt(opts) {
|
|
|
6602
6780
|
formatWorkspaceInventory(opts.workspaces)
|
|
6603
6781
|
].join("\n");
|
|
6604
6782
|
}
|
|
6605
|
-
var
|
|
6783
|
+
var import_node_fs17, import_node_path20, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
|
|
6606
6784
|
var init_coordinator_prompt = __esm({
|
|
6607
6785
|
"src/orchestrator/coordinator-prompt.ts"() {
|
|
6608
6786
|
"use strict";
|
|
6609
|
-
|
|
6610
|
-
|
|
6787
|
+
import_node_fs17 = require("fs");
|
|
6788
|
+
import_node_path20 = require("path");
|
|
6611
6789
|
init_worktree();
|
|
6612
6790
|
init_app_settings();
|
|
6613
6791
|
init_paths();
|
|
@@ -6617,8 +6795,8 @@ var init_coordinator_prompt = __esm({
|
|
|
6617
6795
|
"Discover:",
|
|
6618
6796
|
"- list_workspaces \u2014 registered repos (path + github slug when known)",
|
|
6619
6797
|
"- 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.",
|
|
6620
|
-
"- list_branches / list_prs / list_issues \u2014 pass repoPath from list_workspaces (issues: Linear, AbleTime MCP, or GitHub Issues)",
|
|
6621
|
-
"- 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.",
|
|
6798
|
+
"- 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.",
|
|
6799
|
+
"- 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.",
|
|
6622
6800
|
"- 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).",
|
|
6623
6801
|
"- 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",
|
|
6624
6802
|
"- 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).",
|
|
@@ -6637,7 +6815,7 @@ var init_coordinator_prompt = __esm({
|
|
|
6637
6815
|
"- 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.",
|
|
6638
6816
|
"- 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.",
|
|
6639
6817
|
"- 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)",
|
|
6640
|
-
"- 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.",
|
|
6818
|
+
"- 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.",
|
|
6641
6819
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
6642
6820
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
6643
6821
|
"Setup / run:",
|
|
@@ -6646,7 +6824,7 @@ var init_coordinator_prompt = __esm({
|
|
|
6646
6824
|
"Inspect / review / PRs:",
|
|
6647
6825
|
"- get_diff \u2014 compact diff summary",
|
|
6648
6826
|
'- 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',
|
|
6649
|
-
"- 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.",
|
|
6827
|
+
"- 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.",
|
|
6650
6828
|
'- 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.',
|
|
6651
6829
|
'- 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.',
|
|
6652
6830
|
"Process guides:",
|
|
@@ -6917,32 +7095,32 @@ var init_global_workspace = __esm({
|
|
|
6917
7095
|
function brightsyConfigPath() {
|
|
6918
7096
|
const override = process.env.BRIGHTSY_CONFIG?.trim();
|
|
6919
7097
|
if (override) return override;
|
|
6920
|
-
return (0,
|
|
7098
|
+
return (0, import_node_path21.join)((0, import_node_os7.homedir)(), ".brightsy", "config.json");
|
|
6921
7099
|
}
|
|
6922
7100
|
function loadBrightsyConfig() {
|
|
6923
7101
|
const path = brightsyConfigPath();
|
|
6924
|
-
if (!(0,
|
|
7102
|
+
if (!(0, import_node_fs18.existsSync)(path)) {
|
|
6925
7103
|
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
6926
7104
|
}
|
|
6927
|
-
const raw = JSON.parse((0,
|
|
7105
|
+
const raw = JSON.parse((0, import_node_fs18.readFileSync)(path, "utf8"));
|
|
6928
7106
|
if (!raw.access_token || !raw.account_id) {
|
|
6929
7107
|
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
6930
7108
|
}
|
|
6931
7109
|
return raw;
|
|
6932
7110
|
}
|
|
6933
7111
|
function saveBrightsyConfig(cfg) {
|
|
6934
|
-
(0,
|
|
7112
|
+
(0, import_node_fs18.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
6935
7113
|
`, {
|
|
6936
7114
|
mode: 384
|
|
6937
7115
|
});
|
|
6938
7116
|
}
|
|
6939
|
-
var
|
|
7117
|
+
var import_node_fs18, import_node_os7, import_node_path21;
|
|
6940
7118
|
var init_config = __esm({
|
|
6941
7119
|
"src/brightsy/config.ts"() {
|
|
6942
7120
|
"use strict";
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
7121
|
+
import_node_fs18 = require("fs");
|
|
7122
|
+
import_node_os7 = require("os");
|
|
7123
|
+
import_node_path21 = require("path");
|
|
6946
7124
|
}
|
|
6947
7125
|
});
|
|
6948
7126
|
|
|
@@ -7059,22 +7237,22 @@ var init_oauth = __esm({
|
|
|
7059
7237
|
|
|
7060
7238
|
// src/brightsy/connected-teams.ts
|
|
7061
7239
|
function storePath4() {
|
|
7062
|
-
return (0,
|
|
7240
|
+
return (0, import_node_path22.join)(appDataDir(), "brightsy-teams.json");
|
|
7063
7241
|
}
|
|
7064
7242
|
function readStore4() {
|
|
7065
7243
|
const path = storePath4();
|
|
7066
|
-
if (!(0,
|
|
7244
|
+
if (!(0, import_node_fs19.existsSync)(path)) return [];
|
|
7067
7245
|
try {
|
|
7068
|
-
const parsed = JSON.parse((0,
|
|
7246
|
+
const parsed = JSON.parse((0, import_node_fs19.readFileSync)(path, "utf8"));
|
|
7069
7247
|
return Array.isArray(parsed.teams) ? parsed.teams : [];
|
|
7070
7248
|
} catch {
|
|
7071
7249
|
return [];
|
|
7072
7250
|
}
|
|
7073
7251
|
}
|
|
7074
7252
|
function writeStore2(teams) {
|
|
7075
|
-
(0,
|
|
7253
|
+
(0, import_node_fs19.mkdirSync)(appDataDir(), { recursive: true });
|
|
7076
7254
|
const path = storePath4();
|
|
7077
|
-
(0,
|
|
7255
|
+
(0, import_node_fs19.writeFileSync)(path, `${JSON.stringify({ teams }, null, 2)}
|
|
7078
7256
|
`, {
|
|
7079
7257
|
mode: 384
|
|
7080
7258
|
});
|
|
@@ -7180,12 +7358,12 @@ function brightsyMcpServerName(slug) {
|
|
|
7180
7358
|
const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
|
|
7181
7359
|
return `brightsy_${cleaned || "team"}`;
|
|
7182
7360
|
}
|
|
7183
|
-
var
|
|
7361
|
+
var import_node_fs19, import_node_path22;
|
|
7184
7362
|
var init_connected_teams = __esm({
|
|
7185
7363
|
"src/brightsy/connected-teams.ts"() {
|
|
7186
7364
|
"use strict";
|
|
7187
|
-
|
|
7188
|
-
|
|
7365
|
+
import_node_fs19 = require("fs");
|
|
7366
|
+
import_node_path22 = require("path");
|
|
7189
7367
|
init_paths();
|
|
7190
7368
|
init_accounts();
|
|
7191
7369
|
init_config();
|
|
@@ -7557,11 +7735,11 @@ async function syncCliForTarget(accountId) {
|
|
|
7557
7735
|
}
|
|
7558
7736
|
applyConnectedTeamToCli(team);
|
|
7559
7737
|
}
|
|
7560
|
-
var
|
|
7738
|
+
var import_node_fs20, brightsyAdapter;
|
|
7561
7739
|
var init_brightsy = __esm({
|
|
7562
7740
|
"src/agents/brightsy.ts"() {
|
|
7563
7741
|
"use strict";
|
|
7564
|
-
|
|
7742
|
+
import_node_fs20 = require("fs");
|
|
7565
7743
|
init_run();
|
|
7566
7744
|
init_connected_teams();
|
|
7567
7745
|
init_config();
|
|
@@ -7576,7 +7754,7 @@ var init_brightsy = __esm({
|
|
|
7576
7754
|
async detect() {
|
|
7577
7755
|
const brightsy = resolveAgentExecutable("brightsy");
|
|
7578
7756
|
if (brightsy !== "brightsy") {
|
|
7579
|
-
if (!(0,
|
|
7757
|
+
if (!(0, import_node_fs20.existsSync)(brightsy)) {
|
|
7580
7758
|
return {
|
|
7581
7759
|
agent: "brightsy",
|
|
7582
7760
|
installed: false,
|
|
@@ -7807,6 +7985,13 @@ function isSubagentToolName(name) {
|
|
|
7807
7985
|
if (/^(task|agent|spawn_agent)$/i.test(n)) return true;
|
|
7808
7986
|
return /connectedAgentRequest/i.test(n);
|
|
7809
7987
|
}
|
|
7988
|
+
function isInternalAgentStatusText(text5) {
|
|
7989
|
+
const t = text5.trim();
|
|
7990
|
+
if (!t) return false;
|
|
7991
|
+
if (/waiting for gate to pass/i.test(t)) return true;
|
|
7992
|
+
if (/^agent is running\b/i.test(t) && t.length < 160) return true;
|
|
7993
|
+
return false;
|
|
7994
|
+
}
|
|
7810
7995
|
function isPollWrapperToolName(name) {
|
|
7811
7996
|
const n = (name ?? "").replace(/[_-]/g, "");
|
|
7812
7997
|
return /^(taskoutput|taskstop|sleep)$/i.test(n);
|
|
@@ -7814,7 +7999,10 @@ function isPollWrapperToolName(name) {
|
|
|
7814
7999
|
function lastTextPart(parts, type) {
|
|
7815
8000
|
for (let i = parts.length - 1; i >= 0; i--) {
|
|
7816
8001
|
const p = parts[i];
|
|
7817
|
-
if (p.type
|
|
8002
|
+
if (p.type !== type) continue;
|
|
8003
|
+
const text5 = p.text.trim();
|
|
8004
|
+
if (!text5 || isInternalAgentStatusText(text5)) continue;
|
|
8005
|
+
return text5;
|
|
7818
8006
|
}
|
|
7819
8007
|
return "";
|
|
7820
8008
|
}
|
|
@@ -8151,43 +8339,43 @@ function electronResourcesPath() {
|
|
|
8151
8339
|
function packagedCursorRuntimeDir() {
|
|
8152
8340
|
const resources = electronResourcesPath();
|
|
8153
8341
|
if (!resources) return null;
|
|
8154
|
-
const dir = (0,
|
|
8155
|
-
if (!(0,
|
|
8342
|
+
const dir = (0, import_node_path23.join)(resources, "cursor-runtime");
|
|
8343
|
+
if (!(0, import_node_fs21.existsSync)((0, import_node_path23.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
|
|
8156
8344
|
return dir;
|
|
8157
8345
|
}
|
|
8158
8346
|
function packagedCursorRunnerPath() {
|
|
8159
8347
|
const dir = packagedCursorRuntimeDir();
|
|
8160
|
-
return dir ? (0,
|
|
8348
|
+
return dir ? (0, import_node_path23.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
|
|
8161
8349
|
}
|
|
8162
8350
|
function packagedMcpDir() {
|
|
8163
8351
|
const resources = electronResourcesPath();
|
|
8164
8352
|
if (!resources) return null;
|
|
8165
|
-
const dir = (0,
|
|
8166
|
-
if (!(0,
|
|
8353
|
+
const dir = (0, import_node_path23.join)(resources, "sideboard-mcp");
|
|
8354
|
+
if (!(0, import_node_fs21.existsSync)((0, import_node_path23.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
|
|
8167
8355
|
return dir;
|
|
8168
8356
|
}
|
|
8169
8357
|
function packagedMcpStdioPath() {
|
|
8170
8358
|
const dir = packagedMcpDir();
|
|
8171
|
-
return dir ? (0,
|
|
8359
|
+
return dir ? (0, import_node_path23.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
|
|
8172
8360
|
}
|
|
8173
8361
|
function packagedBundledNodePath() {
|
|
8174
8362
|
const resources = electronResourcesPath();
|
|
8175
8363
|
if (!resources) return null;
|
|
8176
|
-
const bin = (0,
|
|
8177
|
-
if (!(0,
|
|
8364
|
+
const bin = (0, import_node_path23.join)(resources, "node", "bin", "node");
|
|
8365
|
+
if (!(0, import_node_fs21.existsSync)(bin)) return null;
|
|
8178
8366
|
return bin;
|
|
8179
8367
|
}
|
|
8180
8368
|
function packagedCursorRipgrepCandidate(platformPkg, binName) {
|
|
8181
8369
|
const dir = packagedCursorRuntimeDir();
|
|
8182
8370
|
if (!dir) return null;
|
|
8183
|
-
return (0,
|
|
8371
|
+
return (0, import_node_path23.join)(dir, "node_modules", platformPkg, "bin", binName);
|
|
8184
8372
|
}
|
|
8185
|
-
var
|
|
8373
|
+
var import_node_fs21, import_node_path23;
|
|
8186
8374
|
var init_packaged_runtime = __esm({
|
|
8187
8375
|
"src/agents/packaged-runtime.ts"() {
|
|
8188
8376
|
"use strict";
|
|
8189
|
-
|
|
8190
|
-
|
|
8377
|
+
import_node_fs21 = require("fs");
|
|
8378
|
+
import_node_path23 = require("path");
|
|
8191
8379
|
}
|
|
8192
8380
|
});
|
|
8193
8381
|
|
|
@@ -8221,7 +8409,7 @@ function unpackedAsarPath(filePath) {
|
|
|
8221
8409
|
if (!isAsarPath(filePath)) return null;
|
|
8222
8410
|
const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
|
|
8223
8411
|
if (unpacked === filePath) return null;
|
|
8224
|
-
return (0,
|
|
8412
|
+
return (0, import_node_fs22.existsSync)(unpacked) ? unpacked : null;
|
|
8225
8413
|
}
|
|
8226
8414
|
function nodeReadableScriptPath(scriptPath) {
|
|
8227
8415
|
return unpackedAsarPath(scriptPath) ?? scriptPath;
|
|
@@ -8261,37 +8449,37 @@ function pickPreferredNode(candidates) {
|
|
|
8261
8449
|
return best;
|
|
8262
8450
|
}
|
|
8263
8451
|
function versionDirNodeBins(root, toBin) {
|
|
8264
|
-
if (!(0,
|
|
8452
|
+
if (!(0, import_node_fs22.existsSync)(root)) return [];
|
|
8265
8453
|
try {
|
|
8266
|
-
return (0,
|
|
8454
|
+
return (0, import_node_fs22.readdirSync)(root).map(toBin);
|
|
8267
8455
|
} catch {
|
|
8268
8456
|
return [];
|
|
8269
8457
|
}
|
|
8270
8458
|
}
|
|
8271
|
-
function defaultNodeBinCandidates(home = (0,
|
|
8459
|
+
function defaultNodeBinCandidates(home = (0, import_node_os8.homedir)()) {
|
|
8272
8460
|
const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
|
|
8273
|
-
(prefix) => PREFERRED_LTS_MAJORS.map((major) => (0,
|
|
8461
|
+
(prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path24.join)(prefix, "opt", `node@${major}`, "bin", "node"))
|
|
8274
8462
|
);
|
|
8275
8463
|
return [
|
|
8276
8464
|
...kegs,
|
|
8277
8465
|
"/opt/homebrew/bin/node",
|
|
8278
8466
|
"/usr/local/bin/node",
|
|
8279
|
-
(0,
|
|
8280
|
-
(0,
|
|
8281
|
-
(0,
|
|
8282
|
-
(0,
|
|
8283
|
-
(0,
|
|
8467
|
+
(0, import_node_path24.join)(home, ".local/share/fnm/aliases/default/bin/node"),
|
|
8468
|
+
(0, import_node_path24.join)(home, ".nvm/current/bin/node"),
|
|
8469
|
+
(0, import_node_path24.join)(home, ".volta/bin/node"),
|
|
8470
|
+
(0, import_node_path24.join)(home, ".asdf/shims/node"),
|
|
8471
|
+
(0, import_node_path24.join)(home, ".local/share/mise/shims/node"),
|
|
8284
8472
|
...versionDirNodeBins(
|
|
8285
|
-
(0,
|
|
8286
|
-
(name) => (0,
|
|
8473
|
+
(0, import_node_path24.join)(home, ".nvm", "versions", "node"),
|
|
8474
|
+
(name) => (0, import_node_path24.join)(home, ".nvm", "versions", "node", name, "bin", "node")
|
|
8287
8475
|
),
|
|
8288
8476
|
...versionDirNodeBins(
|
|
8289
|
-
(0,
|
|
8290
|
-
(name) => (0,
|
|
8477
|
+
(0, import_node_path24.join)(home, ".local/share/fnm", "node-versions"),
|
|
8478
|
+
(name) => (0, import_node_path24.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
|
|
8291
8479
|
),
|
|
8292
8480
|
...versionDirNodeBins(
|
|
8293
|
-
(0,
|
|
8294
|
-
(name) => (0,
|
|
8481
|
+
(0, import_node_path24.join)(home, ".volta", "tools", "image", "node"),
|
|
8482
|
+
(name) => (0, import_node_path24.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
|
|
8295
8483
|
)
|
|
8296
8484
|
];
|
|
8297
8485
|
}
|
|
@@ -8300,10 +8488,10 @@ function uniqueExistingNodeBins(paths) {
|
|
|
8300
8488
|
const out = [];
|
|
8301
8489
|
for (const raw of paths) {
|
|
8302
8490
|
const p = raw.trim();
|
|
8303
|
-
if (!p || !(0,
|
|
8491
|
+
if (!p || !(0, import_node_fs22.existsSync)(p) || isElectronLikeCommand(p)) continue;
|
|
8304
8492
|
let key = p;
|
|
8305
8493
|
try {
|
|
8306
|
-
key = (0,
|
|
8494
|
+
key = (0, import_node_fs22.realpathSync)(p);
|
|
8307
8495
|
} catch {
|
|
8308
8496
|
continue;
|
|
8309
8497
|
}
|
|
@@ -8383,13 +8571,13 @@ async function resolveNodeLaunch(scriptPath) {
|
|
|
8383
8571
|
env: { ELECTRON_RUN_AS_NODE: "1" }
|
|
8384
8572
|
};
|
|
8385
8573
|
}
|
|
8386
|
-
var
|
|
8574
|
+
var import_node_fs22, import_node_os8, import_node_path24, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
|
|
8387
8575
|
var init_node_launch = __esm({
|
|
8388
8576
|
"src/agents/node-launch.ts"() {
|
|
8389
8577
|
"use strict";
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8578
|
+
import_node_fs22 = require("fs");
|
|
8579
|
+
import_node_os8 = require("os");
|
|
8580
|
+
import_node_path24 = require("path");
|
|
8393
8581
|
init_nested_electron_env();
|
|
8394
8582
|
init_run();
|
|
8395
8583
|
init_packaged_runtime();
|
|
@@ -8483,37 +8671,37 @@ function corePackageDir() {
|
|
|
8483
8671
|
try {
|
|
8484
8672
|
const url = import_meta.url;
|
|
8485
8673
|
if (typeof url === "string" && url.length > 0) {
|
|
8486
|
-
return (0,
|
|
8674
|
+
return (0, import_node_path25.dirname)((0, import_node_url.fileURLToPath)(url));
|
|
8487
8675
|
}
|
|
8488
8676
|
} catch {
|
|
8489
8677
|
}
|
|
8490
8678
|
try {
|
|
8491
|
-
const req = (0, import_node_module.createRequire)((0,
|
|
8492
|
-
return (0,
|
|
8679
|
+
const req = (0, import_node_module.createRequire)((0, import_node_path25.join)(process.cwd(), "package.json"));
|
|
8680
|
+
return (0, import_node_path25.dirname)(req.resolve("@sideboard-ai/core"));
|
|
8493
8681
|
} catch {
|
|
8494
8682
|
return process.cwd();
|
|
8495
8683
|
}
|
|
8496
8684
|
}
|
|
8497
8685
|
function findSideboardMcpJsEntry() {
|
|
8498
8686
|
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
8499
|
-
if (override && (0,
|
|
8687
|
+
if (override && (0, import_node_fs23.existsSync)(override)) return override;
|
|
8500
8688
|
const packaged = packagedMcpStdioPath();
|
|
8501
8689
|
if (packaged) return packaged;
|
|
8502
8690
|
let dir = corePackageDir();
|
|
8503
8691
|
for (let i = 0; i < 10; i++) {
|
|
8504
8692
|
const candidates = [
|
|
8505
|
-
(0,
|
|
8506
|
-
(0,
|
|
8507
|
-
(0,
|
|
8508
|
-
(0,
|
|
8509
|
-
(0,
|
|
8510
|
-
(0,
|
|
8511
|
-
(0,
|
|
8693
|
+
(0, import_node_path25.join)(dir, "mcp/run-stdio.js"),
|
|
8694
|
+
(0, import_node_path25.join)(dir, "mcp/run-stdio.cjs"),
|
|
8695
|
+
(0, import_node_path25.join)(dir, "dist/mcp/run-stdio.js"),
|
|
8696
|
+
(0, import_node_path25.join)(dir, "dist/mcp/run-stdio.cjs"),
|
|
8697
|
+
(0, import_node_path25.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
|
|
8698
|
+
(0, import_node_path25.join)(dir, "packages/cli/dist/index.js"),
|
|
8699
|
+
(0, import_node_path25.join)(dir, "cli/dist/index.js")
|
|
8512
8700
|
];
|
|
8513
8701
|
for (const p of candidates) {
|
|
8514
|
-
if ((0,
|
|
8702
|
+
if ((0, import_node_fs23.existsSync)(p) && !isAsarPath(p)) return p;
|
|
8515
8703
|
}
|
|
8516
|
-
const parent = (0,
|
|
8704
|
+
const parent = (0, import_node_path25.dirname)(dir);
|
|
8517
8705
|
if (parent === dir) break;
|
|
8518
8706
|
dir = parent;
|
|
8519
8707
|
}
|
|
@@ -8655,19 +8843,19 @@ function writeMcpServersConfig(servers) {
|
|
|
8655
8843
|
...env ? { env } : {}
|
|
8656
8844
|
};
|
|
8657
8845
|
}
|
|
8658
|
-
const dir = (0,
|
|
8659
|
-
const cfgPath = (0,
|
|
8660
|
-
(0,
|
|
8846
|
+
const dir = (0, import_node_fs23.mkdtempSync)((0, import_node_path25.join)((0, import_node_os9.tmpdir)(), "sideboard-mcp-"));
|
|
8847
|
+
const cfgPath = (0, import_node_path25.join)(dir, "mcp.json");
|
|
8848
|
+
(0, import_node_fs23.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
|
|
8661
8849
|
return cfgPath;
|
|
8662
8850
|
}
|
|
8663
|
-
var
|
|
8851
|
+
var import_node_fs23, import_node_module, import_node_os9, import_node_path25, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
|
|
8664
8852
|
var init_injected_mcp = __esm({
|
|
8665
8853
|
"src/agents/injected-mcp.ts"() {
|
|
8666
8854
|
"use strict";
|
|
8667
|
-
|
|
8855
|
+
import_node_fs23 = require("fs");
|
|
8668
8856
|
import_node_module = require("module");
|
|
8669
|
-
|
|
8670
|
-
|
|
8857
|
+
import_node_os9 = require("os");
|
|
8858
|
+
import_node_path25 = require("path");
|
|
8671
8859
|
import_node_url = require("url");
|
|
8672
8860
|
init_run();
|
|
8673
8861
|
init_config();
|
|
@@ -9006,11 +9194,11 @@ function parseIssuesJson(raw) {
|
|
|
9006
9194
|
}
|
|
9007
9195
|
return [];
|
|
9008
9196
|
}
|
|
9009
|
-
var
|
|
9197
|
+
var import_node_fs24, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, mcpListCache, claudeAdapter;
|
|
9010
9198
|
var init_claude = __esm({
|
|
9011
9199
|
"src/agents/claude.ts"() {
|
|
9012
9200
|
"use strict";
|
|
9013
|
-
|
|
9201
|
+
import_node_fs24 = require("fs");
|
|
9014
9202
|
init_run();
|
|
9015
9203
|
init_app_settings();
|
|
9016
9204
|
init_claude_mcp();
|
|
@@ -9050,7 +9238,7 @@ var init_claude = __esm({
|
|
|
9050
9238
|
async detect() {
|
|
9051
9239
|
const claude = resolveClaudeExecutable();
|
|
9052
9240
|
if (claude !== "claude") {
|
|
9053
|
-
if (!(0,
|
|
9241
|
+
if (!(0, import_node_fs24.existsSync)(claude)) {
|
|
9054
9242
|
return {
|
|
9055
9243
|
agent: "claude",
|
|
9056
9244
|
installed: false,
|
|
@@ -9305,7 +9493,7 @@ async function listCodexModels() {
|
|
|
9305
9493
|
if (codex === "codex") {
|
|
9306
9494
|
const which = await run("which", ["codex"], { reject: false });
|
|
9307
9495
|
if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
|
|
9308
|
-
} else if (!(0,
|
|
9496
|
+
} else if (!(0, import_node_fs25.existsSync)(codex)) {
|
|
9309
9497
|
return FALLBACK_CODEX_MODELS;
|
|
9310
9498
|
}
|
|
9311
9499
|
const listed = await run(codex, ["debug", "models"], { reject: false });
|
|
@@ -9340,12 +9528,12 @@ function usageFromCodex(usage) {
|
|
|
9340
9528
|
}
|
|
9341
9529
|
function codexConfigHasNetworkAccess() {
|
|
9342
9530
|
const candidates = [
|
|
9343
|
-
(0,
|
|
9344
|
-
(0,
|
|
9531
|
+
(0, import_node_path26.join)((0, import_node_os10.homedir)(), ".codex", "config.toml"),
|
|
9532
|
+
(0, import_node_path26.join)((0, import_node_os10.homedir)(), ".config", "codex", "config.toml")
|
|
9345
9533
|
];
|
|
9346
9534
|
for (const path of candidates) {
|
|
9347
|
-
if (!(0,
|
|
9348
|
-
const text5 = (0,
|
|
9535
|
+
if (!(0, import_node_fs25.existsSync)(path)) continue;
|
|
9536
|
+
const text5 = (0, import_node_fs25.readFileSync)(path, "utf8");
|
|
9349
9537
|
if (/network_access\s*=\s*true/.test(text5)) return true;
|
|
9350
9538
|
}
|
|
9351
9539
|
return false;
|
|
@@ -9377,21 +9565,21 @@ function asRecord2(value) {
|
|
|
9377
9565
|
return void 0;
|
|
9378
9566
|
}
|
|
9379
9567
|
function codexLooksAuthenticated() {
|
|
9380
|
-
const authPath = (0,
|
|
9381
|
-
if (!(0,
|
|
9568
|
+
const authPath = (0, import_node_path26.join)((0, import_node_os10.homedir)(), ".codex", "auth.json");
|
|
9569
|
+
if (!(0, import_node_fs25.existsSync)(authPath)) return false;
|
|
9382
9570
|
try {
|
|
9383
|
-
return (0,
|
|
9571
|
+
return (0, import_node_fs25.statSync)(authPath).size > 2;
|
|
9384
9572
|
} catch {
|
|
9385
9573
|
return false;
|
|
9386
9574
|
}
|
|
9387
9575
|
}
|
|
9388
|
-
var
|
|
9576
|
+
var import_node_fs25, import_node_os10, import_node_path26, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
|
|
9389
9577
|
var init_codex = __esm({
|
|
9390
9578
|
"src/agents/codex.ts"() {
|
|
9391
9579
|
"use strict";
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9580
|
+
import_node_fs25 = require("fs");
|
|
9581
|
+
import_node_os10 = require("os");
|
|
9582
|
+
import_node_path26 = require("path");
|
|
9395
9583
|
init_run();
|
|
9396
9584
|
init_app_settings();
|
|
9397
9585
|
init_global_workspace();
|
|
@@ -9416,7 +9604,7 @@ var init_codex = __esm({
|
|
|
9416
9604
|
async detect() {
|
|
9417
9605
|
const codex = resolveAgentExecutable("codex");
|
|
9418
9606
|
if (codex !== "codex") {
|
|
9419
|
-
if (!(0,
|
|
9607
|
+
if (!(0, import_node_fs25.existsSync)(codex)) {
|
|
9420
9608
|
return {
|
|
9421
9609
|
agent: "codex",
|
|
9422
9610
|
installed: false,
|
|
@@ -9903,21 +10091,21 @@ function platformRipgrepPackage() {
|
|
|
9903
10091
|
}
|
|
9904
10092
|
function usableRipgrepPath(candidate) {
|
|
9905
10093
|
const raw = candidate?.trim();
|
|
9906
|
-
if (!raw || !(0,
|
|
10094
|
+
if (!raw || !(0, import_node_path27.isAbsolute)(raw)) return null;
|
|
9907
10095
|
const readable = nodeReadableScriptPath(raw);
|
|
9908
|
-
if (!(0,
|
|
10096
|
+
if (!(0, import_node_fs26.existsSync)(readable) || isAsarPath(readable)) return null;
|
|
9909
10097
|
return readable;
|
|
9910
10098
|
}
|
|
9911
10099
|
function walkForBundledRipgrep(startFile) {
|
|
9912
10100
|
if (!startFile) return null;
|
|
9913
10101
|
const pkg = platformRipgrepPackage();
|
|
9914
10102
|
const name = rgBinaryName();
|
|
9915
|
-
let dir = (0,
|
|
9916
|
-
const root = (0,
|
|
10103
|
+
let dir = (0, import_node_path27.dirname)((0, import_node_path27.resolve)(startFile));
|
|
10104
|
+
const root = (0, import_node_path27.parse)(dir).root;
|
|
9917
10105
|
while (dir !== root) {
|
|
9918
|
-
const hit = usableRipgrepPath((0,
|
|
10106
|
+
const hit = usableRipgrepPath((0, import_node_path27.join)(dir, "node_modules", pkg, "bin", name));
|
|
9919
10107
|
if (hit) return hit;
|
|
9920
|
-
const next = (0,
|
|
10108
|
+
const next = (0, import_node_path27.dirname)(dir);
|
|
9921
10109
|
if (next === dir) break;
|
|
9922
10110
|
dir = next;
|
|
9923
10111
|
}
|
|
@@ -9927,7 +10115,7 @@ function requireResolveBundledRipgrep(fromFile) {
|
|
|
9927
10115
|
try {
|
|
9928
10116
|
const req = (0, import_node_module2.createRequire)(fromFile);
|
|
9929
10117
|
const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
|
|
9930
|
-
return usableRipgrepPath((0,
|
|
10118
|
+
return usableRipgrepPath((0, import_node_path27.join)((0, import_node_path27.dirname)(pkgJson), "bin", rgBinaryName()));
|
|
9931
10119
|
} catch {
|
|
9932
10120
|
return null;
|
|
9933
10121
|
}
|
|
@@ -9949,13 +10137,13 @@ function cursorRipgrepEnv(opts) {
|
|
|
9949
10137
|
const path = resolveCursorRipgrepPath(opts);
|
|
9950
10138
|
return path ? { [RIPGREP_ENV]: path } : {};
|
|
9951
10139
|
}
|
|
9952
|
-
var
|
|
10140
|
+
var import_node_fs26, import_node_module2, import_node_path27, RIPGREP_ENV;
|
|
9953
10141
|
var init_cursor_ripgrep = __esm({
|
|
9954
10142
|
"src/agents/cursor-ripgrep.ts"() {
|
|
9955
10143
|
"use strict";
|
|
9956
|
-
|
|
10144
|
+
import_node_fs26 = require("fs");
|
|
9957
10145
|
import_node_module2 = require("module");
|
|
9958
|
-
|
|
10146
|
+
import_node_path27 = require("path");
|
|
9959
10147
|
init_node_launch();
|
|
9960
10148
|
init_packaged_runtime();
|
|
9961
10149
|
RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
|
|
@@ -10001,11 +10189,11 @@ function entryDir() {
|
|
|
10001
10189
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
10002
10190
|
if (cjsDir) return cjsDir;
|
|
10003
10191
|
try {
|
|
10004
|
-
return (0,
|
|
10192
|
+
return (0, import_node_path28.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
|
|
10005
10193
|
} catch {
|
|
10006
10194
|
try {
|
|
10007
10195
|
const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
|
|
10008
|
-
return (0,
|
|
10196
|
+
return (0, import_node_path28.dirname)(req.resolve("@sideboard-ai/core"));
|
|
10009
10197
|
} catch {
|
|
10010
10198
|
return process.cwd();
|
|
10011
10199
|
}
|
|
@@ -10016,27 +10204,27 @@ function cursorRunnerPath() {
|
|
|
10016
10204
|
if (packaged) return packaged;
|
|
10017
10205
|
const root = entryDir();
|
|
10018
10206
|
const candidates = [
|
|
10019
|
-
(0,
|
|
10020
|
-
(0,
|
|
10207
|
+
(0, import_node_path28.join)(root, "agents", "cursor-runner.js"),
|
|
10208
|
+
(0, import_node_path28.join)(root, "agents", "cursor-runner.cjs"),
|
|
10021
10209
|
// If somehow resolved from package root instead of dist/
|
|
10022
|
-
(0,
|
|
10023
|
-
(0,
|
|
10210
|
+
(0, import_node_path28.join)(root, "dist", "agents", "cursor-runner.js"),
|
|
10211
|
+
(0, import_node_path28.join)(root, "dist", "agents", "cursor-runner.cjs"),
|
|
10024
10212
|
// Source tree (dev): packages/core/src/agents/cursor-runner.ts
|
|
10025
|
-
(0,
|
|
10026
|
-
(0,
|
|
10213
|
+
(0, import_node_path28.join)(root, "cursor-runner.ts"),
|
|
10214
|
+
(0, import_node_path28.join)(root, "src", "agents", "cursor-runner.ts")
|
|
10027
10215
|
];
|
|
10028
10216
|
for (const candidate of candidates) {
|
|
10029
|
-
if ((0,
|
|
10217
|
+
if ((0, import_node_fs27.existsSync)(candidate)) return candidate;
|
|
10030
10218
|
}
|
|
10031
10219
|
return candidates[0];
|
|
10032
10220
|
}
|
|
10033
|
-
var
|
|
10221
|
+
var import_node_fs27, import_node_module3, import_node_path28, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
|
|
10034
10222
|
var init_cursor = __esm({
|
|
10035
10223
|
"src/agents/cursor.ts"() {
|
|
10036
10224
|
"use strict";
|
|
10037
|
-
|
|
10225
|
+
import_node_fs27 = require("fs");
|
|
10038
10226
|
import_node_module3 = require("module");
|
|
10039
|
-
|
|
10227
|
+
import_node_path28 = require("path");
|
|
10040
10228
|
import_node_url2 = require("url");
|
|
10041
10229
|
import_sdk = require("@cursor/sdk");
|
|
10042
10230
|
init_run();
|
|
@@ -10187,7 +10375,7 @@ async function listOpencodeModels() {
|
|
|
10187
10375
|
if (opencode === "opencode") {
|
|
10188
10376
|
const which = await run("which", ["opencode"], { reject: false });
|
|
10189
10377
|
if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
|
|
10190
|
-
} else if (!(0,
|
|
10378
|
+
} else if (!(0, import_node_fs28.existsSync)(opencode)) {
|
|
10191
10379
|
return FALLBACK_OPENCODE_MODELS;
|
|
10192
10380
|
}
|
|
10193
10381
|
const listed = await run(opencode, ["models"], { reject: false });
|
|
@@ -10217,11 +10405,11 @@ function usageFromOpencode(tokens) {
|
|
|
10217
10405
|
cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
|
|
10218
10406
|
};
|
|
10219
10407
|
}
|
|
10220
|
-
var
|
|
10408
|
+
var import_node_fs28, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
|
|
10221
10409
|
var init_opencode = __esm({
|
|
10222
10410
|
"src/agents/opencode.ts"() {
|
|
10223
10411
|
"use strict";
|
|
10224
|
-
|
|
10412
|
+
import_node_fs28 = require("fs");
|
|
10225
10413
|
init_run();
|
|
10226
10414
|
init_app_settings();
|
|
10227
10415
|
init_global_workspace();
|
|
@@ -10248,7 +10436,7 @@ var init_opencode = __esm({
|
|
|
10248
10436
|
async detect() {
|
|
10249
10437
|
const opencode = resolveAgentExecutable("opencode");
|
|
10250
10438
|
if (opencode !== "opencode") {
|
|
10251
|
-
if (!(0,
|
|
10439
|
+
if (!(0, import_node_fs28.existsSync)(opencode)) {
|
|
10252
10440
|
return {
|
|
10253
10441
|
agent: "opencode",
|
|
10254
10442
|
installed: false,
|
|
@@ -11849,7 +12037,7 @@ function forkMessageSlice(from, throughIndex) {
|
|
|
11849
12037
|
function buildForkTranscriptAttachment(baseTitle, messages) {
|
|
11850
12038
|
const title = baseTitle || "Chat";
|
|
11851
12039
|
return {
|
|
11852
|
-
id: (0,
|
|
12040
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
11853
12041
|
name: `Transcript of ${title}.md`,
|
|
11854
12042
|
kind: "transcript",
|
|
11855
12043
|
content: formatTranscriptMarkdown(title, messages)
|
|
@@ -11906,11 +12094,11 @@ function forkChatTab(input) {
|
|
|
11906
12094
|
}
|
|
11907
12095
|
return tab;
|
|
11908
12096
|
}
|
|
11909
|
-
var
|
|
12097
|
+
var import_node_crypto6;
|
|
11910
12098
|
var init_chat_tabs = __esm({
|
|
11911
12099
|
"src/threads/chat-tabs.ts"() {
|
|
11912
12100
|
"use strict";
|
|
11913
|
-
|
|
12101
|
+
import_node_crypto6 = require("crypto");
|
|
11914
12102
|
init_context_compact();
|
|
11915
12103
|
init_teams();
|
|
11916
12104
|
init_worktree_labels();
|
|
@@ -12080,21 +12268,21 @@ function shouldRefreshReviewRequestTemplate(content) {
|
|
|
12080
12268
|
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
12081
12269
|
}
|
|
12082
12270
|
function readTextIfPresent(abs) {
|
|
12083
|
-
if (!(0,
|
|
12271
|
+
if (!(0, import_node_fs29.existsSync)(abs)) return null;
|
|
12084
12272
|
try {
|
|
12085
|
-
const content = (0,
|
|
12273
|
+
const content = (0, import_node_fs29.readFileSync)(abs, "utf8");
|
|
12086
12274
|
return content.trim() ? content : null;
|
|
12087
12275
|
} catch {
|
|
12088
12276
|
return null;
|
|
12089
12277
|
}
|
|
12090
12278
|
}
|
|
12091
12279
|
function readLocalGuidelines(worktreePath) {
|
|
12092
|
-
const localAbs = (0,
|
|
12280
|
+
const localAbs = (0, import_node_path29.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
12093
12281
|
const localContent = readTextIfPresent(localAbs);
|
|
12094
12282
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
12095
12283
|
return { path: REVIEW_REQUEST_PATH, content: localContent };
|
|
12096
12284
|
}
|
|
12097
|
-
const legacyAbs = (0,
|
|
12285
|
+
const legacyAbs = (0, import_node_path29.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
|
|
12098
12286
|
const legacyContent = readTextIfPresent(legacyAbs);
|
|
12099
12287
|
if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
|
|
12100
12288
|
return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
|
|
@@ -12110,20 +12298,20 @@ function skillGuidelines(content, source) {
|
|
|
12110
12298
|
};
|
|
12111
12299
|
}
|
|
12112
12300
|
function ensureReviewSkillFile(worktreePath) {
|
|
12113
|
-
const abs = (0,
|
|
12301
|
+
const abs = (0, import_node_path29.join)(worktreePath, REVIEW_SKILL_PATH);
|
|
12114
12302
|
const existing = readTextIfPresent(abs);
|
|
12115
12303
|
if (existing) {
|
|
12116
12304
|
return { path: REVIEW_SKILL_PATH, content: existing, wrote: false };
|
|
12117
12305
|
}
|
|
12118
|
-
const fromRepo = readTextIfPresent((0,
|
|
12306
|
+
const fromRepo = readTextIfPresent((0, import_node_path29.join)(worktreePath, REPO_REVIEW_PATH));
|
|
12119
12307
|
const fromLocal = readLocalGuidelines(worktreePath)?.content ?? null;
|
|
12120
12308
|
const content = wrapReviewSkillMarkdown(fromRepo ?? fromLocal ?? REVIEW_REQUEST_TEMPLATE);
|
|
12121
|
-
(0,
|
|
12122
|
-
(0,
|
|
12309
|
+
(0, import_node_fs29.mkdirSync)((0, import_node_path29.dirname)(abs), { recursive: true });
|
|
12310
|
+
(0, import_node_fs29.writeFileSync)(abs, content, "utf8");
|
|
12123
12311
|
return { path: REVIEW_SKILL_PATH, content, wrote: true };
|
|
12124
12312
|
}
|
|
12125
12313
|
function resolveReviewGuidelines(worktreePath) {
|
|
12126
|
-
const skillContent = readTextIfPresent((0,
|
|
12314
|
+
const skillContent = readTextIfPresent((0, import_node_path29.join)(worktreePath, REVIEW_SKILL_PATH));
|
|
12127
12315
|
if (skillContent) return skillGuidelines(skillContent, "skill");
|
|
12128
12316
|
const local = readLocalGuidelines(worktreePath);
|
|
12129
12317
|
if (local) {
|
|
@@ -12141,7 +12329,7 @@ function buildReviewRequestAttachment(content, opts) {
|
|
|
12141
12329
|
const path = opts?.path ?? REVIEW_SKILL_PATH;
|
|
12142
12330
|
const name = opts?.name ?? (path === REVIEW_SKILL_PATH ? REVIEW_SKILL_NAME : path === REPO_REVIEW_PATH ? REPO_REVIEW_NAME : REVIEW_REQUEST_NAME);
|
|
12143
12331
|
return {
|
|
12144
|
-
id: (0,
|
|
12332
|
+
id: (0, import_node_crypto7.randomUUID)(),
|
|
12145
12333
|
name,
|
|
12146
12334
|
kind: "file",
|
|
12147
12335
|
path,
|
|
@@ -12173,13 +12361,13 @@ async function requestReview(threadRef, send) {
|
|
|
12173
12361
|
const started = await send(tab.id, REVIEW_REQUEST_PREFILL);
|
|
12174
12362
|
return { tab: started, from };
|
|
12175
12363
|
}
|
|
12176
|
-
var
|
|
12364
|
+
var import_node_crypto7, import_node_fs29, import_node_path29, REPO_REVIEW_PATH, REPO_REVIEW_NAME, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
|
|
12177
12365
|
var init_request_review = __esm({
|
|
12178
12366
|
"src/review/request-review.ts"() {
|
|
12179
12367
|
"use strict";
|
|
12180
|
-
|
|
12181
|
-
|
|
12182
|
-
|
|
12368
|
+
import_node_crypto7 = require("crypto");
|
|
12369
|
+
import_node_fs29 = require("fs");
|
|
12370
|
+
import_node_path29 = require("path");
|
|
12183
12371
|
init_global_workspace();
|
|
12184
12372
|
init_chat_tabs();
|
|
12185
12373
|
init_thread_store();
|
|
@@ -12204,9 +12392,9 @@ function matchSimpleGlob(pattern, name) {
|
|
|
12204
12392
|
return new RegExp(`^${escaped}$`).test(name);
|
|
12205
12393
|
}
|
|
12206
12394
|
function readWorktreeInclude(repoPath) {
|
|
12207
|
-
const path = (0,
|
|
12208
|
-
if (!(0,
|
|
12209
|
-
return (0,
|
|
12395
|
+
const path = (0, import_node_path30.join)(repoPath, ".worktreeinclude");
|
|
12396
|
+
if (!(0, import_node_fs30.existsSync)(path)) return [];
|
|
12397
|
+
return (0, import_node_fs30.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
12210
12398
|
}
|
|
12211
12399
|
function resolveFilesToCopy(repoPath) {
|
|
12212
12400
|
const fromInclude = readWorktreeInclude(repoPath);
|
|
@@ -12216,10 +12404,10 @@ function resolveFilesToCopy(repoPath) {
|
|
|
12216
12404
|
if (settings?.fileIncludeGlobs?.length) {
|
|
12217
12405
|
const matched = [];
|
|
12218
12406
|
try {
|
|
12219
|
-
for (const entry of (0,
|
|
12407
|
+
for (const entry of (0, import_node_fs30.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
12220
12408
|
if (!entry.isFile()) continue;
|
|
12221
12409
|
for (const glob of settings.fileIncludeGlobs) {
|
|
12222
|
-
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0,
|
|
12410
|
+
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path30.basename)(glob), entry.name)) {
|
|
12223
12411
|
matched.push(entry.name);
|
|
12224
12412
|
break;
|
|
12225
12413
|
}
|
|
@@ -12231,7 +12419,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
12231
12419
|
}
|
|
12232
12420
|
const defaults = [];
|
|
12233
12421
|
try {
|
|
12234
|
-
for (const entry of (0,
|
|
12422
|
+
for (const entry of (0, import_node_fs30.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
12235
12423
|
if (entry.isFile() && entry.name.startsWith(".env")) {
|
|
12236
12424
|
defaults.push(entry.name);
|
|
12237
12425
|
}
|
|
@@ -12245,11 +12433,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
|
|
|
12245
12433
|
const patterns = resolveFilesToCopy(repoPath);
|
|
12246
12434
|
const copied = [];
|
|
12247
12435
|
for (const rel of patterns) {
|
|
12248
|
-
const src = (0,
|
|
12249
|
-
if (!(0,
|
|
12250
|
-
const dest = (0,
|
|
12251
|
-
(0,
|
|
12252
|
-
(0,
|
|
12436
|
+
const src = (0, import_node_path30.join)(repoPath, rel);
|
|
12437
|
+
if (!(0, import_node_fs30.existsSync)(src)) continue;
|
|
12438
|
+
const dest = (0, import_node_path30.join)(worktreePath, rel);
|
|
12439
|
+
(0, import_node_fs30.mkdirSync)((0, import_node_path30.dirname)(dest), { recursive: true });
|
|
12440
|
+
(0, import_node_fs30.copyFileSync)(src, dest);
|
|
12253
12441
|
copied.push(rel);
|
|
12254
12442
|
}
|
|
12255
12443
|
return copied;
|
|
@@ -12284,7 +12472,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
|
|
|
12284
12472
|
const env = stripNestedElectronEnv({
|
|
12285
12473
|
...baseEnv ?? process.env
|
|
12286
12474
|
});
|
|
12287
|
-
const name = opts.workspaceName ?? (0,
|
|
12475
|
+
const name = opts.workspaceName ?? (0, import_node_path30.basename)(opts.worktreePath);
|
|
12288
12476
|
const ports = opts.ports ?? [];
|
|
12289
12477
|
const primary = ports[0];
|
|
12290
12478
|
env.SIDEBOARD_WORKSPACE_NAME = name;
|
|
@@ -12439,6 +12627,7 @@ async function runConventionSetup(repoPath, worktreePath, onLine, opts) {
|
|
|
12439
12627
|
};
|
|
12440
12628
|
}
|
|
12441
12629
|
async function runWorkspaceSetup(repoPath, worktreePath, onLine, opts) {
|
|
12630
|
+
await ensureWorktreeSideboardIgnored(worktreePath);
|
|
12442
12631
|
const reviewSkill = ensureReviewSkillFile(worktreePath);
|
|
12443
12632
|
if (reviewSkill.wrote) {
|
|
12444
12633
|
onLine?.(
|
|
@@ -12545,13 +12734,13 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
|
12545
12734
|
done: handle.done
|
|
12546
12735
|
};
|
|
12547
12736
|
}
|
|
12548
|
-
var
|
|
12737
|
+
var import_node_fs30, import_node_net, import_node_path30, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
|
|
12549
12738
|
var init_conductor = __esm({
|
|
12550
12739
|
"src/hook/conductor.ts"() {
|
|
12551
12740
|
"use strict";
|
|
12552
|
-
|
|
12741
|
+
import_node_fs30 = require("fs");
|
|
12553
12742
|
import_node_net = require("net");
|
|
12554
|
-
|
|
12743
|
+
import_node_path30 = require("path");
|
|
12555
12744
|
import_execa4 = require("execa");
|
|
12556
12745
|
import_node_readline3 = require("readline");
|
|
12557
12746
|
init_settings();
|
|
@@ -12560,6 +12749,7 @@ var init_conductor = __esm({
|
|
|
12560
12749
|
init_cursor_worktrees();
|
|
12561
12750
|
init_git_auth_mode();
|
|
12562
12751
|
init_request_review();
|
|
12752
|
+
init_worktree_exclude();
|
|
12563
12753
|
init_nested_electron_env();
|
|
12564
12754
|
PORT_RANGE_SIZE = 10;
|
|
12565
12755
|
cachedLoginEnv = null;
|
|
@@ -12577,9 +12767,9 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
12577
12767
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
12578
12768
|
);
|
|
12579
12769
|
const homeRoot = sideboardWorkspacesDir();
|
|
12580
|
-
if ((0,
|
|
12770
|
+
if ((0, import_node_fs31.existsSync)(homeRoot)) {
|
|
12581
12771
|
try {
|
|
12582
|
-
for (const entry of (0,
|
|
12772
|
+
for (const entry of (0, import_node_fs31.readdirSync)(homeRoot, { withFileTypes: true })) {
|
|
12583
12773
|
if (!entry.isDirectory()) continue;
|
|
12584
12774
|
void entry;
|
|
12585
12775
|
}
|
|
@@ -12589,7 +12779,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
12589
12779
|
const orphans = [];
|
|
12590
12780
|
const seen = /* @__PURE__ */ new Set();
|
|
12591
12781
|
for (const repoPath of repos) {
|
|
12592
|
-
if (!repoPath || !(0,
|
|
12782
|
+
if (!repoPath || !(0, import_node_fs31.existsSync)(repoPath)) continue;
|
|
12593
12783
|
try {
|
|
12594
12784
|
const wts = await listWorktrees(repoPath);
|
|
12595
12785
|
for (const wt of wts) {
|
|
@@ -12600,7 +12790,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
12600
12790
|
seen.add(path);
|
|
12601
12791
|
let mtimeMs = 0;
|
|
12602
12792
|
try {
|
|
12603
|
-
mtimeMs = (0,
|
|
12793
|
+
mtimeMs = (0, import_node_fs31.statSync)(path).mtimeMs;
|
|
12604
12794
|
} catch {
|
|
12605
12795
|
mtimeMs = 0;
|
|
12606
12796
|
}
|
|
@@ -12610,16 +12800,16 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
12610
12800
|
}
|
|
12611
12801
|
try {
|
|
12612
12802
|
const root = worktreesRoot(repoPath);
|
|
12613
|
-
if ((0,
|
|
12614
|
-
for (const entry of (0,
|
|
12803
|
+
if ((0, import_node_fs31.existsSync)(root)) {
|
|
12804
|
+
for (const entry of (0, import_node_fs31.readdirSync)(root, { withFileTypes: true })) {
|
|
12615
12805
|
if (!entry.isDirectory()) continue;
|
|
12616
|
-
const path = (0,
|
|
12806
|
+
const path = (0, import_node_path31.join)(root, entry.name).replace(/\/$/, "");
|
|
12617
12807
|
if (known.has(path) || seen.has(path)) continue;
|
|
12618
|
-
if (!(0,
|
|
12808
|
+
if (!(0, import_node_fs31.existsSync)((0, import_node_path31.join)(path, ".git"))) continue;
|
|
12619
12809
|
seen.add(path);
|
|
12620
12810
|
let mtimeMs = 0;
|
|
12621
12811
|
try {
|
|
12622
|
-
mtimeMs = (0,
|
|
12812
|
+
mtimeMs = (0, import_node_fs31.statSync)(path).mtimeMs;
|
|
12623
12813
|
} catch {
|
|
12624
12814
|
mtimeMs = Date.now();
|
|
12625
12815
|
}
|
|
@@ -12671,12 +12861,12 @@ function shouldRunWorktreeCleanup(settings = loadAppSettings()) {
|
|
|
12671
12861
|
const elapsed = Date.now() - Date.parse(last);
|
|
12672
12862
|
return elapsed >= intervalHours * 36e5;
|
|
12673
12863
|
}
|
|
12674
|
-
var
|
|
12864
|
+
var import_node_fs31, import_node_path31;
|
|
12675
12865
|
var init_orphan_cleanup = __esm({
|
|
12676
12866
|
"src/git/orphan-cleanup.ts"() {
|
|
12677
12867
|
"use strict";
|
|
12678
|
-
|
|
12679
|
-
|
|
12868
|
+
import_node_fs31 = require("fs");
|
|
12869
|
+
import_node_path31 = require("path");
|
|
12680
12870
|
init_worktree();
|
|
12681
12871
|
init_thread_store();
|
|
12682
12872
|
init_paths();
|
|
@@ -12783,38 +12973,38 @@ __export(workspaces_exports, {
|
|
|
12783
12973
|
syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
|
|
12784
12974
|
});
|
|
12785
12975
|
function workspacesFile() {
|
|
12786
|
-
return (0,
|
|
12976
|
+
return (0, import_node_path32.join)(appDataDir(), "workspaces.json");
|
|
12787
12977
|
}
|
|
12788
12978
|
function removedWorkspacesFile() {
|
|
12789
|
-
return (0,
|
|
12979
|
+
return (0, import_node_path32.join)(appDataDir(), "removed-workspaces.json");
|
|
12790
12980
|
}
|
|
12791
12981
|
function readAll() {
|
|
12792
12982
|
const path = workspacesFile();
|
|
12793
|
-
if (!(0,
|
|
12983
|
+
if (!(0, import_node_fs32.existsSync)(path)) return [];
|
|
12794
12984
|
try {
|
|
12795
|
-
const raw = JSON.parse((0,
|
|
12985
|
+
const raw = JSON.parse((0, import_node_fs32.readFileSync)(path, "utf8"));
|
|
12796
12986
|
return Array.isArray(raw) ? raw : [];
|
|
12797
12987
|
} catch {
|
|
12798
12988
|
return [];
|
|
12799
12989
|
}
|
|
12800
12990
|
}
|
|
12801
12991
|
function writeAll(list) {
|
|
12802
|
-
(0,
|
|
12803
|
-
(0,
|
|
12992
|
+
(0, import_node_fs32.mkdirSync)(appDataDir(), { recursive: true });
|
|
12993
|
+
(0, import_node_fs32.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
|
|
12804
12994
|
}
|
|
12805
12995
|
function readRemoved() {
|
|
12806
12996
|
const path = removedWorkspacesFile();
|
|
12807
|
-
if (!(0,
|
|
12997
|
+
if (!(0, import_node_fs32.existsSync)(path)) return /* @__PURE__ */ new Set();
|
|
12808
12998
|
try {
|
|
12809
|
-
const raw = JSON.parse((0,
|
|
12999
|
+
const raw = JSON.parse((0, import_node_fs32.readFileSync)(path, "utf8"));
|
|
12810
13000
|
return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
|
|
12811
13001
|
} catch {
|
|
12812
13002
|
return /* @__PURE__ */ new Set();
|
|
12813
13003
|
}
|
|
12814
13004
|
}
|
|
12815
13005
|
function writeRemoved(paths) {
|
|
12816
|
-
(0,
|
|
12817
|
-
(0,
|
|
13006
|
+
(0, import_node_fs32.mkdirSync)(appDataDir(), { recursive: true });
|
|
13007
|
+
(0, import_node_fs32.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
|
|
12818
13008
|
}
|
|
12819
13009
|
function rememberRemoved(repoPath) {
|
|
12820
13010
|
const next = readRemoved();
|
|
@@ -12837,7 +13027,7 @@ function listWorkspaces() {
|
|
|
12837
13027
|
async function addWorkspace(repoPath) {
|
|
12838
13028
|
const root = await resolveRepoRoot(repoPath);
|
|
12839
13029
|
if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
|
|
12840
|
-
if (!(0,
|
|
13030
|
+
if (!(0, import_node_fs32.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
|
|
12841
13031
|
forgetRemoved(root);
|
|
12842
13032
|
await ensureGhPreferOrigin(root);
|
|
12843
13033
|
const current = readAll();
|
|
@@ -12845,7 +13035,7 @@ async function addWorkspace(repoPath) {
|
|
|
12845
13035
|
if (existing) return existing;
|
|
12846
13036
|
const next = {
|
|
12847
13037
|
path: root,
|
|
12848
|
-
name: (0,
|
|
13038
|
+
name: (0, import_node_path32.basename)(root),
|
|
12849
13039
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12850
13040
|
};
|
|
12851
13041
|
writeAll([...current, next]);
|
|
@@ -12867,10 +13057,10 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
12867
13057
|
if (!path || path === "/" || isGlobalRepoPath(path) || byPath.has(path) || removed.has(path)) {
|
|
12868
13058
|
continue;
|
|
12869
13059
|
}
|
|
12870
|
-
if (!(0,
|
|
13060
|
+
if (!(0, import_node_fs32.existsSync)(path)) continue;
|
|
12871
13061
|
const ws = {
|
|
12872
13062
|
path,
|
|
12873
|
-
name: (0,
|
|
13063
|
+
name: (0, import_node_path32.basename)(path),
|
|
12874
13064
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12875
13065
|
};
|
|
12876
13066
|
byPath.set(path, ws);
|
|
@@ -12880,12 +13070,12 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
12880
13070
|
if (dirty) writeAll(next);
|
|
12881
13071
|
return next.sort((a, b) => a.name.localeCompare(b.name));
|
|
12882
13072
|
}
|
|
12883
|
-
var
|
|
13073
|
+
var import_node_fs32, import_node_path32;
|
|
12884
13074
|
var init_workspaces2 = __esm({
|
|
12885
13075
|
"src/store/workspaces.ts"() {
|
|
12886
13076
|
"use strict";
|
|
12887
|
-
|
|
12888
|
-
|
|
13077
|
+
import_node_fs32 = require("fs");
|
|
13078
|
+
import_node_path32 = require("path");
|
|
12889
13079
|
init_paths();
|
|
12890
13080
|
init_global_workspace();
|
|
12891
13081
|
init_worktree();
|
|
@@ -12898,12 +13088,12 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
12898
13088
|
if (!url) throw new Error("Clone URL is required");
|
|
12899
13089
|
let name = opts.name?.trim();
|
|
12900
13090
|
if (!name) {
|
|
12901
|
-
const leaf = (0,
|
|
13091
|
+
const leaf = (0, import_node_path33.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
|
|
12902
13092
|
name = leaf || "repo";
|
|
12903
13093
|
}
|
|
12904
13094
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
12905
|
-
const dest = (0,
|
|
12906
|
-
if ((0,
|
|
13095
|
+
const dest = (0, import_node_path33.join)(sideboardReposDir(), name);
|
|
13096
|
+
if ((0, import_node_fs33.existsSync)(dest)) {
|
|
12907
13097
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
12908
13098
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
12909
13099
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -12918,12 +13108,12 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
12918
13108
|
const workspace = await ensureWorkspace(repoPath);
|
|
12919
13109
|
return { repoPath, workspace };
|
|
12920
13110
|
}
|
|
12921
|
-
var
|
|
13111
|
+
var import_node_fs33, import_node_path33, import_execa6;
|
|
12922
13112
|
var init_clone_repo = __esm({
|
|
12923
13113
|
"src/git/clone-repo.ts"() {
|
|
12924
13114
|
"use strict";
|
|
12925
|
-
|
|
12926
|
-
|
|
13115
|
+
import_node_fs33 = require("fs");
|
|
13116
|
+
import_node_path33 = require("path");
|
|
12927
13117
|
import_execa6 = require("execa");
|
|
12928
13118
|
init_paths();
|
|
12929
13119
|
init_workspaces2();
|
|
@@ -12933,11 +13123,11 @@ var init_clone_repo = __esm({
|
|
|
12933
13123
|
|
|
12934
13124
|
// src/store/desktop-host.ts
|
|
12935
13125
|
function desktopHostPidPath() {
|
|
12936
|
-
return (0,
|
|
13126
|
+
return (0, import_node_path34.join)(appDataDir(), "desktop-host.pid");
|
|
12937
13127
|
}
|
|
12938
13128
|
function readDesktopHostPid() {
|
|
12939
13129
|
try {
|
|
12940
|
-
const pid = Number.parseInt((0,
|
|
13130
|
+
const pid = Number.parseInt((0, import_node_fs34.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
|
|
12941
13131
|
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
12942
13132
|
return pid;
|
|
12943
13133
|
} catch {
|
|
@@ -12963,12 +13153,12 @@ function thisProcessShouldDrainAgentQueues() {
|
|
|
12963
13153
|
if (isThisProcessDesktopHost()) return true;
|
|
12964
13154
|
return !isDesktopHostAlive();
|
|
12965
13155
|
}
|
|
12966
|
-
var
|
|
13156
|
+
var import_node_fs34, import_node_path34;
|
|
12967
13157
|
var init_desktop_host = __esm({
|
|
12968
13158
|
"src/store/desktop-host.ts"() {
|
|
12969
13159
|
"use strict";
|
|
12970
|
-
|
|
12971
|
-
|
|
13160
|
+
import_node_fs34 = require("fs");
|
|
13161
|
+
import_node_path34 = require("path");
|
|
12972
13162
|
init_paths();
|
|
12973
13163
|
}
|
|
12974
13164
|
});
|
|
@@ -13970,7 +14160,7 @@ function persistCreateAttachments(worktreePath, attachments) {
|
|
|
13970
14160
|
}
|
|
13971
14161
|
async function createThread(input, _onSetupLine) {
|
|
13972
14162
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
13973
|
-
if (!(0,
|
|
14163
|
+
if (!(0, import_node_fs35.existsSync)(repoPath)) {
|
|
13974
14164
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
13975
14165
|
}
|
|
13976
14166
|
if (input.reuseExisting !== false) {
|
|
@@ -14145,11 +14335,11 @@ async function listLinearIssues(agent, repoPath) {
|
|
|
14145
14335
|
}
|
|
14146
14336
|
return adapter.listLinearIssues(repoPath);
|
|
14147
14337
|
}
|
|
14148
|
-
var
|
|
14338
|
+
var import_node_fs35;
|
|
14149
14339
|
var init_create = __esm({
|
|
14150
14340
|
"src/threads/create.ts"() {
|
|
14151
14341
|
"use strict";
|
|
14152
|
-
|
|
14342
|
+
import_node_fs35 = require("fs");
|
|
14153
14343
|
init_detect();
|
|
14154
14344
|
init_worktree();
|
|
14155
14345
|
init_home_board();
|
|
@@ -14252,20 +14442,20 @@ function writeTurnLive(threadId, progress) {
|
|
|
14252
14442
|
const path = threadLivePath(threadId);
|
|
14253
14443
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
14254
14444
|
try {
|
|
14255
|
-
(0,
|
|
14256
|
-
(0,
|
|
14445
|
+
(0, import_node_fs36.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
|
|
14446
|
+
(0, import_node_fs36.renameSync)(tmp, path);
|
|
14257
14447
|
} catch {
|
|
14258
14448
|
try {
|
|
14259
|
-
(0,
|
|
14449
|
+
(0, import_node_fs36.unlinkSync)(tmp);
|
|
14260
14450
|
} catch {
|
|
14261
14451
|
}
|
|
14262
14452
|
}
|
|
14263
14453
|
}
|
|
14264
14454
|
function readTurnLive(threadId) {
|
|
14265
14455
|
const path = threadLivePath(threadId);
|
|
14266
|
-
if (!(0,
|
|
14456
|
+
if (!(0, import_node_fs36.existsSync)(path)) return null;
|
|
14267
14457
|
try {
|
|
14268
|
-
const raw = JSON.parse((0,
|
|
14458
|
+
const raw = JSON.parse((0, import_node_fs36.readFileSync)(path, "utf8"));
|
|
14269
14459
|
if (!raw || typeof raw.summary !== "string") return null;
|
|
14270
14460
|
return raw;
|
|
14271
14461
|
} catch {
|
|
@@ -14277,17 +14467,17 @@ function clearTurnLive(threadId) {
|
|
|
14277
14467
|
if (buf?.timer) clearTimeout(buf.timer);
|
|
14278
14468
|
buffers.delete(threadId);
|
|
14279
14469
|
const path = threadLivePath(threadId);
|
|
14280
|
-
if (!(0,
|
|
14470
|
+
if (!(0, import_node_fs36.existsSync)(path)) return;
|
|
14281
14471
|
try {
|
|
14282
|
-
(0,
|
|
14472
|
+
(0, import_node_fs36.unlinkSync)(path);
|
|
14283
14473
|
} catch {
|
|
14284
14474
|
}
|
|
14285
14475
|
}
|
|
14286
|
-
var
|
|
14476
|
+
var import_node_fs36, buffers, FLUSH_MS, MAX_PARTS;
|
|
14287
14477
|
var init_turn_live = __esm({
|
|
14288
14478
|
"src/store/turn-live.ts"() {
|
|
14289
14479
|
"use strict";
|
|
14290
|
-
|
|
14480
|
+
import_node_fs36 = require("fs");
|
|
14291
14481
|
init_message_parts();
|
|
14292
14482
|
init_paths();
|
|
14293
14483
|
buffers = /* @__PURE__ */ new Map();
|
|
@@ -14461,7 +14651,7 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
|
|
|
14461
14651
|
`- Do not wait on the limited ${from.agent} account; keep going on ${fallbackAgent}.`
|
|
14462
14652
|
].join("\n");
|
|
14463
14653
|
return {
|
|
14464
|
-
id: (0,
|
|
14654
|
+
id: (0, import_node_crypto8.randomUUID)(),
|
|
14465
14655
|
name: "Orchestration quota handoff.md",
|
|
14466
14656
|
kind: "transcript",
|
|
14467
14657
|
content: body
|
|
@@ -14482,11 +14672,11 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
|
|
|
14482
14672
|
sourceType: "orchestration"
|
|
14483
14673
|
});
|
|
14484
14674
|
}
|
|
14485
|
-
var
|
|
14675
|
+
var import_node_crypto8, QUOTA_CONTINUE_PROMPT, QUOTA_RESUME_PROMPT;
|
|
14486
14676
|
var init_quota_failover = __esm({
|
|
14487
14677
|
"src/orchestrator/quota-failover.ts"() {
|
|
14488
14678
|
"use strict";
|
|
14489
|
-
|
|
14679
|
+
import_node_crypto8 = require("crypto");
|
|
14490
14680
|
init_session_quota();
|
|
14491
14681
|
init_app_settings();
|
|
14492
14682
|
init_global_workspace();
|
|
@@ -14503,7 +14693,7 @@ var init_quota_failover = __esm({
|
|
|
14503
14693
|
// src/threads/adopt.ts
|
|
14504
14694
|
function thisModuleFile() {
|
|
14505
14695
|
const cjsFile = typeof __filename !== "undefined" ? __filename : "";
|
|
14506
|
-
return cjsFile || process.argv[1] || (0,
|
|
14696
|
+
return cjsFile || process.argv[1] || (0, import_node_path35.join)(process.cwd(), "package.json");
|
|
14507
14697
|
}
|
|
14508
14698
|
function openReadonlySqlite(file) {
|
|
14509
14699
|
const req = (0, import_node_module4.createRequire)(thisModuleFile());
|
|
@@ -14521,21 +14711,21 @@ function mapAgentType(raw) {
|
|
|
14521
14711
|
return null;
|
|
14522
14712
|
}
|
|
14523
14713
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
14524
|
-
if (!workspacePath || !(0,
|
|
14714
|
+
if (!workspacePath || !(0, import_node_fs37.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
14525
14715
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
14526
14716
|
let best = null;
|
|
14527
14717
|
let hashes;
|
|
14528
14718
|
try {
|
|
14529
|
-
hashes = (0,
|
|
14719
|
+
hashes = (0, import_node_fs37.readdirSync)(CURSOR_SDK_STORE);
|
|
14530
14720
|
} catch {
|
|
14531
14721
|
return null;
|
|
14532
14722
|
}
|
|
14533
14723
|
for (const hash of hashes) {
|
|
14534
|
-
const agentsFile = (0,
|
|
14535
|
-
if (!(0,
|
|
14724
|
+
const agentsFile = (0, import_node_path35.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
14725
|
+
if (!(0, import_node_fs37.existsSync)(agentsFile)) continue;
|
|
14536
14726
|
let text5;
|
|
14537
14727
|
try {
|
|
14538
|
-
text5 = (0,
|
|
14728
|
+
text5 = (0, import_node_fs37.readFileSync)(agentsFile, "utf8");
|
|
14539
14729
|
} catch {
|
|
14540
14730
|
continue;
|
|
14541
14731
|
}
|
|
@@ -14559,7 +14749,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
14559
14749
|
return best?.agentId ?? null;
|
|
14560
14750
|
}
|
|
14561
14751
|
async function adoptThread(input) {
|
|
14562
|
-
if (!(0,
|
|
14752
|
+
if (!(0, import_node_fs37.existsSync)(input.worktreePath)) {
|
|
14563
14753
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
14564
14754
|
}
|
|
14565
14755
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -14580,21 +14770,23 @@ async function adoptThread(input) {
|
|
|
14580
14770
|
writeThread(thread);
|
|
14581
14771
|
const { ensureWorkspace: ensureWorkspace2 } = await Promise.resolve().then(() => (init_workspaces2(), workspaces_exports));
|
|
14582
14772
|
await ensureWorkspace2(repoPath);
|
|
14773
|
+
const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await Promise.resolve().then(() => (init_worktree_exclude(), worktree_exclude_exports));
|
|
14774
|
+
await ensureWorktreeSideboardIgnored2(input.worktreePath);
|
|
14583
14775
|
return thread;
|
|
14584
14776
|
}
|
|
14585
14777
|
function listConductorWorkspaces() {
|
|
14586
|
-
if (!(0,
|
|
14778
|
+
if (!(0, import_node_fs37.existsSync)(CONDUCTOR_DB)) {
|
|
14587
14779
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
14588
14780
|
}
|
|
14589
|
-
const tmp = (0,
|
|
14590
|
-
const snapshot = (0,
|
|
14781
|
+
const tmp = (0, import_node_fs37.mkdtempSync)((0, import_node_path35.join)((0, import_node_os11.tmpdir)(), "sideboard-conductor-"));
|
|
14782
|
+
const snapshot = (0, import_node_path35.join)(tmp, "conductor.db");
|
|
14591
14783
|
try {
|
|
14592
|
-
(0,
|
|
14784
|
+
(0, import_node_fs37.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
14593
14785
|
for (const suffix of ["-wal", "-shm"]) {
|
|
14594
14786
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
14595
|
-
if ((0,
|
|
14787
|
+
if ((0, import_node_fs37.existsSync)(src)) {
|
|
14596
14788
|
try {
|
|
14597
|
-
(0,
|
|
14789
|
+
(0, import_node_fs37.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
14598
14790
|
} catch {
|
|
14599
14791
|
}
|
|
14600
14792
|
}
|
|
@@ -14670,22 +14862,22 @@ function listConductorWorkspaces() {
|
|
|
14670
14862
|
db.close();
|
|
14671
14863
|
}
|
|
14672
14864
|
} finally {
|
|
14673
|
-
(0,
|
|
14865
|
+
(0, import_node_fs37.rmSync)(tmp, { recursive: true, force: true });
|
|
14674
14866
|
}
|
|
14675
14867
|
}
|
|
14676
14868
|
function importConductorWorkspace(workspaceId) {
|
|
14677
|
-
if (!(0,
|
|
14869
|
+
if (!(0, import_node_fs37.existsSync)(CONDUCTOR_DB)) {
|
|
14678
14870
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
14679
14871
|
}
|
|
14680
|
-
const tmp = (0,
|
|
14681
|
-
const snapshot = (0,
|
|
14872
|
+
const tmp = (0, import_node_fs37.mkdtempSync)((0, import_node_path35.join)((0, import_node_os11.tmpdir)(), "sideboard-conductor-"));
|
|
14873
|
+
const snapshot = (0, import_node_path35.join)(tmp, "conductor.db");
|
|
14682
14874
|
try {
|
|
14683
|
-
(0,
|
|
14875
|
+
(0, import_node_fs37.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
14684
14876
|
for (const suffix of ["-wal", "-shm"]) {
|
|
14685
14877
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
14686
|
-
if ((0,
|
|
14878
|
+
if ((0, import_node_fs37.existsSync)(src)) {
|
|
14687
14879
|
try {
|
|
14688
|
-
(0,
|
|
14880
|
+
(0, import_node_fs37.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
14689
14881
|
} catch {
|
|
14690
14882
|
}
|
|
14691
14883
|
}
|
|
@@ -14703,7 +14895,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
14703
14895
|
).get(workspaceId);
|
|
14704
14896
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
14705
14897
|
const worktreePath = String(row.workspacePath);
|
|
14706
|
-
if (!(0,
|
|
14898
|
+
if (!(0, import_node_fs37.existsSync)(worktreePath)) {
|
|
14707
14899
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
14708
14900
|
}
|
|
14709
14901
|
let sessionId = null;
|
|
@@ -14766,31 +14958,31 @@ function importConductorWorkspace(workspaceId) {
|
|
|
14766
14958
|
db.close();
|
|
14767
14959
|
}
|
|
14768
14960
|
} finally {
|
|
14769
|
-
(0,
|
|
14961
|
+
(0, import_node_fs37.rmSync)(tmp, { recursive: true, force: true });
|
|
14770
14962
|
}
|
|
14771
14963
|
}
|
|
14772
14964
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
14773
14965
|
return importConductorWorkspace(workspaceId);
|
|
14774
14966
|
}
|
|
14775
|
-
var import_node_child_process3,
|
|
14967
|
+
var import_node_child_process3, import_node_fs37, import_node_os11, import_node_path35, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
|
|
14776
14968
|
var init_adopt = __esm({
|
|
14777
14969
|
"src/threads/adopt.ts"() {
|
|
14778
14970
|
"use strict";
|
|
14779
14971
|
import_node_child_process3 = require("child_process");
|
|
14780
|
-
|
|
14781
|
-
|
|
14782
|
-
|
|
14972
|
+
import_node_fs37 = require("fs");
|
|
14973
|
+
import_node_os11 = require("os");
|
|
14974
|
+
import_node_path35 = require("path");
|
|
14783
14975
|
import_node_module4 = require("module");
|
|
14784
14976
|
init_worktree();
|
|
14785
14977
|
init_thread_store();
|
|
14786
|
-
CONDUCTOR_APP_SUPPORT = (0,
|
|
14978
|
+
CONDUCTOR_APP_SUPPORT = (0, import_node_path35.join)(
|
|
14787
14979
|
process.env.HOME ?? "",
|
|
14788
14980
|
"Library",
|
|
14789
14981
|
"Application Support",
|
|
14790
14982
|
"com.conductor.app"
|
|
14791
14983
|
);
|
|
14792
|
-
CONDUCTOR_DB = (0,
|
|
14793
|
-
CURSOR_SDK_STORE = (0,
|
|
14984
|
+
CONDUCTOR_DB = (0, import_node_path35.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
14985
|
+
CURSOR_SDK_STORE = (0, import_node_path35.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
14794
14986
|
}
|
|
14795
14987
|
});
|
|
14796
14988
|
|
|
@@ -14857,7 +15049,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
14857
15049
|
let createdWorktree = false;
|
|
14858
15050
|
const trees = await listWorktrees(repoPath);
|
|
14859
15051
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
14860
|
-
if (checkedOut?.path && (0,
|
|
15052
|
+
if (checkedOut?.path && (0, import_node_fs38.existsSync)(checkedOut.path)) {
|
|
14861
15053
|
if (input.reuseExistingWorktree !== false) {
|
|
14862
15054
|
worktreePath = checkedOut.path;
|
|
14863
15055
|
} else {
|
|
@@ -14999,7 +15191,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
14999
15191
|
async function createPrStack(input, onSetupLine) {
|
|
15000
15192
|
await requireAgent(input.agent);
|
|
15001
15193
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
15002
|
-
if (!(0,
|
|
15194
|
+
if (!(0, import_node_fs38.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
15003
15195
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
15004
15196
|
const status = await detectGhStack(repoPath);
|
|
15005
15197
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -15066,7 +15258,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
15066
15258
|
}
|
|
15067
15259
|
}
|
|
15068
15260
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
15069
|
-
if (!claimed.has(bootstrap.worktreePath) && (0,
|
|
15261
|
+
if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs38.existsSync)(bootstrap.worktreePath)) {
|
|
15070
15262
|
try {
|
|
15071
15263
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
15072
15264
|
deleteBranch: bootstrap.branchName
|
|
@@ -15076,11 +15268,11 @@ async function createPrStack(input, onSetupLine) {
|
|
|
15076
15268
|
}
|
|
15077
15269
|
return { stack, threads, createdThreadIds };
|
|
15078
15270
|
}
|
|
15079
|
-
var
|
|
15271
|
+
var import_node_fs38;
|
|
15080
15272
|
var init_stack_layers = __esm({
|
|
15081
15273
|
"src/threads/stack-layers.ts"() {
|
|
15082
15274
|
"use strict";
|
|
15083
|
-
|
|
15275
|
+
import_node_fs38 = require("fs");
|
|
15084
15276
|
init_detect();
|
|
15085
15277
|
init_run();
|
|
15086
15278
|
init_stack();
|
|
@@ -15093,7 +15285,7 @@ var init_stack_layers = __esm({
|
|
|
15093
15285
|
|
|
15094
15286
|
// src/diff/diff.ts
|
|
15095
15287
|
async function inspectGitWorktree(worktreePath) {
|
|
15096
|
-
if (!worktreePath || !(0,
|
|
15288
|
+
if (!worktreePath || !(0, import_node_fs39.existsSync)(worktreePath)) return "missing_worktree";
|
|
15097
15289
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
15098
15290
|
reject: false
|
|
15099
15291
|
});
|
|
@@ -15101,7 +15293,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
15101
15293
|
return "ok";
|
|
15102
15294
|
}
|
|
15103
15295
|
async function initializeGitRepository(worktreePath) {
|
|
15104
|
-
if (!worktreePath || !(0,
|
|
15296
|
+
if (!worktreePath || !(0, import_node_fs39.existsSync)(worktreePath)) {
|
|
15105
15297
|
throw new Error("Worktree not found");
|
|
15106
15298
|
}
|
|
15107
15299
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -15235,11 +15427,11 @@ new file mode 100644
|
|
|
15235
15427
|
};
|
|
15236
15428
|
}
|
|
15237
15429
|
async function untrackedPatch(worktreePath, path, maxHunk) {
|
|
15238
|
-
const abs = (0,
|
|
15430
|
+
const abs = (0, import_node_path36.join)(worktreePath, path);
|
|
15239
15431
|
try {
|
|
15240
|
-
const st = (0,
|
|
15432
|
+
const st = (0, import_node_fs39.statSync)(abs);
|
|
15241
15433
|
if (st.isFile() && st.size > maxHunk) {
|
|
15242
|
-
const buf = (0,
|
|
15434
|
+
const buf = (0, import_node_fs39.readFileSync)(abs).subarray(0, maxHunk);
|
|
15243
15435
|
return syntheticAddPatch(path, buf.toString("utf8"), maxHunk);
|
|
15244
15436
|
}
|
|
15245
15437
|
} catch {
|
|
@@ -15728,8 +15920,8 @@ function isImageRelativePath(relativePath) {
|
|
|
15728
15920
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
15729
15921
|
assertSafeRelativePath(relativePath);
|
|
15730
15922
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
15731
|
-
const abs = (0,
|
|
15732
|
-
const st = (0,
|
|
15923
|
+
const abs = (0, import_node_path36.join)(worktreePath, relativePath);
|
|
15924
|
+
const st = (0, import_node_fs39.statSync)(abs);
|
|
15733
15925
|
if (!st.isFile()) {
|
|
15734
15926
|
throw new Error(`Not a file: ${relativePath}`);
|
|
15735
15927
|
}
|
|
@@ -15738,7 +15930,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
15738
15930
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
15739
15931
|
);
|
|
15740
15932
|
}
|
|
15741
|
-
const buf = (0,
|
|
15933
|
+
const buf = (0, import_node_fs39.readFileSync)(abs);
|
|
15742
15934
|
return {
|
|
15743
15935
|
path: relativePath,
|
|
15744
15936
|
contentBase64: buf.toString("base64"),
|
|
@@ -15748,12 +15940,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
15748
15940
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
15749
15941
|
assertSafeRelativePath(relativePath);
|
|
15750
15942
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
15751
|
-
const abs = (0,
|
|
15752
|
-
const st = (0,
|
|
15943
|
+
const abs = (0, import_node_path36.join)(worktreePath, relativePath);
|
|
15944
|
+
const st = (0, import_node_fs39.statSync)(abs);
|
|
15753
15945
|
if (!st.isFile()) {
|
|
15754
15946
|
throw new Error(`Not a file: ${relativePath}`);
|
|
15755
15947
|
}
|
|
15756
|
-
const buf = (0,
|
|
15948
|
+
const buf = (0, import_node_fs39.readFileSync)(abs);
|
|
15757
15949
|
if (isImageRelativePath(relativePath)) {
|
|
15758
15950
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
15759
15951
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -15796,9 +15988,9 @@ function assertSafeRelativePath(relativePath) {
|
|
|
15796
15988
|
}
|
|
15797
15989
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
15798
15990
|
assertSafeRelativePath(relativePath);
|
|
15799
|
-
const abs = (0,
|
|
15800
|
-
(0,
|
|
15801
|
-
(0,
|
|
15991
|
+
const abs = (0, import_node_path36.join)(worktreePath, relativePath);
|
|
15992
|
+
(0, import_node_fs39.mkdirSync)((0, import_node_path36.dirname)(abs), { recursive: true });
|
|
15993
|
+
(0, import_node_fs39.writeFileSync)(abs, content, "utf8");
|
|
15802
15994
|
return { path: relativePath };
|
|
15803
15995
|
}
|
|
15804
15996
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
@@ -15815,12 +16007,12 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
|
15815
16007
|
truncated: full.files.length > maxFiles
|
|
15816
16008
|
};
|
|
15817
16009
|
}
|
|
15818
|
-
var
|
|
16010
|
+
var import_node_fs39, import_node_path36, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
|
|
15819
16011
|
var init_diff = __esm({
|
|
15820
16012
|
"src/diff/diff.ts"() {
|
|
15821
16013
|
"use strict";
|
|
15822
|
-
|
|
15823
|
-
|
|
16014
|
+
import_node_fs39 = require("fs");
|
|
16015
|
+
import_node_path36 = require("path");
|
|
15824
16016
|
init_run();
|
|
15825
16017
|
init_worktree();
|
|
15826
16018
|
mergeBaseCache = /* @__PURE__ */ new Map();
|
|
@@ -15988,7 +16180,7 @@ node <detached-job.js> wait <id> --until-done
|
|
|
15988
16180
|
node <detached-job.js> status <id>
|
|
15989
16181
|
\`\`\`
|
|
15990
16182
|
|
|
15991
|
-
\`<id>\` is kebab-case (\`mac-release\`, \`core-test\`, \`fly-deploy\`). State is \`.sideboard/detached-jobs/<id>/\` (local scratch).
|
|
16183
|
+
\`<id>\` is kebab-case (\`mac-release\`, \`core-test\`, \`fly-deploy\`). State is \`.context/.sideboard/detached-jobs/<id>/\` (local scratch).
|
|
15992
16184
|
|
|
15993
16185
|
Wait JSON:
|
|
15994
16186
|
|
|
@@ -16078,7 +16270,7 @@ function parseFrontmatter(content) {
|
|
|
16078
16270
|
}
|
|
16079
16271
|
function readSkill(skillMd, source) {
|
|
16080
16272
|
try {
|
|
16081
|
-
const content = (0,
|
|
16273
|
+
const content = (0, import_node_fs40.readFileSync)(skillMd, "utf8");
|
|
16082
16274
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
16083
16275
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
16084
16276
|
const name = fmName || dirName;
|
|
@@ -16097,19 +16289,19 @@ function readSkill(skillMd, source) {
|
|
|
16097
16289
|
}
|
|
16098
16290
|
}
|
|
16099
16291
|
function scanSkillsDir(dir, source, out) {
|
|
16100
|
-
if (!(0,
|
|
16292
|
+
if (!(0, import_node_fs40.existsSync)(dir)) return;
|
|
16101
16293
|
let entries;
|
|
16102
16294
|
try {
|
|
16103
|
-
entries = (0,
|
|
16295
|
+
entries = (0, import_node_fs40.readdirSync)(dir);
|
|
16104
16296
|
} catch {
|
|
16105
16297
|
return;
|
|
16106
16298
|
}
|
|
16107
16299
|
for (const entry of entries) {
|
|
16108
16300
|
if (entry.startsWith(".")) continue;
|
|
16109
|
-
const skillMd = (0,
|
|
16110
|
-
if (!(0,
|
|
16301
|
+
const skillMd = (0, import_node_path37.join)(dir, entry, "SKILL.md");
|
|
16302
|
+
if (!(0, import_node_fs40.existsSync)(skillMd)) continue;
|
|
16111
16303
|
try {
|
|
16112
|
-
if (!(0,
|
|
16304
|
+
if (!(0, import_node_fs40.statSync)(skillMd).isFile()) continue;
|
|
16113
16305
|
} catch {
|
|
16114
16306
|
continue;
|
|
16115
16307
|
}
|
|
@@ -16118,24 +16310,24 @@ function scanSkillsDir(dir, source, out) {
|
|
|
16118
16310
|
}
|
|
16119
16311
|
}
|
|
16120
16312
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
16121
|
-
if (!(0,
|
|
16313
|
+
if (!(0, import_node_fs40.existsSync)(pluginsRoot)) return;
|
|
16122
16314
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
16123
16315
|
if (depth > 7) return;
|
|
16124
16316
|
let entries;
|
|
16125
16317
|
try {
|
|
16126
|
-
entries = (0,
|
|
16318
|
+
entries = (0, import_node_fs40.readdirSync)(dir);
|
|
16127
16319
|
} catch {
|
|
16128
16320
|
return;
|
|
16129
16321
|
}
|
|
16130
16322
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
16131
|
-
const skill = readSkill((0,
|
|
16323
|
+
const skill = readSkill((0, import_node_path37.join)(dir, "SKILL.md"), "cli");
|
|
16132
16324
|
if (skill) out.push(skill);
|
|
16133
16325
|
}
|
|
16134
16326
|
for (const entry of entries) {
|
|
16135
16327
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
16136
|
-
const full = (0,
|
|
16328
|
+
const full = (0, import_node_path37.join)(dir, entry);
|
|
16137
16329
|
try {
|
|
16138
|
-
if (!(0,
|
|
16330
|
+
if (!(0, import_node_fs40.statSync)(full).isDirectory()) continue;
|
|
16139
16331
|
} catch {
|
|
16140
16332
|
continue;
|
|
16141
16333
|
}
|
|
@@ -16150,20 +16342,20 @@ function scanClaudePluginSkills(pluginsRoot, out) {
|
|
|
16150
16342
|
walk(pluginsRoot, 0, false);
|
|
16151
16343
|
}
|
|
16152
16344
|
function discoverSkills(worktreePath) {
|
|
16153
|
-
const home = (0,
|
|
16345
|
+
const home = (0, import_node_os12.homedir)();
|
|
16154
16346
|
const collected = [];
|
|
16155
16347
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
16156
|
-
scanSkillsDir((0,
|
|
16348
|
+
scanSkillsDir((0, import_node_path37.join)(worktreePath, rel), "workspace", collected);
|
|
16157
16349
|
}
|
|
16158
16350
|
for (const abs of [
|
|
16159
|
-
(0,
|
|
16160
|
-
(0,
|
|
16161
|
-
(0,
|
|
16162
|
-
(0,
|
|
16351
|
+
(0, import_node_path37.join)(home, ".claude/skills"),
|
|
16352
|
+
(0, import_node_path37.join)(home, ".cursor/skills"),
|
|
16353
|
+
(0, import_node_path37.join)(home, ".sideboard/skills"),
|
|
16354
|
+
(0, import_node_path37.join)(home, ".brightsy/skills")
|
|
16163
16355
|
]) {
|
|
16164
16356
|
scanSkillsDir(abs, "user", collected);
|
|
16165
16357
|
}
|
|
16166
|
-
scanClaudePluginSkills((0,
|
|
16358
|
+
scanClaudePluginSkills((0, import_node_path37.join)(home, ".claude/plugins"), collected);
|
|
16167
16359
|
collected.push(...bundledSkills());
|
|
16168
16360
|
const rank = {
|
|
16169
16361
|
workspace: 0,
|
|
@@ -16189,7 +16381,7 @@ function readSkillBody(skillPath, maxChars = 12e3) {
|
|
|
16189
16381
|
\u2026(truncated)` : body;
|
|
16190
16382
|
}
|
|
16191
16383
|
}
|
|
16192
|
-
const raw = (0,
|
|
16384
|
+
const raw = (0, import_node_fs40.readFileSync)(skillPath, "utf8");
|
|
16193
16385
|
if (raw.startsWith("---")) {
|
|
16194
16386
|
const end = raw.indexOf("\n---", 3);
|
|
16195
16387
|
if (end >= 0) {
|
|
@@ -16203,13 +16395,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
|
|
|
16203
16395
|
|
|
16204
16396
|
\u2026(truncated)` : raw;
|
|
16205
16397
|
}
|
|
16206
|
-
var
|
|
16398
|
+
var import_node_fs40, import_node_os12, import_node_path37, BUNDLED_SKILL_PREFIX;
|
|
16207
16399
|
var init_discover = __esm({
|
|
16208
16400
|
"src/skills/discover.ts"() {
|
|
16209
16401
|
"use strict";
|
|
16210
|
-
|
|
16211
|
-
|
|
16212
|
-
|
|
16402
|
+
import_node_fs40 = require("fs");
|
|
16403
|
+
import_node_os12 = require("os");
|
|
16404
|
+
import_node_path37 = require("path");
|
|
16213
16405
|
init_long_running();
|
|
16214
16406
|
BUNDLED_SKILL_PREFIX = "bundled:";
|
|
16215
16407
|
}
|
|
@@ -16304,17 +16496,17 @@ var init_expand = __esm({
|
|
|
16304
16496
|
function packagedDetachedJobPath() {
|
|
16305
16497
|
const dir = packagedMcpDir();
|
|
16306
16498
|
if (!dir) return null;
|
|
16307
|
-
const script = (0,
|
|
16308
|
-
return (0,
|
|
16499
|
+
const script = (0, import_node_path38.join)(dir, "scripts", "detached-job.js");
|
|
16500
|
+
return (0, import_node_fs41.existsSync)(script) ? script : null;
|
|
16309
16501
|
}
|
|
16310
16502
|
function resolveDetachedJobScript() {
|
|
16311
16503
|
const packaged = packagedDetachedJobPath();
|
|
16312
16504
|
if (packaged) return packaged;
|
|
16313
|
-
let dir = (0,
|
|
16505
|
+
let dir = (0, import_node_path38.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
|
|
16314
16506
|
for (let i = 0; i < 8; i++) {
|
|
16315
|
-
const candidate = (0,
|
|
16316
|
-
if ((0,
|
|
16317
|
-
const parent = (0,
|
|
16507
|
+
const candidate = (0, import_node_path38.join)(dir, "scripts", "detached-job.js");
|
|
16508
|
+
if ((0, import_node_fs41.existsSync)(candidate)) return candidate;
|
|
16509
|
+
const parent = (0, import_node_path38.dirname)(dir);
|
|
16318
16510
|
if (parent === dir) break;
|
|
16319
16511
|
dir = parent;
|
|
16320
16512
|
}
|
|
@@ -16325,12 +16517,12 @@ function formatDetachedJobInvoke(scriptPath) {
|
|
|
16325
16517
|
if (resolved) return `node ${JSON.stringify(resolved)}`;
|
|
16326
16518
|
return "node scripts/detached-job.js";
|
|
16327
16519
|
}
|
|
16328
|
-
var
|
|
16520
|
+
var import_node_fs41, import_node_path38, import_node_url3, import_meta3;
|
|
16329
16521
|
var init_detached_job_path = __esm({
|
|
16330
16522
|
"src/skills/detached-job-path.ts"() {
|
|
16331
16523
|
"use strict";
|
|
16332
|
-
|
|
16333
|
-
|
|
16524
|
+
import_node_fs41 = require("fs");
|
|
16525
|
+
import_node_path38 = require("path");
|
|
16334
16526
|
import_node_url3 = require("url");
|
|
16335
16527
|
init_packaged_runtime();
|
|
16336
16528
|
import_meta3 = {};
|
|
@@ -16403,11 +16595,11 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
16403
16595
|
);
|
|
16404
16596
|
} else if (opts?.githubSlug) {
|
|
16405
16597
|
lines.push(
|
|
16406
|
-
`- 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
|
|
16598
|
+
`- 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\`.`
|
|
16407
16599
|
);
|
|
16408
16600
|
} else {
|
|
16409
16601
|
lines.push(
|
|
16410
|
-
"- 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."
|
|
16602
|
+
"- 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`."
|
|
16411
16603
|
);
|
|
16412
16604
|
}
|
|
16413
16605
|
lines.push("");
|
|
@@ -16463,7 +16655,7 @@ function formatLongRunningDirective(opts) {
|
|
|
16463
16655
|
"- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running` \u2014 the side column is the live view.",
|
|
16464
16656
|
`- Loop \`${invoke} wait <id>\` (returns in ~45s). stillRunning \u2192 present the same id with \`content=delta\` only \u2192 wait again. Do not resend the full log or HTML.`,
|
|
16465
16657
|
"- ok \u2192 finish the task. failed \u2192 read the log, fix, start once.",
|
|
16466
|
-
"State: `.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
|
|
16658
|
+
"State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
|
|
16467
16659
|
].join("\n");
|
|
16468
16660
|
}
|
|
16469
16661
|
function formatLongRunningReminder(opts) {
|
|
@@ -16498,12 +16690,12 @@ function formatArtifactDirective() {
|
|
|
16498
16690
|
function formatUiReminder() {
|
|
16499
16691
|
return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
|
|
16500
16692
|
}
|
|
16501
|
-
var
|
|
16693
|
+
var import_node_fs42, import_node_path39;
|
|
16502
16694
|
var init_instructions = __esm({
|
|
16503
16695
|
"src/agents/instructions.ts"() {
|
|
16504
16696
|
"use strict";
|
|
16505
|
-
|
|
16506
|
-
|
|
16697
|
+
import_node_fs42 = require("fs");
|
|
16698
|
+
import_node_path39 = require("path");
|
|
16507
16699
|
init_git_auth_mode();
|
|
16508
16700
|
init_worktree_labels();
|
|
16509
16701
|
init_detached_job_path();
|
|
@@ -16673,40 +16865,40 @@ __export(plan_file_exports, {
|
|
|
16673
16865
|
writePlanFile: () => writePlanFile
|
|
16674
16866
|
});
|
|
16675
16867
|
function ensureAttachmentsGitignore(worktreePath) {
|
|
16676
|
-
const gitignoreAbs = (0,
|
|
16677
|
-
if ((0,
|
|
16678
|
-
(0,
|
|
16679
|
-
(0,
|
|
16868
|
+
const gitignoreAbs = (0, import_node_path40.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
16869
|
+
if ((0, import_node_fs43.existsSync)(gitignoreAbs)) return;
|
|
16870
|
+
(0, import_node_fs43.mkdirSync)((0, import_node_path40.dirname)(gitignoreAbs), { recursive: true });
|
|
16871
|
+
(0, import_node_fs43.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
16680
16872
|
}
|
|
16681
16873
|
function planFileAbs(worktreePath) {
|
|
16682
|
-
return (0,
|
|
16874
|
+
return (0, import_node_path40.join)(worktreePath, PLAN_FILE_REL);
|
|
16683
16875
|
}
|
|
16684
16876
|
function readTextIfPresent2(abs) {
|
|
16685
|
-
if (!(0,
|
|
16877
|
+
if (!(0, import_node_fs43.existsSync)(abs)) return null;
|
|
16686
16878
|
try {
|
|
16687
|
-
const content = (0,
|
|
16879
|
+
const content = (0, import_node_fs43.readFileSync)(abs, "utf8");
|
|
16688
16880
|
return content.trim() ? content : null;
|
|
16689
16881
|
} catch {
|
|
16690
16882
|
return null;
|
|
16691
16883
|
}
|
|
16692
16884
|
}
|
|
16693
16885
|
function readPlanFile(worktreePath) {
|
|
16694
|
-
return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0,
|
|
16886
|
+
return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path40.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path40.join)(worktreePath, LEGACY_PLAN_FILE_REL));
|
|
16695
16887
|
}
|
|
16696
16888
|
function writePlanFile(worktreePath, content) {
|
|
16697
16889
|
ensureAttachmentsGitignore(worktreePath);
|
|
16698
16890
|
const abs = planFileAbs(worktreePath);
|
|
16699
|
-
(0,
|
|
16891
|
+
(0, import_node_fs43.mkdirSync)((0, import_node_path40.dirname)(abs), { recursive: true });
|
|
16700
16892
|
const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
|
|
16701
|
-
(0,
|
|
16893
|
+
(0, import_node_fs43.writeFileSync)(abs, body, "utf8");
|
|
16702
16894
|
return PLAN_FILE_REL;
|
|
16703
16895
|
}
|
|
16704
|
-
var
|
|
16896
|
+
var import_node_fs43, import_node_path40;
|
|
16705
16897
|
var init_plan_file = __esm({
|
|
16706
16898
|
"src/plan/plan-file.ts"() {
|
|
16707
16899
|
"use strict";
|
|
16708
|
-
|
|
16709
|
-
|
|
16900
|
+
import_node_fs43 = require("fs");
|
|
16901
|
+
import_node_path40 = require("path");
|
|
16710
16902
|
init_workspace_scratch();
|
|
16711
16903
|
init_plan_present();
|
|
16712
16904
|
init_plan_present();
|
|
@@ -16766,7 +16958,7 @@ function setCaffeinateHoldHooks(next) {
|
|
|
16766
16958
|
hooks = next;
|
|
16767
16959
|
}
|
|
16768
16960
|
function caffeinateHoldPath() {
|
|
16769
|
-
return (0,
|
|
16961
|
+
return (0, import_node_path41.join)(appDataDir(), "caffeinate-hold.json");
|
|
16770
16962
|
}
|
|
16771
16963
|
function processAlive(pid) {
|
|
16772
16964
|
if (hooks.processAlive) return hooks.processAlive(pid);
|
|
@@ -16800,9 +16992,9 @@ function uniqueIds(ids) {
|
|
|
16800
16992
|
}
|
|
16801
16993
|
function readHold() {
|
|
16802
16994
|
const path = caffeinateHoldPath();
|
|
16803
|
-
if (!(0,
|
|
16995
|
+
if (!(0, import_node_fs44.existsSync)(path)) return null;
|
|
16804
16996
|
try {
|
|
16805
|
-
const parsed = JSON.parse((0,
|
|
16997
|
+
const parsed = JSON.parse((0, import_node_fs44.readFileSync)(path, "utf8"));
|
|
16806
16998
|
if (typeof parsed?.pid === "number" && parsed.pid > 0) {
|
|
16807
16999
|
return {
|
|
16808
17000
|
pid: parsed.pid,
|
|
@@ -16824,7 +17016,7 @@ function writeHold(pid, threadIds) {
|
|
|
16824
17016
|
}
|
|
16825
17017
|
function clearHold() {
|
|
16826
17018
|
try {
|
|
16827
|
-
(0,
|
|
17019
|
+
(0, import_node_fs44.unlinkSync)(caffeinateHoldPath());
|
|
16828
17020
|
} catch {
|
|
16829
17021
|
}
|
|
16830
17022
|
}
|
|
@@ -16909,13 +17101,13 @@ function releaseCaffeinateHoldForThread(threadId) {
|
|
|
16909
17101
|
}
|
|
16910
17102
|
return setCaffeinateHold(false, { threadId: id });
|
|
16911
17103
|
}
|
|
16912
|
-
var import_node_child_process4,
|
|
17104
|
+
var import_node_child_process4, import_node_fs44, import_node_path41, hooks;
|
|
16913
17105
|
var init_caffeinate_hold = __esm({
|
|
16914
17106
|
"src/store/caffeinate-hold.ts"() {
|
|
16915
17107
|
"use strict";
|
|
16916
17108
|
import_node_child_process4 = require("child_process");
|
|
16917
|
-
|
|
16918
|
-
|
|
17109
|
+
import_node_fs44 = require("fs");
|
|
17110
|
+
import_node_path41 = require("path");
|
|
16919
17111
|
init_paths();
|
|
16920
17112
|
init_private_file();
|
|
16921
17113
|
hooks = {};
|
|
@@ -16924,7 +17116,7 @@ var init_caffeinate_hold = __esm({
|
|
|
16924
17116
|
|
|
16925
17117
|
// src/store/schedules.ts
|
|
16926
17118
|
function schedulesPath() {
|
|
16927
|
-
return (0,
|
|
17119
|
+
return (0, import_node_path42.join)(appDataDir(), "schedules.json");
|
|
16928
17120
|
}
|
|
16929
17121
|
function parseDurationMs(every) {
|
|
16930
17122
|
const m = every.trim().match(DURATION_RE);
|
|
@@ -17024,9 +17216,9 @@ function normalizeTask(raw) {
|
|
|
17024
17216
|
}
|
|
17025
17217
|
function readAll2() {
|
|
17026
17218
|
const path = schedulesPath();
|
|
17027
|
-
if (!(0,
|
|
17219
|
+
if (!(0, import_node_fs45.existsSync)(path)) return [];
|
|
17028
17220
|
try {
|
|
17029
|
-
const parsed = JSON.parse((0,
|
|
17221
|
+
const parsed = JSON.parse((0, import_node_fs45.readFileSync)(path, "utf8"));
|
|
17030
17222
|
if (!Array.isArray(parsed)) return [];
|
|
17031
17223
|
return parsed.map((row) => {
|
|
17032
17224
|
try {
|
|
@@ -17051,7 +17243,7 @@ function buildTask(input, now) {
|
|
|
17051
17243
|
const ts = nowIso2(now);
|
|
17052
17244
|
const agent = input.agent ? coerceOrchestratorAgent(input.agent) : null;
|
|
17053
17245
|
return {
|
|
17054
|
-
id: (0,
|
|
17246
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
17055
17247
|
name: input.name?.trim() || defaultScheduleName(prompt),
|
|
17056
17248
|
prompt,
|
|
17057
17249
|
enabled: input.enabled !== false,
|
|
@@ -17138,13 +17330,13 @@ function recordScheduleRun(id, result) {
|
|
|
17138
17330
|
writeAll2(rows);
|
|
17139
17331
|
return next;
|
|
17140
17332
|
}
|
|
17141
|
-
var
|
|
17333
|
+
var import_node_crypto9, import_node_fs45, import_node_path42, import_croner, DURATION_RE, UNIT_MS;
|
|
17142
17334
|
var init_schedules = __esm({
|
|
17143
17335
|
"src/store/schedules.ts"() {
|
|
17144
17336
|
"use strict";
|
|
17145
|
-
|
|
17146
|
-
|
|
17147
|
-
|
|
17337
|
+
import_node_crypto9 = require("crypto");
|
|
17338
|
+
import_node_fs45 = require("fs");
|
|
17339
|
+
import_node_path42 = require("path");
|
|
17148
17340
|
import_croner = require("croner");
|
|
17149
17341
|
init_orchestrator_capable();
|
|
17150
17342
|
init_paths();
|
|
@@ -17286,13 +17478,13 @@ var init_schedule_runner = __esm({
|
|
|
17286
17478
|
|
|
17287
17479
|
// src/agents/cursor-store.ts
|
|
17288
17480
|
function cursorSdkStoreDir(threadId) {
|
|
17289
|
-
const root = (0,
|
|
17481
|
+
const root = (0, import_node_path43.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
|
|
17290
17482
|
const id = sanitizeCursorStoreSegment(threadId);
|
|
17291
17483
|
if (!id) return root;
|
|
17292
|
-
return (0,
|
|
17484
|
+
return (0, import_node_path43.join)(root, "threads", id);
|
|
17293
17485
|
}
|
|
17294
17486
|
function cursorSdkRunsNdjsonPath(threadId) {
|
|
17295
|
-
return (0,
|
|
17487
|
+
return (0, import_node_path43.join)(cursorSdkStoreDir(threadId), "runs.ndjson");
|
|
17296
17488
|
}
|
|
17297
17489
|
function cursorSdkRunsNdjsonSearchPaths(threadId) {
|
|
17298
17490
|
const scoped = cursorSdkRunsNdjsonPath(threadId);
|
|
@@ -17305,11 +17497,11 @@ function cursorSdkRunsNdjsonSearchPaths(threadId) {
|
|
|
17305
17497
|
function sanitizeCursorStoreSegment(threadId) {
|
|
17306
17498
|
return (threadId ?? "").trim().replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
17307
17499
|
}
|
|
17308
|
-
var
|
|
17500
|
+
var import_node_path43, CURSOR_SDK_STORE_DIR;
|
|
17309
17501
|
var init_cursor_store = __esm({
|
|
17310
17502
|
"src/agents/cursor-store.ts"() {
|
|
17311
17503
|
"use strict";
|
|
17312
|
-
|
|
17504
|
+
import_node_path43 = require("path");
|
|
17313
17505
|
init_paths();
|
|
17314
17506
|
CURSOR_SDK_STORE_DIR = "cursor-sdk-store";
|
|
17315
17507
|
}
|
|
@@ -17331,9 +17523,9 @@ function recoverFinishedCursorRun(opts) {
|
|
|
17331
17523
|
return best;
|
|
17332
17524
|
}
|
|
17333
17525
|
function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
|
|
17334
|
-
if (!(0,
|
|
17526
|
+
if (!(0, import_node_fs46.existsSync)(runsPath)) return null;
|
|
17335
17527
|
try {
|
|
17336
|
-
const lines = (0,
|
|
17528
|
+
const lines = (0, import_node_fs46.readFileSync)(runsPath, "utf8").split("\n");
|
|
17337
17529
|
let best = null;
|
|
17338
17530
|
for (const line of lines) {
|
|
17339
17531
|
const trimmed = line.trim();
|
|
@@ -17359,11 +17551,11 @@ function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
|
|
|
17359
17551
|
return null;
|
|
17360
17552
|
}
|
|
17361
17553
|
}
|
|
17362
|
-
var
|
|
17554
|
+
var import_node_fs46;
|
|
17363
17555
|
var init_cursor_recover = __esm({
|
|
17364
17556
|
"src/agents/cursor-recover.ts"() {
|
|
17365
17557
|
"use strict";
|
|
17366
|
-
|
|
17558
|
+
import_node_fs46 = require("fs");
|
|
17367
17559
|
init_cursor_store();
|
|
17368
17560
|
}
|
|
17369
17561
|
});
|
|
@@ -17402,6 +17594,7 @@ var init_title = __esm({
|
|
|
17402
17594
|
// src/orchestrator/orchestrator.ts
|
|
17403
17595
|
var orchestrator_exports = {};
|
|
17404
17596
|
__export(orchestrator_exports, {
|
|
17597
|
+
LIVE_TURN_SPAWN_GRACE_MS: () => LIVE_TURN_SPAWN_GRACE_MS,
|
|
17405
17598
|
Orchestrator: () => Orchestrator,
|
|
17406
17599
|
getOrchestrator: () => getOrchestrator,
|
|
17407
17600
|
isPidAlive: () => isPidAlive,
|
|
@@ -17494,13 +17687,13 @@ async function startOrchestration(opts) {
|
|
|
17494
17687
|
}
|
|
17495
17688
|
return updated;
|
|
17496
17689
|
}
|
|
17497
|
-
var import_node_events,
|
|
17690
|
+
var import_node_events, import_node_fs47, LIVE_TURN_SPAWN_GRACE_MS, STALE_AGENT_PID_WAIT_MS, Orchestrator, singleton;
|
|
17498
17691
|
var init_orchestrator = __esm({
|
|
17499
17692
|
"src/orchestrator/orchestrator.ts"() {
|
|
17500
17693
|
"use strict";
|
|
17501
17694
|
import_node_events = require("events");
|
|
17502
17695
|
init_outbound_watch();
|
|
17503
|
-
|
|
17696
|
+
import_node_fs47 = require("fs");
|
|
17504
17697
|
init_error_detail();
|
|
17505
17698
|
init_run();
|
|
17506
17699
|
init_stale_lock();
|
|
@@ -17515,6 +17708,7 @@ var init_orchestrator = __esm({
|
|
|
17515
17708
|
init_orphan_cleanup();
|
|
17516
17709
|
init_apply_into_main();
|
|
17517
17710
|
init_clone_repo();
|
|
17711
|
+
init_message_parts();
|
|
17518
17712
|
init_usage();
|
|
17519
17713
|
init_thread_store();
|
|
17520
17714
|
init_desktop_host();
|
|
@@ -17552,6 +17746,7 @@ var init_orchestrator = __esm({
|
|
|
17552
17746
|
init_caffeinate_hold();
|
|
17553
17747
|
init_schedule_runner();
|
|
17554
17748
|
init_coordinator_prompt();
|
|
17749
|
+
LIVE_TURN_SPAWN_GRACE_MS = 15e3;
|
|
17555
17750
|
STALE_AGENT_PID_WAIT_MS = 2500;
|
|
17556
17751
|
Orchestrator = class {
|
|
17557
17752
|
events = new import_node_events.EventEmitter();
|
|
@@ -17608,6 +17803,39 @@ var init_orchestrator = __esm({
|
|
|
17608
17803
|
if (typeof pid === "number" && pid > 0 && isPidAlive(pid)) return false;
|
|
17609
17804
|
return true;
|
|
17610
17805
|
}
|
|
17806
|
+
/**
|
|
17807
|
+
* Whether a child is actually turning — not leftover disk `running` after
|
|
17808
|
+
* the process died. Coordinators were telling users “Agent is running.
|
|
17809
|
+
* Waiting for gate to pass” from stale stillRunning.
|
|
17810
|
+
*/
|
|
17811
|
+
threadLooksLive(thread) {
|
|
17812
|
+
if (thread.status === "queued") {
|
|
17813
|
+
if (this.draining.has(thread.id) || this.startingTurns.has(thread.id)) return true;
|
|
17814
|
+
return thread.queue.length > 0;
|
|
17815
|
+
}
|
|
17816
|
+
if (thread.status !== "running") return false;
|
|
17817
|
+
if (this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id)) return true;
|
|
17818
|
+
const pid = thread.agentPid;
|
|
17819
|
+
if (typeof pid === "number" && pid > 0 && isPidAlive(pid)) return true;
|
|
17820
|
+
const updated = Date.parse(thread.updatedAt ?? "");
|
|
17821
|
+
if (Number.isFinite(updated) && Date.now() - updated < LIVE_TURN_SPAWN_GRACE_MS) return true;
|
|
17822
|
+
return false;
|
|
17823
|
+
}
|
|
17824
|
+
/** Desktop-only: persist idle/stopped when MCP would otherwise keep reporting live. */
|
|
17825
|
+
healStaleReportedActivity(thread) {
|
|
17826
|
+
if (!thisProcessShouldDrainAgentQueues()) return thread;
|
|
17827
|
+
if (this.threadLooksLive(thread)) return thread;
|
|
17828
|
+
if (thread.status === "running") {
|
|
17829
|
+
this.healStaleRunningTurns();
|
|
17830
|
+
return readThread(thread.id) ?? thread;
|
|
17831
|
+
}
|
|
17832
|
+
if (thread.status === "queued" && thread.queue.length === 0 && !this.activeTurns.has(thread.id) && !this.startingTurns.has(thread.id) && !this.draining.has(thread.id)) {
|
|
17833
|
+
setStatus(thread.id, "idle");
|
|
17834
|
+
this.emit({ type: "status_changed", threadId: thread.id, status: "idle" });
|
|
17835
|
+
return readThread(thread.id) ?? thread;
|
|
17836
|
+
}
|
|
17837
|
+
return thread;
|
|
17838
|
+
}
|
|
17611
17839
|
async reconcile(repoPath, opts) {
|
|
17612
17840
|
const reclaimStaleTurns = opts?.reclaimStaleTurns === true;
|
|
17613
17841
|
const drainQueues = opts?.drainQueues !== false;
|
|
@@ -17632,7 +17860,7 @@ var init_orchestrator = __esm({
|
|
|
17632
17860
|
}
|
|
17633
17861
|
continue;
|
|
17634
17862
|
}
|
|
17635
|
-
if (!(0,
|
|
17863
|
+
if (!(0, import_node_fs47.existsSync)(thread.worktreePath)) {
|
|
17636
17864
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
17637
17865
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
17638
17866
|
continue;
|
|
@@ -17942,12 +18170,14 @@ var init_orchestrator = __esm({
|
|
|
17942
18170
|
this.emit({ type: "status_changed", threadId: thread.id, status: thread.status });
|
|
17943
18171
|
return thread;
|
|
17944
18172
|
}
|
|
17945
|
-
async send(threadRef, prompt) {
|
|
18173
|
+
async send(threadRef, prompt, opts) {
|
|
17946
18174
|
const thread = this.requireThread(threadRef);
|
|
17947
18175
|
if (thread.status === "archived") {
|
|
17948
18176
|
throw new Error(`Thread is archived: ${thread.id}`);
|
|
17949
18177
|
}
|
|
17950
|
-
|
|
18178
|
+
const followUp = opts?.followUp === "steer" ? "steer" : "queue";
|
|
18179
|
+
let shouldSteer = false;
|
|
18180
|
+
const sent = await withThreadLock(thread.id, async () => {
|
|
17951
18181
|
const current = this.requireThread(thread.id);
|
|
17952
18182
|
if (current.status === "archived") {
|
|
17953
18183
|
throw new Error(`Thread is archived: ${thread.id}`);
|
|
@@ -17956,6 +18186,7 @@ var init_orchestrator = __esm({
|
|
|
17956
18186
|
this.crashContinued.delete(thread.id);
|
|
17957
18187
|
this.haltDrain.delete(thread.id);
|
|
17958
18188
|
const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id) || current.status === "running";
|
|
18189
|
+
shouldSteer = followUp === "steer" && (inFlight || current.queue.length > 0);
|
|
17959
18190
|
const patch = { queue };
|
|
17960
18191
|
if (!inFlight) patch.status = "queued";
|
|
17961
18192
|
const pid = current.agentPid;
|
|
@@ -17967,16 +18198,20 @@ var init_orchestrator = __esm({
|
|
|
17967
18198
|
if (!inFlight) {
|
|
17968
18199
|
this.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
|
|
17969
18200
|
}
|
|
17970
|
-
if (thisProcessShouldDrainAgentQueues()) {
|
|
18201
|
+
if (thisProcessShouldDrainAgentQueues() && !shouldSteer) {
|
|
17971
18202
|
void this.drainQueue(thread.id);
|
|
17972
18203
|
}
|
|
17973
18204
|
return this.requireThread(thread.id);
|
|
17974
18205
|
});
|
|
18206
|
+
if (shouldSteer && sent.queue.length > 0) {
|
|
18207
|
+
return this.sendQueuedMessageNow(sent.id, sent.queue.length - 1);
|
|
18208
|
+
}
|
|
18209
|
+
return sent;
|
|
17975
18210
|
}
|
|
17976
|
-
async fanOut(threadRefs, prompt) {
|
|
18211
|
+
async fanOut(threadRefs, prompt, opts) {
|
|
17977
18212
|
const results = [];
|
|
17978
18213
|
for (const ref of threadRefs) {
|
|
17979
|
-
results.push(await this.send(ref, prompt));
|
|
18214
|
+
results.push(await this.send(ref, prompt, opts));
|
|
17980
18215
|
}
|
|
17981
18216
|
return results;
|
|
17982
18217
|
}
|
|
@@ -18780,8 +19015,8 @@ var init_orchestrator = __esm({
|
|
|
18780
19015
|
return created;
|
|
18781
19016
|
}
|
|
18782
19017
|
async waitForTurn(threadRef, timeoutMs = 6e5, opts) {
|
|
18783
|
-
const thread = this.requireThread(threadRef);
|
|
18784
|
-
if (!
|
|
19018
|
+
const thread = this.healStaleReportedActivity(this.requireThread(threadRef));
|
|
19019
|
+
if (!this.threadLooksLive(thread)) {
|
|
18785
19020
|
return thread;
|
|
18786
19021
|
}
|
|
18787
19022
|
const start = Date.now();
|
|
@@ -18818,12 +19053,13 @@ var init_orchestrator = __esm({
|
|
|
18818
19053
|
}
|
|
18819
19054
|
});
|
|
18820
19055
|
timer = setInterval(() => {
|
|
18821
|
-
const
|
|
18822
|
-
if (!
|
|
19056
|
+
const raw = readThread(thread.id);
|
|
19057
|
+
if (!raw) {
|
|
18823
19058
|
finish(() => reject(new Error(`Thread not found: ${thread.id}`)));
|
|
18824
19059
|
return;
|
|
18825
19060
|
}
|
|
18826
|
-
|
|
19061
|
+
const current = this.healStaleReportedActivity(raw);
|
|
19062
|
+
if (!this.threadLooksLive(current)) {
|
|
18827
19063
|
finish(() => resolve(current));
|
|
18828
19064
|
return;
|
|
18829
19065
|
}
|
|
@@ -18846,20 +19082,22 @@ var init_orchestrator = __esm({
|
|
|
18846
19082
|
};
|
|
18847
19083
|
}
|
|
18848
19084
|
getTurnResult(threadRef) {
|
|
18849
|
-
const thread = this.requireThread(threadRef);
|
|
19085
|
+
const thread = this.healStaleReportedActivity(this.requireThread(threadRef));
|
|
18850
19086
|
const lastAgent = [...thread.messages].reverse().find((m) => m.role === "agent");
|
|
18851
19087
|
const lastError = thread.lastError ?? null;
|
|
18852
|
-
const
|
|
18853
|
-
const
|
|
19088
|
+
const rawText = (lastAgent?.text ?? "").trim();
|
|
19089
|
+
const text5 = (rawText && !isInternalAgentStatusText(rawText) ? rawText : "") || (thread.status === "error" || thread.status === "stopped" || thread.status === "broken" ? lastError ?? "" : "");
|
|
19090
|
+
const stillRunning = this.threadLooksLive(thread);
|
|
18854
19091
|
const live = stillRunning ? readTurnLive(thread.id) : null;
|
|
18855
|
-
const
|
|
19092
|
+
const liveSummary = live?.summary && !isInternalAgentStatusText(live.summary) ? live.summary : null;
|
|
19093
|
+
const queuedHint = stillRunning && thread.status === "queued" && !liveSummary ? "Queued \u2014 waiting for a concurrency slot" : null;
|
|
18856
19094
|
return {
|
|
18857
19095
|
text: text5,
|
|
18858
19096
|
status: thread.status,
|
|
18859
19097
|
sessionId: thread.sessionId,
|
|
18860
19098
|
lastError,
|
|
18861
19099
|
stillRunning,
|
|
18862
|
-
progress:
|
|
19100
|
+
progress: liveSummary ?? queuedHint,
|
|
18863
19101
|
lastActivityAt: live?.updatedAt ?? null,
|
|
18864
19102
|
usage: lastAgent?.usage ?? null
|
|
18865
19103
|
};
|
|
@@ -19207,7 +19445,14 @@ var init_orchestrator = __esm({
|
|
|
19207
19445
|
);
|
|
19208
19446
|
}
|
|
19209
19447
|
if ((action === "commit-push" || action === "create-draft" || action === "create-web") && thread.worktreePath?.trim() && !await isDirty(thread.worktreePath)) {
|
|
19210
|
-
|
|
19448
|
+
try {
|
|
19449
|
+
await this.pushAndMaybeOpenPr(thread, action);
|
|
19450
|
+
} catch (err) {
|
|
19451
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
19452
|
+
updateThread(thread.id, { lastError: message });
|
|
19453
|
+
this.emit({ type: "error", threadId: thread.id, message });
|
|
19454
|
+
throw err;
|
|
19455
|
+
}
|
|
19211
19456
|
return this.requireThread(threadRef);
|
|
19212
19457
|
}
|
|
19213
19458
|
let prBase;
|
|
@@ -19410,7 +19655,7 @@ var init_orchestrator = __esm({
|
|
|
19410
19655
|
this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
|
|
19411
19656
|
return restored2;
|
|
19412
19657
|
}
|
|
19413
|
-
if (!(0,
|
|
19658
|
+
if (!(0, import_node_fs47.existsSync)(thread.worktreePath)) {
|
|
19414
19659
|
if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
|
|
19415
19660
|
throw new Error(
|
|
19416
19661
|
`Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
|
|
@@ -19422,6 +19667,8 @@ var init_orchestrator = __esm({
|
|
|
19422
19667
|
await withRepoGitLock(thread.repoPath, async () => {
|
|
19423
19668
|
await git(["worktree", "add", dest, thread.branchName], thread.repoPath);
|
|
19424
19669
|
});
|
|
19670
|
+
const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await Promise.resolve().then(() => (init_worktree_exclude(), worktree_exclude_exports));
|
|
19671
|
+
await ensureWorktreeSideboardIgnored2(dest);
|
|
19425
19672
|
void createThreadWorktree2;
|
|
19426
19673
|
void slug;
|
|
19427
19674
|
}
|
|
@@ -19490,8 +19737,8 @@ init_nested_electron_env();
|
|
|
19490
19737
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
19491
19738
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
19492
19739
|
var import_zod5 = require("zod");
|
|
19493
|
-
var
|
|
19494
|
-
var
|
|
19740
|
+
var import_node_crypto12 = require("crypto");
|
|
19741
|
+
var import_node_path46 = require("path");
|
|
19495
19742
|
init_orchestrator();
|
|
19496
19743
|
init_worktree();
|
|
19497
19744
|
|
|
@@ -19505,7 +19752,7 @@ init_abletime();
|
|
|
19505
19752
|
init_fetch();
|
|
19506
19753
|
|
|
19507
19754
|
// src/integrations/linear-oauth.ts
|
|
19508
|
-
var
|
|
19755
|
+
var import_node_crypto10 = require("crypto");
|
|
19509
19756
|
var import_node_http = require("http");
|
|
19510
19757
|
init_app_settings();
|
|
19511
19758
|
init_fetch();
|
|
@@ -19683,6 +19930,22 @@ query SideboardAssignedIssues($first: Int!) {
|
|
|
19683
19930
|
}
|
|
19684
19931
|
}
|
|
19685
19932
|
`;
|
|
19933
|
+
var ISSUES_QUERY = `
|
|
19934
|
+
query SideboardIssues($first: Int!, $filter: IssueFilter) {
|
|
19935
|
+
viewer { id name }
|
|
19936
|
+
issues(first: $first, orderBy: updatedAt, filter: $filter) {
|
|
19937
|
+
nodes { ${LIST_ISSUE_FIELDS} }
|
|
19938
|
+
}
|
|
19939
|
+
}
|
|
19940
|
+
`;
|
|
19941
|
+
var SEARCH_ISSUES_QUERY = `
|
|
19942
|
+
query SideboardSearchIssues($term: String!, $first: Int!, $filter: IssueFilter) {
|
|
19943
|
+
viewer { id name }
|
|
19944
|
+
searchIssues(term: $term, first: $first, includeArchived: false, filter: $filter) {
|
|
19945
|
+
nodes { ${LIST_ISSUE_FIELDS} }
|
|
19946
|
+
}
|
|
19947
|
+
}
|
|
19948
|
+
`;
|
|
19686
19949
|
var TEAMS_QUERY = `
|
|
19687
19950
|
query SideboardTeams {
|
|
19688
19951
|
viewer { id name }
|
|
@@ -19966,19 +20229,73 @@ function normalizePriority(priority) {
|
|
|
19966
20229
|
}
|
|
19967
20230
|
return priority;
|
|
19968
20231
|
}
|
|
19969
|
-
|
|
19970
|
-
|
|
19971
|
-
|
|
20232
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
20233
|
+
function assigneeFilterKey(assignee) {
|
|
20234
|
+
return (assignee ?? "").trim();
|
|
20235
|
+
}
|
|
20236
|
+
function buildLinearIssueFilter(input) {
|
|
20237
|
+
const filter = {
|
|
20238
|
+
state: { type: { nin: ["completed", "canceled"] } }
|
|
20239
|
+
};
|
|
20240
|
+
const raw = assigneeFilterKey(input?.assignee) || "me";
|
|
20241
|
+
const key = raw.toLowerCase();
|
|
20242
|
+
if (key === "all" || key === "*") return filter;
|
|
20243
|
+
if (key === "unassigned" || key === "none" || key === "null") {
|
|
20244
|
+
filter.assignee = { null: true };
|
|
20245
|
+
return filter;
|
|
20246
|
+
}
|
|
20247
|
+
if (key === "me" || key === "@me") {
|
|
20248
|
+
filter.assignee = { isMe: true };
|
|
20249
|
+
return filter;
|
|
20250
|
+
}
|
|
20251
|
+
if (UUID_RE.test(raw)) {
|
|
20252
|
+
filter.assignee = { id: { eq: raw } };
|
|
20253
|
+
return filter;
|
|
20254
|
+
}
|
|
20255
|
+
filter.assignee = { name: { eqIgnoreCase: raw } };
|
|
20256
|
+
return filter;
|
|
20257
|
+
}
|
|
20258
|
+
function isAssignedToMe(assignee) {
|
|
20259
|
+
const key = assignee.toLowerCase();
|
|
20260
|
+
return key === "me" || key === "@me";
|
|
20261
|
+
}
|
|
20262
|
+
function listedLinearIssues(json, nodes) {
|
|
19972
20263
|
return {
|
|
19973
20264
|
viewer: {
|
|
19974
20265
|
id: String(json.viewer?.id ?? ""),
|
|
19975
20266
|
name: String(json.viewer?.name ?? "")
|
|
19976
20267
|
},
|
|
19977
|
-
issues: (
|
|
19978
|
-
(node) => toIssueInfo(mapIssue(node))
|
|
19979
|
-
)
|
|
20268
|
+
issues: (nodes ?? []).map((node) => toIssueInfo(mapIssue(node)))
|
|
19980
20269
|
};
|
|
19981
20270
|
}
|
|
20271
|
+
async function listLinearIssuesFiltered(opts) {
|
|
20272
|
+
const first = Math.max(1, Math.min(250, opts?.limit ?? 200));
|
|
20273
|
+
const query = opts?.query?.trim() ?? "";
|
|
20274
|
+
const assignee = assigneeFilterKey(opts?.assignee) || (query ? "all" : "me");
|
|
20275
|
+
const filter = buildLinearIssueFilter({ assignee });
|
|
20276
|
+
if (query) {
|
|
20277
|
+
const json2 = await linearGraphql(
|
|
20278
|
+
SEARCH_ISSUES_QUERY,
|
|
20279
|
+
{ term: query, first, filter },
|
|
20280
|
+
opts
|
|
20281
|
+
);
|
|
20282
|
+
return listedLinearIssues(json2, json2.searchIssues?.nodes);
|
|
20283
|
+
}
|
|
20284
|
+
if (isAssignedToMe(assignee)) {
|
|
20285
|
+
const json2 = await linearGraphql(
|
|
20286
|
+
ASSIGNED_ISSUES_QUERY,
|
|
20287
|
+
{ first },
|
|
20288
|
+
opts
|
|
20289
|
+
);
|
|
20290
|
+
return listedLinearIssues(json2, json2.viewer?.assignedIssues?.nodes);
|
|
20291
|
+
}
|
|
20292
|
+
const json = await linearGraphql(
|
|
20293
|
+
ISSUES_QUERY,
|
|
20294
|
+
{ first, filter },
|
|
20295
|
+
opts
|
|
20296
|
+
);
|
|
20297
|
+
return listedLinearIssues(json, json.issues?.nodes);
|
|
20298
|
+
}
|
|
19982
20299
|
async function listLinearTeams(opts) {
|
|
19983
20300
|
const json = await linearGraphql(TEAMS_QUERY, void 0, opts);
|
|
19984
20301
|
return {
|
|
@@ -20085,6 +20402,22 @@ async function commentLinearIssue(input, opts) {
|
|
|
20085
20402
|
}
|
|
20086
20403
|
|
|
20087
20404
|
// src/integrations/issues.ts
|
|
20405
|
+
function assigneeKey(assignee) {
|
|
20406
|
+
return (assignee ?? "").trim().toLowerCase();
|
|
20407
|
+
}
|
|
20408
|
+
function issueMatchesAssignee(issue, assignee, viewerName = "") {
|
|
20409
|
+
const key = assigneeKey(assignee);
|
|
20410
|
+
if (!key || key === "all" || key === "*") return true;
|
|
20411
|
+
const names = [...issue.assignees ?? [], issue.assignee ?? ""].map((name) => name.trim().toLowerCase()).filter(Boolean);
|
|
20412
|
+
if (key === "unassigned" || key === "none" || key === "null") {
|
|
20413
|
+
return names.length === 0;
|
|
20414
|
+
}
|
|
20415
|
+
if (key === "me" || key === "@me") {
|
|
20416
|
+
const me = viewerName.trim().toLowerCase();
|
|
20417
|
+
return Boolean(me && names.includes(me));
|
|
20418
|
+
}
|
|
20419
|
+
return names.includes(key);
|
|
20420
|
+
}
|
|
20088
20421
|
async function listGitHubIssues(repoPath, opts) {
|
|
20089
20422
|
const limit = Math.max(1, Math.min(1e3, opts?.limit ?? 200));
|
|
20090
20423
|
const slug = await resolveGithubRepoSlug(repoPath);
|
|
@@ -20098,6 +20431,17 @@ async function listGitHubIssues(repoPath, opts) {
|
|
|
20098
20431
|
"--state",
|
|
20099
20432
|
"open"
|
|
20100
20433
|
];
|
|
20434
|
+
const query = opts?.query?.trim() ?? "";
|
|
20435
|
+
const assignee = opts?.assignee?.trim() ?? "";
|
|
20436
|
+
const key = assignee.toLowerCase();
|
|
20437
|
+
const searchParts = [];
|
|
20438
|
+
if (query) searchParts.push(query);
|
|
20439
|
+
if (key === "unassigned" || key === "none" || key === "null") {
|
|
20440
|
+
searchParts.push("no:assignee");
|
|
20441
|
+
} else if (key && key !== "all" && key !== "*") {
|
|
20442
|
+
args.push("--assignee", key === "me" || key === "@me" ? "@me" : assignee);
|
|
20443
|
+
}
|
|
20444
|
+
if (searchParts.length) args.push("--search", searchParts.join(" "));
|
|
20101
20445
|
if (slug) args.push("--repo", slug);
|
|
20102
20446
|
const { stdout, exitCode } = await gh(args, repoPath, { reject: false });
|
|
20103
20447
|
if (exitCode !== 0 || !stdout.trim()) return [];
|
|
@@ -20135,14 +20479,20 @@ async function githubViewerLogin(repoPath) {
|
|
|
20135
20479
|
if (exitCode !== 0) return "";
|
|
20136
20480
|
return stdout.trim();
|
|
20137
20481
|
}
|
|
20138
|
-
async function listIssues(repoPath) {
|
|
20482
|
+
async function listIssues(repoPath, opts) {
|
|
20139
20483
|
const settings = loadAppSettings();
|
|
20140
20484
|
const preferredSource = settings.integrations.issueSource ?? "github";
|
|
20141
20485
|
const linearConnected = isLinearConnected(settings);
|
|
20142
20486
|
const abletimeConnected = isAbleTimeConnected(settings);
|
|
20143
20487
|
const source = resolveEffectiveIssueSource(settings);
|
|
20488
|
+
const query = opts?.query?.trim() || void 0;
|
|
20489
|
+
const assignee = opts?.assignee?.trim() || void 0;
|
|
20144
20490
|
if (source === "linear") {
|
|
20145
|
-
const listed = await
|
|
20491
|
+
const listed = await listLinearIssuesFiltered({
|
|
20492
|
+
assignee,
|
|
20493
|
+
query,
|
|
20494
|
+
limit: opts?.limit
|
|
20495
|
+
});
|
|
20146
20496
|
return {
|
|
20147
20497
|
source,
|
|
20148
20498
|
preferredSource,
|
|
@@ -20156,13 +20506,20 @@ async function listIssues(repoPath) {
|
|
|
20156
20506
|
};
|
|
20157
20507
|
}
|
|
20158
20508
|
if (source === "abletime") {
|
|
20159
|
-
const listed = await
|
|
20509
|
+
const [listed, searched] = await Promise.all([
|
|
20510
|
+
listAbleTimeAssignedIssues(),
|
|
20511
|
+
query ? searchAbleTimeTasks(query) : Promise.resolve(null)
|
|
20512
|
+
]);
|
|
20513
|
+
const viewerName = listed.viewer.name ?? listed.viewer.id ?? "";
|
|
20514
|
+
const issues2 = (searched ? searched.map(toAbleTimeIssueInfo) : listed.issues).filter(
|
|
20515
|
+
(issue) => issueMatchesAssignee(issue, assignee, viewerName)
|
|
20516
|
+
);
|
|
20160
20517
|
return {
|
|
20161
20518
|
source,
|
|
20162
20519
|
preferredSource,
|
|
20163
20520
|
linearConnected,
|
|
20164
20521
|
abletimeConnected,
|
|
20165
|
-
issues:
|
|
20522
|
+
issues: issues2,
|
|
20166
20523
|
viewer: {
|
|
20167
20524
|
login: listed.viewer.name,
|
|
20168
20525
|
name: listed.viewer.name
|
|
@@ -20170,7 +20527,7 @@ async function listIssues(repoPath) {
|
|
|
20170
20527
|
};
|
|
20171
20528
|
}
|
|
20172
20529
|
const [issues, login] = await Promise.all([
|
|
20173
|
-
listGitHubIssues(repoPath),
|
|
20530
|
+
listGitHubIssues(repoPath, { assignee, query, limit: opts?.limit }),
|
|
20174
20531
|
githubViewerLogin(repoPath)
|
|
20175
20532
|
]);
|
|
20176
20533
|
return {
|
|
@@ -20223,14 +20580,16 @@ function mcpWaitFinishedHint(status) {
|
|
|
20223
20580
|
}
|
|
20224
20581
|
|
|
20225
20582
|
// src/mcp/server.ts
|
|
20583
|
+
init_message_parts();
|
|
20226
20584
|
init_turn_live();
|
|
20227
20585
|
|
|
20228
20586
|
// src/mcp/thread-visibility.ts
|
|
20587
|
+
init_message_parts();
|
|
20229
20588
|
function lastMessagePreview(messages, max = 160) {
|
|
20230
20589
|
if (!messages?.length) return null;
|
|
20231
20590
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
20232
20591
|
const text5 = messages[i]?.text?.trim();
|
|
20233
|
-
if (!text5) continue;
|
|
20592
|
+
if (!text5 || isInternalAgentStatusText(text5)) continue;
|
|
20234
20593
|
const flat = text5.replace(/\s+/g, " ");
|
|
20235
20594
|
return flat.length > max ? `${flat.slice(0, max)}\u2026` : flat;
|
|
20236
20595
|
}
|
|
@@ -20900,6 +21259,22 @@ function registerLinearTools(server) {
|
|
|
20900
21259
|
}
|
|
20901
21260
|
}
|
|
20902
21261
|
);
|
|
21262
|
+
server.tool(
|
|
21263
|
+
"linear_search_issues",
|
|
21264
|
+
"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).",
|
|
21265
|
+
{
|
|
21266
|
+
query: import_zod3.z.string().optional().describe("Search text (identifier, title, description). Omit to list by assignee only."),
|
|
21267
|
+
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."),
|
|
21268
|
+
limit: import_zod3.z.number().int().positive().max(250).optional()
|
|
21269
|
+
},
|
|
21270
|
+
async ({ query, assignee, limit }) => {
|
|
21271
|
+
try {
|
|
21272
|
+
return text3(await listLinearIssuesFiltered({ query, assignee, limit }));
|
|
21273
|
+
} catch (err) {
|
|
21274
|
+
return fail3(err);
|
|
21275
|
+
}
|
|
21276
|
+
}
|
|
21277
|
+
);
|
|
20903
21278
|
server.tool(
|
|
20904
21279
|
"linear_get_issue",
|
|
20905
21280
|
"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.",
|
|
@@ -21134,30 +21509,31 @@ function registerScheduleTools(server) {
|
|
|
21134
21509
|
|
|
21135
21510
|
// src/mcp/server.ts
|
|
21136
21511
|
init_agent_git_actions();
|
|
21512
|
+
init_gh_errors();
|
|
21137
21513
|
init_git_auth_mode();
|
|
21138
21514
|
|
|
21139
21515
|
// src/board/load-home-board.ts
|
|
21140
|
-
var
|
|
21141
|
-
var
|
|
21516
|
+
var import_node_fs49 = require("fs");
|
|
21517
|
+
var import_node_path45 = require("path");
|
|
21142
21518
|
init_worktree();
|
|
21143
21519
|
init_paths();
|
|
21144
21520
|
|
|
21145
21521
|
// src/board/board-pins.ts
|
|
21146
|
-
var
|
|
21147
|
-
var
|
|
21148
|
-
var
|
|
21522
|
+
var import_node_crypto11 = require("crypto");
|
|
21523
|
+
var import_node_fs48 = require("fs");
|
|
21524
|
+
var import_node_path44 = require("path");
|
|
21149
21525
|
init_paths();
|
|
21150
21526
|
init_home_board();
|
|
21151
21527
|
var FILE = "home-board-pins.json";
|
|
21152
21528
|
var VERSION = 1;
|
|
21153
21529
|
function pinsFile() {
|
|
21154
|
-
return (0,
|
|
21530
|
+
return (0, import_node_path44.join)(appDataDir(), FILE);
|
|
21155
21531
|
}
|
|
21156
21532
|
function readDisk() {
|
|
21157
21533
|
const path = pinsFile();
|
|
21158
|
-
if (!(0,
|
|
21534
|
+
if (!(0, import_node_fs48.existsSync)(path)) return [];
|
|
21159
21535
|
try {
|
|
21160
|
-
const raw = JSON.parse((0,
|
|
21536
|
+
const raw = JSON.parse((0, import_node_fs48.readFileSync)(path, "utf8"));
|
|
21161
21537
|
if (raw?.version !== VERSION || !Array.isArray(raw.items)) return [];
|
|
21162
21538
|
return raw.items.filter((item) => item?.id && item.kind && item.ref);
|
|
21163
21539
|
} catch {
|
|
@@ -21165,8 +21541,8 @@ function readDisk() {
|
|
|
21165
21541
|
}
|
|
21166
21542
|
}
|
|
21167
21543
|
function writeDisk(items) {
|
|
21168
|
-
(0,
|
|
21169
|
-
(0,
|
|
21544
|
+
(0, import_node_fs48.mkdirSync)(appDataDir(), { recursive: true });
|
|
21545
|
+
(0, import_node_fs48.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
|
|
21170
21546
|
}
|
|
21171
21547
|
function listBoardPins() {
|
|
21172
21548
|
return readDisk();
|
|
@@ -21187,7 +21563,7 @@ function homeBoardWorkspaceKey(workspaces) {
|
|
|
21187
21563
|
return workspaces.map((w) => w.path).filter(Boolean).sort().join("\n");
|
|
21188
21564
|
}
|
|
21189
21565
|
function cacheFile() {
|
|
21190
|
-
return (0,
|
|
21566
|
+
return (0, import_node_path45.join)(appDataDir(), "home-board-cache.json");
|
|
21191
21567
|
}
|
|
21192
21568
|
function emptyInputs() {
|
|
21193
21569
|
return {
|
|
@@ -21213,9 +21589,9 @@ function shouldCacheHomeBoardInputs(inputs) {
|
|
|
21213
21589
|
}
|
|
21214
21590
|
function readDiskCache() {
|
|
21215
21591
|
const path = cacheFile();
|
|
21216
|
-
if (!(0,
|
|
21592
|
+
if (!(0, import_node_fs49.existsSync)(path)) return null;
|
|
21217
21593
|
try {
|
|
21218
|
-
const raw = JSON.parse((0,
|
|
21594
|
+
const raw = JSON.parse((0, import_node_fs49.readFileSync)(path, "utf8"));
|
|
21219
21595
|
if (raw?.version !== CACHE_VERSION || typeof raw.fetchedAt !== "number") {
|
|
21220
21596
|
return null;
|
|
21221
21597
|
}
|
|
@@ -21229,8 +21605,8 @@ function readDiskCache() {
|
|
|
21229
21605
|
}
|
|
21230
21606
|
function writeDiskCache(entry) {
|
|
21231
21607
|
try {
|
|
21232
|
-
(0,
|
|
21233
|
-
(0,
|
|
21608
|
+
(0, import_node_fs49.mkdirSync)(appDataDir(), { recursive: true });
|
|
21609
|
+
(0, import_node_fs49.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
|
|
21234
21610
|
} catch {
|
|
21235
21611
|
}
|
|
21236
21612
|
}
|
|
@@ -21519,13 +21895,13 @@ async function startMcpServer() {
|
|
|
21519
21895
|
async () => {
|
|
21520
21896
|
const threads = orch.getThreads(true);
|
|
21521
21897
|
const lines = threads.map((t) => {
|
|
21522
|
-
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0,
|
|
21523
|
-
const live =
|
|
21898
|
+
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path46.basename)(t.repoPath) || t.repoPath;
|
|
21899
|
+
const live = orch.threadLooksLive(t) ? readTurnLive(t.id) : null;
|
|
21524
21900
|
const parent = t.parentThreadId ? ` parent:${t.parentThreadId.slice(0, 8)}` : "";
|
|
21525
21901
|
const preview = lastMessagePreview(t.messages, 80);
|
|
21526
21902
|
const previewBit = preview ? ` ${preview}` : "";
|
|
21527
21903
|
const err = t.lastError ? ` error:${t.lastError.replace(/\s+/g, " ").slice(0, 60)}` : "";
|
|
21528
|
-
const progress = live?.summary ? ` ${live.summary}` : "";
|
|
21904
|
+
const progress = live?.summary && !isInternalAgentStatusText(live.summary) ? ` ${live.summary}` : "";
|
|
21529
21905
|
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}`;
|
|
21530
21906
|
});
|
|
21531
21907
|
return {
|
|
@@ -21587,7 +21963,9 @@ async function startMcpServer() {
|
|
|
21587
21963
|
if (!t) {
|
|
21588
21964
|
return { content: [{ type: "text", text: `Thread not found: ${ref}` }], isError: true };
|
|
21589
21965
|
}
|
|
21590
|
-
const
|
|
21966
|
+
const stillRunning = orch.threadLooksLive(t);
|
|
21967
|
+
const live = stillRunning ? readTurnLive(t.id) : null;
|
|
21968
|
+
const liveSummary = live?.summary && !isInternalAgentStatusText(live.summary) ? live.summary : null;
|
|
21591
21969
|
const spend = orch.getThreadUsage(t.id);
|
|
21592
21970
|
const summary = {
|
|
21593
21971
|
id: t.id,
|
|
@@ -21607,8 +21985,8 @@ async function startMcpServer() {
|
|
|
21607
21985
|
devPort: t.devPort,
|
|
21608
21986
|
prUrl: t.prUrl,
|
|
21609
21987
|
lastError: t.lastError ?? null,
|
|
21610
|
-
stillRunning
|
|
21611
|
-
progress:
|
|
21988
|
+
stillRunning,
|
|
21989
|
+
progress: liveSummary ?? (stillRunning && t.status === "queued" ? "Queued \u2014 waiting for a concurrency slot" : null),
|
|
21612
21990
|
lastActivityAt: live?.updatedAt ?? null,
|
|
21613
21991
|
usage: spend.usage,
|
|
21614
21992
|
lastTurnUsage: spend.lastTurnUsage
|
|
@@ -21889,7 +22267,7 @@ async function startMcpServer() {
|
|
|
21889
22267
|
const ident = issue?.identifier ?? ref.trim();
|
|
21890
22268
|
const attachments = issue ? [
|
|
21891
22269
|
{
|
|
21892
|
-
id: (0,
|
|
22270
|
+
id: (0, import_node_crypto12.randomUUID)(),
|
|
21893
22271
|
name: issue.identifier,
|
|
21894
22272
|
kind: "issue",
|
|
21895
22273
|
content: [
|
|
@@ -21965,7 +22343,7 @@ async function startMcpServer() {
|
|
|
21965
22343
|
);
|
|
21966
22344
|
server.tool(
|
|
21967
22345
|
"wait_for_turn",
|
|
21968
|
-
"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).",
|
|
22346
|
+
"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).",
|
|
21969
22347
|
{
|
|
21970
22348
|
ref: import_zod5.z.string(),
|
|
21971
22349
|
timeoutMs: import_zod5.z.number().optional()
|
|
@@ -22157,7 +22535,7 @@ async function startMcpServer() {
|
|
|
22157
22535
|
);
|
|
22158
22536
|
server.tool(
|
|
22159
22537
|
"ask_git",
|
|
22160
|
-
"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`
|
|
22538
|
+
"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.",
|
|
22161
22539
|
{
|
|
22162
22540
|
ref: import_zod5.z.string().describe("Worktree thread id/ref"),
|
|
22163
22541
|
action: import_zod5.z.enum(AGENT_GIT_ACTIONS).describe(
|
|
@@ -22182,8 +22560,26 @@ async function startMcpServer() {
|
|
|
22182
22560
|
]
|
|
22183
22561
|
};
|
|
22184
22562
|
} catch (err) {
|
|
22185
|
-
const
|
|
22186
|
-
|
|
22563
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
22564
|
+
const message = formatGhLandError(raw);
|
|
22565
|
+
return {
|
|
22566
|
+
content: [
|
|
22567
|
+
{
|
|
22568
|
+
type: "text",
|
|
22569
|
+
text: JSON.stringify(
|
|
22570
|
+
{
|
|
22571
|
+
error: true,
|
|
22572
|
+
action,
|
|
22573
|
+
lastError: message,
|
|
22574
|
+
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
|
|
22575
|
+
},
|
|
22576
|
+
null,
|
|
22577
|
+
2
|
|
22578
|
+
)
|
|
22579
|
+
}
|
|
22580
|
+
],
|
|
22581
|
+
isError: true
|
|
22582
|
+
};
|
|
22187
22583
|
}
|
|
22188
22584
|
}
|
|
22189
22585
|
);
|
|
@@ -22578,11 +22974,15 @@ async function startMcpServer() {
|
|
|
22578
22974
|
);
|
|
22579
22975
|
server.tool(
|
|
22580
22976
|
"list_issues",
|
|
22581
|
-
"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.",
|
|
22582
|
-
{
|
|
22583
|
-
|
|
22977
|
+
"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.",
|
|
22978
|
+
{
|
|
22979
|
+
repoPath: import_zod5.z.string(),
|
|
22980
|
+
query: import_zod5.z.string().optional().describe("Search title, identifier, or description"),
|
|
22981
|
+
assignee: import_zod5.z.string().optional().describe("me (Linear default), unassigned, all, a user id, or a GitHub login")
|
|
22982
|
+
},
|
|
22983
|
+
async ({ repoPath, query, assignee }) => {
|
|
22584
22984
|
const root = await resolveRepoRoot(repoPath);
|
|
22585
|
-
const result = await listIssues(root);
|
|
22985
|
+
const result = await listIssues(root, { query, assignee });
|
|
22586
22986
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
22587
22987
|
}
|
|
22588
22988
|
);
|