@sentry/junior 0.122.1 → 0.124.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 (78) hide show
  1. package/dist/{agent-hooks-65WXVKKX.js → agent-hooks-RPQRUAGN.js} +7 -7
  2. package/dist/api/conversations/detail.d.ts +55 -0
  3. package/dist/api/conversations/event-list.d.ts +55 -0
  4. package/dist/api/conversations/events.d.ts +1 -1
  5. package/dist/api/conversations/stats.d.ts +15 -0
  6. package/dist/api/schema/conversation.d.ts +260 -0
  7. package/dist/api/schema.d.ts +1 -1
  8. package/dist/api/schema.js +1 -1
  9. package/dist/api.js +137 -22
  10. package/dist/app.js +33 -20
  11. package/dist/{catalog-runtime-VNNMSKCB.js → catalog-runtime-QM2W6BBD.js} +5 -5
  12. package/dist/chat/agent/action-confirmation-retry.d.ts +6 -0
  13. package/dist/chat/agent/tools.d.ts +12 -0
  14. package/dist/chat/config.d.ts +1 -0
  15. package/dist/chat/conversations/history.d.ts +91 -1
  16. package/dist/chat/conversations/projection.d.ts +24 -0
  17. package/dist/chat/conversations/provenance.d.ts +2 -0
  18. package/dist/chat/conversations/structured-events.d.ts +31 -0
  19. package/dist/chat/mcp/tool-manager.d.ts +1 -1
  20. package/dist/chat/pi/client.d.ts +6 -0
  21. package/dist/chat/pi/sdk.d.ts +1 -1
  22. package/dist/chat/pi/transcript.d.ts +2 -0
  23. package/dist/chat/plugins/agent-hooks.d.ts +2 -0
  24. package/dist/chat/plugins/conversation-events.d.ts +15 -0
  25. package/dist/chat/services/guardian-action-policy.d.ts +12 -0
  26. package/dist/chat/services/guardian-action-review.d.ts +9 -0
  27. package/dist/chat/services/provider-error.d.ts +2 -0
  28. package/dist/chat/tool-support/action-review-evidence.d.ts +4 -0
  29. package/dist/chat/tool-support/action-review-history.d.ts +117 -0
  30. package/dist/chat/tool-support/action-review.d.ts +142 -0
  31. package/dist/chat/tool-support/pi-tool-adapter.d.ts +2 -1
  32. package/dist/chat/tool-support/skill/mcp-tool-summary.d.ts +1 -6
  33. package/dist/chat/tool-support/zod-tool.d.ts +1 -0
  34. package/dist/chat/tools/definition.d.ts +23 -1
  35. package/dist/chat/tools/query-conversation-events.d.ts +1 -1
  36. package/dist/chat/tools/search-tools.d.ts +0 -20
  37. package/dist/chat/tools/skill/search-mcp-tools.d.ts +0 -20
  38. package/dist/{chunk-73TQBD5S.js → chunk-4HQMMFRL.js} +1 -1
  39. package/dist/{chunk-3KYLHUVC.js → chunk-4OWSABFE.js} +1474 -593
  40. package/dist/{chunk-LZ4XXS76.js → chunk-7S36LUYT.js} +3 -2
  41. package/dist/{chunk-4ZV2GNHX.js → chunk-APPWCJVJ.js} +1 -1
  42. package/dist/{chunk-O2ULQJWR.js → chunk-AYQZCJZJ.js} +47 -1
  43. package/dist/{chunk-XBYNPBPQ.js → chunk-EKVBTUVM.js} +2 -2
  44. package/dist/{chunk-VLRECFIC.js → chunk-GBIFLB5Y.js} +57 -11
  45. package/dist/{chunk-MSDKKTRG.js → chunk-HOVHXQQE.js} +4 -4
  46. package/dist/{chunk-TI7SYDD4.js → chunk-IYUHOYFA.js} +68 -4
  47. package/dist/{chunk-HGREP4UX.js → chunk-MG3L3UGS.js} +1 -1
  48. package/dist/{chunk-GPQLJDT5.js → chunk-PBZEJRYY.js} +20 -20
  49. package/dist/{chunk-QE33ATQW.js → chunk-PGLSOXFU.js} +19 -11
  50. package/dist/{chunk-MU6HHZEN.js → chunk-PR3M62LK.js} +74 -0
  51. package/dist/{chunk-WFJ2EG4E.js → chunk-RW6MD6ZV.js} +1 -1
  52. package/dist/{chunk-IEE5CSAP.js → chunk-TFO4SDCQ.js} +1 -1
  53. package/dist/{chunk-PYS4QZAF.js → chunk-UZAOIEAR.js} +1 -1
  54. package/dist/{chunk-4JPJTFUH.js → chunk-VLAWZSCB.js} +9 -4
  55. package/dist/chunk-W4YS2LXS.js +55 -0
  56. package/dist/{chunk-U5PRRZMZ.js → chunk-WFIXN6UU.js} +7 -7
  57. package/dist/{chunk-BXT63TNS.js → chunk-WKLA6WLW.js} +77 -6
  58. package/dist/{chunk-M7KAZXTE.js → chunk-YYAQ5ZNK.js} +30 -2
  59. package/dist/{chunk-PXPBBOIU.js → chunk-ZV2K3WM4.js} +1 -1
  60. package/dist/cli/chat.js +22 -22
  61. package/dist/cli/check.js +6 -6
  62. package/dist/cli/init.js +2 -1
  63. package/dist/cli/plugins.js +10 -10
  64. package/dist/cli/snapshot-create.js +8 -8
  65. package/dist/cli/upgrade.js +5 -5
  66. package/dist/{db-36HXKAKH.js → db-2W4KOPLN.js} +5 -5
  67. package/dist/instrumentation.js +2 -2
  68. package/dist/nitro.js +2 -2
  69. package/dist/{oauth-callback-server-UKOO7KKP.js → oauth-callback-server-3TGRLQUD.js} +16 -15
  70. package/dist/{runner-M66KMCQ7.js → runner-NAVNNKQY.js} +11 -10
  71. package/dist/{skills-TTXTVFOG.js → skills-FIVS6EXW.js} +6 -6
  72. package/dist/{validation-TGASRGNN.js → validation-NX4DAKNV.js} +6 -6
  73. package/dist/version.js +1 -1
  74. package/migrations/0012_structured_conversation_events.sql +4 -0
  75. package/migrations/meta/0012_snapshot.json +1244 -0
  76. package/migrations/meta/_journal.json +7 -0
  77. package/package.json +7 -6
  78. package/dist/chat/tool-support/schema-summary.d.ts +0 -2
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "@sentry/junior",
4
- version: "0.122.1",
4
+ version: "0.124.0",
5
5
  private: false,
