@sideboard-ai/core 0.1.42 → 0.1.44
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/agents/cursor-runner.cjs +14 -5
- package/dist/agents/cursor-runner.js +14 -5
- package/dist/{agents-T6XHC5OV.js → agents-PP3URTSF.js} +3 -2
- package/dist/{app-settings-RSKDEMUI.js → app-settings-ZKVZHJPQ.js} +6 -1
- package/dist/chunk-77WWLBCI.js +50 -0
- package/dist/{chunk-VA2U5EQH.js → chunk-7PCTK4WO.js} +1 -1
- package/dist/{chunk-5UIKSPDD.js → chunk-ENSD62HW.js} +12 -0
- package/dist/{chunk-YZ23S32T.js → chunk-FSIK442J.js} +35 -1
- package/dist/{chunk-6TZSJMXF.js → chunk-I3PKMLFW.js} +4 -3
- package/dist/{chunk-UPMGXM4X.js → chunk-JM2TVGNW.js} +3 -2
- package/dist/{chunk-44LYDJFB.js → chunk-TXFJEXFB.js} +2 -2
- package/dist/{chunk-FZH2SL5I.js → chunk-V3S4NF5F.js} +121 -22
- package/dist/{chunk-SX2R2PCE.js → chunk-XX26NCB6.js} +5 -5
- package/dist/{coordinator-prompt-FAILHO4J.js → coordinator-prompt-I5YNS27B.js} +4 -3
- package/dist/{global-workspace-4GVWSCEX.js → global-workspace-FU6UIPDY.js} +5 -4
- package/dist/index.cjs +237 -17
- package/dist/index.d.cts +105 -5
- package/dist/index.d.ts +105 -5
- package/dist/index.js +40 -8
- package/dist/mcp/run-stdio.cjs +274 -115
- package/dist/mcp/run-stdio.js +9 -8
- package/dist/{thread-store-WPLT3IXM.js → thread-store-EHROA3VZ.js} +4 -1
- package/dist/{workspaces-Z7CSL4O6.js → workspaces-RSEDTBGJ.js} +6 -5
- package/dist/{worktree-M3DTPYBW.js → worktree-N4PRV4V3.js} +3 -2
- package/package.json +1 -1
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -431,14 +431,44 @@ var init_paths = __esm({
|
|
|
431
431
|
}
|
|
432
432
|
});
|
|
433
433
|
|
|
434
|
+
// src/types/thinking-effort.ts
|
|
435
|
+
function normalizeThinkingEffort(value) {
|
|
436
|
+
if (typeof value !== "string") return null;
|
|
437
|
+
const v = value.trim().toLowerCase();
|
|
438
|
+
if (v === "normal") return "medium";
|
|
439
|
+
if (EFFORT_SET.has(v)) return v;
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
var THINKING_EFFORTS, EFFORT_SET;
|
|
443
|
+
var init_thinking_effort = __esm({
|
|
444
|
+
"src/types/thinking-effort.ts"() {
|
|
445
|
+
"use strict";
|
|
446
|
+
THINKING_EFFORTS = [
|
|
447
|
+
"low",
|
|
448
|
+
"medium",
|
|
449
|
+
"high",
|
|
450
|
+
"xhigh",
|
|
451
|
+
"max"
|
|
452
|
+
];
|
|
453
|
+
EFFORT_SET = new Set(THINKING_EFFORTS);
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
|
|
434
457
|
// src/store/thread-store.ts
|
|
435
458
|
function nowIso() {
|
|
436
459
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
437
460
|
}
|
|
461
|
+
function resolveThreadEffort(raw) {
|
|
462
|
+
const fromField = normalizeThinkingEffort(raw.effort);
|
|
463
|
+
if (fromField) return fromField;
|
|
464
|
+
if (raw.fast) return "low";
|
|
465
|
+
return "high";
|
|
466
|
+
}
|
|
438
467
|
function normalizeThread(raw) {
|
|
439
468
|
return {
|
|
440
469
|
...raw,
|
|
441
470
|
model: raw.model ?? null,
|
|
471
|
+
effort: resolveThreadEffort(raw),
|
|
442
472
|
fast: Boolean(raw.fast),
|
|
443
473
|
planMode: Boolean(raw.planMode),
|
|
444
474
|
autonomy: raw.autonomy ?? "default",
|
|
@@ -457,6 +487,7 @@ function createEmptyThread(partial) {
|
|
|
457
487
|
sessionId: partial.sessionId ?? null,
|
|
458
488
|
autonomy: partial.autonomy ?? "default",
|
|
459
489
|
model: partial.model ?? null,
|
|
490
|
+
effort: partial.effort ?? "high",
|
|
460
491
|
fast: partial.fast ?? false,
|
|
461
492
|
planMode: partial.planMode ?? false,
|
|
462
493
|
sourceIsFork: partial.sourceIsFork ?? false,
|
|
@@ -564,6 +595,7 @@ var init_thread_store = __esm({
|
|
|
564
595
|
import_node_crypto = require("crypto");
|
|
565
596
|
import_node_fs3 = require("fs");
|
|
566
597
|
import_proper_lockfile = __toESM(require("proper-lockfile"), 1);
|
|
598
|
+
init_thinking_effort();
|
|
567
599
|
init_paths();
|
|
568
600
|
}
|
|
569
601
|
});
|
|
@@ -2590,6 +2622,8 @@ __export(app_settings_exports, {
|
|
|
2590
2622
|
claudeUserSettingsPath: () => claudeUserSettingsPath,
|
|
2591
2623
|
deleteBranchOnPurgeEnabled: () => deleteBranchOnPurgeEnabled,
|
|
2592
2624
|
getDefaultAgent: () => getDefaultAgent,
|
|
2625
|
+
getDefaultEffort: () => getDefaultEffort,
|
|
2626
|
+
getDefaultFast: () => getDefaultFast,
|
|
2593
2627
|
getDefaultModel: () => getDefaultModel,
|
|
2594
2628
|
getIssueSource: () => getIssueSource,
|
|
2595
2629
|
getLinearApiKey: () => getLinearApiKey,
|
|
@@ -2663,6 +2697,12 @@ function normalizeDefaults(raw) {
|
|
|
2663
2697
|
const model = source.model.trim();
|
|
2664
2698
|
if (model) out.model = model;
|
|
2665
2699
|
}
|
|
2700
|
+
if (normalizeThinkingEffort(source.effort)) {
|
|
2701
|
+
out.effort = normalizeThinkingEffort(source.effort);
|
|
2702
|
+
}
|
|
2703
|
+
if (typeof source.fast === "boolean") {
|
|
2704
|
+
out.fast = source.fast;
|
|
2705
|
+
}
|
|
2666
2706
|
return out;
|
|
2667
2707
|
}
|
|
2668
2708
|
function normalizeAdvanced(raw) {
|
|
@@ -2841,6 +2881,21 @@ function updateDefaultsSettings(patch) {
|
|
|
2841
2881
|
defaults.model = patch.model.trim();
|
|
2842
2882
|
}
|
|
2843
2883
|
}
|
|
2884
|
+
if ("effort" in patch) {
|
|
2885
|
+
if (patch.effort == null) {
|
|
2886
|
+
delete defaults.effort;
|
|
2887
|
+
} else {
|
|
2888
|
+
const effort = normalizeThinkingEffort(patch.effort);
|
|
2889
|
+
if (effort) defaults.effort = effort;
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
if ("fast" in patch) {
|
|
2893
|
+
if (patch.fast == null) {
|
|
2894
|
+
delete defaults.fast;
|
|
2895
|
+
} else {
|
|
2896
|
+
defaults.fast = Boolean(patch.fast);
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2844
2899
|
return saveAppSettings({ ...current, defaults });
|
|
2845
2900
|
}
|
|
2846
2901
|
function getDefaultAgent(settings = loadAppSettings()) {
|
|
@@ -2850,10 +2905,18 @@ function getDefaultModel(settings = loadAppSettings()) {
|
|
|
2850
2905
|
const model = settings.defaults.model?.trim();
|
|
2851
2906
|
return model || null;
|
|
2852
2907
|
}
|
|
2908
|
+
function getDefaultEffort(settings = loadAppSettings()) {
|
|
2909
|
+
return normalizeThinkingEffort(settings.defaults.effort) ?? "high";
|
|
2910
|
+
}
|
|
2911
|
+
function getDefaultFast(settings = loadAppSettings()) {
|
|
2912
|
+
return settings.defaults.fast === true;
|
|
2913
|
+
}
|
|
2853
2914
|
function resolveThreadDefaults(settings = loadAppSettings()) {
|
|
2854
2915
|
return {
|
|
2855
2916
|
agent: getDefaultAgent(settings),
|
|
2856
|
-
model: getDefaultModel(settings)
|
|
2917
|
+
model: getDefaultModel(settings),
|
|
2918
|
+
effort: getDefaultEffort(settings),
|
|
2919
|
+
fast: getDefaultFast(settings)
|
|
2857
2920
|
};
|
|
2858
2921
|
}
|
|
2859
2922
|
function isLinearConnected(settings = loadAppSettings()) {
|
|
@@ -2977,6 +3040,7 @@ var init_app_settings = __esm({
|
|
|
2977
3040
|
import_node_fs5 = require("fs");
|
|
2978
3041
|
import_node_os4 = require("os");
|
|
2979
3042
|
import_node_path6 = require("path");
|
|
3043
|
+
init_thinking_effort();
|
|
2980
3044
|
init_paths();
|
|
2981
3045
|
HARNESS_ENV_KEYS = {
|
|
2982
3046
|
claude: "ANTHROPIC_API_KEY",
|
|
@@ -3171,8 +3235,9 @@ var init_coordinator_prompt = __esm({
|
|
|
3171
3235
|
"Setup / run:",
|
|
3172
3236
|
"- run_setup \u2014 re-run worktree setup",
|
|
3173
3237
|
"- list_run_scripts / run_dev_script / stop_dev_script \u2014 start/stop named run scripts",
|
|
3174
|
-
"Inspect / PRs:",
|
|
3238
|
+
"Inspect / review / PRs:",
|
|
3175
3239
|
"- get_diff \u2014 compact diff summary",
|
|
3240
|
+
"- request_review \u2014 open a Review chat tab on a worktree thread (merge-readiness recommendation); then wait_for_turn / get_turn_result on the returned id",
|
|
3176
3241
|
"- Ask the worktree agent via send_to_thread to open a draft PR with `gh pr create --draft -R <origin-owner/name>` (workspace `github:` slug / that worktree's origin \u2014 never upstream). Do not open PRs from the orchestrator yourself.",
|
|
3177
3242
|
"Human-only (do not attempt): merge, ready-for-review land, purge_thread.",
|
|
3178
3243
|
"Thread links in replies: when mentioning a chat/thread for the user, include a markdown link `[Title](sideboard://thread/<id>)` using the full id (or the link field from create_thread / list_threads). Sideboard renders these as clickable opens.",
|
|
@@ -3272,6 +3337,7 @@ function createGlobalChat(opts) {
|
|
|
3272
3337
|
agent: opts.agent,
|
|
3273
3338
|
autonomy: opts.autonomy ?? "default",
|
|
3274
3339
|
model: opts.model ?? null,
|
|
3340
|
+
effort: opts.effort ?? "high",
|
|
3275
3341
|
fast: Boolean(opts.fast),
|
|
3276
3342
|
planMode: Boolean(opts.planMode),
|
|
3277
3343
|
attachments: opts.attachments ?? [],
|
|
@@ -4382,9 +4448,8 @@ var init_claude = __esm({
|
|
|
4382
4448
|
if (thread.model) {
|
|
4383
4449
|
args.push("--model", thread.model);
|
|
4384
4450
|
}
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
}
|
|
4451
|
+
const effort = thread.effort ?? (thread.fast ? "low" : "high");
|
|
4452
|
+
args.push("--effort", effort);
|
|
4388
4453
|
if (sessionId) {
|
|
4389
4454
|
args.push("--resume", sessionId);
|
|
4390
4455
|
}
|
|
@@ -4972,6 +5037,7 @@ var init_cursor = __esm({
|
|
|
4972
5037
|
cwd: thread.worktreePath,
|
|
4973
5038
|
agentId,
|
|
4974
5039
|
model: thread.model,
|
|
5040
|
+
effort: thread.effort,
|
|
4975
5041
|
fast: thread.fast,
|
|
4976
5042
|
planMode: thread.planMode,
|
|
4977
5043
|
apiKey
|
|
@@ -5625,10 +5691,10 @@ __export(cursor_recover_exports, {
|
|
|
5625
5691
|
function recoverFinishedCursorRun(opts) {
|
|
5626
5692
|
const agentId = opts.agentId.trim();
|
|
5627
5693
|
if (!agentId) return null;
|
|
5628
|
-
const runsPath = (0,
|
|
5629
|
-
if (!(0,
|
|
5694
|
+
const runsPath = (0, import_node_path24.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
|
|
5695
|
+
if (!(0, import_node_fs25.existsSync)(runsPath)) return null;
|
|
5630
5696
|
try {
|
|
5631
|
-
const lines = (0,
|
|
5697
|
+
const lines = (0, import_node_fs25.readFileSync)(runsPath, "utf8").split("\n");
|
|
5632
5698
|
let best = null;
|
|
5633
5699
|
for (const line of lines) {
|
|
5634
5700
|
const trimmed = line.trim();
|
|
@@ -5654,12 +5720,12 @@ function recoverFinishedCursorRun(opts) {
|
|
|
5654
5720
|
return null;
|
|
5655
5721
|
}
|
|
5656
5722
|
}
|
|
5657
|
-
var
|
|
5723
|
+
var import_node_fs25, import_node_path24;
|
|
5658
5724
|
var init_cursor_recover = __esm({
|
|
5659
5725
|
"src/agents/cursor-recover.ts"() {
|
|
5660
5726
|
"use strict";
|
|
5661
|
-
|
|
5662
|
-
|
|
5727
|
+
import_node_fs25 = require("fs");
|
|
5728
|
+
import_node_path24 = require("path");
|
|
5663
5729
|
init_paths();
|
|
5664
5730
|
}
|
|
5665
5731
|
});
|
|
@@ -5668,11 +5734,11 @@ var init_cursor_recover = __esm({
|
|
|
5668
5734
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
5669
5735
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
5670
5736
|
var import_zod = require("zod");
|
|
5671
|
-
var
|
|
5737
|
+
var import_node_path25 = require("path");
|
|
5672
5738
|
|
|
5673
5739
|
// src/orchestrator/orchestrator.ts
|
|
5674
5740
|
var import_node_events = require("events");
|
|
5675
|
-
var
|
|
5741
|
+
var import_node_fs26 = require("fs");
|
|
5676
5742
|
init_error_detail();
|
|
5677
5743
|
|
|
5678
5744
|
// src/agents/spawn.ts
|
|
@@ -6703,6 +6769,7 @@ async function createThread(input, onSetupLine) {
|
|
|
6703
6769
|
agent: input.agent,
|
|
6704
6770
|
autonomy: input.autonomy ?? "default",
|
|
6705
6771
|
model: input.model ?? null,
|
|
6772
|
+
effort: input.effort ?? "high",
|
|
6706
6773
|
fast: Boolean(input.fast),
|
|
6707
6774
|
planMode: Boolean(input.planMode),
|
|
6708
6775
|
attachments: input.attachments ?? [],
|
|
@@ -7094,7 +7161,8 @@ function createChatTab(input) {
|
|
|
7094
7161
|
...binding,
|
|
7095
7162
|
agent: input.agent ?? from.agent,
|
|
7096
7163
|
model: input.model !== void 0 ? input.model : input.agent && input.agent !== from.agent ? null : from.model,
|
|
7097
|
-
|
|
7164
|
+
effort: input.effort !== void 0 ? input.effort : from.effort,
|
|
7165
|
+
fast: input.fast !== void 0 ? Boolean(input.fast) : from.fast,
|
|
7098
7166
|
planMode: from.planMode,
|
|
7099
7167
|
autonomy: input.autonomy ?? from.autonomy,
|
|
7100
7168
|
attachments: input.attachments ?? [],
|
|
@@ -7115,6 +7183,58 @@ function forkChatTab(input) {
|
|
|
7115
7183
|
});
|
|
7116
7184
|
}
|
|
7117
7185
|
|
|
7186
|
+
// src/review/request-review.ts
|
|
7187
|
+
var import_node_crypto3 = require("crypto");
|
|
7188
|
+
var import_node_fs19 = require("fs");
|
|
7189
|
+
var import_node_path18 = require("path");
|
|
7190
|
+
init_global_workspace();
|
|
7191
|
+
init_thread_store();
|
|
7192
|
+
var REVIEW_REQUEST_PATH = ".sideboard/attachments/Review request.md";
|
|
7193
|
+
var REVIEW_REQUEST_NAME = "Review request.md";
|
|
7194
|
+
var REVIEW_REQUEST_PREFILL = `Please review the changes in this workspace and recommend whether they are ready to merge.
|
|
7195
|
+
|
|
7196
|
+
Start with a **Recommendation**: Approve, Approve with nits, Request changes, or Needs more information \u2014 and say why in 1\u20133 sentences. Then list blocking findings vs nits (findings may be empty).`;
|
|
7197
|
+
function buildReviewRequestAttachment(content) {
|
|
7198
|
+
return {
|
|
7199
|
+
id: (0, import_node_crypto3.randomUUID)(),
|
|
7200
|
+
name: REVIEW_REQUEST_NAME,
|
|
7201
|
+
kind: "file",
|
|
7202
|
+
path: REVIEW_REQUEST_PATH,
|
|
7203
|
+
content
|
|
7204
|
+
};
|
|
7205
|
+
}
|
|
7206
|
+
function readExistingReviewRequestFile(worktreePath) {
|
|
7207
|
+
const abs = (0, import_node_path18.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
7208
|
+
if (!(0, import_node_fs19.existsSync)(abs)) return null;
|
|
7209
|
+
try {
|
|
7210
|
+
const content = (0, import_node_fs19.readFileSync)(abs, "utf8");
|
|
7211
|
+
return content.trim() ? content : null;
|
|
7212
|
+
} catch {
|
|
7213
|
+
return null;
|
|
7214
|
+
}
|
|
7215
|
+
}
|
|
7216
|
+
async function requestReview(threadRef, send) {
|
|
7217
|
+
const from = findThreadByRef(threadRef);
|
|
7218
|
+
if (!from) throw new Error(`Thread not found: ${threadRef}`);
|
|
7219
|
+
if (isOrchestratorThread(from)) {
|
|
7220
|
+
throw new Error(
|
|
7221
|
+
"request_review targets a worktree agent thread (not the orchestrator). Pass a child/worktree thread ref."
|
|
7222
|
+
);
|
|
7223
|
+
}
|
|
7224
|
+
if (from.status === "archived") {
|
|
7225
|
+
throw new Error(`Thread is archived: ${from.id}`);
|
|
7226
|
+
}
|
|
7227
|
+
const existing = readExistingReviewRequestFile(from.worktreePath);
|
|
7228
|
+
const attachments = existing ? [buildReviewRequestAttachment(existing)] : [];
|
|
7229
|
+
const tab = createChatTab({
|
|
7230
|
+
fromThreadId: from.id,
|
|
7231
|
+
title: "Review",
|
|
7232
|
+
attachments
|
|
7233
|
+
});
|
|
7234
|
+
const started = await send(tab.id, REVIEW_REQUEST_PREFILL);
|
|
7235
|
+
return { tab: started, from };
|
|
7236
|
+
}
|
|
7237
|
+
|
|
7118
7238
|
// src/threads/fork-worktree.ts
|
|
7119
7239
|
init_thread_store();
|
|
7120
7240
|
function requireThread2(idOrRef) {
|
|
@@ -7134,6 +7254,7 @@ async function forkThreadWorktree(input, onSetupLine) {
|
|
|
7134
7254
|
agent: input.agent ?? from.agent,
|
|
7135
7255
|
autonomy: from.autonomy,
|
|
7136
7256
|
model: from.model,
|
|
7257
|
+
effort: from.effort,
|
|
7137
7258
|
fast: from.fast,
|
|
7138
7259
|
planMode: from.planMode,
|
|
7139
7260
|
title: input.title?.trim() || void 0,
|
|
@@ -7147,20 +7268,20 @@ async function forkThreadWorktree(input, onSetupLine) {
|
|
|
7147
7268
|
|
|
7148
7269
|
// src/threads/adopt.ts
|
|
7149
7270
|
var import_node_child_process = require("child_process");
|
|
7150
|
-
var
|
|
7271
|
+
var import_node_fs20 = require("fs");
|
|
7151
7272
|
var import_node_os8 = require("os");
|
|
7152
|
-
var
|
|
7273
|
+
var import_node_path19 = require("path");
|
|
7153
7274
|
var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
7154
7275
|
init_worktree();
|
|
7155
7276
|
init_thread_store();
|
|
7156
|
-
var CONDUCTOR_APP_SUPPORT = (0,
|
|
7277
|
+
var CONDUCTOR_APP_SUPPORT = (0, import_node_path19.join)(
|
|
7157
7278
|
process.env.HOME ?? "",
|
|
7158
7279
|
"Library",
|
|
7159
7280
|
"Application Support",
|
|
7160
7281
|
"com.conductor.app"
|
|
7161
7282
|
);
|
|
7162
|
-
var CONDUCTOR_DB = (0,
|
|
7163
|
-
var CURSOR_SDK_STORE = (0,
|
|
7283
|
+
var CONDUCTOR_DB = (0, import_node_path19.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
7284
|
+
var CURSOR_SDK_STORE = (0, import_node_path19.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
7164
7285
|
function mapAgentType(raw) {
|
|
7165
7286
|
if (!raw) return null;
|
|
7166
7287
|
const v = raw.toLowerCase();
|
|
@@ -7172,21 +7293,21 @@ function mapAgentType(raw) {
|
|
|
7172
7293
|
return null;
|
|
7173
7294
|
}
|
|
7174
7295
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
7175
|
-
if (!workspacePath || !(0,
|
|
7296
|
+
if (!workspacePath || !(0, import_node_fs20.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
7176
7297
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
7177
7298
|
let best = null;
|
|
7178
7299
|
let hashes;
|
|
7179
7300
|
try {
|
|
7180
|
-
hashes = (0,
|
|
7301
|
+
hashes = (0, import_node_fs20.readdirSync)(CURSOR_SDK_STORE);
|
|
7181
7302
|
} catch {
|
|
7182
7303
|
return null;
|
|
7183
7304
|
}
|
|
7184
7305
|
for (const hash of hashes) {
|
|
7185
|
-
const agentsFile = (0,
|
|
7186
|
-
if (!(0,
|
|
7306
|
+
const agentsFile = (0, import_node_path19.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
7307
|
+
if (!(0, import_node_fs20.existsSync)(agentsFile)) continue;
|
|
7187
7308
|
let text;
|
|
7188
7309
|
try {
|
|
7189
|
-
text = (0,
|
|
7310
|
+
text = (0, import_node_fs20.readFileSync)(agentsFile, "utf8");
|
|
7190
7311
|
} catch {
|
|
7191
7312
|
continue;
|
|
7192
7313
|
}
|
|
@@ -7210,7 +7331,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
7210
7331
|
return best?.agentId ?? null;
|
|
7211
7332
|
}
|
|
7212
7333
|
async function adoptThread(input) {
|
|
7213
|
-
if (!(0,
|
|
7334
|
+
if (!(0, import_node_fs20.existsSync)(input.worktreePath)) {
|
|
7214
7335
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
7215
7336
|
}
|
|
7216
7337
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -7234,18 +7355,18 @@ async function adoptThread(input) {
|
|
|
7234
7355
|
return thread;
|
|
7235
7356
|
}
|
|
7236
7357
|
function listConductorWorkspaces() {
|
|
7237
|
-
if (!(0,
|
|
7358
|
+
if (!(0, import_node_fs20.existsSync)(CONDUCTOR_DB)) {
|
|
7238
7359
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
7239
7360
|
}
|
|
7240
|
-
const tmp = (0,
|
|
7241
|
-
const snapshot = (0,
|
|
7361
|
+
const tmp = (0, import_node_fs20.mkdtempSync)((0, import_node_path19.join)((0, import_node_os8.tmpdir)(), "sideboard-conductor-"));
|
|
7362
|
+
const snapshot = (0, import_node_path19.join)(tmp, "conductor.db");
|
|
7242
7363
|
try {
|
|
7243
|
-
(0,
|
|
7364
|
+
(0, import_node_fs20.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
7244
7365
|
for (const suffix of ["-wal", "-shm"]) {
|
|
7245
7366
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
7246
|
-
if ((0,
|
|
7367
|
+
if ((0, import_node_fs20.existsSync)(src)) {
|
|
7247
7368
|
try {
|
|
7248
|
-
(0,
|
|
7369
|
+
(0, import_node_fs20.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
7249
7370
|
} catch {
|
|
7250
7371
|
}
|
|
7251
7372
|
}
|
|
@@ -7321,22 +7442,22 @@ function listConductorWorkspaces() {
|
|
|
7321
7442
|
db.close();
|
|
7322
7443
|
}
|
|
7323
7444
|
} finally {
|
|
7324
|
-
(0,
|
|
7445
|
+
(0, import_node_fs20.rmSync)(tmp, { recursive: true, force: true });
|
|
7325
7446
|
}
|
|
7326
7447
|
}
|
|
7327
7448
|
function importConductorWorkspace(workspaceId) {
|
|
7328
|
-
if (!(0,
|
|
7449
|
+
if (!(0, import_node_fs20.existsSync)(CONDUCTOR_DB)) {
|
|
7329
7450
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
7330
7451
|
}
|
|
7331
|
-
const tmp = (0,
|
|
7332
|
-
const snapshot = (0,
|
|
7452
|
+
const tmp = (0, import_node_fs20.mkdtempSync)((0, import_node_path19.join)((0, import_node_os8.tmpdir)(), "sideboard-conductor-"));
|
|
7453
|
+
const snapshot = (0, import_node_path19.join)(tmp, "conductor.db");
|
|
7333
7454
|
try {
|
|
7334
|
-
(0,
|
|
7455
|
+
(0, import_node_fs20.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
7335
7456
|
for (const suffix of ["-wal", "-shm"]) {
|
|
7336
7457
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
7337
|
-
if ((0,
|
|
7458
|
+
if ((0, import_node_fs20.existsSync)(src)) {
|
|
7338
7459
|
try {
|
|
7339
|
-
(0,
|
|
7460
|
+
(0, import_node_fs20.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
7340
7461
|
} catch {
|
|
7341
7462
|
}
|
|
7342
7463
|
}
|
|
@@ -7354,7 +7475,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
7354
7475
|
).get(workspaceId);
|
|
7355
7476
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
7356
7477
|
const worktreePath = String(row.workspacePath);
|
|
7357
|
-
if (!(0,
|
|
7478
|
+
if (!(0, import_node_fs20.existsSync)(worktreePath)) {
|
|
7358
7479
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
7359
7480
|
}
|
|
7360
7481
|
let sessionId = null;
|
|
@@ -7417,7 +7538,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
7417
7538
|
db.close();
|
|
7418
7539
|
}
|
|
7419
7540
|
} finally {
|
|
7420
|
-
(0,
|
|
7541
|
+
(0, import_node_fs20.rmSync)(tmp, { recursive: true, force: true });
|
|
7421
7542
|
}
|
|
7422
7543
|
}
|
|
7423
7544
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
@@ -7428,12 +7549,12 @@ async function importConductorWorkspaceAsync(workspaceId) {
|
|
|
7428
7549
|
init_worktree();
|
|
7429
7550
|
|
|
7430
7551
|
// src/diff/diff.ts
|
|
7431
|
-
var
|
|
7432
|
-
var
|
|
7552
|
+
var import_node_fs21 = require("fs");
|
|
7553
|
+
var import_node_path20 = require("path");
|
|
7433
7554
|
init_run();
|
|
7434
7555
|
init_worktree();
|
|
7435
7556
|
async function inspectGitWorktree(worktreePath) {
|
|
7436
|
-
if (!worktreePath || !(0,
|
|
7557
|
+
if (!worktreePath || !(0, import_node_fs21.existsSync)(worktreePath)) return "missing_worktree";
|
|
7437
7558
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
7438
7559
|
reject: false
|
|
7439
7560
|
});
|
|
@@ -7441,7 +7562,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
7441
7562
|
return "ok";
|
|
7442
7563
|
}
|
|
7443
7564
|
async function initializeGitRepository(worktreePath) {
|
|
7444
|
-
if (!worktreePath || !(0,
|
|
7565
|
+
if (!worktreePath || !(0, import_node_fs21.existsSync)(worktreePath)) {
|
|
7445
7566
|
throw new Error("Worktree not found");
|
|
7446
7567
|
}
|
|
7447
7568
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -7873,8 +7994,8 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
|
|
|
7873
7994
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
7874
7995
|
assertSafeRelativePath(relativePath);
|
|
7875
7996
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
7876
|
-
const abs = (0,
|
|
7877
|
-
const st = (0,
|
|
7997
|
+
const abs = (0, import_node_path20.join)(worktreePath, relativePath);
|
|
7998
|
+
const st = (0, import_node_fs21.statSync)(abs);
|
|
7878
7999
|
if (!st.isFile()) {
|
|
7879
8000
|
throw new Error(`Not a file: ${relativePath}`);
|
|
7880
8001
|
}
|
|
@@ -7883,7 +8004,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
7883
8004
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
7884
8005
|
);
|
|
7885
8006
|
}
|
|
7886
|
-
const buf = (0,
|
|
8007
|
+
const buf = (0, import_node_fs21.readFileSync)(abs);
|
|
7887
8008
|
return {
|
|
7888
8009
|
path: relativePath,
|
|
7889
8010
|
contentBase64: buf.toString("base64"),
|
|
@@ -7893,12 +8014,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
7893
8014
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
7894
8015
|
assertSafeRelativePath(relativePath);
|
|
7895
8016
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
7896
|
-
const abs = (0,
|
|
7897
|
-
const st = (0,
|
|
8017
|
+
const abs = (0, import_node_path20.join)(worktreePath, relativePath);
|
|
8018
|
+
const st = (0, import_node_fs21.statSync)(abs);
|
|
7898
8019
|
if (!st.isFile()) {
|
|
7899
8020
|
throw new Error(`Not a file: ${relativePath}`);
|
|
7900
8021
|
}
|
|
7901
|
-
const buf = (0,
|
|
8022
|
+
const buf = (0, import_node_fs21.readFileSync)(abs);
|
|
7902
8023
|
if (isImageRelativePath(relativePath)) {
|
|
7903
8024
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
7904
8025
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -7941,9 +8062,9 @@ function assertSafeRelativePath(relativePath) {
|
|
|
7941
8062
|
}
|
|
7942
8063
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
7943
8064
|
assertSafeRelativePath(relativePath);
|
|
7944
|
-
const abs = (0,
|
|
7945
|
-
(0,
|
|
7946
|
-
(0,
|
|
8065
|
+
const abs = (0, import_node_path20.join)(worktreePath, relativePath);
|
|
8066
|
+
(0, import_node_fs21.mkdirSync)((0, import_node_path20.dirname)(abs), { recursive: true });
|
|
8067
|
+
(0, import_node_fs21.writeFileSync)(abs, content, "utf8");
|
|
7947
8068
|
return { path: relativePath };
|
|
7948
8069
|
}
|
|
7949
8070
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
@@ -8122,9 +8243,9 @@ async function confirmLand(thread, opts) {
|
|
|
8122
8243
|
}
|
|
8123
8244
|
|
|
8124
8245
|
// src/skills/discover.ts
|
|
8125
|
-
var
|
|
8246
|
+
var import_node_fs22 = require("fs");
|
|
8126
8247
|
var import_node_os9 = require("os");
|
|
8127
|
-
var
|
|
8248
|
+
var import_node_path21 = require("path");
|
|
8128
8249
|
function toCommand(name) {
|
|
8129
8250
|
return name.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
8130
8251
|
}
|
|
@@ -8156,7 +8277,7 @@ function parseFrontmatter(content) {
|
|
|
8156
8277
|
}
|
|
8157
8278
|
function readSkill(skillMd, source) {
|
|
8158
8279
|
try {
|
|
8159
|
-
const content = (0,
|
|
8280
|
+
const content = (0, import_node_fs22.readFileSync)(skillMd, "utf8");
|
|
8160
8281
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
8161
8282
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
8162
8283
|
const name = fmName || dirName;
|
|
@@ -8175,19 +8296,19 @@ function readSkill(skillMd, source) {
|
|
|
8175
8296
|
}
|
|
8176
8297
|
}
|
|
8177
8298
|
function scanSkillsDir(dir, source, out) {
|
|
8178
|
-
if (!(0,
|
|
8299
|
+
if (!(0, import_node_fs22.existsSync)(dir)) return;
|
|
8179
8300
|
let entries;
|
|
8180
8301
|
try {
|
|
8181
|
-
entries = (0,
|
|
8302
|
+
entries = (0, import_node_fs22.readdirSync)(dir);
|
|
8182
8303
|
} catch {
|
|
8183
8304
|
return;
|
|
8184
8305
|
}
|
|
8185
8306
|
for (const entry of entries) {
|
|
8186
8307
|
if (entry.startsWith(".")) continue;
|
|
8187
|
-
const skillMd = (0,
|
|
8188
|
-
if (!(0,
|
|
8308
|
+
const skillMd = (0, import_node_path21.join)(dir, entry, "SKILL.md");
|
|
8309
|
+
if (!(0, import_node_fs22.existsSync)(skillMd)) continue;
|
|
8189
8310
|
try {
|
|
8190
|
-
if (!(0,
|
|
8311
|
+
if (!(0, import_node_fs22.statSync)(skillMd).isFile()) continue;
|
|
8191
8312
|
} catch {
|
|
8192
8313
|
continue;
|
|
8193
8314
|
}
|
|
@@ -8196,24 +8317,24 @@ function scanSkillsDir(dir, source, out) {
|
|
|
8196
8317
|
}
|
|
8197
8318
|
}
|
|
8198
8319
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
8199
|
-
if (!(0,
|
|
8320
|
+
if (!(0, import_node_fs22.existsSync)(pluginsRoot)) return;
|
|
8200
8321
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
8201
8322
|
if (depth > 7) return;
|
|
8202
8323
|
let entries;
|
|
8203
8324
|
try {
|
|
8204
|
-
entries = (0,
|
|
8325
|
+
entries = (0, import_node_fs22.readdirSync)(dir);
|
|
8205
8326
|
} catch {
|
|
8206
8327
|
return;
|
|
8207
8328
|
}
|
|
8208
8329
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
8209
|
-
const skill = readSkill((0,
|
|
8330
|
+
const skill = readSkill((0, import_node_path21.join)(dir, "SKILL.md"), "cli");
|
|
8210
8331
|
if (skill) out.push(skill);
|
|
8211
8332
|
}
|
|
8212
8333
|
for (const entry of entries) {
|
|
8213
8334
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
8214
|
-
const full = (0,
|
|
8335
|
+
const full = (0, import_node_path21.join)(dir, entry);
|
|
8215
8336
|
try {
|
|
8216
|
-
if (!(0,
|
|
8337
|
+
if (!(0, import_node_fs22.statSync)(full).isDirectory()) continue;
|
|
8217
8338
|
} catch {
|
|
8218
8339
|
continue;
|
|
8219
8340
|
}
|
|
@@ -8231,17 +8352,17 @@ function discoverSkills(worktreePath) {
|
|
|
8231
8352
|
const home = (0, import_node_os9.homedir)();
|
|
8232
8353
|
const collected = [];
|
|
8233
8354
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
8234
|
-
scanSkillsDir((0,
|
|
8355
|
+
scanSkillsDir((0, import_node_path21.join)(worktreePath, rel), "workspace", collected);
|
|
8235
8356
|
}
|
|
8236
8357
|
for (const abs of [
|
|
8237
|
-
(0,
|
|
8238
|
-
(0,
|
|
8239
|
-
(0,
|
|
8240
|
-
(0,
|
|
8358
|
+
(0, import_node_path21.join)(home, ".claude/skills"),
|
|
8359
|
+
(0, import_node_path21.join)(home, ".cursor/skills"),
|
|
8360
|
+
(0, import_node_path21.join)(home, ".sideboard/skills"),
|
|
8361
|
+
(0, import_node_path21.join)(home, ".brightsy/skills")
|
|
8241
8362
|
]) {
|
|
8242
8363
|
scanSkillsDir(abs, "user", collected);
|
|
8243
8364
|
}
|
|
8244
|
-
scanClaudePluginSkills((0,
|
|
8365
|
+
scanClaudePluginSkills((0, import_node_path21.join)(home, ".claude/plugins"), collected);
|
|
8245
8366
|
const rank = { workspace: 0, user: 1, cli: 2 };
|
|
8246
8367
|
const byCommand = /* @__PURE__ */ new Map();
|
|
8247
8368
|
for (const skill of collected) {
|
|
@@ -8253,7 +8374,7 @@ function discoverSkills(worktreePath) {
|
|
|
8253
8374
|
return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
|
|
8254
8375
|
}
|
|
8255
8376
|
function readSkillBody(skillPath, maxChars = 12e3) {
|
|
8256
|
-
const raw = (0,
|
|
8377
|
+
const raw = (0, import_node_fs22.readFileSync)(skillPath, "utf8");
|
|
8257
8378
|
if (raw.startsWith("---")) {
|
|
8258
8379
|
const end = raw.indexOf("\n---", 3);
|
|
8259
8380
|
if (end >= 0) {
|
|
@@ -8346,9 +8467,9 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
|
|
|
8346
8467
|
}
|
|
8347
8468
|
|
|
8348
8469
|
// src/composer/stage-files.ts
|
|
8349
|
-
var
|
|
8350
|
-
var
|
|
8351
|
-
var
|
|
8470
|
+
var import_node_fs23 = require("fs");
|
|
8471
|
+
var import_node_path22 = require("path");
|
|
8472
|
+
var import_node_crypto4 = require("crypto");
|
|
8352
8473
|
var IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
8353
8474
|
"png",
|
|
8354
8475
|
"jpg",
|
|
@@ -8377,7 +8498,7 @@ var ATTACHMENTS_GITIGNORE = `# Sideboard review / composer attachments (local on
|
|
|
8377
8498
|
var MAX_INLINE_BYTES = 4e5;
|
|
8378
8499
|
var MAX_PREVIEW_BYTES = 5e6;
|
|
8379
8500
|
function fileExtension(filePath) {
|
|
8380
|
-
const base = (0,
|
|
8501
|
+
const base = (0, import_node_path22.basename)(filePath).toLowerCase();
|
|
8381
8502
|
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
8382
8503
|
}
|
|
8383
8504
|
function isImageFilePath(filePath) {
|
|
@@ -8387,24 +8508,24 @@ function imageMimeType(filePath) {
|
|
|
8387
8508
|
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
8388
8509
|
}
|
|
8389
8510
|
function ensureAttachmentsDir(worktreePath) {
|
|
8390
|
-
const dir = (0,
|
|
8391
|
-
(0,
|
|
8392
|
-
const gi = (0,
|
|
8393
|
-
if (!(0,
|
|
8394
|
-
(0,
|
|
8511
|
+
const dir = (0, import_node_path22.join)(worktreePath, ATTACHMENTS_DIR);
|
|
8512
|
+
(0, import_node_fs23.mkdirSync)(dir, { recursive: true });
|
|
8513
|
+
const gi = (0, import_node_path22.join)(dir, ".gitignore");
|
|
8514
|
+
if (!(0, import_node_fs23.existsSync)(gi)) {
|
|
8515
|
+
(0, import_node_fs23.writeFileSync)(gi, ATTACHMENTS_GITIGNORE, "utf8");
|
|
8395
8516
|
}
|
|
8396
8517
|
return dir;
|
|
8397
8518
|
}
|
|
8398
8519
|
function uniqueAttachmentName(dir, originalName) {
|
|
8399
8520
|
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
8400
|
-
if (!(0,
|
|
8401
|
-
const ext = (0,
|
|
8521
|
+
if (!(0, import_node_fs23.existsSync)((0, import_node_path22.join)(dir, safe))) return safe;
|
|
8522
|
+
const ext = (0, import_node_path22.extname)(safe);
|
|
8402
8523
|
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
8403
8524
|
for (let i = 1; i < 1e4; i++) {
|
|
8404
8525
|
const candidate = `${stem}-${i}${ext}`;
|
|
8405
|
-
if (!(0,
|
|
8526
|
+
if (!(0, import_node_fs23.existsSync)((0, import_node_path22.join)(dir, candidate))) return candidate;
|
|
8406
8527
|
}
|
|
8407
|
-
return `${stem}-${(0,
|
|
8528
|
+
return `${stem}-${(0, import_node_crypto4.randomUUID)()}${ext}`;
|
|
8408
8529
|
}
|
|
8409
8530
|
function previewDataUrlFromBuf(filePath, buf) {
|
|
8410
8531
|
if (!isImageFilePath(filePath)) return void 0;
|
|
@@ -8416,7 +8537,7 @@ function attachmentFromBuffer(name, buf, opts) {
|
|
|
8416
8537
|
if (isImageFilePath(name)) {
|
|
8417
8538
|
const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
|
|
8418
8539
|
return {
|
|
8419
|
-
id: (0,
|
|
8540
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
8420
8541
|
name,
|
|
8421
8542
|
kind: "file",
|
|
8422
8543
|
path: opts.path,
|
|
@@ -8429,7 +8550,7 @@ function attachmentFromBuffer(name, buf, opts) {
|
|
|
8429
8550
|
}
|
|
8430
8551
|
if (buf.length > MAX_INLINE_BYTES) {
|
|
8431
8552
|
return {
|
|
8432
|
-
id: (0,
|
|
8553
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
8433
8554
|
name,
|
|
8434
8555
|
kind: "file",
|
|
8435
8556
|
path: opts.path,
|
|
@@ -8438,7 +8559,7 @@ function attachmentFromBuffer(name, buf, opts) {
|
|
|
8438
8559
|
}
|
|
8439
8560
|
if (buf.includes(0)) {
|
|
8440
8561
|
return {
|
|
8441
|
-
id: (0,
|
|
8562
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
8442
8563
|
name,
|
|
8443
8564
|
kind: "file",
|
|
8444
8565
|
path: opts.path,
|
|
@@ -8446,7 +8567,7 @@ function attachmentFromBuffer(name, buf, opts) {
|
|
|
8446
8567
|
};
|
|
8447
8568
|
}
|
|
8448
8569
|
return {
|
|
8449
|
-
id: (0,
|
|
8570
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
8450
8571
|
name,
|
|
8451
8572
|
kind: "file",
|
|
8452
8573
|
path: opts.path,
|
|
@@ -8458,19 +8579,19 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
|
8458
8579
|
const dir = ensureAttachmentsDir(worktreePath);
|
|
8459
8580
|
const out = [];
|
|
8460
8581
|
for (const abs of absolutePaths) {
|
|
8461
|
-
const originalName = (0,
|
|
8582
|
+
const originalName = (0, import_node_path22.basename)(abs);
|
|
8462
8583
|
try {
|
|
8463
|
-
const st = (0,
|
|
8584
|
+
const st = (0, import_node_fs23.statSync)(abs);
|
|
8464
8585
|
if (!st.isFile()) continue;
|
|
8465
8586
|
const name = uniqueAttachmentName(dir, originalName);
|
|
8466
|
-
const destAbs = (0,
|
|
8467
|
-
(0,
|
|
8587
|
+
const destAbs = (0, import_node_path22.join)(dir, name);
|
|
8588
|
+
(0, import_node_fs23.copyFileSync)(abs, destAbs);
|
|
8468
8589
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
8469
|
-
const buf = (0,
|
|
8590
|
+
const buf = (0, import_node_fs23.readFileSync)(destAbs);
|
|
8470
8591
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
8471
8592
|
} catch (err) {
|
|
8472
8593
|
out.push({
|
|
8473
|
-
id: (0,
|
|
8594
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
8474
8595
|
name: originalName,
|
|
8475
8596
|
kind: "file",
|
|
8476
8597
|
content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
|
|
@@ -8488,13 +8609,13 @@ function stageBuffersAsAttachments(worktreePath, buffers) {
|
|
|
8488
8609
|
try {
|
|
8489
8610
|
const buf = Buffer.from(item.dataBase64, "base64");
|
|
8490
8611
|
const name = uniqueAttachmentName(dir, originalName);
|
|
8491
|
-
const destAbs = (0,
|
|
8492
|
-
(0,
|
|
8612
|
+
const destAbs = (0, import_node_path22.join)(dir, name);
|
|
8613
|
+
(0, import_node_fs23.writeFileSync)(destAbs, buf);
|
|
8493
8614
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
8494
8615
|
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
8495
8616
|
} catch (err) {
|
|
8496
8617
|
out.push({
|
|
8497
|
-
id: (0,
|
|
8618
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
8498
8619
|
name: originalName,
|
|
8499
8620
|
kind: "file",
|
|
8500
8621
|
content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
|
|
@@ -8508,23 +8629,23 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
|
8508
8629
|
for (const rel of relativePaths) {
|
|
8509
8630
|
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
8510
8631
|
out.push({
|
|
8511
|
-
id: (0,
|
|
8512
|
-
name: (0,
|
|
8632
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
8633
|
+
name: (0, import_node_path22.basename)(rel) || "file",
|
|
8513
8634
|
kind: "file",
|
|
8514
8635
|
content: `(invalid path: ${rel})`
|
|
8515
8636
|
});
|
|
8516
8637
|
continue;
|
|
8517
8638
|
}
|
|
8518
|
-
const name = (0,
|
|
8639
|
+
const name = (0, import_node_path22.basename)(rel);
|
|
8519
8640
|
try {
|
|
8520
|
-
const abs = (0,
|
|
8521
|
-
const st = (0,
|
|
8641
|
+
const abs = (0, import_node_path22.join)(worktreePath, rel);
|
|
8642
|
+
const st = (0, import_node_fs23.statSync)(abs);
|
|
8522
8643
|
if (!st.isFile()) continue;
|
|
8523
|
-
const buf = (0,
|
|
8644
|
+
const buf = (0, import_node_fs23.readFileSync)(abs);
|
|
8524
8645
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
8525
8646
|
} catch (err) {
|
|
8526
8647
|
out.push({
|
|
8527
|
-
id: (0,
|
|
8648
|
+
id: (0, import_node_crypto4.randomUUID)(),
|
|
8528
8649
|
name,
|
|
8529
8650
|
kind: "file",
|
|
8530
8651
|
content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
|
|
@@ -8535,8 +8656,8 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
|
8535
8656
|
}
|
|
8536
8657
|
|
|
8537
8658
|
// src/agents/instructions.ts
|
|
8538
|
-
var
|
|
8539
|
-
var
|
|
8659
|
+
var import_node_fs24 = require("fs");
|
|
8660
|
+
var import_node_path23 = require("path");
|
|
8540
8661
|
init_worktree_labels();
|
|
8541
8662
|
function normPath2(p) {
|
|
8542
8663
|
return p.replace(/\/+$/, "");
|
|
@@ -8675,11 +8796,11 @@ function loadAgentInstructions(worktreePath, agent) {
|
|
|
8675
8796
|
const out = [];
|
|
8676
8797
|
for (const rel of candidates) {
|
|
8677
8798
|
if (seen.has(rel)) continue;
|
|
8678
|
-
const abs = (0,
|
|
8679
|
-
if (!(0,
|
|
8799
|
+
const abs = (0, import_node_path23.join)(worktreePath, rel);
|
|
8800
|
+
if (!(0, import_node_fs24.existsSync)(abs)) continue;
|
|
8680
8801
|
try {
|
|
8681
|
-
if (!(0,
|
|
8682
|
-
let content = (0,
|
|
8802
|
+
if (!(0, import_node_fs24.statSync)(abs).isFile()) continue;
|
|
8803
|
+
let content = (0, import_node_fs24.readFileSync)(abs, "utf8");
|
|
8683
8804
|
if (!content.trim()) continue;
|
|
8684
8805
|
if (content.length > MAX_CHARS_PER_FILE) {
|
|
8685
8806
|
content = `${content.slice(0, MAX_CHARS_PER_FILE)}
|
|
@@ -8829,7 +8950,7 @@ var Orchestrator = class {
|
|
|
8829
8950
|
}
|
|
8830
8951
|
continue;
|
|
8831
8952
|
}
|
|
8832
|
-
if (!(0,
|
|
8953
|
+
if (!(0, import_node_fs26.existsSync)(thread.worktreePath)) {
|
|
8833
8954
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
8834
8955
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
8835
8956
|
continue;
|
|
@@ -9727,10 +9848,20 @@ var Orchestrator = class {
|
|
|
9727
9848
|
setAutonomy(threadRef, autonomy) {
|
|
9728
9849
|
return this.setThreadOptions(threadRef, { autonomy });
|
|
9729
9850
|
}
|
|
9851
|
+
/**
|
|
9852
|
+
* Open a Review chat tab on a worktree thread (same as the desktop Review button)
|
|
9853
|
+
* and send the merge-readiness prefill.
|
|
9854
|
+
*/
|
|
9855
|
+
async requestReview(threadRef) {
|
|
9856
|
+
const { tab } = await requestReview(threadRef, (ref, prompt) => this.send(ref, prompt));
|
|
9857
|
+
this.emit({ type: "status_changed", threadId: tab.id, status: tab.status });
|
|
9858
|
+
return tab;
|
|
9859
|
+
}
|
|
9730
9860
|
setThreadOptions(threadRef, patch) {
|
|
9731
9861
|
const thread = this.requireThread(threadRef);
|
|
9732
9862
|
const next = {};
|
|
9733
9863
|
if (patch.autonomy !== void 0) next.autonomy = patch.autonomy;
|
|
9864
|
+
if (patch.effort !== void 0) next.effort = patch.effort;
|
|
9734
9865
|
if (patch.fast !== void 0) next.fast = patch.fast;
|
|
9735
9866
|
if (patch.planMode !== void 0) next.planMode = patch.planMode;
|
|
9736
9867
|
if (patch.model !== void 0) next.model = patch.model;
|
|
@@ -9850,7 +9981,7 @@ var Orchestrator = class {
|
|
|
9850
9981
|
updateThread(thread.id, { worktreePath: globalAgentCwd2() });
|
|
9851
9982
|
return setStatus(thread.id, "idle");
|
|
9852
9983
|
}
|
|
9853
|
-
if (!(0,
|
|
9984
|
+
if (!(0, import_node_fs26.existsSync)(thread.worktreePath)) {
|
|
9854
9985
|
const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
|
|
9855
9986
|
const { execa: execa7 } = await import("execa");
|
|
9856
9987
|
const slug = thread.worktreePath.split("/").pop();
|
|
@@ -10068,7 +10199,7 @@ async function startMcpServer() {
|
|
|
10068
10199
|
async () => {
|
|
10069
10200
|
const threads = orch.getThreads(true);
|
|
10070
10201
|
const lines = threads.map((t) => {
|
|
10071
|
-
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0,
|
|
10202
|
+
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path25.basename)(t.repoPath) || t.repoPath;
|
|
10072
10203
|
return `${t.id.slice(0, 8)} ${t.status.padEnd(9)} ${t.agent.padEnd(8)} ${repo} ${t.sourceType}:${t.sourceRef} ${t.title} sideboard://thread/${t.id}${t.devPort ? ` http://localhost:${t.devPort}` : ""}`;
|
|
10073
10204
|
});
|
|
10074
10205
|
return {
|
|
@@ -10411,6 +10542,34 @@ async function startMcpServer() {
|
|
|
10411
10542
|
};
|
|
10412
10543
|
}
|
|
10413
10544
|
);
|
|
10545
|
+
server.tool(
|
|
10546
|
+
"request_review",
|
|
10547
|
+
"Start a merge-readiness Review on a worktree agent thread (same as the desktop Review button). Opens a new Review chat tab, optionally attaches .sideboard/attachments/Review request.md when present, and asks for Approve / Approve with nits / Request changes / Needs more information. Pass a worktree thread ref \u2014 not the orchestrator. Then wait_for_turn / get_turn_result on the returned review tab id.",
|
|
10548
|
+
{ ref: import_zod.z.string().describe("Worktree thread id/ref to review") },
|
|
10549
|
+
async ({ ref }) => {
|
|
10550
|
+
try {
|
|
10551
|
+
const tab = await orch.requestReview(ref);
|
|
10552
|
+
const from = orch.getThread(ref);
|
|
10553
|
+
return {
|
|
10554
|
+
content: [
|
|
10555
|
+
{
|
|
10556
|
+
type: "text",
|
|
10557
|
+
text: JSON.stringify({
|
|
10558
|
+
id: tab.id,
|
|
10559
|
+
title: tab.title,
|
|
10560
|
+
status: tab.status,
|
|
10561
|
+
fromThreadId: from?.id ?? ref,
|
|
10562
|
+
link: `sideboard://thread/${tab.id}`
|
|
10563
|
+
})
|
|
10564
|
+
}
|
|
10565
|
+
]
|
|
10566
|
+
};
|
|
10567
|
+
} catch (err) {
|
|
10568
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
10569
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
10570
|
+
}
|
|
10571
|
+
}
|
|
10572
|
+
);
|
|
10414
10573
|
server.tool(
|
|
10415
10574
|
"run_dev_script",
|
|
10416
10575
|
"Start a .sideboard/.conductor run script for a thread (default script if name omitted); returns port",
|