@sentry/junior 0.86.0 → 0.87.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
@@ -17,7 +17,6 @@ import {
17
17
  createConversationMemoryService,
18
18
  createUserTokenStore,
19
19
  deleteMcpAuthSession,
20
- deleteSlackMessage,
21
20
  deliverResourceEventSubscription,
22
21
  estimateTextTokens,
23
22
  executeCredentialedEgressRequest,
@@ -42,7 +41,6 @@ import {
42
41
  isCooperativeTurnYieldError,
43
42
  isHumanConversationMessage,
44
43
  isPendingAuthLatestRequest,
45
- isRedundantReactionAckText,
46
44
  isRetryableTurnError,
47
45
  isTurnInputCommitLostError,
48
46
  isTurnInputDeferredError,
@@ -77,7 +75,7 @@ import {
77
75
  updateConversationStats,
78
76
  uploadFilesToThread,
79
77
  upsertConversationMessage
80
- } from "./chunk-FPHA6GCQ.js";
78
+ } from "./chunk-B6FQPS7A.js";
81
79
  import {
82
80
  CONVERSATION_WORK_CHECK_IN_INTERVAL_MS,
83
81
  CONVERSATION_WORK_STALE_ENQUEUE_MS,
@@ -139,7 +137,7 @@ import {
139
137
  recordAuthorizationCompleted,
140
138
  splitSlackReplyText,
141
139
  truncateStatusText
142
- } from "./chunk-37B2R2QJ.js";
140
+ } from "./chunk-ACJJJEGG.js";
143
141
  import {
144
142
  validatePluginEgressCredentialHooks,
145
143
  validatePluginRegistrations
@@ -10054,16 +10052,12 @@ function createReplyToThread(deps) {
10054
10052
  });
10055
10053
  }
10056
10054
  const artifactStatePatch = reply.artifactStatePatch ? { ...reply.artifactStatePatch } : {};
10057
- const reactionPerformed = reply.diagnostics.toolCalls.includes(
10058
- "slackMessageAddReaction"
10059
- );
10060
10055
  const plannedPosts = planSlackReplyPosts({ reply });
10061
10056
  const replyFooter = buildSlackReplyFooter({
10062
10057
  conversationId
10063
10058
  });
10064
10059
  const shouldUseSlackFooter = Boolean(replyFooter) && Boolean(channelId && threadTs) && thread.adapter?.name === "slack";
10065
10060
  if (plannedPosts.length > 0) {
10066
- let sent;
10067
10061
  const hasVisibleDelivery = plannedPosts.some(
10068
10062
  hasVisibleSlackDelivery
10069
10063
  );
@@ -10080,7 +10074,7 @@ function createReplyToThread(deps) {
10080
10074
  "Slack footer delivery requires a concrete channel and thread timestamp"
10081
10075
  );
10082
10076
  }
