@sentry/junior 0.90.0 → 0.91.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
@@ -104,7 +104,7 @@ import {
104
104
  shouldPropagateSandboxEgressTrace,
105
105
  startOAuthFlow,
106
106
  unlinkProvider
107
- } from "./chunk-BKSZL4QO.js";
107
+ } from "./chunk-ZGDTBSQ7.js";
108
108
  import {
109
109
  CooperativeTurnYieldError,
110
110
  TurnInputCommitLostError,
@@ -139,11 +139,13 @@ import {
139
139
  import "./chunk-5GBUZI6M.js";
140
140
  import {
141
141
  buildSlackOutputMessage,
142
+ escapeSlackMrkdwnText,
143
+ formatSlackLink,
142
144
  normalizeSlackStatusText,
143
145
  splitSlackReplyText,
144
146
  truncateStatusText,
145
147
  unwrapCurrentInstruction
146
- } from "./chunk-PHZHJTCK.js";
148
+ } from "./chunk-PIB4EOW6.js";
147
149
  import {
148
150
  abandonAgentTurnSessionRecord,
149
151
  commitMessages,
@@ -321,12 +323,6 @@ function getDashboardConversationLink(conversationId) {
321
323
  }
322
324
 
323
325
  // src/chat/slack/footer.ts
324
- function escapeSlackMrkdwn(text) {
325
- return text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
326
- }
327
- function escapeSlackLinkUrl(url) {
328
- return url.replaceAll("&", "&amp;").replaceAll("<", "%3C").replaceAll(">", "%3E");
329
- }
330
326
  function buildSlackReplyFooter(args) {
331
327
  const items = [];
332
328
  const conversationId = args.conversationId?.trim();
@@ -358,7 +354,7 @@ function buildSlackReplyBlocks(text, footer) {
358
354
  type: "context",
359
355
  elements: footer.items.map((item) => ({
360
356
  type: "mrkdwn",
361
- text: item.url ? `*${escapeSlackMrkdwn(item.label)}:* <${escapeSlackLinkUrl(item.url)}|${escapeSlackMrkdwn(item.value)}>` : `*${escapeSlackMrkdwn(item.label)}:* ${escapeSlackMrkdwn(item.value)}`
357
+ text: item.url ? `*${escapeSlackMrkdwnText(item.label)}:* ${formatSlackLink(item.url, item.value)}` : `*${escapeSlackMrkdwnText(item.label)}:* ${escapeSlackMrkdwnText(item.value)}`
362
358
  }))
363
359
  });
364
360
  }
@@ -7521,7 +7517,7 @@ function getQueuedMessages(context, options) {
7521
7517
  stripLeadingSlackMentionToken: options.explicitMention || Boolean(message.isMention)
7522
7518
  });
