@sentry/junior 0.128.0 → 0.129.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 (73) hide show
  1. package/dist/{agent-hooks-F75ANGBV.js → agent-hooks-ZM4WMZCN.js} +9 -9
  2. package/dist/api/schema/task.d.ts +152 -0
  3. package/dist/api/schema.d.ts +2 -0
  4. package/dist/api/schema.js +13 -3
  5. package/dist/api/tasks/routes.d.ts +4 -0
  6. package/dist/api.js +425 -23
  7. package/dist/app.d.ts +2 -1
  8. package/dist/app.js +315 -27
  9. package/dist/{catalog-runtime-ZPSA5QM2.js → catalog-runtime-TN2GPVEI.js} +5 -5
  10. package/dist/chat/agent-dispatch/context.d.ts +18 -0
  11. package/dist/chat/event-tasks/store.d.ts +7 -1
  12. package/dist/chat/event-tasks/tool-support.d.ts +1 -0
  13. package/dist/chat/resource-events/runtime-catalog.d.ts +3 -0
  14. package/dist/chat/sandbox/resources.d.ts +12 -1
  15. package/dist/chat/scheduled-tasks/cadence.d.ts +27 -0
  16. package/dist/chat/scheduled-tasks/heartbeat.d.ts +6 -0
  17. package/dist/chat/scheduled-tasks/identity.d.ts +6 -0
  18. package/dist/chat/scheduled-tasks/personal.d.ts +26 -0
  19. package/dist/chat/scheduled-tasks/schedule-intent.d.ts +61 -0
  20. package/dist/chat/scheduled-tasks/store.d.ts +77 -0
  21. package/dist/chat/scheduled-tasks/tool-support.d.ts +203 -0
  22. package/dist/chat/scheduled-tasks/tools/create.d.ts +80 -0
  23. package/dist/chat/scheduled-tasks/tools/delete.d.ts +56 -0
  24. package/dist/chat/scheduled-tasks/tools/list.d.ts +54 -0
  25. package/dist/chat/scheduled-tasks/tools/run-now.d.ts +56 -0
  26. package/dist/chat/scheduled-tasks/tools/update.d.ts +82 -0
  27. package/dist/chat/scheduled-tasks/tools.d.ts +6 -0
  28. package/dist/chat/scheduled-tasks/types.d.ts +81 -0
  29. package/dist/chat/tasks/read.d.ts +9 -0
  30. package/dist/chat/tools/scheduled-tasks.d.ts +4 -0
  31. package/dist/{chunk-K5ZB3WWH.js → chunk-2BCQKJTX.js} +2 -2
  32. package/dist/{chunk-G6XQODHM.js → chunk-3N4MWF3R.js} +1 -1
  33. package/dist/{chunk-NHWE6Y7G.js → chunk-6CMYU62S.js} +7 -7
  34. package/dist/{chunk-YY6CVET7.js → chunk-6QQOLIJJ.js} +1308 -804
  35. package/dist/{chunk-WZ365SQC.js → chunk-A6QQPVSH.js} +1 -1
  36. package/dist/chunk-BDIEEZK7.js +1470 -0
  37. package/dist/{chunk-AFJF3RGU.js → chunk-BVKP37NE.js} +61 -13
  38. package/dist/{chunk-5KKIBIIP.js → chunk-CZJUBH6O.js} +12 -12
  39. package/dist/{chunk-OLGB5Y7R.js → chunk-CZQ2DSQZ.js} +1 -1
  40. package/dist/{chunk-3PKF6YNU.js → chunk-E4UCPRYL.js} +1 -1
  41. package/dist/{chunk-KNRODVH2.js → chunk-ESYXDXNX.js} +6 -6
  42. package/dist/{chunk-Z4KTQMWW.js → chunk-GPWHBHAG.js} +1 -1
  43. package/dist/{chunk-JDCPDJ54.js → chunk-GURSWCI4.js} +2 -2
  44. package/dist/{chunk-RYWMDDWK.js → chunk-K3U5447S.js} +1 -1
  45. package/dist/{chunk-SHMHHXD5.js → chunk-KB2M27DL.js} +58 -0
  46. package/dist/{chunk-PBWUUVVG.js → chunk-LV2BQ26V.js} +1 -1
  47. package/dist/{chunk-KTGJAWRO.js → chunk-NNRV4T2C.js} +1 -2
  48. package/dist/{chunk-B6E3YA2H.js → chunk-P6I7LFKC.js} +1 -1
  49. package/dist/{chunk-B7FPRGUJ.js → chunk-PQFNTLZI.js} +3 -3
  50. package/dist/{chunk-A76LKS5W.js → chunk-QAOA4GUG.js} +5 -5
  51. package/dist/{chunk-BY43CEXN.js → chunk-R62DRNKB.js} +2 -2
  52. package/dist/{chunk-HBFQLSGV.js → chunk-U23X4ASF.js} +4 -4
  53. package/dist/{chunk-2HTHX6XV.js → chunk-XENYUOZG.js} +38 -17
  54. package/dist/cli/chat.js +24 -24
  55. package/dist/cli/check.js +6 -6
  56. package/dist/cli/plugins.js +12 -12
  57. package/dist/cli/snapshot-create.js +9 -9
  58. package/dist/cli/upgrade.js +9 -17
  59. package/dist/db/schema/scheduled-tasks.d.ts +257 -0
  60. package/dist/db/schema.d.ts +258 -1
  61. package/dist/{db-FYJYPAKG.js → db-ZI6TBXIS.js} +7 -7
  62. package/dist/instrumentation.js +4 -4
  63. package/dist/nitro.js +2 -2
  64. package/dist/{oauth-callback-server-W3PPIHCS.js → oauth-callback-server-TLA4GARF.js} +17 -17
  65. package/dist/{runner-5NOFUYKR.js → runner-23YFRWQJ.js} +11 -11
  66. package/dist/{skills-ENIBKF5V.js → skills-QIUG4D6M.js} +6 -6
  67. package/dist/{validation-BHLBOO6K.js → validation-3KGEBATS.js} +6 -6
  68. package/dist/version.js +1 -1
  69. package/migrations/0016_neat_the_anarchist.sql +171 -0
  70. package/migrations/meta/0016_snapshot.json +1617 -0
  71. package/migrations/meta/_journal.json +7 -0
  72. package/package.json +5 -6
  73. package/dist/chunk-FJEIX3AH.js +0 -37
@@ -30,7 +30,7 @@ import {
30
30
  toMcpProviderError,
31
31
  toolInvocationDestination,
32
32
  uploadFilesToConversation
33
- } from "./chunk-NHWE6Y7G.js";
33
+ } from "./chunk-6CMYU62S.js";
34
34
  import {
35
35
  CooperativeTurnYieldError,
36
36
  JUNIOR_THREAD_STATE_TTL_MS,
@@ -80,7 +80,7 @@ import {
80
80
  stripRuntimeTurnContext,
81
81
  trimTrailingAssistantMessages,
82
82
  updateConversationStats
83
- } from "./chunk-HBFQLSGV.js";
83
+ } from "./chunk-U23X4ASF.js";
84
84
  import {
85
85
  parseSandboxEgressAuthRequiredSignal,
86
86
  parseSandboxEgressPermissionDeniedSignal,
@@ -104,13 +104,42 @@ import {
104
104
  runNonInteractiveCommand,
105
105
  throwSandboxOperationError,
106
106
  wrapSandboxSetupError
107
- } from "./chunk-2HTHX6XV.js";
107
+ } from "./chunk-XENYUOZG.js";
108
108
  import {
109
- incrementStat
110
- } from "./chunk-FJEIX3AH.js";
109
+ SCHEDULED_TASK_SYSTEM_ACTOR,
110
+ ToolInputError,
111
+ compactEventTask,
112
+ createEventTask,
113
+ createSchedulerSqlStore,
114
+ deleteEventTask,
115
+ eventNamespaceSchema,
116
+ eventTaskListToolResultSchema,
117
+ eventTaskMatchesDestination,
118
+ eventTaskSuccess,
119
+ eventTaskToolResultSchema,
120
+ getEventTask,
121
+ getFirstRunAtMs,
122
+ getResourceEventCatalog,
123
+ getZonedDateTimeParts,
124
+ incrementStat,
125
+ injectContinuationToolName,
126
+ juniorToolOutputSchema,
127
+ listEventTasksForTeam,
128
+ makeStructuredToolOutput,
129
+ normalizeEventIdentifier,
130
+ pluginSupportsEvent,
131
+ registeredEventTaskTriggerSchema,
132
+ registeredEventTypeSchema,
133
+ registeredResourceTypeSchema,
134
+ requireEventTaskSlackContext,
135
+ requireSupportedEventTaskTrigger,
136
+ resolveLocalScheduleAtMs,
137
+ saveEventTask,
138
+ writableEventTask
139
+ } from "./chunk-BDIEEZK7.js";
111
140
  import {
112
141
  parseSlackThreadId
113
- } from "./chunk-PBWUUVVG.js";
142
+ } from "./chunk-LV2BQ26V.js";
114
143
  import {
115
144
  addAgentTurnUsage,
116
145
  hasAgentTurnUsage
@@ -120,14 +149,12 @@ import {
120
149
  } from "./chunk-UIE3R5XU.js";
121
150
  import {
122
151
  SlackActionError,
123
- canRouteResourceEvents,
124
152
  createPluginHookRunner,
125
153
  downloadPrivateSlackFile,
126
154
  getFilePermalink,
127
155
  getPluginSystemPromptContributions,
128
156
  getPluginTools,
129
157
  getPluginUserPromptContributions,
130
- getPlugins,
131
158
  getSlackClient,
132
159
  getSlackToolContext,
133
160
  isConversationScopedChannel,
@@ -135,7 +162,7 @@ import {
135
162
  readActorIdentity,
136
163
  resolveChannelCapabilities,
137
164
  withSlackRetries
138
- } from "./chunk-A76LKS5W.js";
165
+ } from "./chunk-QAOA4GUG.js";
139
166
  import {
140
167
  KNOWN_CONVERSATION_EVENT_TYPES,
141
168
  contextProvenance,
@@ -146,10 +173,7 @@ import {
146
173
  instructionActors,
147
174
  instructionProvenanceFor,
148
175
  sameActorIdentity
149
- } from "./chunk-B7FPRGUJ.js";
150
- import {
151
- juniorEventTasks
152
- } from "./chunk-SHMHHXD5.js";
176
+ } from "./chunk-PQFNTLZI.js";
153
177
  import {
154
178
  SANDBOX_DATA_ROOT,
155
179
  SANDBOX_SKILLS_ROOT,
@@ -159,7 +183,7 @@ import {
159
183
  sandboxSkillFile,
160
184
  sandboxSkillPathResolution,
161
185
  sleep
162
- } from "./chunk-G6XQODHM.js";
186
+ } from "./chunk-3N4MWF3R.js";
163
187
  import {
164
188
  ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX,
165
189
  COMPACTION_SUMMARY_PREFIX,
@@ -193,7 +217,7 @@ import {
193
217
  renderCurrentInstruction,
194
218
  resolveGatewayModel,
195
219
  unwrapCurrentInstruction
196
- } from "./chunk-K5ZB3WWH.js";
220
+ } from "./chunk-2BCQKJTX.js";
197
221
  import {
198
222
  canExposeConversationPayload,
199
223
  resolveConversationPrivacy,
@@ -203,16 +227,16 @@ import {
203
227
  toGenAiMessagesTraceAttributes,
204
228
  toGenAiPayloadMetadata,
205
229
  toGenAiPayloadTraceAttributes
206
- } from "./chunk-Z4KTQMWW.js";
230
+ } from "./chunk-GPWHBHAG.js";
207
231
  import {
208
232
  discoverSkills,
209
233
  findSkillByName,
210
234
  loadSkillsByName,
211
235
  parseSkillInvocation
212
- } from "./chunk-BY43CEXN.js";
236
+ } from "./chunk-R62DRNKB.js";
213
237
  import {
214
238
  pluginCatalogRuntime
215
- } from "./chunk-WZ365SQC.js";
239
+ } from "./chunk-A6QQPVSH.js";
216
240
  import {
217
241
  CredentialUnavailableError,
218
242
  OAuthProviderError,
@@ -220,7 +244,7 @@ import {
220
244
  getOAuthProviderErrorAttributes,
221
245
  resolveAuthTokenPlaceholder,
222
246
  resolvePluginCommandEnv
223
- } from "./chunk-OLGB5Y7R.js";
247
+ } from "./chunk-CZQ2DSQZ.js";
224
248
  import {
225
249
  credentialUserSubjectId
226
250
  } from "./chunk-77VDLF3Z.js";
@@ -249,7 +273,7 @@ import {
249
273
  summarizeMessageText,
250
274
  withLogContext,
251
275
  withSpan
252
- } from "./chunk-B6E3YA2H.js";
276
+ } from "./chunk-P6I7LFKC.js";
253
277
  import {
254
278
  startInactiveSpan,
255
279
  withActiveSpan
@@ -863,59 +887,6 @@ function getDiscardedRetryUsage(messages, retryMessages) {
863
887
  return hasAgentTurnUsage(usage) ? usage : void 0;
864
888
  }
865
889
 
866
- // src/chat/tool-support/structured-result.ts
867
- import { z } from "zod";
868
- var juniorToolContinuationSchema = z.object({
869
- arguments: z.record(z.string(), z.unknown()),
870
- reason: z.string().min(1).optional()
871
- }).strict();
872
- var juniorToolBoundContinuationSchema = juniorToolContinuationSchema.extend({
873
- tool_name: z.string().min(1)
874
- });
875
- var juniorToolOutputSchema = z.object({
876
- target: z.string().min(1).optional(),
877
- truncated: z.boolean().optional(),
878
- continuation: juniorToolContinuationSchema.optional()
879
- }).passthrough();
880
- function sortJsonValue(value) {
881
- if (Array.isArray(value)) {
882
- return value.map(sortJsonValue);
883
- }
884
- if (!value || typeof value !== "object") {
885
- return value;
886
- }
887
- return Object.fromEntries(
888
- Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => [key, sortJsonValue(item)])
889
- );
890
- }
891
- function isRecord(value) {
892
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
893
- }
894
- function injectContinuationToolName(details, toolName) {
895
- if (!isRecord(details) || !isRecord(details.continuation)) {
896
- return details;
897
- }
898
- return {
899
- ...details,
900
- continuation: juniorToolBoundContinuationSchema.parse({
901
- ...details.continuation,
902
- tool_name: toolName
903
- })
904
- };
905
- }
906
- function makeStructuredToolOutput(details, options = {}) {
907
- return {
908
- content: [
909
- {
910
- type: "text",
911
- text: JSON.stringify(sortJsonValue(details))
912
- },
913
- ...options.content ?? []
914
- ],
915
- details
916
- };
917
- }
918
-
919
890
  // src/chat/tool-support/turn-deadline-result.ts
