@sentry/junior 0.193.0 → 0.195.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 (99) hide show
  1. package/dist/{agent-hooks-DWY3MZZ7.js → agent-hooks-VIBTIP5F.js} +11 -11
  2. package/dist/api/activity.d.ts +9 -1
  3. package/dist/api/code/overview.d.ts +12 -0
  4. package/dist/api/conversations/aggregate.d.ts +2 -0
  5. package/dist/api/conversations/list.d.ts +1 -1
  6. package/dist/api/conversations/projection.d.ts +1 -1
  7. package/dist/api/locations/detail.d.ts +9 -1
  8. package/dist/api/locations/list.d.ts +5 -0
  9. package/dist/api/people/code.d.ts +6 -0
  10. package/dist/api/people/shared.d.ts +9 -1
  11. package/dist/api/reporting-window.d.ts +39 -1
  12. package/dist/api/schema/code.d.ts +12 -0
  13. package/dist/api/schema/conversation.d.ts +28 -3
  14. package/dist/api/schema/location.d.ts +14 -1
  15. package/dist/api/schema/person.d.ts +15 -1
  16. package/dist/api/schema/task.d.ts +83 -8
  17. package/dist/api/schema.d.ts +2 -2
  18. package/dist/api/schema.js +3 -1
  19. package/dist/api.js +320 -222
  20. package/dist/app.js +108 -39
  21. package/dist/{catalog-runtime-NAD44W5K.js → catalog-runtime-6E6SGRZK.js} +4 -4
  22. package/dist/chat/agent/resume.d.ts +2 -0
  23. package/dist/chat/config.d.ts +2 -0
  24. package/dist/chat/conversations/history.d.ts +4 -2
  25. package/dist/chat/event-tasks/store.d.ts +27 -17
  26. package/dist/chat/resource-events/notification.d.ts +2 -1
  27. package/dist/chat/services/automated-turn-limit.d.ts +110 -0
  28. package/dist/chat/services/turn-limit.d.ts +11 -1
  29. package/dist/chat/slack/automated-turn-limit-notice.d.ts +38 -0
  30. package/dist/chat/slack/{source-link.d.ts → location-url.d.ts} +1 -1
  31. package/dist/chat/task-execution/checkpoint.d.ts +2 -0
  32. package/dist/chat/task-execution/turn-cursor.d.ts +3 -0
  33. package/dist/chat/tasks/execution-stats.d.ts +15 -2
  34. package/dist/chat/tasks/read.d.ts +5 -2
  35. package/dist/chat/usage.d.ts +4 -0
  36. package/dist/{chunk-GUKGU6R7.js → chunk-3VWIZVK7.js} +1 -1
  37. package/dist/{chunk-THYNA2QN.js → chunk-5HNXLP4W.js} +1 -1
  38. package/dist/{chunk-GUMBIDDL.js → chunk-5NR7N567.js} +194 -43
  39. package/dist/{chunk-N6Q2PNSI.js → chunk-6GGDBXXP.js} +3 -3
  40. package/dist/{chunk-HMBTX5RK.js → chunk-6TRQLG3D.js} +1 -1
  41. package/dist/{chunk-IOUUS6H4.js → chunk-7MYXH5LA.js} +1 -1
  42. package/dist/{chunk-WH5VV2RW.js → chunk-7PQMTME5.js} +1 -1
  43. package/dist/{chunk-5E5SLAVD.js → chunk-7UED4D5T.js} +23 -25
  44. package/dist/{chunk-4UA5C7AM.js → chunk-BJZML4RT.js} +8 -8
  45. package/dist/{chunk-QDU5MW2R.js → chunk-C4NY6L7S.js} +1 -1
  46. package/dist/{chunk-DVU734PI.js → chunk-CE2P6TOV.js} +3 -3
  47. package/dist/{chunk-BFP3ZKG6.js → chunk-DTYOEHUP.js} +148 -19
  48. package/dist/{chunk-S5HS6WRH.js → chunk-FE3Y4KES.js} +5 -5
  49. package/dist/{chunk-PYBFVK6K.js → chunk-FEZIEEOP.js} +985 -569
  50. package/dist/{chunk-5S6AQFNG.js → chunk-FPQPYJEG.js} +23 -29
  51. package/dist/{chunk-42N6CDWF.js → chunk-HE5PZAPS.js} +4 -4
  52. package/dist/{chunk-QY2IU47O.js → chunk-HUQOXMDG.js} +1 -1
  53. package/dist/{chunk-IQCL5JGL.js → chunk-I4RH3KLJ.js} +1 -1
  54. package/dist/{chunk-LXRTHE43.js → chunk-JBSCMOLR.js} +5 -5
  55. package/dist/{chunk-OICYQPKP.js → chunk-KBPWC7NU.js} +1 -1
  56. package/dist/{chunk-2CYWEVOP.js → chunk-KQ3GZGBK.js} +88 -68
  57. package/dist/{chunk-GTXQHZ2O.js → chunk-KUQRWV53.js} +5 -5
  58. package/dist/{chunk-IBXXTO3J.js → chunk-L62JVQPL.js} +3 -3
  59. package/dist/{chunk-KWXZMHJS.js → chunk-LM7UE523.js} +3 -3
  60. package/dist/{chunk-WJJDQLVL.js → chunk-LMYRF6HX.js} +6 -2
  61. package/dist/{chunk-AZVDODSP.js → chunk-N67T4VY3.js} +9 -9
  62. package/dist/{chunk-D4XQZOHB.js → chunk-OQHO62VA.js} +8 -8
  63. package/dist/{chunk-FQ5HFSFR.js → chunk-PFQRZ4IB.js} +9 -6
  64. package/dist/{chunk-LG7Q4OW4.js → chunk-PYTRZZ4V.js} +8 -8
  65. package/dist/{chunk-THFNL3TL.js → chunk-QHJZSYKY.js} +2 -2
  66. package/dist/{chunk-5LEVZYXF.js → chunk-QKHZF2LH.js} +4 -4
  67. package/dist/{chunk-EYIMZY5O.js → chunk-QPZL2IYT.js} +100 -9
  68. package/dist/{chunk-D5YQPCEG.js → chunk-R5BGW4WR.js} +24 -2
  69. package/dist/{chunk-COCVPDWX.js → chunk-R5OHONYU.js} +6 -6
  70. package/dist/{chunk-DXFUYLHX.js → chunk-RKA22BQP.js} +1 -1
  71. package/dist/{chunk-3YZ2Q6AW.js → chunk-RQO67SAO.js} +2 -2
  72. package/dist/{chunk-ZFPEPWOO.js → chunk-RZ3PBNDV.js} +60 -29
  73. package/dist/{chunk-K47OVEO4.js → chunk-VYDIA2UL.js} +1 -1
  74. package/dist/{chunk-QWY4KI2V.js → chunk-X3PBQ4BK.js} +1 -1
  75. package/dist/cli/chat.js +33 -33
  76. package/dist/cli/check.js +5 -5
  77. package/dist/cli/plugins.js +12 -12
  78. package/dist/cli/snapshot-create.js +9 -9
  79. package/dist/cli/upgrade.js +6 -6
  80. package/dist/db/schema/event-tasks.d.ts +21 -0
  81. package/dist/db/schema.d.ts +19 -0
  82. package/dist/{db-H5MDRQEY.js → db-FVCSDROR.js} +6 -6
  83. package/dist/instrumentation.js +3 -3
  84. package/dist/nitro.js +6 -6
  85. package/dist/{oauth-callback-server-IOU3NUHT.js → oauth-callback-server-Z5PXTDOE.js} +29 -29
  86. package/dist/{runner-FZ5ZHLFG.js → runner-RHYU7OGV.js} +21 -21
  87. package/dist/{skills-AR3WD6BX.js → skills-QTN73DN5.js} +5 -5
  88. package/dist/spawn-R56OWLUH.js +42 -0
  89. package/dist/task-runner-LLJZTLRP.js +36 -0
  90. package/dist/{validation-VYE7TQY7.js → validation-2ZK7GA6N.js} +5 -5
  91. package/dist/version.js +1 -1
  92. package/dist/{work-CTQFWYKE.js → work-7IBKSZRU.js} +21 -21
  93. package/dist/{worker-6WQU3IT5.js → worker-RNVQVCO7.js} +10 -10
  94. package/migrations/0038_event_task_status.sql +5 -0
  95. package/migrations/meta/0038_snapshot.json +3323 -0
  96. package/migrations/meta/_journal.json +8 -1
  97. package/package.json +4 -4
  98. package/dist/spawn-ZU6JABR7.js +0 -42
  99. package/dist/task-runner-EEGGG2PM.js +0 -36
@@ -7,7 +7,7 @@ import {
7
7
  PluginCredentialFailureError,
8
8
  agentNameSchema,
9
9
  createPluginAuthOrchestration
10
- } from "./chunk-LXRTHE43.js";
10
+ } from "./chunk-JBSCMOLR.js";
11
11
  import {
12
12
  parseSandboxEgressAuthRequiredSignal,
13
13
  parseSandboxEgressPermissionDeniedSignal,
@@ -38,7 +38,7 @@ import {
38
38
  searchSlackUsers,
39
39
  selectPluginGrant,
40
40
  toMcpProviderError
41
- } from "./chunk-D4XQZOHB.js";
41
+ } from "./chunk-OQHO62VA.js";
42
42
  import {
43
43
  RetryableDeliveryError,
44
44
  actorFromRun,
@@ -48,11 +48,12 @@ import {
48
48
  formatProviderLabel,
49
49
  getSlackMessagePermalink,
50
50
  isAgentRunFeatureDisabled,
51
+ postSlackMessage,
51
52
  resolveBaseUrl,
52
53
  surfaceFromRun,
53
54
  toolInvocationDestination,
54
55
  uploadFilesToConversation
55
- } from "./chunk-COCVPDWX.js";
56
+ } from "./chunk-R5OHONYU.js";
56
57
  import {
57
58
  CooperativeTurnYieldError,
58
59
  NO_REPLY_MARKER,
@@ -65,7 +66,7 @@ import {
65
66
  isNoReplyMarker,
66
67
  isTurnInputCommitLostError,
67
68
  sanitizeAssistantText
68
- } from "./chunk-K47OVEO4.js";
69
+ } from "./chunk-VYDIA2UL.js";
69
70
  import {
70
71
  AGENTS_REMOVAL_NOTICE,
71
72
  AGENTS_REPLACEMENT_NOTICE,
@@ -74,6 +75,7 @@ import {
74
75
  RIPGREP_EXCLUDED_GLOBS,
75
76
  TURN_CONTEXT_TAG,
76
77
  TurnSliceLimitExceededError,
78
+ assertTurnToolCallLimit,
77
79
  buildAgentsInstructionsMessage,
78
80
  collectFiles,
79
81
  continuableMessages,
@@ -93,6 +95,7 @@ import {
93
95
  isMissingPathError,
94
96
  isToolResultError,
95
97
  isToolResultMessage,
98
+ isTurnExecutionLimitExceededError,
96
99
  listRepositoryDirectories,
97
100
  loadConnectedMcpProviders,
98
101
  loadConversationProjection,
@@ -119,7 +122,7 @@ import {
119
122
  stripRuntimeTurnContext,
120
123
  trimTrailingAssistantMessages,
121
124
  truncateText
122
- } from "./chunk-ZFPEPWOO.js";
125
+ } from "./chunk-RZ3PBNDV.js";
123
126
  import {
124
127
  SCHEDULED_TASK_SYSTEM_ACTOR,
125
128
  WORKSPACE_SNAPSHOT_FAILED_EVENT,
@@ -160,13 +163,13 @@ import {
160
163
  workspaceSnapshotFinishedEvent,
161
164
  workspaceSnapshotWatch,
162
165
  writableEventTask
163
- } from "./chunk-BFP3ZKG6.js";
166
+ } from "./chunk-DTYOEHUP.js";
164
167
  import {
165
168
  parseSlackThreadId
166
- } from "./chunk-HMBTX5RK.js";
169
+ } from "./chunk-6TRQLG3D.js";
167
170
  import {
168
171
  appendAndEnqueueInboundMessage
169
- } from "./chunk-5LEVZYXF.js";
172
+ } from "./chunk-QKHZF2LH.js";
170
173
  import {
171
174
  SHORT_TITLE_MAX_LENGTH,
172
175
  ToolInputError,
@@ -174,7 +177,7 @@ import {
174
177
  generateShortTitle,
175
178
  hasAgentTurnUsage,
176
179
  resolveTaskTitle
177
- } from "./chunk-D5YQPCEG.js";
180
+ } from "./chunk-R5BGW4WR.js";
178
181
  import {
179
182
  bindSandboxFileSystem,
180
183
  createSandboxSession,
@@ -185,7 +188,7 @@ import {
185
188
  resolve,
186
189
  setSnapshotSpanAttributes,
187
190
  stopSession
188
- } from "./chunk-IBXXTO3J.js";
191
+ } from "./chunk-L62JVQPL.js";
189
192
  import {
190
193
  privateTraceResultAttributes
191
194
  } from "./chunk-UIE3R5XU.js";
@@ -195,7 +198,7 @@ import {
195
198
  } from "./chunk-X6GDDWQH.js";
196
199
  import {
197
200
  getTurnRequestDeadline
198
- } from "./chunk-IQCL5JGL.js";
201
+ } from "./chunk-I4RH3KLJ.js";
199
202
  import {
200
203
  getVercelConversationWorkQueue
201
204
  } from "./chunk-DKIJ2RP5.js";
