@sideboard-ai/core 0.1.89 → 0.1.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/cursor-runner.cjs +129 -14
- package/dist/agents/cursor-runner.js +4 -1
- package/dist/{agents-LMUFTGKF.js → agents-HBLA6FEV.js} +4 -4
- package/dist/{agents-ODBP7J6E.js → agents-WS5QV6LE.js} +5 -5
- package/dist/{chunk-WANQFU3S.js → chunk-6XBXVXX2.js} +2 -2
- package/dist/{chunk-7D27DD2X.js → chunk-CIRXAYWS.js} +260 -61
- package/dist/{chunk-B2KIO2SD.js → chunk-CLGO7TLO.js} +2 -2
- package/dist/{chunk-CBJSPTBG.js → chunk-GXSYI7FH.js} +206 -5
- package/dist/{chunk-RJLBSYUO.js → chunk-KWNUZ4LR.js} +46 -77
- package/dist/{chunk-UHTNJKZX.js → chunk-NR6APJLD.js} +2 -2
- package/dist/{chunk-6EZRSCIT.js → chunk-QKYO6BHB.js} +2 -2
- package/dist/{chunk-ZXYWWSHZ.js → chunk-R7BQBSDT.js} +254 -61
- package/dist/{chunk-JE75QW2I.js → chunk-WBX46OPD.js} +237 -96
- package/dist/{chunk-OB6IRIFV.js → chunk-XH2GS2LO.js} +2 -2
- package/dist/{chunk-VZ2L4AEJ.js → chunk-XUWDLRAE.js} +2 -2
- package/dist/{coordinator-prompt-UK5LYFN5.js → coordinator-prompt-AKEY4WSO.js} +2 -2
- package/dist/{coordinator-prompt-CI5SHONJ.js → coordinator-prompt-OQOOD5ET.js} +2 -2
- package/dist/{global-workspace-2YZ2V4I5.js → global-workspace-3GNPQCLE.js} +3 -3
- package/dist/{global-workspace-JQQLPJM5.js → global-workspace-M3OMVDDH.js} +3 -3
- package/dist/index.cjs +1021 -473
- package/dist/index.d.cts +91 -20
- package/dist/index.d.ts +91 -20
- package/dist/index.js +244 -59
- package/dist/mcp/run-stdio.cjs +816 -428
- package/dist/mcp/run-stdio.js +77 -40
- package/dist/{workspaces-YWCC3WV4.js → workspaces-ERZC7ULY.js} +4 -4
- package/dist/{workspaces-FDO5L4NI.js → workspaces-J4WG6UFR.js} +4 -4
- package/dist/{worktree-7YNSJ224.js → worktree-DA4BOV7G.js} +7 -1
- package/dist/{worktree-4555QBQ7.js → worktree-EO5QAGJU.js} +7 -1
- package/package.json +1 -1
|
@@ -20,8 +20,8 @@ import {
|
|
|
20
20
|
} from "./chunk-3KETJKYA.js";
|
|
21
21
|
|
|
22
22
|
// src/git/worktree.ts
|
|
23
|
-
import { existsSync, readdirSync } from "fs";
|
|
24
|
-
import { join } from "path";
|
|
23
|
+
import { existsSync as existsSync2, readdirSync } from "fs";
|
|
24
|
+
import { join as join2 } from "path";
|
|
25
25
|
|
|
26
26
|
// src/git/team-meta.ts
|
|
27
27
|
var SOCCER_TEAM_META = {
|
|
@@ -898,13 +898,96 @@ function formatMergePrError(raw) {
|
|
|
898
898
|
return extractGhErrorDetail(trimmed) || trimmed;
|
|
899
899
|
}
|
|
900
900
|
|
|
901
|
+
// src/git/git-auth-mode.ts
|
|
902
|
+
import { isAbsolute } from "path";
|
|
903
|
+
|
|
904
|
+
// src/git/github-agent-auth.ts
|
|
905
|
+
import { chmodSync, existsSync, mkdirSync, writeFileSync } from "fs";
|
|
906
|
+
import { homedir } from "os";
|
|
907
|
+
import { dirname, join } from "path";
|
|
908
|
+
function githubAgentAuthDir() {
|
|
909
|
+
const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
|
|
910
|
+
if (override) return override;
|
|
911
|
+
return join(homedir(), ".sideboard-git-auth");
|
|
912
|
+
}
|
|
913
|
+
function githubCredentialStorePath() {
|
|
914
|
+
return join(githubAgentAuthDir(), "git-credentials");
|
|
915
|
+
}
|
|
916
|
+
function githubGhConfigDir() {
|
|
917
|
+
return join(githubAgentAuthDir(), "gh");
|
|
918
|
+
}
|
|
919
|
+
function writePrivateFile(file, body) {
|
|
920
|
+
mkdirSync(dirname(file), { recursive: true, mode: 448 });
|
|
921
|
+
try {
|
|
922
|
+
chmodSync(dirname(file), 448);
|
|
923
|
+
} catch {
|
|
924
|
+
}
|
|
925
|
+
writeFileSync(file, body, { encoding: "utf8", mode: 384 });
|
|
926
|
+
try {
|
|
927
|
+
chmodSync(file, 384);
|
|
928
|
+
} catch {
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
function gitCredentialStoreContents(token) {
|
|
932
|
+
return `https://x-access-token:${encodeURIComponent(token)}@github.com
|
|
933
|
+
`;
|
|
934
|
+
}
|
|
935
|
+
function ghHostsYml(token, user = "x-access-token") {
|
|
936
|
+
const u = user.replace(/[^A-Za-z0-9._-]/g, "") || "x-access-token";
|
|
937
|
+
return [
|
|
938
|
+
"github.com:",
|
|
939
|
+
" git_protocol: https",
|
|
940
|
+
` user: ${u}`,
|
|
941
|
+
` oauth_token: ${token}`,
|
|
942
|
+
" users:",
|
|
943
|
+
` ${u}:`,
|
|
944
|
+
` oauth_token: ${token}`,
|
|
945
|
+
""
|
|
946
|
+
].join("\n");
|
|
947
|
+
}
|
|
948
|
+
function materializeGithubAgentAuth(token, user) {
|
|
949
|
+
const trimmed = token.trim();
|
|
950
|
+
if (!trimmed) return;
|
|
951
|
+
const root = githubAgentAuthDir();
|
|
952
|
+
mkdirSync(root, { recursive: true, mode: 448 });
|
|
953
|
+
try {
|
|
954
|
+
chmodSync(root, 448);
|
|
955
|
+
} catch {
|
|
956
|
+
}
|
|
957
|
+
writePrivateFile(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
|
|
958
|
+
const ghDir = githubGhConfigDir();
|
|
959
|
+
mkdirSync(ghDir, { recursive: true, mode: 448 });
|
|
960
|
+
writePrivateFile(join(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
|
|
961
|
+
writePrivateFile(join(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
|
|
962
|
+
}
|
|
963
|
+
function githubAgentAuthReady() {
|
|
964
|
+
return existsSync(githubCredentialStorePath()) && existsSync(join(githubGhConfigDir(), "hosts.yml"));
|
|
965
|
+
}
|
|
966
|
+
function githubCredentialHelperGitConfig() {
|
|
967
|
+
const file = githubCredentialStorePath();
|
|
968
|
+
return [
|
|
969
|
+
{ key: "credential.helper", value: "" },
|
|
970
|
+
{ key: "credential.helper", value: `store --file=${file}` }
|
|
971
|
+
];
|
|
972
|
+
}
|
|
973
|
+
function githubGhConfigEnv() {
|
|
974
|
+
return {
|
|
975
|
+
GH_CONFIG_DIR: githubGhConfigDir(),
|
|
976
|
+
GH_PROMPT_DISABLED: "1"
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
|
|
901
980
|
// src/git/git-auth-mode.ts
|
|
902
981
|
var HTTPS_REWRITE = [
|
|
903
982
|
{ key: "url.https://github.com/.insteadOf", value: "git@github.com:" },
|
|
904
|
-
{ key: "url.https://github.com/.insteadOf", value: "ssh://git@github.com/" }
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
983
|
+
{ key: "url.https://github.com/.insteadOf", value: "ssh://git@github.com/" }
|
|
984
|
+
];
|
|
985
|
+
var TOKEN_TTL_MS = 12 * 60 * 60 * 1e3;
|
|
986
|
+
var tokenMemo = null;
|
|
987
|
+
var GITHUB_CHILD_TOKEN_KEYS = [
|
|
988
|
+
"GH_TOKEN",
|
|
989
|
+
"GITHUB_TOKEN",
|
|
990
|
+
"GH_ENTERPRISE_TOKEN"
|
|
908
991
|
];
|
|
909
992
|
function nonInteractiveGitProcessEnv() {
|
|
910
993
|
return {
|
|
@@ -929,42 +1012,43 @@ function appendIndexedGitConfig(existing, entries) {
|
|
|
929
1012
|
return out;
|
|
930
1013
|
}
|
|
931
1014
|
function githubAgentGitEnv(existing) {
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
function githubHttpsBearerEnv(existing, token) {
|
|
935
|
-
const rewrite = githubAgentGitEnv(existing);
|
|
936
|
-
const header = appendIndexedGitConfig(
|
|
937
|
-
{ ...existing, ...rewrite },
|
|
938
|
-
[
|
|
939
|
-
{
|
|
940
|
-
key: "http.https://github.com/.extraHeader",
|
|
941
|
-
value: `AUTHORIZATION: bearer ${token}`
|
|
942
|
-
}
|
|
943
|
-
]
|
|
944
|
-
);
|
|
945
|
-
return { ...rewrite, ...header };
|
|
1015
|
+
const helpers = githubAgentAuthReady() ? githubCredentialHelperGitConfig() : [{ key: "credential.helper", value: "" }];
|
|
1016
|
+
return appendIndexedGitConfig(existing, [...HTTPS_REWRITE, ...helpers]);
|
|
946
1017
|
}
|
|
947
1018
|
function applyGithubGitAuthEnv(existing, opts) {
|
|
948
1019
|
const out = { ...nonInteractiveGitProcessEnv() };
|
|
1020
|
+
const token = opts.token?.trim() || existing?.GH_TOKEN?.trim() || "" || "";
|
|
1021
|
+
if (token) materializeGithubAgentAuth(token);
|
|
1022
|
+
Object.assign(out, githubGhConfigEnv());
|
|
949
1023
|
if (opts.mode === "ssh") return out;
|
|
950
|
-
|
|
951
|
-
const provided = existingToken ? "" : opts.token?.trim() || "";
|
|
952
|
-
const token = existingToken || provided;
|
|
953
|
-
Object.assign(
|
|
954
|
-
out,
|
|
955
|
-
token ? githubHttpsBearerEnv(existing, token) : githubAgentGitEnv(existing)
|
|
956
|
-
);
|
|
957
|
-
if (provided) out.GH_TOKEN = provided;
|
|
1024
|
+
Object.assign(out, githubAgentGitEnv(existing));
|
|
958
1025
|
return out;
|
|
959
1026
|
}
|
|
1027
|
+
function scrubGithubTokensFromChildEnv(env) {
|
|
1028
|
+
for (const key of GITHUB_CHILD_TOKEN_KEYS) {
|
|
1029
|
+
delete env[key];
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
function mergeAgentGitAuthEnv(env, gitEnv) {
|
|
1033
|
+
Object.assign(env, gitEnv);
|
|
1034
|
+
scrubGithubTokensFromChildEnv(env);
|
|
1035
|
+
}
|
|
960
1036
|
async function resolveGithubAgentToken(mode, cwd) {
|
|
961
|
-
if (mode ===
|
|
962
|
-
|
|
963
|
-
try {
|
|
964
|
-
return await resolveGhAuthToken(cwd);
|
|
965
|
-
} catch {
|
|
966
|
-
return null;
|
|
1037
|
+
if (tokenMemo && tokenMemo.mode === mode && Date.now() - tokenMemo.at < TOKEN_TTL_MS) {
|
|
1038
|
+
return tokenMemo.value;
|
|
967
1039
|
}
|
|
1040
|
+
let value = null;
|
|
1041
|
+
if (mode === "token") {
|
|
1042
|
+
value = getGithubPat();
|
|
1043
|
+
} else {
|
|
1044
|
+
try {
|
|
1045
|
+
value = await resolveGhAuthToken(cwd);
|
|
1046
|
+
} catch {
|
|
1047
|
+
value = null;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
tokenMemo = { mode, value, at: Date.now() };
|
|
1051
|
+
return value;
|
|
968
1052
|
}
|
|
969
1053
|
async function resolveAgentGitAuthEnv(existing, opts) {
|
|
970
1054
|
let mode = "auto";
|
|
@@ -986,7 +1070,40 @@ async function resolveAgentGitAuthEnv(existing, opts) {
|
|
|
986
1070
|
}
|
|
987
1071
|
return applyGithubGitAuthEnv(existing, { mode, token });
|
|
988
1072
|
}
|
|
989
|
-
function
|
|
1073
|
+
async function warmGithubAgentAuth(opts) {
|
|
1074
|
+
if (!opts?.force && githubAgentAuthReady()) return;
|
|
1075
|
+
await resolveAgentGitAuthEnv(void 0, opts);
|
|
1076
|
+
}
|
|
1077
|
+
function normalizeWritableRoot(raw) {
|
|
1078
|
+
const trimmed = raw.trim().replace(/\/+$/, "");
|
|
1079
|
+
return trimmed && isAbsolute(trimmed) ? trimmed : null;
|
|
1080
|
+
}
|
|
1081
|
+
async function resolveCodexGitWritableRoots(cwd) {
|
|
1082
|
+
const roots = /* @__PURE__ */ new Set();
|
|
1083
|
+
const authDir = normalizeWritableRoot(githubAgentAuthDir());
|
|
1084
|
+
if (authDir) roots.add(authDir);
|
|
1085
|
+
try {
|
|
1086
|
+
const [gitDir, commonDir] = await Promise.all([
|
|
1087
|
+
git(["rev-parse", "--absolute-git-dir"], cwd, { reject: false, timeoutMs: 5e3 }),
|
|
1088
|
+
git(["rev-parse", "--path-format=absolute", "--git-common-dir"], cwd, {
|
|
1089
|
+
reject: false,
|
|
1090
|
+
timeoutMs: 5e3
|
|
1091
|
+
})
|
|
1092
|
+
]);
|
|
1093
|
+
const gitDirPath = gitDir.exitCode === 0 ? normalizeWritableRoot(gitDir.stdout) : null;
|
|
1094
|
+
const commonPath = commonDir.exitCode === 0 ? normalizeWritableRoot(commonDir.stdout) : null;
|
|
1095
|
+
if (gitDirPath) roots.add(gitDirPath);
|
|
1096
|
+
if (commonPath) roots.add(commonPath);
|
|
1097
|
+
} catch {
|
|
1098
|
+
}
|
|
1099
|
+
return [...roots];
|
|
1100
|
+
}
|
|
1101
|
+
function codexSandboxWritableRootsArgs(roots) {
|
|
1102
|
+
const abs = [...new Set(roots.map(normalizeWritableRoot).filter(Boolean))];
|
|
1103
|
+
if (abs.length === 0) return [];
|
|
1104
|
+
return ["-c", `sandbox_workspace_write.writable_roots=${JSON.stringify(abs)}`];
|
|
1105
|
+
}
|
|
1106
|
+
function codexUnattendedGitConfigArgs(sandbox, opts) {
|
|
990
1107
|
const args = [
|
|
991
1108
|
"-c",
|
|
992
1109
|
'shell_environment_policy.inherit="all"',
|
|
@@ -995,39 +1112,44 @@ function codexUnattendedGitConfigArgs(sandbox) {
|
|
|
995
1112
|
];
|
|
996
1113
|
if (sandbox === "workspace-write") {
|
|
997
1114
|
args.push("-c", "sandbox_workspace_write.network_access=true");
|
|
1115
|
+
args.push(...codexSandboxWritableRootsArgs(opts?.writableRoots ?? []));
|
|
998
1116
|
}
|
|
999
1117
|
return args;
|
|
1000
1118
|
}
|
|
1001
1119
|
function formatGitAuthModeDirective(mode) {
|
|
1120
|
+
const shared = [
|
|
1121
|
+
"- `git` and `gh` already authenticate in this process. Do not look for tokens in the environment, paste credentials into commands, or switch remotes to SSH.",
|
|
1122
|
+
"- Do not set GitHub token environment variables, pass `--with-token`, or run `gh auth login` from this turn.",
|
|
1123
|
+
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below.",
|
|
1124
|
+
"- If git/gh fail with auth errors, tell the user to run `gh auth login` on this Mac (or set a PAT in Account \u2192 GitHub). Do not wait for a Keychain dialog."
|
|
1125
|
+
];
|
|
1002
1126
|
switch (mode) {
|
|
1003
1127
|
case "gh":
|
|
1004
1128
|
return [
|
|
1005
1129
|
"Git authentication (Account \u2192 GitHub mode: gh CLI):",
|
|
1006
1130
|
"- This process rewrites `git@github.com:` and `ssh://git@github.com/` to HTTPS.",
|
|
1007
|
-
|
|
1008
|
-
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
1131
|
+
...shared
|
|
1009
1132
|
].join("\n");
|
|
1010
1133
|
case "ssh":
|
|
1011
1134
|
return [
|
|
1012
1135
|
"Git authentication (Account \u2192 GitHub mode: SSH):",
|
|
1013
1136
|
"- Keep SSH remotes (`git@github.com:\u2026`). Do not rewrite them to HTTPS.",
|
|
1014
1137
|
"- SSH is batch-mode: it will not prompt for a Keychain password. If push fails with `Permission denied (publickey)`, tell the user to unlock ssh-agent or switch Account \u2192 GitHub to Auto / gh CLI \u2014 do not rewrite remotes yourself.",
|
|
1015
|
-
"-
|
|
1138
|
+
"- `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.",
|
|
1139
|
+
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
1016
1140
|
].join("\n");
|
|
1017
1141
|
case "token":
|
|
1018
1142
|
return [
|
|
1019
1143
|
"Git authentication (Account \u2192 GitHub mode: personal access token):",
|
|
1020
1144
|
"- This process rewrites GitHub SSH remotes to HTTPS.",
|
|
1021
|
-
|
|
1022
|
-
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
1145
|
+
...shared
|
|
1023
1146
|
].join("\n");
|
|
1024
1147
|
case "auto":
|
|
1025
1148
|
default:
|
|
1026
1149
|
return [
|
|
1027
1150
|
"Git authentication (Account \u2192 GitHub mode: auto):",
|
|
1028
|
-
"- This process rewrites GitHub SSH remotes to HTTPS
|
|
1029
|
-
|
|
1030
|
-
"- If HTTPS auth fails, tell the user to run `gh auth login` on this Mac or set Account \u2192 GitHub to a PAT \u2014 do not wait for a Keychain dialog."
|
|
1151
|
+
"- This process rewrites GitHub SSH remotes to HTTPS so git/ssh never prompt the macOS Keychain (required for unattended orchestrator turns).",
|
|
1152
|
+
...shared
|
|
1031
1153
|
].join("\n");
|
|
1032
1154
|
}
|
|
1033
1155
|
}
|
|
@@ -1408,7 +1530,7 @@ async function originGhRepoEnv(cwd, opts) {
|
|
|
1408
1530
|
await ensureGhPreferOrigin(cwd);
|
|
1409
1531
|
const slug = await resolveGithubRepoSlug(cwd);
|
|
1410
1532
|
const mode = opts?.mode ?? getGithubGitAuthMode();
|
|
1411
|
-
const token =
|
|
1533
|
+
const token = await resolveGithubAgentToken(mode, cwd);
|
|
1412
1534
|
return {
|
|
1413
1535
|
...applyGithubGitAuthEnv(opts?.env, { mode, token }),
|
|
1414
1536
|
...slug ? { GH_REPO: slug } : {}
|
|
@@ -1548,13 +1670,78 @@ async function getPr(repoPath, number) {
|
|
|
1548
1670
|
if (exitCode !== 0 || !stdout.trim()) return null;
|
|
1549
1671
|
return JSON.parse(stdout);
|
|
1550
1672
|
}
|
|
1551
|
-
function
|
|
1552
|
-
|
|
1673
|
+
function normalizeGitBranchName(ref) {
|
|
1674
|
+
return ref.trim().replace(/^refs\/heads\//, "").replace(/^origin\//, "");
|
|
1675
|
+
}
|
|
1676
|
+
function isDefaultishSourceRef(ref) {
|
|
1677
|
+
const n = normalizeGitBranchName(ref ?? "").toLowerCase();
|
|
1678
|
+
return !n || n === "head" || n === "default" || n === "main" || n === "master" || n === "develop" || n === "trunk";
|
|
1679
|
+
}
|
|
1680
|
+
function resolvePrSelectors(thread) {
|
|
1681
|
+
const out = [];
|
|
1682
|
+
const push = (value) => {
|
|
1683
|
+
const v = value?.trim();
|
|
1684
|
+
if (!v || out.includes(v)) return;
|
|
1685
|
+
out.push(v);
|
|
1686
|
+
};
|
|
1687
|
+
push(thread.prUrl);
|
|
1553
1688
|
if (thread.sourceType === "pr" && thread.sourceRef?.trim()) {
|
|
1554
|
-
|
|
1689
|
+
push(thread.sourceRef.replace(/^#/, "").trim());
|
|
1690
|
+
}
|
|
1691
|
+
push(thread.branchName);
|
|
1692
|
+
if (thread.sourceType === "branch") {
|
|
1693
|
+
const source = normalizeGitBranchName(thread.sourceRef ?? "");
|
|
1694
|
+
if (source && !isDefaultishSourceRef(source) && source !== thread.branchName?.trim()) {
|
|
1695
|
+
push(source);
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
return out;
|
|
1699
|
+
}
|
|
1700
|
+
function resolvePrSelector(thread) {
|
|
1701
|
+
return resolvePrSelectors(thread)[0] ?? null;
|
|
1702
|
+
}
|
|
1703
|
+
async function getPrForHeadBranch(repoPath, branch) {
|
|
1704
|
+
const head = normalizeGitBranchName(branch);
|
|
1705
|
+
if (!head || isDefaultishSourceRef(head)) return null;
|
|
1706
|
+
const slug = await resolveGithubRepoSlug(repoPath);
|
|
1707
|
+
const viewArgs = [
|
|
1708
|
+
"pr",
|
|
1709
|
+
"view",
|
|
1710
|
+
head,
|
|
1711
|
+
"--json",
|
|
1712
|
+
"number,title,headRefName,url,isCrossRepository"
|
|
1713
|
+
];
|
|
1714
|
+
if (slug) viewArgs.push("--repo", slug);
|
|
1715
|
+
const viewed = await gh(viewArgs, repoPath, { reject: false });
|
|
1716
|
+
if (viewed.exitCode === 0 && viewed.stdout.trim()) {
|
|
1717
|
+
try {
|
|
1718
|
+
return JSON.parse(viewed.stdout);
|
|
1719
|
+
} catch {
|
|
1720
|
+
return null;
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
const listHead = slug ? ghHeadRef(slug, head) : head;
|
|
1724
|
+
const listArgs = [
|
|
1725
|
+
"pr",
|
|
1726
|
+
"list",
|
|
1727
|
+
"--head",
|
|
1728
|
+
listHead,
|
|
1729
|
+
"--json",
|
|
1730
|
+
"number,title,headRefName,url,isCrossRepository",
|
|
1731
|
+
"--limit",
|
|
1732
|
+
"1",
|
|
1733
|
+
"--state",
|
|
1734
|
+
"open"
|
|
1735
|
+
];
|
|
1736
|
+
if (slug) listArgs.push("--repo", slug);
|
|
1737
|
+
const listed = await gh(listArgs, repoPath, { reject: false });
|
|
1738
|
+
if (listed.exitCode !== 0 || !listed.stdout.trim()) return null;
|
|
1739
|
+
try {
|
|
1740
|
+
const rows = JSON.parse(listed.stdout);
|
|
1741
|
+
return rows[0] ?? null;
|
|
1742
|
+
} catch {
|
|
1743
|
+
return null;
|
|
1555
1744
|
}
|
|
1556
|
-
if (thread.branchName?.trim()) return thread.branchName.trim();
|
|
1557
|
-
return null;
|
|
1558
1745
|
}
|
|
1559
1746
|
function normalizeGhTime(value) {
|
|
1560
1747
|
if (typeof value !== "string" || !value.trim()) return null;
|
|
@@ -1880,7 +2067,7 @@ async function fetchPrHead(repoPath, number, localBranch) {
|
|
|
1880
2067
|
const label = opts?.ghAuth ? `${remote} (gh auth)` : remote;
|
|
1881
2068
|
const gitOpts = { reject: false };
|
|
1882
2069
|
if (opts?.ghAuth) {
|
|
1883
|
-
const token = await
|
|
2070
|
+
const token = await resolveGithubAgentToken(getGithubGitAuthMode(), repoPath);
|
|
1884
2071
|
if (!token) {
|
|
1885
2072
|
errors.push(`${label}: gh auth token unavailable`);
|
|
1886
2073
|
return false;
|
|
@@ -1931,7 +2118,7 @@ async function fetchPrHead(repoPath, number, localBranch) {
|
|
|
1931
2118
|
const ensureOid = async (remote, opts) => {
|
|
1932
2119
|
const gitOpts = { reject: false };
|
|
1933
2120
|
if (opts?.ghAuth) {
|
|
1934
|
-
const token = await
|
|
2121
|
+
const token = await resolveGithubAgentToken(getGithubGitAuthMode(), repoPath);
|
|
1935
2122
|
if (!token) return false;
|
|
1936
2123
|
gitOpts.env = { GIT_TERMINAL_PROMPT: "0" };
|
|
1937
2124
|
gitOpts.config = {
|
|
@@ -1999,8 +2186,8 @@ function isLocalPrFetchBranch(ref) {
|
|
|
1999
2186
|
}
|
|
2000
2187
|
async function createThreadWorktree(opts) {
|
|
2001
2188
|
let branchName = `thread/${opts.slug}`;
|
|
2002
|
-
const worktreePath =
|
|
2003
|
-
if (
|
|
2189
|
+
const worktreePath = join2(worktreesRoot(opts.repoPath), opts.slug);
|
|
2190
|
+
if (existsSync2(worktreePath)) {
|
|
2004
2191
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
2005
2192
|
}
|
|
2006
2193
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -2069,8 +2256,8 @@ ${add.stdout}`;
|
|
|
2069
2256
|
async function createExistingBranchWorktree(opts) {
|
|
2070
2257
|
const branchName = opts.branchName.trim();
|
|
2071
2258
|
if (!branchName) throw new Error("branch name required");
|
|
2072
|
-
const worktreePath =
|
|
2073
|
-
if (
|
|
2259
|
+
const worktreePath = join2(worktreesRoot(opts.repoPath), opts.slug);
|
|
2260
|
+
if (existsSync2(worktreePath)) {
|
|
2074
2261
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
2075
2262
|
}
|
|
2076
2263
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -2181,7 +2368,7 @@ async function pushBranch(worktreePath, branchName) {
|
|
|
2181
2368
|
if (ssh.exitCode === 0) return;
|
|
2182
2369
|
const sshErr = (ssh.stderr || ssh.stdout).trim();
|
|
2183
2370
|
const slug = await resolveGithubRepoSlug(worktreePath);
|
|
2184
|
-
const token = await
|
|
2371
|
+
const token = await resolveGithubAgentToken(getGithubGitAuthMode(), worktreePath);
|
|
2185
2372
|
if (!slug || !token) {
|
|
2186
2373
|
throw new Error(
|
|
2187
2374
|
sshErr || `git push origin ${branchName} failed` + (!token ? " (no SSH agent and gh auth token unavailable \u2014 run: gh auth login)" : "")
|
|
@@ -2358,8 +2545,8 @@ function sameRepoPath(a, b) {
|
|
|
2358
2545
|
return normalizeWorktreePath(a) === normalizeWorktreePath(b);
|
|
2359
2546
|
}
|
|
2360
2547
|
function listLocalThreadBranchSlugs(repoPath) {
|
|
2361
|
-
const refsDir =
|
|
2362
|
-
if (!
|
|
2548
|
+
const refsDir = join2(repoPath, ".git", "refs", "heads", "thread");
|
|
2549
|
+
if (!existsSync2(refsDir)) return [];
|
|
2363
2550
|
try {
|
|
2364
2551
|
return readdirSync(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
|
|
2365
2552
|
} catch {
|
|
@@ -2369,7 +2556,7 @@ function listLocalThreadBranchSlugs(repoPath) {
|
|
|
2369
2556
|
function collectTakenTeamSlugs(repoPath) {
|
|
2370
2557
|
const taken = /* @__PURE__ */ new Set();
|
|
2371
2558
|
const root = worktreesRoot(repoPath);
|
|
2372
|
-
if (
|
|
2559
|
+
if (existsSync2(root)) {
|
|
2373
2560
|
for (const entry of readdirSync(root, { withFileTypes: true })) {
|
|
2374
2561
|
if (entry.isDirectory() && entry.name !== ".DS_Store") {
|
|
2375
2562
|
taken.add(normalizeTakenSlug(entry.name));
|
|
@@ -2391,8 +2578,8 @@ function allocateTeamSlug(repoPath) {
|
|
|
2391
2578
|
const taken = collectTakenTeamSlugs(repoPath);
|
|
2392
2579
|
for (let attempt = 0; attempt < 32; attempt++) {
|
|
2393
2580
|
const team = allocateTeamName(taken);
|
|
2394
|
-
const path =
|
|
2395
|
-
if (!
|
|
2581
|
+
const path = join2(worktreesRoot(repoPath), team.slug);
|
|
2582
|
+
if (!existsSync2(path)) return team;
|
|
2396
2583
|
taken.add(team.slug);
|
|
2397
2584
|
}
|
|
2398
2585
|
throw new Error("No available soccer team worktree directories left");
|
|
@@ -2413,7 +2600,10 @@ export {
|
|
|
2413
2600
|
worktreeDisplayLabelForGroup,
|
|
2414
2601
|
formatGhLandError,
|
|
2415
2602
|
githubAgentGitEnv,
|
|
2603
|
+
mergeAgentGitAuthEnv,
|
|
2416
2604
|
resolveAgentGitAuthEnv,
|
|
2605
|
+
warmGithubAgentAuth,
|
|
2606
|
+
resolveCodexGitWritableRoots,
|
|
2417
2607
|
codexUnattendedGitConfigArgs,
|
|
2418
2608
|
formatGitAuthModeDirective,
|
|
2419
2609
|
detectGhStack,
|
|
@@ -2433,7 +2623,10 @@ export {
|
|
|
2433
2623
|
listBranches,
|
|
2434
2624
|
listPrs,
|
|
2435
2625
|
getPr,
|
|
2626
|
+
isDefaultishSourceRef,
|
|
2627
|
+
resolvePrSelectors,
|
|
2436
2628
|
resolvePrSelector,
|
|
2629
|
+
getPrForHeadBranch,
|
|
2437
2630
|
detectLocalMergeConflicts,
|
|
2438
2631
|
getPrChecks,
|
|
2439
2632
|
getPrMeta,
|