@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.
Files changed (51) hide show
  1. package/dist/agents/cursor-runner.cjs +77 -29
  2. package/dist/agents/cursor-runner.js +55 -17
  3. package/dist/{agents-YAYNNJWC.js → agents-V6PVSQYH.js} +8 -8
  4. package/dist/{agents-FD77JUOP.js → agents-W5446HSV.js} +8 -8
  5. package/dist/{app-settings-PEXK5VEX.js → app-settings-F36ISTCF.js} +2 -2
  6. package/dist/{app-settings-K6RFCRF6.js → app-settings-HFINR3XG.js} +2 -2
  7. package/dist/{caffeinate-hold-EAZNWJBE.js → caffeinate-hold-I7SG6UQR.js} +2 -2
  8. package/dist/{caffeinate-hold-OHAUWOA6.js → caffeinate-hold-U3QJBV67.js} +2 -2
  9. package/dist/{chunk-XVFV56JG.js → chunk-3MA6JH6G.js} +5 -5
  10. package/dist/{chunk-FWJYLBO6.js → chunk-3WA37BRI.js} +1 -1
  11. package/dist/{chunk-JTHWVYSD.js → chunk-4PTN2LED.js} +5 -5
  12. package/dist/{chunk-RV6DBEDQ.js → chunk-7KDBDMNC.js} +1 -1
  13. package/dist/{chunk-SH75CXJR.js → chunk-A7LONVNO.js} +5 -5
  14. package/dist/{chunk-M37RITA6.js → chunk-B4R2VB2A.js} +164 -30
  15. package/dist/{chunk-6WQAYBVE.js → chunk-CY45C3GA.js} +4 -4
  16. package/dist/{chunk-6K5VAPVR.js → chunk-DKHGWYWR.js} +1 -1
  17. package/dist/{chunk-2N5DVTGH.js → chunk-HBXQQ5TO.js} +3 -3
  18. package/dist/{chunk-7MV3RXSC.js → chunk-JL4SJ6V7.js} +137 -26
  19. package/dist/{chunk-7FD7COKE.js → chunk-JOF3XIEM.js} +1 -1
  20. package/dist/{chunk-KRAUS3RF.js → chunk-L63LLCTX.js} +4 -4
  21. package/dist/{chunk-MFF2RE3I.js → chunk-NZPGMNFC.js} +1 -1
  22. package/dist/{chunk-HHTHF5BQ.js → chunk-QSLE4VEM.js} +4 -4
  23. package/dist/{chunk-3CCRD6WS.js → chunk-QWNROSRB.js} +6 -6
  24. package/dist/{chunk-JFQ2M6NQ.js → chunk-R2EOZNQI.js} +3 -3
  25. package/dist/{chunk-AY53MPDE.js → chunk-TC2KY5G7.js} +1 -1
  26. package/dist/{chunk-WGI6KXKJ.js → chunk-U4GZKLIV.js} +6 -6
  27. package/dist/{chunk-6GKDYUTJ.js → chunk-UVNXLTFB.js} +5 -5
  28. package/dist/{chunk-I3FRXL7J.js → chunk-XY6XXMAK.js} +1 -1
  29. package/dist/{connected-teams-BNBM7OIC.js → connected-teams-SWHJWK2A.js} +2 -2
  30. package/dist/{connected-teams-LSQ5TAZP.js → connected-teams-TLVKZPJP.js} +2 -2
  31. package/dist/{coordinator-prompt-VN7FF76K.js → coordinator-prompt-EC3KQLN3.js} +5 -5
  32. package/dist/{coordinator-prompt-YYQSPLIP.js → coordinator-prompt-PYRAXZN3.js} +5 -5
  33. package/dist/{cursor-recover-L5PNQUDT.js → cursor-recover-G34BYKL2.js} +1 -1
  34. package/dist/{cursor-recover-NNK7JPQM.js → cursor-recover-S5ORPW34.js} +1 -1
  35. package/dist/{global-workspace-BRIDCBMY.js → global-workspace-ICWOWUW6.js} +6 -6
  36. package/dist/{global-workspace-U3XVTQLL.js → global-workspace-T5IAJF4R.js} +6 -6
  37. package/dist/index.cjs +633 -526
  38. package/dist/index.d.cts +45 -11
  39. package/dist/index.d.ts +45 -11
  40. package/dist/index.js +212 -252
  41. package/dist/mcp/run-stdio.cjs +570 -490
  42. package/dist/mcp/run-stdio.js +184 -225
  43. package/dist/{paths-VPH3ITBK.js → paths-JQM2XRAD.js} +1 -1
  44. package/dist/{paths-2OFB7UJG.js → paths-TZX4L5X7.js} +1 -1
  45. package/dist/{thread-store-BUBR24YA.js → thread-store-V7NOOXKE.js} +2 -2
  46. package/dist/{thread-store-XTPFCJAI.js → thread-store-XAKWCV2E.js} +2 -2
  47. package/dist/{workspaces-IWQIWAMQ.js → workspaces-AJCAFW64.js} +7 -7
  48. package/dist/{workspaces-AIZDG6PS.js → workspaces-J4ULXOUH.js} +7 -7
  49. package/dist/{worktree-6ZALJUWG.js → worktree-4Z2VSHAQ.js} +4 -4
  50. package/dist/{worktree-7Y22WHR7.js → worktree-H57CCHWO.js} +4 -4
  51. 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 join2 } from "path";
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 join(homedir(), path.slice(2));
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 (!existsSync(path)) return null;
28
- const raw = readFileSync(path, "utf8");
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 = join(rootPath, `.${source}`);
250
+ const dir = join3(rootPath, `.${source}`);
132
251
  return {
133
- toml: join(dir, "settings.toml"),
134
- local: join(dir, "settings.local.toml")
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 existsSync(files.toml) || existsSync(files.local);
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 normPath(p) {
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 && normPath(repoPath) !== normPath(worktreePath) ? detectFamily(repoPath) : null;
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 && normPath(repoPath) !== normPath(worktreePath)) {
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 && normPath(repoPath) !== normPath(worktreePath) && hasRepoHook(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 (existsSync(files.toml) && existsSync(files.local)) {
321
+ if (existsSync3(files.toml) && existsSync3(files.local)) {
203
322
  return `.${family}/settings.toml + local`;
204
323
  }
205
- if (existsSync(files.local)) return `.${family}/settings.local.toml`;
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 && normPath(repoPath) !== normPath(worktreePath)) {
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: Boolean(settings?.setup),
222
- configLabel: workspaceSettingsSourceLabel(worktreePath, repoPath)
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" ? join2(homedir2(), "Library", "Application Support", "sideboard") : process.platform === "win32" ? join2(process.env.APPDATA ?? join2(homedir2(), "AppData", "Roaming"), "sideboard") : join2(homedir2(), ".local", "share", "sideboard");
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 = join2(appDataDir(), "threads");
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 = join2(appDataDir(), "locks");
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 = join2(homedir2(), "sideboard");
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 = join2(sideboardHomeDir(), "repos");
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 = join2(sideboardHomeDir(), "workspaces");
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 = join2(sideboardWorkspacesDir(), repoSlug(repoPath));
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 join2(threadsDir(), `${id}.json`);
401
+ return join4(threadsDir(), `${id}.json`);
273
402
  }
274
403
  function threadLockPath(id) {
275
- return join2(locksDir(), `${id}.lock`);
404
+ return join4(locksDir(), `${id}.lock`);
276
405
  }
277
406
  function globalAgentCwd() {
278
- const dir = join2(appDataDir(), "global");
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-7FD7COKE.js";
8
+ } from "./chunk-JOF3XIEM.js";
9
9
  import {
10
10
  getGithubGitAuthMode,
11
11
  getGithubPat
12
- } from "./chunk-AY53MPDE.js";
12
+ } from "./chunk-TC2KY5G7.js";
13
13
  import {
14
14
  worktreesRoot
15
- } from "./chunk-7MV3RXSC.js";
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 Slack / unattended Cursor).",
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");
@@ -2,7 +2,7 @@
2
2
 
3
3
  import {
4
4
  appDataDir
5
- } from "./chunk-7MV3RXSC.js";
5
+ } from "./chunk-JL4SJ6V7.js";
6
6
  import {
7
7
  run
8
8
  } from "./chunk-3KETJKYA.js";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  isGlobalRepoPath
