@sideboard-ai/core 0.1.120 → 0.1.124

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 (38) hide show
  1. package/dist/agents/cursor-runner.cjs +100 -0
  2. package/dist/agents/cursor-runner.js +24 -1
  3. package/dist/{agents-HOIXQEP5.js → agents-DCXXLTXF.js} +11 -7
  4. package/dist/{agents-XTABRYO5.js → agents-DPR2TDNF.js} +10 -6
  5. package/dist/{app-settings-5XAGNDX7.js → app-settings-IKFWZDUK.js} +3 -1
  6. package/dist/{app-settings-J4LUWIRN.js → app-settings-YFWV7MOG.js} +3 -1
  7. package/dist/{chunk-X3NIPGQT.js → chunk-2X7I6MDW.js} +5 -5
  8. package/dist/{chunk-QI7VC4EG.js → chunk-7Y3AYQWT.js} +81 -9
  9. package/dist/{chunk-SGEVS5SY.js → chunk-BMIRX64H.js} +10 -0
  10. package/dist/{chunk-4NR5FL46.js → chunk-FXQPY2KU.js} +10 -0
  11. package/dist/{chunk-U3IVCVLH.js → chunk-HZLE6LJJ.js} +2 -2
  12. package/dist/{chunk-NZBDVBCP.js → chunk-IUJOI7KK.js} +83 -0
  13. package/dist/{chunk-TDNM7QZJ.js → chunk-JNAIKICO.js} +114 -8
  14. package/dist/{chunk-4WV7C7WP.js → chunk-KWGP6RZM.js} +3 -3
  15. package/dist/{chunk-AFM6442E.js → chunk-MZDAEI3Y.js} +70 -28
  16. package/dist/{chunk-4NAW5BAQ.js → chunk-O43IRQ2Y.js} +3 -3
  17. package/dist/{chunk-WCU3FHEI.js → chunk-OHEFHIG3.js} +1 -1
  18. package/dist/{chunk-BKVDZV7X.js → chunk-RBVVWBVB.js} +2 -2
  19. package/dist/{chunk-4LRPW6QM.js → chunk-SDCPQL27.js} +68 -27
  20. package/dist/{chunk-XTZQL7OU.js → chunk-TRTWH6C2.js} +5 -5
  21. package/dist/{chunk-VGPLXQIH.js → chunk-UAVZ2JSO.js} +1 -1
  22. package/dist/{coordinator-prompt-QMV6YEP5.js → coordinator-prompt-AZ3WRDNC.js} +3 -3
  23. package/dist/{coordinator-prompt-XCBHAOGE.js → coordinator-prompt-LEU62W25.js} +3 -3
  24. package/dist/{global-workspace-Z37MNYU6.js → global-workspace-4YNYDMLQ.js} +4 -4
  25. package/dist/{global-workspace-SBKXKQFS.js → global-workspace-U5UOVXKQ.js} +4 -4
  26. package/dist/index.cjs +190 -22
  27. package/dist/index.d.cts +56 -6
  28. package/dist/index.d.ts +56 -6
  29. package/dist/index.js +30 -17
  30. package/dist/mcp/run-stdio.cjs +180 -22
  31. package/dist/mcp/run-stdio.js +19 -16
  32. package/dist/{orchestrator-NWNKWZLB.js → orchestrator-JS3EHI4E.js} +8 -8
  33. package/dist/{orchestrator-3LJIG6XG.js → orchestrator-VJQ5EWZZ.js} +7 -7
  34. package/dist/{workspaces-C3TJJFY3.js → workspaces-ICK433ZV.js} +5 -5
  35. package/dist/{workspaces-M4OICPWF.js → workspaces-POWKTH2D.js} +5 -5
  36. package/dist/{worktree-MRSTQ32S.js → worktree-CMGBTVN4.js} +2 -2
  37. package/dist/{worktree-7AEKZSEX.js → worktree-T57RD7BQ.js} +2 -2
  38. package/package.json +1 -1
@@ -488,6 +488,85 @@ function usageFromCursor(usage) {
488
488
  cacheWriteTokens: usage.cacheWriteTokens ? Number(usage.cacheWriteTokens) : void 0
489
489
  };
490
490
  }
