@sentry/junior 0.95.0 → 0.96.0

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 (49) hide show
  1. package/dist/{agent-hooks-FTQ5EGPO.js → agent-hooks-5URSMY3O.js} +6 -6
  2. package/dist/api/people/list.js +5 -5
  3. package/dist/api/people/profile.js +5 -5
  4. package/dist/api-reference.d.ts +1 -1
  5. package/dist/app.js +24 -20
  6. package/dist/{catalog-runtime-2D7IVKUT.js → catalog-runtime-MSMAYYIK.js} +3 -3
  7. package/dist/chat/logging.d.ts +2 -2
  8. package/dist/chat/plugins/auth/oauth-request.d.ts +2 -0
  9. package/dist/chat/resource-events/notification.d.ts +2 -0
  10. package/dist/chat/runtime/agent-run-outcome.d.ts +3 -0
  11. package/dist/chat/sentry.d.ts +1 -1
  12. package/dist/chat/state/turn-session.d.ts +3 -1
  13. package/dist/chat/usage.d.ts +27 -13
  14. package/dist/{chunk-E3E2XNCN.js → chunk-2NAZZPPS.js} +2 -2
  15. package/dist/{chunk-CRRBJ3JP.js → chunk-5C6XTTFI.js} +4 -4
  16. package/dist/{chunk-3DA7X2U3.js → chunk-6GWA276C.js} +15 -0
  17. package/dist/{chunk-EKNJM5IG.js → chunk-AAZXTVJT.js} +2 -2
  18. package/dist/{chunk-WCMQJE4F.js → chunk-BYZWPRJA.js} +3 -3
  19. package/dist/{chunk-HZNJLKKI.js → chunk-DZENG5ML.js} +1 -1
  20. package/dist/{chunk-5XMNOD3S.js → chunk-GQ3GK22G.js} +3 -3
  21. package/dist/{chunk-WPOJ443W.js → chunk-I35CTGPO.js} +58 -6
  22. package/dist/{chunk-HCXXB35T.js → chunk-IYM2SIVG.js} +21 -19
  23. package/dist/{chunk-GVOUCI2O.js → chunk-L7CDEIVJ.js} +12 -4
  24. package/dist/{chunk-WAGQ377B.js → chunk-MNTINMWR.js} +170 -29
  25. package/dist/{chunk-XX4N4E6C.js → chunk-P3YFQLEN.js} +8 -8
  26. package/dist/{chunk-HDTO3A74.js → chunk-PMNN6ST4.js} +2 -2
  27. package/dist/{chunk-6ONME5IG.js → chunk-RITD7E5L.js} +2 -2
  28. package/dist/{chunk-NSCHU54X.js → chunk-S5KZ5LPG.js} +4 -4
  29. package/dist/{chunk-KDPCGVIT.js → chunk-UKHVMPX5.js} +5 -61
  30. package/dist/{chunk-N4RNJ32C.js → chunk-WM6KHPBQ.js} +1 -1
  31. package/dist/{chunk-AYP4ERVZ.js → chunk-YDT7SNCN.js} +1 -1
  32. package/dist/{chunk-GUE7HTNR.js → chunk-YDVEH3SB.js} +1 -1
  33. package/dist/cli/chat.js +19 -19
  34. package/dist/cli/check.js +4 -4
  35. package/dist/cli/main.js +1 -1
  36. package/dist/cli/plugins.js +8 -8
  37. package/dist/cli/snapshot-warmup.js +5 -5
  38. package/dist/cli/upgrade.js +8 -8
  39. package/dist/{db-W55B74OP.js → db-2D6RMG67.js} +4 -4
  40. package/dist/instrumentation.js +1 -1
  41. package/dist/{legacy-import-ZPLGLAFD.js → legacy-import-VZ2MEGP7.js} +5 -5
  42. package/dist/reporting/conversations/summaries.d.ts +3 -0
  43. package/dist/reporting/conversations/types.d.ts +13 -0
  44. package/dist/reporting.d.ts +1 -1
  45. package/dist/reporting.js +113 -23
  46. package/dist/{runner-OOSBDYRK.js → runner-JZBRQP4F.js} +10 -10
  47. package/dist/{sentry-EGFOV3DH.js → sentry-JMWTS32N.js} +11 -1
  48. package/dist/{validation-QCGRFRFZ.js → validation-6XOOQGME.js} +4 -4
  49. package/package.json +7 -7
@@ -4,12 +4,13 @@ import {
4
4
  } from "./chunk-OB42YVAE.js";
