@sentry/junior 0.155.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-AWVTLAV2.js → agent-hooks-CCAR46PQ.js} +10 -10
- package/dist/api/locations/detail.d.ts +1 -0
- package/dist/api/schema/conversation.d.ts +19 -4
- package/dist/api/schema/location.d.ts +1 -0
- package/dist/api/schema/person.d.ts +1 -0
- package/dist/api/schema.js +1 -1
- package/dist/api.js +48 -36
- package/dist/app.js +147 -44
- package/dist/{catalog-runtime-V6YD6KH5.js → catalog-runtime-3SNKYCBG.js} +5 -5
- 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/ingress/bot-mention.d.ts +13 -0
- package/dist/chat/plugins/unfinished-work.d.ts +6 -0
- package/dist/chat/runtime/agent-runner.d.ts +2 -0
- 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 +2 -1
- package/dist/chat/tools/types.d.ts +2 -0
- package/dist/{chunk-V57LZDHN.js → chunk-3FFUC32L.js} +6 -6
- package/dist/{chunk-J2SYI36O.js → chunk-3L2PMOSR.js} +4 -4
- package/dist/{chunk-2AHVM3HK.js → chunk-4ZZDTHFC.js} +10 -8
- package/dist/{chunk-AENPRXCG.js → chunk-53W3LZEW.js} +381 -55
- package/dist/{chunk-ELOTIL5F.js → chunk-6CINHXIL.js} +4 -4
- package/dist/{chunk-37G5HJ2X.js → chunk-6JUU7J2B.js} +4 -4
- package/dist/{chunk-KBT2I5ER.js → chunk-7RAETIYO.js} +6 -6
- package/dist/{chunk-NWSKFYOH.js → chunk-A6WPDFHQ.js} +1 -1
- package/dist/{chunk-773XC7P4.js → chunk-AIJRG227.js} +159 -128
- package/dist/{chunk-APHDJYN7.js → chunk-CK2H7CFO.js} +1 -1
- package/dist/{chunk-Y7ZUBP2K.js → chunk-CN2XSVKF.js} +6 -6
- package/dist/{chunk-TVXAN43I.js → chunk-EDJ64P2P.js} +1 -1
- package/dist/{chunk-XFZLQANQ.js → chunk-GKC43TLS.js} +2 -2
- package/dist/{chunk-UWTXAYBP.js → chunk-GSBPZHLQ.js} +9 -9
- package/dist/{chunk-JJX77MB7.js → chunk-IIO5PFZX.js} +3 -3
- package/dist/{chunk-RQ62VKM7.js → chunk-IZEBHYI4.js} +1 -1
- package/dist/{chunk-J7MWZFFP.js → chunk-JUJR6WTL.js} +4 -4
- package/dist/{chunk-JFZBGFNX.js → chunk-KBGMYLSV.js} +2 -1
- package/dist/{chunk-LQT3SWFA.js → chunk-KCA5MKHU.js} +5 -5
- package/dist/{chunk-SDRJ2LE3.js → chunk-MC57E5U5.js} +1 -1
- package/dist/{chunk-2WLJDM23.js → chunk-MJE7XKWP.js} +1 -1
- package/dist/{chunk-TKJ7277U.js → chunk-NTNU6T2D.js} +2 -2
- package/dist/{chunk-EORR34UB.js → chunk-OGZPRMZA.js} +1 -1
- package/dist/{chunk-NKFRRZIT.js → chunk-OMQJB7YN.js} +19 -18
- package/dist/{chunk-Y6MVGU7L.js → chunk-PMFGVLDU.js} +10 -10
- package/dist/{chunk-KTVHAHUV.js → chunk-SE3D225X.js} +1 -1
- package/dist/{chunk-JIC33O5L.js → chunk-SRJA6QLM.js} +2 -2
- package/dist/{chunk-4K5N6HTX.js → chunk-TN4LVILT.js} +5 -5
- package/dist/{chunk-MLBH7J7J.js → chunk-TNXGMFWV.js} +1 -1
- package/dist/{chunk-RN3AWYEP.js → chunk-WD7SEUZO.js} +1 -1
- package/dist/{chunk-ZLSFOSDK.js → chunk-X5NZQH5U.js} +2 -1
- package/dist/{chunk-7NYEB2TM.js → chunk-X7W45B5G.js} +1 -1
- package/dist/{chunk-CPQBTTI6.js → chunk-ZNWRYNCA.js} +5 -5
- package/dist/cli/chat.js +30 -30
- package/dist/cli/check.js +6 -6
- package/dist/cli/plugins.js +13 -13
- package/dist/cli/snapshot-create.js +9 -9
- package/dist/cli/upgrade.js +7 -7
- package/dist/db/schema/attachments.d.ts +178 -0
- package/dist/db/schema.d.ts +179 -1
- package/dist/{db-WT7P56AH.js → db-TYUUKGJX.js} +7 -7
- 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-R2PK2MCA.js → oauth-callback-server-AWVDKPR5.js} +23 -23
- package/dist/{runner-O7YYUIHT.js → runner-JUQXMACC.js} +13 -13
- package/dist/{skills-S6HLQRH7.js → skills-4GZTZX4V.js} +6 -6
- package/dist/spawn-32SSRWU4.js +37 -0
- package/dist/{validation-46WD2OAR.js → validation-DRLNJRND.js} +6 -6
- package/dist/version.js +1 -1
- package/dist/{work-YT5QUBS3.js → work-TGIXRRJY.js} +17 -17
- package/dist/worker-IFXZOYED.js +24 -0
- package/migrations/0027_attachment_storage.sql +16 -0
- package/migrations/meta/0027_snapshot.json +2554 -0
- package/migrations/meta/_journal.json +8 -1
- package/package.json +5 -4
- package/dist/spawn-B4SBFFA2.js +0 -37
- package/dist/worker-4C5BEDWN.js +0 -24
|
@@ -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,7 +48,7 @@ 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,
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
runNonInteractiveCommand,
|
|
75
75
|
throwSandboxOperationError,
|
|
76
76
|
wrapSandboxSetupError
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-6JUU7J2B.js";
|
|
78
78
|
import {
|
|
79
79
|
SCHEDULED_TASK_SYSTEM_ACTOR,
|
|
80
80
|
compactEventTask,
|
|
@@ -106,10 +106,10 @@ import {
|
|
|
106
106
|
saveEventTask,
|
|
107
107
|
scheduledTaskAttributes,
|
|
108
108
|
writableEventTask
|
|
109
|
-
} from "./chunk-
|
|
109
|
+
} from "./chunk-KCA5MKHU.js";
|
|
110
110
|
import {
|
|
111
111
|
parseSlackThreadId
|
|
112
|
-
} from "./chunk-
|
|
112
|
+
} from "./chunk-CK2H7CFO.js";
|
|
113
113
|
import {
|
|
114
114
|
AGENTS_REMOVAL_NOTICE,
|
|
115
115
|
AGENTS_REPLACEMENT_NOTICE,
|
|
@@ -179,7 +179,7 @@ import {
|
|
|
179
179
|
stripRuntimeTurnContext,
|
|
180
180
|
trimTrailingAssistantMessages,
|
|
181
181
|
truncateText
|
|
182
|
-
} from "./chunk-
|
|
182
|
+
} from "./chunk-3L2PMOSR.js";
|
|
183
183
|
import {
|
|
184
184
|
JUNIOR_THREAD_STATE_TTL_MS
|
|
185
185
|
} from "./chunk-3Y47VMHV.js";
|
|
@@ -195,7 +195,7 @@ import {
|
|
|
195
195
|
getSlackToolContext,
|
|
196
196
|
readActorIdentity,
|
|
197
197
|
resolveChannelCapabilities
|
|
198
|
-
} from "./chunk-
|
|
198
|
+
} from "./chunk-3FFUC32L.js";
|
|
199
199
|
import {
|
|
200
200
|
SlackActionError,
|
|
201
201
|
downloadPrivateSlackFile,
|
|
@@ -204,7 +204,7 @@ import {
|
|
|
204
204
|
isConversationScopedChannel,
|
|
205
205
|
normalizeSlackConversationId,
|
|
206
206
|
withSlackRetries
|
|
207
|
-
} from "./chunk-
|
|
207
|
+
} from "./chunk-NTNU6T2D.js";
|
|
208
208
|
import {
|
|
209
209
|
KNOWN_CONVERSATION_EVENT_TYPES,
|
|
210
210
|
contextProvenance,
|
|
@@ -216,10 +216,12 @@ import {
|
|
|
216
216
|
instructionActors,
|
|
217
217
|
instructionProvenanceFor,
|
|
218
218
|
sameActorIdentity
|
|
219
|
-
} from "./chunk-
|
|
219
|
+
} from "./chunk-IIO5PFZX.js";
|
|
220
220
|
import {
|
|
221
|
+
juniorAttachments,
|
|
222
|
+
juniorConversations,
|
|
221
223
|
juniorIdentities
|
|
222
|
-
} from "./chunk-
|
|
224
|
+
} from "./chunk-AIJRG227.js";
|
|
223
225
|
import {
|
|
224
226
|
SANDBOX_DATA_ROOT,
|
|
225
227
|
SANDBOX_SKILLS_ROOT,
|
|
@@ -231,7 +233,7 @@ import {
|
|
|
231
233
|
} from "./chunk-EM225ITJ.js";
|
|
232
234
|
import {
|
|
233
235
|
getStateAdapter
|
|
234
|
-
} from "./chunk-
|
|
236
|
+
} from "./chunk-MC57E5U5.js";
|
|
235
237
|
import {
|
|
236
238
|
ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX,
|
|
237
239
|
COMPACTION_SUMMARY_PREFIX,
|
|
@@ -264,7 +266,7 @@ import {
|
|
|
264
266
|
resolveGatewayCredential,
|
|
265
267
|
resolveGatewayModel,
|
|
266
268
|
unwrapCurrentInstruction
|
|
267
|
-
} from "./chunk-
|
|
269
|
+
} from "./chunk-GKC43TLS.js";
|
|
268
270
|
import {
|
|
269
271
|
canExposeConversationPayload,
|
|
270
272
|
resolveConversationPrivacy,
|
|
@@ -274,16 +276,16 @@ import {
|
|
|
274
276
|
toGenAiMessagesTraceAttributes,
|
|
275
277
|
toGenAiPayloadMetadata,
|
|
276
278
|
toGenAiPayloadTraceAttributes
|
|
277
|
-
} from "./chunk-
|
|
279
|
+
} from "./chunk-MJE7XKWP.js";
|
|
278
280
|
import {
|
|
279
281
|
discoverSkills,
|
|
280
282
|
findSkillByName,
|
|
281
283
|
loadSkillsByName,
|
|
282
284
|
parseSkillInvocation
|
|
283
|
-
} from "./chunk-
|
|
285
|
+
} from "./chunk-SRJA6QLM.js";
|
|
284
286
|
import {
|
|
285
287
|
pluginCatalogRuntime
|
|
286
|
-
} from "./chunk-
|
|
288
|
+
} from "./chunk-EDJ64P2P.js";
|
|
287
289
|
import {
|
|
288
290
|
CredentialUnavailableError,
|
|
289
291
|
OAuthProviderError,
|
|
@@ -291,7 +293,7 @@ import {
|
|
|
291
293
|
getOAuthProviderErrorAttributes,
|
|
292
294
|
resolveAuthTokenPlaceholder,
|
|
293
295
|
resolvePluginCommandEnv
|
|
294
|
-
} from "./chunk-
|
|
296
|
+
} from "./chunk-WD7SEUZO.js";
|
|
295
297
|
import {
|
|
296
298
|
credentialUserSubjectId
|
|
297
299
|
} from "./chunk-BDUENQD3.js";
|
|
@@ -319,7 +321,7 @@ import {
|
|
|
319
321
|
summarizeMessageText,
|
|
320
322
|
withLogContext,
|
|
321
323
|
withSpan
|
|
322
|
-
} from "./chunk-
|
|
324
|
+
} from "./chunk-X7W45B5G.js";
|
|
323
325
|
import {
|
|
324
326
|
startInactiveSpan,
|
|
325
327
|
withActiveSpan
|
|
@@ -10535,15 +10537,327 @@ function createSlackMessageAddReactionTool(context, state) {
|
|
|
10535
10537
|
}
|
|
10536
10538
|
|
|
10537
10539
|
// src/chat/slack/tools/send-files.ts
|
|
10538
|
-
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
|
|
10539
10852
|
import { z as z42 } from "zod";
|
|
10540
10853
|
var sendFilesResultSchema = juniorToolOutputSchema.extend({
|
|
10541
|
-
target: z42.string().min(1),
|
|
10542
|
-
channel_id: z42.string().min(1),
|
|
10543
10854
|
deduplicated: z42.boolean().optional(),
|
|
10544
|
-
|
|
10545
|
-
|
|
10546
|
-
|
|
10855
|
+
attachment_refs: z42.array(
|
|
10856
|
+
z42.object({
|
|
10857
|
+
id: z42.string().min(1),
|
|
10858
|
+
name: z42.string().min(1)
|
|
10859
|
+
})
|
|
10860
|
+
)
|
|
10547
10861
|
});
|
|
10548
10862
|
function normalizeFiles(files) {
|
|
10549
10863
|
return files.map((file) => ({
|
|
@@ -10553,7 +10867,7 @@ function normalizeFiles(files) {
|
|
|
10553
10867
|
}));
|
|
10554
10868
|
}
|
|
10555
10869
|
function fileContentDigest(data) {
|
|
10556
|
-
return
|
|
10870
|
+
return createHash5("sha256").update(data).digest("hex");
|
|
10557
10871
|
}
|
|
10558
10872
|
function fileOperationInput(files) {
|
|
10559
10873
|
return files.map((file) => ({
|
|
@@ -10564,7 +10878,7 @@ function fileOperationInput(files) {
|
|
|
10564
10878
|
sha256: fileContentDigest(file.data)
|
|
10565
10879
|
}));
|
|
10566
10880
|
}
|
|
10567
|
-
function createSendFilesTool(context, state, materializeFile) {
|
|
10881
|
+
function createSendFilesTool(context, state, materializeFile, attachments) {
|
|
10568
10882
|
return zodTool({
|
|
10569
10883
|
annotations: {
|
|
10570
10884
|
destructiveHint: false,
|
|
@@ -10606,22 +10920,26 @@ function createSendFilesTool(context, state, materializeFile) {
|
|
|
10606
10920
|
deduplicated: true
|
|
10607
10921
|
});
|
|
10608
10922
|
}
|
|
10923
|
+
const stored = attachments ? await storeAttachments({
|
|
10924
|
+
conversationId: attachments.conversationId,
|
|
10925
|
+
db: attachments.db,
|
|
10926
|
+
files: materializedFiles,
|
|
10927
|
+
storage: attachments.storage
|
|
10928
|
+
}) : [];
|
|
10609
10929
|
const uploads = materializedFiles.map((file) => ({
|
|
10610
10930
|
data: file.data,
|
|
10611
10931
|
filename: file.filename
|
|
10612
10932
|
}));
|
|
10613
|
-
|
|
10933
|
+
await uploadFilesToConversation({
|
|
10614
10934
|
channelId: activeChannelId,
|
|
10615
10935
|
files: uploads,
|
|
10616
10936
|
threadTs
|
|
10617
10937
|
});
|
|
10618
|
-
const fileIds = uploaded?.files?.map((file) => file.id).filter((id) => Boolean(id));
|
|
10619
10938
|
const response = {
|
|
10620
|
-
|
|
10621
|
-
|
|
10622
|
-
|
|
10623
|
-
|
|
10624
|
-
...fileIds ? { file_ids: fileIds } : {}
|
|
10939
|
+
attachment_refs: stored.map((attachment, index) => ({
|
|
10940
|
+
id: attachment.id,
|
|
10941
|
+
name: materializedFiles[index].filename
|
|
10942
|
+
}))
|
|
10625
10943
|
};
|
|
10626
10944
|
state.setOperationResult(operationKey, response);
|
|
10627
10945
|
return response;
|
|
@@ -12004,7 +12322,7 @@ function createSlackThreadReadTool(context) {
|
|
|
12004
12322
|
}
|
|
12005
12323
|
|
|
12006
12324
|
// src/chat/tools/user-lookup.ts
|
|
12007
|
-
import { and, eq, or, sql } from "drizzle-orm";
|
|
12325
|
+
import { and as and2, eq as eq2, or as or2, sql } from "drizzle-orm";
|
|
12008
12326
|
import { alias } from "drizzle-orm/pg-core";
|
|
12009
12327
|
import { z as z54 } from "zod";
|
|
12010
12328
|
var linkedSlackIdentity = alias(juniorIdentities, "user_lookup_slack_identity");
|
|
@@ -12070,12 +12388,12 @@ async function storedSlackUserByEmail(teamId, email) {
|
|
|
12070
12388
|
const emailNormalized = normalizeIdentityEmail(email);
|
|
12071
12389
|
if (!emailNormalized) return void 0;
|
|
12072
12390
|
const identities = await getSqlExecutor().db().select().from(juniorIdentities).where(
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12078
|
-
|
|
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)
|
|
12079
12397
|
)
|
|
12080
12398
|
).limit(2);
|
|
12081
12399
|
if (identities.length > 1) {
|
|
@@ -12127,18 +12445,18 @@ async function resolveSlack(teamId, query) {
|
|
|
12127
12445
|
async function resolveStoredProvider(teamId, provider, query) {
|
|
12128
12446
|
const rows = await getSqlExecutor().db().select({ slack: linkedSlackIdentity }).from(juniorIdentities).innerJoin(
|
|
12129
12447
|
linkedSlackIdentity,
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12448
|
+
and2(
|
|
12449
|
+
eq2(linkedSlackIdentity.userId, juniorIdentities.userId),
|
|
12450
|
+
eq2(linkedSlackIdentity.kind, "user"),
|
|
12451
|
+
eq2(linkedSlackIdentity.provider, "slack"),
|
|
12452
|
+
eq2(linkedSlackIdentity.providerTenantId, teamId)
|
|
12135
12453
|
)
|
|
12136
12454
|
).where(
|
|
12137
|
-
|
|
12138
|
-
|
|
12139
|
-
|
|
12140
|
-
|
|
12141
|
-
|
|
12455
|
+
and2(
|
|
12456
|
+
eq2(juniorIdentities.kind, "user"),
|
|
12457
|
+
eq2(juniorIdentities.provider, provider),
|
|
12458
|
+
or2(
|
|
12459
|
+
eq2(juniorIdentities.providerSubjectId, query),
|
|
12142
12460
|
sql`lower(${juniorIdentities.handle}) = lower(${query})`
|
|
12143
12461
|
)
|
|
12144
12462
|
)
|
|
@@ -13318,7 +13636,12 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
|
|
|
13318
13636
|
tools.sendFiles = createSendFilesTool(
|
|
13319
13637
|
slackContext,
|
|
13320
13638
|
state,
|
|
13321
|
-
(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
|
|
13322
13645
|
);
|
|
13323
13646
|
}
|
|
13324
13647
|
tools.slackChannelListMessages = createSlackChannelListMessagesTool(slackContext);
|
|
@@ -14667,7 +14990,7 @@ function createMcpAuthOrchestration(input) {
|
|
|
14667
14990
|
}
|
|
14668
14991
|
|
|
14669
14992
|
// src/chat/egress/plugin.ts
|
|
14670
|
-
import { randomUUID as
|
|
14993
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
14671
14994
|
|
|
14672
14995
|
// src/chat/sandbox/egress/credentials.ts
|
|
14673
14996
|
var HTTP_READ_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
|
|
@@ -15404,8 +15727,8 @@ async function executeCredentialedEgressRequest(input) {
|
|
|
15404
15727
|
function credentialContextForPluginEgress(credentialContext) {
|
|
15405
15728
|
return {
|
|
15406
15729
|
credentials: credentialContext,
|
|
15407
|
-
contextId:
|
|
15408
|
-
egressId: `plugin-egress:${
|
|
15730
|
+
contextId: randomUUID4(),
|
|
15731
|
+
egressId: `plugin-egress:${randomUUID4()}`,
|
|
15409
15732
|
expiresAtMs: Date.now() + 30 * 60 * 1e3
|
|
15410
15733
|
};
|
|
15411
15734
|
}
|
|
@@ -15940,7 +16263,8 @@ async function wireAgentTools(args) {
|
|
|
15940
16263
|
});
|
|
15941
16264
|
const toolRuntimeContext = {
|
|
15942
16265
|
...commonToolRuntimeContext,
|
|
15943
|
-
...toolRoute
|
|
16266
|
+
...toolRoute,
|
|
16267
|
+
attachmentStorage: args.run.environment?.attachmentStorage
|
|
15944
16268
|
};
|
|
15945
16269
|
const actionReview = createToolActionReview({
|
|
15946
16270
|
context: {
|
|
@@ -18134,6 +18458,8 @@ export {
|
|
|
18134
18458
|
deliverResourceEventSubscription,
|
|
18135
18459
|
sanitizeScheduledTaskPrincipal,
|
|
18136
18460
|
listThreadReplies,
|
|
18461
|
+
requestAttachmentDeletion,
|
|
18462
|
+
collectAttachmentGarbage,
|
|
18137
18463
|
renderBlockText,
|
|
18138
18464
|
renderAttachmentText,
|
|
18139
18465
|
latestReportedProgress,
|
|
@@ -8,14 +8,14 @@ import {
|
|
|
8
8
|
getConversationStore,
|
|
9
9
|
parseDestination,
|
|
10
10
|
sameDestination
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-IIO5PFZX.js";
|
|
12
12
|
import {
|
|
13
13
|
getDefaultRedisStateAdapterFor,
|
|
14
14
|
getStateAdapter
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-MC57E5U5.js";
|
|
16
16
|
import {
|
|
17
17
|
getChatConfig
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-GKC43TLS.js";
|
|
19
19
|
import {
|
|
20
20
|
parseStoredSlackActor
|
|
21
21
|
} from "./chunk-V7YE4WCP.js";
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
isRecord,
|
|
24
24
|
toOptionalNumber,
|
|
25
25
|
toOptionalString
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-X7W45B5G.js";
|
|
27
27
|
|
|
28
28
|
// src/chat/task-execution/state.ts
|
|
29
29
|
import { randomUUID } from "crypto";
|
|
@@ -4,18 +4,18 @@ import {
|
|
|
4
4
|
} from "./chunk-EM225ITJ.js";
|
|
5
5
|
import {
|
|
6
6
|
getStateAdapter
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MC57E5U5.js";
|
|
8
8
|
import {
|
|
9
9
|
toOptionalTrimmed
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-GKC43TLS.js";
|
|
11
11
|
import {
|
|
12
12
|
pluginCatalogRuntime
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-EDJ64P2P.js";
|
|
14
14
|
import {
|
|
15
15
|
setSpanAttributes,
|
|
16
16
|
setSpanStatus,
|
|
17
17
|
withSpan
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-X7W45B5G.js";
|
|
19
19
|
|
|
20
20
|
// src/chat/sandbox/resources.ts
|
|
21
21
|
var configuredResources;
|