@sideboard-ai/core 0.1.252 → 0.1.253

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 (27) hide show
  1. package/dist/{agents-B66CNEPB.js → agents-6HDC7UA7.js} +3 -3
  2. package/dist/{agents-C7T4US6D.js → agents-RKZ2NBIV.js} +3 -3
  3. package/dist/{chunk-AQQWP2TL.js → chunk-46KDLP6T.js} +37 -25
  4. package/dist/{chunk-4DGYMF7H.js → chunk-6ZYSXLXK.js} +16 -4
  5. package/dist/{chunk-FKGVQKRX.js → chunk-GZRS5QVL.js} +38 -26
  6. package/dist/{chunk-6IP4FWMK.js → chunk-IAS7Q2YF.js} +2 -2
  7. package/dist/{chunk-SJ3IUYG2.js → chunk-JUYD2YUC.js} +2 -2
  8. package/dist/{chunk-BHPGORIY.js → chunk-MLB5CFUP.js} +22 -5
  9. package/dist/{chunk-NYXDZCMP.js → chunk-PLMMPA6A.js} +18 -2
  10. package/dist/{chunk-PV4KCI2S.js → chunk-WVNQML4W.js} +18 -2
  11. package/dist/{coordinator-prompt-A2JJ5X7B.js → coordinator-prompt-JKW7YZOC.js} +2 -2
  12. package/dist/{coordinator-prompt-BX2R5EMW.js → coordinator-prompt-YSIC6YFC.js} +2 -2
  13. package/dist/{global-workspace-PUJEGSOB.js → global-workspace-3Q57XYG4.js} +2 -2
  14. package/dist/{global-workspace-JJRPZNTY.js → global-workspace-DMR5JB7T.js} +2 -2
  15. package/dist/index.cjs +657 -606
  16. package/dist/index.d.cts +14 -9
  17. package/dist/index.d.ts +14 -9
  18. package/dist/index.js +22 -14
  19. package/dist/mcp/run-stdio.cjs +73 -29
  20. package/dist/mcp/run-stdio.js +21 -14
  21. package/dist/{orchestrator-O3V4UH73.js → orchestrator-PJCQSVLY.js} +4 -4
  22. package/dist/{orchestrator-O3TVI7SN.js → orchestrator-W6DUFWVE.js} +4 -4
  23. package/dist/{workspaces-V3PZRTY5.js → workspaces-6A3ASHHI.js} +2 -2
  24. package/dist/{workspaces-FUOZIR3V.js → workspaces-PS3IO4VJ.js} +2 -2
  25. package/dist/{worktree-UK62JCYF.js → worktree-7WTVHFGF.js} +1 -1
  26. package/dist/{worktree-4DNK2CK6.js → worktree-DLSVHUF6.js} +1 -1
  27. package/package.json +1 -1
@@ -46,9 +46,9 @@ import {
46
46
  resolveLoginCommand,
47
47
  resolveQuotaFallbackAgent,
48
48
  whichOnPath
49
- } from "./chunk-BHPGORIY.js";
50
- import "./chunk-SJ3IUYG2.js";
51
- import "./chunk-NYXDZCMP.js";
49
+ } from "./chunk-MLB5CFUP.js";
50
+ import "./chunk-JUYD2YUC.js";
51
+ import "./chunk-PLMMPA6A.js";
52
52
  import "./chunk-6K64FJDD.js";
53
53
  import "./chunk-2P4XKWV2.js";
54
54
  import "./chunk-5F4YFGHL.js";
@@ -55,12 +55,12 @@ import {
55
55
  resolveQuotaFallbackAgent,
56
56
  turnCostUsdFromCursorUsage,
57
57
  whichOnPath
58
- } from "./chunk-4DGYMF7H.js";
59
- import "./chunk-6IP4FWMK.js";
58
+ } from "./chunk-6ZYSXLXK.js";
59
+ import "./chunk-IAS7Q2YF.js";
60
60
  import "./chunk-XAISOBBG.js";
61
61
  import "./chunk-P2BSMNHB.js";
62
62
  import "./chunk-VKQGAWHY.js";
63
- import "./chunk-PV4KCI2S.js";
63
+ import "./chunk-WVNQML4W.js";
64
64
  import "./chunk-D6JWYJ4P.js";
65
65
  import "./chunk-RJC2MKXN.js";
66
66
  import "./chunk-H547WSSZ.js";
