@sentry/junior 0.104.2 → 0.106.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/{agent-hooks-EOFSY2PD.js → agent-hooks-KR5BCWOK.js} +5 -5
  2. package/dist/api/conversations/schema.d.ts +13 -0
  3. package/dist/api/schema.d.ts +1 -1
  4. package/dist/api/schema.js +1 -1
  5. package/dist/api.js +76 -39
  6. package/dist/app.js +68 -17
  7. package/dist/chat/agent/request.d.ts +9 -0
  8. package/dist/chat/agent-dispatch/types.d.ts +2 -1
  9. package/dist/chat/config.d.ts +1 -0
  10. package/dist/chat/no-reply.d.ts +0 -2
  11. package/dist/chat/services/turn-limit.d.ts +6 -0
  12. package/dist/chat/services/turn-session-record.d.ts +0 -1
  13. package/dist/chat/slack/action-token.d.ts +6 -0
  14. package/dist/chat/slack/tools/public-search.d.ts +74 -0
  15. package/dist/chat/tools/definition.d.ts +2 -0
  16. package/dist/chat/tools/index.d.ts +2 -2
  17. package/dist/chat/tools/types.d.ts +3 -0
  18. package/dist/{chunk-CCTCIISK.js → chunk-3MPPVPGZ.js} +1 -1
  19. package/dist/{chunk-7G4J3CR7.js → chunk-3NYUCBLE.js} +1 -1
  20. package/dist/{chunk-U26ZWZCN.js → chunk-3OUSJPR7.js} +1 -1
  21. package/dist/{chunk-M3UAVLEN.js → chunk-4UYIRWDW.js} +2 -0
  22. package/dist/{chunk-QVTVCJR4.js → chunk-4W4O4DCV.js} +7 -7
  23. package/dist/{chunk-4PDVOHXP.js → chunk-AZ5OMSN5.js} +1 -1
  24. package/dist/{chunk-RMZ65YAA.js → chunk-BKM4UXUD.js} +21 -6
  25. package/dist/{chunk-AIRE7Q2W.js → chunk-CCFROYAV.js} +7 -0
  26. package/dist/{chunk-QDKRE3LS.js → chunk-DDRQ4U7I.js} +3 -3
  27. package/dist/{chunk-TMWUGGSA.js → chunk-GPPUTY5M.js} +327 -187
  28. package/dist/{chunk-RYDF4GOX.js → chunk-P4P7O5WG.js} +3 -3
  29. package/dist/{chunk-O7ILGCMJ.js → chunk-R5BFYK2O.js} +1 -1
  30. package/dist/{chunk-BCULHGZK.js → chunk-XTKJPSMF.js} +1 -1
  31. package/dist/{chunk-VDHMFCDY.js → chunk-ZMRLBBD5.js} +4 -4
  32. package/dist/cli/chat.js +13 -13
  33. package/dist/cli/plugins.js +5 -5
  34. package/dist/cli/snapshot-warmup.js +2 -2
  35. package/dist/cli/upgrade.js +6 -6
  36. package/dist/{db-PDMC67T3.js → db-S33LFWG2.js} +2 -2
  37. package/dist/{legacy-import-G333RHJZ.js → legacy-import-TMJISRKO.js} +3 -3
  38. package/dist/{runner-6A7MQRUE.js → runner-HA5XAL6K.js} +9 -9
  39. package/package.json +6 -6
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  CooperativeTurnYieldError,
3
3
  TurnInputCommitLostError,
4
+ TurnSliceLimitExceededError,
4
5
  abandonReplacedPendingAuth,
5
6
  canReusePendingAuthLink,
6
7
  getInterruptionMarker,
@@ -11,7 +12,7 @@ import {
11
12
  persistRunningSessionRecord,
12
13
  persistTimeoutSessionRecord,
13
14
  persistYieldSessionRecord
14
- } from "./chunk-RMZ65YAA.js";
15
+ } from "./chunk-BKM4UXUD.js";
15
16
  import {
16
17
  JUNIOR_THREAD_STATE_TTL_MS
17
18
  } from "./chunk-XIMUQ4IU.js";
@@ -24,7 +25,7 @@ import {
24
25
  isSnapshotMissingError,
25
26
  resolveRuntimeDependencySnapshot,
26
27
  runNonInteractiveCommand
27
- } from "./chunk-7G4J3CR7.js";
28
+ } from "./chunk-3NYUCBLE.js";
28
29
  import {
29
30
  addAgentTurnUsage,
30
31
  hasAgentTurnUsage,
@@ -34,12 +35,12 @@ import {
34
35
  recordAuthorizationRequested,
35
36
  recordMcpProviderConnected,
36
37
  recordToolExecutionStarted
37
- } from "./chunk-QDKRE3LS.js";
38
+ } from "./chunk-DDRQ4U7I.js";
38
39
  import {
39
40
  estimateTextTokens,
40
41
  getAgentContextCompactionTriggerTokens,
41
42
  updateConversationStats
42
- } from "./chunk-RYDF4GOX.js";
43
+ } from "./chunk-P4P7O5WG.js";
43
44
  import {
44
45
  privateTraceResultAttributes
45
46
  } from "./chunk-UIE3R5XU.js";
@@ -51,10 +52,10 @@ import {
51
52
  getPlugins,
52
53
  getSlackToolContext,
53
54
  resolveChannelCapabilities
54
- } from "./chunk-VDHMFCDY.js";
55
+ } from "./chunk-ZMRLBBD5.js";
55
56
  import {
56
57
  createPluginLogger
57
- } from "./chunk-4PDVOHXP.js";
58
+ } from "./chunk-AZ5OMSN5.js";
58
59
  import {
59
60
  SANDBOX_DATA_ROOT,
60
61
  SANDBOX_SKILLS_ROOT,
@@ -71,7 +72,7 @@ import {
71
72
  isDmChannel,
72
73
  normalizeSlackConversationId,
73
74
  withSlackRetries
74
- } from "./chunk-CCTCIISK.js";
75
+ } from "./chunk-3MPPVPGZ.js";
75
76
  import {
76
77
  contextProvenance,
77
78
  getAgentStepStore,
@@ -80,7 +81,7 @@ import {
80
81
  getDb,
81
82
  instructionActors,
82
83
  instructionProvenanceFor
83
- } from "./chunk-BCULHGZK.js";
84
+ } from "./chunk-XTKJPSMF.js";
84
85
  import {
85
86
  sleep
86
87
  } from "./chunk-4ZNGQH7C.js";