5
5
  import {
6
6
  captureException,
7
+ getActiveSpan,
7
8
  sentry_exports,
8
9
  setTag,
9
10
  setUser,
10
11
  startSpan,
11
12
  withScope
12
- } from "./chunk-3DA7X2U3.js";
13
+ } from "./chunk-6GWA276C.js";
13
14
  import {
14
15
  getDeploymentTelemetryAttributes,
15
16
  parseSlackTeamId
@@ -1184,14 +1185,14 @@ function getTracePropagationHeaders() {
1184
1185
  return headers;
1185
1186
  }
1186
1187
  function setSpanAttributes(attributes) {
1187
- const span = (void 0)();
1188
+ const span = getActiveSpan();
1188
1189
  if (!span) {
1189
1190
  return;
1190
1191
  }
1191
1192
  setAttributesOnSpan(span, attributes);
1192
1193
  }
1193
1194
  function setSpanStatus(status) {
1194
- const span = (void 0)();
1195
+ const span = getActiveSpan();
1195
1196
  if (!span) {
1196
1197
  return;
1197
1198
  }
@@ -1288,6 +1289,12 @@ function toFiniteTokenCount(value) {
1288
1289
  const rounded = Math.floor(value);
1289
1290
  return rounded >= 0 ? rounded : void 0;
1290
1291
  }
1292
+ function toFiniteCost(value) {
1293
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
1294
+ }
1295
+ function addCost(left, right) {
1296
+ return Math.round(((left ?? 0) + right) * 1e12) / 1e12;
1297
+ }
1291
1298
  function sumTokenCounts(...values) {
1292
1299
  let total = 0;
1293
1300
  let hasValue = false;
@@ -1305,8 +1312,16 @@ var PI_USAGE_FIELDS = [
1305
1312
  ["output", "outputTokens"],
1306
1313
  ["cacheRead", "cachedInputTokens"],
1307
1314
  ["cacheWrite", "cacheCreationTokens"],
1315
+ ["reasoning", "reasoningTokens"],
1308
1316
  ["totalTokens", "totalTokens"]
1309
1317
  ];
1318
+ var PI_COST_FIELDS = [
1319
+ "input",
1320
+ "output",
1321
+ "cacheRead",
1322
+ "cacheWrite",
1323
+ "total"
1324
+ ];
1310
1325
  function readPiUsage(source) {
1311
1326
  const record = asRecord(source);
1312
1327
  if (!record) {
@@ -1320,17 +1335,46 @@ function readPiUsage(source) {
1320
1335
  summary[ourKey] = value;
1321
1336
  }
1322
1337
  }
1338
+ const piCost = asRecord(usage.cost);
1339
+ if (piCost) {
1340
+ const cost = {};
1341
+ for (const field of PI_COST_FIELDS) {
1342
+ const value = toFiniteCost(piCost[field]);
1343
+ if (value !== void 0) {
1344
+ cost[field] = value;
1345
+ }
1346
+ }
1347
+ if (Object.keys(cost).length > 0) {
1348
+ summary.cost = cost;
1349
+ }
1350
+ }
1323
1351
  return summary;
1324
1352
  }
1325
1353
  function extractGenAiUsageSummary(...sources) {
1326
1354
  const summary = {};
1355
+ const cost = {};
1327
1356
  for (const source of sources) {
1328
1357
  const single = readPiUsage(source);
1329
- for (const field of Object.keys(single)) {
1358
+ for (const field of [
1359
+ "inputTokens",
1360
+ "outputTokens",
1361
+ "cachedInputTokens",
1362
+ "cacheCreationTokens",
1363
+ "reasoningTokens",
1364
+ "totalTokens"
1365
+ ]) {
1330
1366
  const value = single[field];
1331
1367
  if (value === void 0) continue;
1332
1368
  summary[field] = (summary[field] ?? 0) + value;
1333
1369
  }
1370
+ for (const field of PI_COST_FIELDS) {
1371
+ const value = single.cost?.[field];
1372
+ if (value === void 0) continue;
1373
+ cost[field] = addCost(cost[field], value);
1374
+ }
1375
+ }
1376
+ if (Object.keys(cost).length > 0) {
1377
+ summary.cost = cost;
1334
1378
  }
1335
1379
  return summary;
1336
1380
  }
@@ -1340,7 +1384,9 @@ function extractGenAiUsageAttributes(...sources) {
1340
1384
  outputTokens,
1341
1385
  cachedInputTokens,
1342
1386
  cacheCreationTokens,
1343
- totalTokens
1387
+ reasoningTokens,
1388
+ totalTokens,
1389
+ cost
1344
1390
  } = extractGenAiUsageSummary(...sources);
1345
1391
  const semanticInputTokens = sumTokenCounts(
1346
1392
  inputTokens,
@@ -1353,7 +1399,13 @@ function extractGenAiUsageAttributes(...sources) {
1353
1399
  ...outputTokens !== void 0 ? { "gen_ai.usage.output_tokens": outputTokens } : {},
1354
1400
  ...semanticTotalTokens !== void 0 ? { "gen_ai.usage.total_tokens": semanticTotalTokens } : {},
1355
1401
  ...cachedInputTokens !== void 0 ? { "gen_ai.usage.input_tokens.cached": cachedInputTokens } : {},
1356
- ...cacheCreationTokens !== void 0 ? { "gen_ai.usage.input_tokens.cache_write": cacheCreationTokens } : {}
1402
+ ...cacheCreationTokens !== void 0 ? { "gen_ai.usage.input_tokens.cache_write": cacheCreationTokens } : {},
1403
+ ...reasoningTokens !== void 0 ? { "app.ai.reasoning_tokens": reasoningTokens } : {},
1404
+ ...cost?.input !== void 0 ? { "app.ai.cost.input_usd": cost.input } : {},
1405
+ ...cost?.output !== void 0 ? { "app.ai.cost.output_usd": cost.output } : {},
1406
+ ...cost?.cacheRead !== void 0 ? { "app.ai.cost.cache_read_usd": cost.cacheRead } : {},
1407
+ ...cost?.cacheWrite !== void 0 ? { "app.ai.cost.cache_write_usd": cost.cacheWrite } : {},
1408
+ ...cost?.total !== void 0 ? { "app.ai.cost.total_usd": cost.total } : {}
1357
1409
  };
1358
1410
  }
1359
1411
 
@@ -1,10 +1,8 @@
1
1
  import {
2
2
  CooperativeTurnYieldError,
3
3
  TurnInputCommitLostError,
4
- addAgentTurnUsage,
5
4
  canReusePendingAuthLink,
6
5
  getInterruptionMarker,
7
- hasAgentTurnUsage,
8
6
  isTurnInputCommitLostError,
9
7
  loadTurnSessionRecord,
10
8
  mergeArtifactsState,
@@ -12,7 +10,7 @@ import {
12
10
  persistRunningSessionRecord,
13
11
  persistTimeoutSessionRecord,
14
12
  persistYieldSessionRecord
15
- } from "./chunk-KDPCGVIT.js";
13
+ } from "./chunk-UKHVMPX5.js";
16
14
  import {
17
15
  buildNonInteractiveShellScript,
18
16
  createSandboxInstance,
@@ -22,24 +20,26 @@ import {
22
20
  isSnapshotMissingError,
23
21
  resolveRuntimeDependencySnapshot,
24
22
  runNonInteractiveCommand
25
- } from "./chunk-WCMQJE4F.js";
23
+ } from "./chunk-BYZWPRJA.js";
26
24
  import {
27
25
  privateTraceResultAttributes
28
26
  } from "./chunk-CM5EZD5F.js";
29
27
  import {
30
28
  renderAdvisorRequest
31
- } from "./chunk-N4RNJ32C.js";
29
+ } from "./chunk-WM6KHPBQ.js";
32
30
  import {
31
+ addAgentTurnUsage,
33
32
  commitMessages,
33
+ hasAgentTurnUsage,
34
34
  loadConnectedMcpProviders,
35
35
  loadProjection,
36
36
  recordAuthorizationRequested,
37
37
  recordMcpProviderConnected,
38
38
  recordToolExecutionStarted
39
- } from "./chunk-WAGQ377B.js";
39
+ } from "./chunk-MNTINMWR.js";
40
40
  import {
41
41
  JUNIOR_THREAD_STATE_TTL_MS
42
- } from "./chunk-CRRBJ3JP.js";
42
+ } from "./chunk-5C6XTTFI.js";
43
43
  import {
44
44
  SlackActionError,
45
45
  createPluginHookRunner,
@@ -56,10 +56,10 @@ import {
56
56
  normalizeSlackConversationId,
57
57
  resolveChannelCapabilities,
58
58
  withSlackRetries
59
- } from "./chunk-NSCHU54X.js";
59
+ } from "./chunk-S5KZ5LPG.js";
60
60
  import {
61
61
  createPluginLogger
62
- } from "./chunk-E3E2XNCN.js";
62
+ } from "./chunk-2NAZZPPS.js";
63
63
  import {
64
64
  SANDBOX_DATA_ROOT,
65
65
  SANDBOX_SKILLS_ROOT,
@@ -74,7 +74,7 @@ import {
74
74
  getDb,
75
75
  instructionActors,
76
76
  instructionProvenanceFor
77
- } from "./chunk-6ONME5IG.js";
77
+ } from "./chunk-RITD7E5L.js";
78
78
  import {
79
79
  GEN_AI_PROVIDER_NAME,
80
80
  GEN_AI_SERVER_ADDRESS,
@@ -102,7 +102,7 @@ import {
102
102
  renderCurrentInstruction,
103
103
  resolveGatewayModel,
104
104
  stripRuntimeTurnContext
105
- } from "./chunk-GUE7HTNR.js";
105
+ } from "./chunk-YDVEH3SB.js";
106
106
  import {
107
107
  parseSlackThreadId,
108
108
  resolveConversationPrivacy,
@@ -123,14 +123,14 @@ import {
123
123
  findSkillByName,
124
124
  loadSkillsByName,
125
125
  parseSkillInvocation
126
- } from "./chunk-HDTO3A74.js";
126
+ } from "./chunk-PMNN6ST4.js";
127
127
  import {
128
128
  CredentialUnavailableError,
129
129
  credentialContextSchema,
130
130
  pluginCatalogRuntime,
131
131
  resolveAuthTokenPlaceholder,
132
132
  resolvePluginCommandEnv
133
- } from "./chunk-GVOUCI2O.js";
133
+ } from "./chunk-L7CDEIVJ.js";
134
134
  import {
135
135
  createActor,
136
136
  extractGenAiUsageAttributes,
@@ -149,14 +149,14 @@ import {
149
149
  setTags,
150
150
  summarizeMessageText,
151
151
  withSpan
152
- } from "./chunk-WPOJ443W.js";
152
+ } from "./chunk-I35CTGPO.js";
153
153
  import {
154
154
  isRecord
155
155
  } from "./chunk-OB42YVAE.js";
