@sentry/junior 0.104.2 → 0.105.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.
@@ -616,9 +616,6 @@ function isNoReplyMarker(text) {
616
616
  function containsNoReplyMarker(text) {
617
617
  return text.includes(NO_REPLY_MARKER);
618
618
  }
619
- function stripNoReplyMarker(text) {
620
- return text.replaceAll(NO_REPLY_MARKER, "").trim();
621
- }
622
619
 
623
620
  // src/chat/services/turn-result.ts
624
621
  function isExecutionDeferralResponse(text) {
@@ -731,7 +728,8 @@ function buildTurnResult(input) {
731
728
  ).trim();
732
729
  const exactNoReplyMarker = isNoReplyMarker(rawPrimaryText);
733
730
  const mixedNoReplyMarker = !exactNoReplyMarker && containsNoReplyMarker(rawPrimaryText);
734
- const primaryText = exactNoReplyMarker ? "" : mixedNoReplyMarker ? stripNoReplyMarker(rawPrimaryText) : rawPrimaryText;
731
+ const noReplyRequested = exactNoReplyMarker || mixedNoReplyMarker;
732
+ const primaryText = noReplyRequested ? "" : rawPrimaryText;
735
733
  const toolErrorCount = toolResults.filter((result) => result.isError).length;
736
734
  const successfulToolResults = toolResults.filter(
737
735
  (result) => !isToolResultError(result)
@@ -741,7 +739,7 @@ function buildTurnResult(input) {
741
739
  );
742
740
  const canvasCreated = successfulToolNames.has("slackCanvasCreate");
743
741
  const reactionPerformed = successfulToolNames.has("addReaction");
744
- const silentCompletionSuccess = exactNoReplyMarker;
742
+ const silentCompletionSuccess = noReplyRequested;
745
743
  const baseDeliveryPlan = {
746
744
  mode: "thread",
747
745
  postThreadText: true
@@ -6814,8 +6812,129 @@ function createSlackConversationSearchTool(scope, currentConversationId, deps =
6814
6812
  });
6815
6813
  }
6816
6814
 
6817
- // src/chat/slack/tools/message-add-reaction.ts
6815
+ // src/chat/slack/tools/public-search.ts
6818
6816
  import { z as z20 } from "zod";
6817
+ var DEFAULT_LIMIT2 = 10;
6818
+ var optionalTimestampSchema = z20.preprocess(
6819
+ (value) => typeof value === "string" && value.trim() === "" ? void 0 : value,
6820
+ z20.coerce.number().int().nonnegative().describe("Optional Unix timestamp bound.").optional()
6821
+ );
6822
+ var searchMessageSchema = z20.object({
6823
+ author_name: z20.string().optional(),
6824
+ author_user_id: z20.string().optional(),
6825
+ channel_id: z20.string().min(1),
6826
+ channel_name: z20.string().optional(),
6827
+ message_ts: z20.string().min(1),
6828
+ content: z20.string(),
6829
+ is_author_bot: z20.boolean().optional(),
6830
+ permalink: z20.string().url()
6831
+ });
6832
+ var publicSearchOutputSchema = juniorToolResultSchema.extend({
6833
+ query: z20.string(),
6834
+ count: z20.number().int().nonnegative(),
6835
+ messages: z20.array(searchMessageSchema),
6836
+ next_cursor: z20.string().optional()
6837
+ });
6838
+ function normalizeMessage(value) {
6839
+ const parsed = searchMessageSchema.safeParse(value);
6840
+ return parsed.success ? parsed.data : void 0;
6841
+ }
6842
+ function explicitSearchError(error) {
6843
+ if (error.code === "missing_scope") {
6844
+ return "Public Slack search is unavailable because this installation is missing the `search:read.public` scope.";
6845
+ }
6846
+ if (error.code === "feature_unavailable") {
6847
+ return "Public Slack search is not available for this Slack workspace or app installation.";
6848
+ }
6849
+ if (error.apiError === "invalid_action_token") {
6850
+ return "Public Slack search could not use the current Slack interaction token. Ask again in a new message or mention.";
6851
+ }
6852
+ return void 0;
6853
+ }
6854
+ function createSlackPublicSearchTool(actionToken) {
6855
+ return zodTool({
6856
+ description: "Search public Slack channel messages across the current workspace. Use when the user asks about company activity, announcements, public mentions, or context outside the active channel. Search only when requested or clearly needed, prefer focused keywords and time bounds, and cite returned permalinks. This never searches private channels or DMs.",
6857
+ annotations: { readOnlyHint: true, destructiveHint: false },
6858
+ inputSchema: z20.object({
6859
+ query: z20.string().trim().min(1).max(500).describe(
6860
+ "A focused Slack search query, including Slack search filters when useful."
6861
+ ),
6862
+ after: optionalTimestampSchema.describe(
6863
+ "Optional Unix timestamp lower bound."
6864
+ ),
6865
+ before: optionalTimestampSchema.describe(
6866
+ "Optional Unix timestamp upper bound."
6867
+ ),
6868
+ cursor: z20.string().min(1).describe("Cursor for the next result page.").optional(),
6869
+ limit: z20.coerce.number().int().min(1).max(20).describe("Maximum results to return; Slack allows at most 20.").optional(),
6870
+ sort: z20.enum(["score", "timestamp"]).describe("Rank by relevance or timestamp.").optional(),
6871
+ sort_dir: z20.enum(["asc", "desc"]).describe("Sort direction.").optional()
6872
+ }),
6873
+ outputSchema: publicSearchOutputSchema,
6874
+ execute: async ({
6875
+ query,
6876
+ after,
6877
+ before,
6878
+ cursor,
6879
+ limit,
6880
+ sort,
6881
+ sort_dir
6882
+ }) => {
6883
+ try {
6884
+ const normalizedAfter = optionalTimestampSchema.parse(after);
6885
+ const normalizedBefore = optionalTimestampSchema.parse(before);
6886
+ const response = await withSlackRetries(
6887
+ () => getSlackClient().apiCall("assistant.search.context", {
6888
+ action_token: actionToken,
6889
+ query,
6890
+ channel_types: ["public_channel"],
6891
+ content_types: ["messages"],
6892
+ include_bots: true,
6893
+ limit: limit ?? DEFAULT_LIMIT2,
6894
+ ...normalizedAfter !== void 0 ? { after: normalizedAfter } : {},
6895
+ ...normalizedBefore !== void 0 ? { before: normalizedBefore } : {},
6896
+ ...cursor ? { cursor } : {},
6897
+ ...sort ? { sort } : {},
6898
+ ...sort_dir ? { sort_dir } : {}
6899
+ }),
6900
+ 3,
6901
+ {
6902
+ action: "assistant.search.context",
6903
+ idempotent: true
6904
+ }
6905
+ );
6906
+ const messages = (response.results?.messages ?? []).map(normalizeMessage).filter((message) => Boolean(message));
6907
+ const nextCursor = response.results?.next_cursor;
6908
+ return {
6909
+ ok: true,
6910
+ status: "success",
6911
+ query,
6912
+ count: messages.length,
6913
+ messages,
6914
+ ...typeof nextCursor === "string" && nextCursor ? { next_cursor: nextCursor } : {}
6915
+ };
6916
+ } catch (error) {
6917
+ if (error instanceof SlackActionError) {
6918
+ const message = explicitSearchError(error);
6919
+ if (message) {
6920
+ return {
6921
+ ok: false,
6922
+ status: "error",
6923
+ error: message,
6924
+ query,
6925
+ count: 0,
6926
+ messages: []
6927
+ };
6928
+ }
6929
+ }
6930
+ throw error;
6931
+ }
6932
+ }
6933
+ });
6934
+ }
6935
+
6936
+ // src/chat/slack/tools/message-add-reaction.ts
6937
+ import { z as z21 } from "zod";
6819
6938
 
6820
6939
  // src/chat/tools/idempotency.ts
6821
6940
  function stableSerialize(value) {
@@ -6839,8 +6958,8 @@ function createOperationKey(toolName, input) {
6839
6958
  function createSlackMessageAddReactionTool(context, state) {
6840
6959
  return zodTool({
6841
6960
  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.",
6842
- inputSchema: z20.object({
6843
- emoji: z20.string().min(1).max(64).describe(
6961
+ inputSchema: z21.object({
6962
+ emoji: z21.string().min(1).max(64).describe(
6844
6963
  "Slack emoji alias name to react with (for example `thumbsup`, `white_check_mark`, or `thumbsup::skin-tone-6`). Optional surrounding colons are allowed."
6845
6964
  )
6846
6965
  }),
@@ -6891,15 +7010,15 @@ function createSlackMessageAddReactionTool(context, state) {
6891
7010
 
6892
7011
  // src/chat/slack/tools/send-message.ts
6893
7012
  import { createHash as createHash2 } from "crypto";
6894
- import { z as z21 } from "zod";
6895
- var fileInputSchema = z21.object({
6896
- path: z21.string().min(1).describe(
7013
+ import { z as z22 } from "zod";
7014
+ var fileInputSchema = z22.object({
7015
+ path: z22.string().min(1).describe(
6897
7016
  "Sandbox file path to include in the message. Absolute paths and workspace-relative paths are supported."
6898
7017
  ),
6899
- filename: z21.string().min(1).nullable().optional().describe(
7018
+ filename: z22.string().min(1).nullable().optional().describe(
6900
7019
  "Optional filename override shown in Slack. Null is treated as omitted."
6901
7020
  ),
6902
- mimeType: z21.string().min(1).nullable().optional().describe("Optional MIME type override. Null is treated as omitted.")
7021
+ mimeType: z22.string().min(1).nullable().optional().describe("Optional MIME type override. Null is treated as omitted.")
6903
7022
  });
6904
7023
  function hasText(text) {
6905
7024
  return typeof text === "string" && text.trim().length > 0;
@@ -6926,9 +7045,9 @@ function fileOperationInput(files) {
6926
7045
  function createSendMessageTool(context, state, materializeFile) {
6927
7046
  return zodTool({
6928
7047
  description: "Send a Slack message with optional files into the active Slack conversation. Use when the user asks to attach, send, or share files here, in this conversation, or in this thread. The message can contain text, files, or both; file-only messages are allowed. Do not use for top-level channel posts, other named channels, inline @mentions, or pinging mentioned users.",
6929
- inputSchema: z21.object({
6930
- text: z21.string().max(4e4).nullable().optional().describe("Slack mrkdwn text to send. Null is treated as omitted."),
6931
- files: z21.array(fileInputSchema).min(1).nullable().optional().describe(
7048
+ inputSchema: z22.object({
7049
+ text: z22.string().max(4e4).nullable().optional().describe("Slack mrkdwn text to send. Null is treated as omitted."),
7050
+ files: z22.array(fileInputSchema).min(1).nullable().optional().describe(
6932
7051
  "Sandbox files to include in the message. Null is treated as omitted."
6933
7052
  )
6934
7053
  }),
@@ -7256,13 +7375,13 @@ function storedCanvasUrl(state, canvasId) {
7256
7375
  }
7257
7376
 
7258
7377
  // src/chat/slack/tools/canvas/create.ts
7259
- import { z as z22 } from "zod";
7378
+ import { z as z23 } from "zod";
7260
7379
  function createSlackCanvasCreateTool(context, state) {
7261
7380
  return zodTool({
7262
7381
  description: "Create a Slack canvas for long-form output in the active assistant context channel. Use when the answer is better as a reusable document than a thread reply: long-form research, timelines, bios/profiles, structured notes, plans, comparisons, or anything likely to exceed one compact Slack reply. After creating it, reply with one or two short sentences plus the canvas link; do not recap the canvas contents. Do not use for short answers that fit cleanly in one normal thread reply.",
7263
- inputSchema: z22.object({
7264
- title: z22.string().min(1).max(160).describe("Canvas title."),
7265
- markdown: z22.string().min(1).describe("Canvas markdown body content.")
7382
+ inputSchema: z23.object({
7383
+ title: z23.string().min(1).max(160).describe("Canvas title."),
7384
+ markdown: z23.string().min(1).describe("Canvas markdown body content.")
7266
7385
  }),
7267
7386
  outputSchema: juniorToolResultSchema,
7268
7387
  execute: async ({ title, markdown }) => {
@@ -7325,35 +7444,35 @@ function createSlackCanvasCreateTool(context, state) {
7325
7444
  }
7326
7445
 
7327
7446
  // src/chat/slack/tools/canvas/edit.ts
7328
- import { z as z23 } from "zod";
7447
+ import { z as z24 } from "zod";
7329
7448
  function prepareCanvasEditArguments(input) {
7330
7449
  return prepareTextReplacementArguments(input);
7331
7450
  }
7332
- var editReplacementSchema2 = z23.object({
7333
- oldText: z23.string().min(1).describe(
7451
+ var editReplacementSchema2 = z24.object({
7452
+ oldText: z24.string().min(1).describe(
7334
7453
  "Exact Canvas markdown to replace. It must be unique in the current Canvas body and must not overlap another edit."
7335
7454
  ),
7336
- newText: z23.string().describe("Replacement Canvas markdown for this edit.")
7455
+ newText: z24.string().describe("Replacement Canvas markdown for this edit.")
7337
7456
  });
7338
7457
  var slackCanvasEditOutputSchema = juniorToolResultSchema.extend({
7339
- canvas_id: z23.string().optional(),
7340
- title: z23.string().optional(),
7341
- permalink: z23.string().optional(),
7342
- diff: z23.string().optional(),
7343
- first_changed_line: z23.number().int().positive().optional(),
7344
- replacements: z23.number().int().nonnegative().optional(),
7345
- normalized_heading_count: z23.number().int().nonnegative().optional(),
7346
- summary: z23.string().optional(),
7347
- deduplicated: z23.boolean().optional()
7458
+ canvas_id: z24.string().optional(),
7459
+ title: z24.string().optional(),
7460
+ permalink: z24.string().optional(),
7461
+ diff: z24.string().optional(),
7462
+ first_changed_line: z24.number().int().positive().optional(),
7463
+ replacements: z24.number().int().nonnegative().optional(),
7464
+ normalized_heading_count: z24.number().int().nonnegative().optional(),
7465
+ summary: z24.string().optional(),
7466
+ deduplicated: z24.boolean().optional()
7348
7467
  }).strict();
7349
7468
  function createSlackCanvasEditTool(state) {
7350
7469
  return zodTool({
7351
7470
  description: "Edit one Slack canvas with exact markdown replacements. Use for precise changes to existing Canvas content; prefer this over slackCanvasWrite for targeted changes. Each oldText must match exactly, be unique, and not overlap another edit. Returns a diff. Multiple changes to the same canvas: use one edits[] call.",
7352
7471
  prepareArguments: prepareCanvasEditArguments,
7353
7472
  executionMode: "sequential",
7354
- inputSchema: z23.object({
7355
- canvas: z23.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
7356
- edits: z23.array(editReplacementSchema2).min(1).describe(
7473
+ inputSchema: z24.object({
7474
+ canvas: z24.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
7475
+ edits: z24.array(editReplacementSchema2).min(1).describe(
7357
7476
  "Exact replacements matched against the current Canvas body, not incrementally."
7358
7477
  )
7359
7478
  }),
@@ -7431,29 +7550,29 @@ function createSlackCanvasEditTool(state) {
7431
7550
  }
7432
7551
 
7433
7552
  // src/chat/slack/tools/canvas/read.ts
7434
- import { z as z24 } from "zod";
7553
+ import { z as z25 } from "zod";
7435
7554
  var slackCanvasReadOutputSchema = juniorToolResultSchema.extend({
7436
- canvas_id: z24.string().optional(),
7437
- title: z24.string().optional(),
7438
- permalink: z24.string().optional(),
7439
- mimetype: z24.string().optional(),
7440
- filetype: z24.string().optional(),
7441
- original_byte_length: z24.number().int().nonnegative().optional(),
7442
- content: z24.string().optional(),
7443
- start_line: z24.number().int().positive().optional(),
7444
- end_line: z24.number().int().nonnegative().optional(),
7445
- total_lines: z24.number().int().nonnegative().optional()
7555
+ canvas_id: z25.string().optional(),
7556
+ title: z25.string().optional(),
7557
+ permalink: z25.string().optional(),
7558
+ mimetype: z25.string().optional(),
7559
+ filetype: z25.string().optional(),
7560
+ original_byte_length: z25.number().int().nonnegative().optional(),
7561
+ content: z25.string().optional(),
7562
+ start_line: z25.number().int().positive().optional(),
7563
+ end_line: z25.number().int().nonnegative().optional(),
7564
+ total_lines: z25.number().int().nonnegative().optional()
7446
7565
  }).strict();
7447
7566
  function createSlackCanvasReadTool() {
7448
7567
  return zodTool({
7449
7568
  description: "Read a bounded line range from a Slack canvas as markdown. Use when you need exact Canvas contents to verify facts or make edits safely. Do not use for generic web pages \u2014 use webFetch for those.",
7450
7569
  annotations: { readOnlyHint: true, destructiveHint: false },
7451
- inputSchema: z24.object({
7452
- canvas: z24.string().min(1).describe(
7570
+ inputSchema: z25.object({
7571
+ canvas: z25.string().min(1).describe(
7453
7572
  "Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL (e.g. `https://team.slack.com/docs/T.../F...`)."
7454
7573
  ),
7455
- offset: z24.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
7456
- limit: z24.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
7574
+ offset: z25.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
7575
+ limit: z25.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
7457
7576
  }),
7458
7577
  outputSchema: slackCanvasReadOutputSchema,
7459
7578
  execute: async ({ canvas, offset, limit }) => {
@@ -7510,14 +7629,14 @@ function createSlackCanvasReadTool() {
7510
7629
  }
7511
7630
 
7512
7631
  // src/chat/slack/tools/canvas/write.ts
7513
- import { z as z25 } from "zod";
7632
+ import { z as z26 } from "zod";
7514
7633
  function createSlackCanvasWriteTool(state) {
7515
7634
  return zodTool({
7516
7635
  description: "Write UTF-8 markdown content to a Slack canvas. Use for deliberate full-Canvas replacement after validation; use slackCanvasEdit for targeted changes to existing canvas content.",
7517
7636
  executionMode: "sequential",
7518
- inputSchema: z25.object({
7519
- canvas: z25.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
7520
- content: z25.string().describe("UTF-8 markdown content to write.")
7637
+ inputSchema: z26.object({
7638
+ canvas: z26.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
7639
+ content: z26.string().describe("UTF-8 markdown content to write.")
7521
7640
  }),
7522
7641
  outputSchema: juniorToolResultSchema,
7523
7642
  execute: async ({ canvas, content }) => {
@@ -7753,12 +7872,12 @@ async function updateListItem(input) {
7753
7872
  }
7754
7873
 
7755
7874
  // src/chat/slack/id-param.ts
7756
- import { z as z26 } from "zod";
7875
+ import { z as z27 } from "zod";
7757
7876
  function slackChannelIdParam(description) {
7758
- return z26.string().min(1).describe(description);
7877
+ return z27.string().min(1).describe(description);
7759
7878
  }
7760
7879
  function slackUserIdParam(description) {
7761
- return z26.string().min(1).describe(description);
7880
+ return z27.string().min(1).describe(description);
7762
7881
  }
7763
7882
  function parseRequiredSlackChannelIdParam(field, value) {
7764
7883
  const channelId = parseSlackChannelId(value);
@@ -7782,16 +7901,16 @@ function parseRequiredSlackUserIdParam(field, value) {
7782
7901
  }
7783
7902
 
7784
7903
  // src/chat/slack/tools/list/add-items.ts
7785
- import { z as z27 } from "zod";
7904
+ import { z as z28 } from "zod";
7786
7905
  function createSlackListAddItemsTool(state) {
7787
7906
  return zodTool({
7788
7907
  description: "Add tasks to the active Slack list tracked in artifact context. Use when the user wants actionable items recorded in the current thread list. Do not use when no list exists and list creation was not requested.",
7789
- inputSchema: z27.object({
7790
- items: z27.array(z27.string().min(1)).min(1).max(25).describe("List item titles to create."),
7908
+ inputSchema: z28.object({
7909
+ items: z28.array(z28.string().min(1)).min(1).max(25).describe("List item titles to create."),
7791
7910
  assignee_user_id: slackUserIdParam(
7792
7911
  "Optional Slack user ID assigned to all created items."
7793
7912
  ).optional(),
7794
- due_date: z27.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
7913
+ due_date: z28.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
7795
7914
  }),
7796
7915
  outputSchema: juniorToolResultSchema,
7797
7916
  execute: async ({ items, assignee_user_id, due_date }) => {
@@ -7845,12 +7964,12 @@ function createSlackListAddItemsTool(state) {
7845
7964
  }
7846
7965
 
7847
7966
  // src/chat/slack/tools/list/create.ts
7848
- import { z as z28 } from "zod";
7967
+ import { z as z29 } from "zod";
7849
7968
  function createSlackListCreateTool(state) {
7850
7969
  return zodTool({
7851
7970
  description: "Create a Slack todo list for action tracking. Use when the user needs structured tasks with ownership/completion tracking. Do not use for one-off notes without task management needs.",
7852
- inputSchema: z28.object({
7853
- name: z28.string().min(1).max(160).describe("Name for the new Slack list.")
7971
+ inputSchema: z29.object({
7972
+ name: z29.string().min(1).max(160).describe("Name for the new Slack list.")
7854
7973
  }),
7855
7974
  outputSchema: juniorToolResultSchema,
7856
7975
  execute: async ({ name }) => {
@@ -7882,13 +8001,13 @@ function createSlackListCreateTool(state) {
7882
8001
  }
7883
8002
 
7884
8003
  // src/chat/slack/tools/list/get-items.ts
7885
- import { z as z29 } from "zod";
8004
+ import { z as z30 } from "zod";
7886
8005
  function createSlackListGetItemsTool(state) {
7887
8006
  return zodTool({
7888
8007
  description: "Read items from the active Slack list tracked in artifact context. Use when the user asks for task status, open items, or list contents. Do not use when list state is already known from the immediately prior result.",
7889
8008
  annotations: { readOnlyHint: true, destructiveHint: false },
7890
- inputSchema: z29.object({
7891
- limit: z29.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
8009
+ inputSchema: z30.object({
8010
+ limit: z30.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
7892
8011
  }),
7893
8012
  outputSchema: juniorToolResultSchema,
7894
8013
  execute: async ({ limit }) => {
@@ -7913,21 +8032,21 @@ function createSlackListGetItemsTool(state) {
7913
8032
  }
7914
8033
 
7915
8034
  // src/chat/slack/tools/list/update-item.ts
7916
- import { z as z30 } from "zod";
7917
- var booleanInput3 = (description) => z30.preprocess(
8035
+ import { z as z31 } from "zod";
8036
+ var booleanInput3 = (description) => z31.preprocess(
7918
8037
  (value) => value === "true" ? true : value === "false" ? false : value,
7919
- z30.boolean()
8038
+ z31.boolean()
7920
8039
  ).describe(description);
7921
- var updateListItemInputSchema = z30.union([
7922
- z30.object({
7923
- item_id: z30.string().min(1).describe("ID of the Slack list item to update."),
8040
+ var updateListItemInputSchema = z31.union([
8041
+ z31.object({
8042
+ item_id: z31.string().min(1).describe("ID of the Slack list item to update."),
7924
8043
  completed: booleanInput3("Optional completion status update."),
7925
- title: z30.string().min(1).describe("Optional new item title.").optional()
8044
+ title: z31.string().min(1).describe("Optional new item title.").optional()
7926
8045
  }),
7927
- z30.object({
7928
- item_id: z30.string().min(1).describe("ID of the Slack list item to update."),
8046
+ z31.object({
8047
+ item_id: z31.string().min(1).describe("ID of the Slack list item to update."),
7929
8048
  completed: booleanInput3("Optional completion status update.").optional(),
7930
- title: z30.string().min(1).describe("Optional new item title.")
8049
+ title: z31.string().min(1).describe("Optional new item title.")
7931
8050
  })
7932
8051
  ]);
7933
8052
  function createSlackListUpdateItemTool(state) {
@@ -8003,7 +8122,7 @@ async function checkSlackChannelReadAccess(args) {
8003
8122
  }
8004
8123
 
8005
8124
  // src/chat/slack/tools/thread-read.ts
8006
- import { z as z31 } from "zod";
8125
+ import { z as z32 } from "zod";
8007
8126
 
8008
8127
  // src/chat/slack/tools/slack-message-url.ts
8009
8128
  var SLACK_HOST_PATTERN = /^[a-z0-9-]+\.slack(?:-gov)?\.com$/;
@@ -8176,8 +8295,8 @@ function createSlackThreadReadTool(context, deps = {}) {
8176
8295
  return zodTool({
8177
8296
  description: "Read a Slack thread from a shared Slack message archive URL or explicit channel + timestamp. Use when the user shares a Slack message link (https://*.slack.com/archives/...) and you need the referenced message and its thread context. Only the current conversation and public channels Junior has seen in this workspace are readable.",
8178
8297
  annotations: { readOnlyHint: true, destructiveHint: false },
8179
- inputSchema: z31.object({
8180
- url: z31.string().min(1).describe(
8298
+ inputSchema: z32.object({
8299
+ url: z32.string().min(1).describe(
8181
8300
  "Slack message archive URL, e.g. https://workspace.slack.com/archives/C123/p1700000000123456"
8182
8301
  ).optional(),
8183
8302
  channel_id: slackChannelIdParam(
@@ -8186,8 +8305,8 @@ function createSlackThreadReadTool(context, deps = {}) {
8186
8305
  ts: slackTimestampParam(
8187
8306
  "Slack message timestamp (e.g. 1700000000.123456). May be the thread root or any message in the thread."
8188
8307
  ).optional(),
8189
- limit: z31.coerce.number().int().min(1).max(1e3).describe("Maximum number of thread messages to fetch.").optional(),
8190
- max_pages: z31.coerce.number().int().min(1).max(10).describe("Maximum number of Slack API pages to traverse.").optional()
8308
+ limit: z32.coerce.number().int().min(1).max(1e3).describe("Maximum number of thread messages to fetch.").optional(),
8309
+ max_pages: z32.coerce.number().int().min(1).max(10).describe("Maximum number of Slack API pages to traverse.").optional()
8191
8310
  }),
8192
8311
  outputSchema: juniorToolResultSchema,
8193
8312
  execute: async ({ url, channel_id, ts, limit, max_pages }) => {
@@ -8443,29 +8562,29 @@ async function searchSlackUsers(options) {
8443
8562
  }
8444
8563
 
8445
8564
  // src/chat/slack/tools/user-lookup.ts
8446
- import { z as z32 } from "zod";
8447
- var booleanInput4 = (description) => z32.preprocess(
8565
+ import { z as z33 } from "zod";
8566
+ var booleanInput4 = (description) => z33.preprocess(
8448
8567
  (value) => value === "true" ? true : value === "false" ? false : value,
8449
- z32.boolean()
8568
+ z33.boolean()
8450
8569
  ).describe(description);
8451
8570
  function createSlackUserLookupTool() {
8452
8571
  return zodTool({
8453
8572
  description: "Look up Slack user profiles by user ID, email, or name search. Use when you need to identify a user, resolve cross-platform identity, or look up profile details like title or status. Returns profile fields including custom fields. For user ID lookup, pass a Slack user ID (e.g. U039RR91S). For search, pass a name query.",
8454
8573
  annotations: { readOnlyHint: true, destructiveHint: false },
8455
- inputSchema: z32.object({
8574
+ inputSchema: z33.object({
8456
8575
  user_id: slackUserIdParam(
8457
8576
  "Slack user ID to look up (e.g. U039RR91S). Mutually exclusive with email and query."
8458
8577
  ).optional(),
8459
- email: z32.string().min(3).describe(
8578
+ email: z33.string().min(3).describe(
8460
8579
  "Email address to look up. Mutually exclusive with user_id and query."
8461
8580
  ).optional(),
8462
- query: z32.string().min(2).describe(
8581
+ query: z33.string().min(2).describe(
8463
8582
  "Name to search for (matches against username, display name, real name). Mutually exclusive with user_id and email."
8464
8583
  ).optional(),
8465
- limit: z32.coerce.number().int().min(1).max(20).describe(
8584
+ limit: z33.coerce.number().int().min(1).max(20).describe(
8466
8585
  "Maximum number of results to return for name search. Defaults to 10."
8467
8586
  ).optional(),
8468
- max_pages: z32.coerce.number().int().min(1).max(5).describe(
8587
+ max_pages: z33.coerce.number().int().min(1).max(5).describe(
8469
8588
  "Maximum number of Slack API pages to scan for name search. Defaults to 3."
8470
8589
  ).optional(),
8471
8590
  include_bots: booleanInput4(
@@ -8569,18 +8688,18 @@ function createSlackUserLookupTool() {
8569
8688
  }
8570
8689
 
8571
8690
  // src/chat/tools/system-time.ts
8572
- import { z as z33 } from "zod";
8691
+ import { z as z34 } from "zod";
8573
8692
  var systemTimeOutputSchema = juniorToolResultSchema.extend({
8574
- unix_ms: z33.number(),
8575
- iso_utc: z33.string(),
8576
- iso_local: z33.string(),
8577
- timezone_offset_minutes: z33.number()
8693
+ unix_ms: z34.number(),
8694
+ iso_utc: z34.string(),
8695
+ iso_local: z34.string(),
8696
+ timezone_offset_minutes: z34.number()
8578
8697
  });
8579
8698
  function createSystemTimeTool() {
8580
8699
  return zodTool({
8581
8700
  description: "Return current system time in UTC and local ISO formats. Use when the user asks for current time/date context. Do not use as a substitute for historical or timezone-conversion research.",
8582
8701
  annotations: { readOnlyHint: true, destructiveHint: false },
8583
- inputSchema: z33.object({}),
8702
+ inputSchema: z34.object({}),
8584
8703
  outputSchema: systemTimeOutputSchema,
8585
8704
  privateTraceResult: (result) => ({
8586
8705
  ok: result.ok,
@@ -8609,10 +8728,10 @@ function createSystemTimeTool() {
8609
8728
  }
8610
8729
 
8611
8730
  // src/chat/tools/handoff/tool.ts
8612
- import { z as z34 } from "zod";
8731
+ import { z as z35 } from "zod";
8613
8732
  var HANDOFF_TOOL_NAME = "handoff";
8614
8733
  function createHandoffTool(handoff) {
8615
- const profileSchema = z34.enum(handoff.profiles);
8734
+ const profileSchema = z35.enum(handoff.profiles);
8616
8735
  const defaultProfile = handoff.profiles[0];
8617
8736
  const handoffResultSchema = juniorToolResultSchema.extend({
8618
8737
  model_profile: profileSchema
@@ -8621,7 +8740,7 @@ function createHandoffTool(handoff) {
8621
8740
  return zodTool({
8622
8741
  description: `Permanently switch this conversation to a more capable model profile, replace prior context with a continuation summary, and continue the same task with the same workspace and all other normal tools. Available profiles: ${profileNames}. Omit profile to use \`${defaultProfile}\`. Call it as the only tool in the assistant message when the system tool policy requires a model upgrade.`,
8623
8742
  executionMode: "sequential",
8624
- inputSchema: z34.object({
8743
+ inputSchema: z35.object({
8625
8744
  profile: profileSchema.nullish().describe(
8626
8745
  "Named model profile to use for the rest of the conversation; omit or pass null for the default"
8627
8746
  )
@@ -8640,7 +8759,7 @@ function createHandoffTool(handoff) {
8640
8759
  }
8641
8760
 
8642
8761
  // src/chat/tools/web/fetch-tool.ts
8643
- import { z as z35 } from "zod";
8762
+ import { z as z36 } from "zod";
8644
8763
 
8645
8764
  // src/chat/tools/web/constants.ts
8646
8765
  var USER_AGENT = "junior-bot/0.1";
@@ -9087,9 +9206,9 @@ function createWebFetchTool(hooks, options = {}) {
9087
9206
  destructiveHint: false,
9088
9207
  openWorldHint: true
9089
9208
  },
9090
- inputSchema: z35.object({
9091
- url: z35.string().min(1).describe("HTTP(S) URL to fetch."),
9092
- max_chars: z35.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
9209
+ inputSchema: z36.object({
9210
+ url: z36.string().min(1).describe("HTTP(S) URL to fetch."),
9211
+ max_chars: z36.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
9093
9212
  }),
9094
9213
  outputSchema: juniorToolResultSchema,
9095
9214
  execute: async ({ url, max_chars }) => {
@@ -9156,7 +9275,7 @@ function createWebFetchTool(hooks, options = {}) {
9156
9275
  }
9157
9276
 
9158
9277
  // src/chat/tools/web/search.ts
9159
- import { z as z36 } from "zod";
9278
+ import { z as z37 } from "zod";
9160
9279
  import { generateText } from "ai";
9161
9280
  import { createGatewayProvider } from "@ai-sdk/gateway";
9162
9281
  import { getModel } from "@earendil-works/pi-ai/compat";
@@ -9207,9 +9326,9 @@ function createWebSearchTool(override) {
9207
9326
  destructiveHint: false,
9208
9327
  openWorldHint: true
9209
9328
  },
9210
- inputSchema: z36.object({
9211
- query: z36.string().min(1).max(500).describe("Search query."),
9212
- max_results: z36.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
9329
+ inputSchema: z37.object({
9330
+ query: z37.string().min(1).max(500).describe("Search query."),
9331
+ max_results: z37.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
9213
9332
  }),
9214
9333
  outputSchema: juniorToolResultSchema,
9215
9334
  execute: async ({ query, max_results }) => {
@@ -9279,14 +9398,14 @@ function createWebSearchTool(override) {
9279
9398
  }
9280
9399
 
9281
9400
  // src/chat/tools/sandbox/write-file.ts
9282
- import { z as z37 } from "zod";
9401
+ import { z as z38 } from "zod";
9283
9402
  function createWriteFileTool() {
9284
9403
  return zodTool({
9285
9404
  description: "Write UTF-8 content to a file in the sandbox workspace. Use for intentional file creation or deliberate full-file replacement after validation; use editFile instead for targeted changes to existing files. Do not use for exploratory analysis-only turns.",
9286
9405
  executionMode: "sequential",
9287
- inputSchema: z37.object({
9288
- path: z37.string().min(1).describe("Path to write in the sandbox workspace."),
9289
- content: z37.string().describe("UTF-8 file content to write.")
9406
+ inputSchema: z38.object({
9407
+ path: z38.string().min(1).describe("Path to write in the sandbox workspace."),
9408
+ content: z38.string().describe("UTF-8 file content to write.")
9290
9409
  }),
9291
9410
  outputSchema: juniorToolResultSchema,
9292
9411
  execute: async () => {
@@ -9389,6 +9508,11 @@ function createTools(availableSkills, hooks = {}, context) {
9389
9508
  context.conversationId
9390
9509
  );
9391
9510
  }
9511
+ if (context.source.platform === "slack" && context.slackActionToken) {
9512
+ tools.slackPublicSearch = createSlackPublicSearchTool(
9513
+ context.slackActionToken
9514
+ );
9515
+ }
9392
9516
  tools.slackUserLookup = createSlackUserLookupTool();
9393
9517
  tools.slackListCreate = createSlackListCreateTool(state);
9394
9518
  tools.slackListAddItems = createSlackListAddItemsTool(state);
@@ -10001,59 +10125,59 @@ async function startOAuthFlow(provider, input) {
10001
10125
  }
10002
10126
 
10003
10127
  // src/chat/sandbox/egress/schemas.ts
10004
- import { z as z38 } from "zod";
10128
+ import { z as z39 } from "zod";
10005
10129
  import {
10006
10130
  pluginAuthorizationSchema,
10007
10131
  pluginCredentialHeaderTransformSchema,
10008
10132
  pluginGrantSchema,
10009
10133
  pluginProviderAccountSchema
10010
10134
  } from "@sentry/junior-plugin-api";
10011
- var finiteNumberSchema = z38.number().refine(Number.isFinite);
10012
- var httpStatusSchema = z38.number().int().min(100).max(599);
10013
- var providerNameSchema = z38.string().regex(/^[a-z][a-z0-9-]*$/);
10014
- var credentialSignalKindSchema = z38.enum(["auth_required", "unavailable"]);
10135
+ var finiteNumberSchema = z39.number().refine(Number.isFinite);
10136
+ var httpStatusSchema = z39.number().int().min(100).max(599);
10137
+ var providerNameSchema = z39.string().regex(/^[a-z][a-z0-9-]*$/);
10138
+ var credentialSignalKindSchema = z39.enum(["auth_required", "unavailable"]);
10015
10139
  var sandboxEgressGrantSchema = pluginGrantSchema;
10016
- var sandboxEgressCredentialContextSchema = z38.object({
10140
+ var sandboxEgressCredentialContextSchema = z39.object({
10017
10141
  credentials: credentialContextSchema,
10018
- egressId: z38.string().min(1),
10142
+ egressId: z39.string().min(1),
10019
10143
  expiresAtMs: finiteNumberSchema,
10020
- contextId: z38.string().min(1)
10144
+ contextId: z39.string().min(1)
10021
10145
  }).strict();
10022
- var sandboxEgressCredentialLeaseSchema = z38.object({
10146
+ var sandboxEgressCredentialLeaseSchema = z39.object({
10023
10147
  account: pluginProviderAccountSchema.optional(),
10024
10148
  authorization: pluginAuthorizationSchema.optional(),
10025
10149
  grant: sandboxEgressGrantSchema,
10026
10150
  provider: providerNameSchema,
10027
- expiresAt: z38.string().min(1),
10028
- headerTransforms: z38.array(pluginCredentialHeaderTransformSchema).min(1)
10151
+ expiresAt: z39.string().min(1),
10152
+ headerTransforms: z39.array(pluginCredentialHeaderTransformSchema).min(1)
10029
10153
  }).strict();
10030
- var sandboxEgressAuthRequiredSignalSchema = z38.object({
10154
+ var sandboxEgressAuthRequiredSignalSchema = z39.object({
10031
10155
  authorization: pluginAuthorizationSchema.optional(),
10032
10156
  grant: sandboxEgressGrantSchema,
10033
10157
  kind: credentialSignalKindSchema.default("auth_required"),
10034
10158
  provider: providerNameSchema,
10035
- message: z38.string().optional(),
10159
+ message: z39.string().optional(),
10036
10160
  createdAtMs: finiteNumberSchema
10037
10161
  }).strict().superRefine((signal, ctx) => {
10038
10162
  if (signal.authorization && signal.authorization.provider !== signal.provider) {
10039
10163
  ctx.addIssue({
10040
- code: z38.ZodIssueCode.custom,
10164
+ code: z39.ZodIssueCode.custom,
10041
10165
  message: "Auth signal authorization provider must match provider",
10042
10166
  path: ["authorization", "provider"]
10043
10167
  });
10044
10168
  }
10045
10169
  });
10046
- var sandboxEgressPermissionDeniedSignalSchema = z38.object({
10170
+ var sandboxEgressPermissionDeniedSignalSchema = z39.object({
10047
10171
  account: pluginProviderAccountSchema.optional(),
10048
- acceptedPermissions: z38.string().optional(),
10172
+ acceptedPermissions: z39.string().optional(),
10049
10173
  grant: sandboxEgressGrantSchema,
10050
- message: z38.string().min(1),
10174
+ message: z39.string().min(1),
10051
10175
  provider: providerNameSchema,
10052
- source: z38.literal("upstream"),
10053
- sso: z38.string().optional(),
10176
+ source: z39.literal("upstream"),
10177
+ sso: z39.string().optional(),
10054
10178
  status: httpStatusSchema,
10055
- upstreamHost: z38.string().min(1),
10056
- upstreamPath: z38.string().min(1),
10179
+ upstreamHost: z39.string().min(1),
10180
+ upstreamPath: z39.string().min(1),
10057
10181
  createdAtMs: finiteNumberSchema
10058
10182
  }).strict();
10059
10183
  function parseSandboxEgressAuthRequiredSignal(value) {
@@ -10314,15 +10438,15 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, trac
10314
10438
  }
10315
10439
 
10316
10440
  // src/chat/tools/execute-tool.ts
10317
- import { z as z39 } from "zod";
10441
+ import { z as z40 } from "zod";
10318
10442
  var EXECUTE_TOOL_NAME = "executeTool";
10319
10443
  function createExecuteToolTool() {
10320
10444
  return zodTool({
10321
10445
  description: "Execute any catalog tool by exact tool_name from searchTools. Put tool-specific parameters inside arguments.",
10322
10446
  executionMode: "sequential",
10323
- inputSchema: z39.object({
10324
- tool_name: z39.string().min(1).describe("Exact catalog tool_name returned by searchTools."),
10325
- arguments: z39.record(z39.string(), z39.unknown()).describe(
10447
+ inputSchema: z40.object({
10448
+ tool_name: z40.string().min(1).describe("Exact catalog tool_name returned by searchTools."),
10449
+ arguments: z40.record(z40.string(), z40.unknown()).describe(
10326
10450
  'Arguments matching the selected catalog tool schema, for example { "query": "..." }.'
10327
10451
  ).optional()
10328
10452
  }).strict(),
@@ -10362,42 +10486,42 @@ function planToolExposure(tools) {
10362
10486
  }
10363
10487
 
10364
10488
  // src/chat/tools/search-tools.ts
10365
- import { z as z40 } from "zod";
10489
+ import { z as z41 } from "zod";
10366
10490
  var SEARCH_TOOLS_NAME = "searchTools";
10367
10491
  var DEFAULT_MAX_RESULTS2 = 5;
10368
10492
  var MAX_RESULTS3 = 20;
10369
10493
  var MODEL_VISIBLE_DESCRIPTION_CAP = 180;
10370
- var searchToolsSourceSchema = z40.object({
10371
- id: z40.string(),
10372
- description: z40.string()
10494
+ var searchToolsSourceSchema = z41.object({
10495
+ id: z41.string(),
10496
+ description: z41.string()
10373
10497
  }).strict();
10374
- var toolCallExampleSchema = z40.object({
10375
- tool_name: z40.string(),
10376
- arguments: z40.record(z40.string(), z40.string())
10498
+ var toolCallExampleSchema = z41.object({
10499
+ tool_name: z41.string(),
10500
+ arguments: z41.record(z41.string(), z41.string())
10377
10501
  }).strict();
10378
- var searchToolsToolSchema = z40.object({
10379
- tool_name: z40.string(),
10380
- description: z40.string(),
10381
- exposure: z40.enum(["direct", "deferred", "modelOnly", "hidden"]),
10382
- source: z40.string().optional(),
10383
- signature: z40.string(),
10502
+ var searchToolsToolSchema = z41.object({
10503
+ tool_name: z41.string(),
10504
+ description: z41.string(),
10505
+ exposure: z41.enum(["direct", "deferred", "modelOnly", "hidden"]),
10506
+ source: z41.string().optional(),
10507
+ signature: z41.string(),
10384
10508
  call: toolCallExampleSchema,
10385
- input_schema: z40.unknown(),
10386
- input_schema_summary: z40.string(),
10387
- call_notes: z40.array(z40.string()),
10388
- annotations: z40.record(z40.string(), z40.unknown())
10509
+ input_schema: z41.unknown(),
10510
+ input_schema_summary: z41.string(),
10511
+ call_notes: z41.array(z41.string()),
10512
+ annotations: z41.record(z41.string(), z41.unknown())
10389
10513
  }).strict();
10390
10514
  var searchToolsOutputSchema = juniorToolResultSchema.extend({
10391
- query: z40.string().nullable(),
10392
- source: z40.string().nullable(),
10393
- sources: z40.array(searchToolsSourceSchema),
10394
- total_catalog_tools: z40.number().int().nonnegative(),
10395
- total_eligible_tools: z40.number().int().nonnegative(),
10396
- total_matches: z40.number().int().nonnegative(),
10397
- returned_tools: z40.number().int().nonnegative(),
10398
- execution_tool: z40.literal("executeTool"),
10515
+ query: z41.string().nullable(),
10516
+ source: z41.string().nullable(),
10517
+ sources: z41.array(searchToolsSourceSchema),
10518
+ total_catalog_tools: z41.number().int().nonnegative(),
10519
+ total_eligible_tools: z41.number().int().nonnegative(),
10520
+ total_matches: z41.number().int().nonnegative(),
10521
+ returned_tools: z41.number().int().nonnegative(),
10522
+ execution_tool: z41.literal("executeTool"),
10399
10523
  execution_example: toolCallExampleSchema,
10400
- tools: z40.array(searchToolsToolSchema)
10524
+ tools: z41.array(searchToolsToolSchema)
10401
10525
  }).strict();
10402
10526
  function normalize2(value) {
10403
10527
  return value.toLowerCase().replace(/[^a-z0-9_]+/g, " ").trim();
@@ -10589,14 +10713,14 @@ function createSearchToolsTool(catalogTools) {
10589
10713
  return zodTool({
10590
10714
  description: renderSearchToolsDescription(knownSources),
10591
10715
  annotations: { readOnlyHint: true, destructiveHint: false },
10592
- inputSchema: z40.object({
10593
- query: z40.string().nullable().describe(
10716
+ inputSchema: z41.object({
10717
+ query: z41.string().nullable().describe(
10594
10718
  "Optional search terms describing the tool, owner, action, or arguments needed. Empty string lists catalog tools."
10595
10719
  ).optional(),
10596
- source: z40.string().nullable().describe(
10720
+ source: z41.string().nullable().describe(
10597
10721
  "Optional source id to search within, such as a plugin source returned in sources."
10598
10722
  ).optional(),
10599
- max_results: z40.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
10723
+ max_results: z41.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
10600
10724
  }).strict(),
10601
10725
  outputSchema: searchToolsOutputSchema,
10602
10726
  privateTraceResult: (result) => ({
@@ -14642,7 +14766,8 @@ async function wireAgentTools(args) {
14642
14766
  ...commonToolRuntimeContext,
14643
14767
  destination: toolDestination,
14644
14768
  actor: args.currentActor?.platform === "slack" ? args.currentActor : void 0,
14645
- source: runSource
14769
+ source: runSource,
14770
+ slackActionToken: args.routing.slackActionToken
14646
14771
  };
14647
14772
  } else {
14648
14773
  if (toolDestination.platform !== "local") {
@@ -15340,9 +15465,9 @@ async function executeAgentRun(request) {
15340
15465
  const conversationPrivacy = resolveConversationPrivacy({
15341
15466
  channelId: request.routing.correlation?.channelId,
15342
15467
  conversationId: request.routing.correlation?.conversationId ?? request.routing.correlation?.threadId ?? request.routing.correlation?.runId,
15343
- // Source-confirmed visibility from the live event's channel_type; without
15344
- // it the turn fails closed to private telemetry capture.
15345
- visibility: request.routing.slackConversation?.visibility
15468
+ // Destination visibility is provider-neutral. Slack event context remains
15469
+ // a compatibility fallback for callers that have not projected it yet.
15470
+ visibility: request.routing.destinationVisibility ?? request.routing.slackConversation?.visibility
15346
15471
  });
15347
15472
  return runWithConversationPrivacy(
15348
15473
  conversationPrivacy ?? "private",