@sideboard-ai/core 0.1.217 → 0.1.219

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 (59) hide show
  1. package/dist/{abletime-QGGYL2G4.js → abletime-BF253OZT.js} +5 -4
  2. package/dist/{abletime-GDZLZRMY.js → abletime-D6773P33.js} +5 -5
  3. package/dist/{abletime-oauth-F335TWKY.js → abletime-oauth-H4672PRH.js} +4 -3
  4. package/dist/{abletime-oauth-3X3BAPTF.js → abletime-oauth-KQPVVBKA.js} +4 -4
  5. package/dist/{abletime-rest-PLJVY3H3.js → abletime-rest-DAFPXZ7H.js} +4 -4
  6. package/dist/{abletime-rest-LAGTPAJL.js → abletime-rest-OPEVV3XC.js} +4 -3
  7. package/dist/agents/cursor-runner.js +5 -5
  8. package/dist/{agents-HETHRRZJ.js → agents-IFVGY77W.js} +9 -9
  9. package/dist/{agents-WBDDLRBY.js → agents-IK3U4Z2O.js} +8 -7
  10. package/dist/{app-settings-XCRNCEEE.js → app-settings-5RQMQKSB.js} +2 -1
  11. package/dist/{app-settings-2TN3WLZV.js → app-settings-V2BBCX2H.js} +2 -2
  12. package/dist/{chunk-MN6YUD4O.js → chunk-3NWUHXU3.js} +3 -3
  13. package/dist/{chunk-G4TANQC3.js → chunk-646I442S.js} +5 -5
  14. package/dist/{chunk-FNQNJOHY.js → chunk-ABOBTSO6.js} +4 -1
  15. package/dist/{chunk-YVE4PXCJ.js → chunk-CLI5DVU4.js} +2 -2
  16. package/dist/{chunk-C32SBNA3.js → chunk-EIICOB7P.js} +457 -294
  17. package/dist/{chunk-LS6TSOCE.js → chunk-HSYE5ID6.js} +5 -5
  18. package/dist/{chunk-UFHNSFAS.js → chunk-HVUVQXZ2.js} +5 -1
  19. package/dist/{chunk-7MTVRNP4.js → chunk-IAP5NXQ4.js} +1206 -1192
  20. package/dist/{chunk-SALM35KD.js → chunk-IILG7DPX.js} +5 -5
  21. package/dist/{chunk-DFTVZEZY.js → chunk-K642ORWF.js} +1085 -1057
  22. package/dist/{chunk-NI243N27.js → chunk-KTZESHYH.js} +15 -7
  23. package/dist/{chunk-FNGXKY5W.js → chunk-N2VST3NL.js} +68 -8
  24. package/dist/{chunk-XYKVRRC2.js → chunk-NFWPDEN4.js} +15 -7
  25. package/dist/{chunk-KFD2OXCE.js → chunk-P2EAAM3H.js} +68 -8
  26. package/dist/{chunk-QQKDGPUI.js → chunk-PO4M4JAJ.js} +1 -1
  27. package/dist/{chunk-2M5B7YNY.js → chunk-RRW2XWAY.js} +2 -2
  28. package/dist/{chunk-REZRGCKV.js → chunk-SOGGKYFV.js} +3 -3
  29. package/dist/{chunk-3OHR73VK.js → chunk-SVXIJ2IC.js} +1 -1
  30. package/dist/{chunk-SYFVUF2C.js → chunk-SZJZEFTY.js} +1 -1
  31. package/dist/{chunk-42IULNIY.js → chunk-THLVCXLF.js} +3 -3
  32. package/dist/{chunk-JZHRZ3DR.js → chunk-TQBUXKIB.js} +5 -5
  33. package/dist/chunk-WWUABK6B.js +56 -0
  34. package/dist/{chunk-D2IKXMF3.js → chunk-XGE6YUO6.js} +453 -289
  35. package/dist/{chunk-BTC2D6LS.js → chunk-Y5JES2VV.js} +3 -51
  36. package/dist/{connected-teams-WK47ATT7.js → connected-teams-LX5DLL2I.js} +3 -2
  37. package/dist/{connected-teams-PU4AMFNA.js → connected-teams-PQETXUWV.js} +3 -2
  38. package/dist/{coordinator-prompt-FQX6ALAI.js → coordinator-prompt-JLMQVORO.js} +6 -6
  39. package/dist/{coordinator-prompt-LE2GQZ2X.js → coordinator-prompt-VZ7OSRLD.js} +6 -5
  40. package/dist/{global-workspace-6P236KKG.js → global-workspace-3FDAUNN2.js} +6 -6
  41. package/dist/{global-workspace-KT3FRHZL.js → global-workspace-QPSJEXGR.js} +6 -5
  42. package/dist/index.cjs +1107 -826
  43. package/dist/index.d.cts +15 -1
  44. package/dist/index.d.ts +15 -1
  45. package/dist/index.js +24 -18
  46. package/dist/mcp/run-stdio.cjs +1912 -1652
  47. package/dist/mcp/run-stdio.js +16 -14
  48. package/dist/{orchestrator-MI7A5DQZ.js → orchestrator-5VVR7LOU.js} +9 -8
  49. package/dist/{orchestrator-WVZPTHBV.js → orchestrator-LFC3V3AX.js} +10 -10
  50. package/dist/{run-EBWL2Q4N.js → run-QDZCTP4Y.js} +2 -1
  51. package/dist/{run-CAGKZLHA.js → run-UEQM4JMZ.js} +2 -1
  52. package/dist/{workspaces-R5LJCJRB.js → workspaces-76W7IEKR.js} +8 -6
  53. package/dist/{workspaces-KM7KTLVO.js → workspaces-TDBA64II.js} +8 -5
  54. package/dist/{worktree-MDMTCAHX.js → worktree-7V67XTEO.js} +5 -5
  55. package/dist/{worktree-VXRI7LYM.js → worktree-I573UOPD.js} +5 -4
  56. package/dist/{worktree-exclude-N5X5I422.js → worktree-exclude-K7QK4RI5.js} +3 -2
  57. package/dist/{worktree-exclude-X54WSOXM.js → worktree-exclude-L32WEBX6.js} +3 -2
  58. package/package.json +1 -1
  59. package/dist/{chunk-L5CIEBLR.js → chunk-EWHJNJHV.js} +3 -3
