@sideboard-ai/core 0.1.319 → 0.1.320

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 (61) hide show
  1. package/dist/{abletime-L3ODNTBT.js → abletime-CRRLEYTE.js} +4 -4
  2. package/dist/{abletime-DVYO4IVS.js → abletime-ICW6Q2AB.js} +4 -4
  3. package/dist/{abletime-oauth-2VWQCXGT.js → abletime-oauth-P3KPPJE4.js} +3 -3
  4. package/dist/{abletime-oauth-6DTX7LB7.js → abletime-oauth-Q76XBSPG.js} +3 -3
  5. package/dist/{abletime-rest-PYQM234B.js → abletime-rest-DNFAYYLP.js} +3 -3
  6. package/dist/{abletime-rest-7NICZYOC.js → abletime-rest-DQ3PNKXP.js} +3 -3
  7. package/dist/{agents-KABJUDPI.js → agents-CJZYJOWP.js} +7 -7
  8. package/dist/{agents-2AR7I6B6.js → agents-F2E2HACB.js} +7 -7
  9. package/dist/{app-settings-CZVFMOI5.js → app-settings-KMPVI2B7.js} +1 -1
  10. package/dist/{app-settings-V6YPYY57.js → app-settings-P3H4SEIK.js} +1 -1
  11. package/dist/{chunk-YEIHCSZS.js → chunk-4GZC6DDH.js} +2 -0
  12. package/dist/{chunk-5OM7UCTQ.js → chunk-56M6VEXI.js} +3 -3
  13. package/dist/{chunk-ZM43NTJJ.js → chunk-5OQONGHO.js} +5 -5
  14. package/dist/{chunk-A6C67DY5.js → chunk-5S3YP5KH.js} +4 -4
  15. package/dist/{chunk-QPLQXWND.js → chunk-72PUPPV2.js} +3 -3
  16. package/dist/{chunk-OO3R6CS2.js → chunk-B7UL36WH.js} +214 -37
  17. package/dist/{chunk-WLZHRNE6.js → chunk-BTIXTH4N.js} +3 -3
  18. package/dist/{chunk-AESO2KJS.js → chunk-CB5Z5C3J.js} +2 -2
  19. package/dist/{chunk-AUJ4XB6H.js → chunk-DFUXW2IT.js} +2 -2
  20. package/dist/{chunk-ST2UQBJT.js → chunk-DJZRDTZY.js} +6 -6
  21. package/dist/{chunk-TUJFCJJU.js → chunk-EDXTP2VR.js} +2 -2
  22. package/dist/{chunk-I5TESHDN.js → chunk-EQ52JR3Q.js} +5 -5
  23. package/dist/{chunk-FDXHNROD.js → chunk-EQ5JY3MJ.js} +2 -2
  24. package/dist/{chunk-E52SQENB.js → chunk-FZKAAAEB.js} +3 -1
  25. package/dist/{chunk-JD7CC6SW.js → chunk-HHPTGIKS.js} +2 -2
  26. package/dist/{chunk-U2N32EA6.js → chunk-IDPFLXRY.js} +215 -38
  27. package/dist/{chunk-GCHSJCCX.js → chunk-IFU4W4C4.js} +3 -1
  28. package/dist/{chunk-IAPO7ZFG.js → chunk-LLIEU2ZB.js} +5 -5
  29. package/dist/{chunk-MBYGWNLQ.js → chunk-OAFBHCSM.js} +1 -1
  30. package/dist/{chunk-NRSC4N5X.js → chunk-P74GXA5V.js} +6 -6
  31. package/dist/{chunk-A46CIARU.js → chunk-PNLGWAYE.js} +2 -2
  32. package/dist/{chunk-53OCOGND.js → chunk-QGY3UNNL.js} +2 -2
  33. package/dist/{chunk-7Q327QF2.js → chunk-QIC2JXHW.js} +5 -5
  34. package/dist/{chunk-YALFZKSC.js → chunk-RHJPP26T.js} +11 -11
  35. package/dist/{chunk-AZ4GEEGL.js → chunk-UK2KESBN.js} +2 -2
  36. package/dist/{chunk-LXBZQP2Q.js → chunk-V76MQ7MH.js} +5 -5
  37. package/dist/{chunk-HOLB6ZFZ.js → chunk-XMHMVEIY.js} +2 -0
  38. package/dist/{chunk-GH7UMULC.js → chunk-ZYZBCLJR.js} +6 -6
  39. package/dist/{conductor-MG2RAQNT.js → conductor-FPFY6Z5S.js} +6 -6
  40. package/dist/{conductor-NIUBJLTS.js → conductor-JA5W3L7C.js} +6 -6
  41. package/dist/{coordinator-prompt-3CT3D5UM.js → coordinator-prompt-M75TAN43.js} +4 -4
  42. package/dist/{coordinator-prompt-X74F3JIC.js → coordinator-prompt-NUC2ZXMJ.js} +4 -4
  43. package/dist/{global-workspace-BUWMRNW5.js → global-workspace-5A4H34AF.js} +4 -4
  44. package/dist/{global-workspace-FTNJEML3.js → global-workspace-SCLQUNUI.js} +4 -4
  45. package/dist/index.cjs +589 -402
  46. package/dist/index.d.cts +29 -4
  47. package/dist/index.d.ts +29 -4
  48. package/dist/index.js +28 -28
  49. package/dist/mcp/run-stdio.cjs +219 -32
  50. package/dist/mcp/run-stdio.js +23 -23
  51. package/dist/{optional-cli-EMSZBYDE.js → optional-cli-2V3SLME5.js} +3 -3
  52. package/dist/{optional-cli-6GGESWGE.js → optional-cli-MRNQKVIR.js} +4 -4
  53. package/dist/{orchestrator-H3DSZ5RM.js → orchestrator-7BDZ5GWD.js} +10 -10
  54. package/dist/{orchestrator-NCA4LSCC.js → orchestrator-NPFWU3XU.js} +10 -10
  55. package/dist/{thread-store-PLNIWFZ4.js → thread-store-JWHVXLDX.js} +1 -1
  56. package/dist/{thread-store-7BBA63KV.js → thread-store-QHYN2ZMQ.js} +1 -1
  57. package/dist/{workspaces-2V5UYPYC.js → workspaces-5QA3YM4L.js} +4 -4
  58. package/dist/{workspaces-MGKEAYNM.js → workspaces-KWMBOTQD.js} +4 -4
  59. package/dist/{worktree-THAXW5U7.js → worktree-7EATHVYQ.js} +3 -3
  60. package/dist/{worktree-XJKLDYOL.js → worktree-O6BANO2I.js} +3 -3
  61. package/package.json +1 -1