@@ -242,19 +245,23 @@ import {
242
245
  updateWorkspace,
243
246
  withSlackRetries,
244
247
  workspaceRepoCheckoutPath
245
- } from "./chunk-FQ5HFSFR.js";
248
+ } from "./chunk-PFQRZ4IB.js";
246
249
  import {
250
+ JUNIOR_THREAD_STATE_TTL_MS
251
+ } from "./chunk-3Y47VMHV.js";
252
+ import {
253
+ destinationKey,
247
254
  getConversationEventStore,
248
255
  getConversationMessageSearchStore,
249
256
  getConversationStore,
250
257
  getDb,
251
258
  getSqlExecutor
252
- } from "./chunk-2CYWEVOP.js";
259
+ } from "./chunk-KQ3GZGBK.js";
253
260
  import {
254
261
  juniorArtifacts,
255
262
  juniorIdentities,
256
263
  juniorSchedulerRuns
257
- } from "./chunk-5S6AQFNG.js";
264
+ } from "./chunk-FPQPYJEG.js";
258
265
  import {
259
266
  SANDBOX_DATA_ROOT,
260
267
  SANDBOX_REPOS_ROOT,
@@ -285,12 +292,12 @@ import {
285
292
  throwSandboxOperationError,
286
293
  workspaceSnapshotNotReadyUserMessage,
287
294
  wrapSandboxSetupError
288
- } from "./chunk-KWXZMHJS.js";
295
+ } from "./chunk-LM7UE523.js";
289
296
  import {
290
297
  fenceLock,
291
298
  getStateAdapter,
292
299
  withLock
293
- } from "./chunk-IOUUS6H4.js";
300
+ } from "./chunk-7MYXH5LA.js";
294
301
  import {
295
302
  KNOWN_CONVERSATION_EVENT_TYPES,
296
303
  contextProvenance,
@@ -323,7 +330,7 @@ import {
323
330
  resolveGatewayCredential,
324
331
  resolveGatewayModel,
325
332
  unwrapCurrentInstruction
326
- } from "./chunk-WJJDQLVL.js";
333
+ } from "./chunk-LMYRF6HX.js";
327
334
  import {
328
335
  ModelProfileNotConfiguredError,
329
336
  TURN_REASONING_LEVELS,
@@ -340,16 +347,16 @@ import {
340
347
  toGenAiMessagesTraceAttributes,
341
348
  toGenAiPayloadMetadata,
342
349
  toGenAiPayloadTraceAttributes
343
- } from "./chunk-OICYQPKP.js";
350
+ } from "./chunk-KBPWC7NU.js";
344
351
  import {
345
352
  discoverSkills,
346
353
  findSkillByName,
347
354
  loadSkillsByName,
348
355
  parseSkillInvocation
349
- } from "./chunk-3YZ2Q6AW.js";
356
+ } from "./chunk-RQO67SAO.js";
350
357
  import {
351
358
  pluginCatalogRuntime
352
- } from "./chunk-DXFUYLHX.js";
359
+ } from "./chunk-RKA22BQP.js";
353
360
  import {
354
361
  CredentialUnavailableError,
355
362
  OAuthProviderError,
@@ -357,7 +364,7 @@ import {
357
364
  getOAuthProviderErrorAttributes,
358
365
  resolveAuthTokenPlaceholder,
359
366
  resolvePluginCommandEnv
360
- } from "./chunk-QWY4KI2V.js";
367
+ } from "./chunk-X3PBQ4BK.js";
361
368
  import {
362
369
  credentialContextForActor,
363
370
  credentialUserSubjectId
@@ -393,7 +400,7 @@ import {
393
400
  summarizeMessageText,
394
401
  withLogContext,
395
402
  withSpan
396
- } from "./chunk-QY2IU47O.js";
403
+ } from "./chunk-HUQOXMDG.js";
397
404
  import {
398
405
  startInactiveSpan,
399
406
  withActiveSpan
@@ -3094,6 +3101,353 @@ async function prepareWorkspaceSnapshot(params) {
3094
3101
  // src/chat/resource-events/ingest.ts
3095
3102
  import { resourceEventSchema } from "@sentry/junior-plugin-api";
3096
3103
 
3104
+ // src/chat/services/automated-turn-limit.ts
3105
+ import { z as z3 } from "zod";
3106
+ var AUTOMATED_TURN_LIMIT_PREFIX = "junior:automated_turn_limit:v1";
3107
+ var AUTOMATED_TURN_LIMIT_LOCK_TTL_MS = 5e3;
3108
+ var AUTOMATED_TURN_LIMIT_LOCK_WAIT_MS = 2e3;
3109
+ var AUTOMATED_TURN_LIMIT_LOCK_RETRY_MS = 25;
3110
+ var automatedTurnLimitStateSchema = z3.object({
3111
+ consecutiveAutomatedTurns: z3.number().int().nonnegative(),
3112
+ noticePostedAtMs: z3.number().finite().nonnegative().optional(),
3113
+ paused: z3.boolean(),
3114
+ updatedAtMs: z3.number().finite().nonnegative()
3115
+ }).strict();
3116
+ function sleep2(ms) {
3117
+ return new Promise((resolve2) => {
3118
+ const timer = setTimeout(resolve2, ms);
3119
+ timer.unref?.();
3120
+ });
3121
+ }
3122
+ function scopeKey(scope) {
3123
+ if (scope.kind === "conversation") {
3124
+ return `${AUTOMATED_TURN_LIMIT_PREFIX}:conversation:${scope.conversationId}`;
3125
+ }
3126
+ return `${AUTOMATED_TURN_LIMIT_PREFIX}:destination:${destinationKey(scope.destination)}`;
3127
+ }
3128
+ function lockKey(key) {
3129
+ return `${key}:lock`;
3130
+ }
3131
+ function parseState(value) {
3132
+ const parsed = automatedTurnLimitStateSchema.safeParse(value);
3133
+ return parsed.success ? parsed.data : void 0;
3134
+ }
3135
+ async function acquireScopeLock(state, key, waitDeadlineMs = Date.now() + AUTOMATED_TURN_LIMIT_LOCK_WAIT_MS) {
3136
+ while (true) {
3137
+ const lock = await state.acquireLock(
3138
+ lockKey(key),
3139
+ AUTOMATED_TURN_LIMIT_LOCK_TTL_MS
3140
+ );
3141
+ if (lock) {
3142
+ return lock;
3143
+ }
3144
+ if (Date.now() >= waitDeadlineMs) {
3145
+ throw new Error(`Could not acquire automated turn limit lock for ${key}`);
3146
+ }
3147
+ await sleep2(AUTOMATED_TURN_LIMIT_LOCK_RETRY_MS);
3148
+ }
3149
+ }
3150
+ async function withScopeLock(state, key, callback) {
3151
+ const lock = await acquireScopeLock(state, key);
3152
+ try {
3153
+ return await callback();
3154
+ } finally {
3155
+ await state.releaseLock(lock);
3156
+ }
3157
+ }
3158
+ function emptyState(nowMs) {
3159
+ return {
3160
+ consecutiveAutomatedTurns: 0,
3161
+ paused: false,
3162
+ updatedAtMs: nowMs
3163
+ };
3164
+ }
3165
+ function resumeInForScope(scope) {
3166
+ return scope.kind === "conversation" ? "thread" : "channel";
3167
+ }
3168
+ function isAutomatedTurnSource(source) {
3169
+ if (!source) {
3170
+ return false;
3171
+ }
3172
+ return source.kind === "resource_event" || source.kind === "event_task" || source.kind === "scheduled_task" || source.kind === "plugin_dispatch" || source.kind === "agent_invocation";
3173
+ }
3174
+ function automatedTurnLimitScopeForSource(args) {
3175
+ if (!isAutomatedTurnSource(args.source)) {
3176
+ return void 0;
3177
+ }
3178
+ if (args.source?.kind === "resource_event") {
3179
+ return {
3180
+ kind: "conversation",
3181
+ conversationId: args.conversationId
3182
+ };
3183
+ }
3184
+ if (args.destination) {
3185
+ return { kind: "destination", destination: args.destination };
3186
+ }
3187
+ return {
3188
+ kind: "conversation",
3189
+ conversationId: args.conversationId
3190
+ };
3191
+ }
3192
+ function buildAutomatedTurnLimitResponse(args) {
3193
+ const place = args.resumeIn === "channel" ? "channel" : "thread";
3194
+ return `I stopped automatic updates after ${args.maxTurns} replies without a new message from you. Send a message or @mention me in this ${place} to continue.`;
3195
+ }
3196
+ async function admitAutomatedTurn(args) {
3197
+ if (args.maxTurns < 1) {
3198
+ throw new Error("Automated turn limit must be at least 1");
3199
+ }
3200
+ const state = args.state ?? getStateAdapter();
3201
+ await state.connect();
3202
+ const nowMs = args.nowMs ?? Date.now();
3203
+ const key = scopeKey(args.scope);
3204
+ return await withScopeLock(state, key, async () => {
3205
+ const current = parseState(await state.get(key)) ?? emptyState(nowMs);
3206
+ if (current.paused || current.consecutiveAutomatedTurns >= args.maxTurns) {
3207
+ const shouldPostNotice = current.noticePostedAtMs === void 0;
3208
+ const next = {
3209
+ consecutiveAutomatedTurns: Math.max(
3210
+ current.consecutiveAutomatedTurns,
3211
+ args.maxTurns
3212
+ ),
3213
+ paused: true,
3214
+ updatedAtMs: nowMs,
3215
+ // Claim the notice slot so concurrent paused wakes do not all post.
3216
+ // Callers must mark success or clear the claim if the post fails.
3217
+ ...shouldPostNotice ? { noticePostedAtMs: nowMs } : current.noticePostedAtMs !== void 0 ? { noticePostedAtMs: current.noticePostedAtMs } : void 0
3218
+ };
3219
+ await state.set(key, next, JUNIOR_THREAD_STATE_TTL_MS);
3220
+ return {
3221
+ status: "paused",
3222
+ consecutiveAutomatedTurns: next.consecutiveAutomatedTurns,
3223
+ shouldPostNotice
3224
+ };
3225
+ }
3226
+ return {
3227
+ status: "allow",
3228
+ consecutiveAutomatedTurns: current.consecutiveAutomatedTurns
3229
+ };
3230
+ });
3231
+ }
3232
+ async function countAutomatedTurn(args) {
3233
+ if (args.maxTurns < 1) {
3234
+ throw new Error("Automated turn limit must be at least 1");
3235
+ }
3236
+ const state = args.state ?? getStateAdapter();
3237
+ await state.connect();
3238
+ const nowMs = args.nowMs ?? Date.now();
3239
+ const key = scopeKey(args.scope);
3240
+ const resumeIn = resumeInForScope(args.scope);
3241
+ return await withScopeLock(state, key, async () => {
3242
+ const current = parseState(await state.get(key)) ?? emptyState(nowMs);
3243
+ const consecutiveAutomatedTurns = current.consecutiveAutomatedTurns + 1;
3244
+ const paused = consecutiveAutomatedTurns >= args.maxTurns;
3245
+ const shouldPostNotice = paused && current.noticePostedAtMs === void 0;
3246
+ const next = {
3247
+ consecutiveAutomatedTurns,
3248
+ paused,
3249
+ updatedAtMs: nowMs,
3250
+ // Claim the notice slot before the destination post. Mark success after
3251
+ // the post lands; clear the claim if the post fails or is skipped.
3252
+ ...shouldPostNotice ? { noticePostedAtMs: nowMs } : current.noticePostedAtMs !== void 0 ? { noticePostedAtMs: current.noticePostedAtMs } : void 0
3253
+ };
3254
+ await state.set(key, next, JUNIOR_THREAD_STATE_TTL_MS);
3255
+ return {
3256
+ consecutiveAutomatedTurns,
3257
+ paused,
3258
+ shouldPostNotice,
3259
+ resumeIn
3260
+ };
3261
+ });
3262
+ }
3263
+ async function clearAutomatedTurnLimitNoticeClaim(args) {
3264
+ const state = args.state ?? getStateAdapter();
3265
+ await state.connect();
3266
+ const nowMs = args.nowMs ?? Date.now();
3267
+ const key = scopeKey(args.scope);
3268
+ await withScopeLock(state, key, async () => {
3269
+ const current = parseState(await state.get(key));
3270
+ if (!current || current.noticePostedAtMs === void 0) {
3271
+ return;
3272
+ }
3273
+ const { noticePostedAtMs: _noticePostedAtMs, ...rest } = current;
3274
+ await state.set(
3275
+ key,
3276
+ {
3277
+ ...rest,
3278
+ updatedAtMs: nowMs
3279
+ },
3280
+ JUNIOR_THREAD_STATE_TTL_MS
3281
+ );
3282
+ });
3283
+ }
3284
+ async function resetAutomatedTurnLimit(args) {
3285
+ const state = args.state ?? getStateAdapter();
3286
+ await state.connect();
3287
+ const key = scopeKey(args.scope);
3288
+ await withScopeLock(state, key, async () => {
3289
+ await state.delete(key);
3290
+ });
3291
+ }
3292
+ async function recordFinishedTurnForAutomatedLimit(args) {
3293
+ const nowMs = args.nowMs ?? Date.now();
3294
+ const automatedScope = automatedTurnLimitScopeForSource({
3295
+ conversationId: args.conversationId,
3296
+ destination: args.destination,
3297
+ source: args.source
3298
+ });
3299
+ if (automatedScope) {
3300
+ return await countAutomatedTurn({
3301
+ maxTurns: args.maxTurns,
3302
+ nowMs,
3303
+ scope: automatedScope,
3304
+ state: args.state
3305
+ });
3306
+ }
3307
+ await resetAutomatedTurnLimit({
3308
+ nowMs,
3309
+ scope: {
3310
+ kind: "conversation",
3311
+ conversationId: args.conversationId
3312
+ },
3313
+ state: args.state
3314
+ });
3315
+ if (args.destination) {
3316
+ await resetAutomatedTurnLimit({
3317
+ nowMs,
3318
+ scope: { kind: "destination", destination: args.destination },
3319
+ state: args.state
3320
+ });
3321
+ }
3322
+ return void 0;
3323
+ }
3324
+
3325
+ // src/chat/slack/automated-turn-limit-notice.ts
3326
+ async function releaseFailedNoticeClaim(args) {
3327
+ try {
3328
+ await clearAutomatedTurnLimitNoticeClaim(args);
3329
+ } catch (error) {
3330
+ logException(error, "automated_turn_limit.notice_claim_clear_failed");
3331
+ }
3332
+ }
3333
+ async function postAutomatedTurnLimitNoticeForConversation(args) {
3334
+ const scope = args.scope ?? {
3335
+ kind: "conversation",
3336
+ conversationId: args.conversationId
3337
+ };
3338
+ try {
3339
+ const conversation = await getConversationStore().get({
3340
+ conversationId: args.conversationId
3341
+ });
3342
+ const location = conversation?.location;
3343
+ if (!location || location.provider !== "slack") {
3344
+ logWarn("automated_turn_limit.notice_skipped", {
3345
+ conversationId: args.conversationId,
3346
+ "app.automated_turn_limit.reason": location ? "unsupported_location" : "missing_location"
3347
+ });
3348
+ await releaseFailedNoticeClaim({
3349
+ nowMs: args.nowMs,
3350
+ scope
3351
+ });
3352
+ return false;
3353
+ }
3354
+ await postSlackMessage({
3355
+ channelId: location.channelId,
3356
+ text: buildAutomatedTurnLimitResponse({
3357
+ maxTurns: args.maxTurns,
3358
+ resumeIn: args.resumeIn ?? "thread"
3359
+ }),
3360
+ ...location.threadTs ? { threadTs: location.threadTs } : void 0
3361
+ });
3362
+ return true;
3363
+ } catch (error) {
3364
+ logException(error, "automated_turn_limit.notice_failed", {
3365
+ conversationId: args.conversationId
3366
+ });
3367
+ await releaseFailedNoticeClaim({
3368
+ nowMs: args.nowMs,
3369
+ scope
3370
+ });
3371
+ return false;
3372
+ }
3373
+ }
3374
+ async function postAutomatedTurnLimitNoticeForDestination(args) {
3375
+ const scope = args.scope ?? {
3376
+ kind: "destination",
3377
+ destination: args.destination
3378
+ };
3379
+ if (args.destination.platform !== "slack") {
3380
+ logWarn("automated_turn_limit.notice_skipped", {
3381
+ "app.automated_turn_limit.reason": "unsupported_destination"
3382
+ });
3383
+ await releaseFailedNoticeClaim({
3384
+ nowMs: args.nowMs,
3385
+ scope
3386
+ });
3387
+ return false;
3388
+ }
3389
+ try {
3390
+ await postSlackMessage({
3391
+ channelId: args.destination.channelId,
3392
+ text: buildAutomatedTurnLimitResponse({
3393
+ maxTurns: args.maxTurns,
3394
+ resumeIn: args.resumeIn ?? "channel"
3395
+ }),
3396
+ ...args.threadTs ? { threadTs: args.threadTs } : void 0
3397
+ });
3398
+ return true;
3399
+ } catch (error) {
3400
+ logException(error, "automated_turn_limit.notice_failed", {
3401
+ "app.slack.channel_id": args.destination.channelId,
3402
+ "app.slack.team_id": args.destination.teamId
3403
+ });
3404
+ await releaseFailedNoticeClaim({
3405
+ nowMs: args.nowMs,
3406
+ scope
3407
+ });
3408
+ return false;
3409
+ }
3410
+ }
3411
+ async function maybePostAutomatedTurnLimitNotice(args) {
3412
+ if (!args.update?.shouldPostNotice) {
3413
+ return;
3414
+ }
3415
+ if (args.update.resumeIn === "thread") {
3416
+ await postAutomatedTurnLimitNoticeForConversation({
3417
+ conversationId: args.conversationId,
3418
+ maxTurns: args.maxTurns,
3419
+ nowMs: args.nowMs,
3420
+ resumeIn: "thread",
3421
+ scope: {
3422
+ kind: "conversation",
3423
+ conversationId: args.conversationId
3424
+ }
3425
+ });
3426
+ return;
3427
+ }
3428
+ if (args.destination) {
3429
+ await postAutomatedTurnLimitNoticeForDestination({
3430
+ destination: args.destination,
3431
+ maxTurns: args.maxTurns,
3432
+ nowMs: args.nowMs,
3433
+ resumeIn: "channel",
3434
+ scope: { kind: "destination", destination: args.destination },
3435
+ threadTs: args.threadTs
3436
+ });
3437
+ return;
3438
+ }
3439
+ await postAutomatedTurnLimitNoticeForConversation({
3440
+ conversationId: args.conversationId,
3441
+ maxTurns: args.maxTurns,
3442
+ nowMs: args.nowMs,
3443
+ resumeIn: args.update.resumeIn,
3444
+ scope: {
3445
+ kind: "conversation",
3446
+ conversationId: args.conversationId
3447
+ }
3448
+ });
3449
+ }
3450
+
3097
3451
  // src/chat/task-input.ts
3098
3452
  function replyContractLines() {
3099
3453
  return [
@@ -3233,6 +3587,38 @@ function createResourceEventInboundMessage(input) {
3233
3587
  };
3234
3588
  }
3235
3589
  async function enqueueResourceEventNotification(args) {
3590
+ const maxTurns = botConfig.maxConsecutiveAutomatedTurns;
3591
+ const decision = await admitAutomatedTurn({
3592
+ maxTurns,
3593
+ nowMs: args.event.occurredAtMs,
3594
+ scope: {
3595
+ kind: "conversation",
3596
+ conversationId: args.subscription.conversationId
3597
+ },
3598
+ state: args.state
3599
+ });
3600
+ if (decision.status === "paused") {
3601
+ logInfo("resource_events.automated_turn_limit.paused", {
3602
+ conversationId: args.subscription.conversationId,
3603
+ "app.automated_turn_limit.consecutive": decision.consecutiveAutomatedTurns,
3604
+ "app.automated_turn_limit.max": maxTurns,
3605
+ "app.resource_event.event_type": args.event.eventType,
3606
+ "app.resource_event.namespace": args.event.namespace
3607
+ });
3608
+ if (decision.shouldPostNotice) {
3609
+ await postAutomatedTurnLimitNoticeForConversation({
3610
+ conversationId: args.subscription.conversationId,
3611
+ maxTurns,
3612
+ nowMs: args.event.occurredAtMs,
3613
+ resumeIn: "thread",
3614
+ scope: {
3615
+ kind: "conversation",
3616
+ conversationId: args.subscription.conversationId
3617
+ }
3618
+ });
3619
+ }
3620
+ return { status: "duplicate" };
3621
+ }
3236
3622
  const text = renderResourceEventNotificationText(
3237
3623
  args.subscription,
3238
3624
  args.event
@@ -5006,10 +5392,10 @@ function validateAndApplyTextEdits(content, edits, targetName) {
5006
5392
  }
5007
5393
 
5008
5394
  // src/chat/tools/sandbox/edit-file.ts
5009
- import { z as z4 } from "zod";
5395
+ import { z as z5 } from "zod";
5010
5396
 
5011
5397
  // src/chat/tool-support/zod-tool.ts
5012
- import { z as z3 } from "zod";
5398
+ import { z as z4 } from "zod";
5013
5399
  function isContentOnlyToolResult(value) {
5014
5400
  return value !== null && typeof value === "object" && Array.isArray(value.content) && !("details" in value);
5015
5401
  }
@@ -5046,7 +5432,7 @@ function zodTool(definition) {
5046
5432
  const { inputSchema: inputSchema2, outputSchema: outputSchema7, prepareArguments, execute, ...toolDef } = definition;
5047
5433
  let modelInputSchema;
5048
5434
  try {
5049
- modelInputSchema = z3.toJSONSchema(inputSchema2);
5435
+ modelInputSchema = z4.toJSONSchema(inputSchema2);
5050
5436
  } catch (error) {
5051
5437
  throw new TypeError(
5052
5438
  "zodTool() inputSchema must be representable as JSON Schema.",
@@ -5056,7 +5442,7 @@ function zodTool(definition) {
5056
5442
  let modelOutputSchema;
5057
5443
  if (outputSchema7) {
5058
5444
  try {
5059
- modelOutputSchema = z3.toJSONSchema(outputSchema7);
5445
+ modelOutputSchema = z4.toJSONSchema(outputSchema7);
5060
5446
  } catch (error) {
5061
5447
  throw new TypeError(
5062
5448
  "zodTool() outputSchema must be representable as JSON Schema.",
@@ -5141,11 +5527,11 @@ async function editFile(params) {
5141
5527
  truncated: diff.truncated
5142
5528
  });
5143
5529
  }
5144
- var editReplacementSchema = z4.object({
5145
- oldText: z4.string().min(1).describe(
5530
+ var editReplacementSchema = z5.object({
5531
+ oldText: z5.string().min(1).describe(
5146
5532
  "Exact text to replace. It must be unique in the original file and must not overlap another edit."
5147
5533
  ),
5148
- newText: z4.string().describe("Replacement text for this edit.")
5534
+ newText: z5.string().describe("Replacement text for this edit.")
5149
5535
  });
5150
5536
  function createEditFileTool() {
5151
5537
  return zodTool({
@@ -5158,9 +5544,9 @@ function createEditFileTool() {
5158
5544
  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.",
5159
5545
  prepareArguments: prepareEditFileArguments,
5160
5546
  executionMode: "sequential",
5161
- inputSchema: z4.object({
5162
- path: z4.string().min(1).describe("Path to edit in the sandbox workspace."),
5163
- edits: z4.array(editReplacementSchema).min(1).describe(
5547
+ inputSchema: z5.object({
5548
+ path: z5.string().min(1).describe("Path to edit in the sandbox workspace."),
5549
+ edits: z5.array(editReplacementSchema).min(1).describe(
5164
5550
  "Exact replacements matched against the original file, not incrementally."
5165
5551
  )
5166
5552
  }),
@@ -5175,7 +5561,7 @@ function createEditFileTool() {
5175
5561
 
5176
5562
  // src/chat/tools/sandbox/find-files.ts
5177
5563
  import path4 from "path";
5178
- import { z as z5 } from "zod";
5564
+ import { z as z6 } from "zod";
5179
5565
  var DEFAULT_FIND_LIMIT = 100;
5180
5566
  async function findFiles(params) {
5181
5567
  if (!params.pattern.trim()) {
@@ -5348,14 +5734,14 @@ function createFindFilesTool() {
5348
5734
  openWorldHint: false,
5349
5735
  readOnlyHint: true
5350
5736
  },
5351
- inputSchema: z5.object({
5352
- pattern: z5.string().min(1).describe(
5737
+ inputSchema: z6.object({
5738
+ pattern: z6.string().min(1).describe(
5353
5739
  "Glob pattern to match, for example '*.ts', '**/*.json', or 'src/**/*.test.ts'."
5354
5740
  ),
5355
- path: z5.string().min(1).describe(
5741
+ path: z6.string().min(1).describe(
5356
5742
  "Directory or file path in the sandbox workspace. Defaults to the workspace root."
5357
5743
  ).optional(),
5358
- limit: z5.coerce.number().int().min(1).describe("Maximum number of file paths to return. Defaults to 100.").optional()
5744
+ limit: z6.coerce.number().int().min(1).describe("Maximum number of file paths to return. Defaults to 100.").optional()
5359
5745
  }),
5360
5746
  outputSchema: juniorToolOutputSchema,
5361
5747
  execute: async () => {
@@ -5368,12 +5754,12 @@ function createFindFilesTool() {
5368
5754
 
5369
5755
  // src/chat/tools/sandbox/grep.ts
5370
5756
  import path5 from "path";
5371
- import { z as z6 } from "zod";
5757
+ import { z as z7 } from "zod";
5372
5758
  var DEFAULT_GREP_LIMIT = 100;
5373
5759
  var MAX_GREP_LINE_CHARS = 500;
5374
- var booleanInput = (description) => z6.preprocess(
5760
+ var booleanInput = (description) => z7.preprocess(
5375
5761
  (value) => value === "true" ? true : value === "false" ? false : value,
5376
- z6.boolean()
5762
+ z7.boolean()
5377
5763
  ).describe(description);
5378
5764
  function truncateGrepLine(value) {
5379
5765
  if (value.length <= MAX_GREP_LINE_CHARS) {
@@ -5727,20 +6113,20 @@ function createGrepTool() {
5727
6113
  openWorldHint: false,
5728
6114
  readOnlyHint: true
5729
6115
  },
5730
- inputSchema: z6.object({
5731
- pattern: z6.string().min(1).describe("Regex pattern or literal text to search for."),
5732
- path: z6.string().min(1).describe(
6116
+ inputSchema: z7.object({
6117
+ pattern: z7.string().min(1).describe("Regex pattern or literal text to search for."),
6118
+ path: z7.string().min(1).describe(
5733
6119
  "Directory or file path in the sandbox workspace. Defaults to the workspace root."
5734
6120
  ).optional(),
5735
- glob: z6.string().min(1).describe("Optional glob filter such as '*.ts' or '**/*.test.ts'.").optional(),
6121
+ glob: z7.string().min(1).describe("Optional glob filter such as '*.ts' or '**/*.test.ts'.").optional(),
5736
6122
  ignoreCase: booleanInput(
5737
6123
  "Whether matching should ignore case."
5738
6124
  ).optional(),
5739
6125
  literal: booleanInput(
5740
6126
  "Treat pattern as literal text instead of regex."
5741
6127
  ).optional(),
5742
- context: z6.coerce.number().int().min(0).describe("Number of surrounding context lines to include.").optional(),
5743
- limit: z6.coerce.number().int().min(1).describe("Maximum matches to return. Defaults to 100.").optional()
6128
+ context: z7.coerce.number().int().min(0).describe("Number of surrounding context lines to include.").optional(),
6129
+ limit: z7.coerce.number().int().min(1).describe("Maximum matches to return. Defaults to 100.").optional()
5744
6130
  }),
5745
6131
  outputSchema: juniorToolOutputSchema,
5746
6132
  execute: async () => {
@@ -5751,7 +6137,7 @@ function createGrepTool() {
5751
6137
 
5752
6138
  // src/chat/tools/sandbox/list-dir.ts
5753
6139
  import path6 from "path";
5754
- import { z as z7 } from "zod";
6140
+ import { z as z8 } from "zod";
5755
6141
  var DEFAULT_LIST_LIMIT = 500;
5756
6142
  async function listDir(params) {
5757
6143
  const dirPath = resolveWorkspacePath(params.path);
@@ -5832,11 +6218,11 @@ function createListDirTool() {
5832
6218
  openWorldHint: false,
5833
6219
  readOnlyHint: true
5834
6220
  },
5835
- inputSchema: z7.object({
5836
- path: z7.string().min(1).describe(
6221
+ inputSchema: z8.object({
6222
+ path: z8.string().min(1).describe(
5837
6223
  "Directory path in the sandbox workspace. Defaults to the workspace root."
5838
6224
  ).optional(),
5839
- limit: z7.coerce.number().int().min(1).describe("Maximum entries to return. Defaults to 500.").optional()
6225
+ limit: z8.coerce.number().int().min(1).describe("Maximum entries to return. Defaults to 500.").optional()
5840
6226
  }),
5841
6227
  outputSchema: juniorToolOutputSchema,
5842
6228
  execute: async () => {
@@ -5848,7 +6234,7 @@ function createListDirTool() {
5848
6234
  }
5849
6235
 
5850
6236
  // src/chat/tools/sandbox/read-file.ts
5851
- import { z as z8 } from "zod";
6237
+ import { z as z9 } from "zod";
5852
6238
 
5853
6239
  // src/chat/tool-support/text-range-result.ts
5854
6240
  var DEFAULT_READ_LIMIT = 1e3;
@@ -5942,10 +6328,10 @@ function createReadFileTool() {
5942
6328
  openWorldHint: false,
5943
6329
  readOnlyHint: true
5944
6330
  },
5945
- inputSchema: z8.object({
5946
- path: z8.string().min(1).describe("Path to the file in the sandbox workspace."),
5947
- offset: z8.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
5948
- limit: z8.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
6331
+ inputSchema: z9.object({
6332
+ path: z9.string().min(1).describe("Path to the file in the sandbox workspace."),
6333
+ offset: z9.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
6334
+ limit: z9.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
5949
6335
  }),
5950
6336
  outputSchema: juniorToolOutputSchema,
5951
6337
  execute: async () => {
@@ -6545,25 +6931,25 @@ function createSandbox(options) {
6545
6931
 
6546
6932
  // src/chat/tools/sandbox/file-uploads.ts
6547
6933
  import path7 from "path";
6548
- import { z as z9 } from "zod";
6934
+ import { z as z10 } from "zod";
6549
6935
  var MAX_SANDBOX_FILE_UPLOAD_BYTES = 10 * 1024 * 1024;
6550
6936
  var SANDBOX_ARTIFACTS_DIR = "/tmp/junior/artifacts";
6551
- var sandboxFileReferenceSchema = z9.object({
6552
- path: z9.string().min(1).describe(
6937
+ var sandboxFileReferenceSchema = z10.object({
6938
+ path: z10.string().min(1).describe(
6553
6939
  "Exact source path of an existing sandbox file. Preserve paths returned by other tools unchanged; do not move or rewrite them before sending."
6554
6940
  ),
6555
- filename: z9.string().min(1).nullable().optional().describe(
6941
+ filename: z10.string().min(1).nullable().optional().describe(
6556
6942
  "Optional filename override shown to the recipient. Null is treated as omitted."
6557
6943
  ),
6558
- mimeType: z9.string().min(1).nullable().optional().describe("Optional MIME type override. Null is treated as omitted."),
6559
- bytes: z9.number().int().nonnegative().nullable().optional().describe(
6944
+ mimeType: z10.string().min(1).nullable().optional().describe("Optional MIME type override. Null is treated as omitted."),
6945
+ bytes: z10.number().int().nonnegative().nullable().optional().describe(
6560
6946
  "Optional known file size returned by a producing tool. Null is treated as omitted; sending tools validate the file contents directly."
6561
6947
  )
6562
6948
  });
6563
6949
  var generatedArtifactFileRefSchema = sandboxFileReferenceSchema.extend({
6564
- filename: z9.string().min(1),
6565
- mimeType: z9.string().min(1).optional(),
6566
- bytes: z9.number().int().nonnegative()
6950
+ filename: z10.string().min(1),
6951
+ mimeType: z10.string().min(1).optional(),
6952
+ bytes: z10.number().int().nonnegative()
6567
6953
  }).strict();
6568
6954
  var MIME_BY_EXTENSION = {
6569
6955
  ".png": "image/png",
@@ -7814,7 +8200,7 @@ function serializeMcpPayload(payload, privacy, options = {}) {
7814
8200
  }
7815
8201
 
7816
8202
  // src/chat/tools/sandbox/bash.ts
7817
- import { z as z10 } from "zod";
8203
+ import { z as z11 } from "zod";
7818
8204
  function createBashTool() {
7819
8205
  return zodTool({
7820
8206
  annotations: {
@@ -7824,10 +8210,10 @@ function createBashTool() {
7824
8210
  readOnlyHint: false
7825
8211
  },
7826
8212
  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.",
7827
- inputSchema: z10.object({
7828
- command: z10.string().min(1).describe("Bash command to run inside the sandbox."),
7829
- cwd: z10.string().min(1).describe("Optional working directory for this command only.").optional(),
7830
- timeoutMs: z10.coerce.number().int().min(1e3).describe(
8213
+ inputSchema: z11.object({
8214
+ command: z11.string().min(1).describe("Bash command to run inside the sandbox."),
8215
+ cwd: z11.string().min(1).describe("Optional working directory for this command only.").optional(),
8216
+ timeoutMs: z11.coerce.number().int().min(1e3).describe(
7831
8217
  "Optional command timeout in milliseconds. Use for commands that may hang."
7832
8218
  ).optional()
7833
8219
  }),
@@ -7841,14 +8227,14 @@ function createBashTool() {
7841
8227
  }
7842
8228
 
7843
8229
  // src/chat/tools/web/image-generate.ts
7844
- import { z as z11 } from "zod";
8230
+ import { z as z12 } from "zod";
7845
8231
  var imageGenerateOutputSchema = juniorToolOutputSchema.extend({
7846
- model: z11.string(),
7847
- prompt: z11.string(),
7848
- enrichedPrompt: z11.string(),
7849
- image_count: z11.number().int().nonnegative(),
7850
- images: z11.array(generatedArtifactFileRefSchema),
7851
- delivery: z11.string()
8232
+ model: z12.string(),
8233
+ prompt: z12.string(),
8234
+ enrichedPrompt: z12.string(),
8235
+ image_count: z12.number().int().nonnegative(),
8236
+ images: z12.array(generatedArtifactFileRefSchema),
8237
+ delivery: z12.string()
7852
8238
  }).strict();
7853
8239
  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.
7854
8240
 
@@ -7910,8 +8296,8 @@ function createImageGenerateTool(hooks, options, deps = {}) {
7910
8296
  readOnlyHint: false
7911
8297
  },
7912
8298
  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.",
7913
- inputSchema: z11.object({
7914
- prompt: z11.string().min(1).max(4e3).describe("Image generation prompt.")
8299
+ inputSchema: z12.object({
8300
+ prompt: z12.string().min(1).max(4e3).describe("Image generation prompt.")
7915
8301
  }),
7916
8302
  outputSchema: imageGenerateOutputSchema,
7917
8303
  execute: async ({ prompt }) => {
@@ -8001,7 +8387,7 @@ function parseMcpProviderFromToolName(toolName) {
8001
8387
  }
8002
8388
 
8003
8389
  // src/chat/tools/skill/call-mcp-tool.ts
8004
- import { z as z12 } from "zod";
8390
+ import { z as z13 } from "zod";
8005
8391
  function resolveMcpArguments(input) {
8006
8392
  const extraKeys = Object.keys(input).filter(
8007
8393
  (key) => key !== "tool_name" && key !== "arguments"
@@ -8044,9 +8430,9 @@ function createCallMcpToolTool(mcpToolManager) {
8044
8430
  readOnlyHint: false
8045
8431
  },
8046
8432
  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.",
8047
- inputSchema: z12.object({
8048
- tool_name: z12.string().min(1).describe("Exact MCP tool_name from searchMcpTools."),
8049
- arguments: z12.record(z12.string(), z12.unknown()).describe(
8433
+ inputSchema: z13.object({
8434
+ tool_name: z13.string().min(1).describe("Exact MCP tool_name from searchMcpTools."),
8435
+ arguments: z13.record(z13.string(), z13.unknown()).describe(
8050
8436
  'Arguments matching the disclosed MCP tool schema, for example { "query": "..." } when searchMcpTools shows query is required.'
8051
8437
  ).optional()
8052
8438
  }).passthrough(),
@@ -8099,7 +8485,7 @@ function createCallMcpToolTool(mcpToolManager) {
8099
8485
  }
8100
8486
 
8101
8487
  // src/chat/tools/skill/load-skill.ts
8102
- import { z as z13 } from "zod";
8488
+ import { z as z14 } from "zod";
8103
8489
  function toLoadedSkill(result, availableSkills) {
8104
8490
  if (typeof result.skill_name !== "string" || typeof result.description !== "string" || typeof result.skill_dir !== "string" || typeof result.instructions !== "string") {
8105
8491
  return null;
@@ -8149,8 +8535,8 @@ function createLoadSkillTool(availableSkills, options) {
8149
8535
  readOnlyHint: false
8150
8536
  },
8151
8537
  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 skill instructions name an MCP provider, use searchMcpTools before callMcpTool. Use when a request clearly matches a known skill.",
8152
- inputSchema: z13.object({
8153
- skill_name: z13.string().min(1).describe("Skill name to load, without the leading slash.")
8538
+ inputSchema: z14.object({
8539
+ skill_name: z14.string().min(1).describe("Skill name to load, without the leading slash.")
8154
8540
  }),
8155
8541
  outputSchema: juniorToolOutputSchema,
8156
8542
  execute: async ({ skill_name }) => {
@@ -8165,7 +8551,7 @@ function createLoadSkillTool(availableSkills, options) {
8165
8551
  }
8166
8552
 
8167
8553
  // src/chat/tools/skill/search-mcp-tools.ts
8168
- import { z as z14 } from "zod";
8554
+ import { z as z15 } from "zod";
8169
8555
 
8170
8556
  // src/chat/tool-support/skill/mcp-tool-summary.ts
8171
8557
  function toExposedToolSummary(toolDef) {
@@ -8197,29 +8583,29 @@ function toActiveMcpCatalogSummaries(toolDefs) {
8197
8583
  // src/chat/tools/skill/search-mcp-tools.ts
8198
8584
  var DEFAULT_MAX_RESULTS = 5;
8199
8585
  var MAX_RESULTS = 20;
8200
- var providerSummarySchema = z14.object({
8201
- provider: z14.string(),
8202
- description: z14.string(),
8203
- active: z14.boolean()
8586
+ var providerSummarySchema = z15.object({
8587
+ provider: z15.string(),
8588
+ description: z15.string(),
8589
+ active: z15.boolean()
8204
8590
  }).strict();
8205
- var exposedToolSummarySchema = z14.object({
8206
- tool_name: z14.string(),
8207
- mcp_tool_name: z14.string(),
8208
- provider: z14.string(),
8209
- title: z14.string().optional(),
8210
- description: z14.string(),
8211
- input_schema: z14.record(z14.string(), z14.unknown()),
8212
- output_schema: z14.record(z14.string(), z14.unknown()).optional(),
8213
- annotations: z14.record(z14.string(), z14.unknown()).optional()
8591
+ var exposedToolSummarySchema = z15.object({
8592
+ tool_name: z15.string(),
8593
+ mcp_tool_name: z15.string(),
8594
+ provider: z15.string(),
8595
+ title: z15.string().optional(),
8596
+ description: z15.string(),
8597
+ input_schema: z15.record(z15.string(), z15.unknown()),
8598
+ output_schema: z15.record(z15.string(), z15.unknown()).optional(),
8599
+ annotations: z15.record(z15.string(), z15.unknown()).optional()
8214
8600
  }).strict();
8215
8601
  var searchMcpToolsOutputSchema = juniorToolOutputSchema.extend({
8216
- query: z14.string().nullable(),
8217
- provider: z14.string().nullable(),
8218
- total_active_tools: z14.number().int().nonnegative(),
8219
- returned_tools: z14.number().int().nonnegative(),
8220
- execution_tool: z14.literal("callMcpTool"),
8221
- available_providers: z14.array(providerSummarySchema),
8222
- tools: z14.array(exposedToolSummarySchema)
8602
+ query: z15.string().nullable(),
8603
+ provider: z15.string().nullable(),
8604
+ total_active_tools: z15.number().int().nonnegative(),
8605
+ returned_tools: z15.number().int().nonnegative(),
8606
+ execution_tool: z15.literal("callMcpTool"),
8607
+ available_providers: z15.array(providerSummarySchema),
8608
+ tools: z15.array(exposedToolSummarySchema)
8223
8609
  }).strict();
8224
8610
  function normalize(value) {
8225
8611
  return value.toLowerCase().replace(/[^a-z0-9_]+/g, " ").trim();
@@ -8345,14 +8731,14 @@ function createSearchMcpToolsTool(mcpToolManager) {
8345
8731
  readOnlyHint: true
8346
8732
  },
8347
8733
  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.",
8348
- inputSchema: z14.object({
8349
- query: z14.string().min(1).describe(
8734
+ inputSchema: z15.object({
8735
+ query: z15.string().min(1).describe(
8350
8736
  "Optional search terms describing the MCP tool or arguments needed."
8351
8737
  ).optional(),
8352
- provider: z14.string().min(1).describe(
8738
+ provider: z15.string().min(1).describe(
8353
8739
  "Optional provider name to list or search within. If configured but not yet connected, Junior activates it on demand."
8354
8740
  ).optional(),
8355
- max_results: z14.number().int().min(1).max(MAX_RESULTS).describe("Maximum matching tool descriptors to return.").optional()
8741
+ max_results: z15.number().int().min(1).max(MAX_RESULTS).describe("Maximum matching tool descriptors to return.").optional()
8356
8742
  }).strict(),
8357
8743
  outputSchema: searchMcpToolsOutputSchema,
8358
8744
  privateTraceResult: (result) => ({
@@ -8392,10 +8778,10 @@ function createSearchMcpToolsTool(mcpToolManager) {
8392
8778
  }
8393
8779
 
8394
8780
  // src/chat/tools/sandbox/view-image.ts
8395
- import { z as z15 } from "zod";
8781
+ import { z as z16 } from "zod";
8396
8782
  var MAX_VIEW_IMAGE_BYTES = 5 * 1024 * 1024;
8397
- var viewImageInputSchema = z15.object({
8398
- path: z15.string().min(1).describe("Path to an image file in the sandbox workspace.")
8783
+ var viewImageInputSchema = z16.object({
8784
+ path: z16.string().min(1).describe("Path to an image file in the sandbox workspace.")
8399
8785
  }).strict();
8400
8786
  function detectImageMimeType(data) {
8401
8787
  if (data.length >= 8 && data.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
@@ -8462,7 +8848,7 @@ function createViewImageTool(sandbox, supportsImageInput, deps = {}) {
8462
8848
  }
8463
8849
 
8464
8850
  // src/chat/tools/runtime/report-progress.ts
8465
- import { z as z16 } from "zod";
8851
+ import { z as z17 } from "zod";
8466
8852
  function createReportProgressTool() {
8467
8853
  return zodTool({
8468
8854
  annotations: {
@@ -8472,8 +8858,8 @@ function createReportProgressTool() {
8472
8858
  readOnlyHint: false
8473
8859
  },
8474
8860
  description: "Update the user-visible assistant loading message with a short progress phase. Use this only for work with multiple substantive phases or a materially long wait. Skip short lookups, routine commands, generic filler, and minor substeps. After an initial update, 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').",
8475
- inputSchema: z16.object({
8476
- message: z16.string().min(1).describe("Short user-facing progress message.")
8861
+ inputSchema: z17.object({
8862
+ message: z17.string().min(1).describe("Short user-facing progress message.")
8477
8863
  }),
8478
8864
  outputSchema: juniorToolOutputSchema,
8479
8865
  execute: async () => ({})
@@ -8481,9 +8867,9 @@ function createReportProgressTool() {
8481
8867
  }
8482
8868
 
8483
8869
  // src/chat/tools/runtime/spawn-agent.ts
8484
- import { z as z17 } from "zod";
8870
+ import { z as z18 } from "zod";
8485
8871
  var spawnAgentOutputSchema = juniorToolOutputSchema.extend({
8486
- invocation_id: z17.string().min(1)
8872
+ invocation_id: z18.string().min(1)
8487
8873
  });
8488
8874
  function createSpawnAgentTool(spawnAgent) {
8489
8875
  return zodTool({
@@ -8494,10 +8880,10 @@ function createSpawnAgentTool(spawnAgent) {
8494
8880
  openWorldHint: false,
8495
8881
  readOnlyHint: false
8496
8882
  },
8497
- inputSchema: z17.object({
8498
- task: z17.string().trim().min(1).describe("Task for the child agent"),
8883
+ inputSchema: z18.object({
8884
+ task: z18.string().trim().min(1).describe("Task for the child agent"),
8499
8885
  name: agentNameSchema.nullable().optional().describe("Stable child-agent name, or omit for a one-off agent"),
8500
- reasoning_level: z17.enum(TURN_REASONING_LEVELS).nullable().optional().describe(
8886
+ reasoning_level: z18.enum(TURN_REASONING_LEVELS).nullable().optional().describe(
8501
8887
  "Optional reasoning level for this delegated task only"
8502
8888
  )
8503
8889
  }).strict(),
@@ -8542,19 +8928,19 @@ function createSpawnAgentTool(spawnAgent) {
8542
8928
  }
8543
8929
 
8544
8930
  // src/chat/tools/list-resource-event-subscriptions.ts
8545
- import { z as z18 } from "zod";
8546
- var listedResourceWatchSchema = z18.object({
8547
- id: z18.string().min(1),
8548
- label: z18.string().min(1),
8549
- identifier: z18.string().min(1),
8550
- namespace: z18.string().min(1),
8551
- resourceType: z18.string().min(1),
8552
- events: z18.array(z18.string().min(1)).min(1),
8553
- match: z18.record(z18.string(), z18.unknown()).optional(),
8554
- intent: z18.string().min(1),
8555
- expiresAtMs: z18.number().finite()
8931
+ import { z as z19 } from "zod";
8932
+ var listedResourceWatchSchema = z19.object({
8933
+ id: z19.string().min(1),
8934
+ label: z19.string().min(1),
8935
+ identifier: z19.string().min(1),
8936
+ namespace: z19.string().min(1),
8937
+ resourceType: z19.string().min(1),
8938
+ events: z19.array(z19.string().min(1)).min(1),
8939
+ match: z19.record(z19.string(), z19.unknown()).optional(),
8940
+ intent: z19.string().min(1),
8941
+ expiresAtMs: z19.number().finite()
8556
8942
  }).strict();
8557
- var resultDataSchema = z18.object({ subscriptions: z18.array(listedResourceWatchSchema) }).strict();
8943
+ var resultDataSchema = z19.object({ subscriptions: z19.array(listedResourceWatchSchema) }).strict();
8558
8944
  var outputSchema = juniorToolOutputSchema.merge(resultDataSchema);
8559
8945
  function createListResourceEventSubscriptionsTool(context) {
8560
8946
  return zodTool({
@@ -8567,7 +8953,7 @@ function createListResourceEventSubscriptionsTool(context) {
8567
8953
  description: "List active resource event subscriptions for the current conversation.",
8568
8954
  exposure: "deferred",
8569
8955
  source: RESOURCE_WATCH_TOOL_SOURCE,
8570
- inputSchema: z18.object({}).strict(),
8956
+ inputSchema: z19.object({}).strict(),
8571
8957
  outputSchema,
8572
8958
  async execute() {
8573
8959
  const subscriptions = await listResourceEventSubscriptions({
@@ -8594,28 +8980,28 @@ function createListResourceEventSubscriptionsTool(context) {
8594
8980
  }
8595
8981
 
8596
8982
  // src/chat/tools/search-resource-event-types.ts
8597
- import { z as z19 } from "zod";
8983
+ import { z as z20 } from "zod";
8598
8984
  var DEFAULT_SEARCH_RESULTS = 10;
8599
8985
  var MAX_SEARCH_RESULTS = 20;
8600
- var searchedResourceTypeSchema = z19.object({
8601
- namespace: z19.string(),
8602
- type: z19.string(),
8603
- supportedEvents: z19.array(z19.string()),
8604
- suggestedEvents: z19.array(z19.string()).optional(),
8605
- matchFields: z19.record(
8606
- z19.string(),
8607
- z19.object({
8608
- kind: z19.enum(["boolean", "string", "number"]),
8609
- description: z19.string(),
8610
- enum: z19.array(z19.string()).optional()
8986
+ var searchedResourceTypeSchema = z20.object({
8987
+ namespace: z20.string(),
8988
+ type: z20.string(),
8989
+ supportedEvents: z20.array(z20.string()),
8990
+ suggestedEvents: z20.array(z20.string()).optional(),
8991
+ matchFields: z20.record(
8992
+ z20.string(),
8993
+ z20.object({
8994
+ kind: z20.enum(["boolean", "string", "number"]),
8995
+ description: z20.string(),
8996
+ enum: z20.array(z20.string()).optional()
8611
8997
  }).strict()
8612
8998
  ).optional()
8613
8999
  }).strict();
8614
9000
  var outputSchema2 = juniorToolOutputSchema.extend({
8615
- query: z19.string().nullable(),
8616
- namespace: z19.string().nullable(),
8617
- totalMatches: z19.number().int().nonnegative(),
8618
- resourceTypes: z19.array(searchedResourceTypeSchema)
9001
+ query: z20.string().nullable(),
9002
+ namespace: z20.string().nullable(),
9003
+ totalMatches: z20.number().int().nonnegative(),
9004
+ resourceTypes: z20.array(searchedResourceTypeSchema)
8619
9005
  }).strict();
8620
9006
  function normalizeSearchText(value) {
8621
9007
  return value.toLowerCase().replace(/[^a-z0-9_.-]+/g, " ").trim();
@@ -8642,12 +9028,12 @@ function createSearchResourceEventTypesTool(catalog) {
8642
9028
  readOnlyHint: true
8643
9029
  },
8644
9030
  description: "Search the resource event types currently enabled without creating anything. Includes plugin resources and core Workspace snapshot events. Use watchResourceEvents for temporary updates in the current conversation; use createEventTask for durable automation. This tool does not watch a resource, create a task, or list concrete resources.",
8645
- inputSchema: z19.object({
8646
- query: z19.string().nullable().describe(
9031
+ inputSchema: z20.object({
9032
+ query: z20.string().nullable().describe(
8647
9033
  "Optional terms matching a namespace, resource type, or event name. Empty lists all enabled resource event types."
8648
9034
  ).optional(),
8649
9035
  namespace: eventNamespaceSchema(catalog).nullable().describe("Optional enabled plugin namespace to search within.").optional(),
8650
- maxResults: z19.number().int().min(1).max(MAX_SEARCH_RESULTS).nullable().describe("Maximum matching resource types to return.").optional()
9036
+ maxResults: z20.number().int().min(1).max(MAX_SEARCH_RESULTS).nullable().describe("Maximum matching resource types to return.").optional()
8651
9037
  }).strict(),
8652
9038
  outputSchema: outputSchema2,
8653
9039
  async execute({ query, namespace, maxResults }) {
@@ -8686,10 +9072,10 @@ function createSearchResourceEventTypesTool(catalog) {
8686
9072
  }
8687
9073
 
8688
9074
  // src/chat/tools/stop-watching-resources.ts
8689
- import { z as z20 } from "zod";
8690
- var resultDataSchema2 = z20.object({
8691
- watching_status: z20.literal("stopped"),
8692
- stoppedIds: z20.array(z20.string().min(1))
9075
+ import { z as z21 } from "zod";
9076
+ var resultDataSchema2 = z21.object({
9077
+ watching_status: z21.literal("stopped"),
9078
+ stoppedIds: z21.array(z21.string().min(1))
8693
9079
  }).strict();
8694
9080
  var outputSchema3 = juniorToolOutputSchema.merge(resultDataSchema2);
8695
9081
  function createStopWatchingResourcesTool(context) {
@@ -8703,7 +9089,7 @@ function createStopWatchingResourcesTool(context) {
8703
9089
  description: "Stop one resource watch in the current conversation by id. Omit id only when the user explicitly asks to stop every watch in this conversation. Infer terse stop requests from context, inspect active watches when the target is unclear, and call this tool before confirming that watching stopped.",
8704
9090
  exposure: "deferred",
8705
9091
  source: RESOURCE_WATCH_TOOL_SOURCE,
8706
- inputSchema: z20.object({ id: z20.string().min(1).nullable().optional() }).strict(),
9092
+ inputSchema: z21.object({ id: z21.string().min(1).nullable().optional() }).strict(),
8707
9093
  outputSchema: outputSchema3,
8708
9094
  async execute({ id }) {
8709
9095
  let stoppedIds;
@@ -8737,25 +9123,25 @@ function createStopWatchingResourcesTool(context) {
8737
9123
  }
8738
9124
 
8739
9125
  // src/chat/tools/watch-resource-events.ts
8740
- import { z as z21 } from "zod";
9126
+ import { z as z22 } from "zod";
8741
9127
  function inputSchema(catalog) {
8742
- return z21.object({
8743
- identifier: z21.string().trim().min(1).describe("Plugin-defined resource identifier."),
9128
+ return z22.object({
9129
+ identifier: z22.string().trim().min(1).describe("Plugin-defined resource identifier."),
8744
9130
  namespace: eventNamespaceSchema(catalog).describe(
8745
9131
  "Enabled plugin namespace for this resource."
8746
9132
  ),
8747
9133
  resourceType: registeredResourceTypeSchema(catalog).describe(
8748
9134
  "Plugin-defined resource type."
8749
9135
  ),
8750
- label: z21.string().trim().min(1).max(500).describe("Human-readable resource label."),
8751
- events: z21.array(registeredEventTypeSchema(catalog)).min(1).describe(
9136
+ label: z22.string().trim().min(1).max(500).describe("Human-readable resource label."),
9137
+ events: z22.array(registeredEventTypeSchema(catalog)).min(1).describe(
8752
9138
  "High-signal event names to deliver to this conversation when they occur."
8753
9139
  ),
8754
9140
  match: registeredResourceEventMatchSchema(),
8755
- intent: z21.string().trim().min(1).max(4e3).describe(
9141
+ intent: z22.string().trim().min(1).max(4e3).describe(
8756
9142
  "Concise reason this conversation wants these events, used when an event arrives."
8757
9143
  ),
8758
- ttlMs: z21.coerce.number().describe(
9144
+ ttlMs: z22.coerce.number().describe(
8759
9145
  "How long to keep the subscription active. Defaults to 14 days and must not exceed 30 days."
8760
9146
  ).optional()
8761
9147
  }).strict().superRefine((subscription, context) => {
@@ -8775,20 +9161,20 @@ function inputSchema(catalog) {
8775
9161
  });
8776
9162
  });
8777
9163
  }
8778
- var stopWatchingActionSchema = z21.object({
8779
- execution_tool: z21.literal("executeTool"),
8780
- execution_example: z21.object({
8781
- tool_name: z21.literal(STOP_WATCHING_TOOL_NAME),
8782
- arguments: z21.object({ id: z21.string().min(1) }).strict()
9164
+ var stopWatchingActionSchema = z22.object({
9165
+ execution_tool: z22.literal("executeTool"),
9166
+ execution_example: z22.object({
9167
+ tool_name: z22.literal(STOP_WATCHING_TOOL_NAME),
9168
+ arguments: z22.object({ id: z22.string().min(1) }).strict()
8783
9169
  }).strict()
8784
9170
  }).strict();
8785
- var resultDataSchema3 = z21.object({
8786
- id: z21.string().min(1),
8787
- subscription_status: z21.enum(["active", "cancelled", "completed"]),
8788
- identifier: z21.string().min(1),
8789
- events: z21.array(z21.string().min(1)).min(1),
8790
- match: z21.record(z21.string(), z21.unknown()).optional(),
8791
- expiresAtMs: z21.number().finite(),
9171
+ var resultDataSchema3 = z22.object({
9172
+ id: z22.string().min(1),
9173
+ subscription_status: z22.enum(["active", "cancelled", "completed"]),
9174
+ identifier: z22.string().min(1),
9175
+ events: z22.array(z22.string().min(1)).min(1),
9176
+ match: z22.record(z22.string(), z22.unknown()).optional(),
9177
+ expiresAtMs: z22.number().finite(),
8792
9178
  stop_watching: stopWatchingActionSchema
8793
9179
  }).strict();
8794
9180
  var outputSchema4 = juniorToolOutputSchema.merge(resultDataSchema3);
@@ -8890,7 +9276,7 @@ function createResourceEventTools(context, catalog) {
8890
9276
 
8891
9277
  // src/chat/tools/create-event-task.ts
8892
9278
  import { createHash } from "crypto";
8893
- import { z as z22 } from "zod";
9279
+ import { z as z23 } from "zod";
8894
9280
  function buildEventTaskId(args) {
8895
9281
  const toolCallId = args.toolCallId?.trim();
8896
9282
  if (!toolCallId) {
@@ -8918,13 +9304,13 @@ function createEventTaskTool(context, catalog) {
8918
9304
  },
8919
9305
  executionMode: "sequential",
8920
9306
  description: "Create a durable event task that executes the supplied instruction for every matching resource event. Use for whenever-this-happens-do-X automation; ordinary watch, notify, or tell-me-when requests use watchResourceEvents instead. The task may use the creator's connected credentials. Prefer a subscribable tool result when available.",
8921
- inputSchema: z22.object({
8922
- task: z22.string().trim().min(1).max(4e3),
8923
- title: z22.string().trim().min(1).max(SHORT_TITLE_MAX_LENGTH).nullable().describe(
9307
+ inputSchema: z23.object({
9308
+ task: z23.string().trim().min(1).max(4e3),
9309
+ title: z23.string().trim().min(1).max(SHORT_TITLE_MAX_LENGTH).nullable().describe(
8924
9310
  "Optional short display title. Omit or use null to generate one from the task instruction."
8925
9311
  ).optional(),
8926
9312
  trigger,
8927
- credentialMode: z22.enum(["creator", "system"]).nullable().describe(
9313
+ credentialMode: z23.enum(["creator", "system"]).nullable().describe(
8928
9314
  "Use creator to make the task creator's connected credentials available, or system when the creator says not to use them. Omit or use null for the creator default."
8929
9315
  ).optional()
8930
9316
  }).strict(),
@@ -8955,7 +9341,9 @@ function createEventTaskTool(context, catalog) {
8955
9341
  if (!eventTaskMatchesDestination(existing, destination) || existing.createdBy.slackUserId !== actor.userId) {
8956
9342
  throw new ToolInputError("Event task operation identity is invalid.");
8957
9343
  }
8958
- return eventTaskSuccess(existing, catalog);
9344
+ if (existing.status !== "deleted") {
9345
+ return eventTaskSuccess(existing, catalog);
9346
+ }
8959
9347
  }
8960
9348
  const title = await resolveTaskTitle({
8961
9349
  completeText,
@@ -8994,7 +9382,7 @@ function createEventTaskTool(context, catalog) {
8994
9382
  }
8995
9383
 
8996
9384
  // src/chat/tools/delete-event-task.ts
8997
- import { z as z23 } from "zod";
9385
+ import { z as z24 } from "zod";
8998
9386
  function createDeleteEventTaskTool(context, catalog) {
8999
9387
  return zodTool({
9000
9388
  approvalMode: "review",
@@ -9006,7 +9394,7 @@ function createDeleteEventTaskTool(context, catalog) {
9006
9394
  },
9007
9395
  executionMode: "sequential",
9008
9396
  description: "Delete an event task.",
9009
- inputSchema: z23.object({ taskId: z23.string().min(1) }).strict(),
9397
+ inputSchema: z24.object({ taskId: z24.string().min(1) }).strict(),
9010
9398
  outputSchema: eventTaskToolResultSchema,
9011
9399
  async execute({ taskId }) {
9012
9400
  const current = await writableEventTask(context, taskId);
@@ -9020,7 +9408,7 @@ function createDeleteEventTaskTool(context, catalog) {
9020
9408
  }
9021
9409
 
9022
9410
  // src/chat/tools/list-event-tasks.ts
9023
- import { z as z24 } from "zod";
9411
+ import { z as z25 } from "zod";
9024
9412
  var MAX_LISTED_EVENT_TASKS = 50;
9025
9413
  function createListEventTasksTool(context, catalog) {
9026
9414
  return zodTool({
@@ -9031,7 +9419,7 @@ function createListEventTasksTool(context, catalog) {
9031
9419
  readOnlyHint: true
9032
9420
  },
9033
9421
  description: "List event tasks for the current destination. A false triggerAvailable value means the task remains stored but its plugin event is not currently enabled.",
9034
- inputSchema: z24.object({}).strict(),
9422
+ inputSchema: z25.object({}).strict(),
9035
9423
  outputSchema: eventTaskListToolResultSchema,
9036
9424
  async execute() {
9037
9425
  const { destination } = requireEventTaskSlackContext(context);
@@ -9047,7 +9435,7 @@ function createListEventTasksTool(context, catalog) {
9047
9435
 
9048
9436
  // src/chat/tools/update-event-task.ts
9049
9437
  import { stableResourceEventMatchKey } from "@sentry/junior-plugin-api";
9050
- import { z as z25 } from "zod";
9438
+ import { z as z26 } from "zod";
9051
9439
  function changesEventTaskTrigger(current, next) {
9052
9440
  const currentEvents = [...current.events].sort();
9053
9441
  const nextEvents = [...next.events].sort();
@@ -9064,11 +9452,11 @@ function createUpdateEventTaskTool(context, catalog) {
9064
9452
  },
9065
9453
  executionMode: "sequential",
9066
9454
  description: "Update the instruction, registered trigger, or credential use for an event task.",
9067
- inputSchema: z25.object({
9068
- taskId: z25.string().min(1),
9069
- task: z25.string().trim().min(1).max(4e3).nullable().optional(),
9455
+ inputSchema: z26.object({
9456
+ taskId: z26.string().min(1),
9457
+ task: z26.string().trim().min(1).max(4e3).nullable().optional(),
9070
9458
  trigger: registeredEventTaskTriggerSchema(catalog).nullable().optional(),
9071
- credentialMode: z25.enum(["system", "creator"]).nullable().describe(
9459
+ credentialMode: z26.enum(["system", "creator"]).nullable().describe(
9072
9460
  "Set creator to make the task's original creator credentials available, or system to disable them. Creator always means the task's createdBy actor, never the current requester. Only that original creator may enable creator mode. Omit or use null to leave unchanged."
9073
9461
  ).optional()
9074
9462
  }).strict(),
@@ -9150,10 +9538,10 @@ function createEventTaskTools(context, catalog) {
9150
9538
  }
9151
9539
 
9152
9540
  // src/chat/scheduled-tasks/tools/create.ts
9153
- import { z as z28 } from "zod";
9541
+ import { z as z29 } from "zod";
9154
9542
 
9155
9543
  // src/chat/scheduled-tasks/schedule-intent.ts
9156
- import { z as z26 } from "zod";
9544
+ import { z as z27 } from "zod";
9157
9545
 
9158
9546
  // src/chat/scheduled-tasks/cadence.ts
9159
9547
  var FORMATTERS = /* @__PURE__ */ new Map();
@@ -9444,12 +9832,12 @@ function getNextRunAtMs(task, scheduledForMs, afterMs = scheduledForMs) {
9444
9832
  }
9445
9833
 
9446
9834
  // src/chat/scheduled-tasks/schedule-intent.ts
9447
- var localDateSchema = z26.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Use a local date in YYYY-MM-DD format.");
9448
- var localTimeSchema = z26.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "Use local time in HH:MM format.");
9449
- var timezoneSchema = z26.string().min(1).max(80).describe(
9835
+ var localDateSchema = z27.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Use a local date in YYYY-MM-DD format.");
9836
+ var localTimeSchema = z27.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "Use local time in HH:MM format.");
9837
+ var timezoneSchema = z27.string().min(1).max(80).describe(
9450
9838
  "IANA timezone, for example America/Los_Angeles. Omit or use null for the scheduler default."
9451
9839
  ).nullable().optional();
9452
- var weekdaySchema = z26.enum([
9840
+ var weekdaySchema = z27.enum([
9453
9841
  "sunday",
9454
9842
  "monday",
9455
9843
  "tuesday",
@@ -9458,17 +9846,17 @@ var weekdaySchema = z26.enum([
9458
9846
  "friday",
9459
9847
  "saturday"
9460
9848
  ]);
9461
- var oneOffScheduleIntentSchema = z26.object({
9462
- kind: z26.literal("one_off").describe("A schedule that runs once."),
9849
+ var oneOffScheduleIntentSchema = z27.object({
9850
+ kind: z27.literal("one_off").describe("A schedule that runs once."),
9463
9851
  timezone: timezoneSchema,
9464
- timing: z26.discriminatedUnion("type", [
9465
- z26.object({
9466
- type: z26.literal("after").describe("Run after a relative delay from the server clock."),
9467
- value: z26.number().int().positive().max(1e5),
9468
- unit: z26.enum(["second", "minute", "hour", "day", "week"])
9852
+ timing: z27.discriminatedUnion("type", [
9853
+ z27.object({
9854
+ type: z27.literal("after").describe("Run after a relative delay from the server clock."),
9855
+ value: z27.number().int().positive().max(1e5),
9856
+ unit: z27.enum(["second", "minute", "hour", "day", "week"])
9469
9857
  }).strict(),
9470
- z26.object({
9471
- type: z26.literal("at").describe("Run at an explicit local calendar date and time."),
9858
+ z27.object({
9859
+ type: z27.literal("at").describe("Run at an explicit local calendar date and time."),
9472
9860
  date: localDateSchema.describe(
9473
9861
  "Requested local calendar date in YYYY-MM-DD format."
9474
9862
  ),
@@ -9478,16 +9866,16 @@ var oneOffScheduleIntentSchema = z26.object({
9478
9866
  }).strict()
9479
9867
  ]).describe("Relative delay or explicit local time for the one-off run.")
9480
9868
  }).strict();
9481
- var recurringScheduleIntentSchema = z26.object({
9482
- kind: z26.literal("recurring").describe("A repeating calendar schedule."),
9483
- frequency: z26.enum(["daily", "weekly", "monthly", "yearly"]).describe("Recurring tasks can run at most once per day."),
9484
- interval: z26.number().int().positive().max(365).describe("Repeat every N frequency units. Defaults to 1.").nullable().optional(),
9869
+ var recurringScheduleIntentSchema = z27.object({
9870
+ kind: z27.literal("recurring").describe("A repeating calendar schedule."),
9871
+ frequency: z27.enum(["daily", "weekly", "monthly", "yearly"]).describe("Recurring tasks can run at most once per day."),
9872
+ interval: z27.number().int().positive().max(365).describe("Repeat every N frequency units. Defaults to 1.").nullable().optional(),
9485
9873
  time: localTimeSchema.describe(
9486
9874
  "Local wall-clock time for each occurrence in HH:MM format."
9487
9875
  ),
9488
- weekdays: z26.array(weekdaySchema).min(1).max(7).describe("Required for weekly schedules.").nullable().optional(),
9489
- day_of_month: z26.number().int().min(1).max(31).describe("Required for monthly and yearly schedules.").nullable().optional(),
9490
- month: z26.number().int().min(1).max(12).describe("Required for yearly schedules, where January is 1.").nullable().optional(),
9876
+ weekdays: z27.array(weekdaySchema).min(1).max(7).describe("Required for weekly schedules.").nullable().optional(),
9877
+ day_of_month: z27.number().int().min(1).max(31).describe("Required for monthly and yearly schedules.").nullable().optional(),
9878
+ month: z27.number().int().min(1).max(12).describe("Required for yearly schedules, where January is 1.").nullable().optional(),
9491
9879
  start_date: localDateSchema.describe(
9492
9880
  "Optional local calendar date that anchors the recurrence. Omit to start with the next matching occurrence."
9493
9881
  ).nullable().optional(),
@@ -9536,7 +9924,7 @@ var recurringScheduleIntentSchema = z26.object({
9536
9924
  });
9537
9925
  }
9538
9926
  });
9539
- var scheduleIntentSchema = z26.union([
9927
+ var scheduleIntentSchema = z27.union([
9540
9928
  oneOffScheduleIntentSchema,
9541
9929
  recurringScheduleIntentSchema
9542
9930
  ]);
@@ -9731,7 +10119,7 @@ import { createHash as createHash2 } from "crypto";
9731
10119
  import {
9732
10120
  sourceSchema
9733
10121
  } from "@sentry/junior-plugin-api";
9734
- import { z as z27 } from "zod";
10122
+ import { z as z28 } from "zod";
9735
10123
 
9736
10124
  // src/chat/scheduled-tasks/identity.ts
9737
10125
  var SLACK_USER_ID_PATTERN = /^[UW][A-Z0-9]{5,}$/;
@@ -9768,36 +10156,36 @@ function sanitizeScheduledTaskPrincipal(principal) {
9768
10156
  var TASK_ID_PREFIX = "sched";
9769
10157
  var MAX_LISTED_TASKS = 50;
9770
10158
  var DEFAULT_SCHEDULE_TIMEZONE = "America/Los_Angeles";
9771
- var compactTaskResultSchema = z27.object({
9772
- id: z27.string(),
9773
- status: z27.enum(["active", "blocked", "completed", "deleted"]),
9774
- task: z27.string(),
9775
- schedule: z27.string(),
9776
- timezone: z27.string(),
9777
- recurrence: z27.unknown().nullable(),
9778
- next_run_at: z27.string().nullable(),
9779
- destination: z27.object({
9780
- platform: z27.literal("slack"),
9781
- team_id: z27.string().min(1),
9782
- channel_id: z27.string().min(1)
10159
+ var compactTaskResultSchema = z28.object({
10160
+ id: z28.string(),
10161
+ status: z28.enum(["active", "blocked", "completed", "deleted"]),
10162
+ task: z28.string(),
10163
+ schedule: z28.string(),
10164
+ timezone: z28.string(),
10165
+ recurrence: z28.unknown().nullable(),
10166
+ next_run_at: z28.string().nullable(),
10167
+ destination: z28.object({
10168
+ platform: z28.literal("slack"),
10169
+ team_id: z28.string().min(1),
10170
+ channel_id: z28.string().min(1)
9783
10171
  }).strict(),
9784
- conversation_access: z27.object({
9785
- audience: z27.enum(["direct", "group", "channel"]),
9786
- visibility: z27.enum(["private", "public"])
10172
+ conversation_access: z28.object({
10173
+ audience: z28.enum(["direct", "group", "channel"]),
10174
+ visibility: z28.enum(["private", "public"])
9787
10175
  }).strict(),
9788
- credential_mode: z27.enum(["system", "creator"]),
9789
- dashboard_url: z27.string().url().nullable(),
9790
- last_run_at: z27.string().nullable(),
9791
- run_now_at: z27.string().nullable()
10176
+ credential_mode: z28.enum(["system", "creator"]),
10177
+ dashboard_url: z28.string().url().nullable(),
10178
+ last_run_at: z28.string().nullable(),
10179
+ run_now_at: z28.string().nullable()
9792
10180
  }).strict();
9793
10181
  var scheduleTaskToolResultSchema = juniorToolOutputSchema.extend({
9794
- target: z27.string(),
10182
+ target: z28.string(),
9795
10183
  task: compactTaskResultSchema
9796
10184
  }).strict();
9797
10185
  var scheduleListToolResultSchema = juniorToolOutputSchema.extend({
9798
- target: z27.string(),
9799
- tasks: z27.array(compactTaskResultSchema),
9800
- truncated: z27.boolean()
10186
+ target: z28.string(),
10187
+ tasks: z28.array(compactTaskResultSchema),
10188
+ truncated: z28.boolean()
9801
10189
  }).strict();
9802
10190
  function throwToolInputError(error) {
9803
10191
  throw new ToolInputError(error);
@@ -9960,15 +10348,15 @@ function createSlackScheduleCreateTaskTool(context) {
9960
10348
  },
9961
10349
  description: "Create a one-time or recurring Junior task in the active Slack conversation when the user asks Junior to do work later or repeatedly.",
9962
10350
  executionMode: "sequential",
9963
- inputSchema: z28.object({
9964
- task: z28.string().min(1).max(4e3),
9965
- title: z28.string().trim().min(1).max(SHORT_TITLE_MAX_LENGTH).nullable().describe(
10351
+ inputSchema: z29.object({
10352
+ task: z29.string().min(1).max(4e3),
10353
+ title: z29.string().trim().min(1).max(SHORT_TITLE_MAX_LENGTH).nullable().describe(
9966
10354
  "Optional short display title. Omit or use null to generate one from the task instruction."
9967
10355
  ).optional(),
9968
10356
  schedule: scheduleIntentSchema.describe(
9969
10357
  "When the task runs. The scheduler computes the exact next run from this intent and the server clock."
9970
10358
  ),
9971
- credential_mode: z28.enum(["creator", "system"]).nullable().describe(
10359
+ credential_mode: z29.enum(["creator", "system"]).nullable().describe(
9972
10360
  "Use creator to make the task creator's connected credentials available, or system when the creator says not to use them. Omit or use null for the creator default."
9973
10361
  ).optional()
9974
10362
  }).strict(),
@@ -10067,7 +10455,7 @@ function createSlackScheduleCreateTaskTool(context) {
10067
10455
  }
10068
10456
 
10069
10457
  // src/chat/scheduled-tasks/tools/delete.ts
10070
- import { z as z29 } from "zod";
10458
+ import { z as z30 } from "zod";
10071
10459
  function createSlackScheduleDeleteTaskTool(context) {
10072
10460
  return zodTool({
10073
10461
  approvalMode: "review",
@@ -10079,8 +10467,8 @@ function createSlackScheduleDeleteTaskTool(context) {
10079
10467
  },
10080
10468
  description: "Delete one scheduled Junior task from the active Slack conversation. Use only task IDs returned for this conversation. Do not delete schedules from threads, other channels, or another user's DM.",
10081
10469
  executionMode: "sequential",
10082
- inputSchema: z29.object({
10083
- task_id: z29.string().min(1).describe(
10470
+ inputSchema: z30.object({
10471
+ task_id: z30.string().min(1).describe(
10084
10472
  "ID of the task to delete. Must be from this active Slack conversation."
10085
10473
  )
10086
10474
  }),
@@ -10104,12 +10492,12 @@ function createSlackScheduleDeleteTaskTool(context) {
10104
10492
  }
10105
10493
 
10106
10494
  // src/chat/slack/id-param.ts
10107
- import { z as z30 } from "zod";
10495
+ import { z as z31 } from "zod";
10108
10496
  function slackChannelIdParam(description) {
10109
- return z30.string().min(1).describe(description);
10497
+ return z31.string().min(1).describe(description);
10110
10498
  }
10111
10499
  function slackUserIdParam(description) {
10112
- return z30.string().min(1).describe(description);
10500
+ return z31.string().min(1).describe(description);
10113
10501
  }
10114
10502
  function parseRequiredSlackChannelIdParam(field, value) {
10115
10503
  const channelId = parseSlackChannelId(value);
@@ -10133,7 +10521,7 @@ function parseRequiredSlackUserIdParam(field, value) {
10133
10521
  }
10134
10522
 
10135
10523
  // src/chat/scheduled-tasks/tools/list.ts
10136
- import { z as z31 } from "zod";
10524
+ import { z as z32 } from "zod";
10137
10525
  function taskMatchesQuery(task, query) {
10138
10526
  const normalized = query.toLowerCase();
10139
10527
  return [
@@ -10153,11 +10541,11 @@ function createSlackScheduleListTasksTool(context) {
10153
10541
  openWorldHint: false,
10154
10542
  readOnlyHint: true
10155
10543
  },
10156
- inputSchema: z31.object({
10544
+ inputSchema: z32.object({
10157
10545
  channel_id: slackChannelIdParam(
10158
10546
  "Current destination channel ID to filter by. Use the ID from a channel mention; do not guess."
10159
10547
  ).nullable().optional(),
10160
- query: z31.string().trim().min(1).max(200).nullable().describe("Text to match in the requester's scheduled tasks.").optional()
10548
+ query: z32.string().trim().min(1).max(200).nullable().describe("Text to match in the requester's scheduled tasks.").optional()
10161
10549
  }).strict(),
10162
10550
  outputSchema: scheduleListToolResultSchema,
10163
10551
  execute: async (input) => {
@@ -10205,7 +10593,7 @@ function createSlackScheduleListTasksTool(context) {
10205
10593
  }
10206
10594
 
10207
10595
  // src/chat/scheduled-tasks/tools/run-now.ts
10208
- import { z as z32 } from "zod";
10596
+ import { z as z33 } from "zod";
10209
10597
  function createSlackScheduleRunTaskNowTool(context) {
10210
10598
  return zodTool({
10211
10599
  approvalMode: "review",
@@ -10217,8 +10605,8 @@ function createSlackScheduleRunTaskNowTool(context) {
10217
10605
  },
10218
10606
  description: "Queue an existing active scheduled Junior task to run as soon as possible, without changing its cadence. Use when the user asks to run an existing scheduled task now. Use only task IDs returned for this conversation.",
10219
10607
  executionMode: "sequential",
10220
- inputSchema: z32.object({
10221
- task_id: z32.string().min(1).describe(
10608
+ inputSchema: z33.object({
10609
+ task_id: z33.string().min(1).describe(
10222
10610
  "ID of the active task to run now. Must be from this active Slack conversation."
10223
10611
  )
10224
10612
  }),
@@ -10246,7 +10634,7 @@ function createSlackScheduleRunTaskNowTool(context) {
10246
10634
  }
10247
10635
 
10248
10636
  // src/chat/scheduled-tasks/tools/update.ts
10249
- import { z as z33 } from "zod";
10637
+ import { z as z34 } from "zod";
10250
10638
  import { and, eq, inArray } from "drizzle-orm";
10251
10639
  function createSlackScheduleUpdateTaskTool(context) {
10252
10640
  return zodTool({
@@ -10259,17 +10647,17 @@ function createSlackScheduleUpdateTaskTool(context) {
10259
10647
  },
10260
10648
  description: `Update a scheduled task. To move the requester's task into this Slack conversation, set destination to "here".`,
10261
10649
  executionMode: "sequential",
10262
- inputSchema: z33.object({
10263
- task_id: z33.string().min(1).describe("Scheduled task ID returned by slackScheduleListTasks."),
10264
- task: z33.string().min(1).max(4e3).optional(),
10650
+ inputSchema: z34.object({
10651
+ task_id: z34.string().min(1).describe("Scheduled task ID returned by slackScheduleListTasks."),
10652
+ task: z34.string().min(1).max(4e3).optional(),
10265
10653
  schedule: scheduleIntentSchema.describe("Complete replacement schedule. Omit to keep it unchanged.").nullable().optional(),
10266
- status: z33.enum(["active", "blocked"]).describe(
10654
+ status: z34.enum(["active", "blocked"]).describe(
10267
10655
  "Set active to resume a blocked task, or blocked to stop dispatch."
10268
10656
  ).optional(),
10269
- destination: z33.literal("here").nullable().describe(
10657
+ destination: z34.literal("here").nullable().describe(
10270
10658
  `Set to "here" to move the creator's task into this Slack conversation. Omit to keep its destination.`
10271
10659
  ).optional(),
10272
- credential_mode: z33.enum(["system", "creator"]).nullable().describe(
10660
+ credential_mode: z34.enum(["system", "creator"]).nullable().describe(
10273
10661
  "Use creator credentials or system credentials. Only the task creator may enable creator mode. Omit to keep unchanged."
10274
10662
  ).optional()
10275
10663
  }).strict(),
@@ -10628,9 +11016,9 @@ async function joinPublicChannelForRead(args) {
10628
11016
  }
10629
11017
 
10630
11018
  // src/chat/slack/tool-support/channel-target.ts
10631
- import { z as z34 } from "zod";
11019
+ import { z as z35 } from "zod";
10632
11020
  var SLACK_CHANNEL_REF_MAX_LENGTH = 160;
10633
- var slackChannelRefParam = z34.string().trim().min(1).max(SLACK_CHANNEL_REF_MAX_LENGTH).describe(
11021
+ var slackChannelRefParam = z35.string().trim().min(1).max(SLACK_CHANNEL_REF_MAX_LENGTH).describe(
10634
11022
  "Slack channel id (`C123`), mention (`<#C123>` / `<#C123|name>`), Junior slack reference (`slack:C123`), or a channel name Junior already knows in this workspace."
10635
11023
  );
10636
11024
  async function resolveSlackChannelRef(input) {
@@ -10678,7 +11066,7 @@ async function resolveOptionalSlackChannelRef(input) {
10678
11066
  }
10679
11067
 
10680
11068
  // src/chat/slack/tools/channel-join.ts
10681
- import { z as z35 } from "zod";
11069
+ import { z as z36 } from "zod";
10682
11070
  function createSlackChannelJoinTool(context) {
10683
11071
  return zodTool({
10684
11072
  description: "Join a public Slack channel.",
@@ -10688,7 +11076,7 @@ function createSlackChannelJoinTool(context) {
10688
11076
  openWorldHint: true,
10689
11077
  readOnlyHint: false
10690
11078
  },
10691
- inputSchema: z35.object({
11079
+ inputSchema: z36.object({
10692
11080
  channel_id: slackChannelRefParam
10693
11081
  }),
10694
11082
  outputSchema: juniorToolOutputSchema,
@@ -10745,11 +11133,11 @@ function createSlackChannelJoinTool(context) {
10745
11133
  }
10746
11134
 
10747
11135
  // src/chat/slack/timestamp-param.ts
10748
- import { z as z36 } from "zod";
11136
+ import { z as z37 } from "zod";
10749
11137
  function slackTimestampParam(description) {
10750
- return z36.preprocess(
11138
+ return z37.preprocess(
10751
11139
  (value) => typeof value === "number" && Number.isFinite(value) ? String(value) : value,
10752
- z36.string().min(1)
11140
+ z37.string().min(1)
10753
11141
  ).describe(description);
10754
11142
  }
10755
11143
  function parseSlackTimestampParam(field, value) {
@@ -10777,10 +11165,10 @@ function parseRequiredSlackTimestampParam(field, value) {
10777
11165
  }
10778
11166
 
10779
11167
  // src/chat/slack/tools/channel-list-messages.ts
10780
- import { z as z37 } from "zod";
10781
- var booleanInput2 = (description) => z37.preprocess(
11168
+ import { z as z38 } from "zod";
11169
+ var booleanInput2 = (description) => z38.preprocess(
10782
11170
  (value) => value === "true" ? true : value === "false" ? false : value,
10783
- z37.boolean()
11171
+ z38.boolean()
10784
11172
  ).describe(description);
10785
11173
  function normalizeRangeTimestamp(field, value, targetChannelId) {
10786
11174
  if (value === void 0) {
@@ -10812,10 +11200,10 @@ function createSlackChannelListMessagesTool(context) {
10812
11200
  openWorldHint: true,
10813
11201
  readOnlyHint: true
10814
11202
  },
10815
- inputSchema: z37.object({
11203
+ inputSchema: z38.object({
10816
11204
  channel_id: slackChannelRefParam.optional(),
10817
- limit: z37.coerce.number().int().min(1).max(1e3).describe("Maximum number of messages to return across pages.").optional(),
10818
- cursor: z37.string().min(1).describe("Optional cursor to continue from a prior call.").optional(),
11205
+ limit: z38.coerce.number().int().min(1).max(1e3).describe("Maximum number of messages to return across pages.").optional(),
11206
+ cursor: z38.string().min(1).describe("Optional cursor to continue from a prior call.").optional(),
10819
11207
  oldest: slackTimestampParam(
10820
11208
  "Oldest message timestamp (Slack ts) for range filtering."
10821
11209
  ).optional(),
@@ -10825,7 +11213,7 @@ function createSlackChannelListMessagesTool(context) {
10825
11213
  inclusive: booleanInput2(
10826
11214
  "Whether oldest/latest bounds should be inclusive."
10827
11215
  ).optional(),
10828
- max_pages: z37.coerce.number().int().min(1).max(10).describe("Maximum number of API pages to traverse in a single call.").optional()
11216
+ max_pages: z38.coerce.number().int().min(1).max(10).describe("Maximum number of API pages to traverse in a single call.").optional()
10829
11217
  }),
10830
11218
  outputSchema: juniorToolOutputSchema,
10831
11219
  execute: async ({
@@ -10948,7 +11336,7 @@ function createSlackChannelListMessagesTool(context) {
10948
11336
  }
10949
11337
 
10950
11338
  // src/chat/slack/tools/conversation-message-search.ts
10951
- import { z as z38 } from "zod";
11339
+ import { z as z39 } from "zod";
10952
11340
 
10953
11341
  // src/chat/conversations/tool-source.ts
10954
11342
  var CONVERSATIONS_TOOL_SOURCE = {
@@ -10960,23 +11348,23 @@ var CONVERSATIONS_TOOL_SOURCE = {
10960
11348
  var DEFAULT_LIMIT = 20;
10961
11349
  var MAX_LIMIT = 50;
10962
11350
  var conversationMessageSearchOutputSchema = juniorToolOutputSchema.extend({
10963
- after: z38.string().datetime().optional(),
10964
- annotation: z38.string().min(1).optional(),
10965
- before: z38.string().datetime().optional(),
10966
- channel_id: z38.string().min(1).optional(),
10967
- count: z38.number().int().nonnegative(),
10968
- query: z38.string().optional(),
10969
- matches: z38.array(
10970
- z38.object({
10971
- channel_id: z38.string().min(1),
10972
- channel_name: z38.string().min(1).optional(),
10973
- conversation_id: z38.string().min(1),
10974
- excerpt: z38.string(),
10975
- message_id: z38.string().min(1),
10976
- message_role: z38.enum(["assistant", "user"]),
10977
- message_timestamp: z38.string().datetime(),
10978
- permalink: z38.string().url().optional(),
10979
- thread_ts: z38.string().min(1)
11351
+ after: z39.string().datetime().optional(),
11352
+ annotation: z39.string().min(1).optional(),
11353
+ before: z39.string().datetime().optional(),
11354
+ channel_id: z39.string().min(1).optional(),
11355
+ count: z39.number().int().nonnegative(),
11356
+ query: z39.string().optional(),
11357
+ matches: z39.array(
11358
+ z39.object({
11359
+ channel_id: z39.string().min(1),
11360
+ channel_name: z39.string().min(1).optional(),
11361
+ conversation_id: z39.string().min(1),
11362
+ excerpt: z39.string(),
11363
+ message_id: z39.string().min(1),
11364
+ message_role: z39.enum(["assistant", "user"]),
11365
+ message_timestamp: z39.string().datetime(),
11366
+ permalink: z39.string().url().optional(),
11367
+ thread_ts: z39.string().min(1)
10980
11368
  }).strict()
10981
11369
  )
10982
11370
  });
@@ -11031,15 +11419,15 @@ function createSlackConversationMessageSearchTool(scope, currentConversationId)
11031
11419
  openWorldHint: false,
11032
11420
  readOnlyHint: true
11033
11421
  },
11034
- inputSchema: z38.object({
11035
- after: z38.string().datetime().nullable().describe("Include conversations active at or after this timestamp.").optional(),
11036
- annotation: z38.string().trim().min(1).max(256).nullable().describe(
11422
+ inputSchema: z39.object({
11423
+ after: z39.string().datetime().nullable().describe("Include conversations active at or after this timestamp.").optional(),
11424
+ annotation: z39.string().trim().min(1).max(256).nullable().describe(
11037
11425
  "Linked resource key. Matches that key, or nested children that continue with #."
11038
11426
  ).optional(),
11039
- before: z38.string().datetime().nullable().describe("Include conversations active before this timestamp.").optional(),
11427
+ before: z39.string().datetime().nullable().describe("Include conversations active before this timestamp.").optional(),
11040
11428
  channel_id: slackChannelRefParam.nullable().optional(),
11041
- query: z38.string().trim().min(1).max(200).nullable().describe("Words or phrase to match in message text.").optional(),
11042
- limit: z38.number().int().min(1).max(MAX_LIMIT).describe(
11429
+ query: z39.string().trim().min(1).max(200).nullable().describe("Words or phrase to match in message text.").optional(),
11430
+ limit: z39.number().int().min(1).max(MAX_LIMIT).describe(
11043
11431
  `Maximum conversations. Default ${DEFAULT_LIMIT}; max ${MAX_LIMIT}.`
11044
11432
  ).nullable().optional()
11045
11433
  }).strict(),
@@ -11098,13 +11486,13 @@ function createSlackConversationMessageSearchTool(scope, currentConversationId)
11098
11486
  }
11099
11487
 
11100
11488
  // src/chat/slack/tools/public-search.ts
11101
- import { z as z39 } from "zod";
11489
+ import { z as z40 } from "zod";
11102
11490
  var DEFAULT_LIMIT2 = 10;
11103
11491
  var DEFAULT_CONTENT_TYPES = ["messages"];
11104
11492
  var CONTENT_TYPES = ["messages", "files", "channels", "users"];
11105
- var unixTimestampParam = z39.coerce.number().int().nonnegative();
11493
+ var unixTimestampParam = z40.coerce.number().int().nonnegative();
11106
11494
  function optionalUnixTimestampParam(description) {
11107
- return z39.preprocess(
11495
+ return z40.preprocess(
11108
11496
  (value) => typeof value === "string" && value.trim() === "" ? void 0 : value,
11109
11497
  unixTimestampParam.optional()
11110
11498
  ).describe(description);
@@ -11118,64 +11506,64 @@ function normalizeOptionalUnixTimestamp(value) {
11118
11506
  }
11119
11507
  return unixTimestampParam.parse(value);
11120
11508
  }
11121
- var searchMessageSchema = z39.object({
11122
- author_name: z39.string().min(1).optional().describe("Author display name."),
11123
- author_user_id: z39.string().min(1).optional().describe("Author user ID."),
11124
- channel_id: z39.string().min(1).describe("Channel ID."),
11125
- channel_name: z39.string().min(1).optional().describe("Channel name."),
11126
- message_ts: z39.string().min(1).describe("Message timestamp."),
11127
- content: z39.string().describe("Message text."),
11128
- is_author_bot: z39.boolean().optional().describe("Whether the author is a bot."),
11129
- permalink: z39.string().url().describe("Message permalink.")
11509
+ var searchMessageSchema = z40.object({
11510
+ author_name: z40.string().min(1).optional().describe("Author display name."),
11511
+ author_user_id: z40.string().min(1).optional().describe("Author user ID."),
11512
+ channel_id: z40.string().min(1).describe("Channel ID."),
11513
+ channel_name: z40.string().min(1).optional().describe("Channel name."),
11514
+ message_ts: z40.string().min(1).describe("Message timestamp."),
11515
+ content: z40.string().describe("Message text."),
11516
+ is_author_bot: z40.boolean().optional().describe("Whether the author is a bot."),
11517
+ permalink: z40.string().url().describe("Message permalink.")
11130
11518
  });
11131
- var searchFileSchema = z39.object({
11132
- file_id: z39.string().min(1).describe("File ID."),
11133
- title: z39.string().min(1).optional().describe("File title."),
11134
- name: z39.string().min(1).optional().describe("File name."),
11135
- filetype: z39.string().min(1).optional().describe("File type."),
11136
- user_id: z39.string().min(1).optional().describe("Uploader user ID."),
11137
- user_name: z39.string().min(1).optional().describe("Uploader user name."),
11138
- channel_id: z39.string().min(1).optional().describe("Channel ID."),
11139
- channel_name: z39.string().min(1).optional().describe("Channel name."),
11140
- permalink: z39.string().url().optional().describe("File permalink."),
11141
- content: z39.string().min(1).optional().describe("File preview or content snippet.")
11519
+ var searchFileSchema = z40.object({
11520
+ file_id: z40.string().min(1).describe("File ID."),
11521
+ title: z40.string().min(1).optional().describe("File title."),
11522
+ name: z40.string().min(1).optional().describe("File name."),
11523
+ filetype: z40.string().min(1).optional().describe("File type."),
11524
+ user_id: z40.string().min(1).optional().describe("Uploader user ID."),
11525
+ user_name: z40.string().min(1).optional().describe("Uploader user name."),
11526
+ channel_id: z40.string().min(1).optional().describe("Channel ID."),
11527
+ channel_name: z40.string().min(1).optional().describe("Channel name."),
11528
+ permalink: z40.string().url().optional().describe("File permalink."),
11529
+ content: z40.string().min(1).optional().describe("File preview or content snippet.")
11142
11530
  });
11143
- var searchChannelSchema = z39.object({
11144
- channel_id: z39.string().min(1).describe("Channel ID."),
11145
- channel_name: z39.string().min(1).optional().describe("Channel name."),
11146
- is_private: z39.boolean().optional().describe("Whether the channel is private."),
11147
- is_member: z39.boolean().optional().describe("Whether the bot is a member."),
11148
- topic: z39.string().min(1).optional().describe("Channel topic."),
11149
- purpose: z39.string().min(1).optional().describe("Channel purpose."),
11150
- permalink: z39.string().url().optional().describe("Channel permalink.")
11531
+ var searchChannelSchema = z40.object({
11532
+ channel_id: z40.string().min(1).describe("Channel ID."),
11533
+ channel_name: z40.string().min(1).optional().describe("Channel name."),
11534
+ is_private: z40.boolean().optional().describe("Whether the channel is private."),
11535
+ is_member: z40.boolean().optional().describe("Whether the bot is a member."),
11536
+ topic: z40.string().min(1).optional().describe("Channel topic."),
11537
+ purpose: z40.string().min(1).optional().describe("Channel purpose."),
11538
+ permalink: z40.string().url().optional().describe("Channel permalink.")
11151
11539
  });
11152
- var searchUserSchema = z39.object({
11153
- user_id: z39.string().min(1).describe("User ID."),
11154
- user_name: z39.string().min(1).optional().describe("Username."),
11155
- real_name: z39.string().min(1).optional().describe("Real name."),
11156
- display_name: z39.string().min(1).optional().describe("Display name."),
11157
- title: z39.string().min(1).optional().describe("Profile title."),
11158
- permalink: z39.string().url().optional().describe("Profile permalink.")
11540
+ var searchUserSchema = z40.object({
11541
+ user_id: z40.string().min(1).describe("User ID."),
11542
+ user_name: z40.string().min(1).optional().describe("Username."),
11543
+ real_name: z40.string().min(1).optional().describe("Real name."),
11544
+ display_name: z40.string().min(1).optional().describe("Display name."),
11545
+ title: z40.string().min(1).optional().describe("Profile title."),
11546
+ permalink: z40.string().url().optional().describe("Profile permalink.")
11159
11547
  });
11160
11548
  var publicSearchOutputSchema = juniorToolOutputSchema.extend({
11161
- query: z39.string().describe("Search query."),
11162
- content_types: z39.array(z39.enum(CONTENT_TYPES)).describe("Content types included in the search."),
11163
- count: z39.number().int().nonnegative().describe("Total matched results."),
11164
- messages: z39.array(searchMessageSchema).describe("Matched messages."),
11165
- files: z39.array(searchFileSchema).describe("Matched files."),
11166
- channels: z39.array(searchChannelSchema).describe("Matched channels."),
11167
- users: z39.array(searchUserSchema).describe("Matched users."),
11168
- next_cursor: z39.string().min(1).optional().describe("Cursor for the next result page.")
11549
+ query: z40.string().describe("Search query."),
11550
+ content_types: z40.array(z40.enum(CONTENT_TYPES)).describe("Content types included in the search."),
11551
+ count: z40.number().int().nonnegative().describe("Total matched results."),
11552
+ messages: z40.array(searchMessageSchema).describe("Matched messages."),
11553
+ files: z40.array(searchFileSchema).describe("Matched files."),
11554
+ channels: z40.array(searchChannelSchema).describe("Matched channels."),
11555
+ users: z40.array(searchUserSchema).describe("Matched users."),
11556
+ next_cursor: z40.string().min(1).optional().describe("Cursor for the next result page.")
11169
11557
  });
11170
- var nonEmptyString = z39.string().trim().min(1);
11171
- var optionalWireString = z39.preprocess((value) => {
11558
+ var nonEmptyString = z40.string().trim().min(1);
11559
+ var optionalWireString = z40.preprocess((value) => {
11172
11560
  if (typeof value !== "string") {
11173
11561
  return void 0;
11174
11562
  }
11175
11563
  const trimmed = value.trim();
11176
11564
  return trimmed === "" ? void 0 : trimmed;
11177
11565
  }, nonEmptyString.optional());
11178
- var optionalWireUrl = z39.preprocess((value) => {
11566
+ var optionalWireUrl = z40.preprocess((value) => {
11179
11567
  if (typeof value !== "string") {
11180
11568
  return void 0;
11181
11569
  }
@@ -11189,20 +11577,20 @@ var optionalWireUrl = z39.preprocess((value) => {
11189
11577
  } catch {
11190
11578
  return void 0;
11191
11579
  }
11192
- }, z39.string().url().optional());
11193
- var optionalWireBoolean = z39.preprocess(
11580
+ }, z40.string().url().optional());
11581
+ var optionalWireBoolean = z40.preprocess(
11194
11582
  (value) => typeof value === "boolean" ? value : void 0,
11195
- z39.boolean().optional()
11583
+ z40.boolean().optional()
11196
11584
  );
11197
- var slackSearchMessageWireSchema = z39.object({
11585
+ var slackSearchMessageWireSchema = z40.object({
11198
11586
  author_name: optionalWireString,
11199
11587
  author_user_id: optionalWireString,
11200
11588
  channel_id: nonEmptyString,
11201
11589
  channel_name: optionalWireString,
11202
11590
  message_ts: nonEmptyString,
11203
- content: z39.string(),
11591
+ content: z40.string(),
11204
11592
  is_author_bot: optionalWireBoolean,
11205
- permalink: z39.string().url()
11593
+ permalink: z40.string().url()
11206
11594
  }).transform(
11207
11595
  (value) => ({
11208
11596
  channel_id: value.channel_id,
@@ -11215,7 +11603,7 @@ var slackSearchMessageWireSchema = z39.object({
11215
11603
  ...value.is_author_bot !== void 0 ? { is_author_bot: value.is_author_bot } : void 0
11216
11604
  })
11217
11605
  );
11218
- var slackSearchFileWireSchema = z39.object({
11606
+ var slackSearchFileWireSchema = z40.object({
11219
11607
  id: optionalWireString,
11220
11608
  file_id: optionalWireString,
11221
11609
  title: optionalWireString,
@@ -11249,7 +11637,7 @@ var slackSearchFileWireSchema = z39.object({
11249
11637
  ...value.content ?? value.preview ? { content: value.content ?? value.preview } : void 0
11250
11638
  };
11251
11639
  });
11252
- var slackSearchChannelWireSchema = z39.object({
11640
+ var slackSearchChannelWireSchema = z40.object({
11253
11641
  id: optionalWireString,
11254
11642
  channel_id: optionalWireString,
11255
11643
  name: optionalWireString,
@@ -11274,7 +11662,7 @@ var slackSearchChannelWireSchema = z39.object({
11274
11662
  ...value.permalink ? { permalink: value.permalink } : void 0
11275
11663
  };
11276
11664
  });
11277
- var slackSearchUserWireSchema = z39.object({
11665
+ var slackSearchUserWireSchema = z40.object({
11278
11666
  id: optionalWireString,
11279
11667
  user_id: optionalWireString,
11280
11668
  name: optionalWireString,
@@ -11298,12 +11686,12 @@ var slackSearchUserWireSchema = z39.object({
11298
11686
  ...value.permalink ? { permalink: value.permalink } : void 0
11299
11687
  };
11300
11688
  });
11301
- var slackSearchResponseSchema = z39.object({
11302
- results: z39.object({
11303
- messages: z39.array(z39.unknown()).default([]),
11304
- files: z39.array(z39.unknown()).default([]),
11305
- channels: z39.array(z39.unknown()).default([]),
11306
- users: z39.array(z39.unknown()).default([]),
11689
+ var slackSearchResponseSchema = z40.object({
11690
+ results: z40.object({
11691
+ messages: z40.array(z40.unknown()).default([]),
11692
+ files: z40.array(z40.unknown()).default([]),
11693
+ channels: z40.array(z40.unknown()).default([]),
11694
+ users: z40.array(z40.unknown()).default([]),
11307
11695
  // Slack often returns "" on the final page; omit rather than fail the parse.
11308
11696
  next_cursor: optionalWireString
11309
11697
  }).default({
@@ -11352,15 +11740,15 @@ function createSlackPublicSearchTool(actionToken) {
11352
11740
  openWorldHint: true,
11353
11741
  readOnlyHint: true
11354
11742
  },
11355
- inputSchema: z39.object({
11356
- query: z39.string().trim().min(1).max(500).describe("Slack search query."),
11357
- content_types: z39.array(z39.enum(CONTENT_TYPES)).min(1).max(4).describe("Content types to include. Defaults to messages.").optional(),
11743
+ inputSchema: z40.object({
11744
+ query: z40.string().trim().min(1).max(500).describe("Slack search query."),
11745
+ content_types: z40.array(z40.enum(CONTENT_TYPES)).min(1).max(4).describe("Content types to include. Defaults to messages.").optional(),
11358
11746
  after: optionalUnixTimestampParam("Unix timestamp lower bound."),
11359
11747
  before: optionalUnixTimestampParam("Unix timestamp upper bound."),
11360
- cursor: z39.string().min(1).describe("Cursor for the next result page.").optional(),
11361
- limit: z39.coerce.number().int().min(1).max(20).describe("Maximum results to return; Slack allows at most 20.").optional(),
11362
- sort: z39.enum(["score", "timestamp"]).describe("Rank by relevance or timestamp.").optional(),
11363
- sort_dir: z39.enum(["asc", "desc"]).describe("Sort direction.").optional()
11748
+ cursor: z40.string().min(1).describe("Cursor for the next result page.").optional(),
11749
+ limit: z40.coerce.number().int().min(1).max(20).describe("Maximum results to return; Slack allows at most 20.").optional(),
11750
+ sort: z40.enum(["score", "timestamp"]).describe("Rank by relevance or timestamp.").optional(),
11751
+ sort_dir: z40.enum(["asc", "desc"]).describe("Sort direction.").optional()
11364
11752
  }),
11365
11753
  outputSchema: publicSearchOutputSchema,
11366
11754
  execute: async ({
@@ -11445,7 +11833,7 @@ function createSlackPublicSearchTool(actionToken) {
11445
11833
  }
11446
11834
 
11447
11835
  // src/chat/slack/tools/message-add-reaction.ts
11448
- import { z as z40 } from "zod";
11836
+ import { z as z41 } from "zod";
11449
11837
 
11450
11838
  // src/chat/tools/idempotency.ts
11451
11839
  function stableSerialize(value) {
@@ -11476,8 +11864,8 @@ function createSlackMessageAddReactionTool(context, state) {
11476
11864
  readOnlyHint: false
11477
11865
  },
11478
11866
  description: "Add an emoji reaction to the current inbound Slack message.",
11479
- inputSchema: z40.object({
11480
- emoji: z40.string().min(1).max(64).describe(
11867
+ inputSchema: z41.object({
11868
+ emoji: z41.string().min(1).max(64).describe(
11481
11869
  "Slack emoji alias name to react with (for example `thumbsup`, `white_check_mark`, or `thumbsup::skin-tone-6`). Optional surrounding colons are allowed."
11482
11870
  )
11483
11871
  }),
@@ -11526,14 +11914,14 @@ function createSlackMessageAddReactionTool(context, state) {
11526
11914
 
11527
11915
  // src/chat/slack/tools/send-files.ts
11528
11916
  import { createHash as createHash3 } from "crypto";
11529
- import { z as z41 } from "zod";
11917
+ import { z as z42 } from "zod";
11530
11918
  var sendFilesResultSchema = juniorToolOutputSchema.extend({
11531
- deduplicated: z41.boolean().optional(),
11532
- attachment_refs: z41.array(
11533
- z41.object({
11534
- id: z41.string().min(1),
11919
+ deduplicated: z42.boolean().optional(),
11920
+ attachment_refs: z42.array(
11921
+ z42.object({
11922
+ id: z42.string().min(1),
11535
11923
  // Same noun as storage, delivery events, and the report API.
11536
- filename: z41.string().min(1)
11924
+ filename: z42.string().min(1)
11537
11925
  })
11538
11926
  )
11539
11927
  });
@@ -11565,8 +11953,8 @@ function createSendFilesTool(context, state, materializeFile, attachments) {
11565
11953
  readOnlyHint: false
11566
11954
  },
11567
11955
  description: "Send one or more sandbox files into the active Slack conversation.",
11568
- inputSchema: z41.object({
11569
- files: z41.array(sandboxFileReferenceSchema).min(1).describe(
11956
+ inputSchema: z42.object({
11957
+ files: z42.array(sandboxFileReferenceSchema).min(1).describe(
11570
11958
  "One or more existing sandbox files. Objects returned by imageGenerate or webFetch can be passed unchanged."
11571
11959
  )
11572
11960
  }),
@@ -11985,7 +12373,7 @@ async function readCanvas(canvasIdOrUrl) {
11985
12373
  }
11986
12374
 
11987
12375
  // src/chat/slack/tools/canvas/create.ts
11988
- import { z as z42 } from "zod";
12376
+ import { z as z43 } from "zod";
11989
12377
  function createSlackCanvasCreateTool(context, state) {
11990
12378
  return zodTool({
11991
12379
  annotations: {
@@ -11995,9 +12383,9 @@ function createSlackCanvasCreateTool(context, state) {
11995
12383
  readOnlyHint: false
11996
12384
  },
11997
12385
  description: "Create a Slack canvas in the active channel.",
11998
- inputSchema: z42.object({
11999
- title: z42.string().min(1).max(160).describe("Canvas title."),
12000
- markdown: z42.string().min(1).describe("Canvas markdown body content.")
12386
+ inputSchema: z43.object({
12387
+ title: z43.string().min(1).max(160).describe("Canvas title."),
12388
+ markdown: z43.string().min(1).describe("Canvas markdown body content.")
12001
12389
  }),
12002
12390
  outputSchema: juniorToolOutputSchema,
12003
12391
  execute: async ({ title, markdown }) => {
@@ -12041,8 +12429,8 @@ function createSlackCanvasCreateTool(context, state) {
12041
12429
  }
12042
12430
 
12043
12431
  // src/chat/slack/tool-support/canvas/context.ts
12044
- import { z as z43 } from "zod";
12045
- var slackCanvasRefParam = z43.string().min(1).describe("Slack canvas/file ID or canvas/docs URL.");
12432
+ import { z as z44 } from "zod";
12433
+ var slackCanvasRefParam = z44.string().min(1).describe("Slack canvas/file ID or canvas/docs URL.");
12046
12434
  function resolveCanvasTarget(canvas) {
12047
12435
  const canvasId = extractCanvasId(canvas);
12048
12436
  if (!canvasId) {
@@ -12055,26 +12443,26 @@ function resolveCanvasTarget(canvas) {
12055
12443
  }
12056
12444
 
12057
12445
  // src/chat/slack/tools/canvas/edit.ts
12058
- import { z as z44 } from "zod";
12446
+ import { z as z45 } from "zod";
12059
12447
  function prepareCanvasEditArguments(input) {
12060
12448
  return prepareTextReplacementArguments(input);
12061
12449
  }
12062
- var editReplacementSchema2 = z44.object({
12063
- oldText: z44.string().min(1).describe(
12450
+ var editReplacementSchema2 = z45.object({
12451
+ oldText: z45.string().min(1).describe(
12064
12452
  "Exact Canvas markdown to replace. It must be unique in the current Canvas body and must not overlap another edit."
12065
12453
  ),
12066
- newText: z44.string().describe("Replacement Canvas markdown for this edit.")
12454
+ newText: z45.string().describe("Replacement Canvas markdown for this edit.")
12067
12455
  });
12068
12456
  var slackCanvasEditOutputSchema = juniorToolOutputSchema.extend({
12069
- canvas_id: z44.string().optional(),
12070
- title: z44.string().optional(),
12071
- permalink: z44.string().optional(),
12072
- diff: z44.string().optional(),
12073
- first_changed_line: z44.number().int().positive().optional(),
12074
- replacements: z44.number().int().nonnegative().optional(),
12075
- normalized_heading_count: z44.number().int().nonnegative().optional(),
12076
- summary: z44.string().optional(),
12077
- deduplicated: z44.boolean().optional()
12457
+ canvas_id: z45.string().optional(),
12458
+ title: z45.string().optional(),
12459
+ permalink: z45.string().optional(),
12460
+ diff: z45.string().optional(),
12461
+ first_changed_line: z45.number().int().positive().optional(),
12462
+ replacements: z45.number().int().nonnegative().optional(),
12463
+ normalized_heading_count: z45.number().int().nonnegative().optional(),
12464
+ summary: z45.string().optional(),
12465
+ deduplicated: z45.boolean().optional()
12078
12466
  }).strict();
12079
12467
  function createSlackCanvasEditTool(state) {
12080
12468
  return zodTool({
@@ -12087,9 +12475,9 @@ function createSlackCanvasEditTool(state) {
12087
12475
  description: "Edit a Slack canvas with exact markdown replacements. Returns a diff.",
12088
12476
  prepareArguments: prepareCanvasEditArguments,
12089
12477
  executionMode: "sequential",
12090
- inputSchema: z44.object({
12478
+ inputSchema: z45.object({
12091
12479
  canvas: slackCanvasRefParam,
12092
- edits: z44.array(editReplacementSchema2).min(1).describe(
12480
+ edits: z45.array(editReplacementSchema2).min(1).describe(
12093
12481
  "Exact replacements matched against the current Canvas body, not incrementally."
12094
12482
  )
12095
12483
  }),
@@ -12142,18 +12530,18 @@ function createSlackCanvasEditTool(state) {
12142
12530
  }
12143
12531
 
12144
12532
  // src/chat/slack/tools/canvas/read.ts
12145
- import { z as z45 } from "zod";
12533
+ import { z as z46 } from "zod";
12146
12534
  var slackCanvasReadOutputSchema = juniorToolOutputSchema.extend({
12147
- canvas_id: z45.string().optional(),
12148
- title: z45.string().optional(),
12149
- permalink: z45.string().optional(),
12150
- mimetype: z45.string().optional(),
12151
- filetype: z45.string().optional(),
12152
- original_byte_length: z45.number().int().nonnegative().optional(),
12153
- content: z45.string().optional(),
12154
- start_line: z45.number().int().positive().optional(),
12155
- end_line: z45.number().int().nonnegative().optional(),
12156
- total_lines: z45.number().int().nonnegative().optional()
12535
+ canvas_id: z46.string().optional(),
12536
+ title: z46.string().optional(),
12537
+ permalink: z46.string().optional(),
12538
+ mimetype: z46.string().optional(),
12539
+ filetype: z46.string().optional(),
12540
+ original_byte_length: z46.number().int().nonnegative().optional(),
12541
+ content: z46.string().optional(),
12542
+ start_line: z46.number().int().positive().optional(),
12543
+ end_line: z46.number().int().nonnegative().optional(),
12544
+ total_lines: z46.number().int().nonnegative().optional()
12157
12545
  }).strict();
12158
12546
  function createSlackCanvasReadTool() {
12159
12547
  return zodTool({
@@ -12164,10 +12552,10 @@ function createSlackCanvasReadTool() {
12164
12552
  openWorldHint: true,
12165
12553
  readOnlyHint: true
12166
12554
  },
12167
- inputSchema: z45.object({
12555
+ inputSchema: z46.object({
12168
12556
  canvas: slackCanvasRefParam,
12169
- offset: z45.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
12170
- limit: z45.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
12557
+ offset: z46.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
12558
+ limit: z46.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
12171
12559
  }),
12172
12560
  outputSchema: slackCanvasReadOutputSchema,
12173
12561
  execute: async ({ canvas, offset, limit }) => {
@@ -12203,7 +12591,7 @@ function createSlackCanvasReadTool() {
12203
12591
  }
12204
12592
 
12205
12593
  // src/chat/slack/tools/canvas/write.ts
12206
- import { z as z46 } from "zod";
12594
+ import { z as z47 } from "zod";
12207
12595
  function createSlackCanvasWriteTool(state) {
12208
12596
  return zodTool({
12209
12597
  annotations: {
@@ -12214,9 +12602,9 @@ function createSlackCanvasWriteTool(state) {
12214
12602
  },
12215
12603
  description: "Replace the full markdown body of a Slack canvas.",
12216
12604
  executionMode: "sequential",
12217
- inputSchema: z46.object({
12605
+ inputSchema: z47.object({
12218
12606
  canvas: slackCanvasRefParam,
12219
- content: z46.string().describe("UTF-8 markdown content to write.")
12607
+ content: z47.string().describe("UTF-8 markdown content to write.")
12220
12608
  }),
12221
12609
  outputSchema: juniorToolOutputSchema,
12222
12610
  execute: async ({ canvas, content }) => {
@@ -12438,12 +12826,12 @@ async function updateListItem(input) {
12438
12826
  }
12439
12827
 
12440
12828
  // src/chat/slack/tool-support/list/params.ts
12441
- import { z as z47 } from "zod";
12442
- var slackListIdParam = z47.string().min(1).describe("Slack list ID.");
12443
- var slackListItemIdParam = z47.string().min(1).describe("Slack list item ID.");
12829
+ import { z as z48 } from "zod";
12830
+ var slackListIdParam = z48.string().min(1).describe("Slack list ID.");
12831
+ var slackListItemIdParam = z48.string().min(1).describe("Slack list item ID.");
12444
12832
 
12445
12833
  // src/chat/slack/tools/list/add-items.ts
12446
- import { z as z48 } from "zod";
12834
+ import { z as z49 } from "zod";
12447
12835
  function createSlackListAddItemsTool(state) {
12448
12836
  return zodTool({
12449
12837
  annotations: {
@@ -12453,13 +12841,13 @@ function createSlackListAddItemsTool(state) {
12453
12841
  readOnlyHint: false
12454
12842
  },
12455
12843
  description: "Add tasks to a Slack list.",
12456
- inputSchema: z48.object({
12844
+ inputSchema: z49.object({
12457
12845
  list_id: slackListIdParam,
12458
- items: z48.array(z48.string().min(1)).min(1).max(25).describe("List item titles to create."),
12846
+ items: z49.array(z49.string().min(1)).min(1).max(25).describe("List item titles to create."),
12459
12847
  assignee_user_id: slackUserIdParam(
12460
12848
  "Optional Slack user ID assigned to all created items."
12461
12849
  ).optional(),
12462
- due_date: z48.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
12850
+ due_date: z49.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
12463
12851
  }),
12464
12852
  outputSchema: juniorToolOutputSchema,
12465
12853
  execute: async ({ list_id, items, assignee_user_id, due_date }) => {
@@ -12498,7 +12886,7 @@ function createSlackListAddItemsTool(state) {
12498
12886
  }
12499
12887
 
12500
12888
  // src/chat/slack/tools/list/create.ts
12501
- import { z as z49 } from "zod";
12889
+ import { z as z50 } from "zod";
12502
12890
  function createSlackListCreateTool(state) {
12503
12891
  return zodTool({
12504
12892
  annotations: {
@@ -12508,8 +12896,8 @@ function createSlackListCreateTool(state) {
12508
12896
  readOnlyHint: false
12509
12897
  },
12510
12898
  description: "Create a Slack todo list.",
12511
- inputSchema: z49.object({
12512
- name: z49.string().min(1).max(160).describe("Name for the new Slack list.")
12899
+ inputSchema: z50.object({
12900
+ name: z50.string().min(1).max(160).describe("Name for the new Slack list.")
12513
12901
  }),
12514
12902
  outputSchema: juniorToolOutputSchema,
12515
12903
  execute: async ({ name }) => {
@@ -12534,7 +12922,7 @@ function createSlackListCreateTool(state) {
12534
12922
  }
12535
12923
 
12536
12924
  // src/chat/slack/tools/list/get-items.ts
12537
- import { z as z50 } from "zod";
12925
+ import { z as z51 } from "zod";
12538
12926
  function createSlackListGetItemsTool() {
12539
12927
  return zodTool({
12540
12928
  description: "Read items from a Slack list.",
@@ -12544,9 +12932,9 @@ function createSlackListGetItemsTool() {
12544
12932
  openWorldHint: true,
12545
12933
  readOnlyHint: true
12546
12934
  },
12547
- inputSchema: z50.object({
12935
+ inputSchema: z51.object({
12548
12936
  list_id: slackListIdParam,
12549
- limit: z50.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
12937
+ limit: z51.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
12550
12938
  }),
12551
12939
  outputSchema: juniorToolOutputSchema,
12552
12940
  execute: async ({ list_id, limit }) => {
@@ -12561,23 +12949,23 @@ function createSlackListGetItemsTool() {
12561
12949
  }
12562
12950
 
12563
12951
  // src/chat/slack/tools/list/update-item.ts
12564
- import { z as z51 } from "zod";
12565
- var booleanInput3 = (description) => z51.preprocess(
12952
+ import { z as z52 } from "zod";
12953
+ var booleanInput3 = (description) => z52.preprocess(
12566
12954
  (value) => value === "true" ? true : value === "false" ? false : value,
12567
- z51.boolean()
12955
+ z52.boolean()
12568
12956
  ).describe(description);
12569
- var updateListItemInputSchema = z51.union([
12570
- z51.object({
12957
+ var updateListItemInputSchema = z52.union([
12958
+ z52.object({
12571
12959
  list_id: slackListIdParam,
12572
12960
  item_id: slackListItemIdParam,
12573
12961
  completed: booleanInput3("Optional completion status update."),
12574
- title: z51.string().min(1).describe("Optional new item title.").optional()
12962
+ title: z52.string().min(1).describe("Optional new item title.").optional()
12575
12963
  }),
12576
- z51.object({
12964
+ z52.object({
12577
12965
  list_id: slackListIdParam,
12578
12966
  item_id: slackListItemIdParam,
12579
12967
  completed: booleanInput3("Optional completion status update.").optional(),
12580
- title: z51.string().min(1).describe("Optional new item title.")
12968
+ title: z52.string().min(1).describe("Optional new item title.")
12581
12969
  })
12582
12970
  ]);
12583
12971
  function createSlackListUpdateItemTool(state) {
@@ -12625,7 +13013,7 @@ function createSlackListUpdateItemTool(state) {
12625
13013
  }
12626
13014
 
12627
13015
  // src/chat/slack/tools/thread-read.ts
12628
- import { z as z52 } from "zod";
13016
+ import { z as z53 } from "zod";
12629
13017
 
12630
13018
  // src/chat/slack/tool-support/slack-message-url.ts
12631
13019
  var SLACK_HOST_PATTERN = /^[a-z0-9-]+\.slack(?:-gov)?\.com$/;
@@ -12891,14 +13279,14 @@ function createSlackThreadReadTool(context) {
12891
13279
  openWorldHint: true,
12892
13280
  readOnlyHint: true
12893
13281
  },
12894
- inputSchema: z52.object({
12895
- url: z52.string().min(1).describe("Slack message archive URL.").optional(),
13282
+ inputSchema: z53.object({
13283
+ url: z53.string().min(1).describe("Slack message archive URL.").optional(),
12896
13284
  channel_id: slackChannelRefParam.optional(),
12897
13285
  ts: slackTimestampParam(
12898
13286
  "Slack message timestamp. May be the thread root or any message in the thread."
12899
13287
  ).optional(),
12900
- limit: z52.coerce.number().int().min(1).max(1e3).describe("Maximum number of thread messages to fetch.").optional(),
12901
- max_pages: z52.coerce.number().int().min(1).max(10).describe("Maximum number of Slack API pages to traverse.").optional()
13288
+ limit: z53.coerce.number().int().min(1).max(1e3).describe("Maximum number of thread messages to fetch.").optional(),
13289
+ max_pages: z53.coerce.number().int().min(1).max(10).describe("Maximum number of Slack API pages to traverse.").optional()
12902
13290
  }),
12903
13291
  outputSchema: juniorToolOutputSchema,
12904
13292
  execute: async ({ url, channel_id, ts, limit, max_pages }) => {
@@ -13025,7 +13413,7 @@ function createSlackThreadReadTool(context) {
13025
13413
  // src/chat/tools/user-lookup.ts
13026
13414
  import { and as and2, eq as eq2, or, sql } from "drizzle-orm";
13027
13415
  import { alias } from "drizzle-orm/pg-core";
13028
- import { z as z53 } from "zod";
13416
+ import { z as z54 } from "zod";
13029
13417
  var linkedSlackIdentity = alias(juniorIdentities, "user_lookup_slack_identity");
13030
13418
  function explicitUserLookupError(error) {
13031
13419
  if (error.apiError === "user_not_found" || error.code === "not_found") {
@@ -13174,9 +13562,9 @@ function createUserLookupTool(teamId, providers) {
13174
13562
  openWorldHint: true,
13175
13563
  readOnlyHint: true
13176
13564
  },
13177
- inputSchema: z53.object({
13178
- provider: z53.enum(providers).describe("Enabled identity provider to query."),
13179
- query: z53.string().trim().min(1).describe("Provider subject ID, handle, Slack email, or Slack name.")
13565
+ inputSchema: z54.object({
13566
+ provider: z54.enum(providers).describe("Enabled identity provider to query."),
13567
+ query: z54.string().trim().min(1).describe("Provider subject ID, handle, Slack email, or Slack name.")
13180
13568
  }).strict(),
13181
13569
  outputSchema: juniorToolOutputSchema,
13182
13570
  execute: async ({ provider, query }) => {
@@ -13196,18 +13584,18 @@ function createUserLookupTool(teamId, providers) {
13196
13584
  }
13197
13585
 
13198
13586
  // src/chat/tools/system-time.ts
13199
- import { z as z54 } from "zod";
13200
- var systemTimeInputSchema = z54.object({
13201
- timezone: z54.string().trim().min(1).optional().describe(
13587
+ import { z as z55 } from "zod";
13588
+ var systemTimeInputSchema = z55.object({
13589
+ timezone: z55.string().trim().min(1).optional().describe(
13202
13590
  "Optional IANA timezone, for example America/Los_Angeles. When set, iso_local and timezone_offset_minutes are for that zone."
13203
13591
  )
13204
13592
  });
13205
13593
  var systemTimeOutputSchema = juniorToolOutputSchema.extend({
13206
- unix_ms: z54.number(),
13207
- iso_utc: z54.string(),
13208
- iso_local: z54.string(),
13209
- timezone: z54.string().nullable(),
13210
- timezone_offset_minutes: z54.number()
13594
+ unix_ms: z55.number(),
13595
+ iso_utc: z55.string(),
13596
+ iso_local: z55.string(),
13597
+ timezone: z55.string().nullable(),
13598
+ timezone_offset_minutes: z55.number()
13211
13599
  });
13212
13600
  function createSystemTimeTool() {
13213
13601
  return zodTool({
@@ -13287,7 +13675,7 @@ function getTimeZoneOffsetMinutes(timestampMs, timezone) {
13287
13675
  }
13288
13676
 
13289
13677
  // src/chat/tools/publish-image.ts
13290
- import { z as z55 } from "zod";
13678
+ import { z as z56 } from "zod";
13291
13679
 
13292
13680
  // src/chat/artifacts/store.ts
13293
13681
  import { createHash as createHash4, randomUUID as randomUUID4 } from "crypto";
@@ -13488,10 +13876,10 @@ function unpublishedArtifactHeaders() {
13488
13876
 
13489
13877
  // src/chat/tools/publish-image.ts
13490
13878
  var outputSchema5 = juniorToolOutputSchema.extend({
13491
- bytes: z55.number().int().positive(),
13492
- content_type: z55.string().min(1),
13493
- public: z55.literal(true),
13494
- url: z55.string().url()
13879
+ bytes: z56.number().int().positive(),
13880
+ content_type: z56.string().min(1),
13881
+ public: z56.literal(true),
13882
+ url: z56.string().url()
13495
13883
  });
13496
13884
  function createPublishImageTool(args) {
13497
13885
  return zodTool({
@@ -13505,8 +13893,8 @@ function createPublishImageTool(args) {
13505
13893
  description: "Publish one sandbox image to a durable public HTTPS URL. Anyone on the internet with the URL can view the image. Use only when an external destination needs a public image URL. Do not use for private file sharing or private conversation storage. Supports PNG, JPEG, GIF, and WebP up to 10 MB.",
13506
13894
  describeProposal: ({ path: path8 }) => `Publish sandbox image ${path8} to a public internet URL.`,
13507
13895
  executionMode: "sequential",
13508
- inputSchema: z55.object({
13509
- path: z55.string().min(1).describe("Exact sandbox path of an existing image file.")
13896
+ inputSchema: z56.object({
13897
+ path: z56.string().min(1).describe("Exact sandbox path of an existing image file.")
13510
13898
  }).strict(),
13511
13899
  outputSchema: outputSchema5,
13512
13900
  async execute({ path: path8 }) {
@@ -13539,10 +13927,10 @@ function createPublishImageTool(args) {
13539
13927
  }
13540
13928
 
13541
13929
  // src/chat/tools/unpublish-image.ts
13542
- import { z as z56 } from "zod";
13930
+ import { z as z57 } from "zod";
13543
13931
  var outputSchema6 = juniorToolOutputSchema.extend({
13544
- filename: z56.string().min(1),
13545
- unpublished: z56.literal(true)
13932
+ filename: z57.string().min(1),
13933
+ unpublished: z57.literal(true)
13546
13934
  });
13547
13935
  function createUnpublishImageTool(args) {
13548
13936
  return zodTool({
@@ -13556,8 +13944,8 @@ function createUnpublishImageTool(args) {
13556
13944
  description: "Unpublish one public image previously published in this conversation so its public URL stops serving. Pass the public artifact URL or `<id>.<ext>` filename. Only images owned by this conversation can be unpublished. Republishing the same image bytes later in this conversation restores a live URL for this conversation. Does not remove copies already fetched by browsers or GitHub.",
13557
13945
  describeProposal: ({ ref }) => `Unpublish public image ${ref}.`,
13558
13946
  executionMode: "sequential",
13559
- inputSchema: z56.object({
13560
- ref: z56.string().min(1).describe(
13947
+ inputSchema: z57.object({
13948
+ ref: z57.string().min(1).describe(
13561
13949
  "Public artifact URL or artifact filename (`<id>.<ext>`)."
13562
13950
  )
13563
13951
  }).strict(),
@@ -13577,27 +13965,27 @@ function createUnpublishImageTool(args) {
13577
13965
  }
13578
13966
 
13579
13967
  // src/chat/tools/search-conversation-events.ts
13580
- import { z as z57 } from "zod";
13968
+ import { z as z58 } from "zod";
13581
13969
  var DEFAULT_LIMIT3 = 25;
13582
13970
  var MAX_LIMIT2 = 100;
13583
13971
  var MAX_EVENT_DATA_BYTES = 4e3;
13584
13972
  var MAX_EVENTS_JSON_BYTES = 2e4;
13585
13973
  var MAX_IDENTITY_CHARS = 256;
13586
13974
  var textEncoder = new TextEncoder();
13587
- var knownEventTypeSchema = z57.enum(KNOWN_CONVERSATION_EVENT_TYPES);
13588
- var projectedEventSchema = z57.object({
13589
- seq: z57.number().int().nonnegative().describe("Stable event position for pagination."),
13590
- history_version: z57.number().int().nonnegative().describe("Agent history generation after replacement."),
13591
- created_at: z57.iso.datetime().describe("When the event was recorded."),
13592
- idempotency_key: z57.string().min(1).optional().describe("Retry-stable event identity, when assigned."),
13593
- data: z57.record(z57.string(), z57.unknown()).describe("Bounded event data.")
13975
+ var knownEventTypeSchema = z58.enum(KNOWN_CONVERSATION_EVENT_TYPES);
13976
+ var projectedEventSchema = z58.object({
13977
+ seq: z58.number().int().nonnegative().describe("Stable event position for pagination."),
13978
+ history_version: z58.number().int().nonnegative().describe("Agent history generation after replacement."),
13979
+ created_at: z58.iso.datetime().describe("When the event was recorded."),
13980
+ idempotency_key: z58.string().min(1).optional().describe("Retry-stable event identity, when assigned."),
13981
+ data: z58.record(z58.string(), z58.unknown()).describe("Bounded event data.")
13594
13982
  }).strict();
13595
13983
  var searchConversationEventsOutputSchema = juniorToolOutputSchema.extend({
13596
- conversation_id: z57.string().min(1),
13597
- events: z57.array(projectedEventSchema),
13598
- has_older: z57.boolean().describe("Whether matching older events exist."),
13599
- has_newer: z57.boolean().describe("Whether matching newer events exist."),
13600
- omitted_event_count: z57.number().int().nonnegative().optional().describe("Events omitted by the response byte limit.")
13984
+ conversation_id: z58.string().min(1),
13985
+ events: z58.array(projectedEventSchema),
13986
+ has_older: z58.boolean().describe("Whether matching older events exist."),
13987
+ has_newer: z58.boolean().describe("Whether matching newer events exist."),
13988
+ omitted_event_count: z58.number().int().nonnegative().optional().describe("Events omitted by the response byte limit.")
13601
13989
  });
13602
13990
  function createSearchConversationEventsTool(context) {
13603
13991
  return zodTool({
@@ -13610,16 +13998,16 @@ function createSearchConversationEventsTool(context) {
13610
13998
  openWorldHint: false,
13611
13999
  readOnlyHint: true
13612
14000
  },
13613
- inputSchema: z57.object({
13614
- conversation_id: z57.string().trim().min(1).nullable().describe(
14001
+ inputSchema: z58.object({
14002
+ conversation_id: z58.string().trim().min(1).nullable().describe(
13615
14003
  "Conversation ID to search. Omit or null for the current conversation."
13616
14004
  ).optional(),
13617
- after_seq: z57.number().int().nonnegative().nullable().describe("Exclusive event sequence lower bound; returns ascending.").optional(),
13618
- before_seq: z57.number().int().nonnegative().nullable().describe("Exclusive event sequence upper bound.").optional(),
13619
- limit: z57.number().int().min(1).max(MAX_LIMIT2).nullable().describe(
14005
+ after_seq: z58.number().int().nonnegative().nullable().describe("Exclusive event sequence lower bound; returns ascending.").optional(),
14006
+ before_seq: z58.number().int().nonnegative().nullable().describe("Exclusive event sequence upper bound.").optional(),
14007
+ limit: z58.number().int().min(1).max(MAX_LIMIT2).nullable().describe(
13620
14008
  `Maximum events. Default ${DEFAULT_LIMIT3}; max ${MAX_LIMIT2}.`
13621
14009
  ).optional(),
13622
- types: z57.array(knownEventTypeSchema).min(1).nullable().describe("Event types to include; omit for all types.").optional()
14010
+ types: z58.array(knownEventTypeSchema).min(1).nullable().describe("Event types to include; omit for all types.").optional()
13623
14011
  }).strict(),
13624
14012
  outputSchema: searchConversationEventsOutputSchema,
13625
14013
  execute: async (input) => {
@@ -13868,10 +14256,10 @@ function stripReplacementHistoryField(value) {
13868
14256
  }
13869
14257
 
13870
14258
  // src/chat/tools/handoff/tool.ts
13871
- import { z as z58 } from "zod";
14259
+ import { z as z59 } from "zod";
13872
14260
  var HANDOFF_TOOL_NAME = "handoff";
13873
14261
  function createHandoffTool(handoff) {
13874
- const profileSchema = z58.enum(handoff.profiles);
14262
+ const profileSchema = z59.enum(handoff.profiles);
13875
14263
  const handoffResultSchema = juniorToolOutputSchema.extend({
13876
14264
  model_profile: modelProfileSchema
13877
14265
  });
@@ -13885,7 +14273,7 @@ function createHandoffTool(handoff) {
13885
14273
  },
13886
14274
  description: `Switch to another model profile and continue the same task. Profiles: ${profileNames}. Call this as the only tool.`,
13887
14275
  executionMode: "sequential",
13888
- inputSchema: z58.object({
14276
+ inputSchema: z59.object({
13889
14277
  profile: profileSchema.describe("Target model profile")
13890
14278
  }).strict(),
13891
14279
  outputSchema: handoffResultSchema,
@@ -13906,7 +14294,7 @@ function createHandoffTool(handoff) {
13906
14294
  }
13907
14295
 
13908
14296
  // src/chat/tools/web/fetch-tool.ts
13909
- import { z as z59 } from "zod";
14297
+ import { z as z60 } from "zod";
13910
14298
 
13911
14299
  // src/chat/tools/web/constants.ts
13912
14300
  var USER_AGENT = "junior-bot/0.1";
@@ -14355,9 +14743,9 @@ function createWebFetchTool(hooks, options = {}) {
14355
14743
  openWorldHint: true,
14356
14744
  readOnlyHint: true
14357
14745
  },
14358
- inputSchema: z59.object({
14359
- url: z59.string().min(1).describe("HTTP(S) URL to fetch."),
14360
- max_chars: z59.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
14746
+ inputSchema: z60.object({
14747
+ url: z60.string().min(1).describe("HTTP(S) URL to fetch."),
14748
+ max_chars: z60.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
14361
14749
  }),
14362
14750
  outputSchema: juniorToolOutputSchema,
14363
14751
  execute: async ({ url, max_chars }) => {
@@ -14402,7 +14790,7 @@ function createWebFetchTool(hooks, options = {}) {
14402
14790
  }
14403
14791
 
14404
14792
  // src/chat/tools/web/search.ts
14405
- import { z as z60 } from "zod";
14793
+ import { z as z61 } from "zod";
14406
14794
  import { generateText } from "ai";
14407
14795
  import { createGatewayProvider } from "@ai-sdk/gateway";
14408
14796
  var SEARCH_TIMEOUT_MS = 6e4;
@@ -14444,9 +14832,9 @@ function createWebSearchTool(modelId, override) {
14444
14832
  openWorldHint: true,
14445
14833
  readOnlyHint: true
14446
14834
  },
14447
- inputSchema: z60.object({
14448
- query: z60.string().min(1).max(500).describe("Search query."),
14449
- max_results: z60.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
14835
+ inputSchema: z61.object({
14836
+ query: z61.string().min(1).max(500).describe("Search query."),
14837
+ max_results: z61.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
14450
14838
  }),
14451
14839
  outputSchema: juniorToolOutputSchema,
14452
14840
  execute: async ({ query, max_results }) => {
@@ -14488,7 +14876,7 @@ function createWebSearchTool(modelId, override) {
14488
14876
  }
14489
14877
 
14490
14878
  // src/chat/tools/sandbox/write-file.ts
14491
- import { z as z61 } from "zod";
14879
+ import { z as z62 } from "zod";
14492
14880
  function createWriteFileTool() {
14493
14881
  return zodTool({
14494
14882
  annotations: {
@@ -14499,9 +14887,9 @@ function createWriteFileTool() {
14499
14887
  },
14500
14888
  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.",
14501
14889
  executionMode: "sequential",
14502
- inputSchema: z61.object({
14503
- path: z61.string().min(1).describe("Path to write in the sandbox workspace."),
14504
- content: z61.string().describe("UTF-8 file content to write.")
14890
+ inputSchema: z62.object({
14891
+ path: z62.string().min(1).describe("Path to write in the sandbox workspace."),
14892
+ content: z62.string().describe("UTF-8 file content to write.")
14505
14893
  }),
14506
14894
  outputSchema: juniorToolOutputSchema,
14507
14895
  execute: async () => {
@@ -14513,7 +14901,7 @@ function createWriteFileTool() {
14513
14901
  }
14514
14902
 
14515
14903
  // src/chat/workspaces/tools.ts
14516
- import { z as z62 } from "zod";
14904
+ import { z as z63 } from "zod";
14517
14905
  import {
14518
14906
  resourceEventSubscriptionResultSchema
14519
14907
  } from "@sentry/junior-plugin-api";
@@ -14545,16 +14933,16 @@ async function stopWorkspaceSnapshotWatch(input) {
14545
14933
  });
14546
14934
  }
14547
14935
  }
14548
- var repoSchema = z62.object({
14549
- provider: z62.string(),
14550
- repo: z62.string(),
14551
- checkout_path: z62.string()
14936
+ var repoSchema = z63.object({
14937
+ provider: z63.string(),
14938
+ repo: z63.string(),
14939
+ checkout_path: z63.string()
14552
14940
  });
14553
- var workspaceSchema = z62.object({
14554
- id: z62.string(),
14555
- name: z62.string(),
14556
- setup_script: z62.string(),
14557
- repos: z62.array(repoSchema)
14941
+ var workspaceSchema = z63.object({
14942
+ id: z63.string(),
14943
+ name: z63.string(),
14944
+ setup_script: z63.string(),
14945
+ repos: z63.array(repoSchema)
14558
14946
  });
14559
14947
  function view(workspace) {
14560
14948
  return {
@@ -14587,18 +14975,18 @@ function workspaceProviderNames() {
14587
14975
  }
14588
14976
  function workspaceWriteSchemas(providers) {
14589
14977
  const providerNames = providers.map((provider) => `\`${provider}\``).join(", ");
14590
- const repoInputSchema = z62.object({
14591
- provider: z62.enum(providers).describe(`Repository provider. Supported: ${providerNames}.`),
14592
- repo: z62.string().trim().min(1).describe("Repository in owner/name format.")
14978
+ const repoInputSchema = z63.object({
14979
+ provider: z63.enum(providers).describe(`Repository provider. Supported: ${providerNames}.`),
14980
+ repo: z63.string().trim().min(1).describe("Repository in owner/name format.")
14593
14981
  }).strict();
14594
- const workspaceInputSchema = z62.object({
14595
- name: z62.string().trim().min(1).describe(
14982
+ const workspaceInputSchema = z63.object({
14983
+ name: z63.string().trim().min(1).describe(
14596
14984
  "Workspace name. Use lowercase letters, digits, underscores, or hyphens."
14597
14985
  ),
14598
- setup_script: z62.string().nullable().describe(
14986
+ setup_script: z63.string().nullable().describe(
14599
14987
  "Optional shell script to run after repository checkout whenever this Workspace starts. Omit or use null for no setup script."
14600
14988
  ).optional(),
14601
- repos: z62.array(repoInputSchema).max(32).describe("Complete repository list.")
14989
+ repos: z63.array(repoInputSchema).max(32).describe("Complete repository list.")
14602
14990
  }).strict();
14603
14991
  return { providerNames, workspaceInputSchema };
14604
14992
  }
@@ -14673,7 +15061,7 @@ function createWorkspaceWriteTools(providers) {
14673
15061
  },
14674
15062
  description: `Replace an install-wide Workspace recipe. Repository providers: ${providerNames}. Use the Workspace ID returned by listWorkspaces.`,
14675
15063
  inputSchema: workspaceInputSchema.extend({
14676
- id: z62.string().uuid().describe("Workspace ID from listWorkspaces.")
15064
+ id: z63.string().uuid().describe("Workspace ID from listWorkspaces.")
14677
15065
  }).strict(),
14678
15066
  prepareArguments(args) {
14679
15067
  const input = args;
@@ -14706,11 +15094,11 @@ function createWorkspaceWriteTools(providers) {
14706
15094
  readOnlyHint: false
14707
15095
  },
14708
15096
  description: "Delete one install-wide Workspace recipe. Use the Workspace ID returned by listWorkspaces.",
14709
- inputSchema: z62.object({
14710
- id: z62.string().uuid().describe("Workspace ID from listWorkspaces.")
15097
+ inputSchema: z63.object({
15098
+ id: z63.string().uuid().describe("Workspace ID from listWorkspaces.")
14711
15099
  }).strict(),
14712
15100
  outputSchema: juniorToolOutputSchema.extend({
14713
- deleted: z62.literal(true)
15101
+ deleted: z63.literal(true)
14714
15102
  }),
14715
15103
  async execute({ id }) {
14716
15104
  const deleted = await workspaceWrite(() => deleteWorkspace(id));
@@ -14735,10 +15123,10 @@ function createWorkspaceTools(context) {
14735
15123
  readOnlyHint: true
14736
15124
  },
14737
15125
  description: "List named repository workspaces that can replace the current sandbox.",
14738
- inputSchema: z62.object({}).strict(),
15126
+ inputSchema: z63.object({}).strict(),
14739
15127
  outputSchema: juniorToolOutputSchema.extend({
14740
- active_workspace_id: z62.string().nullable(),
14741
- workspaces: z62.array(workspaceSchema)
15128
+ active_workspace_id: z63.string().nullable(),
15129
+ workspaces: z63.array(workspaceSchema)
14742
15130
  }),
14743
15131
  async execute() {
14744
15132
  return {
@@ -14756,12 +15144,12 @@ function createWorkspaceTools(context) {
14756
15144
  readOnlyHint: false
14757
15145
  },
14758
15146
  description: "Replace the current sandbox with a named repository Workspace. Files in the old sandbox do not carry over. Returns ready after the switch, or building with a temporary subscription when the snapshot is still being prepared. When building, wait for the ready event and call switchWorkspace again with the same name.",
14759
- inputSchema: z62.object({
14760
- name: z62.string().trim().min(1).describe("Exact workspace name.")
15147
+ inputSchema: z63.object({
15148
+ name: z63.string().trim().min(1).describe("Exact workspace name.")
14761
15149
  }).strict(),
14762
15150
  outputSchema: juniorToolOutputSchema.extend({
14763
15151
  workspace: workspaceSchema,
14764
- status: z62.enum(["ready", "building"]),
15152
+ status: z63.enum(["ready", "building"]),
14765
15153
  subscription: resourceEventSubscriptionResultSchema.optional().describe(
14766
15154
  "Present when the snapshot ready and failed events are already watched for this conversation."
14767
15155
  )
@@ -15547,7 +15935,7 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, conv
15547
15935
  }
15548
15936
 
15549
15937
  // src/chat/tools/execute-tool.ts
15550
- import { z as z63 } from "zod";
15938
+ import { z as z64 } from "zod";
15551
15939
  var EXECUTE_TOOL_NAME = "executeTool";
15552
15940
  function createExecuteToolTool() {
15553
15941
  return zodTool({
@@ -15559,11 +15947,11 @@ function createExecuteToolTool() {
15559
15947
  },
15560
15948
  description: "Execute any catalog tool by exact tool_name from searchTools or a tool-result execution hint. Put tool-specific parameters inside arguments.",
15561
15949
  executionMode: "sequential",
15562
- inputSchema: z63.object({
15563
- tool_name: z63.string().min(1).describe(
15950
+ inputSchema: z64.object({
15951
+ tool_name: z64.string().min(1).describe(
15564
15952
  "Exact catalog tool_name returned by searchTools or a tool-result execution hint."
15565
15953
  ),
15566
- arguments: z63.record(z63.string(), z63.unknown()).describe(
15954
+ arguments: z64.record(z64.string(), z64.unknown()).describe(
15567
15955
  'Arguments matching the selected catalog tool schema, for example { "query": "..." }.'
15568
15956
  ).optional()
15569
15957
  }).strict(),
@@ -15603,7 +15991,7 @@ function planToolExposure(tools) {
15603
15991
  }
15604
15992
 
15605
15993
  // src/chat/tools/search-tools.ts
15606
- import { z as z64 } from "zod";
15994
+ import { z as z65 } from "zod";
15607
15995
  var SEARCH_TOOLS_NAME = "searchTools";
15608
15996
  var DEFAULT_MAX_RESULTS2 = 5;
15609
15997
  var MAX_RESULTS3 = 20;
@@ -15648,29 +16036,29 @@ var SEARCH_STOP_WORDS = /* @__PURE__ */ new Set([
15648
16036
  "you",
15649
16037
  "your"
15650
16038
  ]);
15651
- var searchToolsSourceSchema = z64.object({
15652
- id: z64.string(),
15653
- description: z64.string()
16039
+ var searchToolsSourceSchema = z65.object({
16040
+ id: z65.string(),
16041
+ description: z65.string()
15654
16042
  }).strict();
15655
- var searchToolsToolSchema = z64.object({
15656
- tool_name: z64.string(),
15657
- description: z64.string(),
15658
- exposure: z64.enum(["direct", "deferred", "modelOnly", "hidden"]),
15659
- source: z64.string().optional(),
15660
- input_schema: z64.unknown(),
15661
- call_notes: z64.array(z64.string()),
15662
- annotations: z64.record(z64.string(), z64.unknown())
16043
+ var searchToolsToolSchema = z65.object({
16044
+ tool_name: z65.string(),
16045
+ description: z65.string(),
16046
+ exposure: z65.enum(["direct", "deferred", "modelOnly", "hidden"]),
16047
+ source: z65.string().optional(),
16048
+ input_schema: z65.unknown(),
16049
+ call_notes: z65.array(z65.string()),
16050
+ annotations: z65.record(z65.string(), z65.unknown())
15663
16051
  }).strict();
15664
16052
  var searchToolsOutputSchema = juniorToolOutputSchema.extend({
15665
- query: z64.string().nullable(),
15666
- source: z64.string().nullable(),
15667
- sources: z64.array(searchToolsSourceSchema),
15668
- total_catalog_tools: z64.number().int().nonnegative(),
15669
- total_eligible_tools: z64.number().int().nonnegative(),
15670
- total_matches: z64.number().int().nonnegative(),
15671
- returned_tools: z64.number().int().nonnegative(),
15672
- execution_tool: z64.literal("executeTool"),
15673
- tools: z64.array(searchToolsToolSchema)
16053
+ query: z65.string().nullable(),
16054
+ source: z65.string().nullable(),
16055
+ sources: z65.array(searchToolsSourceSchema),
16056
+ total_catalog_tools: z65.number().int().nonnegative(),
16057
+ total_eligible_tools: z65.number().int().nonnegative(),
16058
+ total_matches: z65.number().int().nonnegative(),
16059
+ returned_tools: z65.number().int().nonnegative(),
16060
+ execution_tool: z65.literal("executeTool"),
16061
+ tools: z65.array(searchToolsToolSchema)
15674
16062
  }).strict();
15675
16063
  function terms(value) {
15676
16064
  const chunks = value.match(/[\p{L}\p{N}]+/gu) ?? [];
@@ -15881,14 +16269,14 @@ function createSearchToolsTool(catalogTools) {
15881
16269
  openWorldHint: false,
15882
16270
  readOnlyHint: true
15883
16271
  },
15884
- inputSchema: z64.object({
15885
- query: z64.string().nullable().describe(
16272
+ inputSchema: z65.object({
16273
+ query: z65.string().nullable().describe(
15886
16274
  "Optional search terms describing the tool, owner, action, or arguments needed. Empty string lists catalog tools."
15887
16275
  ).optional(),
15888
- source: z64.string().nullable().describe(
16276
+ source: z65.string().nullable().describe(
15889
16277
  "Optional source id to search within, such as a plugin source returned in sources."
15890
16278
  ).optional(),
15891
- max_results: z64.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
16279
+ max_results: z65.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
15892
16280
  }).strict(),
15893
16281
  outputSchema: searchToolsOutputSchema,
15894
16282
  privateTraceResult: (result) => ({
@@ -17186,7 +17574,7 @@ function createPluginEgress(deps) {
17186
17574
  }
17187
17575
 
17188
17576
  // src/chat/services/guardian-action-review.ts
17189
- import { z as z65 } from "zod";
17577
+ import { z as z66 } from "zod";
17190
17578
 
17191
17579
  // src/chat/services/guardian-action-policy.ts
17192
17580
  var GUARDIAN_ACTION_POLICY = `You are judging one planned Junior agent action.
@@ -17260,17 +17648,17 @@ Assess the exact action's intrinsic risk and whether the user's intent authorize
17260
17648
  - Keep the reason to one concise, specific sentence grounded in the main risk or authorization fact. For ask, name the exact action, target, and material side effects the user must confirm.`;
17261
17649
 
17262
17650
  // src/chat/services/guardian-action-review.ts
17263
- var guardianDecisionSchema = z65.object({
17264
- decision: z65.enum(["allow", "ask", "deny"]),
17265
- reason: z65.string().trim().min(1).max(500),
17266
- riskLevel: z65.enum(["low", "medium", "high", "critical"]),
17267
- userAuthorization: z65.enum(["high", "medium", "low", "unknown"])
17651
+ var guardianDecisionSchema = z66.object({
17652
+ decision: z66.enum(["allow", "ask", "deny"]),
17653
+ reason: z66.string().trim().min(1).max(500),
17654
+ riskLevel: z66.enum(["low", "medium", "high", "critical"]),
17655
+ userAuthorization: z66.enum(["high", "medium", "low", "unknown"])
17268
17656
  }).strict();
17269
17657
  var GUARDIAN_REVIEW_TIMEOUT_MS = 6e4;
17270
17658
  var GUARDIAN_REVIEW_MAX_TOKENS = 2e3;
17271
17659
  var MAX_PROPOSAL_CHARS = 192e3;
17272
17660
  function guardianPrompt(proposal) {
17273
- const proposalJson = JSON.stringify(z65.json().parse(proposal), null, 2);
17661
+ const proposalJson = JSON.stringify(z66.json().parse(proposal), null, 2);
17274
17662
  if (proposalJson.length > MAX_PROPOSAL_CHARS) {
17275
17663
  throw new Error(
17276
17664
  `Guardian action proposal exceeds ${MAX_PROPOSAL_CHARS} characters.`
@@ -17868,6 +18256,7 @@ function createResumeState(args) {
17868
18256
  let resumeMessages = [];
17869
18257
  let turnContexts = [];
17870
18258
  let turnStartMessageIndex;
18259
+ let cumulativeToolCallCount = args.checkpoint.record?.cumulativeToolCallCount ?? 0;
17871
18260
  let advancedPastResume = !args.checkpoint.resumed;
17872
18261
  let resumedBoundaryKey = "";
17873
18262
  if (args.checkpoint.resumed && args.checkpoint.record.piMessages.length) {
@@ -17884,6 +18273,7 @@ function createResumeState(args) {
17884
18273
  conversationId: args.conversationId,
17885
18274
  turnId: args.turnId,
17886
18275
  channelName: args.channelName,
18276
+ cumulativeToolCallCount,
17887
18277
  destination: args.destination,
17888
18278
  dispatchId: args.dispatchId,
17889
18279
  source: args.runSource,
@@ -17906,6 +18296,12 @@ function createResumeState(args) {
17906
18296
  setBeforeMessageCount(count) {
17907
18297
  beforeMessageCount = count;
17908
18298
  },
18299
+ /** Admit one tool call against the durable turn total, or throw the limit. */
18300
+ admitToolCall() {
18301
+ const next = cumulativeToolCallCount + 1;
18302
+ assertTurnToolCallLimit(next, botConfig.maxToolCallsPerTurn);
18303
+ cumulativeToolCallCount = next;
18304
+ },
17909
18305
  setTurnContexts(contexts) {
17910
18306
  turnContexts = contexts;
17911
18307
  },
@@ -17999,7 +18395,7 @@ function createResumeState(args) {
17999
18395
  ...usage ? { usage } : void 0
18000
18396
  };
18001
18397
  } catch (error) {
18002
- if (error instanceof AuthPausePersistenceError || error instanceof TurnSliceLimitExceededError) {
18398
+ if (error instanceof AuthPausePersistenceError || isTurnExecutionLimitExceededError(error)) {
18003
18399
  throw error;
18004
18400
  }
18005
18401
  throw new AuthPausePersistenceError(
@@ -19381,6 +19777,17 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
19381
19777
  reason: `${exclusiveTool} must be the only tool call in its assistant message; reissue it alone`
19382
19778
  };
19383
19779
  }
19780
+ try {
19781
+ runResume.admitToolCall();
19782
+ } catch (error) {
19783
+ const limitError = error instanceof Error ? error : new Error(String(error));
19784
+ pendingPiHookError ??= limitError;
19785
+ return {
19786
+ block: true,
19787
+ reason: limitError.message,
19788
+ terminate: true
19789
+ };
19790
+ }
19384
19791
  return void 0;
19385
19792
  },
19386
19793
  afterToolCall: async ({ result: result2, toolCall }, signal2) => {
@@ -19574,6 +19981,11 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
19574
19981
  );
19575
19982
  throw pendingAuthPause;
19576
19983
  }
19984
+ if (pendingPiHookError) {
19985
+ const hookError = pendingPiHookError;
19986
+ pendingPiHookError = void 0;
19987
+ throw hookError;
19988
+ }
19577
19989
  throw error;
19578
19990
  } finally {
19579
19991
  if (timeoutId) {
@@ -19783,7 +20195,7 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
19783
20195
  throw error.originalError;
19784
20196
  }
19785
20197
  const runError = error instanceof AssistantMessageDeliveryError ? error.originalError : error;
19786
- if (runError instanceof AuthPausePersistenceError || runError instanceof TurnSliceLimitExceededError) {
20198
+ if (runError instanceof AuthPausePersistenceError || isTurnExecutionLimitExceededError(runError)) {
19787
20199
  throw runError;
19788
20200
  }
19789
20201
  if (resume && runError instanceof AuthorizationPauseError) {
@@ -19884,6 +20296,10 @@ export {
19884
20296
  normalizeSandboxEgressTracePropagationDomains,
19885
20297
  shouldPropagateSandboxEgressTrace,
19886
20298
  resolveSandboxEgressProviderForHost,
20299
+ admitAutomatedTurn,
20300
+ recordFinishedTurnForAutomatedLimit,
20301
+ postAutomatedTurnLimitNoticeForDestination,
20302
+ maybePostAutomatedTurnLimitNotice,
19887
20303
  renderTaskInput,
19888
20304
  RESOURCE_EVENT_MESSAGE_AUTHOR,
19889
20305
  RESOURCE_EVENT_SYSTEM_ACTOR,