@sideboard-ai/core 0.1.85 → 0.1.87
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 +77 -29
- package/dist/agents/cursor-runner.js +55 -17
- package/dist/{agents-YAYNNJWC.js → agents-V6PVSQYH.js} +8 -8
- package/dist/{agents-FD77JUOP.js → agents-W5446HSV.js} +8 -8
- package/dist/{app-settings-PEXK5VEX.js → app-settings-F36ISTCF.js} +2 -2
- package/dist/{app-settings-K6RFCRF6.js → app-settings-HFINR3XG.js} +2 -2
- package/dist/{caffeinate-hold-EAZNWJBE.js → caffeinate-hold-I7SG6UQR.js} +2 -2
- package/dist/{caffeinate-hold-OHAUWOA6.js → caffeinate-hold-U3QJBV67.js} +2 -2
- package/dist/{chunk-XVFV56JG.js → chunk-3MA6JH6G.js} +5 -5
- package/dist/{chunk-FWJYLBO6.js → chunk-3WA37BRI.js} +1 -1
- package/dist/{chunk-JTHWVYSD.js → chunk-4PTN2LED.js} +5 -5
- package/dist/{chunk-RV6DBEDQ.js → chunk-7KDBDMNC.js} +1 -1
- package/dist/{chunk-SH75CXJR.js → chunk-A7LONVNO.js} +5 -5
- package/dist/{chunk-M37RITA6.js → chunk-B4R2VB2A.js} +164 -30
- package/dist/{chunk-6WQAYBVE.js → chunk-CY45C3GA.js} +4 -4
- package/dist/{chunk-6K5VAPVR.js → chunk-DKHGWYWR.js} +1 -1
- package/dist/{chunk-2N5DVTGH.js → chunk-HBXQQ5TO.js} +3 -3
- package/dist/{chunk-7MV3RXSC.js → chunk-JL4SJ6V7.js} +137 -26
- package/dist/{chunk-7FD7COKE.js → chunk-JOF3XIEM.js} +1 -1
- package/dist/{chunk-KRAUS3RF.js → chunk-L63LLCTX.js} +4 -4
- package/dist/{chunk-MFF2RE3I.js → chunk-NZPGMNFC.js} +1 -1
- package/dist/{chunk-HHTHF5BQ.js → chunk-QSLE4VEM.js} +4 -4
- package/dist/{chunk-3CCRD6WS.js → chunk-QWNROSRB.js} +6 -6
- package/dist/{chunk-JFQ2M6NQ.js → chunk-R2EOZNQI.js} +3 -3
- package/dist/{chunk-AY53MPDE.js → chunk-TC2KY5G7.js} +1 -1
- package/dist/{chunk-WGI6KXKJ.js → chunk-U4GZKLIV.js} +6 -6
- package/dist/{chunk-6GKDYUTJ.js → chunk-UVNXLTFB.js} +5 -5
- package/dist/{chunk-I3FRXL7J.js → chunk-XY6XXMAK.js} +1 -1
- package/dist/{connected-teams-BNBM7OIC.js → connected-teams-SWHJWK2A.js} +2 -2
- package/dist/{connected-teams-LSQ5TAZP.js → connected-teams-TLVKZPJP.js} +2 -2
- package/dist/{coordinator-prompt-VN7FF76K.js → coordinator-prompt-EC3KQLN3.js} +5 -5
- package/dist/{coordinator-prompt-YYQSPLIP.js → coordinator-prompt-PYRAXZN3.js} +5 -5
- package/dist/{cursor-recover-L5PNQUDT.js → cursor-recover-G34BYKL2.js} +1 -1
- package/dist/{cursor-recover-NNK7JPQM.js → cursor-recover-S5ORPW34.js} +1 -1
- package/dist/{global-workspace-BRIDCBMY.js → global-workspace-ICWOWUW6.js} +6 -6
- package/dist/{global-workspace-U3XVTQLL.js → global-workspace-T5IAJF4R.js} +6 -6
- package/dist/index.cjs +633 -526
- package/dist/index.d.cts +45 -11
- package/dist/index.d.ts +45 -11
- package/dist/index.js +212 -252
- package/dist/mcp/run-stdio.cjs +570 -490
- package/dist/mcp/run-stdio.js +184 -225
- package/dist/{paths-VPH3ITBK.js → paths-JQM2XRAD.js} +1 -1
- package/dist/{paths-2OFB7UJG.js → paths-TZX4L5X7.js} +1 -1
- package/dist/{thread-store-BUBR24YA.js → thread-store-V7NOOXKE.js} +2 -2
- package/dist/{thread-store-XTPFCJAI.js → thread-store-XAKWCV2E.js} +2 -2
- package/dist/{workspaces-IWQIWAMQ.js → workspaces-AJCAFW64.js} +7 -7
- package/dist/{workspaces-AIZDG6PS.js → workspaces-J4ULXOUH.js} +7 -7
- package/dist/{worktree-6ZALJUWG.js → worktree-4Z2VSHAQ.js} +4 -4
- package/dist/{worktree-7Y22WHR7.js → worktree-H57CCHWO.js} +4 -4
- package/package.json +1 -1
|
@@ -1,17 +1,136 @@
|
|
|
1
1
|
// src/store/paths.ts
|
|
2
2
|
import { basename } from "path";
|
|
3
3
|
import { homedir as homedir2 } from "os";
|
|
4
|
-
import { join as
|
|
4
|
+
import { join as join4 } from "path";
|
|
5
5
|
import { mkdirSync } from "fs";
|
|
6
6
|
|
|
7
7
|
// src/hook/settings.ts
|
|
8
|
-
import { existsSync, readFileSync } from "fs";
|
|
8
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
9
9
|
import { homedir } from "os";
|
|
10
|
-
import { join } from "path";
|
|
10
|
+
import { join as join3 } from "path";
|
|
11
11
|
import { parse as parseToml } from "smol-toml";
|
|
12
|
+
|
|
13
|
+
// src/hook/convention-setup.ts
|
|
14
|
+
import { existsSync, statSync } from "fs";
|
|
15
|
+
import { join } from "path";
|
|
16
|
+
var CONVENTION_SETUP_RELPATHS = [
|
|
17
|
+
"script/setup",
|
|
18
|
+
"bin/setup",
|
|
19
|
+
"scripts/setup.sh",
|
|
20
|
+
"scripts/setup"
|
|
21
|
+
];
|
|
22
|
+
function isFile(path) {
|
|
23
|
+
try {
|
|
24
|
+
return statSync(path).isFile();
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function normPath(p) {
|
|
30
|
+
return p.replace(/\/+$/, "");
|
|
31
|
+
}
|
|
32
|
+
function findConventionSetup(worktreePath, repoPath) {
|
|
33
|
+
const roots = [
|
|
34
|
+
{ root: worktreePath, where: "worktree" }
|
|
35
|
+
];
|
|
36
|
+
if (repoPath && normPath(repoPath) !== normPath(worktreePath)) {
|
|
37
|
+
roots.push({ root: repoPath, where: "main repo" });
|
|
38
|
+
}
|
|
39
|
+
for (const { root, where } of roots) {
|
|
40
|
+
for (const relPath of CONVENTION_SETUP_RELPATHS) {
|
|
41
|
+
const absPath = join(root, relPath);
|
|
42
|
+
if (!existsSync(absPath) || !isFile(absPath)) continue;
|
|
43
|
+
return {
|
|
44
|
+
relPath,
|
|
45
|
+
absPath,
|
|
46
|
+
command: `bash ${JSON.stringify(absPath)}`,
|
|
47
|
+
source: `${relPath} (${where})`
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
function hasConventionSetup(worktreePath, repoPath) {
|
|
54
|
+
return findConventionSetup(worktreePath, repoPath) !== null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/hook/cursor-worktrees.ts
|
|
58
|
+
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
59
|
+
import { join as join2 } from "path";
|
|
60
|
+
import { execa } from "execa";
|
|
61
|
+
import { createInterface } from "readline";
|
|
62
|
+
function loadCursorWorktreesJson(rootPath) {
|
|
63
|
+
const path = join2(rootPath, ".cursor", "worktrees.json");
|
|
64
|
+
if (!existsSync2(path)) return null;
|
|
65
|
+
try {
|
|
66
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function resolveSetupSpec(config) {
|
|
72
|
+
if (process.platform === "win32") {
|
|
73
|
+
return config["setup-worktree-windows"] ?? config["setup-worktree"] ?? null;
|
|
74
|
+
}
|
|
75
|
+
return config["setup-worktree-unix"] ?? config["setup-worktree"] ?? null;
|
|
76
|
+
}
|
|
77
|
+
async function runCursorWorktreeSetup(repoPath, worktreePath, onLine) {
|
|
78
|
+
const fromWorktree = loadCursorWorktreesJson(worktreePath);
|
|
79
|
+
const fromRepo = worktreePath !== repoPath ? loadCursorWorktreesJson(repoPath) : null;
|
|
80
|
+
const config = fromWorktree ?? fromRepo;
|
|
81
|
+
if (!config) return { ran: false, exitCode: null, source: null };
|
|
82
|
+
const spec = resolveSetupSpec(config);
|
|
83
|
+
if (!spec) return { ran: false, exitCode: null, source: null };
|
|
84
|
+
const sourceLabel = fromWorktree ? ".cursor/worktrees.json (worktree)" : ".cursor/worktrees.json (main repo)";
|
|
85
|
+
const env = {
|
|
86
|
+
...process.env,
|
|
87
|
+
ROOT_WORKTREE_PATH: repoPath
|
|
88
|
+
};
|
|
89
|
+
if (process.platform === "win32") {
|
|
90
|
+
env.ROOT_WORKTREE_PATH = repoPath;
|
|
91
|
+
}
|
|
92
|
+
const commands = Array.isArray(spec) ? spec : [spec.endsWith(".sh") || spec.endsWith(".ps1") ? join2(
|
|
93
|
+
fromWorktree ? worktreePath : repoPath,
|
|
94
|
+
".cursor",
|
|
95
|
+
spec
|
|
96
|
+
) : spec];
|
|
97
|
+
let lastExit = 0;
|
|
98
|
+
for (const command of commands) {
|
|
99
|
+
const isScriptPath = typeof spec === "string" && (spec.endsWith(".sh") || spec.endsWith(".ps1"));
|
|
100
|
+
const shell = process.platform === "win32" ? "powershell" : "bash";
|
|
101
|
+
const args = process.platform === "win32" ? isScriptPath ? ["-File", command] : ["-Command", command] : isScriptPath ? [command] : ["-lc", command];
|
|
102
|
+
onLine?.(`[cursor setup] ${command}`);
|
|
103
|
+
const child = execa(shell, args, {
|
|
104
|
+
cwd: worktreePath,
|
|
105
|
+
reject: false,
|
|
106
|
+
env
|
|
107
|
+
});
|
|
108
|
+
if (child.stdout && onLine) {
|
|
109
|
+
const rl = createInterface({ input: child.stdout });
|
|
110
|
+
rl.on("line", onLine);
|
|
111
|
+
}
|
|
112
|
+
if (child.stderr && onLine) {
|
|
113
|
+
const rl = createInterface({ input: child.stderr });
|
|
114
|
+
rl.on("line", onLine);
|
|
115
|
+
}
|
|
116
|
+
const result = await child;
|
|
117
|
+
lastExit = result.exitCode ?? null;
|
|
118
|
+
if (lastExit !== 0 && lastExit !== null) break;
|
|
119
|
+
}
|
|
120
|
+
return { ran: true, exitCode: lastExit, source: sourceLabel };
|
|
121
|
+
}
|
|
122
|
+
function hasCursorWorktreeSetup(worktreePath, repoPath) {
|
|
123
|
+
if (loadCursorWorktreesJson(worktreePath)) return true;
|
|
124
|
+
if (repoPath && repoPath !== worktreePath && loadCursorWorktreesJson(repoPath)) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/hook/settings.ts
|
|
12
131
|
function expandHome(path) {
|
|
13
132
|
if (path.startsWith("~/") || path === "~") {
|
|
14
|
-
return
|
|
133
|
+
return join3(homedir(), path.slice(2));
|
|
15
134
|
}
|
|
16
135
|
return path;
|
|
17
136
|
}
|
|
@@ -24,8 +143,8 @@ function parseAvailableIn(raw) {
|
|
|
24
143
|
return out.length ? out : void 0;
|
|
25
144
|
}
|
|
26
145
|
function parseSettingsFile(path, source) {
|
|
27
|
-
if (!
|
|
28
|
-
const raw =
|
|
146
|
+
if (!existsSync3(path)) return null;
|
|
147
|
+
const raw = readFileSync2(path, "utf8");
|
|
29
148
|
const data = parseToml(raw);
|
|
30
149
|
const scripts = data.scripts ?? {};
|
|
31
150
|
const setup = typeof scripts.setup === "string" ? scripts.setup : void 0;
|
|
@@ -128,15 +247,15 @@ function finalizeSettings(parsed) {
|
|
|
128
247
|
};
|
|
129
248
|
}
|
|
130
249
|
function familyFiles(rootPath, source) {
|
|
131
|
-
const dir =
|
|
250
|
+
const dir = join3(rootPath, `.${source}`);
|
|
132
251
|
return {
|
|
133
|
-
toml:
|
|
134
|
-
local:
|
|
252
|
+
toml: join3(dir, "settings.toml"),
|
|
253
|
+
local: join3(dir, "settings.local.toml")
|
|
135
254
|
};
|
|
136
255
|
}
|
|
137
256
|
function familyExists(rootPath, source) {
|
|
138
257
|
const files = familyFiles(rootPath, source);
|
|
139
|
-
return
|
|
258
|
+
return existsSync3(files.toml) || existsSync3(files.local);
|
|
140
259
|
}
|
|
141
260
|
function detectFamily(rootPath) {
|
|
142
261
|
if (familyExists(rootPath, "sideboard")) return "sideboard";
|
|
@@ -155,7 +274,7 @@ function loadAnyLocal(rootPath) {
|
|
|
155
274
|
loadLocalToml(rootPath, "sideboard")
|
|
156
275
|
);
|
|
157
276
|
}
|
|
158
|
-
function
|
|
277
|
+
function normPath2(p) {
|
|
159
278
|
return p.replace(/\/+$/, "");
|
|
160
279
|
}
|
|
161
280
|
function loadRepoSettings(repoPath) {
|
|
@@ -169,11 +288,11 @@ function loadRepoSettings(repoPath) {
|
|
|
169
288
|
}
|
|
170
289
|
function loadWorkspaceSettings(worktreePath, repoPath) {
|
|
171
290
|
const wtFamily = detectFamily(worktreePath);
|
|
172
|
-
const repoFamily = repoPath &&
|
|
291
|
+
const repoFamily = repoPath && normPath2(repoPath) !== normPath2(worktreePath) ? detectFamily(repoPath) : null;
|
|
173
292
|
const wtToml = wtFamily ? loadCommittedToml(worktreePath, wtFamily) : null;
|
|
174
293
|
const repoToml = repoPath && repoFamily ? loadCommittedToml(repoPath, repoFamily) : null;
|
|
175
294
|
let merged = wtToml ?? repoToml;
|
|
176
|
-
if (repoPath &&
|
|
295
|
+
if (repoPath && normPath2(repoPath) !== normPath2(worktreePath)) {
|
|
177
296
|
merged = mergeSettings(merged, loadAnyLocal(repoPath));
|
|
178
297
|
}
|
|
179
298
|
merged = mergeSettings(merged, loadAnyLocal(worktreePath));
|
|
@@ -187,7 +306,7 @@ function hasRepoHook(repoPath) {
|
|
|
187
306
|
}
|
|
188
307
|
function hasWorkspaceHook(worktreePath, repoPath) {
|
|
189
308
|
if (hasRepoHook(worktreePath)) return true;
|
|
190
|
-
if (repoPath &&
|
|
309
|
+
if (repoPath && normPath2(repoPath) !== normPath2(worktreePath) && hasRepoHook(repoPath)) {
|
|
191
310
|
return true;
|
|
192
311
|
}
|
|
193
312
|
return false;
|
|
@@ -199,16 +318,16 @@ function settingsSourceLabel(rootPath) {
|
|
|
199
318
|
const family = detectFamily(rootPath);
|
|
200
319
|
if (!family) return null;
|
|
201
320
|
const files = familyFiles(rootPath, family);
|
|
202
|
-
if (
|
|
321
|
+
if (existsSync3(files.toml) && existsSync3(files.local)) {
|
|
203
322
|
return `.${family}/settings.toml + local`;
|
|
204
323
|
}
|
|
205
|
-
if (
|
|
324
|
+
if (existsSync3(files.local)) return `.${family}/settings.local.toml`;
|
|
206
325
|
return `.${family}/settings.toml`;
|
|
207
326
|
}
|
|
208
327
|
function workspaceSettingsSourceLabel(worktreePath, repoPath) {
|
|
209
328
|
const wt = settingsSourceLabel(worktreePath);
|
|
210
329
|
if (wt) return `${wt} (worktree)`;
|
|
211
|
-
if (repoPath &&
|
|
330
|
+
if (repoPath && normPath2(repoPath) !== normPath2(worktreePath)) {
|
|
212
331
|
const repo = settingsSourceLabel(repoPath);
|
|
213
332
|
if (repo) return `${repo} (main repo)`;
|
|
214
333
|
}
|
|
@@ -216,42 +335,52 @@ function workspaceSettingsSourceLabel(worktreePath, repoPath) {
|
|
|
216
335
|
}
|
|
217
336
|
function getRepoSetupInfo(worktreePath, repoPath) {
|
|
218
337
|
const settings = loadWorkspaceSettings(worktreePath, repoPath);
|
|
338
|
+
const convention = findConventionSetup(worktreePath, repoPath);
|
|
339
|
+
const cursor = hasCursorWorktreeSetup(worktreePath, repoPath);
|
|
340
|
+
const hasSetupScript = Boolean(settings?.setup) || cursor || Boolean(convention);
|
|
341
|
+
let configLabel = workspaceSettingsSourceLabel(worktreePath, repoPath);
|
|
342
|
+
if (!settings?.setup) {
|
|
343
|
+
if (convention) configLabel = convention.source;
|
|
344
|
+
else if (cursor) {
|
|
345
|
+
configLabel = hasCursorWorktreeSetup(worktreePath) ? ".cursor/worktrees.json (worktree)" : ".cursor/worktrees.json (main repo)";
|
|
346
|
+
}
|
|
347
|
+
}
|
|
219
348
|
return {
|
|
220
|
-
hasConfig: hasWorkspaceHook(worktreePath, repoPath),
|
|
221
|
-
hasSetupScript
|
|
222
|
-
configLabel
|
|
349
|
+
hasConfig: hasWorkspaceHook(worktreePath, repoPath) || cursor || Boolean(convention),
|
|
350
|
+
hasSetupScript,
|
|
351
|
+
configLabel
|
|
223
352
|
};
|
|
224
353
|
}
|
|
225
354
|
|
|
226
355
|
// src/store/paths.ts
|
|
227
356
|
function appDataDir() {
|
|
228
357
|
const override = process.env.SIDEBOARD_APP_DATA?.trim();
|
|
229
|
-
const base = override ? override : process.platform === "darwin" ?
|
|
358
|
+
const base = override ? override : process.platform === "darwin" ? join4(homedir2(), "Library", "Application Support", "sideboard") : process.platform === "win32" ? join4(process.env.APPDATA ?? join4(homedir2(), "AppData", "Roaming"), "sideboard") : join4(homedir2(), ".local", "share", "sideboard");
|
|
230
359
|
mkdirSync(base, { recursive: true });
|
|
231
360
|
return base;
|
|
232
361
|
}
|
|
233
362
|
function threadsDir() {
|
|
234
|
-
const dir =
|
|
363
|
+
const dir = join4(appDataDir(), "threads");
|
|
235
364
|
mkdirSync(dir, { recursive: true });
|
|
236
365
|
return dir;
|
|
237
366
|
}
|
|
238
367
|
function locksDir() {
|
|
239
|
-
const dir =
|
|
368
|
+
const dir = join4(appDataDir(), "locks");
|
|
240
369
|
mkdirSync(dir, { recursive: true });
|
|
241
370
|
return dir;
|
|
242
371
|
}
|
|
243
372
|
function sideboardHomeDir() {
|
|
244
|
-
const dir =
|
|
373
|
+
const dir = join4(homedir2(), "sideboard");
|
|
245
374
|
mkdirSync(dir, { recursive: true });
|
|
246
375
|
return dir;
|
|
247
376
|
}
|
|
248
377
|
function sideboardReposDir() {
|
|
249
|
-
const dir =
|
|
378
|
+
const dir = join4(sideboardHomeDir(), "repos");
|
|
250
379
|
mkdirSync(dir, { recursive: true });
|
|
251
380
|
return dir;
|
|
252
381
|
}
|
|
253
382
|
function sideboardWorkspacesDir() {
|
|
254
|
-
const dir =
|
|
383
|
+
const dir = join4(sideboardHomeDir(), "workspaces");
|
|
255
384
|
mkdirSync(dir, { recursive: true });
|
|
256
385
|
return dir;
|
|
257
386
|
}
|
|
@@ -264,23 +393,28 @@ function worktreesRoot(repoPath) {
|
|
|
264
393
|
mkdirSync(settings.worktreesRoot, { recursive: true });
|
|
265
394
|
return settings.worktreesRoot;
|
|
266
395
|
}
|
|
267
|
-
const dir =
|
|
396
|
+
const dir = join4(sideboardWorkspacesDir(), repoSlug(repoPath));
|
|
268
397
|
mkdirSync(dir, { recursive: true });
|
|
269
398
|
return dir;
|
|
270
399
|
}
|
|
271
400
|
function threadFilePath(id) {
|
|
272
|
-
return
|
|
401
|
+
return join4(threadsDir(), `${id}.json`);
|
|
273
402
|
}
|
|
274
403
|
function threadLockPath(id) {
|
|
275
|
-
return
|
|
404
|
+
return join4(locksDir(), `${id}.lock`);
|
|
276
405
|
}
|
|
277
406
|
function globalAgentCwd() {
|
|
278
|
-
const dir =
|
|
407
|
+
const dir = join4(appDataDir(), "global");
|
|
279
408
|
mkdirSync(dir, { recursive: true });
|
|
280
409
|
return dir;
|
|
281
410
|
}
|
|
282
411
|
|
|
283
412
|
export {
|
|
413
|
+
CONVENTION_SETUP_RELPATHS,
|
|
414
|
+
findConventionSetup,
|
|
415
|
+
hasConventionSetup,
|
|
416
|
+
runCursorWorktreeSetup,
|
|
417
|
+
hasCursorWorktreeSetup,
|
|
284
418
|
loadRepoSettings,
|
|
285
419
|
loadWorkspaceSettings,
|
|
286
420
|
loadConductorSettings,
|
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
} from "./chunk-B3SJXYIJ.js";
|
|
6
6
|
import {
|
|
7
7
|
listThreads
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-JOF3XIEM.js";
|
|
9
9
|
import {
|
|
10
10
|
getGithubGitAuthMode,
|
|
11
11
|
getGithubPat
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-TC2KY5G7.js";
|
|
13
13
|
import {
|
|
14
14
|
worktreesRoot
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-JL4SJ6V7.js";
|
|
16
16
|
import {
|
|
17
17
|
gh,
|
|
18
18
|
git,
|
|
@@ -1025,7 +1025,7 @@ function formatGitAuthModeDirective(mode) {
|
|
|
1025
1025
|
default:
|
|
1026
1026
|
return [
|
|
1027
1027
|
"Git authentication (Account \u2192 GitHub mode: auto):",
|
|
1028
|
-
"- This process rewrites GitHub SSH remotes to HTTPS and authenticates with `GH_TOKEN` from `gh` so git/ssh never prompt the macOS Keychain (required for
|
|
1028
|
+
"- This process rewrites GitHub SSH remotes to HTTPS and authenticates with `GH_TOKEN` from `gh` so git/ssh never prompt the macOS Keychain (required for unattended orchestrator turns).",
|
|
1029
1029
|
"- Do not switch remotes to SSH. Push with `git push -u origin HEAD`.",
|
|
1030
1030
|
"- If HTTPS auth fails, tell the user to run `gh auth login` on this Mac or set Account \u2192 GitHub to a PAT \u2014 do not wait for a Keychain dialog."
|
|
1031
1031
|
].join("\n");
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isGlobalRepoPath
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4PTN2LED.js";
|
|
4
4
|
import {
|
|
5
5
|
ensureGhPreferOrigin,
|
|
6
6
|
resolveRepoRoot
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-L63LLCTX.js";
|
|
8
8
|
import {
|
|
9
9
|
appDataDir
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-B4R2VB2A.js";
|
|
11
11
|
|
|
12
12
|
// src/store/workspaces.ts
|
|
13
13
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -4,17 +4,126 @@
|
|
|
4
4
|
// src/store/paths.ts
|
|
5
5
|
import { basename } from "path";
|
|
6
6
|
import { homedir as homedir2 } from "os";
|
|
7
|
-
import { join as
|
|
7
|
+
import { join as join4 } from "path";
|
|
8
8
|
import { mkdirSync } from "fs";
|
|
9
9
|
|
|
10
10
|
// src/hook/settings.ts
|
|
11
|
-
import { existsSync, readFileSync } from "fs";
|
|
11
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
12
12
|
import { homedir } from "os";
|
|
13
|
-
import { join } from "path";
|
|
13
|
+
import { join as join3 } from "path";
|
|
14
14
|
import { parse as parseToml } from "smol-toml";
|
|
15
|
+
|
|
16
|
+
// src/hook/convention-setup.ts
|
|
17
|
+
import { existsSync, statSync } from "fs";
|
|
18
|
+
import { join } from "path";
|
|
19
|
+
var CONVENTION_SETUP_RELPATHS = [
|
|
20
|
+
"script/setup",
|
|
21
|
+
"bin/setup",
|
|
22
|
+
"scripts/setup.sh",
|
|
23
|
+
"scripts/setup"
|
|
24
|
+
];
|
|
25
|
+
function isFile(path) {
|
|
26
|
+
try {
|
|
27
|
+
return statSync(path).isFile();
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function normPath(p) {
|
|
33
|
+
return p.replace(/\/+$/, "");
|
|
34
|
+
}
|
|
35
|
+
function findConventionSetup(worktreePath, repoPath) {
|
|
36
|
+
const roots = [
|
|
37
|
+
{ root: worktreePath, where: "worktree" }
|
|
38
|
+
];
|
|
39
|
+
if (repoPath && normPath(repoPath) !== normPath(worktreePath)) {
|
|
40
|
+
roots.push({ root: repoPath, where: "main repo" });
|
|
41
|
+
}
|
|
42
|
+
for (const { root, where } of roots) {
|
|
43
|
+
for (const relPath of CONVENTION_SETUP_RELPATHS) {
|
|
44
|
+
const absPath = join(root, relPath);
|
|
45
|
+
if (!existsSync(absPath) || !isFile(absPath)) continue;
|
|
46
|
+
return {
|
|
47
|
+
relPath,
|
|
48
|
+
absPath,
|
|
49
|
+
command: `bash ${JSON.stringify(absPath)}`,
|
|
50
|
+
source: `${relPath} (${where})`
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/hook/cursor-worktrees.ts
|
|
58
|
+
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
59
|
+
import { join as join2 } from "path";
|
|
60
|
+
import { execa } from "execa";
|
|
61
|
+
import { createInterface } from "readline";
|
|
62
|
+
function loadCursorWorktreesJson(rootPath) {
|
|
63
|
+
const path = join2(rootPath, ".cursor", "worktrees.json");
|
|
64
|
+
if (!existsSync2(path)) return null;
|
|
65
|
+
try {
|
|
66
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function resolveSetupSpec(config) {
|
|
72
|
+
if (process.platform === "win32") {
|
|
73
|
+
return config["setup-worktree-windows"] ?? config["setup-worktree"] ?? null;
|
|
74
|
+
}
|
|
75
|
+
return config["setup-worktree-unix"] ?? config["setup-worktree"] ?? null;
|
|
76
|
+
}
|
|
77
|
+
async function runCursorWorktreeSetup(repoPath, worktreePath, onLine) {
|
|
78
|
+
const fromWorktree = loadCursorWorktreesJson(worktreePath);
|
|
79
|
+
const fromRepo = worktreePath !== repoPath ? loadCursorWorktreesJson(repoPath) : null;
|
|
80
|
+
const config = fromWorktree ?? fromRepo;
|
|
81
|
+
if (!config) return { ran: false, exitCode: null, source: null };
|
|
82
|
+
const spec = resolveSetupSpec(config);
|
|
83
|
+
if (!spec) return { ran: false, exitCode: null, source: null };
|
|
84
|
+
const sourceLabel = fromWorktree ? ".cursor/worktrees.json (worktree)" : ".cursor/worktrees.json (main repo)";
|
|
85
|
+
const env = {
|
|
86
|
+
...process.env,
|
|
87
|
+
ROOT_WORKTREE_PATH: repoPath
|
|
88
|
+
};
|
|
89
|
+
if (process.platform === "win32") {
|
|
90
|
+
env.ROOT_WORKTREE_PATH = repoPath;
|
|
91
|
+
}
|
|
92
|
+
const commands = Array.isArray(spec) ? spec : [spec.endsWith(".sh") || spec.endsWith(".ps1") ? join2(
|
|
93
|
+
fromWorktree ? worktreePath : repoPath,
|
|
94
|
+
".cursor",
|
|
95
|
+
spec
|
|
96
|
+
) : spec];
|
|
97
|
+
let lastExit = 0;
|
|
98
|
+
for (const command of commands) {
|
|
99
|
+
const isScriptPath = typeof spec === "string" && (spec.endsWith(".sh") || spec.endsWith(".ps1"));
|
|
100
|
+
const shell = process.platform === "win32" ? "powershell" : "bash";
|
|
101
|
+
const args = process.platform === "win32" ? isScriptPath ? ["-File", command] : ["-Command", command] : isScriptPath ? [command] : ["-lc", command];
|
|
102
|
+
onLine?.(`[cursor setup] ${command}`);
|
|
103
|
+
const child = execa(shell, args, {
|
|
104
|
+
cwd: worktreePath,
|
|
105
|
+
reject: false,
|
|
106
|
+
env
|
|
107
|
+
});
|
|
108
|
+
if (child.stdout && onLine) {
|
|
109
|
+
const rl = createInterface({ input: child.stdout });
|
|
110
|
+
rl.on("line", onLine);
|
|
111
|
+
}
|
|
112
|
+
if (child.stderr && onLine) {
|
|
113
|
+
const rl = createInterface({ input: child.stderr });
|
|
114
|
+
rl.on("line", onLine);
|
|
115
|
+
}
|
|
116
|
+
const result = await child;
|
|
117
|
+
lastExit = result.exitCode ?? null;
|
|
118
|
+
if (lastExit !== 0 && lastExit !== null) break;
|
|
119
|
+
}
|
|
120
|
+
return { ran: true, exitCode: lastExit, source: sourceLabel };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/hook/settings.ts
|
|
15
124
|
function expandHome(path) {
|
|
16
125
|
if (path.startsWith("~/") || path === "~") {
|
|
17
|
-
return
|
|
126
|
+
return join3(homedir(), path.slice(2));
|
|
18
127
|
}
|
|
19
128
|
return path;
|
|
20
129
|
}
|
|
@@ -27,8 +136,8 @@ function parseAvailableIn(raw) {
|
|
|
27
136
|
return out.length ? out : void 0;
|
|
28
137
|
}
|
|
29
138
|
function parseSettingsFile(path, source) {
|
|
30
|
-
if (!
|
|
31
|
-
const raw =
|
|
139
|
+
if (!existsSync3(path)) return null;
|
|
140
|
+
const raw = readFileSync2(path, "utf8");
|
|
32
141
|
const data = parseToml(raw);
|
|
33
142
|
const scripts = data.scripts ?? {};
|
|
34
143
|
const setup = typeof scripts.setup === "string" ? scripts.setup : void 0;
|
|
@@ -131,15 +240,15 @@ function finalizeSettings(parsed) {
|
|
|
131
240
|
};
|
|
132
241
|
}
|
|
133
242
|
function familyFiles(rootPath, source) {
|
|
134
|
-
const dir =
|
|
243
|
+
const dir = join3(rootPath, `.${source}`);
|
|
135
244
|
return {
|
|
136
|
-
toml:
|
|
137
|
-
local:
|
|
245
|
+
toml: join3(dir, "settings.toml"),
|
|
246
|
+
local: join3(dir, "settings.local.toml")
|
|
138
247
|
};
|
|
139
248
|
}
|
|
140
249
|
function familyExists(rootPath, source) {
|
|
141
250
|
const files = familyFiles(rootPath, source);
|
|
142
|
-
return
|
|
251
|
+
return existsSync3(files.toml) || existsSync3(files.local);
|
|
143
252
|
}
|
|
144
253
|
function detectFamily(rootPath) {
|
|
145
254
|
if (familyExists(rootPath, "sideboard")) return "sideboard";
|
|
@@ -158,7 +267,7 @@ function loadAnyLocal(rootPath) {
|
|
|
158
267
|
loadLocalToml(rootPath, "sideboard")
|
|
159
268
|
);
|
|
160
269
|
}
|
|
161
|
-
function
|
|
270
|
+
function normPath2(p) {
|
|
162
271
|
return p.replace(/\/+$/, "");
|
|
163
272
|
}
|
|
164
273
|
function loadRepoSettings(repoPath) {
|
|
@@ -172,11 +281,11 @@ function loadRepoSettings(repoPath) {
|
|
|
172
281
|
}
|
|
173
282
|
function loadWorkspaceSettings(worktreePath, repoPath) {
|
|
174
283
|
const wtFamily = detectFamily(worktreePath);
|
|
175
|
-
const repoFamily = repoPath &&
|
|
284
|
+
const repoFamily = repoPath && normPath2(repoPath) !== normPath2(worktreePath) ? detectFamily(repoPath) : null;
|
|
176
285
|
const wtToml = wtFamily ? loadCommittedToml(worktreePath, wtFamily) : null;
|
|
177
286
|
const repoToml = repoPath && repoFamily ? loadCommittedToml(repoPath, repoFamily) : null;
|
|
178
287
|
let merged = wtToml ?? repoToml;
|
|
179
|
-
if (repoPath &&
|
|
288
|
+
if (repoPath && normPath2(repoPath) !== normPath2(worktreePath)) {
|
|
180
289
|
merged = mergeSettings(merged, loadAnyLocal(repoPath));
|
|
181
290
|
}
|
|
182
291
|
merged = mergeSettings(merged, loadAnyLocal(worktreePath));
|
|
@@ -186,16 +295,16 @@ function settingsSourceLabel(rootPath) {
|
|
|
186
295
|
const family = detectFamily(rootPath);
|
|
187
296
|
if (!family) return null;
|
|
188
297
|
const files = familyFiles(rootPath, family);
|
|
189
|
-
if (
|
|
298
|
+
if (existsSync3(files.toml) && existsSync3(files.local)) {
|
|
190
299
|
return `.${family}/settings.toml + local`;
|
|
191
300
|
}
|
|
192
|
-
if (
|
|
301
|
+
if (existsSync3(files.local)) return `.${family}/settings.local.toml`;
|
|
193
302
|
return `.${family}/settings.toml`;
|
|
194
303
|
}
|
|
195
304
|
function workspaceSettingsSourceLabel(worktreePath, repoPath) {
|
|
196
305
|
const wt = settingsSourceLabel(worktreePath);
|
|
197
306
|
if (wt) return `${wt} (worktree)`;
|
|
198
|
-
if (repoPath &&
|
|
307
|
+
if (repoPath && normPath2(repoPath) !== normPath2(worktreePath)) {
|
|
199
308
|
const repo = settingsSourceLabel(repoPath);
|
|
200
309
|
if (repo) return `${repo} (main repo)`;
|
|
201
310
|
}
|
|
@@ -205,32 +314,32 @@ function workspaceSettingsSourceLabel(worktreePath, repoPath) {
|
|
|
205
314
|
// src/store/paths.ts
|
|
206
315
|
function appDataDir() {
|
|
207
316
|
const override = process.env.SIDEBOARD_APP_DATA?.trim();
|
|
208
|
-
const base = override ? override : process.platform === "darwin" ?
|
|
317
|
+
const base = override ? override : process.platform === "darwin" ? join4(homedir2(), "Library", "Application Support", "sideboard") : process.platform === "win32" ? join4(process.env.APPDATA ?? join4(homedir2(), "AppData", "Roaming"), "sideboard") : join4(homedir2(), ".local", "share", "sideboard");
|
|
209
318
|
mkdirSync(base, { recursive: true });
|
|
210
319
|
return base;
|
|
211
320
|
}
|
|
212
321
|
function threadsDir() {
|
|
213
|
-
const dir =
|
|
322
|
+
const dir = join4(appDataDir(), "threads");
|
|
214
323
|
mkdirSync(dir, { recursive: true });
|
|
215
324
|
return dir;
|
|
216
325
|
}
|
|
217
326
|
function locksDir() {
|
|
218
|
-
const dir =
|
|
327
|
+
const dir = join4(appDataDir(), "locks");
|
|
219
328
|
mkdirSync(dir, { recursive: true });
|
|
220
329
|
return dir;
|
|
221
330
|
}
|
|
222
331
|
function sideboardHomeDir() {
|
|
223
|
-
const dir =
|
|
332
|
+
const dir = join4(homedir2(), "sideboard");
|
|
224
333
|
mkdirSync(dir, { recursive: true });
|
|
225
334
|
return dir;
|
|
226
335
|
}
|
|
227
336
|
function sideboardReposDir() {
|
|
228
|
-
const dir =
|
|
337
|
+
const dir = join4(sideboardHomeDir(), "repos");
|
|
229
338
|
mkdirSync(dir, { recursive: true });
|
|
230
339
|
return dir;
|
|
231
340
|
}
|
|
232
341
|
function sideboardWorkspacesDir() {
|
|
233
|
-
const dir =
|
|
342
|
+
const dir = join4(sideboardHomeDir(), "workspaces");
|
|
234
343
|
mkdirSync(dir, { recursive: true });
|
|
235
344
|
return dir;
|
|
236
345
|
}
|
|
@@ -243,23 +352,25 @@ function worktreesRoot(repoPath) {
|
|
|
243
352
|
mkdirSync(settings.worktreesRoot, { recursive: true });
|
|
244
353
|
return settings.worktreesRoot;
|
|
245
354
|
}
|
|
246
|
-
const dir =
|
|
355
|
+
const dir = join4(sideboardWorkspacesDir(), repoSlug(repoPath));
|
|
247
356
|
mkdirSync(dir, { recursive: true });
|
|
248
357
|
return dir;
|
|
249
358
|
}
|
|
250
359
|
function threadFilePath(id) {
|
|
251
|
-
return
|
|
360
|
+
return join4(threadsDir(), `${id}.json`);
|
|
252
361
|
}
|
|
253
362
|
function threadLockPath(id) {
|
|
254
|
-
return
|
|
363
|
+
return join4(locksDir(), `${id}.lock`);
|
|
255
364
|
}
|
|
256
365
|
function globalAgentCwd() {
|
|
257
|
-
const dir =
|
|
366
|
+
const dir = join4(appDataDir(), "global");
|
|
258
367
|
mkdirSync(dir, { recursive: true });
|
|
259
368
|
return dir;
|
|
260
369
|
}
|
|
261
370
|
|
|
262
371
|
export {
|
|
372
|
+
findConventionSetup,
|
|
373
|
+
runCursorWorktreeSetup,
|
|
263
374
|
loadRepoSettings,
|
|
264
375
|
loadWorkspaceSettings,
|
|
265
376
|
workspaceSettingsSourceLabel,
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
getGithubGitAuthMode,
|
|
6
6
|
getGithubPat
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-XY6XXMAK.js";
|
|
8
8
|
import {
|
|
9
9
|
listThreads
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-3WA37BRI.js";
|
|
11
11
|
import {
|
|
12
12
|
worktreesRoot
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-B4R2VB2A.js";
|
|
14
14
|
import {
|
|
15
15
|
gh,
|
|
16
16
|
git,
|
|
@@ -1031,7 +1031,7 @@ function formatGitAuthModeDirective(mode) {
|
|
|
1031
1031
|
default:
|
|
1032
1032
|
return [
|
|
1033
1033
|
"Git authentication (Account \u2192 GitHub mode: auto):",
|
|
1034
|
-
"- This process rewrites GitHub SSH remotes to HTTPS and authenticates with `GH_TOKEN` from `gh` so git/ssh never prompt the macOS Keychain (required for
|
|
1034
|
+
"- This process rewrites GitHub SSH remotes to HTTPS and authenticates with `GH_TOKEN` from `gh` so git/ssh never prompt the macOS Keychain (required for unattended orchestrator turns).",
|
|
1035
1035
|
"- Do not switch remotes to SSH. Push with `git push -u origin HEAD`.",
|
|
1036
1036
|
"- 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."
|
|
1037
1037
|
].join("\n");
|