@@ -1405,13 +1405,13 @@ function toolDescription(name, input) {
1405
1405
  else if (/notify_orchestrator$/i.test(name)) return "Notify orchestrator";
1406
1406
  else if (/set_workspace_tags$/i.test(name)) return "Set workspace tags";
1407
1407
  if (/(?:list|set|delete)_env$/i.test(name)) return /list_env$/i.test(name) ? "List env vars" : /set_env$/i.test(name) ? "Set env var" : "Delete env var";
1408
- if (/list_schedules$/i.test(name)) return "List schedules";
1408
+ if (/list_schedules$/i.test(name)) return "List automations";
1409
1409
  if (/create_schedule$/i.test(name)) {
1410
- return str(input?.name) ? `Schedule ${str(input?.name)}` : "Create schedule";
1410
+ return str(input?.name) ? `Automation ${str(input?.name)}` : "Create automation";
1411
1411
  }
1412
- if (/update_schedule$/i.test(name)) return "Update schedule";
1413
- if (/delete_schedule$/i.test(name)) return "Delete schedule";
1414
- if (/run_schedule$/i.test(name)) return "Run schedule";
1412
+ if (/update_schedule$/i.test(name)) return "Update automation";
1413
+ if (/delete_schedule$/i.test(name)) return "Delete automation";
1414
+ if (/run_schedule$/i.test(name)) return "Run automation";
1415
1415
  if (isSkillToolName(name)) {
1416
1416
  const cmd = skillCommandFromInput(input);
1417
1417
  return cmd ? `Using /${cmd}` : "Using skill";
@@ -4532,7 +4532,9 @@ function planHistoryRetention(archived, thresholds = {}) {
4532
4532
  if (archivedUpdatedMs(thread) < cutoff) expiredIds.add(thread.id);
4533
4533
  }
4534
4534
  }
4535
- const remaining = oldestFirst.filter((t) => !expiredIds.has(t.id));
4535
+ const remaining = oldestFirst.filter(
4536
+ (t) => !expiredIds.has(t.id) && !t.ephemeralAutomationId?.trim()
4537
+ );
4536
4538
  const overflow = remaining.length > maxCount ? remaining.slice(0, remaining.length - maxCount) : [];
4537
4539
  const stripIds = [];
4538
4540
  const purgeIds = [...expiredIds];
@@ -7638,6 +7640,7 @@ function normalizeThread(raw) {
7638
7640
  quotaContinuedFromId: raw.quotaContinuedFromId ?? null,
7639
7641
  accountId: raw.accountId === null ? null : typeof raw.accountId === "string" && raw.accountId.trim() ? raw.accountId.trim() : void 0,
7640
7642
  archivedAt: typeof raw.archivedAt === "string" && raw.archivedAt.trim() ? raw.archivedAt.trim() : void 0,
7643
+ ephemeralAutomationId: typeof raw.ephemeralAutomationId === "string" && raw.ephemeralAutomationId.trim() ? raw.ephemeralAutomationId.trim() : void 0,
7641
7644
  compactedMessages: Array.isArray(raw.compactedMessages) ? raw.compactedMessages : void 0
7642
7645
  };
7643
7646
  }
@@ -7824,6 +7827,7 @@ function updateThread(id, patch) {
7824
7827
  } else {
7825
7828
  delete next.archivedAt;
7826
7829
  }
7830
+ if (!next.ephemeralAutomationId?.trim()) delete next.ephemeralAutomationId;
7827
7831
  writeThread(next);
7828
7832
  return next;
7829
7833
  }
