@sentry/junior 0.27.2 → 0.28.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.
package/dist/app.js CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  sandboxSkillDir,
26
26
  sandboxSkillFile,
27
27
  toOptionalTrimmed
28
- } from "./chunk-4PVJHUEV.js";
28
+ } from "./chunk-375D5V4U.js";
29
29
  import {
30
30
  CredentialUnavailableError,
31
31
  buildOAuthTokenRequest,
@@ -2174,7 +2174,8 @@ async function completeText(params) {
2174
2174
  "gen_ai.request.model": params.modelId,
2175
2175
  ...systemInstructionsAttribute ? { "gen_ai.system_instructions": systemInstructionsAttribute } : {},
2176
2176
  ...requestMessagesAttribute ? { "gen_ai.input.messages": requestMessagesAttribute } : {},
2177
- "app.ai.auth_mode": apiKey ? "oidc" : "api_key"
2177
+ "app.ai.auth_mode": apiKey ? "oidc" : "api_key",
2178
+ ...params.thinkingLevel ? { "app.ai.reasoning_effort": params.thinkingLevel } : {}
2178
2179
  };
2179
2180
  setSpanAttributes(startAttributes);
2180
2181
  const message = await completeSimple(
@@ -2187,6 +2188,7 @@ async function completeText(params) {
2187
2188
  ...apiKey ? { apiKey } : {},
2188
2189
  temperature: params.temperature,
2189
2190
  maxTokens: params.maxTokens,
2191
+ reasoning: params.thinkingLevel,
2190
2192
  signal: params.signal,
2191
2193
  metadata: params.metadata
2192
2194
  }
@@ -2205,7 +2207,8 @@ async function completeText(params) {
2205
2207
  "gen_ai.request.model": params.modelId,
2206
2208
  ...outputMessagesAttribute ? { "gen_ai.output.messages": outputMessagesAttribute } : {},
2207
2209
  ...usageAttributes,
2208
- ...message.stopReason ? { "gen_ai.response.finish_reasons": [message.stopReason] } : {}
2210
+ ...message.stopReason ? { "gen_ai.response.finish_reasons": [message.stopReason] } : {},
2211
+ ...params.thinkingLevel ? { "app.ai.reasoning_effort": params.thinkingLevel } : {}
2209
2212
  };
2210
2213
  setSpanAttributes(endAttributes);
2211
2214
  if (message.stopReason === "error") {
@@ -2235,6 +2238,7 @@ async function completeObject(params) {
2235
2238
  ({ text } = await completeText({
2236
2239
  modelId: params.modelId,
2237
2240
  system: params.system,
2241
+ thinkingLevel: params.thinkingLevel,
2238
2242
  temperature: params.temperature,
2239
2243
  maxTokens: params.maxTokens,
2240
2244
  signal: params.signal,
@@ -3354,7 +3358,6 @@ function buildSystemPrompt(params) {
3354
3358
  [
3355
3359
  "- For factual or external questions, run tools/skills first, then answer from evidence.",
3356
3360
  "- Use tool descriptions as the source of truth for when each tool should or should not be called.",
3357
- "- Use `reportProgress` only for sparse, meaningful progress updates. Pass a short user-facing status message, and do not call it for every tool or small substep.",
3358
3361
  "- When using CLI tools through `bash`, prefer deterministic non-interactive flags and avoid commands that wait for prompts or editors.",
3359
3362
  "- Keep routine setup and research steps silent in user-facing replies. Do not narrate duplicate checks, credential issuance, file writes, or similar internal progress unless the result is user-relevant.",
3360
3363
  "- If a routine prerequisite check finds nothing notable, omit it entirely from the final reply and report only the user-relevant outcome.",
@@ -5068,7 +5071,7 @@ function createReadFileTool() {
5068
5071
  import { Type as Type6 } from "@sinclair/typebox";
5069
5072
  function createReportProgressTool() {
5070
5073
  return tool({
5071
- description: "Update assistant status with a short user-facing progress message. Use this sparingly for meaningful progress changes, not for every tool call or minor substep.",
5074
+ description: "Update the user-visible assistant loading message with a short progress phase. For every non-trivial turn, call this early with the initial major work phase, then call it again only when the major phase meaningfully changes. Use concrete labels like Searching docs, Reviewing results, or Running checks. Skip trivial direct answers, generic filler, and minor substeps.",
5072
5075
  inputSchema: Type6.Object({
5073
5076
  message: Type6.String({
5074
5077
  minLength: 1,
@@ -5346,7 +5349,7 @@ function createOperationKey(toolName, input) {
5346
5349
  // src/chat/tools/slack/channel-post-message.ts
5347
5350
  function createSlackChannelPostMessageTool(context, state) {
5348
5351
  return tool({
5349
- description: "Post a message in the active Slack channel context (outside the thread). Use this when the user explicitly asks to post/send/share/say something in the channel. Do not use for normal thread replies or speculative broadcasts. Do not claim a channel message was posted unless this tool succeeds in this turn.",
5352
+ description: "Post a message in the active Slack channel context (outside the thread). Use this only when the user explicitly asks to post/send/share/say something in the current channel. Do not use it for normal thread replies, speculative broadcasts, or requests targeting another named channel; explain that limitation instead. Do not claim a channel message was posted unless this tool succeeds in this turn.",
5350
5353
  inputSchema: Type9.Object({
5351
5354
  text: Type9.String({
5352
5355
  minLength: 1,
@@ -8715,7 +8718,7 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, trac
8715
8718
  }
8716
8719
 
8717
8720
  // src/chat/tools/agent-tools.ts
8718
- function createAgentTools(tools, sandbox, spanContext, onStatus, sandboxExecutor, capabilityRuntime, pluginAuthOrchestration, hooks) {
8721
+ function createAgentTools(tools, sandbox, spanContext, onStatus, sandboxExecutor, capabilityRuntime, pluginAuthOrchestration, onToolCall) {
8719
8722
  const shouldTrace = shouldEmitDevAgentTrace();
8720
8723
  return Object.entries(tools).map(([toolName, toolDef]) => ({
8721
8724
  name: toolName,
@@ -8725,7 +8728,7 @@ function createAgentTools(tools, sandbox, spanContext, onStatus, sandboxExecutor
8725
8728
  execute: async (toolCallId, params) => {
8726
8729
  const normalizedToolCallId = typeof toolCallId === "string" && toolCallId.length > 0 ? toolCallId : void 0;
8727
8730
  const toolArgumentsAttribute = serializeGenAiAttribute(params);
8728
- hooks?.onToolCall?.(toolName);
8731
+ onToolCall?.(toolName);
8729
8732
  const traceToolContext = {
8730
8733
  ...spanContext,
8731
8734
  conversationId: spanContext.conversationId,
@@ -9139,6 +9142,7 @@ function buildTurnResult(input) {
9139
9142
  shouldTrace,
9140
9143
  spanContext,
9141
9144
  usage,
9145
+ thinkingSelection,
9142
9146
  correlation,
9143
9147
  assistantUserName
9144
9148
  } = input;
@@ -9214,6 +9218,7 @@ function buildTurnResult(input) {
9214
9218
  outcome: resolvedOutcome,
9215
9219
  modelId: botConfig.modelId,
9216
9220
  assistantMessageCount: assistantMessages.length,
9221
+ thinkingLevel: thinkingSelection.thinkingLevel,
9217
9222
  toolCalls,
9218
9223
  toolResultCount: toolResults.length,
9219
9224
  toolErrorCount,
@@ -9236,6 +9241,120 @@ function buildTurnResult(input) {
9236
9241
  };
9237
9242
  }
9238
9243
 
9244
+ // src/chat/services/turn-thinking-level.ts
9245
+ import { z } from "zod";
9246
+ var CLASSIFIER_CONFIDENCE_THRESHOLD = 0.75;
9247
+ var MAX_ROUTER_CONTEXT_CHARS = 1200;
9248
+ var TURN_THINKING_LEVELS = ["none", "low", "medium", "high"];
9249
+ var turnExecutionProfileSchema = z.object({
9250
+ thinking_level: z.enum(TURN_THINKING_LEVELS),
9251
+ confidence: z.number().min(0).max(1),
9252
+ reason: z.string().min(1)
9253
+ });
9254
+ var DEFAULT_THINKING_LEVEL = "low";
9255
+ function trimContextForRouter(text) {
9256
+ const trimmed = text?.trim();
9257
+ if (!trimmed) {
9258
+ return void 0;
9259
+ }
9260
+ return trimmed.length <= MAX_ROUTER_CONTEXT_CHARS ? trimmed : trimmed.slice(-MAX_ROUTER_CONTEXT_CHARS);
9261
+ }
9262
+ function buildClassifierSystemPrompt() {
9263
+ return [
9264
+ "You route assistant turns to the cheapest thinking level that is still likely to succeed.",
9265
+ "Choose exactly one bucket: none, low, medium, or high.",
9266
+ "",
9267
+ "Use none for greetings, acknowledgments, and trivial single-step asks.",
9268
+ "Use low for straightforward explanations or simple one-step work.",
9269
+ "Use medium for investigations, ambiguous asks, multi-step analysis, or likely multi-tool work.",
9270
+ "Use high for code changes, debugging/root-cause analysis, research-heavy work, non-trivial drafting, or explicit requests to be thorough.",
9271
+ "",
9272
+ "Return JSON only with thinking_level, confidence, and reason."
9273
+ ].join("\n");
9274
+ }
9275
+ function buildClassifierPrompt(args) {
9276
+ const sections = [];
9277
+ const context = trimContextForRouter(args.conversationContext);
9278
+ if (context) {
9279
+ sections.push("<thread-background>", context, "</thread-background>", "");
9280
+ }
9281
+ sections.push(
9282
+ "<turn-context>",
9283
+ `- active_skills: ${args.activeSkillNames.join(", ") || "none"}`,
9284
+ `- attachment_count: ${args.attachmentCount}`,
9285
+ "</turn-context>",
9286
+ "",
9287
+ '<current-instruction priority="highest">',
9288
+ args.messageText.trim() || "[empty]",
9289
+ "</current-instruction>"
9290
+ );
9291
+ for (const block of args.currentTurnBlocks ?? []) {
9292
+ const trimmed = block.trim();
9293
+ if (!trimmed) {
9294
+ continue;
9295
+ }
9296
+ sections.push("", trimmed);
9297
+ }
9298
+ return sections.join("\n");
9299
+ }
9300
+ async function selectTurnThinkingLevel(args) {
9301
+ const activeSkillNames = [...new Set(args.activeSkillNames ?? [])].sort();
9302
+ try {
9303
+ const result = await args.completeObject({
9304
+ modelId: args.fastModelId,
9305
+ schema: turnExecutionProfileSchema,
9306
+ maxTokens: 120,
9307
+ metadata: {
9308
+ modelId: args.fastModelId,
9309
+ threadId: args.context?.threadId ?? "",
9310
+ channelId: args.context?.channelId ?? "",
9311
+ requesterId: args.context?.requesterId ?? "",
9312
+ runId: args.context?.runId ?? ""
9313
+ },
9314
+ prompt: buildClassifierPrompt({
9315
+ activeSkillNames,
9316
+ attachmentCount: args.attachmentCount ?? 0,
9317
+ conversationContext: args.conversationContext,
9318
+ currentTurnBlocks: args.currentTurnBlocks,
9319
+ messageText: args.messageText
9320
+ }),
9321
+ thinkingLevel: "low",
9322
+ system: buildClassifierSystemPrompt(),
9323
+ temperature: 0
9324
+ });
9325
+ const parsed = turnExecutionProfileSchema.parse(result.object);
9326
+ if (parsed.confidence < CLASSIFIER_CONFIDENCE_THRESHOLD) {
9327
+ return {
9328
+ confidence: parsed.confidence,
9329
+ thinkingLevel: DEFAULT_THINKING_LEVEL,
9330
+ reason: `low_confidence_default:${parsed.reason.trim()}`
9331
+ };
9332
+ }
9333
+ return {
9334
+ confidence: parsed.confidence,
9335
+ thinkingLevel: parsed.thinking_level,
9336
+ reason: parsed.reason.trim()
9337
+ };
9338
+ } catch {
9339
+ return {
9340
+ thinkingLevel: DEFAULT_THINKING_LEVEL,
9341
+ reason: "classifier_error_default"
9342
+ };
9343
+ }
9344
+ }
9345
+ function toAgentThinkingLevel(level) {
9346
+ switch (level) {
9347
+ case "none":
9348
+ return "off";
9349
+ case "low":
9350
+ return "low";
9351
+ case "medium":
9352
+ return "medium";
9353
+ case "high":
9354
+ return "high";
9355
+ }
9356
+ }
9357
+
9239
9358
  // src/chat/state/turn-session-store.ts
9240
9359
  var AGENT_TURN_SESSION_PREFIX = "junior:agent_turn_session";
9241
9360
  var AGENT_TURN_SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -9513,6 +9632,7 @@ function createMcpAuthOrchestration(deps, abortAgent) {
9513
9632
 
9514
9633
  // src/chat/respond.ts
9515
9634
  var startupDiscoveryLogged = false;
9635
+ var MAX_ROUTER_ATTACHMENT_PREVIEW_CHARS = 2e3;
9516
9636
  function buildOmittedImageAttachmentNotice(count) {
9517
9637
  return [
9518
9638
  "<omitted-image-attachments>",
@@ -9523,6 +9643,89 @@ function buildOmittedImageAttachmentNotice(count) {
9523
9643
  "</omitted-image-attachments>"
9524
9644
  ].join("\n");
9525
9645
  }
9646
+ function trimRouterAttachmentText(text) {
9647
+ const normalized = text.replaceAll("\0", " ").trim();
9648
+ if (!normalized) {
9649
+ return "";
9650
+ }
9651
+ return normalized.length <= MAX_ROUTER_ATTACHMENT_PREVIEW_CHARS ? normalized : `${normalized.slice(0, MAX_ROUTER_ATTACHMENT_PREVIEW_CHARS)}...`;
9652
+ }
9653
+ function supportsRouterTextPreview(mediaType) {
9654
+ const baseMediaType = mediaType.split(";", 1)[0]?.trim().toLowerCase();
9655
+ if (!baseMediaType) {
9656
+ return false;
9657
+ }
9658
+ return baseMediaType.startsWith("text/") || baseMediaType === "application/json" || baseMediaType === "application/xml" || baseMediaType === "application/x-www-form-urlencoded" || baseMediaType.endsWith("+json") || baseMediaType.endsWith("+xml");
9659
+ }
9660
+ function buildRouterAttachmentBlock(attachment) {
9661
+ if (attachment.promptText) {
9662
+ return trimRouterAttachmentText(attachment.promptText);
9663
+ }
9664
+ const header = [
9665
+ "<attachment>",
9666
+ `filename: ${attachment.filename ?? "unnamed"}`,
9667
+ `media_type: ${attachment.mediaType}`
9668
+ ];
9669
+ if (attachment.data && supportsRouterTextPreview(attachment.mediaType)) {
9670
+ const preview = trimRouterAttachmentText(attachment.data.toString("utf8"));
9671
+ if (preview) {
9672
+ return [
9673
+ ...header,
9674
+ "<text-preview>",
9675
+ preview,
9676
+ "</text-preview>",
9677
+ "</attachment>"
9678
+ ].join("\n");
9679
+ }
9680
+ }
9681
+ return [...header, "</attachment>"].join("\n");
9682
+ }
9683
+ function buildUserTurnInput(args) {
9684
+ const routerBlocks = [];
9685
+ const userContentParts = [
9686
+ { type: "text", text: args.userTurnText }
9687
+ ];
9688
+ if (args.omittedImageAttachmentCount > 0) {
9689
+ const omittedImagesNotice = buildOmittedImageAttachmentNotice(
9690
+ args.omittedImageAttachmentCount
9691
+ );
9692
+ userContentParts.push({ type: "text", text: omittedImagesNotice });
9693
+ routerBlocks.push(omittedImagesNotice);
9694
+ }
9695
+ for (const attachment of args.userAttachments ?? []) {
9696
+ routerBlocks.push(buildRouterAttachmentBlock(attachment));
9697
+ if (attachment.promptText) {
9698
+ userContentParts.push({
9699
+ type: "text",
9700
+ text: attachment.promptText
9701
+ });
9702
+ continue;
9703
+ }
9704
+ if (attachment.mediaType.startsWith("image/")) {
9705
+ if (!attachment.data) {
9706
+ throw new Error("Image attachment is missing image data");
9707
+ }
9708
+ userContentParts.push({
9709
+ type: "image",
9710
+ data: attachment.data.toString("base64"),
9711
+ mimeType: attachment.mediaType
9712
+ });
9713
+ continue;
9714
+ }
9715
+ if (!attachment.data) {
9716
+ throw new Error("Attachment is missing attachment data");
9717
+ }
9718
+ userContentParts.push({
9719
+ type: "text",
9720
+ text: encodeNonImageAttachmentForPrompt({
9721
+ data: attachment.data,
9722
+ mediaType: attachment.mediaType,
9723
+ filename: attachment.filename
9724
+ })
9725
+ });
9726
+ }
9727
+ return { routerBlocks, userContentParts };
9728
+ }
9526
9729
  function mcpToolsToDefinitions(mcpTools) {
9527
9730
  const defs = {};
9528
9731
  for (const tool2 of mcpTools) {
@@ -9550,6 +9753,7 @@ async function generateAssistantReply(messageText, context = {}) {
9550
9753
  let sandboxExecutor;
9551
9754
  let timedOut = false;
9552
9755
  let turnUsage;
9756
+ let thinkingSelection;
9553
9757
  const getSandboxMetadata = () => sandboxExecutor ? {
9554
9758
  sandboxId: sandboxExecutor.getSandboxId(),
9555
9759
  sandboxDependencyProfileHash: sandboxExecutor.getDependencyProfileHash()
@@ -9728,6 +9932,34 @@ async function generateAssistantReply(messageText, context = {}) {
9728
9932
  turnContext: { traceId: getActiveTraceId() }
9729
9933
  }
9730
9934
  );
9935
+ const { routerBlocks, userContentParts } = buildUserTurnInput({
9936
+ omittedImageAttachmentCount: context.omittedImageAttachmentCount ?? 0,
9937
+ userAttachments: context.userAttachments,
9938
+ userTurnText
9939
+ });
9940
+ thinkingSelection = await selectTurnThinkingLevel({
9941
+ activeSkillNames: activeSkills.map((skill) => skill.name),
9942
+ attachmentCount: context.userAttachments?.length,
9943
+ completeObject,
9944
+ conversationContext: context.conversationContext,
9945
+ context: {
9946
+ threadId: context.correlation?.threadId,
9947
+ channelId: context.correlation?.channelId,
9948
+ requesterId: context.correlation?.requesterId,
9949
+ runId: context.correlation?.runId
9950
+ },
9951
+ currentTurnBlocks: routerBlocks,
9952
+ fastModelId: botConfig.fastModelId,
9953
+ messageText: userInput
9954
+ });
9955
+ setSpanAttributes({
9956
+ "gen_ai.request.model": botConfig.modelId,
9957
+ "app.ai.reasoning_effort": thinkingSelection.thinkingLevel,
9958
+ "app.ai.thinking_level_reason": thinkingSelection.reason,
9959
+ ...thinkingSelection.confidence !== void 0 ? {
9960
+ "app.ai.thinking_level_confidence": thinkingSelection.confidence
9961
+ } : {}
9962
+ });
9731
9963
  timeoutResumeMessages = [];
9732
9964
  const generatedFiles = [];
9733
9965
  const replyFiles = [];
@@ -9889,44 +10121,6 @@ async function generateAssistantReply(messageText, context = {}) {
9889
10121
  runtimeMetadata: getRuntimeMetadata(),
9890
10122
  threadParticipants: context.threadParticipants
9891
10123
  });
9892
- const userContentParts = [{ type: "text", text: userTurnText }];
9893
- const omittedImageAttachmentCount = context.omittedImageAttachmentCount ?? 0;
9894
- if (omittedImageAttachmentCount > 0) {
9895
- userContentParts.push({
9896
- type: "text",
9897
- text: buildOmittedImageAttachmentNotice(omittedImageAttachmentCount)
9898
- });
9899
- }
9900
- for (const attachment of context.userAttachments ?? []) {
9901
- if (attachment.promptText) {
9902
- userContentParts.push({
9903
- type: "text",
9904
- text: attachment.promptText
9905
- });
9906
- } else if (attachment.mediaType.startsWith("image/")) {
9907
- if (!attachment.data) {
9908
- throw new Error("Image attachment is missing image data");
9909
- }
9910
- userContentParts.push({
9911
- type: "image",
9912
- data: attachment.data.toString("base64"),
9913
- mimeType: attachment.mediaType
9914
- });
9915
- } else {
9916
- if (!attachment.data) {
9917
- throw new Error("Attachment is missing attachment data");
9918
- }
9919
- const promptAttachment = {
9920
- data: attachment.data,
9921
- mediaType: attachment.mediaType,
9922
- filename: attachment.filename
9923
- };
9924
- userContentParts.push({
9925
- type: "text",
9926
- text: encodeNonImageAttachmentForPrompt(promptAttachment)
9927
- });
9928
- }
9929
- }
9930
10124
  const inputMessagesAttribute = serializeGenAiAttribute([
9931
10125
  {
9932
10126
  role: "system",
@@ -9937,21 +10131,8 @@ async function generateAssistantReply(messageText, context = {}) {
9937
10131
  content: userContentParts.map((part) => toObservablePromptPart(part))
9938
10132
  }
9939
10133
  ]);
9940
- const agentToolHooks = {
9941
- onToolCall: (toolName) => {
9942
- toolCalls.push(toolName);
9943
- Promise.resolve(context.onToolCall?.(toolName)).catch((error) => {
9944
- logWarn(
9945
- "streaming_tool_call_error",
9946
- {},
9947
- {
9948
- "error.message": error instanceof Error ? error.message : String(error),
9949
- "gen_ai.tool.name": toolName
9950
- },
9951
- "Failed to deliver tool call event to stream coordinator"
9952
- );
9953
- });
9954
- }
10134
+ const onToolCall = (toolName) => {
10135
+ toolCalls.push(toolName);
9955
10136
  };
9956
10137
  const baseAgentTools = createAgentTools(
9957
10138
  tools,
@@ -9961,7 +10142,7 @@ async function generateAssistantReply(messageText, context = {}) {
9961
10142
  sandboxExecutor,
9962
10143
  capabilityRuntime,
9963
10144
  pluginAuth,
9964
- agentToolHooks
10145
+ onToolCall
9965
10146
  );
9966
10147
  const agentTools = [...baseAgentTools];
9967
10148
  const syncMcpAgentTools = () => {
@@ -9975,7 +10156,7 @@ async function generateAssistantReply(messageText, context = {}) {
9975
10156
  sandboxExecutor,
9976
10157
  capabilityRuntime,
9977
10158
  pluginAuth,
9978
- agentToolHooks
10159
+ onToolCall
9979
10160
  );
9980
10161
  agentTools.length = 0;
9981
10162
  agentTools.push(...baseAgentTools, ...mcpAgentTools);
@@ -9986,6 +10167,7 @@ async function generateAssistantReply(messageText, context = {}) {
9986
10167
  initialState: {
9987
10168
  systemPrompt: baseInstructions,
9988
10169
  model: resolveGatewayModel(botConfig.modelId),
10170
+ thinkingLevel: toAgentThinkingLevel(thinkingSelection.thinkingLevel),
9989
10171
  tools: agentTools
9990
10172
  }
9991
10173
  });
@@ -10073,6 +10255,9 @@ async function generateAssistantReply(messageText, context = {}) {
10073
10255
  "gen_ai.provider.name": GEN_AI_PROVIDER_NAME,
10074
10256
  "gen_ai.operation.name": "invoke_agent",
10075
10257
  "gen_ai.request.model": botConfig.modelId,
10258
+ ...thinkingSelection ? {
10259
+ "app.ai.reasoning_effort": thinkingSelection.thinkingLevel
10260
+ } : {},
10076
10261
  "app.ai.turn_timeout_ms": botConfig.turnTimeoutMs
10077
10262
  },
10078
10263
  "Agent turn timed out and was aborted"
@@ -10117,6 +10302,7 @@ async function generateAssistantReply(messageText, context = {}) {
10117
10302
  "gen_ai.provider.name": GEN_AI_PROVIDER_NAME,
10118
10303
  "gen_ai.operation.name": "invoke_agent",
10119
10304
  "gen_ai.request.model": botConfig.modelId,
10305
+ "app.ai.reasoning_effort": thinkingSelection.thinkingLevel,
10120
10306
  ...inputMessagesAttribute ? { "gen_ai.input.messages": inputMessagesAttribute } : {}
10121
10307
  }
10122
10308
  );
@@ -10148,6 +10334,7 @@ async function generateAssistantReply(messageText, context = {}) {
10148
10334
  shouldTrace,
10149
10335
  spanContext,
10150
10336
  usage: turnUsage,
10337
+ thinkingSelection,
10151
10338
  correlation: context.correlation,
10152
10339
  assistantUserName: context.assistant?.userName
10153
10340
  });
@@ -10234,6 +10421,9 @@ async function generateAssistantReply(messageText, context = {}) {
10234
10421
  outcome: "provider_error",
10235
10422
  modelId: botConfig.modelId,
10236
10423
  assistantMessageCount: 0,
10424
+ ...thinkingSelection ? {
10425
+ thinkingLevel: thinkingSelection.thinkingLevel
10426
+ } : {},
10237
10427
  toolCalls: [],
10238
10428
  toolResultCount: 0,
10239
10429
  toolErrorCount: 0,
@@ -12296,14 +12486,14 @@ async function POST(request, waitUntil) {
12296
12486
  }
12297
12487
 
12298
12488
  // src/chat/services/subscribed-decision.ts
12299
- import { z } from "zod";
12300
- var replyDecisionSchema = z.object({
12301
- should_reply: z.boolean().describe("Whether Junior should respond to this thread message."),
12302
- should_unsubscribe: z.boolean().optional().describe(
12489
+ import { z as z2 } from "zod";
12490
+ var replyDecisionSchema = z2.object({
12491
+ should_reply: z2.boolean().describe("Whether Junior should respond to this thread message."),
12492
+ should_unsubscribe: z2.boolean().optional().describe(
12303
12493
  "Whether Junior should unsubscribe from this thread because the user clearly asked it to stop participating."
12304
12494
  ),
12305
- confidence: z.number().min(0).max(1).describe("Classifier confidence from 0 to 1."),
12306
- reason: z.string().optional().describe("Short reason for the decision.")
12495
+ confidence: z2.number().min(0).max(1).describe("Classifier confidence from 0 to 1."),
12496
+ reason: z2.string().optional().describe("Short reason for the decision.")
12307
12497
  });
12308
12498
  var ROUTER_CONFIDENCE_THRESHOLD = 0.8;
12309
12499
  var LEADING_SLACK_MENTION_RE = /^\s*<@([A-Z0-9]+)(?:\|([^>]+))?>[\s,:-]*/i;
@@ -13993,7 +14183,7 @@ function createReplyToThread(deps) {
13993
14183
  slackChannelId: channelId,
13994
14184
  runId,
13995
14185
  assistantUserName: botConfig.userName,
13996
- modelId: botConfig.modelId
14186
+ modelId: reply.diagnostics.modelId
13997
14187
  };
13998
14188
  const diagnosticsAttributes = {
13999
14189
  "gen_ai.provider.name": GEN_AI_PROVIDER_NAME,
@@ -14004,6 +14194,9 @@ function createReplyToThread(deps) {
14004
14194
  "app.ai.tool_error_results": reply.diagnostics.toolErrorCount,
14005
14195
  "app.ai.tool_call_count": reply.diagnostics.toolCalls.length,
14006
14196
  "app.ai.used_primary_text": reply.diagnostics.usedPrimaryText,
14197
+ ...reply.diagnostics.thinkingLevel ? {
14198
+ "app.ai.reasoning_effort": reply.diagnostics.thinkingLevel
14199
+ } : {},
14007
14200
  ...reply.diagnostics.stopReason ? {
14008
14201
  "gen_ai.response.finish_reasons": [
14009
14202
  reply.diagnostics.stopReason
@@ -84,8 +84,8 @@ function readBotConfig(env) {
84
84
  const maxTurnTimeoutMs = resolveMaxTurnTimeoutMs(functionMaxDurationSeconds);
85
85
  return {
86
86
  userName: env.JUNIOR_BOT_NAME ?? "junior",
87
- modelId: env.AI_MODEL ?? "anthropic/claude-sonnet-4.6",
88
- fastModelId: env.AI_FAST_MODEL ?? env.AI_MODEL ?? "anthropic/claude-haiku-4.5",
87
+ modelId: env.AI_MODEL ?? "openai/gpt-5.4",
88
+ fastModelId: env.AI_FAST_MODEL ?? env.AI_MODEL ?? "openai/gpt-5.4-mini",
89
89
  loadingMessages: parseLoadingMessages(env.JUNIOR_LOADING_MESSAGES),
90
90
  visionModelId: toOptionalTrimmed(env.AI_VISION_MODEL),
91
91
  turnTimeoutMs: parseAgentTurnTimeoutMs(
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  disconnectStateAdapter,
3
3
  resolveRuntimeDependencySnapshot
4
- } from "../chunk-4PVJHUEV.js";
4
+ } from "../chunk-375D5V4U.js";
5
5
  import {
6
6
  getPluginProviders,
7
7
  getPluginRuntimeDependencies,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior",
3
- "version": "0.27.2",
3
+ "version": "0.28.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"