@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/index.cjs
CHANGED
|
@@ -1925,7 +1925,9 @@ function planHistoryRetention(archived, thresholds = {}) {
|
|
|
1925
1925
|
if (archivedUpdatedMs(thread) < cutoff) expiredIds.add(thread.id);
|
|
1926
1926
|
}
|
|
1927
1927
|
}
|
|
1928
|
-
const remaining = oldestFirst.filter(
|
|
1928
|
+
const remaining = oldestFirst.filter(
|
|
1929
|
+
(t) => !expiredIds.has(t.id) && !t.ephemeralAutomationId?.trim()
|
|
1930
|
+
);
|
|
1929
1931
|
const overflow = remaining.length > maxCount ? remaining.slice(0, remaining.length - maxCount) : [];
|
|
1930
1932
|
const stripIds = [];
|
|
1931
1933
|
const purgeIds = [...expiredIds];
|
|
@@ -5257,6 +5259,7 @@ function normalizeThread(raw) {
|
|
|
5257
5259
|
quotaContinuedFromId: raw.quotaContinuedFromId ?? null,
|
|
5258
5260
|
accountId: raw.accountId === null ? null : typeof raw.accountId === "string" && raw.accountId.trim() ? raw.accountId.trim() : void 0,
|
|
5259
5261
|
archivedAt: typeof raw.archivedAt === "string" && raw.archivedAt.trim() ? raw.archivedAt.trim() : void 0,
|
|
5262
|
+
ephemeralAutomationId: typeof raw.ephemeralAutomationId === "string" && raw.ephemeralAutomationId.trim() ? raw.ephemeralAutomationId.trim() : void 0,
|
|
5260
5263
|
compactedMessages: Array.isArray(raw.compactedMessages) ? raw.compactedMessages : void 0
|
|
5261
5264
|
};
|
|
5262
5265
|
}
|
|
@@ -5443,6 +5446,7 @@ function updateThread(id, patch) {
|
|
|
5443
5446
|
} else {
|
|
5444
5447
|
delete next.archivedAt;
|
|
5445
5448
|
}
|
|
5449
|
+
if (!next.ephemeralAutomationId?.trim()) delete next.ephemeralAutomationId;
|
|
5446
5450
|
writeThread(next);
|
|
5447
5451
|
return next;
|
|
5448
5452
|
}
|
|
@@ -6093,13 +6097,13 @@ function toolDescription(name, input) {
|
|
|
6093
6097
|
else if (/notify_orchestrator$/i.test(name)) return "Notify orchestrator";
|
|
6094
6098
|
else if (/set_workspace_tags$/i.test(name)) return "Set workspace tags";
|
|
6095
6099
|
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";
|
|
6096
|
-
if (/list_schedules$/i.test(name)) return "List
|
|
6100
|
+
if (/list_schedules$/i.test(name)) return "List automations";
|
|
6097
6101
|
if (/create_schedule$/i.test(name)) {
|
|
6098
|
-
return str2(input?.name) ? `
|
|
6102
|
+
return str2(input?.name) ? `Automation ${str2(input?.name)}` : "Create automation";
|
|
6099
6103
|
}
|
|
6100
|
-
if (/update_schedule$/i.test(name)) return "Update
|
|
6101
|
-
if (/delete_schedule$/i.test(name)) return "Delete
|
|
6102
|
-
if (/run_schedule$/i.test(name)) return "Run
|
|
6104
|
+
if (/update_schedule$/i.test(name)) return "Update automation";
|
|
6105
|
+
if (/delete_schedule$/i.test(name)) return "Delete automation";
|
|
6106
|
+
if (/run_schedule$/i.test(name)) return "Run automation";
|
|
6103
6107
|
if (isSkillToolName(name)) {
|
|
6104
6108
|
const cmd = skillCommandFromInput(input);
|
|
6105
6109
|
return cmd ? `Using /${cmd}` : "Using skill";
|
|
@@ -8302,7 +8306,7 @@ function parseDurationMs(every) {
|
|
|
8302
8306
|
}
|
|
8303
8307
|
function defaultScheduleName(prompt) {
|
|
8304
8308
|
const line = prompt.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
8305
|
-
if (!line) return "Untitled
|
|
8309
|
+
if (!line) return "Untitled automation";
|
|
8306
8310
|
return line.length > 60 ? `${line.slice(0, 57).trimEnd()}\u2026` : line;
|
|
8307
8311
|
}
|
|
8308
8312
|
function resolveScheduleThreadId(raw, env = process.env) {
|
|
@@ -8373,6 +8377,37 @@ function normalizeWhen(raw) {
|
|
|
8373
8377
|
}
|
|
8374
8378
|
throw new Error("Schedule `when` must be once, every, or cron");
|
|
8375
8379
|
}
|
|
8380
|
+
function normalizeOptionalBool(raw) {
|
|
8381
|
+
if (raw === true || raw === false) return raw;
|
|
8382
|
+
return null;
|
|
8383
|
+
}
|
|
8384
|
+
function normalizeAutonomy2(raw) {
|
|
8385
|
+
return raw === "default" || raw === "full" ? raw : null;
|
|
8386
|
+
}
|
|
8387
|
+
function normalizeAttachments(raw) {
|
|
8388
|
+
if (!Array.isArray(raw)) return [];
|
|
8389
|
+
const out = [];
|
|
8390
|
+
for (const item of raw) {
|
|
8391
|
+
if (!item || typeof item !== "object") continue;
|
|
8392
|
+
const row2 = item;
|
|
8393
|
+
if (typeof row2.id !== "string" || !row2.id.trim()) continue;
|
|
8394
|
+
if (typeof row2.name !== "string" || !row2.name) continue;
|
|
8395
|
+
if (typeof row2.content !== "string") continue;
|
|
8396
|
+
if (!ATTACHMENT_KINDS.has(row2.kind)) continue;
|
|
8397
|
+
const next = {
|
|
8398
|
+
id: row2.id,
|
|
8399
|
+
name: row2.name,
|
|
8400
|
+
kind: row2.kind,
|
|
8401
|
+
content: row2.content
|
|
8402
|
+
};
|
|
8403
|
+
if (typeof row2.path === "string" && row2.path) next.path = row2.path;
|
|
8404
|
+
if (typeof row2.previewDataUrl === "string" && row2.previewDataUrl) {
|
|
8405
|
+
next.previewDataUrl = row2.previewDataUrl;
|
|
8406
|
+
}
|
|
8407
|
+
out.push(next);
|
|
8408
|
+
}
|
|
8409
|
+
return out;
|
|
8410
|
+
}
|
|
8376
8411
|
function normalizeTask(raw) {
|
|
8377
8412
|
const when = normalizeWhen(raw.when);
|
|
8378
8413
|
const agent = raw.agent && isOrchestratorCapableAgent(raw.agent) ? raw.agent : null;
|
|
@@ -8385,6 +8420,11 @@ function normalizeTask(raw) {
|
|
|
8385
8420
|
threadId: raw.threadId?.trim() || null,
|
|
8386
8421
|
agent,
|
|
8387
8422
|
model: raw.model?.trim() || null,
|
|
8423
|
+
effort: normalizeThinkingEffort(raw.effort),
|
|
8424
|
+
fast: normalizeOptionalBool(raw.fast),
|
|
8425
|
+
planMode: normalizeOptionalBool(raw.planMode),
|
|
8426
|
+
autonomy: normalizeAutonomy2(raw.autonomy),
|
|
8427
|
+
attachments: normalizeAttachments(raw.attachments),
|
|
8388
8428
|
nextRunAt: raw.nextRunAt,
|
|
8389
8429
|
lastRunAt: raw.lastRunAt ?? null,
|
|
8390
8430
|
lastThreadId: raw.lastThreadId ?? null,
|
|
@@ -8431,6 +8471,11 @@ function buildTask(input, now) {
|
|
|
8431
8471
|
threadId: input.threadId?.trim() || null,
|
|
8432
8472
|
agent,
|
|
8433
8473
|
model: input.model?.trim() || null,
|
|
8474
|
+
effort: input.effort != null ? normalizeThinkingEffort(input.effort) : null,
|
|
8475
|
+
fast: normalizeOptionalBool(input.fast),
|
|
8476
|
+
planMode: normalizeOptionalBool(input.planMode),
|
|
8477
|
+
autonomy: normalizeAutonomy2(input.autonomy),
|
|
8478
|
+
attachments: normalizeAttachments(input.attachments),
|
|
8434
8479
|
nextRunAt,
|
|
8435
8480
|
lastRunAt: null,
|
|
8436
8481
|
lastThreadId: null,
|
|
@@ -8475,7 +8520,7 @@ function createSchedule(input) {
|
|
|
8475
8520
|
function updateSchedule(id, patch) {
|
|
8476
8521
|
const rows = readAll();
|
|
8477
8522
|
const idx = rows.findIndex((row2) => row2.id === id || id.length >= 8 && row2.id.startsWith(id));
|
|
8478
|
-
if (idx < 0) throw new Error(`
|
|
8523
|
+
if (idx < 0) throw new Error(`Automation not found: ${id}`);
|
|
8479
8524
|
const prev = rows[idx];
|
|
8480
8525
|
const when = patch.when ? normalizeWhen(patch.when) : prev.when;
|
|
8481
8526
|
const prompt = patch.prompt !== void 0 ? patch.prompt.trim() : prev.prompt;
|
|
@@ -8490,6 +8535,11 @@ function updateSchedule(id, patch) {
|
|
|
8490
8535
|
threadId: patch.threadId !== void 0 ? patch.threadId?.trim() || null : prev.threadId,
|
|
8491
8536
|
agent: patch.agent !== void 0 ? patch.agent ? coerceOrchestratorAgent(patch.agent) : null : prev.agent,
|
|
8492
8537
|
model: patch.model !== void 0 ? patch.model?.trim() || null : prev.model,
|
|
8538
|
+
effort: patch.effort !== void 0 ? normalizeThinkingEffort(patch.effort) : prev.effort,
|
|
8539
|
+
fast: patch.fast !== void 0 ? normalizeOptionalBool(patch.fast) : prev.fast,
|
|
8540
|
+
planMode: patch.planMode !== void 0 ? normalizeOptionalBool(patch.planMode) : prev.planMode,
|
|
8541
|
+
autonomy: patch.autonomy !== void 0 ? normalizeAutonomy2(patch.autonomy) : prev.autonomy,
|
|
8542
|
+
attachments: patch.attachments !== void 0 ? normalizeAttachments(patch.attachments) : prev.attachments,
|
|
8493
8543
|
nextRunAt: whenChanged ? computeNextRunAt(when).toISOString() : prev.nextRunAt,
|
|
8494
8544
|
lastError: whenChanged ? null : prev.lastError,
|
|
8495
8545
|
updatedAt: nowIso2()
|
|
@@ -8504,13 +8554,13 @@ function deleteSchedule(id) {
|
|
|
8504
8554
|
const next = rows.filter(
|
|
8505
8555
|
(row2) => row2.id !== id && !(id.length >= 8 && row2.id.startsWith(id))
|
|
8506
8556
|
);
|
|
8507
|
-
if (next.length === rows.length) throw new Error(`
|
|
8557
|
+
if (next.length === rows.length) throw new Error(`Automation not found: ${id}`);
|
|
8508
8558
|
writeAll(next);
|
|
8509
8559
|
}
|
|
8510
8560
|
function recordScheduleRun(id, result) {
|
|
8511
8561
|
const rows = readAll();
|
|
8512
8562
|
const idx = rows.findIndex((row2) => row2.id === id);
|
|
8513
|
-
if (idx < 0) throw new Error(`
|
|
8563
|
+
if (idx < 0) throw new Error(`Automation not found: ${id}`);
|
|
8514
8564
|
const prev = rows[idx];
|
|
8515
8565
|
const firedAt = result.firedAt ?? /* @__PURE__ */ new Date();
|
|
8516
8566
|
const next = {
|
|
@@ -8526,7 +8576,7 @@ function recordScheduleRun(id, result) {
|
|
|
8526
8576
|
writeAll(rows);
|
|
8527
8577
|
return next;
|
|
8528
8578
|
}
|
|
8529
|
-
var import_node_crypto8, import_node_fs15, import_node_path18, import_croner, DURATION_RE, UNIT_MS;
|
|
8579
|
+
var import_node_crypto8, import_node_fs15, import_node_path18, import_croner, DURATION_RE, UNIT_MS, ATTACHMENT_KINDS;
|
|
8530
8580
|
var init_schedules = __esm({
|
|
8531
8581
|
"src/store/schedules.ts"() {
|
|
8532
8582
|
"use strict";
|
|
@@ -8535,6 +8585,7 @@ var init_schedules = __esm({
|
|
|
8535
8585
|
import_node_path18 = require("path");
|
|
8536
8586
|
import_croner = require("croner");
|
|
8537
8587
|
init_orchestrator_capable();
|
|
8588
|
+
init_thinking_effort();
|
|
8538
8589
|
init_paths();
|
|
8539
8590
|
init_private_file();
|
|
8540
8591
|
init_app_settings();
|
|
@@ -8545,6 +8596,14 @@ var init_schedules = __esm({
|
|
|
8545
8596
|
h: 36e5,
|
|
8546
8597
|
d: 864e5
|
|
8547
8598
|
};
|
|
8599
|
+
ATTACHMENT_KINDS = /* @__PURE__ */ new Set([
|
|
8600
|
+
"transcript",
|
|
8601
|
+
"file",
|
|
8602
|
+
"issue",
|
|
8603
|
+
"workspace",
|
|
8604
|
+
"diff-comment",
|
|
8605
|
+
"code-ref"
|
|
8606
|
+
]);
|
|
8548
8607
|
}
|
|
8549
8608
|
});
|
|
8550
8609
|
|
|
@@ -8601,6 +8660,303 @@ var init_desktop_host = __esm({
|
|
|
8601
8660
|
}
|
|
8602
8661
|
});
|
|
8603
8662
|
|
|
8663
|
+
// src/paths/workspace-scratch.ts
|
|
8664
|
+
function attachmentsGitignoreBody() {
|
|
8665
|
+
return ATTACHMENTS_GITIGNORE;
|
|
8666
|
+
}
|
|
8667
|
+
function isWorkspaceScratchPath(relativePath) {
|
|
8668
|
+
const p = relativePath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
|
|
8669
|
+
return p === ATTACHMENTS_DIR || p.startsWith(`${ATTACHMENTS_DIR}/`) || p === CLI_DIR || p.startsWith(`${CLI_DIR}/`) || p === LEGACY_ATTACHMENTS_DIR || p.startsWith(`${LEGACY_ATTACHMENTS_DIR}/`) || p === ".sideboard" || p.startsWith(".sideboard/") || p === ".context" || p.startsWith(".context/");
|
|
8670
|
+
}
|
|
8671
|
+
var ATTACHMENTS_DIR, CLI_DIR, DETACHED_JOBS_DIR, LEGACY_ATTACHMENTS_DIR, LEGACY_DETACHED_JOBS_DIR, ATTACHMENTS_GITIGNORE;
|
|
8672
|
+
var init_workspace_scratch = __esm({
|
|
8673
|
+
"src/paths/workspace-scratch.ts"() {
|
|
8674
|
+
"use strict";
|
|
8675
|
+
ATTACHMENTS_DIR = ".context/attachments";
|
|
8676
|
+
CLI_DIR = ".context/cli";
|
|
8677
|
+
DETACHED_JOBS_DIR = ".context/.sideboard/detached-jobs";
|
|
8678
|
+
LEGACY_ATTACHMENTS_DIR = ".sideboard/attachments";
|
|
8679
|
+
LEGACY_DETACHED_JOBS_DIR = ".sideboard/detached-jobs";
|
|
8680
|
+
ATTACHMENTS_GITIGNORE = `# Sideboard / workspace attachments (local only)
|
|
8681
|
+
*
|
|
8682
|
+
!.gitignore
|
|
8683
|
+
`;
|
|
8684
|
+
}
|
|
8685
|
+
});
|
|
8686
|
+
|
|
8687
|
+
// src/composer/stage-files.ts
|
|
8688
|
+
function fileExtension(filePath) {
|
|
8689
|
+
const base = (0, import_node_path20.basename)(filePath).toLowerCase();
|
|
8690
|
+
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
8691
|
+
}
|
|
8692
|
+
function isImageFilePath(filePath) {
|
|
8693
|
+
return IMAGE_EXTENSIONS.has(fileExtension(filePath));
|
|
8694
|
+
}
|
|
8695
|
+
function imageMimeType(filePath) {
|
|
8696
|
+
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
8697
|
+
}
|
|
8698
|
+
function ensureAttachmentsDir(worktreePath) {
|
|
8699
|
+
const dir = (0, import_node_path20.join)(worktreePath, ATTACHMENTS_DIR);
|
|
8700
|
+
(0, import_node_fs17.mkdirSync)(dir, { recursive: true });
|
|
8701
|
+
const gi = (0, import_node_path20.join)(dir, ".gitignore");
|
|
8702
|
+
if (!(0, import_node_fs17.existsSync)(gi)) {
|
|
8703
|
+
(0, import_node_fs17.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
8704
|
+
}
|
|
8705
|
+
return dir;
|
|
8706
|
+
}
|
|
8707
|
+
function uniqueAttachmentName(dir, originalName) {
|
|
8708
|
+
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
8709
|
+
if (!(0, import_node_fs17.existsSync)((0, import_node_path20.join)(dir, safe))) return safe;
|
|
8710
|
+
const ext = (0, import_node_path20.extname)(safe);
|
|
8711
|
+
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
8712
|
+
for (let i = 1; i < 1e4; i++) {
|
|
8713
|
+
const candidate = `${stem}-${i}${ext}`;
|
|
8714
|
+
if (!(0, import_node_fs17.existsSync)((0, import_node_path20.join)(dir, candidate))) return candidate;
|
|
8715
|
+
}
|
|
8716
|
+
return `${stem}-${(0, import_node_crypto9.randomUUID)()}${ext}`;
|
|
8717
|
+
}
|
|
8718
|
+
function previewDataUrlFromBuf(filePath, buf) {
|
|
8719
|
+
if (!isImageFilePath(filePath)) return void 0;
|
|
8720
|
+
if (buf.length > MAX_PREVIEW_BYTES) return void 0;
|
|
8721
|
+
return `data:${imageMimeType(filePath)};base64,${buf.toString("base64")}`;
|
|
8722
|
+
}
|
|
8723
|
+
function attachmentFromBuffer(name, buf, opts) {
|
|
8724
|
+
const previewDataUrl = previewDataUrlFromBuf(name, buf);
|
|
8725
|
+
if (isImageFilePath(name)) {
|
|
8726
|
+
const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
|
|
8727
|
+
return {
|
|
8728
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
8729
|
+
name,
|
|
8730
|
+
kind: "file",
|
|
8731
|
+
path: opts.path,
|
|
8732
|
+
previewDataUrl,
|
|
8733
|
+
content: [
|
|
8734
|
+
`Image attached: ${pathHint}`,
|
|
8735
|
+
opts.path ? `Use the Read tool on \`${opts.path}\` to view this image.` : "The image is shown in the composer; copy it into the worktree if you need to inspect pixels."
|
|
8736
|
+
].join("\n")
|
|
8737
|
+
};
|
|
8738
|
+
}
|
|
8739
|
+
if (buf.length > MAX_INLINE_BYTES) {
|
|
8740
|
+
return {
|
|
8741
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
8742
|
+
name,
|
|
8743
|
+
kind: "file",
|
|
8744
|
+
path: opts.path,
|
|
8745
|
+
content: opts.path ? `(file too large to attach inline: \`${opts.path}\`, ${buf.length} bytes \u2014 use the Read tool)` : `(file too large to attach inline: ${opts.sourceLabel || name}, ${buf.length} bytes)`
|
|
8746
|
+
};
|
|
8747
|
+
}
|
|
8748
|
+
if (buf.includes(0)) {
|
|
8749
|
+
return {
|
|
8750
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
8751
|
+
name,
|
|
8752
|
+
kind: "file",
|
|
8753
|
+
path: opts.path,
|
|
8754
|
+
content: opts.path ? `(binary file at \`${opts.path}\` \u2014 use tools to inspect)` : `(binary file attached by path only: ${opts.sourceLabel || name})`
|
|
8755
|
+
};
|
|
8756
|
+
}
|
|
8757
|
+
return {
|
|
8758
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
8759
|
+
name,
|
|
8760
|
+
kind: "file",
|
|
8761
|
+
path: opts.path,
|
|
8762
|
+
content: buf.toString("utf8")
|
|
8763
|
+
};
|
|
8764
|
+
}
|
|
8765
|
+
function attachmentFromAbsolutePath(absolutePath) {
|
|
8766
|
+
const name = (0, import_node_path20.basename)(absolutePath);
|
|
8767
|
+
try {
|
|
8768
|
+
const st = (0, import_node_fs17.statSync)(absolutePath);
|
|
8769
|
+
if (!st.isFile()) {
|
|
8770
|
+
return {
|
|
8771
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
8772
|
+
name,
|
|
8773
|
+
kind: "file",
|
|
8774
|
+
content: `(not a file: ${absolutePath})`
|
|
8775
|
+
};
|
|
8776
|
+
}
|
|
8777
|
+
const buf = (0, import_node_fs17.readFileSync)(absolutePath);
|
|
8778
|
+
return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
|
|
8779
|
+
} catch (err) {
|
|
8780
|
+
return {
|
|
8781
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
8782
|
+
name,
|
|
8783
|
+
kind: "file",
|
|
8784
|
+
content: `(could not read ${absolutePath}: ${err instanceof Error ? err.message : String(err)})`
|
|
8785
|
+
};
|
|
8786
|
+
}
|
|
8787
|
+
}
|
|
8788
|
+
function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
8789
|
+
if (absolutePaths.length === 0) return [];
|
|
8790
|
+
const dir = ensureAttachmentsDir(worktreePath);
|
|
8791
|
+
const out = [];
|
|
8792
|
+
for (const abs of absolutePaths) {
|
|
8793
|
+
const originalName = (0, import_node_path20.basename)(abs);
|
|
8794
|
+
try {
|
|
8795
|
+
const st = (0, import_node_fs17.statSync)(abs);
|
|
8796
|
+
if (!st.isFile()) continue;
|
|
8797
|
+
const name = uniqueAttachmentName(dir, originalName);
|
|
8798
|
+
const destAbs = (0, import_node_path20.join)(dir, name);
|
|
8799
|
+
(0, import_node_fs17.copyFileSync)(abs, destAbs);
|
|
8800
|
+
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
8801
|
+
const buf = (0, import_node_fs17.readFileSync)(destAbs);
|
|
8802
|
+
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
8803
|
+
} catch (err) {
|
|
8804
|
+
out.push({
|
|
8805
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
8806
|
+
name: originalName,
|
|
8807
|
+
kind: "file",
|
|
8808
|
+
content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
|
|
8809
|
+
});
|
|
8810
|
+
}
|
|
8811
|
+
}
|
|
8812
|
+
return out;
|
|
8813
|
+
}
|
|
8814
|
+
function stageBuffersAsAttachments(worktreePath, buffers2) {
|
|
8815
|
+
if (buffers2.length === 0) return [];
|
|
8816
|
+
const dir = ensureAttachmentsDir(worktreePath);
|
|
8817
|
+
const out = [];
|
|
8818
|
+
for (const item of buffers2) {
|
|
8819
|
+
const originalName = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
8820
|
+
try {
|
|
8821
|
+
const buf = Buffer.from(item.dataBase64, "base64");
|
|
8822
|
+
const name = uniqueAttachmentName(dir, originalName);
|
|
8823
|
+
const destAbs = (0, import_node_path20.join)(dir, name);
|
|
8824
|
+
(0, import_node_fs17.writeFileSync)(destAbs, buf);
|
|
8825
|
+
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
8826
|
+
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
8827
|
+
} catch (err) {
|
|
8828
|
+
out.push({
|
|
8829
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
8830
|
+
name: originalName,
|
|
8831
|
+
kind: "file",
|
|
8832
|
+
content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
|
|
8833
|
+
});
|
|
8834
|
+
}
|
|
8835
|
+
}
|
|
8836
|
+
return out;
|
|
8837
|
+
}
|
|
8838
|
+
function attachmentsFromBuffers(buffers2) {
|
|
8839
|
+
return buffers2.map((item) => {
|
|
8840
|
+
const name = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
8841
|
+
try {
|
|
8842
|
+
const buf = Buffer.from(item.dataBase64, "base64");
|
|
8843
|
+
return attachmentFromBuffer(name, buf, { sourceLabel: name });
|
|
8844
|
+
} catch (err) {
|
|
8845
|
+
return {
|
|
8846
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
8847
|
+
name,
|
|
8848
|
+
kind: "file",
|
|
8849
|
+
content: `(could not attach ${name}: ${err instanceof Error ? err.message : String(err)})`
|
|
8850
|
+
};
|
|
8851
|
+
}
|
|
8852
|
+
});
|
|
8853
|
+
}
|
|
8854
|
+
function isWorktreeRelativePath(p) {
|
|
8855
|
+
if (!p || p.includes("..")) return false;
|
|
8856
|
+
if (p.startsWith("/")) return false;
|
|
8857
|
+
if (/^[A-Za-z]:[\\/]/.test(p)) return false;
|
|
8858
|
+
return true;
|
|
8859
|
+
}
|
|
8860
|
+
function dataUrlToBase64(url) {
|
|
8861
|
+
if (!url) return null;
|
|
8862
|
+
const m = /^data:[^;]+;base64,(.+)$/s.exec(url);
|
|
8863
|
+
return m?.[1] ?? null;
|
|
8864
|
+
}
|
|
8865
|
+
function persistPendingFileAttachments(worktreePath, attachments) {
|
|
8866
|
+
if (attachments.length === 0) return attachments;
|
|
8867
|
+
const keep = [];
|
|
8868
|
+
const buffers2 = [];
|
|
8869
|
+
for (const att of attachments) {
|
|
8870
|
+
if (att.kind !== "file") {
|
|
8871
|
+
keep.push(att);
|
|
8872
|
+
continue;
|
|
8873
|
+
}
|
|
8874
|
+
if (att.path && isWorktreeRelativePath(att.path)) {
|
|
8875
|
+
keep.push(att);
|
|
8876
|
+
continue;
|
|
8877
|
+
}
|
|
8878
|
+
const fromPreview = dataUrlToBase64(att.previewDataUrl);
|
|
8879
|
+
if (fromPreview) {
|
|
8880
|
+
buffers2.push({ name: att.name, dataBase64: fromPreview });
|
|
8881
|
+
continue;
|
|
8882
|
+
}
|
|
8883
|
+
if (att.content && !IMAGE_HINT_RE.test(att.content) && !PLACEHOLDER_CONTENT_RE.test(att.content)) {
|
|
8884
|
+
buffers2.push({
|
|
8885
|
+
name: att.name,
|
|
8886
|
+
dataBase64: Buffer.from(att.content, "utf8").toString("base64")
|
|
8887
|
+
});
|
|
8888
|
+
continue;
|
|
8889
|
+
}
|
|
8890
|
+
keep.push(att);
|
|
8891
|
+
}
|
|
8892
|
+
if (buffers2.length === 0) return attachments;
|
|
8893
|
+
return [...keep, ...stageBuffersAsAttachments(worktreePath, buffers2)];
|
|
8894
|
+
}
|
|
8895
|
+
function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
8896
|
+
const out = [];
|
|
8897
|
+
for (const rel of relativePaths) {
|
|
8898
|
+
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
8899
|
+
out.push({
|
|
8900
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
8901
|
+
name: (0, import_node_path20.basename)(rel) || "file",
|
|
8902
|
+
kind: "file",
|
|
8903
|
+
content: `(invalid path: ${rel})`
|
|
8904
|
+
});
|
|
8905
|
+
continue;
|
|
8906
|
+
}
|
|
8907
|
+
const name = (0, import_node_path20.basename)(rel);
|
|
8908
|
+
try {
|
|
8909
|
+
const abs = (0, import_node_path20.join)(worktreePath, rel);
|
|
8910
|
+
const st = (0, import_node_fs17.statSync)(abs);
|
|
8911
|
+
if (!st.isFile()) continue;
|
|
8912
|
+
const buf = (0, import_node_fs17.readFileSync)(abs);
|
|
8913
|
+
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
8914
|
+
} catch (err) {
|
|
8915
|
+
out.push({
|
|
8916
|
+
id: (0, import_node_crypto9.randomUUID)(),
|
|
8917
|
+
name,
|
|
8918
|
+
kind: "file",
|
|
8919
|
+
content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
|
|
8920
|
+
});
|
|
8921
|
+
}
|
|
8922
|
+
}
|
|
8923
|
+
return out;
|
|
8924
|
+
}
|
|
8925
|
+
var import_node_fs17, import_node_path20, import_node_crypto9, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
|
|
8926
|
+
var init_stage_files = __esm({
|
|
8927
|
+
"src/composer/stage-files.ts"() {
|
|
8928
|
+
"use strict";
|
|
8929
|
+
import_node_fs17 = require("fs");
|
|
8930
|
+
import_node_path20 = require("path");
|
|
8931
|
+
import_node_crypto9 = require("crypto");
|
|
8932
|
+
init_workspace_scratch();
|
|
8933
|
+
IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
8934
|
+
"png",
|
|
8935
|
+
"jpg",
|
|
8936
|
+
"jpeg",
|
|
8937
|
+
"gif",
|
|
8938
|
+
"webp",
|
|
8939
|
+
"svg",
|
|
8940
|
+
"bmp",
|
|
8941
|
+
"ico"
|
|
8942
|
+
]);
|
|
8943
|
+
IMAGE_MIME_BY_EXT = {
|
|
8944
|
+
png: "image/png",
|
|
8945
|
+
jpg: "image/jpeg",
|
|
8946
|
+
jpeg: "image/jpeg",
|
|
8947
|
+
gif: "image/gif",
|
|
8948
|
+
webp: "image/webp",
|
|
8949
|
+
svg: "image/svg+xml",
|
|
8950
|
+
bmp: "image/bmp",
|
|
8951
|
+
ico: "image/x-icon"
|
|
8952
|
+
};
|
|
8953
|
+
MAX_INLINE_BYTES = 4e5;
|
|
8954
|
+
MAX_PREVIEW_BYTES = 5e6;
|
|
8955
|
+
IMAGE_HINT_RE = /^Image attached:/;
|
|
8956
|
+
PLACEHOLDER_CONTENT_RE = /^\((could not |file too large|binary file|not a file|invalid path)/;
|
|
8957
|
+
}
|
|
8958
|
+
});
|
|
8959
|
+
|
|
8604
8960
|
// src/threads/injected-notices.ts
|
|
8605
8961
|
function isSlackExternalReplyText(text7) {
|
|
8606
8962
|
return text7.startsWith("Slack reply from ") && text7.includes("not a command");
|
|
@@ -8752,17 +9108,17 @@ var init_wait_for_turn = __esm({
|
|
|
8752
9108
|
|
|
8753
9109
|
// src/agents/path.ts
|
|
8754
9110
|
function prependPathDir(env, dir) {
|
|
8755
|
-
if (!dir || !(0,
|
|
9111
|
+
if (!dir || !(0, import_node_fs18.existsSync)(dir)) return;
|
|
8756
9112
|
const current = env.PATH ?? "";
|
|
8757
|
-
const parts = current.split(
|
|
9113
|
+
const parts = current.split(import_node_path21.delimiter).filter(Boolean);
|
|
8758
9114
|
if (parts.includes(dir)) {
|
|
8759
9115
|
env.PATH = current;
|
|
8760
9116
|
return;
|
|
8761
9117
|
}
|
|
8762
|
-
env.PATH = [dir, ...parts].join(
|
|
9118
|
+
env.PATH = [dir, ...parts].join(import_node_path21.delimiter);
|
|
8763
9119
|
}
|
|
8764
9120
|
function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os6.homedir)()) {
|
|
8765
|
-
return (0,
|
|
9121
|
+
return (0, import_node_path21.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
|
|
8766
9122
|
}
|
|
8767
9123
|
function isConductorBundledCli(filePath) {
|
|
8768
9124
|
const p = (filePath ?? "").replace(/\\/g, "/");
|
|
@@ -8771,21 +9127,21 @@ function isConductorBundledCli(filePath) {
|
|
|
8771
9127
|
function ensureAgentPath(env = process.env) {
|
|
8772
9128
|
const home = env.HOME || env.USERPROFILE || (0, import_node_os6.homedir)();
|
|
8773
9129
|
const current = env.PATH ?? "";
|
|
8774
|
-
const parts = current.split(
|
|
9130
|
+
const parts = current.split(import_node_path21.delimiter).filter(Boolean);
|
|
8775
9131
|
const seen = new Set(parts);
|
|
8776
9132
|
const extras = [
|
|
8777
|
-
...EXTRA_BIN_DIRS.map((rel) => (0,
|
|
9133
|
+
...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path21.join)(home, rel)),
|
|
8778
9134
|
"/opt/homebrew/bin",
|
|
8779
9135
|
"/usr/local/bin",
|
|
8780
9136
|
// Keep after Homebrew/npm so a user-installed CLI still wins.
|
|
8781
9137
|
conductorBundledBinDir(home)
|
|
8782
9138
|
];
|
|
8783
9139
|
for (const dir of extras.reverse()) {
|
|
8784
|
-
if (!dir || seen.has(dir) || !(0,
|
|
9140
|
+
if (!dir || seen.has(dir) || !(0, import_node_fs18.existsSync)(dir)) continue;
|
|
8785
9141
|
parts.unshift(dir);
|
|
8786
9142
|
seen.add(dir);
|
|
8787
9143
|
}
|
|
8788
|
-
const next = parts.join(
|
|
9144
|
+
const next = parts.join(import_node_path21.delimiter);
|
|
8789
9145
|
env.PATH = next;
|
|
8790
9146
|
return next;
|
|
8791
9147
|
}
|
|
@@ -8793,7 +9149,7 @@ function enrichPathWithNpmGlobalBin(env = process.env) {
|
|
|
8793
9149
|
ensureAgentPath(env);
|
|
8794
9150
|
const prefix = npmGlobalPrefix(env);
|
|
8795
9151
|
if (prefix) {
|
|
8796
|
-
const binDir = process.platform === "win32" ? prefix : (0,
|
|
9152
|
+
const binDir = process.platform === "win32" ? prefix : (0, import_node_path21.join)(prefix, "bin");
|
|
8797
9153
|
prependPathDir(env, binDir);
|
|
8798
9154
|
}
|
|
8799
9155
|
return env.PATH ?? "";
|
|
@@ -8814,8 +9170,8 @@ function npmGlobalPrefix(env = process.env) {
|
|
|
8814
9170
|
function npmGlobalNodeModules(env = process.env) {
|
|
8815
9171
|
const prefix = npmGlobalPrefix(env);
|
|
8816
9172
|
if (!prefix) return null;
|
|
8817
|
-
const dir = process.platform === "win32" ? (0,
|
|
8818
|
-
return (0,
|
|
9173
|
+
const dir = process.platform === "win32" ? (0, import_node_path21.join)(prefix, "node_modules") : (0, import_node_path21.join)(prefix, "lib", "node_modules");
|
|
9174
|
+
return (0, import_node_fs18.existsSync)(dir) ? dir : null;
|
|
8819
9175
|
}
|
|
8820
9176
|
function posixShellSingleQuote(value) {
|
|
8821
9177
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -8838,14 +9194,14 @@ function withExportedPath(command, pathValue) {
|
|
|
8838
9194
|
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
8839
9195
|
return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
|
|
8840
9196
|
}
|
|
8841
|
-
var
|
|
9197
|
+
var import_node_fs18, import_node_child_process3, import_node_os6, import_node_path21, EXTRA_BIN_DIRS;
|
|
8842
9198
|
var init_path = __esm({
|
|
8843
9199
|
"src/agents/path.ts"() {
|
|
8844
9200
|
"use strict";
|
|
8845
|
-
|
|
9201
|
+
import_node_fs18 = require("fs");
|
|
8846
9202
|
import_node_child_process3 = require("child_process");
|
|
8847
9203
|
import_node_os6 = require("os");
|
|
8848
|
-
|
|
9204
|
+
import_node_path21 = require("path");
|
|
8849
9205
|
EXTRA_BIN_DIRS = [
|
|
8850
9206
|
".local/bin",
|
|
8851
9207
|
".cargo/bin",
|
|
@@ -8866,23 +9222,23 @@ var init_path = __esm({
|
|
|
8866
9222
|
function githubAgentAuthDir() {
|
|
8867
9223
|
const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
|
|
8868
9224
|
if (override) return override;
|
|
8869
|
-
return (0,
|
|
9225
|
+
return (0, import_node_path22.join)((0, import_node_os7.homedir)(), ".sideboard-git-auth");
|
|
8870
9226
|
}
|
|
8871
9227
|
function githubCredentialStorePath() {
|
|
8872
|
-
return (0,
|
|
9228
|
+
return (0, import_node_path22.join)(githubAgentAuthDir(), "git-credentials");
|
|
8873
9229
|
}
|
|
8874
9230
|
function githubGhConfigDir() {
|
|
8875
|
-
return (0,
|
|
9231
|
+
return (0, import_node_path22.join)(githubAgentAuthDir(), "gh");
|
|
8876
9232
|
}
|
|
8877
9233
|
function writePrivateFile2(file, body) {
|
|
8878
|
-
(0,
|
|
9234
|
+
(0, import_node_fs19.mkdirSync)((0, import_node_path22.dirname)(file), { recursive: true, mode: 448 });
|
|
8879
9235
|
try {
|
|
8880
|
-
(0,
|
|
9236
|
+
(0, import_node_fs19.chmodSync)((0, import_node_path22.dirname)(file), 448);
|
|
8881
9237
|
} catch {
|
|
8882
9238
|
}
|
|
8883
|
-
(0,
|
|
9239
|
+
(0, import_node_fs19.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
|
|
8884
9240
|
try {
|
|
8885
|
-
(0,
|
|
9241
|
+
(0, import_node_fs19.chmodSync)(file, 384);
|
|
8886
9242
|
} catch {
|
|
8887
9243
|
}
|
|
8888
9244
|
}
|
|
@@ -8907,19 +9263,19 @@ function materializeGithubAgentAuth(token, user) {
|
|
|
8907
9263
|
const trimmed = token.trim();
|
|
8908
9264
|
if (!trimmed) return;
|
|
8909
9265
|
const root = githubAgentAuthDir();
|
|
8910
|
-
(0,
|
|
9266
|
+
(0, import_node_fs19.mkdirSync)(root, { recursive: true, mode: 448 });
|
|
8911
9267
|
try {
|
|
8912
|
-
(0,
|
|
9268
|
+
(0, import_node_fs19.chmodSync)(root, 448);
|
|
8913
9269
|
} catch {
|
|
8914
9270
|
}
|
|
8915
9271
|
writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
|
|
8916
9272
|
const ghDir = githubGhConfigDir();
|
|
8917
|
-
(0,
|
|
8918
|
-
writePrivateFile2((0,
|
|
8919
|
-
writePrivateFile2((0,
|
|
9273
|
+
(0, import_node_fs19.mkdirSync)(ghDir, { recursive: true, mode: 448 });
|
|
9274
|
+
writePrivateFile2((0, import_node_path22.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
|
|
9275
|
+
writePrivateFile2((0, import_node_path22.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
|
|
8920
9276
|
}
|
|
8921
9277
|
function githubAgentAuthReady() {
|
|
8922
|
-
return (0,
|
|
9278
|
+
return (0, import_node_fs19.existsSync)(githubCredentialStorePath()) && (0, import_node_fs19.existsSync)((0, import_node_path22.join)(githubGhConfigDir(), "hosts.yml"));
|
|
8923
9279
|
}
|
|
8924
9280
|
function githubCredentialHelperGitConfig() {
|
|
8925
9281
|
const file = githubCredentialStorePath();
|
|
@@ -8934,13 +9290,13 @@ function githubGhConfigEnv() {
|
|
|
8934
9290
|
GH_PROMPT_DISABLED: "1"
|
|
8935
9291
|
};
|
|
8936
9292
|
}
|
|
8937
|
-
var
|
|
9293
|
+
var import_node_fs19, import_node_os7, import_node_path22;
|
|
8938
9294
|
var init_github_agent_auth = __esm({
|
|
8939
9295
|
"src/git/github-agent-auth.ts"() {
|
|
8940
9296
|
"use strict";
|
|
8941
|
-
|
|
9297
|
+
import_node_fs19 = require("fs");
|
|
8942
9298
|
import_node_os7 = require("os");
|
|
8943
|
-
|
|
9299
|
+
import_node_path22 = require("path");
|
|
8944
9300
|
}
|
|
8945
9301
|
});
|
|
8946
9302
|
|
|
@@ -8949,11 +9305,11 @@ function isIndexLockError(text7) {
|
|
|
8949
9305
|
return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text7);
|
|
8950
9306
|
}
|
|
8951
9307
|
function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
|
|
8952
|
-
const lockPath = (0,
|
|
9308
|
+
const lockPath = (0, import_node_path23.join)(gitDir, "index.lock");
|
|
8953
9309
|
try {
|
|
8954
|
-
if (!(0,
|
|
8955
|
-
if (now - (0,
|
|
8956
|
-
(0,
|
|
9310
|
+
if (!(0, import_node_fs20.existsSync)(lockPath)) return null;
|
|
9311
|
+
if (now - (0, import_node_fs20.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
|
|
9312
|
+
(0, import_node_fs20.unlinkSync)(lockPath);
|
|
8957
9313
|
return lockPath;
|
|
8958
9314
|
} catch {
|
|
8959
9315
|
return null;
|
|
@@ -8968,12 +9324,12 @@ function clearStaleIndexLocks(gitDirs, maxAgeMs = STALE_INDEX_LOCK_MS) {
|
|
|
8968
9324
|
}
|
|
8969
9325
|
return removed;
|
|
8970
9326
|
}
|
|
8971
|
-
var
|
|
9327
|
+
var import_node_fs20, import_node_path23, STALE_INDEX_LOCK_MS;
|
|
8972
9328
|
var init_stale_lock = __esm({
|
|
8973
9329
|
"src/git/stale-lock.ts"() {
|
|
8974
9330
|
"use strict";
|
|
8975
|
-
|
|
8976
|
-
|
|
9331
|
+
import_node_fs20 = require("fs");
|
|
9332
|
+
import_node_path23 = require("path");
|
|
8977
9333
|
STALE_INDEX_LOCK_MS = 2e4;
|
|
8978
9334
|
}
|
|
8979
9335
|
});
|
|
@@ -9224,11 +9580,11 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
|
|
|
9224
9580
|
if (gitDir.exitCode !== 0) return;
|
|
9225
9581
|
const dir = gitDir.stdout.trim();
|
|
9226
9582
|
if (!dir) return;
|
|
9227
|
-
const excludePath = (0,
|
|
9228
|
-
(0,
|
|
9583
|
+
const excludePath = (0, import_node_path24.join)(dir, "info", "exclude");
|
|
9584
|
+
(0, import_node_fs21.mkdirSync)((0, import_node_path24.dirname)(excludePath), { recursive: true });
|
|
9229
9585
|
let body = "";
|
|
9230
9586
|
try {
|
|
9231
|
-
body = (0,
|
|
9587
|
+
body = (0, import_node_fs21.readFileSync)(excludePath, "utf8");
|
|
9232
9588
|
} catch {
|
|
9233
9589
|
body = "";
|
|
9234
9590
|
}
|
|
@@ -9244,7 +9600,7 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
|
|
|
9244
9600
|
` : body;
|
|
9245
9601
|
const header = body.includes(EXCLUDE_COMMENT) ? "" : `${EXCLUDE_COMMENT}
|
|
9246
9602
|
`;
|
|
9247
|
-
(0,
|
|
9603
|
+
(0, import_node_fs21.writeFileSync)(excludePath, `${prefix}${header}${missing.join("\n")}
|
|
9248
9604
|
`, "utf8");
|
|
9249
9605
|
}
|
|
9250
9606
|
const listed = await git(["ls-files", "-z", "--", ".sideboard"], worktreePath, {
|
|
@@ -9259,12 +9615,12 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
|
|
|
9259
9615
|
timeoutMs: 8e3
|
|
9260
9616
|
});
|
|
9261
9617
|
}
|
|
9262
|
-
var
|
|
9618
|
+
var import_node_fs21, import_node_path24, WORKTREE_SIDEBOARD_EXCLUDE, WORKTREE_CONTEXT_EXCLUDE, EXCLUDE_COMMENT;
|
|
9263
9619
|
var init_worktree_exclude = __esm({
|
|
9264
9620
|
"src/git/worktree-exclude.ts"() {
|
|
9265
9621
|
"use strict";
|
|
9266
|
-
|
|
9267
|
-
|
|
9622
|
+
import_node_fs21 = require("fs");
|
|
9623
|
+
import_node_path24 = require("path");
|
|
9268
9624
|
init_run();
|
|
9269
9625
|
WORKTREE_SIDEBOARD_EXCLUDE = ".sideboard/";
|
|
9270
9626
|
WORKTREE_CONTEXT_EXCLUDE = ".context/";
|
|
@@ -9385,7 +9741,7 @@ async function warmGithubAgentAuth(opts) {
|
|
|
9385
9741
|
}
|
|
9386
9742
|
function normalizeWritableRoot(raw) {
|
|
9387
9743
|
const trimmed = raw.trim().replace(/\/+$/, "");
|
|
9388
|
-
return trimmed && (0,
|
|
9744
|
+
return trimmed && (0, import_node_path25.isAbsolute)(trimmed) ? trimmed : null;
|
|
9389
9745
|
}
|
|
9390
9746
|
async function resolveCodexGitWritableRoots(cwd) {
|
|
9391
9747
|
const roots = /* @__PURE__ */ new Set();
|
|
@@ -9463,11 +9819,11 @@ function formatGitAuthModeDirective(mode) {
|
|
|
9463
9819
|
].join("\n");
|
|
9464
9820
|
}
|
|
9465
9821
|
}
|
|
9466
|
-
var
|
|
9822
|
+
var import_node_path25, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
|
|
9467
9823
|
var init_git_auth_mode = __esm({
|
|
9468
9824
|
"src/git/git-auth-mode.ts"() {
|
|
9469
9825
|
"use strict";
|
|
9470
|
-
|
|
9826
|
+
import_node_path25 = require("path");
|
|
9471
9827
|
init_app_settings();
|
|
9472
9828
|
init_github_agent_auth();
|
|
9473
9829
|
init_run();
|
|
@@ -10096,46 +10452,22 @@ var init_stack = __esm({
|
|
|
10096
10452
|
}
|
|
10097
10453
|
});
|
|
10098
10454
|
|
|
10099
|
-
// src/paths/workspace-scratch.ts
|
|
10100
|
-
function attachmentsGitignoreBody() {
|
|
10101
|
-
return ATTACHMENTS_GITIGNORE;
|
|
10102
|
-
}
|
|
10103
|
-
function isWorkspaceScratchPath(relativePath) {
|
|
10104
|
-
const p = relativePath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
|
|
10105
|
-
return p === ATTACHMENTS_DIR || p.startsWith(`${ATTACHMENTS_DIR}/`) || p === CLI_DIR || p.startsWith(`${CLI_DIR}/`) || p === LEGACY_ATTACHMENTS_DIR || p.startsWith(`${LEGACY_ATTACHMENTS_DIR}/`) || p === ".sideboard" || p.startsWith(".sideboard/") || p === ".context" || p.startsWith(".context/");
|
|
10106
|
-
}
|
|
10107
|
-
var ATTACHMENTS_DIR, CLI_DIR, DETACHED_JOBS_DIR, LEGACY_ATTACHMENTS_DIR, LEGACY_DETACHED_JOBS_DIR, ATTACHMENTS_GITIGNORE;
|
|
10108
|
-
var init_workspace_scratch = __esm({
|
|
10109
|
-
"src/paths/workspace-scratch.ts"() {
|
|
10110
|
-
"use strict";
|
|
10111
|
-
ATTACHMENTS_DIR = ".context/attachments";
|
|
10112
|
-
CLI_DIR = ".context/cli";
|
|
10113
|
-
DETACHED_JOBS_DIR = ".context/.sideboard/detached-jobs";
|
|
10114
|
-
LEGACY_ATTACHMENTS_DIR = ".sideboard/attachments";
|
|
10115
|
-
LEGACY_DETACHED_JOBS_DIR = ".sideboard/detached-jobs";
|
|
10116
|
-
ATTACHMENTS_GITIGNORE = `# Sideboard / workspace attachments (local only)
|
|
10117
|
-
*
|
|
10118
|
-
!.gitignore
|
|
10119
|
-
`;
|
|
10120
|
-
}
|
|
10121
|
-
});
|
|
10122
|
-
|
|
10123
10455
|
// src/git/team-slugs.ts
|
|
10124
10456
|
function sameRepoPath2(a, b) {
|
|
10125
10457
|
return normalizeWorktreePath(a) === normalizeWorktreePath(b);
|
|
10126
10458
|
}
|
|
10127
10459
|
function listLocalPlaceholderBranchSlugs(repoPath) {
|
|
10128
10460
|
const slugs = [];
|
|
10129
|
-
const headsDir = (0,
|
|
10130
|
-
const threadDir = (0,
|
|
10461
|
+
const headsDir = (0, import_node_path26.join)(repoPath, ".git", "refs", "heads");
|
|
10462
|
+
const threadDir = (0, import_node_path26.join)(headsDir, "thread");
|
|
10131
10463
|
try {
|
|
10132
|
-
if ((0,
|
|
10133
|
-
for (const name of (0,
|
|
10464
|
+
if ((0, import_node_fs22.existsSync)(threadDir)) {
|
|
10465
|
+
for (const name of (0, import_node_fs22.readdirSync)(threadDir)) {
|
|
10134
10466
|
if (!name.startsWith(".")) slugs.push(normalizeTakenSlug(name));
|
|
10135
10467
|
}
|
|
10136
10468
|
}
|
|
10137
|
-
if ((0,
|
|
10138
|
-
for (const entry of (0,
|
|
10469
|
+
if ((0, import_node_fs22.existsSync)(headsDir)) {
|
|
10470
|
+
for (const entry of (0, import_node_fs22.readdirSync)(headsDir, { withFileTypes: true })) {
|
|
10139
10471
|
if (entry.isFile() && !entry.name.startsWith(".")) {
|
|
10140
10472
|
slugs.push(normalizeTakenSlug(entry.name));
|
|
10141
10473
|
}
|
|
@@ -10149,8 +10481,8 @@ function listLocalPlaceholderBranchSlugs(repoPath) {
|
|
|
10149
10481
|
function collectTakenTeamSlugs(repoPath) {
|
|
10150
10482
|
const taken = /* @__PURE__ */ new Set();
|
|
10151
10483
|
const root = worktreesRoot(repoPath);
|
|
10152
|
-
if ((0,
|
|
10153
|
-
for (const entry of (0,
|
|
10484
|
+
if ((0, import_node_fs22.existsSync)(root)) {
|
|
10485
|
+
for (const entry of (0, import_node_fs22.readdirSync)(root, { withFileTypes: true })) {
|
|
10154
10486
|
if (entry.isDirectory() && entry.name !== ".DS_Store") {
|
|
10155
10487
|
for (const slug of takenSlugsFromThread({ worktreePath: entry.name })) {
|
|
10156
10488
|
taken.add(slug);
|
|
@@ -10175,18 +10507,18 @@ function allocateTeamSlug(repoPath) {
|
|
|
10175
10507
|
const taken = collectTakenTeamSlugs(repoPath);
|
|
10176
10508
|
for (let attempt = 0; attempt < 32; attempt++) {
|
|
10177
10509
|
const team = allocateTeamName(taken);
|
|
10178
|
-
const path2 = (0,
|
|
10179
|
-
if (!(0,
|
|
10510
|
+
const path2 = (0, import_node_path26.join)(worktreesRoot(repoPath), team.slug);
|
|
10511
|
+
if (!(0, import_node_fs22.existsSync)(path2)) return team;
|
|
10180
10512
|
taken.add(team.slug);
|
|
10181
10513
|
}
|
|
10182
10514
|
throw new Error("No available soccer team worktree directories left");
|
|
10183
10515
|
}
|
|
10184
|
-
var
|
|
10516
|
+
var import_node_fs22, import_node_path26;
|
|
10185
10517
|
var init_team_slugs = __esm({
|
|
10186
10518
|
"src/git/team-slugs.ts"() {
|
|
10187
10519
|
"use strict";
|
|
10188
|
-
|
|
10189
|
-
|
|
10520
|
+
import_node_fs22 = require("fs");
|
|
10521
|
+
import_node_path26 = require("path");
|
|
10190
10522
|
init_paths();
|
|
10191
10523
|
init_thread_store();
|
|
10192
10524
|
init_teams();
|
|
@@ -10302,7 +10634,7 @@ async function resolveRepoRoot(cwd) {
|
|
|
10302
10634
|
}
|
|
10303
10635
|
function canonicalizeRepoPath(path2) {
|
|
10304
10636
|
try {
|
|
10305
|
-
return (0,
|
|
10637
|
+
return (0, import_node_fs23.realpathSync)(path2);
|
|
10306
10638
|
} catch {
|
|
10307
10639
|
return path2.replace(/\/+$/, "");
|
|
10308
10640
|
}
|
|
@@ -11220,8 +11552,8 @@ async function refreshOriginAndMaybeFastForwardMain(repoPath, sourceRef) {
|
|
|
11220
11552
|
}
|
|
11221
11553
|
async function createThreadWorktree(opts) {
|
|
11222
11554
|
let branchName = opts.slug;
|
|
11223
|
-
const worktreePath = (0,
|
|
11224
|
-
if ((0,
|
|
11555
|
+
const worktreePath = (0, import_node_path27.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
11556
|
+
if ((0, import_node_fs23.existsSync)(worktreePath)) {
|
|
11225
11557
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
11226
11558
|
}
|
|
11227
11559
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -11262,8 +11594,8 @@ ${add.stdout}`;
|
|
|
11262
11594
|
async function createExistingBranchWorktree(opts) {
|
|
11263
11595
|
const branchName = opts.branchName.trim();
|
|
11264
11596
|
if (!branchName) throw new Error("branch name required");
|
|
11265
|
-
const worktreePath = (0,
|
|
11266
|
-
if ((0,
|
|
11597
|
+
const worktreePath = (0, import_node_path27.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
11598
|
+
if ((0, import_node_fs23.existsSync)(worktreePath)) {
|
|
11267
11599
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
11268
11600
|
}
|
|
11269
11601
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -11602,11 +11934,11 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
11602
11934
|
const headRef = ghHeadRef(slug, opts.head);
|
|
11603
11935
|
const branchOnly = opts.head.trim().replace(/^refs\/heads\//, "");
|
|
11604
11936
|
const bodyText = clampGithubPrBody(opts.body ?? opts.title);
|
|
11605
|
-
const bodyFile = (0,
|
|
11937
|
+
const bodyFile = (0, import_node_path27.join)(
|
|
11606
11938
|
(0, import_node_os8.tmpdir)(),
|
|
11607
|
-
`sideboard-pr-body-${process.pid}-${(0,
|
|
11939
|
+
`sideboard-pr-body-${process.pid}-${(0, import_node_crypto10.randomBytes)(6).toString("hex")}.md`
|
|
11608
11940
|
);
|
|
11609
|
-
(0,
|
|
11941
|
+
(0, import_node_fs23.writeFileSync)(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
|
|
11610
11942
|
`, "utf8");
|
|
11611
11943
|
const bodyArgs = ["--body-file", bodyFile];
|
|
11612
11944
|
try {
|
|
@@ -11620,7 +11952,7 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
11620
11952
|
});
|
|
11621
11953
|
} finally {
|
|
11622
11954
|
try {
|
|
11623
|
-
(0,
|
|
11955
|
+
(0, import_node_fs23.unlinkSync)(bodyFile);
|
|
11624
11956
|
} catch {
|
|
11625
11957
|
}
|
|
11626
11958
|
}
|
|
@@ -11700,14 +12032,14 @@ function suggestSlug(source) {
|
|
|
11700
12032
|
const stamp = Date.now().toString(36).slice(-4);
|
|
11701
12033
|
return `${base || "thread"}-${stamp}`;
|
|
11702
12034
|
}
|
|
11703
|
-
var
|
|
12035
|
+
var import_node_crypto10, import_node_fs23, import_node_os8, import_node_path27, PR_INFO_JSON_FIELDS, PR_DETAILS_JSON_FIELDS;
|
|
11704
12036
|
var init_worktree = __esm({
|
|
11705
12037
|
"src/git/worktree.ts"() {
|
|
11706
12038
|
"use strict";
|
|
11707
|
-
|
|
11708
|
-
|
|
12039
|
+
import_node_crypto10 = require("crypto");
|
|
12040
|
+
import_node_fs23 = require("fs");
|
|
11709
12041
|
import_node_os8 = require("os");
|
|
11710
|
-
|
|
12042
|
+
import_node_path27 = require("path");
|
|
11711
12043
|
init_paths();
|
|
11712
12044
|
init_worktree_labels();
|
|
11713
12045
|
init_gh_errors();
|
|
@@ -11797,279 +12129,6 @@ var init_cloud_connect_constants = __esm({
|
|
|
11797
12129
|
}
|
|
11798
12130
|
});
|
|
11799
12131
|
|
|
11800
|
-
// src/composer/stage-files.ts
|
|
11801
|
-
function fileExtension(filePath) {
|
|
11802
|
-
const base = (0, import_node_path27.basename)(filePath).toLowerCase();
|
|
11803
|
-
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
11804
|
-
}
|
|
11805
|
-
function isImageFilePath(filePath) {
|
|
11806
|
-
return IMAGE_EXTENSIONS.has(fileExtension(filePath));
|
|
11807
|
-
}
|
|
11808
|
-
function imageMimeType(filePath) {
|
|
11809
|
-
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
11810
|
-
}
|
|
11811
|
-
function ensureAttachmentsDir(worktreePath) {
|
|
11812
|
-
const dir = (0, import_node_path27.join)(worktreePath, ATTACHMENTS_DIR);
|
|
11813
|
-
(0, import_node_fs23.mkdirSync)(dir, { recursive: true });
|
|
11814
|
-
const gi = (0, import_node_path27.join)(dir, ".gitignore");
|
|
11815
|
-
if (!(0, import_node_fs23.existsSync)(gi)) {
|
|
11816
|
-
(0, import_node_fs23.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
11817
|
-
}
|
|
11818
|
-
return dir;
|
|
11819
|
-
}
|
|
11820
|
-
function uniqueAttachmentName(dir, originalName) {
|
|
11821
|
-
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
11822
|
-
if (!(0, import_node_fs23.existsSync)((0, import_node_path27.join)(dir, safe))) return safe;
|
|
11823
|
-
const ext = (0, import_node_path27.extname)(safe);
|
|
11824
|
-
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
11825
|
-
for (let i = 1; i < 1e4; i++) {
|
|
11826
|
-
const candidate = `${stem}-${i}${ext}`;
|
|
11827
|
-
if (!(0, import_node_fs23.existsSync)((0, import_node_path27.join)(dir, candidate))) return candidate;
|
|
11828
|
-
}
|
|
11829
|
-
return `${stem}-${(0, import_node_crypto10.randomUUID)()}${ext}`;
|
|
11830
|
-
}
|
|
11831
|
-
function previewDataUrlFromBuf(filePath, buf) {
|
|
11832
|
-
if (!isImageFilePath(filePath)) return void 0;
|
|
11833
|
-
if (buf.length > MAX_PREVIEW_BYTES) return void 0;
|
|
11834
|
-
return `data:${imageMimeType(filePath)};base64,${buf.toString("base64")}`;
|
|
11835
|
-
}
|
|
11836
|
-
function attachmentFromBuffer(name, buf, opts) {
|
|
11837
|
-
const previewDataUrl = previewDataUrlFromBuf(name, buf);
|
|
11838
|
-
if (isImageFilePath(name)) {
|
|
11839
|
-
const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
|
|
11840
|
-
return {
|
|
11841
|
-
id: (0, import_node_crypto10.randomUUID)(),
|
|
11842
|
-
name,
|
|
11843
|
-
kind: "file",
|
|
11844
|
-
path: opts.path,
|
|
11845
|
-
previewDataUrl,
|
|
11846
|
-
content: [
|
|
11847
|
-
`Image attached: ${pathHint}`,
|
|
11848
|
-
opts.path ? `Use the Read tool on \`${opts.path}\` to view this image.` : "The image is shown in the composer; copy it into the worktree if you need to inspect pixels."
|
|
11849
|
-
].join("\n")
|
|
11850
|
-
};
|
|
11851
|
-
}
|
|
11852
|
-
if (buf.length > MAX_INLINE_BYTES) {
|
|
11853
|
-
return {
|
|
11854
|
-
id: (0, import_node_crypto10.randomUUID)(),
|
|
11855
|
-
name,
|
|
11856
|
-
kind: "file",
|
|
11857
|
-
path: opts.path,
|
|
11858
|
-
content: opts.path ? `(file too large to attach inline: \`${opts.path}\`, ${buf.length} bytes \u2014 use the Read tool)` : `(file too large to attach inline: ${opts.sourceLabel || name}, ${buf.length} bytes)`
|
|
11859
|
-
};
|
|
11860
|
-
}
|
|
11861
|
-
if (buf.includes(0)) {
|
|
11862
|
-
return {
|
|
11863
|
-
id: (0, import_node_crypto10.randomUUID)(),
|
|
11864
|
-
name,
|
|
11865
|
-
kind: "file",
|
|
11866
|
-
path: opts.path,
|
|
11867
|
-
content: opts.path ? `(binary file at \`${opts.path}\` \u2014 use tools to inspect)` : `(binary file attached by path only: ${opts.sourceLabel || name})`
|
|
11868
|
-
};
|
|
11869
|
-
}
|
|
11870
|
-
return {
|
|
11871
|
-
id: (0, import_node_crypto10.randomUUID)(),
|
|
11872
|
-
name,
|
|
11873
|
-
kind: "file",
|
|
11874
|
-
path: opts.path,
|
|
11875
|
-
content: buf.toString("utf8")
|
|
11876
|
-
};
|
|
11877
|
-
}
|
|
11878
|
-
function attachmentFromAbsolutePath(absolutePath) {
|
|
11879
|
-
const name = (0, import_node_path27.basename)(absolutePath);
|
|
11880
|
-
try {
|
|
11881
|
-
const st = (0, import_node_fs23.statSync)(absolutePath);
|
|
11882
|
-
if (!st.isFile()) {
|
|
11883
|
-
return {
|
|
11884
|
-
id: (0, import_node_crypto10.randomUUID)(),
|
|
11885
|
-
name,
|
|
11886
|
-
kind: "file",
|
|
11887
|
-
content: `(not a file: ${absolutePath})`
|
|
11888
|
-
};
|
|
11889
|
-
}
|
|
11890
|
-
const buf = (0, import_node_fs23.readFileSync)(absolutePath);
|
|
11891
|
-
return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
|
|
11892
|
-
} catch (err) {
|
|
11893
|
-
return {
|
|
11894
|
-
id: (0, import_node_crypto10.randomUUID)(),
|
|
11895
|
-
name,
|
|
11896
|
-
kind: "file",
|
|
11897
|
-
content: `(could not read ${absolutePath}: ${err instanceof Error ? err.message : String(err)})`
|
|
11898
|
-
};
|
|
11899
|
-
}
|
|
11900
|
-
}
|
|
11901
|
-
function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
11902
|
-
if (absolutePaths.length === 0) return [];
|
|
11903
|
-
const dir = ensureAttachmentsDir(worktreePath);
|
|
11904
|
-
const out = [];
|
|
11905
|
-
for (const abs of absolutePaths) {
|
|
11906
|
-
const originalName = (0, import_node_path27.basename)(abs);
|
|
11907
|
-
try {
|
|
11908
|
-
const st = (0, import_node_fs23.statSync)(abs);
|
|
11909
|
-
if (!st.isFile()) continue;
|
|
11910
|
-
const name = uniqueAttachmentName(dir, originalName);
|
|
11911
|
-
const destAbs = (0, import_node_path27.join)(dir, name);
|
|
11912
|
-
(0, import_node_fs23.copyFileSync)(abs, destAbs);
|
|
11913
|
-
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
11914
|
-
const buf = (0, import_node_fs23.readFileSync)(destAbs);
|
|
11915
|
-
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
11916
|
-
} catch (err) {
|
|
11917
|
-
out.push({
|
|
11918
|
-
id: (0, import_node_crypto10.randomUUID)(),
|
|
11919
|
-
name: originalName,
|
|
11920
|
-
kind: "file",
|
|
11921
|
-
content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
|
|
11922
|
-
});
|
|
11923
|
-
}
|
|
11924
|
-
}
|
|
11925
|
-
return out;
|
|
11926
|
-
}
|
|
11927
|
-
function stageBuffersAsAttachments(worktreePath, buffers2) {
|
|
11928
|
-
if (buffers2.length === 0) return [];
|
|
11929
|
-
const dir = ensureAttachmentsDir(worktreePath);
|
|
11930
|
-
const out = [];
|
|
11931
|
-
for (const item of buffers2) {
|
|
11932
|
-
const originalName = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
11933
|
-
try {
|
|
11934
|
-
const buf = Buffer.from(item.dataBase64, "base64");
|
|
11935
|
-
const name = uniqueAttachmentName(dir, originalName);
|
|
11936
|
-
const destAbs = (0, import_node_path27.join)(dir, name);
|
|
11937
|
-
(0, import_node_fs23.writeFileSync)(destAbs, buf);
|
|
11938
|
-
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
11939
|
-
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
11940
|
-
} catch (err) {
|
|
11941
|
-
out.push({
|
|
11942
|
-
id: (0, import_node_crypto10.randomUUID)(),
|
|
11943
|
-
name: originalName,
|
|
11944
|
-
kind: "file",
|
|
11945
|
-
content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
|
|
11946
|
-
});
|
|
11947
|
-
}
|
|
11948
|
-
}
|
|
11949
|
-
return out;
|
|
11950
|
-
}
|
|
11951
|
-
function attachmentsFromBuffers(buffers2) {
|
|
11952
|
-
return buffers2.map((item) => {
|
|
11953
|
-
const name = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
11954
|
-
try {
|
|
11955
|
-
const buf = Buffer.from(item.dataBase64, "base64");
|
|
11956
|
-
return attachmentFromBuffer(name, buf, { sourceLabel: name });
|
|
11957
|
-
} catch (err) {
|
|
11958
|
-
return {
|
|
11959
|
-
id: (0, import_node_crypto10.randomUUID)(),
|
|
11960
|
-
name,
|
|
11961
|
-
kind: "file",
|
|
11962
|
-
content: `(could not attach ${name}: ${err instanceof Error ? err.message : String(err)})`
|
|
11963
|
-
};
|
|
11964
|
-
}
|
|
11965
|
-
});
|
|
11966
|
-
}
|
|
11967
|
-
function isWorktreeRelativePath(p) {
|
|
11968
|
-
if (!p || p.includes("..")) return false;
|
|
11969
|
-
if (p.startsWith("/")) return false;
|
|
11970
|
-
if (/^[A-Za-z]:[\\/]/.test(p)) return false;
|
|
11971
|
-
return true;
|
|
11972
|
-
}
|
|
11973
|
-
function dataUrlToBase64(url) {
|
|
11974
|
-
if (!url) return null;
|
|
11975
|
-
const m = /^data:[^;]+;base64,(.+)$/s.exec(url);
|
|
11976
|
-
return m?.[1] ?? null;
|
|
11977
|
-
}
|
|
11978
|
-
function persistPendingFileAttachments(worktreePath, attachments) {
|
|
11979
|
-
if (attachments.length === 0) return attachments;
|
|
11980
|
-
const keep = [];
|
|
11981
|
-
const buffers2 = [];
|
|
11982
|
-
for (const att of attachments) {
|
|
11983
|
-
if (att.kind !== "file") {
|
|
11984
|
-
keep.push(att);
|
|
11985
|
-
continue;
|
|
11986
|
-
}
|
|
11987
|
-
if (att.path && isWorktreeRelativePath(att.path)) {
|
|
11988
|
-
keep.push(att);
|
|
11989
|
-
continue;
|
|
11990
|
-
}
|
|
11991
|
-
const fromPreview = dataUrlToBase64(att.previewDataUrl);
|
|
11992
|
-
if (fromPreview) {
|
|
11993
|
-
buffers2.push({ name: att.name, dataBase64: fromPreview });
|
|
11994
|
-
continue;
|
|
11995
|
-
}
|
|
11996
|
-
if (att.content && !IMAGE_HINT_RE.test(att.content) && !PLACEHOLDER_CONTENT_RE.test(att.content)) {
|
|
11997
|
-
buffers2.push({
|
|
11998
|
-
name: att.name,
|
|
11999
|
-
dataBase64: Buffer.from(att.content, "utf8").toString("base64")
|
|
12000
|
-
});
|
|
12001
|
-
continue;
|
|
12002
|
-
}
|
|
12003
|
-
keep.push(att);
|
|
12004
|
-
}
|
|
12005
|
-
if (buffers2.length === 0) return attachments;
|
|
12006
|
-
return [...keep, ...stageBuffersAsAttachments(worktreePath, buffers2)];
|
|
12007
|
-
}
|
|
12008
|
-
function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
12009
|
-
const out = [];
|
|
12010
|
-
for (const rel of relativePaths) {
|
|
12011
|
-
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
12012
|
-
out.push({
|
|
12013
|
-
id: (0, import_node_crypto10.randomUUID)(),
|
|
12014
|
-
name: (0, import_node_path27.basename)(rel) || "file",
|
|
12015
|
-
kind: "file",
|
|
12016
|
-
content: `(invalid path: ${rel})`
|
|
12017
|
-
});
|
|
12018
|
-
continue;
|
|
12019
|
-
}
|
|
12020
|
-
const name = (0, import_node_path27.basename)(rel);
|
|
12021
|
-
try {
|
|
12022
|
-
const abs = (0, import_node_path27.join)(worktreePath, rel);
|
|
12023
|
-
const st = (0, import_node_fs23.statSync)(abs);
|
|
12024
|
-
if (!st.isFile()) continue;
|
|
12025
|
-
const buf = (0, import_node_fs23.readFileSync)(abs);
|
|
12026
|
-
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
12027
|
-
} catch (err) {
|
|
12028
|
-
out.push({
|
|
12029
|
-
id: (0, import_node_crypto10.randomUUID)(),
|
|
12030
|
-
name,
|
|
12031
|
-
kind: "file",
|
|
12032
|
-
content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
|
|
12033
|
-
});
|
|
12034
|
-
}
|
|
12035
|
-
}
|
|
12036
|
-
return out;
|
|
12037
|
-
}
|
|
12038
|
-
var import_node_fs23, import_node_path27, import_node_crypto10, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
|
|
12039
|
-
var init_stage_files = __esm({
|
|
12040
|
-
"src/composer/stage-files.ts"() {
|
|
12041
|
-
"use strict";
|
|
12042
|
-
import_node_fs23 = require("fs");
|
|
12043
|
-
import_node_path27 = require("path");
|
|
12044
|
-
import_node_crypto10 = require("crypto");
|
|
12045
|
-
init_workspace_scratch();
|
|
12046
|
-
IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
12047
|
-
"png",
|
|
12048
|
-
"jpg",
|
|
12049
|
-
"jpeg",
|
|
12050
|
-
"gif",
|
|
12051
|
-
"webp",
|
|
12052
|
-
"svg",
|
|
12053
|
-
"bmp",
|
|
12054
|
-
"ico"
|
|
12055
|
-
]);
|
|
12056
|
-
IMAGE_MIME_BY_EXT = {
|
|
12057
|
-
png: "image/png",
|
|
12058
|
-
jpg: "image/jpeg",
|
|
12059
|
-
jpeg: "image/jpeg",
|
|
12060
|
-
gif: "image/gif",
|
|
12061
|
-
webp: "image/webp",
|
|
12062
|
-
svg: "image/svg+xml",
|
|
12063
|
-
bmp: "image/bmp",
|
|
12064
|
-
ico: "image/x-icon"
|
|
12065
|
-
};
|
|
12066
|
-
MAX_INLINE_BYTES = 4e5;
|
|
12067
|
-
MAX_PREVIEW_BYTES = 5e6;
|
|
12068
|
-
IMAGE_HINT_RE = /^Image attached:/;
|
|
12069
|
-
PLACEHOLDER_CONTENT_RE = /^\((could not |file too large|binary file|not a file|invalid path)/;
|
|
12070
|
-
}
|
|
12071
|
-
});
|
|
12072
|
-
|
|
12073
12132
|
// src/store/workspaces.ts
|
|
12074
12133
|
var workspaces_exports = {};
|
|
12075
12134
|
__export(workspaces_exports, {
|
|
@@ -12558,7 +12617,7 @@ var init_coordinator_prompt = __esm({
|
|
|
12558
12617
|
"- 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.",
|
|
12559
12618
|
"- 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.",
|
|
12560
12619
|
"- 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.",
|
|
12561
|
-
"- list_schedules / create_schedule / update_schedule / delete_schedule / run_schedule \u2014
|
|
12620
|
+
"- 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.",
|
|
12562
12621
|
"Projects:",
|
|
12563
12622
|
"- add_project / remove_project \u2014 register or unregister a git repo",
|
|
12564
12623
|
"Workspaces and chats:",
|
|
@@ -23328,6 +23387,77 @@ var init_steer_request = __esm({
|
|
|
23328
23387
|
}
|
|
23329
23388
|
});
|
|
23330
23389
|
|
|
23390
|
+
// src/orchestrator/ephemeral-automation.ts
|
|
23391
|
+
function ephemeralRunReadyToArchive(thread) {
|
|
23392
|
+
if (!thread.ephemeralAutomationId?.trim()) return false;
|
|
23393
|
+
if (thread.status !== "idle" && thread.status !== "error") return false;
|
|
23394
|
+
if (thread.queue.length > 0) return false;
|
|
23395
|
+
if (thread.agentBlock?.reason?.trim()) return false;
|
|
23396
|
+
if (thread.quotaResumeAt) return false;
|
|
23397
|
+
return true;
|
|
23398
|
+
}
|
|
23399
|
+
function markEphemeralAutomation(threadId, opts) {
|
|
23400
|
+
const id = opts.ephemeralAutomationId?.trim();
|
|
23401
|
+
const current = readThread(threadId);
|
|
23402
|
+
if (!current) throw new Error(`Thread not found: ${threadId}`);
|
|
23403
|
+
if (!id) return current;
|
|
23404
|
+
const title = opts.ephemeralTitle?.trim();
|
|
23405
|
+
return updateThread(threadId, {
|
|
23406
|
+
ephemeralAutomationId: id,
|
|
23407
|
+
...title ? { title, userSetTitle: true } : {}
|
|
23408
|
+
});
|
|
23409
|
+
}
|
|
23410
|
+
async function archiveEphemeralAutomationIfReady(threadId, archive) {
|
|
23411
|
+
const keep = await withThreadLock(threadId, async () => {
|
|
23412
|
+
const thread = readThread(threadId);
|
|
23413
|
+
if (!thread || !ephemeralRunReadyToArchive(thread)) return null;
|
|
23414
|
+
const automationId = thread.ephemeralAutomationId?.trim();
|
|
23415
|
+
if (!automationId) return null;
|
|
23416
|
+
await archive(thread.id);
|
|
23417
|
+
return {
|
|
23418
|
+
automationId,
|
|
23419
|
+
keepId: archivedContinuationId(automationId, threadId) ?? threadId
|
|
23420
|
+
};
|
|
23421
|
+
});
|
|
23422
|
+
if (keep) forgetOlderEphemeralRuns(keep.automationId, keep.keepId);
|
|
23423
|
+
}
|
|
23424
|
+
function archivedContinuationId(automationId, sourceId) {
|
|
23425
|
+
for (const thread of listThreads({ includeArchived: true })) {
|
|
23426
|
+
if (thread.id === sourceId || thread.status !== "archived") continue;
|
|
23427
|
+
if (thread.ephemeralAutomationId !== automationId) continue;
|
|
23428
|
+
if (thread.quotaContinuedFromId !== sourceId) continue;
|
|
23429
|
+
return thread.id;
|
|
23430
|
+
}
|
|
23431
|
+
return null;
|
|
23432
|
+
}
|
|
23433
|
+
function clearEphemeralAutomation(threadId) {
|
|
23434
|
+
const thread = readThread(threadId);
|
|
23435
|
+
if (!thread?.ephemeralAutomationId?.trim()) return;
|
|
23436
|
+
updateThread(threadId, { ephemeralAutomationId: void 0 });
|
|
23437
|
+
}
|
|
23438
|
+
function forgetOlderEphemeralRuns(automationId, keepId) {
|
|
23439
|
+
const id = automationId.trim();
|
|
23440
|
+
if (!id || !keepId) return [];
|
|
23441
|
+
const removed = [];
|
|
23442
|
+
for (const thread of listThreads({ includeArchived: true })) {
|
|
23443
|
+
if (thread.id === keepId) continue;
|
|
23444
|
+
if (thread.status !== "archived") continue;
|
|
23445
|
+
if (thread.ephemeralAutomationId !== id) continue;
|
|
23446
|
+
try {
|
|
23447
|
+
deleteThreadRecord(thread.id);
|
|
23448
|
+
removed.push(thread.id);
|
|
23449
|
+
} catch {
|
|
23450
|
+
}
|
|
23451
|
+
}
|
|
23452
|
+
return removed;
|
|
23453
|
+
}
|
|
23454
|
+
var init_ephemeral_automation = __esm({
|
|
23455
|
+
"src/orchestrator/ephemeral-automation.ts"() {
|
|
23456
|
+
"use strict";
|
|
23457
|
+
init_thread_store();
|
|
23458
|
+
}
|
|
23459
|
+
});
|
|
23460
|
+
|
|
23331
23461
|
// src/threads/title.ts
|
|
23332
23462
|
var title_exports = {};
|
|
23333
23463
|
__export(title_exports, {
|
|
@@ -26296,17 +26426,23 @@ async function isolateQuotaFailover(run2) {
|
|
|
26296
26426
|
}
|
|
26297
26427
|
}
|
|
26298
26428
|
function createQuotaFailoverChat(from, fallbackAgent, limitText, opts) {
|
|
26429
|
+
const ephemeralAutomationId = from.ephemeralAutomationId?.trim();
|
|
26430
|
+
const ephemeralTitle = ephemeralAutomationId ? from.title.trim() : "";
|
|
26299
26431
|
const handoff = buildQuotaHandoffAttachment(from, limitText, fallbackAgent);
|
|
26300
26432
|
const tab = createChatTab({
|
|
26301
26433
|
fromThreadId: from.id,
|
|
26302
26434
|
agent: fallbackAgent,
|
|
26303
26435
|
model: null,
|
|
26304
26436
|
attachments: [handoff],
|
|
26437
|
+
...ephemeralTitle ? { title: ephemeralTitle } : {},
|
|
26305
26438
|
...opts && "accountId" in opts ? { accountId: opts.accountId } : {}
|
|
26306
26439
|
});
|
|
26307
26440
|
const patch = {
|
|
26308
26441
|
quotaContinuedFromId: from.id,
|
|
26309
|
-
sourceRef: from.sourceRef
|
|
26442
|
+
sourceRef: from.sourceRef,
|
|
26443
|
+
// The original drain archives as idle. This sibling has to carry the one-off
|
|
26444
|
+
// so it archives when the continued turn finishes and History keeps it.
|
|
26445
|
+
...ephemeralAutomationId ? { ephemeralAutomationId } : {}
|
|
26310
26446
|
};
|
|
26311
26447
|
if (isOrchestratorThread(from)) {
|
|
26312
26448
|
patch.parentThreadId = from.id;
|
|
@@ -28723,7 +28859,7 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
28723
28859
|
lines.push(formatDevAccessHint(opts?.activeRuns));
|
|
28724
28860
|
lines.push("");
|
|
28725
28861
|
lines.push(
|
|
28726
|
-
"
|
|
28862
|
+
"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."
|
|
28727
28863
|
);
|
|
28728
28864
|
lines.push(
|
|
28729
28865
|
"`set_workspace_tags` labels this checkout (omit ref; replace, add, or remove). Not another checkout."
|
|
@@ -28743,7 +28879,7 @@ function connectedOrchestratorTurnReminder(thread, find) {
|
|
|
28743
28879
|
return formatConnectedOrchestratorReminder(connectedOrchestrator(thread, find));
|
|
28744
28880
|
}
|
|
28745
28881
|
function formatWorktreeReminder() {
|
|
28746
|
-
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.
|
|
28882
|
+
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).";
|
|
28747
28883
|
}
|
|
28748
28884
|
function formatClaudeSubagentReminder() {
|
|
28749
28885
|
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.';
|
|
@@ -29971,10 +30107,11 @@ async function startOrchestration(opts) {
|
|
|
29971
30107
|
planMode: opts.planMode,
|
|
29972
30108
|
attachments: opts.attachments
|
|
29973
30109
|
});
|
|
30110
|
+
const ready2 = markEphemeralAutomation(thread2.id, opts);
|
|
29974
30111
|
if (goal) {
|
|
29975
|
-
return orch.send(
|
|
30112
|
+
return orch.send(ready2.id, goal);
|
|
29976
30113
|
}
|
|
29977
|
-
return
|
|
30114
|
+
return ready2;
|
|
29978
30115
|
}
|
|
29979
30116
|
const { titleFromPrompt: titleFromPrompt2 } = await Promise.resolve().then(() => (init_title(), title_exports));
|
|
29980
30117
|
const title = titleFromPrompt2(goal) || "Orchestration";
|
|
@@ -30009,10 +30146,11 @@ async function startOrchestration(opts) {
|
|
|
30009
30146
|
sourceType: "orchestration",
|
|
30010
30147
|
sourceRef: goal
|
|
30011
30148
|
});
|
|
30149
|
+
const ready = markEphemeralAutomation(updated.id, opts);
|
|
30012
30150
|
if (goal) {
|
|
30013
|
-
return orch.send(
|
|
30151
|
+
return orch.send(ready.id, goal);
|
|
30014
30152
|
}
|
|
30015
|
-
return
|
|
30153
|
+
return ready;
|
|
30016
30154
|
}
|
|
30017
30155
|
var import_node_events, import_node_crypto19, import_node_fs67, LIVE_TURN_SPAWN_GRACE_MS, RUN_SCRIPT_DESKTOP_ADOPT_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton2;
|
|
30018
30156
|
var init_orchestrator = __esm({
|
|
@@ -30053,6 +30191,7 @@ var init_orchestrator = __esm({
|
|
|
30053
30191
|
init_child_halt();
|
|
30054
30192
|
init_stop_reason();
|
|
30055
30193
|
init_steer_request();
|
|
30194
|
+
init_ephemeral_automation();
|
|
30056
30195
|
init_wait_for_job();
|
|
30057
30196
|
init_agent_purpose_title();
|
|
30058
30197
|
init_create();
|
|
@@ -30890,6 +31029,7 @@ var init_orchestrator = __esm({
|
|
|
30890
31029
|
} finally {
|
|
30891
31030
|
this.draining.delete(threadId);
|
|
30892
31031
|
}
|
|
31032
|
+
await archiveEphemeralAutomationIfReady(threadId, (id) => this.archive(id));
|
|
30893
31033
|
}
|
|
30894
31034
|
async runTurn(threadId, prompt) {
|
|
30895
31035
|
const existing = readThread(threadId);
|
|
@@ -32723,6 +32863,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
32723
32863
|
if (thread.status !== "archived") {
|
|
32724
32864
|
throw new Error("Thread is not archived");
|
|
32725
32865
|
}
|
|
32866
|
+
clearEphemeralAutomation(thread.id);
|
|
32726
32867
|
if (isGlobalThread(thread)) {
|
|
32727
32868
|
const { globalAgentCwd: globalAgentCwd2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
32728
32869
|
updateThread(thread.id, { worktreePath: globalAgentCwd2() });
|
|
@@ -32814,17 +32955,52 @@ async function defaultDeps() {
|
|
|
32814
32955
|
const orch = getOrchestrator2();
|
|
32815
32956
|
return {
|
|
32816
32957
|
findThread: (id) => findThreadByRef(id),
|
|
32817
|
-
send: (id, prompt) =>
|
|
32958
|
+
send: async (id, prompt, opts) => {
|
|
32959
|
+
if (opts?.options && Object.keys(opts.options).length > 0) {
|
|
32960
|
+
try {
|
|
32961
|
+
orch.setThreadOptions(id, opts.options);
|
|
32962
|
+
} catch {
|
|
32963
|
+
const rest = scheduleOptionsAfterRefusedAgentSwitch(opts.options);
|
|
32964
|
+
if (Object.keys(rest).length > 0) {
|
|
32965
|
+
try {
|
|
32966
|
+
orch.setThreadOptions(id, rest);
|
|
32967
|
+
} catch {
|
|
32968
|
+
}
|
|
32969
|
+
}
|
|
32970
|
+
}
|
|
32971
|
+
}
|
|
32972
|
+
const thread = findThreadByRef(id);
|
|
32973
|
+
const attachments = thread ? persistPendingFileAttachments(thread.worktreePath, opts?.attachments ?? []) : opts?.attachments ?? [];
|
|
32974
|
+
return orch.send(id, prompt, { attachments });
|
|
32975
|
+
},
|
|
32818
32976
|
startOrchestration: (opts) => startOrchestration2(opts)
|
|
32819
32977
|
};
|
|
32820
32978
|
}
|
|
32979
|
+
function scheduleOptionsAfterRefusedAgentSwitch(options) {
|
|
32980
|
+
const { agent: _agent, model: _model, ...rest } = options;
|
|
32981
|
+
return rest;
|
|
32982
|
+
}
|
|
32983
|
+
function scheduleSendOptions(schedule) {
|
|
32984
|
+
const patch = {};
|
|
32985
|
+
if (schedule.agent) {
|
|
32986
|
+
patch.agent = schedule.agent;
|
|
32987
|
+
patch.model = schedule.model;
|
|
32988
|
+
} else if (schedule.model) {
|
|
32989
|
+
patch.model = schedule.model;
|
|
32990
|
+
}
|
|
32991
|
+
if (schedule.effort) patch.effort = schedule.effort;
|
|
32992
|
+
if (schedule.fast != null) patch.fast = schedule.fast;
|
|
32993
|
+
if (schedule.planMode != null) patch.planMode = schedule.planMode;
|
|
32994
|
+
if (schedule.autonomy) patch.autonomy = schedule.autonomy;
|
|
32995
|
+
return Object.keys(patch).length > 0 ? patch : void 0;
|
|
32996
|
+
}
|
|
32821
32997
|
function pickAgent(schedule) {
|
|
32822
32998
|
if (schedule.agent) return schedule.agent;
|
|
32823
32999
|
return coerceOrchestratorAgent(resolveOrchestratorDefaults().agent);
|
|
32824
33000
|
}
|
|
32825
33001
|
async function fireSchedule(id) {
|
|
32826
33002
|
const schedule = getSchedule(id);
|
|
32827
|
-
if (!schedule) throw new Error(`
|
|
33003
|
+
if (!schedule) throw new Error(`Automation not found: ${id}`);
|
|
32828
33004
|
if (firing.has(schedule.id)) return schedule;
|
|
32829
33005
|
firing.add(schedule.id);
|
|
32830
33006
|
try {
|
|
@@ -32832,18 +33008,28 @@ async function fireSchedule(id) {
|
|
|
32832
33008
|
const prompt = formatScheduledPrompt(schedule.name, schedule.prompt);
|
|
32833
33009
|
const target = schedule.threadId ? deps.findThread(schedule.threadId) : null;
|
|
32834
33010
|
if (target && target.status !== "archived") {
|
|
32835
|
-
const sent = await deps.send(target.id, prompt
|
|
33011
|
+
const sent = await deps.send(target.id, prompt, {
|
|
33012
|
+
attachments: schedule.attachments,
|
|
33013
|
+
options: scheduleSendOptions(schedule)
|
|
33014
|
+
});
|
|
32836
33015
|
return recordScheduleRun(schedule.id, {
|
|
32837
33016
|
lastThreadId: sent.id,
|
|
32838
33017
|
lastError: null
|
|
32839
33018
|
});
|
|
32840
33019
|
}
|
|
33020
|
+
const pinReplacement = Boolean(schedule.threadId) && schedule.when.kind !== "once";
|
|
32841
33021
|
const created = await deps.startOrchestration({
|
|
32842
33022
|
goal: prompt,
|
|
32843
33023
|
agent: pickAgent(schedule),
|
|
32844
|
-
model: schedule.model
|
|
33024
|
+
model: schedule.model,
|
|
33025
|
+
...schedule.effort ? { effort: schedule.effort } : {},
|
|
33026
|
+
...schedule.fast != null ? { fast: schedule.fast } : {},
|
|
33027
|
+
...schedule.planMode != null ? { planMode: schedule.planMode } : {},
|
|
33028
|
+
...schedule.autonomy ? { autonomy: schedule.autonomy } : {},
|
|
33029
|
+
attachments: schedule.attachments,
|
|
33030
|
+
...pinReplacement ? {} : { ephemeralAutomationId: schedule.id, ephemeralTitle: schedule.name }
|
|
32845
33031
|
});
|
|
32846
|
-
if (
|
|
33032
|
+
if (pinReplacement) {
|
|
32847
33033
|
updateSchedule(schedule.id, { threadId: created.id });
|
|
32848
33034
|
}
|
|
32849
33035
|
return recordScheduleRun(schedule.id, {
|
|
@@ -32913,6 +33099,7 @@ var init_schedule_runner = __esm({
|
|
|
32913
33099
|
init_desktop_host();
|
|
32914
33100
|
init_app_settings();
|
|
32915
33101
|
init_schedules();
|
|
33102
|
+
init_stage_files();
|
|
32916
33103
|
init_thread_store();
|
|
32917
33104
|
SET_TIMEOUT_MAX = 2147483647;
|
|
32918
33105
|
fireHooks = null;
|
|
@@ -43639,7 +43826,7 @@ function parseWhen(args) {
|
|
|
43639
43826
|
function registerScheduleTools(server) {
|
|
43640
43827
|
server.tool(
|
|
43641
43828
|
"list_schedules",
|
|
43642
|
-
"List local Sideboard
|
|
43829
|
+
"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.",
|
|
43643
43830
|
{},
|
|
43644
43831
|
async () => {
|
|
43645
43832
|
try {
|
|
@@ -43651,9 +43838,9 @@ function registerScheduleTools(server) {
|
|
|
43651
43838
|
);
|
|
43652
43839
|
server.tool(
|
|
43653
43840
|
"create_schedule",
|
|
43654
|
-
"Create a local
|
|
43841
|
+
"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.",
|
|
43655
43842
|
{
|
|
43656
|
-
prompt: import_zod10.z.string().describe("User message / goal queued when the
|
|
43843
|
+
prompt: import_zod10.z.string().describe("User message / goal queued when the automation fires"),
|
|
43657
43844
|
name: import_zod10.z.string().optional(),
|
|
43658
43845
|
at: import_zod10.z.string().optional().describe("ISO datetime for a one-shot"),
|
|
43659
43846
|
every: import_zod10.z.string().optional().describe("Interval such as 15m, 1h, 6h, 1d"),
|
|
@@ -43689,7 +43876,7 @@ function registerScheduleTools(server) {
|
|
|
43689
43876
|
});
|
|
43690
43877
|
return text6({
|
|
43691
43878
|
schedule,
|
|
43692
|
-
hint: scheduleNeedsCaffeinate(schedule) ? "Fires while Sideboard.app is running. Recurring jobs without chatId create a new orchestration chat each run. Caffeinate while
|
|
43879
|
+
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)."
|
|
43693
43880
|
});
|
|
43694
43881
|
} catch (err) {
|
|
43695
43882
|
return fail4(err);
|
|
@@ -43698,7 +43885,7 @@ function registerScheduleTools(server) {
|
|
|
43698
43885
|
);
|
|
43699
43886
|
server.tool(
|
|
43700
43887
|
"update_schedule",
|
|
43701
|
-
"Update a local
|
|
43888
|
+
"Update a local automation (prompt, cadence, target chat, enabled). Pass id from list_schedules.",
|
|
43702
43889
|
{
|
|
43703
43890
|
id: import_zod10.z.string(),
|
|
43704
43891
|
prompt: import_zod10.z.string().optional(),
|
|
@@ -43753,7 +43940,7 @@ function registerScheduleTools(server) {
|
|
|
43753
43940
|
);
|
|
43754
43941
|
server.tool(
|
|
43755
43942
|
"delete_schedule",
|
|
43756
|
-
"Delete a local
|
|
43943
|
+
"Delete a local automation. Pass id from list_schedules.",
|
|
43757
43944
|
{ id: import_zod10.z.string() },
|
|
43758
43945
|
async ({ id }) => {
|
|
43759
43946
|
try {
|
|
@@ -43766,12 +43953,12 @@ function registerScheduleTools(server) {
|
|
|
43766
43953
|
);
|
|
43767
43954
|
server.tool(
|
|
43768
43955
|
"run_schedule",
|
|
43769
|
-
"Fire
|
|
43956
|
+
"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.",
|
|
43770
43957
|
{ id: import_zod10.z.string() },
|
|
43771
43958
|
async ({ id }) => {
|
|
43772
43959
|
try {
|
|
43773
43960
|
if (!getSchedule(id)) {
|
|
43774
|
-
return fail4(new Error(`
|
|
43961
|
+
return fail4(new Error(`Automation not found: ${id}`));
|
|
43775
43962
|
}
|
|
43776
43963
|
const schedule = await fireSchedule(id);
|
|
43777
43964
|
return text6({ schedule });
|