491
+ function preferredCursorCostCents(cost) {
492
+ if (!cost) return void 0;
493
+ const charged = Number(cost.chargedCents);
494
+ const raw = Number(cost.rawCostCents);
495
+ if (Number.isFinite(charged) && charged > 0) return charged;
496
+ if (Number.isFinite(raw) && raw > 0) return raw;
497
+ if (Number.isFinite(charged)) return charged;
498
+ if (Number.isFinite(raw)) return raw;
499
+ return void 0;
500
+ }
501
+ function turnCostUsdFromCursorUsage(before, after) {
502
+ if (!after) return void 0;
503
+ const beforeIds = new Set((before?.runs ?? []).map((r) => r.runId));
504
+ const newRuns = (after.runs ?? []).filter((r) => !beforeIds.has(r.runId));
505
+ let sum = 0;
506
+ let any = false;
507
+ for (const r of newRuns) {
508
+ const c = preferredCursorCostCents(r.cost);
509
+ if (c != null) {
510
+ sum += c;
511
+ any = true;
512
+ }
513
+ }
514
+ if (any) return sum / 100;
515
+ if (before == null) return void 0;
516
+ const afterCents = preferredCursorCostCents(after.cost);
517
+ if (afterCents == null) return void 0;
518
+ const beforeCents = preferredCursorCostCents(before.cost) ?? 0;
519
+ const delta = afterCents - beforeCents;
520
+ if (!(delta >= 0) || !Number.isFinite(delta)) return void 0;
521
+ return delta / 100;
522
+ }
523
+ function costUsdFromRunSnapshot(usage, runId) {
524
+ if (!usage?.runs?.length || !runId.trim()) return void 0;
525
+ const row = usage.runs.find((r) => r.runId === runId);
526
+ const cents = preferredCursorCostCents(row?.cost);
527
+ return cents != null ? cents / 100 : void 0;
528
+ }
529
+ function cursorGetUsageRunId(runId) {
530
+ const id = runId?.trim();
531
+ if (!id || id.startsWith("run-")) return void 0;
532
+ return id;
533
+ }
534
+ var CURSOR_COST_POLL_MS = [0, 400, 800, 1600, 3200];
535
+ function sleep(ms) {
536
+ return new Promise((resolve) => {
537
+ setTimeout(resolve, ms);
538
+ });
539
+ }
540
+ async function fetchCursorTurnCostUsd(getUsage, usageBefore, opts) {
541
+ const lookupRunId = cursorGetUsageRunId(opts?.runId);
542
+ for (const delay of CURSOR_COST_POLL_MS) {
543
+ if (delay > 0) await sleep(delay);
544
+ try {
545
+ if (lookupRunId) {
546
+ const scoped = await getUsage({ runId: lookupRunId });
547
+ const direct = costUsdFromRunSnapshot(scoped, lookupRunId);
548
+ if (direct != null) return direct;
549
+ }
550
+ const after = await getUsage();
551
+ const delta = turnCostUsdFromCursorUsage(usageBefore, after);
552
+ if (delta != null) return delta;
553
+ } catch (err) {
554
+ if (isCursorUsageUnavailableError(err)) return void 0;
555
+ }
556
+ }
557
+ return void 0;
558
+ }
559
+ function isCursorUsageUnavailableError(err) {
560
+ const msg = err instanceof Error ? err.message : String(err);
561
+ return /feature_unavailable|feature unavailable|not available for your account/i.test(msg);
562
+ }
563
+ function cursorCostOnlyUsageEvent(costUsd) {
564
+ return {
565
+ type: "usage",
566
+ data: { inputTokens: 0, outputTokens: 0, costUsd },
567
+ scope: "turn"
568
+ };
569
+ }
491
570
  function asRecord(value) {
492
571
  if (value && typeof value === "object" && !Array.isArray(value)) {
493
572
  return value;
@@ -790,6 +869,10 @@ export {
790
869
  isAsarPath,
791
870
  applyNodeLaunch,
792
871
  resolveNodeLaunch,
872
+ preferredCursorCostCents,
873
+ turnCostUsdFromCursorUsage,
874
+ fetchCursorTurnCostUsd,
875
+ cursorCostOnlyUsageEvent,
793
876
  cursorSdkMessageToEvents,
794
877
  cursorDeltaToEvents,
795
878
  parseCursorRunnerLine,
@@ -9,13 +9,13 @@ import {
9
9
  } from "./chunk-YMRT2DU6.js";
10
10
  import {
11
11
  isOrchestratorThread
12
- } from "./chunk-4NAW5BAQ.js";
12
+ } from "./chunk-O43IRQ2Y.js";
13
13
  import {
14
14
  codexUnattendedGitConfigArgs,
15
15
  mergeAgentGitAuthEnv,
16
16
  resolveAgentGitAuthEnv,
17
17
  resolveCodexGitWritableRoots
18
- } from "./chunk-WCU3FHEI.js";
18
+ } from "./chunk-OHEFHIG3.js";
19
19
  import {
20
20
  enrichPathWithNpmGlobalBin,
21
21
  isConductorBundledCli,
@@ -31,7 +31,7 @@ import {
31
31
  resolveClaudeExecutable,
32
32
  unwrapStrippedElectronLaunch,
33
33
  wrapElectronAsNodeLaunch
34
- } from "./chunk-SGEVS5SY.js";
34
+ } from "./chunk-BMIRX64H.js";
35
35
  import {
36
36
  appDataDir
37
37
  } from "./chunk-BD2ICC4D.js";
@@ -65,18 +65,53 @@ function mergeUsage(a, b) {
65
65
  outputTokens: (a?.outputTokens ?? 0) + b.outputTokens,
66
66
  cacheReadTokens: sumOptional(a?.cacheReadTokens, b.cacheReadTokens),
67
67
  cacheWriteTokens: sumOptional(a?.cacheWriteTokens, b.cacheWriteTokens),
68
+ costUsd: sumOptional(a?.costUsd, b.costUsd),
68
69
  lastRequestTokens: b.lastRequestTokens ?? a?.lastRequestTokens
69
70
  };
70
71
  }
