@sentry/junior 0.268.0 → 0.269.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/README.md +2 -9
- package/dist/{adapter-04AcD2SO.js → adapter-2-CG25be.js} +3 -49
- package/dist/{admin-DIU1QyG3.js → admin-DSs8S5Uy.js} +1 -1
- package/dist/{agent-runner-CAYfFmU7.js → agent-runner-CrDrPUtY.js} +3208 -2826
- package/dist/api/schema.d.ts +2 -3
- package/dist/api/schema.js +7 -7
- package/dist/api.d.ts +3 -1
- package/dist/api.js +157 -298
- package/dist/{app-z6Uuyq3j.d.ts → app-BrMMzjYm.d.ts} +8 -2
- package/dist/app.d.ts +1 -1
- package/dist/app.js +121 -207
- package/dist/{automation-CmeFBSEh.js → automation-p87hg_AV.js} +74 -74
- package/dist/{briefs-DQbV2jNr.js → briefs-PtODdLNu.js} +4 -4
- package/dist/{catalog-runtime-BD9GSpc6.js → catalog-runtime-BsoSmTM0.js} +1 -1
- package/dist/cli/chat.js +16 -26
- package/dist/cli/check.js +3 -3
- package/dist/cli/main.js +5 -3
- package/dist/cli/plugins.js +4 -4
- package/dist/cli/snapshot-create.js +4 -4
- package/dist/cli/upgrade.d.ts +1 -1
- package/dist/cli/upgrade.js +3 -3
- package/dist/{client-C1yDYjoS.js → client-Cqf4TboL.js} +20 -15
- package/dist/{config-DrTeF80T.js → config-CPsE4T5L.js} +2 -2
- package/dist/{connections-D46f8vvi.js → connections-upFXLmhG.js} +10 -10
- package/dist/{conversation-DSo310Ps.js → conversation-CTpD_PGk.js} +7 -84
- package/dist/{conversation-privacy-CxlOCiUo.js → conversation-privacy-D6zJc8ff.js} +1 -1
- package/dist/{credential-sync-sm9fegLY.js → credential-sync-CS_6IC-f.js} +15 -14
- package/dist/{credentialed-lukuD-cc.js → credentialed-BU-OW7HP.js} +548 -71
- package/dist/{store-xMuuXRE0.d.ts → db-BzOCzVb1.d.ts} +4 -0
- package/dist/{executor-4vhvsMZJ.js → executor-CNS7ONt-.js} +6 -6
- package/dist/instrumentation.js +2 -2
- package/dist/{interruption-marker-CkncDT8d.js → interruption-marker-g6Xup3Fk.js} +1 -1
- package/dist/{job-queue-In9QKz-I.js → job-queue-DI-k-Bbk.js} +2 -2
- package/dist/{list-BkgnXEEB.js → list-CGoQdXTp.js} +193 -656
- package/dist/locks-D-0h111u.js +48 -0
- package/dist/{logging-DLSpkSSr.js → logging-n7knse-O.js} +1 -1
- package/dist/{history-C84mlAwO.js → media-85PDJxO_.js} +83 -1
- package/dist/{message-BObyg59s.js → message-BpaWd8TT.js} +4 -4
- package/dist/nitro.d.ts +1 -1
- package/dist/nitro.js +3 -3
- package/dist/{oauth-callback-server-B-WbSdoH.js → oauth-callback-server-CpGmEw_i.js} +2 -2
- package/dist/{prompt-BW9jFsqZ.js → prompt-BlQB0QQt.js} +1 -1
- package/dist/{registry-BgecKva0.js → registry-By36_xsm.js} +1 -1
- package/dist/reporting-schema-CZREhYc-.js +104 -0
- package/dist/{web-message-id-DlHNANtd.js → reporting-window-CVarfId9.js} +130 -7
- package/dist/{resolve-Cpa4Bu1O.js → resolve-CUIBcdPd.js} +3 -3
- package/dist/{result-D3TSmZZ8.js → result-BemsOMOO.js} +30 -11
- package/dist/{runner-DS5OKhEp.js → runner-BVok7PAA.js} +12 -11
- package/dist/{sandbox-egress-signals-CnDjY5rx.js → sandbox-egress-signals-BSUWQI95.js} +1 -1
- package/dist/{schema-0050HFnB.js → schema-ChnFo5f2.js} +36 -20
- package/dist/{schema-ZngqcOWM.d.ts → schema-jK4-1u_H.d.ts} +126 -12
- package/dist/{service-account-CKV2WTY7.js → service-account-DHvlLnZw.js} +4 -3
- package/dist/{service-account-DGjnDw9y.js → service-account-hMmESDcr.js} +3 -3
- package/dist/{session-stop-Dam1EI7B.js → session-stop-BQW_iFcd.js} +15 -15
- package/dist/{skills-CfAnfImD.js → skills-DmJJIuLF.js} +2 -2
- package/dist/{spawn-cmq9p4Ly.js → spawn-ChCm46i-.js} +2 -2
- package/dist/{store-C5PN02QO.js → store-1DVhoKOL.js} +3 -3
- package/dist/{store-zPEoJPBB.js → store-DCo2n5iJ.js} +3 -3
- package/dist/{task-queue-_mf28dSu.js → task-queue-HMC4QjFm.js} +3 -3
- package/dist/task-runner-cA6yjn_E.js +269 -0
- package/dist/{thread-state-BbbPh0Sn.js → thread-state-CHy8LS0C.js} +5 -5
- package/dist/{turn-failure-response-BKKmnMB5.js → turn-failure-response-Dr7erLWs.js} +9 -9
- package/dist/{turn-lifecycle-oP0kVeGz.js → turn-lifecycle-bf2fIYi_.js} +1 -1
- package/dist/{tasks-SB9z-VTU.js → turn-session-routing-BqO0qXLk.js} +928 -116
- package/dist/{validation--JsAGLwc.js → validation-DHR1ivfh.js} +1 -1
- package/dist/{version-jHwJp4hC.js → version-CXCHLgWm.js} +1 -1
- package/dist/version.js +1 -1
- package/dist/{viewer-CpXTGlep.js → viewer-DSbD6DF6.js} +201 -27
- package/dist/{work-3N-GHY9m.js → work-BE_qTYGi.js} +17 -36
- package/dist/{worker-CCdbcItd.js → worker-Cm9_sWXg.js} +15 -7
- package/migrations/0069_system_identity.sql +25 -0
- package/migrations/0070_review_item_foreign_keys.sql +5 -0
- package/migrations/AGENTS.md +17 -0
- package/migrations/meta/0069_snapshot.json +3979 -0
- package/migrations/meta/0070_snapshot.json +3997 -0
- package/migrations/meta/_journal.json +15 -1
- package/package.json +4 -4
- package/dist/db-BU4LQD8s.d.ts +0 -6
- package/dist/history-BgI33Kie.d.ts +0 -78
- package/dist/reporting-window-DVCD_10C.js +0 -227
- package/dist/task-runner-DMI2prDO.js +0 -1073
- package/migrations/README.md +0 -30
package/dist/app.js
CHANGED
|
@@ -1,43 +1,44 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { _ as snapshotRuntimeConfig, d as restoreRuntimeConfig, f as setBotModelConfig, g as setSlackReactionConfig, h as setRuntimeLimits, i as getChatConfig, m as setProfiles, n as botConfig, o as getSlackBotToken, p as setCrossActorMidRunMode, u as resetRuntimeConfig } from "./config-
|
|
3
|
-
import { A as JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE, E as withSpan, N as JUNIOR_WORKSPACE_SNAPSHOT_JOB_CALLBACK_ROUTE, T as withLogContext, b as setSpanAttributes, h as logWarn, m as logInfo, p as logException, r as createRequestContext, w as withContext, z as normalizeIdentityEmail } from "./logging-
|
|
1
|
+
import { B as readScheduledAutomation, Fr as SubscribedReplyReason, G as blockEventAutomation, H as saveScheduledAutomationInLock, Hr as getExperimentalFeatures, Jn as hasRunnableConversationWork, K as collectEventAutomationMatchKeys, M as recordAutomationExecution, Mn as CONVERSATION_WORK_STALE_ENQUEUE_MS, R as listScheduledAutomationsForTeam, Rr as getThreadStopDecision, S as existingConversationId, U as scheduledRunId, Ur as isExperimentalFeatureEnabled, W as withScheduledAutomationLock, Wr as setExperimentalFeatures, Wt as appendConversationMessages, Xn as isInvalidConversationRecordError, Xr as setConfigDefaults, Xt as settleConversationTitleWork, Y as findMatchingEventAutomations, Yr as getConfigDefaults, a as confirmDispatchMailboxAppend, b as notifyAutomationBlocked, f as getPluginDispatchProjection, ht as eventGuidance, it as automationVersionOf, m as listPendingDispatchMailboxAppends, nt as eventAutomationRunLimitReason, o as createOrGetDispatch, p as isTerminalDispatchStatus, qt as projectConversationMessages, r as buildDispatchId, s as getDispatchConversationId, tt as admitEventAutomationRun, u as getDispatchRecord, v as markDispatchFailed } from "./turn-session-routing-BqO0qXLk.js";
|
|
2
|
+
import { _ as snapshotRuntimeConfig, d as restoreRuntimeConfig, f as setBotModelConfig, g as setSlackReactionConfig, h as setRuntimeLimits, i as getChatConfig, m as setProfiles, n as botConfig, o as getSlackBotToken, p as setCrossActorMidRunMode, u as resetRuntimeConfig } from "./config-CPsE4T5L.js";
|
|
3
|
+
import { A as JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE, E as withSpan, L as GOOGLE_IDENTITY_PROVIDER, N as JUNIOR_WORKSPACE_SNAPSHOT_JOB_CALLBACK_ROUTE, T as withLogContext, b as setSpanAttributes, h as logWarn, m as logInfo, p as logException, r as createRequestContext, w as withContext, z as normalizeIdentityEmail } from "./logging-n7knse-O.js";
|
|
4
4
|
import { n as captureMessage } from "./sentry-MDkYAVPV.js";
|
|
5
|
-
import { t as JUNIOR_VERSION } from "./version-
|
|
5
|
+
import { t as JUNIOR_VERSION } from "./version-CXCHLgWm.js";
|
|
6
6
|
import { f as parseSlackTeamId, g as slackMessageTsSchema, h as slackMessageTsFromMs, m as parseSlackMessageTs, n as createSlackActor, p as parseSlackUserId, s as parseActorUserId, u as parseSlackChannelId } from "./actor-CP9K2Idu.js";
|
|
7
|
-
import {
|
|
7
|
+
import { C as getSqlExecutor, M as resolveActorIdentityId, O as withConversationMutationLock, R as recordGoogleSignIn, S as getDb, T as withConversationEventLock, _ as closeDb, g as createCache, i as readActorIdentity, l as resolveViewerUser, p as parseAvatarUrl, x as getConversationStore, y as getConversationEventStore } from "./viewer-DSbD6DF6.js";
|
|
8
8
|
import { a as juniorAgentInvocations, d as juniorDestinations, i as juniorAgentBindings, s as juniorConversations } from "./agent-invocations-C1RNOCs8.js";
|
|
9
|
-
import { d as juniorAutomations, g as juniorConversationBriefs, l as juniorAutomationRuns, y as juniorConversationEvents } from "./executor-
|
|
10
|
-
import { n as pluginCatalogRuntime } from "./catalog-runtime-
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { a as
|
|
9
|
+
import { c as juniorReviewItems, d as juniorAutomations, g as juniorConversationBriefs, l as juniorAutomationRuns, y as juniorConversationEvents } from "./executor-CNS7ONt-.js";
|
|
10
|
+
import { n as pluginCatalogRuntime } from "./catalog-runtime-BsoSmTM0.js";
|
|
11
|
+
import { A as verifySlackSignature, C as syncReviewItemSlackCards, Ct as processWorkspaceSnapshotJob, D as parseSlackReviewItemFormTarget, E as parseSlackReviewItemClick, J as readViewerAutomationSummary, L as logScheduledAutomationRunSkipped, O as parseSlackUserInputSubmission, Q as effectiveTaskOutcomes, R as scheduledAutomationRunAttributes, S as readSlackReviewItemCardConversationId, T as buildSlackReviewItemModal, _ as unpublishedArtifactHeaders, _t as recordSubagentEnded, ct as webActorFromEmail, dt as collectAttachmentGarbage, et as deliverReviewItemChange, g as readPublicArtifact, gt as stopConversationSession, h as publicArtifactHeaders, it as conversationTurnIdForMessage, j as parseSlackThreadId, k as runWithSlackInstallation, n as executeAgentRun, pt as requestAttachmentDeletion, rt as appendAndEnqueueWebMessage, st as recordWebConversationActivity, t as createAgentRunner, tt as renderReviewItemMessage, v as lookupSlackUserProfile, wt as ingestEvent, x as createSlackReviewItemShow } from "./agent-runner-CrDrPUtY.js";
|
|
12
|
+
import { At as slackEntitySchema, Bn as getDashboardTaskLink, Bt as clearSandboxEgressSignals, Cr as resolveRootVisibility, Dn as getSlackClient, Er as listConversationAnnotations, Fn as runWithWorkspaceTeamId, Ht as consumeSandboxEgressPermissionDeniedSignal, Ln as getDashboardConversationLink, M as canActOnReviewItem, Pn as getWorkspaceTeamId, S as dismissOpenReviewItems, Tt as postSlackEphemeralMessage, Vn as setDashboardConversationLinkOptions, Vt as consumeSandboxEgressAuthRequiredSignal, Wt as parseSandboxEgressCredentialToken, Xt as normalizeSandboxEgressTracePropagationDomains, _n as bindScheduledAutomationCredentialSubject, ar as createPluginLogger, bn as verifyScheduledAutomationCredentialSubject, c as getPluginRoutes, cn as collectEventMatchKeys, ct as proxyVercelSandboxEgressRequest, fn as findMatchingWatches, ft as resolveBaseUrl, gn as bindEventAutomationCredentialSubject, h as validatePlugins, hn as takeDueTimerWatches, jr as createPluginCache, jt as slackExternalRefIdSchema, kn as isDmChannel, m as setPlugins, n as createUserTokenStore, nr as createPluginState, or as readConversationAccessFromSql, p as getPlugins, s as getPluginApiRoutes, st as isVercelSandboxEgressRequest, v as setBriefsConfig, vn as bindSlackDirectCredentialSubject, vt as slackMention, wt as openSlackModal, xn as verifySlackDirectCredentialSubject, yn as verifyEventAutomationCredentialSubject } from "./credentialed-BU-OW7HP.js";
|
|
13
|
+
import { a as withLock, i as fenceLock, n as MUTATION_LOCK_TTL_MS } from "./locks-D-0h111u.js";
|
|
14
|
+
import { r as getStateAdapter, t as disconnectStateAdapter } from "./adapter-2-CG25be.js";
|
|
14
15
|
import { n as getNextRunAtMs } from "./cadence-R7Em4RjE.js";
|
|
15
|
-
import { D as conversationSurfaceSchema, I as annotationCard, T as conversationReportStatusSchema, h as conversationFeedQuerySchema } from "./conversation-
|
|
16
|
-
import { b as listPendingAgentInvocationMailboxAppends, x as listPendingAgentInvocationResults } from "./store-
|
|
17
|
-
import { E as renderSlackObjectCard, S as renderTaskInput, d as getEventCatalog, f as SLACK_EVENT_NAMESPACE, g as slackChannelMessageRunsAutomation, h as slackChannelMessageReplyThreadTs, m as slackChannelMessageEvent } from "./session-stop-
|
|
18
|
-
import {
|
|
19
|
-
import { c as setSandboxResourceConfig, o as getSandboxResourceConfig } from "./resolve-
|
|
20
|
-
import { a as getVercelConversationWorkQueue, d as getQueueProvider, g as isConversationQueueMessageRejectedError, h as conversationQueueMessageSchema, i as verifyWorkspaceSnapshotJobMessage, o as resolveConversationWorkQueueTopic, s as verifyConversationQueueMessage, t as WORKSPACE_SNAPSHOT_JOB_QUEUE_TOPIC } from "./job-queue-
|
|
21
|
-
import { S as removeActiveConversation, _ as hasRunnableConversationWork$1, c as clearExpiredConversationLease, g as getConversationWorkState, h as getConversation, m as ensureConversationWake, r as appendAndEnqueueInboundMessage, v as listActiveConversationIds } from "./store-
|
|
22
|
-
import {
|
|
23
|
-
import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "./validation
|
|
16
|
+
import { D as conversationSurfaceSchema, I as annotationCard, T as conversationReportStatusSchema, h as conversationFeedQuerySchema } from "./conversation-CTpD_PGk.js";
|
|
17
|
+
import { b as listPendingAgentInvocationMailboxAppends, x as listPendingAgentInvocationResults } from "./store-1DVhoKOL.js";
|
|
18
|
+
import { E as renderSlackObjectCard, S as renderTaskInput, d as getEventCatalog, f as SLACK_EVENT_NAMESPACE, g as slackChannelMessageRunsAutomation, h as slackChannelMessageReplyThreadTs, m as slackChannelMessageEvent } from "./session-stop-BQW_iFcd.js";
|
|
19
|
+
import { m as buttonUserInputField } from "./reporting-window-CVarfId9.js";
|
|
20
|
+
import { c as setSandboxResourceConfig, o as getSandboxResourceConfig } from "./resolve-CUIBcdPd.js";
|
|
21
|
+
import { a as getVercelConversationWorkQueue, d as getQueueProvider, g as isConversationQueueMessageRejectedError, h as conversationQueueMessageSchema, i as verifyWorkspaceSnapshotJobMessage, o as resolveConversationWorkQueueTopic, s as verifyConversationQueueMessage, t as WORKSPACE_SNAPSHOT_JOB_QUEUE_TOPIC } from "./job-queue-DI-k-Bbk.js";
|
|
22
|
+
import { S as removeActiveConversation, _ as hasRunnableConversationWork$1, c as clearExpiredConversationLease, g as getConversationWorkState, h as getConversation, m as ensureConversationWake, r as appendAndEnqueueInboundMessage, v as listActiveConversationIds } from "./store-DCo2n5iJ.js";
|
|
23
|
+
import { M as scheduledRunSchema } from "./automation-p87hg_AV.js";
|
|
24
|
+
import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "./validation-DHR1ivfh.js";
|
|
24
25
|
import { a as pluginRuntimeRegistrationsFromPluginSet, n as pluginCatalogConfigFromEnv, r as pluginCatalogConfigFromPluginSet, t as defineJuniorPlugins } from "./plugins-DOm9Y6qI.js";
|
|
25
|
-
import { A as
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import { o as
|
|
30
|
-
import {
|
|
31
|
-
import { a as
|
|
32
|
-
import {
|
|
33
|
-
import { t as
|
|
34
|
-
import { t as
|
|
35
|
-
import { t as
|
|
26
|
+
import { A as stopSlackThread, B as actOnReviewItem, C as isAllowedSignInEmail, D as buildSlackInboundMessage, E as recordSkippedConversationMessage, F as bindMessageAuthorIdentityId, H as readReviewItemForUser, I as startProcessingReaction, K as enqueueAgentDispatch, L as stripLeadingBotMention, M as withNormalizedThreadId, N as stopConversationTurn, O as clearSlackPendingReactions, P as THREAD_OPTOUT_ACK, R as parseContent, S as isAllowedDomain, T as resolveAllowedDomains, U as reviewItemChange, V as closeReviewItemsAnsweredByReply, W as getAttachmentStorage, _ as createProductionConversationWorkOptions, b as createSlackWebApiStatusSender, j as normalizeIncomingSlackThreadId, k as isSlackMessageStopped, q as GET$3, t as readConversationFeed, v as createProductionSlackWebhookServices, w as readEnvList, x as assertNoLegacyAllowedDomains, y as getProductionSlackAdapter, z as ReviewItemActionError } from "./list-CGoQdXTp.js";
|
|
27
|
+
import { n as enqueueAgentInvocationResult, o as getAuthPausedConversationTurnId } from "./result-BemsOMOO.js";
|
|
28
|
+
import { r as enqueueAgentInvocation } from "./work-BE_qTYGi.js";
|
|
29
|
+
import { o as coerceThreadConversationState } from "./thread-state-CHy8LS0C.js";
|
|
30
|
+
import { o as unlinkProvider } from "./connections-upFXLmhG.js";
|
|
31
|
+
import { a as GET$4, i as publishAppHomeView, r as GET$5, t as receiveLocalOAuthCredential } from "./credential-sync-CS_6IC-f.js";
|
|
32
|
+
import { a as pluginTaskQueueConsumer, c as queueCallback, n as createVercelPluginTaskCallback, o as registerVercelPluginTaskDevConsumer } from "./task-queue-HMC4QjFm.js";
|
|
33
|
+
import { t as processConversationWork } from "./worker-Cm9_sWXg.js";
|
|
34
|
+
import { t as bindMessageAgent } from "./message-BpaWd8TT.js";
|
|
35
|
+
import { t as bindSpawnAgent } from "./spawn-ChCm46i-.js";
|
|
36
|
+
import { t as processPluginTask } from "./task-runner-cA6yjn_E.js";
|
|
36
37
|
import { createRequire } from "node:module";
|
|
37
38
|
import { Hono } from "hono";
|
|
38
39
|
import { z } from "zod";
|
|
39
40
|
import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
40
|
-
import { and, asc, eq, inArray, isNotNull, isNull, lte, or, sql } from "drizzle-orm";
|
|
41
|
+
import { and, asc, eq, inArray, isNotNull, isNull, lte, ne, or, sql } from "drizzle-orm";
|
|
41
42
|
import { EVENT_SUMMARY_MAX_LENGTH, EVENT_TEXT_MAX_LENGTH, dispatchOptionsSchema, eventSchema, eventTriggerFiltersText, isSlackDestination, userSchema } from "@sentry/junior-plugin-api";
|
|
42
43
|
import { pathToFileURL } from "node:url";
|
|
43
44
|
import net from "node:net";
|
|
@@ -1226,6 +1227,12 @@ async function selectExpiredRoots(executor, args) {
|
|
|
1226
1227
|
where bindings.parent_conversation_id = tree.conversation_id
|
|
1227
1228
|
or bindings.child_conversation_id = tree.conversation_id
|
|
1228
1229
|
)
|
|
1230
|
+
or exists (
|
|
1231
|
+
select 1 from junior_review_items review_items
|
|
1232
|
+
where review_items.added_by_conversation_id = tree.conversation_id
|
|
1233
|
+
and review_items.status = 'open'
|
|
1234
|
+
and review_items.automation_id is null
|
|
1235
|
+
)
|
|
1229
1236
|
or (
|
|
1230
1237
|
${juniorDestinations.visibility} is distinct from 'public'
|
|
1231
1238
|
and (
|
|
@@ -1233,6 +1240,15 @@ async function selectExpiredRoots(executor, args) {
|
|
|
1233
1240
|
select 1 from junior_conversation_briefs briefs
|
|
1234
1241
|
where briefs.conversation_id = tree.conversation_id
|
|
1235
1242
|
)
|
|
1243
|
+
or exists (
|
|
1244
|
+
select 1 from junior_review_items review_items
|
|
1245
|
+
where review_items.added_by_conversation_id = tree.conversation_id
|
|
1246
|
+
and review_items.visibility = 'private'
|
|
1247
|
+
and (
|
|
1248
|
+
review_items.status <> 'open'
|
|
1249
|
+
or review_items.automation_id is null
|
|
1250
|
+
)
|
|
1251
|
+
)
|
|
1236
1252
|
or exists (
|
|
1237
1253
|
select 1 from junior_conversations metadata
|
|
1238
1254
|
where metadata.conversation_id = tree.conversation_id
|
|
@@ -1258,7 +1274,9 @@ async function selectExpiredRoots(executor, args) {
|
|
|
1258
1274
|
* event rows for the given conversation and every descendant, stamp
|
|
1259
1275
|
* `transcript_purged_at`, and — for non-public content — null the raw-payload
|
|
1260
1276
|
* metadata (`title`, `channel_name`, legacy actor JSON) so purged private
|
|
1261
|
-
* conversations keep only safe metadata.
|
|
1277
|
+
* conversations keep only safe metadata. Non-public content also loses its
|
|
1278
|
+
* Briefs and the Review items that it added. The metadata rows themselves
|
|
1279
|
+
* survive.
|
|
1262
1280
|
*/
|
|
1263
1281
|
async function purgeConversationTree(executor, args) {
|
|
1264
1282
|
return await withConversationMutationLock(executor, args.rootConversationId, async () => {
|
|
@@ -1303,9 +1321,17 @@ async function purgeConversationTree(executor, args) {
|
|
|
1303
1321
|
await executor.db().delete(juniorConversationEvents).where(inArray(juniorConversationEvents.conversationId, ids));
|
|
1304
1322
|
await executor.db().delete(juniorAgentInvocations).where(or(inArray(juniorAgentInvocations.parentConversationId, ids), inArray(juniorAgentInvocations.childConversationId, ids)));
|
|
1305
1323
|
await executor.db().delete(juniorAgentBindings).where(or(inArray(juniorAgentBindings.parentConversationId, ids), inArray(juniorAgentBindings.childConversationId, ids)));
|
|
1324
|
+
await dismissOpenReviewItems(executor.db(), {
|
|
1325
|
+
addedByConversationIds: ids,
|
|
1326
|
+
nowMs: args.nowMs,
|
|
1327
|
+
reason: "Conversation purged"
|
|
1328
|
+
});
|
|
1306
1329
|
await requestAttachmentDeletion(executor, ids, args.nowMs);
|
|
1307
1330
|
const scrubMetadata = args.retention ? !isPublic : resolvedScrubMetadata;
|
|
1308
|
-
if (scrubMetadata)
|
|
1331
|
+
if (scrubMetadata) {
|
|
1332
|
+
await executor.db().delete(juniorConversationBriefs).where(inArray(juniorConversationBriefs.conversationId, ids));
|
|
1333
|
+
await executor.db().delete(juniorReviewItems).where(and(inArray(juniorReviewItems.addedByConversationId, ids), eq(juniorReviewItems.visibility, "private"), or(ne(juniorReviewItems.status, "open"), isNull(juniorReviewItems.automationId))));
|
|
1334
|
+
}
|
|
1309
1335
|
await executor.db().update(juniorConversations).set({
|
|
1310
1336
|
transcriptPurgedAt: new Date(args.nowMs),
|
|
1311
1337
|
...scrubMetadata ? {
|
|
@@ -1776,8 +1802,8 @@ async function refreshCards(services, user, itemId) {
|
|
|
1776
1802
|
}
|
|
1777
1803
|
/**
|
|
1778
1804
|
* Do one person action from a Slack card. The thread of the card gets the
|
|
1779
|
-
* action as Slack input from the person, like
|
|
1780
|
-
*
|
|
1805
|
+
* action as Slack input from the person, like a typed reply. The other
|
|
1806
|
+
* linked Conversations get messages from
|
|
1781
1807
|
* `actOnReviewItem`. An expected failure, such as an item that is already
|
|
1782
1808
|
* closed, goes to the person as an ephemeral message.
|
|
1783
1809
|
*/
|
|
@@ -1789,6 +1815,10 @@ async function act(args) {
|
|
|
1789
1815
|
...target,
|
|
1790
1816
|
itemId: args.itemId
|
|
1791
1817
|
}) ?? `slack:${target.channelId}:${target.threadTs}`;
|
|
1818
|
+
const delivery = {
|
|
1819
|
+
queue: services.queue,
|
|
1820
|
+
show: createSlackReviewItemShow(() => services.adapter)
|
|
1821
|
+
};
|
|
1792
1822
|
let item;
|
|
1793
1823
|
try {
|
|
1794
1824
|
const current = await readReviewItemForUser(actor.user, args.itemId);
|
|
@@ -1796,9 +1826,8 @@ async function act(args) {
|
|
|
1796
1826
|
action: args.action,
|
|
1797
1827
|
exceptConversationId: conversationId,
|
|
1798
1828
|
firstCloseOnly: true,
|
|
1799
|
-
|
|
1829
|
+
delivery,
|
|
1800
1830
|
id: current.id,
|
|
1801
|
-
queue: services.queue,
|
|
1802
1831
|
user: actor.user,
|
|
1803
1832
|
...args.answer ? { answer: args.answer(current) } : void 0
|
|
1804
1833
|
});
|
|
@@ -1824,11 +1853,11 @@ async function act(args) {
|
|
|
1824
1853
|
}));
|
|
1825
1854
|
} catch (error) {
|
|
1826
1855
|
logException(error, "review_item.slack_input.persist.failed", { "app.review_item.id": item.id });
|
|
1827
|
-
await
|
|
1856
|
+
await deliverReviewItemChange({
|
|
1828
1857
|
change,
|
|
1858
|
+
delivery,
|
|
1829
1859
|
item,
|
|
1830
|
-
nowMs: Date.now()
|
|
1831
|
-
queue: services.queue
|
|
1860
|
+
nowMs: Date.now()
|
|
1832
1861
|
});
|
|
1833
1862
|
}
|
|
1834
1863
|
}
|
|
@@ -1972,139 +2001,8 @@ async function handleAppHomeDisconnect(args) {
|
|
|
1972
2001
|
});
|
|
1973
2002
|
}
|
|
1974
2003
|
/**
|
|
1975
|
-
*
|
|
1976
|
-
*
|
|
1977
|
-
* the model reads one format on every surface. Later answers to the same
|
|
1978
|
-
* request do nothing. A stale request, such as one that a newer request
|
|
1979
|
-
* replaced, also does nothing.
|
|
1980
|
-
*/
|
|
1981
|
-
async function answerSlackUserInput(args) {
|
|
1982
|
-
const userId = requireSlackPayloadUserId(args.payload.user?.id, "Slack user input payload");
|
|
1983
|
-
const { channelId, messageTs } = args;
|
|
1984
|
-
const open = await getOpenSlackUserInput(args.state, {
|
|
1985
|
-
channelId,
|
|
1986
|
-
threadTs: args.threadTs
|
|
1987
|
-
});
|
|
1988
|
-
if (!open || open.messageTs !== messageTs) return;
|
|
1989
|
-
const answer = args.answer(open);
|
|
1990
|
-
if (isEmptyUserInputAnswer(answer)) return;
|
|
1991
|
-
const userTeam = args.payload.user?.team_id;
|
|
1992
|
-
if (!await isSlackWorkspaceMember({
|
|
1993
|
-
user: userId,
|
|
1994
|
-
user_team: userTeam
|
|
1995
|
-
}, args.state)) return;
|
|
1996
|
-
if (!await args.isAuthorAllowed(userId)) return;
|
|
1997
|
-
if (!await claimSlackUserInput(args.state, {
|
|
1998
|
-
channelId,
|
|
1999
|
-
claimedBy: userId,
|
|
2000
|
-
messageTs
|
|
2001
|
-
})) return;
|
|
2002
|
-
const message = buildSlackInteractionInput({
|
|
2003
|
-
adapter: args.adapter,
|
|
2004
|
-
channelId,
|
|
2005
|
-
inputTs: args.inputTs,
|
|
2006
|
-
messageId: args.messageId,
|
|
2007
|
-
messageTs,
|
|
2008
|
-
payload: args.payload,
|
|
2009
|
-
text: formatUserInputAnswer(open.request, answer),
|
|
2010
|
-
threadTs: args.threadTs,
|
|
2011
|
-
userId
|
|
2012
|
-
});
|
|
2013
|
-
try {
|
|
2014
|
-
await args.persistMessage(message);
|
|
2015
|
-
} catch (error) {
|
|
2016
|
-
await releaseSlackUserInput(args.state, {
|
|
2017
|
-
channelId,
|
|
2018
|
-
messageTs
|
|
2019
|
-
});
|
|
2020
|
-
throw error;
|
|
2021
|
-
}
|
|
2022
|
-
await closeSlackUserInput({
|
|
2023
|
-
note: slackUserInputAnswerNote({
|
|
2024
|
-
answer,
|
|
2025
|
-
request: open.request,
|
|
2026
|
-
who: slackMention(userId)
|
|
2027
|
-
}),
|
|
2028
|
-
open
|
|
2029
|
-
});
|
|
2030
|
-
}
|
|
2031
|
-
/** Read the request message and thread of a block action. */
|
|
2032
|
-
function blockActionTarget(payload) {
|
|
2033
|
-
const channelId = parseSlackChannelId(payload.channel?.id);
|
|
2034
|
-
const messageTs = parseSlackMessageTs(payload.message?.ts);
|
|
2035
|
-
if (!channelId || !messageTs) throw new Error("Slack user input payload is incomplete");
|
|
2036
|
-
return {
|
|
2037
|
-
channelId,
|
|
2038
|
-
messageTs,
|
|
2039
|
-
threadTs: parseSlackMessageTs(payload.message?.thread_ts) ?? messageTs
|
|
2040
|
-
};
|
|
2041
|
-
}
|
|
2042
|
-
/** Answer a one-click request with the clicked choice. */
|
|
2043
|
-
async function handleUserInputChoice(args) {
|
|
2044
|
-
const target = blockActionTarget(args.payload);
|
|
2045
|
-
const actionTs = parseSlackMessageTs(args.action.action_ts);
|
|
2046
|
-
const choice = args.action.value?.trim();
|
|
2047
|
-
if (!actionTs || !choice) throw new Error("Slack user input click payload is incomplete");
|
|
2048
|
-
await answerSlackUserInput({
|
|
2049
|
-
...target,
|
|
2050
|
-
adapter: args.adapter,
|
|
2051
|
-
answer: (open) => {
|
|
2052
|
-
const field = buttonUserInputField(open.request);
|
|
2053
|
-
return normalizeUserInputAnswer(open.request, {
|
|
2054
|
-
requestId: open.requestId,
|
|
2055
|
-
values: field ? { [field.id]: [choice] } : {}
|
|
2056
|
-
});
|
|
2057
|
-
},
|
|
2058
|
-
inputTs: actionTs,
|
|
2059
|
-
messageId: `slack-user-input-answer:${actionTs}`,
|
|
2060
|
-
payload: args.payload,
|
|
2061
|
-
isAuthorAllowed: args.isAuthorAllowed,
|
|
2062
|
-
persistMessage: args.persistMessage,
|
|
2063
|
-
state: args.state
|
|
2064
|
-
});
|
|
2065
|
-
}
|
|
2066
|
-
/** Open the answer form of the open request for the person who clicked. */
|
|
2067
|
-
async function handleUserInputOpenForm(args) {
|
|
2068
|
-
const target = blockActionTarget(args.payload);
|
|
2069
|
-
const triggerId = args.payload.trigger_id;
|
|
2070
|
-
if (!triggerId) throw new Error("Slack user input form payload is missing a trigger id");
|
|
2071
|
-
const open = await getOpenSlackUserInput(args.state, target);
|
|
2072
|
-
if (!open || open.messageTs !== target.messageTs) return;
|
|
2073
|
-
await openSlackModal({
|
|
2074
|
-
triggerId,
|
|
2075
|
-
view: buildSlackUserInputModal(open.request, target)
|
|
2076
|
-
});
|
|
2077
|
-
}
|
|
2078
|
-
/** Answer a request with the values of its submitted form. */
|
|
2079
|
-
async function handleUserInputSubmission(args) {
|
|
2080
|
-
const view = args.payload.view;
|
|
2081
|
-
const formTarget = parseSlackUserInputFormTarget(view?.private_metadata);
|
|
2082
|
-
const channelId = parseSlackChannelId(formTarget?.channelId);
|
|
2083
|
-
const messageTs = parseSlackMessageTs(formTarget?.messageTs);
|
|
2084
|
-
const threadTs = parseSlackMessageTs(formTarget?.threadTs);
|
|
2085
|
-
if (!view?.id || !channelId || !messageTs || !threadTs) throw new Error("Slack user input form submission is incomplete");
|
|
2086
|
-
const inputTs = slackMessageTsFromMs(Date.now());
|
|
2087
|
-
await answerSlackUserInput({
|
|
2088
|
-
adapter: args.adapter,
|
|
2089
|
-
answer: (open) => parseSlackUserInputSubmission({
|
|
2090
|
-
request: open.request,
|
|
2091
|
-
requestId: open.requestId,
|
|
2092
|
-
values: view.state?.values ?? {}
|
|
2093
|
-
}),
|
|
2094
|
-
channelId,
|
|
2095
|
-
inputTs,
|
|
2096
|
-
messageId: `slack-user-input-answer:${view.id}`,
|
|
2097
|
-
messageTs,
|
|
2098
|
-
payload: args.payload,
|
|
2099
|
-
isAuthorAllowed: args.isAuthorAllowed,
|
|
2100
|
-
persistMessage: args.persistMessage,
|
|
2101
|
-
state: args.state,
|
|
2102
|
-
threadTs
|
|
2103
|
-
});
|
|
2104
|
-
}
|
|
2105
|
-
/**
|
|
2106
|
-
* Handle Slack interactions from App Home, user input requests, and Review
|
|
2107
|
-
* item cards: block actions and submitted forms.
|
|
2004
|
+
* Handle Slack interactions from App Home and Review item cards: block
|
|
2005
|
+
* actions and submitted forms.
|
|
2108
2006
|
*/
|
|
2109
2007
|
async function handleSlackInteractivePayload(args) {
|
|
2110
2008
|
const spanAttributes = { userId: args.payload.user?.id?.trim() || void 0 };
|
|
@@ -2115,10 +2013,6 @@ async function handleSlackInteractivePayload(args) {
|
|
|
2115
2013
|
}));
|
|
2116
2014
|
return;
|
|
2117
2015
|
}
|
|
2118
|
-
if (args.payload.type === "view_submission" && args.payload.view?.callback_id === "junior_user_input") {
|
|
2119
|
-
await withSpan("chat.slack_user_input_submit", "chat.slack_user_input_submit", spanAttributes, () => handleUserInputSubmission(args));
|
|
2120
|
-
return;
|
|
2121
|
-
}
|
|
2122
2016
|
if (args.payload.type !== "block_actions") return;
|
|
2123
2017
|
for (const action of args.payload.actions ?? []) {
|
|
2124
2018
|
const click = parseSlackReviewItemClick(action);
|
|
@@ -2131,18 +2025,6 @@ async function handleSlackInteractivePayload(args) {
|
|
|
2131
2025
|
}));
|
|
2132
2026
|
return;
|
|
2133
2027
|
}
|
|
2134
|
-
const kind = slackUserInputAction(action.action_id);
|
|
2135
|
-
if (kind === "choice") {
|
|
2136
|
-
await withSpan("chat.slack_user_input_click", "chat.slack_user_input_click", spanAttributes, () => handleUserInputChoice({
|
|
2137
|
-
...args,
|
|
2138
|
-
action
|
|
2139
|
-
}));
|
|
2140
|
-
return;
|
|
2141
|
-
}
|
|
2142
|
-
if (kind === "open_form") {
|
|
2143
|
-
await withSpan("chat.slack_user_input_open_form", "chat.slack_user_input_open_form", spanAttributes, () => handleUserInputOpenForm(args));
|
|
2144
|
-
return;
|
|
2145
|
-
}
|
|
2146
2028
|
}
|
|
2147
2029
|
const disconnect = args.payload.actions?.find((candidate) => candidate.action_id === "app_home_disconnect");
|
|
2148
2030
|
const provider = disconnect?.selected_option?.value ?? disconnect?.value;
|
|
@@ -2644,6 +2526,17 @@ async function buildThread(args) {
|
|
|
2644
2526
|
function shouldIgnoreMessage(message) {
|
|
2645
2527
|
return message.author.isMe === true || !parseActorUserId(message.author.userId);
|
|
2646
2528
|
}
|
|
2529
|
+
/**
|
|
2530
|
+
* Resolve the Slack author Identity at ingress and bind its id to the message.
|
|
2531
|
+
* Ingress does no profile lookup. The worker adds the profile names later.
|
|
2532
|
+
* Bot authors wait for their own bot Identity, so they get no id here.
|
|
2533
|
+
*/
|
|
2534
|
+
async function bindSlackAuthorIdentity(message, installation) {
|
|
2535
|
+
const teamId = installation.teamId;
|
|
2536
|
+
const userId = parseActorUserId(message.author.userId);
|
|
2537
|
+
if (!teamId || !userId || message.author.isBot === true) return;
|
|
2538
|
+
bindMessageAuthorIdentityId(message, await resolveActorIdentityId(getSqlExecutor(), createSlackActor(teamId, userId, null)));
|
|
2539
|
+
}
|
|
2647
2540
|
function shouldPersistBeforeAck(body) {
|
|
2648
2541
|
return body.event?.type === "app_mention" || body.event?.type === "message";
|
|
2649
2542
|
}
|
|
@@ -2742,6 +2635,7 @@ async function handleSlackThreadStop(args) {
|
|
|
2742
2635
|
conversationId,
|
|
2743
2636
|
state: args.state
|
|
2744
2637
|
});
|
|
2638
|
+
await bindSlackAuthorIdentity(args.message, args.installation);
|
|
2745
2639
|
const content = parseContent(args.message);
|
|
2746
2640
|
const conversation = coerceThreadConversationState(void 0);
|
|
2747
2641
|
recordSkippedConversationMessage({
|
|
@@ -2848,13 +2742,15 @@ async function routeParsedMessage(args) {
|
|
|
2848
2742
|
});
|
|
2849
2743
|
return;
|
|
2850
2744
|
}
|
|
2851
|
-
|
|
2745
|
+
const isAuthorDomainAllowed = () => isSlackAuthorDomainAllowed({
|
|
2852
2746
|
allowedBotUserIds: args.allowedBotUserIds,
|
|
2853
2747
|
allowedDomains: args.allowedDomains,
|
|
2854
2748
|
state: args.state,
|
|
2855
2749
|
teamId: args.installation.teamId,
|
|
2856
2750
|
user: args.event.user
|
|
2857
|
-
})
|
|
2751
|
+
});
|
|
2752
|
+
if (route === "mention" && !await isAuthorDomainAllowed()) return;
|
|
2753
|
+
await bindSlackAuthorIdentity(message, args.installation);
|
|
2858
2754
|
const conversationId = await resolveSlackConversationId({
|
|
2859
2755
|
canonicalThreadId,
|
|
2860
2756
|
conversationStore: args.conversationStore,
|
|
@@ -2886,22 +2782,34 @@ async function routeParsedMessage(args) {
|
|
|
2886
2782
|
route,
|
|
2887
2783
|
state: args.state
|
|
2888
2784
|
});
|
|
2889
|
-
|
|
2785
|
+
const closeAnswered = async () => {
|
|
2786
|
+
if (message.author.isBot === true) return;
|
|
2787
|
+
await closeReviewItemsAnsweredByReply({
|
|
2788
|
+
...route === "subscribed" ? { canAnswer: isAuthorDomainAllowed } : void 0,
|
|
2789
|
+
conversationId,
|
|
2790
|
+
delivery: {
|
|
2791
|
+
queue: args.queue,
|
|
2792
|
+
show: createSlackReviewItemShow(() => args.adapter)
|
|
2793
|
+
},
|
|
2794
|
+
resolveUser: async () => {
|
|
2795
|
+
const teamId = args.installation.teamId;
|
|
2796
|
+
const userId = parseActorUserId(message.author.userId);
|
|
2797
|
+
if (!teamId || !userId) return void 0;
|
|
2798
|
+
return (await readActorIdentity(createSlackActor(teamId, userId, null)))?.user;
|
|
2799
|
+
},
|
|
2800
|
+
text: stripLeadingBotMention(parseContent(message).topLevelText, {
|
|
2801
|
+
botUserId: args.adapter.botUserId,
|
|
2802
|
+
stripLeadingSlackMentionToken: true
|
|
2803
|
+
})
|
|
2804
|
+
});
|
|
2805
|
+
};
|
|
2806
|
+
try {
|
|
2890
2807
|
await persist();
|
|
2891
|
-
|
|
2808
|
+
} catch (error) {
|
|
2809
|
+
if (error instanceof SlackEventPersistenceError && error.saved) await closeAnswered();
|
|
2810
|
+
throw error;
|
|
2892
2811
|
}
|
|
2893
|
-
await
|
|
2894
|
-
channelId: args.event.channel,
|
|
2895
|
-
claimedBy: message.author.userId,
|
|
2896
|
-
isSaved: (error) => error instanceof SlackEventPersistenceError && error.saved,
|
|
2897
|
-
note: (request) => slackUserInputAnswerNote({
|
|
2898
|
-
request,
|
|
2899
|
-
who: slackMention(message.author.userId)
|
|
2900
|
-
}),
|
|
2901
|
-
persist,
|
|
2902
|
-
state: args.state,
|
|
2903
|
-
threadTs: args.event.thread_ts
|
|
2904
|
-
});
|
|
2812
|
+
await closeAnswered();
|
|
2905
2813
|
}
|
|
2906
2814
|
async function handleSlackEvent(args) {
|
|
2907
2815
|
const event = args.body.event;
|
|
@@ -3005,6 +2913,7 @@ async function handleSlackEvent(args) {
|
|
|
3005
2913
|
*/
|
|
3006
2914
|
async function persistSlackMentionWithLock(args) {
|
|
3007
2915
|
const { message, threadId } = normalizeMessageThreadId(args.message);
|
|
2916
|
+
await bindSlackAuthorIdentity(message, args.installation);
|
|
3008
2917
|
try {
|
|
3009
2918
|
if (!(await withLock(args.state, `slack:ingress:${threadId}`, () => persistSlackMessage({
|
|
3010
2919
|
adapter: args.adapter,
|
|
@@ -6264,7 +6173,8 @@ function createBetterAuth(config) {
|
|
|
6264
6173
|
await recordGoogleSignIn(getSqlExecutor(), {
|
|
6265
6174
|
email,
|
|
6266
6175
|
subject: google.accountId,
|
|
6267
|
-
displayName: created.user.name || void 0
|
|
6176
|
+
displayName: created.user.name || void 0,
|
|
6177
|
+
avatarUrl: parseAvatarUrl(created.user.image, GOOGLE_IDENTITY_PROVIDER)
|
|
6268
6178
|
});
|
|
6269
6179
|
}) }
|
|
6270
6180
|
});
|
|
@@ -6663,7 +6573,10 @@ async function createApp(options) {
|
|
|
6663
6573
|
validatePluginRegistrations(configuredPlugins?.registrations ?? []);
|
|
6664
6574
|
validatePluginEgressCredentialHooks(configuredPlugins?.registrations ?? []);
|
|
6665
6575
|
}
|
|
6666
|
-
pluginRoutes = getPluginRoutes({
|
|
6576
|
+
pluginRoutes = getPluginRoutes({
|
|
6577
|
+
events,
|
|
6578
|
+
showReviewItem: createSlackReviewItemShow(getProductionSlackAdapter)
|
|
6579
|
+
});
|
|
6667
6580
|
if (dashboard && !dashboard.disabled) pluginApiRoutes = getPluginApiRoutes();
|
|
6668
6581
|
} catch (error) {
|
|
6669
6582
|
restoreRuntimeConfig$1();
|
|
@@ -6681,6 +6594,7 @@ async function createApp(options) {
|
|
|
6681
6594
|
attachmentStorage,
|
|
6682
6595
|
bindMessageAgent: (request) => bindMessageAgent(request, { queue: conversationWorkQueue }),
|
|
6683
6596
|
bindSpawnAgent: (request) => bindSpawnAgent(request, { queue: conversationWorkQueue }),
|
|
6597
|
+
conversationWorkQueue,
|
|
6684
6598
|
tracePropagation
|
|
6685
6599
|
});
|
|
6686
6600
|
const runtimeServiceOverrides = {
|