156
156
  import {
157
157
  startInactiveSpan,
158
158
  withActiveSpan
159
- } from "./chunk-3DA7X2U3.js";
159
+ } from "./chunk-6GWA276C.js";
160
160
  import {
161
161
  listReferenceFiles,
162
162
  soulPathCandidates,
@@ -2062,7 +2062,6 @@ var EXECUTION_CONTRACT_RULES = [
2062
2062
  var CONVERSATION_RULES = [
2063
2063
  "- In thread follow-ups, answer from prior thread context; do not repeat resolved clarifying questions.",
2064
2064
  "- Preserve attribution roles from thread context: the actor is the person asking now, which may differ from the original reporter or subject.",
2065
- "- Treat event notifications as subscribed conversation updates, not user-authored commands. Use their subscription intent to decide whether to reply, inspect, suggest, or stay brief.",
2066
2065
  "- Runtime owns continuation and authorization notices; on resumed turns, answer with the final requested content only."
2067
2066
  ];
2068
2067
  var SLACK_ACTION_RULES = [
@@ -14879,7 +14878,8 @@ function createResumeState(args) {
14879
14878
  return {
14880
14879
  outcome: {
14881
14880
  status: "suspended",
14882
- resumeVersion: sessionRecord.version
14881
+ resumeVersion: sessionRecord.version,
14882
+ ...usage ? { usage } : {}
14883
14883
  }
14884
14884
  };
14885
14885
  }
@@ -14903,7 +14903,8 @@ function createResumeState(args) {
14903
14903
  return {
14904
14904
  outcome: {
14905
14905
  status: "suspended",
14906
- resumeVersion: sessionRecord.version
14906
+ resumeVersion: sessionRecord.version,
14907
+ ...usage ? { usage } : {}
14907
14908
  }
14908
14909
  };
14909
14910
  }
@@ -14926,7 +14927,8 @@ function createResumeState(args) {
14926
14927
  return {
14927
14928
  outcome: {
14928
14929
  status: "awaiting_auth",
14929
- providerDisplayName: error.providerDisplayName
14930
+ providerDisplayName: error.providerDisplayName,
14931
+ ...usage ? { usage } : {}
14930
14932
  }
14931
14933
  };
14932
14934
  }
@@ -3,7 +3,7 @@ import {
3
3
  logWarn,
4
4
  parseActorUserId,
5
5
  setSpanAttributes
6
- } from "./chunk-WPOJ443W.js";
6
+ } from "./chunk-I35CTGPO.js";
7
7
  import {
8
8
  discoverInstalledPluginPackageContent,
9
9
  normalizePluginPackageNames,
@@ -1313,7 +1313,10 @@ function buildOAuthTokenRequest(input) {
1313
1313
  function parseOAuthTokenResponse(data, requestedScope, options) {
1314
1314
  const response = requireTokenResponseObject(data);
1315
1315
  const accessToken = requireNonEmptyTokenField(response, "access_token");
1316
- const refreshToken = requireNonEmptyTokenField(response, "refresh_token");
1316
+ const resolvedRefreshToken = response.refresh_token === void 0 ? options?.refreshToken : requireNonEmptyTokenField(response, "refresh_token");
1317
+ if (!resolvedRefreshToken) {
1318
+ throw new Error("OAuth token response missing refresh_token");
1319
+ }
1317
1320
  const expiresIn = response.expires_in;
1318
1321
  const refreshTokenExpiresIn = response.refresh_token_expires_in;
1319
1322
  const responseScope = response.scope;
@@ -1333,7 +1336,11 @@ function parseOAuthTokenResponse(data, requestedScope, options) {
1333
1336
  } else {
1334
1337
  scope = normalizeOAuthScope(requestedScope);
1335
1338
  }
1336
- const result = { accessToken, refreshToken, ...scope ? { scope } : {} };
1339
+ const result = {
1340
+ accessToken,
1341
+ refreshToken: resolvedRefreshToken,
1342
+ ...scope ? { scope } : {}
1343
+ };
1337
1344
  if (expiresIn !== void 0) {
1338
1345
  if (typeof expiresIn !== "number" || !Number.isFinite(expiresIn) || expiresIn <= 0) {
1339
1346
  throw new Error("OAuth token response returned invalid expires_in");
@@ -1409,7 +1416,8 @@ async function refreshAccessToken(refreshToken, oauth, requestedScope) {
1409
1416
  }
1410
1417
  const data = await response.json();
1411
1418
  return parseOAuthTokenResponse(data, requestedScope, {
1412
- treatEmptyScopeAsUnreported: oauth.treatEmptyScopeAsUnreported
1419
+ treatEmptyScopeAsUnreported: oauth.treatEmptyScopeAsUnreported,
1420
+ refreshToken
1413
1421
  });
1414
1422
  }
1415
1423
  function getLeaseExpiry(expiresAt) {
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  ensureLegacyConversationImport
3
- } from "./chunk-CRRBJ3JP.js";
3
+ } from "./chunk-5C6XTTFI.js";
4
4
  import {
5
5
  contextProvenance,
6
6
  getAgentStepStore,
7
7
  getConversationStore,
8
8
  instructionActors,
9
9
  instructionProvenanceFor
10
- } from "./chunk-6ONME5IG.js";
10
+ } from "./chunk-RITD7E5L.js";
11
11
  import {
12
12
  getStateAdapter
13
- } from "./chunk-GUE7HTNR.js";
13
+ } from "./chunk-YDVEH3SB.js";
14
14
  import {
15
15
  toStoredSlackActor
16
- } from "./chunk-WPOJ443W.js";
16
+ } from "./chunk-I35CTGPO.js";
17
17
 
18
18
  // src/chat/conversations/projection.ts
19
19
  import { isDeepStrictEqual } from "util";
@@ -271,6 +271,112 @@ async function recordToolExecutionStarted(args) {
271
271
  ]);
272
272
  }
