@sideboard-ai/core 0.1.235 → 0.1.236

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 (67) hide show
  1. package/dist/{abletime-WZNDTRVL.js → abletime-KOGCIQCO.js} +5 -5
  2. package/dist/{abletime-BGVOCEOU.js → abletime-VSV6AUBV.js} +5 -5
  3. package/dist/{abletime-oauth-ZLU2EYRK.js → abletime-oauth-LY7KZICW.js} +4 -4
  4. package/dist/{abletime-oauth-6M5GWEPX.js → abletime-oauth-QMDV45JC.js} +4 -4
  5. package/dist/{abletime-rest-WNHIATB3.js → abletime-rest-LXOWKPL7.js} +4 -4
  6. package/dist/{abletime-rest-F7XG5NGY.js → abletime-rest-NL56UVK5.js} +4 -4
  7. package/dist/agents/cursor-runner.cjs +39 -35
  8. package/dist/agents/cursor-runner.js +3 -3
  9. package/dist/{agents-37JCAVSC.js → agents-JC6DRIT3.js} +9 -9
  10. package/dist/{agents-MOMMKSYV.js → agents-S4HYHRL3.js} +8 -8
  11. package/dist/{app-settings-KBL2G7M4.js → app-settings-2CFCRYD7.js} +2 -2
  12. package/dist/{app-settings-UXWCPDEA.js → app-settings-I27UBVI4.js} +2 -2
  13. package/dist/{caffeinate-hold-OK4JJ5PP.js → caffeinate-hold-FNKIPXDU.js} +2 -2
  14. package/dist/{caffeinate-hold-22VFDPSO.js → caffeinate-hold-PXHGH7ZN.js} +2 -2
  15. package/dist/{chunk-7J72QJOM.js → chunk-224IXQOM.js} +1 -1
  16. package/dist/{chunk-4VGCG2HV.js → chunk-3AJUH66R.js} +2 -2
  17. package/dist/{chunk-P6ZM5QJW.js → chunk-3PGFAVFL.js} +2 -2
  18. package/dist/{chunk-RZTRWN2V.js → chunk-4H5WO4H3.js} +1 -1
  19. package/dist/{chunk-MVLXDYN5.js → chunk-5ELC3KK3.js} +5 -5
  20. package/dist/{chunk-WPD7BR6C.js → chunk-5SHYLRTU.js} +1 -1
  21. package/dist/{chunk-S2OEFXST.js → chunk-5UN5C5WP.js} +5 -5
  22. package/dist/{chunk-LJWF3VA3.js → chunk-6Q2CFQ4D.js} +74 -30
  23. package/dist/{chunk-WFUDY6PC.js → chunk-A4JGXX2F.js} +155 -24
  24. package/dist/{chunk-EAYXD2IC.js → chunk-ANGPU5JL.js} +282 -14
  25. package/dist/{chunk-GHRZNPBK.js → chunk-C2CBF4YE.js} +2 -2
  26. package/dist/{chunk-TNVJPFHM.js → chunk-CJKL7A4G.js} +5 -5
  27. package/dist/{chunk-SWNEA5OZ.js → chunk-CRAXJAYJ.js} +3 -3
  28. package/dist/{chunk-C774RJJA.js → chunk-CWHMLCLN.js} +3 -3
  29. package/dist/{chunk-YWI3IBP2.js → chunk-DQN5U2VH.js} +1 -1
  30. package/dist/{chunk-D4VKJO5C.js → chunk-DYXNBXE3.js} +304 -16
  31. package/dist/{chunk-SPAMHHJH.js → chunk-J5GON4SU.js} +1 -1
  32. package/dist/{chunk-4VFOJZPS.js → chunk-JXZS56VW.js} +3 -3
  33. package/dist/{chunk-EQNRWDLN.js → chunk-KK63BFYN.js} +151 -24
  34. package/dist/{chunk-X5B3OS5I.js → chunk-N6XI5KXL.js} +1 -1
  35. package/dist/{chunk-XJETIO4K.js → chunk-NJ5OXOTN.js} +2 -2
  36. package/dist/{chunk-RGNPPRZZ.js → chunk-NYAEMZ3L.js} +3 -3
  37. package/dist/{chunk-7H2CVVLF.js → chunk-O3UAQAYA.js} +3 -3
  38. package/dist/{chunk-4TYXWPAJ.js → chunk-OJFEVWZN.js} +1 -1
  39. package/dist/{chunk-I5NC7DWO.js → chunk-P3DCZRER.js} +1 -1
  40. package/dist/{chunk-TWXSZYR2.js → chunk-RRXRLHIE.js} +5 -5
  41. package/dist/{chunk-AS4UN7QL.js → chunk-VVOAXBND.js} +5 -5
  42. package/dist/{chunk-7366AB7E.js → chunk-XMCJDWPA.js} +77 -32
  43. package/dist/{connected-teams-KQUDU7LZ.js → connected-teams-62AJRDDD.js} +2 -2
  44. package/dist/{connected-teams-JUJAQZZE.js → connected-teams-GXV22ZSF.js} +2 -2
  45. package/dist/{coordinator-prompt-CE7MN6QY.js → coordinator-prompt-2BRUH7PJ.js} +6 -6
  46. package/dist/{coordinator-prompt-IGDMFKCD.js → coordinator-prompt-BIP7ZEJ3.js} +6 -6
  47. package/dist/{cursor-recover-DTQAUDGO.js → cursor-recover-DFMCTZA4.js} +2 -2
  48. package/dist/{cursor-recover-4PQAADAU.js → cursor-recover-K3EBEM7M.js} +2 -2
  49. package/dist/{global-workspace-7WH24UFO.js → global-workspace-3XZN3QHZ.js} +6 -6
  50. package/dist/{global-workspace-NCIC2Y2U.js → global-workspace-DWCFG7LP.js} +6 -6
  51. package/dist/index.cjs +1219 -707
  52. package/dist/index.d.cts +70 -1
  53. package/dist/index.d.ts +70 -1
  54. package/dist/index.js +79 -23
  55. package/dist/mcp/run-stdio.cjs +1123 -659
  56. package/dist/mcp/run-stdio.js +45 -22
  57. package/dist/{orchestrator-6NPBOBNA.js → orchestrator-AYPDBGIF.js} +10 -10
  58. package/dist/{orchestrator-RKWRI3PJ.js → orchestrator-TEJJAQWP.js} +11 -11
  59. package/dist/{paths-C2VERLAE.js → paths-LGKOG7MY.js} +1 -1
  60. package/dist/{paths-LOXCISLX.js → paths-O6ZEAEUD.js} +1 -1
  61. package/dist/{thread-store-IKJD4EOK.js → thread-store-AYPBEZT5.js} +3 -3
  62. package/dist/{thread-store-FBK5SZ5P.js → thread-store-YOPKY74K.js} +3 -3
  63. package/dist/{workspaces-H2TRFDE2.js → workspaces-NYT2472Z.js} +6 -6
  64. package/dist/{workspaces-NSQZSDQD.js → workspaces-V7522TQH.js} +6 -6
  65. package/dist/{worktree-W7BSI4GU.js → worktree-AGVPKDBH.js} +5 -5
  66. package/dist/{worktree-FMIX4BRV.js → worktree-IRALYI6A.js} +5 -5
  67. package/package.json +1 -1
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-JFOPOMK7.js";
8
8
  import {
9
9
  releaseCaffeinateHoldForThread
10
- } from "./chunk-YWI3IBP2.js";
10
+ } from "./chunk-DQN5U2VH.js";
11
11
  import {
12
12
  PLAN_MODE_INSTRUCTION,
13
13
  adjustBrightsyTurnExit,
@@ -42,7 +42,7 @@ import {
42
42
  summarizeTurnStderr,
43
43
  toolDescription,
44
44
  turnFailChatText
45
- } from "./chunk-EAYXD2IC.js";
45
+ } from "./chunk-ANGPU5JL.js";
46
46
  import {
47
47
  SLACK_REPLY_FORMATTING,
48
48
  addWorkspace,
@@ -65,7 +65,7 @@ import {
65
65
  stageAbsolutePathsAsAttachments,
66
66
  stageBuffersAsAttachments,
67
67
  syncWorkspacesFromThreads
68
- } from "./chunk-TWXSZYR2.js";
68
+ } from "./chunk-RRXRLHIE.js";
69
69
  import {
70
70
  addPrStackLayer,
71
71
  allocateTeamName,
@@ -114,7 +114,7 @@ import {
114
114
  worktreeDisplayLabelForGroup,
115
115
  worktreeNameFromPath,
116
116
  worktreeSlugForTicket
117
- } from "./chunk-4VFOJZPS.js";
117
+ } from "./chunk-JXZS56VW.js";
118
118
  import {
119
119
  ATTACHMENTS_DIR,
120
120
  DETACHED_JOBS_DIR,
@@ -132,7 +132,7 @@ import {
132
132
  updateThread,
133
133
  withThreadLock,
134
134
  writeThread
135
- } from "./chunk-XJETIO4K.js";
135
+ } from "./chunk-NJ5OXOTN.js";
136
136
  import {
137
137
  ensureWorktreeSideboardIgnored
138
138
  } from "./chunk-DD67JWTN.js";