3
- } from "./chunk-JTHWVYSD.js";
3
+ } from "./chunk-4PTN2LED.js";
4
4
  import {
5
5
  ensureGhPreferOrigin,
6
6
  resolveRepoRoot
7
- } from "./chunk-KRAUS3RF.js";
7
+ } from "./chunk-L63LLCTX.js";
8
8
  import {
9
9
  appDataDir
10
- } from "./chunk-M37RITA6.js";
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 join2 } from "path";
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 join(homedir(), path.slice(2));
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 (!existsSync(path)) return null;
31
- const raw = readFileSync(path, "utf8");
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 = join(rootPath, `.${source}`);
243
+ const dir = join3(rootPath, `.${source}`);
135
244
  return {
136
- toml: join(dir, "settings.toml"),
137
- local: join(dir, "settings.local.toml")
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 existsSync(files.toml) || existsSync(files.local);
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 normPath(p) {
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 && normPath(repoPath) !== normPath(worktreePath) ? detectFamily(repoPath) : null;
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 && normPath(repoPath) !== normPath(worktreePath)) {
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 (existsSync(files.toml) && existsSync(files.local)) {
298
+ if (existsSync3(files.toml) && existsSync3(files.local)) {
190
299
  return `.${family}/settings.toml + local`;
191
300
  }
192
- if (existsSync(files.local)) return `.${family}/settings.local.toml`;
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 && normPath(repoPath) !== normPath(worktreePath)) {
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" ? join2(homedir2(), "Library", "Application Support", "sideboard") : process.platform === "win32" ? join2(process.env.APPDATA ?? join2(homedir2(), "AppData", "Roaming"), "sideboard") : join2(homedir2(), ".local", "share", "sideboard");
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 = join2(appDataDir(), "threads");
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 = join2(appDataDir(), "locks");
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 = join2(homedir2(), "sideboard");
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 = join2(sideboardHomeDir(), "repos");
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 = join2(sideboardHomeDir(), "workspaces");
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 = join2(sideboardWorkspacesDir(), repoSlug(repoPath));
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 join2(threadsDir(), `${id}.json`);
360
+ return join4(threadsDir(), `${id}.json`);
252
361
  }
253
362
  function threadLockPath(id) {
254
- return join2(locksDir(), `${id}.lock`);
363
+ return join4(locksDir(), `${id}.lock`);
255
364
  }
256
365
  function globalAgentCwd() {
257
- const dir = join2(appDataDir(), "global");
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,
@@ -7,7 +7,7 @@ import {
7
7
  threadFilePath,
8
8
  threadLockPath,
9
9
  threadsDir
10
- } from "./chunk-7MV3RXSC.js";
10
+ } from "./chunk-JL4SJ6V7.js";
11
11
 
12
12
  // src/store/thread-store.ts
13
13
  import { randomUUID } from "crypto";
@@ -4,13 +4,13 @@ import {
4
4
  import {
5
5
  getGithubGitAuthMode,
6
6
  getGithubPat
7
- } from "./chunk-I3FRXL7J.js";
7
+ } from "./chunk-XY6XXMAK.js";
8
8
  import {
9
9
  listThreads
10
- } from "./chunk-FWJYLBO6.js";
10
+ } from "./chunk-3WA37BRI.js";
11
11
  import {
12
12
  worktreesRoot
13
- } from "./chunk-M37RITA6.js";
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 Slack / unattended Cursor).",
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");