10083
- const sentMessageTs = await postSlackApiReplyPosts({
10077
+ await postSlackApiReplyPosts({
10084
10078
  beforePost: beforeFirstResponsePost,
10085
10079
  channelId: slackChannelId,
10086
10080
  threadTs: slackThreadTs,
@@ -10101,24 +10095,12 @@ function createReplyToThread(deps) {
10101
10095
  );
10102
10096
  }
10103
10097
  });
10104
- if (sentMessageTs) {
10105
- sent = {
10106
- id: sentMessageTs,
10107
- text: reply.text,
10108
- delete: async () => {
10109
- await deleteSlackMessage({
10110
- channelId: slackChannelId,
10111
- timestamp: sentMessageTs
10112
- });
10113
- }
10114
- };
10115
- }
10116
10098
  } else {
10117
10099
  for (const post of plannedPosts) {
10118
10100
  if (!hasVisibleSlackDelivery(post)) {
10119
10101
  continue;
10120
10102
  }
10121
- sent = await postThreadReply(
10103
+ await postThreadReply(
10122
10104
  buildSlackOutputMessage(post.text, post.files),
10123
10105
  post.stage
10124
10106
  );
@@ -10126,20 +10108,6 @@ function createReplyToThread(deps) {
10126
10108
  }
10127
10109
  finalReplyDelivered = true;
10128
10110
  shouldPersistFailureState = false;
10129
- const firstPlannedMessageHasFiles = (plannedPosts[0]?.files?.length ?? 0) > 0;
10130
- if (sent && reactionPerformed && plannedPosts.length === 1 && !firstPlannedMessageHasFiles && isRedundantReactionAckText(reply.text)) {
10131
- try {
10132
- await sent.delete();
10133
- } catch (error) {
10134
- logException(
10135
- error,
10136
- "slack_redundant_ack_delete_failed",
10137
- turnTraceContext,
10138
- messageTs ? { "messaging.message.id": messageTs } : {},
10139
- "Failed to delete redundant reaction-ack reply"
10140
- );
10141
- }
10142
- }
10143
10111
  } else {
10144
10112
  finalReplyDelivered = true;
10145
10113
  shouldPersistFailureState = false;
@@ -0,0 +1,7 @@
1
+ export declare const NO_REPLY_MARKER = "[[NO_REPLY]]";
2
+ /** Detect the reserved marker so Slack side effects can intentionally complete without thread text. */
3
+ export declare function isNoReplyMarker(text: string): boolean;
4
+ /** Detect marker leaks before publication strips or rejects them. */
5
+ export declare function containsNoReplyMarker(text: string): boolean;
6
+ /** Remove the reserved marker from mixed assistant text so it is never shown to users. */
7
+ export declare function stripNoReplyMarker(text: string): string;
@@ -5,10 +5,6 @@ export interface ReplyDeliveryPlan {
5
5
  postThreadText: boolean;
6
6
  attachFiles: ReplyFileDelivery;
7
7
  }
8
- /** Check if text is a short acknowledgment (emoji, "ok", etc.) that a reaction already covers. */
9
- export declare function isRedundantReactionAckText(text: string): boolean;
10
- /** Check if the user asked for a reaction without also asking for text. */
11
- export declare function isReactionOnlyIntent(text: string): boolean;
12
8
  /** Determine how a reply should be delivered (thread vs channel, file handling). */
13
9
  export declare function buildReplyDeliveryPlan(args: {
14
10
  explicitChannelPostIntent: boolean;
@@ -669,6 +669,18 @@ function getInterruptionMarker() {
669
669
  import fs from "fs";
670
670
  import path from "path";
671
671
 
672
+ // src/chat/no-reply.ts
673
+ var NO_REPLY_MARKER = "[[NO_REPLY]]";
674
+ function isNoReplyMarker(text) {
675
+ return text.trim() === NO_REPLY_MARKER;
676
+ }
677
+ function containsNoReplyMarker(text) {
678
+ return text.includes(NO_REPLY_MARKER);
679
+ }
680
+ function stripNoReplyMarker(text) {
681
+ return text.replaceAll(NO_REPLY_MARKER, "").trim();
682
+ }
683
+
672
684
  // src/chat/slack/status-format.ts
673
685
  var SLACK_STATUS_MAX_LENGTH = 50;
674
686
  function truncateStatusText(text) {
@@ -1360,12 +1372,10 @@ var CONVERSATION_RULES = [
1360
1372
  "- Runtime owns continuation and authorization notices; on resumed turns, answer with the final requested content only."
1361
1373
  ];
1362
1374
  var SLACK_ACTION_RULES = [
1363
- "- Context-bound Slack tools use runtime-owned targets; do not invent channel, canvas, list, or message IDs.",
1364
- "- Use first-class Slack tools for Slack side effects; do not use bash, curl, or provider APIs to bypass Slack tool targeting.",
1365
- "- Use channel-post and emoji-reaction tools only when the user explicitly asks for that Slack side effect.",
1366
- "- For explicit channel-post or emoji-reaction requests, skip a duplicate thread text reply when the tool result already satisfies the request.",
1367
- "- Do not claim an attachment, canvas, channel post, list update, or reaction succeeded unless the tool returned success this turn; when it did, include any link the tool returned.",
1368
- "- Do not use reactions as progress indicators."
1375
+ "- Slack tools target the current runtime context; if the requested Slack target differs, explain the limitation instead of calling the tool.",
1376
+ "- Use channel-post and emoji-reaction tools only for explicit user-requested Slack side effects.",
1377
+ "- Ambient reaction requests target the current inbound message; do not ask for a message reference.",
1378
+ `- Side-effect-only completion for channel posts or reactions: call the requested tool first; if it succeeds and fully satisfies the request, final message must be exactly ${NO_REPLY_MARKER}.`
1369
1379
  ];
1370
1380
  var SAFETY_RULES = [
1371
1381
  "- Stay within the user's request and the runtime's available capabilities; do not pursue independent goals, persistence, replication, credential gathering, or access expansion.",
@@ -1416,7 +1426,7 @@ function buildOutputSection(platform) {
1416
1426
  "- Use Slack-flavored Markdown: **bold** section labels, `code`, [text](url) links, bullet lists, and fenced code blocks. No hash-prefixed headings and no tables. When the answer primarily lists several URLs, show each URL bare instead of as a labeled link.",
1417
1427
  "- Keep replies brief and scannable; use bullets or short code blocks when helpful, and one compact thread reply when it fits.",
1418
1428
  "- When a research or document-style answer would benefit from continuation, multiple sections, or future reference value, create a Slack canvas and keep the thread reply to one or two short sentences plus the link; do not recap the canvas contents.",
1419
- "- Unless a successful Slack side-effect tool intentionally satisfied the request by itself, end every turn with a final user-facing markdown response.",
1429
+ "- End every turn with a final user-facing markdown response unless the Slack action rules allow a side-effect-only completion.",
1420
1430
  "</output>"
1421
1431
  ].join("\n");
1422
1432
  }
@@ -2185,6 +2195,9 @@ async function failAgentTurnSessionRecord(args) {
2185
2195
  }
2186
2196
 
2187
2197
  export {
2198
+ isNoReplyMarker,
2199
+ containsNoReplyMarker,
2200
+ stripNoReplyMarker,
2188
2201
  getInterruptionMarker,
2189
2202
  truncateStatusText,
2190
2203
  normalizeSlackStatusText,
@@ -22,16 +22,19 @@ import {
22
22
  buildPluginSystemPromptContributions,
23
23
  buildSystemPrompt,
24
24
  buildTurnContextPrompt,
25
+ containsNoReplyMarker,
25
26
  getAgentTurnSessionRecord,
26
27
  getInterruptionMarker,
28
+ isNoReplyMarker,
27
29
  loadConnectedMcpProviders,
28
30
  recordAuthorizationRequested,
29
31
  recordMcpProviderConnected,
30
32
  recordSubagentEnded,
31
33
  recordSubagentStarted,
32
34
  recordToolExecutionStarted,
35
+ stripNoReplyMarker,
33
36
  upsertAgentTurnSessionRecord
34
- } from "./chunk-37B2R2QJ.js";
37
+ } from "./chunk-ACJJJEGG.js";
35
38
  import {
36
39
  createPluginEmbedder,
37
40
  createPluginHookRunner,
@@ -4943,31 +4946,6 @@ async function postSlackMessage(input) {
4943
4946
  } : {}
4944
4947
  };
4945
4948
  }
4946
- async function deleteSlackMessage(input) {
4947
- const channelId = requireSlackConversationId(
4948
- input.channelId,
4949
- "Slack message deletion"
4950
- );
4951
- const timestamp = requireSlackMessageTimestamp(
4952
- input.timestamp,
4953
- "Slack message deletion"
4954
- );
4955
- await withSlackRetries(
4956
- () => getSlackClient().chat.delete({
4957
- channel: channelId,
4958
- ts: timestamp
4959
- }),
4960
- 3,
4961
- {
4962
- action: "chat.delete",
4963
- idempotent: true,
4964
- spanAttributes: {
4965
- "app.slack.channel_id": channelId,
4966
- "app.slack.message_ts": timestamp
4967
- }
4968
- }
4969
- );
4970
- }
4971
4949
  async function postSlackEphemeralMessage(input) {
4972
4950
  const channelId = requireSlackConversationId(
4973
4951
  input.channelId,
@@ -5144,7 +5122,7 @@ function createOperationKey(toolName, input) {
5144
5122
  // src/chat/tools/slack/channel-post-message.ts
5145
5123
  function createSlackChannelPostMessageTool(context, state) {
5146
5124
  return tool({
5147
- description: "Post a new top-level message to the current Slack channel. Use only when the user explicitly asks to post/send/share/say something to the channel. Do not use for thread replies, inline @mentions, or pinging mentioned users.",
5125
+ description: "Post a new top-level message to the current Slack channel. Use only when the user explicitly asks to post/send/share/say something to the current channel. Do not use for other named channels, thread replies, inline @mentions, or pinging mentioned users.",
5148
5126
  inputSchema: Type15.Object({
5149
5127
  text: Type15.String({
5150
5128
  minLength: 1,
@@ -5189,7 +5167,7 @@ function createSlackChannelPostMessageTool(context, state) {
5189
5167
  import { Type as Type16 } from "@sinclair/typebox";
5190
5168
  function createSlackMessageAddReactionTool(context, state) {
5191
5169
  return tool({
5192
- description: "Add an emoji reaction to the current inbound Slack message. Use sparingly for lightweight acknowledgements. Provide a Slack emoji alias name (for example `thumbsup`, `white_check_mark`, or `thumbsup::skin-tone-6`), not a unicode emoji glyph. The target message is injected by runtime context; do not use this for arbitrary historical messages.",
5170
+ description: "Add an emoji reaction to the current inbound Slack message. Use when the user asks for a reaction on the current message without another target. Provide a Slack emoji alias name (for example `thumbsup`, `white_check_mark`, or `thumbsup::skin-tone-6`), not a unicode emoji glyph. The target message is injected by runtime context; do not use this for arbitrary historical messages.",
5193
5171
  inputSchema: Type16.Object({
5194
5172
  emoji: Type16.String({
5195
5173
  minLength: 1,
@@ -5201,17 +5179,15 @@ function createSlackMessageAddReactionTool(context, state) {
5201
5179
  const targetChannelId = context.sourceChannelId;
5202
5180
  const targetMessageTs = context.messageTs;
5203
5181
  if (!targetMessageTs) {
5204
- return {
5205
- ok: false,
5206
- error: "No active message timestamp is available for reactions"
5207
- };
5182
+ throw new ToolInputError(
5183
+ "No active message timestamp is available for reactions."
5184
+ );
5208
5185
  }
5209
5186
  const normalizedEmoji = normalizeSlackEmojiName(emoji);
5210
5187
  if (!normalizedEmoji) {
5211
- return {
5212
- ok: false,
5213
- error: "Emoji must be a valid Slack emoji alias name (for example `thumbsup` or `thumbsup::skin-tone-6`)"
5214
- };
5188
+ throw new ToolInputError(
5189
+ "Emoji must be a valid Slack emoji alias name (for example `thumbsup` or `thumbsup::skin-tone-6`)."
5190
+ );
5215
5191
  }
5216
5192
  const operationKey = createOperationKey("slackMessageAddReaction", {
5217
5193
  channel_id: targetChannelId,
@@ -10955,33 +10931,6 @@ function createAgentTools(tools, sandbox, spanContext, onStatus, sandboxExecutor
10955
10931
  }
10956
10932
 
10957
10933
  // src/chat/services/reply-delivery-plan.ts
10958
- var REACTION_ONLY_ACK_RE = /^(?::[a-z0-9_+-]+:|[\p{Extended_Pictographic}\uFE0F\u200D]+)$/u;
10959
- var REDUNDANT_REACTION_ACK_TEXT = ["done", "got it", "ok", "okay"];
10960
- var REACTION_INTENT_RE = /\b(react|reaction|emoji|thumbs?\s*up|acknowledge)\b/i;
10961
- var REACTION_WITH_REPLY_INTENT_RE = /\b(confirm|explain|reply|respond|say|tell|summari[sz]e|why)\b/i;
10962
- function normalizeReactionAckText(text) {
10963
- return text.trim().toLowerCase().replace(/[!.]+$/g, "");
10964
- }
10965
- function isRedundantReactionAckText(text) {
10966
- const trimmed = text.trim();
10967
- if (!trimmed) {
10968
- return false;
10969
- }
10970
- if (REACTION_ONLY_ACK_RE.test(trimmed)) {
10971
- return true;
10972
- }
10973
- const normalized = normalizeReactionAckText(text);
10974
- return REDUNDANT_REACTION_ACK_TEXT.includes(
10975
- normalized
10976
- );
10977
- }
10978
- function isReactionOnlyIntent(text) {
10979
- const normalized = text.trim();
10980
- if (!normalized) {
10981
- return false;
10982
- }
10983
- return REACTION_INTENT_RE.test(normalized) && !REACTION_WITH_REPLY_INTENT_RE.test(normalized);
10984
- }
10985
10934
  function buildReplyDeliveryPlan(args) {
10986
10935
  const mode = args.explicitChannelPostIntent && args.channelPostPerformed ? "channel_only" : "thread";
10987
10936
  let attachFiles = "none";
@@ -11095,9 +11044,12 @@ function buildTurnResult(input) {
11095
11044
  const toolResults = newMessages.filter(isToolResultMessage);
11096
11045
  const assistantMessages = newMessages.filter(isAssistantMessage);
11097
11046
  const terminalAssistantMessages = getTerminalAssistantMessages(newMessages);
11098
- const primaryText = stripThinkingXmlBlocks(
11047
+ const rawPrimaryText = stripThinkingXmlBlocks(
11099
11048
  terminalAssistantMessages.map((message) => extractAssistantText(message)).join("\n\n")
11100
11049
  ).trim();
11050
+ const exactNoReplyMarker = isNoReplyMarker(rawPrimaryText);
11051
+ const mixedNoReplyMarker = !exactNoReplyMarker && containsNoReplyMarker(rawPrimaryText);
11052
+ const primaryText = exactNoReplyMarker ? "" : mixedNoReplyMarker ? stripNoReplyMarker(rawPrimaryText) : rawPrimaryText;
11101
11053
  const toolErrorCount = toolResults.filter((result) => result.isError).length;
11102
11054
  const explicitChannelPostIntent = isExplicitChannelPostIntent(userInput);
11103
11055
  const successfulToolNames = new Set(
@@ -11108,17 +11060,67 @@ function buildTurnResult(input) {
11108
11060
  );
11109
11061
  const canvasCreated = successfulToolNames.has("slackCanvasCreate");
11110
11062
  const reactionPerformed = successfulToolNames.has("slackMessageAddReaction");
11063
+ const markerSideEffectSuccess = exactNoReplyMarker && toolErrorCount === 0 && (reactionPerformed || channelPostPerformed || replyFiles.length > 0);
11064
+ const fileOnlySuccess = !rawPrimaryText && toolErrorCount === 0 && replyFiles.length > 0;
11065
+ const sideEffectOnlySuccess = markerSideEffectSuccess || fileOnlySuccess;
11111
11066
  const baseDeliveryPlan = buildReplyDeliveryPlan({
11112
- explicitChannelPostIntent,
11067
+ explicitChannelPostIntent: exactNoReplyMarker && explicitChannelPostIntent,
11113
11068
  channelPostPerformed,
11114
11069
  hasFiles: replyFiles.length > 0
11115
11070
  });
11116
- const sideEffectOnlySuccess = !primaryText && toolErrorCount === 0 && (reactionPerformed || channelPostPerformed || replyFiles.length > 0);
11117
11071
  const lastAssistant = terminalAssistantMessages.at(-1);
11118
11072
  const stopReason = typeof lastAssistant?.stopReason === "string" ? lastAssistant.stopReason : void 0;
11119
11073
  const errorMessage = typeof lastAssistant?.errorMessage === "string" ? lastAssistant.errorMessage : void 0;
11120
11074
  const isProviderError = stopReason === "error";
11121
- if (!primaryText && !sideEffectOnlySuccess && !isProviderError) {
11075
+ if (exactNoReplyMarker) {
11076
+ const markerCategory = reactionPerformed ? "reaction" : channelPostPerformed ? "channel_post" : replyFiles.length > 0 ? "file" : "none";
11077
+ const markerContext = {
11078
+ slackThreadId: correlation?.threadId,
11079
+ slackUserId: correlation?.requesterId,
11080
+ slackChannelId: correlation?.channelId,
11081
+ runId: correlation?.runId,
11082
+ assistantUserName,
11083
+ modelId: botConfig.modelId
11084
+ };
11085
+ const markerAttributes = {
11086
+ "app.ai.no_reply_marker": true,
11087
+ "app.ai.no_reply_marker_category": markerCategory,
11088
+ "app.ai.no_reply_marker_accepted": sideEffectOnlySuccess && !isProviderError
11089
+ };
11090
+ if (sideEffectOnlySuccess && !isProviderError) {
11091
+ logInfo(
11092
+ "ai_no_reply_marker_accepted",
11093
+ markerContext,
11094
+ markerAttributes,
11095
+ "No-reply marker suppressed visible thread text"
11096
+ );
11097
+ } else if (!isProviderError) {
11098
+ logWarn(
11099
+ "ai_no_reply_marker_rejected",
11100
+ markerContext,
11101
+ markerAttributes,
11102
+ "No-reply marker requires a successful visible side effect"
11103
+ );
11104
+ }
11105
+ } else if (mixedNoReplyMarker) {
11106
+ logWarn(
11107
+ "ai_no_reply_marker_mixed_text",
11108
+ {
11109
+ slackThreadId: correlation?.threadId,
11110
+ slackUserId: correlation?.requesterId,
11111
+ slackChannelId: correlation?.channelId,
11112
+ runId: correlation?.runId,
11113
+ assistantUserName,
11114
+ modelId: botConfig.modelId
11115
+ },
11116
+ {
11117
+ "app.ai.no_reply_marker": true,
11118
+ "app.ai.no_reply_marker_mode": "mixed"
11119
+ },
11120
+ "No-reply marker appeared with visible assistant text"
11121
+ );
11122
+ }
11123
+ if (!primaryText && !sideEffectOnlySuccess && !isProviderError && !exactNoReplyMarker) {
11122
11124
  logWarn(
11123
11125
  "ai_model_response_empty",
11124
11126
  {
@@ -11137,7 +11139,7 @@ function buildTurnResult(input) {
11137
11139
  "Model returned empty text response"
11138
11140
  );
11139
11141
  }
11140
- const usedPrimaryText = Boolean(primaryText);
11142
+ const usedPrimaryText = Boolean(rawPrimaryText);
11141
11143
  let outcome;
11142
11144
  if (isProviderError) {
11143
11145
  outcome = "provider_error";
@@ -11146,8 +11148,7 @@ function buildTurnResult(input) {
11146
11148
  } else {
11147
11149
  outcome = "execution_failure";
11148
11150
  }
11149
- const suppressReactionOnlyText = reactionPerformed && !channelPostPerformed && replyFiles.length === 0 && Boolean(primaryText) && isReactionOnlyIntent(userInput);
11150
- const rawResponseText = suppressReactionOnlyText ? "" : primaryText;
11151
+ const rawResponseText = primaryText;
11151
11152
  const responseText = canvasCreated && isVerbosePostCanvasReply(rawResponseText) ? buildBriefPostCanvasReply(artifactStatePatch) : rawResponseText;
11152
11153
  const escapedOrRawPayload = Boolean(primaryText) && (isExecutionEscapeResponse(primaryText) || isRawToolPayloadResponse(primaryText));
11153
11154
  const resolvedText = escapedOrRawPayload ? "" : enforceAttachmentClaimTruth(responseText, replyFiles.length > 0);
@@ -14911,6 +14912,7 @@ async function processPluginTask(message, options = {}) {
14911
14912
  }
14912
14913
 
14913
14914
  // src/chat/runtime/delivered-turn-state.ts
14915
+ var NO_VISIBLE_REPLY_CONVERSATION_TEXT = "[no visible reply]";
14914
14916
  function buildDeliveredTurnStatePatch(args) {
14915
14917
  const conversation = structuredClone(args.conversation);
14916
14918
  const artifactStatePatch = {
@@ -14919,6 +14921,7 @@ function buildDeliveredTurnStatePatch(args) {
14919
14921
  };
14920
14922
  const artifacts = Object.keys(artifactStatePatch).length > 0 ? mergeArtifactsState(args.artifacts, artifactStatePatch) : void 0;
14921
14923
  clearPendingAuth(conversation, args.sessionId);
14924
+ const assistantText = normalizeConversationText(args.reply.text) || (args.reply.deliveryPlan?.postThreadText === false ? NO_VISIBLE_REPLY_CONVERSATION_TEXT : "[empty response]");
14922
14925
  markConversationMessage(conversation, args.userMessageId, {
14923
14926
  replied: true,
14924
14927
  skippedReason: void 0
@@ -14926,7 +14929,7 @@ function buildDeliveredTurnStatePatch(args) {
14926
14929
  upsertConversationMessage(conversation, {
14927
14930
  id: generateConversationId("assistant"),
14928
14931
  role: "assistant",
14929
- text: normalizeConversationText(args.reply.text) || "[empty response]",
14932
+ text: assistantText,
14930
14933
  createdAtMs: Date.now(),
14931
14934
  author: {
14932
14935
  userName: botConfig.userName,
@@ -14958,7 +14961,6 @@ export {
14958
14961
  deliverResourceEventSubscription,
14959
14962
  listThreadReplies,
14960
14963
  postSlackMessage,
14961
- deleteSlackMessage,
14962
14964
  uploadFilesToThread,
14963
14965
  addReactionToMessage,
14964
14966
  removeReactionFromMessage,
@@ -15002,7 +15004,6 @@ export {
15002
15004
  startActiveTurn,
15003
15005
  markTurnClosed,
15004
15006
  markTurnFailed,
15005
- isRedundantReactionAckText,
15006
15007
  persistCompletedSessionRecord,
15007
15008
  completeDeliveredTurn,
15008
15009
  persistYieldSessionRecord,
package/dist/cli/chat.js CHANGED
@@ -195,7 +195,7 @@ async function runPrompt(options, io, pluginSet) {
195
195
  defaultStateAdapterForLocalChat();
196
196
  await configureLocalChatPlugins(pluginSet);
197
197
  const conversationId = newRunConversationId();
198
- const { runLocalAgentTurn } = await import("../runner-HEBRPNN2.js");
198
+ const { runLocalAgentTurn } = await import("../runner-DMP3IQNM.js");
199
199
  const result = await runLocalAgentTurn(
200
200
  {
201
201
  conversationId,
@@ -219,7 +219,7 @@ async function runInteractive(io, pluginSet) {
219
219
  defaultStateAdapterForLocalChat();
220
220
  await configureLocalChatPlugins(pluginSet);
221
221
  const conversationId = newRunConversationId();
222
- const { runLocalAgentTurn } = await import("../runner-HEBRPNN2.js");
222
+ const { runLocalAgentTurn } = await import("../runner-DMP3IQNM.js");
223
223
  const rl = readline.createInterface({
224
224
  input: io.input,
225
225
  output: io.output,
package/dist/reporting.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  getAgentTurnSessionRecord,
13
13
  listAgentTurnSessionSummariesForConversation,
14
14
  loadActivityEntries
15
- } from "./chunk-37B2R2QJ.js";
15
+ } from "./chunk-ACJJJEGG.js";
16
16
  import {
17
17
  getPluginOperationalReports
18
18
  } from "./chunk-2NFV5FMB.js";
@@ -16,7 +16,7 @@ import {
16
16
  startActiveTurn,
17
17
  updateConversationStats,
18
18
  upsertConversationMessage
19
- } from "./chunk-FPHA6GCQ.js";
19
+ } from "./chunk-B6FQPS7A.js";
20
20
  import {
21
21
  coerceThreadConversationState
22
22
  } from "./chunk-66NX7MNW.js";
@@ -25,7 +25,7 @@ import "./chunk-KNFROR7R.js";
25
25
  import {
26
26
  commitMessages,
27
27
  loadProjection
28
- } from "./chunk-37B2R2QJ.js";
28
+ } from "./chunk-ACJJJEGG.js";
29
29
  import "./chunk-2NFV5FMB.js";
30
30
  import "./chunk-BRSQQRG6.js";
31
31
  import "./chunk-6I6HBOQM.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior",
3
- "version": "0.86.0",
3
+ "version": "0.87.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -70,7 +70,7 @@
70
70
  "pg": "^8.16.3",
71
71
  "yaml": "^2.9.0",
72
72
  "zod": "^4.4.3",
73
- "@sentry/junior-plugin-api": "0.86.0"
73
+ "@sentry/junior-plugin-api": "0.87.0"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@emnapi/core": "^1.10.0",
@@ -86,10 +86,10 @@
86
86
  "typescript": "^6.0.3",
87
87
  "vercel": "^54.4.0",
88
88
  "vitest": "^4.1.7",
89
- "@sentry/junior-github": "0.86.0",
90
- "@sentry/junior-memory": "0.86.0",
89
+ "@sentry/junior-memory": "0.87.0",
90
+ "@sentry/junior-github": "0.87.0",
91
91
  "@sentry/junior-testing": "0.0.0",
92
- "@sentry/junior-scheduler": "0.86.0"
92
+ "@sentry/junior-scheduler": "0.87.0"
93
93
  },
94
94
  "scripts": {
95
95
  "build": "tsup && tsc -p tsconfig.build.json --emitDeclarationOnly",