920
891
  var TURN_DEADLINE_INTERRUPTION = {
921
892
  cause: "turn_deadline",
@@ -941,7 +912,7 @@ function annotateTurnDeadlineToolResult(result) {
941
912
  }
942
913
 
943
914
  // src/chat/services/turn-router.ts
944
- import { z as z2 } from "zod";
915
+ import { z } from "zod";
945
916
  var CLASSIFIER_CONFIDENCE_THRESHOLD = 0.75;
946
917
  var MAX_ROUTER_CONTEXT_CHARS = 8e3;
947
918
  var ROUTER_CONTEXT_HEAD_CHARS = 3e3;
@@ -967,17 +938,17 @@ function coerceClassifierConfidence(value) {
967
938
  return CONFIDENCE_LABELS[trimmed] ?? value;
968
939
  }
969
940
  function createTurnRouteSchema(profiles) {
970
- return z2.object({
971
- reasoning_level: z2.enum(TURN_REASONING_LEVELS),
941
+ return z.object({
942
+ reasoning_level: z.enum(TURN_REASONING_LEVELS),
972
943
  profile: modelProfileSchema.refine(
973
944
  (profile) => Object.hasOwn(profiles, profile),
974
945
  "Profile is not configured"
975
946
  ),
976
- confidence: z2.preprocess(
947
+ confidence: z.preprocess(
977
948
  coerceClassifierConfidence,
978
- z2.number().min(0).max(1)
949
+ z.number().min(0).max(1)
979
950
  ),
980
- reason: z2.string().min(1)
951
+ reason: z.string().min(1)
981
952
  });
982
953
  }
983
954
  var CLASSIFIER_FALLBACK_REASONING_LEVEL = "medium";
@@ -1261,44 +1232,44 @@ async function resolveDestinationVisibility(args) {
1261
1232
  }
1262
1233
 
1263
1234
  // src/chat/tool-support/action-review-history.ts
1264
- import { z as z3 } from "zod";
1235
+ import { z as z2 } from "zod";
1265
1236
  var MAX_VISIBLE_HISTORY_CHARS = 12e3;
1266
- var priorRejectionSchema = z3.object({
1267
- decision: z3.enum(["ask", "deny"]),
1268
- input: z3.record(z3.string(), z3.unknown()),
1269
- reason: z3.string().min(1),
1270
- riskLevel: z3.enum(["low", "medium", "high", "critical"]).optional(),
1271
- tool: z3.object({
1272
- annotations: z3.record(z3.string(), z3.unknown()).optional(),
1273
- description: z3.string(),
1274
- dispatcherName: z3.string().optional(),
1275
- identity: z3.object({
1276
- id: z3.string(),
1277
- name: z3.string(),
1278
- plugin: z3.string()
1237
+ var priorRejectionSchema = z2.object({
1238
+ decision: z2.enum(["ask", "deny"]),
1239
+ input: z2.record(z2.string(), z2.unknown()),
1240
+ reason: z2.string().min(1),
1241
+ riskLevel: z2.enum(["low", "medium", "high", "critical"]).optional(),
1242
+ tool: z2.object({
1243
+ annotations: z2.record(z2.string(), z2.unknown()).optional(),
1244
+ description: z2.string(),
1245
+ dispatcherName: z2.string().optional(),
1246
+ identity: z2.object({
1247
+ id: z2.string(),
1248
+ name: z2.string(),
1249
+ plugin: z2.string()
1279
1250
  }).strict().optional(),
1280
- name: z3.string(),
1281
- proposalDescription: z3.string().optional(),
1282
- catalogSource: z3.object({
1283
- description: z3.string(),
1284
- id: z3.string()
1251
+ name: z2.string(),
1252
+ proposalDescription: z2.string().optional(),
1253
+ catalogSource: z2.object({
1254
+ description: z2.string(),
1255
+ id: z2.string()
1285
1256
  }).strict().optional()
1286
1257
  }).strict(),
1287
- userAuthorization: z3.enum(["high", "medium", "low", "unknown"]).optional()
1258
+ userAuthorization: z2.enum(["high", "medium", "low", "unknown"]).optional()
1288
1259
  }).strict();
1289
- var rejectionMarkerSchema = z3.object({
1290
- decision: z3.enum(["ask", "deny"]),
1260
+ var rejectionMarkerSchema = z2.object({
1261
+ decision: z2.enum(["ask", "deny"]),
1291
1262
  priorRejection: priorRejectionSchema,
1292
- reason: z3.string().min(1),
1293
- riskLevel: z3.enum(["low", "medium", "high", "critical"]).optional(),
1294
- userAuthorization: z3.enum(["high", "medium", "low", "unknown"]).optional(),
1295
- version: z3.literal(1)
1263
+ reason: z2.string().min(1),
1264
+ riskLevel: z2.enum(["low", "medium", "high", "critical"]).optional(),
1265
+ userAuthorization: z2.enum(["high", "medium", "low", "unknown"]).optional(),
1266
+ version: z2.literal(1)
1296
1267
  }).strict();
1297
- function isRecord2(value) {
1268
+ function isRecord(value) {
1298
1269
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
1299
1270
  }
1300
1271
  function getToolActionRejectionMarker(message) {
1301
- if (!isRecord2(message) || !isRecord2(message.details)) {
1272
+ if (!isRecord(message) || !isRecord(message.details)) {
1302
1273
  return void 0;
1303
1274
  }
1304
1275
  const parsed = rejectionMarkerSchema.safeParse(
@@ -1309,7 +1280,7 @@ function getToolActionRejectionMarker(message) {
1309
1280
  function projectToolActionRejection(pending, toolCallId, result) {
1310
1281
  const rejection = pending.get(toolCallId);
1311
1282
  pending.delete(toolCallId);
1312
- const details = isRecord2(result.details) ? result.details : void 0;
1283
+ const details = isRecord(result.details) ? result.details : void 0;
1313
1284
  const hasReservedMarker = details !== void 0 && "guardianActionRejection" in details;
1314
1285
  if (!rejection && !hasReservedMarker) {
1315
1286
  return result;
@@ -1403,7 +1374,7 @@ function parseMcpProviderFromToolName(toolName) {
1403
1374
 
1404
1375
  // src/chat/pi/derived-state.ts
1405
1376
  var MCP_BRIDGE_TOOLS = /* @__PURE__ */ new Set(["callMcpTool", "searchMcpTools"]);
1406
- function isRecord3(value) {
1377
+ function isRecord2(value) {
1407
1378
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
1408
1379
  }
1409
1380
  function providerFromToolName(value) {
@@ -1425,7 +1396,7 @@ function addBridgeToolProvider(toolName, value, providers) {
1425
1396
  if (bridgeTool === "searchMcpTools") {
1426
1397
  for (const argsKey of ["input", "args", "arguments", "params"]) {
1427
1398
  const args = value[argsKey];
1428
- if (isRecord3(args)) {
1399
+ if (isRecord2(args)) {
1429
1400
  addString(providers, args.provider);
1430
1401
  }
1431
1402
  }
@@ -1434,7 +1405,7 @@ function addBridgeToolProvider(toolName, value, providers) {
1434
1405
  if (bridgeTool === "callMcpTool") {
1435
1406
  for (const argsKey of ["input", "args", "arguments", "params"]) {
1436
1407
  const args = value[argsKey];
1437
- if (isRecord3(args)) {
1408
+ if (isRecord2(args)) {
1438
1409
  addString(providers, providerFromToolName(args.tool_name));
1439
1410
  }
1440
1411
  }
@@ -1447,18 +1418,18 @@ function addMcpResultProvider(message, providers) {
1447
1418
  return;
1448
1419
  }
1449
1420
  if (toolName === "loadSkill") {
1450
- if (isRecord3(message.details)) {
1421
+ if (isRecord2(message.details)) {
1451
1422
  addString(providers, message.details.mcp_provider);
1452
1423
  }
1453
1424
  addString(providers, message.mcp_provider);
1454
1425
  return;
1455
1426
  }
1456
1427
  if (toolName === "searchMcpTools") {
1457
- if (isRecord3(message.details)) {
1428
+ if (isRecord2(message.details)) {
1458
1429
  addString(providers, message.details.provider);
1459
1430
  if (Array.isArray(message.details.tools)) {
1460
1431
  for (const tool of message.details.tools) {
1461
- if (isRecord3(tool)) {
1432
+ if (isRecord2(tool)) {
1462
1433
  addString(providers, providerFromToolName(tool.tool_name));
1463
1434
  }
1464
1435
  }
@@ -1470,11 +1441,11 @@ function addMcpResultProvider(message, providers) {
1470
1441
  if (toolName === "callMcpTool") {
1471
1442
  for (const argsKey of ["input", "args", "arguments", "params"]) {
1472
1443
  const args = message[argsKey];
1473
- if (isRecord3(args)) {
1444
+ if (isRecord2(args)) {
1474
1445
  addString(providers, providerFromToolName(args.tool_name));
1475
1446
  }
1476
1447
  }
1477
- if (isRecord3(message.details)) {
1448
+ if (isRecord2(message.details)) {
1478
1449
  addString(providers, message.details.provider);
1479
1450
  addString(providers, providerFromToolName(message.details.tool_name));
1480
1451
  }
@@ -1482,7 +1453,7 @@ function addMcpResultProvider(message, providers) {
1482
1453
  }
1483
1454
  }
1484
1455
  function scanMcpProviders(message, providers) {
1485
- if (!isRecord3(message)) {
1456
+ if (!isRecord2(message)) {
1486
1457
  return;
1487
1458
  }
1488
1459
  if (message.role === "toolResult") {
@@ -1494,15 +1465,15 @@ function scanMcpProviders(message, providers) {
1494
1465
  return;
1495
1466
  }
1496
1467
  for (const part of content) {
1497
- if (!isRecord3(part)) {
1468
+ if (!isRecord2(part)) {
1498
1469
  continue;
1499
1470
  }
1500
1471
  addBridgeToolProvider(getToolName(part), part, providers);
1501
1472
  }
1502
1473
  }
1503
1474
  function scanLoadedSkills(message, skills) {
1504
- if (isRecord3(message) && message.role === "toolResult" && message.toolName === "loadSkill" && message.isError !== true) {
1505
- if (isRecord3(message.details)) {
1475
+ if (isRecord2(message) && message.role === "toolResult" && message.toolName === "loadSkill" && message.isError !== true) {
1476
+ if (isRecord2(message.details)) {
1506
1477
  addString(skills, message.details.skill_name);
1507
1478
  }
1508
1479
  addString(skills, message.skill_name);
@@ -1807,6 +1778,7 @@ var TOOL_POLICY_RULES = [
1807
1778
  "- Use createEventTask only when the user explicitly asks for an event task or durable whenever-this-happens-do-X automation. Ordinary watch, notify, and tell-me-when requests use watchResourceEvents. When an event task's resource and events are known, create it without redundant confirmation.",
1808
1779
  "- Event tasks make the task creator's connected credentials available by default when the requested work needs user-bound authorization. Do not ask for separate confirmation merely to use credentials needed for the requested work. On creation, omit credentialMode for the creator default and set system only when the creator explicitly requires it. For later changes, creator always means the task's original createdBy actor, never the current requester. If the requester is not that creator, do not attempt to enable creator credential use or suggest that confirmation could authorize it.",
1809
1780
  "- Event tasks are managed for the current Slack channel or DM, not one thread. When listing them, use createdBy to explain creator-only credential changes and warn when triggerAvailable is false; an unavailable task remains stored but cannot receive events until its plugin event is enabled again.",
1781
+ "- Scheduled tasks make the task creator's connected credentials available by default when the requested work needs user-bound authorization. Do not ask for separate confirmation merely to use credentials needed for the requested work. On creation, omit credential_mode for the creator default and set system only when the creator explicitly requires it. For later changes, creator always means the task's original created_by actor, never the current requester. If the requester is not that creator, do not attempt to enable creator credential use or suggest that confirmation could authorize it.",
1810
1782
  "- For code changes, debugging or root-cause analysis, broad refactors, and software architecture decisions, use `handoff` before substantive analysis only when it offers a profile that better matches the task. Do not switch merely because the task involves code.",
1811
1783
  "- Run `jr-rpc config get|set|unset|list` for provider defaults and `jr-rpc plugins list` for installed plugin introspection as standalone bash commands; do not chain them with `cd`, `&&`, pipes, or provider commands.",
1812
1784
  "- If the first result is empty, stale, ambiguous, or incomplete, try a focused alternate query, path, command, or source before concluding the answer cannot be verified."
@@ -3874,16 +3846,6 @@ function createSandboxRuntime(options) {
3874
3846
 
3875
3847
  // src/chat/tools/sandbox/file-utils.ts
3876
3848
  import path4 from "path";
3877
-
3878
- // src/chat/tools/execution/tool-input-error.ts
3879
- var ToolInputError = class extends Error {
3880
- constructor(message, options) {
3881
- super(message, options);
3882
- this.name = "ToolInputError";
3883
- }
3884
- };
3885
-
3886
- // src/chat/tools/sandbox/file-utils.ts
3887
3849
  var MAX_TEXT_CHARS = 6e4;
3888
3850
  var RIPGREP_EXCLUDED_GLOBS = [
3889
3851
  "!**/.git/**",
@@ -4260,10 +4222,10 @@ function validateAndApplyTextEdits(content, edits, targetName) {
4260
4222
  }
4261
4223
 
4262
4224
  // src/chat/tools/sandbox/edit-file.ts
4263
- import { z as z5 } from "zod";
4225
+ import { z as z4 } from "zod";
4264
4226
 
4265
4227
  // src/chat/tool-support/zod-tool.ts
4266
- import { z as z4 } from "zod";
4228
+ import { z as z3 } from "zod";
4267
4229
  function isContentOnlyToolResult(value) {
4268
4230
  return value !== null && typeof value === "object" && Array.isArray(value.content) && !("details" in value);
4269
4231
  }
@@ -4300,7 +4262,7 @@ function zodTool(definition) {
4300
4262
  const { inputSchema: inputSchema2, outputSchema: outputSchema5, prepareArguments, execute, ...toolDef } = definition;
4301
4263
  let modelInputSchema;
4302
4264
  try {
4303
- modelInputSchema = z4.toJSONSchema(inputSchema2);
4265
+ modelInputSchema = z3.toJSONSchema(inputSchema2);
4304
4266
  } catch (error) {
4305
4267
  throw new TypeError(
4306
4268
  "zodTool() inputSchema must be representable as JSON Schema.",
@@ -4310,7 +4272,7 @@ function zodTool(definition) {
4310
4272
  let modelOutputSchema;
4311
4273
  if (outputSchema5) {
4312
4274
  try {
4313
- modelOutputSchema = z4.toJSONSchema(outputSchema5);
4275
+ modelOutputSchema = z3.toJSONSchema(outputSchema5);
4314
4276
  } catch (error) {
4315
4277
  throw new TypeError(
4316
4278
  "zodTool() outputSchema must be representable as JSON Schema.",
@@ -4395,11 +4357,11 @@ async function editFile(params) {
4395
4357
  truncated: diff.truncated
4396
4358
  });
4397
4359
  }
4398
- var editReplacementSchema = z5.object({
4399
- oldText: z5.string().min(1).describe(
4360
+ var editReplacementSchema = z4.object({
4361
+ oldText: z4.string().min(1).describe(
4400
4362
  "Exact text to replace. It must be unique in the original file and must not overlap another edit."
4401
4363
  ),
4402
- newText: z5.string().describe("Replacement text for this edit.")
4364
+ newText: z4.string().describe("Replacement text for this edit.")
4403
4365
  });
4404
4366
  function createEditFileTool() {
4405
4367
  return zodTool({
@@ -4412,9 +4374,9 @@ function createEditFileTool() {
4412
4374
  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.",
4413
4375
  prepareArguments: prepareEditFileArguments,
4414
4376
  executionMode: "sequential",
4415
- inputSchema: z5.object({
4416
- path: z5.string().min(1).describe("Path to edit in the sandbox workspace."),
4417
- edits: z5.array(editReplacementSchema).min(1).describe(
4377
+ inputSchema: z4.object({
4378
+ path: z4.string().min(1).describe("Path to edit in the sandbox workspace."),
4379
+ edits: z4.array(editReplacementSchema).min(1).describe(
4418
4380
  "Exact replacements matched against the original file, not incrementally."
4419
4381
  )
4420
4382
  }),
@@ -4429,7 +4391,7 @@ function createEditFileTool() {
4429
4391
 
4430
4392
  // src/chat/tools/sandbox/find-files.ts
4431
4393
  import path5 from "path";
4432
- import { z as z6 } from "zod";
4394
+ import { z as z5 } from "zod";
4433
4395
  var DEFAULT_FIND_LIMIT = 100;
4434
4396
  async function findFiles(params) {
4435
4397
  if (!params.pattern.trim()) {
@@ -4602,14 +4564,14 @@ function createFindFilesTool() {
4602
4564
  openWorldHint: false,
4603
4565
  readOnlyHint: true
4604
4566
  },
4605
- inputSchema: z6.object({
4606
- pattern: z6.string().min(1).describe(
4567
+ inputSchema: z5.object({
4568
+ pattern: z5.string().min(1).describe(
4607
4569
  "Glob pattern to match, for example '*.ts', '**/*.json', or 'src/**/*.test.ts'."
4608
4570
  ),
4609
- path: z6.string().min(1).describe(
4571
+ path: z5.string().min(1).describe(
4610
4572
  "Directory or file path in the sandbox workspace. Defaults to the workspace root."
4611
4573
  ).optional(),
4612
- limit: z6.coerce.number().int().min(1).describe("Maximum number of file paths to return. Defaults to 100.").optional()
4574
+ limit: z5.coerce.number().int().min(1).describe("Maximum number of file paths to return. Defaults to 100.").optional()
4613
4575
  }),
4614
4576
  outputSchema: juniorToolOutputSchema,
4615
4577
  execute: async () => {
@@ -4622,12 +4584,12 @@ function createFindFilesTool() {
4622
4584
 
4623
4585
  // src/chat/tools/sandbox/grep.ts
4624
4586
  import path6 from "path";
4625
- import { z as z7 } from "zod";
4587
+ import { z as z6 } from "zod";
4626
4588
  var DEFAULT_GREP_LIMIT = 100;
4627
4589
  var MAX_GREP_LINE_CHARS = 500;
4628
- var booleanInput = (description) => z7.preprocess(
4590
+ var booleanInput = (description) => z6.preprocess(
4629
4591
  (value) => value === "true" ? true : value === "false" ? false : value,
4630
- z7.boolean()
4592
+ z6.boolean()
4631
4593
  ).describe(description);
4632
4594
  function truncateGrepLine(value) {
4633
4595
  if (value.length <= MAX_GREP_LINE_CHARS) {
@@ -4976,20 +4938,20 @@ function createGrepTool() {
4976
4938
  openWorldHint: false,
4977
4939
  readOnlyHint: true
4978
4940
  },
4979
- inputSchema: z7.object({
4980
- pattern: z7.string().min(1).describe("Regex pattern or literal text to search for."),
4981
- path: z7.string().min(1).describe(
4941
+ inputSchema: z6.object({
4942
+ pattern: z6.string().min(1).describe("Regex pattern or literal text to search for."),
4943
+ path: z6.string().min(1).describe(
4982
4944
  "Directory or file path in the sandbox workspace. Defaults to the workspace root."
4983
4945
  ).optional(),
4984
- glob: z7.string().min(1).describe("Optional glob filter such as '*.ts' or '**/*.test.ts'.").optional(),
4946
+ glob: z6.string().min(1).describe("Optional glob filter such as '*.ts' or '**/*.test.ts'.").optional(),
4985
4947
  ignoreCase: booleanInput(
4986
4948
  "Whether matching should ignore case."
4987
4949
  ).optional(),
4988
4950
  literal: booleanInput(
4989
4951
  "Treat pattern as literal text instead of regex."
4990
4952
  ).optional(),
4991
- context: z7.coerce.number().int().min(0).describe("Number of surrounding context lines to include.").optional(),
4992
- limit: z7.coerce.number().int().min(1).describe("Maximum matches to return. Defaults to 100.").optional()
4953
+ context: z6.coerce.number().int().min(0).describe("Number of surrounding context lines to include.").optional(),
4954
+ limit: z6.coerce.number().int().min(1).describe("Maximum matches to return. Defaults to 100.").optional()
4993
4955
  }),
4994
4956
  outputSchema: juniorToolOutputSchema,
4995
4957
  execute: async () => {
@@ -5000,7 +4962,7 @@ function createGrepTool() {
5000
4962
 
5001
4963
  // src/chat/tools/sandbox/list-dir.ts
5002
4964
  import path7 from "path";
5003
- import { z as z8 } from "zod";
4965
+ import { z as z7 } from "zod";
5004
4966
  var DEFAULT_LIST_LIMIT = 500;
5005
4967
  async function listDir(params) {
5006
4968
  const dirPath = resolveWorkspacePath(params.path);
@@ -5081,11 +5043,11 @@ function createListDirTool() {
5081
5043
  openWorldHint: false,
5082
5044
  readOnlyHint: true
5083
5045
  },
5084
- inputSchema: z8.object({
5085
- path: z8.string().min(1).describe(
5046
+ inputSchema: z7.object({
5047
+ path: z7.string().min(1).describe(
5086
5048
  "Directory path in the sandbox workspace. Defaults to the workspace root."
5087
5049
  ).optional(),
5088
- limit: z8.coerce.number().int().min(1).describe("Maximum entries to return. Defaults to 500.").optional()
5050
+ limit: z7.coerce.number().int().min(1).describe("Maximum entries to return. Defaults to 500.").optional()
5089
5051
  }),
5090
5052
  outputSchema: juniorToolOutputSchema,
5091
5053
  execute: async () => {
@@ -5097,7 +5059,7 @@ function createListDirTool() {
5097
5059
  }
5098
5060
 
5099
5061
  // src/chat/tools/sandbox/read-file.ts
5100
- import { z as z9 } from "zod";
5062
+ import { z as z8 } from "zod";
5101
5063
 
5102
5064
  // src/chat/tool-support/text-range-result.ts
5103
5065
  var DEFAULT_READ_LIMIT = 1e3;
@@ -5191,10 +5153,10 @@ function createReadFileTool() {
5191
5153
  openWorldHint: false,
5192
5154
  readOnlyHint: true
5193
5155
  },
5194
- inputSchema: z9.object({
5195
- path: z9.string().min(1).describe("Path to the file in the sandbox workspace."),
5196
- offset: z9.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
5197
- limit: z9.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
5156
+ inputSchema: z8.object({
5157
+ path: z8.string().min(1).describe("Path to the file in the sandbox workspace."),
5158
+ offset: z8.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
5159
+ limit: z8.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
5198
5160
  }),
5199
5161
  outputSchema: juniorToolOutputSchema,
5200
5162
  execute: async () => {
@@ -5751,25 +5713,25 @@ function createSandbox(options) {
5751
5713
 
5752
5714
  // src/chat/tools/sandbox/file-uploads.ts
5753
5715
  import path8 from "path";
5754
- import { z as z10 } from "zod";
5716
+ import { z as z9 } from "zod";
5755
5717
  var MAX_SANDBOX_FILE_UPLOAD_BYTES = 10 * 1024 * 1024;
5756
5718
  var SANDBOX_ARTIFACTS_DIR = "/tmp/junior/artifacts";
5757
- var sandboxFileReferenceSchema = z10.object({
5758
- path: z10.string().min(1).describe(
5719
+ var sandboxFileReferenceSchema = z9.object({
5720
+ path: z9.string().min(1).describe(
5759
5721
  "Exact source path of an existing sandbox file. Preserve paths returned by other tools unchanged; do not move or rewrite them before sending."
5760
5722
  ),
5761
- filename: z10.string().min(1).nullable().optional().describe(
5723
+ filename: z9.string().min(1).nullable().optional().describe(
5762
5724
  "Optional filename override shown to the recipient. Null is treated as omitted."
5763
5725
  ),
5764
- mimeType: z10.string().min(1).nullable().optional().describe("Optional MIME type override. Null is treated as omitted."),
5765
- bytes: z10.number().int().nonnegative().nullable().optional().describe(
5726
+ mimeType: z9.string().min(1).nullable().optional().describe("Optional MIME type override. Null is treated as omitted."),
5727
+ bytes: z9.number().int().nonnegative().nullable().optional().describe(
5766
5728
  "Optional known file size returned by a producing tool. Null is treated as omitted; sending tools validate the file contents directly."
5767
5729
  )
5768
5730
  });
5769
5731
  var generatedArtifactFileRefSchema = sandboxFileReferenceSchema.extend({
5770
- filename: z10.string().min(1),
5771
- mimeType: z10.string().min(1).optional(),
5772
- bytes: z10.number().int().nonnegative()
5732
+ filename: z9.string().min(1),
5733
+ mimeType: z9.string().min(1).optional(),
5734
+ bytes: z9.number().int().nonnegative()
5773
5735
  }).strict();
5774
5736
  var MIME_BY_EXTENSION = {
5775
5737
  ".png": "image/png",
@@ -6788,7 +6750,7 @@ function serializeMcpPayload(payload, privacy, options = {}) {
6788
6750
  }
6789
6751
 
6790
6752
  // src/chat/tools/sandbox/bash.ts
6791
- import { z as z11 } from "zod";
6753
+ import { z as z10 } from "zod";
6792
6754
  function createBashTool() {
6793
6755
  return zodTool({
6794
6756
  annotations: {
@@ -6798,9 +6760,9 @@ function createBashTool() {
6798
6760
  readOnlyHint: false
6799
6761
  },
6800
6762
  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.",
6801
- inputSchema: z11.object({
6802
- command: z11.string().min(1).describe("Bash command to run inside the sandbox."),
6803
- timeoutMs: z11.coerce.number().int().min(1e3).describe(
6763
+ inputSchema: z10.object({
6764
+ command: z10.string().min(1).describe("Bash command to run inside the sandbox."),
6765
+ timeoutMs: z10.coerce.number().int().min(1e3).describe(
6804
6766
  "Optional command timeout in milliseconds. Use for commands that may hang."
6805
6767
  ).optional()
6806
6768
  }),
@@ -6814,14 +6776,14 @@ function createBashTool() {
6814
6776
  }
6815
6777
 
6816
6778
  // src/chat/tools/web/image-generate.ts
6817
- import { z as z12 } from "zod";
6779
+ import { z as z11 } from "zod";
6818
6780
  var imageGenerateOutputSchema = juniorToolOutputSchema.extend({
6819
- model: z12.string(),
6820
- prompt: z12.string(),
6821
- enrichedPrompt: z12.string(),
6822
- image_count: z12.number().int().nonnegative(),
6823
- images: z12.array(generatedArtifactFileRefSchema),
6824
- delivery: z12.string()
6781
+ model: z11.string(),
6782
+ prompt: z11.string(),
6783
+ enrichedPrompt: z11.string(),
6784
+ image_count: z11.number().int().nonnegative(),
6785
+ images: z11.array(generatedArtifactFileRefSchema),
6786
+ delivery: z11.string()
6825
6787
  }).strict();
6826
6788
  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.
6827
6789
 
@@ -6882,8 +6844,8 @@ function createImageGenerateTool(hooks, options, deps = {}) {
6882
6844
  readOnlyHint: false
6883
6845
  },
6884
6846
  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.",
6885
- inputSchema: z12.object({
6886
- prompt: z12.string().min(1).max(4e3).describe("Image generation prompt.")
6847
+ inputSchema: z11.object({
6848
+ prompt: z11.string().min(1).max(4e3).describe("Image generation prompt.")
6887
6849
  }),
6888
6850
  outputSchema: imageGenerateOutputSchema,
6889
6851
  execute: async ({ prompt }) => {
@@ -6965,7 +6927,7 @@ function createImageGenerateTool(hooks, options, deps = {}) {
6965
6927
  }
6966
6928
 
6967
6929
  // src/chat/tools/skill/call-mcp-tool.ts
6968
- import { z as z13 } from "zod";
6930
+ import { z as z12 } from "zod";
6969
6931
  function resolveMcpArguments(input) {
6970
6932
  const extraKeys = Object.keys(input).filter(
6971
6933
  (key) => key !== "tool_name" && key !== "arguments"
@@ -7008,9 +6970,9 @@ function createCallMcpToolTool(mcpToolManager) {
7008
6970
  readOnlyHint: false
7009
6971
  },
7010
6972
  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.",
7011
- inputSchema: z13.object({
7012
- tool_name: z13.string().min(1).describe("Exact MCP tool_name from searchMcpTools."),
7013
- arguments: z13.record(z13.string(), z13.unknown()).describe(
6973
+ inputSchema: z12.object({
6974
+ tool_name: z12.string().min(1).describe("Exact MCP tool_name from searchMcpTools."),
6975
+ arguments: z12.record(z12.string(), z12.unknown()).describe(
7014
6976
  'Arguments matching the disclosed MCP tool schema, for example { "query": "..." } when searchMcpTools shows query is required.'
7015
6977
  ).optional()
7016
6978
  }).passthrough(),
@@ -7066,7 +7028,7 @@ function createCallMcpToolTool(mcpToolManager) {
7066
7028
  }
7067
7029
 
7068
7030
  // src/chat/tools/skill/load-skill.ts
7069
- import { z as z14 } from "zod";
7031
+ import { z as z13 } from "zod";
7070
7032
  function toLoadedSkill(result, availableSkills) {
7071
7033
  if (typeof result.skill_name !== "string" || typeof result.description !== "string" || typeof result.skill_dir !== "string" || typeof result.instructions !== "string") {
7072
7034
  return null;
@@ -7116,8 +7078,8 @@ function createLoadSkillTool(availableSkills, options) {
7116
7078
  readOnlyHint: false
7117
7079
  },
7118
7080
  description: "Load a skill by name for this turn. The result includes working_directory; resolve skill paths there and run skill-owned bash commands from there or with absolute paths. When the result includes mcp_provider, use searchMcpTools before callMcpTool. Use when a request clearly matches a known skill.",
7119
- inputSchema: z14.object({
7120
- skill_name: z14.string().min(1).describe("Skill name to load, without the leading slash.")
7081
+ inputSchema: z13.object({
7082
+ skill_name: z13.string().min(1).describe("Skill name to load, without the leading slash.")
7121
7083
  }),
7122
7084
  outputSchema: juniorToolOutputSchema,
7123
7085
  execute: async ({ skill_name }) => {
@@ -7135,7 +7097,7 @@ function createLoadSkillTool(availableSkills, options) {
7135
7097
  }
7136
7098
 
7137
7099
  // src/chat/tools/skill/search-mcp-tools.ts
7138
- import { z as z15 } from "zod";
7100
+ import { z as z14 } from "zod";
7139
7101
 
7140
7102
  // src/chat/tool-support/skill/mcp-tool-summary.ts
7141
7103
  function toExposedToolSummary(toolDef) {
@@ -7167,29 +7129,29 @@ function toActiveMcpCatalogSummaries(toolDefs) {
7167
7129
  // src/chat/tools/skill/search-mcp-tools.ts
7168
7130
  var DEFAULT_MAX_RESULTS = 5;
7169
7131
  var MAX_RESULTS = 20;
7170
- var providerSummarySchema = z15.object({
7171
- provider: z15.string(),
7172
- description: z15.string(),
7173
- active: z15.boolean()
7132
+ var providerSummarySchema = z14.object({
7133
+ provider: z14.string(),
7134
+ description: z14.string(),
7135
+ active: z14.boolean()
7174
7136
  }).strict();
7175
- var exposedToolSummarySchema = z15.object({
7176
- tool_name: z15.string(),
7177
- mcp_tool_name: z15.string(),
7178
- provider: z15.string(),
7179
- title: z15.string().optional(),
7180
- description: z15.string(),
7181
- input_schema: z15.record(z15.string(), z15.unknown()),
7182
- output_schema: z15.record(z15.string(), z15.unknown()).optional(),
7183
- annotations: z15.record(z15.string(), z15.unknown()).optional()
7137
+ var exposedToolSummarySchema = z14.object({
7138
+ tool_name: z14.string(),
7139
+ mcp_tool_name: z14.string(),
7140
+ provider: z14.string(),
7141
+ title: z14.string().optional(),
7142
+ description: z14.string(),
7143
+ input_schema: z14.record(z14.string(), z14.unknown()),
7144
+ output_schema: z14.record(z14.string(), z14.unknown()).optional(),
7145
+ annotations: z14.record(z14.string(), z14.unknown()).optional()
7184
7146
  }).strict();
7185
7147
  var searchMcpToolsOutputSchema = juniorToolOutputSchema.extend({
7186
- query: z15.string().nullable(),
7187
- provider: z15.string().nullable(),
7188
- total_active_tools: z15.number().int().nonnegative(),
7189
- returned_tools: z15.number().int().nonnegative(),
7190
- execution_tool: z15.literal("callMcpTool"),
7191
- available_providers: z15.array(providerSummarySchema),
7192
- tools: z15.array(exposedToolSummarySchema)
7148
+ query: z14.string().nullable(),
7149
+ provider: z14.string().nullable(),
7150
+ total_active_tools: z14.number().int().nonnegative(),
7151
+ returned_tools: z14.number().int().nonnegative(),
7152
+ execution_tool: z14.literal("callMcpTool"),
7153
+ available_providers: z14.array(providerSummarySchema),
7154
+ tools: z14.array(exposedToolSummarySchema)
7193
7155
  }).strict();
7194
7156
  function normalize(value) {
7195
7157
  return value.toLowerCase().replace(/[^a-z0-9_]+/g, " ").trim();
@@ -7315,14 +7277,14 @@ function createSearchMcpToolsTool(mcpToolManager) {
7315
7277
  readOnlyHint: true
7316
7278
  },
7317
7279
  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.",
7318
- inputSchema: z15.object({
7319
- query: z15.string().min(1).describe(
7280
+ inputSchema: z14.object({
7281
+ query: z14.string().min(1).describe(
7320
7282
  "Optional search terms describing the MCP tool or arguments needed."
7321
7283
  ).optional(),
7322
- provider: z15.string().min(1).describe(
7284
+ provider: z14.string().min(1).describe(
7323
7285
  "Optional provider name to list or search within. If configured but not yet connected, Junior activates it on demand."
7324
7286
  ).optional(),
7325
- max_results: z15.number().int().min(1).max(MAX_RESULTS).describe("Maximum matching tool descriptors to return.").optional()
7287
+ max_results: z14.number().int().min(1).max(MAX_RESULTS).describe("Maximum matching tool descriptors to return.").optional()
7326
7288
  }).strict(),
7327
7289
  outputSchema: searchMcpToolsOutputSchema,
7328
7290
  privateTraceResult: (result) => ({
@@ -7362,10 +7324,10 @@ function createSearchMcpToolsTool(mcpToolManager) {
7362
7324
  }
7363
7325
 
7364
7326
  // src/chat/tools/sandbox/view-image.ts
7365
- import { z as z16 } from "zod";
7327
+ import { z as z15 } from "zod";
7366
7328
  var MAX_VIEW_IMAGE_BYTES = 5 * 1024 * 1024;
7367
- var viewImageInputSchema = z16.object({
7368
- path: z16.string().min(1).describe("Path to an image file in the sandbox workspace.")
7329
+ var viewImageInputSchema = z15.object({
7330
+ path: z15.string().min(1).describe("Path to an image file in the sandbox workspace.")
7369
7331
  }).strict();
7370
7332
  function detectImageMimeType(data) {
7371
7333
  if (data.length >= 8 && data.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
@@ -7432,7 +7394,7 @@ function createViewImageTool(sandbox, supportsImageInput, deps = {}) {
7432
7394
  }
7433
7395
 
7434
7396
  // src/chat/tools/runtime/report-progress.ts
7435
- import { z as z17 } from "zod";
7397
+ import { z as z16 } from "zod";
7436
7398
  function createReportProgressTool() {
7437
7399
  return zodTool({
7438
7400
  annotations: {
@@ -7442,8 +7404,8 @@ function createReportProgressTool() {
7442
7404
  readOnlyHint: false
7443
7405
  },
7444
7406
  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').",
7445
- inputSchema: z17.object({
7446
- message: z17.string().min(1).describe("Short user-facing progress message.")
7407
+ inputSchema: z16.object({
7408
+ message: z16.string().min(1).describe("Short user-facing progress message.")
7447
7409
  }),
7448
7410
  outputSchema: juniorToolOutputSchema,
7449
7411
  execute: async () => ({})
@@ -7485,7 +7447,7 @@ function isSlackThreadConversationId(conversationId) {
7485
7447
  }
7486
7448
 
7487
7449
  // src/chat/tools/list-resource-event-subscriptions.ts
7488
- import { z as z19 } from "zod";
7450
+ import { z as z18 } from "zod";
7489
7451
 
7490
7452
  // src/chat/resource-events/store.ts
7491
7453
  import { createHash } from "crypto";
@@ -7493,29 +7455,29 @@ import {
7493
7455
  destinationSchema,
7494
7456
  resourceEventTypeSchema
7495
7457
  } from "@sentry/junior-plugin-api";
7496
- import { z as z18 } from "zod";
7458
+ import { z as z17 } from "zod";
7497
7459
  var RESOURCE_EVENT_PREFIX = "junior:resource_event_subscription:v3";
7498
7460
  var INDEX_LOCK_TTL_MS = 1e4;
7499
7461
  var SUBSCRIPTION_LOCK_TTL_MS = 1e4;
7500
7462
  var SUBSCRIPTION_LOCK_WAIT_MS = 1e4;
7501
7463
  var SUBSCRIPTION_LOCK_RETRY_MS = 25;
7502
7464
  var SUBSCRIPTION_LOCK_HEARTBEAT_MS = 3e3;
7503
- var subscriptionStatusSchema = z18.enum(["active", "cancelled", "completed"]);
7504
- var subscriptionIdIndexSchema = z18.array(z18.string().min(1));
7505
- var subscriptionSchema = z18.object({
7506
- conversationId: z18.string().min(1),
7507
- createdAtMs: z18.number().finite(),
7465
+ var subscriptionStatusSchema = z17.enum(["active", "cancelled", "completed"]);
7466
+ var subscriptionIdIndexSchema = z17.array(z17.string().min(1));
7467
+ var subscriptionSchema = z17.object({
7468
+ conversationId: z17.string().min(1),
7469
+ createdAtMs: z17.number().finite(),
7508
7470
  destination: destinationSchema,
7509
- events: z18.array(resourceEventTypeSchema).min(1),
7510
- expiresAtMs: z18.number().finite(),
7511
- id: z18.string().min(1),
7512
- intent: z18.string().min(1),
7513
- label: z18.string().min(1),
7514
- namespace: z18.string().min(1),
7515
- identifier: z18.string().min(1),
7516
- resourceType: z18.string().min(1),
7471
+ events: z17.array(resourceEventTypeSchema).min(1),
7472
+ expiresAtMs: z17.number().finite(),
7473
+ id: z17.string().min(1),
7474
+ intent: z17.string().min(1),
7475
+ label: z17.string().min(1),
7476
+ namespace: z17.string().min(1),
7477
+ identifier: z17.string().min(1),
7478
+ resourceType: z17.string().min(1),
7517
7479
  status: subscriptionStatusSchema,
7518
- updatedAtMs: z18.number().finite()
7480
+ updatedAtMs: z17.number().finite()
7519
7481
  }).strict();
7520
7482
  function digest(value) {
7521
7483
  return createHash("sha256").update(value).digest("hex").slice(0, 32);
@@ -7885,17 +7847,17 @@ async function deliverResourceEventSubscription(input) {
7885
7847
  }
7886
7848
 
7887
7849
  // src/chat/tools/list-resource-event-subscriptions.ts
7888
- var listedResourceWatchSchema = z19.object({
7889
- id: z19.string().min(1),
7890
- label: z19.string().min(1),
7891
- identifier: z19.string().min(1),
7892
- namespace: z19.string().min(1),
7893
- resourceType: z19.string().min(1),
7894
- events: z19.array(z19.string().min(1)).min(1),
7895
- intent: z19.string().min(1),
7896
- expiresAtMs: z19.number().finite()
7850
+ var listedResourceWatchSchema = z18.object({
7851
+ id: z18.string().min(1),
7852
+ label: z18.string().min(1),
7853
+ identifier: z18.string().min(1),
7854
+ namespace: z18.string().min(1),
7855
+ resourceType: z18.string().min(1),
7856
+ events: z18.array(z18.string().min(1)).min(1),
7857
+ intent: z18.string().min(1),
7858
+ expiresAtMs: z18.number().finite()
7897
7859
  }).strict();
7898
- var resultDataSchema = z19.object({ subscriptions: z19.array(listedResourceWatchSchema) }).strict();
7860
+ var resultDataSchema = z18.object({ subscriptions: z18.array(listedResourceWatchSchema) }).strict();
7899
7861
  var outputSchema = juniorToolOutputSchema.extend({
7900
7862
  ...resultDataSchema.shape
7901
7863
  }).strict();
@@ -7910,7 +7872,7 @@ function createListResourceEventSubscriptionsTool(context) {
7910
7872
  description: "List active resource event subscriptions for the current conversation.",
7911
7873
  exposure: "deferred",
7912
7874
  source: RESOURCE_WATCH_TOOL_SOURCE,
7913
- inputSchema: z19.object({}).strict(),
7875
+ inputSchema: z18.object({}).strict(),
7914
7876
  outputSchema,
7915
7877
  async execute() {
7916
7878
  const conversationId = requireResourceWatchConversation(context);
@@ -7937,72 +7899,20 @@ function createListResourceEventSubscriptionsTool(context) {
7937
7899
  }
7938
7900
 
7939
7901
  // src/chat/tools/search-resource-event-types.ts
7940
- import { z as z21 } from "zod";
7941
-
7942
- // src/chat/resource-events/catalog.ts
7943
- import {
7944
- normalizeResourceEventIdentifier
7945
- } from "@sentry/junior-plugin-api";
7946
- import { z as z20 } from "zod";
7947
- function enumSchema(values, unavailableMessage) {
7948
- if (values.length === 0) {
7949
- return z20.string().refine(() => false, unavailableMessage);
7950
- }
7951
- return z20.enum(values);
7952
- }
7953
- function eventNamespaceSchema(catalog) {
7954
- return enumSchema(
7955
- Object.keys(catalog).sort(),
7956
- "No resource event namespaces are enabled."
7957
- );
7958
- }
7959
- function registeredEventTypeSchema(catalog) {
7960
- return enumSchema(
7961
- [
7962
- ...new Set(
7963
- Object.values(catalog).flatMap(
7964
- (registration) => registration.resourceTypes.flatMap(
7965
- (resourceType) => resourceType.supportedEvents
7966
- )
7967
- )
7968
- )
7969
- ].sort(),
7970
- "No resource event types are enabled."
7971
- );
7972
- }
7973
- function registeredResourceTypeSchema(catalog) {
7974
- return enumSchema(
7975
- [
7976
- ...new Set(
7977
- Object.values(catalog).flatMap(
7978
- (registration) => registration.resourceTypes.map((resourceType) => resourceType.type)
7979
- )
7980
- )
7981
- ].sort(),
7982
- "No resource types are enabled."
7983
- );
7984
- }
7985
- function pluginSupportsEvent(catalog, namespace, resourceType, eventType) {
7986
- return catalog[namespace]?.resourceTypes.find((candidate) => candidate.type === resourceType)?.supportedEvents.includes(eventType) ?? false;
7987
- }
7988
- function normalizeEventIdentifier(catalog, namespace, identifier) {
7989
- return normalizeResourceEventIdentifier(catalog[namespace], identifier);
7990
- }
7991
-
7992
- // src/chat/tools/search-resource-event-types.ts
7902
+ import { z as z19 } from "zod";
7993
7903
  var DEFAULT_SEARCH_RESULTS = 10;
7994
7904
  var MAX_SEARCH_RESULTS = 20;
7995
- var searchedResourceTypeSchema = z21.object({
7996
- namespace: z21.string(),
7997
- type: z21.string(),
7998
- supportedEvents: z21.array(z21.string()),
7999
- suggestedEvents: z21.array(z21.string()).optional()
7905
+ var searchedResourceTypeSchema = z19.object({
7906
+ namespace: z19.string(),
7907
+ type: z19.string(),
7908
+ supportedEvents: z19.array(z19.string()),
7909
+ suggestedEvents: z19.array(z19.string()).optional()
8000
7910
  }).strict();
8001
7911
  var outputSchema2 = juniorToolOutputSchema.extend({
8002
- query: z21.string().nullable(),
8003
- namespace: z21.string().nullable(),
8004
- totalMatches: z21.number().int().nonnegative(),
8005
- resourceTypes: z21.array(searchedResourceTypeSchema)
7912
+ query: z19.string().nullable(),
7913
+ namespace: z19.string().nullable(),
7914
+ totalMatches: z19.number().int().nonnegative(),
7915
+ resourceTypes: z19.array(searchedResourceTypeSchema)
8006
7916
  }).strict();
8007
7917
  function normalizeSearchText(value) {
8008
7918
  return value.toLowerCase().replace(/[^a-z0-9_.-]+/g, " ").trim();
@@ -8028,12 +7938,12 @@ function createSearchResourceEventTypesTool(catalog) {
8028
7938
  readOnlyHint: true
8029
7939
  },
8030
7940
  description: "Search the resource event types currently enabled by plugins without creating anything. Use watchResourceEvents to receive temporary updates in the current Slack thread; use createEventTask to execute a durable instruction for matching events. When explaining results, preserve that distinction. This tool does not watch a resource, create a task, or enumerate concrete resources.",
8031
- inputSchema: z21.object({
8032
- query: z21.string().nullable().describe(
7941
+ inputSchema: z19.object({
7942
+ query: z19.string().nullable().describe(
8033
7943
  "Optional terms matching a namespace, resource type, or event name. Empty lists all enabled resource event types."
8034
7944
  ).optional(),
8035
7945
  namespace: eventNamespaceSchema(catalog).nullable().describe("Optional enabled plugin namespace to search within.").optional(),
8036
- maxResults: z21.number().int().min(1).max(MAX_SEARCH_RESULTS).nullable().describe("Maximum matching resource types to return.").optional()
7946
+ maxResults: z19.number().int().min(1).max(MAX_SEARCH_RESULTS).nullable().describe("Maximum matching resource types to return.").optional()
8037
7947
  }).strict(),
8038
7948
  outputSchema: outputSchema2,
8039
7949
  async execute({ query, namespace, maxResults }) {
@@ -8071,10 +7981,10 @@ function createSearchResourceEventTypesTool(catalog) {
8071
7981
  }
8072
7982
 
8073
7983
  // src/chat/tools/stop-watching-resources.ts
8074
- import { z as z22 } from "zod";
8075
- var resultDataSchema2 = z22.object({
8076
- watching_status: z22.literal("stopped"),
8077
- stoppedIds: z22.array(z22.string().min(1))
7984
+ import { z as z20 } from "zod";
7985
+ var resultDataSchema2 = z20.object({
7986
+ watching_status: z20.literal("stopped"),
7987
+ stoppedIds: z20.array(z20.string().min(1))
8078
7988
  }).strict();
8079
7989
  var outputSchema3 = juniorToolOutputSchema.extend({
8080
7990
  ...resultDataSchema2.shape
@@ -8090,7 +8000,7 @@ function createStopWatchingResourcesTool(context) {
8090
8000
  description: "Stop one resource watch in the current Slack thread by id. Omit id only when the user explicitly asks to stop every watch in this thread. Infer terse stop requests from context, inspect active watches when the target is unclear, and call this tool before confirming that watching stopped.",
8091
8001
  exposure: "deferred",
8092
8002
  source: RESOURCE_WATCH_TOOL_SOURCE,
8093
- inputSchema: z22.object({ id: z22.string().min(1).nullable().optional() }).strict(),
8003
+ inputSchema: z20.object({ id: z20.string().min(1).nullable().optional() }).strict(),
8094
8004
  outputSchema: outputSchema3,
8095
8005
  async execute({ id }) {
8096
8006
  const conversationId = requireResourceWatchConversation(context);
@@ -8125,26 +8035,26 @@ function createStopWatchingResourcesTool(context) {
8125
8035
  }
8126
8036
 
8127
8037
  // src/chat/tools/watch-resource-events.ts
8128
- import { z as z23 } from "zod";
8038
+ import { z as z21 } from "zod";
8129
8039
  var DEFAULT_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
8130
8040
  var MAX_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
8131
8041
  function inputSchema(catalog) {
8132
- return z23.object({
8133
- identifier: z23.string().trim().min(1).describe("Plugin-defined resource identifier."),
8042
+ return z21.object({
8043
+ identifier: z21.string().trim().min(1).describe("Plugin-defined resource identifier."),
8134
8044
  namespace: eventNamespaceSchema(catalog).describe(
8135
8045
  "Enabled plugin namespace for this resource."
8136
8046
  ),
8137
8047
  resourceType: registeredResourceTypeSchema(catalog).describe(
8138
8048
  "Plugin-defined resource type."
8139
8049
  ),
8140
- label: z23.string().trim().min(1).max(500).describe("Human-readable resource label."),
8141
- events: z23.array(registeredEventTypeSchema(catalog)).min(1).describe(
8050
+ label: z21.string().trim().min(1).max(500).describe("Human-readable resource label."),
8051
+ events: z21.array(registeredEventTypeSchema(catalog)).min(1).describe(
8142
8052
  "High-signal event names to deliver to this conversation when they occur."
8143
8053
  ),
8144
- intent: z23.string().trim().min(1).max(4e3).describe(
8054
+ intent: z21.string().trim().min(1).max(4e3).describe(
8145
8055
  "Concise reason this conversation wants these events, used when an event arrives."
8146
8056
  ),
8147
- ttlMs: z23.coerce.number().describe(
8057
+ ttlMs: z21.coerce.number().describe(
8148
8058
  "How long to keep the subscription active. Defaults to 14 days and must not exceed 30 days."
8149
8059
  ).optional()
8150
8060
  }).strict().superRefine((subscription, context) => {
@@ -8164,19 +8074,19 @@ function inputSchema(catalog) {
8164
8074
  });
8165
8075
  });
8166
8076
  }
8167
- var stopWatchingActionSchema = z23.object({
8168
- execution_tool: z23.literal("executeTool"),
8169
- execution_example: z23.object({
8170
- tool_name: z23.literal(STOP_WATCHING_TOOL_NAME),
8171
- arguments: z23.object({ id: z23.string().min(1) }).strict()
8077
+ var stopWatchingActionSchema = z21.object({
8078
+ execution_tool: z21.literal("executeTool"),
8079
+ execution_example: z21.object({
8080
+ tool_name: z21.literal(STOP_WATCHING_TOOL_NAME),
8081
+ arguments: z21.object({ id: z21.string().min(1) }).strict()
8172
8082
  }).strict()
8173
8083
  }).strict();
8174
- var resultDataSchema3 = z23.object({
8175
- id: z23.string().min(1),
8176
- subscription_status: z23.enum(["active", "cancelled", "completed"]),
8177
- identifier: z23.string().min(1),
8178
- events: z23.array(z23.string().min(1)).min(1),
8179
- expiresAtMs: z23.number().finite(),
8084
+ var resultDataSchema3 = z21.object({
8085
+ id: z21.string().min(1),
8086
+ subscription_status: z21.enum(["active", "cancelled", "completed"]),
8087
+ identifier: z21.string().min(1),
8088
+ events: z21.array(z21.string().min(1)).min(1),
8089
+ expiresAtMs: z21.number().finite(),
8180
8090
  stop_watching: stopWatchingActionSchema
8181
8091
  }).strict();
8182
8092
  var outputSchema4 = juniorToolOutputSchema.extend({
@@ -8281,195 +8191,7 @@ function createResourceEventTools(context, catalog) {
8281
8191
 
8282
8192
  // src/chat/tools/create-event-task.ts
8283
8193
  import { createHash as createHash2 } from "crypto";
8284
- import { z as z26 } from "zod";
8285
-
8286
- // src/chat/event-tasks/store.ts
8287
- import { and, asc, eq } from "drizzle-orm";
8288
-
8289
- // src/chat/event-tasks/types.ts
8290
- import {
8291
- destinationVisibilitySchema,
8292
- resourceEventTypeSchema as resourceEventTypeSchema2,
8293
- slackActorSchema,
8294
- slackDestinationSchema
8295
- } from "@sentry/junior-plugin-api";
8296
- import { z as z24 } from "zod";
8297
- var EVENT_TASK_IDENTIFIER_MAX_LENGTH = 300;
8298
- var eventTaskPrincipalSchema = z24.object({
8299
- slackUserId: slackActorSchema.shape.userId,
8300
- fullName: z24.string().optional(),
8301
- userName: z24.string().optional()
8302
- }).strict();
8303
- var eventTaskTriggerSchema = z24.object({
8304
- events: z24.array(resourceEventTypeSchema2).min(1),
8305
- label: z24.string().min(1),
8306
- namespace: z24.string().min(1),
8307
- identifier: z24.string().min(1).max(EVENT_TASK_IDENTIFIER_MAX_LENGTH),
8308
- resourceType: z24.string().min(1)
8309
- }).strict();
8310
- var eventTaskSchema = z24.object({
8311
- id: z24.string().min(1),
8312
- createdAtMs: z24.number().finite(),
8313
- createdBy: eventTaskPrincipalSchema,
8314
- credentialMode: z24.enum(["system", "creator"]),
8315
- destination: slackDestinationSchema,
8316
- destinationVisibility: destinationVisibilitySchema,
8317
- task: z24.object({ text: z24.string().min(1) }).strict(),
8318
- trigger: eventTaskTriggerSchema
8319
- }).strict();
8320
-
8321
- // src/chat/event-tasks/store.ts
8322
- function parseTask(value) {
8323
- return eventTaskSchema.parse(value);
8324
- }
8325
- async function getEventTask(db, id) {
8326
- const rows = await db.select({ task: juniorEventTasks.task }).from(juniorEventTasks).where(eq(juniorEventTasks.id, id)).limit(1);
8327
- return rows[0] ? parseTask(rows[0].task) : void 0;
8328
- }
8329
- async function createEventTask(db, task) {
8330
- const parsed = eventTaskSchema.parse(task);
8331
- await db.insert(juniorEventTasks).values({
8332
- id: parsed.id,
8333
- teamId: parsed.destination.teamId,
8334
- namespace: parsed.trigger.namespace,
8335
- identifier: parsed.trigger.identifier,
8336
- createdAtMs: parsed.createdAtMs,
8337
- task: parsed
8338
- }).onConflictDoNothing();
8339
- return await getEventTask(db, parsed.id) ?? parsed;
8340
- }
8341
- async function saveEventTask(db, task) {
8342
- const parsed = eventTaskSchema.parse(task);
8343
- const rows = await db.update(juniorEventTasks).set({
8344
- namespace: parsed.trigger.namespace,
8345
- identifier: parsed.trigger.identifier,
8346
- task: parsed
8347
- }).where(eq(juniorEventTasks.id, parsed.id)).returning({ task: juniorEventTasks.task });
8348
- return rows[0] ? parseTask(rows[0].task) : void 0;
8349
- }
8350
- async function deleteEventTask(db, id) {
8351
- const rows = await db.delete(juniorEventTasks).where(eq(juniorEventTasks.id, id)).returning({ task: juniorEventTasks.task });
8352
- return rows[0] ? parseTask(rows[0].task) : void 0;
8353
- }
8354
- async function listEventTasksForTeam(db, teamId) {
8355
- const rows = await db.select({ task: juniorEventTasks.task }).from(juniorEventTasks).where(eq(juniorEventTasks.teamId, teamId)).orderBy(asc(juniorEventTasks.createdAtMs), asc(juniorEventTasks.id));
8356
- return rows.map((row) => parseTask(row.task));
8357
- }
8358
- async function findMatchingEventTasks(db, event, teamId) {
8359
- const rows = await db.select({ task: juniorEventTasks.task }).from(juniorEventTasks).where(
8360
- and(
8361
- eq(juniorEventTasks.teamId, teamId),
8362
- eq(juniorEventTasks.namespace, event.namespace),
8363
- eq(juniorEventTasks.identifier, event.identifier)
8364
- )
8365
- ).orderBy(asc(juniorEventTasks.createdAtMs), asc(juniorEventTasks.id));
8366
- return rows.map((row) => parseTask(row.task)).filter((task) => task.trigger.events.includes(event.eventType));
8367
- }
8368
-
8369
- // src/chat/event-tasks/tool-support.ts
8370
- import { z as z25 } from "zod";
8371
- var compactEventTaskResultSchema = z25.object({
8372
- id: z25.string().min(1),
8373
- task: z25.string().min(1),
8374
- namespace: z25.string().min(1),
8375
- identifier: z25.string().min(1),
8376
- resourceType: z25.string().min(1),
8377
- label: z25.string().min(1),
8378
- events: z25.array(z25.string().min(1)).min(1),
8379
- credentialMode: z25.enum(["system", "creator"]),
8380
- createdBy: eventTaskPrincipalSchema,
8381
- triggerAvailable: z25.boolean()
8382
- }).strict();
8383
- var eventTaskToolResultSchema = juniorToolOutputSchema.extend({
8384
- task: compactEventTaskResultSchema
8385
- }).strict();
8386
- var eventTaskListToolResultSchema = juniorToolOutputSchema.extend({
8387
- tasks: z25.array(compactEventTaskResultSchema),
8388
- truncated: z25.boolean()
8389
- }).strict();
8390
- function registeredEventTaskTriggerSchema(catalog) {
8391
- return z25.object({
8392
- namespace: eventNamespaceSchema(catalog),
8393
- identifier: z25.string().trim().min(1).max(EVENT_TASK_IDENTIFIER_MAX_LENGTH),
8394
- resourceType: registeredResourceTypeSchema(catalog),
8395
- label: z25.string().trim().min(1).max(500),
8396
- events: z25.array(registeredEventTypeSchema(catalog)).min(1)
8397
- }).strict();
8398
- }
8399
- function requireSupportedEventTaskTrigger(catalog, trigger) {
8400
- for (const eventType of trigger.events) {
8401
- if (!pluginSupportsEvent(
8402
- catalog,
8403
- trigger.namespace,
8404
- trigger.resourceType,
8405
- eventType
8406
- )) {
8407
- throw new ToolInputError(
8408
- `Resource type "${trigger.namespace}:${trigger.resourceType}" does not support event "${eventType}".`
8409
- );
8410
- }
8411
- }
8412
- }
8413
- function requireEventTaskSlackContext(context) {
8414
- if (context.source.platform !== "slack" || context.destination.platform !== "slack" || context.actor?.platform !== "slack" || context.actor.teamId !== context.source.teamId) {
8415
- throw new ToolInputError(
8416
- "Event tasks require an active Slack channel or DM and actor."
8417
- );
8418
- }
8419
- return {
8420
- actor: context.actor,
8421
- destination: {
8422
- platform: "slack",
8423
- teamId: context.source.teamId,
8424
- channelId: context.source.channelId
8425
- },
8426
- source: context.source
8427
- };
8428
- }
8429
- function eventTaskMatchesDestination(task, destination) {
8430
- return task.destination.teamId === destination.teamId && task.destination.channelId === destination.channelId;
8431
- }
8432
- async function writableEventTask(context, id) {
8433
- const { destination } = requireEventTaskSlackContext(context);
8434
- const task = await getEventTask(getDb(), id);
8435
- if (!task || !eventTaskMatchesDestination(task, destination)) {
8436
- throw new ToolInputError(
8437
- "Event task was not found in this Slack channel or DM."
8438
- );
8439
- }
8440
- return task;
8441
- }
8442
- function triggerAvailable(task, catalog) {
8443
- const registration = catalog[task.trigger.namespace];
8444
- return Boolean(
8445
- registration && task.trigger.events.every(
8446
- (eventType) => registration.resourceTypes.some(
8447
- (resourceType) => resourceType.supportedEvents.includes(eventType)
8448
- )
8449
- )
8450
- );
8451
- }
8452
- function compactEventTask(task, catalog) {
8453
- return compactEventTaskResultSchema.parse({
8454
- id: task.id,
8455
- task: task.task.text,
8456
- namespace: task.trigger.namespace,
8457
- identifier: task.trigger.identifier,
8458
- resourceType: task.trigger.resourceType,
8459
- label: task.trigger.label,
8460
- events: task.trigger.events,
8461
- credentialMode: task.credentialMode,
8462
- createdBy: task.createdBy,
8463
- triggerAvailable: triggerAvailable(task, catalog)
8464
- });
8465
- }
8466
- function eventTaskSuccess(task, catalog) {
8467
- return {
8468
- task: compactEventTask(task, catalog)
8469
- };
8470
- }
8471
-
8472
- // src/chat/tools/create-event-task.ts
8194
+ import { z as z22 } from "zod";
8473
8195
  function buildEventTaskId(args) {
8474
8196
  const toolCallId = args.toolCallId?.trim();
8475
8197
  if (!toolCallId) {
@@ -8497,10 +8219,10 @@ function createEventTaskTool(context, catalog) {
8497
8219
  },
8498
8220
  executionMode: "sequential",
8499
8221
  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 remains configured for this Slack channel or DM until deleted and may use the creator's connected credentials. Prefer a subscribable tool result when available.",
8500
- inputSchema: z26.object({
8501
- task: z26.string().trim().min(1).max(4e3),
8222
+ inputSchema: z22.object({
8223
+ task: z22.string().trim().min(1).max(4e3),
8502
8224
  trigger,
8503
- credentialMode: z26.enum(["creator", "system"]).nullable().describe(
8225
+ credentialMode: z22.enum(["creator", "system"]).nullable().describe(
8504
8226
  "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."
8505
8227
  ).optional()
8506
8228
  }).strict(),
@@ -8561,7 +8283,7 @@ function createEventTaskTool(context, catalog) {
8561
8283
  }
8562
8284
 
8563
8285
  // src/chat/tools/delete-event-task.ts
8564
- import { z as z27 } from "zod";
8286
+ import { z as z23 } from "zod";
8565
8287
  function createDeleteEventTaskTool(context, catalog) {
8566
8288
  return zodTool({
8567
8289
  approvalMode: "review",
@@ -8573,7 +8295,7 @@ function createDeleteEventTaskTool(context, catalog) {
8573
8295
  },
8574
8296
  executionMode: "sequential",
8575
8297
  description: "Delete an event task from this Slack channel or DM, including a task created from another thread in the same destination.",
8576
- inputSchema: z27.object({ taskId: z27.string().min(1) }).strict(),
8298
+ inputSchema: z23.object({ taskId: z23.string().min(1) }).strict(),
8577
8299
  outputSchema: eventTaskToolResultSchema,
8578
8300
  async execute({ taskId }) {
8579
8301
  const current = await writableEventTask(context, taskId);
@@ -8589,7 +8311,7 @@ function createDeleteEventTaskTool(context, catalog) {
8589
8311
  }
8590
8312
 
8591
8313
  // src/chat/tools/list-event-tasks.ts
8592
- import { z as z28 } from "zod";
8314
+ import { z as z24 } from "zod";
8593
8315
  var MAX_LISTED_EVENT_TASKS = 50;
8594
8316
  function createListEventTasksTool(context, catalog) {
8595
8317
  return zodTool({
@@ -8600,7 +8322,7 @@ function createListEventTasksTool(context, catalog) {
8600
8322
  readOnlyHint: true
8601
8323
  },
8602
8324
  description: "List event tasks for this Slack channel or DM, including tasks created from other threads in the same destination. A false triggerAvailable value means the task remains stored but its plugin event is not currently enabled.",
8603
- inputSchema: z28.object({}).strict(),
8325
+ inputSchema: z24.object({}).strict(),
8604
8326
  outputSchema: eventTaskListToolResultSchema,
8605
8327
  async execute() {
8606
8328
  const { destination } = requireEventTaskSlackContext(context);
@@ -8615,7 +8337,7 @@ function createListEventTasksTool(context, catalog) {
8615
8337
  }
8616
8338
 
8617
8339
  // src/chat/tools/update-event-task.ts
8618
- import { z as z29 } from "zod";
8340
+ import { z as z25 } from "zod";
8619
8341
  function changesEventTaskTrigger(current, next) {
8620
8342
  const currentEvents = [...current.events].sort();
8621
8343
  const nextEvents = [...next.events].sort();
@@ -8632,11 +8354,11 @@ function createUpdateEventTaskTool(context, catalog) {
8632
8354
  },
8633
8355
  executionMode: "sequential",
8634
8356
  description: "Update the instruction, registered trigger, or credential use for an event task in this Slack channel or DM. Event tasks created from other threads in the same destination are manageable here.",
8635
- inputSchema: z29.object({
8636
- taskId: z29.string().min(1),
8637
- task: z29.string().trim().min(1).max(4e3).nullable().optional(),
8357
+ inputSchema: z25.object({
8358
+ taskId: z25.string().min(1),
8359
+ task: z25.string().trim().min(1).max(4e3).nullable().optional(),
8638
8360
  trigger: registeredEventTaskTriggerSchema(catalog).nullable().optional(),
8639
- credentialMode: z29.enum(["system", "creator"]).nullable().describe(
8361
+ credentialMode: z25.enum(["system", "creator"]).nullable().describe(
8640
8362
  "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."
8641
8363
  ).optional()
8642
8364
  }).strict(),
@@ -8709,45 +8431,834 @@ function createEventTaskTools(context, catalog) {
8709
8431
  };
8710
8432
  }
8711
8433
 
8712
- // src/chat/slack/channel.ts
8713
- async function listChannelMessages(input) {
8714
- const client = getSlackClient();
8715
- const channelId = input.channelId;
8716
- const targetLimit = Math.max(1, Math.min(input.limit, 1e3));
8717
- const maxPages = Math.max(1, Math.min(input.maxPages ?? 5, 10));
8718
- const messages = [];
8719
- let cursor = input.cursor;
8720
- let pages = 0;
8721
- while (messages.length < targetLimit && pages < maxPages) {
8722
- pages += 1;
8723
- const pageLimit = Math.max(1, Math.min(200, targetLimit - messages.length));
8724
- const response = await withSlackRetries(
8725
- () => client.conversations.history({
8726
- channel: channelId,
8727
- limit: pageLimit,
8728
- cursor,
8729
- oldest: input.oldest,
8730
- latest: input.latest,
8731
- inclusive: input.inclusive
8732
- }),
8733
- 3,
8734
- { action: "conversations.history" }
8735
- );
8736
- const batch = response.messages ?? [];
8737
- messages.push(...batch);
8738
- cursor = response.response_metadata?.next_cursor || void 0;
8739
- if (!cursor) {
8740
- break;
8741
- }
8434
+ // src/chat/scheduled-tasks/tools/create.ts
8435
+ import { z as z28 } from "zod";
8436
+
8437
+ // src/chat/scheduled-tasks/schedule-intent.ts
8438
+ import { z as z26 } from "zod";
8439
+ var localDateSchema = z26.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Use a local date in YYYY-MM-DD format.");
8440
+ var localTimeSchema = z26.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "Use local time in HH:MM format.");
8441
+ var timezoneSchema = z26.string().min(1).max(80).describe(
8442
+ "IANA timezone, for example America/Los_Angeles. Omit or use null for the scheduler default."
8443
+ ).nullable().optional();
8444
+ var weekdaySchema = z26.enum([
8445
+ "sunday",
8446
+ "monday",
8447
+ "tuesday",
8448
+ "wednesday",
8449
+ "thursday",
8450
+ "friday",
8451
+ "saturday"
8452
+ ]);
8453
+ var oneOffScheduleIntentSchema = z26.object({
8454
+ kind: z26.literal("one_off").describe("A schedule that runs once."),
8455
+ timezone: timezoneSchema,
8456
+ timing: z26.discriminatedUnion("type", [
8457
+ z26.object({
8458
+ type: z26.literal("after").describe("Run after a relative delay from the server clock."),
8459
+ value: z26.number().int().positive().max(1e5),
8460
+ unit: z26.enum(["second", "minute", "hour", "day", "week"])
8461
+ }).strict(),
8462
+ z26.object({
8463
+ type: z26.literal("at").describe("Run at an explicit local calendar date and time."),
8464
+ date: localDateSchema.describe(
8465
+ "Requested local calendar date in YYYY-MM-DD format."
8466
+ ),
8467
+ time: localTimeSchema.describe(
8468
+ "Requested local wall-clock time in HH:MM format."
8469
+ )
8470
+ }).strict()
8471
+ ]).describe("Relative delay or explicit local time for the one-off run.")
8472
+ }).strict();
8473
+ var recurringScheduleIntentSchema = z26.object({
8474
+ kind: z26.literal("recurring").describe("A repeating calendar schedule."),
8475
+ frequency: z26.enum(["daily", "weekly", "monthly", "yearly"]).describe("Recurring tasks can run at most once per day."),
8476
+ interval: z26.number().int().positive().max(365).describe("Repeat every N frequency units. Defaults to 1.").nullable().optional(),
8477
+ time: localTimeSchema.describe(
8478
+ "Local wall-clock time for each occurrence in HH:MM format."
8479
+ ),
8480
+ weekdays: z26.array(weekdaySchema).min(1).max(7).describe("Required for weekly schedules.").nullable().optional(),
8481
+ day_of_month: z26.number().int().min(1).max(31).describe("Required for monthly and yearly schedules.").nullable().optional(),
8482
+ month: z26.number().int().min(1).max(12).describe("Required for yearly schedules, where January is 1.").nullable().optional(),
8483
+ start_date: localDateSchema.describe(
8484
+ "Optional local calendar date that anchors the recurrence. Omit to start with the next matching occurrence."
8485
+ ).nullable().optional(),
8486
+ timezone: timezoneSchema
8487
+ }).strict().superRefine((schedule, context) => {
8488
+ if (schedule.frequency === "weekly" && schedule.weekdays == null) {
8489
+ context.addIssue({
8490
+ code: "custom",
8491
+ message: "Weekly schedules require weekdays.",
8492
+ path: ["weekdays"]
8493
+ });
8742
8494
  }
8743
- return {
8744
- messages: messages.slice(0, targetLimit),
8745
- nextCursor: cursor
8746
- };
8495
+ if ((schedule.frequency === "monthly" || schedule.frequency === "yearly") && schedule.day_of_month == null) {
8496
+ context.addIssue({
8497
+ code: "custom",
8498
+ message: `${schedule.frequency} schedules require day_of_month.`,
8499
+ path: ["day_of_month"]
8500
+ });
8501
+ }
8502
+ if (schedule.frequency === "yearly" && schedule.month == null) {
8503
+ context.addIssue({
8504
+ code: "custom",
8505
+ message: "Yearly schedules require month.",
8506
+ path: ["month"]
8507
+ });
8508
+ }
8509
+ if (schedule.frequency !== "weekly" && schedule.weekdays != null) {
8510
+ context.addIssue({
8511
+ code: "custom",
8512
+ message: "weekdays applies only to weekly schedules.",
8513
+ path: ["weekdays"]
8514
+ });
8515
+ }
8516
+ if (schedule.frequency !== "monthly" && schedule.frequency !== "yearly" && schedule.day_of_month != null) {
8517
+ context.addIssue({
8518
+ code: "custom",
8519
+ message: "day_of_month applies only to monthly or yearly schedules.",
8520
+ path: ["day_of_month"]
8521
+ });
8522
+ }
8523
+ if (schedule.frequency !== "yearly" && schedule.month != null) {
8524
+ context.addIssue({
8525
+ code: "custom",
8526
+ message: "month applies only to yearly schedules.",
8527
+ path: ["month"]
8528
+ });
8529
+ }
8530
+ });
8531
+ var scheduleIntentSchema = z26.union([
8532
+ oneOffScheduleIntentSchema,
8533
+ recurringScheduleIntentSchema
8534
+ ]);
8535
+ var WEEKDAY_INDEX = {
8536
+ sunday: 0,
8537
+ monday: 1,
8538
+ tuesday: 2,
8539
+ wednesday: 3,
8540
+ thursday: 4,
8541
+ friday: 5,
8542
+ saturday: 6
8543
+ };
8544
+ var DURATION_MS = {
8545
+ second: 1e3,
8546
+ minute: 60 * 1e3,
8547
+ hour: 60 * 60 * 1e3,
8548
+ day: 24 * 60 * 60 * 1e3,
8549
+ week: 7 * 24 * 60 * 60 * 1e3
8550
+ };
8551
+ function parseLocalTime(value) {
8552
+ const [hour, minute] = value.split(":").map(Number);
8553
+ return { hour, minute };
8747
8554
  }
8748
- async function listThreadReplies(input) {
8749
- const client = getSlackClient();
8750
- const channelId = input.channelId;
8555
+ function localDateAt(timestampMs, timezone) {
8556
+ const parts = getZonedDateTimeParts(timestampMs, timezone);
8557
+ return [parts.year, parts.month, parts.day].map(
8558
+ (value, index) => index === 0 ? String(value).padStart(4, "0") : String(value).padStart(2, "0")
8559
+ ).join("-");
8560
+ }
8561
+ function isValidTimeZone(timezone) {
8562
+ try {
8563
+ new Intl.DateTimeFormat("en-US", { timeZone: timezone }).format();
8564
+ return true;
8565
+ } catch {
8566
+ return false;
8567
+ }
8568
+ }
8569
+ function plural(value, unit) {
8570
+ return value === 1 ? unit : `${unit}s`;
8571
+ }
8572
+ function formatWeekdays(weekdays) {
8573
+ const labels = weekdays.map(
8574
+ (weekday) => `${weekday[0].toUpperCase()}${weekday.slice(1)}`
8575
+ );
8576
+ if (labels.length < 2) {
8577
+ return labels[0] ?? "";
8578
+ }
8579
+ return `${labels.slice(0, -1).join(", ")} and ${labels.at(-1)}`;
8580
+ }
8581
+ function recurringDescription(schedule, timezone) {
8582
+ const interval = schedule.interval ?? 1;
8583
+ const cadenceUnit = {
8584
+ daily: "day",
8585
+ weekly: "week",
8586
+ monthly: "month",
8587
+ yearly: "year"
8588
+ }[schedule.frequency];
8589
+ const cadence = interval === 1 ? cadenceUnit : `${interval} ${cadenceUnit}s`;
8590
+ let detail = "";
8591
+ if (schedule.frequency === "weekly") {
8592
+ detail = ` on ${formatWeekdays(schedule.weekdays)}`;
8593
+ } else if (schedule.frequency === "monthly") {
8594
+ detail = ` on day ${schedule.day_of_month}`;
8595
+ } else if (schedule.frequency === "yearly") {
8596
+ detail = ` on ${String(schedule.month).padStart(2, "0")}-${String(
8597
+ schedule.day_of_month
8598
+ ).padStart(2, "0")}`;
8599
+ }
8600
+ return `Every ${cadence}${detail} at ${schedule.time} (${timezone})`;
8601
+ }
8602
+ var ScheduleIntentError = class extends Error {
8603
+ };
8604
+ function compileScheduleIntent(args) {
8605
+ const timezone = args.intent.timezone ?? args.defaultTimezone;
8606
+ if (!isValidTimeZone(timezone)) {
8607
+ throw new ScheduleIntentError("timezone must be a valid IANA time zone.");
8608
+ }
8609
+ if (args.intent.kind === "one_off") {
8610
+ if (args.intent.timing.type === "after") {
8611
+ const nextRunAtMs3 = args.nowMs + args.intent.timing.value * DURATION_MS[args.intent.timing.unit];
8612
+ return {
8613
+ nextRunAtMs: nextRunAtMs3,
8614
+ schedule: {
8615
+ description: `In ${args.intent.timing.value} ${plural(
8616
+ args.intent.timing.value,
8617
+ args.intent.timing.unit
8618
+ )}`,
8619
+ kind: "one_off",
8620
+ timezone
8621
+ }
8622
+ };
8623
+ }
8624
+ const nextRunAtMs2 = resolveLocalScheduleAtMs({
8625
+ date: args.intent.timing.date,
8626
+ time: parseLocalTime(args.intent.timing.time),
8627
+ timezone
8628
+ });
8629
+ if (nextRunAtMs2 === void 0) {
8630
+ throw new ScheduleIntentError(
8631
+ "The requested local date or time does not exist in that timezone."
8632
+ );
8633
+ }
8634
+ if (nextRunAtMs2 <= args.nowMs) {
8635
+ throw new ScheduleIntentError(
8636
+ "The requested one-off schedule must be in the future."
8637
+ );
8638
+ }
8639
+ return {
8640
+ nextRunAtMs: nextRunAtMs2,
8641
+ schedule: {
8642
+ description: `Once on ${args.intent.timing.date} at ${args.intent.timing.time} (${timezone})`,
8643
+ kind: "one_off",
8644
+ timezone
8645
+ }
8646
+ };
8647
+ }
8648
+ const recurrence = {
8649
+ frequency: args.intent.frequency,
8650
+ interval: args.intent.interval ?? 1,
8651
+ startDate: args.intent.start_date ?? localDateAt(args.nowMs, timezone),
8652
+ time: parseLocalTime(args.intent.time),
8653
+ ...args.intent.frequency === "weekly" ? {
8654
+ weekdays: [
8655
+ ...new Set(
8656
+ args.intent.weekdays.map((weekday) => WEEKDAY_INDEX[weekday])
8657
+ )
8658
+ ].sort((left, right) => left - right)
8659
+ } : {},
8660
+ ...args.intent.frequency === "monthly" || args.intent.frequency === "yearly" ? { dayOfMonth: args.intent.day_of_month ?? void 0 } : {},
8661
+ ...args.intent.frequency === "yearly" ? { month: args.intent.month ?? void 0 } : {}
8662
+ };
8663
+ const searchRecurrence = args.intent.start_date ? recurrence : { ...recurrence, interval: 1 };
8664
+ const nextRunAtMs = getFirstRunAtMs({
8665
+ afterMs: args.nowMs,
8666
+ recurrence: searchRecurrence,
8667
+ timezone
8668
+ });
8669
+ if (nextRunAtMs === void 0) {
8670
+ throw new ScheduleIntentError(
8671
+ "The recurring schedule has no valid future occurrence."
8672
+ );
8673
+ }
8674
+ const materializedRecurrence = args.intent.start_date ? recurrence : { ...recurrence, startDate: localDateAt(nextRunAtMs, timezone) };
8675
+ return {
8676
+ nextRunAtMs,
8677
+ schedule: {
8678
+ description: recurringDescription(args.intent, timezone),
8679
+ kind: "recurring",
8680
+ recurrence: materializedRecurrence,
8681
+ timezone
8682
+ }
8683
+ };
8684
+ }
8685
+
8686
+ // src/chat/scheduled-tasks/tool-support.ts
8687
+ import { createHash as createHash3 } from "crypto";
8688
+ import {
8689
+ sourceSchema
8690
+ } from "@sentry/junior-plugin-api";
8691
+ import { z as z27 } from "zod";
8692
+
8693
+ // src/chat/scheduled-tasks/identity.ts
8694
+ var SLACK_USER_ID_PATTERN = /^[UW][A-Z0-9]{5,}$/;
8695
+ function clean(value) {
8696
+ const normalized = value?.trim();
8697
+ return normalized ? normalized : void 0;
8698
+ }
8699
+ function cleanSlackUserId(value) {
8700
+ const normalized = clean(value);
8701
+ return normalized && normalized.toLowerCase() !== "unknown" ? normalized : void 0;
8702
+ }
8703
+ function cleanDisplay(value, slackUserId) {
8704
+ const normalized = clean(value);
8705
+ if (!normalized || normalized.toLowerCase() === "unknown" || normalized === slackUserId) {
8706
+ return void 0;
8707
+ }
8708
+ return SLACK_USER_ID_PATTERN.test(normalized) ? void 0 : normalized;
8709
+ }
8710
+ function sanitizeScheduledTaskPrincipal(principal) {
8711
+ const slackUserId = cleanSlackUserId(principal.slackUserId);
8712
+ if (!slackUserId) {
8713
+ throw new Error("Scheduled task principal requires a Slack user id");
8714
+ }
8715
+ const fullName = cleanDisplay(principal.fullName, slackUserId);
8716
+ const userName = cleanDisplay(principal.userName, slackUserId);
8717
+ return {
8718
+ slackUserId,
8719
+ ...fullName ? { fullName } : {},
8720
+ ...userName ? { userName } : {}
8721
+ };
8722
+ }
8723
+
8724
+ // src/chat/scheduled-tasks/tool-support.ts
8725
+ var TASK_ID_PREFIX = "sched";
8726
+ var MAX_LISTED_TASKS = 50;
8727
+ var DEFAULT_SCHEDULE_TIMEZONE = "America/Los_Angeles";
8728
+ var compactTaskResultSchema = z27.object({
8729
+ id: z27.string(),
8730
+ status: z27.enum(["active", "paused", "blocked", "deleted"]),
8731
+ task: z27.string(),
8732
+ schedule: z27.string(),
8733
+ timezone: z27.string(),
8734
+ recurrence: z27.unknown().nullable(),
8735
+ next_run_at: z27.string().nullable(),
8736
+ conversation_access: z27.object({
8737
+ audience: z27.enum(["direct", "group", "channel"]),
8738
+ visibility: z27.enum(["private", "public"])
8739
+ }).strict(),
8740
+ credential_mode: z27.enum(["system", "creator"]),
8741
+ last_run_at: z27.string().nullable(),
8742
+ run_now_at: z27.string().nullable()
8743
+ }).strict();
8744
+ var scheduleTaskToolResultSchema = juniorToolOutputSchema.extend({
8745
+ target: z27.string(),
8746
+ task: compactTaskResultSchema
8747
+ }).strict();
8748
+ var scheduleListToolResultSchema = juniorToolOutputSchema.extend({
8749
+ target: z27.string(),
8750
+ tasks: z27.array(compactTaskResultSchema),
8751
+ truncated: z27.boolean()
8752
+ }).strict();
8753
+ function throwToolInputError(error) {
8754
+ throw new ToolInputError(error);
8755
+ }
8756
+ function requireActiveConversation(context) {
8757
+ const parsed = sourceSchema.safeParse(context.source);
8758
+ if (!parsed.success) {
8759
+ const source = context.source;
8760
+ const issues = parsed.error.issues;
8761
+ if (!source || source.platform !== "slack") {
8762
+ throwToolInputError("No active Slack conversation is available.");
8763
+ }
8764
+ if (issues.some((issue) => issue.code === "unrecognized_keys")) {
8765
+ throwToolInputError(
8766
+ "Active Slack conversation must not include unknown fields."
8767
+ );
8768
+ }
8769
+ if (issues.some((issue) => issue.path[0] === "channelId")) {
8770
+ throwToolInputError("Active Slack conversation channel is invalid.");
8771
+ }
8772
+ if (issues.some((issue) => issue.path[0] === "teamId")) {
8773
+ throwToolInputError("Active Slack conversation workspace is invalid.");
8774
+ }
8775
+ throwToolInputError("No active Slack conversation is available.");
8776
+ }
8777
+ if (parsed.data.platform !== "slack") {
8778
+ throwToolInputError("No active Slack conversation is available.");
8779
+ }
8780
+ return {
8781
+ platform: "slack",
8782
+ teamId: parsed.data.teamId,
8783
+ channelId: parsed.data.channelId
8784
+ };
8785
+ }
8786
+ function requireActor(context, destination) {
8787
+ if (context.actor?.platform !== "slack" || context.actor.teamId !== destination.teamId) {
8788
+ throwToolInputError("No active Slack actor context is available.");
8789
+ }
8790
+ const userId = context.actor?.userId?.trim();
8791
+ if (!userId || userId.toLowerCase() === "unknown") {
8792
+ throwToolInputError("No active Slack actor context is available.");
8793
+ }
8794
+ return sanitizeScheduledTaskPrincipal({
8795
+ slackUserId: userId,
8796
+ ...context.actor?.userName ? { userName: context.actor.userName } : {},
8797
+ ...context.actor?.fullName ? { fullName: context.actor.fullName } : {}
8798
+ });
8799
+ }
8800
+ function isDmChannel(channelId) {
8801
+ return channelId.startsWith("D");
8802
+ }
8803
+ function getConversationAccess(destination, source) {
8804
+ if (isDmChannel(destination.channelId)) {
8805
+ return { audience: "direct", visibility: "private" };
8806
+ }
8807
+ if (destination.channelId.startsWith("G")) {
8808
+ return { audience: "group", visibility: "private" };
8809
+ }
8810
+ return {
8811
+ audience: "channel",
8812
+ visibility: source?.visibility === "public" ? "public" : "private"
8813
+ };
8814
+ }
8815
+ function sameDestination(task, destination) {
8816
+ const taskDestination = task.destination;
8817
+ return taskDestination.platform === "slack" && taskDestination.teamId === destination.teamId && taskDestination.channelId === destination.channelId;
8818
+ }
8819
+ async function getWritableTask(args) {
8820
+ const destination = requireActiveConversation(args.context);
8821
+ const task = await schedulerStore(args.context).getTask(args.taskId);
8822
+ if (!task || task.status === "deleted") {
8823
+ throwToolInputError(
8824
+ "Scheduled task was not found in the active Slack conversation."
8825
+ );
8826
+ }
8827
+ if (!sameDestination(task, destination)) {
8828
+ throwToolInputError(
8829
+ "Scheduled task can only be managed from the Slack destination where it was created."
8830
+ );
8831
+ }
8832
+ return task;
8833
+ }
8834
+ function compactTask(task) {
8835
+ return compactTaskResultSchema.parse({
8836
+ id: task.id,
8837
+ status: task.status,
8838
+ task: task.task.text,
8839
+ schedule: task.schedule.description,
8840
+ timezone: task.schedule.timezone,
8841
+ recurrence: task.schedule.recurrence ? {
8842
+ frequency: task.schedule.recurrence.frequency,
8843
+ interval: task.schedule.recurrence.interval,
8844
+ start_date: task.schedule.recurrence.startDate,
8845
+ time: task.schedule.recurrence.time,
8846
+ weekdays: task.schedule.recurrence.weekdays,
8847
+ month: task.schedule.recurrence.month,
8848
+ day_of_month: task.schedule.recurrence.dayOfMonth
8849
+ } : null,
8850
+ next_run_at: task.nextRunAtMs ? new Date(task.nextRunAtMs).toISOString() : null,
8851
+ conversation_access: task.conversationAccess,
8852
+ credential_mode: task.credentialMode,
8853
+ last_run_at: task.lastRunAtMs ? new Date(task.lastRunAtMs).toISOString() : null,
8854
+ run_now_at: task.runNowAtMs ? new Date(task.runNowAtMs).toISOString() : null
8855
+ });
8856
+ }
8857
+ function scheduleTaskToolResult(target, task) {
8858
+ return {
8859
+ target,
8860
+ task
8861
+ };
8862
+ }
8863
+ function scheduleListToolResult(args) {
8864
+ return {
8865
+ target: args.target,
8866
+ tasks: args.tasks,
8867
+ truncated: args.truncated
8868
+ };
8869
+ }
8870
+ function buildTaskId(args) {
8871
+ const toolCallId = args.toolCallId?.trim();
8872
+ if (!toolCallId) {
8873
+ throw new Error("Scheduler task creation requires a tool-call identity.");
8874
+ }
8875
+ const digest2 = createHash3("sha256").update(
8876
+ JSON.stringify({
8877
+ actor: args.actor.slackUserId,
8878
+ channel: args.destination.channelId,
8879
+ operation: toolCallId,
8880
+ platform: args.destination.platform,
8881
+ team: args.destination.teamId
8882
+ })
8883
+ ).digest("hex").slice(0, 32);
8884
+ return `${TASK_ID_PREFIX}_${digest2}`;
8885
+ }
8886
+ function schedulerStore(context) {
8887
+ return context.store;
8888
+ }
8889
+ function normalizeStatus(value) {
8890
+ if (value === "active" || value === "paused" || value === "blocked") {
8891
+ return value;
8892
+ }
8893
+ return void 0;
8894
+ }
8895
+ function getDefaultScheduleTimezone() {
8896
+ return process.env.JUNIOR_TIMEZONE?.trim() || DEFAULT_SCHEDULE_TIMEZONE;
8897
+ }
8898
+
8899
+ // src/chat/scheduled-tasks/tools/create.ts
8900
+ function createSlackScheduleCreateTaskTool(context) {
8901
+ return zodTool({
8902
+ approvalMode: "review",
8903
+ annotations: {
8904
+ destructiveHint: false,
8905
+ idempotentHint: true,
8906
+ openWorldHint: true,
8907
+ readOnlyHint: false
8908
+ },
8909
+ 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.",
8910
+ executionMode: "sequential",
8911
+ inputSchema: z28.object({
8912
+ task: z28.string().min(1).max(4e3),
8913
+ schedule: scheduleIntentSchema.describe(
8914
+ "When the task runs. The scheduler computes the exact next run from this intent and the server clock."
8915
+ ),
8916
+ credential_mode: z28.enum(["creator", "system"]).nullable().describe(
8917
+ "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."
8918
+ ).optional()
8919
+ }).strict(),
8920
+ prepareArguments(args) {
8921
+ const input = args;
8922
+ if (input?.credential_mode !== "creator" && input?.credential_mode !== null) {
8923
+ return input;
8924
+ }
8925
+ const prepared = { ...input };
8926
+ delete prepared.credential_mode;
8927
+ return prepared;
8928
+ },
8929
+ outputSchema: scheduleTaskToolResultSchema,
8930
+ execute: async (input, options) => {
8931
+ const destination = requireActiveConversation(context);
8932
+ const actor = requireActor(context, destination);
8933
+ const store = schedulerStore(context);
8934
+ const id = buildTaskId({
8935
+ actor,
8936
+ destination,
8937
+ toolCallId: options.toolCallId
8938
+ });
8939
+ const existing = await store.getTask(id);
8940
+ if (existing) {
8941
+ if (!sameDestination(existing, destination) || existing.createdBy.slackUserId !== actor.slackUserId) {
8942
+ throwToolInputError("Scheduled task operation identity is invalid.");
8943
+ }
8944
+ return scheduleTaskToolResult(
8945
+ "slackScheduleCreateTask",
8946
+ compactTask(existing)
8947
+ );
8948
+ }
8949
+ const creator = await context.users.resolveActor();
8950
+ const identity = creator?.identity;
8951
+ if (!identity || identity.provider !== "slack" || identity.providerTenantId !== destination.teamId || identity.providerSubjectId !== actor.slackUserId) {
8952
+ throwToolInputError("Scheduled task creator identity is unavailable.");
8953
+ }
8954
+ const nowMs = context.now?.() ?? Date.now();
8955
+ let compiled;
8956
+ try {
8957
+ compiled = compileScheduleIntent({
8958
+ defaultTimezone: getDefaultScheduleTimezone(),
8959
+ intent: input.schedule,
8960
+ nowMs
8961
+ });
8962
+ } catch (error) {
8963
+ if (error instanceof ScheduleIntentError) {
8964
+ throwToolInputError(error.message);
8965
+ }
8966
+ throw error;
8967
+ }
8968
+ const conversationAccess = getConversationAccess(
8969
+ destination,
8970
+ context.source
8971
+ );
8972
+ const task = {
8973
+ id,
8974
+ createdAtMs: nowMs,
8975
+ updatedAtMs: nowMs,
8976
+ createdBy: actor,
8977
+ creatorIdentityId: identity.id,
8978
+ conversationAccess,
8979
+ credentialMode: input.credential_mode ?? "creator",
8980
+ destination,
8981
+ executionActor: SCHEDULED_TASK_SYSTEM_ACTOR,
8982
+ nextRunAtMs: compiled.nextRunAtMs,
8983
+ originalRequest: context.userText,
8984
+ schedule: compiled.schedule,
8985
+ status: "active",
8986
+ task: {
8987
+ text: input.task
8988
+ }
8989
+ };
8990
+ const committed = await store.createTask(task);
8991
+ if (!sameDestination(committed, destination) || committed.createdBy.slackUserId !== actor.slackUserId) {
8992
+ throwToolInputError("Scheduled task operation identity is invalid.");
8993
+ }
8994
+ return scheduleTaskToolResult(
8995
+ "slackScheduleCreateTask",
8996
+ compactTask(committed)
8997
+ );
8998
+ }
8999
+ });
9000
+ }
9001
+
9002
+ // src/chat/scheduled-tasks/tools/delete.ts
9003
+ import { z as z29 } from "zod";
9004
+ function createSlackScheduleDeleteTaskTool(context) {
9005
+ return zodTool({
9006
+ annotations: {
9007
+ destructiveHint: true,
9008
+ idempotentHint: true,
9009
+ openWorldHint: false,
9010
+ readOnlyHint: false
9011
+ },
9012
+ 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.",
9013
+ executionMode: "sequential",
9014
+ inputSchema: z29.object({
9015
+ task_id: z29.string().min(1).describe(
9016
+ "ID of the task to delete. Must be from this active Slack conversation."
9017
+ )
9018
+ }),
9019
+ outputSchema: scheduleTaskToolResultSchema,
9020
+ execute: async ({ task_id }) => {
9021
+ const lookup = await getWritableTask({ context, taskId: task_id });
9022
+ const next = {
9023
+ ...lookup,
9024
+ updatedAtMs: Date.now(),
9025
+ status: "deleted",
9026
+ nextRunAtMs: void 0,
9027
+ runNowAtMs: void 0
9028
+ };
9029
+ await schedulerStore(context).saveTask(next);
9030
+ return scheduleTaskToolResult(
9031
+ "slackScheduleDeleteTask",
9032
+ compactTask(next)
9033
+ );
9034
+ }
9035
+ });
9036
+ }
9037
+
9038
+ // src/chat/scheduled-tasks/tools/list.ts
9039
+ import { z as z30 } from "zod";
9040
+ function createSlackScheduleListTasksTool(context) {
9041
+ return zodTool({
9042
+ description: "List scheduled Junior tasks for the active Slack conversation. Use when the user asks what is scheduled here, or when task IDs are needed before editing, deleting, or running schedules. Only manages tasks for the active Slack DM or channel.",
9043
+ annotations: {
9044
+ destructiveHint: false,
9045
+ idempotentHint: true,
9046
+ openWorldHint: false,
9047
+ readOnlyHint: true
9048
+ },
9049
+ inputSchema: z30.object({}),
9050
+ outputSchema: scheduleListToolResultSchema,
9051
+ execute: async () => {
9052
+ const destination = requireActiveConversation(context);
9053
+ const tasks = await schedulerStore(context).listTasksForTeam(
9054
+ destination.teamId
9055
+ );
9056
+ const matching = tasks.filter(
9057
+ (task) => sameDestination(task, destination)
9058
+ );
9059
+ const visible = matching.slice(0, MAX_LISTED_TASKS).map(compactTask);
9060
+ return scheduleListToolResult({
9061
+ target: "slackScheduleListTasks",
9062
+ tasks: visible,
9063
+ truncated: matching.length > visible.length
9064
+ });
9065
+ }
9066
+ });
9067
+ }
9068
+
9069
+ // src/chat/scheduled-tasks/tools/run-now.ts
9070
+ import { z as z31 } from "zod";
9071
+ function createSlackScheduleRunTaskNowTool(context) {
9072
+ return zodTool({
9073
+ annotations: {
9074
+ destructiveHint: false,
9075
+ idempotentHint: false,
9076
+ openWorldHint: true,
9077
+ readOnlyHint: false
9078
+ },
9079
+ 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.",
9080
+ executionMode: "sequential",
9081
+ inputSchema: z31.object({
9082
+ task_id: z31.string().min(1).describe(
9083
+ "ID of the active task to run now. Must be from this active Slack conversation."
9084
+ )
9085
+ }),
9086
+ outputSchema: scheduleTaskToolResultSchema,
9087
+ execute: async ({ task_id }) => {
9088
+ const lookup = await getWritableTask({ context, taskId: task_id });
9089
+ if (lookup.status !== "active") {
9090
+ throwToolInputError(
9091
+ "Scheduled task must be active before it can be run now. Resume the task first if you want it to run."
9092
+ );
9093
+ }
9094
+ const nowMs = Date.now();
9095
+ const next = {
9096
+ ...lookup,
9097
+ updatedAtMs: nowMs,
9098
+ runNowAtMs: nowMs
9099
+ };
9100
+ await schedulerStore(context).saveTask(next);
9101
+ return scheduleTaskToolResult(
9102
+ "slackScheduleRunTaskNow",
9103
+ compactTask(next)
9104
+ );
9105
+ }
9106
+ });
9107
+ }
9108
+
9109
+ // src/chat/scheduled-tasks/tools/update.ts
9110
+ import { z as z32 } from "zod";
9111
+ function createSlackScheduleUpdateTaskTool(context) {
9112
+ return zodTool({
9113
+ approvalMode: "review",
9114
+ annotations: {
9115
+ destructiveHint: true,
9116
+ idempotentHint: true,
9117
+ openWorldHint: true,
9118
+ readOnlyHint: false
9119
+ },
9120
+ description: "Edit, pause, resume, reschedule, or change credential use for an existing Junior scheduled task in the active Slack conversation.",
9121
+ executionMode: "sequential",
9122
+ inputSchema: z32.object({
9123
+ task_id: z32.string().min(1).describe(
9124
+ "ID of the task to update. Must be from this active Slack conversation."
9125
+ ),
9126
+ task: z32.string().min(1).max(4e3).optional(),
9127
+ schedule: scheduleIntentSchema.describe(
9128
+ "Complete replacement schedule when rescheduling. Omit for task, status, or credential-only changes; the scheduler computes the next run."
9129
+ ).nullable().optional(),
9130
+ status: z32.enum(["active", "paused", "blocked"]).describe(
9131
+ "Set to active, paused, or blocked to resume, pause, or block the task."
9132
+ ).optional(),
9133
+ credential_mode: z32.enum(["system", "creator"]).nullable().describe(
9134
+ "Set creator to make the task's original creator credentials available, or system to disable them. Creator always means the task's created_by actor, never the current requester. Only that original creator may enable creator mode. Omit or use null to leave unchanged."
9135
+ ).optional()
9136
+ }).strict(),
9137
+ outputSchema: scheduleTaskToolResultSchema,
9138
+ execute: async (input) => {
9139
+ const lookup = await getWritableTask({
9140
+ context,
9141
+ taskId: input.task_id
9142
+ });
9143
+ const actor = requireActor(context, lookup.destination);
9144
+ const isCreator = actor.slackUserId === lookup.createdBy.slackUserId;
9145
+ if (input.credential_mode === "creator" && !isCreator) {
9146
+ throwToolInputError(
9147
+ "Only the scheduled task creator can enable creator credential use."
9148
+ );
9149
+ }
9150
+ const nowMs = context.now?.() ?? Date.now();
9151
+ let compiled;
9152
+ if (input.schedule) {
9153
+ try {
9154
+ compiled = compileScheduleIntent({
9155
+ defaultTimezone: lookup.schedule.timezone || getDefaultScheduleTimezone(),
9156
+ intent: input.schedule,
9157
+ nowMs
9158
+ });
9159
+ } catch (error) {
9160
+ if (error instanceof ScheduleIntentError) {
9161
+ throwToolInputError(error.message);
9162
+ }
9163
+ throw error;
9164
+ }
9165
+ }
9166
+ const nextRunAtMs = compiled?.nextRunAtMs ?? lookup.nextRunAtMs;
9167
+ const status = normalizeStatus(input.status);
9168
+ if (input.status && !status) {
9169
+ throwToolInputError("status must be active, paused, or blocked.");
9170
+ }
9171
+ if (status === "active" && !nextRunAtMs) {
9172
+ throwToolInputError(
9173
+ "Active scheduled tasks require a schedule with a future occurrence."
9174
+ );
9175
+ }
9176
+ const nextStatus = status ?? lookup.status;
9177
+ const credentialMode = input.task !== void 0 && input.task !== lookup.task.text && !isCreator ? "system" : input.credential_mode ?? lookup.credentialMode;
9178
+ const next = {
9179
+ ...lookup,
9180
+ credentialMode,
9181
+ updatedAtMs: nowMs,
9182
+ nextRunAtMs,
9183
+ runNowAtMs: nextStatus === "active" && !compiled ? lookup.runNowAtMs : void 0,
9184
+ status: nextStatus,
9185
+ statusReason: nextStatus === "blocked" ? lookup.statusReason : void 0,
9186
+ schedule: compiled?.schedule ?? lookup.schedule,
9187
+ task: input.task ? { text: input.task } : lookup.task
9188
+ };
9189
+ await schedulerStore(context).saveTask(next);
9190
+ return scheduleTaskToolResult(
9191
+ "slackScheduleUpdateTask",
9192
+ compactTask(next)
9193
+ );
9194
+ }
9195
+ });
9196
+ }
9197
+
9198
+ // src/chat/tools/scheduled-tasks.ts
9199
+ function scheduledTaskToolContext(context) {
9200
+ if (context.source.platform !== "slack" || context.destination.platform !== "slack" || context.actor?.platform !== "slack" || !context.resolveActorIdentity) {
9201
+ return void 0;
9202
+ }
9203
+ return {
9204
+ actor: context.actor,
9205
+ source: context.source,
9206
+ store: createSchedulerSqlStore(getDb()),
9207
+ users: { resolveActor: context.resolveActorIdentity },
9208
+ ...context.userText ? { userText: context.userText } : {}
9209
+ };
9210
+ }
9211
+ function createScheduledTaskTools(context) {
9212
+ const taskContext = scheduledTaskToolContext(context);
9213
+ if (!taskContext) return {};
9214
+ return {
9215
+ slackScheduleCreateTask: createSlackScheduleCreateTaskTool(taskContext),
9216
+ slackScheduleListTasks: createSlackScheduleListTasksTool(taskContext),
9217
+ slackScheduleUpdateTask: createSlackScheduleUpdateTaskTool(taskContext),
9218
+ slackScheduleDeleteTask: createSlackScheduleDeleteTaskTool(taskContext),
9219
+ slackScheduleRunTaskNow: createSlackScheduleRunTaskNowTool(taskContext)
9220
+ };
9221
+ }
9222
+
9223
+ // src/chat/slack/channel.ts
9224
+ async function listChannelMessages(input) {
9225
+ const client = getSlackClient();
9226
+ const channelId = input.channelId;
9227
+ const targetLimit = Math.max(1, Math.min(input.limit, 1e3));
9228
+ const maxPages = Math.max(1, Math.min(input.maxPages ?? 5, 10));
9229
+ const messages = [];
9230
+ let cursor = input.cursor;
9231
+ let pages = 0;
9232
+ while (messages.length < targetLimit && pages < maxPages) {
9233
+ pages += 1;
9234
+ const pageLimit = Math.max(1, Math.min(200, targetLimit - messages.length));
9235
+ const response = await withSlackRetries(
9236
+ () => client.conversations.history({
9237
+ channel: channelId,
9238
+ limit: pageLimit,
9239
+ cursor,
9240
+ oldest: input.oldest,
9241
+ latest: input.latest,
9242
+ inclusive: input.inclusive
9243
+ }),
9244
+ 3,
9245
+ { action: "conversations.history" }
9246
+ );
9247
+ const batch = response.messages ?? [];
9248
+ messages.push(...batch);
9249
+ cursor = response.response_metadata?.next_cursor || void 0;
9250
+ if (!cursor) {
9251
+ break;
9252
+ }
9253
+ }
9254
+ return {
9255
+ messages: messages.slice(0, targetLimit),
9256
+ nextCursor: cursor
9257
+ };
9258
+ }
9259
+ async function listThreadReplies(input) {
9260
+ const client = getSlackClient();
9261
+ const channelId = input.channelId;
8751
9262
  const targetLimit = Math.max(1, Math.min(input.limit ?? 1e3, 1e3));
8752
9263
  const maxPages = Math.max(1, Math.min(input.maxPages ?? 10, 10));
8753
9264
  const pendingTargets = new Set(
@@ -8788,11 +9299,11 @@ async function listThreadReplies(input) {
8788
9299
  }
8789
9300
 
8790
9301
  // src/chat/slack/timestamp-param.ts
8791
- import { z as z30 } from "zod";
9302
+ import { z as z33 } from "zod";
8792
9303
  function slackTimestampParam(description) {
8793
- return z30.preprocess(
9304
+ return z33.preprocess(
8794
9305
  (value) => typeof value === "number" && Number.isFinite(value) ? String(value) : value,
8795
- z30.string().min(1)
9306
+ z33.string().min(1)
8796
9307
  ).describe(description);
8797
9308
  }
8798
9309
  function optionalSlackTimestampParam(description) {
@@ -8823,10 +9334,10 @@ function parseRequiredSlackTimestampParam(field, value) {
8823
9334
  }
8824
9335
 
8825
9336
  // src/chat/slack/tools/channel-list-messages.ts
8826
- import { z as z31 } from "zod";
8827
- var booleanInput2 = (description) => z31.preprocess(
9337
+ import { z as z34 } from "zod";
9338
+ var booleanInput2 = (description) => z34.preprocess(
8828
9339
  (value) => value === "true" ? true : value === "false" ? false : value,
8829
- z31.boolean()
9340
+ z34.boolean()
8830
9341
  ).describe(description);
8831
9342
  function normalizeRangeTimestamp(field, value, targetChannelId) {
8832
9343
  if (value === void 0) {
@@ -8858,9 +9369,9 @@ function createSlackChannelListMessagesTool(context) {
8858
9369
  openWorldHint: true,
8859
9370
  readOnlyHint: true
8860
9371
  },
8861
- inputSchema: z31.object({
8862
- limit: z31.coerce.number().int().min(1).max(1e3).describe("Maximum number of messages to return across pages.").optional(),
8863
- cursor: z31.string().min(1).describe("Optional cursor to continue from a prior call.").optional(),
9372
+ inputSchema: z34.object({
9373
+ limit: z34.coerce.number().int().min(1).max(1e3).describe("Maximum number of messages to return across pages.").optional(),
9374
+ cursor: z34.string().min(1).describe("Optional cursor to continue from a prior call.").optional(),
8864
9375
  oldest: optionalSlackTimestampParam(
8865
9376
  "Optional oldest message timestamp (Slack ts) for range filtering."
8866
9377
  ),
@@ -8870,7 +9381,7 @@ function createSlackChannelListMessagesTool(context) {
8870
9381
  inclusive: booleanInput2(
8871
9382
  "Whether oldest/latest bounds should be inclusive."
8872
9383
  ).optional(),
8873
- max_pages: z31.coerce.number().int().min(1).max(10).describe("Maximum number of API pages to traverse in a single call.").optional()
9384
+ max_pages: z34.coerce.number().int().min(1).max(10).describe("Maximum number of API pages to traverse in a single call.").optional()
8874
9385
  }),
8875
9386
  outputSchema: juniorToolOutputSchema,
8876
9387
  execute: async ({
@@ -8933,20 +9444,20 @@ function createSlackChannelListMessagesTool(context) {
8933
9444
  }
8934
9445
 
8935
9446
  // src/chat/slack/tools/conversation-search.ts
8936
- import { z as z32 } from "zod";
9447
+ import { z as z35 } from "zod";
8937
9448
  var DEFAULT_LIMIT = 5;
8938
9449
  var conversationSearchOutputSchema = juniorToolOutputSchema.extend({
8939
- query: z32.string(),
8940
- count: z32.number().int().nonnegative(),
8941
- threads: z32.array(
8942
- z32.object({
8943
- conversation_id: z32.string().min(1),
8944
- thread_ts: z32.string().min(1),
8945
- message_id: z32.string().min(1),
8946
- message_role: z32.enum(["assistant", "user"]),
8947
- message_timestamp: z32.string().datetime(),
8948
- excerpt: z32.string(),
8949
- permalink: z32.string().url().optional()
9450
+ query: z35.string(),
9451
+ count: z35.number().int().nonnegative(),
9452
+ threads: z35.array(
9453
+ z35.object({
9454
+ conversation_id: z35.string().min(1),
9455
+ thread_ts: z35.string().min(1),
9456
+ message_id: z35.string().min(1),
9457
+ message_role: z35.enum(["assistant", "user"]),
9458
+ message_timestamp: z35.string().datetime(),
9459
+ excerpt: z35.string(),
9460
+ permalink: z35.string().url().optional()
8950
9461
  }).strict()
8951
9462
  )
8952
9463
  });
@@ -8964,9 +9475,9 @@ function createSlackConversationSearchTool(scope, currentConversationId, deps =
8964
9475
  openWorldHint: false,
8965
9476
  readOnlyHint: true
8966
9477
  },
8967
- inputSchema: z32.object({
8968
- query: z32.string().trim().min(1).max(200).describe("Words or a short phrase to find in prior conversations."),
8969
- limit: z32.number().int().min(1).max(10).describe("Maximum number of prior conversation threads to return.").nullable().optional()
9478
+ inputSchema: z35.object({
9479
+ query: z35.string().trim().min(1).max(200).describe("Words or a short phrase to find in prior conversations."),
9480
+ limit: z35.number().int().min(1).max(10).describe("Maximum number of prior conversation threads to return.").nullable().optional()
8970
9481
  }),
8971
9482
  outputSchema: conversationSearchOutputSchema,
8972
9483
  execute: async ({ query, limit }) => {
@@ -9011,27 +9522,27 @@ function createSlackConversationSearchTool(scope, currentConversationId, deps =
9011
9522
  }
9012
9523
 
9013
9524
  // src/chat/slack/tools/public-search.ts
9014
- import { z as z33 } from "zod";
9525
+ import { z as z36 } from "zod";
9015
9526
  var DEFAULT_LIMIT2 = 10;
9016
- var optionalTimestampSchema = z33.preprocess(
9527
+ var optionalTimestampSchema = z36.preprocess(
9017
9528
  (value) => typeof value === "string" && value.trim() === "" ? void 0 : value,
9018
- z33.coerce.number().int().nonnegative().describe("Optional Unix timestamp bound.").optional()
9529
+ z36.coerce.number().int().nonnegative().describe("Optional Unix timestamp bound.").optional()
9019
9530
  );
9020
- var searchMessageSchema = z33.object({
9021
- author_name: z33.string().optional(),
9022
- author_user_id: z33.string().optional(),
9023
- channel_id: z33.string().min(1),
9024
- channel_name: z33.string().optional(),
9025
- message_ts: z33.string().min(1),
9026
- content: z33.string(),
9027
- is_author_bot: z33.boolean().optional(),
9028
- permalink: z33.string().url()
9531
+ var searchMessageSchema = z36.object({
9532
+ author_name: z36.string().optional(),
9533
+ author_user_id: z36.string().optional(),
9534
+ channel_id: z36.string().min(1),
9535
+ channel_name: z36.string().optional(),
9536
+ message_ts: z36.string().min(1),
9537
+ content: z36.string(),
9538
+ is_author_bot: z36.boolean().optional(),
9539
+ permalink: z36.string().url()
9029
9540
  });
9030
9541
  var publicSearchOutputSchema = juniorToolOutputSchema.extend({
9031
- query: z33.string(),
9032
- count: z33.number().int().nonnegative(),
9033
- messages: z33.array(searchMessageSchema),
9034
- next_cursor: z33.string().optional()
9542
+ query: z36.string(),
9543
+ count: z36.number().int().nonnegative(),
9544
+ messages: z36.array(searchMessageSchema),
9545
+ next_cursor: z36.string().optional()
9035
9546
  });
9036
9547
  function normalizeMessage(value) {
9037
9548
  const parsed = searchMessageSchema.safeParse(value);
@@ -9058,8 +9569,8 @@ function createSlackPublicSearchTool(actionToken) {
9058
9569
  openWorldHint: true,
9059
9570
  readOnlyHint: true
9060
9571
  },
9061
- inputSchema: z33.object({
9062
- query: z33.string().trim().min(1).max(500).describe(
9572
+ inputSchema: z36.object({
9573
+ query: z36.string().trim().min(1).max(500).describe(
9063
9574
  "A focused Slack search query, including Slack search filters when useful."
9064
9575
  ),
9065
9576
  after: optionalTimestampSchema.describe(
@@ -9068,10 +9579,10 @@ function createSlackPublicSearchTool(actionToken) {
9068
9579
  before: optionalTimestampSchema.describe(
9069
9580
  "Optional Unix timestamp upper bound."
9070
9581
  ),
9071
- cursor: z33.string().min(1).describe("Cursor for the next result page.").optional(),
9072
- limit: z33.coerce.number().int().min(1).max(20).describe("Maximum results to return; Slack allows at most 20.").optional(),
9073
- sort: z33.enum(["score", "timestamp"]).describe("Rank by relevance or timestamp.").optional(),
9074
- sort_dir: z33.enum(["asc", "desc"]).describe("Sort direction.").optional()
9582
+ cursor: z36.string().min(1).describe("Cursor for the next result page.").optional(),
9583
+ limit: z36.coerce.number().int().min(1).max(20).describe("Maximum results to return; Slack allows at most 20.").optional(),
9584
+ sort: z36.enum(["score", "timestamp"]).describe("Rank by relevance or timestamp.").optional(),
9585
+ sort_dir: z36.enum(["asc", "desc"]).describe("Sort direction.").optional()
9075
9586
  }),
9076
9587
  outputSchema: publicSearchOutputSchema,
9077
9588
  execute: async ({
@@ -9128,7 +9639,7 @@ function createSlackPublicSearchTool(actionToken) {
9128
9639
  }
9129
9640
 
9130
9641
  // src/chat/slack/tools/message-add-reaction.ts
9131
- import { z as z34 } from "zod";
9642
+ import { z as z37 } from "zod";
9132
9643
 
9133
9644
  // src/chat/tools/idempotency.ts
9134
9645
  function stableSerialize(value) {
@@ -9158,8 +9669,8 @@ function createSlackMessageAddReactionTool(context, state) {
9158
9669
  readOnlyHint: false
9159
9670
  },
9160
9671
  description: "Add an emoji reaction to the current inbound Slack message. Use when the user asks for a reaction on the current message without another target. Provide a Slack emoji alias name (for example `thumbsup`, `white_check_mark`, or `thumbsup::skin-tone-6`), not a unicode emoji glyph. The target message is injected by runtime context; do not use this for arbitrary historical messages.",
9161
- inputSchema: z34.object({
9162
- emoji: z34.string().min(1).max(64).describe(
9672
+ inputSchema: z37.object({
9673
+ emoji: z37.string().min(1).max(64).describe(
9163
9674
  "Slack emoji alias name to react with (for example `thumbsup`, `white_check_mark`, or `thumbsup::skin-tone-6`). Optional surrounding colons are allowed."
9164
9675
  )
9165
9676
  }),
@@ -9207,15 +9718,15 @@ function createSlackMessageAddReactionTool(context, state) {
9207
9718
  }
9208
9719
 
9209
9720
  // src/chat/slack/tools/send-files.ts
9210
- import { createHash as createHash3 } from "crypto";
9211
- import { z as z35 } from "zod";
9721
+ import { createHash as createHash4 } from "crypto";
9722
+ import { z as z38 } from "zod";
9212
9723
  var sendFilesResultSchema = juniorToolOutputSchema.extend({
9213
- target: z35.string().min(1),
9214
- channel_id: z35.string().min(1),
9215
- deduplicated: z35.boolean().optional(),
9216
- file_count: z35.number().int().nonnegative(),
9217
- file_ids: z35.array(z35.string().min(1)).optional(),
9218
- thread_ts: z35.string().min(1)
9724
+ target: z38.string().min(1),
9725
+ channel_id: z38.string().min(1),
9726
+ deduplicated: z38.boolean().optional(),
9727
+ file_count: z38.number().int().nonnegative(),
9728
+ file_ids: z38.array(z38.string().min(1)).optional(),
9729
+ thread_ts: z38.string().min(1)
9219
9730
  });
9220
9731
  function normalizeFiles(files) {
9221
9732
  return files.map((file) => ({
@@ -9225,7 +9736,7 @@ function normalizeFiles(files) {
9225
9736
  }));
9226
9737
  }
9227
9738
  function fileContentDigest(data) {
9228
- return createHash3("sha256").update(data).digest("hex");
9739
+ return createHash4("sha256").update(data).digest("hex");
9229
9740
  }
9230
9741
  function fileOperationInput(files) {
9231
9742
  return files.map((file) => ({
@@ -9245,8 +9756,8 @@ function createSendFilesTool(context, state, materializeFile) {
9245
9756
  readOnlyHint: false
9246
9757
  },
9247
9758
  description: "Send one or more sandbox files into the active Slack conversation. Use when the user asks to attach, send, or share files here, in this conversation, or in this thread. Do not use for ordinary assistant text, top-level channel posts, other named channels, inline @mentions, or pinging mentioned users.",
9248
- inputSchema: z35.object({
9249
- files: z35.array(sandboxFileReferenceSchema).min(1).describe(
9759
+ inputSchema: z38.object({
9760
+ files: z38.array(sandboxFileReferenceSchema).min(1).describe(
9250
9761
  "One or more existing sandbox files. Objects returned by imageGenerate or webFetch can be passed unchanged."
9251
9762
  )
9252
9763
  }),
@@ -9678,7 +10189,7 @@ function storedCanvasUrl(state, canvasId) {
9678
10189
  }
9679
10190
 
9680
10191
  // src/chat/slack/tools/canvas/create.ts
9681
- import { z as z36 } from "zod";
10192
+ import { z as z39 } from "zod";
9682
10193
  function createSlackCanvasCreateTool(context, state) {
9683
10194
  return zodTool({
9684
10195
  annotations: {
@@ -9688,9 +10199,9 @@ function createSlackCanvasCreateTool(context, state) {
9688
10199
  readOnlyHint: false
9689
10200
  },
9690
10201
  description: "Create a Slack canvas for long-form output in the active assistant context channel. Use when the answer is better as a reusable document than a thread reply: long-form research, timelines, bios/profiles, structured notes, plans, comparisons, or anything likely to exceed one compact Slack reply. After creating it, reply with one or two short sentences plus the canvas link; do not recap the canvas contents. Do not use for short answers that fit cleanly in one normal thread reply.",
9691
- inputSchema: z36.object({
9692
- title: z36.string().min(1).max(160).describe("Canvas title."),
9693
- markdown: z36.string().min(1).describe("Canvas markdown body content.")
10202
+ inputSchema: z39.object({
10203
+ title: z39.string().min(1).max(160).describe("Canvas title."),
10204
+ markdown: z39.string().min(1).describe("Canvas markdown body content.")
9694
10205
  }),
9695
10206
  outputSchema: juniorToolOutputSchema,
9696
10207
  execute: async ({ title, markdown }) => {
@@ -9746,26 +10257,26 @@ function createSlackCanvasCreateTool(context, state) {
9746
10257
  }
9747
10258
 
9748
10259
  // src/chat/slack/tools/canvas/edit.ts
9749
- import { z as z37 } from "zod";
10260
+ import { z as z40 } from "zod";
9750
10261
  function prepareCanvasEditArguments(input) {
9751
10262
  return prepareTextReplacementArguments(input);
9752
10263
  }
9753
- var editReplacementSchema2 = z37.object({
9754
- oldText: z37.string().min(1).describe(
10264
+ var editReplacementSchema2 = z40.object({
10265
+ oldText: z40.string().min(1).describe(
9755
10266
  "Exact Canvas markdown to replace. It must be unique in the current Canvas body and must not overlap another edit."
9756
10267
  ),
9757
- newText: z37.string().describe("Replacement Canvas markdown for this edit.")
10268
+ newText: z40.string().describe("Replacement Canvas markdown for this edit.")
9758
10269
  });
9759
10270
  var slackCanvasEditOutputSchema = juniorToolOutputSchema.extend({
9760
- canvas_id: z37.string().optional(),
9761
- title: z37.string().optional(),
9762
- permalink: z37.string().optional(),
9763
- diff: z37.string().optional(),
9764
- first_changed_line: z37.number().int().positive().optional(),
9765
- replacements: z37.number().int().nonnegative().optional(),
9766
- normalized_heading_count: z37.number().int().nonnegative().optional(),
9767
- summary: z37.string().optional(),
9768
- deduplicated: z37.boolean().optional()
10271
+ canvas_id: z40.string().optional(),
10272
+ title: z40.string().optional(),
10273
+ permalink: z40.string().optional(),
10274
+ diff: z40.string().optional(),
10275
+ first_changed_line: z40.number().int().positive().optional(),
10276
+ replacements: z40.number().int().nonnegative().optional(),
10277
+ normalized_heading_count: z40.number().int().nonnegative().optional(),
10278
+ summary: z40.string().optional(),
10279
+ deduplicated: z40.boolean().optional()
9769
10280
  }).strict();
9770
10281
  function createSlackCanvasEditTool(state) {
9771
10282
  return zodTool({
@@ -9778,9 +10289,9 @@ function createSlackCanvasEditTool(state) {
9778
10289
  description: "Edit one Slack canvas with exact markdown replacements. Use for precise changes to existing Canvas content; prefer this over slackCanvasWrite for targeted changes. Each oldText must match exactly, be unique, and not overlap another edit. Returns a diff. Multiple changes to the same canvas: use one edits[] call.",
9779
10290
  prepareArguments: prepareCanvasEditArguments,
9780
10291
  executionMode: "sequential",
9781
- inputSchema: z37.object({
9782
- canvas: z37.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
9783
- edits: z37.array(editReplacementSchema2).min(1).describe(
10292
+ inputSchema: z40.object({
10293
+ canvas: z40.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
10294
+ edits: z40.array(editReplacementSchema2).min(1).describe(
9784
10295
  "Exact replacements matched against the current Canvas body, not incrementally."
9785
10296
  )
9786
10297
  }),
@@ -9837,18 +10348,18 @@ function createSlackCanvasEditTool(state) {
9837
10348
  }
9838
10349
 
9839
10350
  // src/chat/slack/tools/canvas/read.ts
9840
- import { z as z38 } from "zod";
10351
+ import { z as z41 } from "zod";
9841
10352
  var slackCanvasReadOutputSchema = juniorToolOutputSchema.extend({
9842
- canvas_id: z38.string().optional(),
9843
- title: z38.string().optional(),
9844
- permalink: z38.string().optional(),
9845
- mimetype: z38.string().optional(),
9846
- filetype: z38.string().optional(),
9847
- original_byte_length: z38.number().int().nonnegative().optional(),
9848
- content: z38.string().optional(),
9849
- start_line: z38.number().int().positive().optional(),
9850
- end_line: z38.number().int().nonnegative().optional(),
9851
- total_lines: z38.number().int().nonnegative().optional()
10353
+ canvas_id: z41.string().optional(),
10354
+ title: z41.string().optional(),
10355
+ permalink: z41.string().optional(),
10356
+ mimetype: z41.string().optional(),
10357
+ filetype: z41.string().optional(),
10358
+ original_byte_length: z41.number().int().nonnegative().optional(),
10359
+ content: z41.string().optional(),
10360
+ start_line: z41.number().int().positive().optional(),
10361
+ end_line: z41.number().int().nonnegative().optional(),
10362
+ total_lines: z41.number().int().nonnegative().optional()
9852
10363
  }).strict();
9853
10364
  function createSlackCanvasReadTool() {
9854
10365
  return zodTool({
@@ -9859,12 +10370,12 @@ function createSlackCanvasReadTool() {
9859
10370
  openWorldHint: true,
9860
10371
  readOnlyHint: true
9861
10372
  },
9862
- inputSchema: z38.object({
9863
- canvas: z38.string().min(1).describe(
10373
+ inputSchema: z41.object({
10374
+ canvas: z41.string().min(1).describe(
9864
10375
  "Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL (e.g. `https://team.slack.com/docs/T.../F...`)."
9865
10376
  ),
9866
- offset: z38.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
9867
- limit: z38.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
10377
+ offset: z41.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
10378
+ limit: z41.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
9868
10379
  }),
9869
10380
  outputSchema: slackCanvasReadOutputSchema,
9870
10381
  execute: async ({ canvas, offset, limit }) => {
@@ -9900,7 +10411,7 @@ function createSlackCanvasReadTool() {
9900
10411
  }
9901
10412
 
9902
10413
  // src/chat/slack/tools/canvas/write.ts
9903
- import { z as z39 } from "zod";
10414
+ import { z as z42 } from "zod";
9904
10415
  function createSlackCanvasWriteTool(state) {
9905
10416
  return zodTool({
9906
10417
  annotations: {
@@ -9911,9 +10422,9 @@ function createSlackCanvasWriteTool(state) {
9911
10422
  },
9912
10423
  description: "Write UTF-8 markdown content to a Slack canvas. Use for deliberate full-Canvas replacement after validation; use slackCanvasEdit for targeted changes to existing canvas content.",
9913
10424
  executionMode: "sequential",
9914
- inputSchema: z39.object({
9915
- canvas: z39.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
9916
- content: z39.string().describe("UTF-8 markdown content to write.")
10425
+ inputSchema: z42.object({
10426
+ canvas: z42.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
10427
+ content: z42.string().describe("UTF-8 markdown content to write.")
9917
10428
  }),
9918
10429
  outputSchema: juniorToolOutputSchema,
9919
10430
  execute: async ({ canvas, content }) => {
@@ -10128,12 +10639,12 @@ async function updateListItem(input) {
10128
10639
  }
10129
10640
 
10130
10641
  // src/chat/slack/id-param.ts
10131
- import { z as z40 } from "zod";
10642
+ import { z as z43 } from "zod";
10132
10643
  function slackChannelIdParam(description) {
10133
- return z40.string().min(1).describe(description);
10644
+ return z43.string().min(1).describe(description);
10134
10645
  }
10135
10646
  function slackUserIdParam(description) {
10136
- return z40.string().min(1).describe(description);
10647
+ return z43.string().min(1).describe(description);
10137
10648
  }
10138
10649
  function parseRequiredSlackChannelIdParam(field, value) {
10139
10650
  const channelId = parseSlackChannelId(value);
@@ -10157,7 +10668,7 @@ function parseRequiredSlackUserIdParam(field, value) {
10157
10668
  }
10158
10669
 
10159
10670
  // src/chat/slack/tools/list/add-items.ts
10160
- import { z as z41 } from "zod";
10671
+ import { z as z44 } from "zod";
10161
10672
  function createSlackListAddItemsTool(state) {
10162
10673
  return zodTool({
10163
10674
  annotations: {
@@ -10167,12 +10678,12 @@ function createSlackListAddItemsTool(state) {
10167
10678
  readOnlyHint: false
10168
10679
  },
10169
10680
  description: "Add tasks to the active Slack list tracked in artifact context. Use when the user wants actionable items recorded in the current thread list. Do not use when no list exists and list creation was not requested.",
10170
- inputSchema: z41.object({
10171
- items: z41.array(z41.string().min(1)).min(1).max(25).describe("List item titles to create."),
10681
+ inputSchema: z44.object({
10682
+ items: z44.array(z44.string().min(1)).min(1).max(25).describe("List item titles to create."),
10172
10683
  assignee_user_id: slackUserIdParam(
10173
10684
  "Optional Slack user ID assigned to all created items."
10174
10685
  ).optional(),
10175
- due_date: z41.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
10686
+ due_date: z44.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
10176
10687
  }),
10177
10688
  outputSchema: juniorToolOutputSchema,
10178
10689
  execute: async ({ items, assignee_user_id, due_date }) => {
@@ -10220,7 +10731,7 @@ function createSlackListAddItemsTool(state) {
10220
10731
  }
10221
10732
 
10222
10733
  // src/chat/slack/tools/list/create.ts
10223
- import { z as z42 } from "zod";
10734
+ import { z as z45 } from "zod";
10224
10735
  function createSlackListCreateTool(state) {
10225
10736
  return zodTool({
10226
10737
  annotations: {
@@ -10230,8 +10741,8 @@ function createSlackListCreateTool(state) {
10230
10741
  readOnlyHint: false
10231
10742
  },
10232
10743
  description: "Create a Slack todo list for action tracking. Use when the user needs structured tasks with ownership/completion tracking. Do not use for one-off notes without task management needs.",
10233
- inputSchema: z42.object({
10234
- name: z42.string().min(1).max(160).describe("Name for the new Slack list.")
10744
+ inputSchema: z45.object({
10745
+ name: z45.string().min(1).max(160).describe("Name for the new Slack list.")
10235
10746
  }),
10236
10747
  outputSchema: juniorToolOutputSchema,
10237
10748
  execute: async ({ name }) => {
@@ -10261,7 +10772,7 @@ function createSlackListCreateTool(state) {
10261
10772
  }
10262
10773
 
10263
10774
  // src/chat/slack/tools/list/get-items.ts
10264
- import { z as z43 } from "zod";
10775
+ import { z as z46 } from "zod";
10265
10776
  function createSlackListGetItemsTool(state) {
10266
10777
  return zodTool({
10267
10778
  description: "Read items from the active Slack list tracked in artifact context. Use when the user asks for task status, open items, or list contents. Do not use when list state is already known from the immediately prior result.",
@@ -10271,8 +10782,8 @@ function createSlackListGetItemsTool(state) {
10271
10782
  openWorldHint: true,
10272
10783
  readOnlyHint: true
10273
10784
  },
10274
- inputSchema: z43.object({
10275
- limit: z43.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
10785
+ inputSchema: z46.object({
10786
+ limit: z46.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
10276
10787
  }),
10277
10788
  outputSchema: juniorToolOutputSchema,
10278
10789
  execute: async ({ limit }) => {
@@ -10291,21 +10802,21 @@ function createSlackListGetItemsTool(state) {
10291
10802
  }
10292
10803
 
10293
10804
  // src/chat/slack/tools/list/update-item.ts
10294
- import { z as z44 } from "zod";
10295
- var booleanInput3 = (description) => z44.preprocess(
10805
+ import { z as z47 } from "zod";
10806
+ var booleanInput3 = (description) => z47.preprocess(
10296
10807
  (value) => value === "true" ? true : value === "false" ? false : value,
10297
- z44.boolean()
10808
+ z47.boolean()
10298
10809
  ).describe(description);
10299
- var updateListItemInputSchema = z44.union([
10300
- z44.object({
10301
- item_id: z44.string().min(1).describe("ID of the Slack list item to update."),
10810
+ var updateListItemInputSchema = z47.union([
10811
+ z47.object({
10812
+ item_id: z47.string().min(1).describe("ID of the Slack list item to update."),
10302
10813
  completed: booleanInput3("Optional completion status update."),
10303
- title: z44.string().min(1).describe("Optional new item title.").optional()
10814
+ title: z47.string().min(1).describe("Optional new item title.").optional()
10304
10815
  }),
10305
- z44.object({
10306
- item_id: z44.string().min(1).describe("ID of the Slack list item to update."),
10816
+ z47.object({
10817
+ item_id: z47.string().min(1).describe("ID of the Slack list item to update."),
10307
10818
  completed: booleanInput3("Optional completion status update.").optional(),
10308
- title: z44.string().min(1).describe("Optional new item title.")
10819
+ title: z47.string().min(1).describe("Optional new item title.")
10309
10820
  })
10310
10821
  ]);
10311
10822
  function createSlackListUpdateItemTool(state) {
@@ -10381,7 +10892,7 @@ async function checkSlackChannelReadAccess(args) {
10381
10892
  }
10382
10893
 
10383
10894
  // src/chat/slack/tools/thread-read.ts
10384
- import { z as z45 } from "zod";
10895
+ import { z as z48 } from "zod";
10385
10896
 
10386
10897
  // src/chat/slack/tools/slack-message-url.ts
10387
10898
  var SLACK_HOST_PATTERN = /^[a-z0-9-]+\.slack(?:-gov)?\.com$/;
@@ -10559,8 +11070,8 @@ function createSlackThreadReadTool(context, deps = {}) {
10559
11070
  openWorldHint: true,
10560
11071
  readOnlyHint: true
10561
11072
  },
10562
- inputSchema: z45.object({
10563
- url: z45.string().min(1).describe(
11073
+ inputSchema: z48.object({
11074
+ url: z48.string().min(1).describe(
10564
11075
  "Slack message archive URL, e.g. https://workspace.slack.com/archives/C123/p1700000000123456"
10565
11076
  ).optional(),
10566
11077
  channel_id: slackChannelIdParam(
@@ -10569,8 +11080,8 @@ function createSlackThreadReadTool(context, deps = {}) {
10569
11080
  ts: slackTimestampParam(
10570
11081
  "Slack message timestamp (e.g. 1700000000.123456). May be the thread root or any message in the thread."
10571
11082
  ).optional(),
10572
- limit: z45.coerce.number().int().min(1).max(1e3).describe("Maximum number of thread messages to fetch.").optional(),
10573
- max_pages: z45.coerce.number().int().min(1).max(10).describe("Maximum number of Slack API pages to traverse.").optional()
11083
+ limit: z48.coerce.number().int().min(1).max(1e3).describe("Maximum number of thread messages to fetch.").optional(),
11084
+ max_pages: z48.coerce.number().int().min(1).max(10).describe("Maximum number of Slack API pages to traverse.").optional()
10574
11085
  }),
10575
11086
  outputSchema: juniorToolOutputSchema,
10576
11087
  execute: async ({ url, channel_id, ts, limit, max_pages }) => {
@@ -10798,10 +11309,10 @@ async function searchSlackUsers(options) {
10798
11309
  }
10799
11310
 
10800
11311
  // src/chat/slack/tools/user-lookup.ts
10801
- import { z as z46 } from "zod";
10802
- var booleanInput4 = (description) => z46.preprocess(
11312
+ import { z as z49 } from "zod";
11313
+ var booleanInput4 = (description) => z49.preprocess(
10803
11314
  (value) => value === "true" ? true : value === "false" ? false : value,
10804
- z46.boolean()
11315
+ z49.boolean()
10805
11316
  ).describe(description);
10806
11317
  function explicitUserLookupError(error) {
10807
11318
  if (error.apiError === "user_not_found") {
@@ -10830,20 +11341,20 @@ function createSlackUserLookupTool() {
10830
11341
  openWorldHint: true,
10831
11342
  readOnlyHint: true
10832
11343
  },
10833
- inputSchema: z46.object({
11344
+ inputSchema: z49.object({
10834
11345
  user_id: slackUserIdParam(
10835
11346
  "Slack user ID to look up (e.g. U039RR91S). Mutually exclusive with email and query."
10836
11347
  ).optional(),
10837
- email: z46.string().min(3).describe(
11348
+ email: z49.string().min(3).describe(
10838
11349
  "Email address to look up. Mutually exclusive with user_id and query."
10839
11350
  ).optional(),
10840
- query: z46.string().min(2).describe(
11351
+ query: z49.string().min(2).describe(
10841
11352
  "Name to search for (matches against username, display name, real name). Mutually exclusive with user_id and email."
10842
11353
  ).optional(),
10843
- limit: z46.coerce.number().int().min(1).max(20).describe(
11354
+ limit: z49.coerce.number().int().min(1).max(20).describe(
10844
11355
  "Maximum number of results to return for name search. Defaults to 10."
10845
11356
  ).optional(),
10846
- max_pages: z46.coerce.number().int().min(1).max(5).describe(
11357
+ max_pages: z49.coerce.number().int().min(1).max(5).describe(
10847
11358
  "Maximum number of Slack API pages to scan for name search. Defaults to 3."
10848
11359
  ).optional(),
10849
11360
  include_bots: booleanInput4(
@@ -10925,12 +11436,12 @@ function createSlackUserLookupTool() {
10925
11436
  }
10926
11437
 
10927
11438
  // src/chat/tools/system-time.ts
10928
- import { z as z47 } from "zod";
11439
+ import { z as z50 } from "zod";
10929
11440
  var systemTimeOutputSchema = juniorToolOutputSchema.extend({
10930
- unix_ms: z47.number(),
10931
- iso_utc: z47.string(),
10932
- iso_local: z47.string(),
10933
- timezone_offset_minutes: z47.number()
11441
+ unix_ms: z50.number(),
11442
+ iso_utc: z50.string(),
11443
+ iso_local: z50.string(),
11444
+ timezone_offset_minutes: z50.number()
10934
11445
  });
10935
11446
  function createSystemTimeTool() {
10936
11447
  return zodTool({
@@ -10941,7 +11452,7 @@ function createSystemTimeTool() {
10941
11452
  openWorldHint: false,
10942
11453
  readOnlyHint: true
10943
11454
  },
10944
- inputSchema: z47.object({}),
11455
+ inputSchema: z50.object({}),
10945
11456
  outputSchema: systemTimeOutputSchema,
10946
11457
  privateTraceResult: (result) => ({
10947
11458
  unix_ms: result.unix_ms,
@@ -10965,7 +11476,7 @@ function createSystemTimeTool() {
10965
11476
  }
10966
11477
 
10967
11478
  // src/chat/tools/query-conversation-events.ts
10968
- import { z as z48 } from "zod";
11479
+ import { z as z51 } from "zod";
10969
11480
  var DEFAULT_LIMIT3 = 25;
10970
11481
  var MAX_LIMIT = 100;
10971
11482
  var MAX_EVENT_DATA_BYTES = 4e3;
@@ -10976,28 +11487,28 @@ var CONVERSATION_EVENTS_TOOL_SOURCE = {
10976
11487
  id: "conversation-events",
10977
11488
  description: "Inspect Junior's durable conversation event log for debugging runtime behavior."
10978
11489
  };
10979
- var knownEventTypeSchema = z48.enum(KNOWN_CONVERSATION_EVENT_TYPES);
10980
- var projectedEventSchema = z48.object({
10981
- seq: z48.number().int().nonnegative().describe("Stable event position; use it for pagination bounds."),
10982
- history_version: z48.number().int().nonnegative().describe(
11490
+ var knownEventTypeSchema = z51.enum(KNOWN_CONVERSATION_EVENT_TYPES);
11491
+ var projectedEventSchema = z51.object({
11492
+ seq: z51.number().int().nonnegative().describe("Stable event position; use it for pagination bounds."),
11493
+ history_version: z51.number().int().nonnegative().describe(
10983
11494
  "Model-history generation. It increments when handoff or compaction replaces active model context."
10984
11495
  ),
10985
- created_at: z48.iso.datetime().describe("When the event was recorded."),
10986
- idempotency_key: z48.string().min(1).optional().describe("Retry-stable event identity, when one was assigned."),
10987
- data: z48.record(z48.string(), z48.unknown()).describe(
11496
+ created_at: z51.iso.datetime().describe("When the event was recorded."),
11497
+ idempotency_key: z51.string().min(1).optional().describe("Retry-stable event identity, when one was assigned."),
11498
+ data: z51.record(z51.string(), z51.unknown()).describe(
10988
11499
  "Event data. Oversized payloads are replaced by identifying fields, payload_omitted, and payload_json_bytes."
10989
11500
  )
10990
11501
  }).strict();
10991
11502
  var queryConversationEventsOutputSchema = juniorToolOutputSchema.extend({
10992
- conversation_id: z48.string().min(1),
10993
- events: z48.array(projectedEventSchema),
10994
- has_older: z48.boolean().describe(
11503
+ conversation_id: z51.string().min(1),
11504
+ events: z51.array(projectedEventSchema),
11505
+ has_older: z51.boolean().describe(
10995
11506
  "Whether matching events exist before this page; request them with before_seq set to the first returned seq."
10996
11507
  ),
10997
- has_newer: z48.boolean().describe(
11508
+ has_newer: z51.boolean().describe(
10998
11509
  "Whether matching events exist after this page; request them with after_seq set to the last returned seq."
10999
11510
  ),
11000
- omitted_event_count: z48.number().int().nonnegative().optional().describe(
11511
+ omitted_event_count: z51.number().int().nonnegative().optional().describe(
11001
11512
  "Fetched events omitted to keep this response bounded. Continue with the pagination cursor for the omitted direction."
11002
11513
  )
11003
11514
  });
@@ -11012,20 +11523,20 @@ function createQueryConversationEventsTool(context) {
11012
11523
  openWorldHint: false,
11013
11524
  readOnlyHint: true
11014
11525
  },
11015
- inputSchema: z48.object({
11016
- conversation_id: z48.string().trim().min(1).describe(
11526
+ inputSchema: z51.object({
11527
+ conversation_id: z51.string().trim().min(1).describe(
11017
11528
  "Conversation ID to inspect, such as slack:{channelId}:{threadTs} or a child conversation id."
11018
11529
  ),
11019
- after_seq: z48.number().int().nonnegative().nullable().describe(
11530
+ after_seq: z51.number().int().nonnegative().nullable().describe(
11020
11531
  "Exclusive lower bound on event seq. When set, returns the next newer page in ascending order."
11021
11532
  ).optional(),
11022
- before_seq: z48.number().int().nonnegative().nullable().describe(
11533
+ before_seq: z51.number().int().nonnegative().nullable().describe(
11023
11534
  "Exclusive upper bound on event seq. Combine with defaults or after_seq to page older or bounded ranges."
11024
11535
  ).optional(),
11025
- limit: z48.number().int().min(1).max(MAX_LIMIT).nullable().describe(
11536
+ limit: z51.number().int().min(1).max(MAX_LIMIT).nullable().describe(
11026
11537
  `Maximum events to return. Defaults to ${DEFAULT_LIMIT3}; max ${MAX_LIMIT}.`
11027
11538
  ).optional(),
11028
- types: z48.array(knownEventTypeSchema).min(1).nullable().describe(
11539
+ types: z51.array(knownEventTypeSchema).min(1).nullable().describe(
11029
11540
  "Optional event-type filter. Omit to return every durable event type."
11030
11541
  ).optional()
11031
11542
  }).strict(),
@@ -11273,10 +11784,10 @@ function stripReplacementHistoryField(value) {
11273
11784
  }
11274
11785
 
11275
11786
  // src/chat/tools/handoff/tool.ts
11276
- import { z as z49 } from "zod";
11787
+ import { z as z52 } from "zod";
11277
11788
  var HANDOFF_TOOL_NAME = "handoff";
11278
11789
  function createHandoffTool(handoff) {
11279
- const profileSchema = z49.enum(handoff.profiles);
11790
+ const profileSchema = z52.enum(handoff.profiles);
11280
11791
  const handoffResultSchema = juniorToolOutputSchema.extend({
11281
11792
  model_profile: modelProfileSchema
11282
11793
  });
@@ -11290,7 +11801,7 @@ function createHandoffTool(handoff) {
11290
11801
  },
11291
11802
  description: `Switch to another execution profile and continue the same task. Profiles: ${profileNames}. Call this as the only tool.`,
11292
11803
  executionMode: "sequential",
11293
- inputSchema: z49.object({
11804
+ inputSchema: z52.object({
11294
11805
  profile: profileSchema.describe("Target execution profile")
11295
11806
  }).strict(),
11296
11807
  outputSchema: handoffResultSchema,
@@ -11311,7 +11822,7 @@ function createHandoffTool(handoff) {
11311
11822
  }
11312
11823
 
11313
11824
  // src/chat/tools/web/fetch-tool.ts
11314
- import { z as z50 } from "zod";
11825
+ import { z as z53 } from "zod";
11315
11826
 
11316
11827
  // src/chat/tools/web/constants.ts
11317
11828
  var USER_AGENT = "junior-bot/0.1";
@@ -11754,9 +12265,9 @@ function createWebFetchTool(hooks, options = {}) {
11754
12265
  openWorldHint: true,
11755
12266
  readOnlyHint: true
11756
12267
  },
11757
- inputSchema: z50.object({
11758
- url: z50.string().min(1).describe("HTTP(S) URL to fetch."),
11759
- max_chars: z50.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
12268
+ inputSchema: z53.object({
12269
+ url: z53.string().min(1).describe("HTTP(S) URL to fetch."),
12270
+ max_chars: z53.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
11760
12271
  }),
11761
12272
  outputSchema: juniorToolOutputSchema,
11762
12273
  execute: async ({ url, max_chars }) => {
@@ -11801,7 +12312,7 @@ function createWebFetchTool(hooks, options = {}) {
11801
12312
  }
11802
12313
 
11803
12314
  // src/chat/tools/web/search.ts
11804
- import { z as z51 } from "zod";
12315
+ import { z as z54 } from "zod";
11805
12316
  import { generateText } from "ai";
11806
12317
  import { createGatewayProvider } from "@ai-sdk/gateway";
11807
12318
  var SEARCH_TIMEOUT_MS = 6e4;
@@ -11843,9 +12354,9 @@ function createWebSearchTool(modelId, override) {
11843
12354
  openWorldHint: true,
11844
12355
  readOnlyHint: true
11845
12356
  },
11846
- inputSchema: z51.object({
11847
- query: z51.string().min(1).max(500).describe("Search query."),
11848
- max_results: z51.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
12357
+ inputSchema: z54.object({
12358
+ query: z54.string().min(1).max(500).describe("Search query."),
12359
+ max_results: z54.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
11849
12360
  }),
11850
12361
  outputSchema: juniorToolOutputSchema,
11851
12362
  execute: async ({ query, max_results }) => {
@@ -11884,7 +12395,7 @@ function createWebSearchTool(modelId, override) {
11884
12395
  }
11885
12396
 
11886
12397
  // src/chat/tools/sandbox/write-file.ts
11887
- import { z as z52 } from "zod";
12398
+ import { z as z55 } from "zod";
11888
12399
  function createWriteFileTool() {
11889
12400
  return zodTool({
11890
12401
  annotations: {
@@ -11895,9 +12406,9 @@ function createWriteFileTool() {
11895
12406
  },
11896
12407
  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.",
11897
12408
  executionMode: "sequential",
11898
- inputSchema: z52.object({
11899
- path: z52.string().min(1).describe("Path to write in the sandbox workspace."),
11900
- content: z52.string().describe("UTF-8 file content to write.")
12409
+ inputSchema: z55.object({
12410
+ path: z55.string().min(1).describe("Path to write in the sandbox workspace."),
12411
+ content: z55.string().describe("UTF-8 file content to write.")
11901
12412
  }),
11902
12413
  outputSchema: juniorToolOutputSchema,
11903
12414
  execute: async () => {
@@ -11944,15 +12455,7 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
11944
12455
  const canSendFilesToActiveConversation = Boolean(
11945
12456
  slackContext && slackSourceCapabilities?.canSendFiles
11946
12457
  );
11947
- const resourceEventCatalog = Object.fromEntries(
11948
- canRouteResourceEvents() ? getPlugins().flatMap((plugin) => {
11949
- const registration = plugin.resourceEvents;
11950
- if (!registration || registration.isEnabled?.() === false) {
11951
- return [];
11952
- }
11953
- return [[plugin.manifest.name, registration]];
11954
- }) : []
11955
- );
12458
+ const resourceEventCatalog = getResourceEventCatalog();
11956
12459
  const tools = {
11957
12460
  ...options.includeLoadSkill === false ? {} : {
11958
12461
  loadSkill: createLoadSkillTool(availableSkills, {
@@ -11976,7 +12479,8 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
11976
12479
  canSendFilesToActiveConversation
11977
12480
  }),
11978
12481
  ...createResourceEventTools(context, resourceEventCatalog),
11979
- ...createEventTaskTools(context, resourceEventCatalog)
12482
+ ...createEventTaskTools(context, resourceEventCatalog),
12483
+ ...createScheduledTaskTools(context)
11980
12484
  };
11981
12485
  if (context.conversationId) {
11982
12486
  tools.queryConversationEvents = createQueryConversationEventsTool(context);
@@ -12278,11 +12782,11 @@ function replaceGeneratedTextContent(content, text) {
12278
12782
  ...withoutFirstGeneratedTextContent(content)
12279
12783
  ];
12280
12784
  }
12281
- function isRecord4(value) {
12785
+ function isRecord3(value) {
12282
12786
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
12283
12787
  }
12284
12788
  function hasContinuation(value) {
12285
- return isRecord4(value) && isRecord4(value.continuation);
12789
+ return isRecord3(value) && isRecord3(value.continuation);
12286
12790
  }
12287
12791
  function stringField(record, key) {
12288
12792
  const value = record[key];
@@ -12297,7 +12801,7 @@ function stringListField(record, key) {
12297
12801
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
12298
12802
  }
12299
12803
  function accountText(value) {
12300
- if (!isRecord4(value)) {
12804
+ if (!isRecord3(value)) {
12301
12805
  return void 0;
12302
12806
  }
12303
12807
  const label = stringField(value, "label") || stringField(value, "id");
@@ -12308,7 +12812,7 @@ function accountText(value) {
12308
12812
  return id && id !== label ? `${label} (${id})` : label;
12309
12813
  }
12310
12814
  function upstreamPermissionDeniedText(value) {
12311
- if (!isRecord4(value) || !isRecord4(value.permission_denied)) {
12815
+ if (!isRecord3(value) || !isRecord3(value.permission_denied)) {
12312
12816
  return void 0;
12313
12817
  }
12314
12818
  const signal = value.permission_denied;
@@ -12323,7 +12827,7 @@ function upstreamPermissionDeniedText(value) {
12323
12827
  if (!provider || !message || !upstreamHost || !upstreamPath || !status) {
12324
12828
  return void 0;
12325
12829
  }
12326
- const grant = isRecord4(signal.grant) ? signal.grant : {};
12830
+ const grant = isRecord3(signal.grant) ? signal.grant : {};
12327
12831
  const grantName = stringField(grant, "name");
12328
12832
  const grantAccess = stringField(grant, "access");
12329
12833
  const grantReason = stringField(grant, "reason");
@@ -12947,7 +13451,7 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, conv
12947
13451
  }
12948
13452
 
12949
13453
  // src/chat/tools/execute-tool.ts
12950
- import { z as z53 } from "zod";
13454
+ import { z as z56 } from "zod";
12951
13455
  var EXECUTE_TOOL_NAME = "executeTool";
12952
13456
  function createExecuteToolTool() {
12953
13457
  return zodTool({
@@ -12959,11 +13463,11 @@ function createExecuteToolTool() {
12959
13463
  },
12960
13464
  description: "Execute any catalog tool by exact tool_name from searchTools or a tool-result execution hint. Put tool-specific parameters inside arguments.",
12961
13465
  executionMode: "sequential",
12962
- inputSchema: z53.object({
12963
- tool_name: z53.string().min(1).describe(
13466
+ inputSchema: z56.object({
13467
+ tool_name: z56.string().min(1).describe(
12964
13468
  "Exact catalog tool_name returned by searchTools or a tool-result execution hint."
12965
13469
  ),
12966
- arguments: z53.record(z53.string(), z53.unknown()).describe(
13470
+ arguments: z56.record(z56.string(), z56.unknown()).describe(
12967
13471
  'Arguments matching the selected catalog tool schema, for example { "query": "..." }.'
12968
13472
  ).optional()
12969
13473
  }).strict(),
@@ -13003,34 +13507,34 @@ function planToolExposure(tools) {
13003
13507
  }
13004
13508
 
13005
13509
  // src/chat/tools/search-tools.ts
13006
- import { z as z54 } from "zod";
13510
+ import { z as z57 } from "zod";
13007
13511
  var SEARCH_TOOLS_NAME = "searchTools";
13008
13512
  var DEFAULT_MAX_RESULTS2 = 5;
13009
13513
  var MAX_RESULTS3 = 20;
13010
13514
  var MODEL_VISIBLE_DESCRIPTION_CAP = 180;
13011
- var searchToolsSourceSchema = z54.object({
13012
- id: z54.string(),
13013
- description: z54.string()
13515
+ var searchToolsSourceSchema = z57.object({
13516
+ id: z57.string(),
13517
+ description: z57.string()
13014
13518
  }).strict();
13015
- var searchToolsToolSchema = z54.object({
13016
- tool_name: z54.string(),
13017
- description: z54.string(),
13018
- exposure: z54.enum(["direct", "deferred", "modelOnly", "hidden"]),
13019
- source: z54.string().optional(),
13020
- input_schema: z54.unknown(),
13021
- call_notes: z54.array(z54.string()),
13022
- annotations: z54.record(z54.string(), z54.unknown())
13519
+ var searchToolsToolSchema = z57.object({
13520
+ tool_name: z57.string(),
13521
+ description: z57.string(),
13522
+ exposure: z57.enum(["direct", "deferred", "modelOnly", "hidden"]),
13523
+ source: z57.string().optional(),
13524
+ input_schema: z57.unknown(),
13525
+ call_notes: z57.array(z57.string()),
13526
+ annotations: z57.record(z57.string(), z57.unknown())
13023
13527
  }).strict();
13024
13528
  var searchToolsOutputSchema = juniorToolOutputSchema.extend({
13025
- query: z54.string().nullable(),
13026
- source: z54.string().nullable(),
13027
- sources: z54.array(searchToolsSourceSchema),
13028
- total_catalog_tools: z54.number().int().nonnegative(),
13029
- total_eligible_tools: z54.number().int().nonnegative(),
13030
- total_matches: z54.number().int().nonnegative(),
13031
- returned_tools: z54.number().int().nonnegative(),
13032
- execution_tool: z54.literal("executeTool"),
13033
- tools: z54.array(searchToolsToolSchema)
13529
+ query: z57.string().nullable(),
13530
+ source: z57.string().nullable(),
13531
+ sources: z57.array(searchToolsSourceSchema),
13532
+ total_catalog_tools: z57.number().int().nonnegative(),
13533
+ total_eligible_tools: z57.number().int().nonnegative(),
13534
+ total_matches: z57.number().int().nonnegative(),
13535
+ returned_tools: z57.number().int().nonnegative(),
13536
+ execution_tool: z57.literal("executeTool"),
13537
+ tools: z57.array(searchToolsToolSchema)
13034
13538
  }).strict();
13035
13539
  function normalize2(value) {
13036
13540
  return value.toLowerCase().replace(/[^a-z0-9_]+/g, " ").trim();
@@ -13145,14 +13649,14 @@ function createSearchToolsTool(catalogTools) {
13145
13649
  openWorldHint: false,
13146
13650
  readOnlyHint: true
13147
13651
  },
13148
- inputSchema: z54.object({
13149
- query: z54.string().nullable().describe(
13652
+ inputSchema: z57.object({
13653
+ query: z57.string().nullable().describe(
13150
13654
  "Optional search terms describing the tool, owner, action, or arguments needed. Empty string lists catalog tools."
13151
13655
  ).optional(),
13152
- source: z54.string().nullable().describe(
13656
+ source: z57.string().nullable().describe(
13153
13657
  "Optional source id to search within, such as a plugin source returned in sources."
13154
13658
  ).optional(),
13155
- max_results: z54.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
13659
+ max_results: z57.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
13156
13660
  }).strict(),
13157
13661
  outputSchema: searchToolsOutputSchema,
13158
13662
  privateTraceResult: (result) => ({
@@ -14397,7 +14901,7 @@ function createPluginEgress(deps) {
14397
14901
  }
14398
14902
 
14399
14903
  // src/chat/services/guardian-action-review.ts
14400
- import { z as z55 } from "zod";
14904
+ import { z as z58 } from "zod";
14401
14905
 
14402
14906
  // src/chat/services/guardian-action-policy.ts
14403
14907
  var GUARDIAN_ACTION_POLICY = `You are judging one planned Junior agent action.
@@ -14463,17 +14967,17 @@ Assess the exact action's intrinsic risk and whether the user's intent authorize
14463
14967
  - 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.`;
14464
14968
 
14465
14969
  // src/chat/services/guardian-action-review.ts
14466
- var guardianDecisionSchema = z55.object({
14467
- decision: z55.enum(["allow", "ask", "deny"]),
14468
- reason: z55.string().trim().min(1).max(500),
14469
- riskLevel: z55.enum(["low", "medium", "high", "critical"]),
14470
- userAuthorization: z55.enum(["high", "medium", "low", "unknown"])
14970
+ var guardianDecisionSchema = z58.object({
14971
+ decision: z58.enum(["allow", "ask", "deny"]),
14972
+ reason: z58.string().trim().min(1).max(500),
14973
+ riskLevel: z58.enum(["low", "medium", "high", "critical"]),
14974
+ userAuthorization: z58.enum(["high", "medium", "low", "unknown"])
14471
14975
  }).strict();
14472
14976
  var GUARDIAN_REVIEW_TIMEOUT_MS = 6e4;
14473
14977
  var GUARDIAN_REVIEW_MAX_TOKENS = 2e3;
14474
14978
  var MAX_PROPOSAL_CHARS = 192e3;
14475
14979
  function guardianPrompt(proposal) {
14476
- const proposalJson = JSON.stringify(z55.json().parse(proposal), null, 2);
14980
+ const proposalJson = JSON.stringify(z58.json().parse(proposal), null, 2);
14477
14981
  if (proposalJson.length > MAX_PROPOSAL_CHARS) {
14478
14982
  throw new Error(
14479
14983
  `Guardian action proposal exceeds ${MAX_PROPOSAL_CHARS} characters.`
@@ -16852,7 +17356,7 @@ export {
16852
17356
  cancelSubscriptions,
16853
17357
  findMatchingResourceEventSubscriptions,
16854
17358
  deliverResourceEventSubscription,
16855
- findMatchingEventTasks,
17359
+ sanitizeScheduledTaskPrincipal,
16856
17360
  listThreadReplies,
16857
17361
  renderSlackLegacyAttachmentText,
16858
17362
  appendSlackLegacyAttachmentText,