@sideboard-ai/core 0.1.322 → 0.1.323
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.
- package/dist/{abletime-CRRLEYTE.js → abletime-5ZY3ZUUO.js} +4 -4
- package/dist/{abletime-ICW6Q2AB.js → abletime-CU2UPMJF.js} +4 -4
- package/dist/{abletime-oauth-P3KPPJE4.js → abletime-oauth-4TTCR3CT.js} +3 -3
- package/dist/{abletime-oauth-Q76XBSPG.js → abletime-oauth-7EOSBEFM.js} +3 -3
- package/dist/{abletime-rest-DQ3PNKXP.js → abletime-rest-3TG4G7LW.js} +3 -3
- package/dist/{abletime-rest-DNFAYYLP.js → abletime-rest-KOKE7V4B.js} +3 -3
- package/dist/{agents-PFVYC36J.js → agents-2ZXORBEJ.js} +5 -5
- package/dist/{agents-ROFDNE7Z.js → agents-SPRAOMGI.js} +5 -5
- package/dist/{app-settings-KMPVI2B7.js → app-settings-I5HM5RMP.js} +1 -1
- package/dist/{app-settings-P3H4SEIK.js → app-settings-XIF4EC4K.js} +1 -1
- package/dist/{chunk-45UB2J47.js → chunk-4C5PQ7JA.js} +160 -46
- package/dist/{chunk-XDQSHSL6.js → chunk-53SBTCKF.js} +4 -4
- package/dist/{chunk-BPDVHB4U.js → chunk-5GDJSFCT.js} +2 -2
- package/dist/{chunk-H6GXYV5Q.js → chunk-6W3XRKD5.js} +3 -3
- package/dist/{chunk-RHJKZOPQ.js → chunk-74OPNF7U.js} +2 -2
- package/dist/{chunk-BTIXTH4N.js → chunk-7PVT73H6.js} +3 -3
- package/dist/{chunk-JNEFEA2A.js → chunk-D3VSKNVA.js} +4 -4
- package/dist/{chunk-FZKAAAEB.js → chunk-EJ66LEKH.js} +1 -0
- package/dist/{chunk-DFUXW2IT.js → chunk-EKU7FQVG.js} +2 -2
- package/dist/{chunk-5OQONGHO.js → chunk-FR3SAYUL.js} +5 -5
- package/dist/{chunk-UWJUARFA.js → chunk-FUFNMUNR.js} +1 -1
- package/dist/{chunk-TEFFR6PB.js → chunk-INBUV7HY.js} +2 -2
- package/dist/{chunk-LD2DXHBP.js → chunk-JDX3474T.js} +182 -50
- package/dist/{chunk-SPMIZSKH.js → chunk-MYVKOIIY.js} +3 -3
- package/dist/{chunk-7JV5QP5K.js → chunk-MZIZTSR2.js} +2 -2
- package/dist/{chunk-HHPTGIKS.js → chunk-NXUN4U5P.js} +2 -2
- package/dist/{chunk-V76MQ7MH.js → chunk-ODH3XHMI.js} +5 -5
- package/dist/{chunk-IFU4W4C4.js → chunk-OIHRC2ZJ.js} +1 -0
- package/dist/{chunk-56M6VEXI.js → chunk-Q3YJZPQI.js} +3 -3
- package/dist/{chunk-UX6EDDGR.js → chunk-QOS4465Y.js} +1 -1
- package/dist/{chunk-YWBLQBSN.js → chunk-ROOZDDFA.js} +1 -1
- package/dist/{chunk-BANN5HUX.js → chunk-RTVS3M74.js} +4 -4
- package/dist/{chunk-RGUZPMTF.js → chunk-SKO7IGKU.js} +4 -4
- package/dist/{chunk-72PUPPV2.js → chunk-Y3WREIPQ.js} +3 -3
- package/dist/{conductor-XLXJU24U.js → conductor-52KTQ3IM.js} +4 -4
- package/dist/{conductor-CNT3VL3S.js → conductor-FB7MKLRN.js} +4 -4
- package/dist/{coordinator-prompt-D5EE2YTV.js → coordinator-prompt-7HXV7HJ5.js} +3 -3
- package/dist/{coordinator-prompt-TU24TQ4I.js → coordinator-prompt-7W7WPY4X.js} +3 -3
- package/dist/{global-workspace-UPMXDQM7.js → global-workspace-5BWUTSPJ.js} +3 -3
- package/dist/{global-workspace-743TPQNF.js → global-workspace-EI3KBGZE.js} +3 -3
- package/dist/index.cjs +267 -57
- package/dist/index.d.cts +45 -17
- package/dist/index.d.ts +45 -17
- package/dist/index.js +113 -36
- package/dist/mcp/run-stdio.cjs +242 -57
- package/dist/mcp/run-stdio.js +97 -31
- package/dist/{optional-cli-USD6PROE.js → optional-cli-RMMS5L6F.js} +3 -3
- package/dist/{optional-cli-2YDQQCCD.js → optional-cli-Y3Z3GIPZ.js} +4 -4
- package/dist/{orchestrator-VQ4HRYVB.js → orchestrator-2RDE2YS3.js} +8 -8
- package/dist/{orchestrator-B4STIW4B.js → orchestrator-RMPZETOO.js} +8 -8
- package/dist/{workspaces-75FD4QUR.js → workspaces-LJQS73K6.js} +3 -3
- package/dist/{workspaces-47WQL5IG.js → workspaces-OPQ5NMM6.js} +3 -3
- package/dist/{worktree-G3E6WP66.js → worktree-4NGXCCUO.js} +2 -2
- package/dist/{worktree-PDNPL5CQ.js → worktree-ZDA2UJ7C.js} +2 -2
- package/package.json +1 -1
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -10641,7 +10641,7 @@ var init_coordinator_prompt = __esm({
|
|
|
10641
10641
|
"- 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.",
|
|
10642
10642
|
"- 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.",
|
|
10643
10643
|
"- 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.",
|
|
10644
|
-
"- 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
|
|
10644
|
+
"- 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), clock time `time` + `days` (07:30 and weekdays, or mon,wed), or 5-field `cron`. Recurring jobs without chatId open a new chat each run and archive it when that run finishes unless archiveChat is false (leave the chat open to keep talking). History keeps the last 5 archived runs 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.",
|
|
10645
10645
|
"Projects:",
|
|
10646
10646
|
"- add_project / remove_project \u2014 register or unregister a git repo",
|
|
10647
10647
|
"Workspaces and chats:",
|
|
@@ -20515,12 +20515,12 @@ function ephemeralRunReadyToArchive(thread) {
|
|
|
20515
20515
|
}
|
|
20516
20516
|
function markEphemeralAutomation(threadId, opts) {
|
|
20517
20517
|
const id = opts.ephemeralAutomationId?.trim();
|
|
20518
|
+
const title = opts.ephemeralTitle?.trim();
|
|
20518
20519
|
const current = readThread(threadId);
|
|
20519
20520
|
if (!current) throw new Error(`Thread not found: ${threadId}`);
|
|
20520
|
-
if (!id) return current;
|
|
20521
|
-
const title = opts.ephemeralTitle?.trim();
|
|
20521
|
+
if (!id && !title) return current;
|
|
20522
20522
|
return updateThread(threadId, {
|
|
20523
|
-
ephemeralAutomationId: id,
|
|
20523
|
+
...id ? { ephemeralAutomationId: id } : {},
|
|
20524
20524
|
...title ? { title, userSetTitle: true } : {}
|
|
20525
20525
|
});
|
|
20526
20526
|
}
|
|
@@ -20555,11 +20555,19 @@ function clearEphemeralAutomation(threadId) {
|
|
|
20555
20555
|
function forgetOlderEphemeralRuns(automationId, keepId) {
|
|
20556
20556
|
const id = automationId.trim();
|
|
20557
20557
|
if (!id || !keepId) return [];
|
|
20558
|
+
const archived = listThreads({ includeArchived: true }).filter(
|
|
20559
|
+
(thread) => thread.status === "archived" && thread.ephemeralAutomationId === id
|
|
20560
|
+
);
|
|
20561
|
+
const ranked = [...archived].sort((a, b) => {
|
|
20562
|
+
if (a.id === keepId) return -1;
|
|
20563
|
+
if (b.id === keepId) return 1;
|
|
20564
|
+
return archivedUpdatedMs(b) - archivedUpdatedMs(a);
|
|
20565
|
+
});
|
|
20566
|
+
const keep = new Set(ranked.slice(0, EPHEMERAL_AUTOMATION_KEEP).map((thread) => thread.id));
|
|
20567
|
+
keep.add(keepId);
|
|
20558
20568
|
const removed = [];
|
|
20559
|
-
for (const thread of
|
|
20560
|
-
if (thread.id
|
|
20561
|
-
if (thread.status !== "archived") continue;
|
|
20562
|
-
if (thread.ephemeralAutomationId !== id) continue;
|
|
20569
|
+
for (const thread of archived) {
|
|
20570
|
+
if (keep.has(thread.id)) continue;
|
|
20563
20571
|
try {
|
|
20564
20572
|
deleteThreadRecord(thread.id);
|
|
20565
20573
|
removed.push(thread.id);
|
|
@@ -20568,10 +20576,13 @@ function forgetOlderEphemeralRuns(automationId, keepId) {
|
|
|
20568
20576
|
}
|
|
20569
20577
|
return removed;
|
|
20570
20578
|
}
|
|
20579
|
+
var EPHEMERAL_AUTOMATION_KEEP;
|
|
20571
20580
|
var init_ephemeral_automation = __esm({
|
|
20572
20581
|
"src/orchestrator/ephemeral-automation.ts"() {
|
|
20573
20582
|
"use strict";
|
|
20583
|
+
init_history_retention();
|
|
20574
20584
|
init_thread_store();
|
|
20585
|
+
EPHEMERAL_AUTOMATION_KEEP = 5;
|
|
20575
20586
|
}
|
|
20576
20587
|
});
|
|
20577
20588
|
|
|
@@ -26727,7 +26738,7 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
26727
26738
|
lines.push(formatDevAccessHint(opts?.activeRuns));
|
|
26728
26739
|
lines.push("");
|
|
26729
26740
|
lines.push(
|
|
26730
|
-
"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."
|
|
26741
|
+
"Automations (sidebar, after Board): `create_schedule` / `list_schedules` (`at` / `every` / `cron` / `time`+`days`). `archiveChat=false` keeps the new chat. `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."
|
|
26731
26742
|
);
|
|
26732
26743
|
lines.push(
|
|
26733
26744
|
"`set_workspace_tags` labels this checkout (omit ref; replace, add, or remove). Not another checkout."
|
|
@@ -26747,7 +26758,7 @@ function connectedOrchestratorTurnReminder(thread, find) {
|
|
|
26747
26758
|
return formatConnectedOrchestratorReminder(connectedOrchestrator(thread, find));
|
|
26748
26759
|
}
|
|
26749
26760
|
function formatWorktreeReminder() {
|
|
26750
|
-
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).";
|
|
26761
|
+
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, or time + days such as weekdays at 07:30; archiveChat=false leaves the new chat open; chatId=self for this chat). set_workspace_tags updates labels on this workspace (omit ref).";
|
|
26751
26762
|
}
|
|
26752
26763
|
function formatClaudeSubagentReminder() {
|
|
26753
26764
|
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.';
|
|
@@ -27858,10 +27869,7 @@ var init_caffeinate_hold = __esm({
|
|
|
27858
27869
|
}
|
|
27859
27870
|
});
|
|
27860
27871
|
|
|
27861
|
-
// src/store/
|
|
27862
|
-
function schedulesPath() {
|
|
27863
|
-
return (0, import_node_path65.join)(appDataDir(), "schedules.json");
|
|
27864
|
-
}
|
|
27872
|
+
// src/store/schedule-when.ts
|
|
27865
27873
|
function parseDurationMs(every) {
|
|
27866
27874
|
const m = every.trim().match(DURATION_RE);
|
|
27867
27875
|
if (!m) return null;
|
|
@@ -27870,18 +27878,65 @@ function parseDurationMs(every) {
|
|
|
27870
27878
|
const unit = m[2].toLowerCase();
|
|
27871
27879
|
return n * UNIT_MS[unit];
|
|
27872
27880
|
}
|
|
27873
|
-
function
|
|
27874
|
-
const
|
|
27875
|
-
if (
|
|
27876
|
-
return
|
|
27877
|
-
}
|
|
27878
|
-
function
|
|
27879
|
-
const
|
|
27880
|
-
|
|
27881
|
-
|
|
27882
|
-
|
|
27881
|
+
function dayIndex(token) {
|
|
27882
|
+
const text7 = token.trim().toLowerCase();
|
|
27883
|
+
if (/^[0-6]$/.test(text7)) return Number(text7);
|
|
27884
|
+
return DAY_ALIASES[text7];
|
|
27885
|
+
}
|
|
27886
|
+
function normalizeWeekdays(days) {
|
|
27887
|
+
const set = /* @__PURE__ */ new Set();
|
|
27888
|
+
for (const day of days) {
|
|
27889
|
+
if (!Number.isInteger(day) || day < 0 || day > 6) {
|
|
27890
|
+
throw new Error("Days must be 0 (Sunday) through 6 (Saturday)");
|
|
27891
|
+
}
|
|
27892
|
+
set.add(day);
|
|
27893
|
+
}
|
|
27894
|
+
if (set.size === 0) throw new Error("Pick at least one day");
|
|
27895
|
+
return [...set].sort((a, b) => a - b);
|
|
27896
|
+
}
|
|
27897
|
+
function parseWeeklyDays(raw) {
|
|
27898
|
+
const text7 = raw.trim().toLowerCase();
|
|
27899
|
+
if (!text7) throw new Error("Pick at least one day");
|
|
27900
|
+
if (text7 === "daily" || text7 === "all" || text7 === "every day" || text7 === "everyday") {
|
|
27901
|
+
return [0, 1, 2, 3, 4, 5, 6];
|
|
27902
|
+
}
|
|
27903
|
+
if (text7 === "weekdays" || text7 === "weekday") return [1, 2, 3, 4, 5];
|
|
27904
|
+
if (text7 === "weekends" || text7 === "weekend") return [0, 6];
|
|
27905
|
+
const days = [];
|
|
27906
|
+
for (const part of text7.split(/[\s,]+/).filter(Boolean)) {
|
|
27907
|
+
const range = part.split("-");
|
|
27908
|
+
if (range.length === 2 && range[0] && range[1]) {
|
|
27909
|
+
const start = dayIndex(range[0]);
|
|
27910
|
+
const end = dayIndex(range[1]);
|
|
27911
|
+
if (start === void 0 || end === void 0) {
|
|
27912
|
+
throw new Error(`Unknown day: ${part} (use mon,tue, weekdays, weekends, or daily)`);
|
|
27913
|
+
}
|
|
27914
|
+
if (start <= end) {
|
|
27915
|
+
for (let d = start; d <= end; d++) days.push(d);
|
|
27916
|
+
} else {
|
|
27917
|
+
for (let d = start; d <= 6; d++) days.push(d);
|
|
27918
|
+
for (let d = 0; d <= end; d++) days.push(d);
|
|
27919
|
+
}
|
|
27920
|
+
continue;
|
|
27921
|
+
}
|
|
27922
|
+
const n = dayIndex(part);
|
|
27923
|
+
if (n === void 0) {
|
|
27924
|
+
throw new Error(`Unknown day: ${part} (use mon,tue, weekdays, weekends, or daily)`);
|
|
27925
|
+
}
|
|
27926
|
+
days.push(n);
|
|
27883
27927
|
}
|
|
27884
|
-
return
|
|
27928
|
+
return normalizeWeekdays(days);
|
|
27929
|
+
}
|
|
27930
|
+
function normalizeWeeklyTime(raw) {
|
|
27931
|
+
const m = raw.trim().match(TIME_RE);
|
|
27932
|
+
if (!m) throw new Error(`Invalid time: ${raw} (use HH:mm, 24-hour)`);
|
|
27933
|
+
return `${m[1]}:${m[2]}`;
|
|
27934
|
+
}
|
|
27935
|
+
function weeklyCronExpr(when) {
|
|
27936
|
+
const time = normalizeWeeklyTime(when.time);
|
|
27937
|
+
const [hh, mm] = time.split(":");
|
|
27938
|
+
const days = normalizeWeekdays(when.days);
|
|
27939
|
+
return `${Number(mm)} ${Number(hh)} * * ${days.join(",")}`;
|
|
27885
27940
|
}
|
|
27886
27941
|
function computeNextRunAt(when, from = /* @__PURE__ */ new Date()) {
|
|
27887
27942
|
if (when.kind === "once") {
|
|
@@ -27898,6 +27953,12 @@ function computeNextRunAt(when, from = /* @__PURE__ */ new Date()) {
|
|
|
27898
27953
|
}
|
|
27899
27954
|
return new Date(from.getTime() + ms);
|
|
27900
27955
|
}
|
|
27956
|
+
if (when.kind === "weekly") {
|
|
27957
|
+
return computeNextRunAt(
|
|
27958
|
+
{ kind: "cron", expr: weeklyCronExpr(when), tz: when.tz },
|
|
27959
|
+
from
|
|
27960
|
+
);
|
|
27961
|
+
}
|
|
27901
27962
|
try {
|
|
27902
27963
|
const job = new import_croner.Cron(when.expr, {
|
|
27903
27964
|
timezone: when.tz?.trim() || void 0,
|
|
@@ -27913,9 +27974,6 @@ function computeNextRunAt(when, from = /* @__PURE__ */ new Date()) {
|
|
|
27913
27974
|
throw new Error(`Invalid cron: ${message}`);
|
|
27914
27975
|
}
|
|
27915
27976
|
}
|
|
27916
|
-
function nowIso2(d = /* @__PURE__ */ new Date()) {
|
|
27917
|
-
return d.toISOString();
|
|
27918
|
-
}
|
|
27919
27977
|
function normalizeWhen(raw) {
|
|
27920
27978
|
if (!raw || typeof raw !== "object") {
|
|
27921
27979
|
throw new Error("Schedule is missing `when`");
|
|
@@ -27935,7 +27993,70 @@ function normalizeWhen(raw) {
|
|
|
27935
27993
|
tz: typeof rec.tz === "string" && rec.tz.trim() ? rec.tz.trim() : void 0
|
|
27936
27994
|
};
|
|
27937
27995
|
}
|
|
27938
|
-
|
|
27996
|
+
if (kind === "weekly" && Array.isArray(rec.days) && typeof rec.time === "string") {
|
|
27997
|
+
return {
|
|
27998
|
+
kind: "weekly",
|
|
27999
|
+
days: normalizeWeekdays(rec.days.map((day) => Number(day))),
|
|
28000
|
+
time: normalizeWeeklyTime(rec.time),
|
|
28001
|
+
tz: typeof rec.tz === "string" && rec.tz.trim() ? rec.tz.trim() : void 0
|
|
28002
|
+
};
|
|
28003
|
+
}
|
|
28004
|
+
throw new Error("Schedule `when` must be once, every, weekly, or cron");
|
|
28005
|
+
}
|
|
28006
|
+
var import_croner, DURATION_RE, UNIT_MS, DAY_ALIASES, TIME_RE;
|
|
28007
|
+
var init_schedule_when = __esm({
|
|
28008
|
+
"src/store/schedule-when.ts"() {
|
|
28009
|
+
"use strict";
|
|
28010
|
+
import_croner = require("croner");
|
|
28011
|
+
DURATION_RE = /^(\d+)(s|m|h|d)$/i;
|
|
28012
|
+
UNIT_MS = {
|
|
28013
|
+
s: 1e3,
|
|
28014
|
+
m: 6e4,
|
|
28015
|
+
h: 36e5,
|
|
28016
|
+
d: 864e5
|
|
28017
|
+
};
|
|
28018
|
+
DAY_ALIASES = {
|
|
28019
|
+
sun: 0,
|
|
28020
|
+
sunday: 0,
|
|
28021
|
+
mon: 1,
|
|
28022
|
+
monday: 1,
|
|
28023
|
+
tue: 2,
|
|
28024
|
+
tues: 2,
|
|
28025
|
+
tuesday: 2,
|
|
28026
|
+
wed: 3,
|
|
28027
|
+
wednesday: 3,
|
|
28028
|
+
thu: 4,
|
|
28029
|
+
thur: 4,
|
|
28030
|
+
thurs: 4,
|
|
28031
|
+
thursday: 4,
|
|
28032
|
+
fri: 5,
|
|
28033
|
+
friday: 5,
|
|
28034
|
+
sat: 6,
|
|
28035
|
+
saturday: 6
|
|
28036
|
+
};
|
|
28037
|
+
TIME_RE = /^([01]\d|2[0-3]):([0-5]\d)(?::[0-5]\d)?$/;
|
|
28038
|
+
}
|
|
28039
|
+
});
|
|
28040
|
+
|
|
28041
|
+
// src/store/schedules.ts
|
|
28042
|
+
function schedulesPath() {
|
|
28043
|
+
return (0, import_node_path65.join)(appDataDir(), "schedules.json");
|
|
28044
|
+
}
|
|
28045
|
+
function defaultScheduleName(prompt) {
|
|
28046
|
+
const line = prompt.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
28047
|
+
if (!line) return "Untitled automation";
|
|
28048
|
+
return line.length > 60 ? `${line.slice(0, 57).trimEnd()}\u2026` : line;
|
|
28049
|
+
}
|
|
28050
|
+
function resolveScheduleThreadId(raw, env = process.env) {
|
|
28051
|
+
const value = raw?.trim() || "";
|
|
28052
|
+
if (!value) return null;
|
|
28053
|
+
if (value.toLowerCase() === "self") {
|
|
28054
|
+
return env.SIDEBOARD_ORCHESTRATOR_THREAD_ID?.trim() || env.SIDEBOARD_THREAD_ID?.trim() || null;
|
|
28055
|
+
}
|
|
28056
|
+
return value;
|
|
28057
|
+
}
|
|
28058
|
+
function nowIso2(d = /* @__PURE__ */ new Date()) {
|
|
28059
|
+
return d.toISOString();
|
|
27939
28060
|
}
|
|
27940
28061
|
function normalizeOptionalBool(raw) {
|
|
27941
28062
|
if (raw === true || raw === false) return raw;
|
|
@@ -27985,6 +28106,7 @@ function normalizeTask(raw) {
|
|
|
27985
28106
|
planMode: normalizeOptionalBool(raw.planMode),
|
|
27986
28107
|
autonomy: normalizeAutonomy2(raw.autonomy),
|
|
27987
28108
|
attachments: normalizeAttachments(raw.attachments),
|
|
28109
|
+
archiveChat: raw.archiveChat !== false,
|
|
27988
28110
|
nextRunAt: raw.nextRunAt,
|
|
27989
28111
|
lastRunAt: raw.lastRunAt ?? null,
|
|
27990
28112
|
lastThreadId: raw.lastThreadId ?? null,
|
|
@@ -28036,6 +28158,7 @@ function buildTask(input, now) {
|
|
|
28036
28158
|
planMode: normalizeOptionalBool(input.planMode),
|
|
28037
28159
|
autonomy: normalizeAutonomy2(input.autonomy),
|
|
28038
28160
|
attachments: normalizeAttachments(input.attachments),
|
|
28161
|
+
archiveChat: input.archiveChat !== false,
|
|
28039
28162
|
nextRunAt,
|
|
28040
28163
|
lastRunAt: null,
|
|
28041
28164
|
lastThreadId: null,
|
|
@@ -28097,6 +28220,7 @@ function updateSchedule(id, patch) {
|
|
|
28097
28220
|
planMode: patch.planMode !== void 0 ? normalizeOptionalBool(patch.planMode) : prev.planMode,
|
|
28098
28221
|
autonomy: patch.autonomy !== void 0 ? normalizeAutonomy2(patch.autonomy) : prev.autonomy,
|
|
28099
28222
|
attachments: patch.attachments !== void 0 ? normalizeAttachments(patch.attachments) : prev.attachments,
|
|
28223
|
+
archiveChat: patch.archiveChat !== void 0 ? patch.archiveChat !== false : prev.archiveChat,
|
|
28100
28224
|
nextRunAt: whenChanged ? computeNextRunAt(when).toISOString() : prev.nextRunAt,
|
|
28101
28225
|
lastError: whenChanged ? null : prev.lastError,
|
|
28102
28226
|
updatedAt: nowIso2()
|
|
@@ -28133,26 +28257,20 @@ function recordScheduleRun(id, result) {
|
|
|
28133
28257
|
writeAll2(rows);
|
|
28134
28258
|
return next;
|
|
28135
28259
|
}
|
|
28136
|
-
var import_node_crypto17, import_node_fs66, import_node_path65,
|
|
28260
|
+
var import_node_crypto17, import_node_fs66, import_node_path65, ATTACHMENT_KINDS;
|
|
28137
28261
|
var init_schedules = __esm({
|
|
28138
28262
|
"src/store/schedules.ts"() {
|
|
28139
28263
|
"use strict";
|
|
28140
28264
|
import_node_crypto17 = require("crypto");
|
|
28141
28265
|
import_node_fs66 = require("fs");
|
|
28142
28266
|
import_node_path65 = require("path");
|
|
28143
|
-
|
|
28267
|
+
init_schedule_when();
|
|
28144
28268
|
init_orchestrator_capable();
|
|
28145
28269
|
init_thinking_effort();
|
|
28146
28270
|
init_paths();
|
|
28147
28271
|
init_private_file();
|
|
28148
28272
|
init_app_settings();
|
|
28149
|
-
|
|
28150
|
-
UNIT_MS = {
|
|
28151
|
-
s: 1e3,
|
|
28152
|
-
m: 6e4,
|
|
28153
|
-
h: 36e5,
|
|
28154
|
-
d: 864e5
|
|
28155
|
-
};
|
|
28273
|
+
init_schedule_when();
|
|
28156
28274
|
ATTACHMENT_KINDS = /* @__PURE__ */ new Set([
|
|
28157
28275
|
"transcript",
|
|
28158
28276
|
"file",
|
|
@@ -28237,6 +28355,7 @@ async function fireSchedule(id) {
|
|
|
28237
28355
|
});
|
|
28238
28356
|
}
|
|
28239
28357
|
const pinReplacement = Boolean(schedule.threadId) && schedule.when.kind !== "once";
|
|
28358
|
+
const archiveFresh = schedule.archiveChat !== false && !pinReplacement;
|
|
28240
28359
|
const created = await deps.startOrchestration({
|
|
28241
28360
|
goal: prompt,
|
|
28242
28361
|
agent: pickAgent(schedule),
|
|
@@ -28246,7 +28365,8 @@ async function fireSchedule(id) {
|
|
|
28246
28365
|
...schedule.planMode != null ? { planMode: schedule.planMode } : {},
|
|
28247
28366
|
...schedule.autonomy ? { autonomy: schedule.autonomy } : {},
|
|
28248
28367
|
attachments: schedule.attachments,
|
|
28249
|
-
...
|
|
28368
|
+
...archiveFresh ? { ephemeralAutomationId: schedule.id } : {},
|
|
28369
|
+
ephemeralTitle: schedule.name
|
|
28250
28370
|
});
|
|
28251
28371
|
if (pinReplacement) {
|
|
28252
28372
|
updateSchedule(schedule.id, { threadId: created.id });
|
|
@@ -34791,18 +34911,79 @@ function fail4(err) {
|
|
|
34791
34911
|
);
|
|
34792
34912
|
}
|
|
34793
34913
|
function parseWhen(args) {
|
|
34794
|
-
const
|
|
34795
|
-
|
|
34796
|
-
|
|
34914
|
+
const at = args.at?.trim();
|
|
34915
|
+
const every = args.every?.trim();
|
|
34916
|
+
const cron = args.cron?.trim();
|
|
34917
|
+
const time = args.time?.trim();
|
|
34918
|
+
const days = args.days?.trim();
|
|
34919
|
+
if (days && !time && !at && !every && !cron) {
|
|
34920
|
+
throw new Error("days needs time (HH:mm), for example time=07:30 days=weekdays");
|
|
34921
|
+
}
|
|
34922
|
+
const picked = [at, every, cron, time].filter(Boolean);
|
|
34923
|
+
if (picked.length !== 1) {
|
|
34924
|
+
throw new Error(
|
|
34925
|
+
"Pass exactly one of at (ISO datetime), every (15m/1h/6h/1d), time (HH:mm), or cron"
|
|
34926
|
+
);
|
|
34927
|
+
}
|
|
34928
|
+
if (at) return { kind: "once", at };
|
|
34929
|
+
if (every) return { kind: "every", every };
|
|
34930
|
+
if (time) {
|
|
34931
|
+
return {
|
|
34932
|
+
kind: "weekly",
|
|
34933
|
+
time,
|
|
34934
|
+
days: parseWeeklyDays(days || "daily"),
|
|
34935
|
+
tz: args.tz?.trim() || void 0
|
|
34936
|
+
};
|
|
34797
34937
|
}
|
|
34798
|
-
if (args.at?.trim()) return { kind: "once", at: args.at.trim() };
|
|
34799
|
-
if (args.every?.trim()) return { kind: "every", every: args.every.trim() };
|
|
34800
34938
|
return {
|
|
34801
34939
|
kind: "cron",
|
|
34802
|
-
expr:
|
|
34940
|
+
expr: cron,
|
|
34803
34941
|
tz: args.tz?.trim() || void 0
|
|
34804
34942
|
};
|
|
34805
34943
|
}
|
|
34944
|
+
function whenFromUpdate(id, args) {
|
|
34945
|
+
const at = args.at?.trim();
|
|
34946
|
+
const every = args.every?.trim();
|
|
34947
|
+
const cron = args.cron?.trim();
|
|
34948
|
+
const time = args.time?.trim();
|
|
34949
|
+
const days = args.days?.trim();
|
|
34950
|
+
const tzSet = args.tz !== void 0;
|
|
34951
|
+
if (!at && !every && !cron && !time && !days && !tzSet) return void 0;
|
|
34952
|
+
if ((time || days) && !at && !every && !cron) {
|
|
34953
|
+
const current = getSchedule(id);
|
|
34954
|
+
const weekly = current?.when.kind === "weekly" ? current.when : null;
|
|
34955
|
+
if (!weekly && !(time && days)) {
|
|
34956
|
+
const kind = current?.when.kind ?? "missing";
|
|
34957
|
+
throw new Error(
|
|
34958
|
+
`time and days change a days-at-a-time automation. This job is ${kind}. Pass time and days together to switch it, or at / every / cron to replace the cadence.`
|
|
34959
|
+
);
|
|
34960
|
+
}
|
|
34961
|
+
const clock = time || weekly?.time;
|
|
34962
|
+
if (!clock) {
|
|
34963
|
+
throw new Error("time (HH:mm) is required, for example time=07:30 days=weekdays");
|
|
34964
|
+
}
|
|
34965
|
+
const prevTz = current?.when.kind === "weekly" || current?.when.kind === "cron" ? current.when.tz : void 0;
|
|
34966
|
+
return {
|
|
34967
|
+
kind: "weekly",
|
|
34968
|
+
time: clock,
|
|
34969
|
+
days: days ? parseWeeklyDays(days) : weekly?.days ?? parseWeeklyDays("daily"),
|
|
34970
|
+
tz: tzSet ? args.tz?.trim() || void 0 : prevTz
|
|
34971
|
+
};
|
|
34972
|
+
}
|
|
34973
|
+
if (!at && !every && !cron && !time && !days && tzSet) {
|
|
34974
|
+
const current = getSchedule(id);
|
|
34975
|
+
if (current?.when.kind === "weekly" || current?.when.kind === "cron") {
|
|
34976
|
+
return { ...current.when, tz: args.tz?.trim() || void 0 };
|
|
34977
|
+
}
|
|
34978
|
+
return void 0;
|
|
34979
|
+
}
|
|
34980
|
+
return parseWhen(args);
|
|
34981
|
+
}
|
|
34982
|
+
function createdHint(schedule) {
|
|
34983
|
+
const awake = scheduleNeedsCaffeinate(schedule) ? " Caffeinate while automations are enabled is now on so the Mac can stay awake until this job is due." : "";
|
|
34984
|
+
const fresh = schedule.threadId ? "" : schedule.archiveChat === false ? " This job leaves the new chat open so you can keep talking." : " A new Global chat is archived when the run finishes (History keeps the last 5 runs). Pass archiveChat=false to leave it open.";
|
|
34985
|
+
return `Fires while Sideboard.app is running.${fresh}${awake}`;
|
|
34986
|
+
}
|
|
34806
34987
|
function registerScheduleTools(server) {
|
|
34807
34988
|
server.tool(
|
|
34808
34989
|
"list_schedules",
|
|
@@ -34818,14 +34999,19 @@ function registerScheduleTools(server) {
|
|
|
34818
34999
|
);
|
|
34819
35000
|
server.tool(
|
|
34820
35001
|
"create_schedule",
|
|
34821
|
-
"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
|
|
35002
|
+
"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), time (HH:mm, with days such as weekdays or mon,wed), or cron (5-field). Recurring jobs without chatId open a new Global chat each run and archive it when that run finishes unless archiveChat is false (leave the chat open to keep talking, for example a morning start-my-day run). History keeps the last 5 archived runs 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.",
|
|
34822
35003
|
{
|
|
34823
35004
|
prompt: import_zod10.z.string().describe("User message / goal queued when the automation fires"),
|
|
34824
35005
|
name: import_zod10.z.string().optional(),
|
|
34825
35006
|
at: import_zod10.z.string().optional().describe("ISO datetime for a one-shot"),
|
|
34826
35007
|
every: import_zod10.z.string().optional().describe("Interval such as 15m, 1h, 6h, 1d"),
|
|
35008
|
+
time: import_zod10.z.string().optional().describe("HH:mm (24-hour) clock time. Omit days for every day."),
|
|
35009
|
+
days: import_zod10.z.string().optional().describe("daily, weekdays, weekends, or days such as mon,wed,fri or mon-fri. Use with time."),
|
|
34827
35010
|
cron: import_zod10.z.string().optional().describe("5-field cron expression"),
|
|
34828
|
-
tz: import_zod10.z.string().optional().describe("IANA timezone for cron (default: system)"),
|
|
35011
|
+
tz: import_zod10.z.string().optional().describe("IANA timezone for cron or time (default: system)"),
|
|
35012
|
+
archiveChat: import_zod10.z.boolean().optional().describe(
|
|
35013
|
+
"Archive a new Global chat when the run finishes. Default true. Pass false to leave the chat open."
|
|
35014
|
+
),
|
|
34829
35015
|
chatId: import_zod10.z.string().optional().describe(
|
|
34830
35016
|
'Existing chat id (orchestration or workspace), or "self" for this chat. Omit to create a new Global chat on fire.'
|
|
34831
35017
|
),
|
|
@@ -34852,11 +35038,12 @@ function registerScheduleTools(server) {
|
|
|
34852
35038
|
threadId,
|
|
34853
35039
|
agent: args.agent,
|
|
34854
35040
|
model: args.model,
|
|
35041
|
+
archiveChat: args.archiveChat,
|
|
34855
35042
|
createdBy: "mcp"
|
|
34856
35043
|
});
|
|
34857
35044
|
return text6({
|
|
34858
35045
|
schedule,
|
|
34859
|
-
hint:
|
|
35046
|
+
hint: createdHint(schedule)
|
|
34860
35047
|
});
|
|
34861
35048
|
} catch (err) {
|
|
34862
35049
|
return fail4(err);
|
|
@@ -34865,15 +35052,18 @@ function registerScheduleTools(server) {
|
|
|
34865
35052
|
);
|
|
34866
35053
|
server.tool(
|
|
34867
35054
|
"update_schedule",
|
|
34868
|
-
"Update a local automation (prompt, cadence, target chat, enabled). Pass id from list_schedules.",
|
|
35055
|
+
"Update a local automation (prompt, cadence, target chat, archiveChat, enabled). Pass id from list_schedules.",
|
|
34869
35056
|
{
|
|
34870
35057
|
id: import_zod10.z.string(),
|
|
34871
35058
|
prompt: import_zod10.z.string().optional(),
|
|
34872
35059
|
name: import_zod10.z.string().optional(),
|
|
34873
35060
|
at: import_zod10.z.string().optional(),
|
|
34874
35061
|
every: import_zod10.z.string().optional(),
|
|
35062
|
+
time: import_zod10.z.string().optional().describe("HH:mm clock time. Use with days, or alone to change the time of a weekly job."),
|
|
35063
|
+
days: import_zod10.z.string().optional().describe("daily, weekdays, weekends, or mon,wed,fri. Use with time, or alone on an existing weekly job."),
|
|
34875
35064
|
cron: import_zod10.z.string().optional(),
|
|
34876
35065
|
tz: import_zod10.z.string().optional(),
|
|
35066
|
+
archiveChat: import_zod10.z.boolean().optional().describe("Archive a new Global chat when the run finishes. False leaves it open."),
|
|
34877
35067
|
chatId: import_zod10.z.string().optional().describe(
|
|
34878
35068
|
'Existing chat (orchestration or workspace), "self", or empty string to create a new Global chat each run'
|
|
34879
35069
|
),
|
|
@@ -34884,13 +35074,7 @@ function registerScheduleTools(server) {
|
|
|
34884
35074
|
},
|
|
34885
35075
|
async (args) => {
|
|
34886
35076
|
try {
|
|
34887
|
-
const
|
|
34888
|
-
const when = cadenceSet ? parseWhen({
|
|
34889
|
-
at: args.at,
|
|
34890
|
-
every: args.every,
|
|
34891
|
-
cron: args.cron,
|
|
34892
|
-
tz: args.tz
|
|
34893
|
-
}) : void 0;
|
|
35077
|
+
const when = whenFromUpdate(args.id, args);
|
|
34894
35078
|
let threadId;
|
|
34895
35079
|
const rawChatId = args.chatId ?? args.threadId;
|
|
34896
35080
|
if (rawChatId !== void 0) {
|
|
@@ -34910,7 +35094,8 @@ function registerScheduleTools(server) {
|
|
|
34910
35094
|
threadId,
|
|
34911
35095
|
agent: args.agent,
|
|
34912
35096
|
enabled: args.enabled,
|
|
34913
|
-
model: args.model
|
|
35097
|
+
model: args.model,
|
|
35098
|
+
archiveChat: args.archiveChat
|
|
34914
35099
|
});
|
|
34915
35100
|
return text6({ schedule });
|
|
34916
35101
|
} catch (err) {
|