@sideboard-ai/core 0.1.122 → 0.1.125

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.
@@ -349,6 +349,46 @@ function turnCostUsdFromCursorUsage(before, after) {
349
349
  if (!(delta >= 0) || !Number.isFinite(delta)) return void 0;
350
350
  return delta / 100;
351
351
  }
352
+ function costUsdFromRunSnapshot(usage, runId) {
353
+ if (!usage?.runs?.length || !runId.trim()) return void 0;
354
+ const row = usage.runs.find((r) => r.runId === runId);
355
+ const cents = preferredCursorCostCents(row?.cost);
356
+ return cents != null ? cents / 100 : void 0;
357
+ }
358
+ function cursorGetUsageRunId(runId) {
359
+ const id = runId?.trim();
360
+ if (!id || id.startsWith("run-")) return void 0;
361
+ return id;
362
+ }
363
+ var CURSOR_COST_POLL_MS = [0, 400, 800, 1600, 3200];
364
+ function sleep(ms) {
365
+ return new Promise((resolve) => {
366
+ setTimeout(resolve, ms);
367
+ });
368
+ }
369
+ async function fetchCursorTurnCostUsd(getUsage, usageBefore, opts) {
370
+ const lookupRunId = cursorGetUsageRunId(opts?.runId);
371
+ for (const delay of CURSOR_COST_POLL_MS) {
372
+ if (delay > 0) await sleep(delay);
373
+ try {
374
+ if (lookupRunId) {
375
+ const scoped = await getUsage({ runId: lookupRunId });
376
+ const direct = costUsdFromRunSnapshot(scoped, lookupRunId);
377
+ if (direct != null) return direct;
378
+ }
379
+ const after = await getUsage();
380
+ const delta = turnCostUsdFromCursorUsage(usageBefore, after);
381
+ if (delta != null) return delta;
382
+ } catch (err) {
383
+ if (isCursorUsageUnavailableError(err)) return void 0;
384
+ }
385
+ }
386
+ return void 0;
387
+ }
388
+ function isCursorUsageUnavailableError(err) {
389
+ const msg = err instanceof Error ? err.message : String(err);
390
+ return /feature_unavailable|feature unavailable|not available for your account/i.test(msg);
391
+ }
352
392
  function cursorCostOnlyUsageEvent(costUsd) {
353
393
  return {
354
394
  type: "usage",
@@ -782,6 +822,7 @@ async function main() {
782
822
  usageBefore = await agent.getUsage();
783
823
  } catch {
784
824
  }
825
+ let lastUsageRunId;
785
826
  const run2 = await sendPrompt(agent, {
786
827
  onDelta: ({ update }) => {
787
828
  bump();
@@ -807,6 +848,10 @@ async function main() {
807
848
  activity
808
849
  )) {
809
850
  bump();
851
+ const sdkMsg = msg;
852
+ if (sdkMsg.type === "usage" && typeof sdkMsg.run_id === "string" && sdkMsg.run_id.trim()) {
853
+ lastUsageRunId = sdkMsg.run_id.trim();
854
+ }
810
855
  for (const event of cursorSdkMessageToEvents(msg)) {
811
856
  stream.push(event);
812
857
  }
@@ -828,15 +873,11 @@ async function main() {
828
873
  }
829
874
  if (result.status === "cancelled") return 0;
830
875
  try {
831
- let usageAfter = await agent.getUsage();
832
- let costUsd = turnCostUsdFromCursorUsage(usageBefore, usageAfter);
833
- if (costUsd == null) {
834
- await new Promise((resolve) => {
835
- setTimeout(resolve, 400);
836
- });
837
- usageAfter = await agent.getUsage();
838
- costUsd = turnCostUsdFromCursorUsage(usageBefore, usageAfter);
839
- }
876
+ const costUsd = await fetchCursorTurnCostUsd(
877
+ (opts) => agent.getUsage(opts),
878
+ usageBefore,
879
+ { runId: lastUsageRunId }
880
+ );
840
881
  if (costUsd != null) {
841
882
  emit(cursorCostOnlyUsageEvent(costUsd));
842
883
  }
@@ -10,9 +10,9 @@ import {
10
10
  cursorDeltaToEvents,
11
11
  cursorSdkMessageToEvents,
12
12
  ensureCursorRipgrepPath,
13
- formatUnknownDetail,
14
- turnCostUsdFromCursorUsage
15
- } from "../chunk-3M5CVKHK.js";
13
+ fetchCursorTurnCostUsd,
14
+ formatUnknownDetail
15
+ } from "../chunk-IUJOI7KK.js";
16
16
  import {
17
17
  dropNestedElectronEnvFromProcess
18
18
  } from "../chunk-4TR3HZFT.js";
@@ -266,6 +266,7 @@ async function main() {
266
266
  usageBefore = await agent.getUsage();
267
267
  } catch {
268
268
  }
269
+ let lastUsageRunId;
269
270
  const run = await sendPrompt(agent, {
270
271
  onDelta: ({ update }) => {
271
272
  bump();
@@ -291,6 +292,10 @@ async function main() {
291
292
  activity
292
293
  )) {
293
294
  bump();
295
+ const sdkMsg = msg;
296
+ if (sdkMsg.type === "usage" && typeof sdkMsg.run_id === "string" && sdkMsg.run_id.trim()) {
297
+ lastUsageRunId = sdkMsg.run_id.trim();
298
+ }
294
299
  for (const event of cursorSdkMessageToEvents(msg)) {
295
300
  stream.push(event);
296
301
  }
@@ -312,15 +317,11 @@ async function main() {
312
317
  }
313
318
  if (result.status === "cancelled") return 0;
314
319
  try {
315
- let usageAfter = await agent.getUsage();
316
- let costUsd = turnCostUsdFromCursorUsage(usageBefore, usageAfter);
317
- if (costUsd == null) {
318
- await new Promise((resolve) => {
319
- setTimeout(resolve, 400);
320
- });
321
- usageAfter = await agent.getUsage();
322
- costUsd = turnCostUsdFromCursorUsage(usageBefore, usageAfter);
323
- }
320
+ const costUsd = await fetchCursorTurnCostUsd(
321
+ (opts) => agent.getUsage(opts),
322
+ usageBefore,
323
+ { runId: lastUsageRunId }
324
+ );
324
325
  if (costUsd != null) {
325
326
  emit(cursorCostOnlyUsageEvent(costUsd));
326
327
  }
@@ -28,7 +28,7 @@ import {
28
28
  resolveCursorModelId,
29
29
  resolveLoginCommand,
30
30
  resolveQuotaFallbackAgent
31
- } from "./chunk-QHST4DZQ.js";
31
+ } from "./chunk-7Y3AYQWT.js";
32
32
  import "./chunk-EKIDHL2T.js";
33
33
  import {
34
34
  ORCHESTRATOR_AGENT_KINDS,
@@ -42,7 +42,7 @@ import {
42
42
  parseCursorRunnerLine,
43
43
  preferredCursorCostCents,
44
44
  turnCostUsdFromCursorUsage
45
- } from "./chunk-3M5CVKHK.js";
45
+ } from "./chunk-IUJOI7KK.js";
46
46
  import "./chunk-UAVZ2JSO.js";
47
47
  import "./chunk-FKOIHGKV.js";
48
48
  import "./chunk-FXQPY2KU.js";
@@ -34,7 +34,7 @@ import {
34
34
  resolveLoginCommand,
35
35
  resolveQuotaFallbackAgent,
36
36
  turnCostUsdFromCursorUsage
37
- } from "./chunk-OEBYW4TO.js";
37
+ } from "./chunk-JNAIKICO.js";
38
38
  import "./chunk-YMRT2DU6.js";
39
39
  import {
40
40
  ORCHESTRATOR_AGENT_KINDS,
@@ -20,7 +20,7 @@ import {
20
20
  packagedMcpStdioPath,
21
21
  parseCursorRunnerLine,
22
22
  resolveNodeLaunch
23
- } from "./chunk-3M5CVKHK.js";
23
+ } from "./chunk-IUJOI7KK.js";
24
24
  import {
25
25
  codexUnattendedGitConfigArgs,
26
26
  mergeAgentGitAuthEnv,
@@ -18,7 +18,7 @@ import {
18
18
  stripBrightsyNdjsonNoise,
19
19
  sumUsageList,
20
20
  toolDescription
21
- } from "./chunk-QHST4DZQ.js";
21
+ } from "./chunk-7Y3AYQWT.js";
22
22
  import {
23
23
  addWorkspace,
24
24
  ensureWorkspace,
@@ -64,7 +64,7 @@ import {
64
64
  shouldRetryFailedAgentTurn,
65
65
  summarizeTurnStderr,
66
66
  turnFailChatText
67
- } from "./chunk-3M5CVKHK.js";
67
+ } from "./chunk-IUJOI7KK.js";
68
68
  import {
69
69
  releaseCaffeinateHoldForThread
70
70
  } from "./chunk-DCOZABNT.js";
@@ -364,26 +364,9 @@ function storePath3() {
364
364
  function watchId(teamId, channelId, ts) {
365
365
  return `${teamId}:${channelId}:${ts}`;
366
366
  }
367
- function badgeId(teamId, userId) {
368
- return `${teamId}:${userId}`;
369
- }
370
367
  function slackArchiveUrl(channelId, ts) {
371
368
  return `https://slack.com/archives/${channelId}/p${ts.replace(".", "")}`;
372
369
  }
373
- function initialsFromName(name) {
374
- const parts = name.trim().split(/\s+/).filter(Boolean);
375
- if (parts.length === 0) return "?";
376
- if (parts.length === 1) {
377
- const w = parts[0];
378
- return (w.slice(0, 2) || "?").toUpperCase();
379
- }
380
- return `${parts[0][0] ?? ""}${parts[parts.length - 1][0] ?? ""}`.toUpperCase();
381
- }
382
- function hueFromId(id) {
383
- let h = 0;
384
- for (const c of id) h = h * 31 + c.charCodeAt(0) >>> 0;
385
- return h % 360;
386
- }
387
370
  function tsNewer(a, b) {
388
371
  return Number(a) > Number(b);
389
372
  }
@@ -456,7 +439,7 @@ async function continueSourceThread(threadId, prompt) {
456
439
  await continueOnReply(threadId, prompt);
457
440
  return;
458
441
  }
459
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-JE5MSVED.js");
442
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-HN3LYHFN.js");
460
443
  await getOrchestrator2().send(threadId, prompt);
461
444
  } catch {
462
445
  }
@@ -540,7 +523,6 @@ function recordSlackOutboundWatch(input) {
540
523
  sourceThreadId: input.sourceThreadId?.trim() || void 0,
541
524
  postedAt: (/* @__PURE__ */ new Date()).toISOString(),
542
525
  lastSeenTs: ts,
543
- unread: false,
544
526
  permalink: slackArchiveUrl(channelId, ts),
545
527
  injectedReplyTs: [],
546
528
  replies: []
@@ -627,49 +609,9 @@ async function fetchMessages(token, watch, fetchImpl) {
627
609
  }
628
610
  return out;
629
611
  }
630
- function listSlackReplyBadges() {
631
- const unread = readStore3().filter((w) => w.unread && w.replyUserId && w.permalink);
632
- const byUser = /* @__PURE__ */ new Map();
633
- for (const w of unread) {
634
- const id = badgeId(w.teamId, w.replyUserId);
635
- const prev = byUser.get(id);
636
- if (!prev || tsNewer(w.replyTs || "", prev.replyTs || "")) {
637
- byUser.set(id, w);
638
- }
639
- }
640
- return [...byUser.entries()].map(([id, w]) => {
641
- const userName = w.replyUserName || w.toLabel || "Slack";
642
- return {
643
- id,
644
- userId: w.replyUserId,
645
- userName,
646
- initials: initialsFromName(userName),
647
- hue: hueFromId(w.replyUserId),
648
- permalink: w.permalink || slackArchiveUrl(w.channelId, w.replyTs || w.ts),
649
- label: w.toLabel,
650
- preview: w.replyPreview,
651
- repliedAt: w.replyTs || w.postedAt
652
- };
653
- }).sort((a, b) => b.repliedAt.localeCompare(a.repliedAt));
654
- }
655
- function dismissSlackReplyBadge(badgeKey) {
656
- const key = badgeKey.trim();
657
- const watches = readStore3().map((w) => {
658
- if (!w.unread || !w.replyUserId) return w;
659
- if (badgeId(w.teamId, w.replyUserId) !== key) return w;
660
- return { ...w, unread: false };
661
- });
662
- writeStore2(watches);
663
- return listSlackReplyBadges();
664
- }
665
- function permalinkForSlackReplyBadge(badgeKey) {
666
- return listSlackReplyBadges().find((b) => b.id === badgeKey)?.permalink ?? null;
667
- }
668
- async function refreshSlackReplyBadges(opts) {
612
+ async function pollSlackOutboundWatches(opts) {
669
613
  const now = opts?.now ?? Date.now();
670
- if (!opts?.force && now - lastPollMs < POLL_INTERVAL_MS) {
671
- return listSlackReplyBadges();
672
- }
614
+ if (!opts?.force && now - lastPollMs < POLL_INTERVAL_MS) return;
673
615
  lastPollMs = now;
674
616
  const existing = readStore3();
675
617
  let watches = pruneWatches(existing, now);
@@ -680,7 +622,7 @@ async function refreshSlackReplyBadges(opts) {
680
622
  if (!ws) continue;
681
623
  let token;
682
624
  try {
683
- token = slackTokenFor(ws, "read");
625
+ token = slackTokenFor(ws, "write");
684
626
  } catch {
685
627
  continue;
686
628
  }
@@ -690,9 +632,7 @@ async function refreshSlackReplyBadges(opts) {
690
632
  const injected = new Set(watch.injectedReplyTs ?? []);
691
633
  const collected = [...watch.replies ?? []];
692
634
  let lastSeenTs = watch.lastSeenTs;
693
- let latestUser;
694
635
  let latestName;
695
- let latestText = "";
696
636
  let latestPermalink = watch.permalink;
697
637
  let newlyInjected = 0;
698
638
  for (const msg of replies) {
@@ -718,9 +658,7 @@ async function refreshSlackReplyBadges(opts) {
718
658
  text: msg.text ?? ""
719
659
  };
720
660
  if (!collected.some((r) => r.ts === ts)) collected.push(reply);
721
- latestUser = user;
722
661
  latestName = replyUserName;
723
- latestText = reply.text;
724
662
  latestPermalink = permalink;
725
663
  if (injected.has(ts)) {
726
664
  lastSeenTs = ts;
@@ -751,11 +689,6 @@ async function refreshSlackReplyBadges(opts) {
751
689
  watches[i] = {
752
690
  ...watch,
753
691
  lastSeenTs,
754
- unread: true,
755
- replyUserId: latestUser,
756
- replyUserName: latestName,
757
- replyTs: lastSeenTs,
758
- replyPreview: latestText.slice(0, 140),
759
692
  permalink: latestPermalink,
760
693
  injectedReplyTs: [...injected],
761
694
  replies: collected.slice(-MAX_REPLIES_PER_WATCH)
@@ -763,7 +696,6 @@ async function refreshSlackReplyBadges(opts) {
763
696
  changed = true;
764
697
  }
765
698
  if (changed) writeStore2(watches);
766
- return listSlackReplyBadges();
767
699
  }
768
700
 
769
701
  // src/orchestrator/orchestrator.ts
@@ -2487,7 +2419,7 @@ async function createThread(input, _onSetupLine) {
2487
2419
  return readThread(thread.id) ?? thread;
2488
2420
  }
2489
2421
  async function listLinearIssues(agent, repoPath) {
2490
- const { getAdapter: getAdapter2 } = await import("./agents-DRJMECCE.js");
2422
+ const { getAdapter: getAdapter2 } = await import("./agents-DCXXLTXF.js");
2491
2423
  await requireAgent(agent, { requireLinear: true });
2492
2424
  const adapter = getAdapter2(agent);
2493
2425
  if (!adapter.listLinearIssues) {
@@ -5156,7 +5088,7 @@ function formatScheduledPrompt(name, prompt) {
5156
5088
  ${prompt}`;
5157
5089
  }
5158
5090
  async function defaultDeps() {
5159
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-JE5MSVED.js");
5091
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-HN3LYHFN.js");
5160
5092
  const orch = getOrchestrator2();
5161
5093
  return {
5162
5094
  findThread: (id) => findThreadByRef(id),
@@ -7145,10 +7077,7 @@ export {
7145
7077
  formatSlackReplyContinuePrompt,
7146
7078
  listSlackOutboundWatches,
7147
7079
  recordSlackOutboundWatch,
7148
- listSlackReplyBadges,
7149
- dismissSlackReplyBadge,
7150
- permalinkForSlackReplyBadge,
7151
- refreshSlackReplyBadges,
7080
+ pollSlackOutboundWatches,
7152
7081
  applyPromptCacheTtlEnv,
7153
7082
  spawnAgentTurn,
7154
7083
  AGENT_GIT_ACTIONS,
@@ -29,7 +29,7 @@ import {
29
29
  summarizeTurnStderr,
30
30
  toolDescription,
31
31
  turnFailChatText
32
- } from "./chunk-OEBYW4TO.js";
32
+ } from "./chunk-JNAIKICO.js";
33
33
  import {
34
34
  addWorkspace,
35
35
  ensureWorkspace,
@@ -303,26 +303,9 @@ function storePath3() {
303
303
  function watchId(teamId, channelId, ts) {
304
304
  return `${teamId}:${channelId}:${ts}`;
305
305
  }
306
- function badgeId(teamId, userId) {
307
- return `${teamId}:${userId}`;
308
- }
309
306
  function slackArchiveUrl(channelId, ts) {
310
307
  return `https://slack.com/archives/${channelId}/p${ts.replace(".", "")}`;
311
308
  }
312
- function initialsFromName(name) {
313
- const parts = name.trim().split(/\s+/).filter(Boolean);
314
- if (parts.length === 0) return "?";
315
- if (parts.length === 1) {
316
- const w = parts[0];
317
- return (w.slice(0, 2) || "?").toUpperCase();
318
- }
319
- return `${parts[0][0] ?? ""}${parts[parts.length - 1][0] ?? ""}`.toUpperCase();
320
- }
321
- function hueFromId(id) {
322
- let h = 0;
323
- for (const c of id) h = h * 31 + c.charCodeAt(0) >>> 0;
324
- return h % 360;
325
- }
326
309
  function tsNewer(a, b) {
327
310
  return Number(a) > Number(b);
328
311
  }
@@ -395,7 +378,7 @@ async function continueSourceThread(threadId, prompt) {
395
378
  await continueOnReply(threadId, prompt);
396
379
  return;
397
380
  }
398
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-EYU7OUFA.js");
381
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-FZYM7I42.js");
399
382
  await getOrchestrator2().send(threadId, prompt);
400
383
  } catch {
401
384
  }
@@ -479,7 +462,6 @@ function recordSlackOutboundWatch(input) {
479
462
  sourceThreadId: input.sourceThreadId?.trim() || void 0,
480
463
  postedAt: (/* @__PURE__ */ new Date()).toISOString(),
481
464
  lastSeenTs: ts,
482
- unread: false,
483
465
  permalink: slackArchiveUrl(channelId, ts),
484
466
  injectedReplyTs: [],
485
467
  replies: []
@@ -566,36 +548,9 @@ async function fetchMessages(token, watch, fetchImpl) {
566
548
  }
567
549
  return out;
568
550
  }
569
- function listSlackReplyBadges() {
570
- const unread = readStore3().filter((w) => w.unread && w.replyUserId && w.permalink);
571
- const byUser = /* @__PURE__ */ new Map();
572
- for (const w of unread) {
573
- const id = badgeId(w.teamId, w.replyUserId);
574
- const prev = byUser.get(id);
575
- if (!prev || tsNewer(w.replyTs || "", prev.replyTs || "")) {
576
- byUser.set(id, w);
577
- }
578
- }
579
- return [...byUser.entries()].map(([id, w]) => {
580
- const userName = w.replyUserName || w.toLabel || "Slack";
581
- return {
582
- id,
583
- userId: w.replyUserId,
584
- userName,
585
- initials: initialsFromName(userName),
586
- hue: hueFromId(w.replyUserId),
587
- permalink: w.permalink || slackArchiveUrl(w.channelId, w.replyTs || w.ts),
588
- label: w.toLabel,
589
- preview: w.replyPreview,
590
- repliedAt: w.replyTs || w.postedAt
591
- };
592
- }).sort((a, b) => b.repliedAt.localeCompare(a.repliedAt));
593
- }
594
- async function refreshSlackReplyBadges(opts) {
551
+ async function pollSlackOutboundWatches(opts) {
595
552
  const now = opts?.now ?? Date.now();
596
- if (!opts?.force && now - lastPollMs < POLL_INTERVAL_MS) {
597
- return listSlackReplyBadges();
598
- }
553
+ if (!opts?.force && now - lastPollMs < POLL_INTERVAL_MS) return;
599
554
  lastPollMs = now;
600
555
  const existing = readStore3();
601
556
  let watches = pruneWatches(existing, now);
@@ -606,7 +561,7 @@ async function refreshSlackReplyBadges(opts) {
606
561
  if (!ws) continue;
607
562
  let token;
608
563
  try {
609
- token = slackTokenFor(ws, "read");
564
+ token = slackTokenFor(ws, "write");
610
565
  } catch {
611
566
  continue;
612
567
  }
@@ -616,9 +571,7 @@ async function refreshSlackReplyBadges(opts) {
616
571
  const injected = new Set(watch.injectedReplyTs ?? []);
617
572
  const collected = [...watch.replies ?? []];
618
573
  let lastSeenTs = watch.lastSeenTs;
619
- let latestUser;
620
574
  let latestName;
621
- let latestText = "";
622
575
  let latestPermalink = watch.permalink;
623
576
  let newlyInjected = 0;
624
577
  for (const msg of replies) {
@@ -644,9 +597,7 @@ async function refreshSlackReplyBadges(opts) {
644
597
  text: msg.text ?? ""
645
598
  };
646
599
  if (!collected.some((r) => r.ts === ts)) collected.push(reply);
647
- latestUser = user;
648
600
  latestName = replyUserName;
649
- latestText = reply.text;
650
601
  latestPermalink = permalink;
651
602
  if (injected.has(ts)) {
652
603
  lastSeenTs = ts;
@@ -677,11 +628,6 @@ async function refreshSlackReplyBadges(opts) {
677
628
  watches[i] = {
678
629
  ...watch,
679
630
  lastSeenTs,
680
- unread: true,
681
- replyUserId: latestUser,
682
- replyUserName: latestName,
683
- replyTs: lastSeenTs,
684
- replyPreview: latestText.slice(0, 140),
685
631
  permalink: latestPermalink,
686
632
  injectedReplyTs: [...injected],
687
633
  replies: collected.slice(-MAX_REPLIES_PER_WATCH)
@@ -689,7 +635,6 @@ async function refreshSlackReplyBadges(opts) {
689
635
  changed = true;
690
636
  }
691
637
  if (changed) writeStore(watches);
692
- return listSlackReplyBadges();
693
638
  }
694
639
 
695
640
  // src/orchestrator/orchestrator.ts
@@ -2442,7 +2387,7 @@ async function createThread(input, _onSetupLine) {
2442
2387
  return readThread(thread.id) ?? thread;
2443
2388
  }
2444
2389
  async function listLinearIssues(agent, repoPath) {
2445
- const { getAdapter: getAdapter2 } = await import("./agents-U5PWL3AJ.js");
2390
+ const { getAdapter: getAdapter2 } = await import("./agents-DPR2TDNF.js");
2446
2391
  await requireAgent(agent, { requireLinear: true });
2447
2392
  const adapter = getAdapter2(agent);
2448
2393
  if (!adapter.listLinearIssues) {
@@ -4985,7 +4930,7 @@ function formatScheduledPrompt(name, prompt) {
4985
4930
  ${prompt}`;
4986
4931
  }
4987
4932
  async function defaultDeps() {
4988
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-EYU7OUFA.js");
4933
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-FZYM7I42.js");
4989
4934
  const orch = getOrchestrator2();
4990
4935
  return {
4991
4936
  findThread: (id) => findThreadByRef(id),
@@ -6941,7 +6886,7 @@ export {
6941
6886
  requireSlackWorkspace,
6942
6887
  listSlackOutboundWatches,
6943
6888
  recordSlackOutboundWatch,
6944
- refreshSlackReplyBadges,
6889
+ pollSlackOutboundWatches,
6945
6890
  AGENT_GIT_ACTIONS,
6946
6891
  listLinearIssues,
6947
6892
  readTurnLive,
@@ -520,6 +520,46 @@ function turnCostUsdFromCursorUsage(before, after) {
520
520
  if (!(delta >= 0) || !Number.isFinite(delta)) return void 0;
521
521
  return delta / 100;
522
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
+ }
523
563
  function cursorCostOnlyUsageEvent(costUsd) {
524
564
  return {
525
565
  type: "usage",
@@ -831,6 +871,7 @@ export {
831
871
  resolveNodeLaunch,
832
872
  preferredCursorCostCents,
833
873
  turnCostUsdFromCursorUsage,
874
+ fetchCursorTurnCostUsd,
834
875
  cursorCostOnlyUsageEvent,
835
876
  cursorSdkMessageToEvents,
836
877
  cursorDeltaToEvents,