@sentry/junior 0.154.0 → 0.156.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-VEHV2QUA.js → agent-hooks-CCAR46PQ.js} +11 -12
- package/dist/api/conversations/list.d.ts +5 -3
- package/dist/api/conversations/membership.d.ts +16 -0
- package/dist/api/locations/detail.d.ts +2 -0
- package/dist/api/schema/conversation.d.ts +22 -4
- package/dist/api/schema/location.d.ts +2 -0
- package/dist/api/schema/person.d.ts +2 -0
- package/dist/api/schema.js +1 -1
- package/dist/api.js +331 -188
- package/dist/app.js +154 -51
- package/dist/catalog-runtime-3SNKYCBG.js +16 -0
- package/dist/chat/agent/types.d.ts +2 -0
- package/dist/chat/attachments/storage.d.ts +12 -0
- package/dist/chat/attachments/store.d.ts +52 -0
- package/dist/chat/attachments/vercel.d.ts +3 -0
- package/dist/chat/conversations/retention.d.ts +4 -0
- package/dist/chat/conversations/sql/event-actor.d.ts +14 -0
- package/dist/chat/conversations/sql/event-lock.d.ts +1 -1
- package/dist/chat/conversations/sql/participants.d.ts +17 -0
- package/dist/chat/ingress/bot-mention.d.ts +13 -0
- package/dist/chat/plugins/unfinished-work.d.ts +8 -0
- package/dist/chat/runtime/agent-runner.d.ts +4 -0
- package/dist/chat/runtime/slack-resume.d.ts +1 -1
- package/dist/chat/services/conversation-memory.d.ts +1 -1
- package/dist/chat/slack/tools/send-files.d.ts +17 -11
- package/dist/chat/state/conversation.d.ts +3 -1
- package/dist/chat/tools/types.d.ts +2 -0
- package/dist/{chunk-XYMCZGH6.js → chunk-3FFUC32L.js} +8 -10
- package/dist/{chunk-4U4MNYGP.js → chunk-3L2PMOSR.js} +6 -8
- package/dist/{chunk-PTJ75ZWR.js → chunk-4ZZDTHFC.js} +94 -9
- package/dist/{chunk-DAJZZFU7.js → chunk-53W3LZEW.js} +386 -93
- package/dist/{chunk-F7QUK3YP.js → chunk-6CINHXIL.js} +5 -5
- package/dist/{chunk-6VWMX7NS.js → chunk-6JUU7J2B.js} +4 -4
- package/dist/{chunk-HUO3UTAQ.js → chunk-7MA4HV4W.js} +1 -1
- package/dist/{chunk-O4AQDOKA.js → chunk-7RAETIYO.js} +7 -7
- package/dist/{chunk-4R2XCKUH.js → chunk-A6WPDFHQ.js} +1 -1
- package/dist/{chunk-CZD6M57V.js → chunk-AIJRG227.js} +191 -126
- package/dist/{chunk-RUIXF3YQ.js → chunk-BDUENQD3.js} +1 -1
- package/dist/{chunk-NUG3VYHL.js → chunk-CK2H7CFO.js} +2 -2
- package/dist/{chunk-HOGJ6TBT.js → chunk-CN2XSVKF.js} +6 -6
- package/dist/{chunk-3567VGCN.js → chunk-EDJ64P2P.js} +1 -1
- package/dist/{chunk-6PJXR4BC.js → chunk-GKC43TLS.js} +2 -2
- package/dist/{chunk-A6LWN4K6.js → chunk-GSBPZHLQ.js} +11 -11
- package/dist/{chunk-Y654CTW2.js → chunk-IIO5PFZX.js} +366 -138
- package/dist/{chunk-F2Q3ZHW2.js → chunk-IZEBHYI4.js} +1 -1
- package/dist/{chunk-QGR6QTC4.js → chunk-JUJR6WTL.js} +4 -4
- package/dist/{chunk-ZQT4RHUO.js → chunk-KBGMYLSV.js} +4 -1
- package/dist/{chunk-DK2FSQHS.js → chunk-KCA5MKHU.js} +5 -5
- package/dist/{chunk-NNN2WYAD.js → chunk-MC57E5U5.js} +1 -1
- package/dist/{chunk-6AF5GOZA.js → chunk-MJE7XKWP.js} +1 -1
- package/dist/{chunk-7CPN5JTA.js → chunk-NTNU6T2D.js} +3 -3
- package/dist/{chunk-NG4IAOVD.js → chunk-OGZPRMZA.js} +1 -1
- package/dist/{chunk-UCH55IGZ.js → chunk-OMQJB7YN.js} +28 -37
- package/dist/{chunk-2XNVS6RC.js → chunk-PMFGVLDU.js} +12 -11
- package/dist/{chunk-65IAU2L2.js → chunk-SE3D225X.js} +1 -1
- package/dist/{chunk-CCAU73CE.js → chunk-SRJA6QLM.js} +2 -2
- package/dist/{chunk-7RFWIHPM.js → chunk-TN4LVILT.js} +5 -5
- package/dist/{chunk-3ZR2R5EQ.js → chunk-TNXGMFWV.js} +1 -1
- package/dist/{chunk-HZF5P5UN.js → chunk-V7YE4WCP.js} +58 -7
- package/dist/{chunk-MSOZLASC.js → chunk-WD7SEUZO.js} +2 -2
- package/dist/{chunk-UG5UCHHJ.js → chunk-X5NZQH5U.js} +4 -2
- package/dist/{chunk-3HX67UPN.js → chunk-X7W45B5G.js} +1 -1
- package/dist/{chunk-FVY7AJ46.js → chunk-ZNWRYNCA.js} +7 -7
- package/dist/cli/chat.js +36 -36
- package/dist/cli/check.js +8 -9
- package/dist/cli/init.js +41 -7
- package/dist/cli/plugins.js +15 -16
- package/dist/cli/snapshot-create.js +11 -12
- package/dist/cli/upgrade.js +9 -10
- package/dist/db/schema/attachments.d.ts +178 -0
- package/dist/db/schema/conversation-events.d.ts +20 -0
- package/dist/db/schema/conversation-participants.d.ts +63 -0
- package/dist/db/schema.d.ts +255 -1
- package/dist/{db-SOJJLMJK.js → db-TYUUKGJX.js} +8 -8
- package/dist/handlers/retention.d.ts +4 -1
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +2 -2
- package/dist/{oauth-callback-server-GCJROMVO.js → oauth-callback-server-AWVDKPR5.js} +26 -26
- package/dist/{runner-SY6KDQCN.js → runner-JUQXMACC.js} +15 -16
- package/dist/{sandbox-egress-signals-EKPAVWQL.js → sandbox-egress-signals-U3ZX7C5W.js} +3 -4
- package/dist/{skills-XJ2LJ2ML.js → skills-4GZTZX4V.js} +8 -9
- package/dist/spawn-32SSRWU4.js +37 -0
- package/dist/{validation-XQWY6QRY.js → validation-DRLNJRND.js} +8 -9
- package/dist/version.js +1 -1
- package/dist/{work-FFT5JAOU.js → work-TGIXRRJY.js} +20 -21
- package/dist/worker-IFXZOYED.js +24 -0
- package/migrations/0026_conversation_event_actor_and_participants.sql +140 -0
- package/migrations/0027_attachment_storage.sql +16 -0
- package/migrations/meta/0026_snapshot.json +2424 -0
- package/migrations/meta/0027_snapshot.json +2554 -0
- package/migrations/meta/_journal.json +15 -1
- package/package.json +10 -7
- package/dist/catalog-runtime-AK5MY63F.js +0 -17
- package/dist/chunk-F3B2YJ76.js +0 -57
- package/dist/spawn-QFCQREEP.js +0 -38
- package/dist/worker-JAITK72F.js +0 -25
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
PluginCredentialFailureError,
|
|
8
8
|
agentNameSchema,
|
|
9
9
|
createPluginAuthOrchestration
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ZNWRYNCA.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-4ZZDTHFC.js";
|
|
36
36
|
import {
|
|
37
37
|
RetryableDeliveryError,
|
|
38
38
|
actorFromRun,
|
|
@@ -48,16 +48,13 @@ import {
|
|
|
48
48
|
getSlackMessagePermalink,
|
|
49
49
|
resolveBaseUrl,
|
|
50
50
|
uploadFilesToConversation
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-7RAETIYO.js";
|
|
52
52
|
import {
|
|
53
53
|
parseSandboxEgressAuthRequiredSignal,
|
|
54
54
|
parseSandboxEgressPermissionDeniedSignal,
|
|
55
55
|
sandboxEgressCredentialContextSchema,
|
|
56
56
|
sandboxEgressCredentialLeaseSchema
|
|
57
|
-
} from "./chunk-
|
|
58
|
-
import {
|
|
59
|
-
isExperimentalFeatureEnabled
|
|
60
|
-
} from "./chunk-5IDFPCON.js";
|
|
57
|
+
} from "./chunk-7MA4HV4W.js";
|
|
61
58
|
import {
|
|
62
59
|
bindSandboxFileSystem,
|
|
63
60
|
buildCommandScript,
|
|
@@ -77,7 +74,7 @@ import {
|
|
|
77
74
|
runNonInteractiveCommand,
|
|
78
75
|
throwSandboxOperationError,
|
|
79
76
|
wrapSandboxSetupError
|
|
80
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-6JUU7J2B.js";
|
|
81
78
|
import {
|
|
82
79
|
SCHEDULED_TASK_SYSTEM_ACTOR,
|
|
83
80
|
compactEventTask,
|
|
@@ -109,10 +106,10 @@ import {
|
|
|
109
106
|
saveEventTask,
|
|
110
107
|
scheduledTaskAttributes,
|
|
111
108
|
writableEventTask
|
|
112
|
-
} from "./chunk-
|
|
109
|
+
} from "./chunk-KCA5MKHU.js";
|
|
113
110
|
import {
|
|
114
111
|
parseSlackThreadId
|
|
115
|
-
} from "./chunk-
|
|
112
|
+
} from "./chunk-CK2H7CFO.js";
|
|
116
113
|
import {
|
|
117
114
|
AGENTS_REMOVAL_NOTICE,
|
|
118
115
|
AGENTS_REPLACEMENT_NOTICE,
|
|
@@ -182,7 +179,7 @@ import {
|
|
|
182
179
|
stripRuntimeTurnContext,
|
|
183
180
|
trimTrailingAssistantMessages,
|
|
184
181
|
truncateText
|
|
185
|
-
} from "./chunk-
|
|
182
|
+
} from "./chunk-3L2PMOSR.js";
|
|
186
183
|
import {
|
|
187
184
|
JUNIOR_THREAD_STATE_TTL_MS
|
|
188
185
|
} from "./chunk-3Y47VMHV.js";
|
|
@@ -198,7 +195,7 @@ import {
|
|
|
198
195
|
getSlackToolContext,
|
|
199
196
|
readActorIdentity,
|
|
200
197
|
resolveChannelCapabilities
|
|
201
|
-
} from "./chunk-
|
|
198
|
+
} from "./chunk-3FFUC32L.js";
|
|
202
199
|
import {
|
|
203
200
|
SlackActionError,
|
|
204
201
|
downloadPrivateSlackFile,
|
|
@@ -207,7 +204,7 @@ import {
|
|
|
207
204
|
isConversationScopedChannel,
|
|
208
205
|
normalizeSlackConversationId,
|
|
209
206
|
withSlackRetries
|
|
210
|
-
} from "./chunk-
|
|
207
|
+
} from "./chunk-NTNU6T2D.js";
|
|
211
208
|
import {
|
|
212
209
|
KNOWN_CONVERSATION_EVENT_TYPES,
|
|
213
210
|
contextProvenance,
|
|
@@ -219,10 +216,12 @@ import {
|
|
|
219
216
|
instructionActors,
|
|
220
217
|
instructionProvenanceFor,
|
|
221
218
|
sameActorIdentity
|
|
222
|
-
} from "./chunk-
|
|
219
|
+
} from "./chunk-IIO5PFZX.js";
|
|
223
220
|
import {
|
|
221
|
+
juniorAttachments,
|
|
222
|
+
juniorConversations,
|
|
224
223
|
juniorIdentities
|
|
225
|
-
} from "./chunk-
|
|
224
|
+
} from "./chunk-AIJRG227.js";
|
|
226
225
|
import {
|
|
227
226
|
SANDBOX_DATA_ROOT,
|
|
228
227
|
SANDBOX_SKILLS_ROOT,
|
|
@@ -234,7 +233,7 @@ import {
|
|
|
234
233
|
} from "./chunk-EM225ITJ.js";
|
|
235
234
|
import {
|
|
236
235
|
getStateAdapter
|
|
237
|
-
} from "./chunk-
|
|
236
|
+
} from "./chunk-MC57E5U5.js";
|
|
238
237
|
import {
|
|
239
238
|
ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX,
|
|
240
239
|
COMPACTION_SUMMARY_PREFIX,
|
|
@@ -267,7 +266,7 @@ import {
|
|
|
267
266
|
resolveGatewayCredential,
|
|
268
267
|
resolveGatewayModel,
|
|
269
268
|
unwrapCurrentInstruction
|
|
270
|
-
} from "./chunk-
|
|
269
|
+
} from "./chunk-GKC43TLS.js";
|
|
271
270
|
import {
|
|
272
271
|
canExposeConversationPayload,
|
|
273
272
|
resolveConversationPrivacy,
|
|
@@ -277,16 +276,16 @@ import {
|
|
|
277
276
|
toGenAiMessagesTraceAttributes,
|
|
278
277
|
toGenAiPayloadMetadata,
|
|
279
278
|
toGenAiPayloadTraceAttributes
|
|
280
|
-
} from "./chunk-
|
|
279
|
+
} from "./chunk-MJE7XKWP.js";
|
|
281
280
|
import {
|
|
282
281
|
discoverSkills,
|
|
283
282
|
findSkillByName,
|
|
284
283
|
loadSkillsByName,
|
|
285
284
|
parseSkillInvocation
|
|
286
|
-
} from "./chunk-
|
|
285
|
+
} from "./chunk-SRJA6QLM.js";
|
|
287
286
|
import {
|
|
288
287
|
pluginCatalogRuntime
|
|
289
|
-
} from "./chunk-
|
|
288
|
+
} from "./chunk-EDJ64P2P.js";
|
|
290
289
|
import {
|
|
291
290
|
CredentialUnavailableError,
|
|
292
291
|
OAuthProviderError,
|
|
@@ -294,18 +293,16 @@ import {
|
|
|
294
293
|
getOAuthProviderErrorAttributes,
|
|
295
294
|
resolveAuthTokenPlaceholder,
|
|
296
295
|
resolvePluginCommandEnv
|
|
297
|
-
} from "./chunk-
|
|
296
|
+
} from "./chunk-WD7SEUZO.js";
|
|
298
297
|
import {
|
|
299
298
|
credentialUserSubjectId
|
|
300
|
-
} from "./chunk-
|
|
301
|
-
import {
|
|
302
|
-
isUserActor
|
|
303
|
-
} from "./chunk-HZF5P5UN.js";
|
|
299
|
+
} from "./chunk-BDUENQD3.js";
|
|
304
300
|
import {
|
|
301
|
+
isUserActor,
|
|
305
302
|
parseSlackChannelId,
|
|
306
303
|
parseSlackMessageTs,
|
|
307
304
|
parseSlackUserId
|
|
308
|
-
} from "./chunk-
|
|
305
|
+
} from "./chunk-V7YE4WCP.js";
|
|
309
306
|
import {
|
|
310
307
|
extractGenAiUsageAttributes,
|
|
311
308
|
extractGenAiUsageSummary,
|
|
@@ -324,7 +321,7 @@ import {
|
|
|
324
321
|
summarizeMessageText,
|
|
325
322
|
withLogContext,
|
|
326
323
|
withSpan
|
|
327
|
-
} from "./chunk-
|
|
324
|
+
} from "./chunk-X7W45B5G.js";
|
|
328
325
|
import {
|
|
329
326
|
startInactiveSpan,
|
|
330
327
|
withActiveSpan
|
|
@@ -10540,15 +10537,327 @@ function createSlackMessageAddReactionTool(context, state) {
|
|
|
10540
10537
|
}
|
|
10541
10538
|
|
|
10542
10539
|
// src/chat/slack/tools/send-files.ts
|
|
10543
|
-
import { createHash as
|
|
10540
|
+
import { createHash as createHash5 } from "crypto";
|
|
10541
|
+
|
|
10542
|
+
// src/chat/attachments/store.ts
|
|
10543
|
+
import { createHash as createHash4, randomUUID as randomUUID3 } from "crypto";
|
|
10544
|
+
import { and, asc, eq, inArray, isNotNull, isNull, or } from "drizzle-orm";
|
|
10545
|
+
var ATTACHMENT_GC_BATCH_LIMIT = 200;
|
|
10546
|
+
function attachmentDigest(file) {
|
|
10547
|
+
return createHash4("sha256").update(file.data).digest("hex");
|
|
10548
|
+
}
|
|
10549
|
+
function attachmentId(args) {
|
|
10550
|
+
return createHash4("sha256").update(
|
|
10551
|
+
[
|
|
10552
|
+
args.conversationId,
|
|
10553
|
+
args.provider,
|
|
10554
|
+
args.sha256,
|
|
10555
|
+
args.filename,
|
|
10556
|
+
args.contentType
|
|
10557
|
+
].join("\0")
|
|
10558
|
+
).digest("hex");
|
|
10559
|
+
}
|
|
10560
|
+
function attachmentKey(args) {
|
|
10561
|
+
return `conversations/${args.conversationId}/attachments/${args.attachmentId}/${args.writeId}/${args.filename}`;
|
|
10562
|
+
}
|
|
10563
|
+
async function bestEffortDelete(storage, key) {
|
|
10564
|
+
try {
|
|
10565
|
+
await storage.delete([key]);
|
|
10566
|
+
} catch {
|
|
10567
|
+
}
|
|
10568
|
+
}
|
|
10569
|
+
async function isConversationPurged(db, conversationId) {
|
|
10570
|
+
const [row] = await db.db().select({
|
|
10571
|
+
transcriptPurgedAt: juniorConversations.transcriptPurgedAt
|
|
10572
|
+
}).from(juniorConversations).where(eq(juniorConversations.conversationId, conversationId));
|
|
10573
|
+
return row?.transcriptPurgedAt != null;
|
|
10574
|
+
}
|
|
10575
|
+
function purgedConversationError(conversationId) {
|
|
10576
|
+
return new Error(
|
|
10577
|
+
`Cannot store attachment for purged conversation ${conversationId}`
|
|
10578
|
+
);
|
|
10579
|
+
}
|
|
10580
|
+
async function assertConversationNotPurged(db, conversationId) {
|
|
10581
|
+
if (await isConversationPurged(db, conversationId)) {
|
|
10582
|
+
throw purgedConversationError(conversationId);
|
|
10583
|
+
}
|
|
10584
|
+
}
|
|
10585
|
+
async function rejectPurgedAttachmentWrite(args) {
|
|
10586
|
+
await args.db.db().update(juniorAttachments).set({ deleteRequestedAt: args.now }).where(eq(juniorAttachments.id, args.id));
|
|
10587
|
+
await bestEffortDelete(args.storage, args.storageKey);
|
|
10588
|
+
throw purgedConversationError(args.conversationId);
|
|
10589
|
+
}
|
|
10590
|
+
async function reuseLiveAttachment(args) {
|
|
10591
|
+
await bestEffortDelete(args.storage, args.storageKey);
|
|
10592
|
+
await assertConversationNotPurged(args.db, args.conversationId);
|
|
10593
|
+
return { id: args.id };
|
|
10594
|
+
}
|
|
10595
|
+
async function storeAttachment(args) {
|
|
10596
|
+
const now = new Date(args.nowMs ?? Date.now());
|
|
10597
|
+
const sha256 = attachmentDigest(args.file);
|
|
10598
|
+
const id = attachmentId({
|
|
10599
|
+
conversationId: args.conversationId,
|
|
10600
|
+
contentType: args.file.mimeType,
|
|
10601
|
+
filename: args.file.filename,
|
|
10602
|
+
provider: args.storage.provider,
|
|
10603
|
+
sha256
|
|
10604
|
+
});
|
|
10605
|
+
const [existing] = await args.db.db().select({
|
|
10606
|
+
contentType: juniorAttachments.contentType,
|
|
10607
|
+
conversationId: juniorAttachments.conversationId,
|
|
10608
|
+
deleteRequestedAt: juniorAttachments.deleteRequestedAt,
|
|
10609
|
+
filename: juniorAttachments.filename,
|
|
10610
|
+
id: juniorAttachments.id,
|
|
10611
|
+
provider: juniorAttachments.provider,
|
|
10612
|
+
sha256: juniorAttachments.sha256,
|
|
10613
|
+
storageKey: juniorAttachments.storageKey
|
|
10614
|
+
}).from(juniorAttachments).where(eq(juniorAttachments.id, id));
|
|
10615
|
+
if (existing) {
|
|
10616
|
+
if (existing.contentType !== args.file.mimeType || existing.conversationId !== args.conversationId || existing.filename !== args.file.filename || existing.provider !== args.storage.provider || existing.sha256 !== sha256) {
|
|
10617
|
+
throw new Error(`Attachment write conflicts with ${existing.id}`);
|
|
10618
|
+
}
|
|
10619
|
+
if (existing.deleteRequestedAt === null) {
|
|
10620
|
+
await assertConversationNotPurged(args.db, args.conversationId);
|
|
10621
|
+
return { id: existing.id };
|
|
10622
|
+
}
|
|
10623
|
+
}
|
|
10624
|
+
await assertConversationNotPurged(args.db, args.conversationId);
|
|
10625
|
+
const storageKey = attachmentKey({
|
|
10626
|
+
attachmentId: id,
|
|
10627
|
+
conversationId: args.conversationId,
|
|
10628
|
+
filename: args.file.filename,
|
|
10629
|
+
writeId: randomUUID3()
|
|
10630
|
+
});
|
|
10631
|
+
await args.storage.put({
|
|
10632
|
+
body: args.file.data,
|
|
10633
|
+
contentType: args.file.mimeType,
|
|
10634
|
+
key: storageKey
|
|
10635
|
+
});
|
|
10636
|
+
if (existing?.deleteRequestedAt != null) {
|
|
10637
|
+
if (await isConversationPurged(args.db, args.conversationId)) {
|
|
10638
|
+
await bestEffortDelete(args.storage, storageKey);
|
|
10639
|
+
throw purgedConversationError(args.conversationId);
|
|
10640
|
+
}
|
|
10641
|
+
const oldStorageKey = existing.storageKey;
|
|
10642
|
+
const revived2 = await args.db.db().update(juniorAttachments).set({
|
|
10643
|
+
deleteRequestedAt: null,
|
|
10644
|
+
storageKey
|
|
10645
|
+
}).where(
|
|
10646
|
+
and(
|
|
10647
|
+
eq(juniorAttachments.id, id),
|
|
10648
|
+
isNotNull(juniorAttachments.deleteRequestedAt)
|
|
10649
|
+
)
|
|
10650
|
+
).returning({ id: juniorAttachments.id });
|
|
10651
|
+
if (revived2.length > 0) {
|
|
10652
|
+
if (await isConversationPurged(args.db, args.conversationId)) {
|
|
10653
|
+
await rejectPurgedAttachmentWrite({
|
|
10654
|
+
conversationId: args.conversationId,
|
|
10655
|
+
db: args.db,
|
|
10656
|
+
id,
|
|
10657
|
+
now,
|
|
10658
|
+
storage: args.storage,
|
|
10659
|
+
storageKey
|
|
10660
|
+
});
|
|
10661
|
+
}
|
|
10662
|
+
if (oldStorageKey !== storageKey) {
|
|
10663
|
+
await bestEffortDelete(args.storage, oldStorageKey);
|
|
10664
|
+
}
|
|
10665
|
+
return { id };
|
|
10666
|
+
}
|
|
10667
|
+
const [afterRace2] = await args.db.db().select({
|
|
10668
|
+
deleteRequestedAt: juniorAttachments.deleteRequestedAt,
|
|
10669
|
+
id: juniorAttachments.id,
|
|
10670
|
+
storageKey: juniorAttachments.storageKey
|
|
10671
|
+
}).from(juniorAttachments).where(eq(juniorAttachments.id, id));
|
|
10672
|
+
if (afterRace2?.deleteRequestedAt === null) {
|
|
10673
|
+
return reuseLiveAttachment({
|
|
10674
|
+
conversationId: args.conversationId,
|
|
10675
|
+
db: args.db,
|
|
10676
|
+
id: afterRace2.id,
|
|
10677
|
+
storage: args.storage,
|
|
10678
|
+
storageKey
|
|
10679
|
+
});
|
|
10680
|
+
}
|
|
10681
|
+
}
|
|
10682
|
+
let inserted = [];
|
|
10683
|
+
try {
|
|
10684
|
+
inserted = await args.db.db().insert(juniorAttachments).values({
|
|
10685
|
+
id,
|
|
10686
|
+
conversationId: args.conversationId,
|
|
10687
|
+
provider: args.storage.provider,
|
|
10688
|
+
storageKey,
|
|
10689
|
+
filename: args.file.filename,
|
|
10690
|
+
contentType: args.file.mimeType,
|
|
10691
|
+
bytes: args.file.bytes,
|
|
10692
|
+
sha256,
|
|
10693
|
+
createdAt: now
|
|
10694
|
+
}).onConflictDoNothing({ target: juniorAttachments.id }).returning({ id: juniorAttachments.id });
|
|
10695
|
+
} catch (error) {
|
|
10696
|
+
await bestEffortDelete(args.storage, storageKey);
|
|
10697
|
+
throw error;
|
|
10698
|
+
}
|
|
10699
|
+
if (inserted.length > 0) {
|
|
10700
|
+
if (await isConversationPurged(args.db, args.conversationId)) {
|
|
10701
|
+
await rejectPurgedAttachmentWrite({
|
|
10702
|
+
conversationId: args.conversationId,
|
|
10703
|
+
db: args.db,
|
|
10704
|
+
id,
|
|
10705
|
+
now,
|
|
10706
|
+
storage: args.storage,
|
|
10707
|
+
storageKey
|
|
10708
|
+
});
|
|
10709
|
+
}
|
|
10710
|
+
return { id };
|
|
10711
|
+
}
|
|
10712
|
+
const [row] = await args.db.db().select({
|
|
10713
|
+
deleteRequestedAt: juniorAttachments.deleteRequestedAt,
|
|
10714
|
+
id: juniorAttachments.id,
|
|
10715
|
+
storageKey: juniorAttachments.storageKey
|
|
10716
|
+
}).from(juniorAttachments).where(eq(juniorAttachments.id, id));
|
|
10717
|
+
if (!row) {
|
|
10718
|
+
await bestEffortDelete(args.storage, storageKey);
|
|
10719
|
+
throw new Error(`Attachment row missing after write for ${id}`);
|
|
10720
|
+
}
|
|
10721
|
+
if (row.deleteRequestedAt === null) {
|
|
10722
|
+
return reuseLiveAttachment({
|
|
10723
|
+
conversationId: args.conversationId,
|
|
10724
|
+
db: args.db,
|
|
10725
|
+
id: row.id,
|
|
10726
|
+
storage: args.storage,
|
|
10727
|
+
storageKey
|
|
10728
|
+
});
|
|
10729
|
+
}
|
|
10730
|
+
if (await isConversationPurged(args.db, args.conversationId)) {
|
|
10731
|
+
await bestEffortDelete(args.storage, storageKey);
|
|
10732
|
+
throw purgedConversationError(args.conversationId);
|
|
10733
|
+
}
|
|
10734
|
+
const revived = await args.db.db().update(juniorAttachments).set({
|
|
10735
|
+
deleteRequestedAt: null,
|
|
10736
|
+
storageKey
|
|
10737
|
+
}).where(
|
|
10738
|
+
and(
|
|
10739
|
+
eq(juniorAttachments.id, id),
|
|
10740
|
+
isNotNull(juniorAttachments.deleteRequestedAt)
|
|
10741
|
+
)
|
|
10742
|
+
).returning({ id: juniorAttachments.id });
|
|
10743
|
+
if (revived.length > 0) {
|
|
10744
|
+
if (await isConversationPurged(args.db, args.conversationId)) {
|
|
10745
|
+
await rejectPurgedAttachmentWrite({
|
|
10746
|
+
conversationId: args.conversationId,
|
|
10747
|
+
db: args.db,
|
|
10748
|
+
id,
|
|
10749
|
+
now,
|
|
10750
|
+
storage: args.storage,
|
|
10751
|
+
storageKey
|
|
10752
|
+
});
|
|
10753
|
+
}
|
|
10754
|
+
if (row.storageKey !== storageKey) {
|
|
10755
|
+
await bestEffortDelete(args.storage, row.storageKey);
|
|
10756
|
+
}
|
|
10757
|
+
return { id };
|
|
10758
|
+
}
|
|
10759
|
+
const [afterRace] = await args.db.db().select({
|
|
10760
|
+
deleteRequestedAt: juniorAttachments.deleteRequestedAt,
|
|
10761
|
+
id: juniorAttachments.id
|
|
10762
|
+
}).from(juniorAttachments).where(eq(juniorAttachments.id, id));
|
|
10763
|
+
if (afterRace?.deleteRequestedAt === null) {
|
|
10764
|
+
return reuseLiveAttachment({
|
|
10765
|
+
conversationId: args.conversationId,
|
|
10766
|
+
db: args.db,
|
|
10767
|
+
id: afterRace.id,
|
|
10768
|
+
storage: args.storage,
|
|
10769
|
+
storageKey
|
|
10770
|
+
});
|
|
10771
|
+
}
|
|
10772
|
+
await bestEffortDelete(args.storage, storageKey);
|
|
10773
|
+
throw new Error(`Attachment ${id} disappeared while reviving`);
|
|
10774
|
+
}
|
|
10775
|
+
async function storeAttachments(args) {
|
|
10776
|
+
const stored = [];
|
|
10777
|
+
for (const file of args.files) {
|
|
10778
|
+
stored.push(
|
|
10779
|
+
await storeAttachment({
|
|
10780
|
+
conversationId: args.conversationId,
|
|
10781
|
+
db: args.db,
|
|
10782
|
+
file,
|
|
10783
|
+
...args.nowMs !== void 0 ? { nowMs: args.nowMs } : {},
|
|
10784
|
+
storage: args.storage
|
|
10785
|
+
})
|
|
10786
|
+
);
|
|
10787
|
+
}
|
|
10788
|
+
return stored;
|
|
10789
|
+
}
|
|
10790
|
+
async function requestAttachmentDeletion(db, conversationIds, nowMs) {
|
|
10791
|
+
if (conversationIds.length === 0) return;
|
|
10792
|
+
await db.db().update(juniorAttachments).set({ deleteRequestedAt: new Date(nowMs) }).where(
|
|
10793
|
+
and(
|
|
10794
|
+
inArray(juniorAttachments.conversationId, conversationIds),
|
|
10795
|
+
isNull(juniorAttachments.deleteRequestedAt)
|
|
10796
|
+
)
|
|
10797
|
+
);
|
|
10798
|
+
}
|
|
10799
|
+
async function collectAttachmentGarbage(args) {
|
|
10800
|
+
void args.nowMs;
|
|
10801
|
+
const rows = await args.db.db().select({
|
|
10802
|
+
id: juniorAttachments.id,
|
|
10803
|
+
storageKey: juniorAttachments.storageKey
|
|
10804
|
+
}).from(juniorAttachments).innerJoin(
|
|
10805
|
+
juniorConversations,
|
|
10806
|
+
eq(
|
|
10807
|
+
juniorAttachments.conversationId,
|
|
10808
|
+
juniorConversations.conversationId
|
|
10809
|
+
)
|
|
10810
|
+
).where(
|
|
10811
|
+
and(
|
|
10812
|
+
eq(juniorAttachments.provider, args.storage.provider),
|
|
10813
|
+
or(
|
|
10814
|
+
isNotNull(juniorAttachments.deleteRequestedAt),
|
|
10815
|
+
isNotNull(juniorConversations.transcriptPurgedAt)
|
|
10816
|
+
)
|
|
10817
|
+
)
|
|
10818
|
+
).orderBy(asc(juniorAttachments.createdAt), asc(juniorAttachments.id)).limit(args.limit ?? ATTACHMENT_GC_BATCH_LIMIT);
|
|
10819
|
+
if (rows.length === 0) return { deleted: 0 };
|
|
10820
|
+
await args.storage.delete(rows.map((row) => row.storageKey));
|
|
10821
|
+
const stillEligible = await args.db.db().select({ id: juniorAttachments.id }).from(juniorAttachments).innerJoin(
|
|
10822
|
+
juniorConversations,
|
|
10823
|
+
eq(
|
|
10824
|
+
juniorAttachments.conversationId,
|
|
10825
|
+
juniorConversations.conversationId
|
|
10826
|
+
)
|
|
10827
|
+
).where(
|
|
10828
|
+
and(
|
|
10829
|
+
inArray(
|
|
10830
|
+
juniorAttachments.id,
|
|
10831
|
+
rows.map((row) => row.id)
|
|
10832
|
+
),
|
|
10833
|
+
or(
|
|
10834
|
+
isNotNull(juniorAttachments.deleteRequestedAt),
|
|
10835
|
+
isNotNull(juniorConversations.transcriptPurgedAt)
|
|
10836
|
+
)
|
|
10837
|
+
)
|
|
10838
|
+
);
|
|
10839
|
+
if (stillEligible.length === 0) return { deleted: 0 };
|
|
10840
|
+
const removed = await args.db.db().delete(juniorAttachments).where(
|
|
10841
|
+
inArray(
|
|
10842
|
+
juniorAttachments.id,
|
|
10843
|
+
stillEligible.map((row) => row.id)
|
|
10844
|
+
)
|
|
10845
|
+
).returning({
|
|
10846
|
+
id: juniorAttachments.id
|
|
10847
|
+
});
|
|
10848
|
+
return { deleted: removed.length };
|
|
10849
|
+
}
|
|
10850
|
+
|
|
10851
|
+
// src/chat/slack/tools/send-files.ts
|
|
10544
10852
|
import { z as z42 } from "zod";
|
|
10545
10853
|
var sendFilesResultSchema = juniorToolOutputSchema.extend({
|
|
10546
|
-
target: z42.string().min(1),
|
|
10547
|
-
channel_id: z42.string().min(1),
|
|
10548
10854
|
deduplicated: z42.boolean().optional(),
|
|
10549
|
-
|
|
10550
|
-
|
|
10551
|
-
|
|
10855
|
+
attachment_refs: z42.array(
|
|
10856
|
+
z42.object({
|
|
10857
|
+
id: z42.string().min(1),
|
|
10858
|
+
name: z42.string().min(1)
|
|
10859
|
+
})
|
|
10860
|
+
)
|
|
10552
10861
|
});
|
|
10553
10862
|
function normalizeFiles(files) {
|
|
10554
10863
|
return files.map((file) => ({
|
|
@@ -10558,7 +10867,7 @@ function normalizeFiles(files) {
|
|
|
10558
10867
|
}));
|
|
10559
10868
|
}
|
|
10560
10869
|
function fileContentDigest(data) {
|
|
10561
|
-
return
|
|
10870
|
+
return createHash5("sha256").update(data).digest("hex");
|
|
10562
10871
|
}
|
|
10563
10872
|
function fileOperationInput(files) {
|
|
10564
10873
|
return files.map((file) => ({
|
|
@@ -10569,7 +10878,7 @@ function fileOperationInput(files) {
|
|
|
10569
10878
|
sha256: fileContentDigest(file.data)
|
|
10570
10879
|
}));
|
|
10571
10880
|
}
|
|
10572
|
-
function createSendFilesTool(context, state, materializeFile) {
|
|
10881
|
+
function createSendFilesTool(context, state, materializeFile, attachments) {
|
|
10573
10882
|
return zodTool({
|
|
10574
10883
|
annotations: {
|
|
10575
10884
|
destructiveHint: false,
|
|
@@ -10611,22 +10920,26 @@ function createSendFilesTool(context, state, materializeFile) {
|
|
|
10611
10920
|
deduplicated: true
|
|
10612
10921
|
});
|
|
10613
10922
|
}
|
|
10923
|
+
const stored = attachments ? await storeAttachments({
|
|
10924
|
+
conversationId: attachments.conversationId,
|
|
10925
|
+
db: attachments.db,
|
|
10926
|
+
files: materializedFiles,
|
|
10927
|
+
storage: attachments.storage
|
|
10928
|
+
}) : [];
|
|
10614
10929
|
const uploads = materializedFiles.map((file) => ({
|
|
10615
10930
|
data: file.data,
|
|
10616
10931
|
filename: file.filename
|
|
10617
10932
|
}));
|
|
10618
|
-
|
|
10933
|
+
await uploadFilesToConversation({
|
|
10619
10934
|
channelId: activeChannelId,
|
|
10620
10935
|
files: uploads,
|
|
10621
10936
|
threadTs
|
|
10622
10937
|
});
|
|
10623
|
-
const fileIds = uploaded?.files?.map((file) => file.id).filter((id) => Boolean(id));
|
|
10624
10938
|
const response = {
|
|
10625
|
-
|
|
10626
|
-
|
|
10627
|
-
|
|
10628
|
-
|
|
10629
|
-
...fileIds ? { file_ids: fileIds } : {}
|
|
10939
|
+
attachment_refs: stored.map((attachment, index) => ({
|
|
10940
|
+
id: attachment.id,
|
|
10941
|
+
name: materializedFiles[index].filename
|
|
10942
|
+
}))
|
|
10630
10943
|
};
|
|
10631
10944
|
state.setOperationResult(operationKey, response);
|
|
10632
10945
|
return response;
|
|
@@ -12009,7 +12322,7 @@ function createSlackThreadReadTool(context) {
|
|
|
12009
12322
|
}
|
|
12010
12323
|
|
|
12011
12324
|
// src/chat/tools/user-lookup.ts
|
|
12012
|
-
import { and, eq, or, sql } from "drizzle-orm";
|
|
12325
|
+
import { and as and2, eq as eq2, or as or2, sql } from "drizzle-orm";
|
|
12013
12326
|
import { alias } from "drizzle-orm/pg-core";
|
|
12014
12327
|
import { z as z54 } from "zod";
|
|
12015
12328
|
var linkedSlackIdentity = alias(juniorIdentities, "user_lookup_slack_identity");
|
|
@@ -12075,12 +12388,12 @@ async function storedSlackUserByEmail(teamId, email) {
|
|
|
12075
12388
|
const emailNormalized = normalizeIdentityEmail(email);
|
|
12076
12389
|
if (!emailNormalized) return void 0;
|
|
12077
12390
|
const identities = await getSqlExecutor().db().select().from(juniorIdentities).where(
|
|
12078
|
-
|
|
12079
|
-
|
|
12080
|
-
|
|
12081
|
-
|
|
12082
|
-
|
|
12083
|
-
|
|
12391
|
+
and2(
|
|
12392
|
+
eq2(juniorIdentities.provider, "slack"),
|
|
12393
|
+
eq2(juniorIdentities.providerTenantId, teamId),
|
|
12394
|
+
eq2(juniorIdentities.kind, "user"),
|
|
12395
|
+
eq2(juniorIdentities.emailVerified, true),
|
|
12396
|
+
eq2(juniorIdentities.emailNormalized, emailNormalized)
|
|
12084
12397
|
)
|
|
12085
12398
|
).limit(2);
|
|
12086
12399
|
if (identities.length > 1) {
|
|
@@ -12132,18 +12445,18 @@ async function resolveSlack(teamId, query) {
|
|
|
12132
12445
|
async function resolveStoredProvider(teamId, provider, query) {
|
|
12133
12446
|
const rows = await getSqlExecutor().db().select({ slack: linkedSlackIdentity }).from(juniorIdentities).innerJoin(
|
|
12134
12447
|
linkedSlackIdentity,
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12138
|
-
|
|
12139
|
-
|
|
12448
|
+
and2(
|
|
12449
|
+
eq2(linkedSlackIdentity.userId, juniorIdentities.userId),
|
|
12450
|
+
eq2(linkedSlackIdentity.kind, "user"),
|
|
12451
|
+
eq2(linkedSlackIdentity.provider, "slack"),
|
|
12452
|
+
eq2(linkedSlackIdentity.providerTenantId, teamId)
|
|
12140
12453
|
)
|
|
12141
12454
|
).where(
|
|
12142
|
-
|
|
12143
|
-
|
|
12144
|
-
|
|
12145
|
-
|
|
12146
|
-
|
|
12455
|
+
and2(
|
|
12456
|
+
eq2(juniorIdentities.kind, "user"),
|
|
12457
|
+
eq2(juniorIdentities.provider, provider),
|
|
12458
|
+
or2(
|
|
12459
|
+
eq2(juniorIdentities.providerSubjectId, query),
|
|
12147
12460
|
sql`lower(${juniorIdentities.handle}) = lower(${query})`
|
|
12148
12461
|
)
|
|
12149
12462
|
)
|
|
@@ -13323,7 +13636,12 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
|
|
|
13323
13636
|
tools.sendFiles = createSendFilesTool(
|
|
13324
13637
|
slackContext,
|
|
13325
13638
|
state,
|
|
13326
|
-
(input) => readSandboxFileUpload(context.workspace, input)
|
|
13639
|
+
(input) => readSandboxFileUpload(context.workspace, input),
|
|
13640
|
+
context.conversationId && context.attachmentStorage ? {
|
|
13641
|
+
conversationId: context.conversationId,
|
|
13642
|
+
db: getSqlExecutor(),
|
|
13643
|
+
storage: context.attachmentStorage
|
|
13644
|
+
} : void 0
|
|
13327
13645
|
);
|
|
13328
13646
|
}
|
|
13329
13647
|
tools.slackChannelListMessages = createSlackChannelListMessagesTool(slackContext);
|
|
@@ -14672,7 +14990,7 @@ function createMcpAuthOrchestration(input) {
|
|
|
14672
14990
|
}
|
|
14673
14991
|
|
|
14674
14992
|
// src/chat/egress/plugin.ts
|
|
14675
|
-
import { randomUUID as
|
|
14993
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
14676
14994
|
|
|
14677
14995
|
// src/chat/sandbox/egress/credentials.ts
|
|
14678
14996
|
var HTTP_READ_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
|
|
@@ -15409,8 +15727,8 @@ async function executeCredentialedEgressRequest(input) {
|
|
|
15409
15727
|
function credentialContextForPluginEgress(credentialContext) {
|
|
15410
15728
|
return {
|
|
15411
15729
|
credentials: credentialContext,
|
|
15412
|
-
contextId:
|
|
15413
|
-
egressId: `plugin-egress:${
|
|
15730
|
+
contextId: randomUUID4(),
|
|
15731
|
+
egressId: `plugin-egress:${randomUUID4()}`,
|
|
15414
15732
|
expiresAtMs: Date.now() + 30 * 60 * 1e3
|
|
15415
15733
|
};
|
|
15416
15734
|
}
|
|
@@ -15945,7 +16263,8 @@ async function wireAgentTools(args) {
|
|
|
15945
16263
|
});
|
|
15946
16264
|
const toolRuntimeContext = {
|
|
15947
16265
|
...commonToolRuntimeContext,
|
|
15948
|
-
...toolRoute
|
|
16266
|
+
...toolRoute,
|
|
16267
|
+
attachmentStorage: args.run.environment?.attachmentStorage
|
|
15949
16268
|
};
|
|
15950
16269
|
const actionReview = createToolActionReview({
|
|
15951
16270
|
context: {
|
|
@@ -18120,33 +18439,6 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
|
|
|
18120
18439
|
}
|
|
18121
18440
|
}
|
|
18122
18441
|
|
|
18123
|
-
// src/chat/runtime/agent-runner.ts
|
|
18124
|
-
function createAgentRunner(execute, options) {
|
|
18125
|
-
const streamFn = options?.streamFn;
|
|
18126
|
-
const tracePropagation = options?.tracePropagation;
|
|
18127
|
-
const bindSpawnAgent = options?.bindSpawnAgent;
|
|
18128
|
-
const canBindSpawn = Boolean(bindSpawnAgent) && isExperimentalFeatureEnabled("subagents");
|
|
18129
|
-
return {
|
|
18130
|
-
run: async (run) => {
|
|
18131
|
-
const spawnAgent = bindSpawnAgent && canBindSpawn && !isAgentRunFeatureDisabled(run.disabledFeatures, "subagents") ? bindSpawnAgent(run) : void 0;
|
|
18132
|
-
const nextRun = {
|
|
18133
|
-
...run,
|
|
18134
|
-
environment: {
|
|
18135
|
-
...run.environment,
|
|
18136
|
-
sandboxTracePropagation: run.environment?.sandboxTracePropagation ?? tracePropagation
|
|
18137
|
-
},
|
|
18138
|
-
...spawnAgent ? {
|
|
18139
|
-
durability: {
|
|
18140
|
-
...run.durability,
|
|
18141
|
-
spawnAgent
|
|
18142
|
-
}
|
|
18143
|
-
} : {}
|
|
18144
|
-
};
|
|
18145
|
-
return await execute(nextRun, streamFn);
|
|
18146
|
-
}
|
|
18147
|
-
};
|
|
18148
|
-
}
|
|
18149
|
-
|
|
18150
18442
|
export {
|
|
18151
18443
|
setConfigDefaults,
|
|
18152
18444
|
getConfigDefaults,
|
|
@@ -18166,11 +18458,12 @@ export {
|
|
|
18166
18458
|
deliverResourceEventSubscription,
|
|
18167
18459
|
sanitizeScheduledTaskPrincipal,
|
|
18168
18460
|
listThreadReplies,
|
|
18461
|
+
requestAttachmentDeletion,
|
|
18462
|
+
collectAttachmentGarbage,
|
|
18169
18463
|
renderBlockText,
|
|
18170
18464
|
renderAttachmentText,
|
|
18171
18465
|
latestReportedProgress,
|
|
18172
18466
|
executeCredentialedEgressRequest,
|
|
18173
18467
|
createContextCompactor,
|
|
18174
|
-
executeAgentRun
|
|
18175
|
-
createAgentRunner
|
|
18468
|
+
executeAgentRun
|
|
18176
18469
|
};
|