@@ -177,11 +177,12 @@ import {
177
177
  updateAdvancedSettings,
178
178
  usageOnLimit,
179
179
  writeSecureJson
180
- } from "./chunk-RZTRWN2V.js";
180
+ } from "./chunk-4H5WO4H3.js";
181
181
  import {
182
182
  writePrivateFile
183
183
  } from "./chunk-NSTQ6QKD.js";
184
184
  import {
185
+ annotateDevAccessRuns,
185
186
  appDataDir,
186
187
  findConventionSetup,
187
188
  loadRepoSettings,
@@ -193,7 +194,7 @@ import {
193
194
  threadsDir,
194
195
  workspaceSettingsSourceLabel,
195
196
  worktreesRoot
196
- } from "./chunk-EQNRWDLN.js";
197
+ } from "./chunk-KK63BFYN.js";
197
198
  import {
198
199
  stripNestedElectronEnv
199
200
  } from "./chunk-WWUABK6B.js";
@@ -418,7 +419,7 @@ async function continueSourceThread(threadId, prompt) {
418
419
  await continueOnReply(threadId, prompt);
419
420
  return;
420
421
  }
421
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-6NPBOBNA.js");
422
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-AYPDBGIF.js");
422
423
  await getOrchestrator2().send(threadId, prompt);
