@sideboard-ai/core 0.1.294 → 0.1.296

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/agents/claude-runner.cjs +55 -0
  2. package/dist/agents/claude-runner.js +57 -1
  3. package/dist/agents/cursor-runner.cjs +128 -50
  4. package/dist/agents/cursor-runner.js +63 -44
  5. package/dist/{agents-2PDBDZPS.js → agents-DZTPUKVF.js} +5 -5
  6. package/dist/{agents-73JXQXF2.js → agents-ICHYDSCD.js} +8 -8
  7. package/dist/{chunk-SVQTKVXH.js → chunk-2O3ICR77.js} +4 -4
  8. package/dist/{chunk-YKO6HG74.js → chunk-67BWWLEB.js} +6 -6
  9. package/dist/{chunk-JEYJGQ33.js → chunk-6GTABVNG.js} +7 -7
  10. package/dist/{chunk-YEIPPZ5W.js → chunk-BGEECLKH.js} +2 -2
  11. package/dist/{chunk-AFLNFGGB.js → chunk-ED4ZXQVO.js} +1 -0
  12. package/dist/{chunk-MIVX7QKI.js → chunk-HO5R3ZRH.js} +1 -0
  13. package/dist/{chunk-7UUILVMV.js → chunk-IOY2LF3Y.js} +1 -1
  14. package/dist/{chunk-K6IOJI3L.js → chunk-J54UPHXZ.js} +71 -2
  15. package/dist/{chunk-ZEP6JIRF.js → chunk-JWXJXEA3.js} +1 -1
  16. package/dist/{chunk-YSLCWCMJ.js → chunk-Q3DPZ4DE.js} +1 -1
  17. package/dist/{chunk-NYBFYFK7.js → chunk-QDA6NXRA.js} +1 -0
  18. package/dist/{chunk-CECZUHA5.js → chunk-QT36F4TD.js} +55 -26
  19. package/dist/{chunk-YRXV3E7J.js → chunk-TVN4TDFB.js} +9 -0
  20. package/dist/{chunk-6SGYGYH7.js → chunk-VXNZG4J6.js} +1 -1
  21. package/dist/{chunk-BYAFYLLZ.js → chunk-W2A63ZOK.js} +179 -42
  22. package/dist/{chunk-E7G7RY6T.js → chunk-WQREAX35.js} +2 -2
  23. package/dist/{chunk-QB5MDOHL.js → chunk-WZLV4WNS.js} +9 -0
  24. package/dist/{chunk-BJUHZSZQ.js → chunk-ZXWRNA4G.js} +5 -5
  25. package/dist/{conductor-7DEMFEIO.js → conductor-HJFDYIZD.js} +5 -5
  26. package/dist/{conductor-ZQZTYXSX.js → conductor-ZXDIA6OF.js} +6 -6
  27. package/dist/{coordinator-prompt-AROMFCP2.js → coordinator-prompt-ILHSVPOG.js} +3 -3
  28. package/dist/{coordinator-prompt-K6XHUG3N.js → coordinator-prompt-L3V2CMWX.js} +3 -3
  29. package/dist/{global-workspace-4WAU4PAL.js → global-workspace-47G453ZU.js} +3 -3
  30. package/dist/{global-workspace-PX4GUVLW.js → global-workspace-NMRUGGFF.js} +3 -3
  31. package/dist/index.cjs +1039 -700
  32. package/dist/index.d.cts +25 -4
  33. package/dist/index.d.ts +25 -4
  34. package/dist/index.js +299 -125
  35. package/dist/mcp/run-stdio.cjs +250 -144
  36. package/dist/mcp/run-stdio.js +70 -11
  37. package/dist/{orchestrator-LIEGSQ6M.js → orchestrator-MR7TCIPP.js} +7 -7
  38. package/dist/{orchestrator-YNEEEP6O.js → orchestrator-ZQU62CES.js} +10 -10
  39. package/dist/{thread-store-DPKESDFR.js → thread-store-H6D6MDUM.js} +1 -1
  40. package/dist/{thread-store-X6S2GIR5.js → thread-store-SADLLKRE.js} +1 -1
  41. package/dist/{workspaces-MFU3IGAP.js → workspaces-PGY4UWZ3.js} +3 -3
  42. package/dist/{workspaces-U7SSD27C.js → workspaces-WGZPRQJX.js} +3 -3
  43. package/dist/{worktree-TQKASYPZ.js → worktree-3MF5J5XZ.js} +2 -2
  44. package/dist/{worktree-2VSHRI72.js → worktree-JZXDAKQF.js} +2 -2
  45. package/package.json +1 -1
@@ -776,30 +776,6 @@ var init_system_ca = __esm({
776
776
  }
777
777
  });
778
778
 
779
- // src/paths/workspace-scratch.ts
780
- function attachmentsGitignoreBody() {
781
- return ATTACHMENTS_GITIGNORE;
782
- }
783
- function isWorkspaceScratchPath(relativePath) {
784
- const p = relativePath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
785
- 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/");
786
- }
787
- var ATTACHMENTS_DIR, CLI_DIR, DETACHED_JOBS_DIR, LEGACY_ATTACHMENTS_DIR, LEGACY_DETACHED_JOBS_DIR, ATTACHMENTS_GITIGNORE;
788
- var init_workspace_scratch = __esm({
789
- "src/paths/workspace-scratch.ts"() {
790
- "use strict";
791
- ATTACHMENTS_DIR = ".context/attachments";
792
- CLI_DIR = ".context/cli";
793
- DETACHED_JOBS_DIR = ".context/.sideboard/detached-jobs";
794
- LEGACY_ATTACHMENTS_DIR = ".sideboard/attachments";
795
- LEGACY_DETACHED_JOBS_DIR = ".sideboard/detached-jobs";
796
- ATTACHMENTS_GITIGNORE = `# Sideboard / workspace attachments (local only)
797
- *
798
- !.gitignore
799
- `;
800
- }
801
- });
802
-
803
779
  // src/agents/cursor-stream-cutoff.ts
804
780
  function looksLikeCursorStreamCutOff(text7) {
805
781
  return CURSOR_STREAM_CUTOFF.test(text7.trim());
@@ -1200,6 +1176,30 @@ var init_error_detail = __esm({
1200
1176
  }
1201
1177
  });
1202
1178
 
1179
+ // src/paths/workspace-scratch.ts
1180
+ function attachmentsGitignoreBody() {
1181
+ return ATTACHMENTS_GITIGNORE;
1182
+ }
1183
+ function isWorkspaceScratchPath(relativePath) {
1184
+ const p = relativePath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
1185
+ 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/");
1186
+ }
1187
+ var ATTACHMENTS_DIR, CLI_DIR, DETACHED_JOBS_DIR, LEGACY_ATTACHMENTS_DIR, LEGACY_DETACHED_JOBS_DIR, ATTACHMENTS_GITIGNORE;
1188
+ var init_workspace_scratch = __esm({
1189
+ "src/paths/workspace-scratch.ts"() {
1190
+ "use strict";
1191
+ ATTACHMENTS_DIR = ".context/attachments";
1192
+ CLI_DIR = ".context/cli";
1193
+ DETACHED_JOBS_DIR = ".context/.sideboard/detached-jobs";
1194
+ LEGACY_ATTACHMENTS_DIR = ".sideboard/attachments";
1195
+ LEGACY_DETACHED_JOBS_DIR = ".sideboard/detached-jobs";
1196
+ ATTACHMENTS_GITIGNORE = `# Sideboard / workspace attachments (local only)
1197
+ *
1198
+ !.gitignore
1199
+ `;
1200
+ }
1201
+ });
1202
+
1203
1203
  // src/agents/message-parts.ts
