@sentry/junior 0.96.0 → 0.97.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 (135) hide show
  1. package/dist/{agent-hooks-5URSMY3O.js → agent-hooks-XSUIVRQS.js} +8 -6
  2. package/dist/{reporting → api}/conversations/activity.d.ts +1 -1
  3. package/dist/api/conversations/detail-projection.d.ts +10 -0
  4. package/dist/api/conversations/detail.d.ts +3 -0
  5. package/dist/api/conversations/detail.query.d.ts +3 -0
  6. package/dist/api/conversations/list.d.ts +3 -0
  7. package/dist/api/conversations/list.query.d.ts +94 -0
  8. package/dist/api/conversations/projection.d.ts +14 -0
  9. package/dist/api/conversations/schema.d.ts +683 -0
  10. package/dist/{reporting → api}/conversations/shared.d.ts +1 -5
  11. package/dist/api/conversations/stats.d.ts +3 -0
  12. package/dist/api/conversations/stats.query.d.ts +3 -0
  13. package/dist/api/conversations/subagent.d.ts +3 -0
  14. package/dist/{reporting → api}/conversations/transcript.d.ts +4 -4
  15. package/dist/api/people/list.d.ts +1 -2
  16. package/dist/api/people/list.query.d.ts +3 -4
  17. package/dist/api/people/profile.d.ts +1 -2
  18. package/dist/api/people/profile.query.d.ts +3 -4
  19. package/dist/api/people/schema.d.ts +193 -0
  20. package/dist/api/people/shared.d.ts +31 -9
  21. package/dist/api/schema.d.ts +20 -0
  22. package/dist/api/schema.js +50 -0
  23. package/dist/api-reference.d.ts +4 -3
  24. package/dist/api.d.ts +3 -0
  25. package/dist/api.js +156 -0
  26. package/dist/app.d.ts +1 -4
  27. package/dist/app.js +100 -366
  28. package/dist/build/virtual-config.d.ts +2 -2
  29. package/dist/{catalog-runtime-MSMAYYIK.js → catalog-runtime-PFHVMHDR.js} +3 -2
  30. package/dist/chat/agent/resume.d.ts +3 -1
  31. package/dist/chat/agent/tools.d.ts +2 -1
  32. package/dist/chat/config.d.ts +1 -8
  33. package/dist/chat/conversations/history.d.ts +241 -27
  34. package/dist/chat/conversations/legacy-advisor-session.d.ts +7 -0
  35. package/dist/chat/conversations/legacy-import.d.ts +2 -2
  36. package/dist/chat/conversations/projection.d.ts +19 -3
  37. package/dist/chat/conversations/sql/legacy-history-import.d.ts +1 -1
  38. package/dist/chat/conversations/sql/store.d.ts +15 -9
  39. package/dist/chat/conversations/store.d.ts +9 -4
  40. package/dist/chat/model-profile.d.ts +14 -0
  41. package/dist/chat/pi/transcript.d.ts +5 -3
  42. package/dist/chat/resource-events/store.d.ts +2 -2
  43. package/dist/chat/services/context-compaction.d.ts +15 -0
  44. package/dist/chat/services/turn-result.d.ts +1 -0
  45. package/dist/chat/services/turn-session-record.d.ts +6 -6
  46. package/dist/chat/state/turn-session.d.ts +16 -5
  47. package/dist/chat/task-execution/store.d.ts +2 -2
  48. package/dist/chat/tools/handoff/tool.d.ts +45 -0
  49. package/dist/chat/tools/types.d.ts +7 -2
  50. package/dist/chat/usage.d.ts +25 -25
  51. package/dist/{chunk-RITD7E5L.js → chunk-35BNLDOJ.js} +338 -577
  52. package/dist/{chunk-PMNN6ST4.js → chunk-3ECW2K2O.js} +7 -2
  53. package/dist/{chunk-5C6XTTFI.js → chunk-3F4OPKGF.js} +89 -55
  54. package/dist/chunk-3V7OFJZC.js +264 -0
  55. package/dist/chunk-4ZNGQH7C.js +25 -0
  56. package/dist/{chunk-S5KZ5LPG.js → chunk-5HLDPVYS.js} +14 -447
  57. package/dist/{chunk-DZENG5ML.js → chunk-6U26PYI5.js} +24 -14
  58. package/dist/chunk-AUUCAFDE.js +546 -0
  59. package/dist/{chunk-6APU57E6.js → chunk-B3IT5END.js} +41 -260
  60. package/dist/chunk-CEA3A3UA.js +86 -0
  61. package/dist/{chunk-YDT7SNCN.js → chunk-D5KZYS4T.js} +1 -1
  62. package/dist/{chunk-YDVEH3SB.js → chunk-EEZCY5WX.js} +78 -28
  63. package/dist/{chunk-2NAZZPPS.js → chunk-EOWXRY5E.js} +1 -1
  64. package/dist/{chunk-GQ3GK22G.js → chunk-FBHZJFHI.js} +2 -2
  65. package/dist/{chunk-CZEX6KIQ.js → chunk-G3E7SCME.js} +0 -23
  66. package/dist/chunk-GUAP3H7O.js +319 -0
  67. package/dist/{chunk-BYZWPRJA.js → chunk-H66UCBPW.js} +6 -4
  68. package/dist/{chunk-L7CDEIVJ.js → chunk-LMJPRYHP.js} +4 -2
  69. package/dist/chunk-LUAE4MGW.js +199 -0
  70. package/dist/{chunk-GY34VGP5.js → chunk-LVA4I4H7.js} +3 -1
  71. package/dist/chunk-LVUKF5CE.js +63 -0
  72. package/dist/{chunk-AAZXTVJT.js → chunk-NG2AV7IB.js} +2 -72
  73. package/dist/chunk-ON6YKIQ7.js +260 -0
  74. package/dist/chunk-PDO5BLNM.js +22 -0
  75. package/dist/chunk-QNVHH5PU.js +20 -0
  76. package/dist/{chunk-P3YFQLEN.js → chunk-T533JLM3.js} +8 -10
  77. package/dist/chunk-UAMKJPDF.js +11 -0
  78. package/dist/chunk-VFH4ZKZT.js +66 -0
  79. package/dist/{chunk-UKHVMPX5.js → chunk-WGXMTFNU.js} +15 -17
  80. package/dist/{chunk-MNTINMWR.js → chunk-WJOSZOON.js} +184 -300
  81. package/dist/chunk-WTYEKPXU.js +451 -0
  82. package/dist/{chunk-IYM2SIVG.js → chunk-XIRPQQVE.js} +605 -363
  83. package/dist/cli/chat.js +24 -21
  84. package/dist/cli/check.js +4 -3
  85. package/dist/cli/init.js +12 -0
  86. package/dist/cli/plugins.js +12 -9
  87. package/dist/cli/snapshot-warmup.js +8 -6
  88. package/dist/cli/upgrade.js +265 -137
  89. package/dist/db/db.d.ts +4 -0
  90. package/dist/db/schema/conversations.d.ts +128 -0
  91. package/dist/db/schema.d.ts +129 -60
  92. package/dist/{db-2D6RMG67.js → db-BWXYIKFQ.js} +3 -3
  93. package/dist/detail-GA6NXWQJ.js +43 -0
  94. package/dist/discovery-RMHYSRL7.js +43 -0
  95. package/dist/handlers/health.d.ts +3 -0
  96. package/dist/instrumentation.js +1 -1
  97. package/dist/{legacy-import-VZ2MEGP7.js → legacy-import-3NQJVGQL.js} +4 -4
  98. package/dist/{api/people/list.js → list-A3WFRIYX.js} +26 -16
  99. package/dist/list-UXJI5Q5X.js +27 -0
  100. package/dist/nitro.d.ts +1 -1
  101. package/dist/nitro.js +2 -1
  102. package/dist/plugin-conversations-DDNGC35A.js +36 -0
  103. package/dist/{api/people/profile.js → profile-4RYDXWTF.js} +33 -18
  104. package/dist/reporting/plugin-conversations.d.ts +3 -0
  105. package/dist/reporting-schema.d.ts +140 -0
  106. package/dist/reporting.d.ts +12 -81
  107. package/dist/{runner-JZBRQP4F.js → runner-JALSYH2P.js} +17 -12
  108. package/dist/skills-MAZXZ2KE.js +26 -0
  109. package/dist/stats-XKXH3PTY.js +217 -0
  110. package/dist/subagent-TZ55XY37.js +48 -0
  111. package/dist/usage-schema.d.ts +25 -0
  112. package/dist/{validation-6XOOQGME.js → validation-FMEAEKCY.js} +4 -3
  113. package/migrations/0000_initial.sql +115 -0
  114. package/migrations/0001_conversation_metrics.sql +4 -0
  115. package/migrations/README.md +12 -30
  116. package/migrations/meta/0000_snapshot.json +1 -33
  117. package/migrations/meta/0001_snapshot.json +972 -0
  118. package/migrations/meta/_journal.json +9 -2
  119. package/package.json +14 -18
  120. package/dist/api/people/types.d.ts +0 -85
  121. package/dist/chat/advisor-request.d.ts +0 -4
  122. package/dist/chat/conversations/sql/migrations.d.ts +0 -22
  123. package/dist/chat/tools/advisor/session-store.d.ts +0 -9
  124. package/dist/chat/tools/advisor/tool.d.ts +0 -72
  125. package/dist/chunk-RAIB6WSG.js +0 -142
  126. package/dist/chunk-WM6KHPBQ.js +0 -48
  127. package/dist/db/schema/migrations.d.ts +0 -58
  128. package/dist/reporting/conversations/context.d.ts +0 -8
  129. package/dist/reporting/conversations/details.d.ts +0 -6
  130. package/dist/reporting/conversations/index.d.ts +0 -4
  131. package/dist/reporting/conversations/statistics.d.ts +0 -4
  132. package/dist/reporting/conversations/summaries.d.ts +0 -20
  133. package/dist/reporting/conversations/types.d.ts +0 -191
  134. package/dist/reporting/conversations.d.ts +0 -1
  135. package/dist/reporting.js +0 -1155