@@ -44,7 +44,7 @@ import {
44
44
  summarizeTurnStderr,
45
45
  toolDescription,
46
46
  turnFailChatText
47
- } from "./chunk-4DGYMF7H.js";
47
+ } from "./chunk-6ZYSXLXK.js";
48
48
  import {
49
49
  SLACK_REPLY_FORMATTING,
50
50
  addWorkspace,
@@ -67,7 +67,7 @@ import {
67
67
  stageAbsolutePathsAsAttachments,
68
68
  stageBuffersAsAttachments,
69
69
  syncWorkspacesFromThreads
70
- } from "./chunk-6IP4FWMK.js";
70
+ } from "./chunk-IAS7Q2YF.js";
71
71
  import {
72
72
  addPrStackLayer,
73
73
  allocateTeamName,
@@ -117,7 +117,7 @@ import {
117
117
  worktreeDisplayLabelForGroup,
118
118
  worktreeNameFromPath,
119
119
  worktreeSlugForTicket
120
- } from "./chunk-PV4KCI2S.js";
120
+ } from "./chunk-WVNQML4W.js";
121
121
  import {
122
122
  ATTACHMENTS_DIR,
123
123
  DETACHED_JOBS_DIR,
@@ -152,6 +152,7 @@ import {
152
152
  applyTurnUsage,
153
153
  assertOrchestratorCapableAgent,
154
154
  autoCleanupHistoryEnabled,
155
+ caffeinateWhileSchedulesEnabled,
155
156
  childEnvWithAppSettings,
156
157
  coerceOrchestratorAgent,
157
158
  contextTokens,
@@ -491,9 +492,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
491
492
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
492
493
  );
493
494
  }
494
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-JJRPZNTY.js");
495
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-DMR5JB7T.js");
495
496
  if (isGlobalThread2(thread)) {
496
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-A2JJ5X7B.js");
497
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-JKW7YZOC.js");
497
498
  ensureGlobalCoordinatorCwd2(
498
499
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
499
500
  );
@@ -4599,7 +4600,7 @@ async function adoptThread(input) {
4599
4600
  messages: input.messages ?? []
4600
4601
  });
4601
4602
  writeThread(thread);
4602
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-V3PZRTY5.js");
4603
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-6A3ASHHI.js");
4603
4604
  await ensureWorkspace2(repoPath);
4604
4605
  const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-5N2KTYIT.js");
4605
4606
  await ensureWorktreeSideboardIgnored2(input.worktreePath);
@@ -6585,11 +6586,15 @@ function formatWorktreeDirective(thread, opts) {
6585
6586
  lines.push("");
6586
6587
  lines.push(formatDevAccessHint(opts?.activeRuns));
6587
6588
  lines.push("");
6589
+ lines.push(
6590
+ "Schedules: `create_schedule` / `list_schedules` (`at` / `every` / `cron`). `threadId=self` continues this chat; omit threadId for a new Global chat. Fires only while Sideboard.app is running. A future job turns on Settings \u2192 Advanced \u2192 Caffeinate while schedules are enabled."
6591
+ );
6592
+ lines.push("");
6588
6593
  lines.push(formatProcessGuideDirective({ worktreePath: thread.worktreePath }));
6589
6594
  return lines.join("\n");
6590
6595
  }
6591
6596
  function formatWorktreeReminder() {
6592
- return "Sideboard worktree: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout. If a goal is given (Greptile 5/5, CI green), watch-fix-push until it lands \u2014 do not watch after every push.";
6597
+ return "Sideboard worktree: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout. If a goal is given (Greptile 5/5, CI green), watch-fix-push until it lands \u2014 do not watch after every push. Schedules: create_schedule (at / every / cron; threadId=self for this chat).";
6593
6598
  }
6594
6599
  var PR_GOAL_RE = /greptile|\bci\b.*\b(green|pass)|checks?\s+(pass|green)|until\s+.*\b(pass|green|merge|clean)|\bfix ci\b|watch[- ]fix[- ]push/i;
