@sentry/junior 0.194.0 → 0.196.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-IDX764FD.js → agent-hooks-IQLRR4RC.js} +13 -13
- package/dist/api/activity.d.ts +9 -1
- package/dist/api/code/overview.d.ts +12 -0
- package/dist/api/locations/detail.d.ts +8 -0
- package/dist/api/locations/list.d.ts +5 -0
- package/dist/api/people/code.d.ts +6 -0
- package/dist/api/people/shared.d.ts +9 -1
- package/dist/api/reporting-window.d.ts +39 -1
- package/dist/api/schema/code.d.ts +12 -0
- package/dist/api/schema/conversation.d.ts +25 -0
- package/dist/api/schema/location.d.ts +13 -0
- package/dist/api/schema/person.d.ts +14 -0
- package/dist/api/schema/task.d.ts +12 -0
- package/dist/api/schema.js +3 -3
- package/dist/api.js +244 -65
- package/dist/app.d.ts +8 -2
- package/dist/app.js +166 -70
- package/dist/{catalog-runtime-MICXEBLK.js → catalog-runtime-EM7V2F4I.js} +4 -4
- package/dist/chat/agent/handoff.d.ts +73 -0
- package/dist/chat/config.d.ts +3 -2
- package/dist/chat/event-tasks/store.d.ts +27 -17
- package/dist/chat/model-profile.d.ts +12 -0
- package/dist/chat/no-reply.d.ts +4 -3
- package/dist/chat/resource-events/notification.d.ts +2 -1
- package/dist/chat/services/automated-turn-limit.d.ts +110 -0
- package/dist/chat/services/subscribed-decision.d.ts +8 -0
- package/dist/chat/slack/automated-turn-limit-notice.d.ts +38 -0
- package/dist/chat/tasks/execution-stats.d.ts +2 -1
- package/dist/chat/tasks/read.d.ts +5 -2
- package/dist/chat/tools/types.d.ts +6 -2
- package/dist/{chunk-U76RWMFR.js → chunk-5XSEOJPC.js} +87 -14
- package/dist/{chunk-OEQOAONV.js → chunk-6LQNW2CJ.js} +7 -7
- package/dist/{chunk-GFBR4S3Q.js → chunk-7NL7T6VU.js} +1 -1
- package/dist/{chunk-CFGBKPWQ.js → chunk-7TUDDW3Y.js} +3 -3
- package/dist/{chunk-RFE7DCZK.js → chunk-B5WJBVHY.js} +2 -2
- package/dist/{chunk-S7GX44BU.js → chunk-BXIVMNLR.js} +1 -1
- package/dist/{chunk-QMEF4Z7R.js → chunk-CNI74T7U.js} +6 -6
- package/dist/{chunk-X76JVHQ4.js → chunk-CTS72G4B.js} +1 -1
- package/dist/{chunk-G35QGPO2.js → chunk-DFWJJOW3.js} +2 -6
- package/dist/{chunk-INTBMGNX.js → chunk-EEUFKVCD.js} +22 -22
- package/dist/{chunk-H4DCWLTR.js → chunk-EFNUCRB5.js} +8 -8
- package/dist/{chunk-V4HXV5MY.js → chunk-EQBHN4JK.js} +1 -1
- package/dist/{chunk-JOI3DHML.js → chunk-ES7KCEND.js} +1 -1
- package/dist/{chunk-WWXJUURQ.js → chunk-G6YRPYDC.js} +1 -1
- package/dist/{chunk-WMJS5DDV.js → chunk-GZ336GZ5.js} +148 -19
- package/dist/{chunk-IME5OW4Y.js → chunk-I7GEGEHZ.js} +1 -1
- package/dist/{chunk-2NL3Y47F.js → chunk-J357NJQ5.js} +5 -5
- package/dist/{chunk-53IEEFFP.js → chunk-KJGH3KWA.js} +3 -3
- package/dist/{chunk-ELCYG6UU.js → chunk-KZX7LORG.js} +3 -3
- package/dist/{chunk-YSLIB7ER.js → chunk-LBN67OZR.js} +83 -7
- package/dist/{chunk-73JEAQRT.js → chunk-LCAM2P7H.js} +4 -4
- package/dist/{chunk-VOB2DKO6.js → chunk-LGXI6PWX.js} +24 -13
- package/dist/{chunk-P2P6MUQ4.js → chunk-LSPUMNZK.js} +2 -2
- package/dist/{chunk-AWZS5SVX.js → chunk-N2MSPOGG.js} +8 -8
- package/dist/{chunk-CCTYK5RH.js → chunk-NE2UQMC7.js} +10 -7
- package/dist/{chunk-D4YV5TDV.js → chunk-NHJU2ZAL.js} +11 -0
- package/dist/{chunk-G4RARFNT.js → chunk-OVWAO5KY.js} +1194 -726
- package/dist/{chunk-XRDSML3K.js → chunk-P3LE2CSJ.js} +2 -2
- package/dist/{chunk-KNIAWMBU.js → chunk-PI6VXVBK.js} +1 -1
- package/dist/{chunk-XLWZRHX5.js → chunk-PIZJBSGZ.js} +23 -29
- package/dist/{chunk-GY5SEFVL.js → chunk-QAINJHI4.js} +5 -5
- package/dist/{chunk-XND3J6AT.js → chunk-RAWYH7TW.js} +1 -1
- package/dist/{chunk-ENWIHU54.js → chunk-RFNMWONZ.js} +6 -6
- package/dist/{chunk-E53C73ML.js → chunk-S74KAE77.js} +4 -4
- package/dist/{chunk-7ANA7PBB.js → chunk-SR5FS2JP.js} +3 -3
- package/dist/{chunk-F2KSURTJ.js → chunk-VKLQ2M7V.js} +9 -9
- package/dist/{chunk-NWWDFHXP.js → chunk-VRHZXY5X.js} +1 -1
- package/dist/{chunk-6H2MKVV5.js → chunk-VSOO3Y6M.js} +1 -1
- package/dist/{chunk-NPO24LAN.js → chunk-VVU7GHIZ.js} +9 -9
- package/dist/{chunk-IOGDKPVU.js → chunk-VXAQTJSR.js} +1 -1
- package/dist/{chunk-ADEACKAH.js → chunk-XNXKRWWI.js} +11 -4
- package/dist/cli/chat.js +35 -35
- package/dist/cli/check.js +5 -5
- package/dist/cli/plugins.js +14 -14
- package/dist/cli/snapshot-create.js +10 -10
- package/dist/cli/upgrade.js +7 -7
- package/dist/db/schema/event-tasks.d.ts +21 -0
- package/dist/db/schema.d.ts +19 -0
- package/dist/{db-3IEVINAY.js → db-YTM7ZXPK.js} +8 -8
- package/dist/instrumentation.js +3 -3
- package/dist/nitro.js +7 -7
- package/dist/{oauth-callback-server-N7L2BB4L.js → oauth-callback-server-OXW4KQLQ.js} +31 -31
- package/dist/{runner-PTTZV3WU.js → runner-RJY5RNJO.js} +23 -23
- package/dist/{skills-POMWS2RR.js → skills-WZV6NLFY.js} +5 -5
- package/dist/spawn-J7SQJLYF.js +42 -0
- package/dist/task-runner-SMUQ5464.js +36 -0
- package/dist/{validation-U6LOMXR7.js → validation-XS5ZHV3W.js} +5 -5
- package/dist/version.js +1 -1
- package/dist/{work-FHA3BS4L.js → work-LJMSDEY3.js} +23 -23
- package/dist/worker-NMFZ7A2N.js +24 -0
- package/migrations/0038_event_task_status.sql +5 -0
- package/migrations/meta/0038_snapshot.json +3323 -0
- package/migrations/meta/_journal.json +8 -1
- package/package.json +4 -4
- package/dist/spawn-R75MXXKE.js +0 -42
- package/dist/task-runner-OQLRHADB.js +0 -36
- package/dist/worker-GR4UNVVP.js +0 -24
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
PluginCredentialFailureError,
|
|
8
8
|
agentNameSchema,
|
|
9
9
|
createPluginAuthOrchestration
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-CNI74T7U.js";
|
|
11
11
|
import {
|
|
12
12
|
parseSandboxEgressAuthRequiredSignal,
|
|
13
13
|
parseSandboxEgressPermissionDeniedSignal,
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
searchSlackUsers,
|
|
39
39
|
selectPluginGrant,
|
|
40
40
|
toMcpProviderError
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-N2MSPOGG.js";
|
|
42
42
|
import {
|
|
43
43
|
RetryableDeliveryError,
|
|
44
44
|
actorFromRun,
|
|
@@ -48,24 +48,24 @@ import {
|
|
|
48
48
|
formatProviderLabel,
|
|
49
49
|
getSlackMessagePermalink,
|
|
50
50
|
isAgentRunFeatureDisabled,
|
|
51
|
+
postSlackMessage,
|
|
51
52
|
resolveBaseUrl,
|
|
52
53
|
surfaceFromRun,
|
|
53
54
|
toolInvocationDestination,
|
|
54
55
|
uploadFilesToConversation
|
|
55
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-RFNMWONZ.js";
|
|
56
57
|
import {
|
|
57
58
|
CooperativeTurnYieldError,
|
|
58
59
|
NO_REPLY_MARKER,
|
|
59
60
|
TurnInputCommitLostError,
|
|
60
61
|
abandonReplacedPendingAuth,
|
|
61
62
|
canReusePendingAuthLink,
|
|
62
|
-
containsNoReplyMarker,
|
|
63
63
|
decideReply,
|
|
64
64
|
getAssistantReplyText,
|
|
65
65
|
isNoReplyMarker,
|
|
66
66
|
isTurnInputCommitLostError,
|
|
67
67
|
sanitizeAssistantText
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-DFWJJOW3.js";
|
|
69
69
|
import {
|
|
70
70
|
AGENTS_REMOVAL_NOTICE,
|
|
71
71
|
AGENTS_REPLACEMENT_NOTICE,
|
|
@@ -121,7 +121,7 @@ import {
|
|
|
121
121
|
stripRuntimeTurnContext,
|
|
122
122
|
trimTrailingAssistantMessages,
|
|
123
123
|
truncateText
|
|
124
|
-
} from "./chunk-
|
|
124
|
+
} from "./chunk-6LQNW2CJ.js";
|
|
125
125
|
import {
|
|
126
126
|
SCHEDULED_TASK_SYSTEM_ACTOR,
|
|
127
127
|
WORKSPACE_SNAPSHOT_FAILED_EVENT,
|
|
@@ -162,13 +162,13 @@ import {
|
|
|
162
162
|
workspaceSnapshotFinishedEvent,
|
|
163
163
|
workspaceSnapshotWatch,
|
|
164
164
|
writableEventTask
|
|
165
|
-
} from "./chunk-
|
|
165
|
+
} from "./chunk-GZ336GZ5.js";
|
|
166
166
|
import {
|
|
167
167
|
parseSlackThreadId
|
|
168
|
-
} from "./chunk-
|
|
168
|
+
} from "./chunk-VXAQTJSR.js";
|
|
169
169
|
import {
|
|
170
170
|
appendAndEnqueueInboundMessage
|
|
171
|
-
} from "./chunk-
|
|
171
|
+
} from "./chunk-S74KAE77.js";
|
|
172
172
|
import {
|
|
173
173
|
SHORT_TITLE_MAX_LENGTH,
|
|
174
174
|
ToolInputError,
|
|
@@ -176,7 +176,7 @@ import {
|
|
|
176
176
|
generateShortTitle,
|
|
177
177
|
hasAgentTurnUsage,
|
|
178
178
|
resolveTaskTitle
|
|
179
|
-
} from "./chunk-
|
|
179
|
+
} from "./chunk-B5WJBVHY.js";
|
|
180
180
|
import {
|
|
181
181
|
bindSandboxFileSystem,
|
|
182
182
|
createSandboxSession,
|
|
@@ -187,7 +187,7 @@ import {
|
|
|
187
187
|
resolve,
|
|
188
188
|
setSnapshotSpanAttributes,
|
|
189
189
|
stopSession
|
|
190
|
-
} from "./chunk-
|
|
190
|
+
} from "./chunk-KZX7LORG.js";
|
|
191
191
|
import {
|
|
192
192
|
privateTraceResultAttributes
|
|
193
193
|
} from "./chunk-UIE3R5XU.js";
|
|
@@ -197,7 +197,7 @@ import {
|
|
|
197
197
|
} from "./chunk-X6GDDWQH.js";
|
|
198
198
|
import {
|
|
199
199
|
getTurnRequestDeadline
|
|
200
|
-
} from "./chunk-
|
|
200
|
+
} from "./chunk-VRHZXY5X.js";
|
|
201
201
|
import {
|
|
202
202
|
getVercelConversationWorkQueue
|
|
203
203
|
} from "./chunk-DKIJ2RP5.js";
|
|
@@ -244,19 +244,23 @@ import {
|
|
|
244
244
|
updateWorkspace,
|
|
245
245
|
withSlackRetries,
|
|
246
246
|
workspaceRepoCheckoutPath
|
|
247
|
-
} from "./chunk-
|
|
247
|
+
} from "./chunk-NE2UQMC7.js";
|
|
248
248
|
import {
|
|
249
|
+
JUNIOR_THREAD_STATE_TTL_MS
|
|
250
|
+
} from "./chunk-3Y47VMHV.js";
|
|
251
|
+
import {
|
|
252
|
+
destinationKey,
|
|
249
253
|
getConversationEventStore,
|
|
250
254
|
getConversationMessageSearchStore,
|
|
251
255
|
getConversationStore,
|
|
252
256
|
getDb,
|
|
253
257
|
getSqlExecutor
|
|
254
|
-
} from "./chunk-
|
|
258
|
+
} from "./chunk-XNXKRWWI.js";
|
|
255
259
|
import {
|
|
256
260
|
juniorArtifacts,
|
|
257
261
|
juniorIdentities,
|
|
258
262
|
juniorSchedulerRuns
|
|
259
|
-
} from "./chunk-
|
|
263
|
+
} from "./chunk-PIZJBSGZ.js";
|
|
260
264
|
import {
|
|
261
265
|
SANDBOX_DATA_ROOT,
|
|
262
266
|
SANDBOX_REPOS_ROOT,
|
|
@@ -287,19 +291,19 @@ import {
|
|
|
287
291
|
throwSandboxOperationError,
|
|
288
292
|
workspaceSnapshotNotReadyUserMessage,
|
|
289
293
|
wrapSandboxSetupError
|
|
290
|
-
} from "./chunk-
|
|
294
|
+
} from "./chunk-SR5FS2JP.js";
|
|
291
295
|
import {
|
|
292
296
|
fenceLock,
|
|
293
297
|
getStateAdapter,
|
|
294
298
|
withLock
|
|
295
|
-
} from "./chunk-
|
|
299
|
+
} from "./chunk-EQBHN4JK.js";
|
|
296
300
|
import {
|
|
297
301
|
KNOWN_CONVERSATION_EVENT_TYPES,
|
|
298
302
|
contextProvenance,
|
|
299
303
|
instructionActors,
|
|
300
304
|
instructionProvenanceFor,
|
|
301
305
|
sameActorIdentity
|
|
302
|
-
} from "./chunk-
|
|
306
|
+
} from "./chunk-7NL7T6VU.js";
|
|
303
307
|
import {
|
|
304
308
|
ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX,
|
|
305
309
|
COMPACTION_SUMMARY_PREFIX,
|
|
@@ -325,14 +329,16 @@ import {
|
|
|
325
329
|
resolveGatewayCredential,
|
|
326
330
|
resolveGatewayModel,
|
|
327
331
|
unwrapCurrentInstruction
|
|
328
|
-
} from "./chunk-
|
|
332
|
+
} from "./chunk-5XSEOJPC.js";
|
|
329
333
|
import {
|
|
330
334
|
ModelProfileNotConfiguredError,
|
|
331
335
|
TURN_REASONING_LEVELS,
|
|
336
|
+
formatModelProfile,
|
|
337
|
+
formatModelProfiles,
|
|
332
338
|
modelIdForProfile,
|
|
333
339
|
modelProfileSchema,
|
|
334
340
|
profileConfig
|
|
335
|
-
} from "./chunk-
|
|
341
|
+
} from "./chunk-NHJU2ZAL.js";
|
|
336
342
|
import {
|
|
337
343
|
canExposeConversationPayload,
|
|
338
344
|
resolveConversationPrivacy,
|
|
@@ -342,16 +348,16 @@ import {
|
|
|
342
348
|
toGenAiMessagesTraceAttributes,
|
|
343
349
|
toGenAiPayloadMetadata,
|
|
344
350
|
toGenAiPayloadTraceAttributes
|
|
345
|
-
} from "./chunk-
|
|
351
|
+
} from "./chunk-ES7KCEND.js";
|
|
346
352
|
import {
|
|
347
353
|
discoverSkills,
|
|
348
354
|
findSkillByName,
|
|
349
355
|
loadSkillsByName,
|
|
350
356
|
parseSkillInvocation
|
|
351
|
-
} from "./chunk-
|
|
357
|
+
} from "./chunk-LSPUMNZK.js";
|
|
352
358
|
import {
|
|
353
359
|
pluginCatalogRuntime
|
|
354
|
-
} from "./chunk-
|
|
360
|
+
} from "./chunk-G6YRPYDC.js";
|
|
355
361
|
import {
|
|
356
362
|
CredentialUnavailableError,
|
|
357
363
|
OAuthProviderError,
|
|
@@ -359,7 +365,7 @@ import {
|
|
|
359
365
|
getOAuthProviderErrorAttributes,
|
|
360
366
|
resolveAuthTokenPlaceholder,
|
|
361
367
|
resolvePluginCommandEnv
|
|
362
|
-
} from "./chunk-
|
|
368
|
+
} from "./chunk-BXIVMNLR.js";
|
|
363
369
|
import {
|
|
364
370
|
credentialContextForActor,
|
|
365
371
|
credentialUserSubjectId
|
|
@@ -395,7 +401,7 @@ import {
|
|
|
395
401
|
summarizeMessageText,
|
|
396
402
|
withLogContext,
|
|
397
403
|
withSpan
|
|
398
|
-
} from "./chunk-
|
|
404
|
+
} from "./chunk-CTS72G4B.js";
|
|
399
405
|
import {
|
|
400
406
|
startInactiveSpan,
|
|
401
407
|
withActiveSpan
|
|
@@ -919,11 +925,6 @@ function buildTurnResult(input) {
|
|
|
919
925
|
if (!isProviderError) {
|
|
920
926
|
logInfo("ai.no_reply_marker.accepted", markerAttributes);
|
|
921
927
|
}
|
|
922
|
-
} else if (containsNoReplyMarker(rawPrimaryText)) {
|
|
923
|
-
logWarn("ai.no_reply_marker.mixed_text", {
|
|
924
|
-
"app.ai.no_reply_marker": true,
|
|
925
|
-
"app.ai.no_reply_marker_mode": "mixed"
|
|
926
|
-
});
|
|
927
928
|
}
|
|
928
929
|
if (!primaryText && !completedWithoutTerminalText && !isProviderError) {
|
|
929
930
|
logWarn("ai.model_response.empty", {
|
|
@@ -1141,11 +1142,11 @@ function trimContextForRouter(text) {
|
|
|
1141
1142
|
originalCharCount: trimmed.length
|
|
1142
1143
|
};
|
|
1143
1144
|
}
|
|
1144
|
-
function buildClassifierSystemPrompt(profileNames, defaultProfile) {
|
|
1145
|
+
function buildClassifierSystemPrompt(profiles, profileNames, defaultProfile) {
|
|
1146
|
+
const profileList = formatModelProfiles(profiles, profileNames);
|
|
1145
1147
|
return [
|
|
1146
1148
|
"You choose the model profile most likely to produce a complete, source-grounded answer.",
|
|
1147
1149
|
"Choose exactly one bucket: none, low, medium, high, or xhigh.",
|
|
1148
|
-
`Choose profile from the configured profiles: ${profileNames.join(", ")}.`,
|
|
1149
1150
|
"Choose profile independently from the reasoning bucket.",
|
|
1150
1151
|
"",
|
|
1151
1152
|
"Use none only for greetings, acknowledgments, and turns that need no substantive assistant work.",
|
|
@@ -1154,9 +1155,11 @@ function buildClassifierSystemPrompt(profileNames, defaultProfile) {
|
|
|
1154
1155
|
"Use high for research-heavy work, non-trivial drafting, or explicit requests to be thorough.",
|
|
1155
1156
|
"Use xhigh for the most complex tasks: code changes, debugging/root-cause analysis, broad refactors, architecture decisions, multi-file implementation, or any task where deep reasoning across multiple systems or files is required.",
|
|
1156
1157
|
"When unsure between two non-none buckets, choose the higher bucket. Do not use low as the default.",
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
"
|
|
1158
|
+
"",
|
|
1159
|
+
`Default profile: "${defaultProfile}". Keep it unless another profile's description is a clearly better fit.`,
|
|
1160
|
+
"Configured profiles (use each description's use and avoid cases; names are labels only; non-default does not mean stronger):",
|
|
1161
|
+
profileList,
|
|
1162
|
+
"Choose a non-default profile only when its description clearly fits the task. If no description clearly fits, keep the default profile.",
|
|
1160
1163
|
"",
|
|
1161
1164
|
"Classify based on the substance of the task, not the length of the current message. When the current instruction is a short affirmation (for example: 'go', 'do it', 'yes please', 'proceed') and prior thread context contains a pending task, classify the pending task \u2014 not the affirmation.",
|
|
1162
1165
|
"",
|
|
@@ -1294,6 +1297,7 @@ async function classifyTurn(args) {
|
|
|
1294
1297
|
prompt: args.prompt,
|
|
1295
1298
|
thinkingLevel: "low",
|
|
1296
1299
|
system: buildClassifierSystemPrompt(
|
|
1300
|
+
args.profiles,
|
|
1297
1301
|
Object.keys(args.profiles),
|
|
1298
1302
|
args.defaultProfile
|
|
1299
1303
|
),
|
|
@@ -1728,7 +1732,7 @@ var TOOL_POLICY_RULES = [
|
|
|
1728
1732
|
"- 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.",
|
|
1729
1733
|
"- Event tasks list for the current destination, not one thread. Public tasks can also be updated or deleted by task id from another destination in the same workspace. 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.",
|
|
1730
1734
|
"- 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.",
|
|
1731
|
-
"-
|
|
1735
|
+
"- When another model profile fits the task better, call `handoff` before substantial work. Follow the profile list and selection rules in the tool description.",
|
|
1732
1736
|
"- 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.",
|
|
1733
1737
|
"- 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."
|
|
1734
1738
|
];
|
|
@@ -3096,11 +3100,358 @@ async function prepareWorkspaceSnapshot(params) {
|
|
|
3096
3100
|
// src/chat/resource-events/ingest.ts
|
|
3097
3101
|
import { resourceEventSchema } from "@sentry/junior-plugin-api";
|
|
3098
3102
|
|
|
3103
|
+
// src/chat/services/automated-turn-limit.ts
|
|
3104
|
+
import { z as z3 } from "zod";
|
|
3105
|
+
var AUTOMATED_TURN_LIMIT_PREFIX = "junior:automated_turn_limit:v1";
|
|
3106
|
+
var AUTOMATED_TURN_LIMIT_LOCK_TTL_MS = 5e3;
|
|
3107
|
+
var AUTOMATED_TURN_LIMIT_LOCK_WAIT_MS = 2e3;
|
|
3108
|
+
var AUTOMATED_TURN_LIMIT_LOCK_RETRY_MS = 25;
|
|
3109
|
+
var automatedTurnLimitStateSchema = z3.object({
|
|
3110
|
+
consecutiveAutomatedTurns: z3.number().int().nonnegative(),
|
|
3111
|
+
noticePostedAtMs: z3.number().finite().nonnegative().optional(),
|
|
3112
|
+
paused: z3.boolean(),
|
|
3113
|
+
updatedAtMs: z3.number().finite().nonnegative()
|
|
3114
|
+
}).strict();
|
|
3115
|
+
function sleep2(ms) {
|
|
3116
|
+
return new Promise((resolve2) => {
|
|
3117
|
+
const timer = setTimeout(resolve2, ms);
|
|
3118
|
+
timer.unref?.();
|
|
3119
|
+
});
|
|
3120
|
+
}
|
|
3121
|
+
function scopeKey(scope) {
|
|
3122
|
+
if (scope.kind === "conversation") {
|
|
3123
|
+
return `${AUTOMATED_TURN_LIMIT_PREFIX}:conversation:${scope.conversationId}`;
|
|
3124
|
+
}
|
|
3125
|
+
return `${AUTOMATED_TURN_LIMIT_PREFIX}:destination:${destinationKey(scope.destination)}`;
|
|
3126
|
+
}
|
|
3127
|
+
function lockKey(key) {
|
|
3128
|
+
return `${key}:lock`;
|
|
3129
|
+
}
|
|
3130
|
+
function parseState(value) {
|
|
3131
|
+
const parsed = automatedTurnLimitStateSchema.safeParse(value);
|
|
3132
|
+
return parsed.success ? parsed.data : void 0;
|
|
3133
|
+
}
|
|
3134
|
+
async function acquireScopeLock(state, key, waitDeadlineMs = Date.now() + AUTOMATED_TURN_LIMIT_LOCK_WAIT_MS) {
|
|
3135
|
+
while (true) {
|
|
3136
|
+
const lock = await state.acquireLock(
|
|
3137
|
+
lockKey(key),
|
|
3138
|
+
AUTOMATED_TURN_LIMIT_LOCK_TTL_MS
|
|
3139
|
+
);
|
|
3140
|
+
if (lock) {
|
|
3141
|
+
return lock;
|
|
3142
|
+
}
|
|
3143
|
+
if (Date.now() >= waitDeadlineMs) {
|
|
3144
|
+
throw new Error(`Could not acquire automated turn limit lock for ${key}`);
|
|
3145
|
+
}
|
|
3146
|
+
await sleep2(AUTOMATED_TURN_LIMIT_LOCK_RETRY_MS);
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
async function withScopeLock(state, key, callback) {
|
|
3150
|
+
const lock = await acquireScopeLock(state, key);
|
|
3151
|
+
try {
|
|
3152
|
+
return await callback();
|
|
3153
|
+
} finally {
|
|
3154
|
+
await state.releaseLock(lock);
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
function emptyState(nowMs) {
|
|
3158
|
+
return {
|
|
3159
|
+
consecutiveAutomatedTurns: 0,
|
|
3160
|
+
paused: false,
|
|
3161
|
+
updatedAtMs: nowMs
|
|
3162
|
+
};
|
|
3163
|
+
}
|
|
3164
|
+
function resumeInForScope(scope) {
|
|
3165
|
+
return scope.kind === "conversation" ? "thread" : "channel";
|
|
3166
|
+
}
|
|
3167
|
+
function isAutomatedTurnSource(source) {
|
|
3168
|
+
if (!source) {
|
|
3169
|
+
return false;
|
|
3170
|
+
}
|
|
3171
|
+
return source.kind === "resource_event" || source.kind === "event_task" || source.kind === "scheduled_task" || source.kind === "plugin_dispatch" || source.kind === "agent_invocation";
|
|
3172
|
+
}
|
|
3173
|
+
function automatedTurnLimitScopeForSource(args) {
|
|
3174
|
+
if (!isAutomatedTurnSource(args.source)) {
|
|
3175
|
+
return void 0;
|
|
3176
|
+
}
|
|
3177
|
+
if (args.source?.kind === "resource_event") {
|
|
3178
|
+
return {
|
|
3179
|
+
kind: "conversation",
|
|
3180
|
+
conversationId: args.conversationId
|
|
3181
|
+
};
|
|
3182
|
+
}
|
|
3183
|
+
if (args.destination) {
|
|
3184
|
+
return { kind: "destination", destination: args.destination };
|
|
3185
|
+
}
|
|
3186
|
+
return {
|
|
3187
|
+
kind: "conversation",
|
|
3188
|
+
conversationId: args.conversationId
|
|
3189
|
+
};
|
|
3190
|
+
}
|
|
3191
|
+
function buildAutomatedTurnLimitResponse(args) {
|
|
3192
|
+
const place = args.resumeIn === "channel" ? "channel" : "thread";
|
|
3193
|
+
return `I stopped automatic updates after ${args.maxTurns} replies without a new message from you. Send a message or @mention me in this ${place} to continue.`;
|
|
3194
|
+
}
|
|
3195
|
+
async function admitAutomatedTurn(args) {
|
|
3196
|
+
if (args.maxTurns < 1) {
|
|
3197
|
+
throw new Error("Automated turn limit must be at least 1");
|
|
3198
|
+
}
|
|
3199
|
+
const state = args.state ?? getStateAdapter();
|
|
3200
|
+
await state.connect();
|
|
3201
|
+
const nowMs = args.nowMs ?? Date.now();
|
|
3202
|
+
const key = scopeKey(args.scope);
|
|
3203
|
+
return await withScopeLock(state, key, async () => {
|
|
3204
|
+
const current = parseState(await state.get(key)) ?? emptyState(nowMs);
|
|
3205
|
+
if (current.paused || current.consecutiveAutomatedTurns >= args.maxTurns) {
|
|
3206
|
+
const shouldPostNotice = current.noticePostedAtMs === void 0;
|
|
3207
|
+
const next = {
|
|
3208
|
+
consecutiveAutomatedTurns: Math.max(
|
|
3209
|
+
current.consecutiveAutomatedTurns,
|
|
3210
|
+
args.maxTurns
|
|
3211
|
+
),
|
|
3212
|
+
paused: true,
|
|
3213
|
+
updatedAtMs: nowMs,
|
|
3214
|
+
// Claim the notice slot so concurrent paused wakes do not all post.
|
|
3215
|
+
// Callers must mark success or clear the claim if the post fails.
|
|
3216
|
+
...shouldPostNotice ? { noticePostedAtMs: nowMs } : current.noticePostedAtMs !== void 0 ? { noticePostedAtMs: current.noticePostedAtMs } : void 0
|
|
3217
|
+
};
|
|
3218
|
+
await state.set(key, next, JUNIOR_THREAD_STATE_TTL_MS);
|
|
3219
|
+
return {
|
|
3220
|
+
status: "paused",
|
|
3221
|
+
consecutiveAutomatedTurns: next.consecutiveAutomatedTurns,
|
|
3222
|
+
shouldPostNotice
|
|
3223
|
+
};
|
|
3224
|
+
}
|
|
3225
|
+
return {
|
|
3226
|
+
status: "allow",
|
|
3227
|
+
consecutiveAutomatedTurns: current.consecutiveAutomatedTurns
|
|
3228
|
+
};
|
|
3229
|
+
});
|
|
3230
|
+
}
|
|
3231
|
+
async function countAutomatedTurn(args) {
|
|
3232
|
+
if (args.maxTurns < 1) {
|
|
3233
|
+
throw new Error("Automated turn limit must be at least 1");
|
|
3234
|
+
}
|
|
3235
|
+
const state = args.state ?? getStateAdapter();
|
|
3236
|
+
await state.connect();
|
|
3237
|
+
const nowMs = args.nowMs ?? Date.now();
|
|
3238
|
+
const key = scopeKey(args.scope);
|
|
3239
|
+
const resumeIn = resumeInForScope(args.scope);
|
|
3240
|
+
return await withScopeLock(state, key, async () => {
|
|
3241
|
+
const current = parseState(await state.get(key)) ?? emptyState(nowMs);
|
|
3242
|
+
const consecutiveAutomatedTurns = current.consecutiveAutomatedTurns + 1;
|
|
3243
|
+
const paused = consecutiveAutomatedTurns >= args.maxTurns;
|
|
3244
|
+
const shouldPostNotice = paused && current.noticePostedAtMs === void 0;
|
|
3245
|
+
const next = {
|
|
3246
|
+
consecutiveAutomatedTurns,
|
|
3247
|
+
paused,
|
|
3248
|
+
updatedAtMs: nowMs,
|
|
3249
|
+
// Claim the notice slot before the destination post. Mark success after
|
|
3250
|
+
// the post lands; clear the claim if the post fails or is skipped.
|
|
3251
|
+
...shouldPostNotice ? { noticePostedAtMs: nowMs } : current.noticePostedAtMs !== void 0 ? { noticePostedAtMs: current.noticePostedAtMs } : void 0
|
|
3252
|
+
};
|
|
3253
|
+
await state.set(key, next, JUNIOR_THREAD_STATE_TTL_MS);
|
|
3254
|
+
return {
|
|
3255
|
+
consecutiveAutomatedTurns,
|
|
3256
|
+
paused,
|
|
3257
|
+
shouldPostNotice,
|
|
3258
|
+
resumeIn
|
|
3259
|
+
};
|
|
3260
|
+
});
|
|
3261
|
+
}
|
|
3262
|
+
async function clearAutomatedTurnLimitNoticeClaim(args) {
|
|
3263
|
+
const state = args.state ?? getStateAdapter();
|
|
3264
|
+
await state.connect();
|
|
3265
|
+
const nowMs = args.nowMs ?? Date.now();
|
|
3266
|
+
const key = scopeKey(args.scope);
|
|
3267
|
+
await withScopeLock(state, key, async () => {
|
|
3268
|
+
const current = parseState(await state.get(key));
|
|
3269
|
+
if (!current || current.noticePostedAtMs === void 0) {
|
|
3270
|
+
return;
|
|
3271
|
+
}
|
|
3272
|
+
const { noticePostedAtMs: _noticePostedAtMs, ...rest } = current;
|
|
3273
|
+
await state.set(
|
|
3274
|
+
key,
|
|
3275
|
+
{
|
|
3276
|
+
...rest,
|
|
3277
|
+
updatedAtMs: nowMs
|
|
3278
|
+
},
|
|
3279
|
+
JUNIOR_THREAD_STATE_TTL_MS
|
|
3280
|
+
);
|
|
3281
|
+
});
|
|
3282
|
+
}
|
|
3283
|
+
async function resetAutomatedTurnLimit(args) {
|
|
3284
|
+
const state = args.state ?? getStateAdapter();
|
|
3285
|
+
await state.connect();
|
|
3286
|
+
const key = scopeKey(args.scope);
|
|
3287
|
+
await withScopeLock(state, key, async () => {
|
|
3288
|
+
await state.delete(key);
|
|
3289
|
+
});
|
|
3290
|
+
}
|
|
3291
|
+
async function recordFinishedTurnForAutomatedLimit(args) {
|
|
3292
|
+
const nowMs = args.nowMs ?? Date.now();
|
|
3293
|
+
const automatedScope = automatedTurnLimitScopeForSource({
|
|
3294
|
+
conversationId: args.conversationId,
|
|
3295
|
+
destination: args.destination,
|
|
3296
|
+
source: args.source
|
|
3297
|
+
});
|
|
3298
|
+
if (automatedScope) {
|
|
3299
|
+
return await countAutomatedTurn({
|
|
3300
|
+
maxTurns: args.maxTurns,
|
|
3301
|
+
nowMs,
|
|
3302
|
+
scope: automatedScope,
|
|
3303
|
+
state: args.state
|
|
3304
|
+
});
|
|
3305
|
+
}
|
|
3306
|
+
await resetAutomatedTurnLimit({
|
|
3307
|
+
nowMs,
|
|
3308
|
+
scope: {
|
|
3309
|
+
kind: "conversation",
|
|
3310
|
+
conversationId: args.conversationId
|
|
3311
|
+
},
|
|
3312
|
+
state: args.state
|
|
3313
|
+
});
|
|
3314
|
+
if (args.destination) {
|
|
3315
|
+
await resetAutomatedTurnLimit({
|
|
3316
|
+
nowMs,
|
|
3317
|
+
scope: { kind: "destination", destination: args.destination },
|
|
3318
|
+
state: args.state
|
|
3319
|
+
});
|
|
3320
|
+
}
|
|
3321
|
+
return void 0;
|
|
3322
|
+
}
|
|
3323
|
+
|
|
3324
|
+
// src/chat/slack/automated-turn-limit-notice.ts
|
|
3325
|
+
async function releaseFailedNoticeClaim(args) {
|
|
3326
|
+
try {
|
|
3327
|
+
await clearAutomatedTurnLimitNoticeClaim(args);
|
|
3328
|
+
} catch (error) {
|
|
3329
|
+
logException(error, "automated_turn_limit.notice_claim_clear_failed");
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
async function postAutomatedTurnLimitNoticeForConversation(args) {
|
|
3333
|
+
const scope = args.scope ?? {
|
|
3334
|
+
kind: "conversation",
|
|
3335
|
+
conversationId: args.conversationId
|
|
3336
|
+
};
|
|
3337
|
+
try {
|
|
3338
|
+
const conversation = await getConversationStore().get({
|
|
3339
|
+
conversationId: args.conversationId
|
|
3340
|
+
});
|
|
3341
|
+
const location = conversation?.location;
|
|
3342
|
+
if (!location || location.provider !== "slack") {
|
|
3343
|
+
logWarn("automated_turn_limit.notice_skipped", {
|
|
3344
|
+
conversationId: args.conversationId,
|
|
3345
|
+
"app.automated_turn_limit.reason": location ? "unsupported_location" : "missing_location"
|
|
3346
|
+
});
|
|
3347
|
+
await releaseFailedNoticeClaim({
|
|
3348
|
+
nowMs: args.nowMs,
|
|
3349
|
+
scope
|
|
3350
|
+
});
|
|
3351
|
+
return false;
|
|
3352
|
+
}
|
|
3353
|
+
await postSlackMessage({
|
|
3354
|
+
channelId: location.channelId,
|
|
3355
|
+
text: buildAutomatedTurnLimitResponse({
|
|
3356
|
+
maxTurns: args.maxTurns,
|
|
3357
|
+
resumeIn: args.resumeIn ?? "thread"
|
|
3358
|
+
}),
|
|
3359
|
+
...location.threadTs ? { threadTs: location.threadTs } : void 0
|
|
3360
|
+
});
|
|
3361
|
+
return true;
|
|
3362
|
+
} catch (error) {
|
|
3363
|
+
logException(error, "automated_turn_limit.notice_failed", {
|
|
3364
|
+
conversationId: args.conversationId
|
|
3365
|
+
});
|
|
3366
|
+
await releaseFailedNoticeClaim({
|
|
3367
|
+
nowMs: args.nowMs,
|
|
3368
|
+
scope
|
|
3369
|
+
});
|
|
3370
|
+
return false;
|
|
3371
|
+
}
|
|
3372
|
+
}
|
|
3373
|
+
async function postAutomatedTurnLimitNoticeForDestination(args) {
|
|
3374
|
+
const scope = args.scope ?? {
|
|
3375
|
+
kind: "destination",
|
|
3376
|
+
destination: args.destination
|
|
3377
|
+
};
|
|
3378
|
+
if (args.destination.platform !== "slack") {
|
|
3379
|
+
logWarn("automated_turn_limit.notice_skipped", {
|
|
3380
|
+
"app.automated_turn_limit.reason": "unsupported_destination"
|
|
3381
|
+
});
|
|
3382
|
+
await releaseFailedNoticeClaim({
|
|
3383
|
+
nowMs: args.nowMs,
|
|
3384
|
+
scope
|
|
3385
|
+
});
|
|
3386
|
+
return false;
|
|
3387
|
+
}
|
|
3388
|
+
try {
|
|
3389
|
+
await postSlackMessage({
|
|
3390
|
+
channelId: args.destination.channelId,
|
|
3391
|
+
text: buildAutomatedTurnLimitResponse({
|
|
3392
|
+
maxTurns: args.maxTurns,
|
|
3393
|
+
resumeIn: args.resumeIn ?? "channel"
|
|
3394
|
+
}),
|
|
3395
|
+
...args.threadTs ? { threadTs: args.threadTs } : void 0
|
|
3396
|
+
});
|
|
3397
|
+
return true;
|
|
3398
|
+
} catch (error) {
|
|
3399
|
+
logException(error, "automated_turn_limit.notice_failed", {
|
|
3400
|
+
"app.slack.channel_id": args.destination.channelId,
|
|
3401
|
+
"app.slack.team_id": args.destination.teamId
|
|
3402
|
+
});
|
|
3403
|
+
await releaseFailedNoticeClaim({
|
|
3404
|
+
nowMs: args.nowMs,
|
|
3405
|
+
scope
|
|
3406
|
+
});
|
|
3407
|
+
return false;
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
async function maybePostAutomatedTurnLimitNotice(args) {
|
|
3411
|
+
if (!args.update?.shouldPostNotice) {
|
|
3412
|
+
return;
|
|
3413
|
+
}
|
|
3414
|
+
if (args.update.resumeIn === "thread") {
|
|
3415
|
+
await postAutomatedTurnLimitNoticeForConversation({
|
|
3416
|
+
conversationId: args.conversationId,
|
|
3417
|
+
maxTurns: args.maxTurns,
|
|
3418
|
+
nowMs: args.nowMs,
|
|
3419
|
+
resumeIn: "thread",
|
|
3420
|
+
scope: {
|
|
3421
|
+
kind: "conversation",
|
|
3422
|
+
conversationId: args.conversationId
|
|
3423
|
+
}
|
|
3424
|
+
});
|
|
3425
|
+
return;
|
|
3426
|
+
}
|
|
3427
|
+
if (args.destination) {
|
|
3428
|
+
await postAutomatedTurnLimitNoticeForDestination({
|
|
3429
|
+
destination: args.destination,
|
|
3430
|
+
maxTurns: args.maxTurns,
|
|
3431
|
+
nowMs: args.nowMs,
|
|
3432
|
+
resumeIn: "channel",
|
|
3433
|
+
scope: { kind: "destination", destination: args.destination },
|
|
3434
|
+
threadTs: args.threadTs
|
|
3435
|
+
});
|
|
3436
|
+
return;
|
|
3437
|
+
}
|
|
3438
|
+
await postAutomatedTurnLimitNoticeForConversation({
|
|
3439
|
+
conversationId: args.conversationId,
|
|
3440
|
+
maxTurns: args.maxTurns,
|
|
3441
|
+
nowMs: args.nowMs,
|
|
3442
|
+
resumeIn: args.update.resumeIn,
|
|
3443
|
+
scope: {
|
|
3444
|
+
kind: "conversation",
|
|
3445
|
+
conversationId: args.conversationId
|
|
3446
|
+
}
|
|
3447
|
+
});
|
|
3448
|
+
}
|
|
3449
|
+
|
|
3099
3450
|
// src/chat/task-input.ts
|
|
3100
3451
|
function replyContractLines() {
|
|
3101
3452
|
return [
|
|
3102
3453
|
"When you reply, follow any reply format in the instructions.",
|
|
3103
|
-
`If no visible reply is needed,
|
|
3454
|
+
`If no visible reply is needed, your final assistant message must be exactly ${NO_REPLY_MARKER} and nothing else.`,
|
|
3104
3455
|
"Otherwise briefly summarize what you acted on and what you did or need next."
|
|
3105
3456
|
];
|
|
3106
3457
|
}
|
|
@@ -3235,6 +3586,38 @@ function createResourceEventInboundMessage(input) {
|
|
|
3235
3586
|
};
|
|
3236
3587
|
}
|
|
3237
3588
|
async function enqueueResourceEventNotification(args) {
|
|
3589
|
+
const maxTurns = botConfig.maxConsecutiveAutomatedTurns;
|
|
3590
|
+
const decision = await admitAutomatedTurn({
|
|
3591
|
+
maxTurns,
|
|
3592
|
+
nowMs: args.event.occurredAtMs,
|
|
3593
|
+
scope: {
|
|
3594
|
+
kind: "conversation",
|
|
3595
|
+
conversationId: args.subscription.conversationId
|
|
3596
|
+
},
|
|
3597
|
+
state: args.state
|
|
3598
|
+
});
|
|
3599
|
+
if (decision.status === "paused") {
|
|
3600
|
+
logInfo("resource_events.automated_turn_limit.paused", {
|
|
3601
|
+
conversationId: args.subscription.conversationId,
|
|
3602
|
+
"app.automated_turn_limit.consecutive": decision.consecutiveAutomatedTurns,
|
|
3603
|
+
"app.automated_turn_limit.max": maxTurns,
|
|
3604
|
+
"app.resource_event.event_type": args.event.eventType,
|
|
3605
|
+
"app.resource_event.namespace": args.event.namespace
|
|
3606
|
+
});
|
|
3607
|
+
if (decision.shouldPostNotice) {
|
|
3608
|
+
await postAutomatedTurnLimitNoticeForConversation({
|
|
3609
|
+
conversationId: args.subscription.conversationId,
|
|
3610
|
+
maxTurns,
|
|
3611
|
+
nowMs: args.event.occurredAtMs,
|
|
3612
|
+
resumeIn: "thread",
|
|
3613
|
+
scope: {
|
|
3614
|
+
kind: "conversation",
|
|
3615
|
+
conversationId: args.subscription.conversationId
|
|
3616
|
+
}
|
|
3617
|
+
});
|
|
3618
|
+
}
|
|
3619
|
+
return { status: "duplicate" };
|
|
3620
|
+
}
|
|
3238
3621
|
const text = renderResourceEventNotificationText(
|
|
3239
3622
|
args.subscription,
|
|
3240
3623
|
args.event
|
|
@@ -5008,10 +5391,10 @@ function validateAndApplyTextEdits(content, edits, targetName) {
|
|
|
5008
5391
|
}
|
|
5009
5392
|
|
|
5010
5393
|
// src/chat/tools/sandbox/edit-file.ts
|
|
5011
|
-
import { z as
|
|
5394
|
+
import { z as z5 } from "zod";
|
|
5012
5395
|
|
|
5013
5396
|
// src/chat/tool-support/zod-tool.ts
|
|
5014
|
-
import { z as
|
|
5397
|
+
import { z as z4 } from "zod";
|
|
5015
5398
|
function isContentOnlyToolResult(value) {
|
|
5016
5399
|
return value !== null && typeof value === "object" && Array.isArray(value.content) && !("details" in value);
|
|
5017
5400
|
}
|
|
@@ -5048,7 +5431,7 @@ function zodTool(definition) {
|
|
|
5048
5431
|
const { inputSchema: inputSchema2, outputSchema: outputSchema7, prepareArguments, execute, ...toolDef } = definition;
|
|
5049
5432
|
let modelInputSchema;
|
|
5050
5433
|
try {
|
|
5051
|
-
modelInputSchema =
|
|
5434
|
+
modelInputSchema = z4.toJSONSchema(inputSchema2);
|
|
5052
5435
|
} catch (error) {
|
|
5053
5436
|
throw new TypeError(
|
|
5054
5437
|
"zodTool() inputSchema must be representable as JSON Schema.",
|
|
@@ -5058,7 +5441,7 @@ function zodTool(definition) {
|
|
|
5058
5441
|
let modelOutputSchema;
|
|
5059
5442
|
if (outputSchema7) {
|
|
5060
5443
|
try {
|
|
5061
|
-
modelOutputSchema =
|
|
5444
|
+
modelOutputSchema = z4.toJSONSchema(outputSchema7);
|
|
5062
5445
|
} catch (error) {
|
|
5063
5446
|
throw new TypeError(
|
|
5064
5447
|
"zodTool() outputSchema must be representable as JSON Schema.",
|
|
@@ -5143,11 +5526,11 @@ async function editFile(params) {
|
|
|
5143
5526
|
truncated: diff.truncated
|
|
5144
5527
|
});
|
|
5145
5528
|
}
|
|
5146
|
-
var editReplacementSchema =
|
|
5147
|
-
oldText:
|
|
5529
|
+
var editReplacementSchema = z5.object({
|
|
5530
|
+
oldText: z5.string().min(1).describe(
|
|
5148
5531
|
"Exact text to replace. It must be unique in the original file and must not overlap another edit."
|
|
5149
5532
|
),
|
|
5150
|
-
newText:
|
|
5533
|
+
newText: z5.string().describe("Replacement text for this edit.")
|
|
5151
5534
|
});
|
|
5152
5535
|
function createEditFileTool() {
|
|
5153
5536
|
return zodTool({
|
|
@@ -5160,9 +5543,9 @@ function createEditFileTool() {
|
|
|
5160
5543
|
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.",
|
|
5161
5544
|
prepareArguments: prepareEditFileArguments,
|
|
5162
5545
|
executionMode: "sequential",
|
|
5163
|
-
inputSchema:
|
|
5164
|
-
path:
|
|
5165
|
-
edits:
|
|
5546
|
+
inputSchema: z5.object({
|
|
5547
|
+
path: z5.string().min(1).describe("Path to edit in the sandbox workspace."),
|
|
5548
|
+
edits: z5.array(editReplacementSchema).min(1).describe(
|
|
5166
5549
|
"Exact replacements matched against the original file, not incrementally."
|
|
5167
5550
|
)
|
|
5168
5551
|
}),
|
|
@@ -5177,7 +5560,7 @@ function createEditFileTool() {
|
|
|
5177
5560
|
|
|
5178
5561
|
// src/chat/tools/sandbox/find-files.ts
|
|
5179
5562
|
import path4 from "path";
|
|
5180
|
-
import { z as
|
|
5563
|
+
import { z as z6 } from "zod";
|
|
5181
5564
|
var DEFAULT_FIND_LIMIT = 100;
|
|
5182
5565
|
async function findFiles(params) {
|
|
5183
5566
|
if (!params.pattern.trim()) {
|
|
@@ -5350,14 +5733,14 @@ function createFindFilesTool() {
|
|
|
5350
5733
|
openWorldHint: false,
|
|
5351
5734
|
readOnlyHint: true
|
|
5352
5735
|
},
|
|
5353
|
-
inputSchema:
|
|
5354
|
-
pattern:
|
|
5736
|
+
inputSchema: z6.object({
|
|
5737
|
+
pattern: z6.string().min(1).describe(
|
|
5355
5738
|
"Glob pattern to match, for example '*.ts', '**/*.json', or 'src/**/*.test.ts'."
|
|
5356
5739
|
),
|
|
5357
|
-
path:
|
|
5740
|
+
path: z6.string().min(1).describe(
|
|
5358
5741
|
"Directory or file path in the sandbox workspace. Defaults to the workspace root."
|
|
5359
5742
|
).optional(),
|
|
5360
|
-
limit:
|
|
5743
|
+
limit: z6.coerce.number().int().min(1).describe("Maximum number of file paths to return. Defaults to 100.").optional()
|
|
5361
5744
|
}),
|
|
5362
5745
|
outputSchema: juniorToolOutputSchema,
|
|
5363
5746
|
execute: async () => {
|
|
@@ -5370,12 +5753,12 @@ function createFindFilesTool() {
|
|
|
5370
5753
|
|
|
5371
5754
|
// src/chat/tools/sandbox/grep.ts
|
|
5372
5755
|
import path5 from "path";
|
|
5373
|
-
import { z as
|
|
5756
|
+
import { z as z7 } from "zod";
|
|
5374
5757
|
var DEFAULT_GREP_LIMIT = 100;
|
|
5375
5758
|
var MAX_GREP_LINE_CHARS = 500;
|
|
5376
|
-
var booleanInput = (description) =>
|
|
5759
|
+
var booleanInput = (description) => z7.preprocess(
|
|
5377
5760
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
5378
|
-
|
|
5761
|
+
z7.boolean()
|
|
5379
5762
|
).describe(description);
|
|
5380
5763
|
function truncateGrepLine(value) {
|
|
5381
5764
|
if (value.length <= MAX_GREP_LINE_CHARS) {
|
|
@@ -5729,20 +6112,20 @@ function createGrepTool() {
|
|
|
5729
6112
|
openWorldHint: false,
|
|
5730
6113
|
readOnlyHint: true
|
|
5731
6114
|
},
|
|
5732
|
-
inputSchema:
|
|
5733
|
-
pattern:
|
|
5734
|
-
path:
|
|
6115
|
+
inputSchema: z7.object({
|
|
6116
|
+
pattern: z7.string().min(1).describe("Regex pattern or literal text to search for."),
|
|
6117
|
+
path: z7.string().min(1).describe(
|
|
5735
6118
|
"Directory or file path in the sandbox workspace. Defaults to the workspace root."
|
|
5736
6119
|
).optional(),
|
|
5737
|
-
glob:
|
|
6120
|
+
glob: z7.string().min(1).describe("Optional glob filter such as '*.ts' or '**/*.test.ts'.").optional(),
|
|
5738
6121
|
ignoreCase: booleanInput(
|
|
5739
6122
|
"Whether matching should ignore case."
|
|
5740
6123
|
).optional(),
|
|
5741
6124
|
literal: booleanInput(
|
|
5742
6125
|
"Treat pattern as literal text instead of regex."
|
|
5743
6126
|
).optional(),
|
|
5744
|
-
context:
|
|
5745
|
-
limit:
|
|
6127
|
+
context: z7.coerce.number().int().min(0).describe("Number of surrounding context lines to include.").optional(),
|
|
6128
|
+
limit: z7.coerce.number().int().min(1).describe("Maximum matches to return. Defaults to 100.").optional()
|
|
5746
6129
|
}),
|
|
5747
6130
|
outputSchema: juniorToolOutputSchema,
|
|
5748
6131
|
execute: async () => {
|
|
@@ -5753,7 +6136,7 @@ function createGrepTool() {
|
|
|
5753
6136
|
|
|
5754
6137
|
// src/chat/tools/sandbox/list-dir.ts
|
|
5755
6138
|
import path6 from "path";
|
|
5756
|
-
import { z as
|
|
6139
|
+
import { z as z8 } from "zod";
|
|
5757
6140
|
var DEFAULT_LIST_LIMIT = 500;
|
|
5758
6141
|
async function listDir(params) {
|
|
5759
6142
|
const dirPath = resolveWorkspacePath(params.path);
|
|
@@ -5834,11 +6217,11 @@ function createListDirTool() {
|
|
|
5834
6217
|
openWorldHint: false,
|
|
5835
6218
|
readOnlyHint: true
|
|
5836
6219
|
},
|
|
5837
|
-
inputSchema:
|
|
5838
|
-
path:
|
|
6220
|
+
inputSchema: z8.object({
|
|
6221
|
+
path: z8.string().min(1).describe(
|
|
5839
6222
|
"Directory path in the sandbox workspace. Defaults to the workspace root."
|
|
5840
6223
|
).optional(),
|
|
5841
|
-
limit:
|
|
6224
|
+
limit: z8.coerce.number().int().min(1).describe("Maximum entries to return. Defaults to 500.").optional()
|
|
5842
6225
|
}),
|
|
5843
6226
|
outputSchema: juniorToolOutputSchema,
|
|
5844
6227
|
execute: async () => {
|
|
@@ -5850,7 +6233,7 @@ function createListDirTool() {
|
|
|
5850
6233
|
}
|
|
5851
6234
|
|
|
5852
6235
|
// src/chat/tools/sandbox/read-file.ts
|
|
5853
|
-
import { z as
|
|
6236
|
+
import { z as z9 } from "zod";
|
|
5854
6237
|
|
|
5855
6238
|
// src/chat/tool-support/text-range-result.ts
|
|
5856
6239
|
var DEFAULT_READ_LIMIT = 1e3;
|
|
@@ -5944,10 +6327,10 @@ function createReadFileTool() {
|
|
|
5944
6327
|
openWorldHint: false,
|
|
5945
6328
|
readOnlyHint: true
|
|
5946
6329
|
},
|
|
5947
|
-
inputSchema:
|
|
5948
|
-
path:
|
|
5949
|
-
offset:
|
|
5950
|
-
limit:
|
|
6330
|
+
inputSchema: z9.object({
|
|
6331
|
+
path: z9.string().min(1).describe("Path to the file in the sandbox workspace."),
|
|
6332
|
+
offset: z9.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
|
|
6333
|
+
limit: z9.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
|
|
5951
6334
|
}),
|
|
5952
6335
|
outputSchema: juniorToolOutputSchema,
|
|
5953
6336
|
execute: async () => {
|
|
@@ -6547,25 +6930,25 @@ function createSandbox(options) {
|
|
|
6547
6930
|
|
|
6548
6931
|
// src/chat/tools/sandbox/file-uploads.ts
|
|
6549
6932
|
import path7 from "path";
|
|
6550
|
-
import { z as
|
|
6933
|
+
import { z as z10 } from "zod";
|
|
6551
6934
|
var MAX_SANDBOX_FILE_UPLOAD_BYTES = 10 * 1024 * 1024;
|
|
6552
6935
|
var SANDBOX_ARTIFACTS_DIR = "/tmp/junior/artifacts";
|
|
6553
|
-
var sandboxFileReferenceSchema =
|
|
6554
|
-
path:
|
|
6936
|
+
var sandboxFileReferenceSchema = z10.object({
|
|
6937
|
+
path: z10.string().min(1).describe(
|
|
6555
6938
|
"Exact source path of an existing sandbox file. Preserve paths returned by other tools unchanged; do not move or rewrite them before sending."
|
|
6556
6939
|
),
|
|
6557
|
-
filename:
|
|
6940
|
+
filename: z10.string().min(1).nullable().optional().describe(
|
|
6558
6941
|
"Optional filename override shown to the recipient. Null is treated as omitted."
|
|
6559
6942
|
),
|
|
6560
|
-
mimeType:
|
|
6561
|
-
bytes:
|
|
6943
|
+
mimeType: z10.string().min(1).nullable().optional().describe("Optional MIME type override. Null is treated as omitted."),
|
|
6944
|
+
bytes: z10.number().int().nonnegative().nullable().optional().describe(
|
|
6562
6945
|
"Optional known file size returned by a producing tool. Null is treated as omitted; sending tools validate the file contents directly."
|
|
6563
6946
|
)
|
|
6564
6947
|
});
|
|
6565
6948
|
var generatedArtifactFileRefSchema = sandboxFileReferenceSchema.extend({
|
|
6566
|
-
filename:
|
|
6567
|
-
mimeType:
|
|
6568
|
-
bytes:
|
|
6949
|
+
filename: z10.string().min(1),
|
|
6950
|
+
mimeType: z10.string().min(1).optional(),
|
|
6951
|
+
bytes: z10.number().int().nonnegative()
|
|
6569
6952
|
}).strict();
|
|
6570
6953
|
var MIME_BY_EXTENSION = {
|
|
6571
6954
|
".png": "image/png",
|
|
@@ -7816,7 +8199,7 @@ function serializeMcpPayload(payload, privacy, options = {}) {
|
|
|
7816
8199
|
}
|
|
7817
8200
|
|
|
7818
8201
|
// src/chat/tools/sandbox/bash.ts
|
|
7819
|
-
import { z as
|
|
8202
|
+
import { z as z11 } from "zod";
|
|
7820
8203
|
function createBashTool() {
|
|
7821
8204
|
return zodTool({
|
|
7822
8205
|
annotations: {
|
|
@@ -7826,10 +8209,10 @@ function createBashTool() {
|
|
|
7826
8209
|
readOnlyHint: false
|
|
7827
8210
|
},
|
|
7828
8211
|
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.",
|
|
7829
|
-
inputSchema:
|
|
7830
|
-
command:
|
|
7831
|
-
cwd:
|
|
7832
|
-
timeoutMs:
|
|
8212
|
+
inputSchema: z11.object({
|
|
8213
|
+
command: z11.string().min(1).describe("Bash command to run inside the sandbox."),
|
|
8214
|
+
cwd: z11.string().min(1).describe("Optional working directory for this command only.").optional(),
|
|
8215
|
+
timeoutMs: z11.coerce.number().int().min(1e3).describe(
|
|
7833
8216
|
"Optional command timeout in milliseconds. Use for commands that may hang."
|
|
7834
8217
|
).optional()
|
|
7835
8218
|
}),
|
|
@@ -7843,14 +8226,14 @@ function createBashTool() {
|
|
|
7843
8226
|
}
|
|
7844
8227
|
|
|
7845
8228
|
// src/chat/tools/web/image-generate.ts
|
|
7846
|
-
import { z as
|
|
8229
|
+
import { z as z12 } from "zod";
|
|
7847
8230
|
var imageGenerateOutputSchema = juniorToolOutputSchema.extend({
|
|
7848
|
-
model:
|
|
7849
|
-
prompt:
|
|
7850
|
-
enrichedPrompt:
|
|
7851
|
-
image_count:
|
|
7852
|
-
images:
|
|
7853
|
-
delivery:
|
|
8231
|
+
model: z12.string(),
|
|
8232
|
+
prompt: z12.string(),
|
|
8233
|
+
enrichedPrompt: z12.string(),
|
|
8234
|
+
image_count: z12.number().int().nonnegative(),
|
|
8235
|
+
images: z12.array(generatedArtifactFileRefSchema),
|
|
8236
|
+
delivery: z12.string()
|
|
7854
8237
|
}).strict();
|
|
7855
8238
|
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.
|
|
7856
8239
|
|
|
@@ -7912,8 +8295,8 @@ function createImageGenerateTool(hooks, options, deps = {}) {
|
|
|
7912
8295
|
readOnlyHint: false
|
|
7913
8296
|
},
|
|
7914
8297
|
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.",
|
|
7915
|
-
inputSchema:
|
|
7916
|
-
prompt:
|
|
8298
|
+
inputSchema: z12.object({
|
|
8299
|
+
prompt: z12.string().min(1).max(4e3).describe("Image generation prompt.")
|
|
7917
8300
|
}),
|
|
7918
8301
|
outputSchema: imageGenerateOutputSchema,
|
|
7919
8302
|
execute: async ({ prompt }) => {
|
|
@@ -8003,7 +8386,7 @@ function parseMcpProviderFromToolName(toolName) {
|
|
|
8003
8386
|
}
|
|
8004
8387
|
|
|
8005
8388
|
// src/chat/tools/skill/call-mcp-tool.ts
|
|
8006
|
-
import { z as
|
|
8389
|
+
import { z as z13 } from "zod";
|
|
8007
8390
|
function resolveMcpArguments(input) {
|
|
8008
8391
|
const extraKeys = Object.keys(input).filter(
|
|
8009
8392
|
(key) => key !== "tool_name" && key !== "arguments"
|
|
@@ -8046,9 +8429,9 @@ function createCallMcpToolTool(mcpToolManager) {
|
|
|
8046
8429
|
readOnlyHint: false
|
|
8047
8430
|
},
|
|
8048
8431
|
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.",
|
|
8049
|
-
inputSchema:
|
|
8050
|
-
tool_name:
|
|
8051
|
-
arguments:
|
|
8432
|
+
inputSchema: z13.object({
|
|
8433
|
+
tool_name: z13.string().min(1).describe("Exact MCP tool_name from searchMcpTools."),
|
|
8434
|
+
arguments: z13.record(z13.string(), z13.unknown()).describe(
|
|
8052
8435
|
'Arguments matching the disclosed MCP tool schema, for example { "query": "..." } when searchMcpTools shows query is required.'
|
|
8053
8436
|
).optional()
|
|
8054
8437
|
}).passthrough(),
|
|
@@ -8101,7 +8484,7 @@ function createCallMcpToolTool(mcpToolManager) {
|
|
|
8101
8484
|
}
|
|
8102
8485
|
|
|
8103
8486
|
// src/chat/tools/skill/load-skill.ts
|
|
8104
|
-
import { z as
|
|
8487
|
+
import { z as z14 } from "zod";
|
|
8105
8488
|
function toLoadedSkill(result, availableSkills) {
|
|
8106
8489
|
if (typeof result.skill_name !== "string" || typeof result.description !== "string" || typeof result.skill_dir !== "string" || typeof result.instructions !== "string") {
|
|
8107
8490
|
return null;
|
|
@@ -8151,8 +8534,8 @@ function createLoadSkillTool(availableSkills, options) {
|
|
|
8151
8534
|
readOnlyHint: false
|
|
8152
8535
|
},
|
|
8153
8536
|
description: "Load a skill by name for this turn. The result includes working_directory; resolve skill paths there and run skill-owned bash commands from there or with absolute paths. When the skill instructions name an MCP provider, use searchMcpTools before callMcpTool. Use when a request clearly matches a known skill.",
|
|
8154
|
-
inputSchema:
|
|
8155
|
-
skill_name:
|
|
8537
|
+
inputSchema: z14.object({
|
|
8538
|
+
skill_name: z14.string().min(1).describe("Skill name to load, without the leading slash.")
|
|
8156
8539
|
}),
|
|
8157
8540
|
outputSchema: juniorToolOutputSchema,
|
|
8158
8541
|
execute: async ({ skill_name }) => {
|
|
@@ -8167,7 +8550,7 @@ function createLoadSkillTool(availableSkills, options) {
|
|
|
8167
8550
|
}
|
|
8168
8551
|
|
|
8169
8552
|
// src/chat/tools/skill/search-mcp-tools.ts
|
|
8170
|
-
import { z as
|
|
8553
|
+
import { z as z15 } from "zod";
|
|
8171
8554
|
|
|
8172
8555
|
// src/chat/tool-support/skill/mcp-tool-summary.ts
|
|
8173
8556
|
function toExposedToolSummary(toolDef) {
|
|
@@ -8199,29 +8582,29 @@ function toActiveMcpCatalogSummaries(toolDefs) {
|
|
|
8199
8582
|
// src/chat/tools/skill/search-mcp-tools.ts
|
|
8200
8583
|
var DEFAULT_MAX_RESULTS = 5;
|
|
8201
8584
|
var MAX_RESULTS = 20;
|
|
8202
|
-
var providerSummarySchema =
|
|
8203
|
-
provider:
|
|
8204
|
-
description:
|
|
8205
|
-
active:
|
|
8585
|
+
var providerSummarySchema = z15.object({
|
|
8586
|
+
provider: z15.string(),
|
|
8587
|
+
description: z15.string(),
|
|
8588
|
+
active: z15.boolean()
|
|
8206
8589
|
}).strict();
|
|
8207
|
-
var exposedToolSummarySchema =
|
|
8208
|
-
tool_name:
|
|
8209
|
-
mcp_tool_name:
|
|
8210
|
-
provider:
|
|
8211
|
-
title:
|
|
8212
|
-
description:
|
|
8213
|
-
input_schema:
|
|
8214
|
-
output_schema:
|
|
8215
|
-
annotations:
|
|
8590
|
+
var exposedToolSummarySchema = z15.object({
|
|
8591
|
+
tool_name: z15.string(),
|
|
8592
|
+
mcp_tool_name: z15.string(),
|
|
8593
|
+
provider: z15.string(),
|
|
8594
|
+
title: z15.string().optional(),
|
|
8595
|
+
description: z15.string(),
|
|
8596
|
+
input_schema: z15.record(z15.string(), z15.unknown()),
|
|
8597
|
+
output_schema: z15.record(z15.string(), z15.unknown()).optional(),
|
|
8598
|
+
annotations: z15.record(z15.string(), z15.unknown()).optional()
|
|
8216
8599
|
}).strict();
|
|
8217
8600
|
var searchMcpToolsOutputSchema = juniorToolOutputSchema.extend({
|
|
8218
|
-
query:
|
|
8219
|
-
provider:
|
|
8220
|
-
total_active_tools:
|
|
8221
|
-
returned_tools:
|
|
8222
|
-
execution_tool:
|
|
8223
|
-
available_providers:
|
|
8224
|
-
tools:
|
|
8601
|
+
query: z15.string().nullable(),
|
|
8602
|
+
provider: z15.string().nullable(),
|
|
8603
|
+
total_active_tools: z15.number().int().nonnegative(),
|
|
8604
|
+
returned_tools: z15.number().int().nonnegative(),
|
|
8605
|
+
execution_tool: z15.literal("callMcpTool"),
|
|
8606
|
+
available_providers: z15.array(providerSummarySchema),
|
|
8607
|
+
tools: z15.array(exposedToolSummarySchema)
|
|
8225
8608
|
}).strict();
|
|
8226
8609
|
function normalize(value) {
|
|
8227
8610
|
return value.toLowerCase().replace(/[^a-z0-9_]+/g, " ").trim();
|
|
@@ -8347,14 +8730,14 @@ function createSearchMcpToolsTool(mcpToolManager) {
|
|
|
8347
8730
|
readOnlyHint: true
|
|
8348
8731
|
},
|
|
8349
8732
|
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.",
|
|
8350
|
-
inputSchema:
|
|
8351
|
-
query:
|
|
8733
|
+
inputSchema: z15.object({
|
|
8734
|
+
query: z15.string().min(1).describe(
|
|
8352
8735
|
"Optional search terms describing the MCP tool or arguments needed."
|
|
8353
8736
|
).optional(),
|
|
8354
|
-
provider:
|
|
8737
|
+
provider: z15.string().min(1).describe(
|
|
8355
8738
|
"Optional provider name to list or search within. If configured but not yet connected, Junior activates it on demand."
|
|
8356
8739
|
).optional(),
|
|
8357
|
-
max_results:
|
|
8740
|
+
max_results: z15.number().int().min(1).max(MAX_RESULTS).describe("Maximum matching tool descriptors to return.").optional()
|
|
8358
8741
|
}).strict(),
|
|
8359
8742
|
outputSchema: searchMcpToolsOutputSchema,
|
|
8360
8743
|
privateTraceResult: (result) => ({
|
|
@@ -8394,10 +8777,10 @@ function createSearchMcpToolsTool(mcpToolManager) {
|
|
|
8394
8777
|
}
|
|
8395
8778
|
|
|
8396
8779
|
// src/chat/tools/sandbox/view-image.ts
|
|
8397
|
-
import { z as
|
|
8780
|
+
import { z as z16 } from "zod";
|
|
8398
8781
|
var MAX_VIEW_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
8399
|
-
var viewImageInputSchema =
|
|
8400
|
-
path:
|
|
8782
|
+
var viewImageInputSchema = z16.object({
|
|
8783
|
+
path: z16.string().min(1).describe("Path to an image file in the sandbox workspace.")
|
|
8401
8784
|
}).strict();
|
|
8402
8785
|
function detectImageMimeType(data) {
|
|
8403
8786
|
if (data.length >= 8 && data.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
|
|
@@ -8464,7 +8847,7 @@ function createViewImageTool(sandbox, supportsImageInput, deps = {}) {
|
|
|
8464
8847
|
}
|
|
8465
8848
|
|
|
8466
8849
|
// src/chat/tools/runtime/report-progress.ts
|
|
8467
|
-
import { z as
|
|
8850
|
+
import { z as z17 } from "zod";
|
|
8468
8851
|
function createReportProgressTool() {
|
|
8469
8852
|
return zodTool({
|
|
8470
8853
|
annotations: {
|
|
@@ -8474,8 +8857,8 @@ function createReportProgressTool() {
|
|
|
8474
8857
|
readOnlyHint: false
|
|
8475
8858
|
},
|
|
8476
8859
|
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').",
|
|
8477
|
-
inputSchema:
|
|
8478
|
-
message:
|
|
8860
|
+
inputSchema: z17.object({
|
|
8861
|
+
message: z17.string().min(1).describe("Short user-facing progress message.")
|
|
8479
8862
|
}),
|
|
8480
8863
|
outputSchema: juniorToolOutputSchema,
|
|
8481
8864
|
execute: async () => ({})
|
|
@@ -8483,9 +8866,9 @@ function createReportProgressTool() {
|
|
|
8483
8866
|
}
|
|
8484
8867
|
|
|
8485
8868
|
// src/chat/tools/runtime/spawn-agent.ts
|
|
8486
|
-
import { z as
|
|
8869
|
+
import { z as z18 } from "zod";
|
|
8487
8870
|
var spawnAgentOutputSchema = juniorToolOutputSchema.extend({
|
|
8488
|
-
invocation_id:
|
|
8871
|
+
invocation_id: z18.string().min(1)
|
|
8489
8872
|
});
|
|
8490
8873
|
function createSpawnAgentTool(spawnAgent) {
|
|
8491
8874
|
return zodTool({
|
|
@@ -8496,10 +8879,10 @@ function createSpawnAgentTool(spawnAgent) {
|
|
|
8496
8879
|
openWorldHint: false,
|
|
8497
8880
|
readOnlyHint: false
|
|
8498
8881
|
},
|
|
8499
|
-
inputSchema:
|
|
8500
|
-
task:
|
|
8882
|
+
inputSchema: z18.object({
|
|
8883
|
+
task: z18.string().trim().min(1).describe("Task for the child agent"),
|
|
8501
8884
|
name: agentNameSchema.nullable().optional().describe("Stable child-agent name, or omit for a one-off agent"),
|
|
8502
|
-
reasoning_level:
|
|
8885
|
+
reasoning_level: z18.enum(TURN_REASONING_LEVELS).nullable().optional().describe(
|
|
8503
8886
|
"Optional reasoning level for this delegated task only"
|
|
8504
8887
|
)
|
|
8505
8888
|
}).strict(),
|
|
@@ -8544,19 +8927,19 @@ function createSpawnAgentTool(spawnAgent) {
|
|
|
8544
8927
|
}
|
|
8545
8928
|
|
|
8546
8929
|
// src/chat/tools/list-resource-event-subscriptions.ts
|
|
8547
|
-
import { z as
|
|
8548
|
-
var listedResourceWatchSchema =
|
|
8549
|
-
id:
|
|
8550
|
-
label:
|
|
8551
|
-
identifier:
|
|
8552
|
-
namespace:
|
|
8553
|
-
resourceType:
|
|
8554
|
-
events:
|
|
8555
|
-
match:
|
|
8556
|
-
intent:
|
|
8557
|
-
expiresAtMs:
|
|
8930
|
+
import { z as z19 } from "zod";
|
|
8931
|
+
var listedResourceWatchSchema = z19.object({
|
|
8932
|
+
id: z19.string().min(1),
|
|
8933
|
+
label: z19.string().min(1),
|
|
8934
|
+
identifier: z19.string().min(1),
|
|
8935
|
+
namespace: z19.string().min(1),
|
|
8936
|
+
resourceType: z19.string().min(1),
|
|
8937
|
+
events: z19.array(z19.string().min(1)).min(1),
|
|
8938
|
+
match: z19.record(z19.string(), z19.unknown()).optional(),
|
|
8939
|
+
intent: z19.string().min(1),
|
|
8940
|
+
expiresAtMs: z19.number().finite()
|
|
8558
8941
|
}).strict();
|
|
8559
|
-
var resultDataSchema =
|
|
8942
|
+
var resultDataSchema = z19.object({ subscriptions: z19.array(listedResourceWatchSchema) }).strict();
|
|
8560
8943
|
var outputSchema = juniorToolOutputSchema.merge(resultDataSchema);
|
|
8561
8944
|
function createListResourceEventSubscriptionsTool(context) {
|
|
8562
8945
|
return zodTool({
|
|
@@ -8569,7 +8952,7 @@ function createListResourceEventSubscriptionsTool(context) {
|
|
|
8569
8952
|
description: "List active resource event subscriptions for the current conversation.",
|
|
8570
8953
|
exposure: "deferred",
|
|
8571
8954
|
source: RESOURCE_WATCH_TOOL_SOURCE,
|
|
8572
|
-
inputSchema:
|
|
8955
|
+
inputSchema: z19.object({}).strict(),
|
|
8573
8956
|
outputSchema,
|
|
8574
8957
|
async execute() {
|
|
8575
8958
|
const subscriptions = await listResourceEventSubscriptions({
|
|
@@ -8596,28 +8979,28 @@ function createListResourceEventSubscriptionsTool(context) {
|
|
|
8596
8979
|
}
|
|
8597
8980
|
|
|
8598
8981
|
// src/chat/tools/search-resource-event-types.ts
|
|
8599
|
-
import { z as
|
|
8982
|
+
import { z as z20 } from "zod";
|
|
8600
8983
|
var DEFAULT_SEARCH_RESULTS = 10;
|
|
8601
8984
|
var MAX_SEARCH_RESULTS = 20;
|
|
8602
|
-
var searchedResourceTypeSchema =
|
|
8603
|
-
namespace:
|
|
8604
|
-
type:
|
|
8605
|
-
supportedEvents:
|
|
8606
|
-
suggestedEvents:
|
|
8607
|
-
matchFields:
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
kind:
|
|
8611
|
-
description:
|
|
8612
|
-
enum:
|
|
8985
|
+
var searchedResourceTypeSchema = z20.object({
|
|
8986
|
+
namespace: z20.string(),
|
|
8987
|
+
type: z20.string(),
|
|
8988
|
+
supportedEvents: z20.array(z20.string()),
|
|
8989
|
+
suggestedEvents: z20.array(z20.string()).optional(),
|
|
8990
|
+
matchFields: z20.record(
|
|
8991
|
+
z20.string(),
|
|
8992
|
+
z20.object({
|
|
8993
|
+
kind: z20.enum(["boolean", "string", "number"]),
|
|
8994
|
+
description: z20.string(),
|
|
8995
|
+
enum: z20.array(z20.string()).optional()
|
|
8613
8996
|
}).strict()
|
|
8614
8997
|
).optional()
|
|
8615
8998
|
}).strict();
|
|
8616
8999
|
var outputSchema2 = juniorToolOutputSchema.extend({
|
|
8617
|
-
query:
|
|
8618
|
-
namespace:
|
|
8619
|
-
totalMatches:
|
|
8620
|
-
resourceTypes:
|
|
9000
|
+
query: z20.string().nullable(),
|
|
9001
|
+
namespace: z20.string().nullable(),
|
|
9002
|
+
totalMatches: z20.number().int().nonnegative(),
|
|
9003
|
+
resourceTypes: z20.array(searchedResourceTypeSchema)
|
|
8621
9004
|
}).strict();
|
|
8622
9005
|
function normalizeSearchText(value) {
|
|
8623
9006
|
return value.toLowerCase().replace(/[^a-z0-9_.-]+/g, " ").trim();
|
|
@@ -8644,12 +9027,12 @@ function createSearchResourceEventTypesTool(catalog) {
|
|
|
8644
9027
|
readOnlyHint: true
|
|
8645
9028
|
},
|
|
8646
9029
|
description: "Search the resource event types currently enabled without creating anything. Includes plugin resources and core Workspace snapshot events. Use watchResourceEvents for temporary updates in the current conversation; use createEventTask for durable automation. This tool does not watch a resource, create a task, or list concrete resources.",
|
|
8647
|
-
inputSchema:
|
|
8648
|
-
query:
|
|
9030
|
+
inputSchema: z20.object({
|
|
9031
|
+
query: z20.string().nullable().describe(
|
|
8649
9032
|
"Optional terms matching a namespace, resource type, or event name. Empty lists all enabled resource event types."
|
|
8650
9033
|
).optional(),
|
|
8651
9034
|
namespace: eventNamespaceSchema(catalog).nullable().describe("Optional enabled plugin namespace to search within.").optional(),
|
|
8652
|
-
maxResults:
|
|
9035
|
+
maxResults: z20.number().int().min(1).max(MAX_SEARCH_RESULTS).nullable().describe("Maximum matching resource types to return.").optional()
|
|
8653
9036
|
}).strict(),
|
|
8654
9037
|
outputSchema: outputSchema2,
|
|
8655
9038
|
async execute({ query, namespace, maxResults }) {
|
|
@@ -8688,10 +9071,10 @@ function createSearchResourceEventTypesTool(catalog) {
|
|
|
8688
9071
|
}
|
|
8689
9072
|
|
|
8690
9073
|
// src/chat/tools/stop-watching-resources.ts
|
|
8691
|
-
import { z as
|
|
8692
|
-
var resultDataSchema2 =
|
|
8693
|
-
watching_status:
|
|
8694
|
-
stoppedIds:
|
|
9074
|
+
import { z as z21 } from "zod";
|
|
9075
|
+
var resultDataSchema2 = z21.object({
|
|
9076
|
+
watching_status: z21.literal("stopped"),
|
|
9077
|
+
stoppedIds: z21.array(z21.string().min(1))
|
|
8695
9078
|
}).strict();
|
|
8696
9079
|
var outputSchema3 = juniorToolOutputSchema.merge(resultDataSchema2);
|
|
8697
9080
|
function createStopWatchingResourcesTool(context) {
|
|
@@ -8705,7 +9088,7 @@ function createStopWatchingResourcesTool(context) {
|
|
|
8705
9088
|
description: "Stop one resource watch in the current conversation by id. Omit id only when the user explicitly asks to stop every watch in this conversation. Infer terse stop requests from context, inspect active watches when the target is unclear, and call this tool before confirming that watching stopped.",
|
|
8706
9089
|
exposure: "deferred",
|
|
8707
9090
|
source: RESOURCE_WATCH_TOOL_SOURCE,
|
|
8708
|
-
inputSchema:
|
|
9091
|
+
inputSchema: z21.object({ id: z21.string().min(1).nullable().optional() }).strict(),
|
|
8709
9092
|
outputSchema: outputSchema3,
|
|
8710
9093
|
async execute({ id }) {
|
|
8711
9094
|
let stoppedIds;
|
|
@@ -8739,25 +9122,25 @@ function createStopWatchingResourcesTool(context) {
|
|
|
8739
9122
|
}
|
|
8740
9123
|
|
|
8741
9124
|
// src/chat/tools/watch-resource-events.ts
|
|
8742
|
-
import { z as
|
|
9125
|
+
import { z as z22 } from "zod";
|
|
8743
9126
|
function inputSchema(catalog) {
|
|
8744
|
-
return
|
|
8745
|
-
identifier:
|
|
9127
|
+
return z22.object({
|
|
9128
|
+
identifier: z22.string().trim().min(1).describe("Plugin-defined resource identifier."),
|
|
8746
9129
|
namespace: eventNamespaceSchema(catalog).describe(
|
|
8747
9130
|
"Enabled plugin namespace for this resource."
|
|
8748
9131
|
),
|
|
8749
9132
|
resourceType: registeredResourceTypeSchema(catalog).describe(
|
|
8750
9133
|
"Plugin-defined resource type."
|
|
8751
9134
|
),
|
|
8752
|
-
label:
|
|
8753
|
-
events:
|
|
9135
|
+
label: z22.string().trim().min(1).max(500).describe("Human-readable resource label."),
|
|
9136
|
+
events: z22.array(registeredEventTypeSchema(catalog)).min(1).describe(
|
|
8754
9137
|
"High-signal event names to deliver to this conversation when they occur."
|
|
8755
9138
|
),
|
|
8756
9139
|
match: registeredResourceEventMatchSchema(),
|
|
8757
|
-
intent:
|
|
9140
|
+
intent: z22.string().trim().min(1).max(4e3).describe(
|
|
8758
9141
|
"Concise reason this conversation wants these events, used when an event arrives."
|
|
8759
9142
|
),
|
|
8760
|
-
ttlMs:
|
|
9143
|
+
ttlMs: z22.coerce.number().describe(
|
|
8761
9144
|
"How long to keep the subscription active. Defaults to 14 days and must not exceed 30 days."
|
|
8762
9145
|
).optional()
|
|
8763
9146
|
}).strict().superRefine((subscription, context) => {
|
|
@@ -8777,20 +9160,20 @@ function inputSchema(catalog) {
|
|
|
8777
9160
|
});
|
|
8778
9161
|
});
|
|
8779
9162
|
}
|
|
8780
|
-
var stopWatchingActionSchema =
|
|
8781
|
-
execution_tool:
|
|
8782
|
-
execution_example:
|
|
8783
|
-
tool_name:
|
|
8784
|
-
arguments:
|
|
9163
|
+
var stopWatchingActionSchema = z22.object({
|
|
9164
|
+
execution_tool: z22.literal("executeTool"),
|
|
9165
|
+
execution_example: z22.object({
|
|
9166
|
+
tool_name: z22.literal(STOP_WATCHING_TOOL_NAME),
|
|
9167
|
+
arguments: z22.object({ id: z22.string().min(1) }).strict()
|
|
8785
9168
|
}).strict()
|
|
8786
9169
|
}).strict();
|
|
8787
|
-
var resultDataSchema3 =
|
|
8788
|
-
id:
|
|
8789
|
-
subscription_status:
|
|
8790
|
-
identifier:
|
|
8791
|
-
events:
|
|
8792
|
-
match:
|
|
8793
|
-
expiresAtMs:
|
|
9170
|
+
var resultDataSchema3 = z22.object({
|
|
9171
|
+
id: z22.string().min(1),
|
|
9172
|
+
subscription_status: z22.enum(["active", "cancelled", "completed"]),
|
|
9173
|
+
identifier: z22.string().min(1),
|
|
9174
|
+
events: z22.array(z22.string().min(1)).min(1),
|
|
9175
|
+
match: z22.record(z22.string(), z22.unknown()).optional(),
|
|
9176
|
+
expiresAtMs: z22.number().finite(),
|
|
8794
9177
|
stop_watching: stopWatchingActionSchema
|
|
8795
9178
|
}).strict();
|
|
8796
9179
|
var outputSchema4 = juniorToolOutputSchema.merge(resultDataSchema3);
|
|
@@ -8892,7 +9275,7 @@ function createResourceEventTools(context, catalog) {
|
|
|
8892
9275
|
|
|
8893
9276
|
// src/chat/tools/create-event-task.ts
|
|
8894
9277
|
import { createHash } from "crypto";
|
|
8895
|
-
import { z as
|
|
9278
|
+
import { z as z23 } from "zod";
|
|
8896
9279
|
function buildEventTaskId(args) {
|
|
8897
9280
|
const toolCallId = args.toolCallId?.trim();
|
|
8898
9281
|
if (!toolCallId) {
|
|
@@ -8920,13 +9303,13 @@ function createEventTaskTool(context, catalog) {
|
|
|
8920
9303
|
},
|
|
8921
9304
|
executionMode: "sequential",
|
|
8922
9305
|
description: "Create a durable event task that executes the supplied instruction for every matching resource event. Use for whenever-this-happens-do-X automation; ordinary watch, notify, or tell-me-when requests use watchResourceEvents instead. The task may use the creator's connected credentials. Prefer a subscribable tool result when available.",
|
|
8923
|
-
inputSchema:
|
|
8924
|
-
task:
|
|
8925
|
-
title:
|
|
9306
|
+
inputSchema: z23.object({
|
|
9307
|
+
task: z23.string().trim().min(1).max(4e3),
|
|
9308
|
+
title: z23.string().trim().min(1).max(SHORT_TITLE_MAX_LENGTH).nullable().describe(
|
|
8926
9309
|
"Optional short display title. Omit or use null to generate one from the task instruction."
|
|
8927
9310
|
).optional(),
|
|
8928
9311
|
trigger,
|
|
8929
|
-
credentialMode:
|
|
9312
|
+
credentialMode: z23.enum(["creator", "system"]).nullable().describe(
|
|
8930
9313
|
"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."
|
|
8931
9314
|
).optional()
|
|
8932
9315
|
}).strict(),
|
|
@@ -8957,7 +9340,9 @@ function createEventTaskTool(context, catalog) {
|
|
|
8957
9340
|
if (!eventTaskMatchesDestination(existing, destination) || existing.createdBy.slackUserId !== actor.userId) {
|
|
8958
9341
|
throw new ToolInputError("Event task operation identity is invalid.");
|
|
8959
9342
|
}
|
|
8960
|
-
|
|
9343
|
+
if (existing.status !== "deleted") {
|
|
9344
|
+
return eventTaskSuccess(existing, catalog);
|
|
9345
|
+
}
|
|
8961
9346
|
}
|
|
8962
9347
|
const title = await resolveTaskTitle({
|
|
8963
9348
|
completeText,
|
|
@@ -8996,7 +9381,7 @@ function createEventTaskTool(context, catalog) {
|
|
|
8996
9381
|
}
|
|
8997
9382
|
|
|
8998
9383
|
// src/chat/tools/delete-event-task.ts
|
|
8999
|
-
import { z as
|
|
9384
|
+
import { z as z24 } from "zod";
|
|
9000
9385
|
function createDeleteEventTaskTool(context, catalog) {
|
|
9001
9386
|
return zodTool({
|
|
9002
9387
|
approvalMode: "review",
|
|
@@ -9008,7 +9393,7 @@ function createDeleteEventTaskTool(context, catalog) {
|
|
|
9008
9393
|
},
|
|
9009
9394
|
executionMode: "sequential",
|
|
9010
9395
|
description: "Delete an event task.",
|
|
9011
|
-
inputSchema:
|
|
9396
|
+
inputSchema: z24.object({ taskId: z24.string().min(1) }).strict(),
|
|
9012
9397
|
outputSchema: eventTaskToolResultSchema,
|
|
9013
9398
|
async execute({ taskId }) {
|
|
9014
9399
|
const current = await writableEventTask(context, taskId);
|
|
@@ -9022,7 +9407,7 @@ function createDeleteEventTaskTool(context, catalog) {
|
|
|
9022
9407
|
}
|
|
9023
9408
|
|
|
9024
9409
|
// src/chat/tools/list-event-tasks.ts
|
|
9025
|
-
import { z as
|
|
9410
|
+
import { z as z25 } from "zod";
|
|
9026
9411
|
var MAX_LISTED_EVENT_TASKS = 50;
|
|
9027
9412
|
function createListEventTasksTool(context, catalog) {
|
|
9028
9413
|
return zodTool({
|
|
@@ -9033,7 +9418,7 @@ function createListEventTasksTool(context, catalog) {
|
|
|
9033
9418
|
readOnlyHint: true
|
|
9034
9419
|
},
|
|
9035
9420
|
description: "List event tasks for the current destination. A false triggerAvailable value means the task remains stored but its plugin event is not currently enabled.",
|
|
9036
|
-
inputSchema:
|
|
9421
|
+
inputSchema: z25.object({}).strict(),
|
|
9037
9422
|
outputSchema: eventTaskListToolResultSchema,
|
|
9038
9423
|
async execute() {
|
|
9039
9424
|
const { destination } = requireEventTaskSlackContext(context);
|
|
@@ -9049,7 +9434,7 @@ function createListEventTasksTool(context, catalog) {
|
|
|
9049
9434
|
|
|
9050
9435
|
// src/chat/tools/update-event-task.ts
|
|
9051
9436
|
import { stableResourceEventMatchKey } from "@sentry/junior-plugin-api";
|
|
9052
|
-
import { z as
|
|
9437
|
+
import { z as z26 } from "zod";
|
|
9053
9438
|
function changesEventTaskTrigger(current, next) {
|
|
9054
9439
|
const currentEvents = [...current.events].sort();
|
|
9055
9440
|
const nextEvents = [...next.events].sort();
|
|
@@ -9066,11 +9451,11 @@ function createUpdateEventTaskTool(context, catalog) {
|
|
|
9066
9451
|
},
|
|
9067
9452
|
executionMode: "sequential",
|
|
9068
9453
|
description: "Update the instruction, registered trigger, or credential use for an event task.",
|
|
9069
|
-
inputSchema:
|
|
9070
|
-
taskId:
|
|
9071
|
-
task:
|
|
9454
|
+
inputSchema: z26.object({
|
|
9455
|
+
taskId: z26.string().min(1),
|
|
9456
|
+
task: z26.string().trim().min(1).max(4e3).nullable().optional(),
|
|
9072
9457
|
trigger: registeredEventTaskTriggerSchema(catalog).nullable().optional(),
|
|
9073
|
-
credentialMode:
|
|
9458
|
+
credentialMode: z26.enum(["system", "creator"]).nullable().describe(
|
|
9074
9459
|
"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."
|
|
9075
9460
|
).optional()
|
|
9076
9461
|
}).strict(),
|
|
@@ -9152,10 +9537,10 @@ function createEventTaskTools(context, catalog) {
|
|
|
9152
9537
|
}
|
|
9153
9538
|
|
|
9154
9539
|
// src/chat/scheduled-tasks/tools/create.ts
|
|
9155
|
-
import { z as
|
|
9540
|
+
import { z as z29 } from "zod";
|
|
9156
9541
|
|
|
9157
9542
|
// src/chat/scheduled-tasks/schedule-intent.ts
|
|
9158
|
-
import { z as
|
|
9543
|
+
import { z as z27 } from "zod";
|
|
9159
9544
|
|
|
9160
9545
|
// src/chat/scheduled-tasks/cadence.ts
|
|
9161
9546
|
var FORMATTERS = /* @__PURE__ */ new Map();
|
|
@@ -9446,12 +9831,12 @@ function getNextRunAtMs(task, scheduledForMs, afterMs = scheduledForMs) {
|
|
|
9446
9831
|
}
|
|
9447
9832
|
|
|
9448
9833
|
// src/chat/scheduled-tasks/schedule-intent.ts
|
|
9449
|
-
var localDateSchema =
|
|
9450
|
-
var localTimeSchema =
|
|
9451
|
-
var timezoneSchema =
|
|
9834
|
+
var localDateSchema = z27.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Use a local date in YYYY-MM-DD format.");
|
|
9835
|
+
var localTimeSchema = z27.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "Use local time in HH:MM format.");
|
|
9836
|
+
var timezoneSchema = z27.string().min(1).max(80).describe(
|
|
9452
9837
|
"IANA timezone, for example America/Los_Angeles. Omit or use null for the scheduler default."
|
|
9453
9838
|
).nullable().optional();
|
|
9454
|
-
var weekdaySchema =
|
|
9839
|
+
var weekdaySchema = z27.enum([
|
|
9455
9840
|
"sunday",
|
|
9456
9841
|
"monday",
|
|
9457
9842
|
"tuesday",
|
|
@@ -9460,17 +9845,17 @@ var weekdaySchema = z26.enum([
|
|
|
9460
9845
|
"friday",
|
|
9461
9846
|
"saturday"
|
|
9462
9847
|
]);
|
|
9463
|
-
var oneOffScheduleIntentSchema =
|
|
9464
|
-
kind:
|
|
9848
|
+
var oneOffScheduleIntentSchema = z27.object({
|
|
9849
|
+
kind: z27.literal("one_off").describe("A schedule that runs once."),
|
|
9465
9850
|
timezone: timezoneSchema,
|
|
9466
|
-
timing:
|
|
9467
|
-
|
|
9468
|
-
type:
|
|
9469
|
-
value:
|
|
9470
|
-
unit:
|
|
9851
|
+
timing: z27.discriminatedUnion("type", [
|
|
9852
|
+
z27.object({
|
|
9853
|
+
type: z27.literal("after").describe("Run after a relative delay from the server clock."),
|
|
9854
|
+
value: z27.number().int().positive().max(1e5),
|
|
9855
|
+
unit: z27.enum(["second", "minute", "hour", "day", "week"])
|
|
9471
9856
|
}).strict(),
|
|
9472
|
-
|
|
9473
|
-
type:
|
|
9857
|
+
z27.object({
|
|
9858
|
+
type: z27.literal("at").describe("Run at an explicit local calendar date and time."),
|
|
9474
9859
|
date: localDateSchema.describe(
|
|
9475
9860
|
"Requested local calendar date in YYYY-MM-DD format."
|
|
9476
9861
|
),
|
|
@@ -9480,16 +9865,16 @@ var oneOffScheduleIntentSchema = z26.object({
|
|
|
9480
9865
|
}).strict()
|
|
9481
9866
|
]).describe("Relative delay or explicit local time for the one-off run.")
|
|
9482
9867
|
}).strict();
|
|
9483
|
-
var recurringScheduleIntentSchema =
|
|
9484
|
-
kind:
|
|
9485
|
-
frequency:
|
|
9486
|
-
interval:
|
|
9868
|
+
var recurringScheduleIntentSchema = z27.object({
|
|
9869
|
+
kind: z27.literal("recurring").describe("A repeating calendar schedule."),
|
|
9870
|
+
frequency: z27.enum(["daily", "weekly", "monthly", "yearly"]).describe("Recurring tasks can run at most once per day."),
|
|
9871
|
+
interval: z27.number().int().positive().max(365).describe("Repeat every N frequency units. Defaults to 1.").nullable().optional(),
|
|
9487
9872
|
time: localTimeSchema.describe(
|
|
9488
9873
|
"Local wall-clock time for each occurrence in HH:MM format."
|
|
9489
9874
|
),
|
|
9490
|
-
weekdays:
|
|
9491
|
-
day_of_month:
|
|
9492
|
-
month:
|
|
9875
|
+
weekdays: z27.array(weekdaySchema).min(1).max(7).describe("Required for weekly schedules.").nullable().optional(),
|
|
9876
|
+
day_of_month: z27.number().int().min(1).max(31).describe("Required for monthly and yearly schedules.").nullable().optional(),
|
|
9877
|
+
month: z27.number().int().min(1).max(12).describe("Required for yearly schedules, where January is 1.").nullable().optional(),
|
|
9493
9878
|
start_date: localDateSchema.describe(
|
|
9494
9879
|
"Optional local calendar date that anchors the recurrence. Omit to start with the next matching occurrence."
|
|
9495
9880
|
).nullable().optional(),
|
|
@@ -9538,7 +9923,7 @@ var recurringScheduleIntentSchema = z26.object({
|
|
|
9538
9923
|
});
|
|
9539
9924
|
}
|
|
9540
9925
|
});
|
|
9541
|
-
var scheduleIntentSchema =
|
|
9926
|
+
var scheduleIntentSchema = z27.union([
|
|
9542
9927
|
oneOffScheduleIntentSchema,
|
|
9543
9928
|
recurringScheduleIntentSchema
|
|
9544
9929
|
]);
|
|
@@ -9733,7 +10118,7 @@ import { createHash as createHash2 } from "crypto";
|
|
|
9733
10118
|
import {
|
|
9734
10119
|
sourceSchema
|
|
9735
10120
|
} from "@sentry/junior-plugin-api";
|
|
9736
|
-
import { z as
|
|
10121
|
+
import { z as z28 } from "zod";
|
|
9737
10122
|
|
|
9738
10123
|
// src/chat/scheduled-tasks/identity.ts
|
|
9739
10124
|
var SLACK_USER_ID_PATTERN = /^[UW][A-Z0-9]{5,}$/;
|
|
@@ -9770,36 +10155,36 @@ function sanitizeScheduledTaskPrincipal(principal) {
|
|
|
9770
10155
|
var TASK_ID_PREFIX = "sched";
|
|
9771
10156
|
var MAX_LISTED_TASKS = 50;
|
|
9772
10157
|
var DEFAULT_SCHEDULE_TIMEZONE = "America/Los_Angeles";
|
|
9773
|
-
var compactTaskResultSchema =
|
|
9774
|
-
id:
|
|
9775
|
-
status:
|
|
9776
|
-
task:
|
|
9777
|
-
schedule:
|
|
9778
|
-
timezone:
|
|
9779
|
-
recurrence:
|
|
9780
|
-
next_run_at:
|
|
9781
|
-
destination:
|
|
9782
|
-
platform:
|
|
9783
|
-
team_id:
|
|
9784
|
-
channel_id:
|
|
10158
|
+
var compactTaskResultSchema = z28.object({
|
|
10159
|
+
id: z28.string(),
|
|
10160
|
+
status: z28.enum(["active", "blocked", "completed", "deleted"]),
|
|
10161
|
+
task: z28.string(),
|
|
10162
|
+
schedule: z28.string(),
|
|
10163
|
+
timezone: z28.string(),
|
|
10164
|
+
recurrence: z28.unknown().nullable(),
|
|
10165
|
+
next_run_at: z28.string().nullable(),
|
|
10166
|
+
destination: z28.object({
|
|
10167
|
+
platform: z28.literal("slack"),
|
|
10168
|
+
team_id: z28.string().min(1),
|
|
10169
|
+
channel_id: z28.string().min(1)
|
|
9785
10170
|
}).strict(),
|
|
9786
|
-
conversation_access:
|
|
9787
|
-
audience:
|
|
9788
|
-
visibility:
|
|
10171
|
+
conversation_access: z28.object({
|
|
10172
|
+
audience: z28.enum(["direct", "group", "channel"]),
|
|
10173
|
+
visibility: z28.enum(["private", "public"])
|
|
9789
10174
|
}).strict(),
|
|
9790
|
-
credential_mode:
|
|
9791
|
-
dashboard_url:
|
|
9792
|
-
last_run_at:
|
|
9793
|
-
run_now_at:
|
|
10175
|
+
credential_mode: z28.enum(["system", "creator"]),
|
|
10176
|
+
dashboard_url: z28.string().url().nullable(),
|
|
10177
|
+
last_run_at: z28.string().nullable(),
|
|
10178
|
+
run_now_at: z28.string().nullable()
|
|
9794
10179
|
}).strict();
|
|
9795
10180
|
var scheduleTaskToolResultSchema = juniorToolOutputSchema.extend({
|
|
9796
|
-
target:
|
|
10181
|
+
target: z28.string(),
|
|
9797
10182
|
task: compactTaskResultSchema
|
|
9798
10183
|
}).strict();
|
|
9799
10184
|
var scheduleListToolResultSchema = juniorToolOutputSchema.extend({
|
|
9800
|
-
target:
|
|
9801
|
-
tasks:
|
|
9802
|
-
truncated:
|
|
10185
|
+
target: z28.string(),
|
|
10186
|
+
tasks: z28.array(compactTaskResultSchema),
|
|
10187
|
+
truncated: z28.boolean()
|
|
9803
10188
|
}).strict();
|
|
9804
10189
|
function throwToolInputError(error) {
|
|
9805
10190
|
throw new ToolInputError(error);
|
|
@@ -9962,15 +10347,15 @@ function createSlackScheduleCreateTaskTool(context) {
|
|
|
9962
10347
|
},
|
|
9963
10348
|
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.",
|
|
9964
10349
|
executionMode: "sequential",
|
|
9965
|
-
inputSchema:
|
|
9966
|
-
task:
|
|
9967
|
-
title:
|
|
10350
|
+
inputSchema: z29.object({
|
|
10351
|
+
task: z29.string().min(1).max(4e3),
|
|
10352
|
+
title: z29.string().trim().min(1).max(SHORT_TITLE_MAX_LENGTH).nullable().describe(
|
|
9968
10353
|
"Optional short display title. Omit or use null to generate one from the task instruction."
|
|
9969
10354
|
).optional(),
|
|
9970
10355
|
schedule: scheduleIntentSchema.describe(
|
|
9971
10356
|
"When the task runs. The scheduler computes the exact next run from this intent and the server clock."
|
|
9972
10357
|
),
|
|
9973
|
-
credential_mode:
|
|
10358
|
+
credential_mode: z29.enum(["creator", "system"]).nullable().describe(
|
|
9974
10359
|
"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."
|
|
9975
10360
|
).optional()
|
|
9976
10361
|
}).strict(),
|
|
@@ -10069,7 +10454,7 @@ function createSlackScheduleCreateTaskTool(context) {
|
|
|
10069
10454
|
}
|
|
10070
10455
|
|
|
10071
10456
|
// src/chat/scheduled-tasks/tools/delete.ts
|
|
10072
|
-
import { z as
|
|
10457
|
+
import { z as z30 } from "zod";
|
|
10073
10458
|
function createSlackScheduleDeleteTaskTool(context) {
|
|
10074
10459
|
return zodTool({
|
|
10075
10460
|
approvalMode: "review",
|
|
@@ -10081,8 +10466,8 @@ function createSlackScheduleDeleteTaskTool(context) {
|
|
|
10081
10466
|
},
|
|
10082
10467
|
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.",
|
|
10083
10468
|
executionMode: "sequential",
|
|
10084
|
-
inputSchema:
|
|
10085
|
-
task_id:
|
|
10469
|
+
inputSchema: z30.object({
|
|
10470
|
+
task_id: z30.string().min(1).describe(
|
|
10086
10471
|
"ID of the task to delete. Must be from this active Slack conversation."
|
|
10087
10472
|
)
|
|
10088
10473
|
}),
|
|
@@ -10106,12 +10491,12 @@ function createSlackScheduleDeleteTaskTool(context) {
|
|
|
10106
10491
|
}
|
|
10107
10492
|
|
|
10108
10493
|
// src/chat/slack/id-param.ts
|
|
10109
|
-
import { z as
|
|
10494
|
+
import { z as z31 } from "zod";
|
|
10110
10495
|
function slackChannelIdParam(description) {
|
|
10111
|
-
return
|
|
10496
|
+
return z31.string().min(1).describe(description);
|
|
10112
10497
|
}
|
|
10113
10498
|
function slackUserIdParam(description) {
|
|
10114
|
-
return
|
|
10499
|
+
return z31.string().min(1).describe(description);
|
|
10115
10500
|
}
|
|
10116
10501
|
function parseRequiredSlackChannelIdParam(field, value) {
|
|
10117
10502
|
const channelId = parseSlackChannelId(value);
|
|
@@ -10135,7 +10520,7 @@ function parseRequiredSlackUserIdParam(field, value) {
|
|
|
10135
10520
|
}
|
|
10136
10521
|
|
|
10137
10522
|
// src/chat/scheduled-tasks/tools/list.ts
|
|
10138
|
-
import { z as
|
|
10523
|
+
import { z as z32 } from "zod";
|
|
10139
10524
|
function taskMatchesQuery(task, query) {
|
|
10140
10525
|
const normalized = query.toLowerCase();
|
|
10141
10526
|
return [
|
|
@@ -10155,11 +10540,11 @@ function createSlackScheduleListTasksTool(context) {
|
|
|
10155
10540
|
openWorldHint: false,
|
|
10156
10541
|
readOnlyHint: true
|
|
10157
10542
|
},
|
|
10158
|
-
inputSchema:
|
|
10543
|
+
inputSchema: z32.object({
|
|
10159
10544
|
channel_id: slackChannelIdParam(
|
|
10160
10545
|
"Current destination channel ID to filter by. Use the ID from a channel mention; do not guess."
|
|
10161
10546
|
).nullable().optional(),
|
|
10162
|
-
query:
|
|
10547
|
+
query: z32.string().trim().min(1).max(200).nullable().describe("Text to match in the requester's scheduled tasks.").optional()
|
|
10163
10548
|
}).strict(),
|
|
10164
10549
|
outputSchema: scheduleListToolResultSchema,
|
|
10165
10550
|
execute: async (input) => {
|
|
@@ -10207,7 +10592,7 @@ function createSlackScheduleListTasksTool(context) {
|
|
|
10207
10592
|
}
|
|
10208
10593
|
|
|
10209
10594
|
// src/chat/scheduled-tasks/tools/run-now.ts
|
|
10210
|
-
import { z as
|
|
10595
|
+
import { z as z33 } from "zod";
|
|
10211
10596
|
function createSlackScheduleRunTaskNowTool(context) {
|
|
10212
10597
|
return zodTool({
|
|
10213
10598
|
approvalMode: "review",
|
|
@@ -10219,8 +10604,8 @@ function createSlackScheduleRunTaskNowTool(context) {
|
|
|
10219
10604
|
},
|
|
10220
10605
|
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.",
|
|
10221
10606
|
executionMode: "sequential",
|
|
10222
|
-
inputSchema:
|
|
10223
|
-
task_id:
|
|
10607
|
+
inputSchema: z33.object({
|
|
10608
|
+
task_id: z33.string().min(1).describe(
|
|
10224
10609
|
"ID of the active task to run now. Must be from this active Slack conversation."
|
|
10225
10610
|
)
|
|
10226
10611
|
}),
|
|
@@ -10248,7 +10633,7 @@ function createSlackScheduleRunTaskNowTool(context) {
|
|
|
10248
10633
|
}
|
|
10249
10634
|
|
|
10250
10635
|
// src/chat/scheduled-tasks/tools/update.ts
|
|
10251
|
-
import { z as
|
|
10636
|
+
import { z as z34 } from "zod";
|
|
10252
10637
|
import { and, eq, inArray } from "drizzle-orm";
|
|
10253
10638
|
function createSlackScheduleUpdateTaskTool(context) {
|
|
10254
10639
|
return zodTool({
|
|
@@ -10261,17 +10646,17 @@ function createSlackScheduleUpdateTaskTool(context) {
|
|
|
10261
10646
|
},
|
|
10262
10647
|
description: `Update a scheduled task. To move the requester's task into this Slack conversation, set destination to "here".`,
|
|
10263
10648
|
executionMode: "sequential",
|
|
10264
|
-
inputSchema:
|
|
10265
|
-
task_id:
|
|
10266
|
-
task:
|
|
10649
|
+
inputSchema: z34.object({
|
|
10650
|
+
task_id: z34.string().min(1).describe("Scheduled task ID returned by slackScheduleListTasks."),
|
|
10651
|
+
task: z34.string().min(1).max(4e3).optional(),
|
|
10267
10652
|
schedule: scheduleIntentSchema.describe("Complete replacement schedule. Omit to keep it unchanged.").nullable().optional(),
|
|
10268
|
-
status:
|
|
10653
|
+
status: z34.enum(["active", "blocked"]).describe(
|
|
10269
10654
|
"Set active to resume a blocked task, or blocked to stop dispatch."
|
|
10270
10655
|
).optional(),
|
|
10271
|
-
destination:
|
|
10656
|
+
destination: z34.literal("here").nullable().describe(
|
|
10272
10657
|
`Set to "here" to move the creator's task into this Slack conversation. Omit to keep its destination.`
|
|
10273
10658
|
).optional(),
|
|
10274
|
-
credential_mode:
|
|
10659
|
+
credential_mode: z34.enum(["system", "creator"]).nullable().describe(
|
|
10275
10660
|
"Use creator credentials or system credentials. Only the task creator may enable creator mode. Omit to keep unchanged."
|
|
10276
10661
|
).optional()
|
|
10277
10662
|
}).strict(),
|
|
@@ -10630,9 +11015,9 @@ async function joinPublicChannelForRead(args) {
|
|
|
10630
11015
|
}
|
|
10631
11016
|
|
|
10632
11017
|
// src/chat/slack/tool-support/channel-target.ts
|
|
10633
|
-
import { z as
|
|
11018
|
+
import { z as z35 } from "zod";
|
|
10634
11019
|
var SLACK_CHANNEL_REF_MAX_LENGTH = 160;
|
|
10635
|
-
var slackChannelRefParam =
|
|
11020
|
+
var slackChannelRefParam = z35.string().trim().min(1).max(SLACK_CHANNEL_REF_MAX_LENGTH).describe(
|
|
10636
11021
|
"Slack channel id (`C123`), mention (`<#C123>` / `<#C123|name>`), Junior slack reference (`slack:C123`), or a channel name Junior already knows in this workspace."
|
|
10637
11022
|
);
|
|
10638
11023
|
async function resolveSlackChannelRef(input) {
|
|
@@ -10680,7 +11065,7 @@ async function resolveOptionalSlackChannelRef(input) {
|
|
|
10680
11065
|
}
|
|
10681
11066
|
|
|
10682
11067
|
// src/chat/slack/tools/channel-join.ts
|
|
10683
|
-
import { z as
|
|
11068
|
+
import { z as z36 } from "zod";
|
|
10684
11069
|
function createSlackChannelJoinTool(context) {
|
|
10685
11070
|
return zodTool({
|
|
10686
11071
|
description: "Join a public Slack channel.",
|
|
@@ -10690,7 +11075,7 @@ function createSlackChannelJoinTool(context) {
|
|
|
10690
11075
|
openWorldHint: true,
|
|
10691
11076
|
readOnlyHint: false
|
|
10692
11077
|
},
|
|
10693
|
-
inputSchema:
|
|
11078
|
+
inputSchema: z36.object({
|
|
10694
11079
|
channel_id: slackChannelRefParam
|
|
10695
11080
|
}),
|
|
10696
11081
|
outputSchema: juniorToolOutputSchema,
|
|
@@ -10747,11 +11132,11 @@ function createSlackChannelJoinTool(context) {
|
|
|
10747
11132
|
}
|
|
10748
11133
|
|
|
10749
11134
|
// src/chat/slack/timestamp-param.ts
|
|
10750
|
-
import { z as
|
|
11135
|
+
import { z as z37 } from "zod";
|
|
10751
11136
|
function slackTimestampParam(description) {
|
|
10752
|
-
return
|
|
11137
|
+
return z37.preprocess(
|
|
10753
11138
|
(value) => typeof value === "number" && Number.isFinite(value) ? String(value) : value,
|
|
10754
|
-
|
|
11139
|
+
z37.string().min(1)
|
|
10755
11140
|
).describe(description);
|
|
10756
11141
|
}
|
|
10757
11142
|
function parseSlackTimestampParam(field, value) {
|
|
@@ -10779,10 +11164,10 @@ function parseRequiredSlackTimestampParam(field, value) {
|
|
|
10779
11164
|
}
|
|
10780
11165
|
|
|
10781
11166
|
// src/chat/slack/tools/channel-list-messages.ts
|
|
10782
|
-
import { z as
|
|
10783
|
-
var booleanInput2 = (description) =>
|
|
11167
|
+
import { z as z38 } from "zod";
|
|
11168
|
+
var booleanInput2 = (description) => z38.preprocess(
|
|
10784
11169
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
10785
|
-
|
|
11170
|
+
z38.boolean()
|
|
10786
11171
|
).describe(description);
|
|
10787
11172
|
function normalizeRangeTimestamp(field, value, targetChannelId) {
|
|
10788
11173
|
if (value === void 0) {
|
|
@@ -10814,10 +11199,10 @@ function createSlackChannelListMessagesTool(context) {
|
|
|
10814
11199
|
openWorldHint: true,
|
|
10815
11200
|
readOnlyHint: true
|
|
10816
11201
|
},
|
|
10817
|
-
inputSchema:
|
|
11202
|
+
inputSchema: z38.object({
|
|
10818
11203
|
channel_id: slackChannelRefParam.optional(),
|
|
10819
|
-
limit:
|
|
10820
|
-
cursor:
|
|
11204
|
+
limit: z38.coerce.number().int().min(1).max(1e3).describe("Maximum number of messages to return across pages.").optional(),
|
|
11205
|
+
cursor: z38.string().min(1).describe("Optional cursor to continue from a prior call.").optional(),
|
|
10821
11206
|
oldest: slackTimestampParam(
|
|
10822
11207
|
"Oldest message timestamp (Slack ts) for range filtering."
|
|
10823
11208
|
).optional(),
|
|
@@ -10827,7 +11212,7 @@ function createSlackChannelListMessagesTool(context) {
|
|
|
10827
11212
|
inclusive: booleanInput2(
|
|
10828
11213
|
"Whether oldest/latest bounds should be inclusive."
|
|
10829
11214
|
).optional(),
|
|
10830
|
-
max_pages:
|
|
11215
|
+
max_pages: z38.coerce.number().int().min(1).max(10).describe("Maximum number of API pages to traverse in a single call.").optional()
|
|
10831
11216
|
}),
|
|
10832
11217
|
outputSchema: juniorToolOutputSchema,
|
|
10833
11218
|
execute: async ({
|
|
@@ -10950,7 +11335,7 @@ function createSlackChannelListMessagesTool(context) {
|
|
|
10950
11335
|
}
|
|
10951
11336
|
|
|
10952
11337
|
// src/chat/slack/tools/conversation-message-search.ts
|
|
10953
|
-
import { z as
|
|
11338
|
+
import { z as z39 } from "zod";
|
|
10954
11339
|
|
|
10955
11340
|
// src/chat/conversations/tool-source.ts
|
|
10956
11341
|
var CONVERSATIONS_TOOL_SOURCE = {
|
|
@@ -10962,23 +11347,23 @@ var CONVERSATIONS_TOOL_SOURCE = {
|
|
|
10962
11347
|
var DEFAULT_LIMIT = 20;
|
|
10963
11348
|
var MAX_LIMIT = 50;
|
|
10964
11349
|
var conversationMessageSearchOutputSchema = juniorToolOutputSchema.extend({
|
|
10965
|
-
after:
|
|
10966
|
-
annotation:
|
|
10967
|
-
before:
|
|
10968
|
-
channel_id:
|
|
10969
|
-
count:
|
|
10970
|
-
query:
|
|
10971
|
-
matches:
|
|
10972
|
-
|
|
10973
|
-
channel_id:
|
|
10974
|
-
channel_name:
|
|
10975
|
-
conversation_id:
|
|
10976
|
-
excerpt:
|
|
10977
|
-
message_id:
|
|
10978
|
-
message_role:
|
|
10979
|
-
message_timestamp:
|
|
10980
|
-
permalink:
|
|
10981
|
-
thread_ts:
|
|
11350
|
+
after: z39.string().datetime().optional(),
|
|
11351
|
+
annotation: z39.string().min(1).optional(),
|
|
11352
|
+
before: z39.string().datetime().optional(),
|
|
11353
|
+
channel_id: z39.string().min(1).optional(),
|
|
11354
|
+
count: z39.number().int().nonnegative(),
|
|
11355
|
+
query: z39.string().optional(),
|
|
11356
|
+
matches: z39.array(
|
|
11357
|
+
z39.object({
|
|
11358
|
+
channel_id: z39.string().min(1),
|
|
11359
|
+
channel_name: z39.string().min(1).optional(),
|
|
11360
|
+
conversation_id: z39.string().min(1),
|
|
11361
|
+
excerpt: z39.string(),
|
|
11362
|
+
message_id: z39.string().min(1),
|
|
11363
|
+
message_role: z39.enum(["assistant", "user"]),
|
|
11364
|
+
message_timestamp: z39.string().datetime(),
|
|
11365
|
+
permalink: z39.string().url().optional(),
|
|
11366
|
+
thread_ts: z39.string().min(1)
|
|
10982
11367
|
}).strict()
|
|
10983
11368
|
)
|
|
10984
11369
|
});
|
|
@@ -11033,15 +11418,15 @@ function createSlackConversationMessageSearchTool(scope, currentConversationId)
|
|
|
11033
11418
|
openWorldHint: false,
|
|
11034
11419
|
readOnlyHint: true
|
|
11035
11420
|
},
|
|
11036
|
-
inputSchema:
|
|
11037
|
-
after:
|
|
11038
|
-
annotation:
|
|
11421
|
+
inputSchema: z39.object({
|
|
11422
|
+
after: z39.string().datetime().nullable().describe("Include conversations active at or after this timestamp.").optional(),
|
|
11423
|
+
annotation: z39.string().trim().min(1).max(256).nullable().describe(
|
|
11039
11424
|
"Linked resource key. Matches that key, or nested children that continue with #."
|
|
11040
11425
|
).optional(),
|
|
11041
|
-
before:
|
|
11426
|
+
before: z39.string().datetime().nullable().describe("Include conversations active before this timestamp.").optional(),
|
|
11042
11427
|
channel_id: slackChannelRefParam.nullable().optional(),
|
|
11043
|
-
query:
|
|
11044
|
-
limit:
|
|
11428
|
+
query: z39.string().trim().min(1).max(200).nullable().describe("Words or phrase to match in message text.").optional(),
|
|
11429
|
+
limit: z39.number().int().min(1).max(MAX_LIMIT).describe(
|
|
11045
11430
|
`Maximum conversations. Default ${DEFAULT_LIMIT}; max ${MAX_LIMIT}.`
|
|
11046
11431
|
).nullable().optional()
|
|
11047
11432
|
}).strict(),
|
|
@@ -11100,13 +11485,13 @@ function createSlackConversationMessageSearchTool(scope, currentConversationId)
|
|
|
11100
11485
|
}
|
|
11101
11486
|
|
|
11102
11487
|
// src/chat/slack/tools/public-search.ts
|
|
11103
|
-
import { z as
|
|
11488
|
+
import { z as z40 } from "zod";
|
|
11104
11489
|
var DEFAULT_LIMIT2 = 10;
|
|
11105
11490
|
var DEFAULT_CONTENT_TYPES = ["messages"];
|
|
11106
11491
|
var CONTENT_TYPES = ["messages", "files", "channels", "users"];
|
|
11107
|
-
var unixTimestampParam =
|
|
11492
|
+
var unixTimestampParam = z40.coerce.number().int().nonnegative();
|
|
11108
11493
|
function optionalUnixTimestampParam(description) {
|
|
11109
|
-
return
|
|
11494
|
+
return z40.preprocess(
|
|
11110
11495
|
(value) => typeof value === "string" && value.trim() === "" ? void 0 : value,
|
|
11111
11496
|
unixTimestampParam.optional()
|
|
11112
11497
|
).describe(description);
|
|
@@ -11120,64 +11505,64 @@ function normalizeOptionalUnixTimestamp(value) {
|
|
|
11120
11505
|
}
|
|
11121
11506
|
return unixTimestampParam.parse(value);
|
|
11122
11507
|
}
|
|
11123
|
-
var searchMessageSchema =
|
|
11124
|
-
author_name:
|
|
11125
|
-
author_user_id:
|
|
11126
|
-
channel_id:
|
|
11127
|
-
channel_name:
|
|
11128
|
-
message_ts:
|
|
11129
|
-
content:
|
|
11130
|
-
is_author_bot:
|
|
11131
|
-
permalink:
|
|
11508
|
+
var searchMessageSchema = z40.object({
|
|
11509
|
+
author_name: z40.string().min(1).optional().describe("Author display name."),
|
|
11510
|
+
author_user_id: z40.string().min(1).optional().describe("Author user ID."),
|
|
11511
|
+
channel_id: z40.string().min(1).describe("Channel ID."),
|
|
11512
|
+
channel_name: z40.string().min(1).optional().describe("Channel name."),
|
|
11513
|
+
message_ts: z40.string().min(1).describe("Message timestamp."),
|
|
11514
|
+
content: z40.string().describe("Message text."),
|
|
11515
|
+
is_author_bot: z40.boolean().optional().describe("Whether the author is a bot."),
|
|
11516
|
+
permalink: z40.string().url().describe("Message permalink.")
|
|
11132
11517
|
});
|
|
11133
|
-
var searchFileSchema =
|
|
11134
|
-
file_id:
|
|
11135
|
-
title:
|
|
11136
|
-
name:
|
|
11137
|
-
filetype:
|
|
11138
|
-
user_id:
|
|
11139
|
-
user_name:
|
|
11140
|
-
channel_id:
|
|
11141
|
-
channel_name:
|
|
11142
|
-
permalink:
|
|
11143
|
-
content:
|
|
11518
|
+
var searchFileSchema = z40.object({
|
|
11519
|
+
file_id: z40.string().min(1).describe("File ID."),
|
|
11520
|
+
title: z40.string().min(1).optional().describe("File title."),
|
|
11521
|
+
name: z40.string().min(1).optional().describe("File name."),
|
|
11522
|
+
filetype: z40.string().min(1).optional().describe("File type."),
|
|
11523
|
+
user_id: z40.string().min(1).optional().describe("Uploader user ID."),
|
|
11524
|
+
user_name: z40.string().min(1).optional().describe("Uploader user name."),
|
|
11525
|
+
channel_id: z40.string().min(1).optional().describe("Channel ID."),
|
|
11526
|
+
channel_name: z40.string().min(1).optional().describe("Channel name."),
|
|
11527
|
+
permalink: z40.string().url().optional().describe("File permalink."),
|
|
11528
|
+
content: z40.string().min(1).optional().describe("File preview or content snippet.")
|
|
11144
11529
|
});
|
|
11145
|
-
var searchChannelSchema =
|
|
11146
|
-
channel_id:
|
|
11147
|
-
channel_name:
|
|
11148
|
-
is_private:
|
|
11149
|
-
is_member:
|
|
11150
|
-
topic:
|
|
11151
|
-
purpose:
|
|
11152
|
-
permalink:
|
|
11530
|
+
var searchChannelSchema = z40.object({
|
|
11531
|
+
channel_id: z40.string().min(1).describe("Channel ID."),
|
|
11532
|
+
channel_name: z40.string().min(1).optional().describe("Channel name."),
|
|
11533
|
+
is_private: z40.boolean().optional().describe("Whether the channel is private."),
|
|
11534
|
+
is_member: z40.boolean().optional().describe("Whether the bot is a member."),
|
|
11535
|
+
topic: z40.string().min(1).optional().describe("Channel topic."),
|
|
11536
|
+
purpose: z40.string().min(1).optional().describe("Channel purpose."),
|
|
11537
|
+
permalink: z40.string().url().optional().describe("Channel permalink.")
|
|
11153
11538
|
});
|
|
11154
|
-
var searchUserSchema =
|
|
11155
|
-
user_id:
|
|
11156
|
-
user_name:
|
|
11157
|
-
real_name:
|
|
11158
|
-
display_name:
|
|
11159
|
-
title:
|
|
11160
|
-
permalink:
|
|
11539
|
+
var searchUserSchema = z40.object({
|
|
11540
|
+
user_id: z40.string().min(1).describe("User ID."),
|
|
11541
|
+
user_name: z40.string().min(1).optional().describe("Username."),
|
|
11542
|
+
real_name: z40.string().min(1).optional().describe("Real name."),
|
|
11543
|
+
display_name: z40.string().min(1).optional().describe("Display name."),
|
|
11544
|
+
title: z40.string().min(1).optional().describe("Profile title."),
|
|
11545
|
+
permalink: z40.string().url().optional().describe("Profile permalink.")
|
|
11161
11546
|
});
|
|
11162
11547
|
var publicSearchOutputSchema = juniorToolOutputSchema.extend({
|
|
11163
|
-
query:
|
|
11164
|
-
content_types:
|
|
11165
|
-
count:
|
|
11166
|
-
messages:
|
|
11167
|
-
files:
|
|
11168
|
-
channels:
|
|
11169
|
-
users:
|
|
11170
|
-
next_cursor:
|
|
11548
|
+
query: z40.string().describe("Search query."),
|
|
11549
|
+
content_types: z40.array(z40.enum(CONTENT_TYPES)).describe("Content types included in the search."),
|
|
11550
|
+
count: z40.number().int().nonnegative().describe("Total matched results."),
|
|
11551
|
+
messages: z40.array(searchMessageSchema).describe("Matched messages."),
|
|
11552
|
+
files: z40.array(searchFileSchema).describe("Matched files."),
|
|
11553
|
+
channels: z40.array(searchChannelSchema).describe("Matched channels."),
|
|
11554
|
+
users: z40.array(searchUserSchema).describe("Matched users."),
|
|
11555
|
+
next_cursor: z40.string().min(1).optional().describe("Cursor for the next result page.")
|
|
11171
11556
|
});
|
|
11172
|
-
var nonEmptyString =
|
|
11173
|
-
var optionalWireString =
|
|
11557
|
+
var nonEmptyString = z40.string().trim().min(1);
|
|
11558
|
+
var optionalWireString = z40.preprocess((value) => {
|
|
11174
11559
|
if (typeof value !== "string") {
|
|
11175
11560
|
return void 0;
|
|
11176
11561
|
}
|
|
11177
11562
|
const trimmed = value.trim();
|
|
11178
11563
|
return trimmed === "" ? void 0 : trimmed;
|
|
11179
11564
|
}, nonEmptyString.optional());
|
|
11180
|
-
var optionalWireUrl =
|
|
11565
|
+
var optionalWireUrl = z40.preprocess((value) => {
|
|
11181
11566
|
if (typeof value !== "string") {
|
|
11182
11567
|
return void 0;
|
|
11183
11568
|
}
|
|
@@ -11191,20 +11576,20 @@ var optionalWireUrl = z39.preprocess((value) => {
|
|
|
11191
11576
|
} catch {
|
|
11192
11577
|
return void 0;
|
|
11193
11578
|
}
|
|
11194
|
-
},
|
|
11195
|
-
var optionalWireBoolean =
|
|
11579
|
+
}, z40.string().url().optional());
|
|
11580
|
+
var optionalWireBoolean = z40.preprocess(
|
|
11196
11581
|
(value) => typeof value === "boolean" ? value : void 0,
|
|
11197
|
-
|
|
11582
|
+
z40.boolean().optional()
|
|
11198
11583
|
);
|
|
11199
|
-
var slackSearchMessageWireSchema =
|
|
11584
|
+
var slackSearchMessageWireSchema = z40.object({
|
|
11200
11585
|
author_name: optionalWireString,
|
|
11201
11586
|
author_user_id: optionalWireString,
|
|
11202
11587
|
channel_id: nonEmptyString,
|
|
11203
11588
|
channel_name: optionalWireString,
|
|
11204
11589
|
message_ts: nonEmptyString,
|
|
11205
|
-
content:
|
|
11590
|
+
content: z40.string(),
|
|
11206
11591
|
is_author_bot: optionalWireBoolean,
|
|
11207
|
-
permalink:
|
|
11592
|
+
permalink: z40.string().url()
|
|
11208
11593
|
}).transform(
|
|
11209
11594
|
(value) => ({
|
|
11210
11595
|
channel_id: value.channel_id,
|
|
@@ -11217,7 +11602,7 @@ var slackSearchMessageWireSchema = z39.object({
|
|
|
11217
11602
|
...value.is_author_bot !== void 0 ? { is_author_bot: value.is_author_bot } : void 0
|
|
11218
11603
|
})
|
|
11219
11604
|
);
|
|
11220
|
-
var slackSearchFileWireSchema =
|
|
11605
|
+
var slackSearchFileWireSchema = z40.object({
|
|
11221
11606
|
id: optionalWireString,
|
|
11222
11607
|
file_id: optionalWireString,
|
|
11223
11608
|
title: optionalWireString,
|
|
@@ -11251,7 +11636,7 @@ var slackSearchFileWireSchema = z39.object({
|
|
|
11251
11636
|
...value.content ?? value.preview ? { content: value.content ?? value.preview } : void 0
|
|
11252
11637
|
};
|
|
11253
11638
|
});
|
|
11254
|
-
var slackSearchChannelWireSchema =
|
|
11639
|
+
var slackSearchChannelWireSchema = z40.object({
|
|
11255
11640
|
id: optionalWireString,
|
|
11256
11641
|
channel_id: optionalWireString,
|
|
11257
11642
|
name: optionalWireString,
|
|
@@ -11276,7 +11661,7 @@ var slackSearchChannelWireSchema = z39.object({
|
|
|
11276
11661
|
...value.permalink ? { permalink: value.permalink } : void 0
|
|
11277
11662
|
};
|
|
11278
11663
|
});
|
|
11279
|
-
var slackSearchUserWireSchema =
|
|
11664
|
+
var slackSearchUserWireSchema = z40.object({
|
|
11280
11665
|
id: optionalWireString,
|
|
11281
11666
|
user_id: optionalWireString,
|
|
11282
11667
|
name: optionalWireString,
|
|
@@ -11300,12 +11685,12 @@ var slackSearchUserWireSchema = z39.object({
|
|
|
11300
11685
|
...value.permalink ? { permalink: value.permalink } : void 0
|
|
11301
11686
|
};
|
|
11302
11687
|
});
|
|
11303
|
-
var slackSearchResponseSchema =
|
|
11304
|
-
results:
|
|
11305
|
-
messages:
|
|
11306
|
-
files:
|
|
11307
|
-
channels:
|
|
11308
|
-
users:
|
|
11688
|
+
var slackSearchResponseSchema = z40.object({
|
|
11689
|
+
results: z40.object({
|
|
11690
|
+
messages: z40.array(z40.unknown()).default([]),
|
|
11691
|
+
files: z40.array(z40.unknown()).default([]),
|
|
11692
|
+
channels: z40.array(z40.unknown()).default([]),
|
|
11693
|
+
users: z40.array(z40.unknown()).default([]),
|
|
11309
11694
|
// Slack often returns "" on the final page; omit rather than fail the parse.
|
|
11310
11695
|
next_cursor: optionalWireString
|
|
11311
11696
|
}).default({
|
|
@@ -11354,15 +11739,15 @@ function createSlackPublicSearchTool(actionToken) {
|
|
|
11354
11739
|
openWorldHint: true,
|
|
11355
11740
|
readOnlyHint: true
|
|
11356
11741
|
},
|
|
11357
|
-
inputSchema:
|
|
11358
|
-
query:
|
|
11359
|
-
content_types:
|
|
11742
|
+
inputSchema: z40.object({
|
|
11743
|
+
query: z40.string().trim().min(1).max(500).describe("Slack search query."),
|
|
11744
|
+
content_types: z40.array(z40.enum(CONTENT_TYPES)).min(1).max(4).describe("Content types to include. Defaults to messages.").optional(),
|
|
11360
11745
|
after: optionalUnixTimestampParam("Unix timestamp lower bound."),
|
|
11361
11746
|
before: optionalUnixTimestampParam("Unix timestamp upper bound."),
|
|
11362
|
-
cursor:
|
|
11363
|
-
limit:
|
|
11364
|
-
sort:
|
|
11365
|
-
sort_dir:
|
|
11747
|
+
cursor: z40.string().min(1).describe("Cursor for the next result page.").optional(),
|
|
11748
|
+
limit: z40.coerce.number().int().min(1).max(20).describe("Maximum results to return; Slack allows at most 20.").optional(),
|
|
11749
|
+
sort: z40.enum(["score", "timestamp"]).describe("Rank by relevance or timestamp.").optional(),
|
|
11750
|
+
sort_dir: z40.enum(["asc", "desc"]).describe("Sort direction.").optional()
|
|
11366
11751
|
}),
|
|
11367
11752
|
outputSchema: publicSearchOutputSchema,
|
|
11368
11753
|
execute: async ({
|
|
@@ -11447,7 +11832,7 @@ function createSlackPublicSearchTool(actionToken) {
|
|
|
11447
11832
|
}
|
|
11448
11833
|
|
|
11449
11834
|
// src/chat/slack/tools/message-add-reaction.ts
|
|
11450
|
-
import { z as
|
|
11835
|
+
import { z as z41 } from "zod";
|
|
11451
11836
|
|
|
11452
11837
|
// src/chat/tools/idempotency.ts
|
|
11453
11838
|
function stableSerialize(value) {
|
|
@@ -11478,8 +11863,8 @@ function createSlackMessageAddReactionTool(context, state) {
|
|
|
11478
11863
|
readOnlyHint: false
|
|
11479
11864
|
},
|
|
11480
11865
|
description: "Add an emoji reaction to the current inbound Slack message.",
|
|
11481
|
-
inputSchema:
|
|
11482
|
-
emoji:
|
|
11866
|
+
inputSchema: z41.object({
|
|
11867
|
+
emoji: z41.string().min(1).max(64).describe(
|
|
11483
11868
|
"Slack emoji alias name to react with (for example `thumbsup`, `white_check_mark`, or `thumbsup::skin-tone-6`). Optional surrounding colons are allowed."
|
|
11484
11869
|
)
|
|
11485
11870
|
}),
|
|
@@ -11528,14 +11913,14 @@ function createSlackMessageAddReactionTool(context, state) {
|
|
|
11528
11913
|
|
|
11529
11914
|
// src/chat/slack/tools/send-files.ts
|
|
11530
11915
|
import { createHash as createHash3 } from "crypto";
|
|
11531
|
-
import { z as
|
|
11916
|
+
import { z as z42 } from "zod";
|
|
11532
11917
|
var sendFilesResultSchema = juniorToolOutputSchema.extend({
|
|
11533
|
-
deduplicated:
|
|
11534
|
-
attachment_refs:
|
|
11535
|
-
|
|
11536
|
-
id:
|
|
11918
|
+
deduplicated: z42.boolean().optional(),
|
|
11919
|
+
attachment_refs: z42.array(
|
|
11920
|
+
z42.object({
|
|
11921
|
+
id: z42.string().min(1),
|
|
11537
11922
|
// Same noun as storage, delivery events, and the report API.
|
|
11538
|
-
filename:
|
|
11923
|
+
filename: z42.string().min(1)
|
|
11539
11924
|
})
|
|
11540
11925
|
)
|
|
11541
11926
|
});
|
|
@@ -11567,8 +11952,8 @@ function createSendFilesTool(context, state, materializeFile, attachments) {
|
|
|
11567
11952
|
readOnlyHint: false
|
|
11568
11953
|
},
|
|
11569
11954
|
description: "Send one or more sandbox files into the active Slack conversation.",
|
|
11570
|
-
inputSchema:
|
|
11571
|
-
files:
|
|
11955
|
+
inputSchema: z42.object({
|
|
11956
|
+
files: z42.array(sandboxFileReferenceSchema).min(1).describe(
|
|
11572
11957
|
"One or more existing sandbox files. Objects returned by imageGenerate or webFetch can be passed unchanged."
|
|
11573
11958
|
)
|
|
11574
11959
|
}),
|
|
@@ -11987,7 +12372,7 @@ async function readCanvas(canvasIdOrUrl) {
|
|
|
11987
12372
|
}
|
|
11988
12373
|
|
|
11989
12374
|
// src/chat/slack/tools/canvas/create.ts
|
|
11990
|
-
import { z as
|
|
12375
|
+
import { z as z43 } from "zod";
|
|
11991
12376
|
function createSlackCanvasCreateTool(context, state) {
|
|
11992
12377
|
return zodTool({
|
|
11993
12378
|
annotations: {
|
|
@@ -11997,9 +12382,9 @@ function createSlackCanvasCreateTool(context, state) {
|
|
|
11997
12382
|
readOnlyHint: false
|
|
11998
12383
|
},
|
|
11999
12384
|
description: "Create a Slack canvas in the active channel.",
|
|
12000
|
-
inputSchema:
|
|
12001
|
-
title:
|
|
12002
|
-
markdown:
|
|
12385
|
+
inputSchema: z43.object({
|
|
12386
|
+
title: z43.string().min(1).max(160).describe("Canvas title."),
|
|
12387
|
+
markdown: z43.string().min(1).describe("Canvas markdown body content.")
|
|
12003
12388
|
}),
|
|
12004
12389
|
outputSchema: juniorToolOutputSchema,
|
|
12005
12390
|
execute: async ({ title, markdown }) => {
|
|
@@ -12043,8 +12428,8 @@ function createSlackCanvasCreateTool(context, state) {
|
|
|
12043
12428
|
}
|
|
12044
12429
|
|
|
12045
12430
|
// src/chat/slack/tool-support/canvas/context.ts
|
|
12046
|
-
import { z as
|
|
12047
|
-
var slackCanvasRefParam =
|
|
12431
|
+
import { z as z44 } from "zod";
|
|
12432
|
+
var slackCanvasRefParam = z44.string().min(1).describe("Slack canvas/file ID or canvas/docs URL.");
|
|
12048
12433
|
function resolveCanvasTarget(canvas) {
|
|
12049
12434
|
const canvasId = extractCanvasId(canvas);
|
|
12050
12435
|
if (!canvasId) {
|
|
@@ -12057,26 +12442,26 @@ function resolveCanvasTarget(canvas) {
|
|
|
12057
12442
|
}
|
|
12058
12443
|
|
|
12059
12444
|
// src/chat/slack/tools/canvas/edit.ts
|
|
12060
|
-
import { z as
|
|
12445
|
+
import { z as z45 } from "zod";
|
|
12061
12446
|
function prepareCanvasEditArguments(input) {
|
|
12062
12447
|
return prepareTextReplacementArguments(input);
|
|
12063
12448
|
}
|
|
12064
|
-
var editReplacementSchema2 =
|
|
12065
|
-
oldText:
|
|
12449
|
+
var editReplacementSchema2 = z45.object({
|
|
12450
|
+
oldText: z45.string().min(1).describe(
|
|
12066
12451
|
"Exact Canvas markdown to replace. It must be unique in the current Canvas body and must not overlap another edit."
|
|
12067
12452
|
),
|
|
12068
|
-
newText:
|
|
12453
|
+
newText: z45.string().describe("Replacement Canvas markdown for this edit.")
|
|
12069
12454
|
});
|
|
12070
12455
|
var slackCanvasEditOutputSchema = juniorToolOutputSchema.extend({
|
|
12071
|
-
canvas_id:
|
|
12072
|
-
title:
|
|
12073
|
-
permalink:
|
|
12074
|
-
diff:
|
|
12075
|
-
first_changed_line:
|
|
12076
|
-
replacements:
|
|
12077
|
-
normalized_heading_count:
|
|
12078
|
-
summary:
|
|
12079
|
-
deduplicated:
|
|
12456
|
+
canvas_id: z45.string().optional(),
|
|
12457
|
+
title: z45.string().optional(),
|
|
12458
|
+
permalink: z45.string().optional(),
|
|
12459
|
+
diff: z45.string().optional(),
|
|
12460
|
+
first_changed_line: z45.number().int().positive().optional(),
|
|
12461
|
+
replacements: z45.number().int().nonnegative().optional(),
|
|
12462
|
+
normalized_heading_count: z45.number().int().nonnegative().optional(),
|
|
12463
|
+
summary: z45.string().optional(),
|
|
12464
|
+
deduplicated: z45.boolean().optional()
|
|
12080
12465
|
}).strict();
|
|
12081
12466
|
function createSlackCanvasEditTool(state) {
|
|
12082
12467
|
return zodTool({
|
|
@@ -12089,9 +12474,9 @@ function createSlackCanvasEditTool(state) {
|
|
|
12089
12474
|
description: "Edit a Slack canvas with exact markdown replacements. Returns a diff.",
|
|
12090
12475
|
prepareArguments: prepareCanvasEditArguments,
|
|
12091
12476
|
executionMode: "sequential",
|
|
12092
|
-
inputSchema:
|
|
12477
|
+
inputSchema: z45.object({
|
|
12093
12478
|
canvas: slackCanvasRefParam,
|
|
12094
|
-
edits:
|
|
12479
|
+
edits: z45.array(editReplacementSchema2).min(1).describe(
|
|
12095
12480
|
"Exact replacements matched against the current Canvas body, not incrementally."
|
|
12096
12481
|
)
|
|
12097
12482
|
}),
|
|
@@ -12144,18 +12529,18 @@ function createSlackCanvasEditTool(state) {
|
|
|
12144
12529
|
}
|
|
12145
12530
|
|
|
12146
12531
|
// src/chat/slack/tools/canvas/read.ts
|
|
12147
|
-
import { z as
|
|
12532
|
+
import { z as z46 } from "zod";
|
|
12148
12533
|
var slackCanvasReadOutputSchema = juniorToolOutputSchema.extend({
|
|
12149
|
-
canvas_id:
|
|
12150
|
-
title:
|
|
12151
|
-
permalink:
|
|
12152
|
-
mimetype:
|
|
12153
|
-
filetype:
|
|
12154
|
-
original_byte_length:
|
|
12155
|
-
content:
|
|
12156
|
-
start_line:
|
|
12157
|
-
end_line:
|
|
12158
|
-
total_lines:
|
|
12534
|
+
canvas_id: z46.string().optional(),
|
|
12535
|
+
title: z46.string().optional(),
|
|
12536
|
+
permalink: z46.string().optional(),
|
|
12537
|
+
mimetype: z46.string().optional(),
|
|
12538
|
+
filetype: z46.string().optional(),
|
|
12539
|
+
original_byte_length: z46.number().int().nonnegative().optional(),
|
|
12540
|
+
content: z46.string().optional(),
|
|
12541
|
+
start_line: z46.number().int().positive().optional(),
|
|
12542
|
+
end_line: z46.number().int().nonnegative().optional(),
|
|
12543
|
+
total_lines: z46.number().int().nonnegative().optional()
|
|
12159
12544
|
}).strict();
|
|
12160
12545
|
function createSlackCanvasReadTool() {
|
|
12161
12546
|
return zodTool({
|
|
@@ -12166,10 +12551,10 @@ function createSlackCanvasReadTool() {
|
|
|
12166
12551
|
openWorldHint: true,
|
|
12167
12552
|
readOnlyHint: true
|
|
12168
12553
|
},
|
|
12169
|
-
inputSchema:
|
|
12554
|
+
inputSchema: z46.object({
|
|
12170
12555
|
canvas: slackCanvasRefParam,
|
|
12171
|
-
offset:
|
|
12172
|
-
limit:
|
|
12556
|
+
offset: z46.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
|
|
12557
|
+
limit: z46.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
|
|
12173
12558
|
}),
|
|
12174
12559
|
outputSchema: slackCanvasReadOutputSchema,
|
|
12175
12560
|
execute: async ({ canvas, offset, limit }) => {
|
|
@@ -12205,7 +12590,7 @@ function createSlackCanvasReadTool() {
|
|
|
12205
12590
|
}
|
|
12206
12591
|
|
|
12207
12592
|
// src/chat/slack/tools/canvas/write.ts
|
|
12208
|
-
import { z as
|
|
12593
|
+
import { z as z47 } from "zod";
|
|
12209
12594
|
function createSlackCanvasWriteTool(state) {
|
|
12210
12595
|
return zodTool({
|
|
12211
12596
|
annotations: {
|
|
@@ -12216,9 +12601,9 @@ function createSlackCanvasWriteTool(state) {
|
|
|
12216
12601
|
},
|
|
12217
12602
|
description: "Replace the full markdown body of a Slack canvas.",
|
|
12218
12603
|
executionMode: "sequential",
|
|
12219
|
-
inputSchema:
|
|
12604
|
+
inputSchema: z47.object({
|
|
12220
12605
|
canvas: slackCanvasRefParam,
|
|
12221
|
-
content:
|
|
12606
|
+
content: z47.string().describe("UTF-8 markdown content to write.")
|
|
12222
12607
|
}),
|
|
12223
12608
|
outputSchema: juniorToolOutputSchema,
|
|
12224
12609
|
execute: async ({ canvas, content }) => {
|
|
@@ -12440,12 +12825,12 @@ async function updateListItem(input) {
|
|
|
12440
12825
|
}
|
|
12441
12826
|
|
|
12442
12827
|
// src/chat/slack/tool-support/list/params.ts
|
|
12443
|
-
import { z as
|
|
12444
|
-
var slackListIdParam =
|
|
12445
|
-
var slackListItemIdParam =
|
|
12828
|
+
import { z as z48 } from "zod";
|
|
12829
|
+
var slackListIdParam = z48.string().min(1).describe("Slack list ID.");
|
|
12830
|
+
var slackListItemIdParam = z48.string().min(1).describe("Slack list item ID.");
|
|
12446
12831
|
|
|
12447
12832
|
// src/chat/slack/tools/list/add-items.ts
|
|
12448
|
-
import { z as
|
|
12833
|
+
import { z as z49 } from "zod";
|
|
12449
12834
|
function createSlackListAddItemsTool(state) {
|
|
12450
12835
|
return zodTool({
|
|
12451
12836
|
annotations: {
|
|
@@ -12455,13 +12840,13 @@ function createSlackListAddItemsTool(state) {
|
|
|
12455
12840
|
readOnlyHint: false
|
|
12456
12841
|
},
|
|
12457
12842
|
description: "Add tasks to a Slack list.",
|
|
12458
|
-
inputSchema:
|
|
12843
|
+
inputSchema: z49.object({
|
|
12459
12844
|
list_id: slackListIdParam,
|
|
12460
|
-
items:
|
|
12845
|
+
items: z49.array(z49.string().min(1)).min(1).max(25).describe("List item titles to create."),
|
|
12461
12846
|
assignee_user_id: slackUserIdParam(
|
|
12462
12847
|
"Optional Slack user ID assigned to all created items."
|
|
12463
12848
|
).optional(),
|
|
12464
|
-
due_date:
|
|
12849
|
+
due_date: z49.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
|
|
12465
12850
|
}),
|
|
12466
12851
|
outputSchema: juniorToolOutputSchema,
|
|
12467
12852
|
execute: async ({ list_id, items, assignee_user_id, due_date }) => {
|
|
@@ -12500,7 +12885,7 @@ function createSlackListAddItemsTool(state) {
|
|
|
12500
12885
|
}
|
|
12501
12886
|
|
|
12502
12887
|
// src/chat/slack/tools/list/create.ts
|
|
12503
|
-
import { z as
|
|
12888
|
+
import { z as z50 } from "zod";
|
|
12504
12889
|
function createSlackListCreateTool(state) {
|
|
12505
12890
|
return zodTool({
|
|
12506
12891
|
annotations: {
|
|
@@ -12510,8 +12895,8 @@ function createSlackListCreateTool(state) {
|
|
|
12510
12895
|
readOnlyHint: false
|
|
12511
12896
|
},
|
|
12512
12897
|
description: "Create a Slack todo list.",
|
|
12513
|
-
inputSchema:
|
|
12514
|
-
name:
|
|
12898
|
+
inputSchema: z50.object({
|
|
12899
|
+
name: z50.string().min(1).max(160).describe("Name for the new Slack list.")
|
|
12515
12900
|
}),
|
|
12516
12901
|
outputSchema: juniorToolOutputSchema,
|
|
12517
12902
|
execute: async ({ name }) => {
|
|
@@ -12536,7 +12921,7 @@ function createSlackListCreateTool(state) {
|
|
|
12536
12921
|
}
|
|
12537
12922
|
|
|
12538
12923
|
// src/chat/slack/tools/list/get-items.ts
|
|
12539
|
-
import { z as
|
|
12924
|
+
import { z as z51 } from "zod";
|
|
12540
12925
|
function createSlackListGetItemsTool() {
|
|
12541
12926
|
return zodTool({
|
|
12542
12927
|
description: "Read items from a Slack list.",
|
|
@@ -12546,9 +12931,9 @@ function createSlackListGetItemsTool() {
|
|
|
12546
12931
|
openWorldHint: true,
|
|
12547
12932
|
readOnlyHint: true
|
|
12548
12933
|
},
|
|
12549
|
-
inputSchema:
|
|
12934
|
+
inputSchema: z51.object({
|
|
12550
12935
|
list_id: slackListIdParam,
|
|
12551
|
-
limit:
|
|
12936
|
+
limit: z51.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
|
|
12552
12937
|
}),
|
|
12553
12938
|
outputSchema: juniorToolOutputSchema,
|
|
12554
12939
|
execute: async ({ list_id, limit }) => {
|
|
@@ -12563,23 +12948,23 @@ function createSlackListGetItemsTool() {
|
|
|
12563
12948
|
}
|
|
12564
12949
|
|
|
12565
12950
|
// src/chat/slack/tools/list/update-item.ts
|
|
12566
|
-
import { z as
|
|
12567
|
-
var booleanInput3 = (description) =>
|
|
12951
|
+
import { z as z52 } from "zod";
|
|
12952
|
+
var booleanInput3 = (description) => z52.preprocess(
|
|
12568
12953
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
12569
|
-
|
|
12954
|
+
z52.boolean()
|
|
12570
12955
|
).describe(description);
|
|
12571
|
-
var updateListItemInputSchema =
|
|
12572
|
-
|
|
12956
|
+
var updateListItemInputSchema = z52.union([
|
|
12957
|
+
z52.object({
|
|
12573
12958
|
list_id: slackListIdParam,
|
|
12574
12959
|
item_id: slackListItemIdParam,
|
|
12575
12960
|
completed: booleanInput3("Optional completion status update."),
|
|
12576
|
-
title:
|
|
12961
|
+
title: z52.string().min(1).describe("Optional new item title.").optional()
|
|
12577
12962
|
}),
|
|
12578
|
-
|
|
12963
|
+
z52.object({
|
|
12579
12964
|
list_id: slackListIdParam,
|
|
12580
12965
|
item_id: slackListItemIdParam,
|
|
12581
12966
|
completed: booleanInput3("Optional completion status update.").optional(),
|
|
12582
|
-
title:
|
|
12967
|
+
title: z52.string().min(1).describe("Optional new item title.")
|
|
12583
12968
|
})
|
|
12584
12969
|
]);
|
|
12585
12970
|
function createSlackListUpdateItemTool(state) {
|
|
@@ -12627,7 +13012,7 @@ function createSlackListUpdateItemTool(state) {
|
|
|
12627
13012
|
}
|
|
12628
13013
|
|
|
12629
13014
|
// src/chat/slack/tools/thread-read.ts
|
|
12630
|
-
import { z as
|
|
13015
|
+
import { z as z53 } from "zod";
|
|
12631
13016
|
|
|
12632
13017
|
// src/chat/slack/tool-support/slack-message-url.ts
|
|
12633
13018
|
var SLACK_HOST_PATTERN = /^[a-z0-9-]+\.slack(?:-gov)?\.com$/;
|
|
@@ -12893,14 +13278,14 @@ function createSlackThreadReadTool(context) {
|
|
|
12893
13278
|
openWorldHint: true,
|
|
12894
13279
|
readOnlyHint: true
|
|
12895
13280
|
},
|
|
12896
|
-
inputSchema:
|
|
12897
|
-
url:
|
|
13281
|
+
inputSchema: z53.object({
|
|
13282
|
+
url: z53.string().min(1).describe("Slack message archive URL.").optional(),
|
|
12898
13283
|
channel_id: slackChannelRefParam.optional(),
|
|
12899
13284
|
ts: slackTimestampParam(
|
|
12900
13285
|
"Slack message timestamp. May be the thread root or any message in the thread."
|
|
12901
13286
|
).optional(),
|
|
12902
|
-
limit:
|
|
12903
|
-
max_pages:
|
|
13287
|
+
limit: z53.coerce.number().int().min(1).max(1e3).describe("Maximum number of thread messages to fetch.").optional(),
|
|
13288
|
+
max_pages: z53.coerce.number().int().min(1).max(10).describe("Maximum number of Slack API pages to traverse.").optional()
|
|
12904
13289
|
}),
|
|
12905
13290
|
outputSchema: juniorToolOutputSchema,
|
|
12906
13291
|
execute: async ({ url, channel_id, ts, limit, max_pages }) => {
|
|
@@ -13027,7 +13412,7 @@ function createSlackThreadReadTool(context) {
|
|
|
13027
13412
|
// src/chat/tools/user-lookup.ts
|
|
13028
13413
|
import { and as and2, eq as eq2, or, sql } from "drizzle-orm";
|
|
13029
13414
|
import { alias } from "drizzle-orm/pg-core";
|
|
13030
|
-
import { z as
|
|
13415
|
+
import { z as z54 } from "zod";
|
|
13031
13416
|
var linkedSlackIdentity = alias(juniorIdentities, "user_lookup_slack_identity");
|
|
13032
13417
|
function explicitUserLookupError(error) {
|
|
13033
13418
|
if (error.apiError === "user_not_found" || error.code === "not_found") {
|
|
@@ -13176,9 +13561,9 @@ function createUserLookupTool(teamId, providers) {
|
|
|
13176
13561
|
openWorldHint: true,
|
|
13177
13562
|
readOnlyHint: true
|
|
13178
13563
|
},
|
|
13179
|
-
inputSchema:
|
|
13180
|
-
provider:
|
|
13181
|
-
query:
|
|
13564
|
+
inputSchema: z54.object({
|
|
13565
|
+
provider: z54.enum(providers).describe("Enabled identity provider to query."),
|
|
13566
|
+
query: z54.string().trim().min(1).describe("Provider subject ID, handle, Slack email, or Slack name.")
|
|
13182
13567
|
}).strict(),
|
|
13183
13568
|
outputSchema: juniorToolOutputSchema,
|
|
13184
13569
|
execute: async ({ provider, query }) => {
|
|
@@ -13198,18 +13583,18 @@ function createUserLookupTool(teamId, providers) {
|
|
|
13198
13583
|
}
|
|
13199
13584
|
|
|
13200
13585
|
// src/chat/tools/system-time.ts
|
|
13201
|
-
import { z as
|
|
13202
|
-
var systemTimeInputSchema =
|
|
13203
|
-
timezone:
|
|
13586
|
+
import { z as z55 } from "zod";
|
|
13587
|
+
var systemTimeInputSchema = z55.object({
|
|
13588
|
+
timezone: z55.string().trim().min(1).optional().describe(
|
|
13204
13589
|
"Optional IANA timezone, for example America/Los_Angeles. When set, iso_local and timezone_offset_minutes are for that zone."
|
|
13205
13590
|
)
|
|
13206
13591
|
});
|
|
13207
13592
|
var systemTimeOutputSchema = juniorToolOutputSchema.extend({
|
|
13208
|
-
unix_ms:
|
|
13209
|
-
iso_utc:
|
|
13210
|
-
iso_local:
|
|
13211
|
-
timezone:
|
|
13212
|
-
timezone_offset_minutes:
|
|
13593
|
+
unix_ms: z55.number(),
|
|
13594
|
+
iso_utc: z55.string(),
|
|
13595
|
+
iso_local: z55.string(),
|
|
13596
|
+
timezone: z55.string().nullable(),
|
|
13597
|
+
timezone_offset_minutes: z55.number()
|
|
13213
13598
|
});
|
|
13214
13599
|
function createSystemTimeTool() {
|
|
13215
13600
|
return zodTool({
|
|
@@ -13289,7 +13674,7 @@ function getTimeZoneOffsetMinutes(timestampMs, timezone) {
|
|
|
13289
13674
|
}
|
|
13290
13675
|
|
|
13291
13676
|
// src/chat/tools/publish-image.ts
|
|
13292
|
-
import { z as
|
|
13677
|
+
import { z as z56 } from "zod";
|
|
13293
13678
|
|
|
13294
13679
|
// src/chat/artifacts/store.ts
|
|
13295
13680
|
import { createHash as createHash4, randomUUID as randomUUID4 } from "crypto";
|
|
@@ -13490,10 +13875,10 @@ function unpublishedArtifactHeaders() {
|
|
|
13490
13875
|
|
|
13491
13876
|
// src/chat/tools/publish-image.ts
|
|
13492
13877
|
var outputSchema5 = juniorToolOutputSchema.extend({
|
|
13493
|
-
bytes:
|
|
13494
|
-
content_type:
|
|
13495
|
-
public:
|
|
13496
|
-
url:
|
|
13878
|
+
bytes: z56.number().int().positive(),
|
|
13879
|
+
content_type: z56.string().min(1),
|
|
13880
|
+
public: z56.literal(true),
|
|
13881
|
+
url: z56.string().url()
|
|
13497
13882
|
});
|
|
13498
13883
|
function createPublishImageTool(args) {
|
|
13499
13884
|
return zodTool({
|
|
@@ -13507,8 +13892,8 @@ function createPublishImageTool(args) {
|
|
|
13507
13892
|
description: "Publish one sandbox image to a durable public HTTPS URL. Anyone on the internet with the URL can view the image. Use only when an external destination needs a public image URL. Do not use for private file sharing or private conversation storage. Supports PNG, JPEG, GIF, and WebP up to 10 MB.",
|
|
13508
13893
|
describeProposal: ({ path: path8 }) => `Publish sandbox image ${path8} to a public internet URL.`,
|
|
13509
13894
|
executionMode: "sequential",
|
|
13510
|
-
inputSchema:
|
|
13511
|
-
path:
|
|
13895
|
+
inputSchema: z56.object({
|
|
13896
|
+
path: z56.string().min(1).describe("Exact sandbox path of an existing image file.")
|
|
13512
13897
|
}).strict(),
|
|
13513
13898
|
outputSchema: outputSchema5,
|
|
13514
13899
|
async execute({ path: path8 }) {
|
|
@@ -13541,10 +13926,10 @@ function createPublishImageTool(args) {
|
|
|
13541
13926
|
}
|
|
13542
13927
|
|
|
13543
13928
|
// src/chat/tools/unpublish-image.ts
|
|
13544
|
-
import { z as
|
|
13929
|
+
import { z as z57 } from "zod";
|
|
13545
13930
|
var outputSchema6 = juniorToolOutputSchema.extend({
|
|
13546
|
-
filename:
|
|
13547
|
-
unpublished:
|
|
13931
|
+
filename: z57.string().min(1),
|
|
13932
|
+
unpublished: z57.literal(true)
|
|
13548
13933
|
});
|
|
13549
13934
|
function createUnpublishImageTool(args) {
|
|
13550
13935
|
return zodTool({
|
|
@@ -13558,8 +13943,8 @@ function createUnpublishImageTool(args) {
|
|
|
13558
13943
|
description: "Unpublish one public image previously published in this conversation so its public URL stops serving. Pass the public artifact URL or `<id>.<ext>` filename. Only images owned by this conversation can be unpublished. Republishing the same image bytes later in this conversation restores a live URL for this conversation. Does not remove copies already fetched by browsers or GitHub.",
|
|
13559
13944
|
describeProposal: ({ ref }) => `Unpublish public image ${ref}.`,
|
|
13560
13945
|
executionMode: "sequential",
|
|
13561
|
-
inputSchema:
|
|
13562
|
-
ref:
|
|
13946
|
+
inputSchema: z57.object({
|
|
13947
|
+
ref: z57.string().min(1).describe(
|
|
13563
13948
|
"Public artifact URL or artifact filename (`<id>.<ext>`)."
|
|
13564
13949
|
)
|
|
13565
13950
|
}).strict(),
|
|
@@ -13579,27 +13964,27 @@ function createUnpublishImageTool(args) {
|
|
|
13579
13964
|
}
|
|
13580
13965
|
|
|
13581
13966
|
// src/chat/tools/search-conversation-events.ts
|
|
13582
|
-
import { z as
|
|
13967
|
+
import { z as z58 } from "zod";
|
|
13583
13968
|
var DEFAULT_LIMIT3 = 25;
|
|
13584
13969
|
var MAX_LIMIT2 = 100;
|
|
13585
13970
|
var MAX_EVENT_DATA_BYTES = 4e3;
|
|
13586
13971
|
var MAX_EVENTS_JSON_BYTES = 2e4;
|
|
13587
13972
|
var MAX_IDENTITY_CHARS = 256;
|
|
13588
13973
|
var textEncoder = new TextEncoder();
|
|
13589
|
-
var knownEventTypeSchema =
|
|
13590
|
-
var projectedEventSchema =
|
|
13591
|
-
seq:
|
|
13592
|
-
history_version:
|
|
13593
|
-
created_at:
|
|
13594
|
-
idempotency_key:
|
|
13595
|
-
data:
|
|
13974
|
+
var knownEventTypeSchema = z58.enum(KNOWN_CONVERSATION_EVENT_TYPES);
|
|
13975
|
+
var projectedEventSchema = z58.object({
|
|
13976
|
+
seq: z58.number().int().nonnegative().describe("Stable event position for pagination."),
|
|
13977
|
+
history_version: z58.number().int().nonnegative().describe("Agent history generation after replacement."),
|
|
13978
|
+
created_at: z58.iso.datetime().describe("When the event was recorded."),
|
|
13979
|
+
idempotency_key: z58.string().min(1).optional().describe("Retry-stable event identity, when assigned."),
|
|
13980
|
+
data: z58.record(z58.string(), z58.unknown()).describe("Bounded event data.")
|
|
13596
13981
|
}).strict();
|
|
13597
13982
|
var searchConversationEventsOutputSchema = juniorToolOutputSchema.extend({
|
|
13598
|
-
conversation_id:
|
|
13599
|
-
events:
|
|
13600
|
-
has_older:
|
|
13601
|
-
has_newer:
|
|
13602
|
-
omitted_event_count:
|
|
13983
|
+
conversation_id: z58.string().min(1),
|
|
13984
|
+
events: z58.array(projectedEventSchema),
|
|
13985
|
+
has_older: z58.boolean().describe("Whether matching older events exist."),
|
|
13986
|
+
has_newer: z58.boolean().describe("Whether matching newer events exist."),
|
|
13987
|
+
omitted_event_count: z58.number().int().nonnegative().optional().describe("Events omitted by the response byte limit.")
|
|
13603
13988
|
});
|
|
13604
13989
|
function createSearchConversationEventsTool(context) {
|
|
13605
13990
|
return zodTool({
|
|
@@ -13612,16 +13997,16 @@ function createSearchConversationEventsTool(context) {
|
|
|
13612
13997
|
openWorldHint: false,
|
|
13613
13998
|
readOnlyHint: true
|
|
13614
13999
|
},
|
|
13615
|
-
inputSchema:
|
|
13616
|
-
conversation_id:
|
|
14000
|
+
inputSchema: z58.object({
|
|
14001
|
+
conversation_id: z58.string().trim().min(1).nullable().describe(
|
|
13617
14002
|
"Conversation ID to search. Omit or null for the current conversation."
|
|
13618
14003
|
).optional(),
|
|
13619
|
-
after_seq:
|
|
13620
|
-
before_seq:
|
|
13621
|
-
limit:
|
|
14004
|
+
after_seq: z58.number().int().nonnegative().nullable().describe("Exclusive event sequence lower bound; returns ascending.").optional(),
|
|
14005
|
+
before_seq: z58.number().int().nonnegative().nullable().describe("Exclusive event sequence upper bound.").optional(),
|
|
14006
|
+
limit: z58.number().int().min(1).max(MAX_LIMIT2).nullable().describe(
|
|
13622
14007
|
`Maximum events. Default ${DEFAULT_LIMIT3}; max ${MAX_LIMIT2}.`
|
|
13623
14008
|
).optional(),
|
|
13624
|
-
types:
|
|
14009
|
+
types: z58.array(knownEventTypeSchema).min(1).nullable().describe("Event types to include; omit for all types.").optional()
|
|
13625
14010
|
}).strict(),
|
|
13626
14011
|
outputSchema: searchConversationEventsOutputSchema,
|
|
13627
14012
|
execute: async (input) => {
|
|
@@ -13870,14 +14255,21 @@ function stripReplacementHistoryField(value) {
|
|
|
13870
14255
|
}
|
|
13871
14256
|
|
|
13872
14257
|
// src/chat/tools/handoff/tool.ts
|
|
13873
|
-
import { z as
|
|
14258
|
+
import { z as z59 } from "zod";
|
|
13874
14259
|
var HANDOFF_TOOL_NAME = "handoff";
|
|
14260
|
+
function formatHandoffProfiles(handoff) {
|
|
14261
|
+
return handoff.profiles.map(
|
|
14262
|
+
(profile) => `- ${formatModelProfile(profile.name, profile.description)}`
|
|
14263
|
+
).join("\n");
|
|
14264
|
+
}
|
|
13875
14265
|
function createHandoffTool(handoff) {
|
|
13876
|
-
const profileSchema =
|
|
14266
|
+
const profileSchema = z59.enum(
|
|
14267
|
+
handoff.profiles.map((profile) => profile.name)
|
|
14268
|
+
);
|
|
13877
14269
|
const handoffResultSchema = juniorToolOutputSchema.extend({
|
|
13878
14270
|
model_profile: modelProfileSchema
|
|
13879
14271
|
});
|
|
13880
|
-
const
|
|
14272
|
+
const profileList = formatHandoffProfiles(handoff);
|
|
13881
14273
|
return zodTool({
|
|
13882
14274
|
annotations: {
|
|
13883
14275
|
destructiveHint: false,
|
|
@@ -13885,10 +14277,21 @@ function createHandoffTool(handoff) {
|
|
|
13885
14277
|
openWorldHint: false,
|
|
13886
14278
|
readOnlyHint: false
|
|
13887
14279
|
},
|
|
13888
|
-
description:
|
|
14280
|
+
description: [
|
|
14281
|
+
"Switch this conversation to another configured model profile and continue the same task.",
|
|
14282
|
+
"Call this as the only tool in the assistant turn, before substantial analysis or implementation, when a listed profile's description fits the task better than the current profile.",
|
|
14283
|
+
"Use each description's use and avoid cases. Do not select by the profile name or assume that a non-default profile is stronger.",
|
|
14284
|
+
"Do not call this for ordinary lookups, short answers, light investigation, or only because the task mentions code.",
|
|
14285
|
+
"Do not call this after you have done the difficult work on the current profile. Do not combine it with other tools in the same assistant message.",
|
|
14286
|
+
"A successful handoff becomes the active profile for later turns. Another handoff can change it again.",
|
|
14287
|
+
`Available profiles:
|
|
14288
|
+
${profileList}`
|
|
14289
|
+
].join(" "),
|
|
13889
14290
|
executionMode: "sequential",
|
|
13890
|
-
inputSchema:
|
|
13891
|
-
profile: profileSchema.describe(
|
|
14291
|
+
inputSchema: z59.object({
|
|
14292
|
+
profile: profileSchema.describe(
|
|
14293
|
+
"Exact configured profile name. Choose the profile whose description best fits the remaining task. If none clearly fits better, do not call handoff."
|
|
14294
|
+
)
|
|
13892
14295
|
}).strict(),
|
|
13893
14296
|
outputSchema: handoffResultSchema,
|
|
13894
14297
|
execute: async (input, options) => {
|
|
@@ -13908,7 +14311,7 @@ function createHandoffTool(handoff) {
|
|
|
13908
14311
|
}
|
|
13909
14312
|
|
|
13910
14313
|
// src/chat/tools/web/fetch-tool.ts
|
|
13911
|
-
import { z as
|
|
14314
|
+
import { z as z60 } from "zod";
|
|
13912
14315
|
|
|
13913
14316
|
// src/chat/tools/web/constants.ts
|
|
13914
14317
|
var USER_AGENT = "junior-bot/0.1";
|
|
@@ -14357,9 +14760,9 @@ function createWebFetchTool(hooks, options = {}) {
|
|
|
14357
14760
|
openWorldHint: true,
|
|
14358
14761
|
readOnlyHint: true
|
|
14359
14762
|
},
|
|
14360
|
-
inputSchema:
|
|
14361
|
-
url:
|
|
14362
|
-
max_chars:
|
|
14763
|
+
inputSchema: z60.object({
|
|
14764
|
+
url: z60.string().min(1).describe("HTTP(S) URL to fetch."),
|
|
14765
|
+
max_chars: z60.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
|
|
14363
14766
|
}),
|
|
14364
14767
|
outputSchema: juniorToolOutputSchema,
|
|
14365
14768
|
execute: async ({ url, max_chars }) => {
|
|
@@ -14404,7 +14807,7 @@ function createWebFetchTool(hooks, options = {}) {
|
|
|
14404
14807
|
}
|
|
14405
14808
|
|
|
14406
14809
|
// src/chat/tools/web/search.ts
|
|
14407
|
-
import { z as
|
|
14810
|
+
import { z as z61 } from "zod";
|
|
14408
14811
|
import { generateText } from "ai";
|
|
14409
14812
|
import { createGatewayProvider } from "@ai-sdk/gateway";
|
|
14410
14813
|
var SEARCH_TIMEOUT_MS = 6e4;
|
|
@@ -14446,9 +14849,9 @@ function createWebSearchTool(modelId, override) {
|
|
|
14446
14849
|
openWorldHint: true,
|
|
14447
14850
|
readOnlyHint: true
|
|
14448
14851
|
},
|
|
14449
|
-
inputSchema:
|
|
14450
|
-
query:
|
|
14451
|
-
max_results:
|
|
14852
|
+
inputSchema: z61.object({
|
|
14853
|
+
query: z61.string().min(1).max(500).describe("Search query."),
|
|
14854
|
+
max_results: z61.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
|
|
14452
14855
|
}),
|
|
14453
14856
|
outputSchema: juniorToolOutputSchema,
|
|
14454
14857
|
execute: async ({ query, max_results }) => {
|
|
@@ -14490,7 +14893,7 @@ function createWebSearchTool(modelId, override) {
|
|
|
14490
14893
|
}
|
|
14491
14894
|
|
|
14492
14895
|
// src/chat/tools/sandbox/write-file.ts
|
|
14493
|
-
import { z as
|
|
14896
|
+
import { z as z62 } from "zod";
|
|
14494
14897
|
function createWriteFileTool() {
|
|
14495
14898
|
return zodTool({
|
|
14496
14899
|
annotations: {
|
|
@@ -14501,9 +14904,9 @@ function createWriteFileTool() {
|
|
|
14501
14904
|
},
|
|
14502
14905
|
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.",
|
|
14503
14906
|
executionMode: "sequential",
|
|
14504
|
-
inputSchema:
|
|
14505
|
-
path:
|
|
14506
|
-
content:
|
|
14907
|
+
inputSchema: z62.object({
|
|
14908
|
+
path: z62.string().min(1).describe("Path to write in the sandbox workspace."),
|
|
14909
|
+
content: z62.string().describe("UTF-8 file content to write.")
|
|
14507
14910
|
}),
|
|
14508
14911
|
outputSchema: juniorToolOutputSchema,
|
|
14509
14912
|
execute: async () => {
|
|
@@ -14515,7 +14918,7 @@ function createWriteFileTool() {
|
|
|
14515
14918
|
}
|
|
14516
14919
|
|
|
14517
14920
|
// src/chat/workspaces/tools.ts
|
|
14518
|
-
import { z as
|
|
14921
|
+
import { z as z63 } from "zod";
|
|
14519
14922
|
import {
|
|
14520
14923
|
resourceEventSubscriptionResultSchema
|
|
14521
14924
|
} from "@sentry/junior-plugin-api";
|
|
@@ -14547,16 +14950,16 @@ async function stopWorkspaceSnapshotWatch(input) {
|
|
|
14547
14950
|
});
|
|
14548
14951
|
}
|
|
14549
14952
|
}
|
|
14550
|
-
var repoSchema =
|
|
14551
|
-
provider:
|
|
14552
|
-
repo:
|
|
14553
|
-
checkout_path:
|
|
14953
|
+
var repoSchema = z63.object({
|
|
14954
|
+
provider: z63.string(),
|
|
14955
|
+
repo: z63.string(),
|
|
14956
|
+
checkout_path: z63.string()
|
|
14554
14957
|
});
|
|
14555
|
-
var workspaceSchema =
|
|
14556
|
-
id:
|
|
14557
|
-
name:
|
|
14558
|
-
setup_script:
|
|
14559
|
-
repos:
|
|
14958
|
+
var workspaceSchema = z63.object({
|
|
14959
|
+
id: z63.string(),
|
|
14960
|
+
name: z63.string(),
|
|
14961
|
+
setup_script: z63.string(),
|
|
14962
|
+
repos: z63.array(repoSchema)
|
|
14560
14963
|
});
|
|
14561
14964
|
function view(workspace) {
|
|
14562
14965
|
return {
|
|
@@ -14589,18 +14992,18 @@ function workspaceProviderNames() {
|
|
|
14589
14992
|
}
|
|
14590
14993
|
function workspaceWriteSchemas(providers) {
|
|
14591
14994
|
const providerNames = providers.map((provider) => `\`${provider}\``).join(", ");
|
|
14592
|
-
const repoInputSchema =
|
|
14593
|
-
provider:
|
|
14594
|
-
repo:
|
|
14995
|
+
const repoInputSchema = z63.object({
|
|
14996
|
+
provider: z63.enum(providers).describe(`Repository provider. Supported: ${providerNames}.`),
|
|
14997
|
+
repo: z63.string().trim().min(1).describe("Repository in owner/name format.")
|
|
14595
14998
|
}).strict();
|
|
14596
|
-
const workspaceInputSchema =
|
|
14597
|
-
name:
|
|
14999
|
+
const workspaceInputSchema = z63.object({
|
|
15000
|
+
name: z63.string().trim().min(1).describe(
|
|
14598
15001
|
"Workspace name. Use lowercase letters, digits, underscores, or hyphens."
|
|
14599
15002
|
),
|
|
14600
|
-
setup_script:
|
|
15003
|
+
setup_script: z63.string().nullable().describe(
|
|
14601
15004
|
"Optional shell script to run after repository checkout whenever this Workspace starts. Omit or use null for no setup script."
|
|
14602
15005
|
).optional(),
|
|
14603
|
-
repos:
|
|
15006
|
+
repos: z63.array(repoInputSchema).max(32).describe("Complete repository list.")
|
|
14604
15007
|
}).strict();
|
|
14605
15008
|
return { providerNames, workspaceInputSchema };
|
|
14606
15009
|
}
|
|
@@ -14675,7 +15078,7 @@ function createWorkspaceWriteTools(providers) {
|
|
|
14675
15078
|
},
|
|
14676
15079
|
description: `Replace an install-wide Workspace recipe. Repository providers: ${providerNames}. Use the Workspace ID returned by listWorkspaces.`,
|
|
14677
15080
|
inputSchema: workspaceInputSchema.extend({
|
|
14678
|
-
id:
|
|
15081
|
+
id: z63.string().uuid().describe("Workspace ID from listWorkspaces.")
|
|
14679
15082
|
}).strict(),
|
|
14680
15083
|
prepareArguments(args) {
|
|
14681
15084
|
const input = args;
|
|
@@ -14708,11 +15111,11 @@ function createWorkspaceWriteTools(providers) {
|
|
|
14708
15111
|
readOnlyHint: false
|
|
14709
15112
|
},
|
|
14710
15113
|
description: "Delete one install-wide Workspace recipe. Use the Workspace ID returned by listWorkspaces.",
|
|
14711
|
-
inputSchema:
|
|
14712
|
-
id:
|
|
15114
|
+
inputSchema: z63.object({
|
|
15115
|
+
id: z63.string().uuid().describe("Workspace ID from listWorkspaces.")
|
|
14713
15116
|
}).strict(),
|
|
14714
15117
|
outputSchema: juniorToolOutputSchema.extend({
|
|
14715
|
-
deleted:
|
|
15118
|
+
deleted: z63.literal(true)
|
|
14716
15119
|
}),
|
|
14717
15120
|
async execute({ id }) {
|
|
14718
15121
|
const deleted = await workspaceWrite(() => deleteWorkspace(id));
|
|
@@ -14737,10 +15140,10 @@ function createWorkspaceTools(context) {
|
|
|
14737
15140
|
readOnlyHint: true
|
|
14738
15141
|
},
|
|
14739
15142
|
description: "List named repository workspaces that can replace the current sandbox.",
|
|
14740
|
-
inputSchema:
|
|
15143
|
+
inputSchema: z63.object({}).strict(),
|
|
14741
15144
|
outputSchema: juniorToolOutputSchema.extend({
|
|
14742
|
-
active_workspace_id:
|
|
14743
|
-
workspaces:
|
|
15145
|
+
active_workspace_id: z63.string().nullable(),
|
|
15146
|
+
workspaces: z63.array(workspaceSchema)
|
|
14744
15147
|
}),
|
|
14745
15148
|
async execute() {
|
|
14746
15149
|
return {
|
|
@@ -14758,12 +15161,12 @@ function createWorkspaceTools(context) {
|
|
|
14758
15161
|
readOnlyHint: false
|
|
14759
15162
|
},
|
|
14760
15163
|
description: "Replace the current sandbox with a named repository Workspace. Files in the old sandbox do not carry over. Returns ready after the switch, or building with a temporary subscription when the snapshot is still being prepared. When building, wait for the ready event and call switchWorkspace again with the same name.",
|
|
14761
|
-
inputSchema:
|
|
14762
|
-
name:
|
|
15164
|
+
inputSchema: z63.object({
|
|
15165
|
+
name: z63.string().trim().min(1).describe("Exact workspace name.")
|
|
14763
15166
|
}).strict(),
|
|
14764
15167
|
outputSchema: juniorToolOutputSchema.extend({
|
|
14765
15168
|
workspace: workspaceSchema,
|
|
14766
|
-
status:
|
|
15169
|
+
status: z63.enum(["ready", "building"]),
|
|
14767
15170
|
subscription: resourceEventSubscriptionResultSchema.optional().describe(
|
|
14768
15171
|
"Present when the snapshot ready and failed events are already watched for this conversation."
|
|
14769
15172
|
)
|
|
@@ -15549,7 +15952,7 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, conv
|
|
|
15549
15952
|
}
|
|
15550
15953
|
|
|
15551
15954
|
// src/chat/tools/execute-tool.ts
|
|
15552
|
-
import { z as
|
|
15955
|
+
import { z as z64 } from "zod";
|
|
15553
15956
|
var EXECUTE_TOOL_NAME = "executeTool";
|
|
15554
15957
|
function createExecuteToolTool() {
|
|
15555
15958
|
return zodTool({
|
|
@@ -15561,11 +15964,11 @@ function createExecuteToolTool() {
|
|
|
15561
15964
|
},
|
|
15562
15965
|
description: "Execute any catalog tool by exact tool_name from searchTools or a tool-result execution hint. Put tool-specific parameters inside arguments.",
|
|
15563
15966
|
executionMode: "sequential",
|
|
15564
|
-
inputSchema:
|
|
15565
|
-
tool_name:
|
|
15967
|
+
inputSchema: z64.object({
|
|
15968
|
+
tool_name: z64.string().min(1).describe(
|
|
15566
15969
|
"Exact catalog tool_name returned by searchTools or a tool-result execution hint."
|
|
15567
15970
|
),
|
|
15568
|
-
arguments:
|
|
15971
|
+
arguments: z64.record(z64.string(), z64.unknown()).describe(
|
|
15569
15972
|
'Arguments matching the selected catalog tool schema, for example { "query": "..." }.'
|
|
15570
15973
|
).optional()
|
|
15571
15974
|
}).strict(),
|
|
@@ -15605,7 +16008,7 @@ function planToolExposure(tools) {
|
|
|
15605
16008
|
}
|
|
15606
16009
|
|
|
15607
16010
|
// src/chat/tools/search-tools.ts
|
|
15608
|
-
import { z as
|
|
16011
|
+
import { z as z65 } from "zod";
|
|
15609
16012
|
var SEARCH_TOOLS_NAME = "searchTools";
|
|
15610
16013
|
var DEFAULT_MAX_RESULTS2 = 5;
|
|
15611
16014
|
var MAX_RESULTS3 = 20;
|
|
@@ -15650,29 +16053,29 @@ var SEARCH_STOP_WORDS = /* @__PURE__ */ new Set([
|
|
|
15650
16053
|
"you",
|
|
15651
16054
|
"your"
|
|
15652
16055
|
]);
|
|
15653
|
-
var searchToolsSourceSchema =
|
|
15654
|
-
id:
|
|
15655
|
-
description:
|
|
16056
|
+
var searchToolsSourceSchema = z65.object({
|
|
16057
|
+
id: z65.string(),
|
|
16058
|
+
description: z65.string()
|
|
15656
16059
|
}).strict();
|
|
15657
|
-
var searchToolsToolSchema =
|
|
15658
|
-
tool_name:
|
|
15659
|
-
description:
|
|
15660
|
-
exposure:
|
|
15661
|
-
source:
|
|
15662
|
-
input_schema:
|
|
15663
|
-
call_notes:
|
|
15664
|
-
annotations:
|
|
16060
|
+
var searchToolsToolSchema = z65.object({
|
|
16061
|
+
tool_name: z65.string(),
|
|
16062
|
+
description: z65.string(),
|
|
16063
|
+
exposure: z65.enum(["direct", "deferred", "modelOnly", "hidden"]),
|
|
16064
|
+
source: z65.string().optional(),
|
|
16065
|
+
input_schema: z65.unknown(),
|
|
16066
|
+
call_notes: z65.array(z65.string()),
|
|
16067
|
+
annotations: z65.record(z65.string(), z65.unknown())
|
|
15665
16068
|
}).strict();
|
|
15666
16069
|
var searchToolsOutputSchema = juniorToolOutputSchema.extend({
|
|
15667
|
-
query:
|
|
15668
|
-
source:
|
|
15669
|
-
sources:
|
|
15670
|
-
total_catalog_tools:
|
|
15671
|
-
total_eligible_tools:
|
|
15672
|
-
total_matches:
|
|
15673
|
-
returned_tools:
|
|
15674
|
-
execution_tool:
|
|
15675
|
-
tools:
|
|
16070
|
+
query: z65.string().nullable(),
|
|
16071
|
+
source: z65.string().nullable(),
|
|
16072
|
+
sources: z65.array(searchToolsSourceSchema),
|
|
16073
|
+
total_catalog_tools: z65.number().int().nonnegative(),
|
|
16074
|
+
total_eligible_tools: z65.number().int().nonnegative(),
|
|
16075
|
+
total_matches: z65.number().int().nonnegative(),
|
|
16076
|
+
returned_tools: z65.number().int().nonnegative(),
|
|
16077
|
+
execution_tool: z65.literal("executeTool"),
|
|
16078
|
+
tools: z65.array(searchToolsToolSchema)
|
|
15676
16079
|
}).strict();
|
|
15677
16080
|
function terms(value) {
|
|
15678
16081
|
const chunks = value.match(/[\p{L}\p{N}]+/gu) ?? [];
|
|
@@ -15883,14 +16286,14 @@ function createSearchToolsTool(catalogTools) {
|
|
|
15883
16286
|
openWorldHint: false,
|
|
15884
16287
|
readOnlyHint: true
|
|
15885
16288
|
},
|
|
15886
|
-
inputSchema:
|
|
15887
|
-
query:
|
|
16289
|
+
inputSchema: z65.object({
|
|
16290
|
+
query: z65.string().nullable().describe(
|
|
15888
16291
|
"Optional search terms describing the tool, owner, action, or arguments needed. Empty string lists catalog tools."
|
|
15889
16292
|
).optional(),
|
|
15890
|
-
source:
|
|
16293
|
+
source: z65.string().nullable().describe(
|
|
15891
16294
|
"Optional source id to search within, such as a plugin source returned in sources."
|
|
15892
16295
|
).optional(),
|
|
15893
|
-
max_results:
|
|
16296
|
+
max_results: z65.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
|
|
15894
16297
|
}).strict(),
|
|
15895
16298
|
outputSchema: searchToolsOutputSchema,
|
|
15896
16299
|
privateTraceResult: (result) => ({
|
|
@@ -17188,7 +17591,7 @@ function createPluginEgress(deps) {
|
|
|
17188
17591
|
}
|
|
17189
17592
|
|
|
17190
17593
|
// src/chat/services/guardian-action-review.ts
|
|
17191
|
-
import { z as
|
|
17594
|
+
import { z as z66 } from "zod";
|
|
17192
17595
|
|
|
17193
17596
|
// src/chat/services/guardian-action-policy.ts
|
|
17194
17597
|
var GUARDIAN_ACTION_POLICY = `You are judging one planned Junior agent action.
|
|
@@ -17262,17 +17665,17 @@ Assess the exact action's intrinsic risk and whether the user's intent authorize
|
|
|
17262
17665
|
- 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.`;
|
|
17263
17666
|
|
|
17264
17667
|
// src/chat/services/guardian-action-review.ts
|
|
17265
|
-
var guardianDecisionSchema =
|
|
17266
|
-
decision:
|
|
17267
|
-
reason:
|
|
17268
|
-
riskLevel:
|
|
17269
|
-
userAuthorization:
|
|
17668
|
+
var guardianDecisionSchema = z66.object({
|
|
17669
|
+
decision: z66.enum(["allow", "ask", "deny"]),
|
|
17670
|
+
reason: z66.string().trim().min(1).max(500),
|
|
17671
|
+
riskLevel: z66.enum(["low", "medium", "high", "critical"]),
|
|
17672
|
+
userAuthorization: z66.enum(["high", "medium", "low", "unknown"])
|
|
17270
17673
|
}).strict();
|
|
17271
17674
|
var GUARDIAN_REVIEW_TIMEOUT_MS = 6e4;
|
|
17272
17675
|
var GUARDIAN_REVIEW_MAX_TOKENS = 2e3;
|
|
17273
17676
|
var MAX_PROPOSAL_CHARS = 192e3;
|
|
17274
17677
|
function guardianPrompt(proposal) {
|
|
17275
|
-
const proposalJson = JSON.stringify(
|
|
17678
|
+
const proposalJson = JSON.stringify(z66.json().parse(proposal), null, 2);
|
|
17276
17679
|
if (proposalJson.length > MAX_PROPOSAL_CHARS) {
|
|
17277
17680
|
throw new Error(
|
|
17278
17681
|
`Guardian action proposal exceeds ${MAX_PROPOSAL_CHARS} characters.`
|
|
@@ -18601,6 +19004,145 @@ ${summary}`
|
|
|
18601
19004
|
return { compacted: true, piMessages: messages };
|
|
18602
19005
|
}
|
|
18603
19006
|
|
|
19007
|
+
// src/chat/agent/handoff.ts
|
|
19008
|
+
var EXCLUSIVE_TOOL_NAMES = [HANDOFF_TOOL_NAME, "switchWorkspace"];
|
|
19009
|
+
function exclusiveToolName(toolCalls) {
|
|
19010
|
+
for (const name of EXCLUSIVE_TOOL_NAMES) {
|
|
19011
|
+
if (toolCalls.some((call) => call.name === name)) {
|
|
19012
|
+
return name;
|
|
19013
|
+
}
|
|
19014
|
+
}
|
|
19015
|
+
return void 0;
|
|
19016
|
+
}
|
|
19017
|
+
function handoffControl(args) {
|
|
19018
|
+
if (!args.enabled) {
|
|
19019
|
+
return void 0;
|
|
19020
|
+
}
|
|
19021
|
+
const profileNames = [
|
|
19022
|
+
botConfig.defaultProfile,
|
|
19023
|
+
...Object.keys(botConfig.profiles).filter((profile) => profile !== botConfig.defaultProfile).sort()
|
|
19024
|
+
].filter((profile) => profile !== args.activeProfile);
|
|
19025
|
+
const [firstProfileName, ...otherProfileNames] = profileNames;
|
|
19026
|
+
if (!firstProfileName) {
|
|
19027
|
+
return void 0;
|
|
19028
|
+
}
|
|
19029
|
+
const toHandoffProfile = (name) => ({
|
|
19030
|
+
name,
|
|
19031
|
+
description: profileConfig(botConfig, name).description
|
|
19032
|
+
});
|
|
19033
|
+
return {
|
|
19034
|
+
profiles: [
|
|
19035
|
+
toHandoffProfile(firstProfileName),
|
|
19036
|
+
...otherProfileNames.map(toHandoffProfile)
|
|
19037
|
+
],
|
|
19038
|
+
execute: args.execute
|
|
19039
|
+
};
|
|
19040
|
+
}
|
|
19041
|
+
function toolsForHandoffProfile(args) {
|
|
19042
|
+
const control = handoffControl({
|
|
19043
|
+
activeProfile: args.activeProfile,
|
|
19044
|
+
enabled: args.enabled,
|
|
19045
|
+
execute: args.execute
|
|
19046
|
+
});
|
|
19047
|
+
if (!control) {
|
|
19048
|
+
return args.agentTools.filter((tool) => tool.name !== HANDOFF_TOOL_NAME);
|
|
19049
|
+
}
|
|
19050
|
+
const handoffAgentTool = args.agentTools.find(
|
|
19051
|
+
(tool) => tool.name === HANDOFF_TOOL_NAME
|
|
19052
|
+
);
|
|
19053
|
+
if (!handoffAgentTool) {
|
|
19054
|
+
throw new Error("Handoff control is missing its Pi tool");
|
|
19055
|
+
}
|
|
19056
|
+
const definition = createHandoffTool(control);
|
|
19057
|
+
return args.agentTools.map(
|
|
19058
|
+
(tool) => tool.name === HANDOFF_TOOL_NAME ? {
|
|
19059
|
+
...handoffAgentTool,
|
|
19060
|
+
description: definition.description,
|
|
19061
|
+
parameters: definition.inputSchema,
|
|
19062
|
+
prepareArguments: definition.prepareArguments
|
|
19063
|
+
} : tool
|
|
19064
|
+
);
|
|
19065
|
+
}
|
|
19066
|
+
async function commitHandoff(args) {
|
|
19067
|
+
if (args.profile === args.activeModelProfile) {
|
|
19068
|
+
return void 0;
|
|
19069
|
+
}
|
|
19070
|
+
const runtimeContext = retainRuntimeTurnContext(
|
|
19071
|
+
args.runtimeContextSourceMessages ?? args.sourceMessages
|
|
19072
|
+
);
|
|
19073
|
+
const phaseUsageSummary = extractGenAiUsageSummary(
|
|
19074
|
+
...args.sourceMessages.slice(args.beforeMessageCount).filter(isAssistantMessage)
|
|
19075
|
+
);
|
|
19076
|
+
const phaseUsage = hasAgentTurnUsage(phaseUsageSummary) ? phaseUsageSummary : void 0;
|
|
19077
|
+
const selectedProfile = profileConfig(botConfig, args.profile);
|
|
19078
|
+
const handoffReasoningLevel = selectedProfile.reasoningLevel ?? args.turnRoute.reasoningLevel;
|
|
19079
|
+
const target = {
|
|
19080
|
+
modelId: selectedProfile.modelId,
|
|
19081
|
+
modelProfile: args.profile,
|
|
19082
|
+
reasoningLevel: handoffReasoningLevel
|
|
19083
|
+
};
|
|
19084
|
+
void (async () => {
|
|
19085
|
+
await args.onStatus?.({ text: "Switching models" });
|
|
19086
|
+
})().catch((error) => {
|
|
19087
|
+
logWarn("assistant.status.observer.failed", {
|
|
19088
|
+
"exception.message": error instanceof Error ? error.message : String(error)
|
|
19089
|
+
});
|
|
19090
|
+
});
|
|
19091
|
+
const handoffMessages = await compactContextForHandoff(
|
|
19092
|
+
{
|
|
19093
|
+
conversationContext: args.conversationContext,
|
|
19094
|
+
conversationId: args.conversationId,
|
|
19095
|
+
piMessages: args.sourceMessages,
|
|
19096
|
+
runtimeContext,
|
|
19097
|
+
signal: args.signal,
|
|
19098
|
+
triggeringToolCallId: args.triggeringToolCallId,
|
|
19099
|
+
target,
|
|
19100
|
+
metadata: args.metadata
|
|
19101
|
+
},
|
|
19102
|
+
{
|
|
19103
|
+
completeText: (completeArgs) => completeText(completeArgs)
|
|
19104
|
+
}
|
|
19105
|
+
);
|
|
19106
|
+
const turnRoute = handoffReasoningLevel === args.turnRoute.reasoningLevel ? args.turnRoute : {
|
|
19107
|
+
...args.turnRoute,
|
|
19108
|
+
reasoningLevel: handoffReasoningLevel,
|
|
19109
|
+
reason: `profile_reasoning_override:${args.profile}:${args.turnRoute.reason}`
|
|
19110
|
+
};
|
|
19111
|
+
return {
|
|
19112
|
+
messages: handoffMessages,
|
|
19113
|
+
model: resolveGatewayModel(target.modelId),
|
|
19114
|
+
modelId: target.modelId,
|
|
19115
|
+
modelProfile: args.profile,
|
|
19116
|
+
phaseUsage,
|
|
19117
|
+
thinkingLevel: toPiReasoningLevel(handoffReasoningLevel),
|
|
19118
|
+
turnRoute
|
|
19119
|
+
};
|
|
19120
|
+
}
|
|
19121
|
+
function applyHandoff(args) {
|
|
19122
|
+
const replacement = [...args.pending.messages];
|
|
19123
|
+
args.agent.state.messages = replacement;
|
|
19124
|
+
args.agent.state.model = args.pending.model;
|
|
19125
|
+
args.agent.state.thinkingLevel = args.pending.thinkingLevel;
|
|
19126
|
+
args.agent.state.tools = args.tools;
|
|
19127
|
+
args.resume.setBeforeMessageCount(replacement.length);
|
|
19128
|
+
args.resume.setTurnStartMessageIndex(0);
|
|
19129
|
+
args.resume.adoptCommittedBoundary(replacement);
|
|
19130
|
+
setSpanAttributes({
|
|
19131
|
+
"gen_ai.agent.model": args.pending.modelId,
|
|
19132
|
+
"gen_ai.agent.model_profile": args.pending.modelProfile,
|
|
19133
|
+
"gen_ai.agent.reasoning.level": args.pending.turnRoute.reasoningLevel
|
|
19134
|
+
});
|
|
19135
|
+
return {
|
|
19136
|
+
context: {
|
|
19137
|
+
systemPrompt: args.baseInstructions,
|
|
19138
|
+
messages: replacement,
|
|
19139
|
+
tools: args.tools
|
|
19140
|
+
},
|
|
19141
|
+
model: args.pending.model,
|
|
19142
|
+
thinkingLevel: args.pending.thinkingLevel
|
|
19143
|
+
};
|
|
19144
|
+
}
|
|
19145
|
+
|
|
18604
19146
|
// src/chat/agent/index.ts
|
|
18605
19147
|
var AGENT_ABORT_SETTLE_GRACE_MS = 5e3;
|
|
18606
19148
|
async function readRunConversationVisibility(conversationId) {
|
|
@@ -18996,93 +19538,56 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
|
|
|
18996
19538
|
activeModelProfile = routedModelProfile;
|
|
18997
19539
|
activeModelId = routedModelId;
|
|
18998
19540
|
let pendingPiHookError;
|
|
18999
|
-
let pendingHandoff;
|
|
19000
19541
|
const currentAgentMessages = () => agent ? [...agent.state.messages] : [];
|
|
19001
|
-
const handoffProfiles = [
|
|
19002
|
-
botConfig.defaultProfile,
|
|
19003
|
-
...Object.keys(botConfig.profiles).filter((profile) => profile !== botConfig.defaultProfile).sort()
|
|
19004
|
-
];
|
|
19005
19542
|
const usageSinceCurrentBoundary = (messages) => {
|
|
19006
19543
|
const usage = extractGenAiUsageSummary(
|
|
19007
19544
|
...messages.slice(runResume.beforeMessageCount).filter(isAssistantMessage)
|
|
19008
19545
|
);
|
|
19009
19546
|
return hasAgentTurnUsage(usage) ? usage : void 0;
|
|
19010
19547
|
};
|
|
19548
|
+
let baseInstructions = "";
|
|
19549
|
+
let pendingHandoff;
|
|
19550
|
+
const handoffMetadata = {
|
|
19551
|
+
threadId: conversationId,
|
|
19552
|
+
channelId: slackChannelId,
|
|
19553
|
+
actorId: slackActor?.userId,
|
|
19554
|
+
runId
|
|
19555
|
+
};
|
|
19011
19556
|
const scheduleHandoff = async (args) => {
|
|
19012
|
-
|
|
19013
|
-
|
|
19014
|
-
|
|
19015
|
-
|
|
19016
|
-
|
|
19017
|
-
|
|
19018
|
-
|
|
19019
|
-
|
|
19020
|
-
|
|
19021
|
-
|
|
19022
|
-
|
|
19023
|
-
|
|
19024
|
-
|
|
19025
|
-
};
|
|
19026
|
-
const handoffModel = resolveGatewayModel(target.modelId);
|
|
19027
|
-
const handoffThinkingLevel = toPiReasoningLevel(handoffReasoningLevel);
|
|
19028
|
-
void (async () => {
|
|
19029
|
-
await observers.onStatus?.({ text: "Switching models" });
|
|
19030
|
-
})().catch((error) => {
|
|
19031
|
-
logWarn("assistant.status.observer.failed", {
|
|
19032
|
-
"exception.message": error instanceof Error ? error.message : String(error)
|
|
19033
|
-
});
|
|
19557
|
+
const pending = await commitHandoff({
|
|
19558
|
+
activeModelProfile,
|
|
19559
|
+
beforeMessageCount: runResume.beforeMessageCount,
|
|
19560
|
+
conversationContext: input.conversationContext,
|
|
19561
|
+
conversationId,
|
|
19562
|
+
metadata: handoffMetadata,
|
|
19563
|
+
onStatus: observers.onStatus,
|
|
19564
|
+
profile: args.profile,
|
|
19565
|
+
runtimeContextSourceMessages: args.runtimeContextSourceMessages,
|
|
19566
|
+
signal: args.signal,
|
|
19567
|
+
sourceMessages: args.sourceMessages,
|
|
19568
|
+
triggeringToolCallId: args.triggeringToolCallId,
|
|
19569
|
+
turnRoute
|
|
19034
19570
|
});
|
|
19035
|
-
|
|
19036
|
-
|
|
19037
|
-
conversationContext: input.conversationContext,
|
|
19038
|
-
conversationId,
|
|
19039
|
-
piMessages: args.sourceMessages,
|
|
19040
|
-
runtimeContext,
|
|
19041
|
-
signal: args.signal,
|
|
19042
|
-
triggeringToolCallId: args.triggeringToolCallId,
|
|
19043
|
-
target,
|
|
19044
|
-
metadata: {
|
|
19045
|
-
threadId: conversationId,
|
|
19046
|
-
channelId: slackChannelId,
|
|
19047
|
-
actorId: slackActor?.userId,
|
|
19048
|
-
runId
|
|
19049
|
-
}
|
|
19050
|
-
},
|
|
19051
|
-
{
|
|
19052
|
-
completeText: (args2) => completeText(args2)
|
|
19053
|
-
}
|
|
19054
|
-
);
|
|
19055
|
-
if (handoffReasoningLevel !== turnRoute.reasoningLevel) {
|
|
19056
|
-
turnRoute = {
|
|
19057
|
-
...turnRoute,
|
|
19058
|
-
reasoningLevel: handoffReasoningLevel,
|
|
19059
|
-
reason: `profile_reasoning_override:${args.profile}:${turnRoute.reason}`
|
|
19060
|
-
};
|
|
19571
|
+
if (!pending) {
|
|
19572
|
+
return;
|
|
19061
19573
|
}
|
|
19062
|
-
priorPhaseUsage = addAgentTurnUsage(priorPhaseUsage, phaseUsage);
|
|
19063
|
-
pendingHandoff =
|
|
19064
|
-
|
|
19065
|
-
|
|
19066
|
-
|
|
19067
|
-
};
|
|
19068
|
-
activeModelProfile = args.profile;
|
|
19069
|
-
activeModelId = target.modelId;
|
|
19070
|
-
};
|
|
19071
|
-
const handoffControlFor = (activeProfile) => {
|
|
19072
|
-
const profiles = handoffProfiles.filter(
|
|
19073
|
-
(profile) => profile !== activeProfile
|
|
19074
|
-
);
|
|
19075
|
-
return profiles.length > 0 ? {
|
|
19076
|
-
profiles,
|
|
19077
|
-
execute: async (profile, options) => await scheduleHandoff({
|
|
19078
|
-
profile,
|
|
19079
|
-
signal: options.signal,
|
|
19080
|
-
sourceMessages: [...agent.state.messages],
|
|
19081
|
-
triggeringToolCallId: options.toolCallId
|
|
19082
|
-
})
|
|
19083
|
-
} : void 0;
|
|
19574
|
+
priorPhaseUsage = addAgentTurnUsage(priorPhaseUsage, pending.phaseUsage);
|
|
19575
|
+
pendingHandoff = pending;
|
|
19576
|
+
activeModelProfile = pending.modelProfile;
|
|
19577
|
+
activeModelId = pending.modelId;
|
|
19578
|
+
turnRoute = pending.turnRoute;
|
|
19084
19579
|
};
|
|
19085
|
-
const
|
|
19580
|
+
const handoffExecute = async (profile, options) => await scheduleHandoff({
|
|
19581
|
+
profile,
|
|
19582
|
+
signal: options.signal,
|
|
19583
|
+
sourceMessages: [...agent.state.messages],
|
|
19584
|
+
triggeringToolCallId: options.toolCallId
|
|
19585
|
+
});
|
|
19586
|
+
const requestHandoff = handoffControl({
|
|
19587
|
+
activeProfile: activeModelProfile,
|
|
19588
|
+
enabled: handoffEnabled,
|
|
19589
|
+
execute: handoffExecute
|
|
19590
|
+
});
|
|
19086
19591
|
setTags({
|
|
19087
19592
|
...runLogContext,
|
|
19088
19593
|
modelId: activeModelId
|
|
@@ -19143,32 +19648,27 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
|
|
|
19143
19648
|
await recordAgentsTransition(initialRepositoryInstructions);
|
|
19144
19649
|
}
|
|
19145
19650
|
const getPendingAuthPause = wiring.getPendingAuthPause;
|
|
19146
|
-
const
|
|
19147
|
-
(
|
|
19148
|
-
|
|
19149
|
-
|
|
19150
|
-
|
|
19151
|
-
|
|
19152
|
-
|
|
19153
|
-
|
|
19154
|
-
|
|
19155
|
-
|
|
19156
|
-
|
|
19157
|
-
|
|
19158
|
-
|
|
19159
|
-
|
|
19160
|
-
|
|
19161
|
-
|
|
19162
|
-
|
|
19163
|
-
|
|
19164
|
-
description: definition.description,
|
|
19165
|
-
parameters: definition.inputSchema,
|
|
19166
|
-
prepareArguments: definition.prepareArguments
|
|
19167
|
-
} : tool
|
|
19168
|
-
);
|
|
19651
|
+
const applyPendingHandoff = () => {
|
|
19652
|
+
if (!pendingHandoff) {
|
|
19653
|
+
return void 0;
|
|
19654
|
+
}
|
|
19655
|
+
const pending = pendingHandoff;
|
|
19656
|
+
pendingHandoff = void 0;
|
|
19657
|
+
return applyHandoff({
|
|
19658
|
+
agent,
|
|
19659
|
+
baseInstructions,
|
|
19660
|
+
pending,
|
|
19661
|
+
resume: runResume,
|
|
19662
|
+
tools: toolsForHandoffProfile({
|
|
19663
|
+
activeProfile: pending.modelProfile,
|
|
19664
|
+
agentTools: wiring.agentTools,
|
|
19665
|
+
enabled: handoffEnabled,
|
|
19666
|
+
execute: handoffExecute
|
|
19667
|
+
})
|
|
19668
|
+
});
|
|
19169
19669
|
};
|
|
19170
19670
|
const {
|
|
19171
|
-
baseInstructions,
|
|
19671
|
+
baseInstructions: assembledBaseInstructions,
|
|
19172
19672
|
contextContentParts: promptContextContentParts,
|
|
19173
19673
|
inputMessages,
|
|
19174
19674
|
inputMessagesAttribute,
|
|
@@ -19204,6 +19704,7 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
|
|
|
19204
19704
|
toolRuntimeContext: wiring.toolRuntimeContext,
|
|
19205
19705
|
userContentParts
|
|
19206
19706
|
});
|
|
19707
|
+
baseInstructions = assembledBaseInstructions;
|
|
19207
19708
|
const repositoryInstructionsContext = createRepositoryInstructionsContext({
|
|
19208
19709
|
capture: wiring.captureRepositoryInstructions,
|
|
19209
19710
|
hasSandbox: () => Boolean(wiring.getSandboxRef()),
|
|
@@ -19218,36 +19719,6 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
|
|
|
19218
19719
|
shouldPromptAgent
|
|
19219
19720
|
});
|
|
19220
19721
|
runResume.setTurnContexts(turnContexts);
|
|
19221
|
-
const applyPendingHandoff = () => {
|
|
19222
|
-
if (!pendingHandoff) {
|
|
19223
|
-
return void 0;
|
|
19224
|
-
}
|
|
19225
|
-
const { messages, model, thinkingLevel } = pendingHandoff;
|
|
19226
|
-
const replacement = [...messages];
|
|
19227
|
-
pendingHandoff = void 0;
|
|
19228
|
-
agent.state.messages = replacement;
|
|
19229
|
-
agent.state.model = model;
|
|
19230
|
-
agent.state.thinkingLevel = thinkingLevel;
|
|
19231
|
-
const tools = toolsForActiveProfile();
|
|
19232
|
-
agent.state.tools = tools;
|
|
19233
|
-
runResume.setBeforeMessageCount(replacement.length);
|
|
19234
|
-
runResume.setTurnStartMessageIndex(0);
|
|
19235
|
-
runResume.adoptCommittedBoundary(replacement);
|
|
19236
|
-
setSpanAttributes({
|
|
19237
|
-
"gen_ai.agent.model": activeModelId,
|
|
19238
|
-
"gen_ai.agent.model_profile": activeModelProfile,
|
|
19239
|
-
"gen_ai.agent.reasoning.level": turnRoute.reasoningLevel
|
|
19240
|
-
});
|
|
19241
|
-
return {
|
|
19242
|
-
context: {
|
|
19243
|
-
systemPrompt: baseInstructions,
|
|
19244
|
-
messages: replacement,
|
|
19245
|
-
tools
|
|
19246
|
-
},
|
|
19247
|
-
model,
|
|
19248
|
-
thinkingLevel
|
|
19249
|
-
};
|
|
19250
|
-
};
|
|
19251
19722
|
const applyActiveContextCompaction = async (messages, hookSignal, pendingMessages, clearSteeringQueueOnCommit = false, pairPendingRuntimeContext = false) => {
|
|
19252
19723
|
const compaction = await compactActiveContextIfNeeded(
|
|
19253
19724
|
{
|
|
@@ -19378,13 +19849,7 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
|
|
|
19378
19849
|
const toolCalls2 = assistantMessage.content.filter(
|
|
19379
19850
|
(part) => part.type === "toolCall"
|
|
19380
19851
|
);
|
|
19381
|
-
const
|
|
19382
|
-
(call) => call.name === HANDOFF_TOOL_NAME
|
|
19383
|
-
);
|
|
19384
|
-
const containsWorkspaceSwitch = toolCalls2.some(
|
|
19385
|
-
(call) => call.name === "switchWorkspace"
|
|
19386
|
-
);
|
|
19387
|
-
const exclusiveTool = containsHandoff ? HANDOFF_TOOL_NAME : containsWorkspaceSwitch ? "switchWorkspace" : void 0;
|
|
19852
|
+
const exclusiveTool = exclusiveToolName(toolCalls2);
|
|
19388
19853
|
if (exclusiveTool && toolCalls2.length !== 1) {
|
|
19389
19854
|
return {
|
|
19390
19855
|
block: true,
|
|
@@ -19461,10 +19926,9 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
|
|
|
19461
19926
|
if (event.message.stopReason === "error" || event.message.stopReason === "aborted") {
|
|
19462
19927
|
return;
|
|
19463
19928
|
}
|
|
19464
|
-
|
|
19929
|
+
if (event.message.content.some(
|
|
19465
19930
|
(part) => part.type === "toolCall" && part.name === HANDOFF_TOOL_NAME
|
|
19466
|
-
)
|
|
19467
|
-
if (containsHandoff) {
|
|
19931
|
+
)) {
|
|
19468
19932
|
return;
|
|
19469
19933
|
}
|
|
19470
19934
|
return deliverAssistantMessage(event.message);
|
|
@@ -19614,9 +20078,9 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
|
|
|
19614
20078
|
}
|
|
19615
20079
|
return result2;
|
|
19616
20080
|
};
|
|
19617
|
-
const requestedProfile = activeModelProfile === botConfig.defaultProfile ? turnRoute.profile : void 0;
|
|
19618
20081
|
let run2;
|
|
19619
20082
|
let handoffApplied = false;
|
|
20083
|
+
const requestedProfile = activeModelProfile === botConfig.defaultProfile ? turnRoute.profile : void 0;
|
|
19620
20084
|
if (requestedProfile && requestedProfile !== botConfig.defaultProfile) {
|
|
19621
20085
|
const handoffAbortController = new AbortController();
|
|
19622
20086
|
await runAgentStep(
|
|
@@ -19910,6 +20374,10 @@ export {
|
|
|
19910
20374
|
normalizeSandboxEgressTracePropagationDomains,
|
|
19911
20375
|
shouldPropagateSandboxEgressTrace,
|
|
19912
20376
|
resolveSandboxEgressProviderForHost,
|
|
20377
|
+
admitAutomatedTurn,
|
|
20378
|
+
recordFinishedTurnForAutomatedLimit,
|
|
20379
|
+
postAutomatedTurnLimitNoticeForDestination,
|
|
20380
|
+
maybePostAutomatedTurnLimitNotice,
|
|
19913
20381
|
renderTaskInput,
|
|
19914
20382
|
RESOURCE_EVENT_MESSAGE_AUTHOR,
|
|
19915
20383
|
RESOURCE_EVENT_SYSTEM_ACTOR,
|