@sentry/junior 0.128.1 → 0.130.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.
- package/dist/{agent-hooks-IWQNFJMS.js → agent-hooks-LJHLLMFC.js} +9 -9
- package/dist/api/schema/task.d.ts +152 -0
- package/dist/api/schema.d.ts +2 -0
- package/dist/api/schema.js +13 -3
- package/dist/api/tasks/routes.d.ts +4 -0
- package/dist/api.js +425 -23
- package/dist/app.js +309 -27
- package/dist/{catalog-runtime-KLSYFS4A.js → catalog-runtime-45AHWLJL.js} +5 -5
- package/dist/chat/agent-dispatch/context.d.ts +18 -0
- package/dist/chat/event-tasks/store.d.ts +7 -1
- package/dist/chat/event-tasks/tool-support.d.ts +1 -0
- package/dist/chat/resource-events/runtime-catalog.d.ts +3 -0
- package/dist/chat/scheduled-tasks/cadence.d.ts +27 -0
- package/dist/chat/scheduled-tasks/heartbeat.d.ts +6 -0
- package/dist/chat/scheduled-tasks/identity.d.ts +6 -0
- package/dist/chat/scheduled-tasks/personal.d.ts +26 -0
- package/dist/chat/scheduled-tasks/schedule-intent.d.ts +61 -0
- package/dist/chat/scheduled-tasks/store.d.ts +77 -0
- package/dist/chat/scheduled-tasks/tool-support.d.ts +203 -0
- package/dist/chat/scheduled-tasks/tools/create.d.ts +80 -0
- package/dist/chat/scheduled-tasks/tools/delete.d.ts +56 -0
- package/dist/chat/scheduled-tasks/tools/list.d.ts +54 -0
- package/dist/chat/scheduled-tasks/tools/run-now.d.ts +56 -0
- package/dist/chat/scheduled-tasks/tools/update.d.ts +82 -0
- package/dist/chat/scheduled-tasks/tools.d.ts +6 -0
- package/dist/chat/scheduled-tasks/types.d.ts +81 -0
- package/dist/chat/tasks/read.d.ts +9 -0
- package/dist/chat/tools/scheduled-tasks.d.ts +4 -0
- package/dist/{chunk-AAMF2IRC.js → chunk-224V72RX.js} +1308 -804
- package/dist/{chunk-54KP2EAH.js → chunk-2V7BQAJ6.js} +12 -12
- package/dist/{chunk-J3YIO3LE.js → chunk-4AF3XOZI.js} +3 -3
- package/dist/{chunk-S2O64VXP.js → chunk-4X2MZ4FP.js} +6 -6
- package/dist/{chunk-5IR7SGRO.js → chunk-5I4SWLD7.js} +2 -2
- package/dist/{chunk-OIQCRZ67.js → chunk-5XDJRSU5.js} +4 -4
- package/dist/{chunk-MZ6ZOWMJ.js → chunk-7OO3LMEP.js} +1 -1
- package/dist/{chunk-Q5TMMCBV.js → chunk-A64VQ4N4.js} +1 -1
- package/dist/{chunk-R2LXTX4J.js → chunk-ATCTPG7J.js} +1 -1
- package/dist/{chunk-AFJF3RGU.js → chunk-BVKP37NE.js} +61 -13
- package/dist/{chunk-EHEACYJ6.js → chunk-DMS2RTEK.js} +1 -1
- package/dist/{chunk-H4HMCSOZ.js → chunk-EKZSU2RK.js} +5 -5
- package/dist/chunk-GXO3EXBM.js +1470 -0
- package/dist/{chunk-ETGUGGO2.js → chunk-H6GDE77O.js} +7 -7
- package/dist/{chunk-P7UUNWC4.js → chunk-HJHTRJKR.js} +4 -4
- package/dist/{chunk-TONH5NXR.js → chunk-J6B27DOC.js} +1 -1
- package/dist/{chunk-SHMHHXD5.js → chunk-KB2M27DL.js} +58 -0
- package/dist/{chunk-EOIA25WC.js → chunk-LYEXN7FN.js} +2 -2
- package/dist/{chunk-O3C5BJFD.js → chunk-PVHL3274.js} +1 -1
- package/dist/{chunk-O3YROBH4.js → chunk-RTJCNKQD.js} +1 -1
- package/dist/{chunk-LIJ4APSS.js → chunk-UDYVHDLH.js} +1 -1
- package/dist/{chunk-PLAMHS3D.js → chunk-XRROAXID.js} +2 -2
- package/dist/{chunk-MKM5552O.js → chunk-Z72XGIFF.js} +1 -2
- package/dist/cli/chat.js +24 -24
- package/dist/cli/check.js +6 -6
- package/dist/cli/plugins.js +12 -12
- package/dist/cli/snapshot-create.js +9 -9
- package/dist/cli/upgrade.js +9 -17
- package/dist/db/schema/scheduled-tasks.d.ts +257 -0
- package/dist/db/schema.d.ts +258 -1
- package/dist/{db-VOU5QNLY.js → db-XE6DXA5Z.js} +7 -7
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +2 -2
- package/dist/{oauth-callback-server-GS7FBYBC.js → oauth-callback-server-O42UXC7E.js} +17 -17
- package/dist/{runner-GSJSBI3J.js → runner-BSP3374N.js} +11 -11
- package/dist/{skills-DSHG54LM.js → skills-BNLHOZ75.js} +6 -6
- package/dist/{validation-25XWT6TA.js → validation-O7BF3JX6.js} +6 -6
- package/dist/version.js +1 -1
- package/migrations/0016_neat_the_anarchist.sql +171 -0
- package/migrations/meta/0016_snapshot.json +1617 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +4 -5
- package/dist/chunk-REHOYCYS.js +0 -37
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
toMcpProviderError,
|
|
31
31
|
toolInvocationDestination,
|
|
32
32
|
uploadFilesToConversation
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-H6GDE77O.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-
|
|
83
|
+
} from "./chunk-5XDJRSU5.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-
|
|
107
|
+
} from "./chunk-HJHTRJKR.js";
|
|
108
108
|
import {
|
|
109
|
-
|
|
110
|
-
|
|
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-GXO3EXBM.js";
|
|
111
140
|
import {
|
|
112
141
|
parseSlackThreadId
|
|
113
|
-
} from "./chunk-
|
|
142
|
+
} from "./chunk-UDYVHDLH.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-
|
|
165
|
+
} from "./chunk-EKZSU2RK.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-
|
|
150
|
-
import {
|
|
151
|
-
juniorEventTasks
|
|
152
|
-
} from "./chunk-SHMHHXD5.js";
|
|
176
|
+
} from "./chunk-4AF3XOZI.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-
|
|
186
|
+
} from "./chunk-7OO3LMEP.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-
|
|
220
|
+
} from "./chunk-5I4SWLD7.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-
|
|
230
|
+
} from "./chunk-DMS2RTEK.js";
|
|
207
231
|
import {
|
|
208
232
|
discoverSkills,
|
|
209
233
|
findSkillByName,
|
|
210
234
|
loadSkillsByName,
|
|
211
235
|
parseSkillInvocation
|
|
212
|
-
} from "./chunk-
|
|
236
|
+
} from "./chunk-LYEXN7FN.js";
|
|
213
237
|
import {
|
|
214
238
|
pluginCatalogRuntime
|
|
215
|
-
} from "./chunk-
|
|
239
|
+
} from "./chunk-ATCTPG7J.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-
|
|
247
|
+
} from "./chunk-RTJCNKQD.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-
|
|
276
|
+
} from "./chunk-J6B27DOC.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
|
|
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
|
|
971
|
-
reasoning_level:
|
|
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:
|
|
947
|
+
confidence: z.preprocess(
|
|
977
948
|
coerceClassifierConfidence,
|
|
978
|
-
|
|
949
|
+
z.number().min(0).max(1)
|
|
979
950
|
),
|
|
980
|
-
reason:
|
|
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
|
|
1235
|
+
import { z as z2 } from "zod";
|
|
1265
1236
|
var MAX_VISIBLE_HISTORY_CHARS = 12e3;
|
|
1266
|
-
var priorRejectionSchema =
|
|
1267
|
-
decision:
|
|
1268
|
-
input:
|
|
1269
|
-
reason:
|
|
1270
|
-
riskLevel:
|
|
1271
|
-
tool:
|
|
1272
|
-
annotations:
|
|
1273
|
-
description:
|
|
1274
|
-
dispatcherName:
|
|
1275
|
-
identity:
|
|
1276
|
-
id:
|
|
1277
|
-
name:
|
|
1278
|
-
plugin:
|
|
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:
|
|
1281
|
-
proposalDescription:
|
|
1282
|
-
catalogSource:
|
|
1283
|
-
description:
|
|
1284
|
-
id:
|
|
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:
|
|
1258
|
+
userAuthorization: z2.enum(["high", "medium", "low", "unknown"]).optional()
|
|
1288
1259
|
}).strict();
|
|
1289
|
-
var rejectionMarkerSchema =
|
|
1290
|
-
decision:
|
|
1260
|
+
var rejectionMarkerSchema = z2.object({
|
|
1261
|
+
decision: z2.enum(["ask", "deny"]),
|
|
1291
1262
|
priorRejection: priorRejectionSchema,
|
|
1292
|
-
reason:
|
|
1293
|
-
riskLevel:
|
|
1294
|
-
userAuthorization:
|
|
1295
|
-
version:
|
|
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
|
|
1268
|
+
function isRecord(value) {
|
|
1298
1269
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
1299
1270
|
}
|
|
1300
1271
|
function getToolActionRejectionMarker(message) {
|
|
1301
|
-
if (!
|
|
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 =
|
|
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
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
1444
|
+
if (isRecord2(args)) {
|
|
1474
1445
|
addString(providers, providerFromToolName(args.tool_name));
|
|
1475
1446
|
}
|
|
1476
1447
|
}
|
|
1477
|
-
if (
|
|
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 (!
|
|
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 (!
|
|
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 (
|
|
1505
|
-
if (
|
|
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
|
|
4225
|
+
import { z as z4 } from "zod";
|
|
4264
4226
|
|
|
4265
4227
|
// src/chat/tool-support/zod-tool.ts
|
|
4266
|
-
import { z as
|
|
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 =
|
|
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 =
|
|
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 =
|
|
4399
|
-
oldText:
|
|
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:
|
|
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:
|
|
4416
|
-
path:
|
|
4417
|
-
edits:
|
|
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
|
|
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:
|
|
4606
|
-
pattern:
|
|
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:
|
|
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:
|
|
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
|
|
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) =>
|
|
4590
|
+
var booleanInput = (description) => z6.preprocess(
|
|
4629
4591
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
4630
|
-
|
|
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:
|
|
4980
|
-
pattern:
|
|
4981
|
-
path:
|
|
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:
|
|
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:
|
|
4992
|
-
limit:
|
|
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
|
|
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:
|
|
5085
|
-
path:
|
|
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:
|
|
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
|
|
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:
|
|
5195
|
-
path:
|
|
5196
|
-
offset:
|
|
5197
|
-
limit:
|
|
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
|
|
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 =
|
|
5758
|
-
path:
|
|
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:
|
|
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:
|
|
5765
|
-
bytes:
|
|
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:
|
|
5771
|
-
mimeType:
|
|
5772
|
-
bytes:
|
|
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
|
|
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:
|
|
6802
|
-
command:
|
|
6803
|
-
timeoutMs:
|
|
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
|
|
6779
|
+
import { z as z11 } from "zod";
|
|
6818
6780
|
var imageGenerateOutputSchema = juniorToolOutputSchema.extend({
|
|
6819
|
-
model:
|
|
6820
|
-
prompt:
|
|
6821
|
-
enrichedPrompt:
|
|
6822
|
-
image_count:
|
|
6823
|
-
images:
|
|
6824
|
-
delivery:
|
|
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:
|
|
6886
|
-
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
|
|
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:
|
|
7012
|
-
tool_name:
|
|
7013
|
-
arguments:
|
|
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
|
|
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:
|
|
7120
|
-
skill_name:
|
|
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
|
|
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 =
|
|
7171
|
-
provider:
|
|
7172
|
-
description:
|
|
7173
|
-
active:
|
|
7132
|
+
var providerSummarySchema = z14.object({
|
|
7133
|
+
provider: z14.string(),
|
|
7134
|
+
description: z14.string(),
|
|
7135
|
+
active: z14.boolean()
|
|
7174
7136
|
}).strict();
|
|
7175
|
-
var exposedToolSummarySchema =
|
|
7176
|
-
tool_name:
|
|
7177
|
-
mcp_tool_name:
|
|
7178
|
-
provider:
|
|
7179
|
-
title:
|
|
7180
|
-
description:
|
|
7181
|
-
input_schema:
|
|
7182
|
-
output_schema:
|
|
7183
|
-
annotations:
|
|
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:
|
|
7187
|
-
provider:
|
|
7188
|
-
total_active_tools:
|
|
7189
|
-
returned_tools:
|
|
7190
|
-
execution_tool:
|
|
7191
|
-
available_providers:
|
|
7192
|
-
tools:
|
|
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:
|
|
7319
|
-
query:
|
|
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:
|
|
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:
|
|
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
|
|
7327
|
+
import { z as z15 } from "zod";
|
|
7366
7328
|
var MAX_VIEW_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
7367
|
-
var viewImageInputSchema =
|
|
7368
|
-
path:
|
|
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
|
|
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:
|
|
7446
|
-
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
|
|
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
|
|
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 =
|
|
7504
|
-
var subscriptionIdIndexSchema =
|
|
7505
|
-
var subscriptionSchema =
|
|
7506
|
-
conversationId:
|
|
7507
|
-
createdAtMs:
|
|
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:
|
|
7510
|
-
expiresAtMs:
|
|
7511
|
-
id:
|
|
7512
|
-
intent:
|
|
7513
|
-
label:
|
|
7514
|
-
namespace:
|
|
7515
|
-
identifier:
|
|
7516
|
-
resourceType:
|
|
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:
|
|
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 =
|
|
7889
|
-
id:
|
|
7890
|
-
label:
|
|
7891
|
-
identifier:
|
|
7892
|
-
namespace:
|
|
7893
|
-
resourceType:
|
|
7894
|
-
events:
|
|
7895
|
-
intent:
|
|
7896
|
-
expiresAtMs:
|
|
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 =
|
|
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:
|
|
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
|
|
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 =
|
|
7996
|
-
namespace:
|
|
7997
|
-
type:
|
|
7998
|
-
supportedEvents:
|
|
7999
|
-
suggestedEvents:
|
|
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:
|
|
8003
|
-
namespace:
|
|
8004
|
-
totalMatches:
|
|
8005
|
-
resourceTypes:
|
|
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:
|
|
8032
|
-
query:
|
|
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:
|
|
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
|
|
8075
|
-
var resultDataSchema2 =
|
|
8076
|
-
watching_status:
|
|
8077
|
-
stoppedIds:
|
|
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:
|
|
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
|
|
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
|
|
8133
|
-
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:
|
|
8141
|
-
events:
|
|
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:
|
|
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:
|
|
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 =
|
|
8168
|
-
execution_tool:
|
|
8169
|
-
execution_example:
|
|
8170
|
-
tool_name:
|
|
8171
|
-
arguments:
|
|
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 =
|
|
8175
|
-
id:
|
|
8176
|
-
subscription_status:
|
|
8177
|
-
identifier:
|
|
8178
|
-
events:
|
|
8179
|
-
expiresAtMs:
|
|
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
|
|
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:
|
|
8501
|
-
task:
|
|
8222
|
+
inputSchema: z22.object({
|
|
8223
|
+
task: z22.string().trim().min(1).max(4e3),
|
|
8502
8224
|
trigger,
|
|
8503
|
-
credentialMode:
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
8636
|
-
taskId:
|
|
8637
|
-
task:
|
|
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:
|
|
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/
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8719
|
-
|
|
8720
|
-
|
|
8721
|
-
|
|
8722
|
-
|
|
8723
|
-
|
|
8724
|
-
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
|
|
8734
|
-
|
|
8735
|
-
|
|
8736
|
-
|
|
8737
|
-
|
|
8738
|
-
|
|
8739
|
-
|
|
8740
|
-
|
|
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
|
-
|
|
8744
|
-
|
|
8745
|
-
|
|
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
|
-
|
|
8749
|
-
const
|
|
8750
|
-
|
|
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
|
|
9302
|
+
import { z as z33 } from "zod";
|
|
8792
9303
|
function slackTimestampParam(description) {
|
|
8793
|
-
return
|
|
9304
|
+
return z33.preprocess(
|
|
8794
9305
|
(value) => typeof value === "number" && Number.isFinite(value) ? String(value) : value,
|
|
8795
|
-
|
|
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
|
|
8827
|
-
var booleanInput2 = (description) =>
|
|
9337
|
+
import { z as z34 } from "zod";
|
|
9338
|
+
var booleanInput2 = (description) => z34.preprocess(
|
|
8828
9339
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
8829
|
-
|
|
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:
|
|
8862
|
-
limit:
|
|
8863
|
-
cursor:
|
|
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:
|
|
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
|
|
9447
|
+
import { z as z35 } from "zod";
|
|
8937
9448
|
var DEFAULT_LIMIT = 5;
|
|
8938
9449
|
var conversationSearchOutputSchema = juniorToolOutputSchema.extend({
|
|
8939
|
-
query:
|
|
8940
|
-
count:
|
|
8941
|
-
threads:
|
|
8942
|
-
|
|
8943
|
-
conversation_id:
|
|
8944
|
-
thread_ts:
|
|
8945
|
-
message_id:
|
|
8946
|
-
message_role:
|
|
8947
|
-
message_timestamp:
|
|
8948
|
-
excerpt:
|
|
8949
|
-
permalink:
|
|
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:
|
|
8968
|
-
query:
|
|
8969
|
-
limit:
|
|
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
|
|
9525
|
+
import { z as z36 } from "zod";
|
|
9015
9526
|
var DEFAULT_LIMIT2 = 10;
|
|
9016
|
-
var optionalTimestampSchema =
|
|
9527
|
+
var optionalTimestampSchema = z36.preprocess(
|
|
9017
9528
|
(value) => typeof value === "string" && value.trim() === "" ? void 0 : value,
|
|
9018
|
-
|
|
9529
|
+
z36.coerce.number().int().nonnegative().describe("Optional Unix timestamp bound.").optional()
|
|
9019
9530
|
);
|
|
9020
|
-
var searchMessageSchema =
|
|
9021
|
-
author_name:
|
|
9022
|
-
author_user_id:
|
|
9023
|
-
channel_id:
|
|
9024
|
-
channel_name:
|
|
9025
|
-
message_ts:
|
|
9026
|
-
content:
|
|
9027
|
-
is_author_bot:
|
|
9028
|
-
permalink:
|
|
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:
|
|
9032
|
-
count:
|
|
9033
|
-
messages:
|
|
9034
|
-
next_cursor:
|
|
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:
|
|
9062
|
-
query:
|
|
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:
|
|
9072
|
-
limit:
|
|
9073
|
-
sort:
|
|
9074
|
-
sort_dir:
|
|
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
|
|
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:
|
|
9162
|
-
emoji:
|
|
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
|
|
9211
|
-
import { z as
|
|
9721
|
+
import { createHash as createHash4 } from "crypto";
|
|
9722
|
+
import { z as z38 } from "zod";
|
|
9212
9723
|
var sendFilesResultSchema = juniorToolOutputSchema.extend({
|
|
9213
|
-
target:
|
|
9214
|
-
channel_id:
|
|
9215
|
-
deduplicated:
|
|
9216
|
-
file_count:
|
|
9217
|
-
file_ids:
|
|
9218
|
-
thread_ts:
|
|
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
|
|
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:
|
|
9249
|
-
files:
|
|
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
|
|
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:
|
|
9692
|
-
title:
|
|
9693
|
-
markdown:
|
|
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
|
|
10260
|
+
import { z as z40 } from "zod";
|
|
9750
10261
|
function prepareCanvasEditArguments(input) {
|
|
9751
10262
|
return prepareTextReplacementArguments(input);
|
|
9752
10263
|
}
|
|
9753
|
-
var editReplacementSchema2 =
|
|
9754
|
-
oldText:
|
|
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:
|
|
10268
|
+
newText: z40.string().describe("Replacement Canvas markdown for this edit.")
|
|
9758
10269
|
});
|
|
9759
10270
|
var slackCanvasEditOutputSchema = juniorToolOutputSchema.extend({
|
|
9760
|
-
canvas_id:
|
|
9761
|
-
title:
|
|
9762
|
-
permalink:
|
|
9763
|
-
diff:
|
|
9764
|
-
first_changed_line:
|
|
9765
|
-
replacements:
|
|
9766
|
-
normalized_heading_count:
|
|
9767
|
-
summary:
|
|
9768
|
-
deduplicated:
|
|
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:
|
|
9782
|
-
canvas:
|
|
9783
|
-
edits:
|
|
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
|
|
10351
|
+
import { z as z41 } from "zod";
|
|
9841
10352
|
var slackCanvasReadOutputSchema = juniorToolOutputSchema.extend({
|
|
9842
|
-
canvas_id:
|
|
9843
|
-
title:
|
|
9844
|
-
permalink:
|
|
9845
|
-
mimetype:
|
|
9846
|
-
filetype:
|
|
9847
|
-
original_byte_length:
|
|
9848
|
-
content:
|
|
9849
|
-
start_line:
|
|
9850
|
-
end_line:
|
|
9851
|
-
total_lines:
|
|
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:
|
|
9863
|
-
canvas:
|
|
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:
|
|
9867
|
-
limit:
|
|
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
|
|
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:
|
|
9915
|
-
canvas:
|
|
9916
|
-
content:
|
|
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
|
|
10642
|
+
import { z as z43 } from "zod";
|
|
10132
10643
|
function slackChannelIdParam(description) {
|
|
10133
|
-
return
|
|
10644
|
+
return z43.string().min(1).describe(description);
|
|
10134
10645
|
}
|
|
10135
10646
|
function slackUserIdParam(description) {
|
|
10136
|
-
return
|
|
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
|
|
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:
|
|
10171
|
-
items:
|
|
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:
|
|
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
|
|
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:
|
|
10234
|
-
name:
|
|
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
|
|
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:
|
|
10275
|
-
limit:
|
|
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
|
|
10295
|
-
var booleanInput3 = (description) =>
|
|
10805
|
+
import { z as z47 } from "zod";
|
|
10806
|
+
var booleanInput3 = (description) => z47.preprocess(
|
|
10296
10807
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
10297
|
-
|
|
10808
|
+
z47.boolean()
|
|
10298
10809
|
).describe(description);
|
|
10299
|
-
var updateListItemInputSchema =
|
|
10300
|
-
|
|
10301
|
-
item_id:
|
|
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:
|
|
10814
|
+
title: z47.string().min(1).describe("Optional new item title.").optional()
|
|
10304
10815
|
}),
|
|
10305
|
-
|
|
10306
|
-
item_id:
|
|
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:
|
|
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
|
|
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:
|
|
10563
|
-
url:
|
|
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:
|
|
10573
|
-
max_pages:
|
|
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
|
|
10802
|
-
var booleanInput4 = (description) =>
|
|
11312
|
+
import { z as z49 } from "zod";
|
|
11313
|
+
var booleanInput4 = (description) => z49.preprocess(
|
|
10803
11314
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
10804
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
11439
|
+
import { z as z50 } from "zod";
|
|
10929
11440
|
var systemTimeOutputSchema = juniorToolOutputSchema.extend({
|
|
10930
|
-
unix_ms:
|
|
10931
|
-
iso_utc:
|
|
10932
|
-
iso_local:
|
|
10933
|
-
timezone_offset_minutes:
|
|
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:
|
|
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
|
|
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 =
|
|
10980
|
-
var projectedEventSchema =
|
|
10981
|
-
seq:
|
|
10982
|
-
history_version:
|
|
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:
|
|
10986
|
-
idempotency_key:
|
|
10987
|
-
data:
|
|
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:
|
|
10993
|
-
events:
|
|
10994
|
-
has_older:
|
|
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:
|
|
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:
|
|
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:
|
|
11016
|
-
conversation_id:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
11787
|
+
import { z as z52 } from "zod";
|
|
11277
11788
|
var HANDOFF_TOOL_NAME = "handoff";
|
|
11278
11789
|
function createHandoffTool(handoff) {
|
|
11279
|
-
const profileSchema =
|
|
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:
|
|
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
|
|
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:
|
|
11758
|
-
url:
|
|
11759
|
-
max_chars:
|
|
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
|
|
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:
|
|
11847
|
-
query:
|
|
11848
|
-
max_results:
|
|
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
|
|
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:
|
|
11899
|
-
path:
|
|
11900
|
-
content:
|
|
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 =
|
|
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
|
|
12785
|
+
function isRecord3(value) {
|
|
12282
12786
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
12283
12787
|
}
|
|
12284
12788
|
function hasContinuation(value) {
|
|
12285
|
-
return
|
|
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 (!
|
|
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 (!
|
|
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 =
|
|
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
|
|
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:
|
|
12963
|
-
tool_name:
|
|
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:
|
|
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
|
|
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 =
|
|
13012
|
-
id:
|
|
13013
|
-
description:
|
|
13515
|
+
var searchToolsSourceSchema = z57.object({
|
|
13516
|
+
id: z57.string(),
|
|
13517
|
+
description: z57.string()
|
|
13014
13518
|
}).strict();
|
|
13015
|
-
var searchToolsToolSchema =
|
|
13016
|
-
tool_name:
|
|
13017
|
-
description:
|
|
13018
|
-
exposure:
|
|
13019
|
-
source:
|
|
13020
|
-
input_schema:
|
|
13021
|
-
call_notes:
|
|
13022
|
-
annotations:
|
|
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:
|
|
13026
|
-
source:
|
|
13027
|
-
sources:
|
|
13028
|
-
total_catalog_tools:
|
|
13029
|
-
total_eligible_tools:
|
|
13030
|
-
total_matches:
|
|
13031
|
-
returned_tools:
|
|
13032
|
-
execution_tool:
|
|
13033
|
-
tools:
|
|
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:
|
|
13149
|
-
query:
|
|
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:
|
|
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:
|
|
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
|
|
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 =
|
|
14467
|
-
decision:
|
|
14468
|
-
reason:
|
|
14469
|
-
riskLevel:
|
|
14470
|
-
userAuthorization:
|
|
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(
|
|
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
|
-
|
|
17359
|
+
sanitizeScheduledTaskPrincipal,
|
|
16856
17360
|
listThreadReplies,
|
|
16857
17361
|
renderSlackLegacyAttachmentText,
|
|
16858
17362
|
appendSlackLegacyAttachmentText,
|