@@ -1,28 +1,29 @@
1
+ import {
2
+ isConversationChannel,
3
+ isConversationScopedChannel,
4
+ isDmChannel,
5
+ normalizeSlackConversationId
6
+ } from "./chunk-WTYEKPXU.js";
1
7
  import {
2
8
  createPluginLogger,
3
9
  createPluginState
4
- } from "./chunk-2NAZZPPS.js";
5
- import {
6
- SANDBOX_WORKSPACE_ROOT,
7
- sleep
8
- } from "./chunk-CZEX6KIQ.js";
10
+ } from "./chunk-EOWXRY5E.js";
9
11
  import {
10
12
  getDb
11
- } from "./chunk-RITD7E5L.js";
13
+ } from "./chunk-35BNLDOJ.js";
14
+ import {
15
+ SANDBOX_WORKSPACE_ROOT
16
+ } from "./chunk-G3E7SCME.js";
12
17
  import {
13
18
  botConfig,
14
19
  completeObject,
15
- embedTexts,
16
- getSlackBotToken
17
- } from "./chunk-YDVEH3SB.js";
20
+ embedTexts
21
+ } from "./chunk-EEZCY5WX.js";
18
22
  import {
19
23
  isActorUserId,
20
24
  logInfo,
21
25
  logWarn,
22
- parseActorUserId,
23
- setSpanAttributes,
24
- setSpanStatus,
25
- withSpan
26
+ parseActorUserId
26
27
  } from "./chunk-I35CTGPO.js";