72
+ function sumUsageList(list) {
73
+ let acc = null;
74
+ for (const u of list) {
75
+ if (!u) continue;
76
+ acc = mergeUsage(acc, {
77
+ inputTokens: u.inputTokens,
78
+ outputTokens: u.outputTokens,
79
+ cacheReadTokens: u.cacheReadTokens,
80
+ cacheWriteTokens: u.cacheWriteTokens,
81
+ costUsd: u.costUsd
82
+ });
83
+ }
84
+ if (!acc) return null;
85
+ return {
86
+ inputTokens: acc.inputTokens,
87
+ outputTokens: acc.outputTokens,
88
+ ...acc.cacheReadTokens != null ? { cacheReadTokens: acc.cacheReadTokens } : {},
89
+ ...acc.cacheWriteTokens != null ? { cacheWriteTokens: acc.cacheWriteTokens } : {},
90
+ ...acc.costUsd != null ? { costUsd: acc.costUsd } : {}
91
+ };
92
+ }
93
+ function hasBilledTokens(u) {
94
+ return Boolean(
95
+ u.inputTokens || u.outputTokens || u.cacheReadTokens || u.cacheWriteTokens
96
+ );
97
+ }
71
98
  function applyTurnUsage(current, incoming, scope = "request") {
72
99
  if (scope === "turn") {
100
+ if (!hasBilledTokens(incoming) && current && incoming.costUsd != null) {
101
+ return { ...current, costUsd: incoming.costUsd };
102
+ }
73
103
  return {
74
104
  ...incoming,
105
+ costUsd: incoming.costUsd ?? current?.costUsd,
75
106
  lastRequestTokens: current?.lastRequestTokens ?? requestOccupancy(incoming)
76
107
  };
77
108
  }
78
109
  const merged = mergeUsage(current, incoming);
79
- return { ...merged, lastRequestTokens: requestOccupancy(incoming) };
110
+ const occ = requestOccupancy(incoming);
111
+ return {
112
+ ...merged,
113
+ lastRequestTokens: occ > 0 ? occ : current?.lastRequestTokens ?? occ
114
+ };
80
115
  }