423
424
  } catch {
424
425
  }
@@ -896,9 +897,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
896
897
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
897
898
  );
898
899
  }
899
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-7WH24UFO.js");
900
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-3XZN3QHZ.js");
900
901
  if (isGlobalThread2(thread)) {
901
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-CE7MN6QY.js");
902
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-2BRUH7PJ.js");
902
903
  ensureGlobalCoordinatorCwd2(
903
904
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
904
905
  );
@@ -3935,7 +3936,7 @@ async function createThread(input, _onSetupLine) {
3935
3936
  });
3936
3937
  await requireAgent(resolved.agent);
3937
3938
  if (input.cowboy) {
3938
- const { cowboyModeEnabled } = await import("./app-settings-KBL2G7M4.js");
3939
+ const { cowboyModeEnabled } = await import("./app-settings-2CFCRYD7.js");
3939
3940
  if (!cowboyModeEnabled()) {
3940
3941
  throw new Error(
3941
3942
  "Cowboy mode is off. Enable it in Settings \u2192 Advanced."
@@ -3993,7 +3994,7 @@ async function createThread(input, _onSetupLine) {
3993
3994
  let sourceIsFork = false;
3994
3995
  if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
3995
3996
  if (isAbleTimeConnected() && getIssueSource() === "abletime") {
3996
- const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-WZNDTRVL.js");
3997
+ const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-KOGCIQCO.js");
3997
3998
  const task = await ensureAbleTimeTask({
3998
3999
  title: title?.trim() || "Untitled work",
3999
4000
  description: input.prompt?.trim() || void 0
@@ -4556,7 +4557,7 @@ async function adoptThread(input) {
4556
4557
  messages: input.messages ?? []
4557
4558
  });
4558
4559
  writeThread(thread);
4559
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-NSQZSDQD.js");
4560
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-V7522TQH.js");
4560
4561
  await ensureWorkspace2(repoPath);
4561
4562
  const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-5N2KTYIT.js");
4562
4563
  await ensureWorktreeSideboardIgnored2(input.worktreePath);
@@ -6465,6 +6466,34 @@ function formatRenameBranchDirective(thread, opts) {
6465
6466
  }
6466
6467
  return lines.join("\n");
6467
6468
  }
6469
+ function localhostPreviewUrl(port) {
6470
+ return `http://localhost:${port}`;
6471
+ }
6472
+ function describeLiveDevRun(run2) {
6473
+ const url = localhostPreviewUrl(run2.port);
6474
+ if (run2.preview === "window") {
6475
+ return `${run2.scriptName} Electron window (renderer ${url})`;
6476
+ }
6477
+ return `${run2.scriptName} ${url}`;
6478
+ }
6479
+ function formatDevAccessHint(runs) {
6480
+ const live = (runs ?? []).filter(
6481
+ (r) => Number.isFinite(r.port) && r.port > 0
6482
+ );
6483
+ if (live.length === 1) {
6484
+ const r = live[0];
6485
+ const url = localhostPreviewUrl(r.port);
6486
+ if (r.preview === "window") {
6487
+ return `This worktree's Dev app is the Electron window (${r.scriptName}). Renderer origin ${url} \u2014 curl to confirm Vite; do not open it in a browser (no preload/IPC). Do not guess :3000.`;
6488
+ }
6489
+ return `This worktree's Dev app is ${url} (${r.scriptName}). Open that URL (browser, curl, Playwright) \u2014 do not guess :3000.`;
6490
+ }
6491
+ if (live.length > 1) {
6492
+ const bits = live.map(describeLiveDevRun).join("; ");
6493
+ return `This worktree's Dev apps: ${bits}. preview=url \u2192 open the URL; preview=window \u2192 Electron window is the app. Do not guess :3000.`;
6494
+ }
6495
+ return "To open the project Dev app: MCP `run_dev_script` (same as the desktop Dev button) returns `{url, port, preview}` (`SIDEBOARD_PORT`, not 3000). preview=url \u2192 open that URL (browser, curl, Playwright). preview=window \u2192 Electron: the native window is the app; url is renderer/HMR only (no preload/IPC in a browser). If already running, `list_run_scripts` `active[].url`. `stop_dev_script` to stop.";
6496
+ }
6468
6497
  function formatWorktreeDirective(thread, opts) {
6469
6498
  const worktree = normPath(thread.worktreePath);
6470
6499
  const repo = normPath(thread.repoPath);
@@ -6512,6 +6541,8 @@ function formatWorktreeDirective(thread, opts) {
6512
6541
  '- Sideboard git buttons send short phrases ("Commit and push.", "Ready for review.", "Merge PR.", \u2026) with their meaning attached \u2014 act on them without asking for clarification. If the user gives a goal (Greptile 5/5, CI green, until checks pass), you get the watch-fix-push playbook with that request.'
6513
6542
  );
6514
6543
  lines.push("");
6544
+ lines.push(formatDevAccessHint(opts?.activeRuns));
6545
+ lines.push("");
6515
6546
  lines.push(formatProcessGuideDirective({ worktreePath: thread.worktreePath }));
6516
6547
  return lines.join("\n");
6517
6548
  }
@@ -6615,12 +6646,12 @@ function formatLongRunningDirective(opts) {
6615
6646
  "- Hanging, no useful output, or the wrong thing \u2192 `stop_job` (or the helper with `stop <id>`). Do not stop a pack/test/deploy that is clearly making progress.",
6616
6647
  "- Stay in the loop until stillRunning is false (or you stopped it). ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
6617
6648
  "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available).",
6618
- "Project Dev / run scripts (`.sideboard` `[scripts.run.*]`, same as the desktop Dev button): use MCP `list_run_scripts` / `run_dev_script` / `stop_dev_script` \u2014 logs and Stop live in the thread UI. Do not detached-job or shell-spawn that same command."
6649
+ "Project Dev / run scripts (`.sideboard` `[scripts.run.*]`, same as the desktop Dev button): use MCP `list_run_scripts` / `run_dev_script` / `stop_dev_script` \u2014 logs and Stop live in the thread UI. Do not detached-job or shell-spawn that same command. `run_dev_script` returns `{url, port, preview}` (`SIDEBOARD_PORT`). preview=url \u2192 open that URL; preview=window \u2192 Electron window is the app (url is renderer/HMR only). Never guess :3000."
6619
6650
  ].join("\n");
6620
6651
  }
6621
6652
  function formatLongRunningReminder(opts) {
6622
6653
  const invoke = formatDetachedJobInvoke(opts?.scriptPath);
6623
- return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait). The log pane updates from wait JSON; present_artifact type=log is optional. stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn. Project Dev button: list_run_scripts / run_dev_script / stop_dev_script (UI-connected \u2014 not detached-job).`;
6654
+ return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait). The log pane updates from wait JSON; present_artifact type=log is optional. stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn. Project Dev button: list_run_scripts / run_dev_script / stop_dev_script (UI-connected \u2014 not detached-job). ${formatDevAccessHint(opts?.activeRuns)}`;
6624
6655
  }
6625
6656
  function formatArtifactDirective() {
6626
6657
  return [
@@ -6632,7 +6663,7 @@ function formatArtifactDirective() {
6632
6663
  ].join("\n");
6633
6664
  }
6634
6665
  function formatUiReminder() {
6635
- return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos, \u201Cwhat next?\u201D, or after a review) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable. Dev / preview: run_dev_script (same as the Dev button); stop_dev_script to stop.";
6666
+ return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos, \u201Cwhat next?\u201D, or after a review) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable. Dev / preview: run_dev_script (same as the Dev button) returns {url, port, preview} (SIDEBOARD_PORT \u2014 never guess :3000). preview=url \u2192 open url; preview=window \u2192 Electron window is the app, url is renderer/HMR only. list_run_scripts active[].url if already running; stop_dev_script to stop.";
6636
6667
  }
6637
6668
 
6638
6669
  // src/review/review-write-gate.ts
@@ -7032,7 +7063,7 @@ function formatScheduledPrompt(name, prompt) {
7032
7063
  ${prompt}`;
7033
7064
  }
7034
7065
  async function defaultDeps() {
7035
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-6NPBOBNA.js");
7066
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-AYPDBGIF.js");
7036
7067
  const orch = getOrchestrator2();
7037
7068
  return {
7038
7069
  findThread: (id) => findThreadByRef(id),
@@ -7357,7 +7388,7 @@ var Orchestrator = class {
7357
7388
  orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
7358
7389
  });
7359
7390
  }
7360
- const { autoCleanupOrphansEnabled } = await import("./app-settings-KBL2G7M4.js");
7391
+ const { autoCleanupOrphansEnabled } = await import("./app-settings-2CFCRYD7.js");
7361
7392
  if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
7362
7393
  await cleanupOrphanWorktrees({ repoPaths });
7363
7394
  }
@@ -7704,7 +7735,7 @@ var Orchestrator = class {
7704
7735
  }
7705
7736
  await setup;
7706
7737
  if (skipSetup) return;
7707
- const { autoRunAfterSetupEnabled } = await import("./app-settings-KBL2G7M4.js");
7738
+ const { autoRunAfterSetupEnabled } = await import("./app-settings-2CFCRYD7.js");
7708
7739
  if (autoRunAfterSetupEnabled()) {
7709
7740
  try {
7710
7741
  await this.startDev(threadId);
@@ -8007,8 +8038,13 @@ var Orchestrator = class {
8007
8038
  SLACK_REPLY_FORMATTING
8008
8039
  ].join("\n") : null
8009
8040
  ].filter(Boolean).join("\n") : null;
8041
+ const worktreeActiveRuns = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && thread.worktreePath ? annotateDevAccessRuns(
8042
+ mergeWorktreeActiveRuns(threadsSharingWorktree(thread.worktreePath)).activeRuns,
8043
+ listRunScripts(thread.worktreePath, thread.repoPath),
8044
+ thread.worktreePath
8045
+ ) : [];
8010
8046
  const artifactReminder = thread.agent !== "brightsy" ? formatUiReminder() : null;
8011
- const longRunningReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatLongRunningReminder() : null;
8047
+ const longRunningReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatLongRunningReminder({ activeRuns: worktreeActiveRuns }) : null;
8012
8048
  const worktreeReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatWorktreeReminder() : null;
8013
8049
  const optionalServicesReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatOptionalServicesReminder(loadAppSettings().integrations) : null;
8014
8050
  const issueTicket = issueTicketFromThread(thread, resolveEffectiveIssueSource());
@@ -8060,7 +8096,7 @@ var Orchestrator = class {
8060
8096
  }
8061
8097
  const isBrightsy = fresh.agent === "brightsy";
8062
8098
  const isOrchestration = isOrchestratorThread(fresh);
8063
- const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-KBL2G7M4.js");
8099
+ const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-2CFCRYD7.js");
8064
8100
  const gitAuthMode = getGithubGitAuthMode();
8065
8101
  const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
8066
8102
  githubSlug: await withTimeout(
@@ -8068,7 +8104,14 @@ var Orchestrator = class {
8068
8104
  8e3,
8069
8105
  "resolveGithubRepoSlug"
8070
8106
  ).catch(() => null),
8071
- gitAuthMode
8107
+ gitAuthMode,
8108
+ activeRuns: annotateDevAccessRuns(
8109
+ mergeWorktreeActiveRuns(
8110
+ threadsSharingWorktree(fresh.worktreePath)
8111
+ ).activeRuns,
8112
+ listRunScripts(fresh.worktreePath, fresh.repoPath),
8113
+ fresh.worktreePath
8114
+ )
8072
8115
  });
8073
8116
  const artifactDirective = isBrightsy ? null : formatArtifactDirective();
8074
8117
  const longRunningDirective = isBrightsy || isOrchestration ? null : formatLongRunningDirective();
@@ -8208,7 +8251,7 @@ var Orchestrator = class {
8208
8251
  if (!this.stoppedTurns.has(threadId) && this.requireThread(threadId).agent === "cursor" && exitCode !== 0 && !assistantText && parts.length === 0) {
8209
8252
  const sessionId = result.sessionId || this.requireThread(threadId).sessionId || "";
8210
8253
  if (sessionId) {
8211
- const { recoverFinishedCursorRun } = await import("./cursor-recover-4PQAADAU.js");
8254
+ const { recoverFinishedCursorRun } = await import("./cursor-recover-K3EBEM7M.js");
8212
8255
  for (let i = 0; i < 8; i++) {
8213
8256
  const recovered = recoverFinishedCursorRun({
8214
8257
  agentId: sessionId,
@@ -9291,7 +9334,7 @@ var Orchestrator = class {
9291
9334
  if (!titled.userSetTitle && meta.title && titled.title !== meta.title) {
9292
9335
  updateThread(thread.id, { title: meta.title });
9293
9336
  }
9294
- const { autoArchiveOnMergeEnabled } = await import("./app-settings-KBL2G7M4.js");
9337
+ const { autoArchiveOnMergeEnabled } = await import("./app-settings-2CFCRYD7.js");
9295
9338
  const latest = this.requireThread(thread.id);
9296
9339
  if (!shouldAutoArchiveOnPrMerge({
9297
9340
  previousPrState: prevState || null,
@@ -9573,7 +9616,7 @@ var Orchestrator = class {
9573
9616
  this.enforceHistoryRetention();
9574
9617
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
9575
9618
  try {
9576
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-NSQZSDQD.js");
9619
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-V7522TQH.js");
9577
9620
  await ensureWorkspace2(thread.repoPath);
9578
9621
  } catch {
9579
9622
  }
@@ -9600,7 +9643,7 @@ var Orchestrator = class {
9600
9643
  await runArchiveScript(thread.repoPath, thread.worktreePath);
9601
9644
  } catch {
9602
9645
  }
9603
- const { deleteBranchOnPurgeEnabled } = await import("./app-settings-KBL2G7M4.js");
9646
+ const { deleteBranchOnPurgeEnabled } = await import("./app-settings-2CFCRYD7.js");
9604
9647
  const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
9605
9648
  await removeWorktree(thread.repoPath, thread.worktreePath, {
9606
9649
  deleteBranch: deleteBranch ? thread.branchName : void 0
@@ -9615,7 +9658,7 @@ var Orchestrator = class {
9615
9658
  throw new Error("Thread is not archived");
9616
9659
  }
9617
9660
  if (isGlobalThread(thread)) {
9618
- const { globalAgentCwd } = await import("./paths-C2VERLAE.js");
9661
+ const { globalAgentCwd } = await import("./paths-LGKOG7MY.js");
9619
9662
  updateThread(thread.id, { worktreePath: globalAgentCwd() });
9620
9663
  const restored2 = setStatus(thread.id, "idle");
9621
9664
  this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
@@ -9627,7 +9670,7 @@ var Orchestrator = class {
9627
9670
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
9628
9671
  );
9629
9672
  }
9630
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-FMIX4BRV.js");
9673
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-IRALYI6A.js");
9631
9674
  const slug = thread.worktreePath.split("/").pop();
9632
9675
  const dest = thread.worktreePath;
9633
9676
  await withRepoGitLock(thread.repoPath, async () => {
@@ -9737,7 +9780,7 @@ async function startOrchestration(opts) {
9737
9780
  sourceRef: "default",
9738
9781
  ...createOpts
9739
9782
  }).catch(async () => {
9740
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-FMIX4BRV.js");
9783
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-IRALYI6A.js");
9741
9784
  const repo = await resolveRepoRoot2(repoPath);
9742
9785
  const def = await resolveDefaultBranch2(repo);
9743
9786
  return orch.createThread({
@@ -9747,7 +9790,7 @@ async function startOrchestration(opts) {
9747
9790
  repoPath: repo
9748
9791
  });
9749
9792
  });
9750
- const { updateThread: upd } = await import("./thread-store-FBK5SZ5P.js");
9793
+ const { updateThread: upd } = await import("./thread-store-YOPKY74K.js");
9751
9794
  const updated = upd(thread.id, {
9752
9795
  sourceType: "orchestration",
9753
9796
  sourceRef: goal
@@ -9788,6 +9831,7 @@ export {
9788
9831
  assembleHomeBoard,
9789
9832
  HOME_BOARD_AGENT_HINT,
9790
9833
  readTurnLive,
9834
+ localhostPreviewUrl,
9791
9835
  resolveScheduleThreadId,
9792
9836
  listSchedules,
9793
9837
  getSchedule,
@@ -1,13 +1,13 @@
1
1
  // src/store/paths.ts
2
2
  import { basename } from "path";
3
3
  import { homedir as homedir2 } from "os";
4
- import { join as join4 } from "path";
4
+ import { join as join5 } from "path";
5
5
  import { mkdirSync } from "fs";
6
6
 
7
7
  // src/hook/settings.ts
8
- import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
8
+ import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
9
9
  import { homedir } from "os";
10
- import { join as join3 } from "path";
10
+ import { join as join4 } from "path";
11
11
  import { parse as parseToml } from "smol-toml";
12
12
 
13
13
  // src/hook/convention-setup.ts
@@ -127,10 +127,133 @@ function hasCursorWorktreeSetup(worktreePath, repoPath) {
127
127
  return false;
128
128
  }
129
129
 
130
+ // src/hook/dev-preview.ts
131
+ import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync2 } from "fs";
132
+ import { join as join3 } from "path";
133
+ var ELECTRON_CMD_RE = /\belectron(?:-vite|-forge|-builder|mon)?\b/i;
134
+ var PNPM_FILTER_RE = /--filter(?:=|\s+)(?:"([^"]+)"|'([^']+)'|([^\s]+))/;
135
+ var SKIP_DIR = /* @__PURE__ */ new Set([
136
+ "node_modules",
137
+ "dist",
138
+ "out",
139
+ "coverage",
140
+ ".git",
141
+ ".context",
142
+ ".next",
143
+ ".turbo",
144
+ ".output"
145
+ ]);
146
+ function parseDevPreview(raw) {
147
+ return raw === "url" || raw === "window" ? raw : void 0;
148
+ }
149
+ function commandLooksLikeElectron(command) {
150
+ return ELECTRON_CMD_RE.test(command);
151
+ }
152
+ function pnpmFilterPackage(command) {
153
+ const m = command.match(PNPM_FILTER_RE);
154
+ return m?.[1] ?? m?.[2] ?? m?.[3] ?? null;
155
+ }
156
+ function readJsonObject(path) {
157
+ try {
158
+ const raw = JSON.parse(readFileSync2(path, "utf8"));
159
+ return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : null;
160
+ } catch {
161
+ return null;
162
+ }
163
+ }
164
+ function packageLooksLikeElectron(pkg) {
165
+ const deps = {
166
+ ...pkg.dependencies,
167
+ ...pkg.devDependencies,
168
+ ...pkg.optionalDependencies
169
+ };
170
+ if (deps.electron || deps["electron-vite"] || deps["electron-builder"] || deps["@electron-forge/cli"] || deps["electron-forge"]) {
171
+ return true;
172
+ }
173
+ const scripts = pkg.scripts;
174
+ if (scripts && typeof scripts === "object") {
175
+ for (const value of Object.values(scripts)) {
176
+ if (typeof value === "string" && commandLooksLikeElectron(value)) {
177
+ return true;
178
+ }
179
+ }
180
+ }
181
+ return false;
182
+ }
183
+ function findPackageJsonByName(root, name, budget = 80) {
184
+ const queue = [root];
185
+ let seen = 0;
186
+ while (queue.length && seen < budget) {
187
+ const dir = queue.shift();
188
+ const pkgPath = join3(dir, "package.json");
189
+ if (existsSync3(pkgPath)) {
190
+ seen += 1;
191
+ const pkg = readJsonObject(pkgPath);
192
+ if (pkg?.name === name) return pkgPath;
193
+ }
194
+ let entries;
195
+ try {
196
+ entries = readdirSync(dir, { withFileTypes: true });
197
+ } catch {
198
+ continue;
199
+ }
200
+ for (const entry of entries) {
201
+ if (!entry.isDirectory() || entry.isSymbolicLink() || SKIP_DIR.has(entry.name) || entry.name.startsWith(".")) {
202
+ continue;
203
+ }
204
+ queue.push(join3(dir, entry.name));
205
+ }
206
+ }
207
+ return null;
208
+ }
209
+ function classifyRunScriptPreview(opts) {
210
+ if (opts.preview === "url" || opts.preview === "window") return opts.preview;
211
+ if (commandLooksLikeElectron(opts.command)) return "window";
212
+ const root = opts.worktreePath?.trim();
213
+ if (!root) return "url";
214
+ const filter = pnpmFilterPackage(opts.command);
215
+ if (filter) {
216
+ if (filter.startsWith(".") || filter.startsWith("/")) {
217
+ const pkg = readJsonObject(join3(root, filter, "package.json"));
218
+ if (pkg && packageLooksLikeElectron(pkg)) return "window";
219
+ } else {
220
+ const found = findPackageJsonByName(root, filter);
221
+ if (found) {
222
+ const pkg = readJsonObject(found);
223
+ if (pkg && packageLooksLikeElectron(pkg)) return "window";
224
+ return "url";
225
+ }
226
+ }
227
+ }
228
+ const rootPkg = readJsonObject(join3(root, "package.json"));
229
+ if (rootPkg && packageLooksLikeElectron(rootPkg)) return "window";
230
+ return "url";
231
+ }
232
+ function runScriptPreview(script, worktreePath) {
233
+ if (!script) return "url";
234
+ return classifyRunScriptPreview({
235
+ command: script.command,
236
+ preview: script.preview,
237
+ worktreePath
238
+ });
239
+ }
240
+ function activeRunPreview(scriptName, scripts, worktreePath) {
241
+ return runScriptPreview(
242
+ scripts.find((s) => s.name === scriptName),
243
+ worktreePath
244
+ );
245
+ }
246
+ function annotateDevAccessRuns(runs, scripts, worktreePath) {
247
+ return runs.map((run) => ({
248
+ ...run,
249
+ preview: activeRunPreview(run.scriptName, scripts, worktreePath)
250
+ }));
251
+ }
252
+
130
253
  // src/hook/settings.ts
131
254
  function expandHome(path) {
132
255
  if (path.startsWith("~/") || path === "~") {
133
- return join3(homedir(), path.slice(2));
256
+ return join4(homedir(), path.slice(2));
134
257
  }
135
258
  return path;
136
259
  }
@@ -143,8 +266,8 @@ function parseAvailableIn(raw) {
143
266
  return out.length ? out : void 0;
144
267
  }
145
268
  function parseSettingsFile(path, source) {
146
- if (!existsSync3(path)) return null;
147
- const raw = readFileSync2(path, "utf8");
269
+ if (!existsSync4(path)) return null;
270
+ const raw = readFileSync3(path, "utf8");
148
271
  const data = parseToml(raw);
149
272
  const scripts = data.scripts ?? {};
150
273
  const setup = typeof scripts.setup === "string" ? scripts.setup : void 0;
@@ -182,7 +305,8 @@ function parseSettingsFile(path, source) {
182
305
  command: value.command,
183
306
  default: Boolean(value.default),
184
307
  icon: typeof value.icon === "string" ? value.icon : void 0,
185
- availableIn: parseAvailableIn(value.available_in)
308
+ availableIn: parseAvailableIn(value.available_in),
309
+ preview: parseDevPreview(value.preview)
186
310
  });
187
311
  }
188
312
  }
@@ -253,15 +377,15 @@ function finalizeSettings(parsed) {
253
377
  };
254
378
  }
255
379
  function familyFiles(rootPath, source) {
256
- const dir = join3(rootPath, `.${source}`);
380
+ const dir = join4(rootPath, `.${source}`);
257
381
  return {
258
- toml: join3(dir, "settings.toml"),
259
- local: join3(dir, "settings.local.toml")
382
+ toml: join4(dir, "settings.toml"),
383
+ local: join4(dir, "settings.local.toml")
260
384
  };
261
385
  }
262
386
  function familyExists(rootPath, source) {
263
387
  const files = familyFiles(rootPath, source);
264
- return existsSync3(files.toml) || existsSync3(files.local);
388
+ return existsSync4(files.toml) || existsSync4(files.local);
265
389
  }
266
390
  function detectFamily(rootPath) {
267
391
  if (familyExists(rootPath, "sideboard")) return "sideboard";
@@ -324,10 +448,10 @@ function settingsSourceLabel(rootPath) {
324
448
  const family = detectFamily(rootPath);
325
449
  if (!family) return null;
326
450
  const files = familyFiles(rootPath, family);
327
- if (existsSync3(files.toml) && existsSync3(files.local)) {
451
+ if (existsSync4(files.toml) && existsSync4(files.local)) {
328
452
  return `.${family}/settings.toml + local`;
329
453
  }
330
- if (existsSync3(files.local)) return `.${family}/settings.local.toml`;
454
+ if (existsSync4(files.local)) return `.${family}/settings.local.toml`;
331
455
  return `.${family}/settings.toml`;
332
456
  }
333
457
  function workspaceSettingsSourceLabel(worktreePath, repoPath) {
@@ -362,32 +486,32 @@ function getRepoSetupInfo(worktreePath, repoPath) {
362
486
  // src/store/paths.ts
363
487
  function appDataDir() {
364
488
  const override = process.env.SIDEBOARD_APP_DATA?.trim();
365
- 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");
489
+ const base = override ? override : process.platform === "darwin" ? join5(homedir2(), "Library", "Application Support", "sideboard") : process.platform === "win32" ? join5(process.env.APPDATA ?? join5(homedir2(), "AppData", "Roaming"), "sideboard") : join5(homedir2(), ".local", "share", "sideboard");
366
490
  mkdirSync(base, { recursive: true });
367
491
  return base;
368
492
  }
369
493
  function threadsDir() {
370
- const dir = join4(appDataDir(), "threads");
494
+ const dir = join5(appDataDir(), "threads");
371
495
  mkdirSync(dir, { recursive: true });
372
496
  return dir;
373
497
  }
374
498
  function locksDir() {
375
- const dir = join4(appDataDir(), "locks");
499
+ const dir = join5(appDataDir(), "locks");
376
500
  mkdirSync(dir, { recursive: true });
377
501
  return dir;
378
502
  }
379
503
  function sideboardHomeDir() {
380
- const dir = join4(homedir2(), "sideboard");
504
+ const dir = join5(homedir2(), "sideboard");
381
505
  mkdirSync(dir, { recursive: true });
382
506
  return dir;
383
507
  }
384
508
  function sideboardReposDir() {
385
- const dir = join4(sideboardHomeDir(), "repos");
509
+ const dir = join5(sideboardHomeDir(), "repos");
386
510
  mkdirSync(dir, { recursive: true });
387
511
  return dir;
388
512
  }
389
513
  function sideboardWorkspacesDir() {
390
- const dir = join4(sideboardHomeDir(), "workspaces");
514
+ const dir = join5(sideboardHomeDir(), "workspaces");
391
515
  mkdirSync(dir, { recursive: true });
392
516
  return dir;
393
517
  }
@@ -400,21 +524,21 @@ function worktreesRoot(repoPath) {
400
524
  mkdirSync(settings.worktreesRoot, { recursive: true });
401
525
  return settings.worktreesRoot;
402
526
  }
403
- const dir = join4(sideboardWorkspacesDir(), repoSlug(repoPath));
527
+ const dir = join5(sideboardWorkspacesDir(), repoSlug(repoPath));
404
528
  mkdirSync(dir, { recursive: true });
405
529
  return dir;
406
530
  }
407
531
  function threadFilePath(id) {
408
- return join4(threadsDir(), `${id}.json`);
532
+ return join5(threadsDir(), `${id}.json`);
409
533
  }
410
534
  function threadLivePath(id) {
411
- return join4(threadsDir(), `${id}.live.json`);
535
+ return join5(threadsDir(), `${id}.live.json`);
412
536
  }
413
537
  function threadLockPath(id) {
414
- return join4(locksDir(), `${id}.lock`);
538
+ return join5(locksDir(), `${id}.lock`);
415
539
  }
416
540
  function globalAgentCwd() {
417
- const dir = join4(appDataDir(), "global");
541
+ const dir = join5(appDataDir(), "global");
418
542
  mkdirSync(dir, { recursive: true });
419
543
  return dir;
420
544
  }
@@ -425,6 +549,13 @@ export {
425
549
  hasConventionSetup,
426
550
  runCursorWorktreeSetup,
427
551
  hasCursorWorktreeSetup,
552
+ parseDevPreview,
553
+ commandLooksLikeElectron,
554
+ pnpmFilterPackage,
555
+ classifyRunScriptPreview,
556
+ runScriptPreview,
557
+ activeRunPreview,
558
+ annotateDevAccessRuns,
428
559
  loadRepoSettings,
429
560
  loadWorkspaceSettings,
430
561
  loadConductorSettings,