6
6
  publishConfig: {
7
7
  access: "public"
@@ -63,6 +63,7 @@ var package_default = {
63
63
  "test:watch": "vitest",
64
64
  typecheck: "tsc --noEmit",
65
65
  "skills:check": "node --test scripts/check-skills.test.mjs && node scripts/check-skills.mjs",
66
+ "tool-annotations:check": "node --test scripts/check-tool-annotations.test.mjs && node scripts/check-tool-annotations.mjs",
66
67
  "test:coverage": "vitest run --maxWorkers=4 --coverage --reporter=default --reporter=junit --outputFile.junit=coverage/results.junit.xml"
67
68
  },
68
69
  dependencies: {
@@ -86,7 +87,7 @@ var package_default = {
86
87
  chat: "4.29.0",
87
88
  commander: "^14.0.3",
88
89
  "drizzle-orm": "catalog:",
89
- hono: "^4.12.22",
90
+ hono: "^4.12.27",
90
91
  jiti: "^2.7.0",
91
92
  jose: "^6.2.3",
92
93
  "just-bash": "3.0.1",
@@ -5,7 +5,7 @@ import {
5
5
  logInfo,
6
6
  logWarn,
7
7
  setSpanAttributes
8
- } from "./chunk-4JPJTFUH.js";
8
+ } from "./chunk-VLAWZSCB.js";
9
9
  import {
10
10
  discoverInstalledPluginPackageContent,
11
11
  normalizePluginPackageNames
@@ -39,7 +39,10 @@ function activityDays(days, nowMs, count) {
39
39
 
40
40
  // src/api/schema/conversation.ts
41
41
  import { z as z2 } from "zod";
42
- import { conversationAnnotationInputSchema } from "@sentry/junior-plugin-api";
42
+ import {
43
+ conversationAnnotationInputSchema,
44
+ conversationEventPresentationSchema
45
+ } from "@sentry/junior-plugin-api";
43
46
  var conversationReportStatusSchema = z2.enum([
44
47
  "active",
45
48
  "completed",
@@ -95,6 +98,7 @@ var conversationReportMessageEventDataSchema = z2.object({
95
98
  type: z2.literal("message"),
96
99
  messageId: z2.string().min(1),
97
100
  role: z2.enum(["assistant", "system", "user"]),
101
+ actorIdentity: actorIdentitySchema.optional(),
98
102
  eventType: z2.string().min(1).optional(),
99
103
  text: z2.string().optional(),
100
104
  redacted: z2.literal(true).optional()
@@ -105,6 +109,12 @@ var conversationReportMessageEventDataSchema = z2.object({
105
109
  message: "message content must be text or explicitly redacted"
106
110
  });
107
111
  }
112
+ if (data.redacted && data.actorIdentity) {
113
+ context.addIssue({
114
+ code: "custom",
115
+ message: "redacted messages must not expose actor identity"
116
+ });
117
+ }
108
118
  });
109
119
  var conversationReportMessageHandledEventDataSchema = z2.object({
110
120
  type: z2.literal("message_handled"),
@@ -210,6 +220,15 @@ var conversationReportTurnRoutedEventDataSchema = z2.object({
210
220
  confidence: z2.number().min(0).max(1).optional(),
211
221
  source: z2.enum(["configured", "inherited", "router"])
212
222
  }).strict();
223
+ var conversationReportGuardianActionReviewedEventDataSchema = z2.object({
224
+ type: z2.literal("guardian_action_reviewed"),
225
+ turnId: z2.string().min(1),
226
+ toolCallId: z2.string().min(1),
227
+ toolName: z2.string().min(1),
228
+ decision: z2.enum(["allow", "ask", "deny"]),
229
+ riskLevel: z2.enum(["low", "medium", "high", "critical"]),
230
+ userAuthorization: z2.enum(["high", "medium", "low", "unknown"])
231
+ }).strict();
213
232
  var conversationReportTurnContextEventDataSchema = z2.object({
214
233
  type: z2.literal("turn_context"),
215
234
  turnId: z2.string().min(1),
@@ -218,6 +237,14 @@ var conversationReportTurnContextEventDataSchema = z2.object({
218
237
  version: z2.number().int().positive(),
219
238
  content: z2.record(z2.string(), z2.unknown())
220
239
  }).strict();
240
+ var conversationReportStructuredEventDataSchema = z2.object({
241
+ type: z2.literal("structured_event"),
242
+ namespace: z2.string().min(1),
243
+ name: z2.string().min(1),
244
+ version: z2.number().int().positive(),
245
+ turnId: z2.string().min(1).optional(),
246
+ presentation: conversationEventPresentationSchema
247
+ }).strict();
221
248
  var conversationReportCompactionEventDataSchema = z2.object({
222
249
  type: z2.literal("compaction"),
223
250
  modelProfile: z2.string().min(1).optional(),
@@ -258,7 +285,9 @@ var conversationReportEventDataSchema = z2.discriminatedUnion("type", [
258
285
  conversationReportToolCallsEventDataSchema,
259
286
  conversationReportTurnLifecycleEventDataSchema,
260
287
  conversationReportTurnContextEventDataSchema,
288
+ conversationReportStructuredEventDataSchema,
261
289
  conversationReportTurnRoutedEventDataSchema,
290
+ conversationReportGuardianActionReviewedEventDataSchema,
262
291
  conversationReportCompactionEventDataSchema,
263
292
  conversationReportHandoffEventDataSchema,
264
293
  conversationReportSubagentEventDataSchema
@@ -396,12 +425,29 @@ var conversationMetricDaySchema = z2.object({
396
425
  durationMs: z2.number(),
397
426
  tokens: z2.number().optional()
398
427
  }).strict();
428
+ var guardianMetricDaySchema = z2.object({
429
+ allow: z2.number(),
430
+ ask: z2.number(),
431
+ costUsd: z2.number().optional(),
432
+ date: z2.string(),
433
+ deny: z2.number(),
434
+ requests: z2.number()
435
+ }).strict();
436
+ var guardianStatsSchema = z2.object({
437
+ allow: z2.number(),
438
+ ask: z2.number(),
439
+ costUsd: z2.number().optional(),
440
+ deny: z2.number(),
441
+ metricDays: z2.array(guardianMetricDaySchema),
442
+ requests: z2.number()
443
+ }).strict();
399
444
  var conversationStatsReportSchema = z2.object({
400
445
  active: z2.number(),
401
446
  conversations: z2.number(),
402
447
  durationMs: z2.number(),
403
448
  failed: z2.number(),
404
449
  generatedAt: z2.string(),
450
+ guardian: guardianStatsSchema,
405
451
  metricDays: z2.array(conversationMetricDaySchema),
406
452
  locations: z2.array(conversationStatsItemSchema),
407
453
  actors: z2.array(conversationStatsItemSchema),
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-73TQBD5S.js";
3
+ } from "./chunk-4HQMMFRL.js";
4
4
  import {
5
5
  logWarn
6
- } from "./chunk-4JPJTFUH.js";
6
+ } from "./chunk-VLAWZSCB.js";
7
7
  import {
8
8
  skillRoots
9
9
  } from "./chunk-H4HBKISO.js";
@@ -13,7 +13,7 @@ import {
13
13
  persistAuthPauseTurnState,
14
14
  requireTurnFailureEventId,
15
15
  scheduleSessionCompletedPluginTasks
16
- } from "./chunk-GPQLJDT5.js";
16
+ } from "./chunk-PBZEJRYY.js";
17
17
  import {
18
18
  buildSentryConversationUrl
19
19
  } from "./chunk-4CODA7P5.js";
@@ -40,7 +40,7 @@ import {
40
40
  resolveBaseUrl,
41
41
  resolvePluginOAuthAccount,
42
42
  truncateStatusText
43
- } from "./chunk-U5PRRZMZ.js";
43
+ } from "./chunk-WFIXN6UU.js";
44
44
  import {
45
45
  JUNIOR_THREAD_STATE_TTL_MS,
46
46
  TurnSliceLimitExceededError,
@@ -68,11 +68,12 @@ import {
68
68
  persistThreadStateById,
69
69
  persistWithRetry,
70
70
  recordAgentTurnSessionSummary,
71
+ recordAuthenticationLinked,
71
72
  recordAuthorizationCompleted,
72
73
  recordDeliveredAssistantMessage,
73
74
  turnHasReply,
74
75
  updateConversationStats
75
- } from "./chunk-BXT63TNS.js";
76
+ } from "./chunk-WKLA6WLW.js";
76
77
  import {
77
78
  SlackActionError,
78
79
  getDashboardConversationLink,
@@ -81,19 +82,19 @@ import {
81
82
  getSlackClient,
82
83
  isDmChannel,
83
84
  normalizeSlackConversationId
84
- } from "./chunk-QE33ATQW.js";
85
+ } from "./chunk-PGLSOXFU.js";
85
86
  import {
86
87
  getConversationEventStore,
87
88
  getConversationStore,
88
89
  parseDestination,
89
90
  requireSlackDestination,
90
91
  sameDestination
91
- } from "./chunk-M7KAZXTE.js";
92
+ } from "./chunk-YYAQ5ZNK.js";
92
93
  import {
93
94
  acquireActiveLock,
94
95
  getDefaultRedisStateAdapterFor,
95
96
  getStateAdapter
96
- } from "./chunk-WFJ2EG4E.js";
97
+ } from "./chunk-RW6MD6ZV.js";
97
98
  import {
98
99
  FUNCTION_TIMEOUT_BUFFER_SECONDS,
99
100
  botConfig,
@@ -102,7 +103,7 @@ import {
102
103
  getRuntimeMetadata,
103
104
  normalizeSlackEmojiName,
104
105
  standardModelId
105
- } from "./chunk-TI7SYDD4.js";
106
+ } from "./chunk-IYUHOYFA.js";
106
107
  import {
107
108
  parseSlackThreadId,
108
109
  readSlackRawMessageContext,
@@ -111,15 +112,15 @@ import {
111
112
  } from "./chunk-S7G34U75.js";
112
113
  import {
113
114
  discoverSkills
114
- } from "./chunk-XBYNPBPQ.js";
115
+ } from "./chunk-EKVBTUVM.js";
115
116
  import {
116
117
  pluginCatalogRuntime
117
- } from "./chunk-73TQBD5S.js";
118
+ } from "./chunk-4HQMMFRL.js";
118
119
  import {
119
120
  buildOAuthTokenRequest,
120
121
  hasRequiredOAuthScope,
121
122
  parseOAuthTokenResponse
122
- } from "./chunk-4ZV2GNHX.js";
123
+ } from "./chunk-APPWCJVJ.js";
123
124
  import {
124
125
  createSlackResumeActor,
125
126
  isUserActor,
@@ -132,7 +133,7 @@ import {
132
133
  logWarn,
133
134
  setTags,
134
135
  withLogContext
135
- } from "./chunk-4JPJTFUH.js";
136
+ } from "./chunk-VLAWZSCB.js";
136
137
  import {
137
138
  isRecord,
138
139
  toOptionalNumber,
@@ -3605,6 +3606,29 @@ async function GET(request, provider, waitUntil, options) {
3605
3606
  mutation
3606
3607
  )
3607
3608
  );
3609
+ let providerLabel;
3610
+ try {
3611
+ providerLabel = formatProviderLabel(provider);
3612
+ } catch {
3613
+ providerLabel = void 0;
3614
+ }
3615
+ try {
3616
+ await recordAuthenticationLinked({
3617
+ conversationId: authSession.conversationId,
3618
+ provider,
3619
+ actorId: authSession.userId,
3620
+ authorizationId: mcpAuthorizationId({
3621
+ provider,
3622
+ sessionId: authSession.sessionId
3623
+ }),
3624
+ turnId: authSession.sessionId,
3625
+ ...providerLabel ? { providerLabel } : {}
3626
+ });
3627
+ } catch (error2) {
3628
+ logException(error2, "mcp.oauth_callback.authentication_event.failed", {
3629
+ "app.credential.provider": provider
3630
+ });
3631
+ }
3608
3632
  try {
3609
3633
  await deleteMcpAuthSession(authSession.authSessionId);
3610
3634
  } catch (cleanupError) {
@@ -4295,6 +4319,28 @@ async function GET2(request, provider, waitUntil, options) {
4295
4319
  ...parsedTokenResponse,
4296
4320
  ...account ? { account } : {}
4297
4321
  });
4322
+ if (stored.resumeConversationId) {
4323
+ try {
4324
+ await recordAuthenticationLinked({
4325
+ conversationId: stored.resumeConversationId,
4326
+ provider,
4327
+ actorId: stored.userId,
4328
+ providerLabel,
4329
+ ...account?.label ? { accountLabel: account.label } : {},
4330
+ ...stored.resumeSessionId ? {
4331
+ authorizationId: pluginAuthorizationId({
4332
+ provider,
4333
+ sessionId: stored.resumeSessionId
4334
+ }),
4335
+ turnId: stored.resumeSessionId
4336
+ } : {}
4337
+ });
4338
+ } catch (error) {
4339
+ logException(error, "oauth.callback.authentication_event.failed", {
4340
+ "app.credential.provider": provider
4341
+ });
4342
+ }
4343
+ }
4298
4344
  if (stored.destination?.platform !== "local") {
4299
4345
  waitUntil(async () => {
4300
4346
  try {
@@ -2,18 +2,18 @@ import {
2
2
  SANDBOX_WORKSPACE_ROOT,
3
3
  getStateAdapter,
4
4
  sleep
5
- } from "./chunk-WFJ2EG4E.js";
5
+ } from "./chunk-RW6MD6ZV.js";
6
6
  import {
7
7
  toOptionalTrimmed
8
- } from "./chunk-TI7SYDD4.js";
8
+ } from "./chunk-IYUHOYFA.js";
9
9
  import {
10
10
  pluginCatalogRuntime
11
- } from "./chunk-73TQBD5S.js";
11
+ } from "./chunk-4HQMMFRL.js";
12
12
  import {
13
13
  setSpanAttributes,
14
14
  setSpanStatus,
15
15
  withSpan
16
- } from "./chunk-4JPJTFUH.js";
16
+ } from "./chunk-VLAWZSCB.js";
17
17
 
18
18
  // src/chat/sandbox/snapshot/profile.ts
19
19
  import { createHash } from "crypto";
@@ -12,7 +12,7 @@ import {
12
12
  normalizeGenAiFinishReason,
13
13
  serializeGenAiAttribute,
14
14
  withSpan
15
- } from "./chunk-4JPJTFUH.js";
15
+ } from "./chunk-VLAWZSCB.js";
16
16
 
17
17
  // src/chat/config.ts
18
18
  import { getModel as getModel2 } from "@earendil-works/pi-ai/compat";
@@ -28,6 +28,7 @@ function toOptionalTrimmed(value) {
28
28
 
29
29
  // src/chat/pi/sdk.ts
30
30
  import {
31
+ calculateCost,
31
32
  completeSimple,
32
33
  getEnvApiKey,
33
34
  getModel,
@@ -42,7 +43,11 @@ import {
42
43
 
43
44
  // src/chat/pi/client.ts
44
45
  import { createGatewayProvider } from "@ai-sdk/gateway";
45
- import { embedMany, generateObject, NoObjectGeneratedError } from "ai";
46
+ import {
47
+ embedMany,
48
+ generateObject,
49
+ NoObjectGeneratedError
50
+ } from "ai";
46
51
 
47
52
  // src/chat/services/provider-error.ts
48
53
  var ProviderError = class extends Error {
@@ -176,6 +181,18 @@ function createProviderError(error, options = {}) {
176
181
  function isProviderRetryError(error) {
177
182
  return error instanceof ProviderError && error.retryable;
178
183
  }
184
+ function findProviderError(error) {
185
+ const visited = /* @__PURE__ */ new Set();
186
+ let current = error;
187
+ while (current instanceof Error && !visited.has(current)) {
188
+ if (current instanceof ProviderError) {
189
+ return current;
190
+ }
191
+ visited.add(current);
192
+ current = current.cause;
193
+ }
194
+ return void 0;
195
+ }
179
196
  function getProviderErrorUserMessage(error) {
180
197
  switch (error.kind) {
181
198
  case "capacity":
@@ -434,11 +451,40 @@ function logContextFromMetadata(modelId, metadata) {
434
451
  ...runId ? { runId } : {}
435
452
  };
436
453
  }
454
+ function objectCompletionCost(modelId, usage) {
455
+ const cacheRead = usage.inputTokenDetails.cacheReadTokens;
456
+ const cacheWrite = usage.inputTokenDetails.cacheWriteTokens;
457
+ const input = usage.inputTokenDetails.noCacheTokens ?? (usage.inputTokens === void 0 ? void 0 : Math.max(0, usage.inputTokens - (cacheRead ?? 0) - (cacheWrite ?? 0)));
458
+ if (input === void 0 && usage.outputTokens === void 0 && cacheRead === void 0 && cacheWrite === void 0) {
459
+ return void 0;
460
+ }
461
+ return calculateCost(resolveGatewayModel(modelId), {
462
+ input: input ?? 0,
463
+ output: usage.outputTokens ?? 0,
464
+ cacheRead: cacheRead ?? 0,
465
+ cacheWrite: cacheWrite ?? 0,
466
+ ...usage.outputTokenDetails.reasoningTokens !== void 0 ? { reasoning: usage.outputTokenDetails.reasoningTokens } : {},
467
+ totalTokens: usage.totalTokens ?? (input ?? 0) + (usage.outputTokens ?? 0) + (cacheRead ?? 0) + (cacheWrite ?? 0),
468
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
469
+ }).total;
470
+ }
471
+ function bestEffortObjectCompletionCost(modelId, usage) {
472
+ try {
473
+ return objectCompletionCost(modelId, usage);
474
+ } catch (error) {
475
+ logWarn("ai.completion.cost_estimate.failed", {
476
+ "exception.message": error instanceof Error ? error.message : String(error),
477
+ "gen_ai.request.model": modelId
478
+ });
479
+ return void 0;
480
+ }
481
+ }
437
482
  async function completeObject(params) {
438
483
  const apiKey = getGatewayApiKey();
439
484
  const provider = createGatewayProvider(apiKey ? { apiKey } : {});
485
+ let result;
440
486
  try {
441
- const result = await withSpan(
487
+ result = await withSpan(
442
488
  `${GEN_AI_OPERATION_CHAT} ${params.modelId}`,
443
489
  "gen_ai.chat",
444
490
  logContextFromMetadata(params.modelId, params.metadata),
@@ -450,6 +496,13 @@ async function completeObject(params) {
450
496
  ...params.system !== void 0 ? { system: params.system } : {},
451
497
  ...params.temperature !== void 0 ? { temperature: params.temperature } : {},
452
498
  ...params.maxTokens !== void 0 ? { maxOutputTokens: params.maxTokens } : {},
499
+ ...params.recordTelemetryPayloads === false ? {
500
+ experimental_telemetry: {
501
+ isEnabled: true,
502
+ recordInputs: false,
503
+ recordOutputs: false
504
+ }
505
+ } : {},
453
506
  ...params.signal !== void 0 ? { abortSignal: params.signal } : {}
454
507
  });
455
508
  setSpanAttributes({
@@ -470,7 +523,6 @@ async function completeObject(params) {
470
523
  ...params.maxTokens !== void 0 ? { "gen_ai.request.max_tokens": params.maxTokens } : {}
471
524
  }
472
525
  );
473
- return { object: result.object };
474
526
  } catch (error) {
475
527
  const providerError = createProviderError(error, {
476
528
  ...NoObjectGeneratedError.isInstance(error) ? { kind: "invalid_response" } : {},
@@ -478,6 +530,11 @@ async function completeObject(params) {
478
530
  });
479
531
  throw providerError;
480
532
  }
533
+ const costUsd = bestEffortObjectCompletionCost(params.modelId, result.usage);
534
+ return {
535
+ object: result.object,
536
+ ...costUsd !== void 0 ? { costUsd } : {}
537
+ };
481
538
  }
482
539
  async function embedTexts(params) {
483
540
  const texts = params.texts.map((text) => text.trim());
@@ -695,6 +752,10 @@ var DEFAULT_FAST_MODEL_ID = getModel2(
695
752
  "vercel-ai-gateway",
696
753
  "anthropic/claude-haiku-4.5"
697
754
  ).id;
755
+ var DEFAULT_GUARDIAN_MODEL_ID = getModel2(
756
+ "vercel-ai-gateway",
757
+ "openai/gpt-5.6-luna"
758
+ ).id;
698
759
  var DEFAULT_HANDOFF_MODEL_ID = getModel2(
699
760
  "vercel-ai-gateway",
700
761
  "openai/gpt-5.6-sol"
@@ -773,6 +834,7 @@ function readBotConfig(env, functionMaxDurationSeconds) {
773
834
  const modelId = validateGatewayModelId(env.AI_MODEL) ?? DEFAULT_MODEL_ID;
774
835
  const reasoningLevel = toOptionalTrimmed(env.AI_REASONING_LEVEL);
775
836
  const fastModelId = validateGatewayModelId(env.AI_FAST_MODEL ?? env.AI_MODEL) ?? DEFAULT_FAST_MODEL_ID;
837
+ const guardianModelId = validateGatewayModelId(env.AI_GUARDIAN_MODEL) ?? DEFAULT_GUARDIAN_MODEL_ID;
776
838
  const handoffModelId = validateGatewayModelId(env.AI_HANDOFF_MODEL) ?? DEFAULT_HANDOFF_MODEL_ID;
777
839
  return {
778
840
  userName: toOptionalTrimmed(env.JUNIOR_BOT_NAME) ?? "junior",
@@ -786,6 +848,7 @@ function readBotConfig(env, functionMaxDurationSeconds) {
786
848
  ) ?? DEFAULT_MODEL_CONTEXT_WINDOW_TOKENS,
787
849
  reasoningLevel: reasoningLevel === void 0 ? void 0 : parseTurnReasoningLevel(reasoningLevel),
788
850
  fastModelId,
851
+ guardianModelId,
789
852
  imageGenerationModelId: toOptionalTrimmed(env.AI_IMAGE_MODEL) ?? DEFAULT_IMAGE_GENERATION_MODEL_ID,
790
853
  embeddingModelId: validateEmbeddingModelId(env.AI_EMBEDDING_MODEL) ?? DEFAULT_EMBEDDING_MODEL_ID,
791
854
  loadingMessages: parseLoadingMessages(env.JUNIOR_LOADING_MESSAGES),
@@ -918,6 +981,7 @@ export {
918
981
  ProviderError,
919
982
  createProviderError,
920
983
  isProviderRetryError,
984
+ findProviderError,
921
985
  getProviderErrorUserMessage,
922
986
  getProviderErrorAttributes,
923
987
  escapeXml,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-73TQBD5S.js";
3
+ } from "./chunk-4HQMMFRL.js";
4
4
 
5
5
  // src/chat/plugins/validation.ts
6
6
  import { isDeepStrictEqual } from "util";
@@ -1,3 +1,6 @@
1
+ import {
2
+ createPluginConversationEvents
3
+ } from "./chunk-W4YS2LXS.js";
1
4
  import {
2
5
  pluginTaskId,
3
6
  pluginTaskParamsSchema,
@@ -22,28 +25,30 @@ import {
22
25
  persistThreadStateById,
23
26
  stripRuntimeTurnContext,
24
27
  updateConversationStats
25
- } from "./chunk-BXT63TNS.js";
28
+ } from "./chunk-WKLA6WLW.js";
26
29
  import {
27
30
  createPluginEmbedder,
28
31
  createPluginLogger,
29
32
  createPluginModel,
30
33
  createPluginState,
31
34
  getPlugins
32
- } from "./chunk-QE33ATQW.js";
35
+ } from "./chunk-PGLSOXFU.js";
33
36
  import {
34
- getDb
35
- } from "./chunk-M7KAZXTE.js";
37
+ getDb,
38
+ sameActorIdentity
39
+ } from "./chunk-YYAQ5ZNK.js";
36
40
  import {
37
41
  getStateAdapter
38
- } from "./chunk-WFJ2EG4E.js";
42
+ } from "./chunk-RW6MD6ZV.js";
39
43
  import {
40
44
  ProviderError,
45
+ findProviderError,
41
46
  getProviderErrorAttributes,
42
47
  getProviderErrorUserMessage
43
- } from "./chunk-TI7SYDD4.js";
48
+ } from "./chunk-IYUHOYFA.js";
44
49
  import {
45
50
  buildTurnFailureResponse
46
- } from "./chunk-4JPJTFUH.js";
51
+ } from "./chunk-VLAWZSCB.js";
47
52
  import {
48
53
  parseSlackMessageTs
49
54
  } from "./chunk-F3B2YJ76.js";
@@ -122,18 +127,6 @@ function sanitizeText(text) {
122
127
  "[image data omitted]"
123
128
  ).replaceAll("\0", " ").trim();
124
129
  }
125
- function sameActorIdentity(left, right) {
126
- if (!left || !right || left.platform !== right.platform) {
127
- return false;
128
- }
129
- if (left.platform === "system" || right.platform === "system") {
130
- return left.platform === "system" && right.platform === "system" && left.name === right.name;
131
- }
132
- if (left.platform === "slack" && right.platform === "slack") {
133
- return left.teamId === right.teamId && left.userId === right.userId;
134
- }
135
- return left.userId === right.userId;
136
- }
137
130
  function messageProvenance(provenance) {
138
131
  return {
139
132
  authority: provenance.authority,
@@ -318,6 +311,12 @@ function taskPluginContext(plugin, message, options = {}) {
318
311
  embedder: createPluginEmbedder(pluginName, {
319
312
  signal: options.signal
320
313
  }),
314
+ events: createPluginConversationEvents({
315
+ conversationId: sessionParams.conversationId,
316
+ operationId: pluginTaskId(message),
317
+ plugin,
318
+ turnId: sessionParams.sessionId
319
+ }),
321
320
  id: pluginTaskId(message),
322
321
  log: createPluginLogger(pluginName),
323
322
  model: createPluginModel(pluginName, plugin.model, {
@@ -412,12 +411,13 @@ function getExecutionFailureReason(reply) {
412
411
  }
413
412
  function getFailureCapture(reply) {
414
413
  if (reply.diagnostics.outcome === "provider_error") {
414
+ const providerError = findProviderError(reply.diagnostics.providerError);
415
415
  return {
416
416
  eventName: "agent.turn.provider_error",
417
417
  error: reply.diagnostics.providerError ?? new Error(
418
418
  reply.diagnostics.errorMessage ?? "Provider error without explicit message"
419
419
  ),
420
- attributes: reply.diagnostics.providerError instanceof ProviderError ? getProviderErrorAttributes(reply.diagnostics.providerError) : {},
420
+ attributes: providerError ? getProviderErrorAttributes(providerError) : {},
421
421
  body: "Agent turn failed with provider error"
422
422
  };
423
423
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getDb
3
- } from "./chunk-M7KAZXTE.js";
3
+ } from "./chunk-YYAQ5ZNK.js";
4
4
  import {
5
5
  juniorConversationAnnotations,
6
6
  juniorIdentities,
@@ -10,14 +10,14 @@ import {
10
10
  SANDBOX_WORKSPACE_ROOT,
11
11
  getStateAdapter,
12
12
  sleep
13
- } from "./chunk-WFJ2EG4E.js";
13
+ } from "./chunk-RW6MD6ZV.js";
14
14
  import {
15
15
  botConfig,
16
16
  completeObject,
17
17
  embedTexts,
18
18
  getSlackBotToken,
19
19
  standardModelId
20
- } from "./chunk-TI7SYDD4.js";
20
+ } from "./chunk-IYUHOYFA.js";
21
21
  import {
22
22
  isActorUserId,
23
23
  parseActorUserId
@@ -30,7 +30,7 @@ import {
30
30
  setSpanAttributes,
31
31
  setSpanStatus,
32
32
  withSpan
33
- } from "./chunk-4JPJTFUH.js";
33
+ } from "./chunk-VLAWZSCB.js";
34
34
  import {
35
35
  parseSlackChannelReferenceId,
36
36
  parseSlackMessageTs,
@@ -39,6 +39,7 @@ import {
39
39
 
40
40
  // src/chat/plugins/agent-hooks.ts
41
41
  import {
42
+ missingToolAnnotationKeys,
42
43
  promptContextSchema,
43
44
  promptMessageSchema,
44
45
  resourceEventSchema
@@ -1337,6 +1338,17 @@ function getPluginTools(context) {
1337
1338
  );
1338
1339
  }
1339
1340
  const definition = tool;
1341
+ const missingAnnotationKeys = missingToolAnnotationKeys(
1342
+ definition.annotations
1343
+ );
1344
+ if (missingAnnotationKeys.length > 0) {
1345
+ logWarn("plugin.tool_annotations.missing", {
1346
+ "app.plugin.name": pluginName,
1347
+ "gen_ai.tool.name": localName,
1348
+ "app.tool.missing_annotations": missingAnnotationKeys.join(",")
1349
+ });
1350
+ }
1351
+ definition.approvalMode ??= "auto";
1340
1352
  definition.identity = {
1341
1353
  id: `${pluginName}.${localName}`,
1342
1354
  name: localName,
@@ -1860,8 +1872,8 @@ function createPluginHookRunner(input = {}) {
1860
1872
  }
1861
1873
  },
1862
1874
  async beforeToolExecute(tool) {
1875
+ const env = {};
1863
1876
  let nextInput = { ...tool.input };
1864
- const env = normalizeEnv(nextInput.env);
1865
1877
  const actors = input.actors?.() ?? (input.actor ? [input.actor] : []);
1866
1878
  for (const plugin of loaded) {
1867
1879
  const pluginName = plugin.manifest.name;
@@ -1881,7 +1893,7 @@ function createPluginHookRunner(input = {}) {
1881
1893
  },
1882
1894
  env: {
1883
1895
  get(key) {
1884
- return env[key];
1896
+ return env[key] ?? normalizeEnv(nextInput.env)[key];
1885
1897
  },
1886
1898
  set(key, value) {
1887
1899
  env[key] = value;
@@ -1906,14 +1918,10 @@ function createPluginHookRunner(input = {}) {
1906
1918
  );
1907
1919
  }
1908
1920
  nextInput = { ...replacement };
1909
- Object.assign(env, normalizeEnv(nextInput.env));
1910
1921
  }
1911
1922
  }
1912
1923
  return {
1913
- input: {
1914
- ...nextInput,
1915
- ...Object.keys(env).length > 0 ? { env } : {}
1916
- },
1924
+ input: nextInput,
1917
1925
  env
1918
1926
  };
1919
1927
  }