@sentry/junior 0.116.1 → 0.118.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-GUAAS3XH.js → agent-hooks-J2FB7XD6.js} +8 -10
- 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/stats.d.ts +22 -0
- package/dist/api/schema.d.ts +2 -0
- package/dist/api/schema.js +7 -3
- package/dist/api/stats.d.ts +16 -0
- package/dist/api/user-pages/routes.d.ts +4 -0
- package/dist/api.js +192 -18
- package/dist/app.js +53 -46
- package/dist/{catalog-runtime-WMPC4J4U.js → catalog-runtime-UHHLU53I.js} +5 -5
- package/dist/chat/agent/prompt.d.ts +6 -2
- 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/plugins/user-pages.d.ts +15 -0
- package/dist/chat/plugins/viewer-actors.d.ts +6 -0
- package/dist/chat/prompt.d.ts +1 -2
- package/dist/chat/sandbox/paths.d.ts +2 -0
- package/dist/chat/sandbox/sandbox.d.ts +3 -1
- 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/sandbox/workspace.d.ts +1 -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/skills.d.ts +1 -2
- package/dist/chat/state/turn-session.d.ts +2 -0
- package/dist/chat/tools/index.d.ts +4 -1
- package/dist/chat/tools/query-conversation-events.d.ts +1 -1
- package/dist/chat/tools/sandbox/file-utils.d.ts +11 -0
- package/dist/chat/tools/sandbox/find-files.d.ts +2 -1
- package/dist/chat/tools/sandbox/grep.d.ts +2 -1
- package/dist/chat/tools/sandbox/view-image.d.ts +11 -0
- package/dist/chat/tools/types.d.ts +7 -0
- package/dist/{chunk-XA3VLFPK.js → chunk-3LGCVRBQ.js} +154 -20
- package/dist/{chunk-JPKGW6L6.js → chunk-3MUSSFMP.js} +78 -39
- package/dist/{chunk-7CSVG54J.js → chunk-3N3FMCKN.js} +30 -2
- package/dist/{chunk-VBMMMVVQ.js → chunk-4LPPH7Y6.js} +405 -446
- package/dist/{chunk-2YYPXQNQ.js → chunk-4SOQPUF4.js} +1 -1
- package/dist/{chunk-H35BDAUS.js → chunk-6BGUAOYP.js} +8 -8
- package/dist/{chunk-GDAXWEIJ.js → chunk-6K2QE2UI.js} +731 -424
- package/dist/{chunk-DLLW5ITL.js → chunk-7GADTCNS.js} +30 -9
- package/dist/{chunk-TC4ZEM2D.js → chunk-7SM3P4XR.js} +28 -1
- package/dist/{chunk-WKU7TY22.js → chunk-FIANEE7Z.js} +3 -1
- package/dist/{chunk-RXRQJF7Y.js → chunk-GCGJGSQL.js} +21 -0
- package/dist/{chunk-ZYHLNTC2.js → chunk-GT2ZUALJ.js} +584 -25
- package/dist/{chunk-KNCELO2M.js → chunk-HN6LFYG3.js} +1 -1
- package/dist/{chunk-N3C4XCRE.js → chunk-HWUBBHLK.js} +1 -1
- package/dist/{chunk-BFYVIOTS.js → chunk-KC5EE27Y.js} +13 -3
- package/dist/chunk-L72GDKSN.js +37 -0
- package/dist/{chunk-F3SWGSPG.js → chunk-MLZFK4KP.js} +1 -1
- package/dist/{chunk-RYFAVWP3.js → chunk-PJPKHGLG.js} +34 -15
- package/dist/{chunk-CY7NXM32.js → chunk-PWRFTDTY.js} +4 -2
- package/dist/{chunk-WLT72MRP.js → chunk-QWCF4RAC.js} +1 -1
- package/dist/{chunk-CGXLCMWI.js → chunk-S6R23MFB.js} +117 -17
- package/dist/{chunk-OY2PQQ4P.js → chunk-UXLYAVYL.js} +1 -1
- package/dist/cli/chat.js +23 -24
- package/dist/cli/check.js +6 -6
- package/dist/cli/main.js +1 -1
- package/dist/cli/plugins.js +12 -14
- package/dist/cli/{snapshot-warmup.js → snapshot-create.js} +17 -20
- package/dist/cli/upgrade.js +7 -7
- package/dist/db/schema/stats.d.ts +93 -0
- package/dist/db/schema.d.ts +94 -1
- package/dist/{db-FH4R5ZQ4.js → db-PMRHFSYL.js} +6 -6
- package/dist/handlers/oauth-html.d.ts +4 -2
- package/dist/instrumentation.js +2 -2
- package/dist/nitro.js +3 -3
- package/dist/{oauth-callback-server-C2SSJ3FQ.js → oauth-callback-server-QJUC7S4X.js} +15 -17
- package/dist/{plugins-IUJA4VBU.js → plugins-HW4VWW6G.js} +1 -1
- package/dist/{runner-NAALFIXM.js → runner-PZMV6JQW.js} +10 -12
- package/dist/{skills-UN2JXYYF.js → skills-W4JETYSV.js} +6 -6
- package/dist/stats.d.ts +18 -0
- package/dist/{validation-EEF4ROHR.js → validation-IJLNHZSU.js} +6 -6
- package/dist/version.js +1 -1
- package/migrations/0011_sour_golden_guardian.sql +8 -0
- package/migrations/meta/0011_snapshot.json +1195 -0
- package/migrations/meta/_journal.json +8 -1
- package/package.json +5 -5
- package/dist/chat/sandbox/runtime-dependency-snapshots.d.ts +0 -20
- package/dist/chunk-4ZNGQH7C.js +0 -25
- package/dist/chunk-FAEALXEH.js +0 -517
|
@@ -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-S6R23MFB.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-PJPKHGLG.js";
|
|
71
77
|
import {
|
|
72
78
|
parseSandboxEgressAuthRequiredSignal,
|
|
73
79
|
parseSandboxEgressPermissionDeniedSignal,
|
|
@@ -78,20 +84,23 @@ 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-4LPPH7Y6.js";
|
|
101
|
+
import {
|
|
102
|
+
incrementStat
|
|
103
|
+
} from "./chunk-L72GDKSN.js";
|
|
95
104
|
import {
|
|
96
105
|
addAgentTurnUsage,
|
|
97
106
|
hasAgentTurnUsage
|
|
@@ -100,30 +109,20 @@ import {
|
|
|
100
109
|
privateTraceResultAttributes
|
|
101
110
|
} from "./chunk-UIE3R5XU.js";
|
|
102
111
|
import {
|
|
112
|
+
SlackActionError,
|
|
103
113
|
createPluginHookRunner,
|
|
114
|
+
downloadPrivateSlackFile,
|
|
115
|
+
getFilePermalink,
|
|
104
116
|
getPluginSystemPromptContributions,
|
|
105
117
|
getPluginTools,
|
|
106
118
|
getPluginUserPromptContributions,
|
|
107
|
-
getSlackToolContext,
|
|
108
|
-
resolveChannelCapabilities
|
|
109
|
-
} from "./chunk-ZYHLNTC2.js";
|
|
110
|
-
import {
|
|
111
|
-
SANDBOX_DATA_ROOT,
|
|
112
|
-
SANDBOX_SKILLS_ROOT,
|
|
113
|
-
SANDBOX_WORKSPACE_ROOT,
|
|
114
|
-
getStateAdapter,
|
|
115
|
-
sandboxSkillDir,
|
|
116
|
-
sandboxSkillFile
|
|
117
|
-
} from "./chunk-7CSVG54J.js";
|
|
118
|
-
import {
|
|
119
|
-
SlackActionError,
|
|
120
|
-
downloadPrivateSlackFile,
|
|
121
|
-
getFilePermalink,
|
|
122
119
|
getSlackClient,
|
|
120
|
+
getSlackToolContext,
|
|
123
121
|
isConversationScopedChannel,
|
|
124
122
|
normalizeSlackConversationId,
|
|
123
|
+
resolveChannelCapabilities,
|
|
125
124
|
withSlackRetries
|
|
126
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-GT2ZUALJ.js";
|
|
127
126
|
import {
|
|
128
127
|
KNOWN_CONVERSATION_EVENT_TYPES,
|
|
129
128
|
contextProvenance,
|
|
@@ -132,11 +131,19 @@ import {
|
|
|
132
131
|
getConversationStore,
|
|
133
132
|
instructionActors,
|
|
134
133
|
instructionProvenanceFor
|
|
135
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-KC5EE27Y.js";
|
|
136
135
|
import {
|
|
136
|
+
SANDBOX_DATA_ROOT,
|
|
137
|
+
SANDBOX_SKILLS_ROOT,
|
|
138
|
+
SANDBOX_WORKSPACE_ROOT,
|
|
139
|
+
getStateAdapter,
|
|
140
|
+
sandboxSkillDir,
|
|
141
|
+
sandboxSkillFile,
|
|
142
|
+
sandboxSkillPathResolution,
|
|
137
143
|
sleep
|
|
138
|
-
} from "./chunk-
|
|
144
|
+
} from "./chunk-3N3FMCKN.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-PWRFTDTY.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-7GADTCNS.js";
|
|
186
193
|
import {
|
|
187
194
|
pluginCatalogRuntime
|
|
188
|
-
} from "./chunk-
|
|
195
|
+
} from "./chunk-UXLYAVYL.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-3LGCVRBQ.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-MLZFK4KP.js";
|
|
218
228
|
import {
|
|
219
229
|
parseSlackChannelId,
|
|
220
230
|
parseSlackMessageTs,
|
|
@@ -1658,13 +1668,10 @@ function formatSkillEntry(skill) {
|
|
|
1658
1668
|
lines.push(" </skill>");
|
|
1659
1669
|
return lines;
|
|
1660
1670
|
}
|
|
1661
|
-
function formatAvailableSkillsForPrompt(skills
|
|
1671
|
+
function formatAvailableSkillsForPrompt(skills) {
|
|
1662
1672
|
const autoSelectable = skills.filter(
|
|
1663
1673
|
(s) => s.disableModelInvocation !== true
|
|
1664
1674
|
);
|
|
1665
|
-
const invokedExplicitOnly = invocation ? skills.filter(
|
|
1666
|
-
(s) => s.disableModelInvocation === true && s.name === invocation.skillName
|
|
1667
|
-
) : [];
|
|
1668
1675
|
const sections = [];
|
|
1669
1676
|
if (autoSelectable.length > 0) {
|
|
1670
1677
|
const available = [
|
|
@@ -1677,17 +1684,6 @@ function formatAvailableSkillsForPrompt(skills, invocation) {
|
|
|
1677
1684
|
available.push("</available-skills>");
|
|
1678
1685
|
sections.push(available.join("\n"));
|
|
1679
1686
|
}
|
|
1680
|
-
if (invokedExplicitOnly.length > 0) {
|
|
1681
|
-
const userCallable = [
|
|
1682
|
-
"<user-callable-skills>",
|
|
1683
|
-
"The user's current message explicitly references this skill by name. Load it when relevant to the request."
|
|
1684
|
-
];
|
|
1685
|
-
for (const skill of invokedExplicitOnly) {
|
|
1686
|
-
userCallable.push(...formatSkillEntry(skill));
|
|
1687
|
-
}
|
|
1688
|
-
userCallable.push("</user-callable-skills>");
|
|
1689
|
-
sections.push(userCallable.join("\n"));
|
|
1690
|
-
}
|
|
1691
1687
|
return sections.length > 0 ? sections.join("\n") : null;
|
|
1692
1688
|
}
|
|
1693
1689
|
function formatActiveMcpCatalogsForPrompt(catalogs) {
|
|
@@ -1800,7 +1796,8 @@ var TOOL_CALL_STYLE_RULES = [
|
|
|
1800
1796
|
"- Keep tool-call explanations separate from final answers; final answers should report results, evidence, or blockers."
|
|
1801
1797
|
];
|
|
1802
1798
|
var SKILL_POLICY_RULES = [
|
|
1803
|
-
"-
|
|
1799
|
+
"- A `<skill>` block in the current user turn is already loaded. Follow its instructions directly and do not call `loadSkill` for that skill.",
|
|
1800
|
+
"- Otherwise, only load skills listed in `<available-skills>`. Never guess or invent a skill name.",
|
|
1804
1801
|
"- Load one skill at a time. After `loadSkill`, follow the instructions returned by that tool result."
|
|
1805
1802
|
];
|
|
1806
1803
|
var EXECUTION_CONTRACT_RULES = [
|
|
@@ -1985,14 +1982,6 @@ function buildContextSection(params) {
|
|
|
1985
1982
|
])
|
|
1986
1983
|
);
|
|
1987
1984
|
}
|
|
1988
|
-
if (params.invocation) {
|
|
1989
|
-
blocks.push(
|
|
1990
|
-
renderTag("explicit-skill-trigger", [
|
|
1991
|
-
"Treat this skill as selected. Load it unless the tool says it is unavailable.",
|
|
1992
|
-
`/${escapeXml(params.invocation.skillName)}`
|
|
1993
|
-
])
|
|
1994
|
-
);
|
|
1995
|
-
}
|
|
1996
1985
|
const body = blocks.map((block) => block.join("\n")).join("\n\n");
|
|
1997
1986
|
if (!body) {
|
|
1998
1987
|
return null;
|
|
@@ -2002,8 +1991,7 @@ function buildContextSection(params) {
|
|
|
2002
1991
|
function buildCapabilitiesSection(params) {
|
|
2003
1992
|
const blocks = [];
|
|
2004
1993
|
const availableSkills = formatAvailableSkillsForPrompt(
|
|
2005
|
-
params.availableSkills
|
|
2006
|
-
params.invocation
|
|
1994
|
+
params.availableSkills
|
|
2007
1995
|
);
|
|
2008
1996
|
if (availableSkills) {
|
|
2009
1997
|
blocks.push(availableSkills);
|
|
@@ -2084,7 +2072,6 @@ function buildTurnContextPrompt(params) {
|
|
|
2084
2072
|
includeSessionContext ? buildCapabilitiesSection({
|
|
2085
2073
|
availableSkills: params.availableSkills,
|
|
2086
2074
|
activeMcpCatalogs: params.activeMcpCatalogs ?? [],
|
|
2087
|
-
invocation: params.invocation,
|
|
2088
2075
|
toolGuidance: params.toolGuidance ?? []
|
|
2089
2076
|
}) : null,
|
|
2090
2077
|
pluginPromptContributions,
|
|
@@ -2092,8 +2079,7 @@ function buildTurnContextPrompt(params) {
|
|
|
2092
2079
|
actor: params.actor,
|
|
2093
2080
|
artifactState: params.artifactState,
|
|
2094
2081
|
configuration: params.configuration,
|
|
2095
|
-
dispatch: params.dispatch
|
|
2096
|
-
invocation: params.invocation
|
|
2082
|
+
dispatch: params.dispatch
|
|
2097
2083
|
}) : null,
|
|
2098
2084
|
includeSessionContext ? buildRuntimeSection(params.runtime ?? {}) : null
|
|
2099
2085
|
].filter((section) => Boolean(section));
|
|
@@ -2136,6 +2122,17 @@ function buildUserTurnText(userInput, conversationContext, actor) {
|
|
|
2136
2122
|
currentInstruction
|
|
2137
2123
|
].join("\n");
|
|
2138
2124
|
}
|
|
2125
|
+
function renderExplicitSkillInstructions(skill) {
|
|
2126
|
+
return [
|
|
2127
|
+
"<skill>",
|
|
2128
|
+
`<name>${escapeXml(skill.name)}</name>`,
|
|
2129
|
+
`<path>${escapeXml(sandboxSkillFile(skill.name))}</path>`,
|
|
2130
|
+
`<working_directory>${escapeXml(sandboxSkillDir(skill.name))}</working_directory>`,
|
|
2131
|
+
`<path_resolution>${escapeXml(sandboxSkillPathResolution(skill.name))}</path_resolution>`,
|
|
2132
|
+
skill.body,
|
|
2133
|
+
"</skill>"
|
|
2134
|
+
].join("\n");
|
|
2135
|
+
}
|
|
2139
2136
|
function encodeNonImageAttachmentForPrompt(attachment) {
|
|
2140
2137
|
const base64 = attachment.data.toString("base64");
|
|
2141
2138
|
const wasTruncated = base64.length > MAX_INLINE_ATTACHMENT_BASE64_CHARS;
|
|
@@ -2302,21 +2299,62 @@ function withoutTrailingUncheckpointedUserPrompt(messages, userContentParts) {
|
|
|
2302
2299
|
function userPromptContentMatches(storedContent, currentContent) {
|
|
2303
2300
|
return isDeepStrictEqual(storedContent, currentContent);
|
|
2304
2301
|
}
|
|
2302
|
+
function isUserContentPart(value) {
|
|
2303
|
+
if (typeof value !== "object" || value === null || !("type" in value)) {
|
|
2304
|
+
return false;
|
|
2305
|
+
}
|
|
2306
|
+
if (value.type === "text") {
|
|
2307
|
+
return "text" in value && typeof value.text === "string";
|
|
2308
|
+
}
|
|
2309
|
+
return value.type === "image" && "data" in value && typeof value.data === "string" && "mimeType" in value && typeof value.mimeType === "string";
|
|
2310
|
+
}
|
|
2311
|
+
function checkpointedPromptContent(args) {
|
|
2312
|
+
if (!args.messages || args.turnStartMessageIndex === void 0 || args.turnStartMessageIndex !== args.messages.length - 1) {
|
|
2313
|
+
return void 0;
|
|
2314
|
+
}
|
|
2315
|
+
const message = args.messages[args.turnStartMessageIndex];
|
|
2316
|
+
if (message?.role !== "user" || !Array.isArray(message.content)) {
|
|
2317
|
+
return void 0;
|
|
2318
|
+
}
|
|
2319
|
+
const durableMessage = stripRuntimeTurnContext([message])[0];
|
|
2320
|
+
if (!userPromptContentMatches(durableMessage?.content, args.userContentParts)) {
|
|
2321
|
+
return void 0;
|
|
2322
|
+
}
|
|
2323
|
+
const content = message.content;
|
|
2324
|
+
if (!content.every(isUserContentPart)) {
|
|
2325
|
+
return void 0;
|
|
2326
|
+
}
|
|
2327
|
+
return content;
|
|
2328
|
+
}
|
|
2305
2329
|
async function assemblePrompt(args) {
|
|
2306
2330
|
const source = args.routing.source;
|
|
2307
2331
|
const hasPromptCheckpoint = args.resumedFromSessionRecord && args.existingTurnStartMessageIndex !== void 0;
|
|
2308
2332
|
const shouldPromptAgent = !args.resumedFromSessionRecord || !hasPromptCheckpoint;
|
|
2333
|
+
const requestContentParts = [
|
|
2334
|
+
...args.explicitSkill ? [
|
|
2335
|
+
{
|
|
2336
|
+
type: "text",
|
|
2337
|
+
text: renderExplicitSkillInstructions(args.explicitSkill)
|
|
2338
|
+
}
|
|
2339
|
+
] : [],
|
|
2340
|
+
...args.userContentParts
|
|
2341
|
+
];
|
|
2309
2342
|
const promptHistoryMessages = shouldPromptAgent ? withoutTrailingUncheckpointedUserPrompt(
|
|
2310
2343
|
args.priorPiMessages,
|
|
2311
|
-
|
|
2344
|
+
requestContentParts
|
|
2312
2345
|
) : args.existingSessionPiMessages;
|
|
2313
|
-
const
|
|
2346
|
+
const replayedPromptContent = shouldPromptAgent && !args.resumedFromSessionRecord ? checkpointedPromptContent({
|
|
2347
|
+
messages: args.existingSessionPiMessages,
|
|
2348
|
+
turnStartMessageIndex: args.existingTurnStartMessageIndex,
|
|
2349
|
+
userContentParts: requestContentParts
|
|
2350
|
+
}) : void 0;
|
|
2351
|
+
const needsBootstrapContextForPrompt = shouldPromptAgent && !replayedPromptContent && !hasRuntimeTurnContext(promptHistoryMessages);
|
|
2314
2352
|
const systemPromptContributions = await getPluginSystemPromptContributions(source);
|
|
2315
2353
|
const pluginSystemPrompt = buildPluginSystemPromptContributions(
|
|
2316
2354
|
systemPromptContributions
|
|
2317
2355
|
);
|
|
2318
2356
|
const baseInstructions = [buildSystemPrompt({ source }), pluginSystemPrompt].filter((section) => Boolean(section)).join("\n\n");
|
|
2319
|
-
const pluginUserPromptContributions = !shouldPromptAgent ? [] : await getPluginUserPromptContributions({
|
|
2357
|
+
const pluginUserPromptContributions = !shouldPromptAgent || replayedPromptContent ? [] : await getPluginUserPromptContributions({
|
|
2320
2358
|
context: args.toolRuntimeContext
|
|
2321
2359
|
});
|
|
2322
2360
|
const turnContextPrompt = needsBootstrapContextForPrompt || pluginUserPromptContributions.length > 0 ? buildTurnContextPrompt({
|
|
@@ -2334,13 +2372,15 @@ async function assemblePrompt(args) {
|
|
|
2334
2372
|
destination: args.routing.destination,
|
|
2335
2373
|
source
|
|
2336
2374
|
} : void 0,
|
|
2337
|
-
invocation: args.invocation,
|
|
2338
2375
|
actor: isUserActor(args.currentActor) ? args.currentActor : void 0,
|
|
2339
2376
|
artifactState: args.artifactState,
|
|
2340
2377
|
configuration: args.configurationValues
|
|
2341
2378
|
}) : null;
|
|
2342
2379
|
const turnContextParts = turnContextPrompt ? [{ type: "text", text: turnContextPrompt }] : [];
|
|
2343
|
-
const promptContentParts = [
|
|
2380
|
+
const promptContentParts = replayedPromptContent ?? [
|
|
2381
|
+
...turnContextParts,
|
|
2382
|
+
...requestContentParts
|
|
2383
|
+
];
|
|
2344
2384
|
const inputMessages = [
|
|
2345
2385
|
{
|
|
2346
2386
|
role: "system",
|
|
@@ -2371,7 +2411,10 @@ async function assemblePrompt(args) {
|
|
|
2371
2411
|
inputMessagesAttribute,
|
|
2372
2412
|
promptContentParts,
|
|
2373
2413
|
promptHistoryMessages,
|
|
2374
|
-
shouldPromptAgent
|
|
2414
|
+
shouldPromptAgent,
|
|
2415
|
+
turnContexts: pluginUserPromptContributions.flatMap(
|
|
2416
|
+
(contribution) => contribution.context ? [contribution.context] : []
|
|
2417
|
+
)
|
|
2375
2418
|
};
|
|
2376
2419
|
}
|
|
2377
2420
|
|
|
@@ -3028,6 +3071,7 @@ import { Sandbox } from "@vercel/sandbox";
|
|
|
3028
3071
|
// src/chat/sandbox/skill-sync.ts
|
|
3029
3072
|
import fs3 from "fs/promises";
|
|
3030
3073
|
import path3 from "path";
|
|
3074
|
+
var DIRECTORY_CREATE_CONCURRENCY = 8;
|
|
3031
3075
|
function toPosixRelative(base, absolute) {
|
|
3032
3076
|
return path3.relative(base, absolute).split(path3.sep).join("/");
|
|
3033
3077
|
}
|
|
@@ -3102,6 +3146,16 @@ function collectDirectories(filesToWrite, workspaceRoot) {
|
|
|
3102
3146
|
(directory) => directory === workspaceRoot || directory.startsWith(`${workspaceRoot}/`)
|
|
3103
3147
|
).sort((a, b) => a.length - b.length);
|
|
3104
3148
|
}
|
|
3149
|
+
function groupDirectoriesByDepth(directories) {
|
|
3150
|
+
const groups = /* @__PURE__ */ new Map();
|
|
3151
|
+
for (const directory of directories) {
|
|
3152
|
+
const depth = directory.split("/").filter(Boolean).length;
|
|
3153
|
+
const group = groups.get(depth) ?? [];
|
|
3154
|
+
group.push(directory);
|
|
3155
|
+
groups.set(depth, group);
|
|
3156
|
+
}
|
|
3157
|
+
return [...groups.entries()].sort(([left], [right]) => left - right).map(([, group]) => group);
|
|
3158
|
+
}
|
|
3105
3159
|
function resolveHostSkillPath(availableSkills, sandboxPath) {
|
|
3106
3160
|
const normalizedPath = path3.posix.normalize(sandboxPath.trim());
|
|
3107
3161
|
for (const skill of availableSkills) {
|
|
@@ -3171,13 +3225,21 @@ async function syncSkillsToSandbox(params) {
|
|
|
3171
3225
|
},
|
|
3172
3226
|
async () => {
|
|
3173
3227
|
try {
|
|
3174
|
-
for (const
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3228
|
+
for (const directoriesAtDepth of groupDirectoriesByDepth(
|
|
3229
|
+
directories
|
|
3230
|
+
)) {
|
|
3231
|
+
for (let offset = 0; offset < directoriesAtDepth.length; offset += DIRECTORY_CREATE_CONCURRENCY) {
|
|
3232
|
+
await Promise.all(
|
|
3233
|
+
directoriesAtDepth.slice(offset, offset + DIRECTORY_CREATE_CONCURRENCY).map(async (directory) => {
|
|
3234
|
+
try {
|
|
3235
|
+
await params.sandbox.mkDir(directory);
|
|
3236
|
+
} catch (error) {
|
|
3237
|
+
if (!isAlreadyExistsError(error)) {
|
|
3238
|
+
throw error;
|
|
3239
|
+
}
|
|
3240
|
+
}
|
|
3241
|
+
})
|
|
3242
|
+
);
|
|
3181
3243
|
}
|
|
3182
3244
|
}
|
|
3183
3245
|
await params.sandbox.writeFiles(filesToWrite);
|
|
@@ -3240,7 +3302,7 @@ function createSandboxRuntime(options) {
|
|
|
3240
3302
|
let closed = false;
|
|
3241
3303
|
const timeoutMs = options.timeoutMs ?? 1e3 * 60 * 30;
|
|
3242
3304
|
const traceContext = options.traceContext ?? {};
|
|
3243
|
-
const dependencyProfileHash =
|
|
3305
|
+
const dependencyProfileHash = hash(SANDBOX_RUNTIME);
|
|
3244
3306
|
const resolveCommandEnv = options.commandEnv ?? (async () => ({}));
|
|
3245
3307
|
const withSandboxSpan = (name, op, attributes, callback) => withSpan(name, op, traceContext, callback, attributes);
|
|
3246
3308
|
const invalidateSession = (sessionId) => {
|
|
@@ -3402,13 +3464,13 @@ function createSandboxRuntime(options) {
|
|
|
3402
3464
|
sandboxName
|
|
3403
3465
|
);
|
|
3404
3466
|
} catch (error) {
|
|
3405
|
-
if (!
|
|
3467
|
+
if (!isMissingError(error)) {
|
|
3406
3468
|
throw error;
|
|
3407
3469
|
}
|
|
3408
3470
|
setSpanAttributes({
|
|
3409
3471
|
"app.sandbox.snapshot.rebuild_after_missing": true
|
|
3410
3472
|
});
|
|
3411
|
-
const rebuiltSnapshot = await
|
|
3473
|
+
const rebuiltSnapshot = await resolve({
|
|
3412
3474
|
runtime,
|
|
3413
3475
|
timeoutMs,
|
|
3414
3476
|
forceRebuild: true,
|
|
@@ -3439,7 +3501,7 @@ function createSandboxRuntime(options) {
|
|
|
3439
3501
|
"app.sandbox.runtime": runtime
|
|
3440
3502
|
},
|
|
3441
3503
|
async () => {
|
|
3442
|
-
const snapshot = await
|
|
3504
|
+
const snapshot = await resolve({
|
|
3443
3505
|
runtime,
|
|
3444
3506
|
timeoutMs
|
|
3445
3507
|
});
|
|
@@ -3774,6 +3836,7 @@ var RIPGREP_EXCLUDED_GLOBS = [
|
|
|
3774
3836
|
"!**/.git/**",
|
|
3775
3837
|
"!**/node_modules/**"
|
|
3776
3838
|
];
|
|
3839
|
+
var DEFAULT_SEARCH_COMMAND_TIMEOUT_MS = 3e4;
|
|
3777
3840
|
var SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
3778
3841
|
function positiveInteger(value) {
|
|
3779
3842
|
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
@@ -4361,7 +4424,7 @@ function createEditFileTool() {
|
|
|
4361
4424
|
// src/chat/tools/sandbox/find-files.ts
|
|
4362
4425
|
import path5 from "path";
|
|
4363
4426
|
import { z as z5 } from "zod";
|
|
4364
|
-
var DEFAULT_FIND_LIMIT =
|
|
4427
|
+
var DEFAULT_FIND_LIMIT = 100;
|
|
4365
4428
|
async function findFiles(params) {
|
|
4366
4429
|
if (!params.pattern.trim()) {
|
|
4367
4430
|
throw new Error("pattern is required");
|
|
@@ -4372,6 +4435,7 @@ async function findFiles(params) {
|
|
|
4372
4435
|
return await findFilesWithRipgrep({
|
|
4373
4436
|
fs: params.fs,
|
|
4374
4437
|
limit,
|
|
4438
|
+
onTelemetry: params.onTelemetry,
|
|
4375
4439
|
path: params.path,
|
|
4376
4440
|
pattern: params.pattern,
|
|
4377
4441
|
root,
|
|
@@ -4440,25 +4504,45 @@ async function findFilesWithRipgrep(params) {
|
|
|
4440
4504
|
throw error;
|
|
4441
4505
|
}
|
|
4442
4506
|
const location = getRipgrepSearchLocation(params.root, rootIsDirectory);
|
|
4443
|
-
const
|
|
4507
|
+
const ripgrepArgs = [
|
|
4444
4508
|
"--files",
|
|
4445
4509
|
"--null",
|
|
4446
4510
|
"--hidden",
|
|
4447
|
-
"--sort=path",
|
|
4448
4511
|
"--glob",
|
|
4449
4512
|
params.pattern
|
|
4450
4513
|
];
|
|
4451
4514
|
for (const excludedGlob of RIPGREP_EXCLUDED_GLOBS) {
|
|
4452
|
-
|
|
4515
|
+
ripgrepArgs.push("--glob", excludedGlob);
|
|
4453
4516
|
}
|
|
4454
|
-
|
|
4517
|
+
ripgrepArgs.push("--", location.target);
|
|
4455
4518
|
const result = await params.runCommand({
|
|
4456
|
-
cmd: "
|
|
4457
|
-
args
|
|
4458
|
-
|
|
4519
|
+
cmd: "bash",
|
|
4520
|
+
args: [
|
|
4521
|
+
"-c",
|
|
4522
|
+
[
|
|
4523
|
+
`rg "$@" | head -z -n ${params.limit + 1}`,
|
|
4524
|
+
'statuses=("${PIPESTATUS[@]}")',
|
|
4525
|
+
"if (( statuses[1] != 0 )); then",
|
|
4526
|
+
' exit "${statuses[1]}"',
|
|
4527
|
+
"fi",
|
|
4528
|
+
"if (( statuses[0] == 0 || statuses[0] == 1 || statuses[0] == 141 )); then",
|
|
4529
|
+
" exit 0",
|
|
4530
|
+
"fi",
|
|
4531
|
+
'exit "${statuses[0]}"'
|
|
4532
|
+
].join("\n"),
|
|
4533
|
+
"find-files",
|
|
4534
|
+
...ripgrepArgs
|
|
4535
|
+
],
|
|
4536
|
+
cwd: location.cwd,
|
|
4537
|
+
timeoutMs: DEFAULT_SEARCH_COMMAND_TIMEOUT_MS
|
|
4459
4538
|
});
|
|
4460
|
-
if (result.exitCode !== 0
|
|
4539
|
+
if (result.exitCode !== 0) {
|
|
4461
4540
|
const detail = result.stderr.trim() || result.stdout.trim() || "command failed";
|
|
4541
|
+
if (/error parsing glob|invalid glob/i.test(detail)) {
|
|
4542
|
+
throw new ToolInputError(`Invalid glob pattern: ${params.pattern}`, {
|
|
4543
|
+
cause: new Error(detail)
|
|
4544
|
+
});
|
|
4545
|
+
}
|
|
4462
4546
|
throw new Error(`ripgrep file search failed: ${detail}`);
|
|
4463
4547
|
}
|
|
4464
4548
|
const allPaths = result.stdout.split("\0").filter(Boolean).map((filePath) => {
|
|
@@ -4482,7 +4566,7 @@ async function findFilesWithRipgrep(params) {
|
|
|
4482
4566
|
const text = notices.length > 0 ? `${bounded.content}
|
|
4483
4567
|
|
|
4484
4568
|
[${notices.join(" ")}]` : bounded.content;
|
|
4485
|
-
|
|
4569
|
+
const response = makeStructuredToolResult(
|
|
4486
4570
|
{
|
|
4487
4571
|
ok: true,
|
|
4488
4572
|
status: "success",
|
|
@@ -4499,6 +4583,19 @@ async function findFilesWithRipgrep(params) {
|
|
|
4499
4583
|
},
|
|
4500
4584
|
{ content: [{ type: "text", text }] }
|
|
4501
4585
|
);
|
|
4586
|
+
params.onTelemetry?.({
|
|
4587
|
+
emittedLineCount: relativePaths.length,
|
|
4588
|
+
limit: params.limit,
|
|
4589
|
+
limitReached,
|
|
4590
|
+
parsedRecordCount: allPaths.length,
|
|
4591
|
+
rawOutputBytes: Buffer.byteLength(result.stdout, "utf8"),
|
|
4592
|
+
resultBytes: response.content.reduce(
|
|
4593
|
+
(total, item) => total + (item.type === "text" ? Buffer.byteLength(item.text, "utf8") : 0),
|
|
4594
|
+
0
|
|
4595
|
+
),
|
|
4596
|
+
resultCount: relativePaths.length
|
|
4597
|
+
});
|
|
4598
|
+
return response;
|
|
4502
4599
|
}
|
|
4503
4600
|
function createFindFilesTool() {
|
|
4504
4601
|
return zodTool({
|
|
@@ -4511,7 +4608,7 @@ function createFindFilesTool() {
|
|
|
4511
4608
|
path: z5.string().min(1).describe(
|
|
4512
4609
|
"Directory or file path in the sandbox workspace. Defaults to the workspace root."
|
|
4513
4610
|
).optional(),
|
|
4514
|
-
limit: z5.coerce.number().int().min(1).describe("Maximum number of file paths to return. Defaults to
|
|
4611
|
+
limit: z5.coerce.number().int().min(1).describe("Maximum number of file paths to return. Defaults to 100.").optional()
|
|
4515
4612
|
}),
|
|
4516
4613
|
outputSchema: juniorToolResultSchema,
|
|
4517
4614
|
execute: async () => {
|
|
@@ -4564,6 +4661,7 @@ async function grepFiles(params) {
|
|
|
4564
4661
|
ignoreCase: params.ignoreCase,
|
|
4565
4662
|
limit,
|
|
4566
4663
|
literal: params.literal,
|
|
4664
|
+
onTelemetry: params.onTelemetry,
|
|
4567
4665
|
path: params.path,
|
|
4568
4666
|
pattern: params.pattern,
|
|
4569
4667
|
root,
|
|
@@ -4711,7 +4809,13 @@ async function grepFilesWithRipgrep(params) {
|
|
|
4711
4809
|
throw error;
|
|
4712
4810
|
}
|
|
4713
4811
|
const location = getRipgrepSearchLocation(params.root, rootIsDirectory);
|
|
4714
|
-
const args = [
|
|
4812
|
+
const args = [
|
|
4813
|
+
"--json",
|
|
4814
|
+
"--line-number",
|
|
4815
|
+
"--hidden",
|
|
4816
|
+
"--max-count",
|
|
4817
|
+
String(params.limit + 1)
|
|
4818
|
+
];
|
|
4715
4819
|
if (params.ignoreCase) {
|
|
4716
4820
|
args.push("--ignore-case");
|
|
4717
4821
|
}
|
|
@@ -4731,7 +4835,8 @@ async function grepFilesWithRipgrep(params) {
|
|
|
4731
4835
|
const result = await params.runCommand({
|
|
4732
4836
|
cmd: "rg",
|
|
4733
4837
|
args,
|
|
4734
|
-
cwd: location.cwd
|
|
4838
|
+
cwd: location.cwd,
|
|
4839
|
+
timeoutMs: DEFAULT_SEARCH_COMMAND_TIMEOUT_MS
|
|
4735
4840
|
});
|
|
4736
4841
|
if (result.exitCode !== 0 && result.exitCode !== 1) {
|
|
4737
4842
|
const detail = result.stderr.trim() || result.stdout.trim() || "command failed";
|
|
@@ -4745,6 +4850,7 @@ async function grepFilesWithRipgrep(params) {
|
|
|
4745
4850
|
const recordsByPath = /* @__PURE__ */ new Map();
|
|
4746
4851
|
const pathOrder = [];
|
|
4747
4852
|
let totalMatches = 0;
|
|
4853
|
+
let parsedRecordCount = 0;
|
|
4748
4854
|
for (const rawLine of normalizeToLf(result.stdout).split("\n")) {
|
|
4749
4855
|
if (!rawLine) {
|
|
4750
4856
|
continue;
|
|
@@ -4755,6 +4861,7 @@ async function grepFilesWithRipgrep(params) {
|
|
|
4755
4861
|
} catch (error) {
|
|
4756
4862
|
throw new Error("ripgrep returned invalid JSON output", { cause: error });
|
|
4757
4863
|
}
|
|
4864
|
+
parsedRecordCount += 1;
|
|
4758
4865
|
if (record.type !== "match" && record.type !== "context") {
|
|
4759
4866
|
continue;
|
|
4760
4867
|
}
|
|
@@ -4836,7 +4943,7 @@ async function grepFilesWithRipgrep(params) {
|
|
|
4836
4943
|
if (bounded.truncated) {
|
|
4837
4944
|
notices.push(`${MAX_TEXT_CHARS} character output limit reached.`);
|
|
4838
4945
|
}
|
|
4839
|
-
|
|
4946
|
+
const response = makeStructuredToolResult({
|
|
4840
4947
|
ok: true,
|
|
4841
4948
|
status: "success",
|
|
4842
4949
|
target: params.path ?? ".",
|
|
@@ -4855,6 +4962,19 @@ async function grepFilesWithRipgrep(params) {
|
|
|
4855
4962
|
...matchLimitReached ? { match_limit_reached: params.limit } : {},
|
|
4856
4963
|
...lineTruncated ? { line_truncated: true } : {}
|
|
4857
4964
|
});
|
|
4965
|
+
params.onTelemetry?.({
|
|
4966
|
+
emittedLineCount: output.length,
|
|
4967
|
+
limit: params.limit,
|
|
4968
|
+
limitReached: matchLimitReached,
|
|
4969
|
+
parsedRecordCount,
|
|
4970
|
+
rawOutputBytes: Buffer.byteLength(result.stdout, "utf8"),
|
|
4971
|
+
resultBytes: response.content.reduce(
|
|
4972
|
+
(total, item) => total + (item.type === "text" ? Buffer.byteLength(item.text, "utf8") : 0),
|
|
4973
|
+
0
|
|
4974
|
+
),
|
|
4975
|
+
resultCount: matchCount
|
|
4976
|
+
});
|
|
4977
|
+
return response;
|
|
4858
4978
|
}
|
|
4859
4979
|
function createGrepTool() {
|
|
4860
4980
|
return zodTool({
|
|
@@ -5194,11 +5314,12 @@ function createSandbox(options) {
|
|
|
5194
5314
|
onSandboxPrepare: options.prepare,
|
|
5195
5315
|
onSandboxRefChanged: options.onSandboxRefChanged
|
|
5196
5316
|
});
|
|
5197
|
-
const createToolCallContext = (signal) => {
|
|
5317
|
+
const createToolCallContext = (signal, setToolCallSpanAttributes) => {
|
|
5198
5318
|
let fileSystemPromise;
|
|
5199
5319
|
let commandRunnerPromise;
|
|
5200
5320
|
return {
|
|
5201
5321
|
signal,
|
|
5322
|
+
setToolCallSpanAttributes,
|
|
5202
5323
|
fileSystem() {
|
|
5203
5324
|
signal?.throwIfAborted();
|
|
5204
5325
|
return fileSystemPromise ??= runtime.tools().then(({ fs: fs5 }) => {
|
|
@@ -5219,10 +5340,31 @@ function createSandbox(options) {
|
|
|
5219
5340
|
};
|
|
5220
5341
|
};
|
|
5221
5342
|
const withSandboxSpan = (name, op, attributes, callback) => withSpan(name, op, traceContext, callback, attributes);
|
|
5222
|
-
const withSandboxToolSpan = (name, op, attributes, callback) => withSandboxSpan(name, op, attributes, async () => {
|
|
5343
|
+
const withSandboxToolSpan = (name, op, attributes, callback) => withSandboxSpan(name, op, attributes, async (setSpanAttributes2) => {
|
|
5223
5344
|
await runtime.refreshNetworkPolicy(getTracePropagationHeaders());
|
|
5224
|
-
return await callback();
|
|
5345
|
+
return await callback(setSpanAttributes2);
|
|
5225
5346
|
});
|
|
5347
|
+
const searchTelemetryAttributes = (telemetry) => ({
|
|
5348
|
+
"app.sandbox.search.raw_output_bytes": telemetry.rawOutputBytes,
|
|
5349
|
+
"app.sandbox.search.parsed_records": telemetry.parsedRecordCount,
|
|
5350
|
+
"app.sandbox.search.result_count": telemetry.resultCount,
|
|
5351
|
+
"app.sandbox.search.emitted_lines": telemetry.emittedLineCount,
|
|
5352
|
+
"app.sandbox.search.result_bytes": telemetry.resultBytes,
|
|
5353
|
+
"app.sandbox.search.limit": telemetry.limit,
|
|
5354
|
+
"app.sandbox.search.limit_reached": telemetry.limitReached
|
|
5355
|
+
});
|
|
5356
|
+
const recordSearchTelemetry = (telemetry, setSearchSpanAttributes, setToolCallSpanAttributes) => {
|
|
5357
|
+
const attributes = searchTelemetryAttributes(telemetry);
|
|
5358
|
+
for (const setAttributes of [
|
|
5359
|
+
setSearchSpanAttributes,
|
|
5360
|
+
setToolCallSpanAttributes
|
|
5361
|
+
]) {
|
|
5362
|
+
try {
|
|
5363
|
+
setAttributes?.(attributes);
|
|
5364
|
+
} catch {
|
|
5365
|
+
}
|
|
5366
|
+
}
|
|
5367
|
+
};
|
|
5226
5368
|
const logSandboxBootRequest = (trigger, details = {}) => {
|
|
5227
5369
|
if (runtime.sandboxRef()) {
|
|
5228
5370
|
return;
|
|
@@ -5467,10 +5609,15 @@ function createSandbox(options) {
|
|
|
5467
5609
|
{
|
|
5468
5610
|
"app.sandbox.pattern.length": pattern.length
|
|
5469
5611
|
},
|
|
5470
|
-
async () => {
|
|
5612
|
+
async (setSearchSpanAttributes) => {
|
|
5471
5613
|
const response = await grepFiles({
|
|
5472
5614
|
fs: fileSystem,
|
|
5473
5615
|
runCommand: await context.commandRunner(),
|
|
5616
|
+
onTelemetry: (telemetry) => recordSearchTelemetry(
|
|
5617
|
+
telemetry,
|
|
5618
|
+
setSearchSpanAttributes,
|
|
5619
|
+
context.setToolCallSpanAttributes
|
|
5620
|
+
),
|
|
5474
5621
|
pattern,
|
|
5475
5622
|
...typeof rawInput.path === "string" ? { path: rawInput.path } : {},
|
|
5476
5623
|
...typeof rawInput.glob === "string" ? { glob: rawInput.glob } : {},
|
|
@@ -5499,10 +5646,15 @@ function createSandbox(options) {
|
|
|
5499
5646
|
{
|
|
5500
5647
|
"app.sandbox.pattern.length": pattern.length
|
|
5501
5648
|
},
|
|
5502
|
-
async () => {
|
|
5649
|
+
async (setSearchSpanAttributes) => {
|
|
5503
5650
|
const response = await findFiles({
|
|
5504
5651
|
fs: fileSystem,
|
|
5505
5652
|
runCommand: await context.commandRunner(),
|
|
5653
|
+
onTelemetry: (telemetry) => recordSearchTelemetry(
|
|
5654
|
+
telemetry,
|
|
5655
|
+
setSearchSpanAttributes,
|
|
5656
|
+
context.setToolCallSpanAttributes
|
|
5657
|
+
),
|
|
5506
5658
|
pattern,
|
|
5507
5659
|
...typeof rawInput.path === "string" ? { path: rawInput.path } : {},
|
|
5508
5660
|
...limit ? { limit } : {}
|
|
@@ -5535,7 +5687,10 @@ function createSandbox(options) {
|
|
|
5535
5687
|
};
|
|
5536
5688
|
const execute = async (params) => {
|
|
5537
5689
|
const rawInput = params.input ?? {};
|
|
5538
|
-
const context = createToolCallContext(
|
|
5690
|
+
const context = createToolCallContext(
|
|
5691
|
+
params.signal,
|
|
5692
|
+
params.setToolCallSpanAttributes
|
|
5693
|
+
);
|
|
5539
5694
|
const bashCommand2 = params.toolName === "bash" ? String(rawInput.command ?? "").trim() : void 0;
|
|
5540
5695
|
if (params.toolName === "bash") {
|
|
5541
5696
|
if (!bashCommand2) {
|
|
@@ -5846,6 +6001,7 @@ function createAgentSandbox(options) {
|
|
|
5846
6001
|
}
|
|
5847
6002
|
|
|
5848
6003
|
// src/chat/mcp/client.ts
|
|
6004
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
5849
6005
|
import { Client } from "@modelcontextprotocol/sdk/client";
|
|
5850
6006
|
import {
|
|
5851
6007
|
UnauthorizedError
|
|
@@ -5887,18 +6043,25 @@ var McpAuthorizationRequiredError = class extends Error {
|
|
|
5887
6043
|
this.provider = provider;
|
|
5888
6044
|
}
|
|
5889
6045
|
};
|
|
6046
|
+
function isMissingSessionError(error) {
|
|
6047
|
+
return error instanceof StreamableHTTPError && (error.code === 404 || /Session not found/i.test(error.message));
|
|
6048
|
+
}
|
|
5890
6049
|
var PluginMcpClient = class {
|
|
5891
6050
|
constructor(plugin, options = {}) {
|
|
5892
6051
|
this.plugin = plugin;
|
|
5893
6052
|
this.options = options;
|
|
6053
|
+
const url = plugin.manifest.mcp?.url;
|
|
6054
|
+
this.resourceHost = url ? new URL(url).hostname : void 0;
|
|
5894
6055
|
}
|
|
5895
6056
|
plugin;
|
|
5896
6057
|
options;
|
|
5897
6058
|
client;
|
|
5898
6059
|
clientPromise;
|
|
5899
6060
|
lastAttemptedTransportSessionId;
|
|
6061
|
+
providerStatusStore = new AsyncLocalStorage();
|
|
5900
6062
|
transport;
|
|
5901
6063
|
listedTools;
|
|
6064
|
+
resourceHost;
|
|
5902
6065
|
async listTools() {
|
|
5903
6066
|
if (this.listedTools) {
|
|
5904
6067
|
return [...this.listedTools];
|
|
@@ -5910,7 +6073,8 @@ var PluginMcpClient = class {
|
|
|
5910
6073
|
let cursor;
|
|
5911
6074
|
do {
|
|
5912
6075
|
const result = await this.wrapAuth(
|
|
5913
|
-
client.listTools(cursor ? { cursor } : void 0)
|
|
6076
|
+
() => client.listTools(cursor ? { cursor } : void 0),
|
|
6077
|
+
"list_tools"
|
|
5914
6078
|
);
|
|
5915
6079
|
await this.syncTransportSessionId();
|
|
5916
6080
|
for (const tool of result.tools) {
|
|
@@ -5943,10 +6107,11 @@ var PluginMcpClient = class {
|
|
|
5943
6107
|
});
|
|
5944
6108
|
}
|
|
5945
6109
|
const result = await this.wrapAuth(
|
|
5946
|
-
client.callTool({
|
|
6110
|
+
() => client.callTool({
|
|
5947
6111
|
name,
|
|
5948
6112
|
arguments: args ?? {}
|
|
5949
|
-
})
|
|
6113
|
+
}),
|
|
6114
|
+
"call_tool"
|
|
5950
6115
|
);
|
|
5951
6116
|
await this.syncTransportSessionId();
|
|
5952
6117
|
return result;
|
|
@@ -5964,7 +6129,7 @@ var PluginMcpClient = class {
|
|
|
5964
6129
|
throw error;
|
|
5965
6130
|
}
|
|
5966
6131
|
await this.clearStoredTransportSessionId();
|
|
5967
|
-
await this.
|
|
6132
|
+
await this.cleanupClientAfterFailure();
|
|
5968
6133
|
return await operation();
|
|
5969
6134
|
}
|
|
5970
6135
|
}
|
|
@@ -6000,7 +6165,12 @@ var PluginMcpClient = class {
|
|
|
6000
6165
|
this.lastAttemptedTransportSessionId = sessionId;
|
|
6001
6166
|
const transport = new StreamableHTTPClientTransport(new URL(mcp.url), {
|
|
6002
6167
|
...Object.keys(requestInit).length > 0 ? { requestInit } : {},
|
|
6003
|
-
|
|
6168
|
+
fetch: fetchWithBoundedOAuthErrorBodies(this.options.fetch, (status) => {
|
|
6169
|
+
const store = this.providerStatusStore.getStore();
|
|
6170
|
+
if (store) {
|
|
6171
|
+
store.status = status;
|
|
6172
|
+
}
|
|
6173
|
+
}),
|
|
6004
6174
|
...this.options.authProvider ? { authProvider: this.options.authProvider } : {},
|
|
6005
6175
|
...sessionId ? { sessionId } : {}
|
|
6006
6176
|
});
|
|
@@ -6009,48 +6179,79 @@ var PluginMcpClient = class {
|
|
|
6009
6179
|
});
|
|
6010
6180
|
this.transport = transport;
|
|
6011
6181
|
try {
|
|
6012
|
-
await this.wrapAuth(client.connect(transport));
|
|
6182
|
+
await this.wrapAuth(() => client.connect(transport), "connect");
|
|
6013
6183
|
this.client = client;
|
|
6014
6184
|
await this.syncTransportSessionId();
|
|
6015
6185
|
return client;
|
|
6016
6186
|
} catch (error) {
|
|
6017
6187
|
await this.syncTransportSessionId();
|
|
6018
|
-
await this.
|
|
6188
|
+
await this.cleanupClientAfterFailure();
|
|
6019
6189
|
throw error;
|
|
6020
6190
|
}
|
|
6021
6191
|
}
|
|
6022
|
-
async wrapAuth(
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6192
|
+
async wrapAuth(operation, phase) {
|
|
6193
|
+
const store = {};
|
|
6194
|
+
return await this.providerStatusStore.run(store, async () => {
|
|
6195
|
+
try {
|
|
6196
|
+
return await operation();
|
|
6197
|
+
} catch (error) {
|
|
6198
|
+
if (error instanceof McpAuthorizationRequiredError) {
|
|
6199
|
+
throw error;
|
|
6200
|
+
}
|
|
6201
|
+
if (error instanceof UnauthorizedError) {
|
|
6202
|
+
throw new McpAuthorizationRequiredError(
|
|
6203
|
+
this.plugin.manifest.name,
|
|
6204
|
+
`MCP authorization required for plugin "${this.plugin.manifest.name}"`
|
|
6205
|
+
);
|
|
6206
|
+
}
|
|
6207
|
+
throw toMcpProviderError(error, {
|
|
6208
|
+
phase,
|
|
6209
|
+
provider: this.plugin.manifest.name,
|
|
6210
|
+
missingSession: isMissingSessionError(error) || void 0,
|
|
6211
|
+
resourceHost: this.resourceHost,
|
|
6212
|
+
status: store.status
|
|
6213
|
+
});
|
|
6034
6214
|
}
|
|
6035
|
-
|
|
6036
|
-
}
|
|
6215
|
+
});
|
|
6037
6216
|
}
|
|
6038
6217
|
async shouldResetMissingSession(error) {
|
|
6039
|
-
if (!(error instanceof
|
|
6218
|
+
if (!(error instanceof McpProviderError && error.missingSession || isMissingSessionError(error))) {
|
|
6040
6219
|
return false;
|
|
6041
6220
|
}
|
|
6042
6221
|
return Boolean(
|
|
6043
6222
|
this.transport?.sessionId ?? this.lastAttemptedTransportSessionId ?? await this.getStoredTransportSessionId()
|
|
6044
6223
|
);
|
|
6045
6224
|
}
|
|
6046
|
-
|
|
6225
|
+
resetClientState() {
|
|
6047
6226
|
const transport = this.transport;
|
|
6048
6227
|
this.listedTools = void 0;
|
|
6049
6228
|
this.transport = void 0;
|
|
6050
6229
|
this.client = void 0;
|
|
6051
6230
|
this.clientPromise = void 0;
|
|
6052
|
-
|
|
6231
|
+
return transport;
|
|
6232
|
+
}
|
|
6233
|
+
async cleanupClientAfterFailure() {
|
|
6234
|
+
const transport = this.resetClientState();
|
|
6235
|
+
if (!transport) {
|
|
6236
|
+
return;
|
|
6237
|
+
}
|
|
6238
|
+
try {
|
|
6053
6239
|
await transport.close();
|
|
6240
|
+
} catch {
|
|
6241
|
+
}
|
|
6242
|
+
}
|
|
6243
|
+
async disposeClient() {
|
|
6244
|
+
const transport = this.resetClientState();
|
|
6245
|
+
if (transport) {
|
|
6246
|
+
try {
|
|
6247
|
+
await transport.close();
|
|
6248
|
+
} catch (error) {
|
|
6249
|
+
throw toMcpProviderError(error, {
|
|
6250
|
+
phase: "close",
|
|
6251
|
+
provider: this.plugin.manifest.name,
|
|
6252
|
+
resourceHost: this.resourceHost
|
|
6253
|
+
});
|
|
6254
|
+
}
|
|
6054
6255
|
}
|
|
6055
6256
|
}
|
|
6056
6257
|
async getStoredTransportSessionId() {
|
|
@@ -6073,29 +6274,6 @@ var PluginMcpClient = class {
|
|
|
6073
6274
|
}
|
|
6074
6275
|
};
|
|
6075
6276
|
|
|
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
6277
|
// src/chat/mcp/tool-manager.ts
|
|
6100
6278
|
var MAX_TOOL_RESULT_TOKENS = 1e4;
|
|
6101
6279
|
var MAX_TOOL_RESULT_BYTES = 32 * 1024;
|
|
@@ -6469,6 +6647,7 @@ var McpToolManager = class {
|
|
|
6469
6647
|
}
|
|
6470
6648
|
const errorAttributes = {
|
|
6471
6649
|
...baseAttributes,
|
|
6650
|
+
...getMcpProviderErrorAttributes(error),
|
|
6472
6651
|
"error.type": getMcpAwareErrorType(error, "mcp_tool_error"),
|
|
6473
6652
|
"exception.message": getMcpAwareTelemetryMessage(
|
|
6474
6653
|
error,
|
|
@@ -6840,7 +7019,7 @@ async function loadSkillFromHost(availableSkills, skillName) {
|
|
|
6840
7019
|
skill_dir: skillDir,
|
|
6841
7020
|
working_directory: skillDir,
|
|
6842
7021
|
location: skillFilePath,
|
|
6843
|
-
path_resolution:
|
|
7022
|
+
path_resolution: sandboxSkillPathResolution(skill.name),
|
|
6844
7023
|
instructions: loaded.body
|
|
6845
7024
|
};
|
|
6846
7025
|
}
|
|
@@ -7207,13 +7386,77 @@ function createSearchMcpToolsTool(mcpToolManager) {
|
|
|
7207
7386
|
});
|
|
7208
7387
|
}
|
|
7209
7388
|
|
|
7210
|
-
// src/chat/tools/
|
|
7389
|
+
// src/chat/tools/sandbox/view-image.ts
|
|
7211
7390
|
import { z as z15 } from "zod";
|
|
7391
|
+
var MAX_VIEW_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
7392
|
+
var viewImageInputSchema = z15.object({
|
|
7393
|
+
path: z15.string().min(1).describe("Path to an image file in the sandbox workspace.")
|
|
7394
|
+
}).strict();
|
|
7395
|
+
function detectImageMimeType(data) {
|
|
7396
|
+
if (data.length >= 8 && data.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
|
|
7397
|
+
return "image/png";
|
|
7398
|
+
}
|
|
7399
|
+
if (data.length >= 3 && data[0] === 255 && data[1] === 216 && data[2] === 255) {
|
|
7400
|
+
return "image/jpeg";
|
|
7401
|
+
}
|
|
7402
|
+
if (data.length >= 6 && (data.subarray(0, 6).toString("ascii") === "GIF87a" || data.subarray(0, 6).toString("ascii") === "GIF89a")) {
|
|
7403
|
+
return "image/gif";
|
|
7404
|
+
}
|
|
7405
|
+
if (data.length >= 12 && data.subarray(0, 4).toString("ascii") === "RIFF" && data.subarray(8, 12).toString("ascii") === "WEBP") {
|
|
7406
|
+
return "image/webp";
|
|
7407
|
+
}
|
|
7408
|
+
return void 0;
|
|
7409
|
+
}
|
|
7410
|
+
function createViewImageTool(sandbox, supportsImageInput, deps = {}) {
|
|
7411
|
+
return zodTool({
|
|
7412
|
+
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.",
|
|
7413
|
+
exposure: "direct",
|
|
7414
|
+
inputSchema: viewImageInputSchema,
|
|
7415
|
+
async execute({ path: path9 }) {
|
|
7416
|
+
if (!supportsImageInput()) {
|
|
7417
|
+
throw new ToolInputError(
|
|
7418
|
+
"viewImage is unavailable because the current model does not support image inputs"
|
|
7419
|
+
);
|
|
7420
|
+
}
|
|
7421
|
+
const targetPath = normalizeSandboxPath(path9);
|
|
7422
|
+
const data = deps.readFile ? await deps.readFile(targetPath) : await sandbox.readFileToBuffer({ path: targetPath });
|
|
7423
|
+
if (!data) {
|
|
7424
|
+
throw new SandboxFileNotFoundError(targetPath);
|
|
7425
|
+
}
|
|
7426
|
+
if (data.byteLength === 0) {
|
|
7427
|
+
throw new ToolInputError(`image file is empty: ${targetPath}`);
|
|
7428
|
+
}
|
|
7429
|
+
if (data.byteLength > MAX_VIEW_IMAGE_BYTES) {
|
|
7430
|
+
throw new ToolInputError(
|
|
7431
|
+
`image exceeds ${MAX_VIEW_IMAGE_BYTES} bytes: ${targetPath} (${data.byteLength} bytes)`
|
|
7432
|
+
);
|
|
7433
|
+
}
|
|
7434
|
+
const mimeType = detectImageMimeType(data);
|
|
7435
|
+
if (!mimeType) {
|
|
7436
|
+
throw new ToolInputError(
|
|
7437
|
+
`unsupported image format: ${targetPath}; use PNG, JPEG, GIF, or WebP`
|
|
7438
|
+
);
|
|
7439
|
+
}
|
|
7440
|
+
return {
|
|
7441
|
+
content: [
|
|
7442
|
+
{
|
|
7443
|
+
type: "image",
|
|
7444
|
+
data: data.toString("base64"),
|
|
7445
|
+
mimeType
|
|
7446
|
+
}
|
|
7447
|
+
]
|
|
7448
|
+
};
|
|
7449
|
+
}
|
|
7450
|
+
});
|
|
7451
|
+
}
|
|
7452
|
+
|
|
7453
|
+
// src/chat/tools/runtime/report-progress.ts
|
|
7454
|
+
import { z as z16 } from "zod";
|
|
7212
7455
|
function createReportProgressTool() {
|
|
7213
7456
|
return zodTool({
|
|
7214
7457
|
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:
|
|
7458
|
+
inputSchema: z16.object({
|
|
7459
|
+
message: z16.string().min(1).describe("Short user-facing progress message.")
|
|
7217
7460
|
}),
|
|
7218
7461
|
outputSchema: juniorToolResultSchema,
|
|
7219
7462
|
execute: async () => ({
|
|
@@ -7224,34 +7467,34 @@ function createReportProgressTool() {
|
|
|
7224
7467
|
}
|
|
7225
7468
|
|
|
7226
7469
|
// src/chat/tools/resource-events.ts
|
|
7227
|
-
import { z as
|
|
7470
|
+
import { z as z18 } from "zod";
|
|
7228
7471
|
|
|
7229
7472
|
// src/chat/resource-events/store.ts
|
|
7230
7473
|
import { createHash } from "crypto";
|
|
7231
7474
|
import { destinationSchema } from "@sentry/junior-plugin-api";
|
|
7232
|
-
import { z as
|
|
7475
|
+
import { z as z17 } from "zod";
|
|
7233
7476
|
var RESOURCE_EVENT_PREFIX = "junior:resource_event_subscription";
|
|
7234
7477
|
var INDEX_LOCK_TTL_MS = 1e4;
|
|
7235
7478
|
var SUBSCRIPTION_LOCK_TTL_MS = 1e4;
|
|
7236
7479
|
var SUBSCRIPTION_LOCK_WAIT_MS = 1e4;
|
|
7237
7480
|
var SUBSCRIPTION_LOCK_RETRY_MS = 25;
|
|
7238
7481
|
var SUBSCRIPTION_LOCK_HEARTBEAT_MS = 3e3;
|
|
7239
|
-
var subscriptionStatusSchema =
|
|
7240
|
-
var subscriptionIdIndexSchema =
|
|
7241
|
-
var subscriptionSchema =
|
|
7242
|
-
conversationId:
|
|
7243
|
-
createdAtMs:
|
|
7482
|
+
var subscriptionStatusSchema = z17.enum(["active", "cancelled", "completed"]);
|
|
7483
|
+
var subscriptionIdIndexSchema = z17.array(z17.string().min(1));
|
|
7484
|
+
var subscriptionSchema = z17.object({
|
|
7485
|
+
conversationId: z17.string().min(1),
|
|
7486
|
+
createdAtMs: z17.number().finite(),
|
|
7244
7487
|
destination: destinationSchema,
|
|
7245
|
-
events:
|
|
7246
|
-
expiresAtMs:
|
|
7247
|
-
id:
|
|
7248
|
-
intent:
|
|
7249
|
-
label:
|
|
7250
|
-
provider:
|
|
7251
|
-
resourceRef:
|
|
7252
|
-
resourceType:
|
|
7488
|
+
events: z17.array(z17.string().min(1)).min(1),
|
|
7489
|
+
expiresAtMs: z17.number().finite(),
|
|
7490
|
+
id: z17.string().min(1),
|
|
7491
|
+
intent: z17.string().min(1),
|
|
7492
|
+
label: z17.string().min(1),
|
|
7493
|
+
provider: z17.string().min(1),
|
|
7494
|
+
resourceRef: z17.string().min(1),
|
|
7495
|
+
resourceType: z17.string().min(1),
|
|
7253
7496
|
status: subscriptionStatusSchema,
|
|
7254
|
-
updatedAtMs:
|
|
7497
|
+
updatedAtMs: z17.number().finite()
|
|
7255
7498
|
}).strict();
|
|
7256
7499
|
function digest(value) {
|
|
7257
7500
|
return createHash("sha256").update(value).digest("hex").slice(0, 32);
|
|
@@ -7272,8 +7515,8 @@ function indexLockKey(key) {
|
|
|
7272
7515
|
return `${key}:lock`;
|
|
7273
7516
|
}
|
|
7274
7517
|
async function sleep2(ms) {
|
|
7275
|
-
await new Promise((
|
|
7276
|
-
const timer = setTimeout(
|
|
7518
|
+
await new Promise((resolve2) => {
|
|
7519
|
+
const timer = setTimeout(resolve2, ms);
|
|
7277
7520
|
timer.unref?.();
|
|
7278
7521
|
});
|
|
7279
7522
|
}
|
|
@@ -7607,18 +7850,18 @@ var RESOURCE_WATCH_TOOL_SOURCE = {
|
|
|
7607
7850
|
id: "resource-watches",
|
|
7608
7851
|
description: "Inspect or stop resource watches for the current conversation."
|
|
7609
7852
|
};
|
|
7610
|
-
var subscribeInputSchema =
|
|
7611
|
-
resourceRef:
|
|
7612
|
-
provider:
|
|
7613
|
-
resourceType:
|
|
7614
|
-
label:
|
|
7615
|
-
events:
|
|
7853
|
+
var subscribeInputSchema = z18.object({
|
|
7854
|
+
resourceRef: z18.string().describe("Opaque resource ref copied from a subscribable tool result."),
|
|
7855
|
+
provider: z18.string().describe("Provider that owns the resource ref."),
|
|
7856
|
+
resourceType: z18.string().describe("Provider-defined resource type from the subscribable hint."),
|
|
7857
|
+
label: z18.string().describe("Human-readable resource label from the subscribable hint."),
|
|
7858
|
+
events: z18.array(z18.string()).min(1).describe(
|
|
7616
7859
|
"High-signal event names to deliver to this conversation when they occur."
|
|
7617
7860
|
),
|
|
7618
|
-
intent:
|
|
7861
|
+
intent: z18.string().describe(
|
|
7619
7862
|
"Concise reason this conversation wants these events, used when an event arrives."
|
|
7620
7863
|
),
|
|
7621
|
-
ttlMs:
|
|
7864
|
+
ttlMs: z18.coerce.number().describe(
|
|
7622
7865
|
"How long to keep the subscription active. Defaults to 14 days and is capped at 30 days."
|
|
7623
7866
|
).optional()
|
|
7624
7867
|
});
|
|
@@ -7711,7 +7954,7 @@ function createListResourceEventSubscriptionsTool(context) {
|
|
|
7711
7954
|
description: "List active resource event subscriptions for the current conversation.",
|
|
7712
7955
|
exposure: "deferred",
|
|
7713
7956
|
source: RESOURCE_WATCH_TOOL_SOURCE,
|
|
7714
|
-
inputSchema:
|
|
7957
|
+
inputSchema: z18.object({}),
|
|
7715
7958
|
outputSchema: juniorToolResultSchema,
|
|
7716
7959
|
async execute() {
|
|
7717
7960
|
const conversationId = requireConversationContext(context);
|
|
@@ -7744,7 +7987,7 @@ function createStopWatchingResourcesTool(context) {
|
|
|
7744
7987
|
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
7988
|
exposure: "deferred",
|
|
7746
7989
|
source: RESOURCE_WATCH_TOOL_SOURCE,
|
|
7747
|
-
inputSchema:
|
|
7990
|
+
inputSchema: z18.object({}),
|
|
7748
7991
|
outputSchema: juniorToolResultSchema,
|
|
7749
7992
|
async execute() {
|
|
7750
7993
|
const conversationId = requireConversationContext(context);
|
|
@@ -7851,11 +8094,11 @@ async function listThreadReplies(input) {
|
|
|
7851
8094
|
}
|
|
7852
8095
|
|
|
7853
8096
|
// src/chat/slack/timestamp-param.ts
|
|
7854
|
-
import { z as
|
|
8097
|
+
import { z as z19 } from "zod";
|
|
7855
8098
|
function slackTimestampParam(description) {
|
|
7856
|
-
return
|
|
8099
|
+
return z19.preprocess(
|
|
7857
8100
|
(value) => typeof value === "number" && Number.isFinite(value) ? String(value) : value,
|
|
7858
|
-
|
|
8101
|
+
z19.string().min(1)
|
|
7859
8102
|
).describe(description);
|
|
7860
8103
|
}
|
|
7861
8104
|
function optionalSlackTimestampParam(description) {
|
|
@@ -7886,10 +8129,10 @@ function parseRequiredSlackTimestampParam(field, value) {
|
|
|
7886
8129
|
}
|
|
7887
8130
|
|
|
7888
8131
|
// src/chat/slack/tools/channel-list-messages.ts
|
|
7889
|
-
import { z as
|
|
7890
|
-
var booleanInput2 = (description) =>
|
|
8132
|
+
import { z as z20 } from "zod";
|
|
8133
|
+
var booleanInput2 = (description) => z20.preprocess(
|
|
7891
8134
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
7892
|
-
|
|
8135
|
+
z20.boolean()
|
|
7893
8136
|
).describe(description);
|
|
7894
8137
|
function normalizeRangeTimestamp(field, value, targetChannelId) {
|
|
7895
8138
|
if (value === void 0) {
|
|
@@ -7916,9 +8159,9 @@ function createSlackChannelListMessagesTool(context) {
|
|
|
7916
8159
|
return zodTool({
|
|
7917
8160
|
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
8161
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
7919
|
-
inputSchema:
|
|
7920
|
-
limit:
|
|
7921
|
-
cursor:
|
|
8162
|
+
inputSchema: z20.object({
|
|
8163
|
+
limit: z20.coerce.number().int().min(1).max(1e3).describe("Maximum number of messages to return across pages.").optional(),
|
|
8164
|
+
cursor: z20.string().min(1).describe("Optional cursor to continue from a prior call.").optional(),
|
|
7922
8165
|
oldest: optionalSlackTimestampParam(
|
|
7923
8166
|
"Optional oldest message timestamp (Slack ts) for range filtering."
|
|
7924
8167
|
),
|
|
@@ -7928,7 +8171,7 @@ function createSlackChannelListMessagesTool(context) {
|
|
|
7928
8171
|
inclusive: booleanInput2(
|
|
7929
8172
|
"Whether oldest/latest bounds should be inclusive."
|
|
7930
8173
|
).optional(),
|
|
7931
|
-
max_pages:
|
|
8174
|
+
max_pages: z20.coerce.number().int().min(1).max(10).describe("Maximum number of API pages to traverse in a single call.").optional()
|
|
7932
8175
|
}),
|
|
7933
8176
|
outputSchema: juniorToolResultSchema,
|
|
7934
8177
|
execute: async ({
|
|
@@ -8002,20 +8245,20 @@ function createSlackChannelListMessagesTool(context) {
|
|
|
8002
8245
|
}
|
|
8003
8246
|
|
|
8004
8247
|
// src/chat/slack/tools/conversation-search.ts
|
|
8005
|
-
import { z as
|
|
8248
|
+
import { z as z21 } from "zod";
|
|
8006
8249
|
var DEFAULT_LIMIT = 5;
|
|
8007
8250
|
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:
|
|
8251
|
+
query: z21.string(),
|
|
8252
|
+
count: z21.number().int().nonnegative(),
|
|
8253
|
+
threads: z21.array(
|
|
8254
|
+
z21.object({
|
|
8255
|
+
conversation_id: z21.string().min(1),
|
|
8256
|
+
thread_ts: z21.string().min(1),
|
|
8257
|
+
message_id: z21.string().min(1),
|
|
8258
|
+
message_role: z21.enum(["assistant", "user"]),
|
|
8259
|
+
message_timestamp: z21.string().datetime(),
|
|
8260
|
+
excerpt: z21.string(),
|
|
8261
|
+
permalink: z21.string().url().optional()
|
|
8019
8262
|
}).strict()
|
|
8020
8263
|
)
|
|
8021
8264
|
});
|
|
@@ -8028,9 +8271,9 @@ function createSlackConversationSearchTool(scope, currentConversationId, deps =
|
|
|
8028
8271
|
description: "Search retained public Junior conversation threads in the current Slack workspace."
|
|
8029
8272
|
},
|
|
8030
8273
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
8031
|
-
inputSchema:
|
|
8032
|
-
query:
|
|
8033
|
-
limit:
|
|
8274
|
+
inputSchema: z21.object({
|
|
8275
|
+
query: z21.string().trim().min(1).max(200).describe("Words or a short phrase to find in prior conversations."),
|
|
8276
|
+
limit: z21.number().int().min(1).max(10).describe("Maximum number of prior conversation threads to return.").nullable().optional()
|
|
8034
8277
|
}),
|
|
8035
8278
|
outputSchema: conversationSearchOutputSchema,
|
|
8036
8279
|
execute: async ({ query, limit }) => {
|
|
@@ -8077,27 +8320,27 @@ function createSlackConversationSearchTool(scope, currentConversationId, deps =
|
|
|
8077
8320
|
}
|
|
8078
8321
|
|
|
8079
8322
|
// src/chat/slack/tools/public-search.ts
|
|
8080
|
-
import { z as
|
|
8323
|
+
import { z as z22 } from "zod";
|
|
8081
8324
|
var DEFAULT_LIMIT2 = 10;
|
|
8082
|
-
var optionalTimestampSchema =
|
|
8325
|
+
var optionalTimestampSchema = z22.preprocess(
|
|
8083
8326
|
(value) => typeof value === "string" && value.trim() === "" ? void 0 : value,
|
|
8084
|
-
|
|
8327
|
+
z22.coerce.number().int().nonnegative().describe("Optional Unix timestamp bound.").optional()
|
|
8085
8328
|
);
|
|
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:
|
|
8329
|
+
var searchMessageSchema = z22.object({
|
|
8330
|
+
author_name: z22.string().optional(),
|
|
8331
|
+
author_user_id: z22.string().optional(),
|
|
8332
|
+
channel_id: z22.string().min(1),
|
|
8333
|
+
channel_name: z22.string().optional(),
|
|
8334
|
+
message_ts: z22.string().min(1),
|
|
8335
|
+
content: z22.string(),
|
|
8336
|
+
is_author_bot: z22.boolean().optional(),
|
|
8337
|
+
permalink: z22.string().url()
|
|
8095
8338
|
});
|
|
8096
8339
|
var publicSearchOutputSchema = juniorToolResultSchema.extend({
|
|
8097
|
-
query:
|
|
8098
|
-
count:
|
|
8099
|
-
messages:
|
|
8100
|
-
next_cursor:
|
|
8340
|
+
query: z22.string(),
|
|
8341
|
+
count: z22.number().int().nonnegative(),
|
|
8342
|
+
messages: z22.array(searchMessageSchema),
|
|
8343
|
+
next_cursor: z22.string().optional()
|
|
8101
8344
|
});
|
|
8102
8345
|
function normalizeMessage(value) {
|
|
8103
8346
|
const parsed = searchMessageSchema.safeParse(value);
|
|
@@ -8119,8 +8362,8 @@ function createSlackPublicSearchTool(actionToken) {
|
|
|
8119
8362
|
return zodTool({
|
|
8120
8363
|
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
8364
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
8122
|
-
inputSchema:
|
|
8123
|
-
query:
|
|
8365
|
+
inputSchema: z22.object({
|
|
8366
|
+
query: z22.string().trim().min(1).max(500).describe(
|
|
8124
8367
|
"A focused Slack search query, including Slack search filters when useful."
|
|
8125
8368
|
),
|
|
8126
8369
|
after: optionalTimestampSchema.describe(
|
|
@@ -8129,10 +8372,10 @@ function createSlackPublicSearchTool(actionToken) {
|
|
|
8129
8372
|
before: optionalTimestampSchema.describe(
|
|
8130
8373
|
"Optional Unix timestamp upper bound."
|
|
8131
8374
|
),
|
|
8132
|
-
cursor:
|
|
8133
|
-
limit:
|
|
8134
|
-
sort:
|
|
8135
|
-
sort_dir:
|
|
8375
|
+
cursor: z22.string().min(1).describe("Cursor for the next result page.").optional(),
|
|
8376
|
+
limit: z22.coerce.number().int().min(1).max(20).describe("Maximum results to return; Slack allows at most 20.").optional(),
|
|
8377
|
+
sort: z22.enum(["score", "timestamp"]).describe("Rank by relevance or timestamp.").optional(),
|
|
8378
|
+
sort_dir: z22.enum(["asc", "desc"]).describe("Sort direction.").optional()
|
|
8136
8379
|
}),
|
|
8137
8380
|
outputSchema: publicSearchOutputSchema,
|
|
8138
8381
|
execute: async ({
|
|
@@ -8198,7 +8441,7 @@ function createSlackPublicSearchTool(actionToken) {
|
|
|
8198
8441
|
}
|
|
8199
8442
|
|
|
8200
8443
|
// src/chat/slack/tools/message-add-reaction.ts
|
|
8201
|
-
import { z as
|
|
8444
|
+
import { z as z23 } from "zod";
|
|
8202
8445
|
|
|
8203
8446
|
// src/chat/tools/idempotency.ts
|
|
8204
8447
|
function stableSerialize(value) {
|
|
@@ -8222,8 +8465,8 @@ function createOperationKey(toolName, input) {
|
|
|
8222
8465
|
function createSlackMessageAddReactionTool(context, state) {
|
|
8223
8466
|
return zodTool({
|
|
8224
8467
|
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:
|
|
8468
|
+
inputSchema: z23.object({
|
|
8469
|
+
emoji: z23.string().min(1).max(64).describe(
|
|
8227
8470
|
"Slack emoji alias name to react with (for example `thumbsup`, `white_check_mark`, or `thumbsup::skin-tone-6`). Optional surrounding colons are allowed."
|
|
8228
8471
|
)
|
|
8229
8472
|
}),
|
|
@@ -8274,18 +8517,18 @@ function createSlackMessageAddReactionTool(context, state) {
|
|
|
8274
8517
|
|
|
8275
8518
|
// src/chat/slack/tools/send-files.ts
|
|
8276
8519
|
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:
|
|
8520
|
+
import { z as z24 } from "zod";
|
|
8521
|
+
var sendFilesDataSchema = z24.object({
|
|
8522
|
+
channel_id: z24.string().min(1),
|
|
8523
|
+
deduplicated: z24.boolean().optional(),
|
|
8524
|
+
file_count: z24.number().int().nonnegative(),
|
|
8525
|
+
file_ids: z24.array(z24.string().min(1)).optional(),
|
|
8526
|
+
thread_ts: z24.string().min(1)
|
|
8284
8527
|
});
|
|
8285
8528
|
var sendFilesResultSchema = juniorToolResultSchema.extend({
|
|
8286
|
-
ok:
|
|
8287
|
-
status:
|
|
8288
|
-
target:
|
|
8529
|
+
ok: z24.literal(true),
|
|
8530
|
+
status: z24.literal("success"),
|
|
8531
|
+
target: z24.string().min(1),
|
|
8289
8532
|
data: sendFilesDataSchema
|
|
8290
8533
|
});
|
|
8291
8534
|
function normalizeFiles(files) {
|
|
@@ -8310,8 +8553,8 @@ function fileOperationInput(files) {
|
|
|
8310
8553
|
function createSendFilesTool(context, state, materializeFile) {
|
|
8311
8554
|
return zodTool({
|
|
8312
8555
|
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:
|
|
8556
|
+
inputSchema: z24.object({
|
|
8557
|
+
files: z24.array(sandboxFileReferenceSchema).min(1).describe(
|
|
8315
8558
|
"One or more existing sandbox files. Objects returned by imageGenerate or webFetch can be passed unchanged."
|
|
8316
8559
|
)
|
|
8317
8560
|
}),
|
|
@@ -8615,13 +8858,13 @@ function storedCanvasUrl(state, canvasId) {
|
|
|
8615
8858
|
}
|
|
8616
8859
|
|
|
8617
8860
|
// src/chat/slack/tools/canvas/create.ts
|
|
8618
|
-
import { z as
|
|
8861
|
+
import { z as z25 } from "zod";
|
|
8619
8862
|
function createSlackCanvasCreateTool(context, state) {
|
|
8620
8863
|
return zodTool({
|
|
8621
8864
|
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:
|
|
8865
|
+
inputSchema: z25.object({
|
|
8866
|
+
title: z25.string().min(1).max(160).describe("Canvas title."),
|
|
8867
|
+
markdown: z25.string().min(1).describe("Canvas markdown body content.")
|
|
8625
8868
|
}),
|
|
8626
8869
|
outputSchema: juniorToolResultSchema,
|
|
8627
8870
|
execute: async ({ title, markdown }) => {
|
|
@@ -8684,35 +8927,35 @@ function createSlackCanvasCreateTool(context, state) {
|
|
|
8684
8927
|
}
|
|
8685
8928
|
|
|
8686
8929
|
// src/chat/slack/tools/canvas/edit.ts
|
|
8687
|
-
import { z as
|
|
8930
|
+
import { z as z26 } from "zod";
|
|
8688
8931
|
function prepareCanvasEditArguments(input) {
|
|
8689
8932
|
return prepareTextReplacementArguments(input);
|
|
8690
8933
|
}
|
|
8691
|
-
var editReplacementSchema2 =
|
|
8692
|
-
oldText:
|
|
8934
|
+
var editReplacementSchema2 = z26.object({
|
|
8935
|
+
oldText: z26.string().min(1).describe(
|
|
8693
8936
|
"Exact Canvas markdown to replace. It must be unique in the current Canvas body and must not overlap another edit."
|
|
8694
8937
|
),
|
|
8695
|
-
newText:
|
|
8938
|
+
newText: z26.string().describe("Replacement Canvas markdown for this edit.")
|
|
8696
8939
|
});
|
|
8697
8940
|
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:
|
|
8941
|
+
canvas_id: z26.string().optional(),
|
|
8942
|
+
title: z26.string().optional(),
|
|
8943
|
+
permalink: z26.string().optional(),
|
|
8944
|
+
diff: z26.string().optional(),
|
|
8945
|
+
first_changed_line: z26.number().int().positive().optional(),
|
|
8946
|
+
replacements: z26.number().int().nonnegative().optional(),
|
|
8947
|
+
normalized_heading_count: z26.number().int().nonnegative().optional(),
|
|
8948
|
+
summary: z26.string().optional(),
|
|
8949
|
+
deduplicated: z26.boolean().optional()
|
|
8707
8950
|
}).strict();
|
|
8708
8951
|
function createSlackCanvasEditTool(state) {
|
|
8709
8952
|
return zodTool({
|
|
8710
8953
|
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
8954
|
prepareArguments: prepareCanvasEditArguments,
|
|
8712
8955
|
executionMode: "sequential",
|
|
8713
|
-
inputSchema:
|
|
8714
|
-
canvas:
|
|
8715
|
-
edits:
|
|
8956
|
+
inputSchema: z26.object({
|
|
8957
|
+
canvas: z26.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
|
|
8958
|
+
edits: z26.array(editReplacementSchema2).min(1).describe(
|
|
8716
8959
|
"Exact replacements matched against the current Canvas body, not incrementally."
|
|
8717
8960
|
)
|
|
8718
8961
|
}),
|
|
@@ -8790,29 +9033,29 @@ function createSlackCanvasEditTool(state) {
|
|
|
8790
9033
|
}
|
|
8791
9034
|
|
|
8792
9035
|
// src/chat/slack/tools/canvas/read.ts
|
|
8793
|
-
import { z as
|
|
9036
|
+
import { z as z27 } from "zod";
|
|
8794
9037
|
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:
|
|
9038
|
+
canvas_id: z27.string().optional(),
|
|
9039
|
+
title: z27.string().optional(),
|
|
9040
|
+
permalink: z27.string().optional(),
|
|
9041
|
+
mimetype: z27.string().optional(),
|
|
9042
|
+
filetype: z27.string().optional(),
|
|
9043
|
+
original_byte_length: z27.number().int().nonnegative().optional(),
|
|
9044
|
+
content: z27.string().optional(),
|
|
9045
|
+
start_line: z27.number().int().positive().optional(),
|
|
9046
|
+
end_line: z27.number().int().nonnegative().optional(),
|
|
9047
|
+
total_lines: z27.number().int().nonnegative().optional()
|
|
8805
9048
|
}).strict();
|
|
8806
9049
|
function createSlackCanvasReadTool() {
|
|
8807
9050
|
return zodTool({
|
|
8808
9051
|
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
9052
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
8810
|
-
inputSchema:
|
|
8811
|
-
canvas:
|
|
9053
|
+
inputSchema: z27.object({
|
|
9054
|
+
canvas: z27.string().min(1).describe(
|
|
8812
9055
|
"Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL (e.g. `https://team.slack.com/docs/T.../F...`)."
|
|
8813
9056
|
),
|
|
8814
|
-
offset:
|
|
8815
|
-
limit:
|
|
9057
|
+
offset: z27.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
|
|
9058
|
+
limit: z27.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
|
|
8816
9059
|
}),
|
|
8817
9060
|
outputSchema: slackCanvasReadOutputSchema,
|
|
8818
9061
|
execute: async ({ canvas, offset, limit }) => {
|
|
@@ -8869,14 +9112,14 @@ function createSlackCanvasReadTool() {
|
|
|
8869
9112
|
}
|
|
8870
9113
|
|
|
8871
9114
|
// src/chat/slack/tools/canvas/write.ts
|
|
8872
|
-
import { z as
|
|
9115
|
+
import { z as z28 } from "zod";
|
|
8873
9116
|
function createSlackCanvasWriteTool(state) {
|
|
8874
9117
|
return zodTool({
|
|
8875
9118
|
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
9119
|
executionMode: "sequential",
|
|
8877
|
-
inputSchema:
|
|
8878
|
-
canvas:
|
|
8879
|
-
content:
|
|
9120
|
+
inputSchema: z28.object({
|
|
9121
|
+
canvas: z28.string().min(1).describe("Canvas/file ID (e.g. `F0ABCDEF`) or Slack canvas/docs URL."),
|
|
9122
|
+
content: z28.string().describe("UTF-8 markdown content to write.")
|
|
8880
9123
|
}),
|
|
8881
9124
|
outputSchema: juniorToolResultSchema,
|
|
8882
9125
|
execute: async ({ canvas, content }) => {
|
|
@@ -9112,12 +9355,12 @@ async function updateListItem(input) {
|
|
|
9112
9355
|
}
|
|
9113
9356
|
|
|
9114
9357
|
// src/chat/slack/id-param.ts
|
|
9115
|
-
import { z as
|
|
9358
|
+
import { z as z29 } from "zod";
|
|
9116
9359
|
function slackChannelIdParam(description) {
|
|
9117
|
-
return
|
|
9360
|
+
return z29.string().min(1).describe(description);
|
|
9118
9361
|
}
|
|
9119
9362
|
function slackUserIdParam(description) {
|
|
9120
|
-
return
|
|
9363
|
+
return z29.string().min(1).describe(description);
|
|
9121
9364
|
}
|
|
9122
9365
|
function parseRequiredSlackChannelIdParam(field, value) {
|
|
9123
9366
|
const channelId = parseSlackChannelId(value);
|
|
@@ -9141,16 +9384,16 @@ function parseRequiredSlackUserIdParam(field, value) {
|
|
|
9141
9384
|
}
|
|
9142
9385
|
|
|
9143
9386
|
// src/chat/slack/tools/list/add-items.ts
|
|
9144
|
-
import { z as
|
|
9387
|
+
import { z as z30 } from "zod";
|
|
9145
9388
|
function createSlackListAddItemsTool(state) {
|
|
9146
9389
|
return zodTool({
|
|
9147
9390
|
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:
|
|
9391
|
+
inputSchema: z30.object({
|
|
9392
|
+
items: z30.array(z30.string().min(1)).min(1).max(25).describe("List item titles to create."),
|
|
9150
9393
|
assignee_user_id: slackUserIdParam(
|
|
9151
9394
|
"Optional Slack user ID assigned to all created items."
|
|
9152
9395
|
).optional(),
|
|
9153
|
-
due_date:
|
|
9396
|
+
due_date: z30.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
|
|
9154
9397
|
}),
|
|
9155
9398
|
outputSchema: juniorToolResultSchema,
|
|
9156
9399
|
execute: async ({ items, assignee_user_id, due_date }) => {
|
|
@@ -9204,12 +9447,12 @@ function createSlackListAddItemsTool(state) {
|
|
|
9204
9447
|
}
|
|
9205
9448
|
|
|
9206
9449
|
// src/chat/slack/tools/list/create.ts
|
|
9207
|
-
import { z as
|
|
9450
|
+
import { z as z31 } from "zod";
|
|
9208
9451
|
function createSlackListCreateTool(state) {
|
|
9209
9452
|
return zodTool({
|
|
9210
9453
|
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:
|
|
9454
|
+
inputSchema: z31.object({
|
|
9455
|
+
name: z31.string().min(1).max(160).describe("Name for the new Slack list.")
|
|
9213
9456
|
}),
|
|
9214
9457
|
outputSchema: juniorToolResultSchema,
|
|
9215
9458
|
execute: async ({ name }) => {
|
|
@@ -9241,13 +9484,13 @@ function createSlackListCreateTool(state) {
|
|
|
9241
9484
|
}
|
|
9242
9485
|
|
|
9243
9486
|
// src/chat/slack/tools/list/get-items.ts
|
|
9244
|
-
import { z as
|
|
9487
|
+
import { z as z32 } from "zod";
|
|
9245
9488
|
function createSlackListGetItemsTool(state) {
|
|
9246
9489
|
return zodTool({
|
|
9247
9490
|
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
9491
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
9249
|
-
inputSchema:
|
|
9250
|
-
limit:
|
|
9492
|
+
inputSchema: z32.object({
|
|
9493
|
+
limit: z32.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
|
|
9251
9494
|
}),
|
|
9252
9495
|
outputSchema: juniorToolResultSchema,
|
|
9253
9496
|
execute: async ({ limit }) => {
|
|
@@ -9272,21 +9515,21 @@ function createSlackListGetItemsTool(state) {
|
|
|
9272
9515
|
}
|
|
9273
9516
|
|
|
9274
9517
|
// src/chat/slack/tools/list/update-item.ts
|
|
9275
|
-
import { z as
|
|
9276
|
-
var booleanInput3 = (description) =>
|
|
9518
|
+
import { z as z33 } from "zod";
|
|
9519
|
+
var booleanInput3 = (description) => z33.preprocess(
|
|
9277
9520
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
9278
|
-
|
|
9521
|
+
z33.boolean()
|
|
9279
9522
|
).describe(description);
|
|
9280
|
-
var updateListItemInputSchema =
|
|
9281
|
-
|
|
9282
|
-
item_id:
|
|
9523
|
+
var updateListItemInputSchema = z33.union([
|
|
9524
|
+
z33.object({
|
|
9525
|
+
item_id: z33.string().min(1).describe("ID of the Slack list item to update."),
|
|
9283
9526
|
completed: booleanInput3("Optional completion status update."),
|
|
9284
|
-
title:
|
|
9527
|
+
title: z33.string().min(1).describe("Optional new item title.").optional()
|
|
9285
9528
|
}),
|
|
9286
|
-
|
|
9287
|
-
item_id:
|
|
9529
|
+
z33.object({
|
|
9530
|
+
item_id: z33.string().min(1).describe("ID of the Slack list item to update."),
|
|
9288
9531
|
completed: booleanInput3("Optional completion status update.").optional(),
|
|
9289
|
-
title:
|
|
9532
|
+
title: z33.string().min(1).describe("Optional new item title.")
|
|
9290
9533
|
})
|
|
9291
9534
|
]);
|
|
9292
9535
|
function createSlackListUpdateItemTool(state) {
|
|
@@ -9362,7 +9605,7 @@ async function checkSlackChannelReadAccess(args) {
|
|
|
9362
9605
|
}
|
|
9363
9606
|
|
|
9364
9607
|
// src/chat/slack/tools/thread-read.ts
|
|
9365
|
-
import { z as
|
|
9608
|
+
import { z as z34 } from "zod";
|
|
9366
9609
|
|
|
9367
9610
|
// src/chat/slack/tools/slack-message-url.ts
|
|
9368
9611
|
var SLACK_HOST_PATTERN = /^[a-z0-9-]+\.slack(?:-gov)?\.com$/;
|
|
@@ -9535,8 +9778,8 @@ function createSlackThreadReadTool(context, deps = {}) {
|
|
|
9535
9778
|
return zodTool({
|
|
9536
9779
|
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
9780
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
9538
|
-
inputSchema:
|
|
9539
|
-
url:
|
|
9781
|
+
inputSchema: z34.object({
|
|
9782
|
+
url: z34.string().min(1).describe(
|
|
9540
9783
|
"Slack message archive URL, e.g. https://workspace.slack.com/archives/C123/p1700000000123456"
|
|
9541
9784
|
).optional(),
|
|
9542
9785
|
channel_id: slackChannelIdParam(
|
|
@@ -9545,8 +9788,8 @@ function createSlackThreadReadTool(context, deps = {}) {
|
|
|
9545
9788
|
ts: slackTimestampParam(
|
|
9546
9789
|
"Slack message timestamp (e.g. 1700000000.123456). May be the thread root or any message in the thread."
|
|
9547
9790
|
).optional(),
|
|
9548
|
-
limit:
|
|
9549
|
-
max_pages:
|
|
9791
|
+
limit: z34.coerce.number().int().min(1).max(1e3).describe("Maximum number of thread messages to fetch.").optional(),
|
|
9792
|
+
max_pages: z34.coerce.number().int().min(1).max(10).describe("Maximum number of Slack API pages to traverse.").optional()
|
|
9550
9793
|
}),
|
|
9551
9794
|
outputSchema: juniorToolResultSchema,
|
|
9552
9795
|
execute: async ({ url, channel_id, ts, limit, max_pages }) => {
|
|
@@ -9802,29 +10045,29 @@ async function searchSlackUsers(options) {
|
|
|
9802
10045
|
}
|
|
9803
10046
|
|
|
9804
10047
|
// src/chat/slack/tools/user-lookup.ts
|
|
9805
|
-
import { z as
|
|
9806
|
-
var booleanInput4 = (description) =>
|
|
10048
|
+
import { z as z35 } from "zod";
|
|
10049
|
+
var booleanInput4 = (description) => z35.preprocess(
|
|
9807
10050
|
(value) => value === "true" ? true : value === "false" ? false : value,
|
|
9808
|
-
|
|
10051
|
+
z35.boolean()
|
|
9809
10052
|
).describe(description);
|
|
9810
10053
|
function createSlackUserLookupTool() {
|
|
9811
10054
|
return zodTool({
|
|
9812
10055
|
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
10056
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
9814
|
-
inputSchema:
|
|
10057
|
+
inputSchema: z35.object({
|
|
9815
10058
|
user_id: slackUserIdParam(
|
|
9816
10059
|
"Slack user ID to look up (e.g. U039RR91S). Mutually exclusive with email and query."
|
|
9817
10060
|
).optional(),
|
|
9818
|
-
email:
|
|
10061
|
+
email: z35.string().min(3).describe(
|
|
9819
10062
|
"Email address to look up. Mutually exclusive with user_id and query."
|
|
9820
10063
|
).optional(),
|
|
9821
|
-
query:
|
|
10064
|
+
query: z35.string().min(2).describe(
|
|
9822
10065
|
"Name to search for (matches against username, display name, real name). Mutually exclusive with user_id and email."
|
|
9823
10066
|
).optional(),
|
|
9824
|
-
limit:
|
|
10067
|
+
limit: z35.coerce.number().int().min(1).max(20).describe(
|
|
9825
10068
|
"Maximum number of results to return for name search. Defaults to 10."
|
|
9826
10069
|
).optional(),
|
|
9827
|
-
max_pages:
|
|
10070
|
+
max_pages: z35.coerce.number().int().min(1).max(5).describe(
|
|
9828
10071
|
"Maximum number of Slack API pages to scan for name search. Defaults to 3."
|
|
9829
10072
|
).optional(),
|
|
9830
10073
|
include_bots: booleanInput4(
|
|
@@ -9928,18 +10171,18 @@ function createSlackUserLookupTool() {
|
|
|
9928
10171
|
}
|
|
9929
10172
|
|
|
9930
10173
|
// src/chat/tools/system-time.ts
|
|
9931
|
-
import { z as
|
|
10174
|
+
import { z as z36 } from "zod";
|
|
9932
10175
|
var systemTimeOutputSchema = juniorToolResultSchema.extend({
|
|
9933
|
-
unix_ms:
|
|
9934
|
-
iso_utc:
|
|
9935
|
-
iso_local:
|
|
9936
|
-
timezone_offset_minutes:
|
|
10176
|
+
unix_ms: z36.number(),
|
|
10177
|
+
iso_utc: z36.string(),
|
|
10178
|
+
iso_local: z36.string(),
|
|
10179
|
+
timezone_offset_minutes: z36.number()
|
|
9937
10180
|
});
|
|
9938
10181
|
function createSystemTimeTool() {
|
|
9939
10182
|
return zodTool({
|
|
9940
10183
|
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
10184
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
9942
|
-
inputSchema:
|
|
10185
|
+
inputSchema: z36.object({}),
|
|
9943
10186
|
outputSchema: systemTimeOutputSchema,
|
|
9944
10187
|
privateTraceResult: (result) => ({
|
|
9945
10188
|
ok: result.ok,
|
|
@@ -9968,32 +10211,32 @@ function createSystemTimeTool() {
|
|
|
9968
10211
|
}
|
|
9969
10212
|
|
|
9970
10213
|
// src/chat/tools/query-conversation-events.ts
|
|
9971
|
-
import { z as
|
|
10214
|
+
import { z as z37 } from "zod";
|
|
9972
10215
|
var DEFAULT_LIMIT3 = 25;
|
|
9973
10216
|
var MAX_LIMIT = 100;
|
|
9974
10217
|
var CONVERSATION_EVENTS_TOOL_SOURCE = {
|
|
9975
10218
|
id: "conversation-events",
|
|
9976
10219
|
description: "Inspect Junior's durable conversation event log for debugging runtime behavior."
|
|
9977
10220
|
};
|
|
9978
|
-
var knownEventTypeSchema =
|
|
9979
|
-
var projectedEventSchema =
|
|
9980
|
-
seq:
|
|
9981
|
-
history_version:
|
|
10221
|
+
var knownEventTypeSchema = z37.enum(KNOWN_CONVERSATION_EVENT_TYPES);
|
|
10222
|
+
var projectedEventSchema = z37.object({
|
|
10223
|
+
seq: z37.number().int().nonnegative().describe("Stable event position; use it for pagination bounds."),
|
|
10224
|
+
history_version: z37.number().int().nonnegative().describe(
|
|
9982
10225
|
"Model-history generation. It increments when handoff or compaction replaces active model context."
|
|
9983
10226
|
),
|
|
9984
|
-
created_at:
|
|
9985
|
-
idempotency_key:
|
|
9986
|
-
data:
|
|
10227
|
+
created_at: z37.iso.datetime().describe("When the event was recorded."),
|
|
10228
|
+
idempotency_key: z37.string().min(1).optional().describe("Retry-stable event identity, when one was assigned."),
|
|
10229
|
+
data: z37.record(z37.string(), z37.unknown()).describe(
|
|
9987
10230
|
"Event payload. The type field identifies the event; replacement-history events report replacement_history_count instead of replaying the full model context."
|
|
9988
10231
|
)
|
|
9989
10232
|
}).strict();
|
|
9990
10233
|
var queryConversationEventsOutputSchema = juniorToolResultSchema.extend({
|
|
9991
|
-
conversation_id:
|
|
9992
|
-
events:
|
|
9993
|
-
has_older:
|
|
10234
|
+
conversation_id: z37.string().min(1),
|
|
10235
|
+
events: z37.array(projectedEventSchema),
|
|
10236
|
+
has_older: z37.boolean().describe(
|
|
9994
10237
|
"Whether matching events exist before this page; request them with before_seq set to the first returned seq."
|
|
9995
10238
|
),
|
|
9996
|
-
has_newer:
|
|
10239
|
+
has_newer: z37.boolean().describe(
|
|
9997
10240
|
"Whether matching events exist after this page; request them with after_seq set to the last returned seq."
|
|
9998
10241
|
)
|
|
9999
10242
|
});
|
|
@@ -10003,20 +10246,20 @@ function createQueryConversationEventsTool(context) {
|
|
|
10003
10246
|
exposure: "deferred",
|
|
10004
10247
|
source: CONVERSATION_EVENTS_TOOL_SOURCE,
|
|
10005
10248
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
10006
|
-
inputSchema:
|
|
10007
|
-
conversation_id:
|
|
10249
|
+
inputSchema: z37.object({
|
|
10250
|
+
conversation_id: z37.string().trim().min(1).describe(
|
|
10008
10251
|
"Conversation ID to inspect, such as slack:{channelId}:{threadTs} or a child conversation id."
|
|
10009
10252
|
),
|
|
10010
|
-
after_seq:
|
|
10253
|
+
after_seq: z37.number().int().nonnegative().nullable().describe(
|
|
10011
10254
|
"Exclusive lower bound on event seq. When set, returns the next newer page in ascending order."
|
|
10012
10255
|
).optional(),
|
|
10013
|
-
before_seq:
|
|
10256
|
+
before_seq: z37.number().int().nonnegative().nullable().describe(
|
|
10014
10257
|
"Exclusive upper bound on event seq. Combine with defaults or after_seq to page older or bounded ranges."
|
|
10015
10258
|
).optional(),
|
|
10016
|
-
limit:
|
|
10259
|
+
limit: z37.number().int().min(1).max(MAX_LIMIT).nullable().describe(
|
|
10017
10260
|
`Maximum events to return. Defaults to ${DEFAULT_LIMIT3}; max ${MAX_LIMIT}.`
|
|
10018
10261
|
).optional(),
|
|
10019
|
-
types:
|
|
10262
|
+
types: z37.array(knownEventTypeSchema).min(1).nullable().describe(
|
|
10020
10263
|
"Optional event-type filter. Omit to return every durable event type."
|
|
10021
10264
|
).optional()
|
|
10022
10265
|
}).strict(),
|
|
@@ -10206,10 +10449,10 @@ function stripReplacementHistoryField(value) {
|
|
|
10206
10449
|
}
|
|
10207
10450
|
|
|
10208
10451
|
// src/chat/tools/handoff/tool.ts
|
|
10209
|
-
import { z as
|
|
10452
|
+
import { z as z38 } from "zod";
|
|
10210
10453
|
var HANDOFF_TOOL_NAME = "handoff";
|
|
10211
10454
|
function createHandoffTool(handoff) {
|
|
10212
|
-
const profileSchema =
|
|
10455
|
+
const profileSchema = z38.enum(handoff.profiles);
|
|
10213
10456
|
const handoffResultSchema = juniorToolResultSchema.extend({
|
|
10214
10457
|
model_profile: profileSchema
|
|
10215
10458
|
});
|
|
@@ -10217,7 +10460,7 @@ function createHandoffTool(handoff) {
|
|
|
10217
10460
|
return zodTool({
|
|
10218
10461
|
description: `Switch to another execution profile and continue the same task. Profiles: ${profileNames}. Call this as the only tool.`,
|
|
10219
10462
|
executionMode: "sequential",
|
|
10220
|
-
inputSchema:
|
|
10463
|
+
inputSchema: z38.object({
|
|
10221
10464
|
profile: profileSchema.describe("Target execution profile")
|
|
10222
10465
|
}).strict(),
|
|
10223
10466
|
outputSchema: handoffResultSchema,
|
|
@@ -10240,7 +10483,7 @@ function createHandoffTool(handoff) {
|
|
|
10240
10483
|
}
|
|
10241
10484
|
|
|
10242
10485
|
// src/chat/tools/web/fetch-tool.ts
|
|
10243
|
-
import { z as
|
|
10486
|
+
import { z as z39 } from "zod";
|
|
10244
10487
|
|
|
10245
10488
|
// src/chat/tools/web/constants.ts
|
|
10246
10489
|
var USER_AGENT = "junior-bot/0.1";
|
|
@@ -10368,7 +10611,7 @@ async function fetchWithPinnedLookup(url, resolved, signal) {
|
|
|
10368
10611
|
}
|
|
10369
10612
|
const client = url.protocol === "https:" ? https : http;
|
|
10370
10613
|
const lookup = createPinnedLookup(resolved);
|
|
10371
|
-
return new Promise((
|
|
10614
|
+
return new Promise((resolve2, reject) => {
|
|
10372
10615
|
const request = client.request(
|
|
10373
10616
|
{
|
|
10374
10617
|
protocol: url.protocol,
|
|
@@ -10398,7 +10641,7 @@ async function fetchWithPinnedLookup(url, resolved, signal) {
|
|
|
10398
10641
|
}
|
|
10399
10642
|
const rawStatus = response.statusCode ?? 500;
|
|
10400
10643
|
const status = rawStatus >= 200 && rawStatus <= 599 ? rawStatus : 502;
|
|
10401
|
-
|
|
10644
|
+
resolve2(
|
|
10402
10645
|
new Response(Buffer.concat(chunks), {
|
|
10403
10646
|
status,
|
|
10404
10647
|
headers
|
|
@@ -10690,9 +10933,9 @@ function createWebFetchTool(hooks, options = {}) {
|
|
|
10690
10933
|
destructiveHint: false,
|
|
10691
10934
|
openWorldHint: true
|
|
10692
10935
|
},
|
|
10693
|
-
inputSchema:
|
|
10694
|
-
url:
|
|
10695
|
-
max_chars:
|
|
10936
|
+
inputSchema: z39.object({
|
|
10937
|
+
url: z39.string().min(1).describe("HTTP(S) URL to fetch."),
|
|
10938
|
+
max_chars: z39.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
|
|
10696
10939
|
}),
|
|
10697
10940
|
outputSchema: juniorToolResultSchema,
|
|
10698
10941
|
execute: async ({ url, max_chars }) => {
|
|
@@ -10753,7 +10996,7 @@ function createWebFetchTool(hooks, options = {}) {
|
|
|
10753
10996
|
}
|
|
10754
10997
|
|
|
10755
10998
|
// src/chat/tools/web/search.ts
|
|
10756
|
-
import { z as
|
|
10999
|
+
import { z as z40 } from "zod";
|
|
10757
11000
|
import { generateText } from "ai";
|
|
10758
11001
|
import { createGatewayProvider } from "@ai-sdk/gateway";
|
|
10759
11002
|
var SEARCH_TIMEOUT_MS = 6e4;
|
|
@@ -10802,9 +11045,9 @@ function createWebSearchTool(modelId, override) {
|
|
|
10802
11045
|
destructiveHint: false,
|
|
10803
11046
|
openWorldHint: true
|
|
10804
11047
|
},
|
|
10805
|
-
inputSchema:
|
|
10806
|
-
query:
|
|
10807
|
-
max_results:
|
|
11048
|
+
inputSchema: z40.object({
|
|
11049
|
+
query: z40.string().min(1).max(500).describe("Search query."),
|
|
11050
|
+
max_results: z40.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
|
|
10808
11051
|
}),
|
|
10809
11052
|
outputSchema: juniorToolResultSchema,
|
|
10810
11053
|
execute: async ({ query, max_results }) => {
|
|
@@ -10873,14 +11116,14 @@ function createWebSearchTool(modelId, override) {
|
|
|
10873
11116
|
}
|
|
10874
11117
|
|
|
10875
11118
|
// src/chat/tools/sandbox/write-file.ts
|
|
10876
|
-
import { z as
|
|
11119
|
+
import { z as z41 } from "zod";
|
|
10877
11120
|
function createWriteFileTool() {
|
|
10878
11121
|
return zodTool({
|
|
10879
11122
|
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
11123
|
executionMode: "sequential",
|
|
10881
|
-
inputSchema:
|
|
10882
|
-
path:
|
|
10883
|
-
content:
|
|
11124
|
+
inputSchema: z41.object({
|
|
11125
|
+
path: z41.string().min(1).describe("Path to write in the sandbox workspace."),
|
|
11126
|
+
content: z41.string().describe("UTF-8 file content to write.")
|
|
10884
11127
|
}),
|
|
10885
11128
|
outputSchema: juniorToolResultSchema,
|
|
10886
11129
|
execute: async () => {
|
|
@@ -10920,7 +11163,7 @@ function createToolState(hooks, context) {
|
|
|
10920
11163
|
}
|
|
10921
11164
|
};
|
|
10922
11165
|
}
|
|
10923
|
-
function createTools(availableSkills, hooks = {}, context) {
|
|
11166
|
+
function createTools(availableSkills, hooks = {}, context, options = {}) {
|
|
10924
11167
|
const state = createToolState(hooks, context);
|
|
10925
11168
|
const slackContext = getSlackToolContext(context);
|
|
10926
11169
|
const slackSourceCapabilities = slackContext ? resolveChannelCapabilities(slackContext.sourceChannelId) : void 0;
|
|
@@ -10928,9 +11171,11 @@ function createTools(availableSkills, hooks = {}, context) {
|
|
|
10928
11171
|
slackContext && slackSourceCapabilities?.canSendFiles
|
|
10929
11172
|
);
|
|
10930
11173
|
const tools = {
|
|
10931
|
-
|
|
10932
|
-
|
|
10933
|
-
|
|
11174
|
+
...options.includeLoadSkill === false ? {} : {
|
|
11175
|
+
loadSkill: createLoadSkillTool(availableSkills, {
|
|
11176
|
+
onSkillLoaded: hooks.onSkillLoaded
|
|
11177
|
+
})
|
|
11178
|
+
},
|
|
10934
11179
|
reportProgress: createReportProgressTool(),
|
|
10935
11180
|
systemTime: createSystemTimeTool(),
|
|
10936
11181
|
bash: createBashTool(),
|
|
@@ -10952,6 +11197,13 @@ function createTools(availableSkills, hooks = {}, context) {
|
|
|
10952
11197
|
if (context.conversationId) {
|
|
10953
11198
|
tools.queryConversationEvents = createQueryConversationEventsTool(context);
|
|
10954
11199
|
}
|
|
11200
|
+
if (context.supportsImageInput) {
|
|
11201
|
+
tools.viewImage = createViewImageTool(
|
|
11202
|
+
context.workspace,
|
|
11203
|
+
context.supportsImageInput,
|
|
11204
|
+
hooks.toolOverrides?.viewImage
|
|
11205
|
+
);
|
|
11206
|
+
}
|
|
10955
11207
|
if (hooks.writeGeneratedArtifacts) {
|
|
10956
11208
|
tools.imageGenerate = createImageGenerateTool(
|
|
10957
11209
|
{
|
|
@@ -11546,6 +11798,8 @@ function isPluginToolInputError(error) {
|
|
|
11546
11798
|
}
|
|
11547
11799
|
function getToolErrorType(error) {
|
|
11548
11800
|
if (error instanceof McpToolError) return "tool_error";
|
|
11801
|
+
if (error instanceof McpProviderError) return "mcp_provider_error";
|
|
11802
|
+
if (error instanceof OAuthProviderError) return "oauth_provider_error";
|
|
11549
11803
|
if (error instanceof ToolInputError || isPluginToolInputError(error)) {
|
|
11550
11804
|
return "tool_input_error";
|
|
11551
11805
|
}
|
|
@@ -11568,6 +11822,8 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, trac
|
|
|
11568
11822
|
const errorMessage = getMcpAwareTelemetryMessage(error, conversationPrivacy);
|
|
11569
11823
|
const errorAttributes = {
|
|
11570
11824
|
"error.type": errorType,
|
|
11825
|
+
...getMcpProviderErrorAttributes(error),
|
|
11826
|
+
...getOAuthProviderErrorAttributes(error),
|
|
11571
11827
|
...error instanceof PluginCredentialFailureError ? { "app.credential.provider": error.provider } : {}
|
|
11572
11828
|
};
|
|
11573
11829
|
if (setExecutionSpanAttributes) {
|
|
@@ -11600,7 +11856,7 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, trac
|
|
|
11600
11856
|
"gen_ai.operation.name": "execute_tool",
|
|
11601
11857
|
"gen_ai.tool.name": toolName,
|
|
11602
11858
|
...toolCallId ? { "gen_ai.tool.call.id": toolCallId } : {},
|
|
11603
|
-
|
|
11859
|
+
...errorAttributes,
|
|
11604
11860
|
"exception.message": errorMessage
|
|
11605
11861
|
},
|
|
11606
11862
|
"Agent tool call failed"
|
|
@@ -11616,6 +11872,7 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, trac
|
|
|
11616
11872
|
"gen_ai.operation.name": "execute_tool",
|
|
11617
11873
|
"gen_ai.tool.name": toolName,
|
|
11618
11874
|
...toolCallId ? { "gen_ai.tool.call.id": toolCallId } : {},
|
|
11875
|
+
...errorAttributes,
|
|
11619
11876
|
...getToolErrorAttributes(error)
|
|
11620
11877
|
},
|
|
11621
11878
|
"Agent tool call failed"
|
|
@@ -11625,17 +11882,17 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, trac
|
|
|
11625
11882
|
}
|
|
11626
11883
|
|
|
11627
11884
|
// src/chat/tools/execute-tool.ts
|
|
11628
|
-
import { z as
|
|
11885
|
+
import { z as z42 } from "zod";
|
|
11629
11886
|
var EXECUTE_TOOL_NAME = "executeTool";
|
|
11630
11887
|
function createExecuteToolTool() {
|
|
11631
11888
|
return zodTool({
|
|
11632
11889
|
description: "Execute any catalog tool by exact tool_name from searchTools or a tool-result execution hint. Put tool-specific parameters inside arguments.",
|
|
11633
11890
|
executionMode: "sequential",
|
|
11634
|
-
inputSchema:
|
|
11635
|
-
tool_name:
|
|
11891
|
+
inputSchema: z42.object({
|
|
11892
|
+
tool_name: z42.string().min(1).describe(
|
|
11636
11893
|
"Exact catalog tool_name returned by searchTools or a tool-result execution hint."
|
|
11637
11894
|
),
|
|
11638
|
-
arguments:
|
|
11895
|
+
arguments: z42.record(z42.string(), z42.unknown()).describe(
|
|
11639
11896
|
'Arguments matching the selected catalog tool schema, for example { "query": "..." }.'
|
|
11640
11897
|
).optional()
|
|
11641
11898
|
}).strict(),
|
|
@@ -11675,42 +11932,42 @@ function planToolExposure(tools) {
|
|
|
11675
11932
|
}
|
|
11676
11933
|
|
|
11677
11934
|
// src/chat/tools/search-tools.ts
|
|
11678
|
-
import { z as
|
|
11935
|
+
import { z as z43 } from "zod";
|
|
11679
11936
|
var SEARCH_TOOLS_NAME = "searchTools";
|
|
11680
11937
|
var DEFAULT_MAX_RESULTS2 = 5;
|
|
11681
11938
|
var MAX_RESULTS3 = 20;
|
|
11682
11939
|
var MODEL_VISIBLE_DESCRIPTION_CAP = 180;
|
|
11683
|
-
var searchToolsSourceSchema =
|
|
11684
|
-
id:
|
|
11685
|
-
description:
|
|
11940
|
+
var searchToolsSourceSchema = z43.object({
|
|
11941
|
+
id: z43.string(),
|
|
11942
|
+
description: z43.string()
|
|
11686
11943
|
}).strict();
|
|
11687
|
-
var toolCallExampleSchema =
|
|
11688
|
-
tool_name:
|
|
11689
|
-
arguments:
|
|
11944
|
+
var toolCallExampleSchema = z43.object({
|
|
11945
|
+
tool_name: z43.string(),
|
|
11946
|
+
arguments: z43.record(z43.string(), z43.string())
|
|
11690
11947
|
}).strict();
|
|
11691
|
-
var searchToolsToolSchema =
|
|
11692
|
-
tool_name:
|
|
11693
|
-
description:
|
|
11694
|
-
exposure:
|
|
11695
|
-
source:
|
|
11696
|
-
signature:
|
|
11948
|
+
var searchToolsToolSchema = z43.object({
|
|
11949
|
+
tool_name: z43.string(),
|
|
11950
|
+
description: z43.string(),
|
|
11951
|
+
exposure: z43.enum(["direct", "deferred", "modelOnly", "hidden"]),
|
|
11952
|
+
source: z43.string().optional(),
|
|
11953
|
+
signature: z43.string(),
|
|
11697
11954
|
call: toolCallExampleSchema,
|
|
11698
|
-
input_schema:
|
|
11699
|
-
input_schema_summary:
|
|
11700
|
-
call_notes:
|
|
11701
|
-
annotations:
|
|
11955
|
+
input_schema: z43.unknown(),
|
|
11956
|
+
input_schema_summary: z43.string(),
|
|
11957
|
+
call_notes: z43.array(z43.string()),
|
|
11958
|
+
annotations: z43.record(z43.string(), z43.unknown())
|
|
11702
11959
|
}).strict();
|
|
11703
11960
|
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:
|
|
11961
|
+
query: z43.string().nullable(),
|
|
11962
|
+
source: z43.string().nullable(),
|
|
11963
|
+
sources: z43.array(searchToolsSourceSchema),
|
|
11964
|
+
total_catalog_tools: z43.number().int().nonnegative(),
|
|
11965
|
+
total_eligible_tools: z43.number().int().nonnegative(),
|
|
11966
|
+
total_matches: z43.number().int().nonnegative(),
|
|
11967
|
+
returned_tools: z43.number().int().nonnegative(),
|
|
11968
|
+
execution_tool: z43.literal("executeTool"),
|
|
11712
11969
|
execution_example: toolCallExampleSchema,
|
|
11713
|
-
tools:
|
|
11970
|
+
tools: z43.array(searchToolsToolSchema)
|
|
11714
11971
|
}).strict();
|
|
11715
11972
|
function normalize2(value) {
|
|
11716
11973
|
return value.toLowerCase().replace(/[^a-z0-9_]+/g, " ").trim();
|
|
@@ -11902,14 +12159,14 @@ function createSearchToolsTool(catalogTools) {
|
|
|
11902
12159
|
return zodTool({
|
|
11903
12160
|
description: renderSearchToolsDescription(knownSources),
|
|
11904
12161
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
11905
|
-
inputSchema:
|
|
11906
|
-
query:
|
|
12162
|
+
inputSchema: z43.object({
|
|
12163
|
+
query: z43.string().nullable().describe(
|
|
11907
12164
|
"Optional search terms describing the tool, owner, action, or arguments needed. Empty string lists catalog tools."
|
|
11908
12165
|
).optional(),
|
|
11909
|
-
source:
|
|
12166
|
+
source: z43.string().nullable().describe(
|
|
11910
12167
|
"Optional source id to search within, such as a plugin source returned in sources."
|
|
11911
12168
|
).optional(),
|
|
11912
|
-
max_results:
|
|
12169
|
+
max_results: z43.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
|
|
11913
12170
|
}).strict(),
|
|
11914
12171
|
outputSchema: searchToolsOutputSchema,
|
|
11915
12172
|
privateTraceResult: (result) => ({
|
|
@@ -12027,7 +12284,8 @@ function createPiAgentTools(tools, sandbox, spanContext, onStatus, sandboxTools,
|
|
|
12027
12284
|
const result = isSandbox ? await sandboxTools.execute({
|
|
12028
12285
|
toolName,
|
|
12029
12286
|
input: sandboxInput,
|
|
12030
|
-
...signal ? { signal } : {}
|
|
12287
|
+
...signal ? { signal } : {},
|
|
12288
|
+
...toolName === "grep" || toolName === "findFiles" ? { setToolCallSpanAttributes: setSpanAttributes2 } : {}
|
|
12031
12289
|
}) : await toolDef.execute(toolInput, {
|
|
12032
12290
|
experimental_context: sandbox,
|
|
12033
12291
|
...signal ? { signal } : {},
|
|
@@ -13174,6 +13432,27 @@ function createPluginEgress(deps) {
|
|
|
13174
13432
|
}
|
|
13175
13433
|
|
|
13176
13434
|
// src/chat/agent/tools.ts
|
|
13435
|
+
async function tryRecordSkillLoadStat(skill, spanContext) {
|
|
13436
|
+
if (!process.env.DATABASE_URL) return;
|
|
13437
|
+
try {
|
|
13438
|
+
await incrementStat({
|
|
13439
|
+
namespace: skill.pluginProvider ?? "junior",
|
|
13440
|
+
metric: "skill_load",
|
|
13441
|
+
name: skill.name
|
|
13442
|
+
});
|
|
13443
|
+
} catch (error) {
|
|
13444
|
+
logWarn(
|
|
13445
|
+
"skill_load_stat_failed",
|
|
13446
|
+
spanContext,
|
|
13447
|
+
{
|
|
13448
|
+
"app.skill.name": skill.name,
|
|
13449
|
+
"app.plugin.name": skill.pluginProvider,
|
|
13450
|
+
"exception.message": error instanceof Error ? error.message : String(error)
|
|
13451
|
+
},
|
|
13452
|
+
"Failed to record skill load stat"
|
|
13453
|
+
);
|
|
13454
|
+
}
|
|
13455
|
+
}
|
|
13177
13456
|
async function wireAgentTools(args) {
|
|
13178
13457
|
const runSource = args.routing.source;
|
|
13179
13458
|
const credentialUserId = args.routing.credentialContext ? credentialUserSubjectId(args.routing.credentialContext) : void 0;
|
|
@@ -13248,6 +13527,9 @@ async function wireAgentTools(args) {
|
|
|
13248
13527
|
const loadableSkills = args.availableSkills.filter(
|
|
13249
13528
|
(skill) => skill.disableModelInvocation !== true || skill.name === args.invokedSkill?.name
|
|
13250
13529
|
);
|
|
13530
|
+
const explicitSkillLoaded = Boolean(
|
|
13531
|
+
args.invokedSkill && args.activeSkills.some((skill) => skill.name === args.invokedSkill?.name)
|
|
13532
|
+
);
|
|
13251
13533
|
const commonToolRuntimeContext = {
|
|
13252
13534
|
conversationId: args.conversationId,
|
|
13253
13535
|
userText: args.userInput,
|
|
@@ -13272,6 +13554,7 @@ async function wireAgentTools(args) {
|
|
|
13272
13554
|
}),
|
|
13273
13555
|
mcpToolManager,
|
|
13274
13556
|
workspace: agentSandbox.workspace,
|
|
13557
|
+
supportsImageInput: args.supportsImageInput,
|
|
13275
13558
|
surface: args.surface,
|
|
13276
13559
|
...args.requestHandoff ? { handoff: args.requestHandoff } : {}
|
|
13277
13560
|
};
|
|
@@ -13327,6 +13610,7 @@ async function wireAgentTools(args) {
|
|
|
13327
13610
|
if (await mcpToolManager.activateForSkill(effective)) {
|
|
13328
13611
|
await args.recordConnectedMcpProvider(effective.pluginProvider);
|
|
13329
13612
|
}
|
|
13613
|
+
await tryRecordSkillLoadStat(effective, args.spanContext);
|
|
13330
13614
|
if (mcpAuth.getPendingPause()) {
|
|
13331
13615
|
return void 0;
|
|
13332
13616
|
}
|
|
@@ -13345,7 +13629,8 @@ async function wireAgentTools(args) {
|
|
|
13345
13629
|
};
|
|
13346
13630
|
}
|
|
13347
13631
|
},
|
|
13348
|
-
toolRuntimeContext
|
|
13632
|
+
toolRuntimeContext,
|
|
13633
|
+
{ includeLoadSkill: !explicitSkillLoaded }
|
|
13349
13634
|
);
|
|
13350
13635
|
const plannedToolExposure = planToolExposure(
|
|
13351
13636
|
tools
|
|
@@ -13430,7 +13715,11 @@ async function wireAgentTools(args) {
|
|
|
13430
13715
|
"mcp_tool_manager_close_failed",
|
|
13431
13716
|
{},
|
|
13432
13717
|
{
|
|
13433
|
-
|
|
13718
|
+
...getMcpProviderErrorAttributes(closeError),
|
|
13719
|
+
"exception.message": getMcpAwareTelemetryMessage(
|
|
13720
|
+
closeError,
|
|
13721
|
+
args.conversationPrivacy
|
|
13722
|
+
)
|
|
13434
13723
|
},
|
|
13435
13724
|
"Failed to close MCP tool manager"
|
|
13436
13725
|
);
|
|
@@ -13454,6 +13743,7 @@ function createResumeState(args) {
|
|
|
13454
13743
|
let latestSafeBoundaryMessages = [];
|
|
13455
13744
|
let timedOut = false;
|
|
13456
13745
|
let resumeMessages = [];
|
|
13746
|
+
let turnContexts = [];
|
|
13457
13747
|
let turnStartMessageIndex;
|
|
13458
13748
|
const currentSliceId = args.sessionRecordState.currentSliceId;
|
|
13459
13749
|
const currentDurationMs = () => Date.now() - args.startedAtMs;
|
|
@@ -13487,6 +13777,9 @@ function createResumeState(args) {
|
|
|
13487
13777
|
setBeforeMessageCount(count) {
|
|
13488
13778
|
beforeMessageCount = count;
|
|
13489
13779
|
},
|
|
13780
|
+
setTurnContexts(contexts) {
|
|
13781
|
+
turnContexts = contexts;
|
|
13782
|
+
},
|
|
13490
13783
|
/** Adopt an already committed epoch replacement as every resume baseline. */
|
|
13491
13784
|
adoptCommittedBoundary(messages) {
|
|
13492
13785
|
latestSafeBoundaryMessages = [...messages];
|
|
@@ -13514,6 +13807,7 @@ function createResumeState(args) {
|
|
|
13514
13807
|
sliceId: currentSliceId,
|
|
13515
13808
|
messages,
|
|
13516
13809
|
...trailingMessageProvenance ? { trailingMessageProvenance } : {},
|
|
13810
|
+
...turnContexts.length > 0 ? { turnContexts } : {},
|
|
13517
13811
|
...turnStartMessageIndex !== void 0 ? { turnStartMessageIndex } : {}
|
|
13518
13812
|
});
|
|
13519
13813
|
if (!persisted) {
|
|
@@ -13780,6 +14074,27 @@ function renderSummaryInput(piMessages, conversationContext) {
|
|
|
13780
14074
|
}
|
|
13781
14075
|
async function summarizeContext(args, deps) {
|
|
13782
14076
|
const source = renderSummaryInput(args.piMessages, args.conversationContext);
|
|
14077
|
+
const instructions = args.purpose === "active_turn" ? [
|
|
14078
|
+
"You are performing an ACTIVE-TURN CONTEXT CHECKPOINT COMPACTION for Junior.",
|
|
14079
|
+
"Create concise internal continuation state for the same agent run, which must continue the unfinished task immediately after this checkpoint.",
|
|
14080
|
+
"",
|
|
14081
|
+
"Include:",
|
|
14082
|
+
"- Work completed and concrete outcomes",
|
|
14083
|
+
"- Exact work currently in progress",
|
|
14084
|
+
"- The immediate next action",
|
|
14085
|
+
"- Durable constraints, user preferences, IDs, URLs, artifacts, sandbox references, auth state, and unresolved blockers",
|
|
14086
|
+
"",
|
|
14087
|
+
"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."
|
|
14088
|
+
] : [
|
|
14089
|
+
"You are performing a CONTEXT CHECKPOINT COMPACTION for Junior.",
|
|
14090
|
+
"Create a concise continuation summary for the agent that will continue this Slack thread.",
|
|
14091
|
+
"",
|
|
14092
|
+
"Include:",
|
|
14093
|
+
"- Current outstanding asks",
|
|
14094
|
+
"- Key decisions, completed work, and outcomes",
|
|
14095
|
+
"- Durable constraints, user preferences, IDs, URLs, artifacts, canvas links, sandbox references, and auth state",
|
|
14096
|
+
"- Clear next steps and unresolved blockers"
|
|
14097
|
+
];
|
|
13783
14098
|
const result = await deps.completeText({
|
|
13784
14099
|
modelId: botConfig.fastModelId,
|
|
13785
14100
|
messageAttributeMode: "metadata",
|
|
@@ -13789,14 +14104,7 @@ async function summarizeContext(args, deps) {
|
|
|
13789
14104
|
{
|
|
13790
14105
|
role: "user",
|
|
13791
14106
|
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",
|
|
14107
|
+
...instructions,
|
|
13800
14108
|
"",
|
|
13801
14109
|
"Do not invent details. Do not include raw secrets or credentials.",
|
|
13802
14110
|
"",
|
|
@@ -14022,7 +14330,8 @@ async function compactActiveContextIfNeeded(args, deps) {
|
|
|
14022
14330
|
summary = await summarizeContext(
|
|
14023
14331
|
{
|
|
14024
14332
|
...args,
|
|
14025
|
-
piMessages: args.piMessages
|
|
14333
|
+
piMessages: args.piMessages,
|
|
14334
|
+
purpose: "active_turn"
|
|
14026
14335
|
},
|
|
14027
14336
|
deps
|
|
14028
14337
|
);
|
|
@@ -14052,22 +14361,15 @@ async function compactActiveContextIfNeeded(args, deps) {
|
|
|
14052
14361
|
);
|
|
14053
14362
|
return { compacted: false, reason: "summary_failed" };
|
|
14054
14363
|
}
|
|
14055
|
-
const
|
|
14056
|
-
|
|
14057
|
-
|
|
14058
|
-
|
|
14059
|
-
|
|
14060
|
-
...runtimeMessage,
|
|
14061
|
-
content: [
|
|
14062
|
-
...runtimeMessage.content,
|
|
14063
|
-
{ type: "text", text: summaryText }
|
|
14064
|
-
]
|
|
14065
|
-
}
|
|
14066
|
-
] : [userMessage(summaryText)];
|
|
14364
|
+
const summaryMessage = userMessage(
|
|
14365
|
+
`${ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX}
|
|
14366
|
+
${summary}`
|
|
14367
|
+
);
|
|
14368
|
+
const runtimeMessages = retainRuntimeTurnContext(args.piMessages);
|
|
14067
14369
|
const retainedInstruction = pendingMessages.length === 0 ? await loadLastInstruction(args.conversationId) : void 0;
|
|
14068
14370
|
const instructionMessages = retainedInstruction ? [retainedInstruction.message] : pendingMessages.map((entry) => entry.message);
|
|
14069
14371
|
const instructionProvenance = retainedInstruction ? [retainedInstruction.provenance] : pendingMessages.map((entry) => entry.provenance);
|
|
14070
|
-
const messages = [...
|
|
14372
|
+
const messages = [...runtimeMessages, ...instructionMessages, summaryMessage];
|
|
14071
14373
|
const replacementInputTokens = estimateHistoryTokens(messages);
|
|
14072
14374
|
if (replacementInputTokens >= inputLimitTokens) {
|
|
14073
14375
|
throw new ContextInputLimitExceededError(
|
|
@@ -14100,10 +14402,11 @@ ${summary}`;
|
|
|
14100
14402
|
},
|
|
14101
14403
|
summary,
|
|
14102
14404
|
replacementHistory: replacementMessages.map((message, index) => {
|
|
14103
|
-
const
|
|
14405
|
+
const isSummary = index === replacementMessages.length - 1;
|
|
14406
|
+
const provenance = isSummary ? contextProvenance : instructionProvenance[index];
|
|
14104
14407
|
return {
|
|
14105
14408
|
item: historyItemFromPiMessage(message, provenance),
|
|
14106
|
-
...index ===
|
|
14409
|
+
...index === 0 && retainedInstruction ? { sourceEventSeq: retainedInstruction.sourceEventSeq } : {}
|
|
14107
14410
|
};
|
|
14108
14411
|
})
|
|
14109
14412
|
}
|
|
@@ -14130,12 +14433,12 @@ var AssistantMessageDeliveryError = class extends Error {
|
|
|
14130
14433
|
originalError;
|
|
14131
14434
|
};
|
|
14132
14435
|
function waitForAbortSettlement(promise, timeoutMs) {
|
|
14133
|
-
return new Promise((
|
|
14436
|
+
return new Promise((resolve2) => {
|
|
14134
14437
|
let done = false;
|
|
14135
14438
|
const timeoutId = setTimeout(() => {
|
|
14136
14439
|
if (!done) {
|
|
14137
14440
|
done = true;
|
|
14138
|
-
|
|
14441
|
+
resolve2(false);
|
|
14139
14442
|
}
|
|
14140
14443
|
}, timeoutMs);
|
|
14141
14444
|
timeoutId.unref?.();
|
|
@@ -14144,14 +14447,14 @@ function waitForAbortSettlement(promise, timeoutMs) {
|
|
|
14144
14447
|
if (!done) {
|
|
14145
14448
|
done = true;
|
|
14146
14449
|
clearTimeout(timeoutId);
|
|
14147
|
-
|
|
14450
|
+
resolve2(true);
|
|
14148
14451
|
}
|
|
14149
14452
|
},
|
|
14150
14453
|
() => {
|
|
14151
14454
|
if (!done) {
|
|
14152
14455
|
done = true;
|
|
14153
14456
|
clearTimeout(timeoutId);
|
|
14154
|
-
|
|
14457
|
+
resolve2(true);
|
|
14155
14458
|
}
|
|
14156
14459
|
}
|
|
14157
14460
|
);
|
|
@@ -14374,6 +14677,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
14374
14677
|
skillSandbox,
|
|
14375
14678
|
syncLoadedSkillNamesForResume
|
|
14376
14679
|
});
|
|
14680
|
+
const explicitSkill = invokedSkill ? activeSkills.find((skill) => skill.name === invokedSkill.name) ?? null : null;
|
|
14377
14681
|
const { routerBlocks, userContentParts } = buildPromptInput(input);
|
|
14378
14682
|
const preAgentPromptMessages = () => existingSessionRecord?.piMessages ?? [...input.piMessages ?? []];
|
|
14379
14683
|
const storedTurnRoute = await loadTurnRoute({ conversationId, turnId });
|
|
@@ -14577,6 +14881,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
14577
14881
|
skillSandbox,
|
|
14578
14882
|
spanContext,
|
|
14579
14883
|
state,
|
|
14884
|
+
supportsImageInput: () => resolveGatewayModel(activeModelId).input.includes("image"),
|
|
14580
14885
|
surface,
|
|
14581
14886
|
syncLoadedSkillNamesForResume,
|
|
14582
14887
|
toolCalls,
|
|
@@ -14592,7 +14897,8 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
14592
14897
|
inputMessagesAttribute,
|
|
14593
14898
|
promptContentParts,
|
|
14594
14899
|
promptHistoryMessages,
|
|
14595
|
-
shouldPromptAgent
|
|
14900
|
+
shouldPromptAgent,
|
|
14901
|
+
turnContexts
|
|
14596
14902
|
} = await assemblePrompt({
|
|
14597
14903
|
activeMcpCatalogs: wiring.activeMcpCatalogs,
|
|
14598
14904
|
currentActor: actor,
|
|
@@ -14602,7 +14908,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
14602
14908
|
conversationPrivacy,
|
|
14603
14909
|
existingSessionPiMessages: existingSessionRecord?.piMessages,
|
|
14604
14910
|
existingTurnStartMessageIndex: existingSessionRecord?.turnStartMessageIndex,
|
|
14605
|
-
|
|
14911
|
+
explicitSkill,
|
|
14606
14912
|
priorPiMessages,
|
|
14607
14913
|
resumedFromSessionRecord,
|
|
14608
14914
|
routing,
|
|
@@ -14611,6 +14917,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
|
|
|
14611
14917
|
toolRuntimeContext: wiring.toolRuntimeContext,
|
|
14612
14918
|
userContentParts
|
|
14613
14919
|
});
|
|
14920
|
+
runResume.setTurnContexts(turnContexts);
|
|
14614
14921
|
const applyPendingHandoff = () => {
|
|
14615
14922
|
if (!pendingHandoff) {
|
|
14616
14923
|
return void 0;
|