1204
1204
  function asRecord(input) {
1205
1205
  if (input && typeof input === "object" && !Array.isArray(input)) {
@@ -3460,9 +3460,18 @@ function branchDisplayLabel(branchName, worktreePath) {
3460
3460
  }
3461
3461
  return branchName.trim();
3462
3462
  }
3463
+ function taskPurposeTitle(title) {
3464
+ const trimmed = title?.trim() ?? "";
3465
+ if (!trimmed || teamSlugFromName(trimmed)) return null;
3466
+ return trimmed;
3467
+ }
3463
3468
  function threadDisplayLabel(thread) {
3464
3469
  if (thread.userSetTitle && thread.title?.trim()) return thread.title.trim();
3465
3470
  if (thread.prTitle?.trim()) return thread.prTitle.trim();
3471
+ if (isPlaceholderBranch(thread.branchName, thread.worktreePath)) {
3472
+ const purpose = taskPurposeTitle(thread.title);
3473
+ if (purpose) return purpose;
3474
+ }
3466
3475
  return branchDisplayLabel(thread.branchName, thread.worktreePath);
3467
3476
  }
3468
3477
  function worktreeDisplayLabel(thread) {
@@ -3480,16 +3489,16 @@ function agentNicknameFromWorktreePath(worktreePath) {
3480
3489
  }
3481
3490
  function worktreeIdentityTitles(thread, parentTitle) {
3482
3491
  const out = [];
3483
- const push = (value) => {
3492
+ const push2 = (value) => {
3484
3493
  const trimmed = value?.trim();
3485
3494
  if (trimmed) out.push(trimmed);
3486
3495
  };
3487
- push(parentTitle);
3488
- push(thread.prTitle);
3496
+ push2(parentTitle);
3497
+ push2(thread.prTitle);
3489
3498
  const branch = thread.branchName?.trim() ?? "";
3490
3499
  const path = thread.worktreePath?.trim() ?? "";
3491
3500
  if (branch && path && branch !== "HEAD" && !isPlaceholderBranch(branch, path)) {
3492
- push(branch);
3501
+ push2(branch);
3493
3502
  }
3494
3503
  return out;
3495
3504
  }
@@ -3758,14 +3767,14 @@ function legacyRoleLabels(roles, legacyRole) {
3758
3767
  const raw = Array.isArray(roles) ? roles : [];
3759
3768
  const out = [];
3760
3769
  const seen = /* @__PURE__ */ new Set();
3761
- const push = (value) => {
3770
+ const push2 = (value) => {
3762
3771
  const role = normalizeLegacyRole(typeof value === "string" ? value : "");
3763
3772
  if (!role || seen.has(role) || out.length >= 16) return;
3764
3773
  seen.add(role);
3765
3774
  out.push(legacyRoleLabel(role));
3766
3775
  };
3767
- for (const item of raw) push(item);
3768
- if (out.length === 0) push(legacyRole);
3776
+ for (const item of raw) push2(item);
3777
+ if (out.length === 0) push2(legacyRole);
3769
3778
  return out;
3770
3779
  }
3771
3780
  function normalizeProfileNotes(value) {
@@ -7991,20 +8000,20 @@ function isDefaultishSourceRef(ref) {
7991
8000
  }
7992
8001
  function resolvePrSelectors(thread) {
7993
8002
  const out = [];
7994
- const push = (value) => {
8003
+ const push2 = (value) => {
7995
8004
  const v = value?.trim();
7996
8005
  if (!v || out.includes(v)) return;
7997
8006
  out.push(v);
7998
8007
  };
7999
- push(thread.prUrl);
8008
+ push2(thread.prUrl);
8000
8009
  if (thread.sourceType === "pr" && thread.sourceRef?.trim()) {
8001
- push(thread.sourceRef.replace(/^#/, "").trim());
8010
+ push2(thread.sourceRef.replace(/^#/, "").trim());
8002
8011
  }
8003
- push(thread.branchName);
8012
+ push2(thread.branchName);
8004
8013
  if (thread.sourceType === "branch") {
8005
8014
  const source = normalizeGitBranchName(thread.sourceRef ?? "");
8006
8015
  if (source && !isDefaultishSourceRef(source) && source !== thread.branchName?.trim()) {
8007
- push(source);
8016
+ push2(source);
8008
8017
  }
8009
8018
  }
8010
8019
  return out;
@@ -8014,13 +8023,13 @@ function resolvePrSelector(thread) {
8014
8023
  }
8015
8024
  function connectedPrSelectors(thread, currentHeadPrUrl) {
8016
8025
  const out = [];
8017
- const push = (value) => {
8026
+ const push2 = (value) => {
8018
8027
  const v = value?.trim();
8019
8028
  if (!v || out.includes(v)) return;
8020
8029
  out.push(v);
8021
8030
  };
8022
- push(currentHeadPrUrl);
8023
- for (const selector of resolvePrSelectors(thread)) push(selector);
8031
+ push2(currentHeadPrUrl);
8032
+ for (const selector of resolvePrSelectors(thread)) push2(selector);
8024
8033
  return out;
8025
8034
  }
8026
8035
  async function getPrForHeadBranch(repoPath, branch) {
@@ -14966,6 +14975,7 @@ async function spawnAgentTurn(thread, input, onEvent) {
14966
14975
  }
14967
14976
  applyManagedAccountEnv(env, thread.agent, resolveAccountForThread(thread, accounts));
14968
14977
  sanitizeAgentHostEnv(env, cmd.cwd);
14978
+ env[SIDEBOARD_THREAD_ID_ENV] = thread.id;
14969
14979
  ensureAgentPath(env);
14970
14980
  applyPromptCacheTtlEnv(thread.agent, env);
14971
14981
  applyAgentRunnerHeapEnv(env);
@@ -15103,6 +15113,7 @@ var init_spawn = __esm({
15103
15113
  init_message_parts();
15104
15114
  init_stdout_replay();
15105
15115
  init_agent_host_env();
15116
+ init_profile();
15106
15117
  init_worktree_pkg_cache();
15107
15118
  init_node_launch();
15108
15119
  init_path();
@@ -18189,6 +18200,37 @@ var init_desktop_host = __esm({
18189
18200
  }
18190
18201
  });
18191
18202
 
18203
+ // src/agents/tool-permission.ts
18204
+ function setToolPermissionPublisher(next) {
18205
+ publisher = next;
18206
+ }
18207
+ function denied(message) {
18208
+ return { behavior: "deny", message, decisionClassification: "user_reject" };
18209
+ }
18210
+ function clearPrompt(threadId, id) {
18211
+ publisher?.clear(threadId, id);
18212
+ }
18213
+ function denyPendingToolPermissions(threadId) {
18214
+ const q = queues.get(threadId);
18215
+ if (!q?.length) return;
18216
+ const pending = q.splice(0, q.length);
18217
+ queues.delete(threadId);
18218
+ const answer = denied("The turn ended before this was allowed.");
18219
+ for (const item of pending) item.resolve(answer);
18220
+ const last = pending[pending.length - 1];
18221
+ if (last) clearPrompt(threadId, last.id);
18222
+ }
18223
+ var import_node_crypto10, import_node_path52, queues, publisher;
18224
+ var init_tool_permission = __esm({
18225
+ "src/agents/tool-permission.ts"() {
18226
+ "use strict";
18227
+ import_node_crypto10 = require("crypto");
18228
+ import_node_path52 = require("path");
18229
+ queues = /* @__PURE__ */ new Map();
18230
+ publisher = null;
18231
+ }
18232
+ });
18233
+
18192
18234
  // src/plan/plan-present.ts
18193
18235
  function asRecord5(v) {
18194
18236
  return v != null && typeof v === "object" && !Array.isArray(v) ? v : null;
@@ -18416,6 +18458,7 @@ function writeAgentBlock(threadId, block) {
18416
18458
  updateThread(threadId, { agentBlock: block });
18417
18459
  }
18418
18460
  function settleAgentBlock(threadId, parts, failed) {
18461
+ denyPendingToolPermissions(threadId);
18419
18462
  const thread = readThread(threadId);
18420
18463
  if (!thread || thread.status === "archived") return;
18421
18464
  const next = agentBlockAfterTurn({
@@ -18467,6 +18510,7 @@ var MAX_AGENT_BLOCK_REASON;
18467
18510
  var init_agent_block = __esm({
18468
18511
  "src/orchestrator/agent-block.ts"() {
18469
18512
  "use strict";
18513
+ init_tool_permission();
18470
18514
  init_ask_user();
18471
18515
  init_plan_present();
18472
18516
  init_thread_store();
@@ -18560,7 +18604,7 @@ function isUnclaimedSteerRequest(req) {
18560
18604
  }
18561
18605
  function nextSteerRequest(existing) {
18562
18606
  if (existing?.requestId && !existing.claimedAt) return existing;
18563
- return { requestId: (0, import_node_crypto10.randomUUID)(), requestedAt: (/* @__PURE__ */ new Date()).toISOString() };
18607
+ return { requestId: (0, import_node_crypto11.randomUUID)(), requestedAt: (/* @__PURE__ */ new Date()).toISOString() };
18564
18608
  }
18565
18609
  function claimSteerRequest(threadId) {
18566
18610
  const pending = readThread(threadId)?.steerRequest;
@@ -18569,11 +18613,11 @@ function claimSteerRequest(threadId) {
18569
18613
  steerRequest: { ...pending, claimedAt: (/* @__PURE__ */ new Date()).toISOString() }
18570
18614
  });
18571
18615
  }
18572
- var import_node_crypto10;
18616
+ var import_node_crypto11;
18573
18617
  var init_steer_request = __esm({
18574
18618
  "src/orchestrator/steer-request.ts"() {
18575
18619
  "use strict";
18576
- import_node_crypto10 = require("crypto");
18620
+ import_node_crypto11 = require("crypto");
18577
18621
  init_thread_store();
18578
18622
  }
18579
18623
  });
@@ -18612,7 +18656,6 @@ var init_title = __esm({
18612
18656
  // src/threads/agent-purpose-title.ts
18613
18657
  function agentPurposeStamp(input) {
18614
18658
  if (input.autoContinue) return null;
18615
- if (input.thread.sourceType === "orchestration") return null;
18616
18659
  if (input.thread.title.trim() === REVIEW_TAB_TITLE) return null;
18617
18660
  const identities = worktreeIdentityTitles(input.thread);
18618
18661
  const titled = input.thread.title?.trim() || "";
@@ -19343,8 +19386,8 @@ function resolveAbleTimeOAuthHost(requested, saved) {
19343
19386
  return fromSaved || void 0;
19344
19387
  }
19345
19388
  function createAbleTimePkce() {
19346
- const verifier = (0, import_node_crypto11.randomBytes)(32).toString("base64url");
19347
- const challenge = (0, import_node_crypto11.createHash)("sha256").update(verifier).digest("base64url");
19389
+ const verifier = (0, import_node_crypto12.randomBytes)(32).toString("base64url");
19390
+ const challenge = (0, import_node_crypto12.createHash)("sha256").update(verifier).digest("base64url");
19348
19391
  return { verifier, challenge };
19349
19392
  }
19350
19393
  function ableTimeOAuthAuthorizeUrl(clientId, state, codeChallenge, host) {
@@ -19449,7 +19492,7 @@ async function startAbleTimeOAuth(opts) {
19449
19492
  opts?.host,
19450
19493
  loadAppSettings().integrations.abletimeHost
19451
19494
  );
19452
- const state = (0, import_node_crypto11.randomBytes)(16).toString("hex");
19495
+ const state = (0, import_node_crypto12.randomBytes)(16).toString("hex");
19453
19496
  const pkce = createAbleTimePkce();
19454
19497
  const authorizeUrl = ableTimeOAuthAuthorizeUrl(clientId, state, pkce.challenge, host);
19455
19498
  const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
@@ -19549,11 +19592,11 @@ async function startAbleTimeOAuth(opts) {
19549
19592
  return loadAppSettings();
19550
19593
  }
19551
19594
  }
19552
- var import_node_crypto11, import_node_http, ABLETIME_OAUTH_CALLBACK_PATH, ABLETIME_OAUTH_PORT, ABLETIME_OAUTH_LOCAL_CALLBACK, ABLETIME_OAUTH_REDIRECT, BOUNCE_QUERY_KEYS, BAKED_ABLETIME_OAUTH_CLIENT_ID, ABLETIME_OAUTH_RESOURCE, REFRESH_SKEW_MS2, refreshInFlight2, ABLETIME_OAUTH_CANCELLED, AbleTimeOAuthCancelledError;
19595
+ var import_node_crypto12, import_node_http, ABLETIME_OAUTH_CALLBACK_PATH, ABLETIME_OAUTH_PORT, ABLETIME_OAUTH_LOCAL_CALLBACK, ABLETIME_OAUTH_REDIRECT, BOUNCE_QUERY_KEYS, BAKED_ABLETIME_OAUTH_CLIENT_ID, ABLETIME_OAUTH_RESOURCE, REFRESH_SKEW_MS2, refreshInFlight2, ABLETIME_OAUTH_CANCELLED, AbleTimeOAuthCancelledError;
19553
19596
  var init_abletime_oauth = __esm({
19554
19597
  "src/integrations/abletime-oauth.ts"() {
19555
19598
  "use strict";
19556
- import_node_crypto11 = require("crypto");
19599
+ import_node_crypto12 = require("crypto");
19557
19600
  import_node_http = require("http");
19558
19601
  init_fetch();
19559
19602
  init_app_settings();
@@ -20250,9 +20293,9 @@ function issueAttachmentWorktreePath(repoPath) {
20250
20293
  return raw || process.cwd();
20251
20294
  }
20252
20295
  function ensureIssueAttachmentsDir(worktreePath) {
20253
- const dir = (0, import_node_path52.join)(worktreePath, ATTACHMENTS_DIR);
20296
+ const dir = (0, import_node_path53.join)(worktreePath, ATTACHMENTS_DIR);
20254
20297
  (0, import_node_fs52.mkdirSync)(dir, { recursive: true });
20255
- const gi = (0, import_node_path52.join)(dir, ".gitignore");
20298
+ const gi = (0, import_node_path53.join)(dir, ".gitignore");
20256
20299
  if (!(0, import_node_fs52.existsSync)(gi)) {
20257
20300
  (0, import_node_fs52.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
20258
20301
  }
@@ -20284,7 +20327,7 @@ function looksLikeFileUrl(url) {
20284
20327
  function filenameFromUrl(url, fallback = "attachment") {
20285
20328
  try {
20286
20329
  const parsed = new URL(url);
20287
- const last = decodeURIComponent((0, import_node_path52.basename)(parsed.pathname)).replace(/[/\\]/g, "_");
20330
+ const last = decodeURIComponent((0, import_node_path53.basename)(parsed.pathname)).replace(/[/\\]/g, "_");
20288
20331
  if (last && last !== "/" && last !== ".") return last;
20289
20332
  } catch {
20290
20333
  }
@@ -20306,21 +20349,21 @@ function filenameFromContentDisposition(header) {
20306
20349
  }
20307
20350
  function uniqueAttachmentFileName(dir, originalName) {
20308
20351
  const safe = originalName.replace(/[/\\]/g, "_").replace(/^\.+/, "") || "file";
20309
- if (!(0, import_node_fs52.existsSync)((0, import_node_path52.join)(dir, safe))) return safe;
20310
- const ext = (0, import_node_path52.extname)(safe);
20352
+ if (!(0, import_node_fs52.existsSync)((0, import_node_path53.join)(dir, safe))) return safe;
20353
+ const ext = (0, import_node_path53.extname)(safe);
20311
20354
  const stem = ext ? safe.slice(0, -ext.length) : safe;
20312
20355
  for (let i = 1; i < 1e4; i++) {
20313
20356
  const candidate = `${stem}-${i}${ext}`;
20314
- if (!(0, import_node_fs52.existsSync)((0, import_node_path52.join)(dir, candidate))) return candidate;
20357
+ if (!(0, import_node_fs52.existsSync)((0, import_node_path53.join)(dir, candidate))) return candidate;
20315
20358
  }
20316
- return `${stem}-${(0, import_node_crypto12.randomUUID)()}${ext}`;
20359
+ return `${stem}-${(0, import_node_crypto13.randomUUID)()}${ext}`;
20317
20360
  }
20318
20361
  function extractHttpUrls(markdown) {
20319
20362
  const text7 = markdown ?? "";
20320
20363
  if (!text7.trim()) return [];
20321
20364
  const found = [];
20322
20365
  const seen = /* @__PURE__ */ new Set();
20323
- const push = (raw) => {
20366
+ const push2 = (raw) => {
20324
20367
  const url = raw.replace(/[).,;]+$/, "");
20325
20368
  if (!looksLikeHttpUrl(url) || seen.has(url)) return;
20326
20369
  seen.add(url);
@@ -20330,8 +20373,8 @@ function extractHttpUrls(markdown) {
20330
20373
  re.lastIndex = 0;
20331
20374
  let match;
20332
20375
  while (match = re.exec(text7)) {
20333
- if (match[1]) push(match[1]);
20334
- else if (re === BARE_URL_RE) push(match[0]);
20376
+ if (match[1]) push2(match[1]);
20377
+ else if (re === BARE_URL_RE) push2(match[0]);
20335
20378
  }
20336
20379
  }
20337
20380
  return found;
@@ -20359,7 +20402,7 @@ function mergeIssueAttachments(items) {
20359
20402
  return out;
20360
20403
  }
20361
20404
  function extensionForContentType(contentType, name) {
20362
- if ((0, import_node_path52.extname)(name)) return name;
20405
+ if ((0, import_node_path53.extname)(name)) return name;
20363
20406
  const mime = (contentType ?? "").split(";")[0]?.trim().toLowerCase() ?? "";
20364
20407
  const ext = EXT_BY_MIME[mime];
20365
20408
  return ext ? `${name}${ext}` : name;
@@ -20411,7 +20454,7 @@ async function downloadAuthenticatedFile(opts) {
20411
20454
  const dir = ensureIssueAttachmentsDir(opts.worktreePath);
20412
20455
  const hinted = opts.name?.trim() || filenameFromContentDisposition(res.headers.get("content-disposition")) || filenameFromUrl(url);
20413
20456
  const name = uniqueAttachmentFileName(dir, extensionForContentType(contentType, hinted));
20414
- (0, import_node_fs52.writeFileSync)((0, import_node_path52.join)(dir, name), buf);
20457
+ (0, import_node_fs52.writeFileSync)((0, import_node_path53.join)(dir, name), buf);
20415
20458
  return {
20416
20459
  name,
20417
20460
  path: `${ATTACHMENTS_DIR}/${name}`,
@@ -20419,13 +20462,13 @@ async function downloadAuthenticatedFile(opts) {
20419
20462
  ...contentType ? { contentType } : {}
20420
20463
  };
20421
20464
  }
20422
- var import_node_fs52, import_node_path52, import_node_crypto12, ISSUE_ATTACHMENT_MAX_BYTES, MARKDOWN_IMAGE_RE, MARKDOWN_LINK_RE, HTML_SRC_RE, BARE_URL_RE, EXT_BY_MIME;
20465
+ var import_node_fs52, import_node_path53, import_node_crypto13, ISSUE_ATTACHMENT_MAX_BYTES, MARKDOWN_IMAGE_RE, MARKDOWN_LINK_RE, HTML_SRC_RE, BARE_URL_RE, EXT_BY_MIME;
20423
20466
  var init_issue_attachments = __esm({
20424
20467
  "src/integrations/issue-attachments.ts"() {
20425
20468
  "use strict";
20426
20469
  import_node_fs52 = require("fs");
20427
- import_node_path52 = require("path");
20428
- import_node_crypto12 = require("crypto");
20470
+ import_node_path53 = require("path");
20471
+ import_node_crypto13 = require("crypto");
20429
20472
  init_fetch();
20430
20473
  init_workspace_scratch();
20431
20474
  ISSUE_ATTACHMENT_MAX_BYTES = 25 * 1024 * 1024;
@@ -21409,7 +21452,7 @@ function createLineCoalescer(onChunk, opts) {
21409
21452
  buffer = [];
21410
21453
  onChunk(chunk);
21411
21454
  };
21412
- const push = (line) => {
21455
+ const push2 = (line) => {
21413
21456
  buffer.push(line);
21414
21457
  if (buffer.length >= maxLines) {
21415
21458
  flush2();
@@ -21417,7 +21460,7 @@ function createLineCoalescer(onChunk, opts) {
21417
21460
  }
21418
21461
  if (!timer) timer = setTimeout(flush2, delayMs);
21419
21462
  };
21420
- return { push, flush: flush2 };
21463
+ return { push: push2, flush: flush2 };
21421
21464
  }
21422
21465
  var init_line_coalescer = __esm({
21423
21466
  "src/util/line-coalescer.ts"() {
@@ -21752,7 +21795,7 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
21752
21795
  ...instructions
21753
21796
  ].join("\n");
21754
21797
  return {
21755
- id: (0, import_node_crypto13.randomUUID)(),
21798
+ id: (0, import_node_crypto14.randomUUID)(),
21756
21799
  name: orch ? "Orchestration quota handoff.md" : "Quota handoff.md",
21757
21800
  kind: "transcript",
21758
21801
  content: body
@@ -21784,11 +21827,11 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText, opts) {
21784
21827
  }
21785
21828
  return updateThread(tab.id, patch);
21786
21829
  }
21787
- var import_node_crypto13, QUOTA_CONTINUE_PROMPT, QUOTA_CONTINUE_ACCOUNT_PROMPT, QUOTA_RESUME_PROMPT;
21830
+ var import_node_crypto14, QUOTA_CONTINUE_PROMPT, QUOTA_CONTINUE_ACCOUNT_PROMPT, QUOTA_RESUME_PROMPT;
21788
21831
  var init_quota_failover = __esm({
21789
21832
  "src/orchestrator/quota-failover.ts"() {
21790
21833
  "use strict";
21791
- import_node_crypto13 = require("crypto");
21834
+ import_node_crypto14 = require("crypto");
21792
21835
  init_session_quota();
21793
21836
  init_app_settings();
21794
21837
  init_managed_accounts();
@@ -21810,7 +21853,7 @@ var init_quota_failover = __esm({
21810
21853
  // src/threads/adopt.ts
21811
21854
  function thisModuleFile2() {
21812
21855
  const cjsFile = typeof __filename !== "undefined" ? __filename : "";
21813
- return cjsFile || process.argv[1] || (0, import_node_path53.join)(process.cwd(), "package.json");
21856
+ return cjsFile || process.argv[1] || (0, import_node_path54.join)(process.cwd(), "package.json");
21814
21857
  }
21815
21858
  function openReadonlySqlite(file) {
21816
21859
  const req = (0, import_node_module6.createRequire)(thisModuleFile2());
@@ -21838,7 +21881,7 @@ function resolveConductorCursorAgentId(workspacePath) {
21838
21881
  return null;
21839
21882
  }
21840
21883
  for (const hash of hashes) {
21841
- const agentsFile = (0, import_node_path53.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
21884
+ const agentsFile = (0, import_node_path54.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
21842
21885
  if (!(0, import_node_fs55.existsSync)(agentsFile)) continue;
21843
21886
  let text7;
21844
21887
  try {
@@ -21895,8 +21938,8 @@ function listConductorWorkspaces() {
21895
21938
  if (!(0, import_node_fs55.existsSync)(CONDUCTOR_DB)) {
21896
21939
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
21897
21940
  }
21898
- const tmp = (0, import_node_fs55.mkdtempSync)((0, import_node_path53.join)((0, import_node_os16.tmpdir)(), "sideboard-conductor-"));
21899
- const snapshot = (0, import_node_path53.join)(tmp, "conductor.db");
21941
+ const tmp = (0, import_node_fs55.mkdtempSync)((0, import_node_path54.join)((0, import_node_os16.tmpdir)(), "sideboard-conductor-"));
21942
+ const snapshot = (0, import_node_path54.join)(tmp, "conductor.db");
21900
21943
  try {
21901
21944
  (0, import_node_fs55.copyFileSync)(CONDUCTOR_DB, snapshot);
21902
21945
  for (const suffix of ["-wal", "-shm"]) {
@@ -21986,8 +22029,8 @@ function importConductorWorkspace(workspaceId) {
21986
22029
  if (!(0, import_node_fs55.existsSync)(CONDUCTOR_DB)) {
21987
22030
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
21988
22031
  }
21989
- const tmp = (0, import_node_fs55.mkdtempSync)((0, import_node_path53.join)((0, import_node_os16.tmpdir)(), "sideboard-conductor-"));
21990
- const snapshot = (0, import_node_path53.join)(tmp, "conductor.db");
22032
+ const tmp = (0, import_node_fs55.mkdtempSync)((0, import_node_path54.join)((0, import_node_os16.tmpdir)(), "sideboard-conductor-"));
22033
+ const snapshot = (0, import_node_path54.join)(tmp, "conductor.db");
21991
22034
  try {
21992
22035
  (0, import_node_fs55.copyFileSync)(CONDUCTOR_DB, snapshot);
21993
22036
  for (const suffix of ["-wal", "-shm"]) {
@@ -22081,25 +22124,25 @@ function importConductorWorkspace(workspaceId) {
22081
22124
  async function importConductorWorkspaceAsync(workspaceId) {
22082
22125
  return importConductorWorkspace(workspaceId);
22083
22126
  }
22084
- var import_node_child_process5, import_node_fs55, import_node_os16, import_node_path53, import_node_module6, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
22127
+ var import_node_child_process5, import_node_fs55, import_node_os16, import_node_path54, import_node_module6, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
22085
22128
  var init_adopt = __esm({
22086
22129
  "src/threads/adopt.ts"() {
22087
22130
  "use strict";
22088
22131
  import_node_child_process5 = require("child_process");
22089
22132
  import_node_fs55 = require("fs");
22090
22133
  import_node_os16 = require("os");
22091
- import_node_path53 = require("path");
22134
+ import_node_path54 = require("path");
22092
22135
  import_node_module6 = require("module");
22093
22136
  init_worktree();
22094
22137
  init_thread_store();
22095
- CONDUCTOR_APP_SUPPORT = (0, import_node_path53.join)(
22138
+ CONDUCTOR_APP_SUPPORT = (0, import_node_path54.join)(
22096
22139
  process.env.HOME ?? "",
22097
22140
  "Library",
22098
22141
  "Application Support",
22099
22142
  "com.conductor.app"
22100
22143
  );
22101
- CONDUCTOR_DB = (0, import_node_path53.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
22102
- CURSOR_SDK_STORE = (0, import_node_path53.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
22144
+ CONDUCTOR_DB = (0, import_node_path54.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
22145
+ CURSOR_SDK_STORE = (0, import_node_path54.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
22103
22146
  }
22104
22147
  });
22105
22148
 
@@ -22544,7 +22587,7 @@ new file mode 100644
22544
22587
  };
22545
22588
  }
22546
22589
  async function untrackedPatch(worktreePath, path, maxHunk) {
22547
- const abs = (0, import_node_path54.join)(worktreePath, path);
22590
+ const abs = (0, import_node_path55.join)(worktreePath, path);
22548
22591
  try {
22549
22592
  const st = (0, import_node_fs57.statSync)(abs);
22550
22593
  if (st.isFile() && st.size > maxHunk) {
@@ -23015,7 +23058,7 @@ async function getDiff(worktreePath, repoPath, opts) {
23015
23058
  }
23016
23059
  function statWorktreePath(worktreePath, relativePath) {
23017
23060
  assertSafeRelativePath(relativePath);
23018
- const abs = (0, import_node_path54.join)(worktreePath, relativePath);
23061
+ const abs = (0, import_node_path55.join)(worktreePath, relativePath);
23019
23062
  if (!(0, import_node_fs57.existsSync)(abs)) return "missing";
23020
23063
  const st = (0, import_node_fs57.statSync)(abs);
23021
23064
  if (st.isDirectory()) return "dir";
@@ -23046,7 +23089,7 @@ function isImageRelativePath(relativePath) {
23046
23089
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
23047
23090
  assertSafeRelativePath(relativePath);
23048
23091
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
23049
- const abs = (0, import_node_path54.join)(worktreePath, relativePath);
23092
+ const abs = (0, import_node_path55.join)(worktreePath, relativePath);
23050
23093
  const st = (0, import_node_fs57.statSync)(abs);
23051
23094
  if (!st.isFile()) {
23052
23095
  throw new Error(`Not a file: ${relativePath}`);
@@ -23066,7 +23109,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
23066
23109
  function readWorktreeFile(worktreePath, relativePath, opts) {
23067
23110
  assertSafeRelativePath(relativePath);
23068
23111
  const maxBytes = opts?.maxBytes ?? 2e5;
23069
- const abs = (0, import_node_path54.join)(worktreePath, relativePath);
23112
+ const abs = (0, import_node_path55.join)(worktreePath, relativePath);
23070
23113
  const st = (0, import_node_fs57.statSync)(abs);
23071
23114
  if (!st.isFile()) {
23072
23115
  throw new Error(`Not a file: ${relativePath}`);
@@ -23114,8 +23157,8 @@ function assertSafeRelativePath(relativePath) {
23114
23157
  }
23115
23158
  function writeWorktreeFile(worktreePath, relativePath, content) {
23116
23159
  assertSafeRelativePath(relativePath);
23117
- const abs = (0, import_node_path54.join)(worktreePath, relativePath);
23118
- (0, import_node_fs57.mkdirSync)((0, import_node_path54.dirname)(abs), { recursive: true });
23160
+ const abs = (0, import_node_path55.join)(worktreePath, relativePath);
23161
+ (0, import_node_fs57.mkdirSync)((0, import_node_path55.dirname)(abs), { recursive: true });
23119
23162
  (0, import_node_fs57.writeFileSync)(abs, content, "utf8");
23120
23163
  return { path: relativePath };
23121
23164
  }
@@ -23156,12 +23199,12 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
23156
23199
  truncated: full.files.length > maxFiles
23157
23200
  };
23158
23201
  }
23159
- var import_node_fs57, import_node_path54, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
23202
+ var import_node_fs57, import_node_path55, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
23160
23203
  var init_diff = __esm({
23161
23204
  "src/diff/diff.ts"() {
23162
23205
  "use strict";
23163
23206
  import_node_fs57 = require("fs");
23164
- import_node_path54 = require("path");
23207
+ import_node_path55 = require("path");
23165
23208
  init_run();
23166
23209
  init_worktree();
23167
23210
  mergeBaseCache = /* @__PURE__ */ new Map();
@@ -23383,7 +23426,7 @@ function readWorktreeFileTail(worktreePath, relativePath, maxBytes = WORKTREE_TA
23383
23426
  if (!relativePath || relativePath.includes("..") || relativePath.startsWith("/")) {
23384
23427
  throw new Error("Invalid path");
23385
23428
  }
23386
- const abs = (0, import_node_path55.join)(worktreePath, relativePath);
23429
+ const abs = (0, import_node_path56.join)(worktreePath, relativePath);
23387
23430
  const fd = (0, import_node_fs58.openSync)(abs, "r");
23388
23431
  try {
23389
23432
  const st = (0, import_node_fs58.fstatSync)(fd);
@@ -23413,12 +23456,12 @@ function readWorktreeFileTail(worktreePath, relativePath, maxBytes = WORKTREE_TA
23413
23456
  (0, import_node_fs58.closeSync)(fd);
23414
23457
  }
23415
23458
  }
23416
- var import_node_fs58, import_node_path55, WORKTREE_TAIL_BYTES;
23459
+ var import_node_fs58, import_node_path56, WORKTREE_TAIL_BYTES;
23417
23460
  var init_read_worktree_tail = __esm({
23418
23461
  "src/diff/read-worktree-tail.ts"() {
23419
23462
  "use strict";
23420
23463
  import_node_fs58 = require("fs");
23421
- import_node_path55 = require("path");
23464
+ import_node_path56 = require("path");
23422
23465
  WORKTREE_TAIL_BYTES = 2e5;
23423
23466
  }
23424
23467
  });
@@ -23595,7 +23638,7 @@ function scanSkillsDir(dir, source, out) {
23595
23638
  }
23596
23639
  for (const entry of entries) {
23597
23640
  if (entry.startsWith(".")) continue;
23598
- const skillMd = (0, import_node_path56.join)(dir, entry, "SKILL.md");
23641
+ const skillMd = (0, import_node_path57.join)(dir, entry, "SKILL.md");
23599
23642
  if (!(0, import_node_fs59.existsSync)(skillMd)) continue;
23600
23643
  try {
23601
23644
  if (!(0, import_node_fs59.statSync)(skillMd).isFile()) continue;
@@ -23617,12 +23660,12 @@ function scanClaudePluginSkills(pluginsRoot, out) {
23617
23660
  return;
23618
23661
  }
23619
23662
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
23620
- const skill = readSkill((0, import_node_path56.join)(dir, "SKILL.md"), "cli");
23663
+ const skill = readSkill((0, import_node_path57.join)(dir, "SKILL.md"), "cli");
23621
23664
  if (skill) out.push(skill);
23622
23665
  }
23623
23666
  for (const entry of entries) {
23624
23667
  if (entry === "node_modules" || entry === ".git") continue;
23625
- const full = (0, import_node_path56.join)(dir, entry);
23668
+ const full = (0, import_node_path57.join)(dir, entry);
23626
23669
  try {
23627
23670
  if (!(0, import_node_fs59.statSync)(full).isDirectory()) continue;
23628
23671
  } catch {
@@ -23642,17 +23685,17 @@ function discoverSkills(worktreePath) {
23642
23685
  const home = (0, import_node_os17.homedir)();
23643
23686
  const collected = [];
23644
23687
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
23645
- scanSkillsDir((0, import_node_path56.join)(worktreePath, rel), "workspace", collected);
23688
+ scanSkillsDir((0, import_node_path57.join)(worktreePath, rel), "workspace", collected);
23646
23689
  }
23647
23690
  for (const abs of [
23648
- (0, import_node_path56.join)(home, ".claude/skills"),
23649
- (0, import_node_path56.join)(home, ".cursor/skills"),
23650
- (0, import_node_path56.join)(home, ".sideboard/skills"),
23651
- (0, import_node_path56.join)(home, ".brightsy/skills")
23691
+ (0, import_node_path57.join)(home, ".claude/skills"),
23692
+ (0, import_node_path57.join)(home, ".cursor/skills"),
23693
+ (0, import_node_path57.join)(home, ".sideboard/skills"),
23694
+ (0, import_node_path57.join)(home, ".brightsy/skills")
23652
23695
  ]) {
23653
23696
  scanSkillsDir(abs, "user", collected);
23654
23697
  }
23655
- scanClaudePluginSkills((0, import_node_path56.join)(home, ".claude/plugins"), collected);
23698
+ scanClaudePluginSkills((0, import_node_path57.join)(home, ".claude/plugins"), collected);
23656
23699
  collected.push(...bundledSkills());
23657
23700
  const rank = {
23658
23701
  workspace: 0,
@@ -23692,13 +23735,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
23692
23735
 
23693
23736
  \u2026(truncated)` : raw;
23694
23737
  }
23695
- var import_node_fs59, import_node_os17, import_node_path56, BUNDLED_SKILL_PREFIX;
23738
+ var import_node_fs59, import_node_os17, import_node_path57, BUNDLED_SKILL_PREFIX;
23696
23739
  var init_discover = __esm({
23697
23740
  "src/skills/discover.ts"() {
23698
23741
  "use strict";
23699
23742
  import_node_fs59 = require("fs");
23700
23743
  import_node_os17 = require("os");
23701
- import_node_path56 = require("path");
23744
+ import_node_path57 = require("path");
23702
23745
  init_long_running();
23703
23746
  BUNDLED_SKILL_PREFIX = "bundled:";
23704
23747
  }
@@ -23853,7 +23896,7 @@ function compiledModuleDir() {
23853
23896
  try {
23854
23897
  const url = import_meta5.url;
23855
23898
  if (typeof url === "string" && url.length > 0) {
23856
- return (0, import_node_path57.dirname)((0, import_node_url5.fileURLToPath)(url));
23899
+ return (0, import_node_path58.dirname)((0, import_node_url5.fileURLToPath)(url));
23857
23900
  }
23858
23901
  } catch {
23859
23902
  }
@@ -23861,7 +23904,7 @@ function compiledModuleDir() {
23861
23904
  }
23862
23905
  function detachedJobScriptIn(dir) {
23863
23906
  for (const name of DETACHED_JOB_FILENAMES) {
23864
- const script = (0, import_node_path57.join)(dir, "scripts", name);
23907
+ const script = (0, import_node_path58.join)(dir, "scripts", name);
23865
23908
  if ((0, import_node_fs60.existsSync)(script)) return script;
23866
23909
  }
23867
23910
  return null;
@@ -23879,7 +23922,7 @@ function resolveDetachedJobScript() {
23879
23922
  for (let i = 0; i < 8; i++) {
23880
23923
  const candidate = detachedJobScriptIn(dir);
23881
23924
  if (candidate) return candidate;
23882
- const parent = (0, import_node_path57.dirname)(dir);
23925
+ const parent = (0, import_node_path58.dirname)(dir);
23883
23926
  if (parent === dir) break;
23884
23927
  dir = parent;
23885
23928
  }
@@ -23890,12 +23933,12 @@ function formatDetachedJobInvoke(scriptPath) {
23890
23933
  if (resolved) return `node ${JSON.stringify(resolved)}`;
23891
23934
  return "node scripts/detached-job.cjs";
23892
23935
  }
23893
- var import_node_fs60, import_node_path57, import_node_url5, import_meta5, DETACHED_JOB_FILENAMES;
23936
+ var import_node_fs60, import_node_path58, import_node_url5, import_meta5, DETACHED_JOB_FILENAMES;
23894
23937
  var init_detached_job_path = __esm({
23895
23938
  "src/skills/detached-job-path.ts"() {
23896
23939
  "use strict";
23897
23940
  import_node_fs60 = require("fs");
23898
- import_node_path57 = require("path");
23941
+ import_node_path58 = require("path");
23899
23942
  import_node_url5 = require("url");
23900
23943
  init_packaged_runtime();
23901
23944
  import_meta5 = {};
@@ -24092,9 +24135,9 @@ function formatPrGateDirective() {
24092
24135
  }
24093
24136
  function formatProcessGuideDirective(opts) {
24094
24137
  const worktree = opts?.worktreePath?.trim();
24095
- const hasGraphSkill = !!worktree && (0, import_node_fs61.existsSync)((0, import_node_path58.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
24096
- const hasReviewSkill = !!worktree && (0, import_node_fs61.existsSync)((0, import_node_path58.join)(worktree, ".claude/skills/review/SKILL.md"));
24097
- const hasInstallSkill = !!worktree && (0, import_node_fs61.existsSync)((0, import_node_path58.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
24138
+ const hasGraphSkill = !!worktree && (0, import_node_fs61.existsSync)((0, import_node_path59.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
24139
+ const hasReviewSkill = !!worktree && (0, import_node_fs61.existsSync)((0, import_node_path59.join)(worktree, ".claude/skills/review/SKILL.md"));
24140
+ const hasInstallSkill = !!worktree && (0, import_node_fs61.existsSync)((0, import_node_path59.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
24098
24141
  return [
24099
24142
  "Process guides (recurring work only):",
24100
24143
  hasGraphSkill ? "- Migrations, ports, batch fixes, and other fan-out: follow `.claude/skills/graph-engineering/SKILL.md` (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch around it." : null,
@@ -24134,12 +24177,12 @@ function formatArtifactDirective() {
24134
24177
  function formatUiReminder() {
24135
24178
  return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). Chat links: `[name](sideboard://artifact/<id-or-title>)` opens that pane; `[name](sideboard://file/path#L12-L40)` opens a file. ask_user only for a real multiple-choice (not hellos, \u201Cwhat next?\u201D, or after a review) \u2014 reply in chat. ask_user wakes the parent orchestrator; notify_orchestrator if blocked without a picker. Do not say artifacts/CMS UI are unavailable. Dev / preview: run_dev_script (same as the Dev button; pass name \u2014 several scripts can run at once) returns {url, port, preview} (SIDEBOARD_PORT \u2014 never guess :3000). preview=url \u2192 open url; preview=window \u2192 Electron window is the app, url is renderer/HMR only. list_run_scripts active[].url if already running; get_run_log for that script\u2019s Run-tab terminal; stop_dev_script to stop one.";
24136
24179
  }
24137
- var import_node_fs61, import_node_path58, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
24180
+ var import_node_fs61, import_node_path59, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
24138
24181
  var init_instructions = __esm({
24139
24182
  "src/agents/instructions.ts"() {
24140
24183
  "use strict";
24141
24184
  import_node_fs61 = require("fs");
24142
- import_node_path58 = require("path");
24185
+ import_node_path59 = require("path");
24143
24186
  init_git_auth_mode();
24144
24187
  init_branch_prefix();
24145
24188
  init_worktree_labels();
@@ -24878,13 +24921,13 @@ __export(plan_file_exports, {
24878
24921
  writePlanFile: () => writePlanFile
24879
24922
  });
24880
24923
  function ensureAttachmentsGitignore(worktreePath) {
24881
- const gitignoreAbs = (0, import_node_path59.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
24924
+ const gitignoreAbs = (0, import_node_path60.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
24882
24925
  if ((0, import_node_fs62.existsSync)(gitignoreAbs)) return;
24883
- (0, import_node_fs62.mkdirSync)((0, import_node_path59.dirname)(gitignoreAbs), { recursive: true });
24926
+ (0, import_node_fs62.mkdirSync)((0, import_node_path60.dirname)(gitignoreAbs), { recursive: true });
24884
24927
  (0, import_node_fs62.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
24885
24928
  }
24886
24929
  function planFileAbs(worktreePath) {
24887
- return (0, import_node_path59.join)(worktreePath, PLAN_FILE_REL);
24930
+ return (0, import_node_path60.join)(worktreePath, PLAN_FILE_REL);
24888
24931
  }
24889
24932
  function readTextIfPresent2(abs) {
24890
24933
  if (!(0, import_node_fs62.existsSync)(abs)) return null;
@@ -24896,22 +24939,22 @@ function readTextIfPresent2(abs) {
24896
24939
  }
24897
24940
  }
24898
24941
  function readPlanFile(worktreePath) {
24899
- return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path59.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path59.join)(worktreePath, LEGACY_PLAN_FILE_REL));
24942
+ return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path60.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path60.join)(worktreePath, LEGACY_PLAN_FILE_REL));
24900
24943
  }
24901
24944
  function writePlanFile(worktreePath, content) {
24902
24945
  ensureAttachmentsGitignore(worktreePath);
24903
24946
  const abs = planFileAbs(worktreePath);
24904
- (0, import_node_fs62.mkdirSync)((0, import_node_path59.dirname)(abs), { recursive: true });
24947
+ (0, import_node_fs62.mkdirSync)((0, import_node_path60.dirname)(abs), { recursive: true });
24905
24948
  const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
24906
24949
  (0, import_node_fs62.writeFileSync)(abs, body, "utf8");
24907
24950
  return PLAN_FILE_REL;
24908
24951
  }
24909
- var import_node_fs62, import_node_path59;
24952
+ var import_node_fs62, import_node_path60;
24910
24953
  var init_plan_file = __esm({
24911
24954
  "src/plan/plan-file.ts"() {
24912
24955
  "use strict";
24913
24956
  import_node_fs62 = require("fs");
24914
- import_node_path59 = require("path");
24957
+ import_node_path60 = require("path");
24915
24958
  init_workspace_scratch();
24916
24959
  init_plan_present();
24917
24960
  init_plan_present();
@@ -24960,7 +25003,7 @@ function setCaffeinateHoldHooks(next) {
24960
25003
  hooks = next;
24961
25004
  }
24962
25005
  function caffeinateHoldPath() {
24963
- return (0, import_node_path60.join)(appDataDir(), "caffeinate-hold.json");
25006
+ return (0, import_node_path61.join)(appDataDir(), "caffeinate-hold.json");
24964
25007
  }
24965
25008
  function processAlive(pid) {
24966
25009
  if (hooks.processAlive) return hooks.processAlive(pid);
@@ -25103,13 +25146,13 @@ function releaseCaffeinateHoldForThread(threadId) {
25103
25146
  }
25104
25147
  return setCaffeinateHold(false, { threadId: id });
25105
25148
  }
25106
- var import_node_child_process6, import_node_fs63, import_node_path60, hooks;
25149
+ var import_node_child_process6, import_node_fs63, import_node_path61, hooks;
25107
25150
  var init_caffeinate_hold = __esm({
25108
25151
  "src/store/caffeinate-hold.ts"() {
25109
25152
  "use strict";
25110
25153
  import_node_child_process6 = require("child_process");
25111
25154
  import_node_fs63 = require("fs");
25112
- import_node_path60 = require("path");
25155
+ import_node_path61 = require("path");
25113
25156
  init_paths();
25114
25157
  init_private_file();
25115
25158
  hooks = {};
@@ -25118,7 +25161,7 @@ var init_caffeinate_hold = __esm({
25118
25161
 
25119
25162
  // src/store/schedules.ts
25120
25163
  function schedulesPath() {
25121
- return (0, import_node_path61.join)(appDataDir(), "schedules.json");
25164
+ return (0, import_node_path62.join)(appDataDir(), "schedules.json");
25122
25165
  }
25123
25166
  function parseDurationMs(every) {
25124
25167
  const m = every.trim().match(DURATION_RE);
@@ -25245,7 +25288,7 @@ function buildTask(input, now) {
25245
25288
  const ts = nowIso2(now);
25246
25289
  const agent = input.agent ? coerceOrchestratorAgent(input.agent) : null;
25247
25290
  return {
25248
- id: (0, import_node_crypto14.randomUUID)(),
25291
+ id: (0, import_node_crypto15.randomUUID)(),
25249
25292
  name: input.name?.trim() || defaultScheduleName(prompt),
25250
25293
  prompt,
25251
25294
  enabled: input.enabled !== false,
@@ -25345,13 +25388,13 @@ function recordScheduleRun(id, result) {
25345
25388
  writeAll2(rows);
25346
25389
  return next;
25347
25390
  }
25348
- var import_node_crypto14, import_node_fs64, import_node_path61, import_croner, DURATION_RE, UNIT_MS;
25391
+ var import_node_crypto15, import_node_fs64, import_node_path62, import_croner, DURATION_RE, UNIT_MS;
25349
25392
  var init_schedules = __esm({
25350
25393
  "src/store/schedules.ts"() {
25351
25394
  "use strict";
25352
- import_node_crypto14 = require("crypto");
25395
+ import_node_crypto15 = require("crypto");
25353
25396
  import_node_fs64 = require("fs");
25354
- import_node_path61 = require("path");
25397
+ import_node_path62 = require("path");
25355
25398
  import_croner = require("croner");
25356
25399
  init_orchestrator_capable();
25357
25400
  init_paths();
@@ -25655,7 +25698,7 @@ async function startOrchestration(opts) {
25655
25698
  }
25656
25699
  return updated;
25657
25700
  }
25658
- var import_node_events, import_node_crypto15, import_node_fs66, LIVE_TURN_SPAWN_GRACE_MS, RUN_SCRIPT_DESKTOP_ADOPT_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton;
25701
+ var import_node_events, import_node_crypto16, import_node_fs66, LIVE_TURN_SPAWN_GRACE_MS, RUN_SCRIPT_DESKTOP_ADOPT_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton;
25659
25702
  var init_orchestrator = __esm({
25660
25703
  "src/orchestrator/orchestrator.ts"() {
25661
25704
  "use strict";
@@ -25663,7 +25706,7 @@ var init_orchestrator = __esm({
25663
25706
  init_injected_notices();
25664
25707
  init_task_state();
25665
25708
  init_wait_for_turn();
25666
- import_node_crypto15 = require("crypto");
25709
+ import_node_crypto16 = require("crypto");
25667
25710
  import_node_fs66 = require("fs");
25668
25711
  init_error_detail();
25669
25712
  init_run();
@@ -27312,7 +27355,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
27312
27355
  const request = sameIntent ? pending : {
27313
27356
  op,
27314
27357
  scriptName: scriptName ?? null,
27315
- requestId: (0, import_node_crypto15.randomUUID)(),
27358
+ requestId: (0, import_node_crypto16.randomUUID)(),
27316
27359
  requestedAt: (/* @__PURE__ */ new Date()).toISOString()
27317
27360
  };
27318
27361
  if (!sameIntent) {
@@ -28440,6 +28483,10 @@ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
28440
28483
  // src/mcp/wrap-mcp-tools.ts
28441
28484
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
28442
28485
 
28486
+ // src/agents/cursor-tool-guard.ts
28487
+ init_error_detail();
28488
+ init_cursor_stream_cutoff();
28489
+
28443
28490
  // src/agents/tool-result-clip.ts
28444
28491
  var import_node_fs7 = require("fs");
28445
28492
  var import_node_path8 = require("path");
@@ -28488,11 +28535,30 @@ function clipMcpToolResult(result, cwd) {
28488
28535
  };
28489
28536
  }
28490
28537
 
28538
+ // src/agents/cursor-tool-guard.ts
28539
+ var CURSOR_TOOL_RECOVERY_HINT = "Continue with a smaller request. If you were reading a large file or API payload, pass offset and limit or write the output to .context/cli/ and read a slice. Do not retry the same call.";
28540
+ function cursorToolErrorText(err) {
28541
+ const raw = formatUnknownDetail(err).replace(/\s+/g, " ").trim();
28542
+ const message = looksLikeHugeToolResultDump(raw) ? HUGE_TOOL_RESULT_SUMMARY : (raw || "unknown tool error").slice(0, 500);
28543
+ return `Error: ${message}
28544
+ ${CURSOR_TOOL_RECOVERY_HINT}`;
28545
+ }
28546
+
28491
28547
  // src/mcp/wrap-mcp-tools.ts
28492
28548
  function wrapToolCallback(fn, cwd) {
28493
28549
  return async (...args) => {
28494
- const result = await fn(...args);
28495
- return clipMcpToolResult(result, cwd());
28550
+ try {
28551
+ const result = await fn(...args);
28552
+ return clipMcpToolResult(
28553
+ result,
28554
+ cwd()
28555
+ );
28556
+ } catch (err) {
28557
+ return {
28558
+ isError: true,
28559
+ content: [{ type: "text", text: cursorToolErrorText(err) }]
28560
+ };
28561
+ }
28496
28562
  };
28497
28563
  }
28498
28564
  function wrapRegistrar(orig, cwd) {
@@ -28523,8 +28589,8 @@ function createClippedMcpServer() {
28523
28589
 
28524
28590
  // src/mcp/server.ts
28525
28591
  var import_zod10 = require("zod");
28526
- var import_node_crypto19 = require("crypto");
28527
- var import_node_path65 = require("path");
28592
+ var import_node_crypto20 = require("crypto");
28593
+ var import_node_path66 = require("path");
28528
28594
  init_orchestrator();
28529
28595
  init_task_state();
28530
28596
  init_worktree();
@@ -29035,7 +29101,7 @@ init_fetch();
29035
29101
  init_issue_attachments();
29036
29102
 
29037
29103
  // src/integrations/linear-oauth.ts
29038
- var import_node_crypto16 = require("crypto");
29104
+ var import_node_crypto17 = require("crypto");
29039
29105
  var import_node_http2 = require("http");
29040
29106
  init_app_settings();
29041
29107
  init_fetch();
@@ -31898,13 +31964,53 @@ function registerScheduleTools(server) {
31898
31964
  }
31899
31965
 
31900
31966
  // src/agent-rpc/handlers.ts
31901
- var import_node_crypto17 = require("crypto");
31902
- var import_node_path62 = require("path");
31967
+ var import_node_crypto18 = require("crypto");
31968
+ var import_node_path63 = require("path");
31903
31969
  init_wait_for_job();
31904
31970
  init_wait_for_turn();
31971
+
31972
+ // src/agent-rpc/permission-handler.ts
31973
+ init_agent_block();
31974
+ init_thread_store();
31975
+ init_tool_permission();
31976
+
31977
+ // src/remote/phone-permission.ts
31978
+ init_thread_store();
31979
+ init_tool_permission();
31980
+ var push = null;
31981
+ function notifyPhonePermission(chatId, prompt) {
31982
+ const id = chatId.trim();
31983
+ if (!id) return;
31984
+ push?.(id, prompt);
31985
+ }
31986
+
31987
+ // src/agent-rpc/permission-handler.ts
31988
+ setToolPermissionPublisher({
31989
+ show(item) {
31990
+ const thread = readThread(item.threadId);
31991
+ if (!thread || thread.status === "archived") return false;
31992
+ writeAgentBlock(item.threadId, {
31993
+ source: "permission",
31994
+ reason: clampBlockReason(item.prompt.title),
31995
+ at: (/* @__PURE__ */ new Date()).toISOString(),
31996
+ permission: item.prompt
31997
+ });
31998
+ notifyPhonePermission(item.threadId, item.prompt);
31999
+ return true;
32000
+ },
32001
+ clear(threadId, id) {
32002
+ const thread = readThread(threadId);
32003
+ if (thread?.agentBlock?.source === "permission" && thread.agentBlock.permission?.id === id) {
32004
+ updateThread(threadId, { agentBlock: null });
32005
+ notifyPhonePermission(threadId, null);
32006
+ }
32007
+ }
32008
+ });
32009
+
32010
+ // src/agent-rpc/handlers.ts
31905
32011
  init_protocol();
31906
32012
  function presentArtifactResult(input) {
31907
- const id = input.artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${(0, import_node_crypto17.randomUUID)().slice(0, 8)}`;
32013
+ const id = input.artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${(0, import_node_crypto18.randomUUID)().slice(0, 8)}`;
31908
32014
  return {
31909
32015
  ok: true,
31910
32016
  artifact_id: id,
@@ -31924,20 +32030,20 @@ init_git_auth_mode();
31924
32030
 
31925
32031
  // src/board/load-home-board.ts
31926
32032
  var import_node_fs68 = require("fs");
31927
- var import_node_path64 = require("path");
32033
+ var import_node_path65 = require("path");
31928
32034
  init_worktree();
31929
32035
  init_paths();
31930
32036
 
31931
32037
  // src/board/board-pins.ts
31932
- var import_node_crypto18 = require("crypto");
32038
+ var import_node_crypto19 = require("crypto");
31933
32039
  var import_node_fs67 = require("fs");
31934
- var import_node_path63 = require("path");
32040
+ var import_node_path64 = require("path");
31935
32041
  init_paths();
31936
32042
  init_home_board();
31937
32043
  var FILE = "home-board-pins.json";
31938
32044
  var VERSION = 1;
31939
32045
  function pinsFile() {
31940
- return (0, import_node_path63.join)(appDataDir(), FILE);
32046
+ return (0, import_node_path64.join)(appDataDir(), FILE);
31941
32047
  }
31942
32048
  function readDisk() {
31943
32049
  const path = pinsFile();
@@ -31973,7 +32079,7 @@ function homeBoardWorkspaceKey(workspaces) {
31973
32079
  return workspaces.map((w) => w.path).filter(Boolean).sort().join("\n");
31974
32080
  }
31975
32081
  function cacheFile() {
31976
- return (0, import_node_path64.join)(appDataDir(), "home-board-cache.json");
32082
+ return (0, import_node_path65.join)(appDataDir(), "home-board-cache.json");
31977
32083
  }
31978
32084
  function emptyInputs() {
31979
32085
  return {
@@ -32271,7 +32377,7 @@ async function startMcpServer() {
32271
32377
  async () => {
32272
32378
  const threads = orch.getThreads(true);
32273
32379
  const lines = threads.map((t) => {
32274
- const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path65.basename)(t.repoPath) || t.repoPath;
32380
+ const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path66.basename)(t.repoPath) || t.repoPath;
32275
32381
  const live = orch.threadLooksLive(t) ? readTurnLive(t.id) : null;
32276
32382
  const parent = t.parentThreadId ? ` parent:${t.parentThreadId.slice(0, 8)}` : "";
32277
32383
  const preview = lastMessagePreview(t.messages, 80);
@@ -32854,7 +32960,7 @@ async function startMcpServer() {
32854
32960
  const ident = issue?.identifier ?? ref.trim();
32855
32961
  const attachments = issue ? [
32856
32962
  {
32857
- id: (0, import_node_crypto19.randomUUID)(),
32963
+ id: (0, import_node_crypto20.randomUUID)(),
32858
32964
  name: issue.identifier,
32859
32965
  kind: "issue",
32860
32966
  content: [