@sideboard-ai/core 0.1.88 → 0.1.92
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/cursor-runner.cjs +176 -15
- package/dist/agents/cursor-runner.js +11 -2
- package/dist/{agents-LMUFTGKF.js → agents-JXQ5QHDU.js} +4 -4
- package/dist/{agents-ODBP7J6E.js → agents-TUV4NH7S.js} +5 -5
- package/dist/{chunk-RJLBSYUO.js → chunk-35LKGGOC.js} +45 -77
- package/dist/{chunk-WANQFU3S.js → chunk-6XBXVXX2.js} +2 -2
- package/dist/{chunk-7D27DD2X.js → chunk-CIRXAYWS.js} +260 -61
- package/dist/{chunk-B2KIO2SD.js → chunk-CLGO7TLO.js} +2 -2
- package/dist/{chunk-JE75QW2I.js → chunk-GJ2HJQIU.js} +236 -96
- package/dist/{chunk-CBJSPTBG.js → chunk-GXSYI7FH.js} +206 -5
- package/dist/chunk-MMI4RJ5I.js +46 -0
- package/dist/{chunk-UHTNJKZX.js → chunk-NR6APJLD.js} +2 -2
- package/dist/{chunk-6EZRSCIT.js → chunk-QKYO6BHB.js} +2 -2
- package/dist/{chunk-ZXYWWSHZ.js → chunk-R7BQBSDT.js} +254 -61
- package/dist/{chunk-OB6IRIFV.js → chunk-XH2GS2LO.js} +2 -2
- package/dist/{chunk-VZ2L4AEJ.js → chunk-XUWDLRAE.js} +2 -2
- package/dist/{coordinator-prompt-UK5LYFN5.js → coordinator-prompt-AKEY4WSO.js} +2 -2
- package/dist/{coordinator-prompt-CI5SHONJ.js → coordinator-prompt-OQOOD5ET.js} +2 -2
- package/dist/{global-workspace-2YZ2V4I5.js → global-workspace-3GNPQCLE.js} +3 -3
- package/dist/{global-workspace-JQQLPJM5.js → global-workspace-M3OMVDDH.js} +3 -3
- package/dist/index.cjs +998 -463
- package/dist/index.d.cts +77 -19
- package/dist/index.d.ts +77 -19
- package/dist/index.js +181 -50
- package/dist/mcp/run-stdio.cjs +872 -436
- package/dist/mcp/run-stdio.js +132 -48
- package/dist/{workspaces-YWCC3WV4.js → workspaces-ERZC7ULY.js} +4 -4
- package/dist/{workspaces-FDO5L4NI.js → workspaces-J4WG6UFR.js} +4 -4
- package/dist/{worktree-7YNSJ224.js → worktree-DA4BOV7G.js} +7 -1
- package/dist/{worktree-4555QBQ7.js → worktree-EO5QAGJU.js} +7 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3068,42 +3068,124 @@ var init_gh_errors = __esm({
|
|
|
3068
3068
|
}
|
|
3069
3069
|
});
|
|
3070
3070
|
|
|
3071
|
+
// src/git/github-agent-auth.ts
|
|
3072
|
+
function githubAgentAuthDir() {
|
|
3073
|
+
const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
|
|
3074
|
+
if (override) return override;
|
|
3075
|
+
return (0, import_node_path10.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
|
|
3076
|
+
}
|
|
3077
|
+
function githubCredentialStorePath() {
|
|
3078
|
+
return (0, import_node_path10.join)(githubAgentAuthDir(), "git-credentials");
|
|
3079
|
+
}
|
|
3080
|
+
function githubGhConfigDir() {
|
|
3081
|
+
return (0, import_node_path10.join)(githubAgentAuthDir(), "gh");
|
|
3082
|
+
}
|
|
3083
|
+
function writePrivateFile2(file, body) {
|
|
3084
|
+
(0, import_node_fs10.mkdirSync)((0, import_node_path10.dirname)(file), { recursive: true, mode: 448 });
|
|
3085
|
+
try {
|
|
3086
|
+
(0, import_node_fs10.chmodSync)((0, import_node_path10.dirname)(file), 448);
|
|
3087
|
+
} catch {
|
|
3088
|
+
}
|
|
3089
|
+
(0, import_node_fs10.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
|
|
3090
|
+
try {
|
|
3091
|
+
(0, import_node_fs10.chmodSync)(file, 384);
|
|
3092
|
+
} catch {
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3095
|
+
function gitCredentialStoreContents(token) {
|
|
3096
|
+
return `https://x-access-token:${encodeURIComponent(token)}@github.com
|
|
3097
|
+
`;
|
|
3098
|
+
}
|
|
3099
|
+
function ghHostsYml(token, user = "x-access-token") {
|
|
3100
|
+
const u = user.replace(/[^A-Za-z0-9._-]/g, "") || "x-access-token";
|
|
3101
|
+
return [
|
|
3102
|
+
"github.com:",
|
|
3103
|
+
" git_protocol: https",
|
|
3104
|
+
` user: ${u}`,
|
|
3105
|
+
` oauth_token: ${token}`,
|
|
3106
|
+
" users:",
|
|
3107
|
+
` ${u}:`,
|
|
3108
|
+
` oauth_token: ${token}`,
|
|
3109
|
+
""
|
|
3110
|
+
].join("\n");
|
|
3111
|
+
}
|
|
3112
|
+
function materializeGithubAgentAuth(token, user) {
|
|
3113
|
+
const trimmed = token.trim();
|
|
3114
|
+
if (!trimmed) return;
|
|
3115
|
+
const root = githubAgentAuthDir();
|
|
3116
|
+
(0, import_node_fs10.mkdirSync)(root, { recursive: true, mode: 448 });
|
|
3117
|
+
try {
|
|
3118
|
+
(0, import_node_fs10.chmodSync)(root, 448);
|
|
3119
|
+
} catch {
|
|
3120
|
+
}
|
|
3121
|
+
writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
|
|
3122
|
+
const ghDir = githubGhConfigDir();
|
|
3123
|
+
(0, import_node_fs10.mkdirSync)(ghDir, { recursive: true, mode: 448 });
|
|
3124
|
+
writePrivateFile2((0, import_node_path10.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
|
|
3125
|
+
writePrivateFile2((0, import_node_path10.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
|
|
3126
|
+
}
|
|
3127
|
+
function githubAgentAuthReady() {
|
|
3128
|
+
return (0, import_node_fs10.existsSync)(githubCredentialStorePath()) && (0, import_node_fs10.existsSync)((0, import_node_path10.join)(githubGhConfigDir(), "hosts.yml"));
|
|
3129
|
+
}
|
|
3130
|
+
function githubCredentialHelperGitConfig() {
|
|
3131
|
+
const file = githubCredentialStorePath();
|
|
3132
|
+
return [
|
|
3133
|
+
{ key: "credential.helper", value: "" },
|
|
3134
|
+
{ key: "credential.helper", value: `store --file=${file}` }
|
|
3135
|
+
];
|
|
3136
|
+
}
|
|
3137
|
+
function githubGhConfigEnv() {
|
|
3138
|
+
return {
|
|
3139
|
+
GH_CONFIG_DIR: githubGhConfigDir(),
|
|
3140
|
+
GH_PROMPT_DISABLED: "1"
|
|
3141
|
+
};
|
|
3142
|
+
}
|
|
3143
|
+
var import_node_fs10, import_node_os4, import_node_path10;
|
|
3144
|
+
var init_github_agent_auth = __esm({
|
|
3145
|
+
"src/git/github-agent-auth.ts"() {
|
|
3146
|
+
"use strict";
|
|
3147
|
+
import_node_fs10 = require("fs");
|
|
3148
|
+
import_node_os4 = require("os");
|
|
3149
|
+
import_node_path10 = require("path");
|
|
3150
|
+
}
|
|
3151
|
+
});
|
|
3152
|
+
|
|
3071
3153
|
// src/agents/path.ts
|
|
3072
3154
|
function prependPathDir(env, dir) {
|
|
3073
|
-
if (!dir || !(0,
|
|
3155
|
+
if (!dir || !(0, import_node_fs11.existsSync)(dir)) return;
|
|
3074
3156
|
const current = env.PATH ?? "";
|
|
3075
|
-
const parts = current.split(
|
|
3157
|
+
const parts = current.split(import_node_path11.delimiter).filter(Boolean);
|
|
3076
3158
|
if (parts.includes(dir)) {
|
|
3077
3159
|
env.PATH = current;
|
|
3078
3160
|
return;
|
|
3079
3161
|
}
|
|
3080
|
-
env.PATH = [dir, ...parts].join(
|
|
3162
|
+
env.PATH = [dir, ...parts].join(import_node_path11.delimiter);
|
|
3081
3163
|
}
|
|
3082
|
-
function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0,
|
|
3083
|
-
return (0,
|
|
3164
|
+
function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os5.homedir)()) {
|
|
3165
|
+
return (0, import_node_path11.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
|
|
3084
3166
|
}
|
|
3085
3167
|
function isConductorBundledCli(filePath) {
|
|
3086
3168
|
const p = (filePath ?? "").replace(/\\/g, "/");
|
|
3087
3169
|
return p.includes("/com.conductor.app/bin/") || p.endsWith("/com.conductor.app/bin");
|
|
3088
3170
|
}
|
|
3089
3171
|
function ensureAgentPath(env = process.env) {
|
|
3090
|
-
const home = env.HOME || env.USERPROFILE || (0,
|
|
3172
|
+
const home = env.HOME || env.USERPROFILE || (0, import_node_os5.homedir)();
|
|
3091
3173
|
const current = env.PATH ?? "";
|
|
3092
|
-
const parts = current.split(
|
|
3174
|
+
const parts = current.split(import_node_path11.delimiter).filter(Boolean);
|
|
3093
3175
|
const seen = new Set(parts);
|
|
3094
3176
|
const extras = [
|
|
3095
|
-
...EXTRA_BIN_DIRS.map((rel) => (0,
|
|
3177
|
+
...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path11.join)(home, rel)),
|
|
3096
3178
|
"/opt/homebrew/bin",
|
|
3097
3179
|
"/usr/local/bin",
|
|
3098
3180
|
// Keep after Homebrew/npm so a user-installed CLI still wins.
|
|
3099
3181
|
conductorBundledBinDir(home)
|
|
3100
3182
|
];
|
|
3101
3183
|
for (const dir of extras.reverse()) {
|
|
3102
|
-
if (!dir || seen.has(dir) || !(0,
|
|
3184
|
+
if (!dir || seen.has(dir) || !(0, import_node_fs11.existsSync)(dir)) continue;
|
|
3103
3185
|
parts.unshift(dir);
|
|
3104
3186
|
seen.add(dir);
|
|
3105
3187
|
}
|
|
3106
|
-
const next = parts.join(
|
|
3188
|
+
const next = parts.join(import_node_path11.delimiter);
|
|
3107
3189
|
env.PATH = next;
|
|
3108
3190
|
return next;
|
|
3109
3191
|
}
|
|
@@ -3117,7 +3199,7 @@ function enrichPathWithNpmGlobalBin(env = process.env) {
|
|
|
3117
3199
|
stdio: ["ignore", "pipe", "ignore"]
|
|
3118
3200
|
}).trim().split(/\r?\n/).find(Boolean);
|
|
3119
3201
|
if (prefix) {
|
|
3120
|
-
const binDir = process.platform === "win32" ? prefix : (0,
|
|
3202
|
+
const binDir = process.platform === "win32" ? prefix : (0, import_node_path11.join)(prefix, "bin");
|
|
3121
3203
|
prependPathDir(env, binDir);
|
|
3122
3204
|
}
|
|
3123
3205
|
} catch {
|
|
@@ -3145,14 +3227,14 @@ function withExportedPath(command, pathValue) {
|
|
|
3145
3227
|
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
3146
3228
|
return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
|
|
3147
3229
|
}
|
|
3148
|
-
var
|
|
3230
|
+
var import_node_fs11, import_node_child_process3, import_node_os5, import_node_path11, EXTRA_BIN_DIRS;
|
|
3149
3231
|
var init_path = __esm({
|
|
3150
3232
|
"src/agents/path.ts"() {
|
|
3151
3233
|
"use strict";
|
|
3152
|
-
|
|
3234
|
+
import_node_fs11 = require("fs");
|
|
3153
3235
|
import_node_child_process3 = require("child_process");
|
|
3154
|
-
|
|
3155
|
-
|
|
3236
|
+
import_node_os5 = require("os");
|
|
3237
|
+
import_node_path11 = require("path");
|
|
3156
3238
|
EXTRA_BIN_DIRS = [
|
|
3157
3239
|
".local/bin",
|
|
3158
3240
|
".cargo/bin",
|
|
@@ -3277,42 +3359,46 @@ function appendIndexedGitConfig(existing, entries) {
|
|
|
3277
3359
|
return out;
|
|
3278
3360
|
}
|
|
3279
3361
|
function githubAgentGitEnv(existing) {
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
function githubHttpsBearerEnv(existing, token) {
|
|
3283
|
-
const rewrite = githubAgentGitEnv(existing);
|
|
3284
|
-
const header = appendIndexedGitConfig(
|
|
3285
|
-
{ ...existing, ...rewrite },
|
|
3286
|
-
[
|
|
3287
|
-
{
|
|
3288
|
-
key: "http.https://github.com/.extraHeader",
|
|
3289
|
-
value: `AUTHORIZATION: bearer ${token}`
|
|
3290
|
-
}
|
|
3291
|
-
]
|
|
3292
|
-
);
|
|
3293
|
-
return { ...rewrite, ...header };
|
|
3362
|
+
const helpers = githubAgentAuthReady() ? githubCredentialHelperGitConfig() : [{ key: "credential.helper", value: "" }];
|
|
3363
|
+
return appendIndexedGitConfig(existing, [...HTTPS_REWRITE, ...helpers]);
|
|
3294
3364
|
}
|
|
3295
3365
|
function applyGithubGitAuthEnv(existing, opts) {
|
|
3296
3366
|
const out = { ...nonInteractiveGitProcessEnv() };
|
|
3367
|
+
const token = opts.token?.trim() || existing?.GH_TOKEN?.trim() || "" || "";
|
|
3368
|
+
if (token) materializeGithubAgentAuth(token);
|
|
3369
|
+
Object.assign(out, githubGhConfigEnv());
|
|
3297
3370
|
if (opts.mode === "ssh") return out;
|
|
3298
|
-
|
|
3299
|
-
const provided = existingToken ? "" : opts.token?.trim() || "";
|
|
3300
|
-
const token = existingToken || provided;
|
|
3301
|
-
Object.assign(
|
|
3302
|
-
out,
|
|
3303
|
-
token ? githubHttpsBearerEnv(existing, token) : githubAgentGitEnv(existing)
|
|
3304
|
-
);
|
|
3305
|
-
if (provided) out.GH_TOKEN = provided;
|
|
3371
|
+
Object.assign(out, githubAgentGitEnv(existing));
|
|
3306
3372
|
return out;
|
|
3307
3373
|
}
|
|
3374
|
+
function scrubGithubTokensFromChildEnv(env) {
|
|
3375
|
+
for (const key of GITHUB_CHILD_TOKEN_KEYS) {
|
|
3376
|
+
delete env[key];
|
|
3377
|
+
}
|
|
3378
|
+
}
|
|
3379
|
+
function mergeAgentGitAuthEnv(env, gitEnv) {
|
|
3380
|
+
Object.assign(env, gitEnv);
|
|
3381
|
+
scrubGithubTokensFromChildEnv(env);
|
|
3382
|
+
}
|
|
3308
3383
|
async function resolveGithubAgentToken(mode, cwd) {
|
|
3309
|
-
if (mode ===
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3384
|
+
if (tokenMemo && tokenMemo.mode === mode && Date.now() - tokenMemo.at < TOKEN_TTL_MS) {
|
|
3385
|
+
return tokenMemo.value;
|
|
3386
|
+
}
|
|
3387
|
+
let value = null;
|
|
3388
|
+
if (mode === "token") {
|
|
3389
|
+
value = getGithubPat();
|
|
3390
|
+
} else {
|
|
3391
|
+
try {
|
|
3392
|
+
value = await resolveGhAuthToken(cwd);
|
|
3393
|
+
} catch {
|
|
3394
|
+
value = null;
|
|
3395
|
+
}
|
|
3315
3396
|
}
|
|
3397
|
+
tokenMemo = { mode, value, at: Date.now() };
|
|
3398
|
+
return value;
|
|
3399
|
+
}
|
|
3400
|
+
function resetGithubAgentTokenMemo() {
|
|
3401
|
+
tokenMemo = null;
|
|
3316
3402
|
}
|
|
3317
3403
|
async function resolveAgentGitAuthEnv(existing, opts) {
|
|
3318
3404
|
let mode = "auto";
|
|
@@ -3334,7 +3420,40 @@ async function resolveAgentGitAuthEnv(existing, opts) {
|
|
|
3334
3420
|
}
|
|
3335
3421
|
return applyGithubGitAuthEnv(existing, { mode, token });
|
|
3336
3422
|
}
|
|
3337
|
-
function
|
|
3423
|
+
async function warmGithubAgentAuth(opts) {
|
|
3424
|
+
if (!opts?.force && githubAgentAuthReady()) return;
|
|
3425
|
+
await resolveAgentGitAuthEnv(void 0, opts);
|
|
3426
|
+
}
|
|
3427
|
+
function normalizeWritableRoot(raw) {
|
|
3428
|
+
const trimmed = raw.trim().replace(/\/+$/, "");
|
|
3429
|
+
return trimmed && (0, import_node_path12.isAbsolute)(trimmed) ? trimmed : null;
|
|
3430
|
+
}
|
|
3431
|
+
async function resolveCodexGitWritableRoots(cwd) {
|
|
3432
|
+
const roots = /* @__PURE__ */ new Set();
|
|
3433
|
+
const authDir = normalizeWritableRoot(githubAgentAuthDir());
|
|
3434
|
+
if (authDir) roots.add(authDir);
|
|
3435
|
+
try {
|
|
3436
|
+
const [gitDir, commonDir] = await Promise.all([
|
|
3437
|
+
git(["rev-parse", "--absolute-git-dir"], cwd, { reject: false, timeoutMs: 5e3 }),
|
|
3438
|
+
git(["rev-parse", "--path-format=absolute", "--git-common-dir"], cwd, {
|
|
3439
|
+
reject: false,
|
|
3440
|
+
timeoutMs: 5e3
|
|
3441
|
+
})
|
|
3442
|
+
]);
|
|
3443
|
+
const gitDirPath = gitDir.exitCode === 0 ? normalizeWritableRoot(gitDir.stdout) : null;
|
|
3444
|
+
const commonPath = commonDir.exitCode === 0 ? normalizeWritableRoot(commonDir.stdout) : null;
|
|
3445
|
+
if (gitDirPath) roots.add(gitDirPath);
|
|
3446
|
+
if (commonPath) roots.add(commonPath);
|
|
3447
|
+
} catch {
|
|
3448
|
+
}
|
|
3449
|
+
return [...roots];
|
|
3450
|
+
}
|
|
3451
|
+
function codexSandboxWritableRootsArgs(roots) {
|
|
3452
|
+
const abs = [...new Set(roots.map(normalizeWritableRoot).filter(Boolean))];
|
|
3453
|
+
if (abs.length === 0) return [];
|
|
3454
|
+
return ["-c", `sandbox_workspace_write.writable_roots=${JSON.stringify(abs)}`];
|
|
3455
|
+
}
|
|
3456
|
+
function codexUnattendedGitConfigArgs(sandbox, opts) {
|
|
3338
3457
|
const args = [
|
|
3339
3458
|
"-c",
|
|
3340
3459
|
'shell_environment_policy.inherit="all"',
|
|
@@ -3343,54 +3462,65 @@ function codexUnattendedGitConfigArgs(sandbox) {
|
|
|
3343
3462
|
];
|
|
3344
3463
|
if (sandbox === "workspace-write") {
|
|
3345
3464
|
args.push("-c", "sandbox_workspace_write.network_access=true");
|
|
3465
|
+
args.push(...codexSandboxWritableRootsArgs(opts?.writableRoots ?? []));
|
|
3346
3466
|
}
|
|
3347
3467
|
return args;
|
|
3348
3468
|
}
|
|
3349
3469
|
function formatGitAuthModeDirective(mode) {
|
|
3470
|
+
const shared = [
|
|
3471
|
+
"- `git` and `gh` already authenticate in this process. Do not look for tokens in the environment, paste credentials into commands, or switch remotes to SSH.",
|
|
3472
|
+
"- Do not set GitHub token environment variables, pass `--with-token`, or run `gh auth login` from this turn.",
|
|
3473
|
+
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below.",
|
|
3474
|
+
"- If git/gh fail with auth errors, tell the user to run `gh auth login` on this Mac (or set a PAT in Account \u2192 GitHub). Do not wait for a Keychain dialog."
|
|
3475
|
+
];
|
|
3350
3476
|
switch (mode) {
|
|
3351
3477
|
case "gh":
|
|
3352
3478
|
return [
|
|
3353
3479
|
"Git authentication (Account \u2192 GitHub mode: gh CLI):",
|
|
3354
3480
|
"- This process rewrites `git@github.com:` and `ssh://git@github.com/` to HTTPS.",
|
|
3355
|
-
|
|
3356
|
-
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
3481
|
+
...shared
|
|
3357
3482
|
].join("\n");
|
|
3358
3483
|
case "ssh":
|
|
3359
3484
|
return [
|
|
3360
3485
|
"Git authentication (Account \u2192 GitHub mode: SSH):",
|
|
3361
3486
|
"- Keep SSH remotes (`git@github.com:\u2026`). Do not rewrite them to HTTPS.",
|
|
3362
3487
|
"- SSH is batch-mode: it will not prompt for a Keychain password. If push fails with `Permission denied (publickey)`, tell the user to unlock ssh-agent or switch Account \u2192 GitHub to Auto / gh CLI \u2014 do not rewrite remotes yourself.",
|
|
3363
|
-
"-
|
|
3488
|
+
"- `gh` already authenticates for PRs/API (no token in the environment). Do not set GitHub token environment variables or run `gh auth login` from this turn.",
|
|
3489
|
+
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
3364
3490
|
].join("\n");
|
|
3365
3491
|
case "token":
|
|
3366
3492
|
return [
|
|
3367
3493
|
"Git authentication (Account \u2192 GitHub mode: personal access token):",
|
|
3368
3494
|
"- This process rewrites GitHub SSH remotes to HTTPS.",
|
|
3369
|
-
|
|
3370
|
-
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
3495
|
+
...shared
|
|
3371
3496
|
].join("\n");
|
|
3372
3497
|
case "auto":
|
|
3373
3498
|
default:
|
|
3374
3499
|
return [
|
|
3375
3500
|
"Git authentication (Account \u2192 GitHub mode: auto):",
|
|
3376
|
-
"- This process rewrites GitHub SSH remotes to HTTPS
|
|
3377
|
-
|
|
3378
|
-
"- If HTTPS auth fails, tell the user to run `gh auth login` on this Mac or set Account \u2192 GitHub to a PAT \u2014 do not wait for a Keychain dialog."
|
|
3501
|
+
"- This process rewrites GitHub SSH remotes to HTTPS so git/ssh never prompt the macOS Keychain (required for unattended orchestrator turns).",
|
|
3502
|
+
...shared
|
|
3379
3503
|
].join("\n");
|
|
3380
3504
|
}
|
|
3381
3505
|
}
|
|
3382
|
-
var HTTPS_REWRITE;
|
|
3506
|
+
var import_node_path12, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
|
|
3383
3507
|
var init_git_auth_mode = __esm({
|
|
3384
3508
|
"src/git/git-auth-mode.ts"() {
|
|
3385
3509
|
"use strict";
|
|
3510
|
+
import_node_path12 = require("path");
|
|
3386
3511
|
init_app_settings();
|
|
3512
|
+
init_github_agent_auth();
|
|
3387
3513
|
init_run();
|
|
3388
3514
|
HTTPS_REWRITE = [
|
|
3389
3515
|
{ key: "url.https://github.com/.insteadOf", value: "git@github.com:" },
|
|
3390
|
-
{ key: "url.https://github.com/.insteadOf", value: "ssh://git@github.com/" }
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3516
|
+
{ key: "url.https://github.com/.insteadOf", value: "ssh://git@github.com/" }
|
|
3517
|
+
];
|
|
3518
|
+
TOKEN_TTL_MS = 12 * 60 * 60 * 1e3;
|
|
3519
|
+
tokenMemo = null;
|
|
3520
|
+
GITHUB_CHILD_TOKEN_KEYS = [
|
|
3521
|
+
"GH_TOKEN",
|
|
3522
|
+
"GITHUB_TOKEN",
|
|
3523
|
+
"GH_ENTERPRISE_TOKEN"
|
|
3394
3524
|
];
|
|
3395
3525
|
}
|
|
3396
3526
|
});
|
|
@@ -3751,10 +3881,12 @@ __export(worktree_exports, {
|
|
|
3751
3881
|
getPr: () => getPr,
|
|
3752
3882
|
getPrChecks: () => getPrChecks,
|
|
3753
3883
|
getPrDetails: () => getPrDetails,
|
|
3884
|
+
getPrForHeadBranch: () => getPrForHeadBranch,
|
|
3754
3885
|
getPrMeta: () => getPrMeta,
|
|
3755
3886
|
ghHeadRef: () => ghHeadRef,
|
|
3756
3887
|
ghRepoSelectArgs: () => ghRepoSelectArgs,
|
|
3757
3888
|
githubAgentGitEnv: () => githubAgentGitEnv,
|
|
3889
|
+
isDefaultishSourceRef: () => isDefaultishSourceRef,
|
|
3758
3890
|
isDirty: () => isDirty,
|
|
3759
3891
|
isPlaceholderBranch: () => isPlaceholderBranch,
|
|
3760
3892
|
isSideboardScratchPath: () => isSideboardScratchPath,
|
|
@@ -3772,6 +3904,7 @@ __export(worktree_exports, {
|
|
|
3772
3904
|
resolveDiffBaseRef: () => resolveDiffBaseRef,
|
|
3773
3905
|
resolveGithubRepoSlug: () => resolveGithubRepoSlug,
|
|
3774
3906
|
resolvePrSelector: () => resolvePrSelector,
|
|
3907
|
+
resolvePrSelectors: () => resolvePrSelectors,
|
|
3775
3908
|
resolveRepoRoot: () => resolveRepoRoot,
|
|
3776
3909
|
resolveWorktreeStartPoint: () => resolveWorktreeStartPoint,
|
|
3777
3910
|
slugify: () => slugify,
|
|
@@ -3880,7 +4013,7 @@ async function originGhRepoEnv(cwd, opts) {
|
|
|
3880
4013
|
await ensureGhPreferOrigin(cwd);
|
|
3881
4014
|
const slug = await resolveGithubRepoSlug(cwd);
|
|
3882
4015
|
const mode = opts?.mode ?? getGithubGitAuthMode();
|
|
3883
|
-
const token =
|
|
4016
|
+
const token = await resolveGithubAgentToken(mode, cwd);
|
|
3884
4017
|
return {
|
|
3885
4018
|
...applyGithubGitAuthEnv(opts?.env, { mode, token }),
|
|
3886
4019
|
...slug ? { GH_REPO: slug } : {}
|
|
@@ -4020,13 +4153,78 @@ async function getPr(repoPath, number) {
|
|
|
4020
4153
|
if (exitCode !== 0 || !stdout.trim()) return null;
|
|
4021
4154
|
return JSON.parse(stdout);
|
|
4022
4155
|
}
|
|
4023
|
-
function
|
|
4024
|
-
|
|
4156
|
+
function normalizeGitBranchName(ref) {
|
|
4157
|
+
return ref.trim().replace(/^refs\/heads\//, "").replace(/^origin\//, "");
|
|
4158
|
+
}
|
|
4159
|
+
function isDefaultishSourceRef(ref) {
|
|
4160
|
+
const n = normalizeGitBranchName(ref ?? "").toLowerCase();
|
|
4161
|
+
return !n || n === "head" || n === "default" || n === "main" || n === "master" || n === "develop" || n === "trunk";
|
|
4162
|
+
}
|
|
4163
|
+
function resolvePrSelectors(thread) {
|
|
4164
|
+
const out = [];
|
|
4165
|
+
const push = (value) => {
|
|
4166
|
+
const v = value?.trim();
|
|
4167
|
+
if (!v || out.includes(v)) return;
|
|
4168
|
+
out.push(v);
|
|
4169
|
+
};
|
|
4170
|
+
push(thread.prUrl);
|
|
4025
4171
|
if (thread.sourceType === "pr" && thread.sourceRef?.trim()) {
|
|
4026
|
-
|
|
4172
|
+
push(thread.sourceRef.replace(/^#/, "").trim());
|
|
4173
|
+
}
|
|
4174
|
+
push(thread.branchName);
|
|
4175
|
+
if (thread.sourceType === "branch") {
|
|
4176
|
+
const source = normalizeGitBranchName(thread.sourceRef ?? "");
|
|
4177
|
+
if (source && !isDefaultishSourceRef(source) && source !== thread.branchName?.trim()) {
|
|
4178
|
+
push(source);
|
|
4179
|
+
}
|
|
4180
|
+
}
|
|
4181
|
+
return out;
|
|
4182
|
+
}
|
|
4183
|
+
function resolvePrSelector(thread) {
|
|
4184
|
+
return resolvePrSelectors(thread)[0] ?? null;
|
|
4185
|
+
}
|
|
4186
|
+
async function getPrForHeadBranch(repoPath, branch) {
|
|
4187
|
+
const head = normalizeGitBranchName(branch);
|
|
4188
|
+
if (!head || isDefaultishSourceRef(head)) return null;
|
|
4189
|
+
const slug = await resolveGithubRepoSlug(repoPath);
|
|
4190
|
+
const viewArgs = [
|
|
4191
|
+
"pr",
|
|
4192
|
+
"view",
|
|
4193
|
+
head,
|
|
4194
|
+
"--json",
|
|
4195
|
+
"number,title,headRefName,url,isCrossRepository"
|
|
4196
|
+
];
|
|
4197
|
+
if (slug) viewArgs.push("--repo", slug);
|
|
4198
|
+
const viewed = await gh(viewArgs, repoPath, { reject: false });
|
|
4199
|
+
if (viewed.exitCode === 0 && viewed.stdout.trim()) {
|
|
4200
|
+
try {
|
|
4201
|
+
return JSON.parse(viewed.stdout);
|
|
4202
|
+
} catch {
|
|
4203
|
+
return null;
|
|
4204
|
+
}
|
|
4205
|
+
}
|
|
4206
|
+
const listHead = slug ? ghHeadRef(slug, head) : head;
|
|
4207
|
+
const listArgs = [
|
|
4208
|
+
"pr",
|
|
4209
|
+
"list",
|
|
4210
|
+
"--head",
|
|
4211
|
+
listHead,
|
|
4212
|
+
"--json",
|
|
4213
|
+
"number,title,headRefName,url,isCrossRepository",
|
|
4214
|
+
"--limit",
|
|
4215
|
+
"1",
|
|
4216
|
+
"--state",
|
|
4217
|
+
"open"
|
|
4218
|
+
];
|
|
4219
|
+
if (slug) listArgs.push("--repo", slug);
|
|
4220
|
+
const listed = await gh(listArgs, repoPath, { reject: false });
|
|
4221
|
+
if (listed.exitCode !== 0 || !listed.stdout.trim()) return null;
|
|
4222
|
+
try {
|
|
4223
|
+
const rows = JSON.parse(listed.stdout);
|
|
4224
|
+
return rows[0] ?? null;
|
|
4225
|
+
} catch {
|
|
4226
|
+
return null;
|
|
4027
4227
|
}
|
|
4028
|
-
if (thread.branchName?.trim()) return thread.branchName.trim();
|
|
4029
|
-
return null;
|
|
4030
4228
|
}
|
|
4031
4229
|
function normalizeGhTime(value) {
|
|
4032
4230
|
if (typeof value !== "string" || !value.trim()) return null;
|
|
@@ -4352,7 +4550,7 @@ async function fetchPrHead(repoPath, number, localBranch) {
|
|
|
4352
4550
|
const label = opts?.ghAuth ? `${remote} (gh auth)` : remote;
|
|
4353
4551
|
const gitOpts = { reject: false };
|
|
4354
4552
|
if (opts?.ghAuth) {
|
|
4355
|
-
const token = await
|
|
4553
|
+
const token = await resolveGithubAgentToken(getGithubGitAuthMode(), repoPath);
|
|
4356
4554
|
if (!token) {
|
|
4357
4555
|
errors.push(`${label}: gh auth token unavailable`);
|
|
4358
4556
|
return false;
|
|
@@ -4403,7 +4601,7 @@ async function fetchPrHead(repoPath, number, localBranch) {
|
|
|
4403
4601
|
const ensureOid = async (remote, opts) => {
|
|
4404
4602
|
const gitOpts = { reject: false };
|
|
4405
4603
|
if (opts?.ghAuth) {
|
|
4406
|
-
const token = await
|
|
4604
|
+
const token = await resolveGithubAgentToken(getGithubGitAuthMode(), repoPath);
|
|
4407
4605
|
if (!token) return false;
|
|
4408
4606
|
gitOpts.env = { GIT_TERMINAL_PROMPT: "0" };
|
|
4409
4607
|
gitOpts.config = {
|
|
@@ -4471,8 +4669,8 @@ function isLocalPrFetchBranch(ref) {
|
|
|
4471
4669
|
}
|
|
4472
4670
|
async function createThreadWorktree(opts) {
|
|
4473
4671
|
let branchName = `thread/${opts.slug}`;
|
|
4474
|
-
const worktreePath = (0,
|
|
4475
|
-
if ((0,
|
|
4672
|
+
const worktreePath = (0, import_node_path13.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
4673
|
+
if ((0, import_node_fs12.existsSync)(worktreePath)) {
|
|
4476
4674
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
4477
4675
|
}
|
|
4478
4676
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -4541,8 +4739,8 @@ ${add.stdout}`;
|
|
|
4541
4739
|
async function createExistingBranchWorktree(opts) {
|
|
4542
4740
|
const branchName = opts.branchName.trim();
|
|
4543
4741
|
if (!branchName) throw new Error("branch name required");
|
|
4544
|
-
const worktreePath = (0,
|
|
4545
|
-
if ((0,
|
|
4742
|
+
const worktreePath = (0, import_node_path13.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
4743
|
+
if ((0, import_node_fs12.existsSync)(worktreePath)) {
|
|
4546
4744
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
4547
4745
|
}
|
|
4548
4746
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -4653,7 +4851,7 @@ async function pushBranch(worktreePath, branchName) {
|
|
|
4653
4851
|
if (ssh.exitCode === 0) return;
|
|
4654
4852
|
const sshErr = (ssh.stderr || ssh.stdout).trim();
|
|
4655
4853
|
const slug = await resolveGithubRepoSlug(worktreePath);
|
|
4656
|
-
const token = await
|
|
4854
|
+
const token = await resolveGithubAgentToken(getGithubGitAuthMode(), worktreePath);
|
|
4657
4855
|
if (!slug || !token) {
|
|
4658
4856
|
throw new Error(
|
|
4659
4857
|
sshErr || `git push origin ${branchName} failed` + (!token ? " (no SSH agent and gh auth token unavailable \u2014 run: gh auth login)" : "")
|
|
@@ -4830,10 +5028,10 @@ function sameRepoPath(a, b) {
|
|
|
4830
5028
|
return normalizeWorktreePath(a) === normalizeWorktreePath(b);
|
|
4831
5029
|
}
|
|
4832
5030
|
function listLocalThreadBranchSlugs(repoPath) {
|
|
4833
|
-
const refsDir = (0,
|
|
4834
|
-
if (!(0,
|
|
5031
|
+
const refsDir = (0, import_node_path13.join)(repoPath, ".git", "refs", "heads", "thread");
|
|
5032
|
+
if (!(0, import_node_fs12.existsSync)(refsDir)) return [];
|
|
4835
5033
|
try {
|
|
4836
|
-
return (0,
|
|
5034
|
+
return (0, import_node_fs12.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
|
|
4837
5035
|
} catch {
|
|
4838
5036
|
return [];
|
|
4839
5037
|
}
|
|
@@ -4841,8 +5039,8 @@ function listLocalThreadBranchSlugs(repoPath) {
|
|
|
4841
5039
|
function collectTakenTeamSlugs(repoPath) {
|
|
4842
5040
|
const taken = /* @__PURE__ */ new Set();
|
|
4843
5041
|
const root = worktreesRoot(repoPath);
|
|
4844
|
-
if ((0,
|
|
4845
|
-
for (const entry of (0,
|
|
5042
|
+
if ((0, import_node_fs12.existsSync)(root)) {
|
|
5043
|
+
for (const entry of (0, import_node_fs12.readdirSync)(root, { withFileTypes: true })) {
|
|
4846
5044
|
if (entry.isDirectory() && entry.name !== ".DS_Store") {
|
|
4847
5045
|
taken.add(normalizeTakenSlug(entry.name));
|
|
4848
5046
|
}
|
|
@@ -4863,18 +5061,18 @@ function allocateTeamSlug(repoPath) {
|
|
|
4863
5061
|
const taken = collectTakenTeamSlugs(repoPath);
|
|
4864
5062
|
for (let attempt = 0; attempt < 32; attempt++) {
|
|
4865
5063
|
const team = allocateTeamName(taken);
|
|
4866
|
-
const path2 = (0,
|
|
4867
|
-
if (!(0,
|
|
5064
|
+
const path2 = (0, import_node_path13.join)(worktreesRoot(repoPath), team.slug);
|
|
5065
|
+
if (!(0, import_node_fs12.existsSync)(path2)) return team;
|
|
4868
5066
|
taken.add(team.slug);
|
|
4869
5067
|
}
|
|
4870
5068
|
throw new Error("No available soccer team worktree directories left");
|
|
4871
5069
|
}
|
|
4872
|
-
var
|
|
5070
|
+
var import_node_fs12, import_node_path13;
|
|
4873
5071
|
var init_worktree = __esm({
|
|
4874
5072
|
"src/git/worktree.ts"() {
|
|
4875
5073
|
"use strict";
|
|
4876
|
-
|
|
4877
|
-
|
|
5074
|
+
import_node_fs12 = require("fs");
|
|
5075
|
+
import_node_path13 = require("path");
|
|
4878
5076
|
init_paths();
|
|
4879
5077
|
init_thread_store();
|
|
4880
5078
|
init_teams();
|
|
@@ -4958,7 +5156,7 @@ function coordinatorTurnReminder(opts) {
|
|
|
4958
5156
|
function ensureGlobalCoordinatorCwd(opts) {
|
|
4959
5157
|
const dir = globalAgentCwd();
|
|
4960
5158
|
try {
|
|
4961
|
-
(0,
|
|
5159
|
+
(0, import_node_fs13.mkdirSync)(dir, { recursive: true });
|
|
4962
5160
|
} catch {
|
|
4963
5161
|
return dir;
|
|
4964
5162
|
}
|
|
@@ -4966,7 +5164,7 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
4966
5164
|
let orchId = opts?.orchestratorThreadId?.trim() || "";
|
|
4967
5165
|
if (!orchId) {
|
|
4968
5166
|
try {
|
|
4969
|
-
const existing = (0,
|
|
5167
|
+
const existing = (0, import_node_fs13.readFileSync)((0, import_node_path14.join)(dir, "AGENTS.md"), "utf8");
|
|
4970
5168
|
const m = existing.match(
|
|
4971
5169
|
/YOUR orchestration thread id is `([0-9a-f-]{36})`/i
|
|
4972
5170
|
);
|
|
@@ -5008,9 +5206,9 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
5008
5206
|
"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."
|
|
5009
5207
|
].join("\n");
|
|
5010
5208
|
try {
|
|
5011
|
-
(0,
|
|
5209
|
+
(0, import_node_fs13.writeFileSync)((0, import_node_path14.join)(dir, "CLAUDE.md"), `${body}
|
|
5012
5210
|
`, "utf8");
|
|
5013
|
-
(0,
|
|
5211
|
+
(0, import_node_fs13.writeFileSync)((0, import_node_path14.join)(dir, "AGENTS.md"), `${body}
|
|
5014
5212
|
`, "utf8");
|
|
5015
5213
|
} catch {
|
|
5016
5214
|
}
|
|
@@ -5042,12 +5240,12 @@ function coordinatorSystemPrompt(opts) {
|
|
|
5042
5240
|
formatWorkspaceInventory(opts.workspaces)
|
|
5043
5241
|
].join("\n");
|
|
5044
5242
|
}
|
|
5045
|
-
var
|
|
5243
|
+
var import_node_fs13, import_node_path14, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
|
|
5046
5244
|
var init_coordinator_prompt = __esm({
|
|
5047
5245
|
"src/orchestrator/coordinator-prompt.ts"() {
|
|
5048
5246
|
"use strict";
|
|
5049
|
-
|
|
5050
|
-
|
|
5247
|
+
import_node_fs13 = require("fs");
|
|
5248
|
+
import_node_path14 = require("path");
|
|
5051
5249
|
init_worktree();
|
|
5052
5250
|
init_app_settings();
|
|
5053
5251
|
init_paths();
|
|
@@ -5063,7 +5261,7 @@ var init_coordinator_prompt = __esm({
|
|
|
5063
5261
|
"- get_pr_stack / open_pr_stack_layers / add_stack_layer / create_pr_stack \u2014 GitHub stacked PRs (`gh stack`); one worktree per layer",
|
|
5064
5262
|
"- list_models \u2014 only when you need a specific model (rare); otherwise omit model so Account defaults apply",
|
|
5065
5263
|
"- list_threads / get_thread \u2014 fleet status (what is going on)",
|
|
5066
|
-
"- ask_user \u2014 multiple-choice
|
|
5264
|
+
"- ask_user \u2014 composer multiple-choice only when blocked on a concrete choice (approach fork, which API). Never for hellos, check-ins, or invented \u201Cwhat should we do?\u201D menus \u2014 reply in chat. Explain options first, description on every option, then wait.",
|
|
5067
5265
|
"- set_caffeinate \u2014 keep this Mac awake across turns (macOS caffeinate). Turn on for Slack / away-from-keyboard work. Turn OFF when the user says they are done, wrapping up, going to sleep, or no longer need the machine awake. Closing this chat also releases it.",
|
|
5068
5266
|
"Workspaces:",
|
|
5069
5267
|
"- add_workspace / remove_workspace \u2014 register or unregister a git repo",
|
|
@@ -5353,38 +5551,38 @@ __export(workspaces_exports, {
|
|
|
5353
5551
|
syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
|
|
5354
5552
|
});
|
|
5355
5553
|
function workspacesFile() {
|
|
5356
|
-
return (0,
|
|
5554
|
+
return (0, import_node_path15.join)(appDataDir(), "workspaces.json");
|
|
5357
5555
|
}
|
|
5358
5556
|
function removedWorkspacesFile() {
|
|
5359
|
-
return (0,
|
|
5557
|
+
return (0, import_node_path15.join)(appDataDir(), "removed-workspaces.json");
|
|
5360
5558
|
}
|
|
5361
5559
|
function readAll() {
|
|
5362
5560
|
const path2 = workspacesFile();
|
|
5363
|
-
if (!(0,
|
|
5561
|
+
if (!(0, import_node_fs14.existsSync)(path2)) return [];
|
|
5364
5562
|
try {
|
|
5365
|
-
const raw = JSON.parse((0,
|
|
5563
|
+
const raw = JSON.parse((0, import_node_fs14.readFileSync)(path2, "utf8"));
|
|
5366
5564
|
return Array.isArray(raw) ? raw : [];
|
|
5367
5565
|
} catch {
|
|
5368
5566
|
return [];
|
|
5369
5567
|
}
|
|
5370
5568
|
}
|
|
5371
5569
|
function writeAll(list) {
|
|
5372
|
-
(0,
|
|
5373
|
-
(0,
|
|
5570
|
+
(0, import_node_fs14.mkdirSync)(appDataDir(), { recursive: true });
|
|
5571
|
+
(0, import_node_fs14.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
|
|
5374
5572
|
}
|
|
5375
5573
|
function readRemoved() {
|
|
5376
5574
|
const path2 = removedWorkspacesFile();
|
|
5377
|
-
if (!(0,
|
|
5575
|
+
if (!(0, import_node_fs14.existsSync)(path2)) return /* @__PURE__ */ new Set();
|
|
5378
5576
|
try {
|
|
5379
|
-
const raw = JSON.parse((0,
|
|
5577
|
+
const raw = JSON.parse((0, import_node_fs14.readFileSync)(path2, "utf8"));
|
|
5380
5578
|
return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
|
|
5381
5579
|
} catch {
|
|
5382
5580
|
return /* @__PURE__ */ new Set();
|
|
5383
5581
|
}
|
|
5384
5582
|
}
|
|
5385
5583
|
function writeRemoved(paths) {
|
|
5386
|
-
(0,
|
|
5387
|
-
(0,
|
|
5584
|
+
(0, import_node_fs14.mkdirSync)(appDataDir(), { recursive: true });
|
|
5585
|
+
(0, import_node_fs14.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
|
|
5388
5586
|
}
|
|
5389
5587
|
function rememberRemoved(repoPath) {
|
|
5390
5588
|
const next = readRemoved();
|
|
@@ -5407,7 +5605,7 @@ function listWorkspaces() {
|
|
|
5407
5605
|
async function addWorkspace(repoPath) {
|
|
5408
5606
|
const root = await resolveRepoRoot(repoPath);
|
|
5409
5607
|
if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
|
|
5410
|
-
if (!(0,
|
|
5608
|
+
if (!(0, import_node_fs14.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
|
|
5411
5609
|
forgetRemoved(root);
|
|
5412
5610
|
await ensureGhPreferOrigin(root);
|
|
5413
5611
|
const current = readAll();
|
|
@@ -5415,7 +5613,7 @@ async function addWorkspace(repoPath) {
|
|
|
5415
5613
|
if (existing) return existing;
|
|
5416
5614
|
const next = {
|
|
5417
5615
|
path: root,
|
|
5418
|
-
name: (0,
|
|
5616
|
+
name: (0, import_node_path15.basename)(root),
|
|
5419
5617
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5420
5618
|
};
|
|
5421
5619
|
writeAll([...current, next]);
|
|
@@ -5437,10 +5635,10 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
5437
5635
|
if (!path2 || path2 === "/" || isGlobalRepoPath(path2) || byPath.has(path2) || removed.has(path2)) {
|
|
5438
5636
|
continue;
|
|
5439
5637
|
}
|
|
5440
|
-
if (!(0,
|
|
5638
|
+
if (!(0, import_node_fs14.existsSync)(path2)) continue;
|
|
5441
5639
|
const ws = {
|
|
5442
5640
|
path: path2,
|
|
5443
|
-
name: (0,
|
|
5641
|
+
name: (0, import_node_path15.basename)(path2),
|
|
5444
5642
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5445
5643
|
};
|
|
5446
5644
|
byPath.set(path2, ws);
|
|
@@ -5450,12 +5648,12 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
5450
5648
|
if (dirty) writeAll(next);
|
|
5451
5649
|
return next.sort((a, b) => a.name.localeCompare(b.name));
|
|
5452
5650
|
}
|
|
5453
|
-
var
|
|
5651
|
+
var import_node_fs14, import_node_path15;
|
|
5454
5652
|
var init_workspaces = __esm({
|
|
5455
5653
|
"src/store/workspaces.ts"() {
|
|
5456
5654
|
"use strict";
|
|
5457
|
-
|
|
5458
|
-
|
|
5655
|
+
import_node_fs14 = require("fs");
|
|
5656
|
+
import_node_path15 = require("path");
|
|
5459
5657
|
init_paths();
|
|
5460
5658
|
init_global_workspace();
|
|
5461
5659
|
init_worktree();
|
|
@@ -5464,32 +5662,32 @@ var init_workspaces = __esm({
|
|
|
5464
5662
|
|
|
5465
5663
|
// src/brightsy/config.ts
|
|
5466
5664
|
function brightsyConfigPath() {
|
|
5467
|
-
return (0,
|
|
5665
|
+
return (0, import_node_path16.join)((0, import_node_os6.homedir)(), ".brightsy", "config.json");
|
|
5468
5666
|
}
|
|
5469
5667
|
function loadBrightsyConfig() {
|
|
5470
5668
|
const path2 = brightsyConfigPath();
|
|
5471
|
-
if (!(0,
|
|
5669
|
+
if (!(0, import_node_fs15.existsSync)(path2)) {
|
|
5472
5670
|
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
5473
5671
|
}
|
|
5474
|
-
const raw = JSON.parse((0,
|
|
5672
|
+
const raw = JSON.parse((0, import_node_fs15.readFileSync)(path2, "utf8"));
|
|
5475
5673
|
if (!raw.access_token || !raw.account_id) {
|
|
5476
5674
|
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
5477
5675
|
}
|
|
5478
5676
|
return raw;
|
|
5479
5677
|
}
|
|
5480
5678
|
function saveBrightsyConfig(cfg) {
|
|
5481
|
-
(0,
|
|
5679
|
+
(0, import_node_fs15.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
5482
5680
|
`, {
|
|
5483
5681
|
mode: 384
|
|
5484
5682
|
});
|
|
5485
5683
|
}
|
|
5486
|
-
var
|
|
5684
|
+
var import_node_fs15, import_node_os6, import_node_path16;
|
|
5487
5685
|
var init_config = __esm({
|
|
5488
5686
|
"src/brightsy/config.ts"() {
|
|
5489
5687
|
"use strict";
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5688
|
+
import_node_fs15 = require("fs");
|
|
5689
|
+
import_node_os6 = require("os");
|
|
5690
|
+
import_node_path16 = require("path");
|
|
5493
5691
|
}
|
|
5494
5692
|
});
|
|
5495
5693
|
|
|
@@ -5592,22 +5790,22 @@ __export(connected_teams_exports, {
|
|
|
5592
5790
|
listConnectedBrightsyTeams: () => listConnectedBrightsyTeams
|
|
5593
5791
|
});
|
|
5594
5792
|
function storePath() {
|
|
5595
|
-
return (0,
|
|
5793
|
+
return (0, import_node_path17.join)(appDataDir(), "brightsy-teams.json");
|
|
5596
5794
|
}
|
|
5597
5795
|
function readStore() {
|
|
5598
5796
|
const path2 = storePath();
|
|
5599
|
-
if (!(0,
|
|
5797
|
+
if (!(0, import_node_fs16.existsSync)(path2)) return [];
|
|
5600
5798
|
try {
|
|
5601
|
-
const parsed = JSON.parse((0,
|
|
5799
|
+
const parsed = JSON.parse((0, import_node_fs16.readFileSync)(path2, "utf8"));
|
|
5602
5800
|
return Array.isArray(parsed.teams) ? parsed.teams : [];
|
|
5603
5801
|
} catch {
|
|
5604
5802
|
return [];
|
|
5605
5803
|
}
|
|
5606
5804
|
}
|
|
5607
5805
|
function writeStore(teams) {
|
|
5608
|
-
(0,
|
|
5806
|
+
(0, import_node_fs16.mkdirSync)(appDataDir(), { recursive: true });
|
|
5609
5807
|
const path2 = storePath();
|
|
5610
|
-
(0,
|
|
5808
|
+
(0, import_node_fs16.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
|
|
5611
5809
|
`, {
|
|
5612
5810
|
mode: 384
|
|
5613
5811
|
});
|
|
@@ -5769,12 +5967,12 @@ function brightsyMcpServerName(slug) {
|
|
|
5769
5967
|
const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
|
|
5770
5968
|
return `brightsy_${cleaned || "team"}`;
|
|
5771
5969
|
}
|
|
5772
|
-
var
|
|
5970
|
+
var import_node_fs16, import_node_path17;
|
|
5773
5971
|
var init_connected_teams = __esm({
|
|
5774
5972
|
"src/brightsy/connected-teams.ts"() {
|
|
5775
5973
|
"use strict";
|
|
5776
|
-
|
|
5777
|
-
|
|
5974
|
+
import_node_fs16 = require("fs");
|
|
5975
|
+
import_node_path17 = require("path");
|
|
5778
5976
|
init_paths();
|
|
5779
5977
|
init_accounts();
|
|
5780
5978
|
init_config();
|
|
@@ -5911,17 +6109,27 @@ function extractJsonErrorMessage(obj) {
|
|
|
5911
6109
|
}
|
|
5912
6110
|
return null;
|
|
5913
6111
|
}
|
|
6112
|
+
function isPinnedStderrLine(line) {
|
|
6113
|
+
if (/^\s*at\s/.test(line)) return false;
|
|
6114
|
+
return /cannot find (?:package|module)|ERR_MODULE_NOT_FOUND|cursor startup failed:/i.test(
|
|
6115
|
+
line
|
|
6116
|
+
);
|
|
6117
|
+
}
|
|
5914
6118
|
function pushTurnStderr(tail, line, maxLines = 12) {
|
|
5915
6119
|
const trimmed = line.trim();
|
|
5916
6120
|
if (!trimmed) return;
|
|
5917
6121
|
if (NODE_VERSION_FOOTER.test(trimmed)) return;
|
|
5918
6122
|
if (/^reconnecting\.\.\./i.test(trimmed)) return;
|
|
5919
6123
|
tail.push(trimmed);
|
|
5920
|
-
while (tail.length > maxLines)
|
|
6124
|
+
while (tail.length > maxLines) {
|
|
6125
|
+
const dropIdx = tail.findIndex((l) => !isPinnedStderrLine(l));
|
|
6126
|
+
if (dropIdx === -1) tail.shift();
|
|
6127
|
+
else tail.splice(dropIdx, 1);
|
|
6128
|
+
}
|
|
5921
6129
|
}
|
|
5922
6130
|
function looksLikeMinifiedJsDump(line) {
|
|
5923
6131
|
if (line.length < 200) return false;
|
|
5924
|
-
return /yield Promise\.all/.test(line) || /\(0,[A-Za-z$]\.\w+\)/.test(line) || /CURSOR_RIPGREP_PATH/.test(line);
|
|
6132
|
+
return /yield Promise\.all/.test(line) || /\(0,[A-Za-z$]\.\w+\)/.test(line) || /CURSOR_RIPGREP_PATH/.test(line) || /findFilesWithRipgrep/.test(line) || /@cursor\/sdk\/dist\//.test(line);
|
|
5925
6133
|
}
|
|
5926
6134
|
function looksLikeNestedElectronCrash(line) {
|
|
5927
6135
|
return /HasCustomHostObject|ElectronInitializeICUandStartNode/i.test(line);
|
|
@@ -5936,7 +6144,15 @@ function summarizeTurnStderr(tail, maxChars = 500) {
|
|
|
5936
6144
|
const cursorStartup = [...tail].reverse().find((line) => /cursor startup failed:/i.test(line));
|
|
5937
6145
|
if (cursorStartup) return clipStderr(cursorStartup, maxChars);
|
|
5938
6146
|
if (tail.some(looksLikeNestedElectronCrash)) return NESTED_ELECTRON_SUMMARY;
|
|
5939
|
-
|
|
6147
|
+
if (tail.some(
|
|
6148
|
+
(line) => /\[resource_exhausted\]|resource_exhausted/i.test(line) || /findFilesWithRipgrep/.test(line)
|
|
6149
|
+
)) {
|
|
6150
|
+
return clipStderr(
|
|
6151
|
+
"Cursor local file search failed (ripgrep / resource_exhausted). Wait a minute and retry; if it keeps happening, check Cursor usage.",
|
|
6152
|
+
maxChars
|
|
6153
|
+
);
|
|
6154
|
+
}
|
|
6155
|
+
const moduleMissing = [...tail].reverse().find((line) => /cannot find (?:package|module)/i.test(line));
|
|
5940
6156
|
if (moduleMissing) return clipStderr(moduleMissing, maxChars);
|
|
5941
6157
|
const useful = tail.filter((line) => !looksLikeMinifiedJsDump(line));
|
|
5942
6158
|
if (useful.length === 0 && tail.some(looksLikeMinifiedJsDump)) {
|
|
@@ -5955,7 +6171,7 @@ function looksLikeAgentFailureMessage(text3) {
|
|
|
5955
6171
|
if (!lower) return false;
|
|
5956
6172
|
return /you've hit your|hit your (session|weekly|opus) limit|usage limit/.test(lower) || /credit balance is too low|out of credits|insufficient.?quota|quota.?exceeded/.test(lower) || /invalid user api key|invalid api key|not logged in|not authenticated|unauthorized/.test(
|
|
5957
6173
|
lower
|
|
5958
|
-
) || /\b429\b|too many requests|rate.?limit/.test(lower) || /prompt is too long|context.*(too long|exceed)|conversation too long/.test(lower);
|
|
6174
|
+
) || /\b429\b|too many requests|rate.?limit/.test(lower) || /prompt is too long|context.*(too long|exceed)|conversation too long/.test(lower) || /\[resource_exhausted\]|resource_exhausted/.test(lower) || /findFilesWithRipgrep/.test(text3);
|
|
5959
6175
|
}
|
|
5960
6176
|
function fallbackTurnFailDetail(assistantText) {
|
|
5961
6177
|
const t = assistantText.trim();
|
|
@@ -5977,6 +6193,9 @@ function humanizeAgentFailDetail(detail) {
|
|
|
5977
6193
|
if (/\b429\b|rate.?limit|too many requests/.test(lower)) {
|
|
5978
6194
|
return `${raw} \u2014 wait a moment and retry.`;
|
|
5979
6195
|
}
|
|
6196
|
+
if (/\[resource_exhausted\]|resource_exhausted|findfileswithripgrep/.test(lower)) {
|
|
6197
|
+
return "Cursor local file search failed (ripgrep / resource_exhausted). Wait a minute and retry; if it keeps happening, check Cursor usage.";
|
|
6198
|
+
}
|
|
5980
6199
|
if (/invalid user api key|invalid api key|not logged in|not authenticated|unauthorized|authentication|please run.*login|codex login|claude auth|cursor api/.test(
|
|
5981
6200
|
lower
|
|
5982
6201
|
)) {
|
|
@@ -6303,11 +6522,11 @@ async function syncCliForTarget(accountId) {
|
|
|
6303
6522
|
}
|
|
6304
6523
|
applyConnectedTeamToCli(team);
|
|
6305
6524
|
}
|
|
6306
|
-
var
|
|
6525
|
+
var import_node_fs17, brightsyAdapter;
|
|
6307
6526
|
var init_brightsy = __esm({
|
|
6308
6527
|
"src/agents/brightsy.ts"() {
|
|
6309
6528
|
"use strict";
|
|
6310
|
-
|
|
6529
|
+
import_node_fs17 = require("fs");
|
|
6311
6530
|
init_run();
|
|
6312
6531
|
init_connected_teams();
|
|
6313
6532
|
init_config();
|
|
@@ -6322,7 +6541,7 @@ var init_brightsy = __esm({
|
|
|
6322
6541
|
async detect() {
|
|
6323
6542
|
const brightsy = resolveAgentExecutable("brightsy");
|
|
6324
6543
|
if (brightsy !== "brightsy") {
|
|
6325
|
-
if (!(0,
|
|
6544
|
+
if (!(0, import_node_fs17.existsSync)(brightsy)) {
|
|
6326
6545
|
return {
|
|
6327
6546
|
agent: "brightsy",
|
|
6328
6547
|
installed: false,
|
|
@@ -6457,13 +6676,38 @@ var init_profile = __esm({
|
|
|
6457
6676
|
|
|
6458
6677
|
// src/agents/node-launch.ts
|
|
6459
6678
|
function isAsarPath(filePath) {
|
|
6679
|
+
if (/\.asar\.unpacked([/\\]|$)/.test(filePath)) return false;
|
|
6460
6680
|
return /\.asar([/\\]|$)/.test(filePath);
|
|
6461
6681
|
}
|
|
6682
|
+
function unpackedAsarPath(filePath) {
|
|
6683
|
+
if (!isAsarPath(filePath)) return null;
|
|
6684
|
+
const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
|
|
6685
|
+
if (unpacked === filePath) return null;
|
|
6686
|
+
return (0, import_node_fs18.existsSync)(unpacked) ? unpacked : null;
|
|
6687
|
+
}
|
|
6688
|
+
function nodeReadableScriptPath(scriptPath) {
|
|
6689
|
+
return unpackedAsarPath(scriptPath) ?? scriptPath;
|
|
6690
|
+
}
|
|
6691
|
+
async function findSystemNode() {
|
|
6692
|
+
const whichNode = await run("which", ["node"], { reject: false });
|
|
6693
|
+
const fromWhich = whichNode.exitCode === 0 && whichNode.stdout.trim() ? whichNode.stdout.trim() : "";
|
|
6694
|
+
if (fromWhich && !isElectronLikeCommand(fromWhich)) return fromWhich;
|
|
6695
|
+
const fallbacks = [
|
|
6696
|
+
...WELL_KNOWN_NODE_BINS,
|
|
6697
|
+
(0, import_node_path18.join)((0, import_node_os7.homedir)(), ".local/share/fnm/aliases/default/bin/node"),
|
|
6698
|
+
(0, import_node_path18.join)((0, import_node_os7.homedir)(), ".nvm/current/bin/node")
|
|
6699
|
+
];
|
|
6700
|
+
for (const bin of fallbacks) {
|
|
6701
|
+
if ((0, import_node_fs18.existsSync)(bin) && !isElectronLikeCommand(bin)) return bin;
|
|
6702
|
+
}
|
|
6703
|
+
return null;
|
|
6704
|
+
}
|
|
6462
6705
|
function applyNodeLaunch(launch, args) {
|
|
6706
|
+
const readableArgs = args.map(nodeReadableScriptPath);
|
|
6463
6707
|
if (!launch.env.ELECTRON_RUN_AS_NODE) {
|
|
6464
|
-
return { file: launch.file, args, env: launch.env };
|
|
6708
|
+
return { file: launch.file, args: readableArgs, env: launch.env };
|
|
6465
6709
|
}
|
|
6466
|
-
const wrapped = wrapElectronAsNodeLaunch(launch.file,
|
|
6710
|
+
const wrapped = wrapElectronAsNodeLaunch(launch.file, readableArgs);
|
|
6467
6711
|
if (process.platform === "win32") {
|
|
6468
6712
|
return { file: wrapped.file, args: wrapped.args, env: launch.env };
|
|
6469
6713
|
}
|
|
@@ -6472,27 +6716,73 @@ function applyNodeLaunch(launch, args) {
|
|
|
6472
6716
|
return { file: wrapped.file, args: wrapped.args, env };
|
|
6473
6717
|
}
|
|
6474
6718
|
async function resolveNodeLaunch(scriptPath) {
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
const whichNode = await run("which", ["node"], { reject: false });
|
|
6482
|
-
const nodeBin = whichNode.exitCode === 0 && whichNode.stdout.trim() ? whichNode.stdout.trim() : null;
|
|
6483
|
-
if (nodeBin) {
|
|
6484
|
-
return { file: nodeBin, env: {} };
|
|
6719
|
+
const script = nodeReadableScriptPath(scriptPath);
|
|
6720
|
+
if (!isAsarPath(script)) {
|
|
6721
|
+
const nodeBin = await findSystemNode();
|
|
6722
|
+
if (nodeBin) {
|
|
6723
|
+
return { file: nodeBin, env: {} };
|
|
6724
|
+
}
|
|
6485
6725
|
}
|
|
6486
6726
|
return {
|
|
6487
6727
|
file: process.execPath,
|
|
6488
6728
|
env: { ELECTRON_RUN_AS_NODE: "1" }
|
|
6489
6729
|
};
|
|
6490
6730
|
}
|
|
6731
|
+
var import_node_fs18, import_node_os7, import_node_path18, WELL_KNOWN_NODE_BINS;
|
|
6491
6732
|
var init_node_launch = __esm({
|
|
6492
6733
|
"src/agents/node-launch.ts"() {
|
|
6493
6734
|
"use strict";
|
|
6735
|
+
import_node_fs18 = require("fs");
|
|
6736
|
+
import_node_os7 = require("os");
|
|
6737
|
+
import_node_path18 = require("path");
|
|
6494
6738
|
init_nested_electron_env();
|
|
6495
6739
|
init_run();
|
|
6740
|
+
WELL_KNOWN_NODE_BINS = [
|
|
6741
|
+
"/opt/homebrew/bin/node",
|
|
6742
|
+
"/usr/local/bin/node"
|
|
6743
|
+
];
|
|
6744
|
+
}
|
|
6745
|
+
});
|
|
6746
|
+
|
|
6747
|
+
// src/agents/packaged-runtime.ts
|
|
6748
|
+
function electronResourcesPath() {
|
|
6749
|
+
const resources = process.resourcesPath;
|
|
6750
|
+
if (typeof resources !== "string" || !resources) return null;
|
|
6751
|
+
return resources;
|
|
6752
|
+
}
|
|
6753
|
+
function packagedCursorRuntimeDir() {
|
|
6754
|
+
const resources = electronResourcesPath();
|
|
6755
|
+
if (!resources) return null;
|
|
6756
|
+
const dir = (0, import_node_path19.join)(resources, "cursor-runtime");
|
|
6757
|
+
if (!(0, import_node_fs19.existsSync)((0, import_node_path19.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
|
|
6758
|
+
return dir;
|
|
6759
|
+
}
|
|
6760
|
+
function packagedCursorRunnerPath() {
|
|
6761
|
+
const dir = packagedCursorRuntimeDir();
|
|
6762
|
+
return dir ? (0, import_node_path19.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
|
|
6763
|
+
}
|
|
6764
|
+
function packagedMcpDir() {
|
|
6765
|
+
const resources = electronResourcesPath();
|
|
6766
|
+
if (!resources) return null;
|
|
6767
|
+
const dir = (0, import_node_path19.join)(resources, "sideboard-mcp");
|
|
6768
|
+
if (!(0, import_node_fs19.existsSync)((0, import_node_path19.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
|
|
6769
|
+
return dir;
|
|
6770
|
+
}
|
|
6771
|
+
function packagedMcpStdioPath() {
|
|
6772
|
+
const dir = packagedMcpDir();
|
|
6773
|
+
return dir ? (0, import_node_path19.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
|
|
6774
|
+
}
|
|
6775
|
+
function packagedCursorRipgrepCandidate(platformPkg, binName) {
|
|
6776
|
+
const dir = packagedCursorRuntimeDir();
|
|
6777
|
+
if (!dir) return null;
|
|
6778
|
+
return (0, import_node_path19.join)(dir, "node_modules", platformPkg, "bin", binName);
|
|
6779
|
+
}
|
|
6780
|
+
var import_node_fs19, import_node_path19;
|
|
6781
|
+
var init_packaged_runtime = __esm({
|
|
6782
|
+
"src/agents/packaged-runtime.ts"() {
|
|
6783
|
+
"use strict";
|
|
6784
|
+
import_node_fs19 = require("fs");
|
|
6785
|
+
import_node_path19 = require("path");
|
|
6496
6786
|
}
|
|
6497
6787
|
});
|
|
6498
6788
|
|
|
@@ -6579,35 +6869,37 @@ function corePackageDir() {
|
|
|
6579
6869
|
try {
|
|
6580
6870
|
const url = import_meta.url;
|
|
6581
6871
|
if (typeof url === "string" && url.length > 0) {
|
|
6582
|
-
return (0,
|
|
6872
|
+
return (0, import_node_path20.dirname)((0, import_node_url.fileURLToPath)(url));
|
|
6583
6873
|
}
|
|
6584
6874
|
} catch {
|
|
6585
6875
|
}
|
|
6586
6876
|
try {
|
|
6587
|
-
const req = (0, import_node_module.createRequire)((0,
|
|
6588
|
-
return (0,
|
|
6877
|
+
const req = (0, import_node_module.createRequire)((0, import_node_path20.join)(process.cwd(), "package.json"));
|
|
6878
|
+
return (0, import_node_path20.dirname)(req.resolve("@sideboard-ai/core"));
|
|
6589
6879
|
} catch {
|
|
6590
6880
|
return process.cwd();
|
|
6591
6881
|
}
|
|
6592
6882
|
}
|
|
6593
6883
|
function findSideboardMcpJsEntry() {
|
|
6594
6884
|
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
6595
|
-
if (override && (0,
|
|
6885
|
+
if (override && (0, import_node_fs20.existsSync)(override)) return override;
|
|
6886
|
+
const packaged = packagedMcpStdioPath();
|
|
6887
|
+
if (packaged) return packaged;
|
|
6596
6888
|
let dir = corePackageDir();
|
|
6597
6889
|
for (let i = 0; i < 10; i++) {
|
|
6598
6890
|
const candidates = [
|
|
6599
|
-
(0,
|
|
6600
|
-
(0,
|
|
6601
|
-
(0,
|
|
6602
|
-
(0,
|
|
6603
|
-
(0,
|
|
6604
|
-
(0,
|
|
6605
|
-
(0,
|
|
6891
|
+
(0, import_node_path20.join)(dir, "mcp/run-stdio.js"),
|
|
6892
|
+
(0, import_node_path20.join)(dir, "mcp/run-stdio.cjs"),
|
|
6893
|
+
(0, import_node_path20.join)(dir, "dist/mcp/run-stdio.js"),
|
|
6894
|
+
(0, import_node_path20.join)(dir, "dist/mcp/run-stdio.cjs"),
|
|
6895
|
+
(0, import_node_path20.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
|
|
6896
|
+
(0, import_node_path20.join)(dir, "packages/cli/dist/index.js"),
|
|
6897
|
+
(0, import_node_path20.join)(dir, "cli/dist/index.js")
|
|
6606
6898
|
];
|
|
6607
6899
|
for (const p of candidates) {
|
|
6608
|
-
if ((0,
|
|
6900
|
+
if ((0, import_node_fs20.existsSync)(p) && !isAsarPath(p)) return p;
|
|
6609
6901
|
}
|
|
6610
|
-
const parent = (0,
|
|
6902
|
+
const parent = (0, import_node_path20.dirname)(dir);
|
|
6611
6903
|
if (parent === dir) break;
|
|
6612
6904
|
dir = parent;
|
|
6613
6905
|
}
|
|
@@ -6619,12 +6911,14 @@ async function resolveSideboardMcpServer() {
|
|
|
6619
6911
|
const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
|
|
6620
6912
|
const scriptArgs = isCli ? [entry, "mcp"] : [entry];
|
|
6621
6913
|
const launch = applyNodeLaunch(await resolveNodeLaunch(entry), scriptArgs);
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6914
|
+
if (launch.file !== "/bin/sh" && !isElectronLikeCommand(launch.file)) {
|
|
6915
|
+
return {
|
|
6916
|
+
name: "sideboard",
|
|
6917
|
+
command: launch.file,
|
|
6918
|
+
args: launch.args,
|
|
6919
|
+
...Object.keys(launch.env).length > 0 ? { env: launch.env } : {}
|
|
6920
|
+
};
|
|
6921
|
+
}
|
|
6628
6922
|
}
|
|
6629
6923
|
const which = await run("which", ["sideboard"], { reject: false });
|
|
6630
6924
|
if (which.exitCode === 0 && which.stdout.trim()) {
|
|
@@ -6647,7 +6941,10 @@ async function buildInjectedMcpServers(opts) {
|
|
|
6647
6941
|
sideboard.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID = orchId;
|
|
6648
6942
|
}
|
|
6649
6943
|
try {
|
|
6650
|
-
|
|
6944
|
+
mergeAgentGitAuthEnv(
|
|
6945
|
+
sideboard.env,
|
|
6946
|
+
await resolveAgentGitAuthEnv(sideboard.env)
|
|
6947
|
+
);
|
|
6651
6948
|
} catch {
|
|
6652
6949
|
}
|
|
6653
6950
|
servers.push(sideboard);
|
|
@@ -6669,9 +6966,6 @@ async function buildInjectedMcpServers(opts) {
|
|
|
6669
6966
|
}
|
|
6670
6967
|
return servers;
|
|
6671
6968
|
}
|
|
6672
|
-
function shSingleQuote(value) {
|
|
6673
|
-
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
6674
|
-
}
|
|
6675
6969
|
function cursorSafeMcpLaunch(command, args) {
|
|
6676
6970
|
if (process.platform === "win32") {
|
|
6677
6971
|
return args && args.length > 0 ? { command, args } : { command };
|
|
@@ -6679,31 +6973,13 @@ function cursorSafeMcpLaunch(command, args) {
|
|
|
6679
6973
|
const unwrapped = unwrapStrippedElectronLaunch(command, args);
|
|
6680
6974
|
const file = unwrapped?.file ?? command;
|
|
6681
6975
|
const fileArgs = unwrapped?.args ?? args ?? [];
|
|
6682
|
-
|
|
6683
|
-
return fileArgs.length > 0 ? { command: file, args: fileArgs } : { command: file };
|
|
6684
|
-
}
|
|
6685
|
-
const dir = (0, import_node_path16.join)(appDataDir(), "mcp-launch");
|
|
6686
|
-
(0, import_node_fs17.mkdirSync)(dir, { recursive: true });
|
|
6687
|
-
const wrap = (0, import_node_path16.join)(dir, "cursor-electron-as-node.sh");
|
|
6688
|
-
const execLine = [file, ...fileArgs].map(shSingleQuote).join(" ");
|
|
6689
|
-
(0, import_node_fs17.writeFileSync)(
|
|
6690
|
-
wrap,
|
|
6691
|
-
[
|
|
6692
|
-
"#!/bin/sh",
|
|
6693
|
-
"vars=`printenv | awk -F= '/^(ELECTRON_|CHROME_)/{print $1}'`",
|
|
6694
|
-
'[ -n "$vars" ] && unset $vars',
|
|
6695
|
-
"export ELECTRON_RUN_AS_NODE=1",
|
|
6696
|
-
`exec ${execLine} "$@"`,
|
|
6697
|
-
""
|
|
6698
|
-
].join("\n"),
|
|
6699
|
-
{ mode: 493 }
|
|
6700
|
-
);
|
|
6701
|
-
return { command: wrap };
|
|
6976
|
+
return fileArgs.length > 0 ? { command: file, args: fileArgs } : { command: file };
|
|
6702
6977
|
}
|
|
6703
6978
|
function mcpSpawnEnv(env) {
|
|
6704
6979
|
if (!env) return void 0;
|
|
6705
6980
|
const out = { ...env };
|
|
6706
6981
|
delete out.ELECTRON_RUN_AS_NODE;
|
|
6982
|
+
delete out.ELECTRON_RUN_AS_NODE;
|
|
6707
6983
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
6708
6984
|
}
|
|
6709
6985
|
function toCursorMcpServers(servers) {
|
|
@@ -6763,22 +7039,22 @@ function writeMcpServersConfig(servers) {
|
|
|
6763
7039
|
...env ? { env } : {}
|
|
6764
7040
|
};
|
|
6765
7041
|
}
|
|
6766
|
-
const dir = (0,
|
|
6767
|
-
const cfgPath = (0,
|
|
6768
|
-
(0,
|
|
7042
|
+
const dir = (0, import_node_fs20.mkdtempSync)((0, import_node_path20.join)((0, import_node_os8.tmpdir)(), "sideboard-mcp-"));
|
|
7043
|
+
const cfgPath = (0, import_node_path20.join)(dir, "mcp.json");
|
|
7044
|
+
(0, import_node_fs20.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
|
|
6769
7045
|
return cfgPath;
|
|
6770
7046
|
}
|
|
6771
7047
|
async function writeInjectedMcpConfig(opts) {
|
|
6772
7048
|
return writeMcpServersConfig(await buildInjectedMcpServers(opts));
|
|
6773
7049
|
}
|
|
6774
|
-
var
|
|
7050
|
+
var import_node_fs20, import_node_module, import_node_os8, import_node_path20, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
|
|
6775
7051
|
var init_injected_mcp = __esm({
|
|
6776
7052
|
"src/agents/injected-mcp.ts"() {
|
|
6777
7053
|
"use strict";
|
|
6778
|
-
|
|
7054
|
+
import_node_fs20 = require("fs");
|
|
6779
7055
|
import_node_module = require("module");
|
|
6780
|
-
|
|
6781
|
-
|
|
7056
|
+
import_node_os8 = require("os");
|
|
7057
|
+
import_node_path20 = require("path");
|
|
6782
7058
|
import_node_url = require("url");
|
|
6783
7059
|
init_run();
|
|
6784
7060
|
init_config();
|
|
@@ -6787,6 +7063,7 @@ var init_injected_mcp = __esm({
|
|
|
6787
7063
|
init_app_settings();
|
|
6788
7064
|
init_paths();
|
|
6789
7065
|
init_node_launch();
|
|
7066
|
+
init_packaged_runtime();
|
|
6790
7067
|
init_nested_electron_env();
|
|
6791
7068
|
init_git_auth_mode();
|
|
6792
7069
|
import_meta = {};
|
|
@@ -6860,7 +7137,7 @@ var PLAN_MODE_INSTRUCTION;
|
|
|
6860
7137
|
var init_types = __esm({
|
|
6861
7138
|
"src/agents/types.ts"() {
|
|
6862
7139
|
"use strict";
|
|
6863
|
-
PLAN_MODE_INSTRUCTION = "Plan mode is active and must remain active until the user turns Plan mode off in the UI (or Approves / Hands off the plan). Analyze the codebase, search and read files as needed, and produce or refine a clear implementation plan. Do not modify, create, or delete any project files except via Sideboard MCP present_plan (writes .context/attachments/plan.md). When you need a clarifying decision (approach forks, auth choice, scope): (1) first write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it) \u2014 do not leave the user staring at bare labels; (2) then call Sideboard MCP ask_user with the same options, including a description on every option. Sideboard shows questions in the composer and mirrors them in chat. After ask_user, wait for the user's next message with their answers before finalizing the plan. When the plan is ready for approval: (1) call present_plan with the full markdown plan (title + content) so Sideboard saves .context/attachments/plan.md and shows it in chat for Approve / Hand off / Copy; (2) Claude should also call ExitPlanMode after present_plan. Do not skip present_plan \u2014 the plan must be a markdown file, not only chat prose.";
|
|
7140
|
+
PLAN_MODE_INSTRUCTION = "Plan mode is active and must remain active until the user turns Plan mode off in the UI (or Approves / Hands off the plan). Analyze the codebase, search and read files as needed, and produce or refine a clear implementation plan. Do not modify, create, or delete any project files except via Sideboard MCP present_plan (writes .context/attachments/plan.md). When you need a clarifying decision (approach forks, auth choice, scope) \u2014 not greetings, check-ins, or an invented task menu: (1) first write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it) \u2014 do not leave the user staring at bare labels; (2) then call Sideboard MCP ask_user with the same options, including a description on every option. If one option is the obvious default, proceed without asking. Sideboard shows questions in the composer and mirrors them in chat. After ask_user, wait for the user's next message with their answers before finalizing the plan. When the plan is ready for approval: (1) call present_plan with the full markdown plan (title + content) so Sideboard saves .context/attachments/plan.md and shows it in chat for Approve / Hand off / Copy; (2) Claude should also call ExitPlanMode after present_plan. Do not skip present_plan \u2014 the plan must be a markdown file, not only chat prose.";
|
|
6864
7141
|
}
|
|
6865
7142
|
});
|
|
6866
7143
|
|
|
@@ -6970,11 +7247,11 @@ function parseIssuesJson(raw) {
|
|
|
6970
7247
|
}
|
|
6971
7248
|
return [];
|
|
6972
7249
|
}
|
|
6973
|
-
var
|
|
7250
|
+
var import_node_fs21, BASE_ALLOWED_TOOLS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
|
|
6974
7251
|
var init_claude = __esm({
|
|
6975
7252
|
"src/agents/claude.ts"() {
|
|
6976
7253
|
"use strict";
|
|
6977
|
-
|
|
7254
|
+
import_node_fs21 = require("fs");
|
|
6978
7255
|
init_run();
|
|
6979
7256
|
init_app_settings();
|
|
6980
7257
|
init_claude_mcp();
|
|
@@ -7003,7 +7280,7 @@ var init_claude = __esm({
|
|
|
7003
7280
|
async detect() {
|
|
7004
7281
|
const claude = resolveClaudeExecutable();
|
|
7005
7282
|
if (claude !== "claude") {
|
|
7006
|
-
if (!(0,
|
|
7283
|
+
if (!(0, import_node_fs21.existsSync)(claude)) {
|
|
7007
7284
|
return {
|
|
7008
7285
|
agent: "claude",
|
|
7009
7286
|
installed: false,
|
|
@@ -7240,7 +7517,7 @@ async function listCodexModels() {
|
|
|
7240
7517
|
if (codex === "codex") {
|
|
7241
7518
|
const which = await run("which", ["codex"], { reject: false });
|
|
7242
7519
|
if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
|
|
7243
|
-
} else if (!(0,
|
|
7520
|
+
} else if (!(0, import_node_fs22.existsSync)(codex)) {
|
|
7244
7521
|
return FALLBACK_CODEX_MODELS;
|
|
7245
7522
|
}
|
|
7246
7523
|
const listed = await run(codex, ["debug", "models"], { reject: false });
|
|
@@ -7275,12 +7552,12 @@ function usageFromCodex(usage) {
|
|
|
7275
7552
|
}
|
|
7276
7553
|
function codexConfigHasNetworkAccess() {
|
|
7277
7554
|
const candidates = [
|
|
7278
|
-
(0,
|
|
7279
|
-
(0,
|
|
7555
|
+
(0, import_node_path21.join)((0, import_node_os9.homedir)(), ".codex", "config.toml"),
|
|
7556
|
+
(0, import_node_path21.join)((0, import_node_os9.homedir)(), ".config", "codex", "config.toml")
|
|
7280
7557
|
];
|
|
7281
7558
|
for (const path2 of candidates) {
|
|
7282
|
-
if (!(0,
|
|
7283
|
-
const text3 = (0,
|
|
7559
|
+
if (!(0, import_node_fs22.existsSync)(path2)) continue;
|
|
7560
|
+
const text3 = (0, import_node_fs22.readFileSync)(path2, "utf8");
|
|
7284
7561
|
if (/network_access\s*=\s*true/.test(text3)) return true;
|
|
7285
7562
|
}
|
|
7286
7563
|
return false;
|
|
@@ -7312,21 +7589,21 @@ function asRecord(value) {
|
|
|
7312
7589
|
return void 0;
|
|
7313
7590
|
}
|
|
7314
7591
|
function codexLooksAuthenticated() {
|
|
7315
|
-
const authPath = (0,
|
|
7316
|
-
if (!(0,
|
|
7592
|
+
const authPath = (0, import_node_path21.join)((0, import_node_os9.homedir)(), ".codex", "auth.json");
|
|
7593
|
+
if (!(0, import_node_fs22.existsSync)(authPath)) return false;
|
|
7317
7594
|
try {
|
|
7318
|
-
return (0,
|
|
7595
|
+
return (0, import_node_fs22.statSync)(authPath).size > 2;
|
|
7319
7596
|
} catch {
|
|
7320
7597
|
return false;
|
|
7321
7598
|
}
|
|
7322
7599
|
}
|
|
7323
|
-
var
|
|
7600
|
+
var import_node_fs22, import_node_os9, import_node_path21, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
|
|
7324
7601
|
var init_codex = __esm({
|
|
7325
7602
|
"src/agents/codex.ts"() {
|
|
7326
7603
|
"use strict";
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7604
|
+
import_node_fs22 = require("fs");
|
|
7605
|
+
import_node_os9 = require("os");
|
|
7606
|
+
import_node_path21 = require("path");
|
|
7330
7607
|
init_run();
|
|
7331
7608
|
init_app_settings();
|
|
7332
7609
|
init_global_workspace();
|
|
@@ -7351,7 +7628,7 @@ var init_codex = __esm({
|
|
|
7351
7628
|
async detect() {
|
|
7352
7629
|
const codex = resolveAgentExecutable("codex");
|
|
7353
7630
|
if (codex !== "codex") {
|
|
7354
|
-
if (!(0,
|
|
7631
|
+
if (!(0, import_node_fs22.existsSync)(codex)) {
|
|
7355
7632
|
return {
|
|
7356
7633
|
agent: "codex",
|
|
7357
7634
|
installed: false,
|
|
@@ -7424,8 +7701,13 @@ var init_codex = __esm({
|
|
|
7424
7701
|
// `codex exec` rejects `--ask-for-approval` (global-only on newer CLIs).
|
|
7425
7702
|
"-c",
|
|
7426
7703
|
'approval_policy="never"',
|
|
7427
|
-
// Seatbelt cannot use the login Keychain;
|
|
7428
|
-
|
|
7704
|
+
// Seatbelt cannot use the login Keychain; inherit GH_CONFIG_DIR / GIT_CONFIG_*.
|
|
7705
|
+
// Default policy also strips *TOKEN*. Linked worktrees need the main
|
|
7706
|
+
// repo `.git` (+ `.git/worktrees/<name>`) as writable_roots so git commit
|
|
7707
|
+
// can create index.lock.
|
|
7708
|
+
...codexUnattendedGitConfigArgs(mode.codexSandbox, {
|
|
7709
|
+
writableRoots: mode.codexSandbox === "workspace-write" ? await resolveCodexGitWritableRoots(thread.worktreePath) : []
|
|
7710
|
+
}),
|
|
7429
7711
|
...model ? ["--model", model] : [],
|
|
7430
7712
|
...mcpOverrides
|
|
7431
7713
|
];
|
|
@@ -7746,6 +8028,74 @@ var init_cursor_events = __esm({
|
|
|
7746
8028
|
}
|
|
7747
8029
|
});
|
|
7748
8030
|
|
|
8031
|
+
// src/agents/cursor-ripgrep.ts
|
|
8032
|
+
function rgBinaryName() {
|
|
8033
|
+
return process.platform === "win32" ? "rg.exe" : "rg";
|
|
8034
|
+
}
|
|
8035
|
+
function platformRipgrepPackage() {
|
|
8036
|
+
return `@cursor/sdk-${process.platform}-${process.arch}`;
|
|
8037
|
+
}
|
|
8038
|
+
function usableRipgrepPath(candidate) {
|
|
8039
|
+
const raw = candidate?.trim();
|
|
8040
|
+
if (!raw || !(0, import_node_path22.isAbsolute)(raw)) return null;
|
|
8041
|
+
const readable = nodeReadableScriptPath(raw);
|
|
8042
|
+
if (!(0, import_node_fs23.existsSync)(readable) || isAsarPath(readable)) return null;
|
|
8043
|
+
return readable;
|
|
8044
|
+
}
|
|
8045
|
+
function walkForBundledRipgrep(startFile) {
|
|
8046
|
+
if (!startFile) return null;
|
|
8047
|
+
const pkg = platformRipgrepPackage();
|
|
8048
|
+
const name = rgBinaryName();
|
|
8049
|
+
let dir = (0, import_node_path22.dirname)((0, import_node_path22.resolve)(startFile));
|
|
8050
|
+
const root = (0, import_node_path22.parse)(dir).root;
|
|
8051
|
+
while (dir !== root) {
|
|
8052
|
+
const hit = usableRipgrepPath((0, import_node_path22.join)(dir, "node_modules", pkg, "bin", name));
|
|
8053
|
+
if (hit) return hit;
|
|
8054
|
+
const next = (0, import_node_path22.dirname)(dir);
|
|
8055
|
+
if (next === dir) break;
|
|
8056
|
+
dir = next;
|
|
8057
|
+
}
|
|
8058
|
+
return null;
|
|
8059
|
+
}
|
|
8060
|
+
function requireResolveBundledRipgrep(fromFile) {
|
|
8061
|
+
try {
|
|
8062
|
+
const req = (0, import_node_module2.createRequire)(fromFile);
|
|
8063
|
+
const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
|
|
8064
|
+
return usableRipgrepPath((0, import_node_path22.join)((0, import_node_path22.dirname)(pkgJson), "bin", rgBinaryName()));
|
|
8065
|
+
} catch {
|
|
8066
|
+
return null;
|
|
8067
|
+
}
|
|
8068
|
+
}
|
|
8069
|
+
function resolveCursorRipgrepPath(opts) {
|
|
8070
|
+
const env = opts?.env ?? process.env;
|
|
8071
|
+
const fromEnv = usableRipgrepPath(env[RIPGREP_ENV]);
|
|
8072
|
+
if (fromEnv) return fromEnv;
|
|
8073
|
+
const fromPackaged = usableRipgrepPath(
|
|
8074
|
+
packagedCursorRipgrepCandidate(platformRipgrepPackage(), rgBinaryName())
|
|
8075
|
+
);
|
|
8076
|
+
if (fromPackaged) return fromPackaged;
|
|
8077
|
+
const start = opts?.startFile?.trim() || process.argv[1] || (0, import_node_url2.fileURLToPath)(import_meta2.url);
|
|
8078
|
+
return walkForBundledRipgrep(start) ?? requireResolveBundledRipgrep(start);
|
|
8079
|
+
}
|
|
8080
|
+
function cursorRipgrepEnv(opts) {
|
|
8081
|
+
const path2 = resolveCursorRipgrepPath(opts);
|
|
8082
|
+
return path2 ? { [RIPGREP_ENV]: path2 } : {};
|
|
8083
|
+
}
|
|
8084
|
+
var import_node_fs23, import_node_module2, import_node_path22, import_node_url2, import_meta2, RIPGREP_ENV;
|
|
8085
|
+
var init_cursor_ripgrep = __esm({
|
|
8086
|
+
"src/agents/cursor-ripgrep.ts"() {
|
|
8087
|
+
"use strict";
|
|
8088
|
+
import_node_fs23 = require("fs");
|
|
8089
|
+
import_node_module2 = require("module");
|
|
8090
|
+
import_node_path22 = require("path");
|
|
8091
|
+
import_node_url2 = require("url");
|
|
8092
|
+
init_node_launch();
|
|
8093
|
+
init_packaged_runtime();
|
|
8094
|
+
import_meta2 = {};
|
|
8095
|
+
RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
|
|
8096
|
+
}
|
|
8097
|
+
});
|
|
8098
|
+
|
|
7749
8099
|
// src/agents/cursor.ts
|
|
7750
8100
|
function resolveCursorApiKey() {
|
|
7751
8101
|
const fromEnv = (process.env.CURSOR_API_KEY || "").trim();
|
|
@@ -7785,51 +8135,55 @@ function entryDir() {
|
|
|
7785
8135
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
7786
8136
|
if (cjsDir) return cjsDir;
|
|
7787
8137
|
try {
|
|
7788
|
-
return (0,
|
|
8138
|
+
return (0, import_node_path23.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
|
|
7789
8139
|
} catch {
|
|
7790
8140
|
try {
|
|
7791
|
-
const req = (0,
|
|
7792
|
-
return (0,
|
|
8141
|
+
const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
|
|
8142
|
+
return (0, import_node_path23.dirname)(req.resolve("@sideboard-ai/core"));
|
|
7793
8143
|
} catch {
|
|
7794
8144
|
return process.cwd();
|
|
7795
8145
|
}
|
|
7796
8146
|
}
|
|
7797
8147
|
}
|
|
7798
8148
|
function cursorRunnerPath() {
|
|
8149
|
+
const packaged = packagedCursorRunnerPath();
|
|
8150
|
+
if (packaged) return packaged;
|
|
7799
8151
|
const root = entryDir();
|
|
7800
8152
|
const candidates = [
|
|
7801
|
-
(0,
|
|
7802
|
-
(0,
|
|
8153
|
+
(0, import_node_path23.join)(root, "agents", "cursor-runner.js"),
|
|
8154
|
+
(0, import_node_path23.join)(root, "agents", "cursor-runner.cjs"),
|
|
7803
8155
|
// If somehow resolved from package root instead of dist/
|
|
7804
|
-
(0,
|
|
7805
|
-
(0,
|
|
8156
|
+
(0, import_node_path23.join)(root, "dist", "agents", "cursor-runner.js"),
|
|
8157
|
+
(0, import_node_path23.join)(root, "dist", "agents", "cursor-runner.cjs"),
|
|
7806
8158
|
// Source tree (dev): packages/core/src/agents/cursor-runner.ts
|
|
7807
|
-
(0,
|
|
7808
|
-
(0,
|
|
8159
|
+
(0, import_node_path23.join)(root, "cursor-runner.ts"),
|
|
8160
|
+
(0, import_node_path23.join)(root, "src", "agents", "cursor-runner.ts")
|
|
7809
8161
|
];
|
|
7810
8162
|
for (const candidate of candidates) {
|
|
7811
|
-
if ((0,
|
|
8163
|
+
if ((0, import_node_fs24.existsSync)(candidate)) return candidate;
|
|
7812
8164
|
}
|
|
7813
8165
|
return candidates[0];
|
|
7814
8166
|
}
|
|
7815
|
-
var
|
|
8167
|
+
var import_node_fs24, import_node_module3, import_node_path23, import_node_url3, import_sdk, import_meta3, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
|
|
7816
8168
|
var init_cursor = __esm({
|
|
7817
8169
|
"src/agents/cursor.ts"() {
|
|
7818
8170
|
"use strict";
|
|
7819
|
-
|
|
7820
|
-
|
|
7821
|
-
|
|
7822
|
-
|
|
8171
|
+
import_node_fs24 = require("fs");
|
|
8172
|
+
import_node_module3 = require("module");
|
|
8173
|
+
import_node_path23 = require("path");
|
|
8174
|
+
import_node_url3 = require("url");
|
|
7823
8175
|
import_sdk = require("@cursor/sdk");
|
|
7824
8176
|
init_run();
|
|
7825
8177
|
init_app_settings();
|
|
7826
8178
|
init_global_workspace();
|
|
7827
8179
|
init_cursor_events();
|
|
7828
8180
|
init_injected_mcp();
|
|
8181
|
+
init_cursor_ripgrep();
|
|
7829
8182
|
init_node_launch();
|
|
8183
|
+
init_packaged_runtime();
|
|
7830
8184
|
init_turn_input();
|
|
7831
8185
|
init_cursor_events();
|
|
7832
|
-
|
|
8186
|
+
import_meta3 = {};
|
|
7833
8187
|
FALLBACK_CURSOR_MODELS = [
|
|
7834
8188
|
{ id: "default", displayName: "Auto" },
|
|
7835
8189
|
{ id: "composer-2.5", displayName: "Composer 2.5" },
|
|
@@ -7896,6 +8250,7 @@ var init_cursor = __esm({
|
|
|
7896
8250
|
stdin: JSON.stringify(req),
|
|
7897
8251
|
env: {
|
|
7898
8252
|
...launch.env,
|
|
8253
|
+
...cursorRipgrepEnv({ startFile: runner }),
|
|
7899
8254
|
...apiKey ? { CURSOR_API_KEY: apiKey } : {}
|
|
7900
8255
|
}
|
|
7901
8256
|
};
|
|
@@ -7947,7 +8302,7 @@ async function listOpencodeModels() {
|
|
|
7947
8302
|
if (opencode === "opencode") {
|
|
7948
8303
|
const which = await run("which", ["opencode"], { reject: false });
|
|
7949
8304
|
if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
|
|
7950
|
-
} else if (!(0,
|
|
8305
|
+
} else if (!(0, import_node_fs25.existsSync)(opencode)) {
|
|
7951
8306
|
return FALLBACK_OPENCODE_MODELS;
|
|
7952
8307
|
}
|
|
7953
8308
|
const listed = await run(opencode, ["models"], { reject: false });
|
|
@@ -7977,11 +8332,11 @@ function usageFromOpencode(tokens) {
|
|
|
7977
8332
|
cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
|
|
7978
8333
|
};
|
|
7979
8334
|
}
|
|
7980
|
-
var
|
|
8335
|
+
var import_node_fs25, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
|
|
7981
8336
|
var init_opencode = __esm({
|
|
7982
8337
|
"src/agents/opencode.ts"() {
|
|
7983
8338
|
"use strict";
|
|
7984
|
-
|
|
8339
|
+
import_node_fs25 = require("fs");
|
|
7985
8340
|
init_run();
|
|
7986
8341
|
init_app_settings();
|
|
7987
8342
|
init_global_workspace();
|
|
@@ -8007,7 +8362,7 @@ var init_opencode = __esm({
|
|
|
8007
8362
|
async detect() {
|
|
8008
8363
|
const opencode = resolveAgentExecutable("opencode");
|
|
8009
8364
|
if (opencode !== "opencode") {
|
|
8010
|
-
if (!(0,
|
|
8365
|
+
if (!(0, import_node_fs25.existsSync)(opencode)) {
|
|
8011
8366
|
return {
|
|
8012
8367
|
agent: "opencode",
|
|
8013
8368
|
installed: false,
|
|
@@ -8804,40 +9159,40 @@ __export(plan_file_exports, {
|
|
|
8804
9159
|
writePlanFile: () => writePlanFile
|
|
8805
9160
|
});
|
|
8806
9161
|
function ensureAttachmentsGitignore2(worktreePath) {
|
|
8807
|
-
const gitignoreAbs = (0,
|
|
8808
|
-
if ((0,
|
|
8809
|
-
(0,
|
|
8810
|
-
(0,
|
|
9162
|
+
const gitignoreAbs = (0, import_node_path36.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
9163
|
+
if ((0, import_node_fs39.existsSync)(gitignoreAbs)) return;
|
|
9164
|
+
(0, import_node_fs39.mkdirSync)((0, import_node_path36.dirname)(gitignoreAbs), { recursive: true });
|
|
9165
|
+
(0, import_node_fs39.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
8811
9166
|
}
|
|
8812
9167
|
function planFileAbs(worktreePath) {
|
|
8813
|
-
return (0,
|
|
9168
|
+
return (0, import_node_path36.join)(worktreePath, PLAN_FILE_REL);
|
|
8814
9169
|
}
|
|
8815
9170
|
function readTextIfPresent2(abs) {
|
|
8816
|
-
if (!(0,
|
|
9171
|
+
if (!(0, import_node_fs39.existsSync)(abs)) return null;
|
|
8817
9172
|
try {
|
|
8818
|
-
const content = (0,
|
|
9173
|
+
const content = (0, import_node_fs39.readFileSync)(abs, "utf8");
|
|
8819
9174
|
return content.trim() ? content : null;
|
|
8820
9175
|
} catch {
|
|
8821
9176
|
return null;
|
|
8822
9177
|
}
|
|
8823
9178
|
}
|
|
8824
9179
|
function readPlanFile(worktreePath) {
|
|
8825
|
-
return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0,
|
|
9180
|
+
return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path36.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path36.join)(worktreePath, LEGACY_PLAN_FILE_REL));
|
|
8826
9181
|
}
|
|
8827
9182
|
function writePlanFile(worktreePath, content) {
|
|
8828
9183
|
ensureAttachmentsGitignore2(worktreePath);
|
|
8829
9184
|
const abs = planFileAbs(worktreePath);
|
|
8830
|
-
(0,
|
|
9185
|
+
(0, import_node_fs39.mkdirSync)((0, import_node_path36.dirname)(abs), { recursive: true });
|
|
8831
9186
|
const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
|
|
8832
|
-
(0,
|
|
9187
|
+
(0, import_node_fs39.writeFileSync)(abs, body, "utf8");
|
|
8833
9188
|
return PLAN_FILE_REL;
|
|
8834
9189
|
}
|
|
8835
|
-
var
|
|
9190
|
+
var import_node_fs39, import_node_path36;
|
|
8836
9191
|
var init_plan_file = __esm({
|
|
8837
9192
|
"src/plan/plan-file.ts"() {
|
|
8838
9193
|
"use strict";
|
|
8839
|
-
|
|
8840
|
-
|
|
9194
|
+
import_node_fs39 = require("fs");
|
|
9195
|
+
import_node_path36 = require("path");
|
|
8841
9196
|
init_workspace_scratch();
|
|
8842
9197
|
init_plan_present();
|
|
8843
9198
|
init_plan_present();
|
|
@@ -8852,10 +9207,10 @@ __export(cursor_recover_exports, {
|
|
|
8852
9207
|
function recoverFinishedCursorRun(opts) {
|
|
8853
9208
|
const agentId = opts.agentId.trim();
|
|
8854
9209
|
if (!agentId) return null;
|
|
8855
|
-
const runsPath = (0,
|
|
8856
|
-
if (!(0,
|
|
9210
|
+
const runsPath = (0, import_node_path37.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
|
|
9211
|
+
if (!(0, import_node_fs40.existsSync)(runsPath)) return null;
|
|
8857
9212
|
try {
|
|
8858
|
-
const lines = (0,
|
|
9213
|
+
const lines = (0, import_node_fs40.readFileSync)(runsPath, "utf8").split("\n");
|
|
8859
9214
|
let best = null;
|
|
8860
9215
|
for (const line of lines) {
|
|
8861
9216
|
const trimmed = line.trim();
|
|
@@ -8881,12 +9236,12 @@ function recoverFinishedCursorRun(opts) {
|
|
|
8881
9236
|
return null;
|
|
8882
9237
|
}
|
|
8883
9238
|
}
|
|
8884
|
-
var
|
|
9239
|
+
var import_node_fs40, import_node_path37;
|
|
8885
9240
|
var init_cursor_recover = __esm({
|
|
8886
9241
|
"src/agents/cursor-recover.ts"() {
|
|
8887
9242
|
"use strict";
|
|
8888
|
-
|
|
8889
|
-
|
|
9243
|
+
import_node_fs40 = require("fs");
|
|
9244
|
+
import_node_path37 = require("path");
|
|
8890
9245
|
init_paths();
|
|
8891
9246
|
}
|
|
8892
9247
|
});
|
|
@@ -9040,6 +9395,7 @@ __export(index_exports, {
|
|
|
9040
9395
|
cleanupOrphanWorktrees: () => cleanupOrphanWorktrees,
|
|
9041
9396
|
cloneRepoIntoSideboard: () => cloneRepoIntoSideboard,
|
|
9042
9397
|
codexAdapter: () => codexAdapter,
|
|
9398
|
+
codexSandboxWritableRootsArgs: () => codexSandboxWritableRootsArgs,
|
|
9043
9399
|
codexUnattendedGitConfigArgs: () => codexUnattendedGitConfigArgs,
|
|
9044
9400
|
coerceOrchestratorAgent: () => coerceOrchestratorAgent,
|
|
9045
9401
|
collectTakenTeamSlugs: () => collectTakenTeamSlugs,
|
|
@@ -9156,6 +9512,7 @@ __export(index_exports, {
|
|
|
9156
9512
|
getPr: () => getPr,
|
|
9157
9513
|
getPrChecks: () => getPrChecks,
|
|
9158
9514
|
getPrDetails: () => getPrDetails,
|
|
9515
|
+
getPrForHeadBranch: () => getPrForHeadBranch,
|
|
9159
9516
|
getPrMeta: () => getPrMeta,
|
|
9160
9517
|
getPrStack: () => getPrStack,
|
|
9161
9518
|
getRepoSetupInfo: () => getRepoSetupInfo,
|
|
@@ -9192,6 +9549,7 @@ __export(index_exports, {
|
|
|
9192
9549
|
isCloudCoordinatorThread: () => isCloudCoordinatorThread,
|
|
9193
9550
|
isConductorBundledCli: () => isConductorBundledCli,
|
|
9194
9551
|
isCursorAutoModel: () => isCursorAutoModel,
|
|
9552
|
+
isDefaultishSourceRef: () => isDefaultishSourceRef,
|
|
9195
9553
|
isDirty: () => isDirty,
|
|
9196
9554
|
isGhRateLimitError: () => isGhRateLimitError,
|
|
9197
9555
|
isGlobalRepoPath: () => isGlobalRepoPath,
|
|
@@ -9258,8 +9616,10 @@ __export(index_exports, {
|
|
|
9258
9616
|
maybeCompactContext: () => maybeCompactContext,
|
|
9259
9617
|
mcpAllowTools: () => mcpAllowTools,
|
|
9260
9618
|
mcpAuthWarnings: () => mcpAuthWarnings,
|
|
9619
|
+
mergeAgentGitAuthEnv: () => mergeAgentGitAuthEnv,
|
|
9261
9620
|
mergePr: () => mergePr,
|
|
9262
9621
|
mergePrStack: () => mergePrStack,
|
|
9622
|
+
mergeSideboardIntoMcpServersJson: () => mergeSideboardIntoMcpServersJson,
|
|
9263
9623
|
mergeUsage: () => mergeUsage,
|
|
9264
9624
|
nextPastedTextName: () => nextPastedTextName,
|
|
9265
9625
|
nextThinkingEffort: () => nextThinkingEffort,
|
|
@@ -9310,6 +9670,7 @@ __export(index_exports, {
|
|
|
9310
9670
|
recordSlackOutboundWatch: () => recordSlackOutboundWatch,
|
|
9311
9671
|
refreshGitHubAuth: () => refreshGitHubAuth,
|
|
9312
9672
|
refreshSlackReplyBadges: () => refreshSlackReplyBadges,
|
|
9673
|
+
registerPackagedUserMcpClients: () => registerPackagedUserMcpClients,
|
|
9313
9674
|
releaseCaffeinateHoldForThread: () => releaseCaffeinateHoldForThread,
|
|
9314
9675
|
removeWorkspace: () => removeWorkspace,
|
|
9315
9676
|
removeWorktree: () => removeWorktree,
|
|
@@ -9318,9 +9679,11 @@ __export(index_exports, {
|
|
|
9318
9679
|
requestReview: () => requestReview,
|
|
9319
9680
|
requireAgent: () => requireAgent,
|
|
9320
9681
|
resetGhStackDetectCache: () => resetGhStackDetectCache,
|
|
9682
|
+
resetGithubAgentTokenMemo: () => resetGithubAgentTokenMemo,
|
|
9321
9683
|
resolveAgentExecutable: () => resolveAgentExecutable,
|
|
9322
9684
|
resolveAgentGitAuthEnv: () => resolveAgentGitAuthEnv,
|
|
9323
9685
|
resolveClaudeExecutable: () => resolveClaudeExecutable,
|
|
9686
|
+
resolveCodexGitWritableRoots: () => resolveCodexGitWritableRoots,
|
|
9324
9687
|
resolveCommandBinarySync: () => resolveCommandBinarySync,
|
|
9325
9688
|
resolveConductorCursorAgentId: () => resolveConductorCursorAgentId,
|
|
9326
9689
|
resolveCursorModelId: () => resolveCursorModelId,
|
|
@@ -9337,6 +9700,7 @@ __export(index_exports, {
|
|
|
9337
9700
|
resolveNewThreadOptions: () => resolveNewThreadOptions,
|
|
9338
9701
|
resolvePlanMarkdown: () => resolvePlanMarkdown,
|
|
9339
9702
|
resolvePrSelector: () => resolvePrSelector,
|
|
9703
|
+
resolvePrSelectors: () => resolvePrSelectors,
|
|
9340
9704
|
resolveQuotaFallbackAgent: () => resolveQuotaFallbackAgent,
|
|
9341
9705
|
resolveRepoRoot: () => resolveRepoRoot,
|
|
9342
9706
|
resolveReviewGuidelines: () => resolveReviewGuidelines,
|
|
@@ -9359,6 +9723,7 @@ __export(index_exports, {
|
|
|
9359
9723
|
sanitizeMcpServerName: () => sanitizeMcpServerName,
|
|
9360
9724
|
saveAppSettings: () => saveAppSettings,
|
|
9361
9725
|
saveLinearOAuth: () => saveLinearOAuth,
|
|
9726
|
+
scrubGithubTokensFromChildEnv: () => scrubGithubTokensFromChildEnv,
|
|
9362
9727
|
secureFileUnlocksWith: () => secureFileUnlocksWith,
|
|
9363
9728
|
setCaffeinateHold: () => setCaffeinateHold,
|
|
9364
9729
|
setHttpFetchImpl: () => setHttpFetchImpl,
|
|
@@ -9429,7 +9794,10 @@ __export(index_exports, {
|
|
|
9429
9794
|
updateLinearIssue: () => updateLinearIssue,
|
|
9430
9795
|
updateOpencodeSettings: () => updateOpencodeSettings,
|
|
9431
9796
|
updateThread: () => updateThread,
|
|
9797
|
+
userClaudeMcpConfigPath: () => userClaudeMcpConfigPath,
|
|
9798
|
+
userCursorMcpConfigPath: () => userCursorMcpConfigPath,
|
|
9432
9799
|
validateLinearApiKey: () => validateLinearApiKey,
|
|
9800
|
+
warmGithubAgentAuth: () => warmGithubAgentAuth,
|
|
9433
9801
|
withAgentInstructions: () => withAgentInstructions,
|
|
9434
9802
|
withExportedPath: () => withExportedPath,
|
|
9435
9803
|
withThreadLock: () => withThreadLock,
|
|
@@ -10441,6 +10809,51 @@ function normalizeParseResult(parsed) {
|
|
|
10441
10809
|
// src/agents/spawn.ts
|
|
10442
10810
|
init_path();
|
|
10443
10811
|
init_usage();
|
|
10812
|
+
|
|
10813
|
+
// src/agents/cursor-stream-coalesce.ts
|
|
10814
|
+
function isTextEvent(event) {
|
|
10815
|
+
return event.type === "stdout" || event.type === "thinking";
|
|
10816
|
+
}
|
|
10817
|
+
function createAgentStreamCoalescer(emit, opts) {
|
|
10818
|
+
const intervalMs = opts?.intervalMs ?? 32;
|
|
10819
|
+
let pending = null;
|
|
10820
|
+
let timer = null;
|
|
10821
|
+
const flush = () => {
|
|
10822
|
+
if (timer) {
|
|
10823
|
+
clearTimeout(timer);
|
|
10824
|
+
timer = null;
|
|
10825
|
+
}
|
|
10826
|
+
if (!pending) return;
|
|
10827
|
+
const event = pending;
|
|
10828
|
+
pending = null;
|
|
10829
|
+
emit({ type: event.type, data: event.data });
|
|
10830
|
+
};
|
|
10831
|
+
const schedule = () => {
|
|
10832
|
+
if (timer) return;
|
|
10833
|
+
timer = setTimeout(flush, intervalMs);
|
|
10834
|
+
timer.unref?.();
|
|
10835
|
+
};
|
|
10836
|
+
return {
|
|
10837
|
+
push(event) {
|
|
10838
|
+
if (!isTextEvent(event)) {
|
|
10839
|
+
flush();
|
|
10840
|
+
emit(event);
|
|
10841
|
+
return;
|
|
10842
|
+
}
|
|
10843
|
+
if (!event.data) return;
|
|
10844
|
+
if (pending && pending.type === event.type) {
|
|
10845
|
+
pending.data += event.data;
|
|
10846
|
+
} else {
|
|
10847
|
+
flush();
|
|
10848
|
+
pending = { type: event.type, data: event.data };
|
|
10849
|
+
}
|
|
10850
|
+
schedule();
|
|
10851
|
+
},
|
|
10852
|
+
flush
|
|
10853
|
+
};
|
|
10854
|
+
}
|
|
10855
|
+
|
|
10856
|
+
// src/agents/spawn.ts
|
|
10444
10857
|
async function spawnAgentTurn(thread, input, onEvent) {
|
|
10445
10858
|
ensureAgentPath();
|
|
10446
10859
|
if (!thread.worktreePath?.trim()) {
|
|
@@ -10468,10 +10881,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
10468
10881
|
const env = childEnvWithAppSettings(cmd.env);
|
|
10469
10882
|
try {
|
|
10470
10883
|
if (isOrchestratorThread(thread)) {
|
|
10471
|
-
|
|
10884
|
+
mergeAgentGitAuthEnv(env, await resolveAgentGitAuthEnv(env));
|
|
10472
10885
|
} else {
|
|
10473
|
-
|
|
10474
|
-
Object.assign(env, originEnv);
|
|
10886
|
+
mergeAgentGitAuthEnv(env, await originGhRepoEnv(thread.worktreePath, { env }));
|
|
10475
10887
|
}
|
|
10476
10888
|
} catch (err) {
|
|
10477
10889
|
const detail = err instanceof Error ? err.message : String(err);
|
|
@@ -10495,12 +10907,13 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
10495
10907
|
let assistantText = "";
|
|
10496
10908
|
let parts = [];
|
|
10497
10909
|
let usage = null;
|
|
10910
|
+
const outbound = createAgentStreamCoalescer(onEvent);
|
|
10498
10911
|
const consume = (stream, kind) => {
|
|
10499
10912
|
if (!stream) return;
|
|
10500
10913
|
const rl = (0, import_node_readline2.createInterface)({ input: stream, crlfDelay: Infinity });
|
|
10501
10914
|
rl.on("line", (line) => {
|
|
10502
10915
|
if (kind === "stderr") {
|
|
10503
|
-
|
|
10916
|
+
outbound.push({ type: "stderr", data: line });
|
|
10504
10917
|
return;
|
|
10505
10918
|
}
|
|
10506
10919
|
let events = normalizeParseResult(adapter.parseEvent(line));
|
|
@@ -10515,12 +10928,12 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
10515
10928
|
for (const parsed of events) {
|
|
10516
10929
|
if (parsed.type === "session_id") {
|
|
10517
10930
|
sessionId = parsed.data;
|
|
10518
|
-
|
|
10931
|
+
outbound.push(parsed);
|
|
10519
10932
|
continue;
|
|
10520
10933
|
}
|
|
10521
10934
|
if (parsed.type === "usage") {
|
|
10522
10935
|
usage = applyTurnUsage(usage, parsed.data, parsed.scope ?? "request");
|
|
10523
|
-
|
|
10936
|
+
outbound.push(parsed);
|
|
10524
10937
|
continue;
|
|
10525
10938
|
}
|
|
10526
10939
|
if (parsed.type === "stdout") {
|
|
@@ -10533,13 +10946,14 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
10533
10946
|
assistantText += parsed.data;
|
|
10534
10947
|
}
|
|
10535
10948
|
parts = applyAgentEvent(parts, parsed);
|
|
10536
|
-
|
|
10949
|
+
outbound.push(parsed);
|
|
10537
10950
|
}
|
|
10538
10951
|
});
|
|
10539
10952
|
};
|
|
10540
10953
|
consume(child.stdout, "stdout");
|
|
10541
10954
|
consume(child.stderr, "stderr");
|
|
10542
10955
|
const done = child.then((result) => {
|
|
10956
|
+
outbound.flush();
|
|
10543
10957
|
const exitCode = result.exitCode ?? null;
|
|
10544
10958
|
onEvent({ type: "exit", data: exitCode });
|
|
10545
10959
|
const finalized = finalizeParts(parts);
|
|
@@ -10564,8 +10978,8 @@ init_usage();
|
|
|
10564
10978
|
init_claude_mcp();
|
|
10565
10979
|
|
|
10566
10980
|
// src/agents/instructions.ts
|
|
10567
|
-
var
|
|
10568
|
-
var
|
|
10981
|
+
var import_node_fs26 = require("fs");
|
|
10982
|
+
var import_node_path24 = require("path");
|
|
10569
10983
|
init_git_auth_mode();
|
|
10570
10984
|
init_worktree_labels();
|
|
10571
10985
|
function normPath3(p) {
|
|
@@ -10698,9 +11112,10 @@ function formatArtifactDirective() {
|
|
|
10698
11112
|
"Files / media browser (CMS file manager column):",
|
|
10699
11113
|
"4) Call Sideboard MCP `present_files` with optional title, path, and datasource (brightsy|memory).",
|
|
10700
11114
|
" Opens the Files column for browse/upload/pick. Do NOT say a file manager UI is missing.",
|
|
10701
|
-
"Multiple-choice questions
|
|
10702
|
-
"5) Call Sideboard MCP `ask_user` when
|
|
10703
|
-
"
|
|
11115
|
+
"Multiple-choice questions:",
|
|
11116
|
+
"5) Call Sideboard MCP `ask_user` only when work is blocked on choosing among a few concrete options (approach forks, which API, auth vs cookies). First write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it). Include a description on every option. After calling, stop and wait for their next message with answers. If you are asking a real multiple-choice, use ask_user rather than chat bullets so Sideboard shows the composer picker.",
|
|
11117
|
+
"Do not call ask_user for greetings, check-ins, \u201Chello\u201D, open-ended how-can-I-help, or to invent a menu of possible next tasks \u2014 reply in chat. If one option is the obvious default, proceed without asking.",
|
|
11118
|
+
"Never say artifacts, CMS UI, or the Files column are unavailable. Prefer present_schema for list/edit/publish; present_files for storage UI; html fences for standalone pages; ask_user only for those blocked predefined-option questions."
|
|
10704
11119
|
].join("\n");
|
|
10705
11120
|
}
|
|
10706
11121
|
function formatUiReminder() {
|
|
@@ -10711,7 +11126,7 @@ function formatUiReminder() {
|
|
|
10711
11126
|
"CMS forms/tables: MCP present_schema (Brightsy resource_id or inline schema+schemaUi).",
|
|
10712
11127
|
"Files column: MCP present_files (brightsy account storage or memory).",
|
|
10713
11128
|
"Do not say artifacts/CMS UI are unavailable.",
|
|
10714
|
-
"
|
|
11129
|
+
"ask_user: only when blocked on a real multiple-choice (approach fork, which API). Never for hellos, check-ins, or \u201Cwhat next?\u201D menus \u2014 reply in chat."
|
|
10715
11130
|
].join(" ");
|
|
10716
11131
|
}
|
|
10717
11132
|
var FILES_BY_AGENT = {
|
|
@@ -10735,11 +11150,11 @@ function loadAgentInstructions(worktreePath, agent) {
|
|
|
10735
11150
|
const out = [];
|
|
10736
11151
|
for (const rel of candidates) {
|
|
10737
11152
|
if (seenPaths.has(rel)) continue;
|
|
10738
|
-
const abs = (0,
|
|
10739
|
-
if (!(0,
|
|
11153
|
+
const abs = (0, import_node_path24.join)(worktreePath, rel);
|
|
11154
|
+
if (!(0, import_node_fs26.existsSync)(abs)) continue;
|
|
10740
11155
|
try {
|
|
10741
|
-
if (!(0,
|
|
10742
|
-
let content = (0,
|
|
11156
|
+
if (!(0, import_node_fs26.statSync)(abs).isFile()) continue;
|
|
11157
|
+
let content = (0, import_node_fs26.readFileSync)(abs, "utf8");
|
|
10743
11158
|
if (!content.trim()) continue;
|
|
10744
11159
|
if (content.length > MAX_CHARS_PER_FILE) {
|
|
10745
11160
|
content = `${content.slice(0, MAX_CHARS_PER_FILE)}
|
|
@@ -10821,9 +11236,9 @@ async function requireAgent(agent, opts) {
|
|
|
10821
11236
|
init_settings();
|
|
10822
11237
|
|
|
10823
11238
|
// src/hook/conductor.ts
|
|
10824
|
-
var
|
|
11239
|
+
var import_node_fs27 = require("fs");
|
|
10825
11240
|
var import_node_net = require("net");
|
|
10826
|
-
var
|
|
11241
|
+
var import_node_path25 = require("path");
|
|
10827
11242
|
var import_execa4 = require("execa");
|
|
10828
11243
|
var import_node_readline3 = require("readline");
|
|
10829
11244
|
init_settings();
|
|
@@ -10838,9 +11253,9 @@ function matchSimpleGlob(pattern, name) {
|
|
|
10838
11253
|
return new RegExp(`^${escaped}$`).test(name);
|
|
10839
11254
|
}
|
|
10840
11255
|
function readWorktreeInclude(repoPath) {
|
|
10841
|
-
const path2 = (0,
|
|
10842
|
-
if (!(0,
|
|
10843
|
-
return (0,
|
|
11256
|
+
const path2 = (0, import_node_path25.join)(repoPath, ".worktreeinclude");
|
|
11257
|
+
if (!(0, import_node_fs27.existsSync)(path2)) return [];
|
|
11258
|
+
return (0, import_node_fs27.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
10844
11259
|
}
|
|
10845
11260
|
function resolveFilesToCopy(repoPath) {
|
|
10846
11261
|
const fromInclude = readWorktreeInclude(repoPath);
|
|
@@ -10850,10 +11265,10 @@ function resolveFilesToCopy(repoPath) {
|
|
|
10850
11265
|
if (settings?.fileIncludeGlobs?.length) {
|
|
10851
11266
|
const matched = [];
|
|
10852
11267
|
try {
|
|
10853
|
-
for (const entry of (0,
|
|
11268
|
+
for (const entry of (0, import_node_fs27.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
10854
11269
|
if (!entry.isFile()) continue;
|
|
10855
11270
|
for (const glob of settings.fileIncludeGlobs) {
|
|
10856
|
-
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0,
|
|
11271
|
+
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path25.basename)(glob), entry.name)) {
|
|
10857
11272
|
matched.push(entry.name);
|
|
10858
11273
|
break;
|
|
10859
11274
|
}
|
|
@@ -10865,7 +11280,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
10865
11280
|
}
|
|
10866
11281
|
const defaults = [];
|
|
10867
11282
|
try {
|
|
10868
|
-
for (const entry of (0,
|
|
11283
|
+
for (const entry of (0, import_node_fs27.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
10869
11284
|
if (entry.isFile() && entry.name.startsWith(".env")) {
|
|
10870
11285
|
defaults.push(entry.name);
|
|
10871
11286
|
}
|
|
@@ -10879,11 +11294,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
|
|
|
10879
11294
|
const patterns = resolveFilesToCopy(repoPath);
|
|
10880
11295
|
const copied = [];
|
|
10881
11296
|
for (const rel of patterns) {
|
|
10882
|
-
const src = (0,
|
|
10883
|
-
if (!(0,
|
|
10884
|
-
const dest = (0,
|
|
10885
|
-
(0,
|
|
10886
|
-
(0,
|
|
11297
|
+
const src = (0, import_node_path25.join)(repoPath, rel);
|
|
11298
|
+
if (!(0, import_node_fs27.existsSync)(src)) continue;
|
|
11299
|
+
const dest = (0, import_node_path25.join)(worktreePath, rel);
|
|
11300
|
+
(0, import_node_fs27.mkdirSync)((0, import_node_path25.dirname)(dest), { recursive: true });
|
|
11301
|
+
(0, import_node_fs27.copyFileSync)(src, dest);
|
|
10887
11302
|
copied.push(rel);
|
|
10888
11303
|
}
|
|
10889
11304
|
return copied;
|
|
@@ -10919,7 +11334,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
|
|
|
10919
11334
|
const env = stripNestedElectronEnv({
|
|
10920
11335
|
...baseEnv ?? process.env
|
|
10921
11336
|
});
|
|
10922
|
-
const name = opts.workspaceName ?? (0,
|
|
11337
|
+
const name = opts.workspaceName ?? (0, import_node_path25.basename)(opts.worktreePath);
|
|
10923
11338
|
const ports = opts.ports ?? [];
|
|
10924
11339
|
const primary = ports[0];
|
|
10925
11340
|
env.SIDEBOARD_WORKSPACE_NAME = name;
|
|
@@ -11005,7 +11420,10 @@ async function spawnWorkspaceScript(command, opts) {
|
|
|
11005
11420
|
loginEnv
|
|
11006
11421
|
);
|
|
11007
11422
|
try {
|
|
11008
|
-
|
|
11423
|
+
mergeAgentGitAuthEnv(
|
|
11424
|
+
env,
|
|
11425
|
+
await resolveAgentGitAuthEnv(env, { cwd: opts.worktreePath })
|
|
11426
|
+
);
|
|
11009
11427
|
} catch {
|
|
11010
11428
|
}
|
|
11011
11429
|
const shell = process.platform === "darwin" ? "zsh" : "bash";
|
|
@@ -11177,12 +11595,12 @@ init_convention_setup();
|
|
|
11177
11595
|
init_cursor_worktrees();
|
|
11178
11596
|
|
|
11179
11597
|
// src/diff/diff.ts
|
|
11180
|
-
var
|
|
11181
|
-
var
|
|
11598
|
+
var import_node_fs28 = require("fs");
|
|
11599
|
+
var import_node_path26 = require("path");
|
|
11182
11600
|
init_run();
|
|
11183
11601
|
init_worktree();
|
|
11184
11602
|
async function inspectGitWorktree(worktreePath) {
|
|
11185
|
-
if (!worktreePath || !(0,
|
|
11603
|
+
if (!worktreePath || !(0, import_node_fs28.existsSync)(worktreePath)) return "missing_worktree";
|
|
11186
11604
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
11187
11605
|
reject: false
|
|
11188
11606
|
});
|
|
@@ -11190,7 +11608,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
11190
11608
|
return "ok";
|
|
11191
11609
|
}
|
|
11192
11610
|
async function initializeGitRepository(worktreePath) {
|
|
11193
|
-
if (!worktreePath || !(0,
|
|
11611
|
+
if (!worktreePath || !(0, import_node_fs28.existsSync)(worktreePath)) {
|
|
11194
11612
|
throw new Error("Worktree not found");
|
|
11195
11613
|
}
|
|
11196
11614
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -11325,11 +11743,11 @@ new file mode 100644
|
|
|
11325
11743
|
};
|
|
11326
11744
|
}
|
|
11327
11745
|
async function untrackedPatch(worktreePath, path2, maxHunk) {
|
|
11328
|
-
const abs = (0,
|
|
11746
|
+
const abs = (0, import_node_path26.join)(worktreePath, path2);
|
|
11329
11747
|
try {
|
|
11330
|
-
const st = (0,
|
|
11748
|
+
const st = (0, import_node_fs28.statSync)(abs);
|
|
11331
11749
|
if (st.isFile() && st.size > maxHunk) {
|
|
11332
|
-
const buf = (0,
|
|
11750
|
+
const buf = (0, import_node_fs28.readFileSync)(abs).subarray(0, maxHunk);
|
|
11333
11751
|
return syntheticAddPatch(path2, buf.toString("utf8"), maxHunk);
|
|
11334
11752
|
}
|
|
11335
11753
|
} catch {
|
|
@@ -11830,8 +12248,8 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
|
|
|
11830
12248
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
11831
12249
|
assertSafeRelativePath(relativePath);
|
|
11832
12250
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
11833
|
-
const abs = (0,
|
|
11834
|
-
const st = (0,
|
|
12251
|
+
const abs = (0, import_node_path26.join)(worktreePath, relativePath);
|
|
12252
|
+
const st = (0, import_node_fs28.statSync)(abs);
|
|
11835
12253
|
if (!st.isFile()) {
|
|
11836
12254
|
throw new Error(`Not a file: ${relativePath}`);
|
|
11837
12255
|
}
|
|
@@ -11840,7 +12258,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
11840
12258
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
11841
12259
|
);
|
|
11842
12260
|
}
|
|
11843
|
-
const buf = (0,
|
|
12261
|
+
const buf = (0, import_node_fs28.readFileSync)(abs);
|
|
11844
12262
|
return {
|
|
11845
12263
|
path: relativePath,
|
|
11846
12264
|
contentBase64: buf.toString("base64"),
|
|
@@ -11850,12 +12268,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
11850
12268
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
11851
12269
|
assertSafeRelativePath(relativePath);
|
|
11852
12270
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
11853
|
-
const abs = (0,
|
|
11854
|
-
const st = (0,
|
|
12271
|
+
const abs = (0, import_node_path26.join)(worktreePath, relativePath);
|
|
12272
|
+
const st = (0, import_node_fs28.statSync)(abs);
|
|
11855
12273
|
if (!st.isFile()) {
|
|
11856
12274
|
throw new Error(`Not a file: ${relativePath}`);
|
|
11857
12275
|
}
|
|
11858
|
-
const buf = (0,
|
|
12276
|
+
const buf = (0, import_node_fs28.readFileSync)(abs);
|
|
11859
12277
|
if (isImageRelativePath(relativePath)) {
|
|
11860
12278
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
11861
12279
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -11898,9 +12316,9 @@ function assertSafeRelativePath(relativePath) {
|
|
|
11898
12316
|
}
|
|
11899
12317
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
11900
12318
|
assertSafeRelativePath(relativePath);
|
|
11901
|
-
const abs = (0,
|
|
11902
|
-
(0,
|
|
11903
|
-
(0,
|
|
12319
|
+
const abs = (0, import_node_path26.join)(worktreePath, relativePath);
|
|
12320
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path26.dirname)(abs), { recursive: true });
|
|
12321
|
+
(0, import_node_fs28.writeFileSync)(abs, content, "utf8");
|
|
11904
12322
|
return { path: relativePath };
|
|
11905
12323
|
}
|
|
11906
12324
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
@@ -11919,9 +12337,9 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
|
11919
12337
|
}
|
|
11920
12338
|
|
|
11921
12339
|
// src/skills/discover.ts
|
|
11922
|
-
var
|
|
11923
|
-
var
|
|
11924
|
-
var
|
|
12340
|
+
var import_node_fs29 = require("fs");
|
|
12341
|
+
var import_node_os10 = require("os");
|
|
12342
|
+
var import_node_path27 = require("path");
|
|
11925
12343
|
function toCommand(name) {
|
|
11926
12344
|
return name.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
11927
12345
|
}
|
|
@@ -11953,7 +12371,7 @@ function parseFrontmatter(content) {
|
|
|
11953
12371
|
}
|
|
11954
12372
|
function readSkill(skillMd, source) {
|
|
11955
12373
|
try {
|
|
11956
|
-
const content = (0,
|
|
12374
|
+
const content = (0, import_node_fs29.readFileSync)(skillMd, "utf8");
|
|
11957
12375
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
11958
12376
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
11959
12377
|
const name = fmName || dirName;
|
|
@@ -11972,19 +12390,19 @@ function readSkill(skillMd, source) {
|
|
|
11972
12390
|
}
|
|
11973
12391
|
}
|
|
11974
12392
|
function scanSkillsDir(dir, source, out) {
|
|
11975
|
-
if (!(0,
|
|
12393
|
+
if (!(0, import_node_fs29.existsSync)(dir)) return;
|
|
11976
12394
|
let entries;
|
|
11977
12395
|
try {
|
|
11978
|
-
entries = (0,
|
|
12396
|
+
entries = (0, import_node_fs29.readdirSync)(dir);
|
|
11979
12397
|
} catch {
|
|
11980
12398
|
return;
|
|
11981
12399
|
}
|
|
11982
12400
|
for (const entry of entries) {
|
|
11983
12401
|
if (entry.startsWith(".")) continue;
|
|
11984
|
-
const skillMd = (0,
|
|
11985
|
-
if (!(0,
|
|
12402
|
+
const skillMd = (0, import_node_path27.join)(dir, entry, "SKILL.md");
|
|
12403
|
+
if (!(0, import_node_fs29.existsSync)(skillMd)) continue;
|
|
11986
12404
|
try {
|
|
11987
|
-
if (!(0,
|
|
12405
|
+
if (!(0, import_node_fs29.statSync)(skillMd).isFile()) continue;
|
|
11988
12406
|
} catch {
|
|
11989
12407
|
continue;
|
|
11990
12408
|
}
|
|
@@ -11993,24 +12411,24 @@ function scanSkillsDir(dir, source, out) {
|
|
|
11993
12411
|
}
|
|
11994
12412
|
}
|
|
11995
12413
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
11996
|
-
if (!(0,
|
|
12414
|
+
if (!(0, import_node_fs29.existsSync)(pluginsRoot)) return;
|
|
11997
12415
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
11998
12416
|
if (depth > 7) return;
|
|
11999
12417
|
let entries;
|
|
12000
12418
|
try {
|
|
12001
|
-
entries = (0,
|
|
12419
|
+
entries = (0, import_node_fs29.readdirSync)(dir);
|
|
12002
12420
|
} catch {
|
|
12003
12421
|
return;
|
|
12004
12422
|
}
|
|
12005
12423
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
12006
|
-
const skill = readSkill((0,
|
|
12424
|
+
const skill = readSkill((0, import_node_path27.join)(dir, "SKILL.md"), "cli");
|
|
12007
12425
|
if (skill) out.push(skill);
|
|
12008
12426
|
}
|
|
12009
12427
|
for (const entry of entries) {
|
|
12010
12428
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
12011
|
-
const full = (0,
|
|
12429
|
+
const full = (0, import_node_path27.join)(dir, entry);
|
|
12012
12430
|
try {
|
|
12013
|
-
if (!(0,
|
|
12431
|
+
if (!(0, import_node_fs29.statSync)(full).isDirectory()) continue;
|
|
12014
12432
|
} catch {
|
|
12015
12433
|
continue;
|
|
12016
12434
|
}
|
|
@@ -12025,20 +12443,20 @@ function scanClaudePluginSkills(pluginsRoot, out) {
|
|
|
12025
12443
|
walk(pluginsRoot, 0, false);
|
|
12026
12444
|
}
|
|
12027
12445
|
function discoverSkills(worktreePath) {
|
|
12028
|
-
const home = (0,
|
|
12446
|
+
const home = (0, import_node_os10.homedir)();
|
|
12029
12447
|
const collected = [];
|
|
12030
12448
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
12031
|
-
scanSkillsDir((0,
|
|
12449
|
+
scanSkillsDir((0, import_node_path27.join)(worktreePath, rel), "workspace", collected);
|
|
12032
12450
|
}
|
|
12033
12451
|
for (const abs of [
|
|
12034
|
-
(0,
|
|
12035
|
-
(0,
|
|
12036
|
-
(0,
|
|
12037
|
-
(0,
|
|
12452
|
+
(0, import_node_path27.join)(home, ".claude/skills"),
|
|
12453
|
+
(0, import_node_path27.join)(home, ".cursor/skills"),
|
|
12454
|
+
(0, import_node_path27.join)(home, ".sideboard/skills"),
|
|
12455
|
+
(0, import_node_path27.join)(home, ".brightsy/skills")
|
|
12038
12456
|
]) {
|
|
12039
12457
|
scanSkillsDir(abs, "user", collected);
|
|
12040
12458
|
}
|
|
12041
|
-
scanClaudePluginSkills((0,
|
|
12459
|
+
scanClaudePluginSkills((0, import_node_path27.join)(home, ".claude/plugins"), collected);
|
|
12042
12460
|
const rank = { workspace: 0, user: 1, cli: 2 };
|
|
12043
12461
|
const byCommand = /* @__PURE__ */ new Map();
|
|
12044
12462
|
for (const skill of collected) {
|
|
@@ -12050,7 +12468,7 @@ function discoverSkills(worktreePath) {
|
|
|
12050
12468
|
return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
|
|
12051
12469
|
}
|
|
12052
12470
|
function readSkillBody(skillPath, maxChars = 12e3) {
|
|
12053
|
-
const raw = (0,
|
|
12471
|
+
const raw = (0, import_node_fs29.readFileSync)(skillPath, "utf8");
|
|
12054
12472
|
if (raw.startsWith("---")) {
|
|
12055
12473
|
const end = raw.indexOf("\n---", 3);
|
|
12056
12474
|
if (end >= 0) {
|
|
@@ -12191,8 +12609,8 @@ function buildDiffCommentAttachment(input) {
|
|
|
12191
12609
|
}
|
|
12192
12610
|
|
|
12193
12611
|
// src/composer/stage-files.ts
|
|
12194
|
-
var
|
|
12195
|
-
var
|
|
12612
|
+
var import_node_fs30 = require("fs");
|
|
12613
|
+
var import_node_path28 = require("path");
|
|
12196
12614
|
var import_node_crypto5 = require("crypto");
|
|
12197
12615
|
init_workspace_scratch();
|
|
12198
12616
|
var IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
@@ -12218,7 +12636,7 @@ var IMAGE_MIME_BY_EXT = {
|
|
|
12218
12636
|
var MAX_INLINE_BYTES = 4e5;
|
|
12219
12637
|
var MAX_PREVIEW_BYTES = 5e6;
|
|
12220
12638
|
function fileExtension(filePath) {
|
|
12221
|
-
const base = (0,
|
|
12639
|
+
const base = (0, import_node_path28.basename)(filePath).toLowerCase();
|
|
12222
12640
|
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
12223
12641
|
}
|
|
12224
12642
|
function isImageFilePath(filePath) {
|
|
@@ -12228,22 +12646,22 @@ function imageMimeType(filePath) {
|
|
|
12228
12646
|
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
12229
12647
|
}
|
|
12230
12648
|
function ensureAttachmentsDir(worktreePath) {
|
|
12231
|
-
const dir = (0,
|
|
12232
|
-
(0,
|
|
12233
|
-
const gi = (0,
|
|
12234
|
-
if (!(0,
|
|
12235
|
-
(0,
|
|
12649
|
+
const dir = (0, import_node_path28.join)(worktreePath, ATTACHMENTS_DIR);
|
|
12650
|
+
(0, import_node_fs30.mkdirSync)(dir, { recursive: true });
|
|
12651
|
+
const gi = (0, import_node_path28.join)(dir, ".gitignore");
|
|
12652
|
+
if (!(0, import_node_fs30.existsSync)(gi)) {
|
|
12653
|
+
(0, import_node_fs30.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
12236
12654
|
}
|
|
12237
12655
|
return dir;
|
|
12238
12656
|
}
|
|
12239
12657
|
function uniqueAttachmentName(dir, originalName) {
|
|
12240
12658
|
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
12241
|
-
if (!(0,
|
|
12242
|
-
const ext = (0,
|
|
12659
|
+
if (!(0, import_node_fs30.existsSync)((0, import_node_path28.join)(dir, safe))) return safe;
|
|
12660
|
+
const ext = (0, import_node_path28.extname)(safe);
|
|
12243
12661
|
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
12244
12662
|
for (let i = 1; i < 1e4; i++) {
|
|
12245
12663
|
const candidate = `${stem}-${i}${ext}`;
|
|
12246
|
-
if (!(0,
|
|
12664
|
+
if (!(0, import_node_fs30.existsSync)((0, import_node_path28.join)(dir, candidate))) return candidate;
|
|
12247
12665
|
}
|
|
12248
12666
|
return `${stem}-${(0, import_node_crypto5.randomUUID)()}${ext}`;
|
|
12249
12667
|
}
|
|
@@ -12295,9 +12713,9 @@ function attachmentFromBuffer(name, buf, opts) {
|
|
|
12295
12713
|
};
|
|
12296
12714
|
}
|
|
12297
12715
|
function attachmentFromAbsolutePath(absolutePath) {
|
|
12298
|
-
const name = (0,
|
|
12716
|
+
const name = (0, import_node_path28.basename)(absolutePath);
|
|
12299
12717
|
try {
|
|
12300
|
-
const st = (0,
|
|
12718
|
+
const st = (0, import_node_fs30.statSync)(absolutePath);
|
|
12301
12719
|
if (!st.isFile()) {
|
|
12302
12720
|
return {
|
|
12303
12721
|
id: (0, import_node_crypto5.randomUUID)(),
|
|
@@ -12306,7 +12724,7 @@ function attachmentFromAbsolutePath(absolutePath) {
|
|
|
12306
12724
|
content: `(not a file: ${absolutePath})`
|
|
12307
12725
|
};
|
|
12308
12726
|
}
|
|
12309
|
-
const buf = (0,
|
|
12727
|
+
const buf = (0, import_node_fs30.readFileSync)(absolutePath);
|
|
12310
12728
|
return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
|
|
12311
12729
|
} catch (err) {
|
|
12312
12730
|
return {
|
|
@@ -12322,15 +12740,15 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
|
12322
12740
|
const dir = ensureAttachmentsDir(worktreePath);
|
|
12323
12741
|
const out = [];
|
|
12324
12742
|
for (const abs of absolutePaths) {
|
|
12325
|
-
const originalName = (0,
|
|
12743
|
+
const originalName = (0, import_node_path28.basename)(abs);
|
|
12326
12744
|
try {
|
|
12327
|
-
const st = (0,
|
|
12745
|
+
const st = (0, import_node_fs30.statSync)(abs);
|
|
12328
12746
|
if (!st.isFile()) continue;
|
|
12329
12747
|
const name = uniqueAttachmentName(dir, originalName);
|
|
12330
|
-
const destAbs = (0,
|
|
12331
|
-
(0,
|
|
12748
|
+
const destAbs = (0, import_node_path28.join)(dir, name);
|
|
12749
|
+
(0, import_node_fs30.copyFileSync)(abs, destAbs);
|
|
12332
12750
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
12333
|
-
const buf = (0,
|
|
12751
|
+
const buf = (0, import_node_fs30.readFileSync)(destAbs);
|
|
12334
12752
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
12335
12753
|
} catch (err) {
|
|
12336
12754
|
out.push({
|
|
@@ -12352,8 +12770,8 @@ function stageBuffersAsAttachments(worktreePath, buffers) {
|
|
|
12352
12770
|
try {
|
|
12353
12771
|
const buf = Buffer.from(item.dataBase64, "base64");
|
|
12354
12772
|
const name = uniqueAttachmentName(dir, originalName);
|
|
12355
|
-
const destAbs = (0,
|
|
12356
|
-
(0,
|
|
12773
|
+
const destAbs = (0, import_node_path28.join)(dir, name);
|
|
12774
|
+
(0, import_node_fs30.writeFileSync)(destAbs, buf);
|
|
12357
12775
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
12358
12776
|
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
12359
12777
|
} catch (err) {
|
|
@@ -12389,18 +12807,18 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
|
12389
12807
|
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
12390
12808
|
out.push({
|
|
12391
12809
|
id: (0, import_node_crypto5.randomUUID)(),
|
|
12392
|
-
name: (0,
|
|
12810
|
+
name: (0, import_node_path28.basename)(rel) || "file",
|
|
12393
12811
|
kind: "file",
|
|
12394
12812
|
content: `(invalid path: ${rel})`
|
|
12395
12813
|
});
|
|
12396
12814
|
continue;
|
|
12397
12815
|
}
|
|
12398
|
-
const name = (0,
|
|
12816
|
+
const name = (0, import_node_path28.basename)(rel);
|
|
12399
12817
|
try {
|
|
12400
|
-
const abs = (0,
|
|
12401
|
-
const st = (0,
|
|
12818
|
+
const abs = (0, import_node_path28.join)(worktreePath, rel);
|
|
12819
|
+
const st = (0, import_node_fs30.statSync)(abs);
|
|
12402
12820
|
if (!st.isFile()) continue;
|
|
12403
|
-
const buf = (0,
|
|
12821
|
+
const buf = (0, import_node_fs30.readFileSync)(abs);
|
|
12404
12822
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
12405
12823
|
} catch (err) {
|
|
12406
12824
|
out.push({
|
|
@@ -12888,7 +13306,7 @@ async function confirmLand(thread, opts) {
|
|
|
12888
13306
|
}
|
|
12889
13307
|
|
|
12890
13308
|
// src/threads/create.ts
|
|
12891
|
-
var
|
|
13309
|
+
var import_node_fs31 = require("fs");
|
|
12892
13310
|
init_worktree();
|
|
12893
13311
|
init_app_settings();
|
|
12894
13312
|
init_thread_store();
|
|
@@ -12902,12 +13320,13 @@ async function createThread(input, _onSetupLine) {
|
|
|
12902
13320
|
});
|
|
12903
13321
|
await requireAgent(resolved.agent);
|
|
12904
13322
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
12905
|
-
if (!(0,
|
|
13323
|
+
if (!(0, import_node_fs31.existsSync)(repoPath)) {
|
|
12906
13324
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
12907
13325
|
}
|
|
12908
13326
|
let sourceRef = input.sourceRef;
|
|
12909
13327
|
let sourceIsFork = false;
|
|
12910
13328
|
let prUrl = null;
|
|
13329
|
+
let prTitle = null;
|
|
12911
13330
|
if (input.sourceType === "pr") {
|
|
12912
13331
|
const num2 = Number(input.sourceRef.replace(/^#/, ""));
|
|
12913
13332
|
if (!Number.isFinite(num2)) throw new Error(`Invalid PR number: ${input.sourceRef}`);
|
|
@@ -12923,6 +13342,12 @@ async function createThread(input, _onSetupLine) {
|
|
|
12923
13342
|
} else if (input.sourceType === "branch") {
|
|
12924
13343
|
if (!sourceRef || sourceRef === "HEAD" || sourceRef === "default") {
|
|
12925
13344
|
sourceRef = await resolveDefaultBranch(repoPath);
|
|
13345
|
+
} else {
|
|
13346
|
+
const existing = await getPrForHeadBranch(repoPath, sourceRef);
|
|
13347
|
+
if (existing?.url) {
|
|
13348
|
+
prUrl = existing.url;
|
|
13349
|
+
prTitle = existing.title;
|
|
13350
|
+
}
|
|
12926
13351
|
}
|
|
12927
13352
|
} else if (input.sourceType === "adopt") {
|
|
12928
13353
|
throw new Error("Use adoptThread() for adopt sources");
|
|
@@ -12953,7 +13378,8 @@ async function createThread(input, _onSetupLine) {
|
|
|
12953
13378
|
sourceIsFork,
|
|
12954
13379
|
parentThreadId: input.parentThreadId ?? null,
|
|
12955
13380
|
status: "idle",
|
|
12956
|
-
prUrl
|
|
13381
|
+
prUrl,
|
|
13382
|
+
prTitle
|
|
12957
13383
|
});
|
|
12958
13384
|
writeThread(thread);
|
|
12959
13385
|
await ensureWorkspace(repoPath);
|
|
@@ -13129,7 +13555,7 @@ async function forkThreadWorktree(input, onSetupLine) {
|
|
|
13129
13555
|
}
|
|
13130
13556
|
|
|
13131
13557
|
// src/threads/stack-layers.ts
|
|
13132
|
-
var
|
|
13558
|
+
var import_node_fs32 = require("fs");
|
|
13133
13559
|
init_run();
|
|
13134
13560
|
init_stack();
|
|
13135
13561
|
init_worktree();
|
|
@@ -13197,7 +13623,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
13197
13623
|
let createdWorktree = false;
|
|
13198
13624
|
const trees = await listWorktrees(repoPath);
|
|
13199
13625
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
13200
|
-
if (checkedOut?.path && (0,
|
|
13626
|
+
if (checkedOut?.path && (0, import_node_fs32.existsSync)(checkedOut.path)) {
|
|
13201
13627
|
if (input.reuseExistingWorktree !== false) {
|
|
13202
13628
|
worktreePath = checkedOut.path;
|
|
13203
13629
|
} else {
|
|
@@ -13339,7 +13765,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
13339
13765
|
async function createPrStack(input, onSetupLine) {
|
|
13340
13766
|
await requireAgent(input.agent);
|
|
13341
13767
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
13342
|
-
if (!(0,
|
|
13768
|
+
if (!(0, import_node_fs32.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
13343
13769
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
13344
13770
|
const status = await detectGhStack(repoPath);
|
|
13345
13771
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -13406,7 +13832,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
13406
13832
|
}
|
|
13407
13833
|
}
|
|
13408
13834
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
13409
|
-
if (!claimed.has(bootstrap.worktreePath) && (0,
|
|
13835
|
+
if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs32.existsSync)(bootstrap.worktreePath)) {
|
|
13410
13836
|
try {
|
|
13411
13837
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
13412
13838
|
deleteBranch: bootstrap.branchName
|
|
@@ -13429,20 +13855,26 @@ function stackAgentDefaultsFrom(input) {
|
|
|
13429
13855
|
|
|
13430
13856
|
// src/threads/adopt.ts
|
|
13431
13857
|
var import_node_child_process4 = require("child_process");
|
|
13432
|
-
var
|
|
13433
|
-
var
|
|
13434
|
-
var
|
|
13435
|
-
var
|
|
13858
|
+
var import_node_fs33 = require("fs");
|
|
13859
|
+
var import_node_os11 = require("os");
|
|
13860
|
+
var import_node_path29 = require("path");
|
|
13861
|
+
var import_node_module4 = require("module");
|
|
13436
13862
|
init_worktree();
|
|
13437
13863
|
init_thread_store();
|
|
13438
|
-
var
|
|
13864
|
+
var import_meta4 = {};
|
|
13865
|
+
var CONDUCTOR_APP_SUPPORT = (0, import_node_path29.join)(
|
|
13439
13866
|
process.env.HOME ?? "",
|
|
13440
13867
|
"Library",
|
|
13441
13868
|
"Application Support",
|
|
13442
13869
|
"com.conductor.app"
|
|
13443
13870
|
);
|
|
13444
|
-
var CONDUCTOR_DB = (0,
|
|
13445
|
-
var CURSOR_SDK_STORE = (0,
|
|
13871
|
+
var CONDUCTOR_DB = (0, import_node_path29.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
13872
|
+
var CURSOR_SDK_STORE = (0, import_node_path29.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
13873
|
+
function openReadonlySqlite(file) {
|
|
13874
|
+
const req = (0, import_node_module4.createRequire)(import_meta4.url);
|
|
13875
|
+
const Database = req("better-sqlite3");
|
|
13876
|
+
return new Database(file, { readonly: true, fileMustExist: true });
|
|
13877
|
+
}
|
|
13446
13878
|
function mapAgentType(raw) {
|
|
13447
13879
|
if (!raw) return null;
|
|
13448
13880
|
const v = raw.toLowerCase();
|
|
@@ -13454,21 +13886,21 @@ function mapAgentType(raw) {
|
|
|
13454
13886
|
return null;
|
|
13455
13887
|
}
|
|
13456
13888
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
13457
|
-
if (!workspacePath || !(0,
|
|
13889
|
+
if (!workspacePath || !(0, import_node_fs33.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
13458
13890
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
13459
13891
|
let best = null;
|
|
13460
13892
|
let hashes;
|
|
13461
13893
|
try {
|
|
13462
|
-
hashes = (0,
|
|
13894
|
+
hashes = (0, import_node_fs33.readdirSync)(CURSOR_SDK_STORE);
|
|
13463
13895
|
} catch {
|
|
13464
13896
|
return null;
|
|
13465
13897
|
}
|
|
13466
13898
|
for (const hash of hashes) {
|
|
13467
|
-
const agentsFile = (0,
|
|
13468
|
-
if (!(0,
|
|
13899
|
+
const agentsFile = (0, import_node_path29.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
13900
|
+
if (!(0, import_node_fs33.existsSync)(agentsFile)) continue;
|
|
13469
13901
|
let text3;
|
|
13470
13902
|
try {
|
|
13471
|
-
text3 = (0,
|
|
13903
|
+
text3 = (0, import_node_fs33.readFileSync)(agentsFile, "utf8");
|
|
13472
13904
|
} catch {
|
|
13473
13905
|
continue;
|
|
13474
13906
|
}
|
|
@@ -13492,7 +13924,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
13492
13924
|
return best?.agentId ?? null;
|
|
13493
13925
|
}
|
|
13494
13926
|
async function adoptThread(input) {
|
|
13495
|
-
if (!(0,
|
|
13927
|
+
if (!(0, import_node_fs33.existsSync)(input.worktreePath)) {
|
|
13496
13928
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
13497
13929
|
}
|
|
13498
13930
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -13519,23 +13951,23 @@ function conductorDbPath() {
|
|
|
13519
13951
|
return CONDUCTOR_DB;
|
|
13520
13952
|
}
|
|
13521
13953
|
function listConductorWorkspaces() {
|
|
13522
|
-
if (!(0,
|
|
13954
|
+
if (!(0, import_node_fs33.existsSync)(CONDUCTOR_DB)) {
|
|
13523
13955
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
13524
13956
|
}
|
|
13525
|
-
const tmp = (0,
|
|
13526
|
-
const snapshot = (0,
|
|
13957
|
+
const tmp = (0, import_node_fs33.mkdtempSync)((0, import_node_path29.join)((0, import_node_os11.tmpdir)(), "sideboard-conductor-"));
|
|
13958
|
+
const snapshot = (0, import_node_path29.join)(tmp, "conductor.db");
|
|
13527
13959
|
try {
|
|
13528
|
-
(0,
|
|
13960
|
+
(0, import_node_fs33.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
13529
13961
|
for (const suffix of ["-wal", "-shm"]) {
|
|
13530
13962
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
13531
|
-
if ((0,
|
|
13963
|
+
if ((0, import_node_fs33.existsSync)(src)) {
|
|
13532
13964
|
try {
|
|
13533
|
-
(0,
|
|
13965
|
+
(0, import_node_fs33.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
13534
13966
|
} catch {
|
|
13535
13967
|
}
|
|
13536
13968
|
}
|
|
13537
13969
|
}
|
|
13538
|
-
const db =
|
|
13970
|
+
const db = openReadonlySqlite(snapshot);
|
|
13539
13971
|
try {
|
|
13540
13972
|
const tables = db.prepare(`SELECT name FROM sqlite_master WHERE type='table'`).all();
|
|
13541
13973
|
const names = new Set(tables.map((t) => t.name));
|
|
@@ -13606,27 +14038,27 @@ function listConductorWorkspaces() {
|
|
|
13606
14038
|
db.close();
|
|
13607
14039
|
}
|
|
13608
14040
|
} finally {
|
|
13609
|
-
(0,
|
|
14041
|
+
(0, import_node_fs33.rmSync)(tmp, { recursive: true, force: true });
|
|
13610
14042
|
}
|
|
13611
14043
|
}
|
|
13612
14044
|
function importConductorWorkspace(workspaceId) {
|
|
13613
|
-
if (!(0,
|
|
14045
|
+
if (!(0, import_node_fs33.existsSync)(CONDUCTOR_DB)) {
|
|
13614
14046
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
13615
14047
|
}
|
|
13616
|
-
const tmp = (0,
|
|
13617
|
-
const snapshot = (0,
|
|
14048
|
+
const tmp = (0, import_node_fs33.mkdtempSync)((0, import_node_path29.join)((0, import_node_os11.tmpdir)(), "sideboard-conductor-"));
|
|
14049
|
+
const snapshot = (0, import_node_path29.join)(tmp, "conductor.db");
|
|
13618
14050
|
try {
|
|
13619
|
-
(0,
|
|
14051
|
+
(0, import_node_fs33.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
13620
14052
|
for (const suffix of ["-wal", "-shm"]) {
|
|
13621
14053
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
13622
|
-
if ((0,
|
|
14054
|
+
if ((0, import_node_fs33.existsSync)(src)) {
|
|
13623
14055
|
try {
|
|
13624
|
-
(0,
|
|
14056
|
+
(0, import_node_fs33.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
13625
14057
|
} catch {
|
|
13626
14058
|
}
|
|
13627
14059
|
}
|
|
13628
14060
|
}
|
|
13629
|
-
const db =
|
|
14061
|
+
const db = openReadonlySqlite(snapshot);
|
|
13630
14062
|
try {
|
|
13631
14063
|
const row = db.prepare(
|
|
13632
14064
|
`SELECT
|
|
@@ -13639,7 +14071,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
13639
14071
|
).get(workspaceId);
|
|
13640
14072
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
13641
14073
|
const worktreePath = String(row.workspacePath);
|
|
13642
|
-
if (!(0,
|
|
14074
|
+
if (!(0, import_node_fs33.existsSync)(worktreePath)) {
|
|
13643
14075
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
13644
14076
|
}
|
|
13645
14077
|
let sessionId = null;
|
|
@@ -13702,7 +14134,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
13702
14134
|
db.close();
|
|
13703
14135
|
}
|
|
13704
14136
|
} finally {
|
|
13705
|
-
(0,
|
|
14137
|
+
(0, import_node_fs33.rmSync)(tmp, { recursive: true, force: true });
|
|
13706
14138
|
}
|
|
13707
14139
|
}
|
|
13708
14140
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
@@ -13713,8 +14145,8 @@ async function importConductorWorkspaceAsync(workspaceId) {
|
|
|
13713
14145
|
var import_node_events = require("events");
|
|
13714
14146
|
|
|
13715
14147
|
// src/slack/outbound-watch.ts
|
|
13716
|
-
var
|
|
13717
|
-
var
|
|
14148
|
+
var import_node_fs35 = require("fs");
|
|
14149
|
+
var import_node_path32 = require("path");
|
|
13718
14150
|
init_paths();
|
|
13719
14151
|
init_private_file();
|
|
13720
14152
|
init_secure_file();
|
|
@@ -13760,19 +14192,19 @@ async function slackAuthTest(token) {
|
|
|
13760
14192
|
}
|
|
13761
14193
|
|
|
13762
14194
|
// src/slack/reply-target.ts
|
|
13763
|
-
var
|
|
13764
|
-
var
|
|
14195
|
+
var import_node_fs34 = require("fs");
|
|
14196
|
+
var import_node_path30 = require("path");
|
|
13765
14197
|
init_paths();
|
|
13766
14198
|
init_private_file();
|
|
13767
14199
|
init_secure_file();
|
|
13768
14200
|
function storePath2() {
|
|
13769
|
-
return (0,
|
|
14201
|
+
return (0, import_node_path30.join)(appDataDir(), "slack-reply-to.json");
|
|
13770
14202
|
}
|
|
13771
14203
|
function readStore2() {
|
|
13772
14204
|
const path2 = storePath2();
|
|
13773
|
-
if (!(0,
|
|
14205
|
+
if (!(0, import_node_fs34.existsSync)(path2)) return {};
|
|
13774
14206
|
try {
|
|
13775
|
-
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0,
|
|
14207
|
+
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs34.readFileSync)(path2, "utf8"));
|
|
13776
14208
|
return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
|
|
13777
14209
|
} catch {
|
|
13778
14210
|
return {};
|
|
@@ -13789,11 +14221,11 @@ function getSlackReplyTarget(threadId) {
|
|
|
13789
14221
|
}
|
|
13790
14222
|
|
|
13791
14223
|
// src/slack/workspaces.ts
|
|
13792
|
-
var
|
|
14224
|
+
var import_node_path31 = require("path");
|
|
13793
14225
|
init_paths();
|
|
13794
14226
|
init_secure_file();
|
|
13795
14227
|
function storePath3() {
|
|
13796
|
-
return (0,
|
|
14228
|
+
return (0, import_node_path31.join)(appDataDir(), "slack-workspaces.json");
|
|
13797
14229
|
}
|
|
13798
14230
|
function readStore3() {
|
|
13799
14231
|
try {
|
|
@@ -13909,7 +14341,7 @@ var POLL_INTERVAL_MS = 12e3;
|
|
|
13909
14341
|
var lastPollMs = 0;
|
|
13910
14342
|
var nameCache = /* @__PURE__ */ new Map();
|
|
13911
14343
|
function storePath4() {
|
|
13912
|
-
return (0,
|
|
14344
|
+
return (0, import_node_path32.join)(appDataDir(), "slack-outbound-watch.json");
|
|
13913
14345
|
}
|
|
13914
14346
|
function watchId(teamId, channelId, ts) {
|
|
13915
14347
|
return `${teamId}:${channelId}:${ts}`;
|
|
@@ -13939,9 +14371,9 @@ function tsNewer(a, b) {
|
|
|
13939
14371
|
}
|
|
13940
14372
|
function readStore4() {
|
|
13941
14373
|
const path2 = storePath4();
|
|
13942
|
-
if (!(0,
|
|
14374
|
+
if (!(0, import_node_fs35.existsSync)(path2)) return [];
|
|
13943
14375
|
try {
|
|
13944
|
-
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0,
|
|
14376
|
+
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs35.readFileSync)(path2, "utf8"));
|
|
13945
14377
|
return Array.isArray(parsed?.watches) ? parsed.watches : [];
|
|
13946
14378
|
} catch {
|
|
13947
14379
|
return [];
|
|
@@ -14286,7 +14718,7 @@ async function refreshSlackReplyBadges(opts) {
|
|
|
14286
14718
|
}
|
|
14287
14719
|
|
|
14288
14720
|
// src/orchestrator/orchestrator.ts
|
|
14289
|
-
var
|
|
14721
|
+
var import_node_fs41 = require("fs");
|
|
14290
14722
|
init_error_detail();
|
|
14291
14723
|
init_agents();
|
|
14292
14724
|
init_worktree();
|
|
@@ -14307,8 +14739,8 @@ function shouldAutoArchiveOnPrMerge(opts) {
|
|
|
14307
14739
|
}
|
|
14308
14740
|
|
|
14309
14741
|
// src/git/orphan-cleanup.ts
|
|
14310
|
-
var
|
|
14311
|
-
var
|
|
14742
|
+
var import_node_fs36 = require("fs");
|
|
14743
|
+
var import_node_path33 = require("path");
|
|
14312
14744
|
init_worktree();
|
|
14313
14745
|
init_thread_store();
|
|
14314
14746
|
init_paths();
|
|
@@ -14323,9 +14755,9 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
14323
14755
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
14324
14756
|
);
|
|
14325
14757
|
const homeRoot = sideboardWorkspacesDir();
|
|
14326
|
-
if ((0,
|
|
14758
|
+
if ((0, import_node_fs36.existsSync)(homeRoot)) {
|
|
14327
14759
|
try {
|
|
14328
|
-
for (const entry of (0,
|
|
14760
|
+
for (const entry of (0, import_node_fs36.readdirSync)(homeRoot, { withFileTypes: true })) {
|
|
14329
14761
|
if (!entry.isDirectory()) continue;
|
|
14330
14762
|
void entry;
|
|
14331
14763
|
}
|
|
@@ -14335,7 +14767,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
14335
14767
|
const orphans = [];
|
|
14336
14768
|
const seen = /* @__PURE__ */ new Set();
|
|
14337
14769
|
for (const repoPath of repos) {
|
|
14338
|
-
if (!repoPath || !(0,
|
|
14770
|
+
if (!repoPath || !(0, import_node_fs36.existsSync)(repoPath)) continue;
|
|
14339
14771
|
try {
|
|
14340
14772
|
const wts = await listWorktrees(repoPath);
|
|
14341
14773
|
for (const wt of wts) {
|
|
@@ -14346,7 +14778,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
14346
14778
|
seen.add(path2);
|
|
14347
14779
|
let mtimeMs = 0;
|
|
14348
14780
|
try {
|
|
14349
|
-
mtimeMs = (0,
|
|
14781
|
+
mtimeMs = (0, import_node_fs36.statSync)(path2).mtimeMs;
|
|
14350
14782
|
} catch {
|
|
14351
14783
|
mtimeMs = 0;
|
|
14352
14784
|
}
|
|
@@ -14356,16 +14788,16 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
14356
14788
|
}
|
|
14357
14789
|
try {
|
|
14358
14790
|
const root = worktreesRoot(repoPath);
|
|
14359
|
-
if ((0,
|
|
14360
|
-
for (const entry of (0,
|
|
14791
|
+
if ((0, import_node_fs36.existsSync)(root)) {
|
|
14792
|
+
for (const entry of (0, import_node_fs36.readdirSync)(root, { withFileTypes: true })) {
|
|
14361
14793
|
if (!entry.isDirectory()) continue;
|
|
14362
|
-
const path2 = (0,
|
|
14794
|
+
const path2 = (0, import_node_path33.join)(root, entry.name).replace(/\/$/, "");
|
|
14363
14795
|
if (known.has(path2) || seen.has(path2)) continue;
|
|
14364
|
-
if (!(0,
|
|
14796
|
+
if (!(0, import_node_fs36.existsSync)((0, import_node_path33.join)(path2, ".git"))) continue;
|
|
14365
14797
|
seen.add(path2);
|
|
14366
14798
|
let mtimeMs = 0;
|
|
14367
14799
|
try {
|
|
14368
|
-
mtimeMs = (0,
|
|
14800
|
+
mtimeMs = (0, import_node_fs36.statSync)(path2).mtimeMs;
|
|
14369
14801
|
} catch {
|
|
14370
14802
|
mtimeMs = Date.now();
|
|
14371
14803
|
}
|
|
@@ -14511,8 +14943,8 @@ async function applyThreadIntoMain(thread, opts) {
|
|
|
14511
14943
|
}
|
|
14512
14944
|
|
|
14513
14945
|
// src/git/clone-repo.ts
|
|
14514
|
-
var
|
|
14515
|
-
var
|
|
14946
|
+
var import_node_fs37 = require("fs");
|
|
14947
|
+
var import_node_path34 = require("path");
|
|
14516
14948
|
var import_execa6 = require("execa");
|
|
14517
14949
|
init_paths();
|
|
14518
14950
|
init_workspaces();
|
|
@@ -14522,12 +14954,12 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
14522
14954
|
if (!url) throw new Error("Clone URL is required");
|
|
14523
14955
|
let name = opts.name?.trim();
|
|
14524
14956
|
if (!name) {
|
|
14525
|
-
const leaf = (0,
|
|
14957
|
+
const leaf = (0, import_node_path34.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
|
|
14526
14958
|
name = leaf || "repo";
|
|
14527
14959
|
}
|
|
14528
14960
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
14529
|
-
const dest = (0,
|
|
14530
|
-
if ((0,
|
|
14961
|
+
const dest = (0, import_node_path34.join)(sideboardReposDir(), name);
|
|
14962
|
+
if ((0, import_node_fs37.existsSync)(dest)) {
|
|
14531
14963
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
14532
14964
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
14533
14965
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -14549,8 +14981,8 @@ init_orchestrator_capable();
|
|
|
14549
14981
|
|
|
14550
14982
|
// src/review/request-review.ts
|
|
14551
14983
|
var import_node_crypto8 = require("crypto");
|
|
14552
|
-
var
|
|
14553
|
-
var
|
|
14984
|
+
var import_node_fs38 = require("fs");
|
|
14985
|
+
var import_node_path35 = require("path");
|
|
14554
14986
|
init_global_workspace();
|
|
14555
14987
|
init_thread_store();
|
|
14556
14988
|
|
|
@@ -14698,22 +15130,22 @@ function shouldRefreshReviewRequestTemplate(content) {
|
|
|
14698
15130
|
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
14699
15131
|
}
|
|
14700
15132
|
function readTextIfPresent(abs) {
|
|
14701
|
-
if (!(0,
|
|
15133
|
+
if (!(0, import_node_fs38.existsSync)(abs)) return null;
|
|
14702
15134
|
try {
|
|
14703
|
-
const content = (0,
|
|
15135
|
+
const content = (0, import_node_fs38.readFileSync)(abs, "utf8");
|
|
14704
15136
|
return content.trim() ? content : null;
|
|
14705
15137
|
} catch {
|
|
14706
15138
|
return null;
|
|
14707
15139
|
}
|
|
14708
15140
|
}
|
|
14709
15141
|
function ensureAttachmentsGitignore(worktreePath) {
|
|
14710
|
-
const gitignoreAbs = (0,
|
|
14711
|
-
if ((0,
|
|
14712
|
-
(0,
|
|
14713
|
-
(0,
|
|
15142
|
+
const gitignoreAbs = (0, import_node_path35.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
15143
|
+
if ((0, import_node_fs38.existsSync)(gitignoreAbs)) return;
|
|
15144
|
+
(0, import_node_fs38.mkdirSync)((0, import_node_path35.dirname)(gitignoreAbs), { recursive: true });
|
|
15145
|
+
(0, import_node_fs38.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
14714
15146
|
}
|
|
14715
15147
|
function resolveReviewGuidelines(worktreePath) {
|
|
14716
|
-
const repoAbs = (0,
|
|
15148
|
+
const repoAbs = (0, import_node_path35.join)(worktreePath, REPO_REVIEW_PATH);
|
|
14717
15149
|
const repoContent = readTextIfPresent(repoAbs);
|
|
14718
15150
|
if (repoContent) {
|
|
14719
15151
|
return {
|
|
@@ -14723,7 +15155,7 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
14723
15155
|
source: "repo"
|
|
14724
15156
|
};
|
|
14725
15157
|
}
|
|
14726
|
-
const localAbs = (0,
|
|
15158
|
+
const localAbs = (0, import_node_path35.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
14727
15159
|
const localContent = readTextIfPresent(localAbs);
|
|
14728
15160
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
14729
15161
|
return {
|
|
@@ -14733,7 +15165,7 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
14733
15165
|
source: "local"
|
|
14734
15166
|
};
|
|
14735
15167
|
}
|
|
14736
|
-
const legacyAbs = (0,
|
|
15168
|
+
const legacyAbs = (0, import_node_path35.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
|
|
14737
15169
|
const legacyContent = readTextIfPresent(legacyAbs);
|
|
14738
15170
|
if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
|
|
14739
15171
|
return {
|
|
@@ -14744,8 +15176,8 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
14744
15176
|
};
|
|
14745
15177
|
}
|
|
14746
15178
|
ensureAttachmentsGitignore(worktreePath);
|
|
14747
|
-
(0,
|
|
14748
|
-
(0,
|
|
15179
|
+
(0, import_node_fs38.mkdirSync)((0, import_node_path35.dirname)(localAbs), { recursive: true });
|
|
15180
|
+
(0, import_node_fs38.writeFileSync)(localAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
|
|
14749
15181
|
return {
|
|
14750
15182
|
path: REVIEW_REQUEST_PATH,
|
|
14751
15183
|
name: REVIEW_REQUEST_NAME,
|
|
@@ -14754,7 +15186,7 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
14754
15186
|
};
|
|
14755
15187
|
}
|
|
14756
15188
|
function ensureReviewRequestFile(worktreePath) {
|
|
14757
|
-
const repoAbs = (0,
|
|
15189
|
+
const repoAbs = (0, import_node_path35.join)(worktreePath, REPO_REVIEW_PATH);
|
|
14758
15190
|
const repoContent = readTextIfPresent(repoAbs);
|
|
14759
15191
|
if (repoContent) {
|
|
14760
15192
|
return {
|
|
@@ -14764,10 +15196,10 @@ function ensureReviewRequestFile(worktreePath) {
|
|
|
14764
15196
|
source: "repo"
|
|
14765
15197
|
};
|
|
14766
15198
|
}
|
|
14767
|
-
const localAbs = (0,
|
|
14768
|
-
const localContent = readTextIfPresent(localAbs) ?? readTextIfPresent((0,
|
|
15199
|
+
const localAbs = (0, import_node_path35.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
15200
|
+
const localContent = readTextIfPresent(localAbs) ?? readTextIfPresent((0, import_node_path35.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
|
|
14769
15201
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
14770
|
-
const path2 = (0,
|
|
15202
|
+
const path2 = (0, import_node_fs38.existsSync)(localAbs) ? REVIEW_REQUEST_PATH : LEGACY_REVIEW_REQUEST_PATH;
|
|
14771
15203
|
return {
|
|
14772
15204
|
path: path2,
|
|
14773
15205
|
name: REVIEW_REQUEST_NAME,
|
|
@@ -14775,8 +15207,8 @@ function ensureReviewRequestFile(worktreePath) {
|
|
|
14775
15207
|
source: "local"
|
|
14776
15208
|
};
|
|
14777
15209
|
}
|
|
14778
|
-
(0,
|
|
14779
|
-
(0,
|
|
15210
|
+
(0, import_node_fs38.mkdirSync)((0, import_node_path35.dirname)(repoAbs), { recursive: true });
|
|
15211
|
+
(0, import_node_fs38.writeFileSync)(repoAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
|
|
14780
15212
|
return {
|
|
14781
15213
|
path: REPO_REVIEW_PATH,
|
|
14782
15214
|
name: REPO_REVIEW_NAME,
|
|
@@ -14796,7 +15228,7 @@ function buildReviewRequestAttachment(content, opts) {
|
|
|
14796
15228
|
};
|
|
14797
15229
|
}
|
|
14798
15230
|
function readExistingReviewRequestFile(worktreePath) {
|
|
14799
|
-
return readTextIfPresent((0,
|
|
15231
|
+
return readTextIfPresent((0, import_node_path35.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path35.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path35.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
|
|
14800
15232
|
}
|
|
14801
15233
|
async function requestReview(threadRef, send2) {
|
|
14802
15234
|
const from = findThreadByRef(threadRef);
|
|
@@ -15057,7 +15489,7 @@ var Orchestrator = class {
|
|
|
15057
15489
|
}
|
|
15058
15490
|
continue;
|
|
15059
15491
|
}
|
|
15060
|
-
if (!(0,
|
|
15492
|
+
if (!(0, import_node_fs41.existsSync)(thread.worktreePath)) {
|
|
15061
15493
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
15062
15494
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
15063
15495
|
continue;
|
|
@@ -15560,10 +15992,12 @@ var Orchestrator = class {
|
|
|
15560
15992
|
if (event.type === "stderr" && typeof event.data === "string") {
|
|
15561
15993
|
pushTurnStderr(stderrTail, event.data);
|
|
15562
15994
|
}
|
|
15563
|
-
|
|
15564
|
-
|
|
15565
|
-
|
|
15566
|
-
|
|
15995
|
+
if (event.type !== "stdout" && event.type !== "thinking") {
|
|
15996
|
+
const live = readThread(threadId);
|
|
15997
|
+
if (live?.lastError?.includes("reconciled on startup") && (this.activeTurns.has(threadId) || this.startingTurns.has(threadId))) {
|
|
15998
|
+
setStatus(threadId, "running");
|
|
15999
|
+
this.emit({ type: "status_changed", threadId, status: "running" });
|
|
16000
|
+
}
|
|
15567
16001
|
}
|
|
15568
16002
|
}
|
|
15569
16003
|
);
|
|
@@ -16147,8 +16581,9 @@ var Orchestrator = class {
|
|
|
16147
16581
|
return result;
|
|
16148
16582
|
}
|
|
16149
16583
|
async mergePr(threadRef) {
|
|
16150
|
-
const { thread,
|
|
16584
|
+
const { thread, selectors, cwd } = await this.withPrSelector(threadRef);
|
|
16151
16585
|
this.assertNotGlobal(thread, "Merge PR");
|
|
16586
|
+
const selector = selectors[0];
|
|
16152
16587
|
if (!selector) throw new Error("No pull request linked to this thread");
|
|
16153
16588
|
const result = await mergePr(cwd, selector);
|
|
16154
16589
|
const state = normalizePrState(result.state) || "MERGED";
|
|
@@ -16168,29 +16603,34 @@ var Orchestrator = class {
|
|
|
16168
16603
|
await this.persistPrMetaAndMaybeArchive(thread, metaLike);
|
|
16169
16604
|
return { url: metaLike.url, state };
|
|
16170
16605
|
}
|
|
16171
|
-
/** Resolve PR
|
|
16606
|
+
/** Resolve PR selectors and optionally persist `prUrl` when found. */
|
|
16172
16607
|
async withPrSelector(threadRef) {
|
|
16173
16608
|
const thread = this.requireThread(threadRef);
|
|
16174
|
-
const
|
|
16609
|
+
const selectors = resolvePrSelectors(thread);
|
|
16175
16610
|
const cwd = thread.worktreePath;
|
|
16176
16611
|
if (!cwd?.trim()) {
|
|
16177
16612
|
throw new Error(`Thread ${threadRef} has no worktreePath`);
|
|
16178
16613
|
}
|
|
16179
|
-
return { thread,
|
|
16614
|
+
return { thread, selectors, cwd };
|
|
16180
16615
|
}
|
|
16181
16616
|
async getPrChecks(threadRef) {
|
|
16182
|
-
const {
|
|
16183
|
-
|
|
16184
|
-
|
|
16617
|
+
const { selectors, cwd } = await this.withPrSelector(threadRef);
|
|
16618
|
+
for (const selector of selectors) {
|
|
16619
|
+
const checks = await getPrChecks(cwd, selector);
|
|
16620
|
+
if (checks) return checks;
|
|
16621
|
+
}
|
|
16622
|
+
return null;
|
|
16185
16623
|
}
|
|
16186
16624
|
async getPrMeta(threadRef) {
|
|
16187
|
-
const { thread,
|
|
16188
|
-
|
|
16189
|
-
|
|
16190
|
-
|
|
16191
|
-
|
|
16625
|
+
const { thread, selectors, cwd } = await this.withPrSelector(threadRef);
|
|
16626
|
+
for (const selector of selectors) {
|
|
16627
|
+
const meta = await getPrMeta(cwd, selector);
|
|
16628
|
+
if (meta) {
|
|
16629
|
+
await this.persistPrMetaAndMaybeArchive(thread, meta);
|
|
16630
|
+
return meta;
|
|
16631
|
+
}
|
|
16192
16632
|
}
|
|
16193
|
-
return
|
|
16633
|
+
return null;
|
|
16194
16634
|
}
|
|
16195
16635
|
/**
|
|
16196
16636
|
* Persist PR URL/title/state and Conductor-style auto-archive when the PR
|
|
@@ -16314,9 +16754,12 @@ var Orchestrator = class {
|
|
|
16314
16754
|
return { stack: result.stack, threads: result.threads };
|
|
16315
16755
|
}
|
|
16316
16756
|
async getPrDetails(threadRef) {
|
|
16317
|
-
const { thread,
|
|
16318
|
-
|
|
16319
|
-
const
|
|
16757
|
+
const { thread, selectors, cwd } = await this.withPrSelector(threadRef);
|
|
16758
|
+
let details = null;
|
|
16759
|
+
for (const selector of selectors) {
|
|
16760
|
+
details = await getPrDetails(cwd, selector);
|
|
16761
|
+
if (details) break;
|
|
16762
|
+
}
|
|
16320
16763
|
if (details) {
|
|
16321
16764
|
const patch = {};
|
|
16322
16765
|
if (details.url && details.url !== thread.prUrl) patch.prUrl = details.url;
|
|
@@ -16543,7 +16986,7 @@ var Orchestrator = class {
|
|
|
16543
16986
|
this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
|
|
16544
16987
|
return restored2;
|
|
16545
16988
|
}
|
|
16546
|
-
if (!(0,
|
|
16989
|
+
if (!(0, import_node_fs41.existsSync)(thread.worktreePath)) {
|
|
16547
16990
|
const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
|
|
16548
16991
|
const { execa: execa7 } = await import("execa");
|
|
16549
16992
|
const slug = thread.worktreePath.split("/").pop();
|
|
@@ -16784,7 +17227,7 @@ init_coordinator_prompt();
|
|
|
16784
17227
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
16785
17228
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
16786
17229
|
var import_zod3 = require("zod");
|
|
16787
|
-
var
|
|
17230
|
+
var import_node_path38 = require("path");
|
|
16788
17231
|
init_worktree();
|
|
16789
17232
|
init_global_workspace();
|
|
16790
17233
|
init_list_models();
|
|
@@ -17398,6 +17841,7 @@ function registerLinearTools(server) {
|
|
|
17398
17841
|
}
|
|
17399
17842
|
|
|
17400
17843
|
// src/mcp/server.ts
|
|
17844
|
+
init_git_auth_mode();
|
|
17401
17845
|
var MAX_ORCH_THREADS = 5;
|
|
17402
17846
|
var CREATE_THREAD_TIMEOUT_MS = 9e4;
|
|
17403
17847
|
function withTimeout(promise, ms, label) {
|
|
@@ -17419,6 +17863,14 @@ function withTimeout(promise, ms, label) {
|
|
|
17419
17863
|
}
|
|
17420
17864
|
async function startMcpServer() {
|
|
17421
17865
|
const orch = getOrchestrator();
|
|
17866
|
+
try {
|
|
17867
|
+
await warmGithubAgentAuth();
|
|
17868
|
+
} catch (err) {
|
|
17869
|
+
console.error(
|
|
17870
|
+
"[sideboard-mcp] GitHub agent auth warm skipped:",
|
|
17871
|
+
err instanceof Error ? err.message : err
|
|
17872
|
+
);
|
|
17873
|
+
}
|
|
17422
17874
|
try {
|
|
17423
17875
|
const { maxConcurrentAgents: maxConcurrentAgents2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
17424
17876
|
orch.setMaxConcurrent(maxConcurrentAgents2());
|
|
@@ -17462,7 +17914,7 @@ async function startMcpServer() {
|
|
|
17462
17914
|
async () => {
|
|
17463
17915
|
const threads = orch.getThreads(true);
|
|
17464
17916
|
const lines = threads.map((t) => {
|
|
17465
|
-
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0,
|
|
17917
|
+
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path38.basename)(t.repoPath) || t.repoPath;
|
|
17466
17918
|
return `${t.id.slice(0, 8)} ${t.status.padEnd(9)} ${t.agent.padEnd(8)} ${repo} ${t.sourceType}:${t.sourceRef} ${t.title} sideboard://thread/${t.id}${t.devPort ? ` http://localhost:${t.devPort}` : ""}`;
|
|
17467
17919
|
});
|
|
17468
17920
|
return {
|
|
@@ -17525,7 +17977,7 @@ async function startMcpServer() {
|
|
|
17525
17977
|
);
|
|
17526
17978
|
server.tool(
|
|
17527
17979
|
"ask_user",
|
|
17528
|
-
"Ask the user clarifying multiple-choice
|
|
17980
|
+
"Ask the user a clarifying multiple-choice question in Sideboard\u2019s composer. Call only when work is blocked on choosing among a few concrete options (approach fork, which API, auth vs cookies). Do not call for greetings, check-ins, \u201Chello\u201D, open-ended how-can-I-help, or to invent a menu of possible next tasks \u2014 reply in chat instead. If one option is the obvious default, proceed without asking. Before calling, write a short chat message explaining the decision and what each option means. Include a description on every option. After calling, stop and wait for answers. Not for \u201Cis the plan ready?\u201D.",
|
|
17529
17981
|
{
|
|
17530
17982
|
questions: import_zod3.z.array(
|
|
17531
17983
|
import_zod3.z.object({
|
|
@@ -18770,6 +19222,76 @@ init_accounts();
|
|
|
18770
19222
|
init_connected_teams();
|
|
18771
19223
|
init_injected_mcp();
|
|
18772
19224
|
|
|
19225
|
+
// src/agents/user-mcp-config.ts
|
|
19226
|
+
var import_node_fs42 = require("fs");
|
|
19227
|
+
var import_node_os12 = require("os");
|
|
19228
|
+
var import_node_path39 = require("path");
|
|
19229
|
+
init_paths();
|
|
19230
|
+
init_injected_mcp();
|
|
19231
|
+
function userCursorMcpConfigPath() {
|
|
19232
|
+
return (0, import_node_path39.join)((0, import_node_os12.homedir)(), ".cursor", "mcp.json");
|
|
19233
|
+
}
|
|
19234
|
+
function userClaudeMcpConfigPath() {
|
|
19235
|
+
return (0, import_node_path39.join)((0, import_node_os12.homedir)(), ".claude.json");
|
|
19236
|
+
}
|
|
19237
|
+
function asObject(value) {
|
|
19238
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
19239
|
+
return { ...value };
|
|
19240
|
+
}
|
|
19241
|
+
function stripElectronSpawnEnv(env) {
|
|
19242
|
+
if (!env) return void 0;
|
|
19243
|
+
const next = { ...env };
|
|
19244
|
+
delete next.ELECTRON_RUN_AS_NODE;
|
|
19245
|
+
delete next.ELECTRON_RUN_AS_NODE;
|
|
19246
|
+
return Object.keys(next).length > 0 ? next : void 0;
|
|
19247
|
+
}
|
|
19248
|
+
function mergeSideboardIntoMcpServersJson(existing, sideboard) {
|
|
19249
|
+
const root = asObject(existing);
|
|
19250
|
+
const servers = asObject(root.mcpServers);
|
|
19251
|
+
const env = stripElectronSpawnEnv(sideboard.env);
|
|
19252
|
+
servers.sideboard = {
|
|
19253
|
+
command: sideboard.command,
|
|
19254
|
+
...sideboard.args && sideboard.args.length > 0 ? { args: sideboard.args } : {},
|
|
19255
|
+
...env ? { env } : {}
|
|
19256
|
+
};
|
|
19257
|
+
return { ...root, mcpServers: servers };
|
|
19258
|
+
}
|
|
19259
|
+
function writeMergedMcpServersJson(configPath, sideboard) {
|
|
19260
|
+
let existing = {};
|
|
19261
|
+
if ((0, import_node_fs42.existsSync)(configPath)) {
|
|
19262
|
+
try {
|
|
19263
|
+
existing = JSON.parse((0, import_node_fs42.readFileSync)(configPath, "utf8"));
|
|
19264
|
+
} catch {
|
|
19265
|
+
existing = {};
|
|
19266
|
+
}
|
|
19267
|
+
}
|
|
19268
|
+
const next = mergeSideboardIntoMcpServersJson(existing, sideboard);
|
|
19269
|
+
(0, import_node_fs42.mkdirSync)((0, import_node_path39.dirname)(configPath), { recursive: true });
|
|
19270
|
+
(0, import_node_fs42.writeFileSync)(configPath, `${JSON.stringify(next, null, 2)}
|
|
19271
|
+
`);
|
|
19272
|
+
}
|
|
19273
|
+
function launchFromResolved(server) {
|
|
19274
|
+
return {
|
|
19275
|
+
command: server.command,
|
|
19276
|
+
args: server.args,
|
|
19277
|
+
env: {
|
|
19278
|
+
...server.env ?? {},
|
|
19279
|
+
SIDEBOARD_APP_DATA: appDataDir()
|
|
19280
|
+
}
|
|
19281
|
+
};
|
|
19282
|
+
}
|
|
19283
|
+
async function registerPackagedUserMcpClients() {
|
|
19284
|
+
const launch = launchFromResolved(await resolveSideboardMcpServer());
|
|
19285
|
+
const cursor = userCursorMcpConfigPath();
|
|
19286
|
+
writeMergedMcpServersJson(cursor, launch);
|
|
19287
|
+
const claude = userClaudeMcpConfigPath();
|
|
19288
|
+
if ((0, import_node_fs42.existsSync)(claude)) {
|
|
19289
|
+
writeMergedMcpServersJson(claude, launch);
|
|
19290
|
+
return { cursor, claude };
|
|
19291
|
+
}
|
|
19292
|
+
return { cursor };
|
|
19293
|
+
}
|
|
19294
|
+
|
|
18773
19295
|
// src/slack/oauth.ts
|
|
18774
19296
|
var import_node_crypto10 = require("crypto");
|
|
18775
19297
|
init_app_settings();
|
|
@@ -20076,9 +20598,9 @@ var import_node_http3 = require("http");
|
|
|
20076
20598
|
var import_ws3 = require("ws");
|
|
20077
20599
|
|
|
20078
20600
|
// src/slack/relay-static.ts
|
|
20079
|
-
var
|
|
20601
|
+
var import_node_fs43 = require("fs");
|
|
20080
20602
|
var import_promises = require("fs/promises");
|
|
20081
|
-
var
|
|
20603
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
20082
20604
|
var TYPES = {
|
|
20083
20605
|
".css": "text/css; charset=utf-8",
|
|
20084
20606
|
".html": "text/html; charset=utf-8",
|
|
@@ -20109,9 +20631,9 @@ function resolveStaticPath(root, requestUrl) {
|
|
|
20109
20631
|
return null;
|
|
20110
20632
|
}
|
|
20111
20633
|
if (!pathname.startsWith("/") || pathname.includes("\0")) return null;
|
|
20112
|
-
const rootResolved =
|
|
20113
|
-
const candidate =
|
|
20114
|
-
if (candidate !== rootResolved && !candidate.startsWith(rootResolved +
|
|
20634
|
+
const rootResolved = import_node_path40.default.resolve(root);
|
|
20635
|
+
const candidate = import_node_path40.default.resolve(rootResolved, `.${pathname}`);
|
|
20636
|
+
if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path40.default.sep)) {
|
|
20115
20637
|
return null;
|
|
20116
20638
|
}
|
|
20117
20639
|
return candidate;
|
|
@@ -20125,7 +20647,7 @@ async function fileSize(file) {
|
|
|
20125
20647
|
}
|
|
20126
20648
|
}
|
|
20127
20649
|
function sendFile(req, res, file, size) {
|
|
20128
|
-
const ext =
|
|
20650
|
+
const ext = import_node_path40.default.extname(file).toLowerCase();
|
|
20129
20651
|
res.writeHead(200, {
|
|
20130
20652
|
"Content-Type": TYPES[ext] ?? "application/octet-stream",
|
|
20131
20653
|
"Content-Length": size,
|
|
@@ -20135,7 +20657,7 @@ function sendFile(req, res, file, size) {
|
|
|
20135
20657
|
res.end();
|
|
20136
20658
|
return true;
|
|
20137
20659
|
}
|
|
20138
|
-
(0,
|
|
20660
|
+
(0, import_node_fs43.createReadStream)(file).pipe(res);
|
|
20139
20661
|
return true;
|
|
20140
20662
|
}
|
|
20141
20663
|
async function tryServeStatic(req, res, root) {
|
|
@@ -20144,7 +20666,7 @@ async function tryServeStatic(req, res, root) {
|
|
|
20144
20666
|
if (!candidate) return false;
|
|
20145
20667
|
const direct = await fileSize(candidate);
|
|
20146
20668
|
if (direct != null) return sendFile(req, res, candidate, direct);
|
|
20147
|
-
const asIndex =
|
|
20669
|
+
const asIndex = import_node_path40.default.join(candidate, "index.html");
|
|
20148
20670
|
const indexSize = await fileSize(asIndex);
|
|
20149
20671
|
if (indexSize != null) return sendFile(req, res, asIndex, indexSize);
|
|
20150
20672
|
return false;
|
|
@@ -20477,6 +20999,7 @@ async function startSlackRelayServer(opts) {
|
|
|
20477
20999
|
cleanupOrphanWorktrees,
|
|
20478
21000
|
cloneRepoIntoSideboard,
|
|
20479
21001
|
codexAdapter,
|
|
21002
|
+
codexSandboxWritableRootsArgs,
|
|
20480
21003
|
codexUnattendedGitConfigArgs,
|
|
20481
21004
|
coerceOrchestratorAgent,
|
|
20482
21005
|
collectTakenTeamSlugs,
|
|
@@ -20593,6 +21116,7 @@ async function startSlackRelayServer(opts) {
|
|
|
20593
21116
|
getPr,
|
|
20594
21117
|
getPrChecks,
|
|
20595
21118
|
getPrDetails,
|
|
21119
|
+
getPrForHeadBranch,
|
|
20596
21120
|
getPrMeta,
|
|
20597
21121
|
getPrStack,
|
|
20598
21122
|
getRepoSetupInfo,
|
|
@@ -20629,6 +21153,7 @@ async function startSlackRelayServer(opts) {
|
|
|
20629
21153
|
isCloudCoordinatorThread,
|
|
20630
21154
|
isConductorBundledCli,
|
|
20631
21155
|
isCursorAutoModel,
|
|
21156
|
+
isDefaultishSourceRef,
|
|
20632
21157
|
isDirty,
|
|
20633
21158
|
isGhRateLimitError,
|
|
20634
21159
|
isGlobalRepoPath,
|
|
@@ -20695,8 +21220,10 @@ async function startSlackRelayServer(opts) {
|
|
|
20695
21220
|
maybeCompactContext,
|
|
20696
21221
|
mcpAllowTools,
|
|
20697
21222
|
mcpAuthWarnings,
|
|
21223
|
+
mergeAgentGitAuthEnv,
|
|
20698
21224
|
mergePr,
|
|
20699
21225
|
mergePrStack,
|
|
21226
|
+
mergeSideboardIntoMcpServersJson,
|
|
20700
21227
|
mergeUsage,
|
|
20701
21228
|
nextPastedTextName,
|
|
20702
21229
|
nextThinkingEffort,
|
|
@@ -20747,6 +21274,7 @@ async function startSlackRelayServer(opts) {
|
|
|
20747
21274
|
recordSlackOutboundWatch,
|
|
20748
21275
|
refreshGitHubAuth,
|
|
20749
21276
|
refreshSlackReplyBadges,
|
|
21277
|
+
registerPackagedUserMcpClients,
|
|
20750
21278
|
releaseCaffeinateHoldForThread,
|
|
20751
21279
|
removeWorkspace,
|
|
20752
21280
|
removeWorktree,
|
|
@@ -20755,9 +21283,11 @@ async function startSlackRelayServer(opts) {
|
|
|
20755
21283
|
requestReview,
|
|
20756
21284
|
requireAgent,
|
|
20757
21285
|
resetGhStackDetectCache,
|
|
21286
|
+
resetGithubAgentTokenMemo,
|
|
20758
21287
|
resolveAgentExecutable,
|
|
20759
21288
|
resolveAgentGitAuthEnv,
|
|
20760
21289
|
resolveClaudeExecutable,
|
|
21290
|
+
resolveCodexGitWritableRoots,
|
|
20761
21291
|
resolveCommandBinarySync,
|
|
20762
21292
|
resolveConductorCursorAgentId,
|
|
20763
21293
|
resolveCursorModelId,
|
|
@@ -20774,6 +21304,7 @@ async function startSlackRelayServer(opts) {
|
|
|
20774
21304
|
resolveNewThreadOptions,
|
|
20775
21305
|
resolvePlanMarkdown,
|
|
20776
21306
|
resolvePrSelector,
|
|
21307
|
+
resolvePrSelectors,
|
|
20777
21308
|
resolveQuotaFallbackAgent,
|
|
20778
21309
|
resolveRepoRoot,
|
|
20779
21310
|
resolveReviewGuidelines,
|
|
@@ -20796,6 +21327,7 @@ async function startSlackRelayServer(opts) {
|
|
|
20796
21327
|
sanitizeMcpServerName,
|
|
20797
21328
|
saveAppSettings,
|
|
20798
21329
|
saveLinearOAuth,
|
|
21330
|
+
scrubGithubTokensFromChildEnv,
|
|
20799
21331
|
secureFileUnlocksWith,
|
|
20800
21332
|
setCaffeinateHold,
|
|
20801
21333
|
setHttpFetchImpl,
|
|
@@ -20866,7 +21398,10 @@ async function startSlackRelayServer(opts) {
|
|
|
20866
21398
|
updateLinearIssue,
|
|
20867
21399
|
updateOpencodeSettings,
|
|
20868
21400
|
updateThread,
|
|
21401
|
+
userClaudeMcpConfigPath,
|
|
21402
|
+
userCursorMcpConfigPath,
|
|
20869
21403
|
validateLinearApiKey,
|
|
21404
|
+
warmGithubAgentAuth,
|
|
20870
21405
|
withAgentInstructions,
|
|
20871
21406
|
withExportedPath,
|
|
20872
21407
|
withThreadLock,
|