@sentry/junior 0.160.0 → 0.162.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-U6R3O2V4.js → agent-hooks-TL2SGC5W.js} +13 -10
- package/dist/api/locations/detail.d.ts +17 -0
- package/dist/api/people/plugin-reports.d.ts +7 -0
- package/dist/api/schema/conversation.d.ts +80 -8
- package/dist/api/schema/location.d.ts +30 -0
- package/dist/api/schema/person.d.ts +30 -0
- package/dist/api/schema.js +1 -1
- package/dist/api.js +128 -27
- package/dist/app.js +73 -42
- package/dist/{catalog-runtime-HIDNHGOP.js → catalog-runtime-IGSMIADJ.js} +5 -5
- package/dist/chat/artifacts/store.d.ts +42 -0
- package/dist/chat/conversations/message-search.d.ts +6 -0
- package/dist/chat/plugins/agent-hooks.d.ts +9 -1
- package/dist/chat/plugins/annotations.d.ts +3 -0
- package/dist/chat/plugins/conversation-sidebar.d.ts +3 -0
- package/dist/chat/plugins/viewer.d.ts +4 -0
- package/dist/chat/slack/mrkdwn.d.ts +3 -4
- package/dist/chat/slack/tools/conversation-message-search.d.ts +9 -0
- package/dist/chat/tools/publish-image.d.ts +44 -0
- package/dist/chat/tools/unpublish-image.d.ts +35 -0
- package/dist/{chunk-RJGRXDA7.js → chunk-4WYGQ47U.js} +5 -5
- package/dist/{chunk-FKMWPA4A.js → chunk-5NEBOHRG.js} +4 -4
- package/dist/{chunk-BGVQGEKB.js → chunk-6BJFIWEV.js} +4 -4
- package/dist/{chunk-TBRJGMTO.js → chunk-7DTPFFQX.js} +1 -1
- package/dist/{chunk-WACYTIIK.js → chunk-AJ7J2HWY.js} +6 -6
- package/dist/{chunk-YPMDNE7R.js → chunk-BPZQWAZJ.js} +1 -1
- package/dist/{chunk-TPFOVXRB.js → chunk-C3KUKA27.js} +19 -21
- package/dist/{chunk-4UO3UAW7.js → chunk-CZ6EHOU5.js} +239 -199
- package/dist/{chunk-JQZIUESN.js → chunk-DDQ43S5Q.js} +49 -4
- package/dist/{chunk-UNDTW2PY.js → chunk-DZC3F2UI.js} +1 -1
- package/dist/{chunk-42E7432W.js → chunk-EBEHJPFF.js} +1 -1
- package/dist/{chunk-M5HCOMDR.js → chunk-EHQLTK3X.js} +450 -115
- package/dist/{chunk-2SFMRMDV.js → chunk-FESUWAYU.js} +1 -1
- package/dist/{chunk-XPX3DYG7.js → chunk-FEWT5KPP.js} +2 -2
- package/dist/{chunk-2MK6S2UA.js → chunk-H2KW7AZC.js} +1 -1
- package/dist/{chunk-FJR66CQT.js → chunk-HW4BW3PC.js} +4 -4
- package/dist/{chunk-PZUJPPON.js → chunk-JJ3VXFDI.js} +1 -1
- package/dist/{chunk-MBDWMEO6.js → chunk-JRVURR3H.js} +10 -10
- package/dist/{chunk-756F567I.js → chunk-K7IV6UV3.js} +5 -5
- package/dist/{chunk-URPLKXLG.js → chunk-KQSO4DJ4.js} +9 -9
- package/dist/{chunk-LNUZXEEI.js → chunk-MMBMDSRK.js} +1 -1
- package/dist/{chunk-J77DLAPE.js → chunk-MNCEGXEH.js} +2 -2
- package/dist/{chunk-P7W3ZL5J.js → chunk-O6P7DZ6O.js} +8 -36
- package/dist/{chunk-PVIM2RWO.js → chunk-OBFRMQBY.js} +8 -10
- package/dist/{chunk-3AHIB66R.js → chunk-OPNJRQDP.js} +5 -5
- package/dist/{chunk-U26KRMYX.js → chunk-QHCIZLIX.js} +537 -27
- package/dist/{chunk-472VVYYV.js → chunk-RDV4BQRZ.js} +1 -1
- package/dist/{chunk-UYUS4L6F.js → chunk-SA6BEEAB.js} +16 -9
- package/dist/{chunk-HDPH4CHJ.js → chunk-THXMSSFZ.js} +1 -1
- package/dist/{chunk-RLOXMHLA.js → chunk-V7QL4QMW.js} +4 -4
- package/dist/{chunk-56TFPTZU.js → chunk-WHAJ3QVY.js} +1 -1
- package/dist/{chunk-ZNBGWMVQ.js → chunk-Y75ZDQB5.js} +1 -1
- package/dist/cli/chat.js +29 -30
- package/dist/cli/check.js +6 -6
- package/dist/cli/plugins.js +12 -13
- package/dist/cli/snapshot-create.js +9 -9
- package/dist/cli/upgrade.js +7 -7
- package/dist/db/schema/artifacts.d.ts +178 -0
- package/dist/db/schema.d.ts +179 -1
- package/dist/{db-2JKT3BB5.js → db-66XZ4HHQ.js} +7 -7
- package/dist/handlers/artifacts.d.ts +8 -0
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +2 -2
- package/dist/{oauth-callback-server-7MC2UMQC.js → oauth-callback-server-FMLKDUUF.js} +22 -23
- package/dist/{runner-GUU4G7XO.js → runner-YZONUMNY.js} +12 -13
- package/dist/{skills-7NW5N3VM.js → skills-3UDJJXSO.js} +6 -6
- package/dist/spawn-TBPVA5S2.js +37 -0
- package/dist/{validation-AQLI6N2C.js → validation-3HTDBONC.js} +6 -6
- package/dist/version.js +1 -1
- package/dist/{work-FLFK5XNU.js → work-O4YTIS54.js} +17 -17
- package/dist/worker-WHURUEYX.js +24 -0
- package/migrations/0028_artifacts.sql +16 -0
- package/migrations/meta/0028_snapshot.json +2685 -0
- package/migrations/meta/_journal.json +8 -1
- package/package.json +4 -4
- package/dist/chunk-OUAZDZTZ.js +0 -441
- package/dist/spawn-WGK4W3XF.js +0 -37
- package/dist/worker-KSJIRBQJ.js +0 -24
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
PluginCredentialFailureError,
|
|
8
8
|
agentNameSchema,
|
|
9
9
|
createPluginAuthOrchestration
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-K7IV6UV3.js";
|
|
11
11
|
import {
|
|
12
12
|
authorizationId
|
|
13
13
|
} from "./chunk-DIB4GX3G.js";
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
searchSlackUsers,
|
|
33
33
|
selectPluginGrant,
|
|
34
34
|
toMcpProviderError
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-OBFRMQBY.js";
|
|
36
36
|
import {
|
|
37
37
|
RetryableDeliveryError,
|
|
38
38
|
actorFromRun,
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
getSlackMessagePermalink,
|
|
49
49
|
resolveBaseUrl,
|
|
50
50
|
uploadFilesToConversation
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-O6P7DZ6O.js";
|
|
52
52
|
import {
|
|
53
53
|
parseSandboxEgressAuthRequiredSignal,
|
|
54
54
|
parseSandboxEgressPermissionDeniedSignal,
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
runNonInteractiveCommand,
|
|
75
75
|
throwSandboxOperationError,
|
|
76
76
|
wrapSandboxSetupError
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-6BJFIWEV.js";
|
|
78
78
|
import {
|
|
79
79
|
SCHEDULED_TASK_SYSTEM_ACTOR,
|
|
80
80
|
compactEventTask,
|
|
@@ -107,10 +107,10 @@ import {
|
|
|
107
107
|
scheduledTaskAttributes,
|
|
108
108
|
storeAttachments,
|
|
109
109
|
writableEventTask
|
|
110
|
-
} from "./chunk-
|
|
110
|
+
} from "./chunk-4WYGQ47U.js";
|
|
111
111
|
import {
|
|
112
112
|
parseSlackThreadId
|
|
113
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-WHAJ3QVY.js";
|
|
114
114
|
import {
|
|
115
115
|
AGENTS_REMOVAL_NOTICE,
|
|
116
116
|
AGENTS_REPLACEMENT_NOTICE,
|
|
@@ -181,7 +181,7 @@ import {
|
|
|
181
181
|
stripRuntimeTurnContext,
|
|
182
182
|
trimTrailingAssistantMessages,
|
|
183
183
|
truncateText
|
|
184
|
-
} from "./chunk-
|
|
184
|
+
} from "./chunk-V7QL4QMW.js";
|
|
185
185
|
import {
|
|
186
186
|
JUNIOR_THREAD_STATE_TTL_MS
|
|
187
187
|
} from "./chunk-3Y47VMHV.js";
|
|
@@ -189,24 +189,22 @@ import {
|
|
|
189
189
|
privateTraceResultAttributes
|
|
190
190
|
} from "./chunk-UIE3R5XU.js";
|
|
191
191
|
import {
|
|
192
|
+
SlackActionError,
|
|
192
193
|
createPluginHookRunner,
|
|
194
|
+
downloadPrivateSlackFile,
|
|
193
195
|
getDashboardTaskLink,
|
|
196
|
+
getFilePermalink,
|
|
194
197
|
getPluginSystemPromptContributions,
|
|
195
198
|
getPluginTools,
|
|
196
199
|
getPluginUserPromptContributions,
|
|
197
|
-
getSlackToolContext,
|
|
198
|
-
readActorIdentity,
|
|
199
|
-
resolveChannelCapabilities
|
|
200
|
-
} from "./chunk-U26KRMYX.js";
|
|
201
|
-
import {
|
|
202
|
-
SlackActionError,
|
|
203
|
-
downloadPrivateSlackFile,
|
|
204
|
-
getFilePermalink,
|
|
205
200
|
getSlackClient,
|
|
201
|
+
getSlackToolContext,
|
|
206
202
|
isConversationScopedChannel,
|
|
207
203
|
normalizeSlackConversationId,
|
|
204
|
+
readActorIdentity,
|
|
205
|
+
resolveChannelCapabilities,
|
|
208
206
|
withSlackRetries
|
|
209
|
-
} from "./chunk-
|
|
207
|
+
} from "./chunk-QHCIZLIX.js";
|
|
210
208
|
import {
|
|
211
209
|
KNOWN_CONVERSATION_EVENT_TYPES,
|
|
212
210
|
contextProvenance,
|
|
@@ -218,10 +216,11 @@ import {
|
|
|
218
216
|
instructionActors,
|
|
219
217
|
instructionProvenanceFor,
|
|
220
218
|
sameActorIdentity
|
|
221
|
-
} from "./chunk-
|
|
219
|
+
} from "./chunk-DDQ43S5Q.js";
|
|
222
220
|
import {
|
|
221
|
+
juniorArtifacts,
|
|
223
222
|
juniorIdentities
|
|
224
|
-
} from "./chunk-
|
|
223
|
+
} from "./chunk-CZ6EHOU5.js";
|
|
225
224
|
import {
|
|
226
225
|
SANDBOX_DATA_ROOT,
|
|
227
226
|
SANDBOX_SKILLS_ROOT,
|
|
@@ -233,7 +232,7 @@ import {
|
|
|
233
232
|
} from "./chunk-EM225ITJ.js";
|
|
234
233
|
import {
|
|
235
234
|
getStateAdapter
|
|
236
|
-
} from "./chunk-
|
|
235
|
+
} from "./chunk-DZC3F2UI.js";
|
|
237
236
|
import {
|
|
238
237
|
ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX,
|
|
239
238
|
COMPACTION_SUMMARY_PREFIX,
|
|
@@ -266,7 +265,7 @@ import {
|
|
|
266
265
|
resolveGatewayCredential,
|
|
267
266
|
resolveGatewayModel,
|
|
268
267
|
unwrapCurrentInstruction
|
|
269
|
-
} from "./chunk-
|
|
268
|
+
} from "./chunk-MNCEGXEH.js";
|
|
270
269
|
import {
|
|
271
270
|
canExposeConversationPayload,
|
|
272
271
|
resolveConversationPrivacy,
|
|
@@ -276,16 +275,16 @@ import {
|
|
|
276
275
|
toGenAiMessagesTraceAttributes,
|
|
277
276
|
toGenAiPayloadMetadata,
|
|
278
277
|
toGenAiPayloadTraceAttributes
|
|
279
|
-
} from "./chunk-
|
|
278
|
+
} from "./chunk-7DTPFFQX.js";
|
|
280
279
|
import {
|
|
281
280
|
discoverSkills,
|
|
282
281
|
findSkillByName,
|
|
283
282
|
loadSkillsByName,
|
|
284
283
|
parseSkillInvocation
|
|
285
|
-
} from "./chunk-
|
|
284
|
+
} from "./chunk-FEWT5KPP.js";
|
|
286
285
|
import {
|
|
287
286
|
pluginCatalogRuntime
|
|
288
|
-
} from "./chunk-
|
|
287
|
+
} from "./chunk-FESUWAYU.js";
|
|
289
288
|
import {
|
|
290
289
|
CredentialUnavailableError,
|
|
291
290
|
OAuthProviderError,
|
|
@@ -293,7 +292,7 @@ import {
|
|
|
293
292
|
getOAuthProviderErrorAttributes,
|
|
294
293
|
resolveAuthTokenPlaceholder,
|
|
295
294
|
resolvePluginCommandEnv
|
|
296
|
-
} from "./chunk-
|
|
295
|
+
} from "./chunk-EBEHJPFF.js";
|
|
297
296
|
import {
|
|
298
297
|
credentialUserSubjectId
|
|
299
298
|
} from "./chunk-BDUENQD3.js";
|
|
@@ -321,7 +320,7 @@ import {
|
|
|
321
320
|
summarizeMessageText,
|
|
322
321
|
withLogContext,
|
|
323
322
|
withSpan
|
|
324
|
-
} from "./chunk-
|
|
323
|
+
} from "./chunk-Y75ZDQB5.js";
|
|
325
324
|
import {
|
|
326
325
|
startInactiveSpan,
|
|
327
326
|
withActiveSpan
|
|
@@ -1732,7 +1731,6 @@ function buildOutputSection(platform) {
|
|
|
1732
1731
|
`<output format="markdown">`,
|
|
1733
1732
|
"- Start with the answer or result, not internal process narration.",
|
|
1734
1733
|
"- Use concise Markdown suitable for terminal output: short paragraphs, bullets, links, and fenced code blocks when helpful.",
|
|
1735
|
-
"- When you mention a pull request, include a direct link. Prefer the full PR URL or a Markdown link; do not leave bare `PR #123` text without a URL or repo.",
|
|
1736
1734
|
"- End every turn with a final user-facing response.",
|
|
1737
1735
|
"</output>"
|
|
1738
1736
|
].join("\n");
|
|
@@ -1742,7 +1740,6 @@ function buildOutputSection(platform) {
|
|
|
1742
1740
|
"- Default to the shortest complete reply\u2014usually 1\u20135 sentences and under 800 characters. Include only the outcome, decisive evidence, and any blocker or required next action. If useful detail would exceed that, put it in a Slack canvas and reply with the link. An explicit user request for detail overrides this target.",
|
|
1743
1741
|
"- Start with the answer or result, not internal process narration.",
|
|
1744
1742
|
"- Use Slack-flavored Markdown: **bold** section labels, `code`, [text](url) links, bullet lists, and fenced code blocks. No hash-prefixed headings and no tables. When the answer primarily lists several URLs, show each URL bare instead of as a labeled link.",
|
|
1745
|
-
"- When you mention a pull request, include a direct link. Prefer the full PR URL or a Markdown link; `owner/repo#number` is also accepted and is linkified on delivery. Do not leave bare `PR #123` text without a URL or repo.",
|
|
1746
1743
|
"- End every turn with a final user-facing markdown response unless the Slack action rules allow a no-reply completion.",
|
|
1747
1744
|
"</output>"
|
|
1748
1745
|
].join("\n");
|
|
@@ -3982,7 +3979,7 @@ function parseToolInput(schema, args) {
|
|
|
3982
3979
|
return result.data;
|
|
3983
3980
|
}
|
|
3984
3981
|
function zodTool(definition) {
|
|
3985
|
-
const { inputSchema: inputSchema2, outputSchema:
|
|
3982
|
+
const { inputSchema: inputSchema2, outputSchema: outputSchema7, prepareArguments, execute, ...toolDef } = definition;
|
|
3986
3983
|
let modelInputSchema;
|
|
3987
3984
|
try {
|
|
3988
3985
|
modelInputSchema = z3.toJSONSchema(inputSchema2);
|
|
@@ -3993,9 +3990,9 @@ function zodTool(definition) {
|
|
|
3993
3990
|
);
|
|
3994
3991
|
}
|
|
3995
3992
|
let modelOutputSchema;
|
|
3996
|
-
if (
|
|
3993
|
+
if (outputSchema7) {
|
|
3997
3994
|
try {
|
|
3998
|
-
modelOutputSchema = z3.toJSONSchema(
|
|
3995
|
+
modelOutputSchema = z3.toJSONSchema(outputSchema7);
|
|
3999
3996
|
} catch (error) {
|
|
4000
3997
|
throw new TypeError(
|
|
4001
3998
|
"zodTool() outputSchema must be representable as JSON Schema.",
|
|
@@ -4019,7 +4016,7 @@ function zodTool(definition) {
|
|
|
4019
4016
|
input,
|
|
4020
4017
|
options
|
|
4021
4018
|
);
|
|
4022
|
-
if (!
|
|
4019
|
+
if (!outputSchema7) {
|
|
4023
4020
|
if (isContentOnlyToolResult(result)) {
|
|
4024
4021
|
return result;
|
|
4025
4022
|
}
|
|
@@ -4030,10 +4027,10 @@ function zodTool(definition) {
|
|
|
4030
4027
|
if (isStructuredToolResultEnvelope(result)) {
|
|
4031
4028
|
return {
|
|
4032
4029
|
content: parseToolContent(result.content),
|
|
4033
|
-
details:
|
|
4030
|
+
details: outputSchema7.parse(result.details)
|
|
4034
4031
|
};
|
|
4035
4032
|
}
|
|
4036
|
-
return
|
|
4033
|
+
return outputSchema7.parse(result);
|
|
4037
4034
|
}
|
|
4038
4035
|
} : {}
|
|
4039
4036
|
};
|
|
@@ -6494,7 +6491,7 @@ var McpToolManager = class {
|
|
|
6494
6491
|
return client;
|
|
6495
6492
|
}
|
|
6496
6493
|
toManagedTool(plugin, client, tool) {
|
|
6497
|
-
const
|
|
6494
|
+
const outputSchema7 = toOptionalRecord(tool.outputSchema);
|
|
6498
6495
|
const annotations = tool.annotations;
|
|
6499
6496
|
const missingAnnotationKeys = missingToolAnnotationKeys(annotations);
|
|
6500
6497
|
if (missingAnnotationKeys.length > 0) {
|
|
@@ -6511,7 +6508,7 @@ var McpToolManager = class {
|
|
|
6511
6508
|
provider: plugin.manifest.name,
|
|
6512
6509
|
rawName: tool.name,
|
|
6513
6510
|
...tool.title?.trim() ? { title: tool.title.trim() } : {},
|
|
6514
|
-
...
|
|
6511
|
+
...outputSchema7 ? { outputSchema: outputSchema7 } : {},
|
|
6515
6512
|
...annotations ? { annotations } : {},
|
|
6516
6513
|
execute: async (args, options) => {
|
|
6517
6514
|
const resolvedArgs = typeof args === "object" && args !== null ? args : {};
|
|
@@ -10011,8 +10008,12 @@ var CONVERSATIONS_TOOL_SOURCE = {
|
|
|
10011
10008
|
};
|
|
10012
10009
|
|
|
10013
10010
|
// src/chat/slack/tools/conversation-message-search.ts
|
|
10014
|
-
var DEFAULT_LIMIT =
|
|
10011
|
+
var DEFAULT_LIMIT = 20;
|
|
10012
|
+
var MAX_LIMIT = 50;
|
|
10015
10013
|
var conversationMessageSearchOutputSchema = juniorToolOutputSchema.extend({
|
|
10014
|
+
after: z39.string().datetime().optional(),
|
|
10015
|
+
annotation: z39.string().min(1).optional(),
|
|
10016
|
+
before: z39.string().datetime().optional(),
|
|
10016
10017
|
channel_id: z39.string().min(1).optional(),
|
|
10017
10018
|
count: z39.number().int().nonnegative(),
|
|
10018
10019
|
query: z39.string().optional(),
|
|
@@ -10030,8 +10031,21 @@ var conversationMessageSearchOutputSchema = juniorToolOutputSchema.extend({
|
|
|
10030
10031
|
}).strict()
|
|
10031
10032
|
)
|
|
10032
10033
|
});
|
|
10034
|
+
function parseTimestamp(field, value) {
|
|
10035
|
+
if (value == null || value.trim() === "") {
|
|
10036
|
+
return void 0;
|
|
10037
|
+
}
|
|
10038
|
+
const parsed = Date.parse(value);
|
|
10039
|
+
if (!Number.isFinite(parsed)) {
|
|
10040
|
+
throw new ToolInputError(`${field} must be a valid ISO-8601 timestamp`);
|
|
10041
|
+
}
|
|
10042
|
+
return parsed;
|
|
10043
|
+
}
|
|
10033
10044
|
async function resolveSearchFilters(input) {
|
|
10034
10045
|
const query = input.query?.trim() || void 0;
|
|
10046
|
+
const annotation = input.annotation?.trim() || void 0;
|
|
10047
|
+
const afterMs = parseTimestamp("after", input.after);
|
|
10048
|
+
const beforeMs = parseTimestamp("before", input.before);
|
|
10035
10049
|
let channelId;
|
|
10036
10050
|
if (input.channel_id != null && input.channel_id.trim() !== "") {
|
|
10037
10051
|
const target = await resolveSlackChannelRef({
|
|
@@ -10040,19 +10054,25 @@ async function resolveSearchFilters(input) {
|
|
|
10040
10054
|
});
|
|
10041
10055
|
channelId = target.channelId;
|
|
10042
10056
|
}
|
|
10043
|
-
if (
|
|
10057
|
+
if (afterMs !== void 0 && beforeMs !== void 0 && afterMs >= beforeMs) {
|
|
10058
|
+
throw new ToolInputError("`after` must be earlier than `before`");
|
|
10059
|
+
}
|
|
10060
|
+
if (!query && !channelId && !annotation) {
|
|
10044
10061
|
throw new ToolInputError(
|
|
10045
|
-
"Provide at least one of `query` or `
|
|
10062
|
+
"Provide at least one of `query`, `channel_id`, or `annotation`."
|
|
10046
10063
|
);
|
|
10047
10064
|
}
|
|
10048
10065
|
return {
|
|
10066
|
+
...afterMs !== void 0 ? { afterMs } : {},
|
|
10067
|
+
...annotation ? { annotation } : {},
|
|
10068
|
+
...beforeMs !== void 0 ? { beforeMs } : {},
|
|
10049
10069
|
...channelId ? { channelId } : {},
|
|
10050
10070
|
...query ? { query } : {}
|
|
10051
10071
|
};
|
|
10052
10072
|
}
|
|
10053
10073
|
function createSlackConversationMessageSearchTool(scope, currentConversationId) {
|
|
10054
10074
|
return zodTool({
|
|
10055
|
-
description: "Search retained user and assistant messages from public conversations in this Slack workspace. Excludes the current conversation. Not live Slack workspace search.",
|
|
10075
|
+
description: "Search retained user and assistant messages from public conversations in this Slack workspace. Filter by message text, channel, time range, or linked annotation such as a resource key. Excludes the current conversation. Not live Slack workspace search.",
|
|
10056
10076
|
exposure: "deferred",
|
|
10057
10077
|
source: CONVERSATIONS_TOOL_SOURCE,
|
|
10058
10078
|
annotations: {
|
|
@@ -10062,9 +10082,16 @@ function createSlackConversationMessageSearchTool(scope, currentConversationId)
|
|
|
10062
10082
|
readOnlyHint: true
|
|
10063
10083
|
},
|
|
10064
10084
|
inputSchema: z39.object({
|
|
10085
|
+
after: z39.string().datetime().nullable().describe("Include conversations active at or after this timestamp.").optional(),
|
|
10086
|
+
annotation: z39.string().trim().min(1).max(256).nullable().describe(
|
|
10087
|
+
"Linked resource key. Matches that key, or nested children that continue with #."
|
|
10088
|
+
).optional(),
|
|
10089
|
+
before: z39.string().datetime().nullable().describe("Include conversations active before this timestamp.").optional(),
|
|
10065
10090
|
channel_id: slackChannelRefParam.nullable().optional(),
|
|
10066
10091
|
query: z39.string().trim().min(1).max(200).nullable().describe("Words or phrase to match in message text.").optional(),
|
|
10067
|
-
limit: z39.number().int().min(1).max(
|
|
10092
|
+
limit: z39.number().int().min(1).max(MAX_LIMIT).describe(
|
|
10093
|
+
`Maximum conversations. Default ${DEFAULT_LIMIT}; max ${MAX_LIMIT}.`
|
|
10094
|
+
).nullable().optional()
|
|
10068
10095
|
}).strict(),
|
|
10069
10096
|
outputSchema: conversationMessageSearchOutputSchema,
|
|
10070
10097
|
execute: async (input) => {
|
|
@@ -10102,6 +10129,9 @@ function createSlackConversationMessageSearchTool(scope, currentConversationId)
|
|
|
10102
10129
|
})
|
|
10103
10130
|
);
|
|
10104
10131
|
return {
|
|
10132
|
+
...filters.afterMs !== void 0 ? { after: new Date(filters.afterMs).toISOString() } : {},
|
|
10133
|
+
...filters.annotation ? { annotation: filters.annotation } : {},
|
|
10134
|
+
...filters.beforeMs !== void 0 ? { before: new Date(filters.beforeMs).toISOString() } : {},
|
|
10105
10135
|
...filters.query ? { query: filters.query } : {},
|
|
10106
10136
|
...filters.channelId ? { channel_id: filters.channelId } : {},
|
|
10107
10137
|
count: matchesOutput.length,
|
|
@@ -12307,28 +12337,318 @@ function getTimeZoneOffsetMinutes(timestampMs, timezone) {
|
|
|
12307
12337
|
return Math.round((timestampMs - asUtcMs) / 6e4);
|
|
12308
12338
|
}
|
|
12309
12339
|
|
|
12310
|
-
// src/chat/tools/
|
|
12340
|
+
// src/chat/tools/publish-image.ts
|
|
12311
12341
|
import { z as z56 } from "zod";
|
|
12342
|
+
|
|
12343
|
+
// src/chat/artifacts/store.ts
|
|
12344
|
+
import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
|
|
12345
|
+
import { and as and2, eq as eq2, isNull } from "drizzle-orm";
|
|
12346
|
+
var MAX_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
12347
|
+
var IMAGE_TYPES = {
|
|
12348
|
+
gif: "image/gif",
|
|
12349
|
+
jpg: "image/jpeg",
|
|
12350
|
+
png: "image/png",
|
|
12351
|
+
webp: "image/webp"
|
|
12352
|
+
};
|
|
12353
|
+
var FILENAME_RE = /^([0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\.(gif|jpg|png|webp)$/i;
|
|
12354
|
+
function detectImageType(data) {
|
|
12355
|
+
if (data.length >= 8 && data.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
|
|
12356
|
+
return { contentType: IMAGE_TYPES.png, extension: "png" };
|
|
12357
|
+
}
|
|
12358
|
+
if (data.length >= 3 && data[0] === 255 && data[1] === 216 && data[2] === 255) {
|
|
12359
|
+
return { contentType: IMAGE_TYPES.jpg, extension: "jpg" };
|
|
12360
|
+
}
|
|
12361
|
+
if (data.length >= 6 && (data.subarray(0, 6).toString("ascii") === "GIF87a" || data.subarray(0, 6).toString("ascii") === "GIF89a")) {
|
|
12362
|
+
return { contentType: IMAGE_TYPES.gif, extension: "gif" };
|
|
12363
|
+
}
|
|
12364
|
+
if (data.length >= 12 && data.subarray(0, 4).toString("ascii") === "RIFF" && data.subarray(8, 12).toString("ascii") === "WEBP") {
|
|
12365
|
+
return { contentType: IMAGE_TYPES.webp, extension: "webp" };
|
|
12366
|
+
}
|
|
12367
|
+
return null;
|
|
12368
|
+
}
|
|
12369
|
+
function artifactKey(filename) {
|
|
12370
|
+
return `artifacts/${filename}`;
|
|
12371
|
+
}
|
|
12372
|
+
function parseArtifactFilename(filename) {
|
|
12373
|
+
const match = filename.match(FILENAME_RE);
|
|
12374
|
+
if (!match) return null;
|
|
12375
|
+
return {
|
|
12376
|
+
id: match[1].toLowerCase(),
|
|
12377
|
+
ext: match[2].toLowerCase()
|
|
12378
|
+
};
|
|
12379
|
+
}
|
|
12380
|
+
function artifactFilenameFromRef(ref) {
|
|
12381
|
+
const trimmed = ref.trim();
|
|
12382
|
+
if (FILENAME_RE.test(trimmed)) {
|
|
12383
|
+
const parsed = parseArtifactFilename(trimmed);
|
|
12384
|
+
return parsed ? `${parsed.id}.${parsed.ext}` : null;
|
|
12385
|
+
}
|
|
12386
|
+
try {
|
|
12387
|
+
const url = new URL(trimmed);
|
|
12388
|
+
const marker = "/public/artifacts/";
|
|
12389
|
+
const index = url.pathname.lastIndexOf(marker);
|
|
12390
|
+
if (index === -1) return null;
|
|
12391
|
+
const filename = url.pathname.slice(index + marker.length);
|
|
12392
|
+
const parsed = parseArtifactFilename(filename);
|
|
12393
|
+
return parsed ? `${parsed.id}.${parsed.ext}` : null;
|
|
12394
|
+
} catch {
|
|
12395
|
+
return null;
|
|
12396
|
+
}
|
|
12397
|
+
}
|
|
12398
|
+
function resolvePublicBaseUrl(publicBaseUrl) {
|
|
12399
|
+
const baseUrl = publicBaseUrl.trim().replace(/\/+$/, "");
|
|
12400
|
+
let parsedBaseUrl;
|
|
12401
|
+
try {
|
|
12402
|
+
parsedBaseUrl = new URL(baseUrl);
|
|
12403
|
+
} catch {
|
|
12404
|
+
throw new Error("public base URL must be an absolute HTTP(S) URL");
|
|
12405
|
+
}
|
|
12406
|
+
if (parsedBaseUrl.protocol !== "http:" && parsedBaseUrl.protocol !== "https:") {
|
|
12407
|
+
throw new Error("public base URL must use HTTP(S)");
|
|
12408
|
+
}
|
|
12409
|
+
return baseUrl;
|
|
12410
|
+
}
|
|
12411
|
+
async function publishImage(args) {
|
|
12412
|
+
if (args.body.byteLength === 0) {
|
|
12413
|
+
throw new ToolInputError("image is empty");
|
|
12414
|
+
}
|
|
12415
|
+
if (args.body.byteLength > MAX_IMAGE_BYTES) {
|
|
12416
|
+
throw new ToolInputError(
|
|
12417
|
+
`image exceeds ${MAX_IMAGE_BYTES} bytes (${args.body.byteLength} bytes)`
|
|
12418
|
+
);
|
|
12419
|
+
}
|
|
12420
|
+
const imageType = detectImageType(args.body);
|
|
12421
|
+
if (!imageType) {
|
|
12422
|
+
throw new ToolInputError(
|
|
12423
|
+
"unsupported image format; use PNG, JPEG, GIF, or WebP"
|
|
12424
|
+
);
|
|
12425
|
+
}
|
|
12426
|
+
const baseUrl = resolvePublicBaseUrl(args.publicBaseUrl);
|
|
12427
|
+
const sha256 = createHash5("sha256").update(args.body).digest("hex");
|
|
12428
|
+
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
12429
|
+
const [existing] = await args.db.db().select({
|
|
12430
|
+
id: juniorArtifacts.id
|
|
12431
|
+
}).from(juniorArtifacts).where(
|
|
12432
|
+
and2(
|
|
12433
|
+
eq2(juniorArtifacts.conversationId, args.conversationId),
|
|
12434
|
+
eq2(juniorArtifacts.sha256, sha256)
|
|
12435
|
+
)
|
|
12436
|
+
);
|
|
12437
|
+
const id = existing?.id ?? randomUUID3();
|
|
12438
|
+
const filename = `${id}.${imageType.extension}`;
|
|
12439
|
+
const storageKey = artifactKey(filename);
|
|
12440
|
+
await args.storage.put({
|
|
12441
|
+
body: args.body,
|
|
12442
|
+
contentType: imageType.contentType,
|
|
12443
|
+
key: storageKey
|
|
12444
|
+
});
|
|
12445
|
+
const [row] = await args.db.db().insert(juniorArtifacts).values({
|
|
12446
|
+
bytes: args.body.byteLength,
|
|
12447
|
+
contentType: imageType.contentType,
|
|
12448
|
+
conversationId: args.conversationId,
|
|
12449
|
+
createdAt: now,
|
|
12450
|
+
deleteRequestedAt: null,
|
|
12451
|
+
ext: imageType.extension,
|
|
12452
|
+
id,
|
|
12453
|
+
public: true,
|
|
12454
|
+
sha256,
|
|
12455
|
+
storageKey
|
|
12456
|
+
}).onConflictDoUpdate({
|
|
12457
|
+
target: [juniorArtifacts.conversationId, juniorArtifacts.sha256],
|
|
12458
|
+
set: {
|
|
12459
|
+
bytes: args.body.byteLength,
|
|
12460
|
+
contentType: imageType.contentType,
|
|
12461
|
+
deleteRequestedAt: null,
|
|
12462
|
+
ext: imageType.extension,
|
|
12463
|
+
public: true
|
|
12464
|
+
// Keep the winning row's id/storage key. A raced put may leave an
|
|
12465
|
+
// unused object; that is fine for mvp.
|
|
12466
|
+
}
|
|
12467
|
+
}).returning({
|
|
12468
|
+
ext: juniorArtifacts.ext,
|
|
12469
|
+
id: juniorArtifacts.id
|
|
12470
|
+
});
|
|
12471
|
+
if (!row) {
|
|
12472
|
+
throw new Error("failed to publish artifact row");
|
|
12473
|
+
}
|
|
12474
|
+
return {
|
|
12475
|
+
bytes: args.body.byteLength,
|
|
12476
|
+
contentType: imageType.contentType,
|
|
12477
|
+
url: `${baseUrl}/public/artifacts/${row.id}.${row.ext}`
|
|
12478
|
+
};
|
|
12479
|
+
}
|
|
12480
|
+
async function unpublishArtifact(args) {
|
|
12481
|
+
const filename = artifactFilenameFromRef(args.ref);
|
|
12482
|
+
if (!filename) {
|
|
12483
|
+
throw new ToolInputError(
|
|
12484
|
+
"artifact ref must be a public artifact URL or <id>.<ext> filename"
|
|
12485
|
+
);
|
|
12486
|
+
}
|
|
12487
|
+
const parsed = parseArtifactFilename(filename);
|
|
12488
|
+
if (!parsed) {
|
|
12489
|
+
throw new ToolInputError(
|
|
12490
|
+
"artifact ref must be a public artifact URL or <id>.<ext> filename"
|
|
12491
|
+
);
|
|
12492
|
+
}
|
|
12493
|
+
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
12494
|
+
const updated = await args.db.db().update(juniorArtifacts).set({ deleteRequestedAt: now }).where(
|
|
12495
|
+
and2(
|
|
12496
|
+
eq2(juniorArtifacts.id, parsed.id),
|
|
12497
|
+
eq2(juniorArtifacts.conversationId, args.conversationId)
|
|
12498
|
+
)
|
|
12499
|
+
).returning({ id: juniorArtifacts.id });
|
|
12500
|
+
if (updated.length === 0) {
|
|
12501
|
+
throw new ToolInputError(
|
|
12502
|
+
`artifact not found for this conversation: ${filename}`
|
|
12503
|
+
);
|
|
12504
|
+
}
|
|
12505
|
+
return { filename };
|
|
12506
|
+
}
|
|
12507
|
+
async function readPublicArtifact(args) {
|
|
12508
|
+
const parsed = parseArtifactFilename(args.filename);
|
|
12509
|
+
if (!parsed) return null;
|
|
12510
|
+
const [row] = await args.db.db().select({
|
|
12511
|
+
contentType: juniorArtifacts.contentType,
|
|
12512
|
+
storageKey: juniorArtifacts.storageKey
|
|
12513
|
+
}).from(juniorArtifacts).where(
|
|
12514
|
+
and2(
|
|
12515
|
+
eq2(juniorArtifacts.id, parsed.id),
|
|
12516
|
+
eq2(juniorArtifacts.public, true),
|
|
12517
|
+
isNull(juniorArtifacts.deleteRequestedAt)
|
|
12518
|
+
)
|
|
12519
|
+
);
|
|
12520
|
+
if (!row) return null;
|
|
12521
|
+
const body = await args.storage.get(row.storageKey);
|
|
12522
|
+
if (!body) return null;
|
|
12523
|
+
return { body, contentType: row.contentType };
|
|
12524
|
+
}
|
|
12525
|
+
function publicArtifactHeaders(contentType) {
|
|
12526
|
+
return new Headers({
|
|
12527
|
+
// Keep TTL short so unpublish can take effect. Do not mark immutable.
|
|
12528
|
+
"cache-control": "public, max-age=300, must-revalidate",
|
|
12529
|
+
"content-type": contentType,
|
|
12530
|
+
"x-content-type-options": "nosniff"
|
|
12531
|
+
});
|
|
12532
|
+
}
|
|
12533
|
+
function unpublishedArtifactHeaders() {
|
|
12534
|
+
return new Headers({
|
|
12535
|
+
"cache-control": "private, no-store",
|
|
12536
|
+
"x-content-type-options": "nosniff"
|
|
12537
|
+
});
|
|
12538
|
+
}
|
|
12539
|
+
|
|
12540
|
+
// src/chat/tools/publish-image.ts
|
|
12541
|
+
var outputSchema5 = juniorToolOutputSchema.extend({
|
|
12542
|
+
bytes: z56.number().int().positive(),
|
|
12543
|
+
content_type: z56.string().min(1),
|
|
12544
|
+
public: z56.literal(true),
|
|
12545
|
+
url: z56.string().url()
|
|
12546
|
+
});
|
|
12547
|
+
function createPublishImageTool(args) {
|
|
12548
|
+
return zodTool({
|
|
12549
|
+
annotations: {
|
|
12550
|
+
destructiveHint: false,
|
|
12551
|
+
idempotentHint: true,
|
|
12552
|
+
openWorldHint: true,
|
|
12553
|
+
readOnlyHint: false
|
|
12554
|
+
},
|
|
12555
|
+
approvalMode: "review",
|
|
12556
|
+
description: "Publish one sandbox image to a durable public HTTPS URL. Anyone on the internet with the URL can view the image. Use only when an external destination needs a public image URL. Do not use for private file sharing or private conversation storage. Supports PNG, JPEG, GIF, and WebP up to 10 MB.",
|
|
12557
|
+
describeProposal: ({ path: path8 }) => `Publish sandbox image ${path8} to a public internet URL.`,
|
|
12558
|
+
executionMode: "sequential",
|
|
12559
|
+
inputSchema: z56.object({
|
|
12560
|
+
path: z56.string().min(1).describe("Exact sandbox path of an existing image file.")
|
|
12561
|
+
}).strict(),
|
|
12562
|
+
outputSchema: outputSchema5,
|
|
12563
|
+
async execute({ path: path8 }) {
|
|
12564
|
+
const publicBaseUrl = (args.publicBaseUrl ?? resolveBaseUrl)()?.trim();
|
|
12565
|
+
if (!publicBaseUrl) {
|
|
12566
|
+
throw new Error(
|
|
12567
|
+
"publishImage requires JUNIOR_BASE_URL or a Vercel deployment URL."
|
|
12568
|
+
);
|
|
12569
|
+
}
|
|
12570
|
+
const targetPath = normalizeSandboxPath(path8);
|
|
12571
|
+
const body = await args.workspace.readFileToBuffer({ path: targetPath });
|
|
12572
|
+
if (!body) {
|
|
12573
|
+
throw new SandboxFileNotFoundError(targetPath);
|
|
12574
|
+
}
|
|
12575
|
+
const image = await publishImage({
|
|
12576
|
+
body,
|
|
12577
|
+
conversationId: args.conversationId,
|
|
12578
|
+
db: args.db,
|
|
12579
|
+
publicBaseUrl,
|
|
12580
|
+
storage: args.storage
|
|
12581
|
+
});
|
|
12582
|
+
return {
|
|
12583
|
+
bytes: image.bytes,
|
|
12584
|
+
content_type: image.contentType,
|
|
12585
|
+
public: true,
|
|
12586
|
+
url: image.url
|
|
12587
|
+
};
|
|
12588
|
+
}
|
|
12589
|
+
});
|
|
12590
|
+
}
|
|
12591
|
+
|
|
12592
|
+
// src/chat/tools/unpublish-image.ts
|
|
12593
|
+
import { z as z57 } from "zod";
|
|
12594
|
+
var outputSchema6 = juniorToolOutputSchema.extend({
|
|
12595
|
+
filename: z57.string().min(1),
|
|
12596
|
+
unpublished: z57.literal(true)
|
|
12597
|
+
});
|
|
12598
|
+
function createUnpublishImageTool(args) {
|
|
12599
|
+
return zodTool({
|
|
12600
|
+
annotations: {
|
|
12601
|
+
destructiveHint: true,
|
|
12602
|
+
idempotentHint: true,
|
|
12603
|
+
openWorldHint: false,
|
|
12604
|
+
readOnlyHint: false
|
|
12605
|
+
},
|
|
12606
|
+
approvalMode: "review",
|
|
12607
|
+
description: "Unpublish one public image previously published in this conversation so its public URL stops serving. Pass the public artifact URL or `<id>.<ext>` filename. Only images owned by this conversation can be unpublished. Republishing the same image bytes later in this conversation restores a live URL for this conversation. Does not remove copies already fetched by browsers or GitHub.",
|
|
12608
|
+
describeProposal: ({ ref }) => `Unpublish public image ${ref}.`,
|
|
12609
|
+
executionMode: "sequential",
|
|
12610
|
+
inputSchema: z57.object({
|
|
12611
|
+
ref: z57.string().min(1).describe(
|
|
12612
|
+
"Public artifact URL or artifact filename (`<id>.<ext>`)."
|
|
12613
|
+
)
|
|
12614
|
+
}).strict(),
|
|
12615
|
+
outputSchema: outputSchema6,
|
|
12616
|
+
async execute({ ref }) {
|
|
12617
|
+
const result = await unpublishArtifact({
|
|
12618
|
+
conversationId: args.conversationId,
|
|
12619
|
+
db: args.db,
|
|
12620
|
+
ref
|
|
12621
|
+
});
|
|
12622
|
+
return {
|
|
12623
|
+
filename: result.filename,
|
|
12624
|
+
unpublished: true
|
|
12625
|
+
};
|
|
12626
|
+
}
|
|
12627
|
+
});
|
|
12628
|
+
}
|
|
12629
|
+
|
|
12630
|
+
// src/chat/tools/search-conversation-events.ts
|
|
12631
|
+
import { z as z58 } from "zod";
|
|
12312
12632
|
var DEFAULT_LIMIT3 = 25;
|
|
12313
|
-
var
|
|
12633
|
+
var MAX_LIMIT2 = 100;
|
|
12314
12634
|
var MAX_EVENT_DATA_BYTES = 4e3;
|
|
12315
12635
|
var MAX_EVENTS_JSON_BYTES = 2e4;
|
|
12316
12636
|
var MAX_IDENTITY_CHARS = 256;
|
|
12317
12637
|
var textEncoder = new TextEncoder();
|
|
12318
|
-
var knownEventTypeSchema =
|
|
12319
|
-
var projectedEventSchema =
|
|
12320
|
-
seq:
|
|
12321
|
-
history_version:
|
|
12322
|
-
created_at:
|
|
12323
|
-
idempotency_key:
|
|
12324
|
-
data:
|
|
12638
|
+
var knownEventTypeSchema = z58.enum(KNOWN_CONVERSATION_EVENT_TYPES);
|
|
12639
|
+
var projectedEventSchema = z58.object({
|
|
12640
|
+
seq: z58.number().int().nonnegative().describe("Stable event position for pagination."),
|
|
12641
|
+
history_version: z58.number().int().nonnegative().describe("Agent history generation after replacement."),
|
|
12642
|
+
created_at: z58.iso.datetime().describe("When the event was recorded."),
|
|
12643
|
+
idempotency_key: z58.string().min(1).optional().describe("Retry-stable event identity, when assigned."),
|
|
12644
|
+
data: z58.record(z58.string(), z58.unknown()).describe("Bounded event data.")
|
|
12325
12645
|
}).strict();
|
|
12326
12646
|
var searchConversationEventsOutputSchema = juniorToolOutputSchema.extend({
|
|
12327
|
-
conversation_id:
|
|
12328
|
-
events:
|
|
12329
|
-
has_older:
|
|
12330
|
-
has_newer:
|
|
12331
|
-
omitted_event_count:
|
|
12647
|
+
conversation_id: z58.string().min(1),
|
|
12648
|
+
events: z58.array(projectedEventSchema),
|
|
12649
|
+
has_older: z58.boolean().describe("Whether matching older events exist."),
|
|
12650
|
+
has_newer: z58.boolean().describe("Whether matching newer events exist."),
|
|
12651
|
+
omitted_event_count: z58.number().int().nonnegative().optional().describe("Events omitted by the response byte limit.")
|
|
12332
12652
|
});
|
|
12333
12653
|
function createSearchConversationEventsTool(context) {
|
|
12334
12654
|
return zodTool({
|
|
@@ -12341,16 +12661,16 @@ function createSearchConversationEventsTool(context) {
|
|
|
12341
12661
|
openWorldHint: false,
|
|
12342
12662
|
readOnlyHint: true
|
|
12343
12663
|
},
|
|
12344
|
-
inputSchema:
|
|
12345
|
-
conversation_id:
|
|
12664
|
+
inputSchema: z58.object({
|
|
12665
|
+
conversation_id: z58.string().trim().min(1).nullable().describe(
|
|
12346
12666
|
"Conversation ID to search. Omit or null for the current conversation."
|
|
12347
12667
|
).optional(),
|
|
12348
|
-
after_seq:
|
|
12349
|
-
before_seq:
|
|
12350
|
-
limit:
|
|
12351
|
-
`Maximum events. Default ${DEFAULT_LIMIT3}; max ${
|
|
12668
|
+
after_seq: z58.number().int().nonnegative().nullable().describe("Exclusive event sequence lower bound; returns ascending.").optional(),
|
|
12669
|
+
before_seq: z58.number().int().nonnegative().nullable().describe("Exclusive event sequence upper bound.").optional(),
|
|
12670
|
+
limit: z58.number().int().min(1).max(MAX_LIMIT2).nullable().describe(
|
|
12671
|
+
`Maximum events. Default ${DEFAULT_LIMIT3}; max ${MAX_LIMIT2}.`
|
|
12352
12672
|
).optional(),
|
|
12353
|
-
types:
|
|
12673
|
+
types: z58.array(knownEventTypeSchema).min(1).nullable().describe("Event types to include; omit for all types.").optional()
|
|
12354
12674
|
}).strict(),
|
|
12355
12675
|
outputSchema: searchConversationEventsOutputSchema,
|
|
12356
12676
|
execute: async (input) => {
|
|
@@ -12596,10 +12916,10 @@ function stripReplacementHistoryField(value) {
|
|
|
12596
12916
|
}
|
|
12597
12917
|
|
|
12598
12918
|
// src/chat/tools/handoff/tool.ts
|
|
12599
|
-
import { z as
|
|
12919
|
+
import { z as z59 } from "zod";
|
|
12600
12920
|
var HANDOFF_TOOL_NAME = "handoff";
|
|
12601
12921
|
function createHandoffTool(handoff) {
|
|
12602
|
-
const profileSchema =
|
|
12922
|
+
const profileSchema = z59.enum(handoff.profiles);
|
|
12603
12923
|
const handoffResultSchema = juniorToolOutputSchema.extend({
|
|
12604
12924
|
model_profile: modelProfileSchema
|
|
12605
12925
|
});
|
|
@@ -12613,7 +12933,7 @@ function createHandoffTool(handoff) {
|
|
|
12613
12933
|
},
|
|
12614
12934
|
description: `Switch to another execution profile and continue the same task. Profiles: ${profileNames}. Call this as the only tool.`,
|
|
12615
12935
|
executionMode: "sequential",
|
|
12616
|
-
inputSchema:
|
|
12936
|
+
inputSchema: z59.object({
|
|
12617
12937
|
profile: profileSchema.describe("Target execution profile")
|
|
12618
12938
|
}).strict(),
|
|
12619
12939
|
outputSchema: handoffResultSchema,
|
|
@@ -12634,7 +12954,7 @@ function createHandoffTool(handoff) {
|
|
|
12634
12954
|
}
|
|
12635
12955
|
|
|
12636
12956
|
// src/chat/tools/web/fetch-tool.ts
|
|
12637
|
-
import { z as
|
|
12957
|
+
import { z as z60 } from "zod";
|
|
12638
12958
|
|
|
12639
12959
|
// src/chat/tools/web/constants.ts
|
|
12640
12960
|
var USER_AGENT = "junior-bot/0.1";
|
|
@@ -13077,9 +13397,9 @@ function createWebFetchTool(hooks, options = {}) {
|
|
|
13077
13397
|
openWorldHint: true,
|
|
13078
13398
|
readOnlyHint: true
|
|
13079
13399
|
},
|
|
13080
|
-
inputSchema:
|
|
13081
|
-
url:
|
|
13082
|
-
max_chars:
|
|
13400
|
+
inputSchema: z60.object({
|
|
13401
|
+
url: z60.string().min(1).describe("HTTP(S) URL to fetch."),
|
|
13402
|
+
max_chars: z60.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
|
|
13083
13403
|
}),
|
|
13084
13404
|
outputSchema: juniorToolOutputSchema,
|
|
13085
13405
|
execute: async ({ url, max_chars }) => {
|
|
@@ -13124,7 +13444,7 @@ function createWebFetchTool(hooks, options = {}) {
|
|
|
13124
13444
|
}
|
|
13125
13445
|
|
|
13126
13446
|
// src/chat/tools/web/search.ts
|
|
13127
|
-
import { z as
|
|
13447
|
+
import { z as z61 } from "zod";
|
|
13128
13448
|
import { generateText } from "ai";
|
|
13129
13449
|
import { createGatewayProvider } from "@ai-sdk/gateway";
|
|
13130
13450
|
var SEARCH_TIMEOUT_MS = 6e4;
|
|
@@ -13166,9 +13486,9 @@ function createWebSearchTool(modelId, override) {
|
|
|
13166
13486
|
openWorldHint: true,
|
|
13167
13487
|
readOnlyHint: true
|
|
13168
13488
|
},
|
|
13169
|
-
inputSchema:
|
|
13170
|
-
query:
|
|
13171
|
-
max_results:
|
|
13489
|
+
inputSchema: z61.object({
|
|
13490
|
+
query: z61.string().min(1).max(500).describe("Search query."),
|
|
13491
|
+
max_results: z61.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
|
|
13172
13492
|
}),
|
|
13173
13493
|
outputSchema: juniorToolOutputSchema,
|
|
13174
13494
|
execute: async ({ query, max_results }) => {
|
|
@@ -13210,7 +13530,7 @@ function createWebSearchTool(modelId, override) {
|
|
|
13210
13530
|
}
|
|
13211
13531
|
|
|
13212
13532
|
// src/chat/tools/sandbox/write-file.ts
|
|
13213
|
-
import { z as
|
|
13533
|
+
import { z as z62 } from "zod";
|
|
13214
13534
|
function createWriteFileTool() {
|
|
13215
13535
|
return zodTool({
|
|
13216
13536
|
annotations: {
|
|
@@ -13221,9 +13541,9 @@ function createWriteFileTool() {
|
|
|
13221
13541
|
},
|
|
13222
13542
|
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.",
|
|
13223
13543
|
executionMode: "sequential",
|
|
13224
|
-
inputSchema:
|
|
13225
|
-
path:
|
|
13226
|
-
content:
|
|
13544
|
+
inputSchema: z62.object({
|
|
13545
|
+
path: z62.string().min(1).describe("Path to write in the sandbox workspace."),
|
|
13546
|
+
content: z62.string().describe("UTF-8 file content to write.")
|
|
13227
13547
|
}),
|
|
13228
13548
|
outputSchema: juniorToolOutputSchema,
|
|
13229
13549
|
execute: async () => {
|
|
@@ -13300,6 +13620,18 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
|
|
|
13300
13620
|
hooks.toolOverrides?.imageGenerate
|
|
13301
13621
|
);
|
|
13302
13622
|
}
|
|
13623
|
+
if (context.attachmentStorage && context.conversationId) {
|
|
13624
|
+
tools.publishImage = createPublishImageTool({
|
|
13625
|
+
conversationId: context.conversationId,
|
|
13626
|
+
db: getSqlExecutor(),
|
|
13627
|
+
storage: context.attachmentStorage,
|
|
13628
|
+
workspace: context.workspace
|
|
13629
|
+
});
|
|
13630
|
+
tools.unpublishImage = createUnpublishImageTool({
|
|
13631
|
+
conversationId: context.conversationId,
|
|
13632
|
+
db: getSqlExecutor()
|
|
13633
|
+
});
|
|
13634
|
+
}
|
|
13303
13635
|
if (context.handoff) {
|
|
13304
13636
|
tools.handoff = createHandoffTool(context.handoff);
|
|
13305
13637
|
}
|
|
@@ -13946,7 +14278,7 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, conv
|
|
|
13946
14278
|
}
|
|
13947
14279
|
|
|
13948
14280
|
// src/chat/tools/execute-tool.ts
|
|
13949
|
-
import { z as
|
|
14281
|
+
import { z as z63 } from "zod";
|
|
13950
14282
|
var EXECUTE_TOOL_NAME = "executeTool";
|
|
13951
14283
|
function createExecuteToolTool() {
|
|
13952
14284
|
return zodTool({
|
|
@@ -13958,11 +14290,11 @@ function createExecuteToolTool() {
|
|
|
13958
14290
|
},
|
|
13959
14291
|
description: "Execute any catalog tool by exact tool_name from searchTools or a tool-result execution hint. Put tool-specific parameters inside arguments.",
|
|
13960
14292
|
executionMode: "sequential",
|
|
13961
|
-
inputSchema:
|
|
13962
|
-
tool_name:
|
|
14293
|
+
inputSchema: z63.object({
|
|
14294
|
+
tool_name: z63.string().min(1).describe(
|
|
13963
14295
|
"Exact catalog tool_name returned by searchTools or a tool-result execution hint."
|
|
13964
14296
|
),
|
|
13965
|
-
arguments:
|
|
14297
|
+
arguments: z63.record(z63.string(), z63.unknown()).describe(
|
|
13966
14298
|
'Arguments matching the selected catalog tool schema, for example { "query": "..." }.'
|
|
13967
14299
|
).optional()
|
|
13968
14300
|
}).strict(),
|
|
@@ -14002,7 +14334,7 @@ function planToolExposure(tools) {
|
|
|
14002
14334
|
}
|
|
14003
14335
|
|
|
14004
14336
|
// src/chat/tools/search-tools.ts
|
|
14005
|
-
import { z as
|
|
14337
|
+
import { z as z64 } from "zod";
|
|
14006
14338
|
var SEARCH_TOOLS_NAME = "searchTools";
|
|
14007
14339
|
var DEFAULT_MAX_RESULTS2 = 5;
|
|
14008
14340
|
var MAX_RESULTS3 = 20;
|
|
@@ -14047,29 +14379,29 @@ var SEARCH_STOP_WORDS = /* @__PURE__ */ new Set([
|
|
|
14047
14379
|
"you",
|
|
14048
14380
|
"your"
|
|
14049
14381
|
]);
|
|
14050
|
-
var searchToolsSourceSchema =
|
|
14051
|
-
id:
|
|
14052
|
-
description:
|
|
14382
|
+
var searchToolsSourceSchema = z64.object({
|
|
14383
|
+
id: z64.string(),
|
|
14384
|
+
description: z64.string()
|
|
14053
14385
|
}).strict();
|
|
14054
|
-
var searchToolsToolSchema =
|
|
14055
|
-
tool_name:
|
|
14056
|
-
description:
|
|
14057
|
-
exposure:
|
|
14058
|
-
source:
|
|
14059
|
-
input_schema:
|
|
14060
|
-
call_notes:
|
|
14061
|
-
annotations:
|
|
14386
|
+
var searchToolsToolSchema = z64.object({
|
|
14387
|
+
tool_name: z64.string(),
|
|
14388
|
+
description: z64.string(),
|
|
14389
|
+
exposure: z64.enum(["direct", "deferred", "modelOnly", "hidden"]),
|
|
14390
|
+
source: z64.string().optional(),
|
|
14391
|
+
input_schema: z64.unknown(),
|
|
14392
|
+
call_notes: z64.array(z64.string()),
|
|
14393
|
+
annotations: z64.record(z64.string(), z64.unknown())
|
|
14062
14394
|
}).strict();
|
|
14063
14395
|
var searchToolsOutputSchema = juniorToolOutputSchema.extend({
|
|
14064
|
-
query:
|
|
14065
|
-
source:
|
|
14066
|
-
sources:
|
|
14067
|
-
total_catalog_tools:
|
|
14068
|
-
total_eligible_tools:
|
|
14069
|
-
total_matches:
|
|
14070
|
-
returned_tools:
|
|
14071
|
-
execution_tool:
|
|
14072
|
-
tools:
|
|
14396
|
+
query: z64.string().nullable(),
|
|
14397
|
+
source: z64.string().nullable(),
|
|
14398
|
+
sources: z64.array(searchToolsSourceSchema),
|
|
14399
|
+
total_catalog_tools: z64.number().int().nonnegative(),
|
|
14400
|
+
total_eligible_tools: z64.number().int().nonnegative(),
|
|
14401
|
+
total_matches: z64.number().int().nonnegative(),
|
|
14402
|
+
returned_tools: z64.number().int().nonnegative(),
|
|
14403
|
+
execution_tool: z64.literal("executeTool"),
|
|
14404
|
+
tools: z64.array(searchToolsToolSchema)
|
|
14073
14405
|
}).strict();
|
|
14074
14406
|
function terms(value) {
|
|
14075
14407
|
const chunks = value.match(/[\p{L}\p{N}]+/gu) ?? [];
|
|
@@ -14280,14 +14612,14 @@ function createSearchToolsTool(catalogTools) {
|
|
|
14280
14612
|
openWorldHint: false,
|
|
14281
14613
|
readOnlyHint: true
|
|
14282
14614
|
},
|
|
14283
|
-
inputSchema:
|
|
14284
|
-
query:
|
|
14615
|
+
inputSchema: z64.object({
|
|
14616
|
+
query: z64.string().nullable().describe(
|
|
14285
14617
|
"Optional search terms describing the tool, owner, action, or arguments needed. Empty string lists catalog tools."
|
|
14286
14618
|
).optional(),
|
|
14287
|
-
source:
|
|
14619
|
+
source: z64.string().nullable().describe(
|
|
14288
14620
|
"Optional source id to search within, such as a plugin source returned in sources."
|
|
14289
14621
|
).optional(),
|
|
14290
|
-
max_results:
|
|
14622
|
+
max_results: z64.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
|
|
14291
14623
|
}).strict(),
|
|
14292
14624
|
outputSchema: searchToolsOutputSchema,
|
|
14293
14625
|
privateTraceResult: (result) => ({
|
|
@@ -14733,7 +15065,7 @@ function createMcpAuthOrchestration(input) {
|
|
|
14733
15065
|
}
|
|
14734
15066
|
|
|
14735
15067
|
// src/chat/egress/plugin.ts
|
|
14736
|
-
import { randomUUID as
|
|
15068
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
14737
15069
|
|
|
14738
15070
|
// src/chat/sandbox/egress/credentials.ts
|
|
14739
15071
|
var HTTP_READ_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
|
|
@@ -15487,8 +15819,8 @@ async function executeCredentialedEgressRequest(input) {
|
|
|
15487
15819
|
function credentialContextForPluginEgress(credentialContext) {
|
|
15488
15820
|
return {
|
|
15489
15821
|
credentials: credentialContext,
|
|
15490
|
-
contextId:
|
|
15491
|
-
egressId: `plugin-egress:${
|
|
15822
|
+
contextId: randomUUID4(),
|
|
15823
|
+
egressId: `plugin-egress:${randomUUID4()}`,
|
|
15492
15824
|
expiresAtMs: Date.now() + 30 * 60 * 1e3
|
|
15493
15825
|
};
|
|
15494
15826
|
}
|
|
@@ -15546,7 +15878,7 @@ function createPluginEgress(deps) {
|
|
|
15546
15878
|
}
|
|
15547
15879
|
|
|
15548
15880
|
// src/chat/services/guardian-action-review.ts
|
|
15549
|
-
import { z as
|
|
15881
|
+
import { z as z65 } from "zod";
|
|
15550
15882
|
|
|
15551
15883
|
// src/chat/services/guardian-action-policy.ts
|
|
15552
15884
|
var GUARDIAN_ACTION_POLICY = `You are judging one planned Junior agent action.
|
|
@@ -15614,17 +15946,17 @@ Assess the exact action's intrinsic risk and whether the user's intent authorize
|
|
|
15614
15946
|
- Keep the reason to one concise, specific sentence grounded in the main risk or authorization fact. For ask, name the exact action, target, and material side effects the user must confirm.`;
|
|
15615
15947
|
|
|
15616
15948
|
// src/chat/services/guardian-action-review.ts
|
|
15617
|
-
var guardianDecisionSchema =
|
|
15618
|
-
decision:
|
|
15619
|
-
reason:
|
|
15620
|
-
riskLevel:
|
|
15621
|
-
userAuthorization:
|
|
15949
|
+
var guardianDecisionSchema = z65.object({
|
|
15950
|
+
decision: z65.enum(["allow", "ask", "deny"]),
|
|
15951
|
+
reason: z65.string().trim().min(1).max(500),
|
|
15952
|
+
riskLevel: z65.enum(["low", "medium", "high", "critical"]),
|
|
15953
|
+
userAuthorization: z65.enum(["high", "medium", "low", "unknown"])
|
|
15622
15954
|
}).strict();
|
|
15623
15955
|
var GUARDIAN_REVIEW_TIMEOUT_MS = 6e4;
|
|
15624
15956
|
var GUARDIAN_REVIEW_MAX_TOKENS = 2e3;
|
|
15625
15957
|
var MAX_PROPOSAL_CHARS = 192e3;
|
|
15626
15958
|
function guardianPrompt(proposal) {
|
|
15627
|
-
const proposalJson = JSON.stringify(
|
|
15959
|
+
const proposalJson = JSON.stringify(z65.json().parse(proposal), null, 2);
|
|
15628
15960
|
if (proposalJson.length > MAX_PROPOSAL_CHARS) {
|
|
15629
15961
|
throw new Error(
|
|
15630
15962
|
`Guardian action proposal exceeds ${MAX_PROPOSAL_CHARS} characters.`
|
|
@@ -18220,6 +18552,9 @@ export {
|
|
|
18220
18552
|
listThreadReplies,
|
|
18221
18553
|
renderBlockText,
|
|
18222
18554
|
renderAttachmentText,
|
|
18555
|
+
readPublicArtifact,
|
|
18556
|
+
publicArtifactHeaders,
|
|
18557
|
+
unpublishedArtifactHeaders,
|
|
18223
18558
|
latestReportedProgress,
|
|
18224
18559
|
executeCredentialedEgressRequest,
|
|
18225
18560
|
createContextCompactor,
|