@sentry/junior 0.116.0 → 0.117.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-67NFITDH.js → agent-hooks-5IK4LPLP.js} +8 -8
- package/dist/api/conversations/detail.d.ts +7 -0
- package/dist/api/conversations/event-list.d.ts +7 -0
- package/dist/api/conversations/events.d.ts +1 -1
- package/dist/api/schema/conversation.d.ts +28 -0
- package/dist/api/schema.js +1 -1
- package/dist/api.js +25 -12
- package/dist/app.js +32 -30
- package/dist/{catalog-runtime-CWZY6GTH.js → catalog-runtime-MTUYW3AA.js} +5 -5
- package/dist/chat/agent/prompt.d.ts +2 -0
- package/dist/chat/agent/request.d.ts +2 -1
- package/dist/chat/agent/resume.d.ts +2 -0
- package/dist/chat/agent/tools.d.ts +1 -0
- package/dist/chat/conversations/history.d.ts +22 -1
- package/dist/chat/conversations/projection.d.ts +6 -0
- package/dist/chat/mcp/client.d.ts +4 -0
- package/dist/chat/mcp/errors.d.ts +22 -1
- package/dist/chat/oauth-response.d.ts +21 -0
- package/dist/chat/plugins/prompt.d.ts +9 -0
- package/dist/chat/plugins/types.d.ts +2 -21
- package/dist/chat/sandbox/snapshot/install.d.ts +6 -0
- package/dist/chat/sandbox/snapshot/profile.d.ts +14 -0
- package/dist/chat/sandbox/snapshot/resolve.d.ts +22 -0
- package/dist/chat/sandbox/snapshot/span.d.ts +2 -0
- package/dist/chat/services/context-compaction-marker.d.ts +1 -0
- package/dist/chat/services/turn-session-record.d.ts +2 -0
- package/dist/chat/state/turn-session.d.ts +2 -0
- package/dist/chat/tools/query-conversation-events.d.ts +1 -1
- package/dist/chat/tools/sandbox/view-image.d.ts +11 -0
- package/dist/chat/tools/types.d.ts +7 -0
- package/dist/{chunk-OF5FODBL.js → chunk-27KWTFP6.js} +33 -12
- package/dist/{chunk-MGH5ADQS.js → chunk-3GE3F4LT.js} +1 -1
- package/dist/{chunk-JZPQ5K4V.js → chunk-5O3JDQDG.js} +154 -20
- package/dist/{chunk-PGKWXHYJ.js → chunk-6G45D3YG.js} +114 -10
- package/dist/{chunk-3JOGUT46.js → chunk-72Z3HNTQ.js} +1 -1
- package/dist/{chunk-6RQ5GCWH.js → chunk-AKG4TZNH.js} +2 -2
- package/dist/{chunk-TC4ZEM2D.js → chunk-BFIRIZPH.js} +9 -0
- package/dist/{chunk-25GU5B5E.js → chunk-CU7HTGNI.js} +1 -1
- package/dist/{chunk-PZGPCOSD.js → chunk-DS27ZBSP.js} +4 -2
- package/dist/{chunk-3H45VOBZ.js → chunk-FAWBONPC.js} +404 -391
- package/dist/{chunk-53ZKTQO6.js → chunk-KU6ALEJC.js} +1 -1
- package/dist/{chunk-UEVLIYK5.js → chunk-LN765Y4N.js} +6 -6
- package/dist/{chunk-4DD6AOCG.js → chunk-LUMEBOWC.js} +1 -1
- package/dist/{chunk-5UNB623T.js → chunk-NHZEUHKH.js} +514 -344
- package/dist/{chunk-VZCSLYCE.js → chunk-STUI6NIL.js} +78 -16
- package/dist/{chunk-BXLS3I4W.js → chunk-W5JEQQEA.js} +1 -1
- package/dist/{chunk-VKZ6WVAY.js → chunk-WEK3V5RI.js} +73 -32
- package/dist/{chunk-N7TMYLF2.js → chunk-WUNPRM76.js} +1 -1
- package/dist/{chunk-CI3VK7X5.js → chunk-YRWJ3KEU.js} +2 -2
- package/dist/{chunk-KBNDFU6J.js → chunk-ZRQUQJUV.js} +12 -2
- package/dist/cli/chat.js +21 -21
- package/dist/cli/check.js +6 -6
- package/dist/cli/main.js +1 -1
- package/dist/cli/plugins.js +11 -11
- package/dist/cli/{snapshot-warmup.js → snapshot-create.js} +17 -19
- package/dist/cli/upgrade.js +5 -5
- package/dist/{db-57FHVGGQ.js → db-J2ITKS63.js} +5 -5
- package/dist/handlers/oauth-html.d.ts +4 -2
- package/dist/instrumentation.js +2 -2
- package/dist/nitro.js +2 -2
- package/dist/{oauth-callback-server-PAQRPXZX.js → oauth-callback-server-NQYKBT24.js} +15 -15
- package/dist/{runner-4ISZYJEX.js → runner-53V5GIQM.js} +10 -10
- package/dist/{skills-UE2KXQMB.js → skills-BU3ZMLVB.js} +6 -6
- package/dist/{validation-PO5LHTJT.js → validation-74EIKKE6.js} +6 -6
- package/dist/version.js +1 -1
- package/package.json +6 -6
- package/dist/chat/sandbox/runtime-dependency-snapshots.d.ts +0 -20
|
@@ -2,6 +2,8 @@ import {
|
|
|
2
2
|
authorizationId
|
|
3
3
|
} from "./chunk-DIB4GX3G.js";
|
|
4
4
|
import {
|
|
5
|
+
McpProviderError,
|
|
6
|
+
McpToolError,
|
|
5
7
|
RetryableDeliveryError,
|
|
6
8
|
actorFromRouting,
|
|
7
9
|
addReactionToMessage,
|
|
@@ -12,6 +14,9 @@ import {
|
|
|
12
14
|
deliverOAuthAuthorization,
|
|
13
15
|
formatProviderLabel,
|
|
14
16
|
getMcpAuthSession,
|
|
17
|
+
getMcpAwareErrorType,
|
|
18
|
+
getMcpAwareTelemetryMessage,
|
|
19
|
+
getMcpProviderErrorAttributes,
|
|
15
20
|
getSlackMessagePermalink,
|
|
16
21
|
hasEgressCredentialHooks,
|
|
17
22
|
issuePluginCredential,
|
|
@@ -23,9 +28,10 @@ import {
|
|
|
23
28
|
slackOutputPolicy,
|
|
24
29
|
startOAuthFlow,
|
|
25
30
|
surfaceFromRouting,
|
|
31
|
+
toMcpProviderError,
|
|
26
32
|
toolInvocationDestination,
|
|
27
33
|
uploadFilesToConversation
|
|
28
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-6G45D3YG.js";
|
|
29
35
|
import {
|
|
30
36
|
CooperativeTurnYieldError,
|
|
31
37
|
JUNIOR_THREAD_STATE_TTL_MS,
|
|
@@ -67,7 +73,7 @@ import {
|
|
|
67
73
|
stripRuntimeTurnContext,
|
|
68
74
|
trimTrailingAssistantMessages,
|
|
69
75
|
updateConversationStats
|
|
70
|
-
} from "./chunk-
|
|
76
|
+
} from "./chunk-27KWTFP6.js";
|
|
71
77
|
import {
|
|
72
78
|
parseSandboxEgressAuthRequiredSignal,
|
|
73
79
|
parseSandboxEgressPermissionDeniedSignal,
|
|
@@ -78,20 +84,20 @@ import {
|
|
|
78
84
|
bindSandboxFileSystem,
|
|
79
85
|
buildNonInteractiveShellScript,
|
|
80
86
|
createSandboxSession,
|
|
81
|
-
getRuntimeDependencyProfileHash,
|
|
82
87
|
getSandboxResources,
|
|
83
88
|
getVercelSandboxCredentials,
|
|
89
|
+
hash,
|
|
84
90
|
isAlreadyExistsError,
|
|
91
|
+
isMissingError,
|
|
85
92
|
isSandboxCommandStreamInterruptedError,
|
|
86
93
|
isSandboxMissingError,
|
|
87
94
|
isSandboxUnavailableError,
|
|
88
|
-
isSnapshotMissingError,
|
|
89
95
|
isSnapshottingError,
|
|
90
|
-
|
|
96
|
+
resolve,
|
|
91
97
|
runNonInteractiveCommand,
|
|
92
98
|
throwSandboxOperationError,
|
|
93
99
|
wrapSandboxSetupError
|
|
94
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-FAWBONPC.js";
|
|
95
101
|
import {
|
|
96
102
|
addAgentTurnUsage,
|
|
97
103
|
hasAgentTurnUsage
|
|
@@ -106,7 +112,7 @@ import {
|
|
|
106
112
|
getPluginUserPromptContributions,
|
|
107
113
|
getSlackToolContext,
|
|
108
114
|
resolveChannelCapabilities
|
|
109
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-STUI6NIL.js";
|
|
110
116
|
import {
|
|
111
117
|
SANDBOX_DATA_ROOT,
|
|
112
118
|
SANDBOX_SKILLS_ROOT,
|
|
@@ -114,7 +120,7 @@ import {
|
|
|
114
120
|
getStateAdapter,
|
|
115
121
|
sandboxSkillDir,
|
|
116
122
|
sandboxSkillFile
|
|
117
|
-
} from "./chunk-
|
|
123
|
+
} from "./chunk-KU6ALEJC.js";
|
|
118
124
|
import {
|
|
119
125
|
SlackActionError,
|
|
120
126
|
downloadPrivateSlackFile,
|
|
@@ -123,7 +129,7 @@ import {
|
|
|
123
129
|
isConversationScopedChannel,
|
|
124
130
|
normalizeSlackConversationId,
|
|
125
131
|
withSlackRetries
|
|
126
|
-
} from "./chunk-
|
|
132
|
+
} from "./chunk-YRWJ3KEU.js";
|
|
127
133
|
import {
|
|
128
134
|
KNOWN_CONVERSATION_EVENT_TYPES,
|
|
129
135
|
contextProvenance,
|
|
@@ -132,11 +138,12 @@ import {
|
|
|
132
138
|
getConversationStore,
|
|
133
139
|
instructionActors,
|
|
134
140
|
instructionProvenanceFor
|
|
135
|
-
} from "./chunk-
|
|
141
|
+
} from "./chunk-ZRQUQJUV.js";
|
|
136
142
|
import {
|
|
137
143
|
sleep
|
|
138
144
|
} from "./chunk-4ZNGQH7C.js";
|
|
139
145
|
import {
|
|
146
|
+
ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX,
|
|
140
147
|
COMPACTION_SUMMARY_PREFIX,
|
|
141
148
|
DEFAULT_HANDOFF_MODEL_PROFILE,
|
|
142
149
|
GEN_AI_PROVIDER_NAME,
|
|
@@ -165,7 +172,7 @@ import {
|
|
|
165
172
|
renderCurrentInstruction,
|
|
166
173
|
resolveGatewayModel,
|
|
167
174
|
unwrapCurrentInstruction
|
|
168
|
-
} from "./chunk-
|
|
175
|
+
} from "./chunk-DS27ZBSP.js";
|
|
169
176
|
import {
|
|
170
177
|
canExposeConversationPayload,
|
|
171
178
|
parseSlackThreadId,
|
|
@@ -182,15 +189,18 @@ import {
|
|
|
182
189
|
findSkillByName,
|
|
183
190
|
loadSkillsByName,
|
|
184
191
|
parseSkillInvocation
|
|
185
|
-
} from "./chunk-
|
|
192
|
+
} from "./chunk-AKG4TZNH.js";
|
|
186
193
|
import {
|
|
187
194
|
pluginCatalogRuntime
|
|
188
|
-
} from "./chunk-
|
|
195
|
+
} from "./chunk-CU7HTGNI.js";
|
|
189
196
|
import {
|
|
190
197
|
CredentialUnavailableError,
|
|
198
|
+
OAuthProviderError,
|
|
199
|
+
fetchWithBoundedOAuthErrorBodies,
|
|
200
|
+
getOAuthProviderErrorAttributes,
|
|
191
201
|
resolveAuthTokenPlaceholder,
|
|
192
202
|
resolvePluginCommandEnv
|
|
193
|
-
} from "./chunk-
|
|
203
|
+
} from "./chunk-5O3JDQDG.js";
|
|
194
204
|
import {
|
|
195
205
|
credentialUserSubjectId
|
|
196
206
|
} from "./chunk-W3U3YQYI.js";
|
|
@@ -214,7 +224,7 @@ import {
|
|
|
214
224
|
summarizeMessageText,
|
|
215
225
|
withLogContext,
|
|
216
226
|
withSpan
|
|
217
|
-
} from "./chunk-
|
|
227
|
+
} from "./chunk-72Z3HNTQ.js";
|
|
218
228
|
import {
|
|
219
229
|
parseSlackChannelId,
|
|
220
230
|
parseSlackMessageTs,
|
|
@@ -2302,6 +2312,33 @@ function withoutTrailingUncheckpointedUserPrompt(messages, userContentParts) {
|
|
|
2302
2312
|
function userPromptContentMatches(storedContent, currentContent) {
|
|
2303
2313
|
return isDeepStrictEqual(storedContent, currentContent);
|
|
2304
2314
|
}
|
|
2315
|
+
function isUserContentPart(value) {
|
|
2316
|
+
if (typeof value !== "object" || value === null || !("type" in value)) {
|
|
2317
|
+
return false;
|
|
2318
|
+
}
|
|
2319
|
+
if (value.type === "text") {
|
|
2320
|
+
return "text" in value && typeof value.text === "string";
|
|
2321
|
+
}
|
|
2322
|
+
return value.type === "image" && "data" in value && typeof value.data === "string" && "mimeType" in value && typeof value.mimeType === "string";
|
|
2323
|
+
}
|
|
2324
|
+
function checkpointedPromptContent(args) {
|
|
2325
|
+
if (!args.messages || args.turnStartMessageIndex === void 0 || args.turnStartMessageIndex !== args.messages.length - 1) {
|
|
2326
|
+
return void 0;
|
|
2327
|
+
}
|
|
2328
|
+
const message = args.messages[args.turnStartMessageIndex];
|
|
2329
|
+
if (message?.role !== "user" || !Array.isArray(message.content)) {
|
|
2330
|
+
return void 0;
|
|
2331
|
+
}
|
|
2332
|
+
const durableMessage = stripRuntimeTurnContext([message])[0];
|
|
2333
|
+
if (!userPromptContentMatches(durableMessage?.content, args.userContentParts)) {
|
|
2334
|
+
return void 0;
|
|
2335
|
+
}
|
|
2336
|
+
const content = message.content;
|
|
2337
|
+
if (!content.every(isUserContentPart)) {
|
|
2338
|
+
return void 0;
|
|
2339
|
+
}
|
|
2340
|
+
return content;
|
|
2341
|
+
}
|
|
2305
2342
|
async function assemblePrompt(args) {
|
|
2306
2343
|
const source = args.routing.source;
|
|
2307
2344
|
const hasPromptCheckpoint = args.resumedFromSessionRecord && args.existingTurnStartMessageIndex !== void 0;
|
|
@@ -2310,13 +2347,18 @@ async function assemblePrompt(args) {
|
|
|
2310
2347
|
args.priorPiMessages,
|
|
2311
2348
|
args.userContentParts
|
|
2312
2349
|
) : args.existingSessionPiMessages;
|
|
2313
|
-
const
|
|
2350
|
+
const replayedPromptContent = shouldPromptAgent && !args.resumedFromSessionRecord ? checkpointedPromptContent({
|
|
2351
|
+
messages: args.existingSessionPiMessages,
|
|
2352
|
+
turnStartMessageIndex: args.existingTurnStartMessageIndex,
|
|
2353
|
+
userContentParts: args.userContentParts
|
|
2354
|
+
}) : void 0;
|
|
2355
|
+
const needsBootstrapContextForPrompt = shouldPromptAgent && !replayedPromptContent && !hasRuntimeTurnContext(promptHistoryMessages);
|
|
2314
2356
|
const systemPromptContributions = await getPluginSystemPromptContributions(source);
|
|
2315
2357
|
const pluginSystemPrompt = buildPluginSystemPromptContributions(
|
|
2316
2358
|
systemPromptContributions
|
|
2317
2359
|
);
|
|
2318
2360
|
const baseInstructions = [buildSystemPrompt({ source }), pluginSystemPrompt].filter((section) => Boolean(section)).join("\n\n");
|
|
2319
|
-
const pluginUserPromptContributions = !shouldPromptAgent ? [] : await getPluginUserPromptContributions({
|
|
2361
|
+
const pluginUserPromptContributions = !shouldPromptAgent || replayedPromptContent ? [] : await getPluginUserPromptContributions({
|
|
2320
2362
|
context: args.toolRuntimeContext
|
|
2321
2363
|
});
|
|
2322
2364
|
const turnContextPrompt = needsBootstrapContextForPrompt || pluginUserPromptContributions.length > 0 ? buildTurnContextPrompt({
|
|
@@ -2340,7 +2382,10 @@ async function assemblePrompt(args) {
|
|
|
2340
2382
|
configuration: args.configurationValues
|
|
2341
2383
|
}) : null;
|
|
2342
2384
|
const turnContextParts = turnContextPrompt ? [{ type: "text", text: turnContextPrompt }] : [];
|
|
2343
|
-
const promptContentParts = [
|
|
2385
|
+
const promptContentParts = replayedPromptContent ?? [
|
|
2386
|
+
...turnContextParts,
|
|
2387
|
+
...args.userContentParts
|
|
2388
|
+
];
|
|
2344
2389
|
const inputMessages = [
|
|
2345
2390
|
{
|
|
2346
2391
|
role: "system",
|
|
@@ -2371,7 +2416,10 @@ async function assemblePrompt(args) {
|
|
|
2371
2416
|
inputMessagesAttribute,
|
|
2372
2417
|
promptContentParts,
|
|
2373
2418
|
promptHistoryMessages,
|
|
2374
|
-
shouldPromptAgent
|
|
2419
|
+
shouldPromptAgent,
|
|
2420
|
+
turnContexts: pluginUserPromptContributions.flatMap(
|
|
2421
|
+
(contribution) => contribution.context ? [contribution.context] : []
|
|
2422
|
+
)
|
|
2375
2423
|
};
|
|
2376
2424
|
}
|
|
2377
2425
|
|
|
@@ -3240,7 +3288,7 @@ function createSandboxRuntime(options) {
|
|
|
3240
3288
|
let closed = false;
|
|
3241
3289
|
const timeoutMs = options.timeoutMs ?? 1e3 * 60 * 30;
|
|
3242
3290
|
const traceContext = options.traceContext ?? {};
|
|
3243
|
-
const dependencyProfileHash =
|
|
3291
|
+
const dependencyProfileHash = hash(SANDBOX_RUNTIME);
|
|
3244
3292
|
const resolveCommandEnv = options.commandEnv ?? (async () => ({}));
|
|
3245
3293
|
const withSandboxSpan = (name, op, attributes, callback) => withSpan(name, op, traceContext, callback, attributes);
|
|
3246
3294
|
const invalidateSession = (sessionId) => {
|
|
@@ -3402,13 +3450,13 @@ function createSandboxRuntime(options) {
|
|
|
3402
3450
|
sandboxName
|
|
3403
3451
|
);
|
|
3404
3452
|
} catch (error) {
|
|
3405
|
-
if (!
|
|
3453
|
+
if (!isMissingError(error)) {
|
|
3406
3454
|
throw error;
|
|
3407
3455
|
}
|
|
3408
3456
|
setSpanAttributes({
|
|
3409
3457
|
"app.sandbox.snapshot.rebuild_after_missing": true
|
|
3410
3458
|
});
|
|
3411
|
-
const rebuiltSnapshot = await
|
|
3459
|
+
const rebuiltSnapshot = await resolve({
|
|
3412
3460
|
runtime,
|
|
3413
3461
|
timeoutMs,
|
|
3414
3462
|
forceRebuild: true,
|
|
@@ -3439,7 +3487,7 @@ function createSandboxRuntime(options) {
|
|
|
3439
3487
|
"app.sandbox.runtime": runtime
|
|
3440
3488
|
},
|
|
3441
3489
|
async () => {
|
|
3442
|
-
const snapshot = await
|
|
3490
|
+
const snapshot = await resolve({
|
|
3443
3491
|
runtime,
|
|
3444
3492
|
timeoutMs
|
|
3445
3493
|
});
|
|
@@ -5846,6 +5894,7 @@ function createAgentSandbox(options) {
|
|
|
5846
5894
|
}
|
|
5847
5895
|
|
|
5848
5896
|
// src/chat/mcp/client.ts
|
|
5897
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
5849
5898
|
import { Client } from "@modelcontextprotocol/sdk/client";
|
|
5850
5899
|
import {
|
|
5851
5900
|
UnauthorizedError
|
|
@@ -5887,18 +5936,25 @@ var McpAuthorizationRequiredError = class extends Error {
|
|
|
5887
5936
|
this.provider = provider;
|
|
5888
5937
|
}
|
|
5889
5938
|
};
|
|
5939
|
+
function isMissingSessionError(error) {
|
|
5940
|
+
return error instanceof StreamableHTTPError && (error.code === 404 || /Session not found/i.test(error.message));
|
|
5941
|
+
}
|
|
5890
5942
|
var PluginMcpClient = class {
|
|
5891
5943
|
constructor(plugin, options = {}) {
|
|
5892
5944
|
this.plugin = plugin;
|
|
5893
5945
|
this.options = options;
|
|
5946
|
+
const url = plugin.manifest.mcp?.url;
|
|
5947
|
+
this.resourceHost = url ? new URL(url).hostname : void 0;
|
|
5894
5948
|
}
|
|
5895
5949
|
plugin;
|
|
5896
5950
|
options;
|
|
5897
5951
|
client;
|
|
5898
5952
|
clientPromise;
|
|
5899
5953
|
lastAttemptedTransportSessionId;
|
|
5954
|
+
providerStatusStore = new AsyncLocalStorage();
|
|
5900
5955
|
transport;
|
|
5901
5956
|
listedTools;
|
|
5957
|
+
resourceHost;
|
|
5902
5958
|
async listTools() {
|
|
5903
5959
|
if (this.listedTools) {
|
|
5904
5960
|
return [...this.listedTools];
|
|
@@ -5910,7 +5966,8 @@ var PluginMcpClient = class {
|
|
|
5910
5966
|
let cursor;
|
|
5911
5967
|
do {
|
|
5912
5968
|
const result = await this.wrapAuth(
|
|
5913
|
-
client.listTools(cursor ? { cursor } : void 0)
|
|
5969
|
+
() => client.listTools(cursor ? { cursor } : void 0),
|
|
5970
|
+
"list_tools"
|
|
5914
5971
|
);
|
|
5915
5972
|
await this.syncTransportSessionId();
|
|
5916
5973
|
for (const tool of result.tools) {
|
|
@@ -5943,10 +6000,11 @@ var PluginMcpClient = class {
|
|
|
5943
6000
|
});
|
|
5944
6001
|
}
|
|
5945
6002
|
const result = await this.wrapAuth(
|
|
5946
|
-
client.callTool({
|
|
6003
|
+
() => client.callTool({
|
|
5947
6004
|
name,
|
|
5948
6005
|
arguments: args ?? {}
|
|
5949
|
-
})
|
|
6006
|
+
}),
|
|
6007
|
+
"call_tool"
|
|
5950
6008
|
);
|
|
5951
6009
|
await this.syncTransportSessionId();
|
|
5952
6010
|
return result;
|
|
@@ -5964,7 +6022,7 @@ var PluginMcpClient = class {
|
|
|
5964
6022
|
throw error;
|
|
5965
6023
|
}
|
|
5966
6024
|
await this.clearStoredTransportSessionId();
|
|
5967
|
-
await this.
|
|
6025
|
+
await this.cleanupClientAfterFailure();
|
|
5968
6026
|
return await operation();
|
|
5969
6027
|
}
|
|
5970
6028
|
}
|
|
@@ -6000,7 +6058,12 @@ var PluginMcpClient = class {
|
|
|
6000
6058
|
this.lastAttemptedTransportSessionId = sessionId;
|
|
6001
6059
|
const transport = new StreamableHTTPClientTransport(new URL(mcp.url), {
|
|
6002
6060
|
...Object.keys(requestInit).length > 0 ? { requestInit } : {},
|
|
6003
|
-
|
|
6061
|
+
fetch: fetchWithBoundedOAuthErrorBodies(this.options.fetch, (status) => {
|
|
6062
|
+
const store = this.providerStatusStore.getStore();
|
|
6063
|
+
if (store) {
|
|
6064
|
+
store.status = status;
|
|
6065
|
+
}
|
|
6066
|
+
}),
|
|
6004
6067
|
...this.options.authProvider ? { authProvider: this.options.authProvider } : {},
|
|
6005
6068
|
...sessionId ? { sessionId } : {}
|
|
6006
6069
|
});
|
|
@@ -6009,48 +6072,79 @@ var PluginMcpClient = class {
|
|
|
6009
6072
|
});
|
|
6010
6073
|
this.transport = transport;
|
|
6011
6074
|
try {
|
|
6012
|
-
await this.wrapAuth(client.connect(transport));
|
|
6075
|
+
await this.wrapAuth(() => client.connect(transport), "connect");
|
|
6013
6076
|
this.client = client;
|
|
6014
6077
|
await this.syncTransportSessionId();
|
|
6015
6078
|
return client;
|
|
6016
6079
|
} catch (error) {
|
|
6017
6080
|
await this.syncTransportSessionId();
|
|
6018
|
-
await this.
|
|
6081
|
+
await this.cleanupClientAfterFailure();
|
|
6019
6082
|
throw error;
|
|
6020
6083
|
}
|
|
6021
6084
|
}
|
|
6022
|
-
async wrapAuth(
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6085
|
+
async wrapAuth(operation, phase) {
|
|
6086
|
+
const store = {};
|
|
6087
|
+
return await this.providerStatusStore.run(store, async () => {
|
|
6088
|
+
try {
|
|
6089
|
+
return await operation();
|
|
6090
|
+
} catch (error) {
|
|
6091
|
+
if (error instanceof McpAuthorizationRequiredError) {
|
|
6092
|
+
throw error;
|
|
6093
|
+
}
|
|
6094
|
+
if (error instanceof UnauthorizedError) {
|
|
6095
|
+
throw new McpAuthorizationRequiredError(
|
|
6096
|
+
this.plugin.manifest.name,
|
|
6097
|
+
`MCP authorization required for plugin "${this.plugin.manifest.name}"`
|
|
6098
|
+
);
|
|
6099
|
+
}
|
|
6100
|
+
throw toMcpProviderError(error, {
|
|
6101
|
+
phase,
|
|
6102
|
+
provider: this.plugin.manifest.name,
|
|
6103
|
+
missingSession: isMissingSessionError(error) || void 0,
|
|
6104
|
+
resourceHost: this.resourceHost,
|
|
6105
|
+
status: store.status
|
|
6106
|
+
});
|
|
6034
6107
|
}
|
|
6035
|
-
|
|
6036
|
-
}
|
|
6108
|
+
});
|
|
6037
6109
|
}
|
|
6038
6110
|
async shouldResetMissingSession(error) {
|
|
6039
|
-
if (!(error instanceof
|
|
6111
|
+
if (!(error instanceof McpProviderError && error.missingSession || isMissingSessionError(error))) {
|
|
6040
6112
|
return false;
|
|
6041
6113
|
}
|
|
6042
6114
|
return Boolean(
|
|
6043
6115
|
this.transport?.sessionId ?? this.lastAttemptedTransportSessionId ?? await this.getStoredTransportSessionId()
|
|
6044
6116
|
);
|
|
6045
6117
|
}
|
|
6046
|
-
|
|
6118
|
+
resetClientState() {
|
|
6047
6119
|
const transport = this.transport;
|
|
6048
6120
|
this.listedTools = void 0;
|
|
6049
6121
|
this.transport = void 0;
|
|
6050
6122
|
this.client = void 0;
|
|
6051
6123
|
this.clientPromise = void 0;
|
|
6052
|
-
|
|
6124
|
+
return transport;
|
|
6125
|
+
}
|
|
6126
|
+
async cleanupClientAfterFailure() {
|
|
6127
|
+
const transport = this.resetClientState();
|
|
6128
|
+
if (!transport) {
|
|
6129
|
+
return;
|
|
6130
|
+
}
|
|
6131
|
+
try {
|
|
6053
6132
|
await transport.close();
|
|
6133
|
+
} catch {
|
|
6134
|
+
}
|
|
6135
|
+
}
|
|
6136
|
+
async disposeClient() {
|
|
6137
|
+
const transport = this.resetClientState();
|
|
6138
|
+
if (transport) {
|
|
6139
|
+
try {
|
|
6140
|
+
await transport.close();
|
|
6141
|
+
} catch (error) {
|
|
6142
|
+
throw toMcpProviderError(error, {
|
|
6143
|
+
phase: "close",
|
|
6144
|
+
provider: this.plugin.manifest.name,
|
|
6145
|
+
resourceHost: this.resourceHost
|
|
6146
|
+
});
|
|
6147
|
+
}
|
|
6054
6148
|
}
|
|
6055
6149
|
}
|
|
6056
6150
|
async getStoredTransportSessionId() {
|
|
@@ -6073,29 +6167,6 @@ var PluginMcpClient = class {
|
|
|
6073
6167
|
}
|
|
6074
6168
|
};
|
|
6075
6169
|
|
|
6076
|
-
// src/chat/mcp/errors.ts
|
|
6077
|
-
var McpToolError = class extends Error {
|
|
6078
|
-
constructor(message) {
|
|
6079
|
-
super(message);
|
|
6080
|
-
this.name = "McpToolError";
|
|
6081
|
-
}
|
|
6082
|
-
};
|
|
6083
|
-
function getMcpAwareErrorType(error, fallback) {
|
|
6084
|
-
if (error instanceof McpToolError) {
|
|
6085
|
-
return "tool_error";
|
|
6086
|
-
}
|
|
6087
|
-
return error instanceof Error ? error.name : fallback;
|
|
6088
|
-
}
|
|
6089
|
-
function getMcpAwareErrorMessage(error) {
|
|
6090
|
-
return error instanceof Error ? error.message : String(error);
|
|
6091
|
-
}
|
|
6092
|
-
function getMcpAwareTelemetryMessage(error, privacy) {
|
|
6093
|
-
if (privacy === "private" && error instanceof McpToolError) {
|
|
6094
|
-
return "MCP tool call failed";
|
|
6095
|
-
}
|
|
6096
|
-
return getMcpAwareErrorMessage(error);
|
|
6097
|
-
}
|
|
6098
|
-
|
|
6099
6170
|
// src/chat/mcp/tool-manager.ts
|
|
6100
6171
|
var MAX_TOOL_RESULT_TOKENS = 1e4;
|
|
6101
6172
|
var MAX_TOOL_RESULT_BYTES = 32 * 1024;
|
|
@@ -6469,6 +6540,7 @@ var McpToolManager = class {
|
|
|
6469
6540
|
}
|
|
6470
6541
|
const errorAttributes = {
|
|
6471
6542
|
...baseAttributes,
|
|
6543
|
+
...getMcpProviderErrorAttributes(error),
|
|
6472
6544
|
"error.type": getMcpAwareErrorType(error, "mcp_tool_error"),
|
|
6473
6545
|
"exception.message": getMcpAwareTelemetryMessage(
|
|
6474
6546
|
error,
|
|
@@ -7207,13 +7279,77 @@ function createSearchMcpToolsTool(mcpToolManager) {
|
|
|
7207
7279
|
});
|
|
7208
7280
|
}
|
|
7209
7281
|
|
|
7210
|
-
// src/chat/tools/
|
|
7282
|
+
// src/chat/tools/sandbox/view-image.ts
|
|
7211
7283
|
import { z as z15 } from "zod";
|
|
7284
|
+
var MAX_VIEW_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
7285
|
+
var viewImageInputSchema = z15.object({
|
|
7286
|
+
path: z15.string().min(1).describe("Path to an image file in the sandbox workspace.")
|
|
7287
|
+
}).strict();
|
|
7288
|
+
function detectImageMimeType(data) {
|
|
7289
|
+
if (data.length >= 8 && data.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
|
|
7290
|
+
return "image/png";
|
|
7291
|
+
}
|
|
7292
|
+
if (data.length >= 3 && data[0] === 255 && data[1] === 216 && data[2] === 255) {
|
|
7293
|
+
return "image/jpeg";
|
|
7294
|
+
}
|
|
7295
|
+
if (data.length >= 6 && (data.subarray(0, 6).toString("ascii") === "GIF87a" || data.subarray(0, 6).toString("ascii") === "GIF89a")) {
|
|
7296
|
+
return "image/gif";
|
|
7297
|
+
}
|
|
7298
|
+
if (data.length >= 12 && data.subarray(0, 4).toString("ascii") === "RIFF" && data.subarray(8, 12).toString("ascii") === "WEBP") {
|
|
7299
|
+
return "image/webp";
|
|
7300
|
+
}
|
|
7301
|
+
return void 0;
|
|
7302
|
+
}
|
|
7303
|
+
function createViewImageTool(sandbox, supportsImageInput, deps = {}) {
|
|
7304
|
+
return zodTool({
|
|
7305
|
+
description: "View an image file from the sandbox workspace when visual inspection is needed. Supports PNG, JPEG, GIF, and WebP images up to 5 MB.",
|
|
7306
|
+
exposure: "direct",
|
|
7307
|
+
inputSchema: viewImageInputSchema,
|
|
7308
|
+
async execute({ path: path9 }) {
|
|
7309
|
+
if (!supportsImageInput()) {
|
|
7310
|
+
throw new ToolInputError(
|
|
7311
|
+
"viewImage is unavailable because the current model does not support image inputs"
|
|
7312
|
+
);
|
|
7313
|
+
}
|
|
7314
|
+
const targetPath = normalizeSandboxPath(path9);
|
|
7315
|
+
const data = deps.readFile ? await deps.readFile(targetPath) : await sandbox.readFileToBuffer({ path: targetPath });
|
|
7316
|
+
if (!data) {
|
|
7317
|
+
throw new SandboxFileNotFoundError(targetPath);
|
|
7318
|
+
}
|
|
7319
|
+
if (data.byteLength === 0) {
|
|
7320
|
+
throw new ToolInputError(`image file is empty: ${targetPath}`);
|
|
7321
|
+
}
|
|
7322
|
+
if (data.byteLength > MAX_VIEW_IMAGE_BYTES) {
|
|
7323
|
+
throw new ToolInputError(
|
|
7324
|
+
`image exceeds ${MAX_VIEW_IMAGE_BYTES} bytes: ${targetPath} (${data.byteLength} bytes)`
|
|
7325
|
+
);
|
|
7326
|
+
}
|
|
7327
|
+
const mimeType = detectImageMimeType(data);
|
|
7328
|
+
if (!mimeType) {
|
|
7329
|
+
throw new ToolInputError(
|
|
7330
|
+
`unsupported image format: ${targetPath}; use PNG, JPEG, GIF, or WebP`
|
|
7331
|
+
);
|
|
7332
|
+
}
|
|
7333
|
+
return {
|
|
7334
|
+
content: [
|
|
7335
|
+
{
|
|
7336
|
+
type: "image",
|
|
7337
|
+
data: data.toString("base64"),
|
|
7338
|
+
mimeType
|
|
7339
|
+
}
|
|
7340
|
+
]
|
|
7341
|
+
};
|
|
7342
|
+
}
|
|
7343
|
+
});
|
|
7344
|
+
}
|
|
7345
|
+
|
|
7346
|
+
// src/chat/tools/runtime/report-progress.ts
|
|
7347
|
+
import { z as z16 } from "zod";
|
|
7212
7348
|
function createReportProgressTool() {
|
|
7213
7349
|
return zodTool({
|
|
7214
7350
|
description: "Update the user-visible assistant loading message with a short progress phase. For every non-trivial turn, call this early with the initial major work phase, then call it again only when the major phase meaningfully changes. Messages must be written in sentence case with a present-participle verb (e.g. 'Searching docs', 'Reviewing results', 'Running checks'). Skip trivial direct answers, generic filler, and minor substeps.",
|
|
7215
|
-
inputSchema:
|
|
7216
|
-
message:
|
|
7351
|
+
inputSchema: z16.object({
|
|
7352
|
+
message: z16.string().min(1).describe("Short user-facing progress message.")
|
|
7217
7353
|
}),
|
|
7218
7354
|
outputSchema: juniorToolResultSchema,
|
|
7219
7355
|
execute: async () => ({
|
|
@@ -7224,34 +7360,34 @@ function createReportProgressTool() {
|
|
|
7224
7360
|
}
|
|
7225
7361
|
|
|
7226
7362
|
// src/chat/tools/resource-events.ts
|
|
7227
|
-
import { z as
|
|
7363
|
+
import { z as z18 } from "zod";
|
|
7228
7364
|
|
|
7229
7365
|
// src/chat/resource-events/store.ts
|
|
7230
7366
|
import { createHash } from "crypto";
|
|
7231
7367
|
import { destinationSchema } from "@sentry/junior-plugin-api";
|
|
7232
|
-
import { z as
|
|
7368
|
+
import { z as z17 } from "zod";
|
|
7233
7369
|
var RESOURCE_EVENT_PREFIX = "junior:resource_event_subscription";
|
|
7234
7370
|
var INDEX_LOCK_TTL_MS = 1e4;
|
|
7235
7371
|
var SUBSCRIPTION_LOCK_TTL_MS = 1e4;
|
|
7236
7372
|
var SUBSCRIPTION_LOCK_WAIT_MS = 1e4;
|
|
7237
7373
|
var SUBSCRIPTION_LOCK_RETRY_MS = 25;
|
|
7238
7374
|
var SUBSCRIPTION_LOCK_HEARTBEAT_MS = 3e3;
|
|
7239
|
-
var subscriptionStatusSchema =
|
|
7240
|
-
var subscriptionIdIndexSchema =
|
|
7241
|
-
var subscriptionSchema =
|
|
7242
|
-
conversationId:
|
|
7243
|
-
createdAtMs:
|
|
7375
|
+
var subscriptionStatusSchema = z17.enum(["active", "cancelled", "completed"]);
|
|
7376
|
+
var subscriptionIdIndexSchema = z17.array(z17.string().min(1));
|
|
7377
|
+
var subscriptionSchema = z17.object({
|
|
7378
|
+
conversationId: z17.string().min(1),
|
|
7379
|
+
createdAtMs: z17.number().finite(),
|
|
7244
7380
|
destination: destinationSchema,
|
|
7245
|
-
events:
|
|
7246
|
-
expiresAtMs:
|
|
7247
|
-
id:
|
|
7248
|
-
intent:
|
|
7249
|
-
label:
|
|
7250
|
-
provider:
|
|
7251
|
-
resourceRef:
|
|
7252
|
-
resourceType:
|
|
7381
|
+
events: z17.array(z17.string().min(1)).min(1),
|
|
7382
|
+
expiresAtMs: z17.number().finite(),
|
|
7383
|
+
id: z17.string().min(1),
|
|
7384
|
+
intent: z17.string().min(1),
|
|
7385
|
+
label: z17.string().min(1),
|
|
7386
|
+
provider: z17.string().min(1),
|
|
7387
|
+
resourceRef: z17.string().min(1),
|
|
7388
|
+
resourceType: z17.string().min(1),
|
|
7253
7389
|
status: subscriptionStatusSchema,
|
|
7254
|
-
updatedAtMs:
|
|
7390
|
+
updatedAtMs: z17.number().finite()
|
|
7255
7391
|
}).strict();
|
|
7256
7392
|
function digest(value) {
|
|
7257
7393
|
return createHash("sha256").update(value).digest("hex").slice(0, 32);
|
|
@@ -7272,8 +7408,8 @@ function indexLockKey(key) {
|
|
|
7272
7408
|
return `${key}:lock`;
|
|
7273
7409
|
}
|
|
7274
7410
|
async function sleep2(ms) {
|
|
7275
|
-
await new Promise((
|
|
7276
|
-
const timer = setTimeout(
|
|
7411
|
+
await new Promise((resolve2) => {
|
|
7412
|
+
const timer = setTimeout(resolve2, ms);
|
|
7277
7413
|
timer.unref?.();
|
|
7278
7414
|
});
|
|
7279
7415
|
}
|
|
@@ -7607,18 +7743,18 @@ var RESOURCE_WATCH_TOOL_SOURCE = {
|
|
|
7607
7743
|
id: "resource-watches",
|
|
7608
7744
|
description: "Inspect or stop resource watches for the current conversation."
|
|
7609
7745
|
};
|
|
7610
|
-
var subscribeInputSchema =
|
|
7611
|
-
resourceRef:
|
|
7612
|
-
provider:
|
|
7613
|
-
resourceType:
|
|
7614
|
-
label:
|
|
7615
|
-
events:
|
|
7746
|
+
var subscribeInputSchema = z18.object({
|
|
7747
|
+
resourceRef: z18.string().describe("Opaque resource ref copied from a subscribable tool result."),
|
|
7748
|
+
provider: z18.string().describe("Provider that owns the resource ref."),
|
|
7749
|
+
resourceType: z18.string().describe("Provider-defined resource type from the subscribable hint."),
|
|
7750
|
+
label: z18.string().describe("Human-readable resource label from the subscribable hint."),
|
|
7751
|
+
events: z18.array(z18.string()).min(1).describe(
|
|
7616
7752
|
"High-signal event names to deliver to this conversation when they occur."
|
|
7617
7753
|
),
|
|
7618
|
-
intent:
|
|
7754
|
+
intent: z18.string().describe(
|
|
7619
7755
|
"Concise reason this conversation wants these events, used when an event arrives."
|
|
7620
7756
|
),
|
|
7621
|
-
ttlMs:
|
|
7757
|
+
ttlMs: z18.coerce.number().describe(
|
|
7622
7758
|
"How long to keep the subscription active. Defaults to 14 days and is capped at 30 days."
|
|
7623
7759
|
).optional()
|
|
7624
7760
|
});
|
|
@@ -7711,7 +7847,7 @@ function createListResourceEventSubscriptionsTool(context) {
|
|
|
7711
7847
|
description: "List active resource event subscriptions for the current conversation.",
|
|
7712
7848
|
exposure: "deferred",
|
|
7713
7849
|
source: RESOURCE_WATCH_TOOL_SOURCE,
|
|
7714
|
-
inputSchema:
|
|
7850
|
+
inputSchema: z18.object({}),
|
|
7715
7851
|
outputSchema: juniorToolResultSchema,
|
|
7716
7852
|
async execute() {
|
|
7717
7853
|
const conversationId = requireConversationContext(context);
|
|
@@ -7744,7 +7880,7 @@ function createStopWatchingResourcesTool(context) {
|
|
|
7744
7880
|
description: "Stop every resource watch for the current conversation. Infer the user's intent from context instead of requiring a special command, and call this tool before confirming that watching stopped.",
|
|
7745
7881
|
exposure: "deferred",
|
|
7746
7882
|
source: RESOURCE_WATCH_TOOL_SOURCE,
|
|
7747
|
-
inputSchema:
|
|
7883
|
+
inputSchema: z18.object({}),
|
|
7748
7884
|
outputSchema: juniorToolResultSchema,
|
|
7749
7885
|
async execute() {
|
|
7750
7886
|
const conversationId = requireConversationContext(context);
|
|
@@ -7851,11 +7987,11 @@ async function listThreadReplies(input) {
|
|
|
7851
7987
|
}
|
|
7852
7988
|
|
|
7853
7989
|
// src/chat/slack/timestamp-param.ts
|
|
7854
|
-
import { z as
|
|
7990
|
+
import { z as z19 } from "zod";
|
|
7855
7991
|
function slackTimestampParam(description) {
|
|
7856
|
-
return
|
|
7992
|
+
return z19.preprocess(
|
|
7857
7993
|
(value) => typeof value === "number" && Number.isFinite(value) ? String(value) : value,
|
|
7858
|
-
|
|
7994
|
+
z19.string().min(1)
|
|
7859
7995
|
).describe(description);
|
|
7860
7996
|
}
|
|
7861
7997
|
function optionalSlackTimestampParam(description) {
|
|
@@ -7886,10 +8022,10 @@ function parseRequiredSlackTimestampParam(field, value) {
|
|
|
7886
8022
|
}
|
|
7887
8023
|
|
|
7888
8024
|
// src/chat/slack/tools/channel-list-messages.ts
|
|
7889
|
-
import { z as
|
|
7890
|
-
var booleanInput2 = (description) =>
|
|
8025
|
+
import { z as z20 } from "zod";
|
|
8026
|
+
var booleanInput2 = (description) => z20.preprocess(
|
|
7891
8027
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
7892
|
-
|
|
8028
|
+
z20.boolean()
|
|
7893
8029
|
).describe(description);
|
|
7894
8030
|
function normalizeRangeTimestamp(field, value, targetChannelId) {
|
|
7895
8031
|
if (value === void 0) {
|
|
@@ -7916,9 +8052,9 @@ function createSlackChannelListMessagesTool(context) {
|
|
|
7916
8052
|
return zodTool({
|
|
7917
8053
|
description: "List channel messages from Slack history in the active channel context. Use when the user asks for recent or historical channel context outside this thread. Do not use for live monitoring or when current thread context already answers the question.",
|
|
7918
8054
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
7919
|
-
inputSchema:
|
|
7920
|
-
limit:
|
|
7921
|
-
cursor:
|
|
8055
|
+
inputSchema: z20.object({
|
|
8056
|
+
limit: z20.coerce.number().int().min(1).max(1e3).describe("Maximum number of messages to return across pages.").optional(),
|
|
8057
|
+
cursor: z20.string().min(1).describe("Optional cursor to continue from a prior call.").optional(),
|
|
7922
8058
|
oldest: optionalSlackTimestampParam(
|
|
7923
8059
|
"Optional oldest message timestamp (Slack ts) for range filtering."
|
|
7924
8060
|
),
|
|
@@ -7928,7 +8064,7 @@ function createSlackChannelListMessagesTool(context) {
|
|
|
7928
8064
|
inclusive: booleanInput2(
|
|
7929
8065
|
"Whether oldest/latest bounds should be inclusive."
|
|
7930
8066
|
).optional(),
|
|
7931
|
-
max_pages:
|
|
8067
|
+
max_pages: z20.coerce.number().int().min(1).max(10).describe("Maximum number of API pages to traverse in a single call.").optional()
|
|
7932
8068
|
}),
|
|
7933
8069
|
outputSchema: juniorToolResultSchema,
|
|
7934
8070
|
execute: async ({
|
|
@@ -8002,20 +8138,20 @@ function createSlackChannelListMessagesTool(context) {
|
|
|
8002
8138
|
}
|
|
8003
8139
|
|
|
8004
8140
|
// src/chat/slack/tools/conversation-search.ts
|
|
8005
|
-
import { z as
|
|
8141
|
+
import { z as z21 } from "zod";
|
|
8006
8142
|
var DEFAULT_LIMIT = 5;
|
|
8007
8143
|
var conversationSearchOutputSchema = juniorToolResultSchema.extend({
|
|
8008
|
-
query:
|
|
8009
|
-
count:
|
|
8010
|
-
threads:
|
|
8011
|
-
|
|
8012
|
-
conversation_id:
|
|
8013
|
-
thread_ts:
|
|
8014
|
-
message_id:
|
|
8015
|
-
message_role:
|
|
8016
|
-
message_timestamp:
|
|
8017
|
-
excerpt:
|
|
8018
|
-
permalink:
|
|
8144
|
+
query: z21.string(),
|
|
8145
|
+
count: z21.number().int().nonnegative(),
|
|
8146
|
+
threads: z21.array(
|
|
8147
|
+
z21.object({
|
|
8148
|
+
conversation_id: z21.string().min(1),
|
|
8149
|
+
thread_ts: z21.string().min(1),
|
|
8150
|
+
message_id: z21.string().min(1),
|
|
8151
|
+
message_role: z21.enum(["assistant", "user"]),
|
|
8152
|
+
message_timestamp: z21.string().datetime(),
|
|
8153
|
+
excerpt: z21.string(),
|
|
8154
|
+
permalink: z21.string().url().optional()
|
|
8019
8155
|
}).strict()
|
|
8020
8156
|
)
|
|
8021
8157
|
});
|
|
@@ -8028,9 +8164,9 @@ function createSlackConversationSearchTool(scope, currentConversationId, deps =
|
|
|
8028
8164
|
description: "Search retained public Junior conversation threads in the current Slack workspace."
|
|
8029
8165
|
},
|
|
8030
8166
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
8031
|
-
inputSchema:
|
|
8032
|
-
query:
|
|
8033
|
-
limit:
|
|
8167
|
+
inputSchema: z21.object({
|
|
8168
|
+
query: z21.string().trim().min(1).max(200).describe("Words or a short phrase to find in prior conversations."),
|
|
8169
|
+
limit: z21.number().int().min(1).max(10).describe("Maximum number of prior conversation threads to return.").nullable().optional()
|
|
8034
8170
|
}),
|
|
8035
8171
|
outputSchema: conversationSearchOutputSchema,
|
|
8036
8172
|
execute: async ({ query, limit }) => {
|
|
@@ -8077,27 +8213,27 @@ function createSlackConversationSearchTool(scope, currentConversationId, deps =
|
|
|
8077
8213
|
}
|
|
8078
8214
|
|
|
8079
8215
|
// src/chat/slack/tools/public-search.ts
|
|
8080
|
-
import { z as
|
|
8216
|
+
import { z as z22 } from "zod";
|
|
8081
8217
|
var DEFAULT_LIMIT2 = 10;
|
|
8082
|
-
var optionalTimestampSchema =
|
|
8218
|
+
var optionalTimestampSchema = z22.preprocess(
|
|
8083
8219
|
(value) => typeof value === "string" && value.trim() === "" ? void 0 : value,
|
|
8084
|
-
|
|
8220
|
+
z22.coerce.number().int().nonnegative().describe("Optional Unix timestamp bound.").optional()
|
|
8085
8221
|
);
|
|
8086
|
-
var searchMessageSchema =
|
|
8087
|
-
author_name:
|
|
8088
|
-
author_user_id:
|
|
8089
|
-
channel_id:
|
|
8090
|
-
channel_name:
|
|
8091
|
-
message_ts:
|
|
8092
|
-
content:
|
|
8093
|
-
is_author_bot:
|
|
8094
|
-
permalink:
|
|
8222
|
+
var searchMessageSchema = z22.object({
|
|
8223
|
+
author_name: z22.string().optional(),
|
|
8224
|
+
author_user_id: z22.string().optional(),
|
|
8225
|
+
channel_id: z22.string().min(1),
|
|
8226
|
+
channel_name: z22.string().optional(),
|
|
8227
|
+
message_ts: z22.string().min(1),
|
|
8228
|
+
content: z22.string(),
|
|
8229
|
+
is_author_bot: z22.boolean().optional(),
|
|
8230
|
+
permalink: z22.string().url()
|
|
8095
8231
|
});
|
|
8096
8232
|
var publicSearchOutputSchema = juniorToolResultSchema.extend({
|
|
8097
|
-
query:
|
|
8098
|
-
count:
|
|
8099
|
-
messages:
|
|
8100
|
-
next_cursor:
|
|
8233
|
+
query: z22.string(),
|
|
8234
|
+
count: z22.number().int().nonnegative(),
|
|
8235
|
+
messages: z22.array(searchMessageSchema),
|
|
8236
|
+
next_cursor: z22.string().optional()
|
|
8101
8237
|
});
|
|
8102
8238
|
function normalizeMessage(value) {
|
|
8103
8239
|
const parsed = searchMessageSchema.safeParse(value);
|
|
@@ -8119,8 +8255,8 @@ function createSlackPublicSearchTool(actionToken) {
|
|
|
8119
8255
|
return zodTool({
|
|
8120
8256
|
description: "Search public Slack channel messages across the current workspace. Use when the user asks about company activity, announcements, public mentions, or context outside the active channel. Search only when requested or clearly needed, prefer focused keywords and time bounds, and cite returned permalinks. This never searches private channels or DMs.",
|
|
8121
8257
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
8122
|
-
inputSchema:
|
|
8123
|
-
query:
|
|
8258
|
+
inputSchema: z22.object({
|
|
8259
|
+
query: z22.string().trim().min(1).max(500).describe(
|
|
8124
8260
|
"A focused Slack search query, including Slack search filters when useful."
|
|
8125
8261
|
),
|
|
8126
8262
|
after: optionalTimestampSchema.describe(
|
|
@@ -8129,10 +8265,10 @@ function createSlackPublicSearchTool(actionToken) {
|
|
|
8129
8265
|
before: optionalTimestampSchema.describe(
|
|
8130
8266
|
"Optional Unix timestamp upper bound."
|
|
8131
8267
|
),
|
|
8132
|
-
cursor:
|
|
8133
|
-
limit:
|
|
8134
|
-
sort:
|
|
8135
|
-
sort_dir:
|
|
8268
|
+
cursor: z22.string().min(1).describe("Cursor for the next result page.").optional(),
|
|
8269
|
+
limit: z22.coerce.number().int().min(1).max(20).describe("Maximum results to return; Slack allows at most 20.").optional(),
|
|
8270
|
+
sort: z22.enum(["score", "timestamp"]).describe("Rank by relevance or timestamp.").optional(),
|
|
8271
|
+
sort_dir: z22.enum(["asc", "desc"]).describe("Sort direction.").optional()
|
|
8136
8272
|
}),
|
|
8137
8273
|
outputSchema: publicSearchOutputSchema,
|
|
8138
8274
|
execute: async ({
|
|
@@ -8198,7 +8334,7 @@ function createSlackPublicSearchTool(actionToken) {
|
|
|
8198
8334
|
}
|
|
8199
8335
|
|
|
8200
8336
|
// src/chat/slack/tools/message-add-reaction.ts
|
|
8201
|
-
import { z as
|
|
8337
|
+
import { z as z23 } from "zod";
|
|
8202
8338
|
|
|
8203
8339
|
// src/chat/tools/idempotency.ts
|
|
8204
8340
|
function stableSerialize(value) {
|
|
@@ -8222,8 +8358,8 @@ function createOperationKey(toolName, input) {
|
|
|
8222
8358
|
function createSlackMessageAddReactionTool(context, state) {
|
|
8223
8359
|
return zodTool({
|
|
8224
8360
|
description: "Add an emoji reaction to the current inbound Slack message. Use when the user asks for a reaction on the current message without another target. Provide a Slack emoji alias name (for example `thumbsup`, `white_check_mark`, or `thumbsup::skin-tone-6`), not a unicode emoji glyph. The target message is injected by runtime context; do not use this for arbitrary historical messages.",
|
|
8225
|
-
inputSchema:
|
|
8226
|
-
emoji:
|
|
8361
|
+
inputSchema: z23.object({
|
|
8362
|
+
emoji: z23.string().min(1).max(64).describe(
|
|
8227
8363
|
"Slack emoji alias name to react with (for example `thumbsup`, `white_check_mark`, or `thumbsup::skin-tone-6`). Optional surrounding colons are allowed."
|
|
8228
8364
|
)
|
|
8229
8365
|
}),
|
|
@@ -8274,18 +8410,18 @@ function createSlackMessageAddReactionTool(context, state) {
|
|
|
8274
8410
|
|
|
8275
8411
|
// src/chat/slack/tools/send-files.ts
|
|
8276
8412
|
import { createHash as createHash2 } from "crypto";
|
|
8277
|
-
import { z as
|
|
8278
|
-
var sendFilesDataSchema =
|
|
8279
|
-
channel_id:
|
|
8280
|
-
deduplicated:
|
|
8281
|
-
file_count:
|
|
8282
|
-
file_ids:
|
|
8283
|
-
thread_ts:
|
|
8413
|
+
import { z as z24 } from "zod";
|
|
8414
|
+
var sendFilesDataSchema = z24.object({
|
|
8415
|
+
channel_id: z24.string().min(1),
|
|
8416
|
+
deduplicated: z24.boolean().optional(),
|
|
8417
|
+
file_count: z24.number().int().nonnegative(),
|
|
8418
|
+
file_ids: z24.array(z24.string().min(1)).optional(),
|
|
8419
|
+
thread_ts: z24.string().min(1)
|
|
8284
8420
|
});
|
|
8285
8421
|
var sendFilesResultSchema = juniorToolResultSchema.extend({
|
|
8286
|
-
ok:
|
|
8287
|
-
status:
|
|
8288
|
-
target:
|
|
8422
|
+
ok: z24.literal(true),
|
|
8423
|
+
status: z24.literal("success"),
|
|
8424
|
+
target: z24.string().min(1),
|
|
8289
8425
|
data: sendFilesDataSchema
|
|
8290
8426
|
});
|
|
8291
8427
|
function normalizeFiles(files) {
|
|
@@ -8310,8 +8446,8 @@ function fileOperationInput(files) {
|
|
|
8310
8446
|
function createSendFilesTool(context, state, materializeFile) {
|
|
8311
8447
|
return zodTool({
|
|
8312
8448
|
description: "Send one or more sandbox files into the active Slack conversation. Use when the user asks to attach, send, or share files here, in this conversation, or in this thread. Do not use for ordinary assistant text, top-level channel posts, other named channels, inline @mentions, or pinging mentioned users.",
|
|
8313
|
-
inputSchema:
|
|
8314
|
-
files:
|
|
8449
|
+
inputSchema: z24.object({
|
|
8450
|
+
files: z24.array(sandboxFileReferenceSchema).min(1).describe(
|
|
8315
8451
|
"One or more existing sandbox files. Objects returned by imageGenerate or webFetch can be passed unchanged."
|
|
8316
8452
|
)
|
|
8317
8453
|
}),
|
|
@@ -8615,13 +8751,13 @@ function storedCanvasUrl(state, canvasId) {
|
|
|
8615
8751
|
}
|
|
8616
8752
|
|
|
8617
8753
|
// src/chat/slack/tools/canvas/create.ts
|
|
8618
|
-
import { z as
|
|
8754
|
+
import { z as z25 } from "zod";
|
|
8619
8755
|
function createSlackCanvasCreateTool(context, state) {
|
|
8620
8756
|
return zodTool({
|
|
8621
8757
|
description: "Create a Slack canvas for long-form output in the active assistant context channel. Use when the answer is better as a reusable document than a thread reply: long-form research, timelines, bios/profiles, structured notes, plans, comparisons, or anything likely to exceed one compact Slack reply. After creating it, reply with one or two short sentences plus the canvas link; do not recap the canvas contents. Do not use for short answers that fit cleanly in one normal thread reply.",
|
|
8622
|
-
inputSchema:
|
|
8623
|
-
title:
|
|
8624
|
-
markdown:
|
|
8758
|
+
inputSchema: z25.object({
|
|
8759
|
+
title: z25.string().min(1).max(160).describe("Canvas title."),
|
|
8760
|
+
markdown: z25.string().min(1).describe("Canvas markdown body content.")
|
|
8625
8761
|
}),
|
|
8626
8762
|
outputSchema: juniorToolResultSchema,
|
|
8627
8763
|
execute: async ({ title, markdown }) => {
|
|
@@ -8684,35 +8820,35 @@ function createSlackCanvasCreateTool(context, state) {
|
|
|
8684
8820
|
}
|
|
8685
8821
|
|
|
8686
8822
|
// src/chat/slack/tools/canvas/edit.ts
|
|
8687
|
-
import { z as
|
|
8823
|
+
import { z as z26 } from "zod";
|
|
8688
8824
|
function prepareCanvasEditArguments(input) {
|
|
8689
8825
|
return prepareTextReplacementArguments(input);
|
|
8690
8826
|
}
|
|
8691
|
-
var editReplacementSchema2 =
|
|
8692
|
-
oldText:
|
|
8827
|
+
var editReplacementSchema2 = z26.object({
|
|
8828
|
+
oldText: z26.string().min(1).describe(
|
|
8693
8829
|
"Exact Canvas markdown to replace. It must be unique in the current Canvas body and must not overlap another edit."
|
|
8694
8830
|
),
|
|
8695
|
-
newText:
|
|
8831
|
+
newText: z26.string().describe("Replacement Canvas markdown for this edit.")
|
|
8696
8832
|
});
|
|
8697
8833
|
var slackCanvasEditOutputSchema = juniorToolResultSchema.extend({
|
|
8698
|
-
canvas_id:
|
|
8699
|
-
title:
|
|
8700
|
-
permalink:
|
|
8701
|
-
diff:
|
|
8702
|
-
first_changed_line:
|
|
8703
|
-
replacements:
|
|
8704
|
-
normalized_heading_count:
|
|
8705
|
-
summary:
|
|
8706
|
-
deduplicated:
|
|
8834
|
+
canvas_id: z26.string().optional(),
|
|
8835
|
+
title: z26.string().optional(),
|
|
8836
|
+
permalink: z26.string().optional(),
|
|
8837
|
+
diff: z26.string().optional(),
|
|
8838
|
+
first_changed_line: z26.number().int().positive().optional(),
|
|
8839
|
+
replacements: z26.number().int().nonnegative().optional(),
|
|
8840
|
+
normalized_heading_count: z26.number().int().nonnegative().optional(),
|
|
8841
|
+
summary: z26.string().optional(),
|
|
8842
|
+
deduplicated: z26.boolean().optional()
|
|
8707
8843
|
}).strict();
|
|
8708
8844
|
function createSlackCanvasEditTool(state) {
|
|
8709
8845
|
return zodTool({
|
|
8710
8846
|
description: "Edit one Slack canvas with exact markdown replacements. Use for precise changes to existing Canvas content; prefer this over slackCanvasWrite for targeted changes. Each oldText must match exactly, be unique, and not overlap another edit. Returns a diff. Multiple changes to the same canvas: use one edits[] call.",
|
|
8711
8847
|
prepareArguments: prepareCanvasEditArguments,
|
|
8712
8848
|
executionMode: "sequential",
|
|
8713
|
-
inputSchema:
|
|
8714
|
-
canvas:
|
|
8715
|
-
edits:
|
|
8849
|
+
inputSchema: z26.object({
|
|
8850
|
+
canvas: z26.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
|
|
8851
|
+
edits: z26.array(editReplacementSchema2).min(1).describe(
|
|
8716
8852
|
"Exact replacements matched against the current Canvas body, not incrementally."
|
|
8717
8853
|
)
|
|
8718
8854
|
}),
|
|
@@ -8790,29 +8926,29 @@ function createSlackCanvasEditTool(state) {
|
|
|
8790
8926
|
}
|
|
8791
8927
|
|
|
8792
8928
|
// src/chat/slack/tools/canvas/read.ts
|
|
8793
|
-
import { z as
|
|
8929
|
+
import { z as z27 } from "zod";
|
|
8794
8930
|
var slackCanvasReadOutputSchema = juniorToolResultSchema.extend({
|
|
8795
|
-
canvas_id:
|
|
8796
|
-
title:
|
|
8797
|
-
permalink:
|
|
8798
|
-
mimetype:
|
|
8799
|
-
filetype:
|
|
8800
|
-
original_byte_length:
|
|
8801
|
-
content:
|
|
8802
|
-
start_line:
|
|
8803
|
-
end_line:
|
|
8804
|
-
total_lines:
|
|
8931
|
+
canvas_id: z27.string().optional(),
|
|
8932
|
+
title: z27.string().optional(),
|
|
8933
|
+
permalink: z27.string().optional(),
|
|
8934
|
+
mimetype: z27.string().optional(),
|
|
8935
|
+
filetype: z27.string().optional(),
|
|
8936
|
+
original_byte_length: z27.number().int().nonnegative().optional(),
|
|
8937
|
+
content: z27.string().optional(),
|
|
8938
|
+
start_line: z27.number().int().positive().optional(),
|
|
8939
|
+
end_line: z27.number().int().nonnegative().optional(),
|
|
8940
|
+
total_lines: z27.number().int().nonnegative().optional()
|
|
8805
8941
|
}).strict();
|
|
8806
8942
|
function createSlackCanvasReadTool() {
|
|
8807
8943
|
return zodTool({
|
|
8808
8944
|
description: "Read a bounded line range from a Slack canvas as markdown. Use when you need exact Canvas contents to verify facts or make edits safely. Do not use for generic web pages \u2014 use webFetch for those.",
|
|
8809
8945
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
8810
|
-
inputSchema:
|
|
8811
|
-
canvas:
|
|
8946
|
+
inputSchema: z27.object({
|
|
8947
|
+
canvas: z27.string().min(1).describe(
|
|
8812
8948
|
"Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL (e.g. `https://team.slack.com/docs/T.../F...`)."
|
|
8813
8949
|
),
|
|
8814
|
-
offset:
|
|
8815
|
-
limit:
|
|
8950
|
+
offset: z27.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
|
|
8951
|
+
limit: z27.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
|
|
8816
8952
|
}),
|
|
8817
8953
|
outputSchema: slackCanvasReadOutputSchema,
|
|
8818
8954
|
execute: async ({ canvas, offset, limit }) => {
|
|
@@ -8869,14 +9005,14 @@ function createSlackCanvasReadTool() {
|
|
|
8869
9005
|
}
|
|
8870
9006
|
|
|
8871
9007
|
// src/chat/slack/tools/canvas/write.ts
|
|
8872
|
-
import { z as
|
|
9008
|
+
import { z as z28 } from "zod";
|
|
8873
9009
|
function createSlackCanvasWriteTool(state) {
|
|
8874
9010
|
return zodTool({
|
|
8875
9011
|
description: "Write UTF-8 markdown content to a Slack canvas. Use for deliberate full-Canvas replacement after validation; use slackCanvasEdit for targeted changes to existing canvas content.",
|
|
8876
9012
|
executionMode: "sequential",
|
|
8877
|
-
inputSchema:
|
|
8878
|
-
canvas:
|
|
8879
|
-
content:
|
|
9013
|
+
inputSchema: z28.object({
|
|
9014
|
+
canvas: z28.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
|
|
9015
|
+
content: z28.string().describe("UTF-8 markdown content to write.")
|
|
8880
9016
|
}),
|
|
8881
9017
|
outputSchema: juniorToolResultSchema,
|
|
8882
9018
|
execute: async ({ canvas, content }) => {
|
|
@@ -9112,12 +9248,12 @@ async function updateListItem(input) {
|
|
|
9112
9248
|
}
|
|
9113
9249
|
|
|
9114
9250
|
// src/chat/slack/id-param.ts
|
|
9115
|
-
import { z as
|
|
9251
|
+
import { z as z29 } from "zod";
|
|
9116
9252
|
function slackChannelIdParam(description) {
|
|
9117
|
-
return
|
|
9253
|
+
return z29.string().min(1).describe(description);
|
|
9118
9254
|
}
|
|
9119
9255
|
function slackUserIdParam(description) {
|
|
9120
|
-
return
|
|
9256
|
+
return z29.string().min(1).describe(description);
|
|
9121
9257
|
}
|
|
9122
9258
|
function parseRequiredSlackChannelIdParam(field, value) {
|
|
9123
9259
|
const channelId = parseSlackChannelId(value);
|
|
@@ -9141,16 +9277,16 @@ function parseRequiredSlackUserIdParam(field, value) {
|
|
|
9141
9277
|
}
|
|
9142
9278
|
|
|
9143
9279
|
// src/chat/slack/tools/list/add-items.ts
|
|
9144
|
-
import { z as
|
|
9280
|
+
import { z as z30 } from "zod";
|
|
9145
9281
|
function createSlackListAddItemsTool(state) {
|
|
9146
9282
|
return zodTool({
|
|
9147
9283
|
description: "Add tasks to the active Slack list tracked in artifact context. Use when the user wants actionable items recorded in the current thread list. Do not use when no list exists and list creation was not requested.",
|
|
9148
|
-
inputSchema:
|
|
9149
|
-
items:
|
|
9284
|
+
inputSchema: z30.object({
|
|
9285
|
+
items: z30.array(z30.string().min(1)).min(1).max(25).describe("List item titles to create."),
|
|
9150
9286
|
assignee_user_id: slackUserIdParam(
|
|
9151
9287
|
"Optional Slack user ID assigned to all created items."
|
|
9152
9288
|
).optional(),
|
|
9153
|
-
due_date:
|
|
9289
|
+
due_date: z30.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
|
|
9154
9290
|
}),
|
|
9155
9291
|
outputSchema: juniorToolResultSchema,
|
|
9156
9292
|
execute: async ({ items, assignee_user_id, due_date }) => {
|
|
@@ -9204,12 +9340,12 @@ function createSlackListAddItemsTool(state) {
|
|
|
9204
9340
|
}
|
|
9205
9341
|
|
|
9206
9342
|
// src/chat/slack/tools/list/create.ts
|
|
9207
|
-
import { z as
|
|
9343
|
+
import { z as z31 } from "zod";
|
|
9208
9344
|
function createSlackListCreateTool(state) {
|
|
9209
9345
|
return zodTool({
|
|
9210
9346
|
description: "Create a Slack todo list for action tracking. Use when the user needs structured tasks with ownership/completion tracking. Do not use for one-off notes without task management needs.",
|
|
9211
|
-
inputSchema:
|
|
9212
|
-
name:
|
|
9347
|
+
inputSchema: z31.object({
|
|
9348
|
+
name: z31.string().min(1).max(160).describe("Name for the new Slack list.")
|
|
9213
9349
|
}),
|
|
9214
9350
|
outputSchema: juniorToolResultSchema,
|
|
9215
9351
|
execute: async ({ name }) => {
|
|
@@ -9241,13 +9377,13 @@ function createSlackListCreateTool(state) {
|
|
|
9241
9377
|
}
|
|
9242
9378
|
|
|
9243
9379
|
// src/chat/slack/tools/list/get-items.ts
|
|
9244
|
-
import { z as
|
|
9380
|
+
import { z as z32 } from "zod";
|
|
9245
9381
|
function createSlackListGetItemsTool(state) {
|
|
9246
9382
|
return zodTool({
|
|
9247
9383
|
description: "Read items from the active Slack list tracked in artifact context. Use when the user asks for task status, open items, or list contents. Do not use when list state is already known from the immediately prior result.",
|
|
9248
9384
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
9249
|
-
inputSchema:
|
|
9250
|
-
limit:
|
|
9385
|
+
inputSchema: z32.object({
|
|
9386
|
+
limit: z32.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
|
|
9251
9387
|
}),
|
|
9252
9388
|
outputSchema: juniorToolResultSchema,
|
|
9253
9389
|
execute: async ({ limit }) => {
|
|
@@ -9272,21 +9408,21 @@ function createSlackListGetItemsTool(state) {
|
|
|
9272
9408
|
}
|
|
9273
9409
|
|
|
9274
9410
|
// src/chat/slack/tools/list/update-item.ts
|
|
9275
|
-
import { z as
|
|
9276
|
-
var booleanInput3 = (description) =>
|
|
9411
|
+
import { z as z33 } from "zod";
|
|
9412
|
+
var booleanInput3 = (description) => z33.preprocess(
|
|
9277
9413
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
9278
|
-
|
|
9414
|
+
z33.boolean()
|
|
9279
9415
|
).describe(description);
|
|
9280
|
-
var updateListItemInputSchema =
|
|
9281
|
-
|
|
9282
|
-
item_id:
|
|
9416
|
+
var updateListItemInputSchema = z33.union([
|
|
9417
|
+
z33.object({
|
|
9418
|
+
item_id: z33.string().min(1).describe("ID of the Slack list item to update."),
|
|
9283
9419
|
completed: booleanInput3("Optional completion status update."),
|
|
9284
|
-
title:
|
|
9420
|
+
title: z33.string().min(1).describe("Optional new item title.").optional()
|
|
9285
9421
|
}),
|
|
9286
|
-
|
|
9287
|
-
item_id:
|
|
9422
|
+
z33.object({
|
|
9423
|
+
item_id: z33.string().min(1).describe("ID of the Slack list item to update."),
|
|
9288
9424
|
completed: booleanInput3("Optional completion status update.").optional(),
|
|
9289
|
-
title:
|
|
9425
|
+
title: z33.string().min(1).describe("Optional new item title.")
|
|
9290
9426
|
})
|
|
9291
9427
|
]);
|
|
9292
9428
|
function createSlackListUpdateItemTool(state) {
|
|
@@ -9362,7 +9498,7 @@ async function checkSlackChannelReadAccess(args) {
|
|
|
9362
9498
|
}
|
|
9363
9499
|
|
|
9364
9500
|
// src/chat/slack/tools/thread-read.ts
|
|
9365
|
-
import { z as
|
|
9501
|
+
import { z as z34 } from "zod";
|
|
9366
9502
|
|
|
9367
9503
|
// src/chat/slack/tools/slack-message-url.ts
|
|
9368
9504
|
var SLACK_HOST_PATTERN = /^[a-z0-9-]+\.slack(?:-gov)?\.com$/;
|
|
@@ -9535,8 +9671,8 @@ function createSlackThreadReadTool(context, deps = {}) {
|
|
|
9535
9671
|
return zodTool({
|
|
9536
9672
|
description: "Read a Slack thread from a shared Slack message archive URL or explicit channel + timestamp. Use when the user shares a Slack message link (https://*.slack.com/archives/...) and you need the referenced message and its thread context. Only the current conversation and public channels Junior has seen in this workspace are readable.",
|
|
9537
9673
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
9538
|
-
inputSchema:
|
|
9539
|
-
url:
|
|
9674
|
+
inputSchema: z34.object({
|
|
9675
|
+
url: z34.string().min(1).describe(
|
|
9540
9676
|
"Slack message archive URL, e.g. https://workspace.slack.com/archives/C123/p1700000000123456"
|
|
9541
9677
|
).optional(),
|
|
9542
9678
|
channel_id: slackChannelIdParam(
|
|
@@ -9545,8 +9681,8 @@ function createSlackThreadReadTool(context, deps = {}) {
|
|
|
9545
9681
|
ts: slackTimestampParam(
|
|
9546
9682
|
"Slack message timestamp (e.g. 1700000000.123456). May be the thread root or any message in the thread."
|
|
9547
9683
|
).optional(),
|
|
9548
|
-
limit:
|
|
9549
|
-
max_pages:
|
|
9684
|
+
limit: z34.coerce.number().int().min(1).max(1e3).describe("Maximum number of thread messages to fetch.").optional(),
|
|
9685
|
+
max_pages: z34.coerce.number().int().min(1).max(10).describe("Maximum number of Slack API pages to traverse.").optional()
|
|
9550
9686
|
}),
|
|
9551
9687
|
outputSchema: juniorToolResultSchema,
|
|
9552
9688
|
execute: async ({ url, channel_id, ts, limit, max_pages }) => {
|
|
@@ -9802,29 +9938,29 @@ async function searchSlackUsers(options) {
|
|
|
9802
9938
|
}
|
|
9803
9939
|
|
|
9804
9940
|
// src/chat/slack/tools/user-lookup.ts
|
|
9805
|
-
import { z as
|
|
9806
|
-
var booleanInput4 = (description) =>
|
|
9941
|
+
import { z as z35 } from "zod";
|
|
9942
|
+
var booleanInput4 = (description) => z35.preprocess(
|
|
9807
9943
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
9808
|
-
|
|
9944
|
+
z35.boolean()
|
|
9809
9945
|
).describe(description);
|
|
9810
9946
|
function createSlackUserLookupTool() {
|
|
9811
9947
|
return zodTool({
|
|
9812
9948
|
description: "Look up Slack user profiles by user ID, email, or name search. Use when you need to identify a user, resolve cross-platform identity, or look up profile details like title or status. Returns profile fields including custom fields. For user ID lookup, pass a Slack user ID (e.g. U039RR91S). For search, pass a name query.",
|
|
9813
9949
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
9814
|
-
inputSchema:
|
|
9950
|
+
inputSchema: z35.object({
|
|
9815
9951
|
user_id: slackUserIdParam(
|
|
9816
9952
|
"Slack user ID to look up (e.g. U039RR91S). Mutually exclusive with email and query."
|
|
9817
9953
|
).optional(),
|
|
9818
|
-
email:
|
|
9954
|
+
email: z35.string().min(3).describe(
|
|
9819
9955
|
"Email address to look up. Mutually exclusive with user_id and query."
|
|
9820
9956
|
).optional(),
|
|
9821
|
-
query:
|
|
9957
|
+
query: z35.string().min(2).describe(
|
|
9822
9958
|
"Name to search for (matches against username, display name, real name). Mutually exclusive with user_id and email."
|
|
9823
9959
|
).optional(),
|
|
9824
|
-
limit:
|
|
9960
|
+
limit: z35.coerce.number().int().min(1).max(20).describe(
|
|
9825
9961
|
"Maximum number of results to return for name search. Defaults to 10."
|
|
9826
9962
|
).optional(),
|
|
9827
|
-
max_pages:
|
|
9963
|
+
max_pages: z35.coerce.number().int().min(1).max(5).describe(
|
|
9828
9964
|
"Maximum number of Slack API pages to scan for name search. Defaults to 3."
|
|
9829
9965
|
).optional(),
|
|
9830
9966
|
include_bots: booleanInput4(
|
|
@@ -9928,18 +10064,18 @@ function createSlackUserLookupTool() {
|
|
|
9928
10064
|
}
|
|
9929
10065
|
|
|
9930
10066
|
// src/chat/tools/system-time.ts
|
|
9931
|
-
import { z as
|
|
10067
|
+
import { z as z36 } from "zod";
|
|
9932
10068
|
var systemTimeOutputSchema = juniorToolResultSchema.extend({
|
|
9933
|
-
unix_ms:
|
|
9934
|
-
iso_utc:
|
|
9935
|
-
iso_local:
|
|
9936
|
-
timezone_offset_minutes:
|
|
10069
|
+
unix_ms: z36.number(),
|
|
10070
|
+
iso_utc: z36.string(),
|
|
10071
|
+
iso_local: z36.string(),
|
|
10072
|
+
timezone_offset_minutes: z36.number()
|
|
9937
10073
|
});
|
|
9938
10074
|
function createSystemTimeTool() {
|
|
9939
10075
|
return zodTool({
|
|
9940
10076
|
description: "Return current system time in UTC and local ISO formats. Use when the user asks for current time/date context. Do not use as a substitute for historical or timezone-conversion research.",
|
|
9941
10077
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
9942
|
-
inputSchema:
|
|
10078
|
+
inputSchema: z36.object({}),
|
|
9943
10079
|
outputSchema: systemTimeOutputSchema,
|
|
9944
10080
|
privateTraceResult: (result) => ({
|
|
9945
10081
|
ok: result.ok,
|
|
@@ -9968,32 +10104,32 @@ function createSystemTimeTool() {
|
|
|
9968
10104
|
}
|
|
9969
10105
|
|
|
9970
10106
|
// src/chat/tools/query-conversation-events.ts
|
|
9971
|
-
import { z as
|
|
10107
|
+
import { z as z37 } from "zod";
|
|
9972
10108
|
var DEFAULT_LIMIT3 = 25;
|
|
9973
10109
|
var MAX_LIMIT = 100;
|
|
9974
10110
|
var CONVERSATION_EVENTS_TOOL_SOURCE = {
|
|
9975
10111
|
id: "conversation-events",
|
|
9976
10112
|
description: "Inspect Junior's durable conversation event log for debugging runtime behavior."
|
|
9977
10113
|
};
|
|
9978
|
-
var knownEventTypeSchema =
|
|
9979
|
-
var projectedEventSchema =
|
|
9980
|
-
seq:
|
|
9981
|
-
history_version:
|
|
10114
|
+
var knownEventTypeSchema = z37.enum(KNOWN_CONVERSATION_EVENT_TYPES);
|
|
10115
|
+
var projectedEventSchema = z37.object({
|
|
10116
|
+
seq: z37.number().int().nonnegative().describe("Stable event position; use it for pagination bounds."),
|
|
10117
|
+
history_version: z37.number().int().nonnegative().describe(
|
|
9982
10118
|
"Model-history generation. It increments when handoff or compaction replaces active model context."
|
|
9983
10119
|
),
|
|
9984
|
-
created_at:
|
|
9985
|
-
idempotency_key:
|
|
9986
|
-
data:
|
|
10120
|
+
created_at: z37.iso.datetime().describe("When the event was recorded."),
|
|
10121
|
+
idempotency_key: z37.string().min(1).optional().describe("Retry-stable event identity, when one was assigned."),
|
|
10122
|
+
data: z37.record(z37.string(), z37.unknown()).describe(
|
|
9987
10123
|
"Event payload. The type field identifies the event; replacement-history events report replacement_history_count instead of replaying the full model context."
|
|
9988
10124
|
)
|
|
9989
10125
|
}).strict();
|
|
9990
10126
|
var queryConversationEventsOutputSchema = juniorToolResultSchema.extend({
|
|
9991
|
-
conversation_id:
|
|
9992
|
-
events:
|
|
9993
|
-
has_older:
|
|
10127
|
+
conversation_id: z37.string().min(1),
|
|
10128
|
+
events: z37.array(projectedEventSchema),
|
|
10129
|
+
has_older: z37.boolean().describe(
|
|
9994
10130
|
"Whether matching events exist before this page; request them with before_seq set to the first returned seq."
|
|
9995
10131
|
),
|
|
9996
|
-
has_newer:
|
|
10132
|
+
has_newer: z37.boolean().describe(
|
|
9997
10133
|
"Whether matching events exist after this page; request them with after_seq set to the last returned seq."
|
|
9998
10134
|
)
|
|
9999
10135
|
});
|
|
@@ -10003,20 +10139,20 @@ function createQueryConversationEventsTool(context) {
|
|
|
10003
10139
|
exposure: "deferred",
|
|
10004
10140
|
source: CONVERSATION_EVENTS_TOOL_SOURCE,
|
|
10005
10141
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
10006
|
-
inputSchema:
|
|
10007
|
-
conversation_id:
|
|
10142
|
+
inputSchema: z37.object({
|
|
10143
|
+
conversation_id: z37.string().trim().min(1).describe(
|
|
10008
10144
|
"Conversation ID to inspect, such as slack:{channelId}:{threadTs} or a child conversation id."
|
|
10009
10145
|
),
|
|
10010
|
-
after_seq:
|
|
10146
|
+
after_seq: z37.number().int().nonnegative().nullable().describe(
|
|
10011
10147
|
"Exclusive lower bound on event seq. When set, returns the next newer page in ascending order."
|
|
10012
10148
|
).optional(),
|
|
10013
|
-
before_seq:
|
|
10149
|
+
before_seq: z37.number().int().nonnegative().nullable().describe(
|
|
10014
10150
|
"Exclusive upper bound on event seq. Combine with defaults or after_seq to page older or bounded ranges."
|
|
10015
10151
|
).optional(),
|
|
10016
|
-
limit:
|
|
10152
|
+
limit: z37.number().int().min(1).max(MAX_LIMIT).nullable().describe(
|
|
10017
10153
|
`Maximum events to return. Defaults to ${DEFAULT_LIMIT3}; max ${MAX_LIMIT}.`
|
|
10018
10154
|
).optional(),
|
|
10019
|
-
types:
|
|
10155
|
+
types: z37.array(knownEventTypeSchema).min(1).nullable().describe(
|
|
10020
10156
|
"Optional event-type filter. Omit to return every durable event type."
|
|
10021
10157
|
).optional()
|
|
10022
10158
|
}).strict(),
|
|
@@ -10206,10 +10342,10 @@ function stripReplacementHistoryField(value) {
|
|
|
10206
10342
|
}
|
|
10207
10343
|
|
|
10208
10344
|
// src/chat/tools/handoff/tool.ts
|
|
10209
|
-
import { z as
|
|
10345
|
+
import { z as z38 } from "zod";
|
|
10210
10346
|
var HANDOFF_TOOL_NAME = "handoff";
|
|
10211
10347
|
function createHandoffTool(handoff) {
|
|
10212
|
-
const profileSchema =
|
|
10348
|
+
const profileSchema = z38.enum(handoff.profiles);
|
|
10213
10349
|
const handoffResultSchema = juniorToolResultSchema.extend({
|
|
10214
10350
|
model_profile: profileSchema
|
|
10215
10351
|
});
|
|
@@ -10217,7 +10353,7 @@ function createHandoffTool(handoff) {
|
|
|
10217
10353
|
return zodTool({
|
|
10218
10354
|
description: `Switch to another execution profile and continue the same task. Profiles: ${profileNames}. Call this as the only tool.`,
|
|
10219
10355
|
executionMode: "sequential",
|
|
10220
|
-
inputSchema:
|
|
10356
|
+
inputSchema: z38.object({
|
|
10221
10357
|
profile: profileSchema.describe("Target execution profile")
|
|
10222
10358
|
}).strict(),
|
|
10223
10359
|
outputSchema: handoffResultSchema,
|
|
@@ -10240,7 +10376,7 @@ function createHandoffTool(handoff) {
|
|
|
10240
10376
|
}
|
|
10241
10377
|
|
|
10242
10378
|
// src/chat/tools/web/fetch-tool.ts
|
|
10243
|
-
import { z as
|
|
10379
|
+
import { z as z39 } from "zod";
|
|
10244
10380
|
|
|
10245
10381
|
// src/chat/tools/web/constants.ts
|
|
10246
10382
|
var USER_AGENT = "junior-bot/0.1";
|
|
@@ -10368,7 +10504,7 @@ async function fetchWithPinnedLookup(url, resolved, signal) {
|
|
|
10368
10504
|
}
|
|
10369
10505
|
const client = url.protocol === "https:" ? https : http;
|
|
10370
10506
|
const lookup = createPinnedLookup(resolved);
|
|
10371
|
-
return new Promise((
|
|
10507
|
+
return new Promise((resolve2, reject) => {
|
|
10372
10508
|
const request = client.request(
|
|
10373
10509
|
{
|
|
10374
10510
|
protocol: url.protocol,
|
|
@@ -10398,7 +10534,7 @@ async function fetchWithPinnedLookup(url, resolved, signal) {
|
|
|
10398
10534
|
}
|
|
10399
10535
|
const rawStatus = response.statusCode ?? 500;
|
|
10400
10536
|
const status = rawStatus >= 200 && rawStatus <= 599 ? rawStatus : 502;
|
|
10401
|
-
|
|
10537
|
+
resolve2(
|
|
10402
10538
|
new Response(Buffer.concat(chunks), {
|
|
10403
10539
|
status,
|
|
10404
10540
|
headers
|
|
@@ -10690,9 +10826,9 @@ function createWebFetchTool(hooks, options = {}) {
|
|
|
10690
10826
|
destructiveHint: false,
|
|
10691
10827
|
openWorldHint: true
|
|
10692
10828
|
},
|
|
10693
|
-
inputSchema:
|
|
10694
|
-
url:
|
|
10695
|
-
max_chars:
|
|
10829
|
+
inputSchema: z39.object({
|
|
10830
|
+
url: z39.string().min(1).describe("HTTP(S) URL to fetch."),
|
|
10831
|
+
max_chars: z39.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
|
|
10696
10832
|
}),
|
|
10697
10833
|
outputSchema: juniorToolResultSchema,
|
|
10698
10834
|
execute: async ({ url, max_chars }) => {
|
|
@@ -10753,7 +10889,7 @@ function createWebFetchTool(hooks, options = {}) {
|
|
|
10753
10889
|
}
|
|
10754
10890
|
|
|
10755
10891
|
// src/chat/tools/web/search.ts
|
|
10756
|
-
import { z as
|
|
10892
|
+
import { z as z40 } from "zod";
|
|
10757
10893
|
import { generateText } from "ai";
|
|
10758
10894
|
import { createGatewayProvider } from "@ai-sdk/gateway";
|
|
10759
10895
|
var SEARCH_TIMEOUT_MS = 6e4;
|
|
@@ -10802,9 +10938,9 @@ function createWebSearchTool(modelId, override) {
|
|
|
10802
10938
|
destructiveHint: false,
|
|
10803
10939
|
openWorldHint: true
|
|
10804
10940
|
},
|
|
10805
|
-
inputSchema:
|
|
10806
|
-
query:
|
|
10807
|
-
max_results:
|
|
10941
|
+
inputSchema: z40.object({
|
|
10942
|
+
query: z40.string().min(1).max(500).describe("Search query."),
|
|
10943
|
+
max_results: z40.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
|
|
10808
10944
|
}),
|
|
10809
10945
|
outputSchema: juniorToolResultSchema,
|
|
10810
10946
|
execute: async ({ query, max_results }) => {
|
|
@@ -10873,14 +11009,14 @@ function createWebSearchTool(modelId, override) {
|
|
|
10873
11009
|
}
|
|
10874
11010
|
|
|
10875
11011
|
// src/chat/tools/sandbox/write-file.ts
|
|
10876
|
-
import { z as
|
|
11012
|
+
import { z as z41 } from "zod";
|
|
10877
11013
|
function createWriteFileTool() {
|
|
10878
11014
|
return zodTool({
|
|
10879
11015
|
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.",
|
|
10880
11016
|
executionMode: "sequential",
|
|
10881
|
-
inputSchema:
|
|
10882
|
-
path:
|
|
10883
|
-
content:
|
|
11017
|
+
inputSchema: z41.object({
|
|
11018
|
+
path: z41.string().min(1).describe("Path to write in the sandbox workspace."),
|
|
11019
|
+
content: z41.string().describe("UTF-8 file content to write.")
|
|
10884
11020
|
}),
|
|
10885
11021
|
outputSchema: juniorToolResultSchema,
|
|
10886
11022
|
execute: async () => {
|
|
@@ -10952,6 +11088,13 @@ function createTools(availableSkills, hooks = {}, context) {
|
|
|
10952
11088
|
if (context.conversationId) {
|
|
10953
11089
|
tools.queryConversationEvents = createQueryConversationEventsTool(context);
|
|
10954
11090
|
}
|
|
11091
|
+
if (context.supportsImageInput) {
|
|
11092
|
+
tools.viewImage = createViewImageTool(
|
|
11093
|
+
context.workspace,
|
|
11094
|
+
context.supportsImageInput,
|
|
11095
|
+
hooks.toolOverrides?.viewImage
|
|
11096
|
+
);
|
|
11097
|
+
}
|
|
10955
11098
|
if (hooks.writeGeneratedArtifacts) {
|
|
10956
11099
|
tools.imageGenerate = createImageGenerateTool(
|
|
10957
11100
|
{
|
|
@@ -11546,6 +11689,8 @@ function isPluginToolInputError(error) {
|
|
|
11546
11689
|
}
|
|
11547
11690
|
function getToolErrorType(error) {
|
|
11548
11691
|
if (error instanceof McpToolError) return "tool_error";
|
|
11692
|
+
if (error instanceof McpProviderError) return "mcp_provider_error";
|
|
11693
|
+
if (error instanceof OAuthProviderError) return "oauth_provider_error";
|
|
11549
11694
|
if (error instanceof ToolInputError || isPluginToolInputError(error)) {
|
|
11550
11695
|
return "tool_input_error";
|
|
11551
11696
|
}
|
|
@@ -11568,6 +11713,8 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, trac
|
|
|
11568
11713
|
const errorMessage = getMcpAwareTelemetryMessage(error, conversationPrivacy);
|
|
11569
11714
|
const errorAttributes = {
|
|
11570
11715
|
"error.type": errorType,
|
|
11716
|
+
...getMcpProviderErrorAttributes(error),
|
|
11717
|
+
...getOAuthProviderErrorAttributes(error),
|
|
11571
11718
|
...error instanceof PluginCredentialFailureError ? { "app.credential.provider": error.provider } : {}
|
|
11572
11719
|
};
|
|
11573
11720
|
if (setExecutionSpanAttributes) {
|
|
@@ -11600,7 +11747,7 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, trac
|
|
|
11600
11747
|
"gen_ai.operation.name": "execute_tool",
|
|
11601
11748
|
"gen_ai.tool.name": toolName,
|
|
11602
11749
|
...toolCallId ? { "gen_ai.tool.call.id": toolCallId } : {},
|
|
11603
|
-
|
|
11750
|
+
...errorAttributes,
|
|
11604
11751
|
"exception.message": errorMessage
|
|
11605
11752
|
},
|
|
11606
11753
|
"Agent tool call failed"
|
|
@@ -11616,6 +11763,7 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, trac
|
|
|
11616
11763
|
"gen_ai.operation.name": "execute_tool",
|
|
11617
11764
|
"gen_ai.tool.name": toolName,
|
|
11618
11765
|
...toolCallId ? { "gen_ai.tool.call.id": toolCallId } : {},
|
|
11766
|
+
...errorAttributes,
|
|
11619
11767
|
...getToolErrorAttributes(error)
|
|
11620
11768
|
},
|
|
11621
11769
|
"Agent tool call failed"
|
|
@@ -11625,17 +11773,17 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, trac
|
|
|
11625
11773
|
}
|
|
11626
11774
|
|
|
11627
11775
|
// src/chat/tools/execute-tool.ts
|
|
11628
|
-
import { z as
|
|
11776
|
+
import { z as z42 } from "zod";
|
|
11629
11777
|
var EXECUTE_TOOL_NAME = "executeTool";
|
|
11630
11778
|
function createExecuteToolTool() {
|
|
11631
11779
|
return zodTool({
|
|
11632
11780
|
description: "Execute any catalog tool by exact tool_name from searchTools or a tool-result execution hint. Put tool-specific parameters inside arguments.",
|
|
11633
11781
|
executionMode: "sequential",
|
|
11634
|
-
inputSchema:
|
|
11635
|
-
tool_name:
|
|
11782
|
+
inputSchema: z42.object({
|
|
11783
|
+
tool_name: z42.string().min(1).describe(
|
|
11636
11784
|
"Exact catalog tool_name returned by searchTools or a tool-result execution hint."
|
|
11637
11785
|
),
|
|
11638
|
-
arguments:
|
|
11786
|
+
arguments: z42.record(z42.string(), z42.unknown()).describe(
|
|
11639
11787
|
'Arguments matching the selected catalog tool schema, for example { "query": "..." }.'
|
|
11640
11788
|
).optional()
|
|
11641
11789
|
}).strict(),
|
|
@@ -11675,42 +11823,42 @@ function planToolExposure(tools) {
|
|
|
11675
11823
|
}
|
|
11676
11824
|
|
|
11677
11825
|
// src/chat/tools/search-tools.ts
|
|
11678
|
-
import { z as
|
|
11826
|
+
import { z as z43 } from "zod";
|
|
11679
11827
|
var SEARCH_TOOLS_NAME = "searchTools";
|
|
11680
11828
|
var DEFAULT_MAX_RESULTS2 = 5;
|
|
11681
11829
|
var MAX_RESULTS3 = 20;
|
|
11682
11830
|
var MODEL_VISIBLE_DESCRIPTION_CAP = 180;
|
|
11683
|
-
var searchToolsSourceSchema =
|
|
11684
|
-
id:
|
|
11685
|
-
description:
|
|
11831
|
+
var searchToolsSourceSchema = z43.object({
|
|
11832
|
+
id: z43.string(),
|
|
11833
|
+
description: z43.string()
|
|
11686
11834
|
}).strict();
|
|
11687
|
-
var toolCallExampleSchema =
|
|
11688
|
-
tool_name:
|
|
11689
|
-
arguments:
|
|
11835
|
+
var toolCallExampleSchema = z43.object({
|
|
11836
|
+
tool_name: z43.string(),
|
|
11837
|
+
arguments: z43.record(z43.string(), z43.string())
|
|
11690
11838
|
}).strict();
|
|
11691
|
-
var searchToolsToolSchema =
|
|
11692
|
-
tool_name:
|
|
11693
|
-
description:
|
|
11694
|
-
exposure:
|
|
11695
|
-
source:
|
|
11696
|
-
signature:
|
|
11839
|
+
var searchToolsToolSchema = z43.object({
|
|
11840
|
+
tool_name: z43.string(),
|
|
11841
|
+
description: z43.string(),
|
|
11842
|
+
exposure: z43.enum(["direct", "deferred", "modelOnly", "hidden"]),
|
|
11843
|
+
source: z43.string().optional(),
|
|
11844
|
+
signature: z43.string(),
|
|
11697
11845
|
call: toolCallExampleSchema,
|
|
11698
|
-
input_schema:
|
|
11699
|
-
input_schema_summary:
|
|
11700
|
-
call_notes:
|
|
11701
|
-
annotations:
|
|
11846
|
+
input_schema: z43.unknown(),
|
|
11847
|
+
input_schema_summary: z43.string(),
|
|
11848
|
+
call_notes: z43.array(z43.string()),
|
|
11849
|
+
annotations: z43.record(z43.string(), z43.unknown())
|
|
11702
11850
|
}).strict();
|
|
11703
11851
|
var searchToolsOutputSchema = juniorToolResultSchema.extend({
|
|
11704
|
-
query:
|
|
11705
|
-
source:
|
|
11706
|
-
sources:
|
|
11707
|
-
total_catalog_tools:
|
|
11708
|
-
total_eligible_tools:
|
|
11709
|
-
total_matches:
|
|
11710
|
-
returned_tools:
|
|
11711
|
-
execution_tool:
|
|
11852
|
+
query: z43.string().nullable(),
|
|
11853
|
+
source: z43.string().nullable(),
|
|
11854
|
+
sources: z43.array(searchToolsSourceSchema),
|
|
11855
|
+
total_catalog_tools: z43.number().int().nonnegative(),
|
|
11856
|
+
total_eligible_tools: z43.number().int().nonnegative(),
|
|
11857
|
+
total_matches: z43.number().int().nonnegative(),
|
|
11858
|
+
returned_tools: z43.number().int().nonnegative(),
|
|
11859
|
+
execution_tool: z43.literal("executeTool"),
|
|
11712
11860
|
execution_example: toolCallExampleSchema,
|
|
11713
|
-
tools:
|
|
11861
|
+
tools: z43.array(searchToolsToolSchema)
|
|
11714
11862
|
}).strict();
|
|
11715
11863
|
function normalize2(value) {
|
|
11716
11864
|
return value.toLowerCase().replace(/[^a-z0-9_]+/g, " ").trim();
|
|
@@ -11902,14 +12050,14 @@ function createSearchToolsTool(catalogTools) {
|
|
|
11902
12050
|
return zodTool({
|
|
11903
12051
|
description: renderSearchToolsDescription(knownSources),
|
|
11904
12052
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
11905
|
-
inputSchema:
|
|
11906
|
-
query:
|
|
12053
|
+
inputSchema: z43.object({
|
|
12054
|
+
query: z43.string().nullable().describe(
|
|
11907
12055
|
"Optional search terms describing the tool, owner, action, or arguments needed. Empty string lists catalog tools."
|
|
11908
12056
|
).optional(),
|
|
11909
|
-
source:
|
|
12057
|
+
source: z43.string().nullable().describe(
|
|
11910
12058
|
"Optional source id to search within, such as a plugin source returned in sources."
|
|
11911
12059
|
).optional(),
|
|
11912
|
-
max_results:
|
|
12060
|
+
max_results: z43.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
|
|
11913
12061
|
}).strict(),
|
|
11914
12062
|
outputSchema: searchToolsOutputSchema,
|
|
11915
12063
|
privateTraceResult: (result) => ({
|
|
@@ -13272,6 +13420,7 @@ async function wireAgentTools(args) {
|
|
|
13272
13420
|
}),
|
|
13273
13421
|
mcpToolManager,
|
|
13274
13422
|
workspace: agentSandbox.workspace,
|
|
13423
|
+
supportsImageInput: args.supportsImageInput,
|
|
13275
13424
|
surface: args.surface,
|
|
13276
13425
|
...args.requestHandoff ? { handoff: args.requestHandoff } : {}
|
|
13277
13426
|
};
|
|
@@ -13430,7 +13579,11 @@ async function wireAgentTools(args) {
|
|
|
13430
13579
|
"mcp_tool_manager_close_failed",
|
|
13431
13580
|
{},
|
|
13432
13581
|
{
|
|
13433
|
-
|
|
13582
|
+
...getMcpProviderErrorAttributes(closeError),
|
|
13583
|
+
"exception.message": getMcpAwareTelemetryMessage(
|
|
13584
|
+
closeError,
|
|
13585
|
+
args.conversationPrivacy
|
|
13586
|
+
)
|
|
13434
13587
|
},
|
|
13435
13588
|
"Failed to close MCP tool manager"
|
|
13436
13589
|
);
|
|
@@ -13454,6 +13607,7 @@ function createResumeState(args) {
|
|
|
13454
13607
|
let latestSafeBoundaryMessages = [];
|
|
13455
13608
|
let timedOut = false;
|
|
13456
13609
|
let resumeMessages = [];
|
|
13610
|
+
let turnContexts = [];
|
|
13457
13611
|
let turnStartMessageIndex;
|
|
13458
13612
|
const currentSliceId = args.sessionRecordState.currentSliceId;
|
|
13459
13613
|
const currentDurationMs = () => Date.now() - args.startedAtMs;
|
|
@@ -13487,6 +13641,9 @@ function createResumeState(args) {
|
|
|
13487
13641
|
setBeforeMessageCount(count) {
|
|
13488
13642
|
beforeMessageCount = count;
|
|
13489
13643
|
},
|
|
13644
|
+
setTurnContexts(contexts) {
|
|
13645
|
+
turnContexts = contexts;
|
|
13646
|
+
},
|
|
13490
13647
|
/** Adopt an already committed epoch replacement as every resume baseline. */
|
|
13491
13648
|
adoptCommittedBoundary(messages) {
|
|
13492
13649
|
latestSafeBoundaryMessages = [...messages];
|
|
@@ -13514,6 +13671,7 @@ function createResumeState(args) {
|
|
|
13514
13671
|
sliceId: currentSliceId,
|
|
13515
13672
|
messages,
|
|
13516
13673
|
...trailingMessageProvenance ? { trailingMessageProvenance } : {},
|
|
13674
|
+
...turnContexts.length > 0 ? { turnContexts } : {},
|
|
13517
13675
|
...turnStartMessageIndex !== void 0 ? { turnStartMessageIndex } : {}
|
|
13518
13676
|
});
|
|
13519
13677
|
if (!persisted) {
|
|
@@ -13780,6 +13938,27 @@ function renderSummaryInput(piMessages, conversationContext) {
|
|
|
13780
13938
|
}
|
|
13781
13939
|
async function summarizeContext(args, deps) {
|
|
13782
13940
|
const source = renderSummaryInput(args.piMessages, args.conversationContext);
|
|
13941
|
+
const instructions = args.purpose === "active_turn" ? [
|
|
13942
|
+
"You are performing an ACTIVE-TURN CONTEXT CHECKPOINT COMPACTION for Junior.",
|
|
13943
|
+
"Create concise internal continuation state for the same agent run, which must continue the unfinished task immediately after this checkpoint.",
|
|
13944
|
+
"",
|
|
13945
|
+
"Include:",
|
|
13946
|
+
"- Work completed and concrete outcomes",
|
|
13947
|
+
"- Exact work currently in progress",
|
|
13948
|
+
"- The immediate next action",
|
|
13949
|
+
"- Durable constraints, user preferences, IDs, URLs, artifacts, sandbox references, auth state, and unresolved blockers",
|
|
13950
|
+
"",
|
|
13951
|
+
"Do not write a user-facing reply, announce a plan, or imply that the task is complete unless the source history proves it is complete."
|
|
13952
|
+
] : [
|
|
13953
|
+
"You are performing a CONTEXT CHECKPOINT COMPACTION for Junior.",
|
|
13954
|
+
"Create a concise continuation summary for the agent that will continue this Slack thread.",
|
|
13955
|
+
"",
|
|
13956
|
+
"Include:",
|
|
13957
|
+
"- Current outstanding asks",
|
|
13958
|
+
"- Key decisions, completed work, and outcomes",
|
|
13959
|
+
"- Durable constraints, user preferences, IDs, URLs, artifacts, canvas links, sandbox references, and auth state",
|
|
13960
|
+
"- Clear next steps and unresolved blockers"
|
|
13961
|
+
];
|
|
13783
13962
|
const result = await deps.completeText({
|
|
13784
13963
|
modelId: botConfig.fastModelId,
|
|
13785
13964
|
messageAttributeMode: "metadata",
|
|
@@ -13789,14 +13968,7 @@ async function summarizeContext(args, deps) {
|
|
|
13789
13968
|
{
|
|
13790
13969
|
role: "user",
|
|
13791
13970
|
content: [
|
|
13792
|
-
|
|
13793
|
-
"Create a concise continuation summary for the agent that will continue this Slack thread.",
|
|
13794
|
-
"",
|
|
13795
|
-
"Include:",
|
|
13796
|
-
"- Current outstanding asks",
|
|
13797
|
-
"- Key decisions, completed work, and outcomes",
|
|
13798
|
-
"- Durable constraints, user preferences, IDs, URLs, artifacts, canvas links, sandbox references, and auth state",
|
|
13799
|
-
"- Clear next steps and unresolved blockers",
|
|
13971
|
+
...instructions,
|
|
13800
13972
|
"",
|
|
13801
13973
|
"Do not invent details. Do not include raw secrets or credentials.",
|
|
13802
13974
|
"",
|
|
@@ -14022,7 +14194,8 @@ async function compactActiveContextIfNeeded(args, deps) {
|
|
|
14022
14194
|
summary = await summarizeContext(
|
|
14023
14195
|
{
|
|
14024
14196
|
...args,
|
|
14025
|
-
piMessages: args.piMessages
|
|
14197
|
+
piMessages: args.piMessages,
|
|
14198
|
+
purpose: "active_turn"
|
|
14026
14199
|
},
|
|
14027
14200
|
deps
|
|
14028
14201
|
);
|
|
@@ -14052,22 +14225,15 @@ async function compactActiveContextIfNeeded(args, deps) {
|
|
|
14052
14225
|
);
|
|
14053
14226
|
return { compacted: false, reason: "summary_failed" };
|
|
14054
14227
|
}
|
|
14055
|
-
const
|
|
14056
|
-
|
|
14057
|
-
|
|
14058
|
-
|
|
14059
|
-
|
|
14060
|
-
...runtimeMessage,
|
|
14061
|
-
content: [
|
|
14062
|
-
...runtimeMessage.content,
|
|
14063
|
-
{ type: "text", text: summaryText }
|
|
14064
|
-
]
|
|
14065
|
-
}
|
|
14066
|
-
] : [userMessage(summaryText)];
|
|
14228
|
+
const summaryMessage = userMessage(
|
|
14229
|
+
`${ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX}
|
|
14230
|
+
${summary}`
|
|
14231
|
+
);
|
|
14232
|
+
const runtimeMessages = retainRuntimeTurnContext(args.piMessages);
|
|
14067
14233
|
const retainedInstruction = pendingMessages.length === 0 ? await loadLastInstruction(args.conversationId) : void 0;
|
|
14068
14234
|
const instructionMessages = retainedInstruction ? [retainedInstruction.message] : pendingMessages.map((entry) => entry.message);
|
|
14069
14235
|
const instructionProvenance = retainedInstruction ? [retainedInstruction.provenance] : pendingMessages.map((entry) => entry.provenance);
|
|
14070
|
-
const messages = [...
|
|
14236
|
+
const messages = [...runtimeMessages, ...instructionMessages, summaryMessage];
|
|
14071
14237
|
const replacementInputTokens = estimateHistoryTokens(messages);
|
|
14072
14238
|
if (replacementInputTokens >= inputLimitTokens) {
|
|
14073
14239
|
throw new ContextInputLimitExceededError(
|
|
@@ -14100,10 +14266,11 @@ ${summary}`;
|
|
|
14100
14266
|
},
|
|
14101
14267
|
summary,
|
|
14102
14268
|
replacementHistory: replacementMessages.map((message, index) => {
|
|
14103
|
-
const
|
|
14269
|
+
const isSummary = index === replacementMessages.length - 1;
|
|
14270
|
+
const provenance = isSummary ? contextProvenance : instructionProvenance[index];
|
|
14104
14271
|
return {
|
|
14105
14272
|
item: historyItemFromPiMessage(message, provenance),
|
|
14106
|
-
...index ===
|
|
14273
|
+
...index === 0 && retainedInstruction ? { sourceEventSeq: retainedInstruction.sourceEventSeq } : {}
|
|
14107
14274
|
};
|
|
14108
14275
|
})
|
|
14109
14276
|
}
|
|
@@ -14130,12 +14297,12 @@ var AssistantMessageDeliveryError = class extends Error {
|
|
|
14130
14297
|
originalError;
|
|
14131
14298
|
};
|
|
14132
14299
|
function waitForAbortSettlement(promise, timeoutMs) {
|
|
14133
|
-
return new Promise((
|
|
14300
|
+
return new Promise((resolve2) => {
|
|
14134
14301
|
let done = false;
|
|
14135
14302
|
const timeoutId = setTimeout(() => {
|
|
14136
14303
|
if (!done) {
|
|
14137
14304
|
done = true;
|
|
14138
|
-
|
|
14305
|
+
resolve2(false);
|
|
14139
14306
|
}
|
|
14140
14307
|
}, timeoutMs);
|
|
14141
14308
|
timeoutId.unref?.();
|
|
@@ -14144,14 +14311,14 @@ function waitForAbortSettlement(promise, timeoutMs) {
|
|
|
14144
14311
|
if (!done) {
|
|
14145
14312
|
done = true;
|
|
14146
14313
|
clearTimeout(timeoutId);
|
|
14147
|
-
|
|
14314
|
+
resolve2(true);
|
|
14148
14315
|
}
|
|
14149
14316
|
},
|
|
14150
14317
|
() => {
|
|
14151
14318
|
if (!done) {
|
|
14152
14319
|
done = true;
|
|
14153
14320
|
clearTimeout(timeoutId);
|
|
14154
|
-
|
|
14321
|
+
resolve2(true);
|
|
14155
14322
|
}
|
|
14156
14323
|
}
|
|
14157
14324
|
);
|
|
@@ -14577,6 +14744,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
14577
14744
|
skillSandbox,
|
|
14578
14745
|
spanContext,
|
|
14579
14746
|
state,
|
|
14747
|
+
supportsImageInput: () => resolveGatewayModel(activeModelId).input.includes("image"),
|
|
14580
14748
|
surface,
|
|
14581
14749
|
syncLoadedSkillNamesForResume,
|
|
14582
14750
|
toolCalls,
|
|
@@ -14592,7 +14760,8 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
14592
14760
|
inputMessagesAttribute,
|
|
14593
14761
|
promptContentParts,
|
|
14594
14762
|
promptHistoryMessages,
|
|
14595
|
-
shouldPromptAgent
|
|
14763
|
+
shouldPromptAgent,
|
|
14764
|
+
turnContexts
|
|
14596
14765
|
} = await assemblePrompt({
|
|
14597
14766
|
activeMcpCatalogs: wiring.activeMcpCatalogs,
|
|
14598
14767
|
currentActor: actor,
|
|
@@ -14611,6 +14780,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
14611
14780
|
toolRuntimeContext: wiring.toolRuntimeContext,
|
|
14612
14781
|
userContentParts
|
|
14613
14782
|
});
|
|
14783
|
+
runResume.setTurnContexts(turnContexts);
|
|
14614
14784
|
const applyPendingHandoff = () => {
|
|
14615
14785
|
if (!pendingHandoff) {
|
|
14616
14786
|
return void 0;
|