273
273
 
274
+ // src/chat/usage.ts
275
+ import { z } from "zod";
276
+ var agentTurnCostSchema = z.object({
277
+ input: z.number().finite().nonnegative().optional(),
278
+ output: z.number().finite().nonnegative().optional(),
279
+ cacheRead: z.number().finite().nonnegative().optional(),
280
+ cacheWrite: z.number().finite().nonnegative().optional(),
281
+ total: z.number().finite().nonnegative().optional()
282
+ }).strict();
283
+ var agentTurnUsageSchema = z.object({
284
+ inputTokens: z.number().int().nonnegative().optional(),
285
+ outputTokens: z.number().int().nonnegative().optional(),
286
+ cachedInputTokens: z.number().int().nonnegative().optional(),
287
+ cacheCreationTokens: z.number().int().nonnegative().optional(),
288
+ reasoningTokens: z.number().int().nonnegative().optional(),
289
+ totalTokens: z.number().int().nonnegative().optional(),
290
+ cost: agentTurnCostSchema.optional()
291
+ }).strict();
292
+ var COMPONENT_USAGE_FIELDS = [
293
+ "inputTokens",
294
+ "outputTokens",
295
+ "cachedInputTokens",
296
+ "cacheCreationTokens"
297
+ ];
298
+ var COST_COMPONENT_FIELDS = [
299
+ "input",
300
+ "output",
301
+ "cacheRead",
302
+ "cacheWrite"
303
+ ];
304
+ function hasAgentTurnUsage(usage) {
305
+ return Boolean(
306
+ usage && (Object.entries(usage).some(
307
+ ([field, value]) => field !== "cost" && typeof value === "number" && Number.isFinite(value)
308
+ ) || Object.values(usage.cost ?? {}).some(
309
+ (value) => typeof value === "number" && Number.isFinite(value)
310
+ ))
311
+ );
312
+ }
313
+ function getFiniteCount(value) {
314
+ return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : void 0;
315
+ }
316
+ function getFiniteCost(value) {
317
+ return typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : void 0;
318
+ }
319
+ function addCost(left, right) {
320
+ return Math.round(((left ?? 0) + right) * 1e12) / 1e12;
321
+ }
322
+ function getComponentTotal(usage) {
323
+ let total;
324
+ for (const field of COMPONENT_USAGE_FIELDS) {
325
+ const value = getFiniteCount(usage[field]);
326
+ if (value === void 0) continue;
327
+ total = (total ?? 0) + value;
328
+ }
329
+ return total;
330
+ }
331
+ function addAgentTurnUsage(...usages) {
332
+ const components = {};
333
+ let componentTotal;
334
+ let totalOnlyTokens;
335
+ let reasoningTokens;
336
+ const cost = {};
337
+ for (const usage of usages) {
338
+ if (!usage) continue;
339
+ const reasoning = getFiniteCount(usage.reasoningTokens);
340
+ if (reasoning !== void 0) {
341
+ reasoningTokens = (reasoningTokens ?? 0) + reasoning;
342
+ }
343
+ if (usage.cost) {
344
+ for (const field of [...COST_COMPONENT_FIELDS, "total"]) {
345
+ const value = getFiniteCost(usage.cost[field]);
346
+ if (value === void 0) continue;
347
+ cost[field] = addCost(cost[field], value);
348
+ }
349
+ }
350
+ const usageComponentTotal = getComponentTotal(usage);
351
+ if (usageComponentTotal !== void 0) {
352
+ componentTotal = (componentTotal ?? 0) + usageComponentTotal;
353
+ for (const field of COMPONENT_USAGE_FIELDS) {
354
+ const value = getFiniteCount(usage[field]);
355
+ if (value === void 0) continue;
356
+ components[field] = (components[field] ?? 0) + value;
357
+ }
358
+ continue;
359
+ }
360
+ const totalTokens = getFiniteCount(usage.totalTokens);
361
+ if (totalTokens !== void 0) {
362
+ totalOnlyTokens = (totalOnlyTokens ?? 0) + totalTokens;
363
+ }
364
+ }
365
+ if (totalOnlyTokens !== void 0) {
366
+ return {
367
+ totalTokens: totalOnlyTokens + (componentTotal ?? 0),
368
+ ...reasoningTokens !== void 0 ? { reasoningTokens } : {},
369
+ ...Object.keys(cost).length > 0 ? { cost } : {}
370
+ };
371
+ }
372
+ const result = {
373
+ ...components,
374
+ ...reasoningTokens !== void 0 ? { reasoningTokens } : {},
375
+ ...Object.keys(cost).length > 0 ? { cost } : {}
376
+ };
377
+ return hasAgentTurnUsage(result) ? result : void 0;
378
+ }
379
+
274
380
  // src/chat/state/turn-session.ts
