@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.
- package/dist/{abletime-L3ODNTBT.js → abletime-CRRLEYTE.js} +4 -4
- package/dist/{abletime-DVYO4IVS.js → abletime-ICW6Q2AB.js} +4 -4
- package/dist/{abletime-oauth-2VWQCXGT.js → abletime-oauth-P3KPPJE4.js} +3 -3
- package/dist/{abletime-oauth-6DTX7LB7.js → abletime-oauth-Q76XBSPG.js} +3 -3
- package/dist/{abletime-rest-PYQM234B.js → abletime-rest-DNFAYYLP.js} +3 -3
- package/dist/{abletime-rest-7NICZYOC.js → abletime-rest-DQ3PNKXP.js} +3 -3
- package/dist/{agents-KABJUDPI.js → agents-CJZYJOWP.js} +7 -7
- package/dist/{agents-2AR7I6B6.js → agents-F2E2HACB.js} +7 -7
- package/dist/{app-settings-CZVFMOI5.js → app-settings-KMPVI2B7.js} +1 -1
- package/dist/{app-settings-V6YPYY57.js → app-settings-P3H4SEIK.js} +1 -1
- package/dist/{chunk-YEIHCSZS.js → chunk-4GZC6DDH.js} +2 -0
- package/dist/{chunk-5OM7UCTQ.js → chunk-56M6VEXI.js} +3 -3
- package/dist/{chunk-ZM43NTJJ.js → chunk-5OQONGHO.js} +5 -5
- package/dist/{chunk-A6C67DY5.js → chunk-5S3YP5KH.js} +4 -4
- package/dist/{chunk-QPLQXWND.js → chunk-72PUPPV2.js} +3 -3
- package/dist/{chunk-OO3R6CS2.js → chunk-B7UL36WH.js} +214 -37
- package/dist/{chunk-WLZHRNE6.js → chunk-BTIXTH4N.js} +3 -3
- package/dist/{chunk-AESO2KJS.js → chunk-CB5Z5C3J.js} +2 -2
- package/dist/{chunk-AUJ4XB6H.js → chunk-DFUXW2IT.js} +2 -2
- package/dist/{chunk-ST2UQBJT.js → chunk-DJZRDTZY.js} +6 -6
- package/dist/{chunk-TUJFCJJU.js → chunk-EDXTP2VR.js} +2 -2
- package/dist/{chunk-I5TESHDN.js → chunk-EQ52JR3Q.js} +5 -5
- package/dist/{chunk-FDXHNROD.js → chunk-EQ5JY3MJ.js} +2 -2
- package/dist/{chunk-E52SQENB.js → chunk-FZKAAAEB.js} +3 -1
- package/dist/{chunk-JD7CC6SW.js → chunk-HHPTGIKS.js} +2 -2
- package/dist/{chunk-U2N32EA6.js → chunk-IDPFLXRY.js} +215 -38
- package/dist/{chunk-GCHSJCCX.js → chunk-IFU4W4C4.js} +3 -1
- package/dist/{chunk-IAPO7ZFG.js → chunk-LLIEU2ZB.js} +5 -5
- package/dist/{chunk-MBYGWNLQ.js → chunk-OAFBHCSM.js} +1 -1
- package/dist/{chunk-NRSC4N5X.js → chunk-P74GXA5V.js} +6 -6
- package/dist/{chunk-A46CIARU.js → chunk-PNLGWAYE.js} +2 -2
- package/dist/{chunk-53OCOGND.js → chunk-QGY3UNNL.js} +2 -2
- package/dist/{chunk-7Q327QF2.js → chunk-QIC2JXHW.js} +5 -5
- package/dist/{chunk-YALFZKSC.js → chunk-RHJPP26T.js} +11 -11
- package/dist/{chunk-AZ4GEEGL.js → chunk-UK2KESBN.js} +2 -2
- package/dist/{chunk-LXBZQP2Q.js → chunk-V76MQ7MH.js} +5 -5
- package/dist/{chunk-HOLB6ZFZ.js → chunk-XMHMVEIY.js} +2 -0
- package/dist/{chunk-GH7UMULC.js → chunk-ZYZBCLJR.js} +6 -6
- package/dist/{conductor-MG2RAQNT.js → conductor-FPFY6Z5S.js} +6 -6
- package/dist/{conductor-NIUBJLTS.js → conductor-JA5W3L7C.js} +6 -6
- package/dist/{coordinator-prompt-3CT3D5UM.js → coordinator-prompt-M75TAN43.js} +4 -4
- package/dist/{coordinator-prompt-X74F3JIC.js → coordinator-prompt-NUC2ZXMJ.js} +4 -4
- package/dist/{global-workspace-BUWMRNW5.js → global-workspace-5A4H34AF.js} +4 -4
- package/dist/{global-workspace-FTNJEML3.js → global-workspace-SCLQUNUI.js} +4 -4
- package/dist/index.cjs +589 -402
- package/dist/index.d.cts +29 -4
- package/dist/index.d.ts +29 -4
- package/dist/index.js +28 -28
- package/dist/mcp/run-stdio.cjs +219 -32
- package/dist/mcp/run-stdio.js +23 -23
- package/dist/{optional-cli-EMSZBYDE.js → optional-cli-2V3SLME5.js} +3 -3
- package/dist/{optional-cli-6GGESWGE.js → optional-cli-MRNQKVIR.js} +4 -4
- package/dist/{orchestrator-H3DSZ5RM.js → orchestrator-7BDZ5GWD.js} +10 -10
- package/dist/{orchestrator-NCA4LSCC.js → orchestrator-NPFWU3XU.js} +10 -10
- package/dist/{thread-store-PLNIWFZ4.js → thread-store-JWHVXLDX.js} +1 -1
- package/dist/{thread-store-7BBA63KV.js → thread-store-QHYN2ZMQ.js} +1 -1
- package/dist/{workspaces-2V5UYPYC.js → workspaces-5QA3YM4L.js} +4 -4
- package/dist/{workspaces-MGKEAYNM.js → workspaces-KWMBOTQD.js} +4 -4
- package/dist/{worktree-THAXW5U7.js → worktree-7EATHVYQ.js} +3 -3
- package/dist/{worktree-XJKLDYOL.js → worktree-O6BANO2I.js} +3 -3
- package/package.json +1 -1
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -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
|
|
1408
|
+
if (/list_schedules$/i.test(name)) return "List automations";
|
|
1409
1409
|
if (/create_schedule$/i.test(name)) {
|
|
1410
|
-
return str(input?.name) ? `
|
|
1410
|
+
return str(input?.name) ? `Automation ${str(input?.name)}` : "Create automation";
|
|
1411
1411
|
}
|
|
1412
|
-
if (/update_schedule$/i.test(name)) return "Update
|
|
1413
|
-
if (/delete_schedule$/i.test(name)) return "Delete
|
|
1414
|
-
if (/run_schedule$/i.test(name)) return "Run
|
|
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(
|
|
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
|
|
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
|
-
"
|
|
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.
|
|
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
|
|
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(`
|
|
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(`
|
|
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(`
|
|
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) =>
|
|
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(`
|
|
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 (
|
|
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(
|
|
27790
|
+
return orch.send(ready2.id, goal);
|
|
27608
27791
|
}
|
|
27609
|
-
return
|
|
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(
|
|
27829
|
+
return orch.send(ready.id, goal);
|
|
27646
27830
|
}
|
|
27647
|
-
return
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(`
|
|
34229
|
+
return fail4(new Error(`Automation not found: ${id}`));
|
|
34043
34230
|
}
|
|
34044
34231
|
const schedule = await fireSchedule(id);
|
|
34045
34232
|
return text6({ schedule });
|