81
116
  function contextTokens(u) {
82
117
  if (u.lastRequestTokens != null && u.lastRequestTokens > 0) return u.lastRequestTokens;
@@ -362,11 +397,16 @@ ${prompt}`;
362
397
  // src/agents/brightsy.ts
363
398
  function usageFromBrightsy(usage) {
364
399
  if (!usage) return null;
365
- return fromInclusiveInputUsage({
400
+ const mapped = fromInclusiveInputUsage({
366
401
  inputTokens: Number(usage.prompt_tokens ?? 0),
367
402
  outputTokens: Number(usage.completion_tokens ?? 0),
368
403
  cachedInputTokens: Number(usage.prompt_tokens_details?.cached_tokens ?? 0)
369
404
  });
405
+ if (!mapped) return null;
406
+ if (usage.cost != null && Number.isFinite(Number(usage.cost))) {
407
+ mapped.costUsd = Number(usage.cost);
408
+ }
409
+ return mapped;
370
410
  }
371
411
  function parseBrightsyCliLine(line) {
372
412
  const trimmed = line.trim();
@@ -1737,6 +1777,28 @@ function usageFromClaude(usage) {
1737
1777
  cacheWriteTokens: cacheWriteTokens || void 0
1738
1778
  };
1739
1779
  }
1780
+ function costUsdFromClaudeResult(obj) {
1781
+ const modelUsage = obj.modelUsage ?? obj.model_usage;
1782
+ if (modelUsage && typeof modelUsage === "object") {
1783
+ let sum = 0;
1784
+ let any = false;
1785
+ for (const entry of Object.values(modelUsage)) {
1786
+ if (!entry || typeof entry !== "object") continue;
1787
+ const row = entry;
1788
+ const cost = row.costUSD ?? row.cost_usd;
1789
+ if (cost != null && Number.isFinite(Number(cost))) {
1790
+ sum += Number(cost);
1791
+ any = true;
1792
+ }
1793
+ }
1794
+ if (any) return sum;
1795
+ }
1796
+ const totalCost = obj.total_cost_usd ?? obj.totalCostUsd;
1797
+ if (totalCost != null && Number.isFinite(Number(totalCost))) {
1798
+ return Number(totalCost);
1799
+ }
1800
+ return void 0;
1801
+ }
1740
1802
  function claudeResultErrorDetail(obj) {
1741
1803
  const isError = Boolean(obj.is_error) || typeof obj.subtype === "string" && /^error/i.test(obj.subtype);
1742
1804
  const fromResult = typeof obj.result === "string" ? obj.result.trim() : "";
@@ -1942,7 +2004,7 @@ var claudeAdapter = {
1942
2004
  );
1943
2005
  }
1944
2006
  const mode = permissionMode(thread);
1945
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-Z37MNYU6.js");
2007
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-4YNYDMLQ.js");
1946
2008
  const isOrchestrator = isOrchestratorThread2(thread);
1947
2009
  const injectedServers = await buildInjectedMcpServers({
1948
2010
  includeSideboard: true,
@@ -2089,7 +2151,11 @@ var claudeAdapter = {
2089
2151
  if (typeof text === "string" && text) events.push({ type: "stdout", data: text });
2090
2152
  }
2091
2153
  const usage = usageFromClaude(obj.usage);
2092
- if (usage) events.push({ type: "usage", data: usage, scope: "turn" });
2154
+ if (usage) {
2155
+ const costUsd = costUsdFromClaudeResult(obj);
2156
+ if (costUsd != null) usage.costUsd = costUsd;
2157
+ events.push({ type: "usage", data: usage, scope: "turn" });
2158
+ }
2093
2159
  if (events.length === 0) return null;
2094
2160
  return events.length === 1 ? events[0] : events;
2095
2161
  }
@@ -2544,6 +2610,38 @@ function usageFromCursor(usage) {
2544
2610
  cacheWriteTokens: usage.cacheWriteTokens ? Number(usage.cacheWriteTokens) : void 0
2545
2611
  };
2546
2612
  }
2613
+ function preferredCursorCostCents(cost) {
2614
+ if (!cost) return void 0;
2615
+ const charged = Number(cost.chargedCents);
2616
+ const raw = Number(cost.rawCostCents);
2617
+ if (Number.isFinite(charged) && charged > 0) return charged;
2618
+ if (Number.isFinite(raw) && raw > 0) return raw;
2619
+ if (Number.isFinite(charged)) return charged;
2620
+ if (Number.isFinite(raw)) return raw;
2621
+ return void 0;
2622
+ }
2623
+ function turnCostUsdFromCursorUsage(before, after) {
2624
+ if (!after) return void 0;
2625
+ const beforeIds = new Set((before?.runs ?? []).map((r) => r.runId));
2626
+ const newRuns = (after.runs ?? []).filter((r) => !beforeIds.has(r.runId));
2627
+ let sum = 0;
2628
+ let any = false;
2629
+ for (const r of newRuns) {
2630
+ const c = preferredCursorCostCents(r.cost);
2631
+ if (c != null) {
2632
+ sum += c;
2633
+ any = true;
2634
+ }
2635
+ }
2636
+ if (any) return sum / 100;
2637
+ if (before == null) return void 0;
2638
+ const afterCents = preferredCursorCostCents(after.cost);
2639
+ if (afterCents == null) return void 0;
2640
+ const beforeCents = preferredCursorCostCents(before.cost) ?? 0;
2641
+ const delta = afterCents - beforeCents;
2642
+ if (!(delta >= 0) || !Number.isFinite(delta)) return void 0;
2643
+ return delta / 100;
2644
+ }
2547
2645
  function asRecord3(value) {
2548
2646
  if (value && typeof value === "object" && !Array.isArray(value)) {
2549
2647
  return value;
@@ -3208,7 +3306,12 @@ var opencodeAdapter = {
3208
3306
  const usage = usageFromOpencode(
3209
3307
  part?.tokens ?? obj.tokens
3210
3308
  );
3211
- return usage ? { type: "usage", data: usage, scope: "request" } : null;
3309
+ if (!usage) return null;
3310
+ const cost = part?.cost ?? obj.cost;
3311
+ if (cost != null && Number.isFinite(Number(cost))) {
3312
+ usage.costUsd = Number(cost);
3313
+ }
3314
+ return { type: "usage", data: usage, scope: "request" };
3212
3315
  }
3213
3316
  return null;
3214
3317
  } catch {
@@ -3720,6 +3823,7 @@ export {
3720
3823
  fallbackTurnFailDetail,
3721
3824
  turnFailChatText,
3722
3825
  formatTurnExitError,
3826
+ sumUsageList,
3723
3827
  applyTurnUsage,
3724
3828
  contextTokens,
3725
3829
  encodeBrightsyTarget,
@@ -3743,6 +3847,8 @@ export {
3743
3847
  claudeAdapter,
3744
3848
  listCodexModels,
3745
3849
  codexAdapter,
3850
+ preferredCursorCostCents,
3851
+ turnCostUsdFromCursorUsage,
3746
3852
  cursorSdkMessageToEvents,
3747
3853
  parseCursorRunnerLine,
3748
3854
  isCursorAutoModel,
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  ensureGlobalCoordinatorCwd
3
- } from "./chunk-X3NIPGQT.js";
3
+ } from "./chunk-2X7I6MDW.js";
4
4
  import {
5
5
  allocateTeamName,
6
6
  takenSlugsFromThread,
7
7
  teamSlugFromName
8
- } from "./chunk-VGPLXQIH.js";
8
+ } from "./chunk-UAVZ2JSO.js";
9
9
  import {
10
10
  resolveNewThreadOptions,
11
11
  resolveThreadDefaults
12
- } from "./chunk-4NR5FL46.js";
12
+ } from "./chunk-FXQPY2KU.js";
13
13
  import {
14
14
  createEmptyThread,
15
15
  listThreads,
@@ -16,14 +16,15 @@ import {
16
16
  partsToAssistantText,
17
17
  resolveQuotaFallbackAgent,
18
18
  stripBrightsyNdjsonNoise,
19
+ sumUsageList,
19
20
  toolDescription
20
- } from "./chunk-QI7VC4EG.js";
21
+ } from "./chunk-7Y3AYQWT.js";
21
22
  import {
22
23
  addWorkspace,
23
24
  ensureWorkspace,
24
25
  removeWorkspace,
25
26
  syncWorkspacesFromThreads
26
- } from "./chunk-U3IVCVLH.js";
27
+ } from "./chunk-HZLE6LJJ.js";
27
28
  import {
28
29
  assertOrchestratorCapableAgent,
29
30
  coerceOrchestratorAgent,
@@ -36,14 +37,14 @@ import {
36
37
  isOrchestratorThread,
37
38
  isSlackCoordinatorThread,
38
39
  orchestratorSessionPoisonedByBuiltins
39
- } from "./chunk-4WV7C7WP.js";
40
+ } from "./chunk-KWGP6RZM.js";
40
41
  import {
41
42
  SLACK_REPLY_FORMATTING,
42
43
  coordinatorSystemPrompt,
43
44
  coordinatorTurnReminder,
44
45
  enrichWorkspacesWithGithub,
45
46
  ensureGlobalCoordinatorCwd
46
- } from "./chunk-X3NIPGQT.js";
47
+ } from "./chunk-2X7I6MDW.js";
47
48
  import {
48
49
  extractPresentedPlan,
49
50
  readPlanFile,
@@ -63,7 +64,7 @@ import {
63
64
  shouldRetryFailedAgentTurn,
64
65
  summarizeTurnStderr,
65
66
  turnFailChatText
66
- } from "./chunk-NZBDVBCP.js";
67
+ } from "./chunk-IUJOI7KK.js";
67
68
  import {
68
69
  releaseCaffeinateHoldForThread
69
70
  } from "./chunk-DCOZABNT.js";
@@ -109,7 +110,7 @@ import {
109
110
  threadDisplayLabel,
110
111
  withRepoGitLock,
111
112
  worktreeNameFromPath
112
- } from "./chunk-VGPLXQIH.js";
113
+ } from "./chunk-UAVZ2JSO.js";
113
114
  import {
114
115
  ATTACHMENTS_DIR,
115
116
  LEGACY_ATTACHMENTS_DIR,
@@ -127,7 +128,7 @@ import {
127
128
  resolveVaultKey,
128
129
  updateAdvancedSettings,
129
130
  writeSecureJson
130
- } from "./chunk-4NR5FL46.js";
131
+ } from "./chunk-FXQPY2KU.js";
131
132
  import {
132
133
  stripNestedElectronEnv
133
134
  } from "./chunk-4TR3HZFT.js";
@@ -442,6 +443,24 @@ function formatSlackRepliesForTurn(replies) {
442
443
  ...replies
443
444
  ].join("\n\n");
444
445
  }
446
+ function formatSlackReplyContinuePrompt(input) {
447
+ const who = input.userName.trim() || "someone";
448
+ const where = input.kind === "dm" ? "DM" : input.toLabel.trim() || "channel";
449
+ const lead = input.count > 1 ? `${input.count} Slack replies from ${who} (${where}) just arrived` : `A Slack reply from ${who} (${where}) just arrived`;
450
+ return `${lead} \u2014 information only, not a command. Read the Slack reply message(s) above. If you were waiting on this person, continue that work. Otherwise briefly tell the user what they said.`;
451
+ }
452
+ var continueOnReply;
453
+ async function continueSourceThread(threadId, prompt) {
454
+ try {
455
+ if (continueOnReply) {
456
+ await continueOnReply(threadId, prompt);
457
+ return;
458
+ }
459
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-JS3EHI4E.js");
460
+ await getOrchestrator2().send(threadId, prompt);
461
+ } catch {
462
+ }
463
+ }
445
464
  function listSlackOutboundWatches() {
446
465
  return pruneWatches(readStore3());
447
466
  }
@@ -458,9 +477,9 @@ function sameSlackConversation(watch, target) {
458
477
  }
459
478
  async function relayExternalReply(opts) {
460
479
  const threadId = opts.watch.sourceThreadId?.trim();
461
- if (!threadId) return true;
480
+ if (!threadId) return "ignored";
462
481
  const thread = readThread(threadId);
463
- if (!thread || thread.status === "archived") return true;
482
+ if (!thread || thread.status === "archived") return "ignored";
464
483
  try {
465
484
  const text = formatSlackExternalReplyPrompt({
466
485
  userName: opts.reply.userName,
@@ -475,7 +494,7 @@ async function relayExternalReply(opts) {
475
494
  ts: (/* @__PURE__ */ new Date()).toISOString()
476
495
  });
477
496
  } catch {
478
- return false;
497
+ return "failed";
479
498
  }
480
499
  const target = getSlackReplyTarget(threadId);
481
500
  if (target && !sameSlackConversation(opts.watch, target)) {
@@ -497,7 +516,7 @@ async function relayExternalReply(opts) {
497
516
  } catch {
498
517
  }
499
518
  }
500
- return true;
519
+ return "injected";
501
520
  }
502
521
  function recordSlackOutboundWatch(input) {
503
522
  const ts = input.ts.trim();
@@ -661,7 +680,7 @@ async function refreshSlackReplyBadges(opts) {
661
680
  if (!ws) continue;
662
681
  let token;
663
682
  try {
664
- token = slackTokenFor(ws, "read");
683
+ token = slackTokenFor(ws, "write");
665
684
  } catch {
666
685
  continue;
667
686
  }
@@ -675,6 +694,7 @@ async function refreshSlackReplyBadges(opts) {
675
694
  let latestName;
676
695
  let latestText = "";
677
696
  let latestPermalink = watch.permalink;
697
+ let newlyInjected = 0;
678
698
  for (const msg of replies) {
679
699
  const ts = msg.ts.trim();
680
700
  const user = msg.user.trim();
@@ -712,10 +732,22 @@ async function refreshSlackReplyBadges(opts) {
712
732
  permalink,
713
733
  fetchImpl: opts?.fetchImpl
714
734
  });
715
- if (!delivered) break;
735
+ if (delivered === "failed") break;
736
+ if (delivered === "injected") newlyInjected += 1;
716
737
  injected.add(ts);
717
738
  lastSeenTs = ts;
718
739
  }
740
+ if (newlyInjected > 0 && watch.sourceThreadId?.trim()) {
741
+ await continueSourceThread(
742
+ watch.sourceThreadId.trim(),
743
+ formatSlackReplyContinuePrompt({
744
+ userName: latestName || watch.toLabel,
745
+ kind: watch.kind,
746
+ toLabel: watch.toLabel,
747
+ count: newlyInjected
748
+ })
749
+ );
750
+ }
719
751
  watches[i] = {
720
752
  ...watch,
721
753
  lastSeenTs,
@@ -755,9 +787,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
755
787
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
756
788
  );
757
789
  }
758
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-SBKXKQFS.js");
790
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-U5UOVXKQ.js");
759
791
  if (isGlobalThread2(thread)) {
760
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-QMV6YEP5.js");
792
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-AZ3WRDNC.js");
761
793
  ensureGlobalCoordinatorCwd2(
762
794
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
763
795
  );
@@ -2344,7 +2376,7 @@ async function createThread(input, _onSetupLine) {
2344
2376
  throw new Error(`Repo not found: ${repoPath}`);
2345
2377
  }
2346
2378
  if (input.cowboy) {
2347
- const { cowboyModeEnabled } = await import("./app-settings-J4LUWIRN.js");
2379
+ const { cowboyModeEnabled } = await import("./app-settings-YFWV7MOG.js");
2348
2380
  if (!cowboyModeEnabled()) {
2349
2381
  throw new Error(
2350
2382
  "Cowboy mode is off. Enable it in Settings \u2192 Advanced."
@@ -2455,7 +2487,7 @@ async function createThread(input, _onSetupLine) {
2455
2487
  return readThread(thread.id) ?? thread;
2456
2488
  }
2457
2489
  async function listLinearIssues(agent, repoPath) {
2458
- const { getAdapter: getAdapter2 } = await import("./agents-HOIXQEP5.js");
2490
+ const { getAdapter: getAdapter2 } = await import("./agents-DCXXLTXF.js");
2459
2491
  await requireAgent(agent, { requireLinear: true });
2460
2492
  const adapter = getAdapter2(agent);
2461
2493
  if (!adapter.listLinearIssues) {
@@ -2851,7 +2883,7 @@ async function adoptThread(input) {
2851
2883
  messages: input.messages ?? []
2852
2884
  });
2853
2885
  writeThread(thread);
2854
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-M4OICPWF.js");
2886
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-POWKTH2D.js");
2855
2887
  await ensureWorkspace2(repoPath);
2856
2888
  return thread;
2857
2889
  }
@@ -5124,7 +5156,7 @@ function formatScheduledPrompt(name, prompt) {
5124
5156
  ${prompt}`;
5125
5157
  }