@@ -123,7 +124,7 @@ import {
123
124
  stripRuntimeTurnContext,
124
125
  trimTrailingAssistantMessages,
125
126
  unwrapCurrentInstruction
126
- } from "./chunk-M3UAVLEN.js";
127
+ } from "./chunk-4UYIRWDW.js";
127
128
  import {
128
129
  parseSlackThreadId,
129
130
  resolveConversationPrivacy,
@@ -616,9 +617,6 @@ function isNoReplyMarker(text) {
616
617
  function containsNoReplyMarker(text) {
617
618
  return text.includes(NO_REPLY_MARKER);
618
619
  }
619
- function stripNoReplyMarker(text) {
620
- return text.replaceAll(NO_REPLY_MARKER, "").trim();
621
- }
622
620
 
623
621
  // src/chat/services/turn-result.ts
624
622
  function isExecutionDeferralResponse(text) {
@@ -731,7 +729,8 @@ function buildTurnResult(input) {
731
729
  ).trim();
732
730
  const exactNoReplyMarker = isNoReplyMarker(rawPrimaryText);
733
731
  const mixedNoReplyMarker = !exactNoReplyMarker && containsNoReplyMarker(rawPrimaryText);
734
- const primaryText = exactNoReplyMarker ? "" : mixedNoReplyMarker ? stripNoReplyMarker(rawPrimaryText) : rawPrimaryText;
732
+ const noReplyRequested = exactNoReplyMarker || mixedNoReplyMarker;
733
+ const primaryText = noReplyRequested ? "" : rawPrimaryText;
735
734
  const toolErrorCount = toolResults.filter((result) => result.isError).length;
736
735
  const successfulToolResults = toolResults.filter(
737
736
  (result) => !isToolResultError(result)
@@ -741,7 +740,7 @@ function buildTurnResult(input) {
741
740
  );
742
741
  const canvasCreated = successfulToolNames.has("slackCanvasCreate");
743
742
  const reactionPerformed = successfulToolNames.has("addReaction");
744
- const silentCompletionSuccess = exactNoReplyMarker;
743
+ const silentCompletionSuccess = noReplyRequested;
745
744
  const baseDeliveryPlan = {
746
745
  mode: "thread",
747
746
  postThreadText: true
@@ -2103,7 +2102,7 @@ var SKILL_POLICY_RULES = [
2103
2102
  var EXECUTION_CONTRACT_RULES = [
2104
2103
  "- Actionable request: act in this turn.",
2105
2104
  "- Continue until done or genuinely blocked. Do not finish with a plan, promise, or offer to check next when an available tool or source can move the request forward.",
2106
- "- Completion means the final answer covers the user's actual ask, including requested follow-up checks, and is grounded in the best evidence you could access.",
2105
+ "- Complete the full task, but report only the result and evidence the user needs; do not narrate every step, check, or detail.",
2107
2106
  "- Ask the user only for missing access, approval, or a decision that blocks safe progress. Ask one focused question; otherwise infer conservatively and continue.",
2108
2107
  "- For conflicting evidence, compare sources and state which source is authoritative for the answer.",
2109
2108
  "- For non-trivial or long-running work, call `reportProgress` early when available, then only when the major phase changes. Routine tool calls should stay silent."
@@ -2168,8 +2167,8 @@ function buildOutputSection(platform) {
2168
2167
  openTag,
2169
2168
  "- Start with the answer or result, not internal process narration.",
2170
2169
  "- 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.",
2171
- "- Keep replies brief and scannable; use bullets or short code blocks when helpful, and one compact thread reply when it fits.",
2172
- "- 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.",
2170
+ "- Default to one compact thread reply containing the conclusion and only decisive evidence or action. Do not split an explainer across multiple Slack messages.",
2171
+ "- Put plans, research, and other long or multi-section explainers in a Slack canvas; reply with one or two short sentences plus the link, without recapping the canvas.",
2173
2172
  "- End every turn with a final user-facing markdown response unless the Slack action rules allow a no-reply completion.",
2174
2173
  "</output>"
2175
2174
  ].join("\n");
@@ -6814,8 +6813,129 @@ function createSlackConversationSearchTool(scope, currentConversationId, deps =
6814
6813
  });
6815
6814
  }
6816
6815
 
6817
- // src/chat/slack/tools/message-add-reaction.ts
6816
+ // src/chat/slack/tools/public-search.ts
6818
6817
  import { z as z20 } from "zod";
6818
+ var DEFAULT_LIMIT2 = 10;
6819
+ var optionalTimestampSchema = z20.preprocess(
6820
+ (value) => typeof value === "string" && value.trim() === "" ? void 0 : value,
6821
+ z20.coerce.number().int().nonnegative().describe("Optional Unix timestamp bound.").optional()
6822
+ );
6823
+ var searchMessageSchema = z20.object({
6824
+ author_name: z20.string().optional(),
6825
+ author_user_id: z20.string().optional(),
6826
+ channel_id: z20.string().min(1),
6827
+ channel_name: z20.string().optional(),
6828
+ message_ts: z20.string().min(1),
6829
+ content: z20.string(),
6830
+ is_author_bot: z20.boolean().optional(),
6831
+ permalink: z20.string().url()
6832
+ });
6833
+ var publicSearchOutputSchema = juniorToolResultSchema.extend({
6834
+ query: z20.string(),
6835
+ count: z20.number().int().nonnegative(),
6836
+ messages: z20.array(searchMessageSchema),
6837
+ next_cursor: z20.string().optional()
6838
+ });
6839
+ function normalizeMessage(value) {
6840
+ const parsed = searchMessageSchema.safeParse(value);
6841
+ return parsed.success ? parsed.data : void 0;
6842
+ }
6843
+ function explicitSearchError(error) {
6844
+ if (error.code === "missing_scope") {
6845
+ return "Public Slack search is unavailable because this installation is missing the `search:read.public` scope.";
6846
+ }
6847
+ if (error.code === "feature_unavailable") {
6848
+ return "Public Slack search is not available for this Slack workspace or app installation.";
6849
+ }
6850
+ if (error.apiError === "invalid_action_token") {
6851
+ return "Public Slack search could not use the current Slack interaction token. Ask again in a new message or mention.";
6852
+ }
6853
+ return void 0;
6854
+ }
6855
+ function createSlackPublicSearchTool(actionToken) {
6856
+ return zodTool({
6857
+ 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.",
6858
+ annotations: { readOnlyHint: true, destructiveHint: false },
6859
+ inputSchema: z20.object({
6860
+ query: z20.string().trim().min(1).max(500).describe(
6861
+ "A focused Slack search query, including Slack search filters when useful."
6862
+ ),
6863
+ after: optionalTimestampSchema.describe(
6864
+ "Optional Unix timestamp lower bound."
6865
+ ),
6866
+ before: optionalTimestampSchema.describe(
6867
+ "Optional Unix timestamp upper bound."
6868
+ ),
6869
+ cursor: z20.string().min(1).describe("Cursor for the next result page.").optional(),
6870
+ limit: z20.coerce.number().int().min(1).max(20).describe("Maximum results to return; Slack allows at most 20.").optional(),
6871
+ sort: z20.enum(["score", "timestamp"]).describe("Rank by relevance or timestamp.").optional(),
6872
+ sort_dir: z20.enum(["asc", "desc"]).describe("Sort direction.").optional()
6873
+ }),
6874
+ outputSchema: publicSearchOutputSchema,
6875
+ execute: async ({
6876
+ query,
6877
+ after,
6878
+ before,
6879
+ cursor,
6880
+ limit,
6881
+ sort,
6882
+ sort_dir
6883
+ }) => {
6884
+ try {
6885
+ const normalizedAfter = optionalTimestampSchema.parse(after);
6886
+ const normalizedBefore = optionalTimestampSchema.parse(before);
6887
+ const response = await withSlackRetries(
6888
+ () => getSlackClient().apiCall("assistant.search.context", {
6889
+ action_token: actionToken,
6890
+ query,
6891
+ channel_types: ["public_channel"],
6892
+ content_types: ["messages"],
6893
+ include_bots: true,
6894
+ limit: limit ?? DEFAULT_LIMIT2,
6895
+ ...normalizedAfter !== void 0 ? { after: normalizedAfter } : {},
6896
+ ...normalizedBefore !== void 0 ? { before: normalizedBefore } : {},
6897
+ ...cursor ? { cursor } : {},
6898
+ ...sort ? { sort } : {},
6899
+ ...sort_dir ? { sort_dir } : {}
6900
+ }),
6901
+ 3,
6902
+ {
6903
+ action: "assistant.search.context",
6904
+ idempotent: true
6905
+ }
6906
+ );
6907
+ const messages = (response.results?.messages ?? []).map(normalizeMessage).filter((message) => Boolean(message));
6908
+ const nextCursor = response.results?.next_cursor;
6909
+ return {
6910
+ ok: true,
6911
+ status: "success",
6912
+ query,
6913
+ count: messages.length,
6914
+ messages,
6915
+ ...typeof nextCursor === "string" && nextCursor ? { next_cursor: nextCursor } : {}
6916
+ };
6917
+ } catch (error) {
6918
+ if (error instanceof SlackActionError) {
6919
+ const message = explicitSearchError(error);
6920
+ if (message) {
6921
+ return {
6922
+ ok: false,
6923
+ status: "error",
6924
+ error: message,
6925
+ query,
6926
+ count: 0,
6927
+ messages: []
6928
+ };
6929
+ }
6930
+ }
6931
+ throw error;
6932
+ }
6933
+ }
6934
+ });
6935
+ }
6936
+
6937
+ // src/chat/slack/tools/message-add-reaction.ts
6938
+ import { z as z21 } from "zod";
6819
6939
 
6820
6940
  // src/chat/tools/idempotency.ts
6821
6941
  function stableSerialize(value) {
@@ -6839,8 +6959,8 @@ function createOperationKey(toolName, input) {
6839
6959
  function createSlackMessageAddReactionTool(context, state) {
6840
6960
  return zodTool({
6841
6961
  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(
6962
+ inputSchema: z21.object({
6963
+ emoji: z21.string().min(1).max(64).describe(
6844
6964
  "Slack emoji alias name to react with (for example `thumbsup`, `white_check_mark`, or `thumbsup::skin-tone-6`). Optional surrounding colons are allowed."
6845
6965
  )
6846
6966
  }),
@@ -6891,15 +7011,15 @@ function createSlackMessageAddReactionTool(context, state) {
6891
7011
 
6892
7012
  // src/chat/slack/tools/send-message.ts
6893
7013
  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(
7014
+ import { z as z22 } from "zod";
7015
+ var fileInputSchema = z22.object({
7016
+ path: z22.string().min(1).describe(
6897
7017
  "Sandbox file path to include in the message. Absolute paths and workspace-relative paths are supported."
6898
7018
  ),
6899
- filename: z21.string().min(1).nullable().optional().describe(
7019
+ filename: z22.string().min(1).nullable().optional().describe(
6900
7020
  "Optional filename override shown in Slack. Null is treated as omitted."
6901
7021
  ),
6902
- mimeType: z21.string().min(1).nullable().optional().describe("Optional MIME type override. Null is treated as omitted.")
7022
+ mimeType: z22.string().min(1).nullable().optional().describe("Optional MIME type override. Null is treated as omitted.")
6903
7023
  });
6904
7024
  function hasText(text) {
6905
7025
  return typeof text === "string" && text.trim().length > 0;
@@ -6926,9 +7046,9 @@ function fileOperationInput(files) {
6926
7046
  function createSendMessageTool(context, state, materializeFile) {
6927
7047
  return zodTool({
6928
7048
  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(
7049
+ inputSchema: z22.object({
7050
+ text: z22.string().max(4e4).nullable().optional().describe("Slack mrkdwn text to send. Null is treated as omitted."),
7051
+ files: z22.array(fileInputSchema).min(1).nullable().optional().describe(
6932
7052
  "Sandbox files to include in the message. Null is treated as omitted."
6933
7053
  )
6934
7054
  }),
@@ -7256,13 +7376,13 @@ function storedCanvasUrl(state, canvasId) {
7256
7376
  }
7257
7377
 
7258
7378
  // src/chat/slack/tools/canvas/create.ts
7259
- import { z as z22 } from "zod";
7379
+ import { z as z23 } from "zod";
7260
7380
  function createSlackCanvasCreateTool(context, state) {
7261
7381
  return zodTool({
7262
7382
  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.")
7383
+ inputSchema: z23.object({
7384
+ title: z23.string().min(1).max(160).describe("Canvas title."),
7385
+ markdown: z23.string().min(1).describe("Canvas markdown body content.")
7266
7386
  }),
7267
7387
  outputSchema: juniorToolResultSchema,
7268
7388
  execute: async ({ title, markdown }) => {
@@ -7325,35 +7445,35 @@ function createSlackCanvasCreateTool(context, state) {
7325
7445
  }
7326
7446
 
7327
7447
  // src/chat/slack/tools/canvas/edit.ts
7328
- import { z as z23 } from "zod";
7448
+ import { z as z24 } from "zod";
7329
7449
  function prepareCanvasEditArguments(input) {
7330
7450
  return prepareTextReplacementArguments(input);
7331
7451
  }
7332
- var editReplacementSchema2 = z23.object({
7333
- oldText: z23.string().min(1).describe(
7452
+ var editReplacementSchema2 = z24.object({
7453
+ oldText: z24.string().min(1).describe(
7334
7454
  "Exact Canvas markdown to replace. It must be unique in the current Canvas body and must not overlap another edit."
7335
7455
  ),
7336
- newText: z23.string().describe("Replacement Canvas markdown for this edit.")
7456
+ newText: z24.string().describe("Replacement Canvas markdown for this edit.")
7337
7457
  });
7338
7458
  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()
7459
+ canvas_id: z24.string().optional(),
7460
+ title: z24.string().optional(),
7461
+ permalink: z24.string().optional(),
7462
+ diff: z24.string().optional(),
7463
+ first_changed_line: z24.number().int().positive().optional(),
7464
+ replacements: z24.number().int().nonnegative().optional(),
7465
+ normalized_heading_count: z24.number().int().nonnegative().optional(),
7466
+ summary: z24.string().optional(),
7467
+ deduplicated: z24.boolean().optional()
7348
7468
  }).strict();
7349
7469
  function createSlackCanvasEditTool(state) {
7350
7470
  return zodTool({
7351
7471
  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
7472
  prepareArguments: prepareCanvasEditArguments,
7353
7473
  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(
7474
+ inputSchema: z24.object({
7475
+ canvas: z24.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
7476
+ edits: z24.array(editReplacementSchema2).min(1).describe(
7357
7477
  "Exact replacements matched against the current Canvas body, not incrementally."
7358
7478
  )
7359
7479
  }),
@@ -7431,29 +7551,29 @@ function createSlackCanvasEditTool(state) {
7431
7551
  }
7432
7552
 
7433
7553
  // src/chat/slack/tools/canvas/read.ts
7434
- import { z as z24 } from "zod";
7554
+ import { z as z25 } from "zod";
7435
7555
  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()
7556
+ canvas_id: z25.string().optional(),
7557
+ title: z25.string().optional(),
7558
+ permalink: z25.string().optional(),
7559
+ mimetype: z25.string().optional(),
7560
+ filetype: z25.string().optional(),
7561
+ original_byte_length: z25.number().int().nonnegative().optional(),
7562
+ content: z25.string().optional(),
7563
+ start_line: z25.number().int().positive().optional(),
7564
+ end_line: z25.number().int().nonnegative().optional(),
7565
+ total_lines: z25.number().int().nonnegative().optional()
7446
7566
  }).strict();
7447
7567
  function createSlackCanvasReadTool() {
7448
7568
  return zodTool({
7449
7569
  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
7570
  annotations: { readOnlyHint: true, destructiveHint: false },
7451
- inputSchema: z24.object({
7452
- canvas: z24.string().min(1).describe(
7571
+ inputSchema: z25.object({
7572
+ canvas: z25.string().min(1).describe(
7453
7573
  "Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL (e.g. `https://team.slack.com/docs/T.../F...`)."
7454
7574
  ),
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()
7575
+ offset: z25.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
7576
+ limit: z25.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
7457
7577
  }),
7458
7578
  outputSchema: slackCanvasReadOutputSchema,
7459
7579
  execute: async ({ canvas, offset, limit }) => {
@@ -7510,14 +7630,14 @@ function createSlackCanvasReadTool() {
7510
7630
  }
7511
7631
 
7512
7632
  // src/chat/slack/tools/canvas/write.ts
7513
- import { z as z25 } from "zod";
7633
+ import { z as z26 } from "zod";
7514
7634
  function createSlackCanvasWriteTool(state) {
7515
7635
  return zodTool({
7516
7636
  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
7637
  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.")
7638
+ inputSchema: z26.object({
7639
+ canvas: z26.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
7640
+ content: z26.string().describe("UTF-8 markdown content to write.")
7521
7641
  }),
7522
7642
  outputSchema: juniorToolResultSchema,
7523
7643
  execute: async ({ canvas, content }) => {
@@ -7753,12 +7873,12 @@ async function updateListItem(input) {
7753
7873
  }
7754
7874
 
7755
7875
  // src/chat/slack/id-param.ts
7756
- import { z as z26 } from "zod";
7876
+ import { z as z27 } from "zod";
7757
7877
  function slackChannelIdParam(description) {
7758
- return z26.string().min(1).describe(description);
7878
+ return z27.string().min(1).describe(description);
7759
7879
  }
7760
7880
  function slackUserIdParam(description) {
7761
- return z26.string().min(1).describe(description);
7881
+ return z27.string().min(1).describe(description);
7762
7882
  }
7763
7883
  function parseRequiredSlackChannelIdParam(field, value) {
7764
7884
  const channelId = parseSlackChannelId(value);
@@ -7782,16 +7902,16 @@ function parseRequiredSlackUserIdParam(field, value) {
7782
7902
  }
7783
7903
 
7784
7904
  // src/chat/slack/tools/list/add-items.ts
7785
- import { z as z27 } from "zod";
7905
+ import { z as z28 } from "zod";
7786
7906
  function createSlackListAddItemsTool(state) {
7787
7907
  return zodTool({
7788
7908
  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."),
7909
+ inputSchema: z28.object({
7910
+ items: z28.array(z28.string().min(1)).min(1).max(25).describe("List item titles to create."),
7791
7911
  assignee_user_id: slackUserIdParam(
7792
7912
  "Optional Slack user ID assigned to all created items."
7793
7913
  ).optional(),
7794
- due_date: z27.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
7914
+ due_date: z28.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
7795
7915
  }),
7796
7916
  outputSchema: juniorToolResultSchema,
7797
7917
  execute: async ({ items, assignee_user_id, due_date }) => {
@@ -7845,12 +7965,12 @@ function createSlackListAddItemsTool(state) {
7845
7965
  }
7846
7966
 
7847
7967
  // src/chat/slack/tools/list/create.ts
7848
- import { z as z28 } from "zod";
7968
+ import { z as z29 } from "zod";
7849
7969
  function createSlackListCreateTool(state) {
7850
7970
  return zodTool({
7851
7971
  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.")
7972
+ inputSchema: z29.object({
7973
+ name: z29.string().min(1).max(160).describe("Name for the new Slack list.")
7854
7974
  }),
7855
7975
  outputSchema: juniorToolResultSchema,
7856
7976
  execute: async ({ name }) => {
@@ -7882,13 +8002,13 @@ function createSlackListCreateTool(state) {
7882
8002
  }
7883
8003
 
7884
8004
  // src/chat/slack/tools/list/get-items.ts
7885
- import { z as z29 } from "zod";
8005
+ import { z as z30 } from "zod";
7886
8006
  function createSlackListGetItemsTool(state) {
7887
8007
  return zodTool({
7888
8008
  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
8009
  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()
8010
+ inputSchema: z30.object({
8011
+ limit: z30.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
7892
8012
  }),
7893
8013
  outputSchema: juniorToolResultSchema,
7894
8014
  execute: async ({ limit }) => {
@@ -7913,21 +8033,21 @@ function createSlackListGetItemsTool(state) {
7913
8033
  }
7914
8034
 
7915
8035
  // src/chat/slack/tools/list/update-item.ts
7916
- import { z as z30 } from "zod";
7917
- var booleanInput3 = (description) => z30.preprocess(
8036
+ import { z as z31 } from "zod";
8037
+ var booleanInput3 = (description) => z31.preprocess(
7918
8038
  (value) => value === "true" ? true : value === "false" ? false : value,
7919
- z30.boolean()
8039
+ z31.boolean()
7920
8040
  ).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."),
8041
+ var updateListItemInputSchema = z31.union([
8042
+ z31.object({
8043
+ item_id: z31.string().min(1).describe("ID of the Slack list item to update."),
7924
8044
  completed: booleanInput3("Optional completion status update."),
7925
- title: z30.string().min(1).describe("Optional new item title.").optional()
8045
+ title: z31.string().min(1).describe("Optional new item title.").optional()
7926
8046
  }),
7927
- z30.object({
7928
- item_id: z30.string().min(1).describe("ID of the Slack list item to update."),
8047
+ z31.object({
8048
+ item_id: z31.string().min(1).describe("ID of the Slack list item to update."),
7929
8049
  completed: booleanInput3("Optional completion status update.").optional(),
7930
- title: z30.string().min(1).describe("Optional new item title.")
8050
+ title: z31.string().min(1).describe("Optional new item title.")
7931
8051
  })
7932
8052
  ]);
7933
8053
  function createSlackListUpdateItemTool(state) {
@@ -8003,7 +8123,7 @@ async function checkSlackChannelReadAccess(args) {
8003
8123
  }
8004
8124
 
8005
8125
  // src/chat/slack/tools/thread-read.ts
8006
- import { z as z31 } from "zod";
8126
+ import { z as z32 } from "zod";
8007
8127
 
8008
8128
  // src/chat/slack/tools/slack-message-url.ts
8009
8129
  var SLACK_HOST_PATTERN = /^[a-z0-9-]+\.slack(?:-gov)?\.com$/;
@@ -8176,8 +8296,8 @@ function createSlackThreadReadTool(context, deps = {}) {
8176
8296
  return zodTool({
8177
8297
  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
8298
  annotations: { readOnlyHint: true, destructiveHint: false },
8179
- inputSchema: z31.object({
8180
- url: z31.string().min(1).describe(
8299
+ inputSchema: z32.object({
8300
+ url: z32.string().min(1).describe(
8181
8301
  "Slack message archive URL, e.g. https://workspace.slack.com/archives/C123/p1700000000123456"
8182
8302
  ).optional(),
8183
8303
  channel_id: slackChannelIdParam(
@@ -8186,8 +8306,8 @@ function createSlackThreadReadTool(context, deps = {}) {
8186
8306
  ts: slackTimestampParam(
8187
8307
  "Slack message timestamp (e.g. 1700000000.123456). May be the thread root or any message in the thread."
8188
8308
  ).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()
8309
+ limit: z32.coerce.number().int().min(1).max(1e3).describe("Maximum number of thread messages to fetch.").optional(),
8310
+ max_pages: z32.coerce.number().int().min(1).max(10).describe("Maximum number of Slack API pages to traverse.").optional()
8191
8311
  }),
8192
8312
  outputSchema: juniorToolResultSchema,
8193
8313
  execute: async ({ url, channel_id, ts, limit, max_pages }) => {
@@ -8443,29 +8563,29 @@ async function searchSlackUsers(options) {
8443
8563
  }
8444
8564
 
8445
8565
  // src/chat/slack/tools/user-lookup.ts
8446
- import { z as z32 } from "zod";
8447
- var booleanInput4 = (description) => z32.preprocess(
8566
+ import { z as z33 } from "zod";
8567
+ var booleanInput4 = (description) => z33.preprocess(
8448
8568
  (value) => value === "true" ? true : value === "false" ? false : value,
8449
- z32.boolean()
8569
+ z33.boolean()
8450
8570
  ).describe(description);
8451
8571
  function createSlackUserLookupTool() {
8452
8572
  return zodTool({
8453
8573
  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
8574
  annotations: { readOnlyHint: true, destructiveHint: false },
8455
- inputSchema: z32.object({
8575
+ inputSchema: z33.object({
8456
8576
  user_id: slackUserIdParam(
8457
8577
  "Slack user ID to look up (e.g. U039RR91S). Mutually exclusive with email and query."
8458
8578
  ).optional(),
8459
- email: z32.string().min(3).describe(
8579
+ email: z33.string().min(3).describe(
8460
8580
  "Email address to look up. Mutually exclusive with user_id and query."
8461
8581
  ).optional(),
8462
- query: z32.string().min(2).describe(
8582
+ query: z33.string().min(2).describe(
8463
8583
  "Name to search for (matches against username, display name, real name). Mutually exclusive with user_id and email."
8464
8584
  ).optional(),
8465
- limit: z32.coerce.number().int().min(1).max(20).describe(
8585
+ limit: z33.coerce.number().int().min(1).max(20).describe(
8466
8586
  "Maximum number of results to return for name search. Defaults to 10."
8467
8587
  ).optional(),
8468
- max_pages: z32.coerce.number().int().min(1).max(5).describe(
8588
+ max_pages: z33.coerce.number().int().min(1).max(5).describe(
8469
8589
  "Maximum number of Slack API pages to scan for name search. Defaults to 3."
8470
8590
  ).optional(),
8471
8591
  include_bots: booleanInput4(
@@ -8569,18 +8689,18 @@ function createSlackUserLookupTool() {
8569
8689
  }
8570
8690
 
8571
8691
  // src/chat/tools/system-time.ts
8572
- import { z as z33 } from "zod";
8692
+ import { z as z34 } from "zod";
8573
8693
  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()
8694
+ unix_ms: z34.number(),
8695
+ iso_utc: z34.string(),
8696
+ iso_local: z34.string(),
8697
+ timezone_offset_minutes: z34.number()
8578
8698
  });
8579
8699
  function createSystemTimeTool() {
8580
8700
  return zodTool({
8581
8701
  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
8702
  annotations: { readOnlyHint: true, destructiveHint: false },
8583
- inputSchema: z33.object({}),
8703
+ inputSchema: z34.object({}),
8584
8704
  outputSchema: systemTimeOutputSchema,
8585
8705
  privateTraceResult: (result) => ({
8586
8706
  ok: result.ok,
@@ -8609,10 +8729,10 @@ function createSystemTimeTool() {
8609
8729
  }
8610
8730
 
8611
8731
  // src/chat/tools/handoff/tool.ts
8612
- import { z as z34 } from "zod";
8732
+ import { z as z35 } from "zod";
8613
8733
  var HANDOFF_TOOL_NAME = "handoff";
8614
8734
  function createHandoffTool(handoff) {
8615
- const profileSchema = z34.enum(handoff.profiles);
8735
+ const profileSchema = z35.enum(handoff.profiles);
8616
8736
  const defaultProfile = handoff.profiles[0];
8617
8737
  const handoffResultSchema = juniorToolResultSchema.extend({
8618
8738
  model_profile: profileSchema
@@ -8621,7 +8741,7 @@ function createHandoffTool(handoff) {
8621
8741
  return zodTool({
8622
8742
  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
8743
  executionMode: "sequential",
8624
- inputSchema: z34.object({
8744
+ inputSchema: z35.object({
8625
8745
  profile: profileSchema.nullish().describe(
8626
8746
  "Named model profile to use for the rest of the conversation; omit or pass null for the default"
8627
8747
  )
@@ -8640,7 +8760,7 @@ function createHandoffTool(handoff) {
8640
8760
  }
8641
8761
 
8642
8762
  // src/chat/tools/web/fetch-tool.ts
8643
- import { z as z35 } from "zod";
8763
+ import { z as z36 } from "zod";
8644
8764
 
8645
8765
  // src/chat/tools/web/constants.ts
8646
8766
  var USER_AGENT = "junior-bot/0.1";
@@ -9087,9 +9207,9 @@ function createWebFetchTool(hooks, options = {}) {
9087
9207
  destructiveHint: false,
9088
9208
  openWorldHint: true
9089
9209
  },
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()
9210
+ inputSchema: z36.object({
9211
+ url: z36.string().min(1).describe("HTTP(S) URL to fetch."),
9212
+ max_chars: z36.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
9093
9213
  }),
9094
9214
  outputSchema: juniorToolResultSchema,
9095
9215
  execute: async ({ url, max_chars }) => {
@@ -9156,7 +9276,7 @@ function createWebFetchTool(hooks, options = {}) {
9156
9276
  }
9157
9277
 
9158
9278
  // src/chat/tools/web/search.ts
9159
- import { z as z36 } from "zod";
9279
+ import { z as z37 } from "zod";
9160
9280
  import { generateText } from "ai";
9161
9281
  import { createGatewayProvider } from "@ai-sdk/gateway";
9162
9282
  import { getModel } from "@earendil-works/pi-ai/compat";
@@ -9207,9 +9327,9 @@ function createWebSearchTool(override) {
9207
9327
  destructiveHint: false,
9208
9328
  openWorldHint: true
9209
9329
  },
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()
9330
+ inputSchema: z37.object({
9331
+ query: z37.string().min(1).max(500).describe("Search query."),
9332
+ max_results: z37.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
9213
9333
  }),
9214
9334
  outputSchema: juniorToolResultSchema,
9215
9335
  execute: async ({ query, max_results }) => {
@@ -9279,14 +9399,14 @@ function createWebSearchTool(override) {
9279
9399
  }
9280
9400
 
9281
9401
  // src/chat/tools/sandbox/write-file.ts
9282
- import { z as z37 } from "zod";
9402
+ import { z as z38 } from "zod";
9283
9403
  function createWriteFileTool() {
9284
9404
  return zodTool({
9285
9405
  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
9406
  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.")
9407
+ inputSchema: z38.object({
9408
+ path: z38.string().min(1).describe("Path to write in the sandbox workspace."),
9409
+ content: z38.string().describe("UTF-8 file content to write.")
9290
9410
  }),
9291
9411
  outputSchema: juniorToolResultSchema,
9292
9412
  execute: async () => {
@@ -9389,6 +9509,11 @@ function createTools(availableSkills, hooks = {}, context) {
9389
9509
  context.conversationId
9390
9510
  );
9391
9511
  }
9512
+ if (context.source.platform === "slack" && context.slackActionToken) {
9513
+ tools.slackPublicSearch = createSlackPublicSearchTool(
9514
+ context.slackActionToken
9515
+ );
9516
+ }
9392
9517
  tools.slackUserLookup = createSlackUserLookupTool();
9393
9518
  tools.slackListCreate = createSlackListCreateTool(state);
9394
9519
  tools.slackListAddItems = createSlackListAddItemsTool(state);
@@ -10001,59 +10126,59 @@ async function startOAuthFlow(provider, input) {
10001
10126
  }
10002
10127
 
10003
10128
  // src/chat/sandbox/egress/schemas.ts
10004
- import { z as z38 } from "zod";
10129
+ import { z as z39 } from "zod";
10005
10130
  import {
10006
10131
  pluginAuthorizationSchema,
10007
10132
  pluginCredentialHeaderTransformSchema,
10008
10133
  pluginGrantSchema,
10009
10134
  pluginProviderAccountSchema
10010
10135
  } 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"]);
10136
+ var finiteNumberSchema = z39.number().refine(Number.isFinite);
10137
+ var httpStatusSchema = z39.number().int().min(100).max(599);
10138
+ var providerNameSchema = z39.string().regex(/^[a-z][a-z0-9-]*$/);
10139
+ var credentialSignalKindSchema = z39.enum(["auth_required", "unavailable"]);
10015
10140
  var sandboxEgressGrantSchema = pluginGrantSchema;
10016
- var sandboxEgressCredentialContextSchema = z38.object({
10141
+ var sandboxEgressCredentialContextSchema = z39.object({
10017
10142
  credentials: credentialContextSchema,
10018
- egressId: z38.string().min(1),
10143
+ egressId: z39.string().min(1),
10019
10144
  expiresAtMs: finiteNumberSchema,
10020
- contextId: z38.string().min(1)
10145
+ contextId: z39.string().min(1)
10021
10146
  }).strict();
10022
- var sandboxEgressCredentialLeaseSchema = z38.object({
10147
+ var sandboxEgressCredentialLeaseSchema = z39.object({
10023
10148
  account: pluginProviderAccountSchema.optional(),
10024
10149
  authorization: pluginAuthorizationSchema.optional(),
10025
10150
  grant: sandboxEgressGrantSchema,
10026
10151
  provider: providerNameSchema,
10027
- expiresAt: z38.string().min(1),
10028
- headerTransforms: z38.array(pluginCredentialHeaderTransformSchema).min(1)
10152
+ expiresAt: z39.string().min(1),
10153
+ headerTransforms: z39.array(pluginCredentialHeaderTransformSchema).min(1)
10029
10154
  }).strict();
10030
- var sandboxEgressAuthRequiredSignalSchema = z38.object({
10155
+ var sandboxEgressAuthRequiredSignalSchema = z39.object({
10031
10156
  authorization: pluginAuthorizationSchema.optional(),
10032
10157
  grant: sandboxEgressGrantSchema,
10033
10158
  kind: credentialSignalKindSchema.default("auth_required"),
10034
10159
  provider: providerNameSchema,
10035
- message: z38.string().optional(),
10160
+ message: z39.string().optional(),
10036
10161
  createdAtMs: finiteNumberSchema
10037
10162
  }).strict().superRefine((signal, ctx) => {
10038
10163
  if (signal.authorization && signal.authorization.provider !== signal.provider) {
10039
10164
  ctx.addIssue({
10040
- code: z38.ZodIssueCode.custom,
10165
+ code: z39.ZodIssueCode.custom,
10041
10166
  message: "Auth signal authorization provider must match provider",
10042
10167
  path: ["authorization", "provider"]
10043
10168
  });
10044
10169
  }
10045
10170
  });
10046
- var sandboxEgressPermissionDeniedSignalSchema = z38.object({
10171
+ var sandboxEgressPermissionDeniedSignalSchema = z39.object({
10047
10172
  account: pluginProviderAccountSchema.optional(),
10048
- acceptedPermissions: z38.string().optional(),
10173
+ acceptedPermissions: z39.string().optional(),
10049
10174
  grant: sandboxEgressGrantSchema,
10050
- message: z38.string().min(1),
10175
+ message: z39.string().min(1),
10051
10176
  provider: providerNameSchema,
10052
- source: z38.literal("upstream"),
10053
- sso: z38.string().optional(),
10177
+ source: z39.literal("upstream"),
10178
+ sso: z39.string().optional(),
10054
10179
  status: httpStatusSchema,
10055
- upstreamHost: z38.string().min(1),
10056
- upstreamPath: z38.string().min(1),
10180
+ upstreamHost: z39.string().min(1),
10181
+ upstreamPath: z39.string().min(1),
10057
10182
  createdAtMs: finiteNumberSchema
10058
10183
  }).strict();
10059
10184
  function parseSandboxEgressAuthRequiredSignal(value) {
@@ -10314,15 +10439,15 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, trac
10314
10439
  }
10315
10440
 
10316
10441
  // src/chat/tools/execute-tool.ts
10317
- import { z as z39 } from "zod";
10442
+ import { z as z40 } from "zod";
10318
10443
  var EXECUTE_TOOL_NAME = "executeTool";
10319
10444
  function createExecuteToolTool() {
10320
10445
  return zodTool({
10321
10446
  description: "Execute any catalog tool by exact tool_name from searchTools. Put tool-specific parameters inside arguments.",
10322
10447
  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(
10448
+ inputSchema: z40.object({
10449
+ tool_name: z40.string().min(1).describe("Exact catalog tool_name returned by searchTools."),
10450
+ arguments: z40.record(z40.string(), z40.unknown()).describe(
10326
10451
  'Arguments matching the selected catalog tool schema, for example { "query": "..." }.'
10327
10452
  ).optional()
10328
10453
  }).strict(),
@@ -10362,42 +10487,42 @@ function planToolExposure(tools) {
10362
10487
  }
10363
10488
 
10364
10489
  // src/chat/tools/search-tools.ts
10365
- import { z as z40 } from "zod";
10490
+ import { z as z41 } from "zod";
10366
10491
  var SEARCH_TOOLS_NAME = "searchTools";
10367
10492
  var DEFAULT_MAX_RESULTS2 = 5;
10368
10493
  var MAX_RESULTS3 = 20;
10369
10494
  var MODEL_VISIBLE_DESCRIPTION_CAP = 180;
10370
- var searchToolsSourceSchema = z40.object({
10371
- id: z40.string(),
10372
- description: z40.string()
10495
+ var searchToolsSourceSchema = z41.object({
10496
+ id: z41.string(),
10497
+ description: z41.string()
10373
10498
  }).strict();
10374
- var toolCallExampleSchema = z40.object({
10375
- tool_name: z40.string(),
10376
- arguments: z40.record(z40.string(), z40.string())
10499
+ var toolCallExampleSchema = z41.object({
10500
+ tool_name: z41.string(),
10501
+ arguments: z41.record(z41.string(), z41.string())
10377
10502
  }).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(),
10503
+ var searchToolsToolSchema = z41.object({
10504
+ tool_name: z41.string(),
10505
+ description: z41.string(),
10506
+ exposure: z41.enum(["direct", "deferred", "modelOnly", "hidden"]),
10507
+ source: z41.string().optional(),
10508
+ signature: z41.string(),
10384
10509
  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())
10510
+ input_schema: z41.unknown(),
10511
+ input_schema_summary: z41.string(),
10512
+ call_notes: z41.array(z41.string()),
10513
+ annotations: z41.record(z41.string(), z41.unknown())
10389
10514
  }).strict();
10390
10515
  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"),
10516
+ query: z41.string().nullable(),
10517
+ source: z41.string().nullable(),
10518
+ sources: z41.array(searchToolsSourceSchema),
10519
+ total_catalog_tools: z41.number().int().nonnegative(),
10520
+ total_eligible_tools: z41.number().int().nonnegative(),
10521
+ total_matches: z41.number().int().nonnegative(),
10522
+ returned_tools: z41.number().int().nonnegative(),
10523
+ execution_tool: z41.literal("executeTool"),
10399
10524
  execution_example: toolCallExampleSchema,
10400
- tools: z40.array(searchToolsToolSchema)
10525
+ tools: z41.array(searchToolsToolSchema)
10401
10526
  }).strict();
10402
10527
  function normalize2(value) {
10403
10528
  return value.toLowerCase().replace(/[^a-z0-9_]+/g, " ").trim();
@@ -10589,14 +10714,14 @@ function createSearchToolsTool(catalogTools) {
10589
10714
  return zodTool({
10590
10715
  description: renderSearchToolsDescription(knownSources),
10591
10716
  annotations: { readOnlyHint: true, destructiveHint: false },
10592
- inputSchema: z40.object({
10593
- query: z40.string().nullable().describe(
10717
+ inputSchema: z41.object({
10718
+ query: z41.string().nullable().describe(
10594
10719
  "Optional search terms describing the tool, owner, action, or arguments needed. Empty string lists catalog tools."
10595
10720
  ).optional(),
10596
- source: z40.string().nullable().describe(
10721
+ source: z41.string().nullable().describe(
10597
10722
  "Optional source id to search within, such as a plugin source returned in sources."
10598
10723
  ).optional(),
10599
- max_results: z40.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
10724
+ max_results: z41.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
10600
10725
  }).strict(),
10601
10726
  outputSchema: searchToolsOutputSchema,
10602
10727
  privateTraceResult: (result) => ({
@@ -11306,6 +11431,19 @@ function findInErrorChain(error, predicate) {
11306
11431
  }
11307
11432
  return false;
11308
11433
  }
11434
+ function isRecord5(value) {
11435
+ return typeof value === "object" && value !== null;
11436
+ }
11437
+ function isInvalidSandboxSessionError(error) {
11438
+ if (!isRecord5(error)) {
11439
+ return false;
11440
+ }
11441
+ if (isRecord5(error.json) && error.json.invalidToken === true) {
11442
+ return true;
11443
+ }
11444
+ const response = error.response;
11445
+ return isRecord5(response) && response.status === 403 && typeof response.url === "string" && response.url.includes("/sandboxes/sessions");
11446
+ }
11309
11447
  function getFirstErrorMessage(error) {
11310
11448
  const seen = /* @__PURE__ */ new Set();
11311
11449
  let current = error;
@@ -11327,9 +11465,12 @@ function isAlreadyExistsError(error) {
11327
11465
  }
11328
11466
  function isSandboxUnavailableError(error) {
11329
11467
  return findInErrorChain(error, (candidate) => {
11468
+ if (isInvalidSandboxSessionError(candidate)) {
11469
+ return true;
11470
+ }
11330
11471
  const details = getSandboxErrorDetails(candidate);
11331
11472
  const searchable = `${details.searchableText} ${details.summary}`.toLowerCase();
11332
- return searchable.includes("sandbox_stopped") || searchable.includes("status=410") || searchable.includes("status code 410") || searchable.includes("no longer available");
11473
+ return searchable.includes("sandbox_stopped") || searchable.includes("status=410") || searchable.includes("status code 410") || searchable.includes("no longer available") || searchable.includes("stream was closed and is not accepting commands");
11333
11474
  });
11334
11475
  }
11335
11476
  function isSnapshottingError(error) {
@@ -14642,7 +14783,8 @@ async function wireAgentTools(args) {
14642
14783
  ...commonToolRuntimeContext,
14643
14784
  destination: toolDestination,
14644
14785
  actor: args.currentActor?.platform === "slack" ? args.currentActor : void 0,
14645
- source: runSource
14786
+ source: runSource,
14787
+ slackActionToken: args.routing.slackActionToken
14646
14788
  };
14647
14789
  } else {
14648
14790
  if (toolDestination.platform !== "local") {
@@ -14957,9 +15099,7 @@ function createResumeState(args) {
14957
15099
  }
14958
15100
  };
14959
15101
  }
14960
- throw new Error(
14961
- sessionRecord.errorMessage ?? (error instanceof Error ? error.message : String(error))
14962
- );
15102
+ throw new TurnSliceLimitExceededError(botConfig.maxSlicesPerTurn);
14963
15103
  }
14964
15104
  if (error instanceof AuthorizationPauseError) {
14965
15105
  const usage = args2.currentUsage ?? (resumeMessages.length > 0 ? extractSliceUsage(resumeMessages, beforeMessageCount) : void 0);
@@ -15340,9 +15480,9 @@ async function executeAgentRun(request) {
15340
15480
  const conversationPrivacy = resolveConversationPrivacy({
15341
15481
  channelId: request.routing.correlation?.channelId,
15342
15482
  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
15483
+ // Destination visibility is provider-neutral. Slack event context remains
15484
+ // a compatibility fallback for callers that have not projected it yet.
15485
+ visibility: request.routing.destinationVisibility ?? request.routing.slackConversation?.visibility
15346
15486
  });
15347
15487
  return runWithConversationPrivacy(
15348
15488
  conversationPrivacy ?? "private",