@@ -10250,7 +10254,7 @@ var init_coordinator_prompt = __esm({
10250
10254
  "- 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_projects (this cwd is not a project). update_viewer_context requires confirmed=true after ask_user. Never write context unprompted.",
10251
10255
  "- list_env / set_env / delete_env \u2014 Settings \u2192 Environment. scope=project requires repoPath from list_projects and stores the key under that project prefix (the project name, uppercased, plus _). APPLE_ID for sideboard is SIDEBOARD_APPLE_ID. scope=account is shared by every project and is not prefixed. list_env returns names only.",
10252
10256
  "- set_caffeinate \u2014 keep this Mac awake across turns (macOS caffeinate). Turn on for phone remote / 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.",
10253
- "- list_schedules / create_schedule / update_schedule / delete_schedule / run_schedule \u2014 local jobs that send a prompt to a chat (chatId or self) or start a new Global chat (omit chatId). One-shot `at`, interval `every` (15m/1h/6h/1d), or 5-field `cron`. Recurring jobs without chatId open a new chat each run. Worktree agents have the same tools (`chatId=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).",
10257
+ "- list_schedules / create_schedule / update_schedule / delete_schedule / run_schedule \u2014 automations that send a prompt to a chat (chatId or self) or start a new Global chat (omit chatId). One-shot `at`, interval `every` (15m/1h/6h/1d), or 5-field `cron`. Recurring jobs without chatId open a new chat each run and archive it when that run finishes (History keeps the latest run for that automation). Worktree agents have the same tools (`chatId=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 automations are enabled (or call set_caffeinate). The desktop lists them in the sidebar after Board.",
10254
10258
  "Projects:",
10255
10259
  "- add_project / remove_project \u2014 register or unregister a git repo",
10256
10260
  "Workspaces and chats:",
@@ -20060,6 +20064,77 @@ var init_steer_request = __esm({
20060
20064
  }
20061
20065
  });
20062
20066
 
20067
+ // src/orchestrator/ephemeral-automation.ts
20068
+ function ephemeralRunReadyToArchive(thread) {
20069
+ if (!thread.ephemeralAutomationId?.trim()) return false;
20070
+ if (thread.status !== "idle" && thread.status !== "error") return false;
20071
+ if (thread.queue.length > 0) return false;
20072
+ if (thread.agentBlock?.reason?.trim()) return false;
20073
+ if (thread.quotaResumeAt) return false;
20074
+ return true;
20075
+ }
20076
+ function markEphemeralAutomation(threadId, opts) {
20077
+ const id = opts.ephemeralAutomationId?.trim();
20078
+ const current = readThread(threadId);
20079
+ if (!current) throw new Error(`Thread not found: ${threadId}`);
20080
+ if (!id) return current;
20081
+ const title = opts.ephemeralTitle?.trim();
20082
+ return updateThread(threadId, {
20083
+ ephemeralAutomationId: id,
20084
+ ...title ? { title, userSetTitle: true } : {}
20085
+ });
20086
+ }
20087
+ async function archiveEphemeralAutomationIfReady(threadId, archive) {
20088
+ const keep = await withThreadLock(threadId, async () => {
20089
+ const thread = readThread(threadId);
20090
+ if (!thread || !ephemeralRunReadyToArchive(thread)) return null;
20091
+ const automationId = thread.ephemeralAutomationId?.trim();
20092
+ if (!automationId) return null;
20093
+ await archive(thread.id);
20094
+ return {
20095
+ automationId,
20096
+ keepId: archivedContinuationId(automationId, threadId) ?? threadId
20097
+ };
20098
+ });
20099
+ if (keep) forgetOlderEphemeralRuns(keep.automationId, keep.keepId);
20100
+ }
20101
+ function archivedContinuationId(automationId, sourceId) {
20102
+ for (const thread of listThreads({ includeArchived: true })) {
20103
+ if (thread.id === sourceId || thread.status !== "archived") continue;
20104
+ if (thread.ephemeralAutomationId !== automationId) continue;
20105
+ if (thread.quotaContinuedFromId !== sourceId) continue;
20106
+ return thread.id;
20107
+ }
20108
+ return null;
20109
+ }
20110
+ function clearEphemeralAutomation(threadId) {
20111
+ const thread = readThread(threadId);
20112
+ if (!thread?.ephemeralAutomationId?.trim()) return;
20113
+ updateThread(threadId, { ephemeralAutomationId: void 0 });
20114
+ }
20115
+ function forgetOlderEphemeralRuns(automationId, keepId) {
20116
+ const id = automationId.trim();
20117
+ if (!id || !keepId) return [];
20118
+ const removed = [];
20119
+ for (const thread of listThreads({ includeArchived: true })) {
20120
+ if (thread.id === keepId) continue;
20121
+ if (thread.status !== "archived") continue;
20122
+ if (thread.ephemeralAutomationId !== id) continue;
20123
+ try {
20124
+ deleteThreadRecord(thread.id);
20125
+ removed.push(thread.id);
20126
+ } catch {
20127
+ }
20128
+ }
20129
+ return removed;
20130
+ }
20131
+ var init_ephemeral_automation = __esm({
20132
+ "src/orchestrator/ephemeral-automation.ts"() {
20133
+ "use strict";
20134
+ init_thread_store();
20135
+ }
20136
+ });
20137
+
20063
20138
  // src/threads/title.ts
20064
20139
  var title_exports = {};
20065
20140
  __export(title_exports, {
@@ -23568,17 +23643,23 @@ async function isolateQuotaFailover(run2) {
23568
23643
  }
23569
23644
  }
23570
23645
  function createQuotaFailoverChat(from, fallbackAgent, limitText, opts) {
23646
+ const ephemeralAutomationId = from.ephemeralAutomationId?.trim();
23647
+ const ephemeralTitle = ephemeralAutomationId ? from.title.trim() : "";
23571
23648
  const handoff = buildQuotaHandoffAttachment(from, limitText, fallbackAgent);
23572
23649
  const tab = createChatTab({
23573
23650
  fromThreadId: from.id,
23574
23651
  agent: fallbackAgent,
23575
23652
  model: null,
23576
23653
  attachments: [handoff],
23654
+ ...ephemeralTitle ? { title: ephemeralTitle } : {},
23577
23655
  ...opts && "accountId" in opts ? { accountId: opts.accountId } : {}
23578
23656
  });
23579
23657
  const patch = {
23580
23658
  quotaContinuedFromId: from.id,
23581
- sourceRef: from.sourceRef
23659
+ sourceRef: from.sourceRef,
23660
+ // The original drain archives as idle. This sibling has to carry the one-off
23661
+ // so it archives when the continued turn finishes and History keeps it.
23662
+ ...ephemeralAutomationId ? { ephemeralAutomationId } : {}
23582
23663
  };
23583
23664
  if (isOrchestratorThread(from)) {
23584
23665
  patch.parentThreadId = from.id;
@@ -25982,7 +26063,7 @@ function formatWorktreeDirective(thread, opts) {
25982
26063
  lines.push(formatDevAccessHint(opts?.activeRuns));
25983
26064
  lines.push("");
25984
26065
  lines.push(
25985
- "Schedules: `create_schedule` / `list_schedules` (`at` / `every` / `cron`). `chatId=self` continues this chat; omit chatId 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."
26066
+ "Automations (sidebar, after Board): `create_schedule` / `list_schedules` (`at` / `every` / `cron`). `chatId=self` continues this chat; omit chatId for a new Global chat. Fires only while Sideboard.app is running. A future job turns on Settings \u2192 Advanced \u2192 Caffeinate while automations are enabled."
25986
26067
  );
25987
26068
  lines.push(
25988
26069
  "`set_workspace_tags` labels this checkout (omit ref; replace, add, or remove). Not another checkout."
@@ -26002,7 +26083,7 @@ function connectedOrchestratorTurnReminder(thread, find) {
26002
26083
  return formatConnectedOrchestratorReminder(connectedOrchestrator(thread, find));
26003
26084
  }
26004
26085
  function formatWorktreeReminder() {
26005
- return "Sideboard workspace: 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; chatId=self for this chat). set_workspace_tags updates labels on this workspace (omit ref).";
26086
+ return "Sideboard workspace: 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. Automations: create_schedule (at / every / cron; chatId=self for this chat). set_workspace_tags updates labels on this workspace (omit ref).";
26006
26087
  }
26007
26088
  function formatClaudeSubagentReminder() {
26008
26089
  return 'Claude subagents: if Task/Agent workers will edit files, write a short plan in this chat and continue in the same turn. Do not ask the user whether to isolate, and do not set worktree.bgIsolation to none. One writer may edit this workspace. Every other writer is an Agent with isolation "worktree" and a disjoint file list (read-only explore agents may overlap). While those agents run, leave their files alone. Merge each returned branch into this workspace, then remove the temporary worktree. You stay in this cwd. If Claude says another write-capable agent is in this directory, or that writes to the shared checkout are blocked, re-spawn that agent with isolation "worktree" or make the edit yourself. That note is another worker in this chat, or a worker Claude still has marked running. Do not mention it to the user.';
@@ -27125,7 +27206,7 @@ function parseDurationMs(every) {
27125
27206
  }
27126
27207
  function defaultScheduleName(prompt) {
27127
27208
  const line = prompt.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
27128
- if (!line) return "Untitled schedule";
27209
+ if (!line) return "Untitled automation";
27129
27210
  return line.length > 60 ? `${line.slice(0, 57).trimEnd()}\u2026` : line;
27130
27211
  }
27131
27212
  function resolveScheduleThreadId(raw, env = process.env) {
@@ -27190,6 +27271,37 @@ function normalizeWhen(raw) {
27190
27271
  }
27191
27272
  throw new Error("Schedule `when` must be once, every, or cron");
27192
27273
  }
27274
+ function normalizeOptionalBool(raw) {
27275
+ if (raw === true || raw === false) return raw;
27276
+ return null;
27277
+ }
27278
+ function normalizeAutonomy2(raw) {
27279
+ return raw === "default" || raw === "full" ? raw : null;
27280
+ }
27281
+ function normalizeAttachments(raw) {
27282
+ if (!Array.isArray(raw)) return [];
27283
+ const out = [];
27284
+ for (const item of raw) {
27285
+ if (!item || typeof item !== "object") continue;
27286
+ const row = item;
27287
+ if (typeof row.id !== "string" || !row.id.trim()) continue;
27288
+ if (typeof row.name !== "string" || !row.name) continue;
27289
+ if (typeof row.content !== "string") continue;
27290
+ if (!ATTACHMENT_KINDS.has(row.kind)) continue;
27291
+ const next = {
27292
+ id: row.id,
27293
+ name: row.name,
27294
+ kind: row.kind,
27295
+ content: row.content
27296
+ };
27297
+ if (typeof row.path === "string" && row.path) next.path = row.path;
27298
+ if (typeof row.previewDataUrl === "string" && row.previewDataUrl) {
27299
+ next.previewDataUrl = row.previewDataUrl;
27300
+ }
27301
+ out.push(next);
27302
+ }
27303
+ return out;
27304
+ }
27193
27305
  function normalizeTask(raw) {
27194
27306
  const when = normalizeWhen(raw.when);
27195
27307
  const agent = raw.agent && isOrchestratorCapableAgent(raw.agent) ? raw.agent : null;
@@ -27202,6 +27314,11 @@ function normalizeTask(raw) {
27202
27314
  threadId: raw.threadId?.trim() || null,
27203
27315
  agent,
27204
27316
  model: raw.model?.trim() || null,
27317
+ effort: normalizeThinkingEffort(raw.effort),
27318
+ fast: normalizeOptionalBool(raw.fast),
27319
+ planMode: normalizeOptionalBool(raw.planMode),
27320
+ autonomy: normalizeAutonomy2(raw.autonomy),
27321
+ attachments: normalizeAttachments(raw.attachments),
27205
27322
  nextRunAt: raw.nextRunAt,
27206
27323
  lastRunAt: raw.lastRunAt ?? null,
27207
27324
  lastThreadId: raw.lastThreadId ?? null,
@@ -27248,6 +27365,11 @@ function buildTask(input, now) {
27248
27365
  threadId: input.threadId?.trim() || null,
27249
27366
  agent,
27250
27367
  model: input.model?.trim() || null,
27368
+ effort: input.effort != null ? normalizeThinkingEffort(input.effort) : null,
27369
+ fast: normalizeOptionalBool(input.fast),
27370
+ planMode: normalizeOptionalBool(input.planMode),
27371
+ autonomy: normalizeAutonomy2(input.autonomy),
27372
+ attachments: normalizeAttachments(input.attachments),
27251
27373
  nextRunAt,
27252
27374
  lastRunAt: null,
27253
27375
  lastThreadId: null,
@@ -27289,7 +27411,7 @@ function createSchedule(input) {
27289
27411
  function updateSchedule(id, patch) {
27290
27412
  const rows = readAll2();
27291
27413
  const idx = rows.findIndex((row) => row.id === id || id.length >= 8 && row.id.startsWith(id));
27292
- if (idx < 0) throw new Error(`Schedule not found: ${id}`);
27414
+ if (idx < 0) throw new Error(`Automation not found: ${id}`);
27293
27415
  const prev = rows[idx];
27294
27416
  const when = patch.when ? normalizeWhen(patch.when) : prev.when;
27295
27417
  const prompt = patch.prompt !== void 0 ? patch.prompt.trim() : prev.prompt;
@@ -27304,6 +27426,11 @@ function updateSchedule(id, patch) {
27304
27426
  threadId: patch.threadId !== void 0 ? patch.threadId?.trim() || null : prev.threadId,
27305
27427
  agent: patch.agent !== void 0 ? patch.agent ? coerceOrchestratorAgent(patch.agent) : null : prev.agent,
27306
27428
  model: patch.model !== void 0 ? patch.model?.trim() || null : prev.model,
27429
+ effort: patch.effort !== void 0 ? normalizeThinkingEffort(patch.effort) : prev.effort,
27430
+ fast: patch.fast !== void 0 ? normalizeOptionalBool(patch.fast) : prev.fast,
27431
+ planMode: patch.planMode !== void 0 ? normalizeOptionalBool(patch.planMode) : prev.planMode,
27432
+ autonomy: patch.autonomy !== void 0 ? normalizeAutonomy2(patch.autonomy) : prev.autonomy,
27433
+ attachments: patch.attachments !== void 0 ? normalizeAttachments(patch.attachments) : prev.attachments,
27307
27434
  nextRunAt: whenChanged ? computeNextRunAt(when).toISOString() : prev.nextRunAt,
27308
27435
  lastError: whenChanged ? null : prev.lastError,
27309
27436
  updatedAt: nowIso2()
@@ -27318,13 +27445,13 @@ function deleteSchedule(id) {
27318
27445
  const next = rows.filter(
27319
27446
  (row) => row.id !== id && !(id.length >= 8 && row.id.startsWith(id))
27320
27447
  );
27321
- if (next.length === rows.length) throw new Error(`Schedule not found: ${id}`);
27448
+ if (next.length === rows.length) throw new Error(`Automation not found: ${id}`);
27322
27449
  writeAll2(next);
27323
27450
  }
27324
27451
  function recordScheduleRun(id, result) {
27325
27452
  const rows = readAll2();
27326
27453
  const idx = rows.findIndex((row) => row.id === id);
27327
- if (idx < 0) throw new Error(`Schedule not found: ${id}`);
27454
+ if (idx < 0) throw new Error(`Automation not found: ${id}`);
27328
27455
  const prev = rows[idx];
27329
27456
  const firedAt = result.firedAt ?? /* @__PURE__ */ new Date();
27330
27457
  const next = {
@@ -27340,7 +27467,7 @@ function recordScheduleRun(id, result) {
27340
27467
  writeAll2(rows);
27341
27468
  return next;
27342
27469
  }
27343
- var import_node_crypto17, import_node_fs65, import_node_path64, import_croner, DURATION_RE, UNIT_MS;
27470
+ var import_node_crypto17, import_node_fs65, import_node_path64, import_croner, DURATION_RE, UNIT_MS, ATTACHMENT_KINDS;
27344
27471
  var init_schedules = __esm({
27345
27472
  "src/store/schedules.ts"() {
27346
27473
  "use strict";
@@ -27349,6 +27476,7 @@ var init_schedules = __esm({
27349
27476
  import_node_path64 = require("path");
27350
27477
  import_croner = require("croner");
27351
27478
  init_orchestrator_capable();
27479
+ init_thinking_effort();
27352
27480
  init_paths();
27353
27481
  init_private_file();
27354
27482
  init_app_settings();
@@ -27359,6 +27487,14 @@ var init_schedules = __esm({
27359
27487
  h: 36e5,
27360
27488
  d: 864e5
27361
27489
  };
27490
+ ATTACHMENT_KINDS = /* @__PURE__ */ new Set([
27491
+ "transcript",
27492
+ "file",
27493
+ "issue",
27494
+ "workspace",
27495
+ "diff-comment",
27496
+ "code-ref"
27497
+ ]);
27362
27498
  }
27363
27499
  });
27364
27500
 
@@ -27372,17 +27508,52 @@ async function defaultDeps() {
27372
27508
  const orch = getOrchestrator2();
27373
27509
  return {
27374
27510
  findThread: (id) => findThreadByRef(id),
27375
- send: (id, prompt) => orch.send(id, prompt),
27511
+ send: async (id, prompt, opts) => {
27512
+ if (opts?.options && Object.keys(opts.options).length > 0) {
27513
+ try {
27514
+ orch.setThreadOptions(id, opts.options);
27515
+ } catch {
27516
+ const rest = scheduleOptionsAfterRefusedAgentSwitch(opts.options);
27517
+ if (Object.keys(rest).length > 0) {
27518
+ try {
27519
+ orch.setThreadOptions(id, rest);
27520
+ } catch {
27521
+ }
27522
+ }
27523
+ }
27524
+ }
27525
+ const thread = findThreadByRef(id);
27526
+ const attachments = thread ? persistPendingFileAttachments(thread.worktreePath, opts?.attachments ?? []) : opts?.attachments ?? [];
27527
+ return orch.send(id, prompt, { attachments });
27528
+ },
27376
27529
  startOrchestration: (opts) => startOrchestration2(opts)
27377
27530
  };
27378
27531
  }
27532
+ function scheduleOptionsAfterRefusedAgentSwitch(options) {
27533
+ const { agent: _agent, model: _model, ...rest } = options;
27534
+ return rest;
27535
+ }
27536
+ function scheduleSendOptions(schedule) {
27537
+ const patch = {};
27538
+ if (schedule.agent) {
27539
+ patch.agent = schedule.agent;
27540
+ patch.model = schedule.model;
27541
+ } else if (schedule.model) {
27542
+ patch.model = schedule.model;
27543
+ }
27544
+ if (schedule.effort) patch.effort = schedule.effort;
27545
+ if (schedule.fast != null) patch.fast = schedule.fast;
27546
+ if (schedule.planMode != null) patch.planMode = schedule.planMode;
27547
+ if (schedule.autonomy) patch.autonomy = schedule.autonomy;
27548
+ return Object.keys(patch).length > 0 ? patch : void 0;
27549
+ }
27379
27550
  function pickAgent(schedule) {
27380
27551
  if (schedule.agent) return schedule.agent;
27381
27552
  return coerceOrchestratorAgent(resolveOrchestratorDefaults().agent);
27382
27553
  }
27383
27554
  async function fireSchedule(id) {
27384
27555
  const schedule = getSchedule(id);
27385
- if (!schedule) throw new Error(`Schedule not found: ${id}`);
27556
+ if (!schedule) throw new Error(`Automation not found: ${id}`);
27386
27557
  if (firing.has(schedule.id)) return schedule;
27387
27558
  firing.add(schedule.id);
27388
27559
  try {
@@ -27390,18 +27561,28 @@ async function fireSchedule(id) {
27390
27561
  const prompt = formatScheduledPrompt(schedule.name, schedule.prompt);
27391
27562
  const target = schedule.threadId ? deps.findThread(schedule.threadId) : null;
27392
27563
  if (target && target.status !== "archived") {
27393
- const sent = await deps.send(target.id, prompt);
27564
+ const sent = await deps.send(target.id, prompt, {
27565
+ attachments: schedule.attachments,
27566
+ options: scheduleSendOptions(schedule)
27567
+ });
27394
27568
  return recordScheduleRun(schedule.id, {
27395
27569
  lastThreadId: sent.id,
27396
27570
  lastError: null
27397
27571
  });
27398
27572
  }
27573
+ const pinReplacement = Boolean(schedule.threadId) && schedule.when.kind !== "once";
27399
27574
  const created = await deps.startOrchestration({
27400
27575
  goal: prompt,
27401
27576
  agent: pickAgent(schedule),
27402
- model: schedule.model
27577
+ model: schedule.model,
27578
+ ...schedule.effort ? { effort: schedule.effort } : {},
27579
+ ...schedule.fast != null ? { fast: schedule.fast } : {},
27580
+ ...schedule.planMode != null ? { planMode: schedule.planMode } : {},
27581
+ ...schedule.autonomy ? { autonomy: schedule.autonomy } : {},
27582
+ attachments: schedule.attachments,
27583
+ ...pinReplacement ? {} : { ephemeralAutomationId: schedule.id, ephemeralTitle: schedule.name }
27403
27584
  });
27404
- if (schedule.threadId && schedule.when.kind !== "once") {
27585
+ if (pinReplacement) {
27405
27586
  updateSchedule(schedule.id, { threadId: created.id });
27406
27587
  }
27407
27588
  return recordScheduleRun(schedule.id, {
@@ -27471,6 +27652,7 @@ var init_schedule_runner = __esm({
27471
27652
  init_desktop_host();
27472
27653
  init_app_settings();
27473
27654
  init_schedules();
27655
+ init_stage_files();
27474
27656
  init_thread_store();
27475
27657
  SET_TIMEOUT_MAX = 2147483647;
27476
27658
  fireHooks = null;
@@ -27603,10 +27785,11 @@ async function startOrchestration(opts) {
27603
27785
  planMode: opts.planMode,
27604
27786
  attachments: opts.attachments
27605
27787
  });
27788
+ const ready2 = markEphemeralAutomation(thread2.id, opts);
27606
27789
  if (goal) {
27607
- return orch.send(thread2.id, goal);
27790
+ return orch.send(ready2.id, goal);
27608
27791
  }
27609
- return thread2;
27792
+ return ready2;
27610
27793
  }
27611
27794
  const { titleFromPrompt: titleFromPrompt2 } = await Promise.resolve().then(() => (init_title(), title_exports));
27612
27795
  const title = titleFromPrompt2(goal) || "Orchestration";
@@ -27641,10 +27824,11 @@ async function startOrchestration(opts) {
27641
27824
  sourceType: "orchestration",
27642
27825
  sourceRef: goal
27643
27826
  });
27827
+ const ready = markEphemeralAutomation(updated.id, opts);
27644
27828
  if (goal) {
27645
- return orch.send(updated.id, goal);
27829
+ return orch.send(ready.id, goal);
27646
27830
  }
27647
- return updated;
27831
+ return ready;
27648
27832
  }
27649
27833
  var import_node_events, import_node_crypto18, import_node_fs67, LIVE_TURN_SPAWN_GRACE_MS, RUN_SCRIPT_DESKTOP_ADOPT_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton2;
27650
27834
  var init_orchestrator = __esm({
@@ -27685,6 +27869,7 @@ var init_orchestrator = __esm({
27685
27869
  init_child_halt();
27686
27870
  init_stop_reason();
27687
27871
  init_steer_request();
27872
+ init_ephemeral_automation();
27688
27873
  init_wait_for_job();
27689
27874
  init_agent_purpose_title();
27690
27875
  init_create();
@@ -28522,6 +28707,7 @@ var init_orchestrator = __esm({
28522
28707
  } finally {
28523
28708
  this.draining.delete(threadId);
28524
28709
  }
28710
+ await archiveEphemeralAutomationIfReady(threadId, (id) => this.archive(id));
28525
28711
  }
28526
28712
  async runTurn(threadId, prompt) {
28527
28713
  const existing = readThread(threadId);
@@ -30355,6 +30541,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
30355
30541
  if (thread.status !== "archived") {
30356
30542
  throw new Error("Thread is not archived");
30357
30543
  }
30544
+ clearEphemeralAutomation(thread.id);
30358
30545
  if (isGlobalThread(thread)) {
30359
30546
  const { globalAgentCwd: globalAgentCwd2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
30360
30547
  updateThread(thread.id, { worktreePath: globalAgentCwd2() });
@@ -33907,7 +34094,7 @@ function parseWhen(args) {
33907
34094
  function registerScheduleTools(server) {
33908
34095
  server.tool(
33909
34096
  "list_schedules",
33910
- "List local Sideboard schedules that trigger a chat when due. Jobs fire only while Sideboard.app is running on this Mac (sleep skips until wake).",
34097
+ "List local Sideboard automations that trigger a chat when due. Jobs fire only while Sideboard.app is running on this Mac (sleep skips until wake). Shown in the sidebar after Board.",
33911
34098
  {},
33912
34099
  async () => {
33913
34100
  try {
@@ -33919,9 +34106,9 @@ function registerScheduleTools(server) {
33919
34106
  );
33920
34107
  server.tool(
33921
34108
  "create_schedule",
33922
- "Create a local schedule that, when due, sends a prompt to an existing chat (chatId) or starts a new Global orchestration chat (omit chatId). Pass chatId=self to continue this chat. If that chat is missing or archived when the job fires, Sideboard starts a new Global chat (recurring jobs then continue that chat). Exactly one of at (ISO datetime), every (15m/1h/6h/1d), or cron (5-field). Recurring jobs without chatId open a new Global chat each run. Creating or enabling a future job turns on Settings \u2192 Advanced \u2192 Caffeinate while schedules are enabled so the Mac stays awake until due. Sideboard.app must be running for the job to fire.",
34109
+ "Create a local automation that, when due, sends a prompt to an existing chat (chatId) or starts a new Global orchestration chat (omit chatId). Pass chatId=self to continue this chat. If that chat is missing or archived when the job fires, Sideboard starts a new Global chat (recurring jobs then continue that chat). Exactly one of at (ISO datetime), every (15m/1h/6h/1d), or cron (5-field). Recurring jobs without chatId open a new Global chat each run and archive it when that run finishes. History keeps the latest run for that automation. Creating or enabling a future job turns on Settings \u2192 Advanced \u2192 Caffeinate while automations are enabled so the Mac stays awake until due. Sideboard.app must be running for the job to fire.",
33923
34110
  {
33924
- prompt: import_zod10.z.string().describe("User message / goal queued when the schedule fires"),
34111
+ prompt: import_zod10.z.string().describe("User message / goal queued when the automation fires"),
33925
34112
  name: import_zod10.z.string().optional(),
33926
34113
  at: import_zod10.z.string().optional().describe("ISO datetime for a one-shot"),
33927
34114
  every: import_zod10.z.string().optional().describe("Interval such as 15m, 1h, 6h, 1d"),
@@ -33957,7 +34144,7 @@ function registerScheduleTools(server) {
33957
34144
  });
33958
34145
  return text6({
33959
34146
  schedule,
33960
- hint: scheduleNeedsCaffeinate(schedule) ? "Fires while Sideboard.app is running. Recurring jobs without chatId create a new orchestration chat each run. Caffeinate while schedules are enabled is now on so the Mac can stay awake until this job is due." : "Fires while Sideboard.app is running. Recurring jobs without chatId create a new orchestration chat each run."
34147
+ hint: scheduleNeedsCaffeinate(schedule) ? "Fires while Sideboard.app is running. Recurring jobs without chatId create a new orchestration chat each run and archive it when that run finishes (History keeps the latest). Caffeinate while automations are enabled is now on so the Mac can stay awake until this job is due." : "Fires while Sideboard.app is running. Recurring jobs without chatId create a new orchestration chat each run and archive it when that run finishes (History keeps the latest)."
33961
34148
  });
33962
34149
  } catch (err) {
33963
34150
  return fail4(err);
@@ -33966,7 +34153,7 @@ function registerScheduleTools(server) {
33966
34153
  );
33967
34154
  server.tool(
33968
34155
  "update_schedule",
33969
- "Update a local schedule (prompt, cadence, target chat, enabled). Pass id from list_schedules.",
34156
+ "Update a local automation (prompt, cadence, target chat, enabled). Pass id from list_schedules.",
33970
34157
  {
33971
34158
  id: import_zod10.z.string(),
33972
34159
  prompt: import_zod10.z.string().optional(),
@@ -34021,7 +34208,7 @@ function registerScheduleTools(server) {
34021
34208
  );
34022
34209
  server.tool(
34023
34210
  "delete_schedule",
34024
- "Delete a local schedule. Pass id from list_schedules.",
34211
+ "Delete a local automation. Pass id from list_schedules.",
34025
34212
  { id: import_zod10.z.string() },
34026
34213
  async ({ id }) => {
34027
34214
  try {
@@ -34034,12 +34221,12 @@ function registerScheduleTools(server) {
34034
34221
  );
34035
34222
  server.tool(
34036
34223
  "run_schedule",
34037
- "Fire a schedule now (does not wait for nextRunAt). Queues the prompt on the target chat or starts a new Global chat. If Sideboard.app is running, the desktop drains the turn.",
34224
+ "Fire an automation now (does not wait for nextRunAt). Queues the prompt on the target chat or starts a new Global chat. If Sideboard.app is running, the desktop drains the turn.",
34038
34225
  { id: import_zod10.z.string() },
34039
34226
  async ({ id }) => {
34040
34227
  try {
34041
34228
  if (!getSchedule(id)) {
34042
- return fail4(new Error(`Schedule not found: ${id}`));
34229
+ return fail4(new Error(`Automation not found: ${id}`));
34043
34230
  }
34044
34231
  const schedule = await fireSchedule(id);
34045
34232
  return text6({ schedule });