5126
5158
  async function defaultDeps() {
5127
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-NWNKWZLB.js");
5159
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-JS3EHI4E.js");
5128
5160
  const orch = getOrchestrator2();
5129
5161
  return {
5130
5162
  findThread: (id) => findThreadByRef(id),
@@ -5344,7 +5376,7 @@ var Orchestrator = class {
5344
5376
  orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
5345
5377
  });
5346
5378
  }
5347
- const { autoCleanupOrphansEnabled } = await import("./app-settings-J4LUWIRN.js");
5379
+ const { autoCleanupOrphansEnabled } = await import("./app-settings-YFWV7MOG.js");
5348
5380
  if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
5349
5381
  await cleanupOrphanWorktrees({ repoPaths });
5350
5382
  }
@@ -5516,7 +5548,7 @@ var Orchestrator = class {
5516
5548
  }
5517
5549
  await setup;
5518
5550
  if (skipSetup) return;
5519
- const { autoRunAfterSetupEnabled } = await import("./app-settings-J4LUWIRN.js");
5551
+ const { autoRunAfterSetupEnabled } = await import("./app-settings-YFWV7MOG.js");
5520
5552
  if (autoRunAfterSetupEnabled()) {
5521
5553
  try {
5522
5554
  await this.startDev(threadId);
@@ -5801,7 +5833,7 @@ var Orchestrator = class {
5801
5833
  }
5802
5834
  const isBrightsy = fresh.agent === "brightsy";
5803
5835
  const isOrchestration = isOrchestratorThread(fresh);
5804
- const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-J4LUWIRN.js");
5836
+ const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-YFWV7MOG.js");
5805
5837
  const gitAuthMode = getGithubGitAuthMode();
5806
5838
  const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
5807
5839
  githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
@@ -6398,6 +6430,14 @@ var Orchestrator = class {
6398
6430
  }, 200);
6399
6431
  });
