@sentry/junior 0.90.0 → 0.91.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,11 +30,11 @@ import {
30
30
  buildSystemPrompt,
31
31
  buildTurnContextPrompt,
32
32
  containsNoReplyMarker,
33
- extractCurrentInstructionBody,
33
+ formatSlackLink,
34
34
  isNoReplyMarker,
35
35
  renderCurrentInstruction,
36
36
  stripNoReplyMarker
37
- } from "./chunk-PHZHJTCK.js";
37
+ } from "./chunk-PIB4EOW6.js";
38
38
  import {
39
39
  escapeXml,
40
40
  loadConnectedMcpProviders,
@@ -1347,15 +1347,12 @@ async function restoreSkillRuntime(args) {
1347
1347
  }
1348
1348
 
1349
1349
  // src/chat/agent/prompt.ts
1350
- import { z as z2 } from "zod";
1351
1350
  var MAX_INLINE_ATTACHMENT_BASE64_CHARS = 12e4;
1352
1351
  var MAX_ROUTER_ATTACHMENT_PREVIEW_CHARS = 2e3;
1353
- var legacyStoredTextPartSchema = z2.object({
1354
- text: z2.string(),
1355
- type: z2.literal("text")
1356
- }).strict();
1357
1352
  function isStructuredThreadContext(context) {
1358
- return /^<thread-(compactions|transcript)>/.test(context);
1353
+ return /^<(recent-thread-messages|thread-(compactions|transcript))>/.test(
1354
+ context
1355
+ );
1359
1356
  }
1360
1357
  function renderThreadContextForPrompt(context) {
1361
1358
  if (isStructuredThreadContext(context)) {
@@ -1363,9 +1360,9 @@ function renderThreadContextForPrompt(context) {
1363
1360
  }
1364
1361
  return ["<thread-background>", context, "</thread-background>"].join("\n");
1365
1362
  }
1366
- function buildUserTurnText(userInput, conversationContext) {
1363
+ function buildUserTurnText(userInput, conversationContext, actor) {
1367
1364
  const trimmedContext = conversationContext?.trim();
1368
- const currentInstruction = renderCurrentInstruction(userInput);
1365
+ const currentInstruction = renderCurrentInstruction(userInput, actor);
1369
1366
  if (!trimmedContext) {
1370
1367
  return currentInstruction;
1371
1368
  }
@@ -1498,10 +1495,11 @@ function buildUserTurnInput(args) {
1498
1495
  return { routerBlocks, userContentParts };
1499
1496
  }
1500
1497
  function buildPromptInput(input) {
1501
- const promptConversationContext = input.piMessages && input.piMessages.length > 0 ? void 0 : input.conversationContext;
1498
+ const promptConversationContext = input.piMessages && input.piMessages.length > 0 && !input.includeConversationContextWithPiMessages ? void 0 : input.conversationContext;
1502
1499
  const userTurnText = buildUserTurnText(
1503
1500
  input.messageText,
1504
- promptConversationContext
1501
+ promptConversationContext,
1502
+ input.actor
1505
1503
  );
1506
1504
  return buildUserTurnInput({
1507
1505
  omittedImageAttachmentCount: input.omittedImageAttachmentCount ?? 0,
@@ -1511,7 +1509,7 @@ function buildPromptInput(input) {
1511
1509
  }
1512
1510
  function buildSteeringPiMessage(message) {
1513
1511
  const { userContentParts } = buildUserTurnInput({
1514
- userTurnText: buildUserTurnText(message.text),
1512
+ userTurnText: buildUserTurnText(message.text, void 0, message.actor),
1515
1513
  userAttachments: message.userAttachments,
1516
1514
  omittedImageAttachmentCount: message.omittedImageAttachmentCount ?? 0
1517
1515
  });
@@ -1538,35 +1536,7 @@ function withoutTrailingUncheckpointedUserPrompt(messages, userContentParts) {
1538
1536
  return messages.slice(0, -1);
1539
1537
  }
1540
1538
  function userPromptContentMatches(storedContent, currentContent) {
1541
- if (JSON.stringify(storedContent) === JSON.stringify(currentContent)) {
1542
- return true;
1543
- }
1544
- if (!Array.isArray(storedContent)) {
1545
- return false;
1546
- }
1547
- if (storedContent.length !== currentContent.length) {
1548
- return false;
1549
- }
1550
- return storedContent.every((storedPart, index) => {
1551
- const currentPart = currentContent[index];
1552
- if (index === 0 && currentPart?.type === "text") {
1553
- const legacyTextPart = legacyStoredTextPartSchema.safeParse(storedPart);
1554
- if (legacyTextPart.success) {
1555
- return legacyTextPartMatchesCurrentText(
1556
- legacyTextPart.data.text,
1557
- currentPart.text
1558
- );
1559
- }
1560
- }
1561
- return JSON.stringify(storedPart) === JSON.stringify(currentPart);
1562
- });
1563
- }
1564
- function legacyTextPartMatchesCurrentText(storedText, currentText) {
1565
- const storedInstructionBody = extractCurrentInstructionBody(storedText);
1566
- if (storedInstructionBody !== void 0) {
1567
- return renderCurrentInstruction(storedInstructionBody) === currentText;
1568
- }
1569
- return renderCurrentInstruction(storedText) === currentText;
1539
+ return JSON.stringify(storedContent) === JSON.stringify(currentContent);
1570
1540
  }
1571
1541
  async function assemblePrompt(args) {
1572
1542
  const source = args.routing.source;
@@ -2698,30 +2668,30 @@ function serializeMcpPayload(payload, privacy) {
2698
2668
  }
2699
2669
 
2700
2670
  // src/chat/tools/sandbox/bash.ts
2701
- import { z as z5 } from "zod";
2671
+ import { z as z4 } from "zod";
2702
2672
 
2703
2673
  // src/chat/tool-support/structured-result.ts
2704
- import { z as z3 } from "zod";
2705
- var juniorToolContinuationSchema = z3.object({
2706
- arguments: z3.record(z3.string(), z3.unknown()),
2707
- reason: z3.string().min(1).optional()
2674
+ import { z as z2 } from "zod";
2675
+ var juniorToolContinuationSchema = z2.object({
2676
+ arguments: z2.record(z2.string(), z2.unknown()),
2677
+ reason: z2.string().min(1).optional()
2708
2678
  }).strict();
2709
2679
  var juniorToolBoundContinuationSchema = juniorToolContinuationSchema.extend({
2710
- tool_name: z3.string().min(1)
2680
+ tool_name: z2.string().min(1)
2711
2681
  });
2712
- var juniorToolErrorSchema = z3.object({
2713
- kind: z3.string().min(1),
2714
- message: z3.string().min(1),
2715
- retryable: z3.boolean().optional()
2682
+ var juniorToolErrorSchema = z2.object({
2683
+ kind: z2.string().min(1),
2684
+ message: z2.string().min(1),
2685
+ retryable: z2.boolean().optional()
2716
2686
  }).strict();
2717
- var juniorToolResultSchema = z3.object({
2718
- ok: z3.boolean(),
2719
- status: z3.enum(["success", "error"]),
2720
- target: z3.string().min(1).optional(),
2721
- data: z3.unknown().optional(),
2722
- truncated: z3.boolean().optional(),
2687
+ var juniorToolResultSchema = z2.object({
2688
+ ok: z2.boolean(),
2689
+ status: z2.enum(["success", "error"]),
2690
+ target: z2.string().min(1).optional(),
2691
+ data: z2.unknown().optional(),
2692
+ truncated: z2.boolean().optional(),
2723
2693
  continuation: juniorToolContinuationSchema.optional(),
2724
- error: z3.union([juniorToolErrorSchema, z3.string()]).optional()
2694
+ error: z2.union([juniorToolErrorSchema, z2.string()]).optional()
2725
2695
  }).passthrough();
2726
2696
  var juniorToolResultWithBoundContinuationSchema = juniorToolResultSchema.extend({
2727
2697
  continuation: juniorToolBoundContinuationSchema.optional()
@@ -2768,7 +2738,7 @@ function makeStructuredToolResult(details, options = {}) {
2768
2738
  }
2769
2739
 
2770
2740
  // src/chat/tool-support/zod-tool.ts
2771
- import { z as z4 } from "zod";
2741
+ import { z as z3 } from "zod";
2772
2742
 
2773
2743
  // src/chat/tools/execution/tool-input-error.ts
2774
2744
  var ToolInputError = class extends Error {
@@ -2802,7 +2772,7 @@ function zodTool(definition) {
2802
2772
  const { inputSchema, outputSchema, prepareArguments, execute, ...toolDef } = definition;
2803
2773
  let modelInputSchema;
2804
2774
  try {
2805
- modelInputSchema = z4.toJSONSchema(inputSchema);
2775
+ modelInputSchema = z3.toJSONSchema(inputSchema);
2806
2776
  } catch (error) {
2807
2777
  throw new TypeError(
2808
2778
  "zodTool() inputSchema must be representable as JSON Schema.",
@@ -2812,7 +2782,7 @@ function zodTool(definition) {
2812
2782
  let modelOutputSchema;
2813
2783
  if (outputSchema) {
2814
2784
  try {
2815
- modelOutputSchema = z4.toJSONSchema(outputSchema);
2785
+ modelOutputSchema = z3.toJSONSchema(outputSchema);
2816
2786
  } catch (error) {
2817
2787
  throw new TypeError(
2818
2788
  "zodTool() outputSchema must be representable as JSON Schema.",
@@ -2854,9 +2824,9 @@ function zodTool(definition) {
2854
2824
  function createBashTool() {
2855
2825
  return zodTool({
2856
2826
  description: "Run a bash command inside the isolated sandbox workspace. Use this for repository inspection/execution tasks that need shell access. Do not use for network-sensitive or destructive actions unless explicitly required.",
2857
- inputSchema: z5.object({
2858
- command: z5.string().min(1).describe("Bash command to run inside the sandbox."),
2859
- timeoutMs: z5.coerce.number().int().min(1e3).describe(
2827
+ inputSchema: z4.object({
2828
+ command: z4.string().min(1).describe("Bash command to run inside the sandbox."),
2829
+ timeoutMs: z4.coerce.number().int().min(1e3).describe(
2860
2830
  "Optional command timeout in milliseconds. Use for commands that may hang."
2861
2831
  ).optional()
2862
2832
  }),
@@ -3230,7 +3200,7 @@ function validateAndApplyTextEdits(content, edits, targetName) {
3230
3200
  }
3231
3201
 
3232
3202
  // src/chat/tools/sandbox/edit-file.ts
3233
- import { z as z6 } from "zod";
3203
+ import { z as z5 } from "zod";
3234
3204
  function prepareEditFileArguments(input) {
3235
3205
  return prepareTextReplacementArguments(input);
3236
3206
  }
@@ -3328,20 +3298,20 @@ async function editFile(params) {
3328
3298
  replacements: params.edits.length
3329
3299
  });
3330
3300
  }
3331
- var editReplacementSchema = z6.object({
3332
- oldText: z6.string().min(1).describe(
3301
+ var editReplacementSchema = z5.object({
3302
+ oldText: z5.string().min(1).describe(
3333
3303
  "Exact text to replace. It must be unique in the original file and must not overlap another edit."
3334
3304
  ),
3335
- newText: z6.string().describe("Replacement text for this edit.")
3305
+ newText: z5.string().describe("Replacement text for this edit.")
3336
3306
  });
3337
3307
  function createEditFileTool() {
3338
3308
  return zodTool({
3339
3309
  description: "Edit one sandbox workspace file with exact text replacements. Use for precise changes to existing files; prefer this over writeFile for targeted changes. Each oldText must match exactly, be unique, and not overlap another edit. Returns a diff. Multiple changes to the same file: use one edits[] call.",
3340
3310
  prepareArguments: prepareEditFileArguments,
3341
3311
  executionMode: "sequential",
3342
- inputSchema: z6.object({
3343
- path: z6.string().min(1).describe("Path to edit in the sandbox workspace."),
3344
- edits: z6.array(editReplacementSchema).min(1).describe(
3312
+ inputSchema: z5.object({
3313
+ path: z5.string().min(1).describe("Path to edit in the sandbox workspace."),
3314
+ edits: z5.array(editReplacementSchema).min(1).describe(
3345
3315
  "Exact replacements matched against the original file, not incrementally."
3346
3316
  )
3347
3317
  }),
@@ -3356,7 +3326,7 @@ function createEditFileTool() {
3356
3326
 
3357
3327
  // src/chat/tools/sandbox/find-files.ts
3358
3328
  import path3 from "path";
3359
- import { z as z7 } from "zod";
3329
+ import { z as z6 } from "zod";
3360
3330
  var DEFAULT_FIND_LIMIT = 1e3;
3361
3331
  async function findFiles(params) {
3362
3332
  if (!params.pattern.trim()) {
@@ -3416,14 +3386,14 @@ function createFindFilesTool() {
3416
3386
  return zodTool({
3417
3387
  description: "Find sandbox workspace files by glob pattern. Returns bounded paths relative to the search root and skips dependency/cache directories.",
3418
3388
  annotations: { readOnlyHint: true, destructiveHint: false },
3419
- inputSchema: z7.object({
3420
- pattern: z7.string().min(1).describe(
3389
+ inputSchema: z6.object({
3390
+ pattern: z6.string().min(1).describe(
3421
3391
  "Glob pattern to match, for example '*.ts', '**/*.json', or 'src/**/*.test.ts'."
3422
3392
  ),
3423
- path: z7.string().min(1).describe(
3393
+ path: z6.string().min(1).describe(
3424
3394
  "Directory or file path in the sandbox workspace. Defaults to the workspace root."
3425
3395
  ).optional(),
3426
- limit: z7.coerce.number().int().min(1).describe("Maximum number of file paths to return. Defaults to 1000.").optional()
3396
+ limit: z6.coerce.number().int().min(1).describe("Maximum number of file paths to return. Defaults to 1000.").optional()
3427
3397
  }),
3428
3398
  outputSchema: juniorToolResultSchema,
3429
3399
  execute: async () => {
@@ -3436,12 +3406,12 @@ function createFindFilesTool() {
3436
3406
 
3437
3407
  // src/chat/tools/sandbox/grep.ts
3438
3408
  import path4 from "path";
3439
- import { z as z8 } from "zod";
3409
+ import { z as z7 } from "zod";
3440
3410
  var DEFAULT_GREP_LIMIT = 100;
3441
3411
  var MAX_GREP_LINE_CHARS = 500;
3442
- var booleanInput = (description) => z8.preprocess(
3412
+ var booleanInput = (description) => z7.preprocess(
3443
3413
  (value) => value === "true" ? true : value === "false" ? false : value,
3444
- z8.boolean()
3414
+ z7.boolean()
3445
3415
  ).describe(description);
3446
3416
  function truncateGrepLine(value) {
3447
3417
  if (value.length <= MAX_GREP_LINE_CHARS) {
@@ -3590,20 +3560,20 @@ function createGrepTool() {
3590
3560
  return zodTool({
3591
3561
  description: "Search sandbox workspace file contents. Returns bounded matching lines with file paths and line numbers. Respects path/glob filters and includes truncation notices.",
3592
3562
  annotations: { readOnlyHint: true, destructiveHint: false },
3593
- inputSchema: z8.object({
3594
- pattern: z8.string().min(1).describe("Regex pattern or literal text to search for."),
3595
- path: z8.string().min(1).describe(
3563
+ inputSchema: z7.object({
3564
+ pattern: z7.string().min(1).describe("Regex pattern or literal text to search for."),
3565
+ path: z7.string().min(1).describe(
3596
3566
  "Directory or file path in the sandbox workspace. Defaults to the workspace root."
3597
3567
  ).optional(),
3598
- glob: z8.string().min(1).describe("Optional glob filter such as '*.ts' or '**/*.test.ts'.").optional(),
3568
+ glob: z7.string().min(1).describe("Optional glob filter such as '*.ts' or '**/*.test.ts'.").optional(),
3599
3569
  ignoreCase: booleanInput(
3600
3570
  "Whether matching should ignore case."
3601
3571
  ).optional(),
3602
3572
  literal: booleanInput(
3603
3573
  "Treat pattern as literal text instead of regex."
3604
3574
  ).optional(),
3605
- context: z8.coerce.number().int().min(0).describe("Number of surrounding context lines to include.").optional(),
3606
- limit: z8.coerce.number().int().min(1).describe("Maximum matches to return. Defaults to 100.").optional()
3575
+ context: z7.coerce.number().int().min(0).describe("Number of surrounding context lines to include.").optional(),
3576
+ limit: z7.coerce.number().int().min(1).describe("Maximum matches to return. Defaults to 100.").optional()
3607
3577
  }),
3608
3578
  outputSchema: juniorToolResultSchema,
3609
3579
  execute: async () => {
@@ -3721,7 +3691,7 @@ async function readSandboxFileUpload(sandbox, input) {
3721
3691
 
3722
3692
  // src/chat/tools/sandbox/list-dir.ts
3723
3693
  import path6 from "path";
3724
- import { z as z9 } from "zod";
3694
+ import { z as z8 } from "zod";
3725
3695
  var DEFAULT_LIST_LIMIT = 500;
3726
3696
  async function listDir(params) {
3727
3697
  const dirPath = resolveWorkspacePath(params.path);
@@ -3802,11 +3772,11 @@ function createListDirTool() {
3802
3772
  return zodTool({
3803
3773
  description: "List a sandbox workspace directory. Returns sorted entries with '/' suffixes for directories and bounded truncation notices.",
3804
3774
  annotations: { readOnlyHint: true, destructiveHint: false },
3805
- inputSchema: z9.object({
3806
- path: z9.string().min(1).describe(
3775
+ inputSchema: z8.object({
3776
+ path: z8.string().min(1).describe(
3807
3777
  "Directory path in the sandbox workspace. Defaults to the workspace root."
3808
3778
  ).optional(),
3809
- limit: z9.coerce.number().int().min(1).describe("Maximum entries to return. Defaults to 500.").optional()
3779
+ limit: z8.coerce.number().int().min(1).describe("Maximum entries to return. Defaults to 500.").optional()
3810
3780
  }),
3811
3781
  outputSchema: juniorToolResultSchema,
3812
3782
  execute: async () => {
@@ -3818,7 +3788,7 @@ function createListDirTool() {
3818
3788
  }
3819
3789
 
3820
3790
  // src/chat/tools/web/image-generate.ts
3821
- import { z as z10 } from "zod";
3791
+ import { z as z9 } from "zod";
3822
3792
  var DEFAULT_IMAGE_MODEL = "google/gemini-3-pro-image";
3823
3793
  var ENRICHMENT_SYSTEM_PROMPT = `You are an image prompt enrichment agent. Your job is to rewrite image generation requests to reflect a specific visual identity and mood.
3824
3794
 
@@ -3879,8 +3849,8 @@ function parseImageGenerationError(status, body, model) {
3879
3849
  function createImageGenerateTool(hooks, options = {}, deps = {}) {
3880
3850
  return zodTool({
3881
3851
  description: "Generate images from a prompt. Use when the user wants to visually show or represent something \u2014 feelings, concepts, art, humor, or any visual idea. Also use for explicit image creation requests.",
3882
- inputSchema: z10.object({
3883
- prompt: z10.string().min(1).max(4e3).describe("Image generation prompt.")
3852
+ inputSchema: z9.object({
3853
+ prompt: z9.string().min(1).max(4e3).describe("Image generation prompt.")
3884
3854
  }),
3885
3855
  outputSchema: juniorToolResultSchema,
3886
3856
  execute: async ({ prompt }) => {
@@ -3972,7 +3942,7 @@ function createImageGenerateTool(hooks, options = {}, deps = {}) {
3972
3942
  }
3973
3943
 
3974
3944
  // src/chat/tools/skill/call-mcp-tool.ts
3975
- import { z as z11 } from "zod";
3945
+ import { z as z10 } from "zod";
3976
3946
  function resolveMcpArguments(input) {
3977
3947
  const extraKeys = Object.keys(input).filter(
3978
3948
  (key) => key !== "tool_name" && key !== "arguments"
@@ -4008,9 +3978,9 @@ function missingToolMessage(toolName, provider) {
4008
3978
  function createCallMcpToolTool(mcpToolManager) {
4009
3979
  return zodTool({
4010
3980
  description: "Call an active MCP tool by exact tool_name. Use searchMcpTools to discover tool names and schemas; copy required provider fields into arguments. Do not call with only tool_name unless the discovered tool has no arguments. Authorization is handled by the runtime when required.",
4011
- inputSchema: z11.object({
4012
- tool_name: z11.string().min(1).describe("Exact MCP tool_name from searchMcpTools."),
4013
- arguments: z11.unknown().describe(
3981
+ inputSchema: z10.object({
3982
+ tool_name: z10.string().min(1).describe("Exact MCP tool_name from searchMcpTools."),
3983
+ arguments: z10.unknown().describe(
4014
3984
  'Arguments matching the disclosed MCP tool schema, for example { "query": "..." } when searchMcpTools shows query is required.'
4015
3985
  ).optional()
4016
3986
  }).passthrough(),
@@ -4051,7 +4021,7 @@ function createCallMcpToolTool(mcpToolManager) {
4051
4021
  }
4052
4022
 
4053
4023
  // src/chat/tools/skill/load-skill.ts
4054
- import { z as z12 } from "zod";
4024
+ import { z as z11 } from "zod";
4055
4025
  function toLoadedSkill(result, availableSkills) {
4056
4026
  if (result.ok !== true || typeof result.skill_name !== "string" || typeof result.description !== "string" || typeof result.skill_dir !== "string" || typeof result.instructions !== "string") {
4057
4027
  return null;
@@ -4100,8 +4070,8 @@ async function loadSkillFromHost(availableSkills, skillName) {
4100
4070
  function createLoadSkillTool(availableSkills, options) {
4101
4071
  return zodTool({
4102
4072
  description: "Load a skill by name for this turn. The result includes working_directory; resolve skill paths there and run skill-owned bash commands from there or with absolute paths. When the result includes mcp_provider, use searchMcpTools before callMcpTool. Use when a request clearly matches a known skill.",
4103
- inputSchema: z12.object({
4104
- skill_name: z12.string().min(1).describe("Skill name to load, without the leading slash.")
4073
+ inputSchema: z11.object({
4074
+ skill_name: z11.string().min(1).describe("Skill name to load, without the leading slash.")
4105
4075
  }),
4106
4076
  outputSchema: juniorToolResultSchema,
4107
4077
  execute: async ({ skill_name }) => {
@@ -4119,7 +4089,7 @@ function createLoadSkillTool(availableSkills, options) {
4119
4089
  }
4120
4090
 
4121
4091
  // src/chat/tools/skill/search-mcp-tools.ts
4122
- import { z as z13 } from "zod";
4092
+ import { z as z12 } from "zod";
4123
4093
 
4124
4094
  // src/chat/tool-support/schema-summary.ts
4125
4095
  function getSchemaProperties(schema) {
@@ -4367,14 +4337,14 @@ function searchProviderCatalog(providers, query) {
4367
4337
  function createSearchMcpToolsTool(mcpToolManager) {
4368
4338
  return zodTool({
4369
4339
  description: "List or search MCP providers and active MCP tools. When provider is supplied and not yet active, Junior connects to it on demand and returns tool descriptors including schemas. Without provider, returns active tools plus matching configured providers without connecting. Use when choosing a provider tool or when callMcpTool arguments are unclear.",
4370
- inputSchema: z13.object({
4371
- query: z13.string().min(1).describe(
4340
+ inputSchema: z12.object({
4341
+ query: z12.string().min(1).describe(
4372
4342
  "Optional search terms describing the MCP tool or arguments needed."
4373
4343
  ).optional(),
4374
- provider: z13.string().min(1).describe(
4344
+ provider: z12.string().min(1).describe(
4375
4345
  "Optional provider name to list or search within. If configured but not yet connected, Junior activates it on demand."
4376
4346
  ).optional(),
4377
- max_results: z13.number().int().min(1).max(MAX_RESULTS).describe("Maximum matching tool descriptors to return.").optional()
4347
+ max_results: z12.number().int().min(1).max(MAX_RESULTS).describe("Maximum matching tool descriptors to return.").optional()
4378
4348
  }).strict(),
4379
4349
  outputSchema: juniorToolResultSchema,
4380
4350
  execute: async ({ query, provider, max_results }) => {
@@ -4412,7 +4382,7 @@ function createSearchMcpToolsTool(mcpToolManager) {
4412
4382
  }
4413
4383
 
4414
4384
  // src/chat/tools/sandbox/read-file.ts
4415
- import { z as z14 } from "zod";
4385
+ import { z as z13 } from "zod";
4416
4386
 
4417
4387
  // src/chat/tool-support/text-range-result.ts
4418
4388
  var DEFAULT_READ_LIMIT = 1e3;
@@ -4487,10 +4457,10 @@ function createReadFileTool() {
4487
4457
  return zodTool({
4488
4458
  description: "Read a bounded line range from a file in the sandbox workspace. Use when you need exact file contents to verify facts or make edits safely. Prefer grep/findFiles/listDir for broad discovery.",
4489
4459
  annotations: { readOnlyHint: true, destructiveHint: false },
4490
- inputSchema: z14.object({
4491
- path: z14.string().min(1).describe("Path to the file in the sandbox workspace."),
4492
- offset: z14.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
4493
- limit: z14.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
4460
+ inputSchema: z13.object({
4461
+ path: z13.string().min(1).describe("Path to the file in the sandbox workspace."),
4462
+ offset: z13.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
4463
+ limit: z13.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
4494
4464
  }),
4495
4465
  outputSchema: juniorToolResultSchema,
4496
4466
  execute: async () => {
@@ -4502,12 +4472,12 @@ function createReadFileTool() {
4502
4472
  }
4503
4473
 
4504
4474
  // src/chat/tools/runtime/report-progress.ts
4505
- import { z as z15 } from "zod";
4475
+ import { z as z14 } from "zod";
4506
4476
  function createReportProgressTool() {
4507
4477
  return zodTool({
4508
4478
  description: "Update the user-visible assistant loading message with a short progress phase. For every non-trivial turn, call this early with the initial major work phase, then call it again only when the major phase meaningfully changes. Messages must be written in sentence case with a present-participle verb (e.g. 'Searching docs', 'Reviewing results', 'Running checks'). Skip trivial direct answers, generic filler, and minor substeps.",
4509
- inputSchema: z15.object({
4510
- message: z15.string().min(1).describe("Short user-facing progress message.")
4479
+ inputSchema: z14.object({
4480
+ message: z14.string().min(1).describe("Short user-facing progress message.")
4511
4481
  }),
4512
4482
  outputSchema: juniorToolResultSchema,
4513
4483
  execute: async () => ({
@@ -4518,31 +4488,31 @@ function createReportProgressTool() {
4518
4488
  }
4519
4489
 
4520
4490
  // src/chat/tools/resource-events.ts
4521
- import { z as z17 } from "zod";
4491
+ import { z as z16 } from "zod";
4522
4492
 
4523
4493
  // src/chat/resource-events/store.ts
4524
4494
  import { createHash } from "crypto";
4525
4495
  import { destinationSchema } from "@sentry/junior-plugin-api";
4526
- import { z as z16 } from "zod";
4496
+ import { z as z15 } from "zod";
4527
4497
  var RESOURCE_EVENT_PREFIX = "junior:resource_event_subscription";
4528
4498
  var INDEX_LOCK_TTL_MS = 1e4;
4529
4499
  var SUBSCRIPTION_LOCK_TTL_MS = 1e4;
4530
- var subscriptionStatusSchema = z16.enum(["active", "cancelled", "completed"]);
4531
- var subscriptionIdIndexSchema = z16.array(z16.string().min(1));
4532
- var subscriptionSchema = z16.object({
4533
- conversationId: z16.string().min(1),
4534
- createdAtMs: z16.number().finite(),
4500
+ var subscriptionStatusSchema = z15.enum(["active", "cancelled", "completed"]);
4501
+ var subscriptionIdIndexSchema = z15.array(z15.string().min(1));
4502
+ var subscriptionSchema = z15.object({
4503
+ conversationId: z15.string().min(1),
4504
+ createdAtMs: z15.number().finite(),
4535
4505
  destination: destinationSchema,
4536
- events: z16.array(z16.string().min(1)).min(1),
4537
- expiresAtMs: z16.number().finite(),
4538
- id: z16.string().min(1),
4539
- intent: z16.string().min(1),
4540
- label: z16.string().min(1),
4541
- provider: z16.string().min(1),
4542
- resourceRef: z16.string().min(1),
4543
- resourceType: z16.string().min(1),
4506
+ events: z15.array(z15.string().min(1)).min(1),
4507
+ expiresAtMs: z15.number().finite(),
4508
+ id: z15.string().min(1),
4509
+ intent: z15.string().min(1),
4510
+ label: z15.string().min(1),
4511
+ provider: z15.string().min(1),
4512
+ resourceRef: z15.string().min(1),
4513
+ resourceType: z15.string().min(1),
4544
4514
  status: subscriptionStatusSchema,
4545
- updatedAtMs: z16.number().finite()
4515
+ updatedAtMs: z15.number().finite()
4546
4516
  }).strict();
4547
4517
  function digest(value) {
4548
4518
  return createHash("sha256").update(value).digest("hex").slice(0, 32);
@@ -4832,23 +4802,23 @@ async function deliverResourceEventSubscription(input) {
4832
4802
  // src/chat/tools/resource-events.ts
4833
4803
  var DEFAULT_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
4834
4804
  var MAX_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
4835
- var subscribeInputSchema = z17.object({
4836
- resourceRef: z17.string().describe("Opaque resource ref copied from a subscribable tool result."),
4837
- provider: z17.string().describe("Provider that owns the resource ref."),
4838
- resourceType: z17.string().describe("Provider-defined resource type from the subscribable hint."),
4839
- label: z17.string().describe("Human-readable resource label from the subscribable hint."),
4840
- events: z17.array(z17.string()).min(1).describe(
4805
+ var subscribeInputSchema = z16.object({
4806
+ resourceRef: z16.string().describe("Opaque resource ref copied from a subscribable tool result."),
4807
+ provider: z16.string().describe("Provider that owns the resource ref."),
4808
+ resourceType: z16.string().describe("Provider-defined resource type from the subscribable hint."),
4809
+ label: z16.string().describe("Human-readable resource label from the subscribable hint."),
4810
+ events: z16.array(z16.string()).min(1).describe(
4841
4811
  "High-signal event names to deliver to this conversation when they occur."
4842
4812
  ),
4843
- intent: z17.string().describe(
4813
+ intent: z16.string().describe(
4844
4814
  "Concise reason this conversation wants these events, used when an event arrives."
4845
4815
  ),
4846
- ttlMs: z17.coerce.number().describe(
4816
+ ttlMs: z16.coerce.number().describe(
4847
4817
  "How long to keep the subscription active. Defaults to 14 days and is capped at 30 days."
4848
4818
  ).optional()
4849
4819
  });
4850
- var cancelInputSchema = z17.object({
4851
- subscriptionId: z17.string().describe(
4820
+ var cancelInputSchema = z16.object({
4821
+ subscriptionId: z16.string().describe(
4852
4822
  "Subscription id returned by subscribeToResourceEvents or listResourceEventSubscriptions."
4853
4823
  )
4854
4824
  });
@@ -4932,7 +4902,7 @@ function createSubscribeToResourceEventsTool(context) {
4932
4902
  function createListResourceEventSubscriptionsTool(context) {
4933
4903
  return zodTool({
4934
4904
  description: "List active resource event subscriptions for the current conversation.",
4935
- inputSchema: z17.object({}),
4905
+ inputSchema: z16.object({}),
4936
4906
  outputSchema: juniorToolResultSchema,
4937
4907
  async execute() {
4938
4908
  const conversationId = requireConversationContext(context);
@@ -5067,11 +5037,11 @@ async function listThreadReplies(input) {
5067
5037
  }
5068
5038
 
5069
5039
  // src/chat/slack/timestamp-param.ts
5070
- import { z as z18 } from "zod";
5040
+ import { z as z17 } from "zod";
5071
5041
  function slackTimestampParam(description) {
5072
- return z18.preprocess(
5042
+ return z17.preprocess(
5073
5043
  (value) => typeof value === "number" && Number.isFinite(value) ? String(value) : value,
5074
- z18.string().min(1)
5044
+ z17.string().min(1)
5075
5045
  ).describe(description);
5076
5046
  }
5077
5047
  function optionalSlackTimestampParam(description) {
@@ -5102,10 +5072,10 @@ function parseRequiredSlackTimestampParam(field, value) {
5102
5072
  }
5103
5073
 
5104
5074
  // src/chat/slack/tools/channel-list-messages.ts
5105
- import { z as z19 } from "zod";
5106
- var booleanInput2 = (description) => z19.preprocess(
5075
+ import { z as z18 } from "zod";
5076
+ var booleanInput2 = (description) => z18.preprocess(
5107
5077
  (value) => value === "true" ? true : value === "false" ? false : value,
5108
- z19.boolean()
5078
+ z18.boolean()
5109
5079
  ).describe(description);
5110
5080
  function normalizeRangeTimestamp(field, value, targetChannelId) {
5111
5081
  if (value === void 0) {
@@ -5132,9 +5102,9 @@ function createSlackChannelListMessagesTool(context) {
5132
5102
  return zodTool({
5133
5103
  description: "List channel messages from Slack history in the active channel context. Use when the user asks for recent or historical channel context outside this thread. Do not use for live monitoring or when current thread context already answers the question.",
5134
5104
  annotations: { readOnlyHint: true, destructiveHint: false },
5135
- inputSchema: z19.object({
5136
- limit: z19.coerce.number().int().min(1).max(1e3).describe("Maximum number of messages to return across pages.").optional(),
5137
- cursor: z19.string().min(1).describe("Optional cursor to continue from a prior call.").optional(),
5105
+ inputSchema: z18.object({
5106
+ limit: z18.coerce.number().int().min(1).max(1e3).describe("Maximum number of messages to return across pages.").optional(),
5107
+ cursor: z18.string().min(1).describe("Optional cursor to continue from a prior call.").optional(),
5138
5108
  oldest: optionalSlackTimestampParam(
5139
5109
  "Optional oldest message timestamp (Slack ts) for range filtering."
5140
5110
  ),
@@ -5144,7 +5114,7 @@ function createSlackChannelListMessagesTool(context) {
5144
5114
  inclusive: booleanInput2(
5145
5115
  "Whether oldest/latest bounds should be inclusive."
5146
5116
  ).optional(),
5147
- max_pages: z19.coerce.number().int().min(1).max(10).describe("Maximum number of API pages to traverse in a single call.").optional()
5117
+ max_pages: z18.coerce.number().int().min(1).max(10).describe("Maximum number of API pages to traverse in a single call.").optional()
5148
5118
  }),
5149
5119
  outputSchema: juniorToolResultSchema,
5150
5120
  execute: async ({
@@ -5477,7 +5447,7 @@ async function removeReactionFromMessage(input) {
5477
5447
  }
5478
5448
 
5479
5449
  // src/chat/slack/tools/message-add-reaction.ts
5480
- import { z as z20 } from "zod";
5450
+ import { z as z19 } from "zod";
5481
5451
 
5482
5452
  // src/chat/tools/idempotency.ts
5483
5453
  function stableSerialize(value) {
@@ -5499,8 +5469,8 @@ function createOperationKey(toolName, input) {
5499
5469
  function createSlackMessageAddReactionTool(context, state) {
5500
5470
  return zodTool({
5501
5471
  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.",
5502
- inputSchema: z20.object({
5503
- emoji: z20.string().min(1).max(64).describe(
5472
+ inputSchema: z19.object({
5473
+ emoji: z19.string().min(1).max(64).describe(
5504
5474
  "Slack emoji alias name to react with (for example `thumbsup`, `white_check_mark`, or `thumbsup::skin-tone-6`). Optional surrounding colons are allowed."
5505
5475
  )
5506
5476
  }),
@@ -5551,15 +5521,15 @@ function createSlackMessageAddReactionTool(context, state) {
5551
5521
 
5552
5522
  // src/chat/slack/tools/send-message.ts
5553
5523
  import { createHash as createHash2 } from "crypto";
5554
- import { z as z21 } from "zod";
5555
- var fileInputSchema = z21.object({
5556
- path: z21.string().min(1).describe(
5524
+ import { z as z20 } from "zod";
5525
+ var fileInputSchema = z20.object({
5526
+ path: z20.string().min(1).describe(
5557
5527
  "Sandbox file path to include in the message. Absolute paths and workspace-relative paths are supported."
5558
5528
  ),
5559
- filename: z21.string().min(1).nullable().optional().describe(
5529
+ filename: z20.string().min(1).nullable().optional().describe(
5560
5530
  "Optional filename override shown in Slack. Null is treated as omitted."
5561
5531
  ),
5562
- mimeType: z21.string().min(1).nullable().optional().describe("Optional MIME type override. Null is treated as omitted.")
5532
+ mimeType: z20.string().min(1).nullable().optional().describe("Optional MIME type override. Null is treated as omitted.")
5563
5533
  });
5564
5534
  function hasText(text) {
5565
5535
  return typeof text === "string" && text.trim().length > 0;
@@ -5586,9 +5556,9 @@ function fileOperationInput(files) {
5586
5556
  function createSendMessageTool(context, state, materializeFile) {
5587
5557
  return zodTool({
5588
5558
  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.",
5589
- inputSchema: z21.object({
5590
- text: z21.string().max(4e4).nullable().optional().describe("Slack mrkdwn text to send. Null is treated as omitted."),
5591
- files: z21.array(fileInputSchema).min(1).nullable().optional().describe(
5559
+ inputSchema: z20.object({
5560
+ text: z20.string().max(4e4).nullable().optional().describe("Slack mrkdwn text to send. Null is treated as omitted."),
5561
+ files: z20.array(fileInputSchema).min(1).nullable().optional().describe(
5592
5562
  "Sandbox files to include in the message. Null is treated as omitted."
5593
5563
  )
5594
5564
  }),
@@ -5916,13 +5886,13 @@ function storedCanvasUrl(state, canvasId) {
5916
5886
  }
5917
5887
 
5918
5888
  // src/chat/slack/tools/canvas/create.ts
5919
- import { z as z22 } from "zod";
5889
+ import { z as z21 } from "zod";
5920
5890
  function createSlackCanvasCreateTool(context, state) {
5921
5891
  return zodTool({
5922
5892
  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.",
5923
- inputSchema: z22.object({
5924
- title: z22.string().min(1).max(160).describe("Canvas title."),
5925
- markdown: z22.string().min(1).describe("Canvas markdown body content.")
5893
+ inputSchema: z21.object({
5894
+ title: z21.string().min(1).max(160).describe("Canvas title."),
5895
+ markdown: z21.string().min(1).describe("Canvas markdown body content.")
5926
5896
  }),
5927
5897
  outputSchema: juniorToolResultSchema,
5928
5898
  execute: async ({ title, markdown }) => {
@@ -5985,24 +5955,24 @@ function createSlackCanvasCreateTool(context, state) {
5985
5955
  }
5986
5956
 
5987
5957
  // src/chat/slack/tools/canvas/edit.ts
5988
- import { z as z23 } from "zod";
5958
+ import { z as z22 } from "zod";
5989
5959
  function prepareCanvasEditArguments(input) {
5990
5960
  return prepareTextReplacementArguments(input);
5991
5961
  }
5992
- var editReplacementSchema2 = z23.object({
5993
- oldText: z23.string().min(1).describe(
5962
+ var editReplacementSchema2 = z22.object({
5963
+ oldText: z22.string().min(1).describe(
5994
5964
  "Exact Canvas markdown to replace. It must be unique in the current Canvas body and must not overlap another edit."
5995
5965
  ),
5996
- newText: z23.string().describe("Replacement Canvas markdown for this edit.")
5966
+ newText: z22.string().describe("Replacement Canvas markdown for this edit.")
5997
5967
  });
5998
5968
  function createSlackCanvasEditTool(state) {
5999
5969
  return zodTool({
6000
5970
  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.",
6001
5971
  prepareArguments: prepareCanvasEditArguments,
6002
5972
  executionMode: "sequential",
6003
- inputSchema: z23.object({
6004
- canvas: z23.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
6005
- edits: z23.array(editReplacementSchema2).min(1).describe(
5973
+ inputSchema: z22.object({
5974
+ canvas: z22.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
5975
+ edits: z22.array(editReplacementSchema2).min(1).describe(
6006
5976
  "Exact replacements matched against the current Canvas body, not incrementally."
6007
5977
  )
6008
5978
  }),
@@ -6080,17 +6050,17 @@ function createSlackCanvasEditTool(state) {
6080
6050
  }
6081
6051
 
6082
6052
  // src/chat/slack/tools/canvas/read.ts
6083
- import { z as z24 } from "zod";
6053
+ import { z as z23 } from "zod";
6084
6054
  function createSlackCanvasReadTool() {
6085
6055
  return zodTool({
6086
6056
  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.",
6087
6057
  annotations: { readOnlyHint: true, destructiveHint: false },
6088
- inputSchema: z24.object({
6089
- canvas: z24.string().min(1).describe(
6058
+ inputSchema: z23.object({
6059
+ canvas: z23.string().min(1).describe(
6090
6060
  "Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL (e.g. `https://team.slack.com/docs/T.../F...`)."
6091
6061
  ),
6092
- offset: z24.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
6093
- limit: z24.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
6062
+ offset: z23.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
6063
+ limit: z23.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
6094
6064
  }),
6095
6065
  outputSchema: juniorToolResultSchema,
6096
6066
  execute: async ({ canvas, offset, limit }) => {
@@ -6147,14 +6117,14 @@ function createSlackCanvasReadTool() {
6147
6117
  }
6148
6118
 
6149
6119
  // src/chat/slack/tools/canvas/write.ts
6150
- import { z as z25 } from "zod";
6120
+ import { z as z24 } from "zod";
6151
6121
  function createSlackCanvasWriteTool(state) {
6152
6122
  return zodTool({
6153
6123
  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.",
6154
6124
  executionMode: "sequential",
6155
- inputSchema: z25.object({
6156
- canvas: z25.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
6157
- content: z25.string().describe("UTF-8 markdown content to write.")
6125
+ inputSchema: z24.object({
6126
+ canvas: z24.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
6127
+ content: z24.string().describe("UTF-8 markdown content to write.")
6158
6128
  }),
6159
6129
  outputSchema: juniorToolResultSchema,
6160
6130
  execute: async ({ canvas, content }) => {
@@ -6390,12 +6360,12 @@ async function updateListItem(input) {
6390
6360
  }
6391
6361
 
6392
6362
  // src/chat/slack/id-param.ts
6393
- import { z as z26 } from "zod";
6363
+ import { z as z25 } from "zod";
6394
6364
  function slackChannelIdParam(description) {
6395
- return z26.string().min(1).describe(description);
6365
+ return z25.string().min(1).describe(description);
6396
6366
  }
6397
6367
  function slackUserIdParam(description) {
6398
- return z26.string().min(1).describe(description);
6368
+ return z25.string().min(1).describe(description);
6399
6369
  }
6400
6370
  function parseRequiredSlackChannelIdParam(field, value) {
6401
6371
  const channelId = parseSlackChannelId(value);
@@ -6419,16 +6389,16 @@ function parseRequiredSlackUserIdParam(field, value) {
6419
6389
  }
6420
6390
 
6421
6391
  // src/chat/slack/tools/list/add-items.ts
6422
- import { z as z27 } from "zod";
6392
+ import { z as z26 } from "zod";
6423
6393
  function createSlackListAddItemsTool(state) {
6424
6394
  return zodTool({
6425
6395
  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.",
6426
- inputSchema: z27.object({
6427
- items: z27.array(z27.string().min(1)).min(1).max(25).describe("List item titles to create."),
6396
+ inputSchema: z26.object({
6397
+ items: z26.array(z26.string().min(1)).min(1).max(25).describe("List item titles to create."),
6428
6398
  assignee_user_id: slackUserIdParam(
6429
6399
  "Optional Slack user ID assigned to all created items."
6430
6400
  ).optional(),
6431
- due_date: z27.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
6401
+ due_date: z26.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
6432
6402
  }),
6433
6403
  outputSchema: juniorToolResultSchema,
6434
6404
  execute: async ({ items, assignee_user_id, due_date }) => {
@@ -6482,12 +6452,12 @@ function createSlackListAddItemsTool(state) {
6482
6452
  }
6483
6453
 
6484
6454
  // src/chat/slack/tools/list/create.ts
6485
- import { z as z28 } from "zod";
6455
+ import { z as z27 } from "zod";
6486
6456
  function createSlackListCreateTool(state) {
6487
6457
  return zodTool({
6488
6458
  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.",
6489
- inputSchema: z28.object({
6490
- name: z28.string().min(1).max(160).describe("Name for the new Slack list.")
6459
+ inputSchema: z27.object({
6460
+ name: z27.string().min(1).max(160).describe("Name for the new Slack list.")
6491
6461
  }),
6492
6462
  outputSchema: juniorToolResultSchema,
6493
6463
  execute: async ({ name }) => {
@@ -6519,13 +6489,13 @@ function createSlackListCreateTool(state) {
6519
6489
  }
6520
6490
 
6521
6491
  // src/chat/slack/tools/list/get-items.ts
6522
- import { z as z29 } from "zod";
6492
+ import { z as z28 } from "zod";
6523
6493
  function createSlackListGetItemsTool(state) {
6524
6494
  return zodTool({
6525
6495
  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.",
6526
6496
  annotations: { readOnlyHint: true, destructiveHint: false },
6527
- inputSchema: z29.object({
6528
- limit: z29.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
6497
+ inputSchema: z28.object({
6498
+ limit: z28.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
6529
6499
  }),
6530
6500
  outputSchema: juniorToolResultSchema,
6531
6501
  execute: async ({ limit }) => {
@@ -6550,21 +6520,21 @@ function createSlackListGetItemsTool(state) {
6550
6520
  }
6551
6521
 
6552
6522
  // src/chat/slack/tools/list/update-item.ts
6553
- import { z as z30 } from "zod";
6554
- var booleanInput3 = (description) => z30.preprocess(
6523
+ import { z as z29 } from "zod";
6524
+ var booleanInput3 = (description) => z29.preprocess(
6555
6525
  (value) => value === "true" ? true : value === "false" ? false : value,
6556
- z30.boolean()
6526
+ z29.boolean()
6557
6527
  ).describe(description);
6558
- var updateListItemInputSchema = z30.union([
6559
- z30.object({
6560
- item_id: z30.string().min(1).describe("ID of the Slack list item to update."),
6528
+ var updateListItemInputSchema = z29.union([
6529
+ z29.object({
6530
+ item_id: z29.string().min(1).describe("ID of the Slack list item to update."),
6561
6531
  completed: booleanInput3("Optional completion status update."),
6562
- title: z30.string().min(1).describe("Optional new item title.").optional()
6532
+ title: z29.string().min(1).describe("Optional new item title.").optional()
6563
6533
  }),
6564
- z30.object({
6565
- item_id: z30.string().min(1).describe("ID of the Slack list item to update."),
6534
+ z29.object({
6535
+ item_id: z29.string().min(1).describe("ID of the Slack list item to update."),
6566
6536
  completed: booleanInput3("Optional completion status update.").optional(),
6567
- title: z30.string().min(1).describe("Optional new item title.")
6537
+ title: z29.string().min(1).describe("Optional new item title.")
6568
6538
  })
6569
6539
  ]);
6570
6540
  function createSlackListUpdateItemTool(state) {
@@ -6640,7 +6610,7 @@ async function checkSlackChannelReadAccess(args) {
6640
6610
  }
6641
6611
 
6642
6612
  // src/chat/slack/tools/thread-read.ts
6643
- import { z as z31 } from "zod";
6613
+ import { z as z30 } from "zod";
6644
6614
 
6645
6615
  // src/chat/slack/tools/slack-message-url.ts
6646
6616
  var SLACK_HOST_PATTERN = /^[a-z0-9-]+\.slack(?:-gov)?\.com$/;
@@ -6813,8 +6783,8 @@ function createSlackThreadReadTool(context, deps = {}) {
6813
6783
  return zodTool({
6814
6784
  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.",
6815
6785
  annotations: { readOnlyHint: true, destructiveHint: false },
6816
- inputSchema: z31.object({
6817
- url: z31.string().min(1).describe(
6786
+ inputSchema: z30.object({
6787
+ url: z30.string().min(1).describe(
6818
6788
  "Slack message archive URL, e.g. https://workspace.slack.com/archives/C123/p1700000000123456"
6819
6789
  ).optional(),
6820
6790
  channel_id: slackChannelIdParam(
@@ -6823,8 +6793,8 @@ function createSlackThreadReadTool(context, deps = {}) {
6823
6793
  ts: slackTimestampParam(
6824
6794
  "Slack message timestamp (e.g. 1700000000.123456). May be the thread root or any message in the thread."
6825
6795
  ).optional(),
6826
- limit: z31.coerce.number().int().min(1).max(1e3).describe("Maximum number of thread messages to fetch.").optional(),
6827
- max_pages: z31.coerce.number().int().min(1).max(10).describe("Maximum number of Slack API pages to traverse.").optional()
6796
+ limit: z30.coerce.number().int().min(1).max(1e3).describe("Maximum number of thread messages to fetch.").optional(),
6797
+ max_pages: z30.coerce.number().int().min(1).max(10).describe("Maximum number of Slack API pages to traverse.").optional()
6828
6798
  }),
6829
6799
  outputSchema: juniorToolResultSchema,
6830
6800
  execute: async ({ url, channel_id, ts, limit, max_pages }) => {
@@ -7080,29 +7050,29 @@ async function searchSlackUsers(options) {
7080
7050
  }
7081
7051
 
7082
7052
  // src/chat/slack/tools/user-lookup.ts
7083
- import { z as z32 } from "zod";
7084
- var booleanInput4 = (description) => z32.preprocess(
7053
+ import { z as z31 } from "zod";
7054
+ var booleanInput4 = (description) => z31.preprocess(
7085
7055
  (value) => value === "true" ? true : value === "false" ? false : value,
7086
- z32.boolean()
7056
+ z31.boolean()
7087
7057
  ).describe(description);
7088
7058
  function createSlackUserLookupTool() {
7089
7059
  return zodTool({
7090
7060
  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.",
7091
7061
  annotations: { readOnlyHint: true, destructiveHint: false },
7092
- inputSchema: z32.object({
7062
+ inputSchema: z31.object({
7093
7063
  user_id: slackUserIdParam(
7094
7064
  "Slack user ID to look up (e.g. U039RR91S). Mutually exclusive with email and query."
7095
7065
  ).optional(),
7096
- email: z32.string().min(3).describe(
7066
+ email: z31.string().min(3).describe(
7097
7067
  "Email address to look up. Mutually exclusive with user_id and query."
7098
7068
  ).optional(),
7099
- query: z32.string().min(2).describe(
7069
+ query: z31.string().min(2).describe(
7100
7070
  "Name to search for (matches against username, display name, real name). Mutually exclusive with user_id and email."
7101
7071
  ).optional(),
7102
- limit: z32.coerce.number().int().min(1).max(20).describe(
7072
+ limit: z31.coerce.number().int().min(1).max(20).describe(
7103
7073
  "Maximum number of results to return for name search. Defaults to 10."
7104
7074
  ).optional(),
7105
- max_pages: z32.coerce.number().int().min(1).max(5).describe(
7075
+ max_pages: z31.coerce.number().int().min(1).max(5).describe(
7106
7076
  "Maximum number of Slack API pages to scan for name search. Defaults to 3."
7107
7077
  ).optional(),
7108
7078
  include_bots: booleanInput4(
@@ -7206,12 +7176,12 @@ function createSlackUserLookupTool() {
7206
7176
  }
7207
7177
 
7208
7178
  // src/chat/tools/system-time.ts
7209
- import { z as z33 } from "zod";
7179
+ import { z as z32 } from "zod";
7210
7180
  function createSystemTimeTool() {
7211
7181
  return zodTool({
7212
7182
  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.",
7213
7183
  annotations: { readOnlyHint: true, destructiveHint: false },
7214
- inputSchema: z33.object({}),
7184
+ inputSchema: z32.object({}),
7215
7185
  outputSchema: juniorToolResultSchema,
7216
7186
  execute: async () => {
7217
7187
  const now = /* @__PURE__ */ new Date();
@@ -7268,7 +7238,7 @@ function createStateAdvisorSessionStore() {
7268
7238
  }
7269
7239
 
7270
7240
  // src/chat/tools/advisor/tool.ts
7271
- import { z as z34 } from "zod";
7241
+ import { z as z33 } from "zod";
7272
7242
  var ADVISOR_TOOL_DESCRIPTION = "Second-opinion advisor for hard technical work. Call when you reach a consequential workflow moment: after enough exploration to frame a non-obvious plan; before a non-trivial code change or broad refactor; after repeated failures or when requirements or next steps feel ambiguous or risky; and when verifying a complex change before declaring it done, opening a PR, or reporting results. Ask a focused question and pass curated context: exact evidence, constraints, relevant code snippets, command output, diffs, current plan, and alternatives considered. The advisor has its own history, does not automatically receive the parent transcript, and may use read-only tools to verify. Follow up only with new evidence or changed constraints. Do not use for greetings, simple deterministic edits, routine formatting, or when fresh output makes the next action obvious.";
7273
7243
  var ADVISOR_SYSTEM_PROMPT = [
7274
7244
  "You are a senior technical advisor for the executor.",
@@ -7321,9 +7291,9 @@ function createAdvisorTool(context) {
7321
7291
  const spanContext = context.logContext ?? {};
7322
7292
  return zodTool({
7323
7293
  description: ADVISOR_TOOL_DESCRIPTION,
7324
- inputSchema: z34.object({
7325
- question: z34.string().min(1).describe("Focused advisor question or decision point."),
7326
- context: z34.string().min(1).describe(
7294
+ inputSchema: z33.object({
7295
+ question: z33.string().min(1).describe("Focused advisor question or decision point."),
7296
+ context: z33.string().min(1).describe(
7327
7297
  "Curated evidence packet: relevant requirements, constraints, current plan, alternatives, code snippets, diffs, command output, and open questions."
7328
7298
  )
7329
7299
  }),
@@ -7506,7 +7476,7 @@ function createAdvisorTool(context) {
7506
7476
  }
7507
7477
 
7508
7478
  // src/chat/tools/web/fetch-tool.ts
7509
- import { z as z35 } from "zod";
7479
+ import { z as z34 } from "zod";
7510
7480
 
7511
7481
  // src/chat/tools/web/constants.ts
7512
7482
  var USER_AGENT = "junior-bot/0.1";
@@ -7953,9 +7923,9 @@ function createWebFetchTool(hooks, options = {}) {
7953
7923
  destructiveHint: false,
7954
7924
  openWorldHint: true
7955
7925
  },
7956
- inputSchema: z35.object({
7957
- url: z35.string().min(1).describe("HTTP(S) URL to fetch."),
7958
- max_chars: z35.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
7926
+ inputSchema: z34.object({
7927
+ url: z34.string().min(1).describe("HTTP(S) URL to fetch."),
7928
+ max_chars: z34.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
7959
7929
  }),
7960
7930
  outputSchema: juniorToolResultSchema,
7961
7931
  execute: async ({ url, max_chars }) => {
@@ -8022,7 +7992,7 @@ function createWebFetchTool(hooks, options = {}) {
8022
7992
  }
8023
7993
 
8024
7994
  // src/chat/tools/web/search.ts
8025
- import { z as z36 } from "zod";
7995
+ import { z as z35 } from "zod";
8026
7996
  import { generateText } from "ai";
8027
7997
  import { createGatewayProvider } from "@ai-sdk/gateway";
8028
7998
  import { getModel } from "@earendil-works/pi-ai";
@@ -8073,9 +8043,9 @@ function createWebSearchTool(override) {
8073
8043
  destructiveHint: false,
8074
8044
  openWorldHint: true
8075
8045
  },
8076
- inputSchema: z36.object({
8077
- query: z36.string().min(1).max(500).describe("Search query."),
8078
- max_results: z36.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
8046
+ inputSchema: z35.object({
8047
+ query: z35.string().min(1).max(500).describe("Search query."),
8048
+ max_results: z35.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
8079
8049
  }),
8080
8050
  outputSchema: juniorToolResultSchema,
8081
8051
  execute: async ({ query, max_results }) => {
@@ -8145,14 +8115,14 @@ function createWebSearchTool(override) {
8145
8115
  }
8146
8116
 
8147
8117
  // src/chat/tools/sandbox/write-file.ts
8148
- import { z as z37 } from "zod";
8118
+ import { z as z36 } from "zod";
8149
8119
  function createWriteFileTool() {
8150
8120
  return zodTool({
8151
8121
  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.",
8152
8122
  executionMode: "sequential",
8153
- inputSchema: z37.object({
8154
- path: z37.string().min(1).describe("Path to write in the sandbox workspace."),
8155
- content: z37.string().describe("UTF-8 file content to write.")
8123
+ inputSchema: z36.object({
8124
+ path: z36.string().min(1).describe("Path to write in the sandbox workspace."),
8125
+ content: z36.string().describe("UTF-8 file content to write.")
8156
8126
  }),
8157
8127
  outputSchema: juniorToolResultSchema,
8158
8128
  execute: async () => {
@@ -8891,6 +8861,13 @@ import { randomBytes } from "crypto";
8891
8861
  import {
8892
8862
  sourceSchema as sourceSchema2
8893
8863
  } from "@sentry/junior-plugin-api";
8864
+
8865
+ // src/chat/oauth-authorization-message.ts
8866
+ function formatOAuthAuthorizationMessage(args) {
8867
+ return `${formatSlackLink(args.authorizationUrl, args.label)}. ${args.completionText}`;
8868
+ }
8869
+
8870
+ // src/chat/oauth-flow.ts
8894
8871
  var OAUTH_STATE_TTL_MS = 10 * 60 * 1e3;
8895
8872
  function optionalString(value) {
8896
8873
  return typeof value === "string" ? value : void 0;
@@ -9083,71 +9060,76 @@ async function startOAuthFlow(provider, input) {
9083
9060
  },
9084
9061
  "Initiated OAuth authorization code flow"
9085
9062
  );
9063
+ const authorizationUrl = `${providerConfig.authorizeEndpoint}?${authorizeParams.toString()}`;
9086
9064
  return {
9087
9065
  ok: true,
9088
9066
  delivery: await deliverPrivateMessage({
9089
9067
  channelId: input.channelId,
9090
9068
  threadTs: input.threadTs,
9091
9069
  userId: input.requesterId,
9092
- text: `<${providerConfig.authorizeEndpoint}?${authorizeParams.toString()}|Click here to link your ${formatProviderLabel(provider)} account>. Once you've authorized, you'll see a confirmation in Slack.`
9070
+ text: formatOAuthAuthorizationMessage({
9071
+ authorizationUrl,
9072
+ label: `Click here to link your ${formatProviderLabel(provider)} account`,
9073
+ completionText: "Once you've authorized, you'll see a confirmation in Slack."
9074
+ })
9093
9075
  })
9094
9076
  };
9095
9077
  }
9096
9078
 
9097
9079
  // src/chat/sandbox/egress/schemas.ts
9098
- import { z as z38 } from "zod";
9080
+ import { z as z37 } from "zod";
9099
9081
  import {
9100
9082
  pluginAuthorizationSchema,
9101
9083
  pluginCredentialHeaderTransformSchema,
9102
9084
  pluginGrantSchema,
9103
9085
  pluginProviderAccountSchema
9104
9086
  } from "@sentry/junior-plugin-api";
9105
- var finiteNumberSchema = z38.number().refine(Number.isFinite);
9106
- var httpStatusSchema = z38.number().int().min(100).max(599);
9107
- var providerNameSchema = z38.string().regex(/^[a-z][a-z0-9-]*$/);
9108
- var credentialSignalKindSchema = z38.enum(["auth_required", "unavailable"]);
9087
+ var finiteNumberSchema = z37.number().refine(Number.isFinite);
9088
+ var httpStatusSchema = z37.number().int().min(100).max(599);
9089
+ var providerNameSchema = z37.string().regex(/^[a-z][a-z0-9-]*$/);
9090
+ var credentialSignalKindSchema = z37.enum(["auth_required", "unavailable"]);
9109
9091
  var sandboxEgressGrantSchema = pluginGrantSchema;
9110
- var sandboxEgressCredentialContextSchema = z38.object({
9092
+ var sandboxEgressCredentialContextSchema = z37.object({
9111
9093
  credentials: credentialContextSchema,
9112
- egressId: z38.string().min(1),
9094
+ egressId: z37.string().min(1),
9113
9095
  expiresAtMs: finiteNumberSchema,
9114
- contextId: z38.string().min(1)
9096
+ contextId: z37.string().min(1)
9115
9097
  }).strict();
9116
- var sandboxEgressCredentialLeaseSchema = z38.object({
9098
+ var sandboxEgressCredentialLeaseSchema = z37.object({
9117
9099
  account: pluginProviderAccountSchema.optional(),
9118
9100
  authorization: pluginAuthorizationSchema.optional(),
9119
9101
  grant: sandboxEgressGrantSchema,
9120
9102
  provider: providerNameSchema,
9121
- expiresAt: z38.string().min(1),
9122
- headerTransforms: z38.array(pluginCredentialHeaderTransformSchema).min(1)
9103
+ expiresAt: z37.string().min(1),
9104
+ headerTransforms: z37.array(pluginCredentialHeaderTransformSchema).min(1)
9123
9105
  }).strict();
9124
- var sandboxEgressAuthRequiredSignalSchema = z38.object({
9106
+ var sandboxEgressAuthRequiredSignalSchema = z37.object({
9125
9107
  authorization: pluginAuthorizationSchema.optional(),
9126
9108
  grant: sandboxEgressGrantSchema,
9127
9109
  kind: credentialSignalKindSchema.default("auth_required"),
9128
9110
  provider: providerNameSchema,
9129
- message: z38.string().optional(),
9111
+ message: z37.string().optional(),
9130
9112
  createdAtMs: finiteNumberSchema
9131
9113
  }).strict().superRefine((signal, ctx) => {
9132
9114
  if (signal.authorization && signal.authorization.provider !== signal.provider) {
9133
9115
  ctx.addIssue({
9134
- code: z38.ZodIssueCode.custom,
9116
+ code: z37.ZodIssueCode.custom,
9135
9117
  message: "Auth signal authorization provider must match provider",
9136
9118
  path: ["authorization", "provider"]
9137
9119
  });
9138
9120
  }
9139
9121
  });
9140
- var sandboxEgressPermissionDeniedSignalSchema = z38.object({
9122
+ var sandboxEgressPermissionDeniedSignalSchema = z37.object({
9141
9123
  account: pluginProviderAccountSchema.optional(),
9142
- acceptedPermissions: z38.string().optional(),
9124
+ acceptedPermissions: z37.string().optional(),
9143
9125
  grant: sandboxEgressGrantSchema,
9144
- message: z38.string().min(1),
9126
+ message: z37.string().min(1),
9145
9127
  provider: providerNameSchema,
9146
- source: z38.literal("upstream"),
9147
- sso: z38.string().optional(),
9128
+ source: z37.literal("upstream"),
9129
+ sso: z37.string().optional(),
9148
9130
  status: httpStatusSchema,
9149
- upstreamHost: z38.string().min(1),
9150
- upstreamPath: z38.string().min(1),
9131
+ upstreamHost: z37.string().min(1),
9132
+ upstreamPath: z37.string().min(1),
9151
9133
  createdAtMs: finiteNumberSchema
9152
9134
  }).strict();
9153
9135
  function parseSandboxEgressAuthRequiredSignal(value) {
@@ -9404,15 +9386,15 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, trac
9404
9386
  }
9405
9387
 
9406
9388
  // src/chat/tools/execute-tool.ts
9407
- import { z as z39 } from "zod";
9389
+ import { z as z38 } from "zod";
9408
9390
  var EXECUTE_TOOL_NAME = "executeTool";
9409
9391
  function createExecuteToolTool() {
9410
9392
  return zodTool({
9411
9393
  description: "Execute any catalog tool by exact tool_name from searchTools. Put tool-specific parameters inside arguments.",
9412
9394
  executionMode: "sequential",
9413
- inputSchema: z39.object({
9414
- tool_name: z39.string().min(1).describe("Exact catalog tool_name returned by searchTools."),
9415
- arguments: z39.record(z39.string(), z39.unknown()).describe(
9395
+ inputSchema: z38.object({
9396
+ tool_name: z38.string().min(1).describe("Exact catalog tool_name returned by searchTools."),
9397
+ arguments: z38.record(z38.string(), z38.unknown()).describe(
9416
9398
  'Arguments matching the selected catalog tool schema, for example { "query": "..." }.'
9417
9399
  ).optional()
9418
9400
  }).strict(),
@@ -9452,7 +9434,7 @@ function planToolExposure(tools) {
9452
9434
  }
9453
9435
 
9454
9436
  // src/chat/tools/search-tools.ts
9455
- import { z as z40 } from "zod";
9437
+ import { z as z39 } from "zod";
9456
9438
  var SEARCH_TOOLS_NAME = "searchTools";
9457
9439
  var DEFAULT_MAX_RESULTS2 = 5;
9458
9440
  var MAX_RESULTS3 = 20;
@@ -9523,11 +9505,11 @@ function createSearchToolsTool(catalogTools) {
9523
9505
  return zodTool({
9524
9506
  description: "Search the executable tool catalog. Use this to discover exact tool names, owners, schemas, and call notes before calling executeTool.",
9525
9507
  annotations: { readOnlyHint: true, destructiveHint: false },
9526
- inputSchema: z40.object({
9527
- query: z40.string().nullable().describe(
9508
+ inputSchema: z39.object({
9509
+ query: z39.string().nullable().describe(
9528
9510
  "Optional search terms describing the tool, owner, action, or arguments needed. Empty string lists catalog tools."
9529
9511
  ).optional(),
9530
- max_results: z40.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
9512
+ max_results: z39.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
9531
9513
  }).strict(),
9532
9514
  outputSchema: juniorToolResultSchema,
9533
9515
  execute: async ({ query, max_results }) => {
@@ -11594,6 +11576,13 @@ function createClientMetadata(callbackUrl) {
11594
11576
  token_endpoint_auth_method: "none"
11595
11577
  };
11596
11578
  }
11579
+ function clientAllowsRedirectUri(clientInformation, callbackUrl) {
11580
+ const redirectUris = clientInformation.redirect_uris;
11581
+ if (!Array.isArray(redirectUris)) {
11582
+ return true;
11583
+ }
11584
+ return redirectUris.includes(callbackUrl);
11585
+ }
11597
11586
  var StateBackedMcpOAuthClientProvider = class {
11598
11587
  constructor(authSessionId, callbackUrl, sessionContext) {
11599
11588
  this.authSessionId = authSessionId;
@@ -11617,7 +11606,14 @@ var StateBackedMcpOAuthClientProvider = class {
11617
11606
  session.userId,
11618
11607
  session.provider
11619
11608
  );
11620
- return credentials?.clientInformation;
11609
+ const clientInformation = credentials?.clientInformation;
11610
+ if (!clientInformation) {
11611
+ return void 0;
11612
+ }
11613
+ if (clientAllowsRedirectUri(clientInformation, this.callbackUrl)) {
11614
+ return clientInformation;
11615
+ }
11616
+ return void 0;
11621
11617
  }
11622
11618
  async saveClientInformation(clientInformation) {
11623
11619
  const session = await this.getCredentialContext();
@@ -11928,7 +11924,11 @@ function createMcpAuthOrchestration(input) {
11928
11924
  channelId: authSession.channelId,
11929
11925
  threadTs: authSession.threadTs,
11930
11926
  userId: authSession.userId,
11931
- text: `<${authSession.authorizationUrl}|Click here to link your ${providerLabel} MCP access>. Once you've authorized, this thread will continue automatically.`
11927
+ text: formatOAuthAuthorizationMessage({
11928
+ authorizationUrl: authSession.authorizationUrl,
11929
+ label: `Click here to link your ${providerLabel} MCP access`,
11930
+ completionText: "Once you've authorized, this thread will continue automatically."
11931
+ })
11932
11932
  });
11933
11933
  if (!delivery) {
11934
11934
  throw new Error(