6595
6600
  function mentionsPrGoal(prompt) {
@@ -6899,7 +6904,7 @@ function resolveScheduleThreadId(raw, env = process.env) {
6899
6904
  const value = raw?.trim() || "";
6900
6905
  if (!value) return null;
6901
6906
  if (value.toLowerCase() === "self") {
6902
- return env.SIDEBOARD_ORCHESTRATOR_THREAD_ID?.trim() || null;
6907
+ return env.SIDEBOARD_ORCHESTRATOR_THREAD_ID?.trim() || env.SIDEBOARD_THREAD_ID?.trim() || null;
6903
6908
  }
6904
6909
  return value;
6905
6910
  }
@@ -7027,6 +7032,17 @@ function buildTask(input, now) {
7027
7032
  function listSchedules() {
7028
7033
  return readAll().sort((a, b) => a.nextRunAt.localeCompare(b.nextRunAt));
7029
7034
  }
7035
+ function scheduleNeedsCaffeinate(task, now = /* @__PURE__ */ new Date()) {
7036
+ if (!task.enabled) return false;
7037
+ const at = new Date(task.nextRunAt);
7038
+ if (Number.isNaN(at.getTime())) return false;
7039
+ return at.getTime() > now.getTime();
7040
+ }
7041
+ function ensureCaffeinateForFutureSchedule(task) {
7042
+ if (!scheduleNeedsCaffeinate(task)) return;
7043
+ if (caffeinateWhileSchedulesEnabled()) return;
7044
+ updateAdvancedSettings({ caffeinateWhileSchedules: true });
7045
+ }
7030
7046
  function getSchedule(id) {
7031
7047
  const key = id.trim();
7032
7048
  if (!key) return null;
@@ -7039,6 +7055,7 @@ function createSchedule(input) {
7039
7055
  const rows = readAll();
7040
7056
  rows.push(task);
7041
7057
  writeAll(rows);
7058
+ ensureCaffeinateForFutureSchedule(task);
7042
7059
  return task;
7043
7060
  }
7044
7061
  function updateSchedule(id, patch) {
@@ -7065,6 +7082,7 @@ function updateSchedule(id, patch) {
7065
7082
  };
7066
7083
  rows[idx] = next;
7067
7084
  writeAll(rows);
7085
+ ensureCaffeinateForFutureSchedule(next);
7068
7086
  return next;
7069
7087
  }
7070
7088
  function deleteSchedule(id) {
@@ -7105,7 +7123,7 @@ function formatScheduledPrompt(name, prompt) {
7105
7123
  ${prompt}`;
7106
7124
  }
7107
7125
  async function defaultDeps() {
7108
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-O3TVI7SN.js");
7126
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-W6DUFWVE.js");
7109
7127
  const orch = getOrchestrator2();
7110
7128
  return {
7111
7129
  findThread: (id) => findThreadByRef(id),
@@ -7125,19 +7143,9 @@ async function fireSchedule(id) {
7125
7143
  try {
7126
7144
  const deps = fireHooks ?? await defaultDeps();
7127
7145
  const prompt = formatScheduledPrompt(schedule.name, schedule.prompt);
7128
- if (schedule.threadId) {
7129
- const thread = deps.findThread(schedule.threadId);
7130
- if (!thread || thread.status === "archived") {
7131
- return recordScheduleRun(schedule.id, {
7132
- lastError: thread ? `Orchestration chat ${schedule.threadId} is archived` : `Orchestration chat not found: ${schedule.threadId}`
7133
- });
7134
- }
7135
- if (!isOrchestratorThread(thread)) {
7136
- return recordScheduleRun(schedule.id, {
7137
- lastError: `Thread ${schedule.threadId} is not an orchestration chat`
7138
- });
7139
- }
7140
- const sent = await deps.send(thread.id, prompt);
7146
+ const target = schedule.threadId ? deps.findThread(schedule.threadId) : null;
7147
+ if (target && target.status !== "archived") {
7148
+ const sent = await deps.send(target.id, prompt);
7141
7149
  return recordScheduleRun(schedule.id, {
7142
7150
  lastThreadId: sent.id,
7143
7151
  lastError: null
@@ -7148,6 +7156,9 @@ async function fireSchedule(id) {
7148
7156
  agent: pickAgent(schedule),
7149
7157
  model: schedule.model
7150
7158
  });
7159
+ if (schedule.threadId && schedule.when.kind !== "once") {
7160
+ updateSchedule(schedule.id, { threadId: created.id });
7161
+ }
7151
7162
  return recordScheduleRun(schedule.id, {
7152
7163
  lastThreadId: created.id,
7153
7164
  lastError: null
@@ -9738,7 +9749,7 @@ var Orchestrator = class {
9738
9749
  this.enforceHistoryRetention();
9739
9750
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
9740
9751
  try {
9741
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-V3PZRTY5.js");
9752
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-6A3ASHHI.js");
9742
9753
  await ensureWorkspace2(thread.repoPath);
9743
9754
  } catch {
9744
9755
  }
@@ -9792,7 +9803,7 @@ var Orchestrator = class {
9792
9803
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
9793
9804
  );
9794
9805
  }
9795
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-UK62JCYF.js");
9806
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-7WTVHFGF.js");
9796
9807
  const slug = thread.worktreePath.split("/").pop();
9797
9808
  const dest = thread.worktreePath;
9798
9809
  await withRepoGitLock(thread.repoPath, async () => {
@@ -9902,7 +9913,7 @@ async function startOrchestration(opts) {
9902
9913
  sourceRef: "default",
9903
9914
  ...createOpts
9904
9915
  }).catch(async () => {
9905
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-UK62JCYF.js");
9916
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-7WTVHFGF.js");
9906
9917
  const repo = await resolveRepoRoot2(repoPath);
9907
9918
  const def = await resolveDefaultBranch2(repo);
9908
9919
  return orch.createThread({
@@ -9953,6 +9964,7 @@ export {
9953
9964
  localhostPreviewUrl,
9954
9965
  resolveScheduleThreadId,
9955
9966
  listSchedules,
9967
+ scheduleNeedsCaffeinate,
9956
9968
  getSchedule,
9957
9969
  createSchedule,
9958
9970
  updateSchedule,
@@ -2,7 +2,7 @@
2
2
 
3
3
  import {
4
4
  isOrchestratorThread
5
- } from "./chunk-6IP4FWMK.js";
5
+ } from "./chunk-IAS7Q2YF.js";
6
6
  import {
7
7
  applyConnectedTeamToCli,
8
8
  brightsyMcpServerName,
@@ -20,7 +20,7 @@ import {
20
20
  mergeAgentGitAuthEnv,
21
21
  resolveAgentGitAuthEnv,
22
22
  resolveCodexGitWritableRoots
23
- } from "./chunk-PV4KCI2S.js";
23
+ } from "./chunk-WVNQML4W.js";
24
24
  import {
25
25
  enrichPathWithNpmGlobalBin,
26
26
  isConductorBundledCli,
@@ -1240,7 +1240,12 @@ var SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS = [
1240
1240
  "mcp__sideboard__get_run_log",
1241
1241
  "mcp__sideboard__notify_orchestrator",
1242
1242
  "mcp__sideboard__get_viewer_context",
1243
- "mcp__sideboard__update_viewer_context"
1243
+ "mcp__sideboard__update_viewer_context",
1244
+ "mcp__sideboard__list_schedules",
1245
+ "mcp__sideboard__create_schedule",
1246
+ "mcp__sideboard__update_schedule",
1247
+ "mcp__sideboard__delete_schedule",
1248
+ "mcp__sideboard__run_schedule"
1244
1249
  ];
1245
1250
  var SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS = ["mcp__sideboard__github_*"];
1246
1251
  var SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS = ["mcp__sideboard__linear_*"];
@@ -1830,6 +1835,13 @@ function toolDescription(name, input) {
1830
1835
  return str(input?.name) ? `Read ${str(input?.name)} log` : "Read Dev log";
1831
1836
  }
1832
1837
  if (/notify_orchestrator$/i.test(name)) return "Notify orchestrator";
1838
+ if (/list_schedules$/i.test(name)) return "List schedules";
1839
+ if (/create_schedule$/i.test(name)) {
1840
+ return str(input?.name) ? `Schedule ${str(input?.name)}` : "Create schedule";
1841
+ }
1842
+ if (/update_schedule$/i.test(name)) return "Update schedule";
1843
+ if (/delete_schedule$/i.test(name)) return "Delete schedule";
1844
+ if (/run_schedule$/i.test(name)) return "Run schedule";
1833
1845
  if (isSkillToolName(name)) {
1834
1846
  const cmd = skillCommandFromInput(input);
1835
1847
  return cmd ? `Using /${cmd}` : "Using skill";
@@ -2958,7 +2970,7 @@ var claudeAdapter = {
2958
2970
  );
2959
2971
  }
2960
2972
  const mode = permissionMode(thread);
2961
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-JJRPZNTY.js");
2973
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-DMR5JB7T.js");
2962
2974
  const isOrchestrator = isOrchestratorThread2(thread);
2963
2975
  const injectedServers = await buildInjectedMcpServers({
2964
2976
  includeSideboard: true,
@@ -25,7 +25,7 @@ import {
25
25
  resolveQuotaFallbackAgent,
26
26
  stripBrightsyNdjsonNoise,
27
27
  toolDescription
28
- } from "./chunk-BHPGORIY.js";
28
+ } from "./chunk-MLB5CFUP.js";
29
29
  import {
30
30
  SLACK_REPLY_FORMATTING,
31
31
  addWorkspace,
@@ -48,7 +48,7 @@ import {
48
48
  stageAbsolutePathsAsAttachments,
49
49
  stageBuffersAsAttachments,
50
50
  syncWorkspacesFromThreads
51
- } from "./chunk-SJ3IUYG2.js";
51
+ } from "./chunk-JUYD2YUC.js";
52
52
  import {
53
53
  addPrStackLayer,
54
54
  allocateTeamName,
@@ -98,7 +98,7 @@ import {
98
98
  worktreeDisplayLabelForGroup,
99
99
  worktreeNameFromPath,
100
100
  worktreeSlugForTicket
101
- } from "./chunk-NYXDZCMP.js";
101
+ } from "./chunk-PLMMPA6A.js";
102
102
  import {
103
103
  ATTACHMENTS_DIR,
104
104
  DETACHED_JOBS_DIR,
@@ -136,6 +136,7 @@ import {
136
136
  applyTurnUsage,
137
137
  assertOrchestratorCapableAgent,
138
138
  autoCleanupHistoryEnabled,
139
+ caffeinateWhileSchedulesEnabled,
139
140
  childEnvWithAppSettings,
140
141
  coerceOrchestratorAgent,
141
142
  contextTokens,
@@ -443,9 +444,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
443
444
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
444
445
  );
445
446
  }
446
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-PUJEGSOB.js");
447
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-3Q57XYG4.js");
447
448
  if (isGlobalThread2(thread)) {
448
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-BX2R5EMW.js");
449
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-YSIC6YFC.js");
449
450
  ensureGlobalCoordinatorCwd2(
450
451
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
451
452
  );
@@ -4335,7 +4336,7 @@ async function createThread(input, _onSetupLine) {
4335
4336
  return readThread(thread.id) ?? thread;
4336
4337
  }
4337
4338
  async function listLinearIssues(agent, repoPath) {
4338
- const { getAdapter: getAdapter2 } = await import("./agents-B66CNEPB.js");
4339
+ const { getAdapter: getAdapter2 } = await import("./agents-6HDC7UA7.js");
4339
4340
  await requireAgent(agent, { requireLinear: true });
4340
4341
  const adapter = getAdapter2(agent);
4341
4342
  if (!adapter.listLinearIssues) {
@@ -4808,7 +4809,7 @@ async function adoptThread(input) {
4808
4809
  messages: input.messages ?? []
4809
4810
  });
4810
4811
  writeThread(thread);
4811
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-FUOZIR3V.js");
4812
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-PS3IO4VJ.js");
4812
4813
  await ensureWorkspace2(repoPath);
4813
4814
  const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-RXZPTCNH.js");
4814
4815
  await ensureWorktreeSideboardIgnored2(input.worktreePath);
@@ -6807,11 +6808,15 @@ function formatWorktreeDirective(thread, opts) {
6807
6808
  lines.push("");
6808
6809
  lines.push(formatDevAccessHint(opts?.activeRuns));
6809
6810
  lines.push("");
6811
+ lines.push(
6812
+ "Schedules: `create_schedule` / `list_schedules` (`at` / `every` / `cron`). `threadId=self` continues this chat; omit threadId for a new Global chat. Fires only while Sideboard.app is running. A future job turns on Settings \u2192 Advanced \u2192 Caffeinate while schedules are enabled."
6813
+ );
6814
+ lines.push("");
6810
6815
  lines.push(formatProcessGuideDirective({ worktreePath: thread.worktreePath }));
6811
6816
  return lines.join("\n");
6812
6817
  }
6813
6818
  function formatWorktreeReminder() {
6814
- return "Sideboard worktree: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout. If a goal is given (Greptile 5/5, CI green), watch-fix-push until it lands \u2014 do not watch after every push.";
6819
+ return "Sideboard worktree: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout. If a goal is given (Greptile 5/5, CI green), watch-fix-push until it lands \u2014 do not watch after every push. Schedules: create_schedule (at / every / cron; threadId=self for this chat).";
6815
6820
  }
6816
6821
  var PR_GOAL_RE = /greptile|\bci\b.*\b(green|pass)|checks?\s+(pass|green)|until\s+.*\b(pass|green|merge|clean)|\bfix ci\b|watch[- ]fix[- ]push/i;
6817
6822
  function mentionsPrGoal(prompt) {
@@ -7305,7 +7310,7 @@ function resolveScheduleThreadId(raw, env = process.env) {
7305
7310
  const value = raw?.trim() || "";
7306
7311
  if (!value) return null;
7307
7312
  if (value.toLowerCase() === "self") {
7308
- return env.SIDEBOARD_ORCHESTRATOR_THREAD_ID?.trim() || null;
7313
+ return env.SIDEBOARD_ORCHESTRATOR_THREAD_ID?.trim() || env.SIDEBOARD_THREAD_ID?.trim() || null;
7309
7314
  }
7310
7315
  return value;
7311
7316
  }
@@ -7442,6 +7447,17 @@ function listSchedules() {
7442
7447
  function hasEnabledSchedules() {
7443
7448
  return listSchedules().some((row) => row.enabled);
7444
7449
  }
7450
+ function scheduleNeedsCaffeinate(task, now = /* @__PURE__ */ new Date()) {
7451
+ if (!task.enabled) return false;
7452
+ const at = new Date(task.nextRunAt);
7453
+ if (Number.isNaN(at.getTime())) return false;
7454
+ return at.getTime() > now.getTime();
7455
+ }
7456
+ function ensureCaffeinateForFutureSchedule(task) {
7457
+ if (!scheduleNeedsCaffeinate(task)) return;
7458
+ if (caffeinateWhileSchedulesEnabled()) return;
7459
+ updateAdvancedSettings({ caffeinateWhileSchedules: true });
7460
+ }
7445
7461
  function getSchedule(id) {
7446
7462
  const key = id.trim();
7447
7463
  if (!key) return null;
@@ -7454,6 +7470,7 @@ function createSchedule(input) {
7454
7470
  const rows = readAll();
7455
7471
  rows.push(task);
7456
7472
  writeAll(rows);
7473
+ ensureCaffeinateForFutureSchedule(task);
7457
7474
  return task;
7458
7475
  }
7459
7476
  function updateSchedule(id, patch) {
@@ -7480,6 +7497,7 @@ function updateSchedule(id, patch) {
7480
7497
  };
7481
7498
  rows[idx] = next;
7482
7499
  writeAll(rows);
7500
+ ensureCaffeinateForFutureSchedule(next);
7483
7501
  return next;
7484
7502
  }
7485
7503
  function deleteSchedule(id) {
@@ -7520,7 +7538,7 @@ function formatScheduledPrompt(name, prompt) {
7520
7538
  ${prompt}`;
7521
7539
  }
7522
7540
  async function defaultDeps() {
7523
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-O3V4UH73.js");
7541
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-PJCQSVLY.js");
7524
7542
  const orch = getOrchestrator2();
7525
7543
  return {
7526
7544
  findThread: (id) => findThreadByRef(id),
@@ -7540,19 +7558,9 @@ async function fireSchedule(id) {
7540
7558
  try {
7541
7559
  const deps = fireHooks ?? await defaultDeps();
7542
7560
  const prompt = formatScheduledPrompt(schedule.name, schedule.prompt);
7543
- if (schedule.threadId) {
7544
- const thread = deps.findThread(schedule.threadId);
7545
- if (!thread || thread.status === "archived") {
7546
- return recordScheduleRun(schedule.id, {
7547
- lastError: thread ? `Orchestration chat ${schedule.threadId} is archived` : `Orchestration chat not found: ${schedule.threadId}`
7548
- });
7549
- }
7550
- if (!isOrchestratorThread(thread)) {
7551
- return recordScheduleRun(schedule.id, {
7552
- lastError: `Thread ${schedule.threadId} is not an orchestration chat`
7553
- });
7554
- }
7555
- const sent = await deps.send(thread.id, prompt);
7561
+ const target = schedule.threadId ? deps.findThread(schedule.threadId) : null;
7562
+ if (target && target.status !== "archived") {
7563
+ const sent = await deps.send(target.id, prompt);
7556
7564
  return recordScheduleRun(schedule.id, {
7557
7565
  lastThreadId: sent.id,
7558
7566
  lastError: null
@@ -7563,6 +7571,9 @@ async function fireSchedule(id) {
7563
7571
  agent: pickAgent(schedule),
7564
7572
  model: schedule.model
7565
7573
  });
7574
+ if (schedule.threadId && schedule.when.kind !== "once") {
7575
+ updateSchedule(schedule.id, { threadId: created.id });
7576
+ }
7566
7577
  return recordScheduleRun(schedule.id, {
7567
7578
  lastThreadId: created.id,
7568
7579
  lastError: null
@@ -10153,7 +10164,7 @@ var Orchestrator = class {
10153
10164
  this.enforceHistoryRetention();
10154
10165
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
10155
10166
  try {
10156
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-FUOZIR3V.js");
10167
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-PS3IO4VJ.js");
10157
10168
  await ensureWorkspace2(thread.repoPath);
10158
10169
  } catch {
10159
10170
  }
@@ -10207,7 +10218,7 @@ var Orchestrator = class {
10207
10218
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
10208
10219
  );
10209
10220
  }
10210
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-4DNK2CK6.js");
10221
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-DLSVHUF6.js");
10211
10222
  const slug = thread.worktreePath.split("/").pop();
10212
10223
  const dest = thread.worktreePath;
10213
10224
  await withRepoGitLock(thread.repoPath, async () => {
@@ -10317,7 +10328,7 @@ async function startOrchestration(opts) {
10317
10328
  sourceRef: "default",
10318
10329
  ...createOpts
10319
10330
  }).catch(async () => {
10320
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-4DNK2CK6.js");
10331
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-DLSVHUF6.js");
10321
10332
  const repo = await resolveRepoRoot2(repoPath);
10322
10333
  const def = await resolveDefaultBranch2(repo);
10323
10334
  return orch.createThread({
@@ -10381,6 +10392,7 @@ export {
10381
10392
  formatScheduleWhen,
10382
10393
  listSchedules,
10383
10394
  hasEnabledSchedules,
10395
+ scheduleNeedsCaffeinate,
10384
10396
  getSchedule,
10385
10397
  createSchedule,
10386
10398
  updateSchedule,
@@ -8,7 +8,7 @@ import {
8
8
  resolveRepoRoot,
9
9
  takenSlugsFromThread,
10
10
  teamSlugFromName
11
- } from "./chunk-PV4KCI2S.js";
11
+ } from "./chunk-WVNQML4W.js";
12
12
  import {
13
13
  ATTACHMENTS_DIR,
14
14
  attachmentsGitignoreBody
@@ -353,7 +353,7 @@ var COORDINATOR_TOOL_PLAYBOOK = [
353
353
  "- ask_user \u2014 composer multiple-choice only when blocked on a concrete choice (approach fork, which API, Save this context / Do not save). Never for hellos, check-ins, invented \u201Cwhat should we do?\u201D menus, or after a review \u2014 reply in chat. Explain options first, description on every option, then wait.",
354
354
  "- get_viewer_context / update_viewer_context \u2014 read or replace Settings \u2192 Agents (account) and Settings \u2192 Projects (per-repo) context. You can update a project: pass scope=project and repoPath from list_workspaces (this cwd is not a project). update_viewer_context requires confirmed=true after ask_user. Never write context unprompted.",
355
355
  "- set_caffeinate \u2014 keep this Mac awake across turns (macOS caffeinate). Turn on for Slack / away-from-keyboard work, overnight schedules, or when the user will be away. Turn OFF when they say they are done, wrapping up, going to sleep, or no longer need the machine awake. Closing this chat also releases it.",
356
- "- list_schedules / create_schedule / update_schedule / delete_schedule / run_schedule \u2014 local jobs that send a prompt to an orchestration chat (threadId or self) or start a new Global chat (omit threadId). One-shot `at`, interval `every` (15m/1h/6h/1d), or 5-field `cron`. Recurring jobs without threadId open a new chat each run. Jobs fire only while Sideboard.app is running; sleep skips until wake. Overnight/unattended runs: ask the user to enable Settings \u2192 Advanced \u2192 Caffeinate while schedules are enabled, or call set_caffeinate.",
356
+ "- list_schedules / create_schedule / update_schedule / delete_schedule / run_schedule \u2014 local jobs that send a prompt to a chat (threadId or self) or start a new Global chat (omit threadId). One-shot `at`, interval `every` (15m/1h/6h/1d), or 5-field `cron`. Recurring jobs without threadId open a new chat each run. Worktree agents have the same tools (`threadId=self` continues that coding chat). Jobs fire only while Sideboard.app is running; sleep skips until wake. Creating or enabling a future job turns on Settings \u2192 Advanced \u2192 Caffeinate while schedules are enabled (or call set_caffeinate).",
357
357
  "Workspaces:",
358
358
  "- add_workspace / remove_workspace \u2014 register or unregister a git repo",
359
359
  "Worktree threads (chats):",
@@ -6,7 +6,7 @@ import {
6
6
  resolveRepoRoot,
7
7
  takenSlugsFromThread,
8
8
  teamSlugFromName
9
- } from "./chunk-NYXDZCMP.js";
9
+ } from "./chunk-PLMMPA6A.js";
10
10
  import {
11
11
  ATTACHMENTS_DIR,
12
12
  attachmentsGitignoreBody
@@ -398,7 +398,7 @@ var COORDINATOR_TOOL_PLAYBOOK = [
398
398
  "- ask_user \u2014 composer multiple-choice only when blocked on a concrete choice (approach fork, which API, Save this context / Do not save). Never for hellos, check-ins, invented \u201Cwhat should we do?\u201D menus, or after a review \u2014 reply in chat. Explain options first, description on every option, then wait.",
399
399
  "- get_viewer_context / update_viewer_context \u2014 read or replace Settings \u2192 Agents (account) and Settings \u2192 Projects (per-repo) context. You can update a project: pass scope=project and repoPath from list_workspaces (this cwd is not a project). update_viewer_context requires confirmed=true after ask_user. Never write context unprompted.",
400
400
  "- set_caffeinate \u2014 keep this Mac awake across turns (macOS caffeinate). Turn on for Slack / away-from-keyboard work, overnight schedules, or when the user will be away. Turn OFF when they say they are done, wrapping up, going to sleep, or no longer need the machine awake. Closing this chat also releases it.",
401
- "- list_schedules / create_schedule / update_schedule / delete_schedule / run_schedule \u2014 local jobs that send a prompt to an orchestration chat (threadId or self) or start a new Global chat (omit threadId). One-shot `at`, interval `every` (15m/1h/6h/1d), or 5-field `cron`. Recurring jobs without threadId open a new chat each run. Jobs fire only while Sideboard.app is running; sleep skips until wake. Overnight/unattended runs: ask the user to enable Settings \u2192 Advanced \u2192 Caffeinate while schedules are enabled, or call set_caffeinate.",
401
+ "- list_schedules / create_schedule / update_schedule / delete_schedule / run_schedule \u2014 local jobs that send a prompt to a chat (threadId or self) or start a new Global chat (omit threadId). One-shot `at`, interval `every` (15m/1h/6h/1d), or 5-field `cron`. Recurring jobs without threadId open a new chat each run. Worktree agents have the same tools (`threadId=self` continues that coding chat). Jobs fire only while Sideboard.app is running; sleep skips until wake. Creating or enabling a future job turns on Settings \u2192 Advanced \u2192 Caffeinate while schedules are enabled (or call set_caffeinate).",
402
402
  "Workspaces:",
403
403
  "- add_workspace / remove_workspace \u2014 register or unregister a git repo",
404
404
  "Worktree threads (chats):",
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  isOrchestratorThread
3
- } from "./chunk-SJ3IUYG2.js";
3
+ } from "./chunk-JUYD2YUC.js";
4
4
  import {
5
5
  codexUnattendedGitConfigArgs,
6
6
  mergeAgentGitAuthEnv,
7
7
  resolveAgentGitAuthEnv,
8
8
  resolveCodexGitWritableRoots
9
- } from "./chunk-NYXDZCMP.js";
9
+ } from "./chunk-PLMMPA6A.js";
10
10
  import {
11
11
  applyConnectedTeamToCli,
12
12
  brightsyMcpServerName,
@@ -572,7 +572,12 @@ var WORKTREE_MCP_TOOLS = [
572
572
  "get_run_log",
573
573
  "notify_orchestrator",
574
574
  "get_viewer_context",
575
- "update_viewer_context"
575
+ "update_viewer_context",
576
+ "list_schedules",
577
+ "create_schedule",
578
+ "update_schedule",
579
+ "delete_schedule",
580
+ "run_schedule"
576
581
  ];
577
582
  var WORKTREE_GITHUB_MCP_TOOLS = [
578
583
  "github_search_issues",
@@ -623,7 +628,12 @@ var SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS = [
623
628
  "mcp__sideboard__get_run_log",
624
629
  "mcp__sideboard__notify_orchestrator",
625
630
  "mcp__sideboard__get_viewer_context",
626
- "mcp__sideboard__update_viewer_context"
631
+ "mcp__sideboard__update_viewer_context",
632
+ "mcp__sideboard__list_schedules",
633
+ "mcp__sideboard__create_schedule",
634
+ "mcp__sideboard__update_schedule",
635
+ "mcp__sideboard__delete_schedule",
636
+ "mcp__sideboard__run_schedule"
627
637
  ];
628
638
  var SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS = ["mcp__sideboard__github_*"];
629
639
  var SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS = ["mcp__sideboard__linear_*"];
@@ -1320,6 +1330,13 @@ function toolDescription(name, input) {
1320
1330
  return str(input?.name) ? `Read ${str(input?.name)} log` : "Read Dev log";
1321
1331
  }
1322
1332
  if (/notify_orchestrator$/i.test(name)) return "Notify orchestrator";
1333
+ if (/list_schedules$/i.test(name)) return "List schedules";
1334
+ if (/create_schedule$/i.test(name)) {
1335
+ return str(input?.name) ? `Schedule ${str(input?.name)}` : "Create schedule";
1336
+ }
1337
+ if (/update_schedule$/i.test(name)) return "Update schedule";
1338
+ if (/delete_schedule$/i.test(name)) return "Delete schedule";
1339
+ if (/run_schedule$/i.test(name)) return "Run schedule";
1323
1340
  if (isSkillToolName(name)) {
1324
1341
  const cmd = skillCommandFromInput(input);
1325
1342
  return cmd ? `Using /${cmd}` : "Using skill";
@@ -2544,7 +2561,7 @@ var claudeAdapter = {
2544
2561
  );
2545
2562
  }
2546
2563
  const mode = permissionMode(thread);
2547
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-PUJEGSOB.js");
2564
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-3Q57XYG4.js");
2548
2565
  const isOrchestrator = isOrchestratorThread2(thread);
2549
2566
  const injectedServers = await buildInjectedMcpServers({
2550
2567
  includeSideboard: true,
@@ -2517,6 +2517,7 @@ var PR_DETAILS_JSON_FIELDS = [
2517
2517
  "additions",
2518
2518
  "deletions",
2519
2519
  "changedFiles",
2520
+ "commits",
2520
2521
  "comments",
2521
2522
  "reviews",
2522
2523
  "assignees",
@@ -2527,6 +2528,7 @@ function parsePrDetailsView(view) {
2527
2528
  const author = view.author ?? {};
2528
2529
  const comments = Array.isArray(view.comments) ? view.comments : [];
2529
2530
  const reviews = Array.isArray(view.reviews) ? view.reviews : [];
2531
+ const commits = Array.isArray(view.commits) ? view.commits : [];
2530
2532
  const requested = {
2531
2533
  ids: reviewerIdentities(view.reviewRequests),
2532
2534
  users: humanReviewerLogins(view.reviewRequests),
@@ -2547,8 +2549,22 @@ function parsePrDetailsView(view) {
2547
2549
  additions: Number(view.additions ?? 0),
2548
2550
  deletions: Number(view.deletions ?? 0),
2549
2551
  changedFiles: Number(view.changedFiles ?? 0),
2550
- // Commits live in Changes; omit from GraphQL to save rate-limit points.
2551
- commits: [],
2552
+ commits: commits.map((c) => {
2553
+ const row = c;
2554
+ const authors = Array.isArray(row.authors) ? row.authors.map((a) => {
2555
+ const actor = a;
2556
+ return {
2557
+ login: actor.login?.trim() || actor.name?.trim() || "unknown",
2558
+ name: actor.name ?? null
2559
+ };
2560
+ }) : [];
2561
+ return {
2562
+ oid: String(row.oid ?? ""),
2563
+ messageHeadline: String(row.messageHeadline ?? ""),
2564
+ committedDate: String(row.committedDate ?? ""),
2565
+ authors
2566
+ };
2567
+ }),
2552
2568
  comments: comments.map((c) => {
2553
2569
  const row = c;
2554
2570
  const a = row.author ?? {};
@@ -2480,6 +2480,7 @@ var PR_DETAILS_JSON_FIELDS = [
2480
2480
  "additions",
2481
2481
  "deletions",
2482
2482
  "changedFiles",
2483
+ "commits",
2483
2484
  "comments",
2484
2485
  "reviews",
2485
2486
  "assignees",
@@ -2490,6 +2491,7 @@ function parsePrDetailsView(view) {
2490
2491
  const author = view.author ?? {};
2491
2492
  const comments = Array.isArray(view.comments) ? view.comments : [];
2492
2493
  const reviews = Array.isArray(view.reviews) ? view.reviews : [];
2494
+ const commits = Array.isArray(view.commits) ? view.commits : [];
2493
2495
  const requested = {
2494
2496
  ids: reviewerIdentities(view.reviewRequests),
2495
2497
  users: humanReviewerLogins(view.reviewRequests),
@@ -2510,8 +2512,22 @@ function parsePrDetailsView(view) {
2510
2512
  additions: Number(view.additions ?? 0),
2511
2513
  deletions: Number(view.deletions ?? 0),
2512
2514
  changedFiles: Number(view.changedFiles ?? 0),
2513
- // Commits live in Changes; omit from GraphQL to save rate-limit points.
2514
- commits: [],
2515
+ commits: commits.map((c) => {
2516
+ const row = c;
2517
+ const authors = Array.isArray(row.authors) ? row.authors.map((a) => {
2518
+ const actor = a;
2519
+ return {
2520
+ login: actor.login?.trim() || actor.name?.trim() || "unknown",
2521
+ name: actor.name ?? null
2522
+ };
2523
+ }) : [];
2524
+ return {
2525
+ oid: String(row.oid ?? ""),
2526
+ messageHeadline: String(row.messageHeadline ?? ""),
2527
+ committedDate: String(row.committedDate ?? ""),
2528
+ authors
2529
+ };
2530
+ }),
2515
2531
  comments: comments.map((c) => {
2516
2532
  const row = c;
2517
2533
  const a = row.author ?? {};