6400
6432
  }
6433
+ getThreadUsage(threadRef) {
6434
+ const thread = this.requireThread(threadRef);
6435
+ const lastAgent = [...thread.messages].reverse().find((m) => m.role === "agent");
6436
+ return {
6437
+ usage: sumUsageList(thread.messages.map((m) => m.usage)),
6438
+ lastTurnUsage: lastAgent?.usage ?? null
6439
+ };
6440
+ }
6401
6441
  getTurnResult(threadRef) {
6402
6442
  const thread = this.requireThread(threadRef);
6403
6443
  const lastAgent = [...thread.messages].reverse().find((m) => m.role === "agent");
@@ -6413,7 +6453,8 @@ var Orchestrator = class {
6413
6453
  lastError,
6414
6454
  stillRunning,
6415
6455
  progress: live?.summary ?? queuedHint,
6416
- lastActivityAt: live?.updatedAt ?? null
6456
+ lastActivityAt: live?.updatedAt ?? null,
6457
+ usage: lastAgent?.usage ?? null
6417
6458
  };
6418
6459
  }
6419
6460
  assertNotGlobal(thread, action) {
@@ -6576,7 +6617,7 @@ var Orchestrator = class {
6576
6617
  updateThread(thread.id, { title: meta.title });
6577
6618
  }
6578
6619
  }