27
28
  import {
28
29
  parseSlackChannelReferenceId,
@@ -102,428 +103,6 @@ function getSlackToolContext(context) {
102
103
 
103
104
  // src/chat/credentials/subject.ts
104
105
  import { createHmac, timingSafeEqual } from "crypto";
105
-
106
- // src/chat/slack/client.ts
107
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
108
- import { WebClient } from "@slack/web-api";
109
-
110
- // src/chat/slack/workspace-context.ts
111
- import { AsyncLocalStorage } from "async_hooks";
112
- var workspaceTeamIdStorage = new AsyncLocalStorage();
113
- function runWithWorkspaceTeamId(teamId, fn) {
114
- if (!teamId) return fn();
115
- return workspaceTeamIdStorage.run(teamId, fn);
116
- }
117
- function getWorkspaceTeamId() {
118
- return workspaceTeamIdStorage.getStore();
119
- }
120
-
121
- // src/chat/slack/client.ts
122
- var SlackActionError = class extends Error {
123
- code;
124
- apiError;
125
- needed;
126
- provided;
127
- statusCode;
128
- requestId;
129
- errorData;
130
- retryAfterSeconds;
131
- detail;
132
- detailLine;
133
- detailRule;
134
- constructor(message, code, options = {}) {
135
- super(message);
136
- this.name = "SlackActionError";
137
- this.code = code;
138
- this.apiError = options.apiError;
139
- this.needed = options.needed;
140
- this.provided = options.provided;
141
- this.statusCode = options.statusCode;
142
- this.requestId = options.requestId;
143
- this.errorData = options.errorData;
144
- this.retryAfterSeconds = options.retryAfterSeconds;
145
- this.detail = options.detail;
146
- this.detailLine = options.detailLine;
147
- this.detailRule = options.detailRule;
148
- }
149
- };
150
- function serializeSlackErrorData(data) {
151
- if (!data || typeof data !== "object") {
152
- return void 0;
153
- }
154
- const filtered = Object.fromEntries(
155
- Object.entries(data).filter(
156
- ([key]) => key !== "error"
157
- )
158
- );
159
- if (Object.keys(filtered).length === 0) {
160
- return void 0;
161
- }
162
- try {
163
- const serialized = JSON.stringify(filtered);
164
- return serialized.length <= 600 ? serialized : `${serialized.slice(0, 597)}...`;
165
- } catch {
166
- return void 0;
167
- }
168
- }
169
- function getHeaderString(headers, name) {
170
- if (!headers || typeof headers !== "object") {
171
- return void 0;
172
- }
173
- const key = name.toLowerCase();
174
- const entries = headers;
175
- for (const [entryKey, value] of Object.entries(entries)) {
176
- if (entryKey.toLowerCase() !== key) continue;
177
- if (typeof value === "string") return value;
178
- if (Array.isArray(value)) {
179
- const first = value.find((entry) => typeof entry === "string");
180
- return typeof first === "string" ? first : void 0;
181
- }
182
- }
183
- return void 0;
184
- }
185
- function parseSlackCanvasDetail(detail) {
186
- if (typeof detail !== "string") {
187
- return {};
188
- }
189
- const trimmed = detail.trim();
190
- if (!trimmed) {
191
- return {};
192
- }
193
- const parsed = {
194
- detail: trimmed
195
- };
196
- const lineMatch = trimmed.match(/line\s+(\d+):/i);
197
- if (lineMatch) {
198
- const line = Number.parseInt(lineMatch[1] ?? "", 10);
199
- if (Number.isFinite(line)) {
200
- parsed.detailLine = line;
201
- }
202
- }
203
- if (/unsupported heading depth/i.test(trimmed)) {
204
- parsed.detailRule = "unsupported_heading_depth";
205
- }
206
- return parsed;
207
- }
208
- var installationTokenStorage = new AsyncLocalStorage2();
209
- var clientsByToken = /* @__PURE__ */ new Map();
210
- function runWithSlackInstallationToken(token, fn) {
211
- const trimmed = token.trim();
212
- if (!trimmed) {
213
- throw new SlackActionError(
214
- "Slack installation token binding requires a non-empty token",
215
- "missing_token"
216
- );
217
- }
218
- return installationTokenStorage.run({ token: trimmed }, fn);
219
- }
220
- function resolveSlackToken() {
221
- const ambientToken = installationTokenStorage.getStore()?.token;
222
- if (ambientToken) {
223
- return ambientToken;
224
- }
225
- const envToken = getSlackBotToken();
226
- if (envToken) {
227
- return envToken;
228
- }
229
- const teamId = getWorkspaceTeamId();
230
- if (teamId) {
231
- throw new SlackActionError(
232
- `Slack call is scoped to workspace ${teamId} but no installation token is bound and no default bot token is configured`,
233
- "missing_token"
234
- );
235
- }
236
- throw new SlackActionError(
237
- "SLACK_BOT_TOKEN (or SLACK_BOT_USER_TOKEN) is required for Slack Web API actions in this service",
238
- "missing_token"
239
- );
240
- }
241
- function normalizeSlackConversationId(channelId) {
242
- return parseSlackChannelReferenceId(channelId);
243
- }
244
- function getClient() {
245
- const token = resolveSlackToken();
246
- let cached = clientsByToken.get(token);
247
- if (!cached) {
248
- cached = new WebClient(token, {
249
- retryConfig: { retries: 0 },
250
- rejectRateLimitedCalls: true
251
- });
252
- clientsByToken.set(token, cached);
253
- }
254
- return cached;
255
- }
256
- function mapSlackError(error) {
257
- if (error instanceof SlackActionError) {
258
- return error;
259
- }
260
- const candidate = error;
261
- const apiError = candidate.data?.error;
262
- const message = candidate.message ?? "Slack action failed";
263
- const baseOptions = {
264
- apiError,
265
- statusCode: candidate.statusCode,
266
- requestId: getHeaderString(candidate.headers, "x-slack-req-id"),
267
- errorData: serializeSlackErrorData(candidate.data),
268
- ...parseSlackCanvasDetail(candidate.data?.detail)
269
- };
270
- if (apiError === "missing_scope") {
271
- return new SlackActionError(message, "missing_scope", {
272
- ...baseOptions,
273
- needed: candidate.data?.needed,
274
- provided: candidate.data?.provided
275
- });
276
- }
277
- if (apiError === "not_in_channel") {
278
- return new SlackActionError(message, "not_in_channel", baseOptions);
279
- }
280
- if (apiError === "restricted_action_read_only_channel") {
281
- return new SlackActionError(message, "read_only_channel", baseOptions);
282
- }
283
- if (apiError === "already_reacted") {
284
- return new SlackActionError(message, "already_reacted", baseOptions);
285
- }
286
- if (apiError === "no_reaction") {
287
- return new SlackActionError(message, "no_reaction", baseOptions);
288
- }
289
- if (apiError === "invalid_arguments") {
290
- return new SlackActionError(message, "invalid_arguments", baseOptions);
291
- }
292
- if (apiError === "invalid_cursor") {
293
- return new SlackActionError(message, "invalid_arguments", baseOptions);
294
- }
295
- if (apiError === "invalid_name") {
296
- return new SlackActionError(message, "invalid_arguments", baseOptions);
297
- }
298
- if (apiError === "not_found" || apiError === "channel_not_found" || apiError === "message_not_found") {
299
- return new SlackActionError(message, "not_found", baseOptions);
300
- }
301
- if (apiError === "feature_not_enabled" || apiError === "not_allowed_token_type") {
302
- return new SlackActionError(message, "feature_unavailable", baseOptions);
303
- }
304
- if (apiError === "canvas_creation_failed") {
305
- return new SlackActionError(message, "canvas_creation_failed", baseOptions);
306
- }
307
- if (apiError === "canvas_editing_failed") {
308
- return new SlackActionError(message, "canvas_editing_failed", baseOptions);
309
- }
310
- if (candidate.code === "slack_webapi_rate_limited_error" || candidate.statusCode === 429) {
311
- return new SlackActionError(message, "rate_limited", {
312
- ...baseOptions,
313
- retryAfterSeconds: candidate.retryAfter
314
- });
315
- }
316
- return new SlackActionError(message, "internal_error", baseOptions);
317
- }
318
- var MAX_RETRY_DELAY_MS = 1e4;
319
- var MAX_TOTAL_RETRY_DELAY_MS = 2e4;
320
- var CONNECTION_ERROR_CODES = /* @__PURE__ */ new Set([
321
- "ECONNREFUSED",
322
- "ECONNRESET",
323
- "ENOTFOUND",
324
- "EAI_AGAIN"
325
- ]);
326
- var TIMEOUT_ERROR_CODES = /* @__PURE__ */ new Set([
327
- "ETIMEDOUT",
328
- "ECONNABORTED",
329
- "ESOCKETTIMEDOUT"
330
- ]);
331
- function findNetworkErrorCode(error, depth = 0) {
332
- if (!error || typeof error !== "object" || depth > 4) {
333
- return void 0;
334
- }
335
- const candidate = error;
336
- if (typeof candidate.code === "string" && (CONNECTION_ERROR_CODES.has(candidate.code) || TIMEOUT_ERROR_CODES.has(candidate.code))) {
337
- return candidate.code;
338
- }
339
- return findNetworkErrorCode(candidate.original, depth + 1) ?? findNetworkErrorCode(candidate.cause, depth + 1);
340
- }
341
- function hasSocketHangUpMessage(error) {
342
- return error instanceof Error && error.message.toLowerCase().includes("socket hang up");
343
- }
344
- function classifySlackRetry(raw, mapped) {
345
- if (mapped.code === "rate_limited") {
346
- return "rate_limited";
347
- }
348
- if (mapped.statusCode !== void 0 && mapped.statusCode >= 500) {
349
- return "server_error";
350
- }
351
- const networkCode = findNetworkErrorCode(raw);
352
- if (networkCode && CONNECTION_ERROR_CODES.has(networkCode)) {
353
- return "connection";
354
- }
355
- if (networkCode && TIMEOUT_ERROR_CODES.has(networkCode)) {
356
- return "timeout";
357
- }
358
- if (hasSocketHangUpMessage(raw)) {
359
- return "connection";
360
- }
361
- return "none";
362
- }
363
- async function withSlackRetries(task, maxAttempts = 3, context = {}) {
364
- let attempt = 0;
365
- let totalDelayMs = 0;
366
- const action = context.action ?? "unknown";
367
- while (attempt < maxAttempts) {
368
- attempt += 1;
369
- const attemptNumber = attempt;
370
- try {
371
- return await withSpan(
372
- `POST slack.com/api/${action}`,
373
- "http.client",
374
- {},
375
- async () => {
376
- try {
377
- return await task();
378
- } catch (error) {
379
- const mapped = mapSlackError(error);
380
- const errorAttrs = {
381
- "error.type": mapped.code
382
- };
383
- if (mapped.apiError) {
384
- errorAttrs["app.slack.api_error_code"] = mapped.apiError;
385
- }
386
- if (mapped.code === "rate_limited") {
387
- errorAttrs["http.response.status_code"] = 429;
388
- if (mapped.retryAfterSeconds) {
389
- errorAttrs["app.slack.retry_after_ms"] = mapped.retryAfterSeconds * 1e3;
390
- }
391
- } else if (mapped.statusCode != null) {
392
- errorAttrs["http.response.status_code"] = mapped.statusCode;
393
- }
394
- setSpanAttributes(errorAttrs);
395
- setSpanStatus("error");
396
- throw error;
397
- }
398
- },
399
- {
400
- "http.request.method": "POST",
401
- "server.address": "slack.com",
402
- "url.scheme": "https",
403
- "url.path": `/api/${action}`,
404
- "app.slack.method": action,
405
- "app.retry.max_attempts": maxAttempts,
406
- ...attemptNumber > 1 ? { "http.resend_count": attemptNumber - 1 } : {},
407
- ...context.attributes ?? {},
408
- ...context.spanAttributes ?? {}
409
- }
410
- );
411
- } catch (error) {
412
- const mapped = mapSlackError(error);
413
- const retryClass = classifySlackRetry(error, mapped);
414
- const isRetryable = retryClass === "rate_limited" || retryClass === "connection" || retryClass === "server_error" || retryClass === "timeout" && context.idempotent === true;
415
- const remainingDelayBudgetMs = MAX_TOTAL_RETRY_DELAY_MS - totalDelayMs;
416
- const baseLogAttributes = {
417
- "app.slack.action": action,
418
- "app.slack.error_code": mapped.code,
419
- ...mapped.apiError ? { "app.slack.api_error": mapped.apiError } : {},
420
- ...mapped.detail ? { "app.slack.detail": mapped.detail } : {},
421
- ...mapped.detailLine !== void 0 ? { "app.slack.detail_line": mapped.detailLine } : {},
422
- ...mapped.detailRule ? { "app.slack.detail_rule": mapped.detailRule } : {},
423
- ...mapped.requestId ? { "app.slack.request_id": mapped.requestId } : {},
424
- ...mapped.statusCode !== void 0 ? { "http.response.status_code": mapped.statusCode } : {},
425
- ...context.attributes ?? {}
426
- };
427
- if (!isRetryable || attempt >= maxAttempts || remainingDelayBudgetMs <= 0) {
428
- logWarn(
429
- "slack_action_failed",
430
- {},
431
- {
432
- ...baseLogAttributes,
433
- ...mapped.errorData ? { "app.slack.error_data": mapped.errorData } : {}
434
- },
435
- "Slack action failed"
436
- );
437
- throw mapped;
438
- }
439
- logWarn(
440
- "slack_action_retrying",
441
- {},
442
- {
443
- ...baseLogAttributes,
444
- "app.slack.retry_attempt": attempt,
445
- "app.slack.retry_class": retryClass
446
- },
447
- "Retrying Slack action after transient failure"
448
- );
449
- const retryAfterMs = retryClass === "rate_limited" && mapped.retryAfterSeconds && mapped.retryAfterSeconds > 0 ? mapped.retryAfterSeconds * 1e3 : void 0;
450
- const backoffMs = Math.min(2e3, 250 * 2 ** (attempt - 1));
451
- const delayMs = Math.min(
452
- retryAfterMs ?? backoffMs,
453
- MAX_RETRY_DELAY_MS,
454
- remainingDelayBudgetMs
455
- );
456
- totalDelayMs += delayMs;
457
- await sleep(delayMs);
458
- }
459
- }
460
- throw new SlackActionError(
461
- "Slack action exhausted retries",
462
- "internal_error"
463
- );
464
- }
465
- function getSlackClient() {
466
- return getClient();
467
- }
468
- function isDmChannel(channelId) {
469
- const normalized = normalizeSlackConversationId(channelId);
470
- return Boolean(normalized && normalized.startsWith("D"));
471
- }
472
- function isConversationScopedChannel(channelId) {
473
- const normalized = normalizeSlackConversationId(channelId);
474
- if (!normalized) return false;
475
- return normalized.startsWith("C") || normalized.startsWith("G") || normalized.startsWith("D");
476
- }
477
- function isConversationChannel(channelId) {
478
- const normalized = normalizeSlackConversationId(channelId);
479
- if (!normalized) return false;
480
- return normalized.startsWith("C") || normalized.startsWith("G");
481
- }
482
- async function getFilePermalink(fileId) {
483
- const client = getClient();
484
- const response = await withSlackRetries(
485
- () => client.files.info({
486
- file: fileId
487
- }),
488
- 3,
489
- {
490
- action: "files.info",
491
- idempotent: true,
492
- spanAttributes: { "app.slack.file_id": fileId }
493
- }
494
- );
495
- return response.file?.permalink;
496
- }
497
- async function downloadPrivateSlackFile(url) {
498
- const token = resolveSlackToken();
499
- return withSpan(
500
- "GET files.slack.com",
501
- "http.client",
502
- {},
503
- async () => {
504
- const response = await fetch(url, {
505
- headers: {
506
- Authorization: `Bearer ${token}`
507
- }
508
- });
509
- setSpanAttributes({ "http.response.status_code": response.status });
510
- if (!response.ok) {
511
- setSpanAttributes({ "error.type": String(response.status) });
512
- setSpanStatus("error");
513
- throw new Error(`Slack file download failed: ${response.status}`);
514
- }
515
- return Buffer.from(await response.arrayBuffer());
516
- },
517
- {
518
- "http.request.method": "GET",
519
- "server.address": "files.slack.com",
520
- "url.scheme": "https",
521
- "app.slack.method": "files.download"
522
- }
523
- );
524
- }
525
-
526
- // src/chat/credentials/subject.ts
527
106
  var CREDENTIAL_SUBJECT_HMAC_CONTEXT = "junior.credential_subject.v1";
528
107
  var CREDENTIAL_SUBJECT_SIGNATURE_VERSION = "v1";
529
108
  function getCredentialSubjectSecret() {
@@ -1427,18 +1006,6 @@ export {
1427
1006
  createPluginModel,
1428
1007
  createPluginEmbedder,
1429
1008
  getSlackToolContext,
1430
- runWithWorkspaceTeamId,
1431
- getWorkspaceTeamId,
1432
- SlackActionError,
1433
- getHeaderString,
1434
- runWithSlackInstallationToken,
1435
- normalizeSlackConversationId,
1436
- withSlackRetries,
1437
- getSlackClient,
1438
- isDmChannel,
1439
- isConversationScopedChannel,
1440
- getFilePermalink,
1441
- downloadPrivateSlackFile,
1442
1009
  bindSlackDirectCredentialSubject,
1443
1010
  verifySlackDirectCredentialSubject,
1444
1011
  resolveChannelCapabilities,
@@ -4,7 +4,7 @@ import {
4
4
  juniorDestinations,
5
5
  juniorIdentities,
6
6
  juniorUsers
7
- } from "./chunk-RITD7E5L.js";
7
+ } from "./chunk-35BNLDOJ.js";
8
8
 
9
9
  // src/api/people/shared.ts
10
10
  import { and, asc, desc, eq, sql } from "drizzle-orm";
@@ -96,9 +96,8 @@ function summaryFromRow(row, nowMs) {
96
96
  const channelNameRedacted = Boolean(row.destinationVisibility) && row.destinationVisibility !== "public";
97
97
  return {
98
98
  conversationId: row.conversationId,
99
- cumulativeDurationMs: 0,
99
+ cumulativeDurationMs: row.durationMs,
100
100
  displayTitle: titleFromRow(row, surface),
101
- id: row.runId ?? row.conversationId,
102
101
  lastProgressAt: new Date(
103
102
  row.executionUpdatedAt ?? row.updatedAt
104
103
  ).toISOString(),
@@ -117,6 +116,18 @@ function summaryFromRow(row, nowMs) {
117
116
  ...channelNameRedacted ? { channelNameRedacted: true } : {}
118
117
  };
119
118
  }
119
+ function usageTokens(row) {
120
+ const usage = row.usage;
121
+ if (!usage) return void 0;
122
+ if (usage.totalTokens !== void 0) return usage.totalTokens;
123
+ const values = [
124
+ usage.inputTokens,
125
+ usage.outputTokens,
126
+ usage.cachedInputTokens,
127
+ usage.cacheCreationTokens
128
+ ].filter((value) => value !== void 0);
129
+ return values.length > 0 ? values.reduce((sum, value) => sum + value, 0) : void 0;
130
+ }
120
131
  function emptyTotals() {
121
132
  return {
122
133
  active: 0,
@@ -124,8 +135,7 @@ function emptyTotals() {
124
135
  conversations: 0,
125
136
  durationMs: 0,
126
137
  failed: 0,
127
- hung: 0,
128
- runs: 0
138
+ hung: 0
129
139
  };
130
140
  }
131
141
  function emptyStatsItem(label) {
@@ -135,8 +145,7 @@ function emptyStatsItem(label) {
135
145
  durationMs: 0,
136
146
  failed: 0,
137
147
  hung: 0,
138
- label,
139
- runs: 0
148
+ label
140
149
  };
141
150
  }
142
151
  function emptyActivityDay(date) {
@@ -146,8 +155,7 @@ function emptyActivityDay(date) {
146
155
  date,
147
156
  durationMs: 0,
148
157
  failed: 0,
149
- hung: 0,
150
- runs: 0
158
+ hung: 0
151
159
  };
152
160
  }
153
161
  function signals(summary) {
@@ -194,16 +202,17 @@ function activityDays(days, nowMs) {
194
202
  }
195
203
  function statsItems(map) {
196
204
  return [...map.values()].sort(
197
- (left, right) => right.conversations - left.conversations || right.runs - left.runs || right.durationMs - left.durationMs || left.label.localeCompare(right.label)
205
+ (left, right) => right.conversations - left.conversations || right.durationMs - left.durationMs || left.label.localeCompare(right.label)
198
206
  );
199
207
  }
200
- async function actorRows(options = {}, email) {
208
+ async function actorRows(email) {
201
209
  const normalizedEmail = normalizeEmail(email);
202
- const rows = await (options.db ?? getDb()).select({
210
+ const rows = await getDb().select({
203
211
  channelName: juniorConversations.channelName,
204
212
  conversationId: juniorConversations.conversationId,
205
213
  createdAt: juniorConversations.createdAt,
206
214
  destinationVisibility: juniorDestinations.visibility,
215
+ durationMs: juniorConversations.durationMs,
207
216
  email: juniorUsers.primaryEmailNormalized,
208
217
  executionStatus: juniorConversations.executionStatus,
209
218
  executionUpdatedAt: juniorConversations.executionUpdatedAt,
@@ -211,10 +220,10 @@ async function actorRows(options = {}, email) {
211
220
  handle: juniorIdentities.handle,
212
221
  lastActivityAt: juniorConversations.lastActivityAt,
213
222
  providerSubjectId: juniorIdentities.providerSubjectId,
214
- runId: juniorConversations.runId,
215
223
  source: juniorConversations.source,
216
224
  title: juniorConversations.title,
217
- updatedAt: juniorConversations.updatedAt
225
+ updatedAt: juniorConversations.updatedAt,
226
+ usage: juniorConversations.usage
218
227
  }).from(juniorConversations).innerJoin(
219
228
  juniorIdentities,
220
229
  eq(juniorIdentities.id, juniorConversations.actorIdentityId)
@@ -248,6 +257,7 @@ export {
248
257
  surfaceLabel,
249
258
  slackLocationLabel,
250
259
  summaryFromRow,
260
+ usageTokens,
251
261
  emptyTotals,
252
262
  emptyStatsItem,
253
263
  emptyActivityDay,