275
381
  import { THREAD_STATE_TTL_MS } from "chat";
276
382
  import {
@@ -278,64 +384,58 @@ import {
278
384
  destinationSchema,
279
385
  sourceSchema
280
386
  } from "@sentry/junior-plugin-api";
281
- import { z } from "zod";
387
+ import { z as z2 } from "zod";
282
388
  var AGENT_TURN_SESSION_PREFIX = "junior:agent_turn_session";
283
389
  var AGENT_TURN_SESSION_INDEX_KEY = `${AGENT_TURN_SESSION_PREFIX}:index`;
284
390
  var AGENT_TURN_SESSION_INDEX_MAX_LENGTH = 5e3;
391
+ var AGENT_TURN_SESSION_INDEX_READ_CONCURRENCY = 25;
285
392
  var AGENT_TURN_SESSION_TTL_MS = THREAD_STATE_TTL_MS;
286
- var agentTurnSessionStatusSchema = z.enum([
393
+ var agentTurnSessionStatusSchema = z2.enum([
287
394
  "running",
288
395
  "awaiting_resume",
289
396
  "completed",
290
397
  "failed",
291
398
  "abandoned"
292
399
  ]);
293
- var agentTurnSurfaceSchema = z.enum([
400
+ var agentTurnSurfaceSchema = z2.enum([
294
401
  "slack",
295
402
  "api",
296
403
  "scheduler",
297
404
  "internal"
298
405
  ]);
299
- var agentTurnResumeReasonSchema = z.enum([
406
+ var agentTurnResumeReasonSchema = z2.enum([
300
407
  "timeout",
301
408
  "auth",
302
409
  "yield"
303
410
  ]);
304
- var nonNegativeNumberSchema = z.number().finite().nonnegative();
305
- var seqCursorSchema = z.number().int().min(-1);
306
- var agentTurnUsageSchema = z.object({
307
- inputTokens: nonNegativeNumberSchema.optional(),
308
- outputTokens: nonNegativeNumberSchema.optional(),
309
- cachedInputTokens: nonNegativeNumberSchema.optional(),
310
- cacheCreationTokens: nonNegativeNumberSchema.optional(),
311
- totalTokens: nonNegativeNumberSchema.optional()
312
- }).strict();
313
- var agentTurnSessionSummarySchema = z.object({
314
- channelName: z.string().min(1).optional(),
315
- version: z.number().int().nonnegative(),
316
- conversationId: z.string().min(1),
411
+ var nonNegativeNumberSchema = z2.number().finite().nonnegative();
412
+ var seqCursorSchema = z2.number().int().min(-1);
413
+ var agentTurnSessionSummarySchema = z2.object({
414
+ channelName: z2.string().min(1).optional(),
415
+ version: z2.number().int().nonnegative(),
416
+ conversationId: z2.string().min(1),
317
417
  cumulativeDurationMs: nonNegativeNumberSchema,
318
418
  cumulativeUsage: agentTurnUsageSchema.optional(),
319
419
  destination: destinationSchema.optional(),
320
420
  source: sourceSchema.optional(),
321
421
  lastProgressAtMs: nonNegativeNumberSchema,
322
- loadedSkillNames: z.array(z.string()).optional(),
323
- modelId: z.string().min(1).optional(),
324
- reasoningLevel: z.string().min(1).optional(),
422
+ loadedSkillNames: z2.array(z2.string()).optional(),
423
+ modelId: z2.string().min(1).optional(),
424
+ reasoningLevel: z2.string().min(1).optional(),
325
425
  actor: actorSchema.optional(),
326
426
  resumeReason: agentTurnResumeReasonSchema.optional(),
327
- resumedFromSliceId: z.number().int().nonnegative().optional(),
328
- sessionId: z.string().min(1),
329
- sliceId: z.number().int().nonnegative(),
427
+ resumedFromSliceId: z2.number().int().nonnegative().optional(),
428
+ sessionId: z2.string().min(1),
429
+ sliceId: z2.number().int().nonnegative(),
330
430
  startedAtMs: nonNegativeNumberSchema,
331
431
  state: agentTurnSessionStatusSchema,
332
432
  surface: agentTurnSurfaceSchema.optional(),
333
- traceId: z.string().optional(),
433
+ traceId: z2.string().optional(),
334
434
  updatedAtMs: nonNegativeNumberSchema
335
435
  }).strict();
336
436
  var storedAgentTurnSessionRecordSchema = agentTurnSessionSummarySchema.extend({
337
437
  committedSeq: seqCursorSchema,
338
- errorMessage: z.string().optional(),
438
+ errorMessage: z2.string().optional(),
339
439
  turnStartSeq: seqCursorSchema.optional()
340
440
  }).strict();
341
441
  function agentTurnSessionKey(conversationId, sessionId) {
@@ -676,6 +776,44 @@ async function listAgentTurnSessionSummariesForConversation(conversationId) {
676
776
  }
677
777
  return (await readAgentTurnSessionSummariesFromIndex(AGENT_TURN_SESSION_INDEX_KEY)).filter((summary) => summary.conversationId === conversationId);
678
778
  }
779
+ async function listAgentTurnSessionSummariesForConversations(conversationIds) {
780
+ const ids = [...new Set(conversationIds)];
781
+ const globalSummaries = await readAgentTurnSessionSummariesFromIndex(
782
+ AGENT_TURN_SESSION_INDEX_KEY
783
+ );
784
+ const globalByConversation = /* @__PURE__ */ new Map();
785
+ for (const summary of globalSummaries) {
786
+ globalByConversation.set(summary.conversationId, [
787
+ ...globalByConversation.get(summary.conversationId) ?? [],
788
+ summary
789
+ ]);
790
+ }
791
+ const summariesByConversation = /* @__PURE__ */ new Map();
792
+ let nextIndex = 0;
793
+ const readNext = async () => {
794
+ while (nextIndex < ids.length) {
795
+ const conversationId = ids[nextIndex];
796
+ nextIndex += 1;
797
+ if (!conversationId) continue;
798
+ const summaries = await readAgentTurnSessionSummariesFromIndex(
799
+ agentTurnSessionConversationIndexKey(conversationId)
800
+ );
801
+ summariesByConversation.set(
802
+ conversationId,
803
+ summaries.length > 0 ? summaries : globalByConversation.get(conversationId) ?? []
804
+ );
805
+ }
806
+ };
807
+ await Promise.all(
808
+ Array.from(
809
+ {
810
+ length: Math.min(AGENT_TURN_SESSION_INDEX_READ_CONCURRENCY, ids.length)
811
+ },
812
+ readNext
813
+ )
814
+ );
815
+ return summariesByConversation;
816
+ }
679
817
  async function abandonAgentTurnSessionRecord(args) {
680
818
  const existing = await getAgentTurnSessionRecord(
681
819
  args.conversationId,
@@ -715,10 +853,13 @@ export {
715
853
  recordAuthorizationRequested,
716
854
  recordAuthorizationCompleted,
717
855
  recordToolExecutionStarted,
856
+ hasAgentTurnUsage,
857
+ addAgentTurnUsage,
718
858
  getAgentTurnSessionRecord,
719
859
  upsertAgentTurnSessionRecord,
720
860
  recordAgentTurnSessionSummary,
721
861
  listAgentTurnSessionSummariesForConversation,
862
+ listAgentTurnSessionSummariesForConversations,
722
863
  abandonAgentTurnSessionRecord,
723
864
  failAgentTurnSessionRecord
724
865
  };
@@ -9,13 +9,13 @@ import {
9
9
  getPersistedThreadState,
10
10
  markTurnCompleted,
11
11
  mergeArtifactsState
12
- } from "./chunk-KDPCGVIT.js";
12
+ } from "./chunk-UKHVMPX5.js";
13
13
  import {
14
14
  coerceThreadConversationState
15
15
  } from "./chunk-RAIB6WSG.js";
16
16
  import {
17
17
  getAgentTurnSessionRecord
18
- } from "./chunk-WAGQ377B.js";
18
+ } from "./chunk-MNTINMWR.js";
19
19
  import {
20
20
  generateConversationId,
21
21
  hydrateConversationMessages,
@@ -23,19 +23,19 @@ import {
23
23
  normalizeConversationText,
24
24
  updateConversationStats,
25
25
  upsertConversationMessage
26
- } from "./chunk-CRRBJ3JP.js";
26
+ } from "./chunk-5C6XTTFI.js";
27
27
  import {
28
28
  createPluginEmbedder,
29
29
  createPluginModel,
30
30
  getPlugins
31
- } from "./chunk-NSCHU54X.js";
31
+ } from "./chunk-S5KZ5LPG.js";
32
32
  import {
33
33
  createPluginLogger,
34
34
  createPluginState
35
- } from "./chunk-E3E2XNCN.js";
35
+ } from "./chunk-2NAZZPPS.js";
36
36
  import {
37
37
  getDb
38
- } from "./chunk-6ONME5IG.js";
38
+ } from "./chunk-RITD7E5L.js";
39
39
  import {
40
40
  GEN_AI_PROVIDER_NAME,
41
41
  botConfig,
@@ -46,10 +46,10 @@ import {
46
46
  isToolResultMessage,
47
47
  normalizeToolNameFromResult,
48
48
  stripRuntimeTurnContext
49
- } from "./chunk-GUE7HTNR.js";
49
+ } from "./chunk-YDVEH3SB.js";
50
50
  import {
51
51
  buildTurnFailureResponse
52
- } from "./chunk-WPOJ443W.js";
52
+ } from "./chunk-I35CTGPO.js";
53
53
  import {
54
54
  parseSlackMessageTs
55
55
  } from "./chunk-7FBGKXPE.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-GVOUCI2O.js";
3
+ } from "./chunk-L7CDEIVJ.js";
4
4
  import {
5
5
  logWarn
6
- } from "./chunk-WPOJ443W.js";
6
+ } from "./chunk-I35CTGPO.js";
7
7
  import {
8
8
  skillRoots
9
9
  } from "./chunk-6APU57E6.js";
@@ -2,7 +2,7 @@ import {
2
2
  getChatConfig,
3
3
  getConnectedStateContext,
4
4
  getStateAdapter
5
- } from "./chunk-GUE7HTNR.js";
5
+ } from "./chunk-YDVEH3SB.js";
6
6
  import {
7
7
  parseDestination,
8
8
  sameDestination
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  normalizeIdentityEmail,
12
12
  storedSlackActorSchema
13
- } from "./chunk-WPOJ443W.js";
13
+ } from "./chunk-I35CTGPO.js";
14
14
 
15
15
  // src/chat/conversations/sql/store.ts
16
16
  import { randomUUID as randomUUID2 } from "crypto";