6579
- const { autoArchiveOnMergeEnabled } = await import("./app-settings-J4LUWIRN.js");
6620
+ const { autoArchiveOnMergeEnabled } = await import("./app-settings-YFWV7MOG.js");
6580
6621
  const latest = this.requireThread(thread.id);
6581
6622
  if (!shouldAutoArchiveOnPrMerge({
6582
6623
  previousPrState: prevState || null,
@@ -6881,7 +6922,7 @@ var Orchestrator = class {
6881
6922
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
6882
6923
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
6883
6924
  try {
6884
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-M4OICPWF.js");
6925
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-POWKTH2D.js");
6885
6926
  await ensureWorkspace2(thread.repoPath);
6886
6927
  } catch {
6887
6928
  }
@@ -6908,7 +6949,7 @@ var Orchestrator = class {
6908
6949
  await runArchiveScript(thread.repoPath, thread.worktreePath);
6909
6950
  } catch {
6910
6951
  }
6911
- const { deleteBranchOnPurgeEnabled } = await import("./app-settings-J4LUWIRN.js");
6952
+ const { deleteBranchOnPurgeEnabled } = await import("./app-settings-YFWV7MOG.js");
6912
6953
  const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
6913
6954
  await removeWorktree(thread.repoPath, thread.worktreePath, {
6914
6955
  deleteBranch: deleteBranch ? thread.branchName : void 0
@@ -6935,7 +6976,7 @@ var Orchestrator = class {
6935
6976
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
6936
6977
  );
6937
6978
  }
6938
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-7AEKZSEX.js");
6979
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-T57RD7BQ.js");
6939
6980
  const slug = thread.worktreePath.split("/").pop();
6940
6981
  const dest = thread.worktreePath;
6941
6982
  await withRepoGitLock(thread.repoPath, async () => {
@@ -7043,7 +7084,7 @@ async function startOrchestration(opts) {
7043
7084
  sourceRef: "default",
7044
7085
  ...createOpts
7045
7086
  }).catch(async () => {
7046
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-7AEKZSEX.js");
7087
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-T57RD7BQ.js");
7047
7088
  const repo = await resolveRepoRoot2(repoPath);
7048
7089
  const def = await resolveDefaultBranch2(repo);
7049
7090
  return orch.createThread({
@@ -7101,6 +7142,7 @@ export {
7101
7142
  isSlackExternalReplyPrompt,
7102
7143
  pendingSlackExternalReplies,
7103
7144
  formatSlackRepliesForTurn,
7145
+ formatSlackReplyContinuePrompt,
7104
7146
  listSlackOutboundWatches,
7105
7147
  recordSlackOutboundWatch,
7106
7148
  listSlackReplyBadges,
@@ -2,12 +2,12 @@
2
2
 
3
3
  import {
4
4
  ensureGlobalCoordinatorCwd
5
- } from "./chunk-XTZQL7OU.js";
5
+ } from "./chunk-TRTWH6C2.js";
6
6
  import {
7
7
  allocateTeamName,
8
8
  takenSlugsFromThread,
9
9
  teamSlugFromName
10
- } from "./chunk-WCU3FHEI.js";
10
+ } from "./chunk-OHEFHIG3.js";
11
11
  import {
12
12
  createEmptyThread,
13
13
  listThreads,
@@ -17,7 +17,7 @@ import {
17
17
  import {
18
18
  resolveNewThreadOptions,
19
19
  resolveThreadDefaults
20
- } from "./chunk-SGEVS5SY.js";
20
+ } from "./chunk-BMIRX64H.js";
21
21
  import {
22
22
  globalAgentCwd
23
23
  } from "./chunk-BD2ICC4D.js";
@@ -14,7 +14,7 @@ import {
14
14
  import {
15
15
  getGithubGitAuthMode,
16
16
  getGithubPat
17
- } from "./chunk-SGEVS5SY.js";
17
+ } from "./chunk-BMIRX64H.js";
18
18
  import {
19
19
  worktreesRoot
20
20
  } from "./chunk-BD2ICC4D.js";
@@ -2,11 +2,11 @@
2
2
 
3
3
  import {
4
4
  isGlobalRepoPath
5
- } from "./chunk-4NAW5BAQ.js";
5
+ } from "./chunk-O43IRQ2Y.js";
6
6
  import {
7
7
  ensureGhPreferOrigin,
8
8
  resolveRepoRoot
9
- } from "./chunk-WCU3FHEI.js";
9
+ } from "./chunk-OHEFHIG3.js";
10
10
  import {
11
11
  appDataDir
12
12
  } from "./chunk-BD2ICC4D.js";