7523
7519
  return {
7524
- explicitMention: options.explicitMention || Boolean(message.isMention),
7520
+ explicitMention: Boolean(message.isMention),
7525
7521
  message,
7526
7522
  rawText: appendSlackLegacyAttachmentText(message.text, message.raw),
7527
7523
  userText: appendSlackLegacyAttachmentText(stripped, message.raw)
@@ -9284,6 +9280,56 @@ function parkedInputKey(message) {
9284
9280
  const text = first && typeof first === "object" && "text" in first ? String(first.text ?? "") : "";
9285
9281
  return `${message.timestamp}:${text}`;
9286
9282
  }
9283
+ function renderRecentThreadMessages(conversationContext, messages) {
9284
+ const passiveMessages = messages.filter((queued) => {
9285
+ if (queued.explicitMention) {
9286
+ return false;
9287
+ }
9288
+ const slackTs = queuedInstructionActor(queued)?.slackTs;
9289
+ return !slackTs || !conversationContext?.includes(`slack_ts="${slackTs}"`);
9290
+ });
9291
+ if (passiveMessages.length === 0) {
9292
+ return void 0;
9293
+ }
9294
+ const lines = ["<recent-thread-messages>"];
9295
+ for (const queued of passiveMessages) {
9296
+ const actor = queuedInstructionActor(queued);
9297
+ const attrs = [
9298
+ actor?.authorId ? `author_id="${escapeXml(actor.authorId)}"` : void 0,
9299
+ actor?.authorName ? `author_name="${escapeXml(actor.authorName)}"` : void 0,
9300
+ actor?.slackTs ? `slack_ts="${escapeXml(actor.slackTs)}"` : void 0
9301
+ ].filter((attr) => Boolean(attr)).join(" ");
9302
+ lines.push(
9303
+ attrs ? ` <message ${attrs}>` : " <message>",
9304
+ escapeXml(queued.userText),
9305
+ " </message>"
9306
+ );
9307
+ }
9308
+ lines.push("</recent-thread-messages>");
9309
+ return lines.join("\n");
9310
+ }
9311
+ function appendRecentThreadMessagesToContext(conversationContext, messages, options) {
9312
+ const recentThreadMessages = renderRecentThreadMessages(
9313
+ conversationContext,
9314
+ messages
9315
+ );
9316
+ const contextParts = [
9317
+ options?.includeConversationContext === false ? void 0 : conversationContext?.trim(),
9318
+ recentThreadMessages
9319
+ ].filter((part) => Boolean(part));
9320
+ return contextParts.length > 0 ? contextParts.join("\n\n") : void 0;
9321
+ }
9322
+ function queuedInstructionActor(queued) {
9323
+ const actor = getMessageActorIdentity(queued.message);
9324
+ const authorId = actor?.userId ?? parseActorUserId(queued.message.author.userId);
9325
+ const authorName = actor?.fullName ?? actor?.userName;
9326
+ const slackTs = getSlackMessageTs(queued.message);
9327
+ return {
9328
+ ...authorId ? { authorId } : {},
9329
+ ...authorName ? { authorName } : {},
9330
+ ...slackTs ? { slackTs } : {}
9331
+ };
9332
+ }
9287
9333
  function isResourceEventMessage(message) {
9288
9334
  const raw = message.raw && typeof message.raw === "object" ? message.raw : void 0;
9289
9335
  return raw?.event_type === "resource_event";
@@ -9407,10 +9453,6 @@ function createReplyToThread(deps) {
9407
9453
  message.raw
9408
9454
  )
9409
9455
  };
9410
- const effectiveUserText = combineTurnText(
9411
- options.queuedMessages ?? [],
9412
- currentText
9413
- ).userText;
9414
9456
  await Promise.all(
9415
9457
  (options.queuedMessages ?? []).filter((queued) => !isResourceEventMessage(queued.message)).map(
9416
9458
  (queued) => ensureSlackMessageActorIdentity(
@@ -9420,6 +9462,7 @@ function createReplyToThread(deps) {
9420
9462
  )
9421
9463
  )
9422
9464
  );
9465
+ const effectiveUserText = currentText.userText;
9423
9466
  const credentialContext = resourceEventCredentialContext(message) ?? {
9424
9467
  actor: { type: "user", userId: message.author.userId }
9425
9468
  };
@@ -9511,6 +9554,7 @@ function createReplyToThread(deps) {
9511
9554
  queuedMessages.map(async (queued) => {
9512
9555
  const attachments = queued.message.attachments;
9513
9556
  return {
9557
+ actor: queuedInstructionActor(queued),
9514
9558
  text: queued.userText,
9515
9559
  timestampMs: queued.message.metadata.dateSent.getTime(),
9516
9560
  omittedImageAttachmentCount: !isVisionEnabled() && hasPotentialImageAttachment(attachments) ? countPotentialImageAttachments(attachments) : 0,
@@ -9861,6 +9905,18 @@ function createReplyToThread(deps) {
9861
9905
  });
9862
9906
  }
9863
9907
  }
9908
+ const hasDurablePromptHistory = Boolean(piMessages?.length);
9909
+ const queuedInstructionPiMessages = (await resolveSteeringMessages(
9910
+ (options.queuedMessages ?? []).filter(
9911
+ (queued) => queued.explicitMention
9912
+ )
9913
+ )).map(buildSteeringPiMessage);
9914
+ if (queuedInstructionPiMessages.length > 0) {
9915
+ piMessages = [
9916
+ ...piMessages ?? [],
9917
+ ...queuedInstructionPiMessages
9918
+ ];
9919
+ }
9864
9920
  status.start();
9865
9921
  const assistantTitleTask = maybeUpdateAssistantTitle({
9866
9922
  assistantThreadContext,
@@ -9924,6 +9980,12 @@ function createReplyToThread(deps) {
9924
9980
  );
9925
9981
  });
9926
9982
  const toolChannelId = preparedState.artifacts.assistantContextChannelId ?? channelId;
9983
+ const activeInstructionAuthorId = requester?.userId ?? parseActorUserId(message.author.userId);
9984
+ const activeInstructionAuthorName = requester?.fullName ?? requester?.userName;
9985
+ const promptConversationContext = appendRecentThreadMessagesToContext(
9986
+ preparedState.conversationContext,
9987
+ options.queuedMessages ?? []
9988
+ );
9927
9989
  const drainSteeringMessages = options.drainSteeringMessages ? async (accept) => {
9928
9990
  let acceptedMessages;
9929
9991
  const drained = await options.drainSteeringMessages(
@@ -9937,8 +9999,14 @@ function createReplyToThread(deps) {
9937
9999
  } : void 0;
9938
10000
  const outcome = await deps.services.agentRunner.run({
9939
10001
  input: {
10002
+ actor: {
10003
+ ...activeInstructionAuthorId ? { authorId: activeInstructionAuthorId } : {},
10004
+ ...activeInstructionAuthorName ? { authorName: activeInstructionAuthorName } : {},
10005
+ ...slackMessageTs ? { slackTs: slackMessageTs } : {}
10006
+ },
10007
+ includeConversationContextWithPiMessages: hasDurablePromptHistory,
9940
10008
  messageText: effectiveUserText,
9941
- conversationContext: preparedState.conversationContext,
10009
+ conversationContext: promptConversationContext,
9942
10010
  piMessages,
9943
10011
  inboundAttachmentCount: turnAttachments.length,
9944
10012
  omittedImageAttachmentCount,
@@ -7,7 +7,7 @@ import type { ToolRuntimeContext } from "@/chat/tools/types";
7
7
  import type { AnyToolDefinition } from "@/chat/tools/definition";
8
8
  import type { Requester } from "@/chat/requester";
9
9
  import type { ThreadArtifactsState } from "@/chat/state/artifacts";
10
- import type { AgentRunInput, AgentRunRouting, AgentRunSteeringMessage } from "@/chat/agent/request";
10
+ import type { AgentRunInput, AgentRunInstructionActor, AgentRunRouting, AgentRunSteeringMessage } from "@/chat/agent/request";
11
11
  export type UserContentPart = {
12
12
  type: "text";
13
13
  text: string;
@@ -36,7 +36,7 @@ export interface PromptAssembly {
36
36
  /**
37
37
  * Keep thread text separate from the canonical active task boundary.
38
38
  */
39
- export declare function buildUserTurnText(userInput: string, conversationContext?: string): string;
39
+ export declare function buildUserTurnText(userInput: string, conversationContext?: string, actor?: AgentRunInstructionActor): string;
40
40
  /** Encode a non-image attachment as base64 XML for the prompt. */
41
41
  export declare function encodeNonImageAttachmentForPrompt(attachment: {
42
42
  data: Buffer;
@@ -28,7 +28,13 @@ export interface AgentRunAttachment {
28
28
  filename?: string;
29
29
  promptText?: string;
30
30
  }
31
+ export interface AgentRunInstructionActor {
32
+ authorId?: string;
33
+ authorName?: string;
34
+ slackTs?: string;
35
+ }
31
36
  export interface AgentRunSteeringMessage {
37
+ actor?: AgentRunInstructionActor;
32
38
  omittedImageAttachmentCount?: number;
33
39
  text: string;
34
40
  timestampMs?: number;
@@ -36,6 +42,8 @@ export interface AgentRunSteeringMessage {
36
42
  }
37
43
  /** Carries the user-visible content and prior transcript for one agent-run slice. */
38
44
  export interface AgentRunInput {
45
+ actor?: AgentRunInstructionActor;
46
+ includeConversationContextWithPiMessages?: boolean;
39
47
  messageText: string;
40
48
  userAttachments?: AgentRunAttachment[];
41
49
  inboundAttachmentCount?: number;
@@ -1,6 +1,8 @@
1
1
  /** Render the active user task in a stable prompt boundary. */
2
- export declare function renderCurrentInstruction(instruction: string): string;
3
- /** Read the exact body from a standalone current-task prompt boundary. */
4
- export declare function extractCurrentInstructionBody(text: string): string | undefined;
2
+ export declare function renderCurrentInstruction(instruction: string, attrs?: {
3
+ authorId?: string;
4
+ authorName?: string;
5
+ slackTs?: string;
6
+ }): string;
5
7
  /** Recover display text from the internal current-task prompt boundary. */
6
8
  export declare function unwrapCurrentInstruction(text: string): string | undefined;
@@ -0,0 +1,6 @@
1
+ /** Format the private OAuth authorization prompt for Slack delivery. */
2
+ export declare function formatOAuthAuthorizationMessage(args: {
3
+ authorizationUrl: string;
4
+ label: string;
5
+ completionText: string;
6
+ }): string;
@@ -1,3 +1,9 @@
1
+ /** Escape dynamic text for Slack mrkdwn without changing intended formatting. */
2
+ export declare function escapeSlackMrkdwnText(text: string): string;
3
+ /** Escape a URL for Slack explicit link syntax while preserving query semantics. */
4
+ export declare function escapeSlackLinkUrl(url: string): string;
5
+ /** Build a Slack explicit link from dynamic URL and label values. */
6
+ export declare function formatSlackLink(url: string, label: string): string;
1
7
  /** Insert blank lines between content blocks so Slack renders them with visual separation. */
2
8
  export declare function ensureBlockSpacing(text: string): string;
3
9
  /**
@@ -23,32 +23,53 @@ import {
23
23
 
24
24
  // src/chat/current-instruction.ts
25
25
  var CURRENT_INSTRUCTION_TAG = "current-instruction";
26
- var CURRENT_INSTRUCTION_PATTERN = new RegExp(
27
- `<${CURRENT_INSTRUCTION_TAG}>\\n([\\s\\S]*?)\\n</${CURRENT_INSTRUCTION_TAG}>`
28
- );
29
- var STANDALONE_CURRENT_INSTRUCTION_PATTERN = new RegExp(
30
- `^<${CURRENT_INSTRUCTION_TAG}>\\n([\\s\\S]*?)\\n</${CURRENT_INSTRUCTION_TAG}>$`
31
- );
26
+ var CURRENT_INSTRUCTION_OPEN_PREFIX = `<${CURRENT_INSTRUCTION_TAG}`;
27
+ var CURRENT_INSTRUCTION_OPEN_BARE = `<${CURRENT_INSTRUCTION_TAG}>`;
28
+ var CURRENT_INSTRUCTION_OPEN_ATTR_PREFIX = `<${CURRENT_INSTRUCTION_TAG} `;
29
+ var CURRENT_INSTRUCTION_CLOSE = `
30
+ </${CURRENT_INSTRUCTION_TAG}>`;
32
31
  function unescapeXml(value) {
33
32
  return value.replaceAll("&quot;", '"').replaceAll("&apos;", "'").replaceAll("&gt;", ">").replaceAll("&lt;", "<").replaceAll("&amp;", "&");
34
33
  }
35
- function renderCurrentInstruction(instruction) {
34
+ function isCurrentInstructionOpeningTag(value) {
35
+ return value === CURRENT_INSTRUCTION_OPEN_BARE || value.startsWith(CURRENT_INSTRUCTION_OPEN_ATTR_PREFIX) && value.endsWith(">");
36
+ }
37
+ function readCurrentInstructionBody(text) {
38
+ const start = text.indexOf(CURRENT_INSTRUCTION_OPEN_PREFIX);
39
+ if (start < 0) {
40
+ return void 0;
41
+ }
42
+ const openingEnd = text.indexOf(">\n", start);
43
+ if (openingEnd < 0) {
44
+ return void 0;
45
+ }
46
+ const openingTag = text.slice(start, openingEnd + 1);
47
+ if (!isCurrentInstructionOpeningTag(openingTag)) {
48
+ return void 0;
49
+ }
50
+ const bodyStart = openingEnd + 2;
51
+ const bodyEnd = text.indexOf(CURRENT_INSTRUCTION_CLOSE, bodyStart);
52
+ if (bodyEnd < bodyStart) {
53
+ return void 0;
54
+ }
55
+ return text.slice(bodyStart, bodyEnd);
56
+ }
57
+ function renderCurrentInstruction(instruction, attrs) {
58
+ const renderedAttrs = [
59
+ attrs?.authorId ? `author_id="${escapeXml(attrs.authorId)}"` : void 0,
60
+ attrs?.authorName ? `author_name="${escapeXml(attrs.authorName)}"` : void 0,
61
+ attrs?.slackTs ? `slack_ts="${escapeXml(attrs.slackTs)}"` : void 0
62
+ ].filter((attr) => Boolean(attr)).join(" ");
63
+ const openingTag = renderedAttrs ? `<${CURRENT_INSTRUCTION_TAG} ${renderedAttrs}>` : `<${CURRENT_INSTRUCTION_TAG}>`;
36
64
  return [
37
- `<${CURRENT_INSTRUCTION_TAG}>`,
65
+ openingTag,
38
66
  escapeXml(instruction),
39
67
  `</${CURRENT_INSTRUCTION_TAG}>`
40
68
  ].join("\n");
41
69
  }
42
- function extractCurrentInstructionBody(text) {
43
- const match = text.match(STANDALONE_CURRENT_INSTRUCTION_PATTERN);
44
- return match?.[1];
45
- }
46
70
  function unwrapCurrentInstruction(text) {
47
- const match = text.match(CURRENT_INSTRUCTION_PATTERN);
48
- if (!match) {
49
- return void 0;
50
- }
51
- return unescapeXml(match[1]);
71
+ const body = readCurrentInstructionBody(text);
72
+ return body === void 0 ? void 0 : unescapeXml(body);
52
73
  }
53
74
 
54
75
  // src/chat/prompt.ts
@@ -81,6 +102,15 @@ function truncateStatusText(text) {
81
102
  }
82
103
 
83
104
  // src/chat/slack/mrkdwn.ts
105
+ function escapeSlackMrkdwnText(text) {
106
+ return text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
107
+ }
108
+ function escapeSlackLinkUrl(url) {
109
+ return url.replaceAll("&", "&amp;").replaceAll("<", "%3C").replaceAll(">", "%3E");
110
+ }
111
+ function formatSlackLink(url, label) {
112
+ return `<${escapeSlackLinkUrl(url)}|${escapeSlackMrkdwnText(label)}>`;
113
+ }
84
114
  function readInlineCodeSpan(line, start) {
85
115
  if (line[start] !== "`") {
86
116
  return void 0;
@@ -1049,9 +1079,10 @@ export {
1049
1079
  containsNoReplyMarker,
1050
1080
  stripNoReplyMarker,
1051
1081
  renderCurrentInstruction,
1052
- extractCurrentInstructionBody,
1053
1082
  unwrapCurrentInstruction,
1054
1083
  truncateStatusText,
1084
+ escapeSlackMrkdwnText,
1085
+ formatSlackLink,
1055
1086
  normalizeSlackStatusText,
1056
1087
  splitSlackReplyText,
1057
1088
  buildSlackOutputMessage,