@@ -3,11 +3,11 @@ import {
3
3
  } from "./chunk-6K64FJDD.js";
4
4
  import {
5
5
  ensureWorktreeSideboardIgnored
6
- } from "./chunk-QQKDGPUI.js";
6
+ } from "./chunk-PO4M4JAJ.js";
7
7
  import {
8
8
  getGithubGitAuthMode,
9
9
  getGithubPat
10
- } from "./chunk-L5CIEBLR.js";
10
+ } from "./chunk-EWHJNJHV.js";
11
11
  import {
12
12
  listThreads
13
13
  } from "./chunk-3IMSQNTS.js";
@@ -23,7 +23,7 @@ import {
23
23
  githubGhConfigEnv,
24
24
  materializeGithubAgentAuth,
25
25
  resolveGhAuthToken
26
- } from "./chunk-UFHNSFAS.js";
26
+ } from "./chunk-HVUVQXZ2.js";
27
27
 
28
28
  // src/git/worktree.ts
29
29
  import { randomBytes } from "crypto";
@@ -1902,7 +1902,14 @@ function slugify(input) {
1902
1902
  }
1903
1903
  async function resolveRepoRoot(cwd) {
1904
1904
  const { stdout } = await git(["rev-parse", "--show-toplevel"], cwd);
1905
- return canonicalizeRepoPath(stdout.trim());
1905
+ const toplevel = canonicalizeRepoPath(stdout.trim());
1906
+ try {
1907
+ const listed = await listWorktrees(cwd);
1908
+ const primary = listed[0]?.path;
1909
+ if (primary) return canonicalizeRepoPath(primary);
1910
+ } catch {
1911
+ }
1912
+ return toplevel;
1906
1913
  }
