@sideboard-ai/core 0.1.77 → 0.1.81
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-LKUHPPEQ.js → agents-EBKJ55PN.js} +5 -5
- package/dist/{agents-XJV6J3K2.js → agents-UQ7D6U6L.js} +6 -6
- package/dist/{app-settings-3TLA2EJ7.js → app-settings-6IOQYGBK.js} +7 -1
- package/dist/{app-settings-P42Z3VOB.js → app-settings-NILNWNNQ.js} +7 -1
- package/dist/{chunk-2FJI5JXX.js → chunk-4AVU4QXO.js} +54 -20
- package/dist/{chunk-XJNCWYFR.js → chunk-4HJK57XU.js} +8 -14
- package/dist/{chunk-VERLUKN2.js → chunk-6F2TQFJE.js} +6 -6
- package/dist/{chunk-EEKSZTMU.js → chunk-CQBQWX73.js} +10 -16
- package/dist/{chunk-OE7YBB5X.js → chunk-FUUVPN4A.js} +108 -3
- package/dist/{chunk-W7YOTDVO.js → chunk-IFPN6TER.js} +47 -2
- package/dist/{chunk-75U65MBE.js → chunk-K553XK7M.js} +2 -2
- package/dist/{chunk-GWTLKXXP.js → chunk-P5VDPGAN.js} +3 -3
- package/dist/{chunk-2ZIPJRJE.js → chunk-TDJ43HUD.js} +2 -2
- package/dist/{chunk-PTJJIQK7.js → chunk-XKNBSYA7.js} +47 -2
- package/dist/{chunk-QD37IILI.js → chunk-XNECBC6T.js} +66 -20
- package/dist/{chunk-MF2YMEGD.js → chunk-YVVXWWCC.js} +110 -3
- package/dist/{coordinator-prompt-LLFJUO2R.js → coordinator-prompt-JQF72JKX.js} +4 -4
- package/dist/{coordinator-prompt-MRCMMRSF.js → coordinator-prompt-NYNEFKIV.js} +3 -3
- package/dist/{global-workspace-YNMNO4CL.js → global-workspace-DZM4ZFGU.js} +5 -5
- package/dist/{global-workspace-TWHMYLTZ.js → global-workspace-NUMUJRWG.js} +4 -4
- package/dist/index.cjs +585 -251
- package/dist/index.d.cts +97 -8
- package/dist/index.d.ts +97 -8
- package/dist/index.js +363 -222
- package/dist/mcp/run-stdio.cjs +2502 -2286
- package/dist/mcp/run-stdio.js +162 -133
- package/dist/{workspaces-O3U5BENH.js → workspaces-QLRCOXAY.js} +6 -6
- package/dist/{workspaces-GQ4XKBD3.js → workspaces-SUU2GO3A.js} +5 -5
- package/dist/{worktree-VOCH3WS3.js → worktree-5VLLFI5W.js} +5 -1
- package/dist/{worktree-KWXHMKRN.js → worktree-UNSOCYZU.js} +5 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -79,11 +79,11 @@ var init_thinking_effort = __esm({
|
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
// src/hook/settings.ts
|
|
82
|
-
function expandHome(
|
|
83
|
-
if (
|
|
84
|
-
return (0, import_node_path.join)((0, import_node_os.homedir)(),
|
|
82
|
+
function expandHome(path2) {
|
|
83
|
+
if (path2.startsWith("~/") || path2 === "~") {
|
|
84
|
+
return (0, import_node_path.join)((0, import_node_os.homedir)(), path2.slice(2));
|
|
85
85
|
}
|
|
86
|
-
return
|
|
86
|
+
return path2;
|
|
87
87
|
}
|
|
88
88
|
function parseAvailableIn(raw) {
|
|
89
89
|
if (!Array.isArray(raw)) return void 0;
|
|
@@ -93,9 +93,9 @@ function parseAvailableIn(raw) {
|
|
|
93
93
|
}
|
|
94
94
|
return out.length ? out : void 0;
|
|
95
95
|
}
|
|
96
|
-
function parseSettingsFile(
|
|
97
|
-
if (!(0, import_node_fs.existsSync)(
|
|
98
|
-
const raw = (0, import_node_fs.readFileSync)(
|
|
96
|
+
function parseSettingsFile(path2, source) {
|
|
97
|
+
if (!(0, import_node_fs.existsSync)(path2)) return null;
|
|
98
|
+
const raw = (0, import_node_fs.readFileSync)(path2, "utf8");
|
|
99
99
|
const data = (0, import_smol_toml.parse)(raw);
|
|
100
100
|
const scripts = data.scripts ?? {};
|
|
101
101
|
const setup = typeof scripts.setup === "string" ? scripts.setup : void 0;
|
|
@@ -386,14 +386,14 @@ var init_paths = __esm({
|
|
|
386
386
|
});
|
|
387
387
|
|
|
388
388
|
// src/store/private-file.ts
|
|
389
|
-
function writePrivateFile(
|
|
390
|
-
(0, import_node_fs3.mkdirSync)((0, import_node_path4.dirname)(
|
|
391
|
-
(0, import_node_fs3.writeFileSync)(
|
|
392
|
-
chmodOwnerOnly(
|
|
389
|
+
function writePrivateFile(path2, contents) {
|
|
390
|
+
(0, import_node_fs3.mkdirSync)((0, import_node_path4.dirname)(path2), { recursive: true });
|
|
391
|
+
(0, import_node_fs3.writeFileSync)(path2, contents, { encoding: "utf8", mode: PRIVATE_FILE_MODE });
|
|
392
|
+
chmodOwnerOnly(path2);
|
|
393
393
|
}
|
|
394
|
-
function chmodOwnerOnly(
|
|
394
|
+
function chmodOwnerOnly(path2) {
|
|
395
395
|
try {
|
|
396
|
-
(0, import_node_fs3.chmodSync)(
|
|
396
|
+
(0, import_node_fs3.chmodSync)(path2, PRIVATE_FILE_MODE);
|
|
397
397
|
} catch {
|
|
398
398
|
}
|
|
399
399
|
}
|
|
@@ -493,12 +493,12 @@ function decryptEnvelope(envelope, key) {
|
|
|
493
493
|
]);
|
|
494
494
|
return JSON.parse(plaintext.toString("utf8"));
|
|
495
495
|
}
|
|
496
|
-
function readSecureJson(
|
|
497
|
-
if (!(0, import_node_fs4.existsSync)(
|
|
498
|
-
chmodOwnerOnly(
|
|
496
|
+
function readSecureJson(path2) {
|
|
497
|
+
if (!(0, import_node_fs4.existsSync)(path2)) return null;
|
|
498
|
+
chmodOwnerOnly(path2);
|
|
499
499
|
let parsed;
|
|
500
500
|
try {
|
|
501
|
-
parsed = JSON.parse((0, import_node_fs4.readFileSync)(
|
|
501
|
+
parsed = JSON.parse((0, import_node_fs4.readFileSync)(path2, "utf8"));
|
|
502
502
|
} catch {
|
|
503
503
|
return null;
|
|
504
504
|
}
|
|
@@ -511,24 +511,24 @@ function readSecureJson(path) {
|
|
|
511
511
|
}
|
|
512
512
|
return decryptEnvelope(parsed, key);
|
|
513
513
|
}
|
|
514
|
-
function writeSecureJson(
|
|
514
|
+
function writeSecureJson(path2, value) {
|
|
515
515
|
const key = resolveVaultKey();
|
|
516
516
|
const body = key ? encryptJson(value, key) : value;
|
|
517
|
-
writePrivateFile(
|
|
517
|
+
writePrivateFile(path2, `${JSON.stringify(body, null, 2)}
|
|
518
518
|
`);
|
|
519
519
|
}
|
|
520
|
-
function isSecureFileEncrypted(
|
|
521
|
-
if (!(0, import_node_fs4.existsSync)(
|
|
520
|
+
function isSecureFileEncrypted(path2) {
|
|
521
|
+
if (!(0, import_node_fs4.existsSync)(path2)) return false;
|
|
522
522
|
try {
|
|
523
|
-
return isEnvelope(JSON.parse((0, import_node_fs4.readFileSync)(
|
|
523
|
+
return isEnvelope(JSON.parse((0, import_node_fs4.readFileSync)(path2, "utf8")));
|
|
524
524
|
} catch {
|
|
525
525
|
return false;
|
|
526
526
|
}
|
|
527
527
|
}
|
|
528
|
-
function secureFileUnlocksWith(
|
|
529
|
-
if (!(0, import_node_fs4.existsSync)(
|
|
528
|
+
function secureFileUnlocksWith(path2, key) {
|
|
529
|
+
if (!(0, import_node_fs4.existsSync)(path2) || key.length !== 32) return true;
|
|
530
530
|
try {
|
|
531
|
-
const parsed = JSON.parse((0, import_node_fs4.readFileSync)(
|
|
531
|
+
const parsed = JSON.parse((0, import_node_fs4.readFileSync)(path2, "utf8"));
|
|
532
532
|
if (!isEnvelope(parsed)) return true;
|
|
533
533
|
decryptEnvelope(parsed, key);
|
|
534
534
|
return true;
|
|
@@ -583,6 +583,9 @@ function normalizeVault(raw) {
|
|
|
583
583
|
if (typeof raw.slackAppToken === "string" && raw.slackAppToken.trim()) {
|
|
584
584
|
out.slackAppToken = raw.slackAppToken.trim();
|
|
585
585
|
}
|
|
586
|
+
if (typeof raw.githubPat === "string" && raw.githubPat.trim()) {
|
|
587
|
+
out.githubPat = raw.githubPat.trim();
|
|
588
|
+
}
|
|
586
589
|
if (raw.environment && typeof raw.environment === "object") {
|
|
587
590
|
const environment = {};
|
|
588
591
|
for (const [key, value] of Object.entries(raw.environment)) {
|
|
@@ -607,6 +610,7 @@ var init_secret_vault = __esm({
|
|
|
607
610
|
// src/store/app-settings.ts
|
|
608
611
|
var app_settings_exports = {};
|
|
609
612
|
__export(app_settings_exports, {
|
|
613
|
+
GITHUB_GIT_AUTH_MODES: () => GITHUB_GIT_AUTH_MODES,
|
|
610
614
|
HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
|
|
611
615
|
appSettingsPath: () => appSettingsPath,
|
|
612
616
|
applyAppEnvironment: () => applyAppEnvironment,
|
|
@@ -630,6 +634,8 @@ __export(app_settings_exports, {
|
|
|
630
634
|
getDefaultEffort: () => getDefaultEffort,
|
|
631
635
|
getDefaultFast: () => getDefaultFast,
|
|
632
636
|
getDefaultModel: () => getDefaultModel,
|
|
637
|
+
getGithubGitAuthMode: () => getGithubGitAuthMode,
|
|
638
|
+
getGithubPat: () => getGithubPat,
|
|
633
639
|
getIssueSource: () => getIssueSource,
|
|
634
640
|
getLinearApiKey: () => getLinearApiKey,
|
|
635
641
|
harnessEnvKey: () => harnessEnvKey,
|
|
@@ -674,12 +680,14 @@ function toPublicAppSettings(settings) {
|
|
|
674
680
|
const integrations = { ...settings.integrations };
|
|
675
681
|
const slackClientSecret = integrations.slackClientSecret;
|
|
676
682
|
const slackAppToken = integrations.slackAppToken;
|
|
683
|
+
const githubPat = integrations.githubPat;
|
|
677
684
|
delete integrations.linearApiKey;
|
|
678
685
|
delete integrations.linearAccessToken;
|
|
679
686
|
delete integrations.linearRefreshToken;
|
|
680
687
|
delete integrations.linearClientSecret;
|
|
681
688
|
delete integrations.slackClientSecret;
|
|
682
689
|
delete integrations.slackAppToken;
|
|
690
|
+
delete integrations.githubPat;
|
|
683
691
|
return {
|
|
684
692
|
...settings,
|
|
685
693
|
environment,
|
|
@@ -688,7 +696,8 @@ function toPublicAppSettings(settings) {
|
|
|
688
696
|
hasLinearApiKey: hasLinearCredentials(settings.integrations),
|
|
689
697
|
hasLinearOAuth: hasLinearOAuth(settings.integrations),
|
|
690
698
|
hasSlackClientSecret: Boolean(slackClientSecret?.trim()),
|
|
691
|
-
hasSlackAppToken: Boolean(slackAppToken?.trim())
|
|
699
|
+
hasSlackAppToken: Boolean(slackAppToken?.trim()),
|
|
700
|
+
hasGithubPat: Boolean(githubPat?.trim())
|
|
692
701
|
}
|
|
693
702
|
};
|
|
694
703
|
}
|
|
@@ -703,8 +712,8 @@ function normalizeClaude(raw) {
|
|
|
703
712
|
const source = raw;
|
|
704
713
|
const out = {};
|
|
705
714
|
if (typeof source.executablePath === "string") {
|
|
706
|
-
const
|
|
707
|
-
if (
|
|
715
|
+
const path2 = source.executablePath.trim();
|
|
716
|
+
if (path2) out.executablePath = path2;
|
|
708
717
|
}
|
|
709
718
|
if (typeof source.chromeEnabled === "boolean") {
|
|
710
719
|
out.chromeEnabled = source.chromeEnabled;
|
|
@@ -716,8 +725,8 @@ function normalizeCliExecutable(raw) {
|
|
|
716
725
|
const source = raw;
|
|
717
726
|
const out = {};
|
|
718
727
|
if (typeof source.executablePath === "string") {
|
|
719
|
-
const
|
|
720
|
-
if (
|
|
728
|
+
const path2 = source.executablePath.trim();
|
|
729
|
+
if (path2) out.executablePath = path2;
|
|
721
730
|
}
|
|
722
731
|
return out;
|
|
723
732
|
}
|
|
@@ -726,8 +735,8 @@ function normalizeBrightsy(raw) {
|
|
|
726
735
|
const source = raw;
|
|
727
736
|
const out = {};
|
|
728
737
|
if (typeof source.executablePath === "string") {
|
|
729
|
-
const
|
|
730
|
-
if (
|
|
738
|
+
const path2 = source.executablePath.trim();
|
|
739
|
+
if (path2) out.executablePath = path2;
|
|
731
740
|
}
|
|
732
741
|
if (typeof source.cloudConnectEnabled === "boolean") {
|
|
733
742
|
out.cloudConnectEnabled = source.cloudConnectEnabled;
|
|
@@ -804,6 +813,13 @@ function normalizeIntegrations(raw) {
|
|
|
804
813
|
const label = source.slackDeviceLabel.trim().slice(0, 64);
|
|
805
814
|
if (label) out.slackDeviceLabel = label;
|
|
806
815
|
}
|
|
816
|
+
if (typeof source.githubGitAuthMode === "string" && GIT_AUTH_MODES.has(source.githubGitAuthMode)) {
|
|
817
|
+
out.githubGitAuthMode = source.githubGitAuthMode;
|
|
818
|
+
}
|
|
819
|
+
if (typeof source.githubPat === "string") {
|
|
820
|
+
const pat = source.githubPat.trim();
|
|
821
|
+
if (pat) out.githubPat = pat;
|
|
822
|
+
}
|
|
807
823
|
return out;
|
|
808
824
|
}
|
|
809
825
|
function normalizeDefaults(raw) {
|
|
@@ -931,11 +947,11 @@ function normalizeSettings(raw) {
|
|
|
931
947
|
};
|
|
932
948
|
}
|
|
933
949
|
function readSettingsFile() {
|
|
934
|
-
const
|
|
935
|
-
if (!(0, import_node_fs5.existsSync)(
|
|
950
|
+
const path2 = appSettingsPath();
|
|
951
|
+
if (!(0, import_node_fs5.existsSync)(path2)) return { ...EMPTY_SETTINGS };
|
|
936
952
|
try {
|
|
937
|
-
chmodOwnerOnly(
|
|
938
|
-
const parsed = JSON.parse((0, import_node_fs5.readFileSync)(
|
|
953
|
+
chmodOwnerOnly(path2);
|
|
954
|
+
const parsed = JSON.parse((0, import_node_fs5.readFileSync)(path2, "utf8"));
|
|
939
955
|
return normalizeSettings(parsed);
|
|
940
956
|
} catch {
|
|
941
957
|
return { ...EMPTY_SETTINGS };
|
|
@@ -943,7 +959,7 @@ function readSettingsFile() {
|
|
|
943
959
|
}
|
|
944
960
|
function diskHoldsSecrets(disk) {
|
|
945
961
|
return Boolean(
|
|
946
|
-
disk.integrations.linearApiKey || disk.integrations.linearAccessToken || disk.integrations.linearRefreshToken || disk.integrations.linearClientSecret || disk.integrations.slackClientSecret || disk.integrations.slackAppToken || Object.keys(disk.environment).length > 0
|
|
962
|
+
disk.integrations.linearApiKey || disk.integrations.linearAccessToken || disk.integrations.linearRefreshToken || disk.integrations.linearClientSecret || disk.integrations.slackClientSecret || disk.integrations.slackAppToken || disk.integrations.githubPat || Object.keys(disk.environment).length > 0
|
|
947
963
|
);
|
|
948
964
|
}
|
|
949
965
|
function mergeVault(disk) {
|
|
@@ -968,6 +984,9 @@ function mergeVault(disk) {
|
|
|
968
984
|
if (vault.slackAppToken && !integrations.slackAppToken) {
|
|
969
985
|
integrations.slackAppToken = vault.slackAppToken;
|
|
970
986
|
}
|
|
987
|
+
if (vault.githubPat && !integrations.githubPat) {
|
|
988
|
+
integrations.githubPat = vault.githubPat;
|
|
989
|
+
}
|
|
971
990
|
return { ...disk, environment, integrations };
|
|
972
991
|
}
|
|
973
992
|
function persistSplit(settings) {
|
|
@@ -978,12 +997,14 @@ function persistSplit(settings) {
|
|
|
978
997
|
const linearClientSecret = integrations.linearClientSecret;
|
|
979
998
|
const slackClientSecret = integrations.slackClientSecret;
|
|
980
999
|
const slackAppToken = integrations.slackAppToken;
|
|
1000
|
+
const githubPat = integrations.githubPat;
|
|
981
1001
|
delete integrations.linearApiKey;
|
|
982
1002
|
delete integrations.linearAccessToken;
|
|
983
1003
|
delete integrations.linearRefreshToken;
|
|
984
1004
|
delete integrations.linearClientSecret;
|
|
985
1005
|
delete integrations.slackClientSecret;
|
|
986
1006
|
delete integrations.slackAppToken;
|
|
1007
|
+
delete integrations.githubPat;
|
|
987
1008
|
writePrivateFile(
|
|
988
1009
|
appSettingsPath(),
|
|
989
1010
|
`${JSON.stringify({ ...settings, environment: {}, integrations }, null, 2)}
|
|
@@ -996,6 +1017,7 @@ function persistSplit(settings) {
|
|
|
996
1017
|
linearClientSecret,
|
|
997
1018
|
slackClientSecret,
|
|
998
1019
|
slackAppToken,
|
|
1020
|
+
githubPat,
|
|
999
1021
|
environment: settings.environment
|
|
1000
1022
|
});
|
|
1001
1023
|
}
|
|
@@ -1161,6 +1183,20 @@ function updateIntegrationsSettings(patch) {
|
|
|
1161
1183
|
integrations.slackDeviceLabel = patch.slackDeviceLabel.trim().slice(0, 64);
|
|
1162
1184
|
}
|
|
1163
1185
|
}
|
|
1186
|
+
if ("githubGitAuthMode" in patch) {
|
|
1187
|
+
if (patch.githubGitAuthMode == null) {
|
|
1188
|
+
delete integrations.githubGitAuthMode;
|
|
1189
|
+
} else if (GIT_AUTH_MODES.has(patch.githubGitAuthMode)) {
|
|
1190
|
+
integrations.githubGitAuthMode = patch.githubGitAuthMode;
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
if ("githubPat" in patch) {
|
|
1194
|
+
if (patch.githubPat == null || patch.githubPat.trim() === "") {
|
|
1195
|
+
delete integrations.githubPat;
|
|
1196
|
+
} else {
|
|
1197
|
+
integrations.githubPat = patch.githubPat.trim();
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1164
1200
|
return saveAppSettings({ ...current, integrations });
|
|
1165
1201
|
}
|
|
1166
1202
|
function updateDefaultsSettings(patch) {
|
|
@@ -1268,6 +1304,13 @@ function disconnectLinearConnection() {
|
|
|
1268
1304
|
function getIssueSource(settings = loadAppSettings()) {
|
|
1269
1305
|
return settings.integrations.issueSource ?? "github";
|
|
1270
1306
|
}
|
|
1307
|
+
function getGithubGitAuthMode(settings = loadAppSettings()) {
|
|
1308
|
+
return settings.integrations.githubGitAuthMode ?? "auto";
|
|
1309
|
+
}
|
|
1310
|
+
function getGithubPat(settings = loadAppSettings()) {
|
|
1311
|
+
const pat = settings.integrations.githubPat?.trim();
|
|
1312
|
+
return pat || null;
|
|
1313
|
+
}
|
|
1271
1314
|
function resolveEffectiveIssueSource(settings = loadAppSettings()) {
|
|
1272
1315
|
const preferred = getIssueSource(settings);
|
|
1273
1316
|
if (preferred === "linear" && !isLinearConnected(settings)) return "github";
|
|
@@ -1468,7 +1511,7 @@ function childEnvWithAppSettings(extra) {
|
|
|
1468
1511
|
function harnessEnvKey(harness) {
|
|
1469
1512
|
return HARNESS_ENV_KEYS[harness];
|
|
1470
1513
|
}
|
|
1471
|
-
var import_node_crypto2, import_node_fs5, import_node_os3, import_node_path6, HARNESS_ENV_KEYS, DEFAULT_AGENTS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, EMPTY_SETTINGS, DEFAULT_CLI_BIN;
|
|
1514
|
+
var import_node_crypto2, import_node_fs5, import_node_os3, import_node_path6, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, DEFAULT_CLI_BIN;
|
|
1472
1515
|
var init_app_settings = __esm({
|
|
1473
1516
|
"src/store/app-settings.ts"() {
|
|
1474
1517
|
"use strict";
|
|
@@ -1494,6 +1537,7 @@ var init_app_settings = __esm({
|
|
|
1494
1537
|
"brightsy",
|
|
1495
1538
|
"cursor"
|
|
1496
1539
|
]);
|
|
1540
|
+
GITHUB_GIT_AUTH_MODES = ["auto", "gh", "ssh", "token"];
|
|
1497
1541
|
CLOUD_CONNECT_AGENTS = /* @__PURE__ */ new Set([
|
|
1498
1542
|
"claude",
|
|
1499
1543
|
"codex",
|
|
@@ -1501,6 +1545,7 @@ var init_app_settings = __esm({
|
|
|
1501
1545
|
"cursor"
|
|
1502
1546
|
]);
|
|
1503
1547
|
ISSUE_SOURCES = /* @__PURE__ */ new Set(["linear", "github"]);
|
|
1548
|
+
GIT_AUTH_MODES = new Set(GITHUB_GIT_AUTH_MODES);
|
|
1504
1549
|
EMPTY_SETTINGS = {
|
|
1505
1550
|
environment: {},
|
|
1506
1551
|
claude: {},
|
|
@@ -1567,10 +1612,10 @@ function uniqueIds(ids) {
|
|
|
1567
1612
|
return out;
|
|
1568
1613
|
}
|
|
1569
1614
|
function readHold() {
|
|
1570
|
-
const
|
|
1571
|
-
if (!(0, import_node_fs6.existsSync)(
|
|
1615
|
+
const path2 = caffeinateHoldPath();
|
|
1616
|
+
if (!(0, import_node_fs6.existsSync)(path2)) return null;
|
|
1572
1617
|
try {
|
|
1573
|
-
const parsed = JSON.parse((0, import_node_fs6.readFileSync)(
|
|
1618
|
+
const parsed = JSON.parse((0, import_node_fs6.readFileSync)(path2, "utf8"));
|
|
1574
1619
|
if (typeof parsed?.pid === "number" && parsed.pid > 0) {
|
|
1575
1620
|
return {
|
|
1576
1621
|
pid: parsed.pid,
|
|
@@ -1790,17 +1835,17 @@ async function withThreadLock(id, fn) {
|
|
|
1790
1835
|
}
|
|
1791
1836
|
}
|
|
1792
1837
|
function readThread(id) {
|
|
1793
|
-
const
|
|
1794
|
-
if (!(0, import_node_fs7.existsSync)(
|
|
1795
|
-
const raw = (0, import_node_fs7.readFileSync)(
|
|
1838
|
+
const path2 = threadFilePath(id);
|
|
1839
|
+
if (!(0, import_node_fs7.existsSync)(path2)) return null;
|
|
1840
|
+
const raw = (0, import_node_fs7.readFileSync)(path2, "utf8");
|
|
1796
1841
|
return normalizeThread(JSON.parse(raw));
|
|
1797
1842
|
}
|
|
1798
1843
|
function writeThread(thread) {
|
|
1799
|
-
const
|
|
1800
|
-
const tmp = `${
|
|
1844
|
+
const path2 = threadFilePath(idPath(thread.id));
|
|
1845
|
+
const tmp = `${path2}.${process.pid}.tmp`;
|
|
1801
1846
|
const next = { ...thread, updatedAt: nowIso() };
|
|
1802
1847
|
(0, import_node_fs7.writeFileSync)(tmp, JSON.stringify(next, null, 2), "utf8");
|
|
1803
|
-
(0, import_node_fs7.renameSync)(tmp,
|
|
1848
|
+
(0, import_node_fs7.renameSync)(tmp, path2);
|
|
1804
1849
|
}
|
|
1805
1850
|
function idPath(id) {
|
|
1806
1851
|
return id;
|
|
@@ -1820,8 +1865,8 @@ function listThreads(opts) {
|
|
|
1820
1865
|
return threads.filter((t) => t.status !== "archived");
|
|
1821
1866
|
}
|
|
1822
1867
|
function deleteThreadRecord(id) {
|
|
1823
|
-
const
|
|
1824
|
-
if ((0, import_node_fs7.existsSync)(
|
|
1868
|
+
const path2 = threadFilePath(id);
|
|
1869
|
+
if ((0, import_node_fs7.existsSync)(path2)) (0, import_node_fs7.unlinkSync)(path2);
|
|
1825
1870
|
const lock = threadLockPath(id);
|
|
1826
1871
|
if ((0, import_node_fs7.existsSync)(lock)) {
|
|
1827
1872
|
try {
|
|
@@ -2820,6 +2865,80 @@ var init_gh_errors = __esm({
|
|
|
2820
2865
|
}
|
|
2821
2866
|
});
|
|
2822
2867
|
|
|
2868
|
+
// src/git/git-auth-mode.ts
|
|
2869
|
+
function appendIndexedGitConfig(existing, entries) {
|
|
2870
|
+
const start = Number.parseInt(String(existing?.GIT_CONFIG_COUNT ?? "0"), 10);
|
|
2871
|
+
const count = Number.isFinite(start) && start > 0 ? start : 0;
|
|
2872
|
+
const out = {};
|
|
2873
|
+
entries.forEach((entry, i) => {
|
|
2874
|
+
const n = count + i;
|
|
2875
|
+
out[`GIT_CONFIG_KEY_${n}`] = entry.key;
|
|
2876
|
+
out[`GIT_CONFIG_VALUE_${n}`] = entry.value;
|
|
2877
|
+
});
|
|
2878
|
+
out.GIT_CONFIG_COUNT = String(count + entries.length);
|
|
2879
|
+
return out;
|
|
2880
|
+
}
|
|
2881
|
+
function githubAgentGitEnv(existing) {
|
|
2882
|
+
return appendIndexedGitConfig(existing, HTTPS_REWRITE);
|
|
2883
|
+
}
|
|
2884
|
+
function applyGithubGitAuthEnv(existing, opts) {
|
|
2885
|
+
const out = {};
|
|
2886
|
+
if (opts.mode === "gh" || opts.mode === "token") {
|
|
2887
|
+
Object.assign(out, githubAgentGitEnv(existing));
|
|
2888
|
+
}
|
|
2889
|
+
if (opts.mode === "token") {
|
|
2890
|
+
const token = opts.token?.trim();
|
|
2891
|
+
if (token && !existing?.GH_TOKEN?.trim()) {
|
|
2892
|
+
out.GH_TOKEN = token;
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
return out;
|
|
2896
|
+
}
|
|
2897
|
+
function formatGitAuthModeDirective(mode) {
|
|
2898
|
+
switch (mode) {
|
|
2899
|
+
case "gh":
|
|
2900
|
+
return [
|
|
2901
|
+
"Git authentication (Account \u2192 GitHub mode: gh CLI):",
|
|
2902
|
+
"- This process rewrites `git@github.com:` and `ssh://git@github.com/` to HTTPS.",
|
|
2903
|
+
"- `gh` supplies credentials (`gh auth git-credential`). Do not switch remotes to SSH.",
|
|
2904
|
+
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
2905
|
+
].join("\n");
|
|
2906
|
+
case "ssh":
|
|
2907
|
+
return [
|
|
2908
|
+
"Git authentication (Account \u2192 GitHub mode: SSH):",
|
|
2909
|
+
"- Keep SSH remotes (`git@github.com:\u2026`). Do not rewrite them to HTTPS.",
|
|
2910
|
+
"- Use this Mac\u2019s SSH agent / keys. If push fails with `Permission denied (publickey)`, tell the user to start ssh-agent or switch Account \u2192 GitHub to Auto / gh CLI \u2014 do not rewrite remotes yourself.",
|
|
2911
|
+
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below (API still uses `gh`)."
|
|
2912
|
+
].join("\n");
|
|
2913
|
+
case "token":
|
|
2914
|
+
return [
|
|
2915
|
+
"Git authentication (Account \u2192 GitHub mode: personal access token):",
|
|
2916
|
+
"- This process rewrites GitHub SSH remotes to HTTPS.",
|
|
2917
|
+
"- `GH_TOKEN` is set in the environment. Use HTTPS git and `gh`; do not paste the token into commands or chat.",
|
|
2918
|
+
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
2919
|
+
].join("\n");
|
|
2920
|
+
case "auto":
|
|
2921
|
+
default:
|
|
2922
|
+
return [
|
|
2923
|
+
"Git authentication (Account \u2192 GitHub mode: auto):",
|
|
2924
|
+
"- Prefer the existing remote URL (SSH or HTTPS). Do not rewrite remotes unless a push/fetch fails.",
|
|
2925
|
+
'- If `git push` fails with `Permission denied (publickey)`, this shell has no ssh-agent. Retry over HTTPS (do not stop): `git -c url.https://github.com/.insteadOf=git@github.com: -c http.extraHeader="AUTHORIZATION: bearer $(gh auth token)" push -u origin HEAD`.',
|
|
2926
|
+
"- Then create/update the PR with `gh` as below."
|
|
2927
|
+
].join("\n");
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
var HTTPS_REWRITE;
|
|
2931
|
+
var init_git_auth_mode = __esm({
|
|
2932
|
+
"src/git/git-auth-mode.ts"() {
|
|
2933
|
+
"use strict";
|
|
2934
|
+
HTTPS_REWRITE = [
|
|
2935
|
+
{ key: "url.https://github.com/.insteadOf", value: "git@github.com:" },
|
|
2936
|
+
{ key: "url.https://github.com/.insteadOf", value: "ssh://git@github.com/" },
|
|
2937
|
+
{ key: "credential.https://github.com.helper", value: "!gh auth git-credential" }
|
|
2938
|
+
];
|
|
2939
|
+
}
|
|
2940
|
+
});
|
|
2941
|
+
|
|
2823
2942
|
// src/agents/path.ts
|
|
2824
2943
|
function prependPathDir(env, dir) {
|
|
2825
2944
|
if (!dir || !(0, import_node_fs8.existsSync)(dir)) return;
|
|
@@ -3357,6 +3476,7 @@ __export(worktree_exports, {
|
|
|
3357
3476
|
getPrMeta: () => getPrMeta,
|
|
3358
3477
|
ghHeadRef: () => ghHeadRef,
|
|
3359
3478
|
ghRepoSelectArgs: () => ghRepoSelectArgs,
|
|
3479
|
+
githubAgentGitEnv: () => githubAgentGitEnv,
|
|
3360
3480
|
isDirty: () => isDirty,
|
|
3361
3481
|
isPlaceholderBranch: () => isPlaceholderBranch,
|
|
3362
3482
|
isSideboardScratchPath: () => isSideboardScratchPath,
|
|
@@ -3478,10 +3598,15 @@ ${view.stderr}`;
|
|
|
3478
3598
|
timeoutMs: 15e3
|
|
3479
3599
|
});
|
|
3480
3600
|
}
|
|
3481
|
-
async function originGhRepoEnv(cwd) {
|
|
3601
|
+
async function originGhRepoEnv(cwd, opts) {
|
|
3482
3602
|
await ensureGhPreferOrigin(cwd);
|
|
3483
3603
|
const slug = await resolveGithubRepoSlug(cwd);
|
|
3484
|
-
|
|
3604
|
+
const mode = opts?.mode ?? getGithubGitAuthMode();
|
|
3605
|
+
const token = mode === "token" ? getGithubPat() : null;
|
|
3606
|
+
return {
|
|
3607
|
+
...applyGithubGitAuthEnv(opts?.env, { mode, token }),
|
|
3608
|
+
...slug ? { GH_REPO: slug } : {}
|
|
3609
|
+
};
|
|
3485
3610
|
}
|
|
3486
3611
|
async function resolveDefaultBranch(repoPath, opts) {
|
|
3487
3612
|
const viaOrigin = await git(
|
|
@@ -4230,7 +4355,33 @@ async function commitAll(worktreePath, message) {
|
|
|
4230
4355
|
return true;
|
|
4231
4356
|
}
|
|
4232
4357
|
async function pushBranch(worktreePath, branchName) {
|
|
4233
|
-
await git(["push", "-u", "origin", branchName], worktreePath
|
|
4358
|
+
const ssh = await git(["push", "-u", "origin", branchName], worktreePath, {
|
|
4359
|
+
reject: false
|
|
4360
|
+
});
|
|
4361
|
+
if (ssh.exitCode === 0) return;
|
|
4362
|
+
const sshErr = (ssh.stderr || ssh.stdout).trim();
|
|
4363
|
+
const slug = await resolveGithubRepoSlug(worktreePath);
|
|
4364
|
+
const token = await resolveGhAuthToken(worktreePath);
|
|
4365
|
+
if (!slug || !token) {
|
|
4366
|
+
throw new Error(
|
|
4367
|
+
sshErr || `git push origin ${branchName} failed` + (!token ? " (no SSH agent and gh auth token unavailable \u2014 run: gh auth login)" : "")
|
|
4368
|
+
);
|
|
4369
|
+
}
|
|
4370
|
+
const tryHttps = async (header) => git(["push", "-u", "origin", branchName], worktreePath, {
|
|
4371
|
+
reject: false,
|
|
4372
|
+
env: { GIT_TERMINAL_PROMPT: "0" },
|
|
4373
|
+
config: {
|
|
4374
|
+
"url.https://github.com/.insteadOf": "git@github.com:",
|
|
4375
|
+
"http.extraHeader": header
|
|
4376
|
+
}
|
|
4377
|
+
});
|
|
4378
|
+
const bearer = await tryHttps(`AUTHORIZATION: bearer ${token}`);
|
|
4379
|
+
if (bearer.exitCode === 0) return;
|
|
4380
|
+
const basic = Buffer.from(`x-access-token:${token}`, "utf8").toString("base64");
|
|
4381
|
+
const basicPush = await tryHttps(`Authorization: Basic ${basic}`);
|
|
4382
|
+
if (basicPush.exitCode === 0) return;
|
|
4383
|
+
const httpsErr = (basicPush.stderr || bearer.stderr || bearer.stdout).trim();
|
|
4384
|
+
throw new Error(httpsErr || sshErr || `git push origin ${branchName} failed`);
|
|
4234
4385
|
}
|
|
4235
4386
|
async function mergePr(cwd, selector, opts) {
|
|
4236
4387
|
const slug = await resolveGithubRepoSlug(cwd);
|
|
@@ -4418,8 +4569,8 @@ function allocateTeamSlug(repoPath) {
|
|
|
4418
4569
|
const taken = collectTakenTeamSlugs(repoPath);
|
|
4419
4570
|
for (let attempt = 0; attempt < 32; attempt++) {
|
|
4420
4571
|
const team = allocateTeamName(taken);
|
|
4421
|
-
const
|
|
4422
|
-
if (!(0, import_node_fs9.existsSync)(
|
|
4572
|
+
const path2 = (0, import_node_path9.join)(worktreesRoot(repoPath), team.slug);
|
|
4573
|
+
if (!(0, import_node_fs9.existsSync)(path2)) return team;
|
|
4423
4574
|
taken.add(team.slug);
|
|
4424
4575
|
}
|
|
4425
4576
|
throw new Error("No available soccer team worktree directories left");
|
|
@@ -4435,10 +4586,13 @@ var init_worktree = __esm({
|
|
|
4435
4586
|
init_teams();
|
|
4436
4587
|
init_worktree_labels();
|
|
4437
4588
|
init_gh_errors();
|
|
4589
|
+
init_git_auth_mode();
|
|
4438
4590
|
init_run();
|
|
4591
|
+
init_app_settings();
|
|
4439
4592
|
init_pr_gates();
|
|
4440
4593
|
init_stack();
|
|
4441
4594
|
init_teams();
|
|
4595
|
+
init_git_auth_mode();
|
|
4442
4596
|
init_workspace_scratch();
|
|
4443
4597
|
init_worktree_labels();
|
|
4444
4598
|
}
|
|
@@ -4501,7 +4655,7 @@ function coordinatorTurnReminder(opts) {
|
|
|
4501
4655
|
goal ? `- Goal / title: ${goal}` : null,
|
|
4502
4656
|
accountDefaultsPlaybookLine(),
|
|
4503
4657
|
`- For "what's going on": call list_threads (and list_workspaces if needed). Summarize fleet status \u2014 do not ls/git-status this synthetic home.`,
|
|
4504
|
-
"- Existing repo: create_thread on a repoPath \u2192 send_to_thread \u2192 wait_for_turn.
|
|
4658
|
+
"- Existing repo: create_thread on a repoPath \u2192 send_to_thread \u2192 wait_for_turn. Commit/push/draft PR with ask_git on the child, then wait_for_turn \u2014 never git/gh from this cwd. Call ask_git merge only if the user explicitly asked to merge.",
|
|
4505
4659
|
"- New repo: Bash (clone or gh repo create under ~/sideboard/repos/<name>) \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 ask_git create-draft.",
|
|
4506
4660
|
"- When naming threads for the user, link them as `[Title](sideboard://thread/<id>)`.",
|
|
4507
4661
|
"- If they will wait on Slack or leave the Mac, call set_caffeinate enabled=true. When they say they are done / wrapping up / going to sleep, call set_caffeinate enabled=false. Closing this chat also turns it off."
|
|
@@ -4555,9 +4709,9 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
4555
4709
|
orchId ? `Pass parentThreadId="${orchId}" (or omit it). Never invent another parentThreadId.` : "Pass `parentThreadId` for children (this chat's id from the turn reminder).",
|
|
4556
4710
|
"Omit `agent` / `model` on `create_thread` unless you have a reason to override Account defaults.",
|
|
4557
4711
|
"Never pass `agent=codex` when you yourself are Codex \u2014 nested Codex deadlocks on shared ~/.codex locks. Omit agent (Account default) or use cursor/claude.",
|
|
4558
|
-
"Typical flow (existing): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 ask_git create-draft \u2192 wait_for_turn
|
|
4712
|
+
"Typical flow (existing): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 ask_git create-draft \u2192 wait_for_turn. Merge only if the user explicitly asked (`ask_git` merge).",
|
|
4559
4713
|
"Typical flow (new app): Bash create/clone under repos dir \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn \u2192 ask_git create-draft.",
|
|
4560
|
-
"Always ask worktree agents to commit, push, open draft PRs
|
|
4714
|
+
"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."
|
|
4561
4715
|
].join("\n");
|
|
4562
4716
|
try {
|
|
4563
4717
|
(0, import_node_fs10.writeFileSync)((0, import_node_path10.join)(dir, "CLAUDE.md"), `${body}
|
|
@@ -4570,7 +4724,6 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
4570
4724
|
}
|
|
4571
4725
|
function coordinatorSystemPrompt(opts) {
|
|
4572
4726
|
const audience = opts.audience ?? "cloud";
|
|
4573
|
-
const reposDir = sideboardReposDir();
|
|
4574
4727
|
const intro = audience === "cloud" ? [
|
|
4575
4728
|
"You are a Sideboard coordinator responding to a request from a Brightsy cloud agent (Discord, Teams, or other chat).",
|
|
4576
4729
|
"Your reply will be sent back to that cloud agent \u2014 be concise and actionable."
|
|
@@ -4588,14 +4741,8 @@ function coordinatorSystemPrompt(opts) {
|
|
|
4588
4741
|
...intro,
|
|
4589
4742
|
"You operate across ALL registered workspaces below.",
|
|
4590
4743
|
"You have no project git home \u2014 this process cwd is synthetic and empty on purpose.",
|
|
4591
|
-
|
|
4592
|
-
accountDefaultsPlaybookLine(),
|
|
4593
|
-
coordinatorGreenfieldPlaybook(reposDir),
|
|
4594
|
-
"When creating threads, pass the correct repoPath for the target workspace.",
|
|
4744
|
+
"Follow AGENTS.md / CLAUDE.md in this cwd for the fleet playbook (they are the same document).",
|
|
4595
4745
|
`YOUR orchestration thread id is ${opts.parentId} \u2014 pass parentThreadId="${opts.parentId}" on create_thread, or omit parentThreadId (Sideboard binds it). Never invent a uuid.`,
|
|
4596
|
-
"Omit agent/model on create_thread unless you need to override Account defaults.",
|
|
4597
|
-
"Typical flow (existing): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn \u2192 ask_git create-draft \u2192 wait_for_turn \u2192 (when ready) ask_git merge \u2192 wait_for_turn. Never target upstream. Never git/gh from this orchestration cwd.",
|
|
4598
|
-
"Typical flow (new app): Bash under repos dir (clone or gh repo create) \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 ask_git create-draft.",
|
|
4599
4746
|
`Goal: ${opts.goal}`,
|
|
4600
4747
|
"Registered workspaces:",
|
|
4601
4748
|
formatWorkspaceInventory(opts.workspaces)
|
|
@@ -4639,7 +4786,8 @@ var init_coordinator_prompt = __esm({
|
|
|
4639
4786
|
"Inspect / review / PRs:",
|
|
4640
4787
|
"- get_diff \u2014 compact diff summary",
|
|
4641
4788
|
'- request_review \u2014 open a Review chat tab on a worktree thread (attaches .sideboard/review.md when present, else local guidelines; sends "Review changes in this workspace."); then wait_for_turn / get_turn_result on the returned id',
|
|
4642
|
-
"- ask_git \u2014
|
|
4789
|
+
"- 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. Prefer this over paraphrasing.",
|
|
4790
|
+
'- 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.',
|
|
4643
4791
|
'- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Fix merge conflicts.", "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.',
|
|
4644
4792
|
"Human-only (do not attempt): ready-for-review land (confirm_land), purge_thread.",
|
|
4645
4793
|
"Thread links in replies: when mentioning a chat/thread for the user, include a markdown link `[Title](sideboard://thread/<id>)` using the full id (or the link field from create_thread / list_threads). Sideboard renders these as clickable opens.",
|
|
@@ -4912,10 +5060,10 @@ function removedWorkspacesFile() {
|
|
|
4912
5060
|
return (0, import_node_path11.join)(appDataDir(), "removed-workspaces.json");
|
|
4913
5061
|
}
|
|
4914
5062
|
function readAll() {
|
|
4915
|
-
const
|
|
4916
|
-
if (!(0, import_node_fs11.existsSync)(
|
|
5063
|
+
const path2 = workspacesFile();
|
|
5064
|
+
if (!(0, import_node_fs11.existsSync)(path2)) return [];
|
|
4917
5065
|
try {
|
|
4918
|
-
const raw = JSON.parse((0, import_node_fs11.readFileSync)(
|
|
5066
|
+
const raw = JSON.parse((0, import_node_fs11.readFileSync)(path2, "utf8"));
|
|
4919
5067
|
return Array.isArray(raw) ? raw : [];
|
|
4920
5068
|
} catch {
|
|
4921
5069
|
return [];
|
|
@@ -4926,10 +5074,10 @@ function writeAll(list) {
|
|
|
4926
5074
|
(0, import_node_fs11.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
|
|
4927
5075
|
}
|
|
4928
5076
|
function readRemoved() {
|
|
4929
|
-
const
|
|
4930
|
-
if (!(0, import_node_fs11.existsSync)(
|
|
5077
|
+
const path2 = removedWorkspacesFile();
|
|
5078
|
+
if (!(0, import_node_fs11.existsSync)(path2)) return /* @__PURE__ */ new Set();
|
|
4931
5079
|
try {
|
|
4932
|
-
const raw = JSON.parse((0, import_node_fs11.readFileSync)(
|
|
5080
|
+
const raw = JSON.parse((0, import_node_fs11.readFileSync)(path2, "utf8"));
|
|
4933
5081
|
return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
|
|
4934
5082
|
} catch {
|
|
4935
5083
|
return /* @__PURE__ */ new Set();
|
|
@@ -4986,17 +5134,17 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
4986
5134
|
const removed = readRemoved();
|
|
4987
5135
|
const byPath = new Map(current.map((w) => [w.path, w]));
|
|
4988
5136
|
let dirty = false;
|
|
4989
|
-
for (const
|
|
4990
|
-
if (!
|
|
5137
|
+
for (const path2 of repoPaths) {
|
|
5138
|
+
if (!path2 || path2 === "/" || isGlobalRepoPath(path2) || byPath.has(path2) || removed.has(path2)) {
|
|
4991
5139
|
continue;
|
|
4992
5140
|
}
|
|
4993
|
-
if (!(0, import_node_fs11.existsSync)(
|
|
5141
|
+
if (!(0, import_node_fs11.existsSync)(path2)) continue;
|
|
4994
5142
|
const ws = {
|
|
4995
|
-
path,
|
|
4996
|
-
name: (0, import_node_path11.basename)(
|
|
5143
|
+
path: path2,
|
|
5144
|
+
name: (0, import_node_path11.basename)(path2),
|
|
4997
5145
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4998
5146
|
};
|
|
4999
|
-
byPath.set(
|
|
5147
|
+
byPath.set(path2, ws);
|
|
5000
5148
|
dirty = true;
|
|
5001
5149
|
}
|
|
5002
5150
|
const next = [...byPath.values()];
|
|
@@ -5020,11 +5168,11 @@ function brightsyConfigPath() {
|
|
|
5020
5168
|
return (0, import_node_path12.join)((0, import_node_os5.homedir)(), ".brightsy", "config.json");
|
|
5021
5169
|
}
|
|
5022
5170
|
function loadBrightsyConfig() {
|
|
5023
|
-
const
|
|
5024
|
-
if (!(0, import_node_fs12.existsSync)(
|
|
5171
|
+
const path2 = brightsyConfigPath();
|
|
5172
|
+
if (!(0, import_node_fs12.existsSync)(path2)) {
|
|
5025
5173
|
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
5026
5174
|
}
|
|
5027
|
-
const raw = JSON.parse((0, import_node_fs12.readFileSync)(
|
|
5175
|
+
const raw = JSON.parse((0, import_node_fs12.readFileSync)(path2, "utf8"));
|
|
5028
5176
|
if (!raw.access_token || !raw.account_id) {
|
|
5029
5177
|
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
5030
5178
|
}
|
|
@@ -5148,10 +5296,10 @@ function storePath() {
|
|
|
5148
5296
|
return (0, import_node_path13.join)(appDataDir(), "brightsy-teams.json");
|
|
5149
5297
|
}
|
|
5150
5298
|
function readStore() {
|
|
5151
|
-
const
|
|
5152
|
-
if (!(0, import_node_fs13.existsSync)(
|
|
5299
|
+
const path2 = storePath();
|
|
5300
|
+
if (!(0, import_node_fs13.existsSync)(path2)) return [];
|
|
5153
5301
|
try {
|
|
5154
|
-
const parsed = JSON.parse((0, import_node_fs13.readFileSync)(
|
|
5302
|
+
const parsed = JSON.parse((0, import_node_fs13.readFileSync)(path2, "utf8"));
|
|
5155
5303
|
return Array.isArray(parsed.teams) ? parsed.teams : [];
|
|
5156
5304
|
} catch {
|
|
5157
5305
|
return [];
|
|
@@ -5159,8 +5307,8 @@ function readStore() {
|
|
|
5159
5307
|
}
|
|
5160
5308
|
function writeStore(teams) {
|
|
5161
5309
|
(0, import_node_fs13.mkdirSync)(appDataDir(), { recursive: true });
|
|
5162
|
-
const
|
|
5163
|
-
(0, import_node_fs13.writeFileSync)(
|
|
5310
|
+
const path2 = storePath();
|
|
5311
|
+
(0, import_node_fs13.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
|
|
5164
5312
|
`, {
|
|
5165
5313
|
mode: 384
|
|
5166
5314
|
});
|
|
@@ -5334,6 +5482,58 @@ var init_connected_teams = __esm({
|
|
|
5334
5482
|
}
|
|
5335
5483
|
});
|
|
5336
5484
|
|
|
5485
|
+
// src/agents/usage.ts
|
|
5486
|
+
function sumOptional(a, b) {
|
|
5487
|
+
if (a == null && b == null) return void 0;
|
|
5488
|
+
return (a ?? 0) + (b ?? 0);
|
|
5489
|
+
}
|
|
5490
|
+
function fromInclusiveInputUsage(opts) {
|
|
5491
|
+
const totalInput = Number(opts.inputTokens) || 0;
|
|
5492
|
+
const outputTokens = Number(opts.outputTokens) || 0;
|
|
5493
|
+
const cached = Number(opts.cachedInputTokens) || 0;
|
|
5494
|
+
if (!totalInput && !outputTokens) return null;
|
|
5495
|
+
const cacheReadTokens = cached > 0 ? Math.min(cached, totalInput) : 0;
|
|
5496
|
+
return {
|
|
5497
|
+
inputTokens: Math.max(0, totalInput - cacheReadTokens),
|
|
5498
|
+
outputTokens,
|
|
5499
|
+
cacheReadTokens: cacheReadTokens || void 0
|
|
5500
|
+
};
|
|
5501
|
+
}
|
|
5502
|
+
function requestOccupancy(u) {
|
|
5503
|
+
return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
|
|
5504
|
+
}
|
|
5505
|
+
function mergeUsage(a, b) {
|
|
5506
|
+
return {
|
|
5507
|
+
inputTokens: (a?.inputTokens ?? 0) + b.inputTokens,
|
|
5508
|
+
outputTokens: (a?.outputTokens ?? 0) + b.outputTokens,
|
|
5509
|
+
cacheReadTokens: sumOptional(a?.cacheReadTokens, b.cacheReadTokens),
|
|
5510
|
+
cacheWriteTokens: sumOptional(a?.cacheWriteTokens, b.cacheWriteTokens),
|
|
5511
|
+
lastRequestTokens: b.lastRequestTokens ?? a?.lastRequestTokens
|
|
5512
|
+
};
|
|
5513
|
+
}
|
|
5514
|
+
function applyTurnUsage(current, incoming, scope = "request") {
|
|
5515
|
+
if (scope === "turn") {
|
|
5516
|
+
return {
|
|
5517
|
+
...incoming,
|
|
5518
|
+
lastRequestTokens: current?.lastRequestTokens ?? requestOccupancy(incoming)
|
|
5519
|
+
};
|
|
5520
|
+
}
|
|
5521
|
+
const merged = mergeUsage(current, incoming);
|
|
5522
|
+
return { ...merged, lastRequestTokens: requestOccupancy(incoming) };
|
|
5523
|
+
}
|
|
5524
|
+
function totalTokens(u) {
|
|
5525
|
+
return u.inputTokens + u.outputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
|
|
5526
|
+
}
|
|
5527
|
+
function contextTokens(u) {
|
|
5528
|
+
if (u.lastRequestTokens != null && u.lastRequestTokens > 0) return u.lastRequestTokens;
|
|
5529
|
+
return requestOccupancy(u);
|
|
5530
|
+
}
|
|
5531
|
+
var init_usage = __esm({
|
|
5532
|
+
"src/agents/usage.ts"() {
|
|
5533
|
+
"use strict";
|
|
5534
|
+
}
|
|
5535
|
+
});
|
|
5536
|
+
|
|
5337
5537
|
// src/agents/brightsy-targets.ts
|
|
5338
5538
|
function encodeBrightsyTarget(type, id, accountId) {
|
|
5339
5539
|
if (accountId) return `team:${accountId}:${type}:${id}`;
|
|
@@ -5569,15 +5769,11 @@ var init_turn_input = __esm({
|
|
|
5569
5769
|
// src/agents/brightsy.ts
|
|
5570
5770
|
function usageFromBrightsy(usage) {
|
|
5571
5771
|
if (!usage) return null;
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
inputTokens,
|
|
5578
|
-
outputTokens,
|
|
5579
|
-
cacheReadTokens: cached || void 0
|
|
5580
|
-
};
|
|
5772
|
+
return fromInclusiveInputUsage({
|
|
5773
|
+
inputTokens: Number(usage.prompt_tokens ?? 0),
|
|
5774
|
+
outputTokens: Number(usage.completion_tokens ?? 0),
|
|
5775
|
+
cachedInputTokens: Number(usage.prompt_tokens_details?.cached_tokens ?? 0)
|
|
5776
|
+
});
|
|
5581
5777
|
}
|
|
5582
5778
|
function parseBrightsyCliLine(line) {
|
|
5583
5779
|
const trimmed = line.trim();
|
|
@@ -5793,6 +5989,7 @@ var init_brightsy = __esm({
|
|
|
5793
5989
|
init_connected_teams();
|
|
5794
5990
|
init_config();
|
|
5795
5991
|
init_app_settings();
|
|
5992
|
+
init_usage();
|
|
5796
5993
|
init_brightsy_targets();
|
|
5797
5994
|
init_error_detail();
|
|
5798
5995
|
init_turn_input();
|
|
@@ -6686,23 +6883,20 @@ async function listCodexModels() {
|
|
|
6686
6883
|
}
|
|
6687
6884
|
function usageFromCodex(usage) {
|
|
6688
6885
|
if (!usage) return null;
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
outputTokens,
|
|
6695
|
-
cacheReadTokens: usage.cached_input_tokens ? Number(usage.cached_input_tokens) : void 0
|
|
6696
|
-
};
|
|
6886
|
+
return fromInclusiveInputUsage({
|
|
6887
|
+
inputTokens: Number(usage.input_tokens ?? 0),
|
|
6888
|
+
outputTokens: Number(usage.output_tokens ?? 0),
|
|
6889
|
+
cachedInputTokens: Number(usage.cached_input_tokens ?? 0)
|
|
6890
|
+
});
|
|
6697
6891
|
}
|
|
6698
6892
|
function codexConfigHasNetworkAccess() {
|
|
6699
6893
|
const candidates = [
|
|
6700
6894
|
(0, import_node_path15.join)((0, import_node_os7.homedir)(), ".codex", "config.toml"),
|
|
6701
6895
|
(0, import_node_path15.join)((0, import_node_os7.homedir)(), ".config", "codex", "config.toml")
|
|
6702
6896
|
];
|
|
6703
|
-
for (const
|
|
6704
|
-
if (!(0, import_node_fs17.existsSync)(
|
|
6705
|
-
const text3 = (0, import_node_fs17.readFileSync)(
|
|
6897
|
+
for (const path2 of candidates) {
|
|
6898
|
+
if (!(0, import_node_fs17.existsSync)(path2)) continue;
|
|
6899
|
+
const text3 = (0, import_node_fs17.readFileSync)(path2, "utf8");
|
|
6706
6900
|
if (/network_access\s*=\s*true/.test(text3)) return true;
|
|
6707
6901
|
}
|
|
6708
6902
|
return false;
|
|
@@ -6753,6 +6947,7 @@ var init_codex = __esm({
|
|
|
6753
6947
|
init_app_settings();
|
|
6754
6948
|
init_global_workspace();
|
|
6755
6949
|
init_error_detail();
|
|
6950
|
+
init_usage();
|
|
6756
6951
|
init_injected_mcp();
|
|
6757
6952
|
init_turn_input();
|
|
6758
6953
|
init_types();
|
|
@@ -8166,8 +8361,8 @@ function extractPresentedPlan(parts) {
|
|
|
8166
8361
|
const content = typeof input.content === "string" ? input.content : typeof input.plan === "string" ? input.plan : typeof input.markdown === "string" ? input.markdown : "";
|
|
8167
8362
|
if (!content.trim()) continue;
|
|
8168
8363
|
const title = typeof input.title === "string" && input.title.trim() ? input.title.trim() : "Plan";
|
|
8169
|
-
const
|
|
8170
|
-
return { title, content: content.trim(), path, source: "present_plan" };
|
|
8364
|
+
const path2 = typeof input.path === "string" && input.path.trim() ? input.path.trim() : PLAN_FILE_REL;
|
|
8365
|
+
return { title, content: content.trim(), path: path2, source: "present_plan" };
|
|
8171
8366
|
}
|
|
8172
8367
|
return null;
|
|
8173
8368
|
}
|
|
@@ -8356,6 +8551,7 @@ __export(index_exports, {
|
|
|
8356
8551
|
CONTEXT_MIN_MESSAGES: () => CONTEXT_MIN_MESSAGES,
|
|
8357
8552
|
COORDINATOR_TOOL_PLAYBOOK: () => COORDINATOR_TOOL_PLAYBOOK,
|
|
8358
8553
|
FAMOUS_SOCCER_TEAMS: () => FAMOUS_SOCCER_TEAMS,
|
|
8554
|
+
GITHUB_GIT_AUTH_MODES: () => GITHUB_GIT_AUTH_MODES,
|
|
8359
8555
|
GLOBAL_WORKSPACE_ID: () => GLOBAL_WORKSPACE_ID,
|
|
8360
8556
|
HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
|
|
8361
8557
|
LEGACY_ATTACHMENTS_DIR: () => LEGACY_ATTACHMENTS_DIR,
|
|
@@ -8405,10 +8601,12 @@ __export(index_exports, {
|
|
|
8405
8601
|
allocateTeamSlug: () => allocateTeamSlug,
|
|
8406
8602
|
appDataDir: () => appDataDir,
|
|
8407
8603
|
appSettingsPath: () => appSettingsPath,
|
|
8604
|
+
appendIndexedGitConfig: () => appendIndexedGitConfig,
|
|
8408
8605
|
appendMessage: () => appendMessage,
|
|
8409
8606
|
applyAgentEvent: () => applyAgentEvent,
|
|
8410
8607
|
applyAppEnvironment: () => applyAppEnvironment,
|
|
8411
8608
|
applyCompaction: () => applyCompaction,
|
|
8609
|
+
applyGithubGitAuthEnv: () => applyGithubGitAuthEnv,
|
|
8412
8610
|
applyThreadIntoMain: () => applyThreadIntoMain,
|
|
8413
8611
|
applyTurnUsage: () => applyTurnUsage,
|
|
8414
8612
|
assertOrchestratorCapableAgent: () => assertOrchestratorCapableAgent,
|
|
@@ -8523,6 +8721,7 @@ __export(index_exports, {
|
|
|
8523
8721
|
formatBrightsyFetchError: () => formatBrightsyFetchError,
|
|
8524
8722
|
formatFetchError: () => formatFetchError,
|
|
8525
8723
|
formatGhLandError: () => formatGhLandError,
|
|
8724
|
+
formatGitAuthModeDirective: () => formatGitAuthModeDirective,
|
|
8526
8725
|
formatIpcInvokeError: () => formatIpcInvokeError,
|
|
8527
8726
|
formatMessagesAsTranscript: () => formatMessagesAsTranscript,
|
|
8528
8727
|
formatPlanQuestionAnswers: () => formatPlanQuestionAnswers,
|
|
@@ -8537,6 +8736,7 @@ __export(index_exports, {
|
|
|
8537
8736
|
formatWorkspaceInventory: () => formatWorkspaceInventory,
|
|
8538
8737
|
formatWorktreeDirective: () => formatWorktreeDirective,
|
|
8539
8738
|
formatWorktreeReminder: () => formatWorktreeReminder,
|
|
8739
|
+
fromInclusiveInputUsage: () => fromInclusiveInputUsage,
|
|
8540
8740
|
getAdapter: () => getAdapter,
|
|
8541
8741
|
getAgentSetupInfo: () => getAgentSetupInfo,
|
|
8542
8742
|
getBrightsySession: () => getBrightsySession,
|
|
@@ -8549,6 +8749,8 @@ __export(index_exports, {
|
|
|
8549
8749
|
getDiff: () => getDiff,
|
|
8550
8750
|
getDiffSummary: () => getDiffSummary,
|
|
8551
8751
|
getGitHubStatus: () => getGitHubStatus,
|
|
8752
|
+
getGithubGitAuthMode: () => getGithubGitAuthMode,
|
|
8753
|
+
getGithubPat: () => getGithubPat,
|
|
8552
8754
|
getIssueSource: () => getIssueSource,
|
|
8553
8755
|
getLinearApiKey: () => getLinearApiKey,
|
|
8554
8756
|
getLinearAuthToken: () => getLinearAuthToken,
|
|
@@ -8567,6 +8769,7 @@ __export(index_exports, {
|
|
|
8567
8769
|
ghHeadRef: () => ghHeadRef,
|
|
8568
8770
|
ghRepoSelectArgs: () => ghRepoSelectArgs,
|
|
8569
8771
|
git: () => git,
|
|
8772
|
+
githubAgentGitEnv: () => githubAgentGitEnv,
|
|
8570
8773
|
globalAgentCwd: () => globalAgentCwd,
|
|
8571
8774
|
handleSlackInbound: () => handleSlackInbound,
|
|
8572
8775
|
harnessEnvKey: () => harnessEnvKey,
|
|
@@ -8789,6 +8992,7 @@ __export(index_exports, {
|
|
|
8789
8992
|
startSlackOAuth: () => startSlackOAuth,
|
|
8790
8993
|
startSlackRelayServer: () => startSlackRelayServer,
|
|
8791
8994
|
stripBrightsyNdjsonNoise: () => stripBrightsyNdjsonNoise,
|
|
8995
|
+
stripNestedElectronEnv: () => stripNestedElectronEnv,
|
|
8792
8996
|
submitPrStack: () => submitPrStack,
|
|
8793
8997
|
suggestSlug: () => suggestSlug,
|
|
8794
8998
|
summarizeConversation: () => summarizeConversation,
|
|
@@ -8847,6 +9051,7 @@ init_workspaces();
|
|
|
8847
9051
|
init_global_workspace();
|
|
8848
9052
|
init_run();
|
|
8849
9053
|
init_gh_errors();
|
|
9054
|
+
init_git_auth_mode();
|
|
8850
9055
|
init_worktree();
|
|
8851
9056
|
init_stack();
|
|
8852
9057
|
|
|
@@ -9613,8 +9818,8 @@ function toolDetail(name, input) {
|
|
|
9613
9818
|
if (!input) return void 0;
|
|
9614
9819
|
const command = str2(input.command) ?? str2(input.cmd);
|
|
9615
9820
|
if (command) return command;
|
|
9616
|
-
const
|
|
9617
|
-
if (
|
|
9821
|
+
const path2 = str2(input.file_path) ?? str2(input.path) ?? str2(input.filePath) ?? str2(input.filename);
|
|
9822
|
+
if (path2) return path2;
|
|
9618
9823
|
const pattern = str2(input.pattern) ?? str2(input.glob) ?? str2(input.glob_pattern);
|
|
9619
9824
|
if (pattern) return pattern;
|
|
9620
9825
|
const query = str2(input.query) ?? str2(input.prompt);
|
|
@@ -9658,12 +9863,12 @@ function toolDescription(name, input) {
|
|
|
9658
9863
|
return "Run shell command";
|
|
9659
9864
|
}
|
|
9660
9865
|
if (/edit|write|apply/i.test(name)) {
|
|
9661
|
-
const
|
|
9662
|
-
return
|
|
9866
|
+
const path2 = str2(input.file_path) ?? str2(input.path);
|
|
9867
|
+
return path2 ? `Edit ${path2.split("/").pop()}` : "Edit file";
|
|
9663
9868
|
}
|
|
9664
9869
|
if (/read/i.test(name)) {
|
|
9665
|
-
const
|
|
9666
|
-
return
|
|
9870
|
+
const path2 = str2(input.file_path) ?? str2(input.path);
|
|
9871
|
+
return path2 ? `Read ${path2.split("/").pop()}` : "Read file";
|
|
9667
9872
|
}
|
|
9668
9873
|
if (/grep/i.test(name)) return "Search files";
|
|
9669
9874
|
if (/glob/i.test(name)) return "Find files";
|
|
@@ -9829,43 +10034,7 @@ function normalizeParseResult(parsed) {
|
|
|
9829
10034
|
|
|
9830
10035
|
// src/agents/spawn.ts
|
|
9831
10036
|
init_path();
|
|
9832
|
-
|
|
9833
|
-
// src/agents/usage.ts
|
|
9834
|
-
function sumOptional(a, b) {
|
|
9835
|
-
if (a == null && b == null) return void 0;
|
|
9836
|
-
return (a ?? 0) + (b ?? 0);
|
|
9837
|
-
}
|
|
9838
|
-
function requestOccupancy(u) {
|
|
9839
|
-
return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
|
|
9840
|
-
}
|
|
9841
|
-
function mergeUsage(a, b) {
|
|
9842
|
-
return {
|
|
9843
|
-
inputTokens: (a?.inputTokens ?? 0) + b.inputTokens,
|
|
9844
|
-
outputTokens: (a?.outputTokens ?? 0) + b.outputTokens,
|
|
9845
|
-
cacheReadTokens: sumOptional(a?.cacheReadTokens, b.cacheReadTokens),
|
|
9846
|
-
cacheWriteTokens: sumOptional(a?.cacheWriteTokens, b.cacheWriteTokens),
|
|
9847
|
-
lastRequestTokens: b.lastRequestTokens ?? a?.lastRequestTokens
|
|
9848
|
-
};
|
|
9849
|
-
}
|
|
9850
|
-
function applyTurnUsage(current, incoming, scope = "request") {
|
|
9851
|
-
if (scope === "turn") {
|
|
9852
|
-
return {
|
|
9853
|
-
...incoming,
|
|
9854
|
-
lastRequestTokens: current?.lastRequestTokens ?? requestOccupancy(incoming)
|
|
9855
|
-
};
|
|
9856
|
-
}
|
|
9857
|
-
const merged = mergeUsage(current, incoming);
|
|
9858
|
-
return { ...merged, lastRequestTokens: requestOccupancy(incoming) };
|
|
9859
|
-
}
|
|
9860
|
-
function totalTokens(u) {
|
|
9861
|
-
return u.inputTokens + u.outputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
|
|
9862
|
-
}
|
|
9863
|
-
function contextTokens(u) {
|
|
9864
|
-
if (u.lastRequestTokens != null && u.lastRequestTokens > 0) return u.lastRequestTokens;
|
|
9865
|
-
return requestOccupancy(u);
|
|
9866
|
-
}
|
|
9867
|
-
|
|
9868
|
-
// src/agents/spawn.ts
|
|
10037
|
+
init_usage();
|
|
9869
10038
|
async function spawnAgentTurn(thread, input, onEvent) {
|
|
9870
10039
|
ensureAgentPath();
|
|
9871
10040
|
if (!thread.worktreePath?.trim()) {
|
|
@@ -9892,8 +10061,13 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
9892
10061
|
}
|
|
9893
10062
|
const env = childEnvWithAppSettings(cmd.env);
|
|
9894
10063
|
if (!isOrchestratorThread(thread)) {
|
|
9895
|
-
|
|
9896
|
-
|
|
10064
|
+
try {
|
|
10065
|
+
const originEnv = await originGhRepoEnv(thread.worktreePath, { env });
|
|
10066
|
+
Object.assign(env, originEnv);
|
|
10067
|
+
} catch (err) {
|
|
10068
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
10069
|
+
console.warn(`[sideboard] originGhRepoEnv failed (${thread.worktreePath}): ${detail}`);
|
|
10070
|
+
}
|
|
9897
10071
|
}
|
|
9898
10072
|
const child = (0, import_execa2.execa)(cmd.file, cmd.args, {
|
|
9899
10073
|
cwd: cmd.cwd,
|
|
@@ -9978,11 +10152,13 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
9978
10152
|
}
|
|
9979
10153
|
|
|
9980
10154
|
// src/index.ts
|
|
10155
|
+
init_usage();
|
|
9981
10156
|
init_claude_mcp();
|
|
9982
10157
|
|
|
9983
10158
|
// src/agents/instructions.ts
|
|
9984
10159
|
var import_node_fs20 = require("fs");
|
|
9985
10160
|
var import_node_path17 = require("path");
|
|
10161
|
+
init_git_auth_mode();
|
|
9986
10162
|
init_worktree_labels();
|
|
9987
10163
|
function normPath2(p) {
|
|
9988
10164
|
return p.replace(/\/+$/, "");
|
|
@@ -10032,6 +10208,8 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
10032
10208
|
lines.push(
|
|
10033
10209
|
"- Push with `git push -u origin HEAD` (or the current branch name). Do not `git push upstream`."
|
|
10034
10210
|
);
|
|
10211
|
+
lines.push("");
|
|
10212
|
+
lines.push(formatGitAuthModeDirective(opts?.gitAuthMode ?? "auto"));
|
|
10035
10213
|
lines.push(
|
|
10036
10214
|
"- Derive the PR title and body from what the changes actually do and why \u2014 inspect the diff/commits and the user request. Do not use the soccer-team worktree nickname or placeholder branch as the PR title."
|
|
10037
10215
|
);
|
|
@@ -10039,7 +10217,7 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
10039
10217
|
"- Prefer a concise imperative title (Conventional Commits style when it fits: feat:/fix:/chore:/docs:). Body should summarize intent, key changes, and test notes."
|
|
10040
10218
|
);
|
|
10041
10219
|
lines.push(
|
|
10042
|
-
"- Commit with messages that state the purpose of the change (same standard as the PR). Stay on this thread branch. Never push directly to main/master or merge locally into the main checkout.
|
|
10220
|
+
"- Commit with messages that state the purpose of the change (same standard as the PR). Stay on this thread branch. Never push directly to main/master or merge locally into the main checkout. Do not merge the PR unless this turn is a Merge PR request or the user explicitly asked. When merging, use GitHub from this worktree (`gh pr merge` / `gh stack merge`)."
|
|
10043
10221
|
);
|
|
10044
10222
|
if (thread.prUrl) {
|
|
10045
10223
|
lines.push(
|
|
@@ -10077,7 +10255,7 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
10077
10255
|
'- "Address review comments." \u2192 read PR review feedback, make the requested changes, commit, and push.'
|
|
10078
10256
|
);
|
|
10079
10257
|
lines.push(
|
|
10080
|
-
'- "Merge PR." \u2192 merge this thread\'s open pull request on GitHub. If `gh stack view` shows a stack, use `gh stack merge`; otherwise `gh pr merge` (respect repo defaults / squash vs merge). Do not force-push main/master or merge locally into the main checkout.'
|
|
10258
|
+
'- "Merge PR." \u2192 merge this thread\'s open pull request on GitHub (this phrase is the explicit ask). If `gh stack view` shows a stack, use `gh stack merge`; otherwise `gh pr merge` (respect repo defaults / squash vs merge). Do not force-push main/master or merge locally into the main checkout.'
|
|
10081
10259
|
);
|
|
10082
10260
|
return lines.join("\n");
|
|
10083
10261
|
}
|
|
@@ -10120,10 +10298,11 @@ var FILES_BY_AGENT = {
|
|
|
10120
10298
|
var MAX_CHARS_PER_FILE = 48e3;
|
|
10121
10299
|
function loadAgentInstructions(worktreePath, agent) {
|
|
10122
10300
|
const candidates = FILES_BY_AGENT[agent] ?? FILES_BY_AGENT.claude;
|
|
10123
|
-
const
|
|
10301
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
10302
|
+
const seenBodies = /* @__PURE__ */ new Set();
|
|
10124
10303
|
const out = [];
|
|
10125
10304
|
for (const rel of candidates) {
|
|
10126
|
-
if (
|
|
10305
|
+
if (seenPaths.has(rel)) continue;
|
|
10127
10306
|
const abs = (0, import_node_path17.join)(worktreePath, rel);
|
|
10128
10307
|
if (!(0, import_node_fs20.existsSync)(abs)) continue;
|
|
10129
10308
|
try {
|
|
@@ -10135,7 +10314,10 @@ function loadAgentInstructions(worktreePath, agent) {
|
|
|
10135
10314
|
|
|
10136
10315
|
\u2026(truncated)`;
|
|
10137
10316
|
}
|
|
10138
|
-
|
|
10317
|
+
const body = content.trim().replace(/\r\n/g, "\n");
|
|
10318
|
+
if (seenBodies.has(body)) continue;
|
|
10319
|
+
seenPaths.add(rel);
|
|
10320
|
+
seenBodies.add(body);
|
|
10139
10321
|
out.push({ relativePath: rel, content });
|
|
10140
10322
|
} catch {
|
|
10141
10323
|
}
|
|
@@ -10219,9 +10401,9 @@ function matchSimpleGlob(pattern, name) {
|
|
|
10219
10401
|
return new RegExp(`^${escaped}$`).test(name);
|
|
10220
10402
|
}
|
|
10221
10403
|
function readWorktreeInclude(repoPath) {
|
|
10222
|
-
const
|
|
10223
|
-
if (!(0, import_node_fs21.existsSync)(
|
|
10224
|
-
return (0, import_node_fs21.readFileSync)(
|
|
10404
|
+
const path2 = (0, import_node_path18.join)(repoPath, ".worktreeinclude");
|
|
10405
|
+
if (!(0, import_node_fs21.existsSync)(path2)) return [];
|
|
10406
|
+
return (0, import_node_fs21.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
10225
10407
|
}
|
|
10226
10408
|
function resolveFilesToCopy(repoPath) {
|
|
10227
10409
|
const fromInclude = readWorktreeInclude(repoPath);
|
|
@@ -10296,8 +10478,20 @@ async function captureLoginEnv() {
|
|
|
10296
10478
|
cachedLoginEnv = { ...process.env };
|
|
10297
10479
|
return { ...cachedLoginEnv };
|
|
10298
10480
|
}
|
|
10481
|
+
var NESTED_ELECTRON_ENV_PREFIXES = ["ELECTRON_", "CHROME_"];
|
|
10482
|
+
function stripNestedElectronEnv(env) {
|
|
10483
|
+
const out = { ...env };
|
|
10484
|
+
for (const key of Object.keys(out)) {
|
|
10485
|
+
if (NESTED_ELECTRON_ENV_PREFIXES.some((prefix) => key.startsWith(prefix))) {
|
|
10486
|
+
delete out[key];
|
|
10487
|
+
}
|
|
10488
|
+
}
|
|
10489
|
+
return out;
|
|
10490
|
+
}
|
|
10299
10491
|
function buildWorkspaceScriptEnv(opts, baseEnv) {
|
|
10300
|
-
const env = {
|
|
10492
|
+
const env = stripNestedElectronEnv({
|
|
10493
|
+
...baseEnv ?? process.env
|
|
10494
|
+
});
|
|
10301
10495
|
const name = opts.workspaceName ?? (0, import_node_path18.basename)(opts.worktreePath);
|
|
10302
10496
|
const ports = opts.ports ?? [];
|
|
10303
10497
|
const primary = ports[0];
|
|
@@ -10522,10 +10716,10 @@ var import_node_path19 = require("path");
|
|
|
10522
10716
|
var import_execa4 = require("execa");
|
|
10523
10717
|
var import_node_readline3 = require("readline");
|
|
10524
10718
|
function loadCursorWorktreesJson(rootPath) {
|
|
10525
|
-
const
|
|
10526
|
-
if (!(0, import_node_fs22.existsSync)(
|
|
10719
|
+
const path2 = (0, import_node_path19.join)(rootPath, ".cursor", "worktrees.json");
|
|
10720
|
+
if (!(0, import_node_fs22.existsSync)(path2)) return null;
|
|
10527
10721
|
try {
|
|
10528
|
-
return JSON.parse((0, import_node_fs22.readFileSync)(
|
|
10722
|
+
return JSON.parse((0, import_node_fs22.readFileSync)(path2, "utf8"));
|
|
10529
10723
|
} catch {
|
|
10530
10724
|
return null;
|
|
10531
10725
|
}
|
|
@@ -10628,9 +10822,9 @@ function parseNameStatus(stdout) {
|
|
|
10628
10822
|
const out = [];
|
|
10629
10823
|
for (const line of stdout.split("\n").filter(Boolean)) {
|
|
10630
10824
|
const [status, ...pathParts] = line.split(" ");
|
|
10631
|
-
const
|
|
10632
|
-
if (!status || !
|
|
10633
|
-
out.push({ status: status[0] ?? status, path });
|
|
10825
|
+
const path2 = pathParts[pathParts.length - 1];
|
|
10826
|
+
if (!status || !path2) continue;
|
|
10827
|
+
out.push({ status: status[0] ?? status, path: path2 });
|
|
10634
10828
|
}
|
|
10635
10829
|
return out;
|
|
10636
10830
|
}
|
|
@@ -10638,12 +10832,12 @@ function parseNumstat(stdout) {
|
|
|
10638
10832
|
const map = /* @__PURE__ */ new Map();
|
|
10639
10833
|
for (const line of stdout.split("\n").filter(Boolean)) {
|
|
10640
10834
|
const [addRaw, delRaw, ...pathParts] = line.split(" ");
|
|
10641
|
-
const
|
|
10642
|
-
if (!
|
|
10835
|
+
const path2 = pathParts[pathParts.length - 1];
|
|
10836
|
+
if (!path2) continue;
|
|
10643
10837
|
const additions = addRaw === "-" ? 0 : Number(addRaw);
|
|
10644
10838
|
const deletions = delRaw === "-" ? 0 : Number(delRaw);
|
|
10645
10839
|
if (!Number.isFinite(additions) && !Number.isFinite(deletions)) continue;
|
|
10646
|
-
map.set(
|
|
10840
|
+
map.set(path2, {
|
|
10647
10841
|
additions: Number.isFinite(additions) ? additions : 0,
|
|
10648
10842
|
deletions: Number.isFinite(deletions) ? deletions : 0
|
|
10649
10843
|
});
|
|
@@ -10720,70 +10914,70 @@ function splitCombinedDiff(stdout) {
|
|
|
10720
10914
|
}
|
|
10721
10915
|
return map;
|
|
10722
10916
|
}
|
|
10723
|
-
function syntheticAddPatch(
|
|
10917
|
+
function syntheticAddPatch(path2, content, maxHunk) {
|
|
10724
10918
|
const lines = content.split("\n");
|
|
10725
10919
|
const body = lines.map((l) => `+${l}`).join("\n");
|
|
10726
|
-
const header = `diff --git a/${
|
|
10920
|
+
const header = `diff --git a/${path2} b/${path2}
|
|
10727
10921
|
new file mode 100644
|
|
10728
10922
|
--- /dev/null
|
|
10729
|
-
+++ b/${
|
|
10923
|
+
+++ b/${path2}
|
|
10730
10924
|
@@ -0,0 +1,${lines.length} @@
|
|
10731
10925
|
`;
|
|
10732
10926
|
return {
|
|
10733
|
-
path,
|
|
10927
|
+
path: path2,
|
|
10734
10928
|
status: "A",
|
|
10735
10929
|
patch: capPatch(`${header}${body}`, maxHunk),
|
|
10736
10930
|
additions: lines.length,
|
|
10737
10931
|
deletions: 0
|
|
10738
10932
|
};
|
|
10739
10933
|
}
|
|
10740
|
-
async function untrackedPatch(worktreePath,
|
|
10741
|
-
const abs = (0, import_node_path20.join)(worktreePath,
|
|
10934
|
+
async function untrackedPatch(worktreePath, path2, maxHunk) {
|
|
10935
|
+
const abs = (0, import_node_path20.join)(worktreePath, path2);
|
|
10742
10936
|
try {
|
|
10743
10937
|
const st = (0, import_node_fs23.statSync)(abs);
|
|
10744
10938
|
if (st.isFile() && st.size > maxHunk) {
|
|
10745
10939
|
const buf = (0, import_node_fs23.readFileSync)(abs).subarray(0, maxHunk);
|
|
10746
|
-
return syntheticAddPatch(
|
|
10940
|
+
return syntheticAddPatch(path2, buf.toString("utf8"), maxHunk);
|
|
10747
10941
|
}
|
|
10748
10942
|
} catch {
|
|
10749
10943
|
}
|
|
10750
10944
|
const { stdout: patch } = await git(
|
|
10751
|
-
["diff", "--no-ext-diff", "--no-color", "--no-index", "--", "/dev/null",
|
|
10945
|
+
["diff", "--no-ext-diff", "--no-color", "--no-index", "--", "/dev/null", path2],
|
|
10752
10946
|
worktreePath,
|
|
10753
10947
|
{ reject: false, timeoutMs: 4e3 }
|
|
10754
10948
|
);
|
|
10755
|
-
const normalized = patch.replace(/^diff --git a\/.+? b\/.+?$/m, `diff --git a/${
|
|
10949
|
+
const normalized = patch.replace(/^diff --git a\/.+? b\/.+?$/m, `diff --git a/${path2} b/${path2}`).replace(/^--- .*$/m, "--- /dev/null").replace(/^\+\+\+ .*$/m, `+++ b/${path2}`);
|
|
10756
10950
|
const addLines = normalized.split("\n").filter((l) => l.startsWith("+") && !l.startsWith("+++")).length;
|
|
10757
10951
|
return {
|
|
10758
|
-
path,
|
|
10952
|
+
path: path2,
|
|
10759
10953
|
status: "A",
|
|
10760
10954
|
patch: capPatch(normalized, maxHunk),
|
|
10761
10955
|
additions: addLines,
|
|
10762
10956
|
deletions: 0
|
|
10763
10957
|
};
|
|
10764
10958
|
}
|
|
10765
|
-
async function listUntrackedPaths(worktreePath,
|
|
10959
|
+
async function listUntrackedPaths(worktreePath, path2) {
|
|
10766
10960
|
const args = ["ls-files", "-z", "--others", "--exclude-standard"];
|
|
10767
|
-
if (
|
|
10961
|
+
if (path2) args.push("--", path2);
|
|
10768
10962
|
const { stdout } = await git(args, worktreePath, { reject: false });
|
|
10769
10963
|
return stdout.split("\0").filter(Boolean).filter((p) => !isSideboardScratchPath(p));
|
|
10770
10964
|
}
|
|
10771
10965
|
async function listUntrackedFiles(worktreePath, maxHunk, paths) {
|
|
10772
10966
|
const list = paths ?? await listUntrackedPaths(worktreePath);
|
|
10773
10967
|
if (list.length === 0) return [];
|
|
10774
|
-
return Promise.all(list.map((
|
|
10968
|
+
return Promise.all(list.map((path2) => untrackedPatch(worktreePath, path2, maxHunk)));
|
|
10775
10969
|
}
|
|
10776
10970
|
function untrackedStubs(paths) {
|
|
10777
|
-
return paths.map((
|
|
10778
|
-
path,
|
|
10971
|
+
return paths.map((path2) => ({
|
|
10972
|
+
path: path2,
|
|
10779
10973
|
status: "A",
|
|
10780
10974
|
patch: "",
|
|
10781
10975
|
additions: 0,
|
|
10782
10976
|
deletions: 0
|
|
10783
10977
|
}));
|
|
10784
10978
|
}
|
|
10785
|
-
function pathspec(
|
|
10786
|
-
return
|
|
10979
|
+
function pathspec(path2) {
|
|
10980
|
+
return path2 ? ["--", path2] : [];
|
|
10787
10981
|
}
|
|
10788
10982
|
function gitDiff(args, cwd, opts) {
|
|
10789
10983
|
return git(["diff", "--no-ext-diff", "--no-color", ...args], cwd, {
|
|
@@ -10791,7 +10985,7 @@ function gitDiff(args, cwd, opts) {
|
|
|
10791
10985
|
timeoutMs: opts?.timeoutMs
|
|
10792
10986
|
});
|
|
10793
10987
|
}
|
|
10794
|
-
function fileFromPatch(
|
|
10988
|
+
function fileFromPatch(path2, patch, maxHunk) {
|
|
10795
10989
|
let status = "M";
|
|
10796
10990
|
if (/^new file mode /m.test(patch) || /^--- \/dev\/null/m.test(patch)) {
|
|
10797
10991
|
status = "A";
|
|
@@ -10803,15 +10997,15 @@ function fileFromPatch(path, patch, maxHunk) {
|
|
|
10803
10997
|
const additions = patch.split("\n").filter((l) => l.startsWith("+") && !l.startsWith("+++")).length;
|
|
10804
10998
|
const deletions = patch.split("\n").filter((l) => l.startsWith("-") && !l.startsWith("---")).length;
|
|
10805
10999
|
return {
|
|
10806
|
-
path,
|
|
11000
|
+
path: path2,
|
|
10807
11001
|
status,
|
|
10808
11002
|
patch: capPatch(patch, maxHunk),
|
|
10809
11003
|
additions,
|
|
10810
11004
|
deletions
|
|
10811
11005
|
};
|
|
10812
11006
|
}
|
|
10813
|
-
async function gitDiffParts(worktreePath, diffArgs, includePatches,
|
|
10814
|
-
const extra = pathspec(
|
|
11007
|
+
async function gitDiffParts(worktreePath, diffArgs, includePatches, path2) {
|
|
11008
|
+
const extra = pathspec(path2);
|
|
10815
11009
|
if (includePatches) {
|
|
10816
11010
|
const diff = await gitDiff([...diffArgs, ...extra], worktreePath, {
|
|
10817
11011
|
timeoutMs: 4e3
|
|
@@ -10849,17 +11043,17 @@ function filesFromDiff(nameStatus, numstat, combinedDiff, maxHunk) {
|
|
|
10849
11043
|
const patches = splitCombinedDiff(combinedDiff);
|
|
10850
11044
|
if (!nameStatus.trim() && patches.size > 0) {
|
|
10851
11045
|
return [...patches.entries()].map(
|
|
10852
|
-
([
|
|
11046
|
+
([path2, patch]) => fileFromPatch(path2, patch, maxHunk)
|
|
10853
11047
|
);
|
|
10854
11048
|
}
|
|
10855
11049
|
const counts = parseNumstat(numstat);
|
|
10856
11050
|
const files = [];
|
|
10857
|
-
for (const { status, path } of parseNameStatus(nameStatus)) {
|
|
10858
|
-
const n = counts.get(
|
|
11051
|
+
for (const { status, path: path2 } of parseNameStatus(nameStatus)) {
|
|
11052
|
+
const n = counts.get(path2);
|
|
10859
11053
|
files.push({
|
|
10860
|
-
path,
|
|
11054
|
+
path: path2,
|
|
10861
11055
|
status,
|
|
10862
|
-
patch: capPatch(patches.get(
|
|
11056
|
+
patch: capPatch(patches.get(path2) ?? "", maxHunk),
|
|
10863
11057
|
additions: n?.additions,
|
|
10864
11058
|
deletions: n?.deletions
|
|
10865
11059
|
});
|
|
@@ -10943,7 +11137,7 @@ function emptyPathDiff(scope, base, hasLastTurnBase, commitSha = null) {
|
|
|
10943
11137
|
};
|
|
10944
11138
|
}
|
|
10945
11139
|
async function getPathDiff(worktreePath, repoPath, opts) {
|
|
10946
|
-
const { path, scope, commitSha, lastTurnBase, hasLastTurnBase, includePatches, maxHunk } = opts;
|
|
11140
|
+
const { path: path2, scope, commitSha, lastTurnBase, hasLastTurnBase, includePatches, maxHunk } = opts;
|
|
10947
11141
|
if (scope === "last_turn" && !lastTurnBase) {
|
|
10948
11142
|
return emptyPathDiff(scope, "last turn", false);
|
|
10949
11143
|
}
|
|
@@ -10982,7 +11176,7 @@ async function getPathDiff(worktreePath, repoPath, opts) {
|
|
|
10982
11176
|
labelBase = "HEAD";
|
|
10983
11177
|
}
|
|
10984
11178
|
const diff = await gitDiff(
|
|
10985
|
-
includePatches ? [...diffArgs, "--",
|
|
11179
|
+
includePatches ? [...diffArgs, "--", path2] : ["--name-status", ...diffArgs, "--", path2],
|
|
10986
11180
|
worktreePath,
|
|
10987
11181
|
{ timeoutMs: 4e3 }
|
|
10988
11182
|
);
|
|
@@ -10990,8 +11184,8 @@ async function getPathDiff(worktreePath, repoPath, opts) {
|
|
|
10990
11184
|
if (includePatches) {
|
|
10991
11185
|
const parsed = filesFromDiff("", "", diff.stdout, maxHunk);
|
|
10992
11186
|
for (const file of parsed) filesMap.set(file.path, file);
|
|
10993
|
-
if (diff.stdout.trim() && !filesMap.has(
|
|
10994
|
-
filesMap.set(
|
|
11187
|
+
if (diff.stdout.trim() && !filesMap.has(path2)) {
|
|
11188
|
+
filesMap.set(path2, fileFromPatch(path2, diff.stdout, maxHunk));
|
|
10995
11189
|
}
|
|
10996
11190
|
} else {
|
|
10997
11191
|
for (const file of filesFromDiff(diff.stdout, "", "", maxHunk)) {
|
|
@@ -10999,7 +11193,7 @@ async function getPathDiff(worktreePath, repoPath, opts) {
|
|
|
10999
11193
|
}
|
|
11000
11194
|
}
|
|
11001
11195
|
if (filesMap.size === 0) {
|
|
11002
|
-
const maybe = await listUntrackedPaths(worktreePath,
|
|
11196
|
+
const maybe = await listUntrackedPaths(worktreePath, path2);
|
|
11003
11197
|
if (maybe.length > 0) {
|
|
11004
11198
|
const extra = includePatches ? await listUntrackedFiles(worktreePath, maxHunk, maybe) : untrackedStubs(maybe);
|
|
11005
11199
|
for (const file of extra) filesMap.set(file.path, file);
|
|
@@ -12025,8 +12219,8 @@ function splitForCompaction(messages, thresholds = {}) {
|
|
|
12025
12219
|
function formatToolPart(t, detail) {
|
|
12026
12220
|
if (detail === "summary") {
|
|
12027
12221
|
const label = t.description || t.detail || t.name;
|
|
12028
|
-
const
|
|
12029
|
-
return `- ${t.name}: ${label}${
|
|
12222
|
+
const path2 = t.filePath ? ` (${t.filePath})` : "";
|
|
12223
|
+
return `- ${t.name}: ${label}${path2}`;
|
|
12030
12224
|
}
|
|
12031
12225
|
const lines = [`#### Tool: ${t.name}`, `Status: ${t.status}`];
|
|
12032
12226
|
if (t.description) lines.push(`Description: ${t.description}`);
|
|
@@ -13182,10 +13376,10 @@ function storePath2() {
|
|
|
13182
13376
|
return (0, import_node_path24.join)(appDataDir(), "slack-reply-to.json");
|
|
13183
13377
|
}
|
|
13184
13378
|
function readStore2() {
|
|
13185
|
-
const
|
|
13186
|
-
if (!(0, import_node_fs29.existsSync)(
|
|
13379
|
+
const path2 = storePath2();
|
|
13380
|
+
if (!(0, import_node_fs29.existsSync)(path2)) return {};
|
|
13187
13381
|
try {
|
|
13188
|
-
const parsed = isSecureFileEncrypted(
|
|
13382
|
+
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs29.readFileSync)(path2, "utf8"));
|
|
13189
13383
|
return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
|
|
13190
13384
|
} catch {
|
|
13191
13385
|
return {};
|
|
@@ -13210,12 +13404,12 @@ function storePath3() {
|
|
|
13210
13404
|
}
|
|
13211
13405
|
function readStore3() {
|
|
13212
13406
|
try {
|
|
13213
|
-
const
|
|
13214
|
-
const wasEncrypted = isSecureFileEncrypted(
|
|
13215
|
-
const parsed = readSecureJson(
|
|
13407
|
+
const path2 = storePath3();
|
|
13408
|
+
const wasEncrypted = isSecureFileEncrypted(path2);
|
|
13409
|
+
const parsed = readSecureJson(path2);
|
|
13216
13410
|
const workspaces = Array.isArray(parsed?.workspaces) ? parsed.workspaces : [];
|
|
13217
13411
|
if (workspaces.length > 0 && !wasEncrypted && resolveVaultKey()) {
|
|
13218
|
-
writeSecureJson(
|
|
13412
|
+
writeSecureJson(path2, { workspaces });
|
|
13219
13413
|
}
|
|
13220
13414
|
return workspaces;
|
|
13221
13415
|
} catch {
|
|
@@ -13351,10 +13545,10 @@ function tsNewer(a, b) {
|
|
|
13351
13545
|
return Number(a) > Number(b);
|
|
13352
13546
|
}
|
|
13353
13547
|
function readStore4() {
|
|
13354
|
-
const
|
|
13355
|
-
if (!(0, import_node_fs30.existsSync)(
|
|
13548
|
+
const path2 = storePath4();
|
|
13549
|
+
if (!(0, import_node_fs30.existsSync)(path2)) return [];
|
|
13356
13550
|
try {
|
|
13357
|
-
const parsed = isSecureFileEncrypted(
|
|
13551
|
+
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs30.readFileSync)(path2, "utf8"));
|
|
13358
13552
|
return Array.isArray(parsed?.watches) ? parsed.watches : [];
|
|
13359
13553
|
} catch {
|
|
13360
13554
|
return [];
|
|
@@ -13726,8 +13920,8 @@ init_worktree();
|
|
|
13726
13920
|
init_thread_store();
|
|
13727
13921
|
init_paths();
|
|
13728
13922
|
init_app_settings();
|
|
13729
|
-
function isSideboardWorktreePath(
|
|
13730
|
-
return
|
|
13923
|
+
function isSideboardWorktreePath(path2) {
|
|
13924
|
+
return path2.includes("/.sideboard/worktrees/") || path2.includes("/sideboard/workspaces/");
|
|
13731
13925
|
}
|
|
13732
13926
|
async function findOrphanWorktrees(repoPaths) {
|
|
13733
13927
|
const threads = listThreads({ includeArchived: true });
|
|
@@ -13752,18 +13946,18 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
13752
13946
|
try {
|
|
13753
13947
|
const wts = await listWorktrees(repoPath);
|
|
13754
13948
|
for (const wt of wts) {
|
|
13755
|
-
const
|
|
13756
|
-
if (!isSideboardWorktreePath(
|
|
13757
|
-
if (known.has(
|
|
13758
|
-
if (seen.has(
|
|
13759
|
-
seen.add(
|
|
13949
|
+
const path2 = wt.path.replace(/\/$/, "");
|
|
13950
|
+
if (!isSideboardWorktreePath(path2)) continue;
|
|
13951
|
+
if (known.has(path2)) continue;
|
|
13952
|
+
if (seen.has(path2)) continue;
|
|
13953
|
+
seen.add(path2);
|
|
13760
13954
|
let mtimeMs = 0;
|
|
13761
13955
|
try {
|
|
13762
|
-
mtimeMs = (0, import_node_fs31.statSync)(
|
|
13956
|
+
mtimeMs = (0, import_node_fs31.statSync)(path2).mtimeMs;
|
|
13763
13957
|
} catch {
|
|
13764
13958
|
mtimeMs = 0;
|
|
13765
13959
|
}
|
|
13766
|
-
orphans.push({ path, repoPath, mtimeMs });
|
|
13960
|
+
orphans.push({ path: path2, repoPath, mtimeMs });
|
|
13767
13961
|
}
|
|
13768
13962
|
} catch {
|
|
13769
13963
|
}
|
|
@@ -13772,17 +13966,17 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
13772
13966
|
if ((0, import_node_fs31.existsSync)(root)) {
|
|
13773
13967
|
for (const entry of (0, import_node_fs31.readdirSync)(root, { withFileTypes: true })) {
|
|
13774
13968
|
if (!entry.isDirectory()) continue;
|
|
13775
|
-
const
|
|
13776
|
-
if (known.has(
|
|
13777
|
-
if (!(0, import_node_fs31.existsSync)((0, import_node_path27.join)(
|
|
13778
|
-
seen.add(
|
|
13969
|
+
const path2 = (0, import_node_path27.join)(root, entry.name).replace(/\/$/, "");
|
|
13970
|
+
if (known.has(path2) || seen.has(path2)) continue;
|
|
13971
|
+
if (!(0, import_node_fs31.existsSync)((0, import_node_path27.join)(path2, ".git"))) continue;
|
|
13972
|
+
seen.add(path2);
|
|
13779
13973
|
let mtimeMs = 0;
|
|
13780
13974
|
try {
|
|
13781
|
-
mtimeMs = (0, import_node_fs31.statSync)(
|
|
13975
|
+
mtimeMs = (0, import_node_fs31.statSync)(path2).mtimeMs;
|
|
13782
13976
|
} catch {
|
|
13783
13977
|
mtimeMs = Date.now();
|
|
13784
13978
|
}
|
|
13785
|
-
orphans.push({ path, repoPath, mtimeMs });
|
|
13979
|
+
orphans.push({ path: path2, repoPath, mtimeMs });
|
|
13786
13980
|
}
|
|
13787
13981
|
}
|
|
13788
13982
|
} catch {
|
|
@@ -14176,9 +14370,9 @@ function ensureReviewRequestFile(worktreePath) {
|
|
|
14176
14370
|
const localAbs = (0, import_node_path29.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
14177
14371
|
const localContent = readTextIfPresent(localAbs) ?? readTextIfPresent((0, import_node_path29.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
|
|
14178
14372
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
14179
|
-
const
|
|
14373
|
+
const path2 = (0, import_node_fs33.existsSync)(localAbs) ? REVIEW_REQUEST_PATH : LEGACY_REVIEW_REQUEST_PATH;
|
|
14180
14374
|
return {
|
|
14181
|
-
path,
|
|
14375
|
+
path: path2,
|
|
14182
14376
|
name: REVIEW_REQUEST_NAME,
|
|
14183
14377
|
content: localContent,
|
|
14184
14378
|
source: "local"
|
|
@@ -14194,13 +14388,13 @@ function ensureReviewRequestFile(worktreePath) {
|
|
|
14194
14388
|
};
|
|
14195
14389
|
}
|
|
14196
14390
|
function buildReviewRequestAttachment(content, opts) {
|
|
14197
|
-
const
|
|
14198
|
-
const name = opts?.name ?? (
|
|
14391
|
+
const path2 = opts?.path ?? REVIEW_REQUEST_PATH;
|
|
14392
|
+
const name = opts?.name ?? (path2 === REPO_REVIEW_PATH ? REPO_REVIEW_NAME : REVIEW_REQUEST_NAME);
|
|
14199
14393
|
return {
|
|
14200
14394
|
id: (0, import_node_crypto8.randomUUID)(),
|
|
14201
14395
|
name,
|
|
14202
14396
|
kind: "file",
|
|
14203
|
-
path,
|
|
14397
|
+
path: path2,
|
|
14204
14398
|
content
|
|
14205
14399
|
};
|
|
14206
14400
|
}
|
|
@@ -14920,14 +15114,16 @@ var Orchestrator = class {
|
|
|
14920
15114
|
}
|
|
14921
15115
|
const isBrightsy = fresh.agent === "brightsy";
|
|
14922
15116
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
15117
|
+
const { autoRenameBranchEnabled: autoRenameBranchEnabled2, getGithubGitAuthMode: getGithubGitAuthMode2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
15118
|
+
const gitAuthMode = getGithubGitAuthMode2();
|
|
14923
15119
|
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
14924
15120
|
githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
|
|
14925
15121
|
() => null
|
|
14926
|
-
)
|
|
15122
|
+
),
|
|
15123
|
+
gitAuthMode
|
|
14927
15124
|
});
|
|
14928
15125
|
const artifactDirective = isBrightsy ? null : formatArtifactDirective();
|
|
14929
15126
|
const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
|
|
14930
|
-
const { autoRenameBranchEnabled: autoRenameBranchEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
14931
15127
|
const renameBranchDirective = !isBrightsy && !isOrchestration && autoRenameBranchEnabled2() ? formatRenameBranchDirective(fresh, {
|
|
14932
15128
|
customPrompt: settings?.prompts?.renameBranch
|
|
14933
15129
|
}) : null;
|
|
@@ -15764,8 +15960,9 @@ var Orchestrator = class {
|
|
|
15764
15960
|
return tab;
|
|
15765
15961
|
}
|
|
15766
15962
|
/**
|
|
15767
|
-
*
|
|
15768
|
-
*
|
|
15963
|
+
* Desktop git buttons + MCP `ask_git`.
|
|
15964
|
+
* When the worktree is clean, push / open the PR here (HTTPS via `gh` if SSH
|
|
15965
|
+
* is missing). When dirty, queue the worktree agent to commit first.
|
|
15769
15966
|
*/
|
|
15770
15967
|
async askGit(threadRef, action) {
|
|
15771
15968
|
if (!AGENT_GIT_ACTIONS.includes(action)) {
|
|
@@ -15783,6 +15980,10 @@ var Orchestrator = class {
|
|
|
15783
15980
|
"No pull request linked. Ask the worktree agent to open a draft PR first (ask_git create-draft)."
|
|
15784
15981
|
);
|
|
15785
15982
|
}
|
|
15983
|
+
if ((action === "commit-push" || action === "create-draft" || action === "create-web") && thread.worktreePath?.trim() && !await isDirty(thread.worktreePath)) {
|
|
15984
|
+
await this.pushAndMaybeOpenPr(thread, action);
|
|
15985
|
+
return this.requireThread(threadRef);
|
|
15986
|
+
}
|
|
15786
15987
|
let prBase;
|
|
15787
15988
|
if (action === "resolve-conflicts") {
|
|
15788
15989
|
try {
|
|
@@ -15793,6 +15994,34 @@ var Orchestrator = class {
|
|
|
15793
15994
|
}
|
|
15794
15995
|
return this.send(threadRef, agentGitPrompt(action, { prBase }));
|
|
15795
15996
|
}
|
|
15997
|
+
/** Push origin (gh HTTPS fallback) and create/update the PR when requested. */
|
|
15998
|
+
async pushAndMaybeOpenPr(thread, action) {
|
|
15999
|
+
const cwd = thread.worktreePath;
|
|
16000
|
+
const branch = await currentBranch(cwd);
|
|
16001
|
+
await pushBranch(cwd, branch);
|
|
16002
|
+
if (action === "commit-push") return;
|
|
16003
|
+
const base = await resolveDefaultBranch(thread.repoPath);
|
|
16004
|
+
const meta = await suggestPrMetadata(cwd, {
|
|
16005
|
+
base,
|
|
16006
|
+
fallbackTitle: thread.prTitle ?? thread.title
|
|
16007
|
+
});
|
|
16008
|
+
const url = await createOrUpdatePr(cwd, {
|
|
16009
|
+
title: meta.title,
|
|
16010
|
+
body: meta.body,
|
|
16011
|
+
base,
|
|
16012
|
+
head: branch,
|
|
16013
|
+
draft: action === "create-draft",
|
|
16014
|
+
web: action === "create-web"
|
|
16015
|
+
});
|
|
16016
|
+
if (!url) return;
|
|
16017
|
+
const patch = { prUrl: url, prTitle: meta.title };
|
|
16018
|
+
try {
|
|
16019
|
+
const fetched = await getPrMeta(cwd, url);
|
|
16020
|
+
if (fetched?.title) patch.prTitle = fetched.title;
|
|
16021
|
+
} catch {
|
|
16022
|
+
}
|
|
16023
|
+
updateThread(thread.id, patch);
|
|
16024
|
+
}
|
|
15796
16025
|
setThreadOptions(threadRef, patch) {
|
|
15797
16026
|
const thread = this.requireThread(threadRef);
|
|
15798
16027
|
const next = {};
|
|
@@ -16373,9 +16602,9 @@ function labelGithubUrl(url) {
|
|
|
16373
16602
|
return null;
|
|
16374
16603
|
}
|
|
16375
16604
|
if (!/(^|\.)github\.com$/i.test(parsed.hostname)) return null;
|
|
16376
|
-
const
|
|
16605
|
+
const path2 = parsed.pathname;
|
|
16377
16606
|
const hash = parsed.hash || "";
|
|
16378
|
-
const pr =
|
|
16607
|
+
const pr = path2.match(/\/([^/]+)\/([^/]+)\/pull\/(\d+)/i);
|
|
16379
16608
|
if (pr) {
|
|
16380
16609
|
const n = pr[3];
|
|
16381
16610
|
if (/#discussion_r\d+/i.test(hash) || /#pullrequestreview-\d+/i.test(hash)) {
|
|
@@ -16386,11 +16615,11 @@ function labelGithubUrl(url) {
|
|
|
16386
16615
|
}
|
|
16387
16616
|
return { kind: "pr", label: `PR #${n}`, url: raw };
|
|
16388
16617
|
}
|
|
16389
|
-
const issueComment =
|
|
16618
|
+
const issueComment = path2.match(/\/([^/]+)\/([^/]+)\/issues\/(\d+)/i);
|
|
16390
16619
|
if (issueComment && /#issuecomment-\d+/i.test(hash)) {
|
|
16391
16620
|
return { kind: "comment", label: `Issue #${issueComment[3]} comment`, url: raw };
|
|
16392
16621
|
}
|
|
16393
|
-
const blob =
|
|
16622
|
+
const blob = path2.match(/\/([^/]+)\/([^/]+)\/blob\/[^/]+\/(.+)$/i);
|
|
16394
16623
|
if (blob) {
|
|
16395
16624
|
const filePath = decodeURIComponent(blob[3]);
|
|
16396
16625
|
const fileName = filePath.split("/").pop() || filePath;
|
|
@@ -16952,10 +17181,10 @@ async function startMcpServer() {
|
|
|
16952
17181
|
const t = orch.getThread(thread_id.trim());
|
|
16953
17182
|
if (t?.worktreePath?.trim()) root = t.worktreePath;
|
|
16954
17183
|
}
|
|
16955
|
-
const
|
|
17184
|
+
const path2 = writePlanFile2(root, content);
|
|
16956
17185
|
const payload = {
|
|
16957
17186
|
ok: true,
|
|
16958
|
-
path,
|
|
17187
|
+
path: path2,
|
|
16959
17188
|
title: title?.trim() || "Plan",
|
|
16960
17189
|
message: "Plan saved to .context/attachments/plan.md and shown in Sideboard chat for approval."
|
|
16961
17190
|
};
|
|
@@ -17175,7 +17404,7 @@ async function startMcpServer() {
|
|
|
17175
17404
|
);
|
|
17176
17405
|
server.tool(
|
|
17177
17406
|
"send_to_thread",
|
|
17178
|
-
|
|
17407
|
+
'Queue a prompt on a worktree thread chat (runs under concurrency cap). Use after create_thread to start or continue a conversation. For commit/push/PR, prefer ask_git (canonical desktop-button phrases). Send "Merge PR." / ask_git merge only when the user explicitly asked to merge. Set force_stop=true to interrupt an in-flight/queued turn (kill + clear queue) before queueing this prompt \u2014 use when the thread is mid-turn or has stale queued prompts you need to replace.',
|
|
17179
17408
|
{
|
|
17180
17409
|
ref: import_zod3.z.string(),
|
|
17181
17410
|
prompt: import_zod3.z.string(),
|
|
@@ -17271,7 +17500,7 @@ async function startMcpServer() {
|
|
|
17271
17500
|
);
|
|
17272
17501
|
server.tool(
|
|
17273
17502
|
"archive_thread",
|
|
17274
|
-
"Archive a thread (stops agent/dev, runs archive script, removes worktree when last chat tab). Coordinators commit, push, open PRs
|
|
17503
|
+
"Archive a thread (stops agent/dev, runs archive script, removes worktree when last chat tab). Coordinators commit, push, and open PRs by asking the worktree agent (ask_git). Merge only when the user explicitly asked.",
|
|
17275
17504
|
{ ref: import_zod3.z.string() },
|
|
17276
17505
|
async ({ ref }) => {
|
|
17277
17506
|
const t = orch.getThread(ref);
|
|
@@ -17379,7 +17608,7 @@ async function startMcpServer() {
|
|
|
17379
17608
|
);
|
|
17380
17609
|
server.tool(
|
|
17381
17610
|
"ask_git",
|
|
17382
|
-
"
|
|
17611
|
+
"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` if SSH is missing). When dirty, queues the worktree agent to commit; then wait_for_turn. 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.",
|
|
17383
17612
|
{
|
|
17384
17613
|
ref: import_zod3.z.string().describe("Worktree thread id/ref"),
|
|
17385
17614
|
action: import_zod3.z.enum(AGENT_GIT_ACTIONS).describe(
|
|
@@ -17680,7 +17909,7 @@ async function startMcpServer() {
|
|
|
17680
17909
|
);
|
|
17681
17910
|
server.tool(
|
|
17682
17911
|
"get_pr_stack",
|
|
17683
|
-
"Load the GitHub PR stack for a thread worktree (`gh stack view --json`). Returns null JSON when the branch is not stacked. Prefer this before ask_git merge on stacked PRs.",
|
|
17912
|
+
"Load the GitHub PR stack for a thread worktree (`gh stack view --json`). Returns null JSON when the branch is not stacked. Prefer this before ask_git merge on stacked PRs (and only merge when the user explicitly asked).",
|
|
17684
17913
|
{ ref: import_zod3.z.string() },
|
|
17685
17914
|
async ({ ref }) => {
|
|
17686
17915
|
const stack = await orch.getPrStack(ref);
|
|
@@ -17852,9 +18081,9 @@ var BrightsySideboardApi = class {
|
|
|
17852
18081
|
get endpoint() {
|
|
17853
18082
|
return (this.cfg.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
17854
18083
|
}
|
|
17855
|
-
async request(
|
|
18084
|
+
async request(path2, init = {}) {
|
|
17856
18085
|
await this.refreshIfNeeded();
|
|
17857
|
-
const url = `${this.endpoint}${
|
|
18086
|
+
const url = `${this.endpoint}${path2}`;
|
|
17858
18087
|
const headers = {
|
|
17859
18088
|
Authorization: `Bearer ${this.cfg.access_token}`,
|
|
17860
18089
|
Accept: "application/json"
|
|
@@ -19461,6 +19690,83 @@ var SlackRelayHub = class {
|
|
|
19461
19690
|
// src/slack/relay-server.ts
|
|
19462
19691
|
var import_node_http3 = require("http");
|
|
19463
19692
|
var import_ws3 = require("ws");
|
|
19693
|
+
|
|
19694
|
+
// src/slack/relay-static.ts
|
|
19695
|
+
var import_node_fs37 = require("fs");
|
|
19696
|
+
var import_promises = require("fs/promises");
|
|
19697
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
19698
|
+
var TYPES = {
|
|
19699
|
+
".css": "text/css; charset=utf-8",
|
|
19700
|
+
".html": "text/html; charset=utf-8",
|
|
19701
|
+
".ico": "image/x-icon",
|
|
19702
|
+
".jpeg": "image/jpeg",
|
|
19703
|
+
".jpg": "image/jpeg",
|
|
19704
|
+
".js": "text/javascript; charset=utf-8",
|
|
19705
|
+
".json": "application/json; charset=utf-8",
|
|
19706
|
+
".png": "image/png",
|
|
19707
|
+
".svg": "image/svg+xml",
|
|
19708
|
+
".txt": "text/plain; charset=utf-8",
|
|
19709
|
+
".webp": "image/webp",
|
|
19710
|
+
".woff2": "font/woff2"
|
|
19711
|
+
};
|
|
19712
|
+
function requestHostname(req) {
|
|
19713
|
+
const raw = req.headers.host ?? "";
|
|
19714
|
+
return raw.split(":")[0]?.toLowerCase() ?? "";
|
|
19715
|
+
}
|
|
19716
|
+
function hostnameAllowed(host, allowed) {
|
|
19717
|
+
if (!allowed || allowed.length === 0) return true;
|
|
19718
|
+
return allowed.includes(host);
|
|
19719
|
+
}
|
|
19720
|
+
function resolveStaticPath(root, requestUrl) {
|
|
19721
|
+
let pathname;
|
|
19722
|
+
try {
|
|
19723
|
+
pathname = decodeURIComponent(new URL(requestUrl, "http://relay.local").pathname);
|
|
19724
|
+
} catch {
|
|
19725
|
+
return null;
|
|
19726
|
+
}
|
|
19727
|
+
if (!pathname.startsWith("/") || pathname.includes("\0")) return null;
|
|
19728
|
+
const rootResolved = import_node_path33.default.resolve(root);
|
|
19729
|
+
const candidate = import_node_path33.default.resolve(rootResolved, `.${pathname}`);
|
|
19730
|
+
if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path33.default.sep)) {
|
|
19731
|
+
return null;
|
|
19732
|
+
}
|
|
19733
|
+
return candidate;
|
|
19734
|
+
}
|
|
19735
|
+
async function fileSize(file) {
|
|
19736
|
+
try {
|
|
19737
|
+
const st = await (0, import_promises.stat)(file);
|
|
19738
|
+
return st.isFile() ? st.size : null;
|
|
19739
|
+
} catch {
|
|
19740
|
+
return null;
|
|
19741
|
+
}
|
|
19742
|
+
}
|
|
19743
|
+
function sendFile(req, res, file, size) {
|
|
19744
|
+
const ext = import_node_path33.default.extname(file).toLowerCase();
|
|
19745
|
+
res.writeHead(200, {
|
|
19746
|
+
"Content-Type": TYPES[ext] ?? "application/octet-stream",
|
|
19747
|
+
"Content-Length": size,
|
|
19748
|
+
"Cache-Control": ext === ".html" ? "no-cache" : "public, max-age=3600"
|
|
19749
|
+
});
|
|
19750
|
+
if (req.method === "HEAD") {
|
|
19751
|
+
res.end();
|
|
19752
|
+
return true;
|
|
19753
|
+
}
|
|
19754
|
+
(0, import_node_fs37.createReadStream)(file).pipe(res);
|
|
19755
|
+
return true;
|
|
19756
|
+
}
|
|
19757
|
+
async function tryServeStatic(req, res, root) {
|
|
19758
|
+
if (req.method !== "GET" && req.method !== "HEAD") return false;
|
|
19759
|
+
const candidate = resolveStaticPath(root, req.url || "/");
|
|
19760
|
+
if (!candidate) return false;
|
|
19761
|
+
const direct = await fileSize(candidate);
|
|
19762
|
+
if (direct != null) return sendFile(req, res, candidate, direct);
|
|
19763
|
+
const asIndex = import_node_path33.default.join(candidate, "index.html");
|
|
19764
|
+
const indexSize = await fileSize(asIndex);
|
|
19765
|
+
if (indexSize != null) return sendFile(req, res, asIndex, indexSize);
|
|
19766
|
+
return false;
|
|
19767
|
+
}
|
|
19768
|
+
|
|
19769
|
+
// src/slack/relay-server.ts
|
|
19464
19770
|
function sendHtml(res, status, title, body) {
|
|
19465
19771
|
res.writeHead(status, { "Content-Type": "text/html; charset=utf-8" });
|
|
19466
19772
|
res.end(slackOAuthHtmlPage(title, body));
|
|
@@ -19559,7 +19865,26 @@ async function startSlackRelayServer(opts) {
|
|
|
19559
19865
|
const reqUrl = req.url || "/";
|
|
19560
19866
|
if (await handleCallback(reqUrl, res)) return;
|
|
19561
19867
|
if (handleResult(reqUrl, res)) return;
|
|
19562
|
-
if (req.url === "/health"
|
|
19868
|
+
if (req.url === "/health") {
|
|
19869
|
+
sendJson(res, 200, {
|
|
19870
|
+
ok: true,
|
|
19871
|
+
service: "sideboard-slack-relay",
|
|
19872
|
+
sessions: hub.listSessions().length,
|
|
19873
|
+
oauth: Boolean(clientSecret)
|
|
19874
|
+
});
|
|
19875
|
+
return;
|
|
19876
|
+
}
|
|
19877
|
+
const hostname2 = requestHostname(req);
|
|
19878
|
+
const canonical = (opts.canonicalSiteHost ?? "www.sideboard.cloud").toLowerCase();
|
|
19879
|
+
if (opts.redirectHosts?.includes(hostname2) && hostname2 !== canonical) {
|
|
19880
|
+
res.writeHead(301, { Location: `https://${canonical}${reqUrl}` });
|
|
19881
|
+
res.end();
|
|
19882
|
+
return;
|
|
19883
|
+
}
|
|
19884
|
+
if (opts.staticRoot && hostnameAllowed(hostname2, opts.staticHosts) && await tryServeStatic(req, res, opts.staticRoot)) {
|
|
19885
|
+
return;
|
|
19886
|
+
}
|
|
19887
|
+
if (req.url === "/") {
|
|
19563
19888
|
sendJson(res, 200, {
|
|
19564
19889
|
ok: true,
|
|
19565
19890
|
service: "sideboard-slack-relay",
|
|
@@ -19669,6 +19994,7 @@ async function startSlackRelayServer(opts) {
|
|
|
19669
19994
|
CONTEXT_MIN_MESSAGES,
|
|
19670
19995
|
COORDINATOR_TOOL_PLAYBOOK,
|
|
19671
19996
|
FAMOUS_SOCCER_TEAMS,
|
|
19997
|
+
GITHUB_GIT_AUTH_MODES,
|
|
19672
19998
|
GLOBAL_WORKSPACE_ID,
|
|
19673
19999
|
HARNESS_ENV_KEYS,
|
|
19674
20000
|
LEGACY_ATTACHMENTS_DIR,
|
|
@@ -19718,10 +20044,12 @@ async function startSlackRelayServer(opts) {
|
|
|
19718
20044
|
allocateTeamSlug,
|
|
19719
20045
|
appDataDir,
|
|
19720
20046
|
appSettingsPath,
|
|
20047
|
+
appendIndexedGitConfig,
|
|
19721
20048
|
appendMessage,
|
|
19722
20049
|
applyAgentEvent,
|
|
19723
20050
|
applyAppEnvironment,
|
|
19724
20051
|
applyCompaction,
|
|
20052
|
+
applyGithubGitAuthEnv,
|
|
19725
20053
|
applyThreadIntoMain,
|
|
19726
20054
|
applyTurnUsage,
|
|
19727
20055
|
assertOrchestratorCapableAgent,
|
|
@@ -19836,6 +20164,7 @@ async function startSlackRelayServer(opts) {
|
|
|
19836
20164
|
formatBrightsyFetchError,
|
|
19837
20165
|
formatFetchError,
|
|
19838
20166
|
formatGhLandError,
|
|
20167
|
+
formatGitAuthModeDirective,
|
|
19839
20168
|
formatIpcInvokeError,
|
|
19840
20169
|
formatMessagesAsTranscript,
|
|
19841
20170
|
formatPlanQuestionAnswers,
|
|
@@ -19850,6 +20179,7 @@ async function startSlackRelayServer(opts) {
|
|
|
19850
20179
|
formatWorkspaceInventory,
|
|
19851
20180
|
formatWorktreeDirective,
|
|
19852
20181
|
formatWorktreeReminder,
|
|
20182
|
+
fromInclusiveInputUsage,
|
|
19853
20183
|
getAdapter,
|
|
19854
20184
|
getAgentSetupInfo,
|
|
19855
20185
|
getBrightsySession,
|
|
@@ -19862,6 +20192,8 @@ async function startSlackRelayServer(opts) {
|
|
|
19862
20192
|
getDiff,
|
|
19863
20193
|
getDiffSummary,
|
|
19864
20194
|
getGitHubStatus,
|
|
20195
|
+
getGithubGitAuthMode,
|
|
20196
|
+
getGithubPat,
|
|
19865
20197
|
getIssueSource,
|
|
19866
20198
|
getLinearApiKey,
|
|
19867
20199
|
getLinearAuthToken,
|
|
@@ -19880,6 +20212,7 @@ async function startSlackRelayServer(opts) {
|
|
|
19880
20212
|
ghHeadRef,
|
|
19881
20213
|
ghRepoSelectArgs,
|
|
19882
20214
|
git,
|
|
20215
|
+
githubAgentGitEnv,
|
|
19883
20216
|
globalAgentCwd,
|
|
19884
20217
|
handleSlackInbound,
|
|
19885
20218
|
harnessEnvKey,
|
|
@@ -20102,6 +20435,7 @@ async function startSlackRelayServer(opts) {
|
|
|
20102
20435
|
startSlackOAuth,
|
|
20103
20436
|
startSlackRelayServer,
|
|
20104
20437
|
stripBrightsyNdjsonNoise,
|
|
20438
|
+
stripNestedElectronEnv,
|
|
20105
20439
|
submitPrStack,
|
|
20106
20440
|
suggestSlug,
|
|
20107
20441
|
summarizeConversation,
|