1907
1914
  function canonicalizeRepoPath(path) {
1908
1915
  try {
@@ -1922,7 +1929,8 @@ function parseGithubSlugFromRemoteUrl(url) {
1922
1929
  }
1923
1930
  async function slugFromGitRemote(repoPath, remote) {
1924
1931
  const result = await git(["remote", "get-url", remote], repoPath, {
1925
- reject: false
1932
+ reject: false,
1933
+ timeoutMs: 5e3
1926
1934
  });
1927
1935
  if (result.exitCode !== 0 || !result.stdout.trim()) return null;
1928
1936
  return parseGithubSlugFromRemoteUrl(result.stdout);
@@ -1935,7 +1943,7 @@ async function resolveGithubRepoSlug(repoPath) {
1935
1943
  const viaGh = await gh(
1936
1944
  ["repo", "view", "--json", "nameWithOwner", "--jq", ".nameWithOwner"],
1937
1945
  repoPath,
1938
- { reject: false }
1946
+ { reject: false, timeoutMs: 8e3 }
1939
1947
  );
1940
1948
  if (viaGh.exitCode === 0 && viaGh.stdout.trim()) {
1941
1949
  return viaGh.stdout.trim();
@@ -2884,7 +2892,7 @@ async function listWorktrees(repoPath) {
2884
2892
  const { stdout } = await git(
2885
2893
  ["worktree", "list", "--porcelain"],
2886
2894
  repoPath,
2887
- { reject: false }
2895
+ { reject: false, timeoutMs: 8e3 }
2888
2896
  );
2889
2897
  if (!stdout.trim()) return [];
2890
2898
  const entries = [];
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  allocateTeamName,
3
+ canonicalizeRepoPath,
3
4
  ensureGhPreferOrigin,
4
5
  resolveGithubRepoSlug,
5
6
  resolveRepoRoot,
6
7
  takenSlugsFromThread,
7
8
  teamSlugFromName
8
- } from "./chunk-NI243N27.js";
9
+ } from "./chunk-KTZESHYH.js";
9
10
  import {
10
11
  ATTACHMENTS_DIR,
11
12
  attachmentsGitignoreBody
@@ -22,7 +23,7 @@ import {
22
23
  resolveThreadDefaults,
23
24
  resolveViewerProfile,
24
25
  resolveViewerProfileForRepo
25
- } from "./chunk-L5CIEBLR.js";
26
+ } from "./chunk-EWHJNJHV.js";
26
27
  import {
27
28
  createEmptyThread,
28
29
  listThreads,
@@ -36,7 +37,7 @@ import {
36
37
  } from "./chunk-WFUDY6PC.js";
37
38
 
38
39
  // src/store/workspaces.ts
39
- import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
40
+ import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync3, statSync as statSync2, writeFileSync as writeFileSync3 } from "fs";
40
41
  import { basename as basename2, join as join3 } from "path";
41
42
 
42
43
  // src/brightsy/cloud-connect-constants.ts
@@ -841,6 +842,41 @@ function listWorkspaces() {
841
842
  if (valid.length !== all.length) writeAll(valid);
842
843
  return valid.sort((a, b) => a.name.localeCompare(b.name));
843
844
  }
845
+ function isLinkedWorktreeOf(path, mainRepo) {
846
+ if (!path || path === mainRepo) return false;
847
+ const git = join3(path, ".git");
848
+ try {
849
+ if (!existsSync2(git) || statSync2(git).isDirectory()) return false;
850
+ const text = readFileSync3(git, "utf8");
851
+ const needle = `${mainRepo.replace(/\/+$/, "")}/.git`;
852
+ return text.includes(needle);
853
+ } catch {
854
+ return false;
855
+ }
856
+ }
857
+ function primaryCheckoutFromLinkedWorktree(path) {
858
+ if (!path) return null;
859
+ const git = join3(path, ".git");
860
+ try {
861
+ if (!existsSync2(git) || statSync2(git).isDirectory()) return null;
862
+ const text = readFileSync3(git, "utf8");
863
+ const match = /^\s*gitdir:\s*(.+)$/m.exec(text);
864
+ if (!match) return null;
865
+ const gitdir = match[1].trim().replace(/\/+$/, "");
866
+ const worktrees = gitdir.lastIndexOf("/.git/worktrees/");
867
+ const root = worktrees > 0 ? gitdir.slice(0, worktrees) : gitdir.endsWith("/.git") ? gitdir.slice(0, -5) : null;
868
+ if (!root) return null;
869
+ return canonicalizeRepoPath(root);
870
+ } catch {
871
+ return null;
872
+ }
873
+ }
874
+ function resolveSyncWorkspacePath(path) {
875
+ if (!path || path === "/") return null;
876
+ const primary = primaryCheckoutFromLinkedWorktree(path);
877
+ if (primary) return primary;
878
+ return canonicalizeRepoPath(path);
879
+ }
844
880
  async function addWorkspace(repoPath) {
845
881
  const root = await resolveRepoRoot(repoPath);
846
882
  if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
@@ -849,13 +885,14 @@ async function addWorkspace(repoPath) {
849
885
  await ensureGhPreferOrigin(root);
850
886
  const current = readAll();
851
887
  const existing = current.find((w) => w.path === root);
852
- if (existing) return existing;
853
- const next = {
888
+ const withoutLinked = current.filter((w) => !isLinkedWorktreeOf(w.path, root));
889
+ if (existing && withoutLinked.length === current.length) return existing;
890
+ const next = existing ?? {
854
891
  path: root,
855
892
  name: basename2(root),
856
893
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
857
894
  };
858
- writeAll([...current, next]);
895
+ writeAll(existing ? withoutLinked : [...withoutLinked, next]);
859
896
  return next;
860
897
  }
861
898
  function removeWorkspace(repoPath) {
@@ -868,9 +905,24 @@ async function ensureWorkspace(repoPath) {
868
905
  function syncWorkspacesFromThreads(repoPaths) {
869
906
  const current = readAll();
870
907
  const removed = readRemoved();
871
- const byPath = new Map(current.map((w) => [w.path, w]));
908
+ const byPath = /* @__PURE__ */ new Map();
872
909
  let dirty = false;
873
- for (const path of repoPaths) {
910
+ for (const w of current) {
911
+ const resolved = resolveSyncWorkspacePath(w.path) ?? w.path;
912
+ if (resolved !== w.path) dirty = true;
913
+ if (!resolved || resolved === "/" || isGlobalRepoPath(resolved) || removed.has(resolved)) {
914
+ dirty = true;
915
+ continue;
916
+ }
917
+ if (!byPath.has(resolved)) {
918
+ byPath.set(
919
+ resolved,
920
+ resolved === w.path ? w : { ...w, path: resolved, name: basename2(resolved) }
921
+ );
922
+ }
923
+ }
924
+ for (const raw of repoPaths) {
925
+ const path = resolveSyncWorkspacePath(raw);
874
926
  if (!path || path === "/" || isGlobalRepoPath(path) || byPath.has(path) || removed.has(path)) {
875
927
  continue;
876
928
  }
@@ -883,6 +935,13 @@ function syncWorkspacesFromThreads(repoPaths) {
883
935
  byPath.set(path, ws);
884
936
  dirty = true;
885
937
  }
938
+ for (const [path] of byPath) {
939
+ const mains = [...byPath.keys()];
940
+ if (mains.some((main) => isLinkedWorktreeOf(path, main))) {
941
+ byPath.delete(path);
942
+ dirty = true;
943
+ }
944
+ }
886
945
  const next = [...byPath.values()];
887
946
  if (dirty) writeAll(next);
888
947
  return next.sort((a, b) => a.name.localeCompare(b.name));
@@ -903,6 +962,7 @@ export {
903
962
  persistPendingFileAttachments,
904
963
  attachmentsFromWorktreePaths,
905
964
  listWorkspaces,
965
+ primaryCheckoutFromLinkedWorktree,
906
966
  addWorkspace,
907
967
  removeWorkspace,
908
968
  ensureWorkspace,
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-HY2GFZ5S.js";
9
9
  import {
10
10
  ensureWorktreeSideboardIgnored
11
- } from "./chunk-SYFVUF2C.js";
11
+ } from "./chunk-SZJZEFTY.js";
12
12
  import {
13
13
  gh,
14
14
  git,
@@ -18,11 +18,11 @@ import {
18
18
  githubGhConfigEnv,
19
19
  materializeGithubAgentAuth,
20
20
  resolveGhAuthToken
21
- } from "./chunk-FNQNJOHY.js";
21
+ } from "./chunk-ABOBTSO6.js";
22
22
  import {
23
23
  getGithubGitAuthMode,
24
24
  getGithubPat
25
- } from "./chunk-BTC2D6LS.js";
25
+ } from "./chunk-Y5JES2VV.js";
26
26
  import {
27
27
  worktreesRoot
28
28
  } from "./chunk-EQNRWDLN.js";
@@ -1865,7 +1865,14 @@ function slugify(input) {
1865
1865
  }
1866
1866
  async function resolveRepoRoot(cwd) {
1867
1867
  const { stdout } = await git(["rev-parse", "--show-toplevel"], cwd);
1868
- return canonicalizeRepoPath(stdout.trim());
1868
+ const toplevel = canonicalizeRepoPath(stdout.trim());
1869
+ try {
1870
+ const listed = await listWorktrees(cwd);
1871
+ const primary = listed[0]?.path;
1872
+ if (primary) return canonicalizeRepoPath(primary);
1873
+ } catch {
1874
+ }
1875
+ return toplevel;
1869
1876
  }
1870
1877
  function canonicalizeRepoPath(path) {
1871
1878
  try {
@@ -1885,7 +1892,8 @@ function parseGithubSlugFromRemoteUrl(url) {
1885
1892
  }
1886
1893
  async function slugFromGitRemote(repoPath, remote) {
1887
1894
  const result = await git(["remote", "get-url", remote], repoPath, {
1888
- reject: false
1895
+ reject: false,
1896
+ timeoutMs: 5e3
1889
1897
  });
1890
1898
  if (result.exitCode !== 0 || !result.stdout.trim()) return null;
1891
1899
  return parseGithubSlugFromRemoteUrl(result.stdout);
@@ -1898,7 +1906,7 @@ async function resolveGithubRepoSlug(repoPath) {
1898
1906
  const viaGh = await gh(
1899
1907
  ["repo", "view", "--json", "nameWithOwner", "--jq", ".nameWithOwner"],
1900
1908
  repoPath,
1901
- { reject: false }
1909
+ { reject: false, timeoutMs: 8e3 }
1902
1910
  );
1903
1911
  if (viaGh.exitCode === 0 && viaGh.stdout.trim()) {
1904
1912
  return viaGh.stdout.trim();
@@ -2847,7 +2855,7 @@ async function listWorktrees(repoPath) {
2847
2855
  const { stdout } = await git(
2848
2856
  ["worktree", "list", "--porcelain"],
2849
2857
  repoPath,
2850
- { reject: false }
2858
+ { reject: false, timeoutMs: 8e3 }
2851
2859
  );
2852
2860
  if (!stdout.trim()) return [];
2853
2861
  const entries = [];
@@ -2,12 +2,13 @@
2
2
 
3
3
  import {
4
4
  allocateTeamName,
5
+ canonicalizeRepoPath,
5
6
  ensureGhPreferOrigin,
6
7
  resolveGithubRepoSlug,
7
8
  resolveRepoRoot,
8
9
  takenSlugsFromThread,
9
10
  teamSlugFromName
10
- } from "./chunk-XYKVRRC2.js";
11
+ } from "./chunk-NFWPDEN4.js";
11
12
  import {
12
13
  ATTACHMENTS_DIR,
13
14
  attachmentsGitignoreBody
@@ -30,7 +31,7 @@ import {
30
31
  resolveThreadDefaults,
31
32
  resolveViewerProfile,
32
33
  resolveViewerProfileForRepo
33
- } from "./chunk-BTC2D6LS.js";
34
+ } from "./chunk-Y5JES2VV.js";
34
35
  import {
35
36
  appDataDir,
36
37
  globalAgentCwd,
@@ -38,7 +39,7 @@ import {
38
39
  } from "./chunk-EQNRWDLN.js";
39
40
 
40
41
  // src/store/workspaces.ts
41
- import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
42
+ import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync3, statSync as statSync2, writeFileSync as writeFileSync3 } from "fs";
42
43
  import { basename as basename2, join as join3 } from "path";
43
44
 
44
45
  // src/brightsy/cloud-connect-constants.ts
@@ -796,6 +797,41 @@ function listWorkspaces() {
796
797
  if (valid.length !== all.length) writeAll(valid);
797
798
  return valid.sort((a, b) => a.name.localeCompare(b.name));
798
799
  }
800
+ function isLinkedWorktreeOf(path, mainRepo) {
801
+ if (!path || path === mainRepo) return false;
802
+ const git = join3(path, ".git");
803
+ try {
804
+ if (!existsSync2(git) || statSync2(git).isDirectory()) return false;
805
+ const text = readFileSync3(git, "utf8");
806
+ const needle = `${mainRepo.replace(/\/+$/, "")}/.git`;
807
+ return text.includes(needle);
808
+ } catch {
809
+ return false;
810
+ }
811
+ }
812
+ function primaryCheckoutFromLinkedWorktree(path) {
813
+ if (!path) return null;
814
+ const git = join3(path, ".git");
815
+ try {
816
+ if (!existsSync2(git) || statSync2(git).isDirectory()) return null;
817
+ const text = readFileSync3(git, "utf8");
818
+ const match = /^\s*gitdir:\s*(.+)$/m.exec(text);
819
+ if (!match) return null;
820
+ const gitdir = match[1].trim().replace(/\/+$/, "");
821
+ const worktrees = gitdir.lastIndexOf("/.git/worktrees/");
822
+ const root = worktrees > 0 ? gitdir.slice(0, worktrees) : gitdir.endsWith("/.git") ? gitdir.slice(0, -5) : null;
823
+ if (!root) return null;
824
+ return canonicalizeRepoPath(root);
825
+ } catch {
826
+ return null;
827
+ }
828
+ }
829
+ function resolveSyncWorkspacePath(path) {
830
+ if (!path || path === "/") return null;
831
+ const primary = primaryCheckoutFromLinkedWorktree(path);
832
+ if (primary) return primary;
833
+ return canonicalizeRepoPath(path);
834
+ }
799
835
  async function addWorkspace(repoPath) {
800
836
  const root = await resolveRepoRoot(repoPath);
801
837
  if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
@@ -804,13 +840,14 @@ async function addWorkspace(repoPath) {
804
840
  await ensureGhPreferOrigin(root);
805
841
  const current = readAll();
806
842
  const existing = current.find((w) => w.path === root);
807
- if (existing) return existing;
808
- const next = {
843
+ const withoutLinked = current.filter((w) => !isLinkedWorktreeOf(w.path, root));
844
+ if (existing && withoutLinked.length === current.length) return existing;
845
+ const next = existing ?? {
809
846
  path: root,
810
847
  name: basename2(root),
811
848
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
812
849
  };
813
- writeAll([...current, next]);
850
+ writeAll(existing ? withoutLinked : [...withoutLinked, next]);
814
851
  return next;
815
852
  }
816
853
  function removeWorkspace(repoPath) {
@@ -823,9 +860,24 @@ async function ensureWorkspace(repoPath) {
823
860
  function syncWorkspacesFromThreads(repoPaths) {
824
861
  const current = readAll();
825
862
  const removed = readRemoved();
826
- const byPath = new Map(current.map((w) => [w.path, w]));
863
+ const byPath = /* @__PURE__ */ new Map();
827
864
  let dirty = false;
828
- for (const path of repoPaths) {
865
+ for (const w of current) {
866
+ const resolved = resolveSyncWorkspacePath(w.path) ?? w.path;
867
+ if (resolved !== w.path) dirty = true;
868
+ if (!resolved || resolved === "/" || isGlobalRepoPath(resolved) || removed.has(resolved)) {
869
+ dirty = true;
870
+ continue;
871
+ }
872
+ if (!byPath.has(resolved)) {
873
+ byPath.set(
874
+ resolved,
875
+ resolved === w.path ? w : { ...w, path: resolved, name: basename2(resolved) }
876
+ );
877
+ }
878
+ }
879
+ for (const raw of repoPaths) {
880
+ const path = resolveSyncWorkspacePath(raw);
829
881
  if (!path || path === "/" || isGlobalRepoPath(path) || byPath.has(path) || removed.has(path)) {
830
882
  continue;
831
883
  }
@@ -838,6 +890,13 @@ function syncWorkspacesFromThreads(repoPaths) {
838
890
  byPath.set(path, ws);
839
891
  dirty = true;
840
892
  }
893
+ for (const [path] of byPath) {
894
+ const mains = [...byPath.keys()];
895
+ if (mains.some((main) => isLinkedWorktreeOf(path, main))) {
896
+ byPath.delete(path);
897
+ dirty = true;
898
+ }
899
+ }
841
900
  const next = [...byPath.values()];
842
901
  if (dirty) writeAll(next);
843
902
  return next.sort((a, b) => a.name.localeCompare(b.name));
@@ -849,6 +908,7 @@ export {
849
908
  persistPendingFileAttachments,
850
909
  attachmentsFromWorktreePaths,
851
910
  listWorkspaces,
911
+ primaryCheckoutFromLinkedWorktree,
852
912
  addWorkspace,
853
913
  removeWorkspace,
854
914
  ensureWorkspace,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  git
3
- } from "./chunk-UFHNSFAS.js";
3
+ } from "./chunk-HVUVQXZ2.js";
4
4
 
5
5
  // src/git/worktree-exclude.ts
6
6
  import { mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -4,14 +4,14 @@ import {
4
4
  normalizeAbleTimeCredential,
5
5
  normalizeAbleTimeHost,
6
6
  rewriteAbleTimeError
7
- } from "./chunk-G4TANQC3.js";
7
+ } from "./chunk-646I442S.js";
8
8
  import {
9
9
  httpFetch
10
10
  } from "./chunk-N7WZ6NIN.js";
11
11
  import {
12
12
  getAbleTimeAccessToken,
13
13
  getAbleTimeHost
14
- } from "./chunk-L5CIEBLR.js";
14
+ } from "./chunk-EWHJNJHV.js";
15
15
 
16
16
  // src/integrations/abletime-rest.ts
17
17
  var ABLETIME_REST_PREFIX = "/api/public/v2";
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  textFromAbleTimeDoc
3
- } from "./chunk-2M5B7YNY.js";
3
+ } from "./chunk-RRW2XWAY.js";
4
4
  import {
5
5
  assertAbleTimeCredential,
6
6
  callAbleTimeTool,
7
7
  normalizeAbleTimeHost,
8
8
  rewriteAbleTimeError
9
- } from "./chunk-G4TANQC3.js";
9
+ } from "./chunk-646I442S.js";
10
10
  import {
11
11
  isAbleTimeConnected,
12
12
  saveAbleTimeConnection
13
- } from "./chunk-L5CIEBLR.js";
13
+ } from "./chunk-EWHJNJHV.js";
14
14
 
15
15
  // src/integrations/abletime.ts
16
16
  var CLOSED_STATES = /* @__PURE__ */ new Set([
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-Y4MIXGPA.js";
10
10
  import {
11
11
  run
12
- } from "./chunk-FNQNJOHY.js";
12
+ } from "./chunk-ABOBTSO6.js";
13
13
  import {
14
14
  appDataDir
15
15
  } from "./chunk-EQNRWDLN.js";
@@ -2,7 +2,7 @@
2
2
 
3
3
  import {
4
4
  git
5
- } from "./chunk-FNQNJOHY.js";
5
+ } from "./chunk-ABOBTSO6.js";
6
6
 
7
7
  // src/git/worktree-exclude.ts
8
8
  import { mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -2,17 +2,17 @@
2
2
 
3
3
  import {
4
4
  textFromAbleTimeDoc
5
- } from "./chunk-YVE4PXCJ.js";
5
+ } from "./chunk-CLI5DVU4.js";
6
6
  import {
7
7
  assertAbleTimeCredential,
8
8
  callAbleTimeTool,
9
9
  normalizeAbleTimeHost,
10
10
  rewriteAbleTimeError
11
- } from "./chunk-LS6TSOCE.js";
11
+ } from "./chunk-HSYE5ID6.js";
12
12
  import {
13
13
  isAbleTimeConnected,
14
14
  saveAbleTimeConnection
15
- } from "./chunk-BTC2D6LS.js";
15
+ } from "./chunk-Y5JES2VV.js";
16
16
 
17
17
  // src/integrations/abletime.ts
18
18
  var CLOSED_STATES = /* @__PURE__ */ new Set([
@@ -1,13 +1,13 @@
1
- import {
2
- isElectronLikeCommand,
3
- wrapElectronAsNodeLaunch
4
- } from "./chunk-4TR3HZFT.js";
5
1
  import {
6
2
  appDataDir
7
3
  } from "./chunk-WFUDY6PC.js";
8
4
  import {
9
5
  run
10
- } from "./chunk-UFHNSFAS.js";
6
+ } from "./chunk-HVUVQXZ2.js";
7
+ import {
8
+ isElectronLikeCommand,
9
+ wrapElectronAsNodeLaunch
10
+ } from "./chunk-4TR3HZFT.js";
11
11
 
12
12
  // src/agents/error-detail.ts
13
13
  function formatUnknownDetail(err) {
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+
3
+
4
+ // src/hook/nested-electron-env.ts
5
+ var NESTED_ELECTRON_ENV_PREFIXES = ["ELECTRON_", "CHROME_"];
6
+ function isNestedElectronEnvKey(key) {
7
+ return NESTED_ELECTRON_ENV_PREFIXES.some((prefix) => key.startsWith(prefix));
8
+ }
9
+ function stripNestedElectronEnv(env) {
10
+ const out = { ...env };
11
+ for (const key of Object.keys(out)) {
12
+ if (isNestedElectronEnvKey(key)) delete out[key];
13
+ }
14
+ return out;
15
+ }
16
+ function dropNestedElectronEnvFromProcess(env = process.env) {
17
+ for (const key of Object.keys(env)) {
18
+ if (isNestedElectronEnvKey(key)) delete env[key];
19
+ }
20
+ }
21
+ var STRIP_NESTED_ELECTRON_THEN_EXEC = [
22
+ "vars=`printenv | awk -F= '/^(ELECTRON_|CHROME_)/{print $1}'`",
23
+ '[ -n "$vars" ] && unset $vars',
24
+ "export ELECTRON_RUN_AS_NODE=1",
25
+ 'exec "$@"'
26
+ ].join("; ");
27
+ function wrapElectronAsNodeLaunch(file, args) {
28
+ if (process.platform === "win32") return { file, args };
29
+ return {
30
+ file: "/bin/sh",
31
+ args: ["-c", STRIP_NESTED_ELECTRON_THEN_EXEC, "sh", file, ...args]
32
+ };
33
+ }
34
+ function isStrippedElectronLaunch(command, args) {
35
+ return command === "/bin/sh" && Boolean(args?.[1]?.includes("ELECTRON_RUN_AS_NODE") && args[1].includes("unset"));
36
+ }
37
+ function isElectronLikeCommand(command) {
38
+ const name = command.trim();
39
+ if (!name) return false;
40
+ if (process.versions.electron && name === process.execPath) return true;
41
+ return /(?:^|[/\\])Electron(?:\.exe)?$/i.test(name) || /(?:^|[/\\])Sideboard(?:\.exe)?$/i.test(name) || /(?:Sideboard|Electron)\.app[/\\]Contents[/\\]MacOS[/\\]/i.test(name);
42
+ }
43
+ function unwrapStrippedElectronLaunch(command, args) {
44
+ if (!isStrippedElectronLaunch(command, args) || !args || args.length < 4) {
45
+ return null;
46
+ }
47
+ return { file: args[3], args: args.slice(4) };
48
+ }
49
+
50
+ export {
51
+ stripNestedElectronEnv,
52
+ dropNestedElectronEnvFromProcess,
53
+ wrapElectronAsNodeLaunch,
54
+ isElectronLikeCommand,
55
+ unwrapStrippedElectronLaunch
56
+ };