@sentry/junior 0.268.0 → 0.270.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-BQNTKVTF.js} +3 -49
- package/dist/{admin-DIU1QyG3.js → admin-CKVEoXa4.js} +1 -1
- package/dist/{agent-runner-CAYfFmU7.js → agent-runner-MSQSMFkq.js} +4538 -3251
- 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 +190 -301
- package/dist/{app-z6Uuyq3j.d.ts → app-Bz8t4P8p.d.ts} +9 -3
- package/dist/app.d.ts +1 -1
- package/dist/app.js +129 -209
- package/dist/{automation-CmeFBSEh.js → automation-Dwh_xcqM.js} +74 -74
- package/dist/{briefs-DQbV2jNr.js → briefs-DNFzFFVx.js} +5 -5
- package/dist/{catalog-runtime-BD9GSpc6.js → catalog-runtime-Bdym_wKy.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-B2MjENki.js} +31 -16
- package/dist/{config-DrTeF80T.js → config-Dm3pWRqY.js} +3 -3
- package/dist/{connections-D46f8vvi.js → connections-0BBhiD-p.js} +10 -10
- package/dist/{conversation-DSo310Ps.js → conversation-AhOVzN_k.js} +11 -86
- package/dist/{conversation-privacy-CxlOCiUo.js → conversation-privacy-C1pJ89rs.js} +1 -1
- package/dist/{credential-sync-sm9fegLY.js → credential-sync-BRiWYs6_.js} +15 -14
- package/dist/{credentialed-lukuD-cc.js → credentialed-BeBaJMZ_.js} +565 -83
- package/dist/{store-xMuuXRE0.d.ts → db-BYOuu6v2.d.ts} +4 -0
- package/dist/{executor-4vhvsMZJ.js → executor-BB6eJkD4.js} +6 -6
- package/dist/instrumentation.js +2 -2
- package/dist/{interruption-marker-CkncDT8d.js → interruption-marker-CdblrIQK.js} +1 -1
- package/dist/{job-queue-In9QKz-I.js → job-queue-DiaXoSDg.js} +2 -2
- package/dist/{list-BkgnXEEB.js → list-BTDRxkOg.js} +331 -662
- package/dist/locks-D-0h111u.js +48 -0
- package/dist/{logging-DLSpkSSr.js → logging-C6EdT6PP.js} +1 -1
- package/dist/{history-C84mlAwO.js → media-U6Tuz6Mi.js} +84 -2
- package/dist/{message-BObyg59s.js → message-DsjiWRVg.js} +4 -4
- package/dist/{model-profile-Bg8EoCKD.js → model-profile-B998sjVd.js} +9 -2
- package/dist/nitro.d.ts +1 -1
- package/dist/nitro.js +5 -3
- package/dist/{oauth-callback-server-B-WbSdoH.js → oauth-callback-server-CjFFVGqa.js} +2 -2
- package/dist/{prompt-BW9jFsqZ.js → prompt-BPSdXYXV.js} +1 -1
- package/dist/{registry-BgecKva0.js → registry-CndmkP2P.js} +1 -1
- package/dist/reporting-schema-CZREhYc-.js +104 -0
- package/dist/{web-message-id-DlHNANtd.js → reporting-window-DRCi1Ls_.js} +139 -7
- package/dist/{resolve-Cpa4Bu1O.js → resolve-BkAA1wH7.js} +3 -3
- package/dist/{result-D3TSmZZ8.js → result-9TJTpuYP.js} +30 -11
- package/dist/{runner-DS5OKhEp.js → runner-BmKLSyJm.js} +12 -11
- package/dist/{sandbox-egress-signals-CnDjY5rx.js → sandbox-egress-signals-CjLaogMo.js} +1 -1
- package/dist/{schema-0050HFnB.js → schema-DNLJ_MzW.js} +36 -20
- package/dist/{schema-ZngqcOWM.d.ts → schema-WayPSHFu.d.ts} +149 -12
- package/dist/{service-account-CKV2WTY7.js → service-account-D6e9cVmH.js} +4 -3
- package/dist/{service-account-DGjnDw9y.js → service-account-DlhYl-Mu.js} +3 -3
- package/dist/{session-stop-Dam1EI7B.js → session-stop-MZRgYqYH.js} +24 -16
- package/dist/{skills-CfAnfImD.js → skills-BggTR_ue.js} +2 -2
- package/dist/{spawn-cmq9p4Ly.js → spawn-DmtlcAT_.js} +2 -2
- package/dist/{store-zPEoJPBB.js → store-BeWGgaMA.js} +3 -3
- package/dist/{store-C5PN02QO.js → store-Byarin7b.js} +4 -4
- package/dist/{task-queue-_mf28dSu.js → task-queue-Dt1_ZoI_.js} +3 -3
- package/dist/task-runner-DyKqAPpm.js +269 -0
- package/dist/{thread-state-BbbPh0Sn.js → thread-state-BHBLMvgb.js} +5 -5
- package/dist/{turn-failure-response-BKKmnMB5.js → turn-failure-response-DWXy_0oJ.js} +9 -9
- package/dist/{turn-lifecycle-oP0kVeGz.js → turn-lifecycle-AiXkVqCB.js} +1 -1
- package/dist/{tasks-SB9z-VTU.js → turn-session-routing-B9KLBhaT.js} +939 -120
- package/dist/{validation--JsAGLwc.js → validation-BW60Vtx_.js} +1 -1
- package/dist/{version-jHwJp4hC.js → version-CivPYmkH.js} +1 -1
- package/dist/version.js +1 -1
- package/dist/{viewer-CpXTGlep.js → viewer-BTgAfdUg.js} +216 -27
- package/dist/{work-3N-GHY9m.js → work-Bjm52fHo.js} +17 -36
- package/dist/{worker-CCdbcItd.js → worker-CMbgtHLu.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 +5 -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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as ConversationWorkQueue, t as ConversationQueueMessage } from "./queue-C37RbDVc.js";
|
|
2
|
-
import { t as ConversationStore } from "./
|
|
3
|
-
import "./
|
|
2
|
+
import { t as ConversationStore } from "./db-BYOuu6v2.js";
|
|
3
|
+
import "./schema-WayPSHFu.js";
|
|
4
4
|
import { n as JuniorPluginSet } from "./plugins-B_0Cr0MO.js";
|
|
5
5
|
import { Hono } from "hono";
|
|
6
6
|
import "@earendil-works/pi-ai/compat";
|
|
@@ -8,12 +8,13 @@ import "@earendil-works/pi-ai/api/anthropic-messages";
|
|
|
8
8
|
import "ai";
|
|
9
9
|
import "@sentry/node";
|
|
10
10
|
import { z } from "zod";
|
|
11
|
+
import "drizzle-orm";
|
|
11
12
|
import { Destination, OwnedObjectAnnotation, PluginRegistration, Source, User } from "@sentry/junior-plugin-api";
|
|
12
13
|
import "@earendil-works/pi-agent-core";
|
|
13
14
|
import "@earendil-works/pi-ai";
|
|
14
|
-
import "@sinclair/typebox";
|
|
15
15
|
import "@modelcontextprotocol/sdk/client/auth.js";
|
|
16
16
|
import { Client } from "@modelcontextprotocol/sdk/client";
|
|
17
|
+
import "@sinclair/typebox";
|
|
17
18
|
import { Message, StateAdapter } from "chat";
|
|
18
19
|
import "@chat-adapter/slack";
|
|
19
20
|
declare const TURN_REASONING_LEVELS: readonly ["none", "low", "medium", "high", "xhigh"];
|
|
@@ -168,6 +169,11 @@ interface InboxAttempt {
|
|
|
168
169
|
drain(handle: (messages: InboundMessage[]) => Promise<readonly string[] | void>, options?: {
|
|
169
170
|
deferred?: boolean;
|
|
170
171
|
}): Promise<InboundMessage[]>;
|
|
172
|
+
/**
|
|
173
|
+
* True when a failure of this attempt can end the work: the worker gives up
|
|
174
|
+
* and drops the mailbox. The adapter must record its own failure first.
|
|
175
|
+
* Resume attempts, which have no messages, can also be final.
|
|
176
|
+
*/
|
|
171
177
|
isFinalAttempt: boolean;
|
|
172
178
|
messages: InboundMessage[];
|
|
173
179
|
}
|
package/dist/app.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ModelProfileInput, i as JuniorDashboardOptions, n as JuniorAppOptions, r as createApp, t as JuniorApp } from "./app-
|
|
1
|
+
import { a as ModelProfileInput, i as JuniorDashboardOptions, n as JuniorAppOptions, r as createApp, t as JuniorApp } from "./app-Bz8t4P8p.js";
|
|
2
2
|
import { i as defineJuniorPlugins, n as JuniorPluginSet, r as JuniorPluginSetOptions, t as JuniorPluginInput } from "./plugins-B_0Cr0MO.js";
|
|
3
3
|
import { t as JUNIOR_VERSION } from "./version-Cc2OFd9G.js";
|
|
4
4
|
export { JUNIOR_VERSION, JuniorApp, JuniorAppOptions, type JuniorDashboardOptions, type JuniorPluginInput, type JuniorPluginSet, type JuniorPluginSetOptions, type ModelProfileInput, createApp, defineJuniorPlugins };
|
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, G as blockEventAutomation, Gr as setExperimentalFeatures, H as saveScheduledAutomationInLock, Ir as SubscribedReplyReason, Jn as hasRunnableConversationWork, K as collectEventAutomationMatchKeys, M as recordAutomationExecution, Mn as CONVERSATION_WORK_STALE_ENQUEUE_MS, R as listScheduledAutomationsForTeam, S as existingConversationId, U as scheduledRunId, Ur as getExperimentalFeatures, W as withScheduledAutomationLock, Wr as isExperimentalFeatureEnabled, Wt as appendConversationMessages, Xn as isInvalidConversationRecordError, Xr as getConfigDefaults, Xt as settleConversationTitleWork, Y as findMatchingEventAutomations, Zr as setConfigDefaults, 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, zr as getThreadStopDecision } from "./turn-session-routing-B9KLBhaT.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-Dm3pWRqY.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-C6EdT6PP.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-CivPYmkH.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-BTgAfdUg.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-BB6eJkD4.js";
|
|
10
|
+
import { n as pluginCatalogRuntime } from "./catalog-runtime-Bdym_wKy.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-MSQSMFkq.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, rr as createPluginEmbedder, 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-BeBaJMZ_.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-BQNTKVTF.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-AhOVzN_k.js";
|
|
17
|
+
import { b as listPendingAgentInvocationMailboxAppends, x as listPendingAgentInvocationResults } from "./store-Byarin7b.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-MZRgYqYH.js";
|
|
19
|
+
import { h as buttonUserInputField } from "./reporting-window-DRCi1Ls_.js";
|
|
20
|
+
import { c as setSandboxResourceConfig, o as getSandboxResourceConfig } from "./resolve-BkAA1wH7.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-DiaXoSDg.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-BeWGgaMA.js";
|
|
23
|
+
import { M as scheduledRunSchema } from "./automation-Dwh_xcqM.js";
|
|
24
|
+
import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "./validation-BW60Vtx_.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-BTDRxkOg.js";
|
|
27
|
+
import { n as enqueueAgentInvocationResult, o as getAuthPausedConversationTurnId } from "./result-9TJTpuYP.js";
|
|
28
|
+
import { r as enqueueAgentInvocation } from "./work-Bjm52fHo.js";
|
|
29
|
+
import { o as coerceThreadConversationState } from "./thread-state-BHBLMvgb.js";
|
|
30
|
+
import { o as unlinkProvider } from "./connections-0BBhiD-p.js";
|
|
31
|
+
import { a as GET$4, i as publishAppHomeView, r as GET$5, t as receiveLocalOAuthCredential } from "./credential-sync-BRiWYs6_.js";
|
|
32
|
+
import { a as pluginTaskQueueConsumer, c as queueCallback, n as createVercelPluginTaskCallback, o as registerVercelPluginTaskDevConsumer } from "./task-queue-Dt1_ZoI_.js";
|
|
33
|
+
import { t as processConversationWork } from "./worker-CMbgtHLu.js";
|
|
34
|
+
import { t as bindMessageAgent } from "./message-DsjiWRVg.js";
|
|
35
|
+
import { t as bindSpawnAgent } from "./spawn-DmtlcAT_.js";
|
|
36
|
+
import { t as processPluginTask } from "./task-runner-DyKqAPpm.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";
|
|
@@ -269,6 +270,7 @@ function createHeartbeatContext(args) {
|
|
|
269
270
|
cache: createPluginCache(pluginName),
|
|
270
271
|
nowMs: args.nowMs,
|
|
271
272
|
db: getDb(),
|
|
273
|
+
embedder: createPluginEmbedder(pluginName),
|
|
272
274
|
state: createPluginState(pluginName),
|
|
273
275
|
log: createPluginLogger(pluginName),
|
|
274
276
|
agent: {
|
|
@@ -1226,6 +1228,12 @@ async function selectExpiredRoots(executor, args) {
|
|
|
1226
1228
|
where bindings.parent_conversation_id = tree.conversation_id
|
|
1227
1229
|
or bindings.child_conversation_id = tree.conversation_id
|
|
1228
1230
|
)
|
|
1231
|
+
or exists (
|
|
1232
|
+
select 1 from junior_review_items review_items
|
|
1233
|
+
where review_items.added_by_conversation_id = tree.conversation_id
|
|
1234
|
+
and review_items.status = 'open'
|
|
1235
|
+
and review_items.automation_id is null
|
|
1236
|
+
)
|
|
1229
1237
|
or (
|
|
1230
1238
|
${juniorDestinations.visibility} is distinct from 'public'
|
|
1231
1239
|
and (
|
|
@@ -1233,6 +1241,15 @@ async function selectExpiredRoots(executor, args) {
|
|
|
1233
1241
|
select 1 from junior_conversation_briefs briefs
|
|
1234
1242
|
where briefs.conversation_id = tree.conversation_id
|
|
1235
1243
|
)
|
|
1244
|
+
or exists (
|
|
1245
|
+
select 1 from junior_review_items review_items
|
|
1246
|
+
where review_items.added_by_conversation_id = tree.conversation_id
|
|
1247
|
+
and review_items.visibility = 'private'
|
|
1248
|
+
and (
|
|
1249
|
+
review_items.status <> 'open'
|
|
1250
|
+
or review_items.automation_id is null
|
|
1251
|
+
)
|
|
1252
|
+
)
|
|
1236
1253
|
or exists (
|
|
1237
1254
|
select 1 from junior_conversations metadata
|
|
1238
1255
|
where metadata.conversation_id = tree.conversation_id
|
|
@@ -1258,7 +1275,9 @@ async function selectExpiredRoots(executor, args) {
|
|
|
1258
1275
|
* event rows for the given conversation and every descendant, stamp
|
|
1259
1276
|
* `transcript_purged_at`, and — for non-public content — null the raw-payload
|
|
1260
1277
|
* metadata (`title`, `channel_name`, legacy actor JSON) so purged private
|
|
1261
|
-
* conversations keep only safe metadata.
|
|
1278
|
+
* conversations keep only safe metadata. Non-public content also loses its
|
|
1279
|
+
* Briefs and the Review items that it added. The metadata rows themselves
|
|
1280
|
+
* survive.
|
|
1262
1281
|
*/
|
|
1263
1282
|
async function purgeConversationTree(executor, args) {
|
|
1264
1283
|
return await withConversationMutationLock(executor, args.rootConversationId, async () => {
|
|
@@ -1303,9 +1322,17 @@ async function purgeConversationTree(executor, args) {
|
|
|
1303
1322
|
await executor.db().delete(juniorConversationEvents).where(inArray(juniorConversationEvents.conversationId, ids));
|
|
1304
1323
|
await executor.db().delete(juniorAgentInvocations).where(or(inArray(juniorAgentInvocations.parentConversationId, ids), inArray(juniorAgentInvocations.childConversationId, ids)));
|
|
1305
1324
|
await executor.db().delete(juniorAgentBindings).where(or(inArray(juniorAgentBindings.parentConversationId, ids), inArray(juniorAgentBindings.childConversationId, ids)));
|
|
1325
|
+
await dismissOpenReviewItems(executor.db(), {
|
|
1326
|
+
addedByConversationIds: ids,
|
|
1327
|
+
nowMs: args.nowMs,
|
|
1328
|
+
reason: "Conversation purged"
|
|
1329
|
+
});
|
|
1306
1330
|
await requestAttachmentDeletion(executor, ids, args.nowMs);
|
|
1307
1331
|
const scrubMetadata = args.retention ? !isPublic : resolvedScrubMetadata;
|
|
1308
|
-
if (scrubMetadata)
|
|
1332
|
+
if (scrubMetadata) {
|
|
1333
|
+
await executor.db().delete(juniorConversationBriefs).where(inArray(juniorConversationBriefs.conversationId, ids));
|
|
1334
|
+
await executor.db().delete(juniorReviewItems).where(and(inArray(juniorReviewItems.addedByConversationId, ids), eq(juniorReviewItems.visibility, "private"), or(ne(juniorReviewItems.status, "open"), isNull(juniorReviewItems.automationId))));
|
|
1335
|
+
}
|
|
1309
1336
|
await executor.db().update(juniorConversations).set({
|
|
1310
1337
|
transcriptPurgedAt: new Date(args.nowMs),
|
|
1311
1338
|
...scrubMetadata ? {
|
|
@@ -1776,8 +1803,8 @@ async function refreshCards(services, user, itemId) {
|
|
|
1776
1803
|
}
|
|
1777
1804
|
/**
|
|
1778
1805
|
* 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
|
-
*
|
|
1806
|
+
* action as Slack input from the person, like a typed reply. The other
|
|
1807
|
+
* linked Conversations get messages from
|
|
1781
1808
|
* `actOnReviewItem`. An expected failure, such as an item that is already
|
|
1782
1809
|
* closed, goes to the person as an ephemeral message.
|
|
1783
1810
|
*/
|
|
@@ -1789,6 +1816,10 @@ async function act(args) {
|
|
|
1789
1816
|
...target,
|
|
1790
1817
|
itemId: args.itemId
|
|
1791
1818
|
}) ?? `slack:${target.channelId}:${target.threadTs}`;
|
|
1819
|
+
const delivery = {
|
|
1820
|
+
queue: services.queue,
|
|
1821
|
+
show: createSlackReviewItemShow(() => services.adapter)
|
|
1822
|
+
};
|
|
1792
1823
|
let item;
|
|
1793
1824
|
try {
|
|
1794
1825
|
const current = await readReviewItemForUser(actor.user, args.itemId);
|
|
@@ -1796,9 +1827,8 @@ async function act(args) {
|
|
|
1796
1827
|
action: args.action,
|
|
1797
1828
|
exceptConversationId: conversationId,
|
|
1798
1829
|
firstCloseOnly: true,
|
|
1799
|
-
|
|
1830
|
+
delivery,
|
|
1800
1831
|
id: current.id,
|
|
1801
|
-
queue: services.queue,
|
|
1802
1832
|
user: actor.user,
|
|
1803
1833
|
...args.answer ? { answer: args.answer(current) } : void 0
|
|
1804
1834
|
});
|
|
@@ -1824,11 +1854,11 @@ async function act(args) {
|
|
|
1824
1854
|
}));
|
|
1825
1855
|
} catch (error) {
|
|
1826
1856
|
logException(error, "review_item.slack_input.persist.failed", { "app.review_item.id": item.id });
|
|
1827
|
-
await
|
|
1857
|
+
await deliverReviewItemChange({
|
|
1828
1858
|
change,
|
|
1859
|
+
delivery,
|
|
1829
1860
|
item,
|
|
1830
|
-
nowMs: Date.now()
|
|
1831
|
-
queue: services.queue
|
|
1861
|
+
nowMs: Date.now()
|
|
1832
1862
|
});
|
|
1833
1863
|
}
|
|
1834
1864
|
}
|
|
@@ -1972,139 +2002,8 @@ async function handleAppHomeDisconnect(args) {
|
|
|
1972
2002
|
});
|
|
1973
2003
|
}
|
|
1974
2004
|
/**
|
|
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.
|
|
2005
|
+
* Handle Slack interactions from App Home and Review item cards: block
|
|
2006
|
+
* actions and submitted forms.
|
|
2108
2007
|
*/
|
|
2109
2008
|
async function handleSlackInteractivePayload(args) {
|
|
2110
2009
|
const spanAttributes = { userId: args.payload.user?.id?.trim() || void 0 };
|
|
@@ -2115,10 +2014,6 @@ async function handleSlackInteractivePayload(args) {
|
|
|
2115
2014
|
}));
|
|
2116
2015
|
return;
|
|
2117
2016
|
}
|
|
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
2017
|
if (args.payload.type !== "block_actions") return;
|
|
2123
2018
|
for (const action of args.payload.actions ?? []) {
|
|
2124
2019
|
const click = parseSlackReviewItemClick(action);
|
|
@@ -2131,18 +2026,6 @@ async function handleSlackInteractivePayload(args) {
|
|
|
2131
2026
|
}));
|
|
2132
2027
|
return;
|
|
2133
2028
|
}
|
|
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
2029
|
}
|
|
2147
2030
|
const disconnect = args.payload.actions?.find((candidate) => candidate.action_id === "app_home_disconnect");
|
|
2148
2031
|
const provider = disconnect?.selected_option?.value ?? disconnect?.value;
|
|
@@ -2644,6 +2527,17 @@ async function buildThread(args) {
|
|
|
2644
2527
|
function shouldIgnoreMessage(message) {
|
|
2645
2528
|
return message.author.isMe === true || !parseActorUserId(message.author.userId);
|
|
2646
2529
|
}
|
|
2530
|
+
/**
|
|
2531
|
+
* Resolve the Slack author Identity at ingress and bind its id to the message.
|
|
2532
|
+
* Ingress does no profile lookup. The worker adds the profile names later.
|
|
2533
|
+
* Bot authors wait for their own bot Identity, so they get no id here.
|
|
2534
|
+
*/
|
|
2535
|
+
async function bindSlackAuthorIdentity(message, installation) {
|
|
2536
|
+
const teamId = installation.teamId;
|
|
2537
|
+
const userId = parseActorUserId(message.author.userId);
|
|
2538
|
+
if (!teamId || !userId || message.author.isBot === true) return;
|
|
2539
|
+
bindMessageAuthorIdentityId(message, await resolveActorIdentityId(getSqlExecutor(), createSlackActor(teamId, userId, null)));
|
|
2540
|
+
}
|
|
2647
2541
|
function shouldPersistBeforeAck(body) {
|
|
2648
2542
|
return body.event?.type === "app_mention" || body.event?.type === "message";
|
|
2649
2543
|
}
|
|
@@ -2742,6 +2636,7 @@ async function handleSlackThreadStop(args) {
|
|
|
2742
2636
|
conversationId,
|
|
2743
2637
|
state: args.state
|
|
2744
2638
|
});
|
|
2639
|
+
await bindSlackAuthorIdentity(args.message, args.installation);
|
|
2745
2640
|
const content = parseContent(args.message);
|
|
2746
2641
|
const conversation = coerceThreadConversationState(void 0);
|
|
2747
2642
|
recordSkippedConversationMessage({
|
|
@@ -2848,13 +2743,15 @@ async function routeParsedMessage(args) {
|
|
|
2848
2743
|
});
|
|
2849
2744
|
return;
|
|
2850
2745
|
}
|
|
2851
|
-
|
|
2746
|
+
const isAuthorDomainAllowed = () => isSlackAuthorDomainAllowed({
|
|
2852
2747
|
allowedBotUserIds: args.allowedBotUserIds,
|
|
2853
2748
|
allowedDomains: args.allowedDomains,
|
|
2854
2749
|
state: args.state,
|
|
2855
2750
|
teamId: args.installation.teamId,
|
|
2856
2751
|
user: args.event.user
|
|
2857
|
-
})
|
|
2752
|
+
});
|
|
2753
|
+
if (route === "mention" && !await isAuthorDomainAllowed()) return;
|
|
2754
|
+
await bindSlackAuthorIdentity(message, args.installation);
|
|
2858
2755
|
const conversationId = await resolveSlackConversationId({
|
|
2859
2756
|
canonicalThreadId,
|
|
2860
2757
|
conversationStore: args.conversationStore,
|
|
@@ -2886,22 +2783,34 @@ async function routeParsedMessage(args) {
|
|
|
2886
2783
|
route,
|
|
2887
2784
|
state: args.state
|
|
2888
2785
|
});
|
|
2889
|
-
|
|
2786
|
+
const closeAnswered = async () => {
|
|
2787
|
+
if (message.author.isBot === true) return;
|
|
2788
|
+
await closeReviewItemsAnsweredByReply({
|
|
2789
|
+
...route === "subscribed" ? { canAnswer: isAuthorDomainAllowed } : void 0,
|
|
2790
|
+
conversationId,
|
|
2791
|
+
delivery: {
|
|
2792
|
+
queue: args.queue,
|
|
2793
|
+
show: createSlackReviewItemShow(() => args.adapter)
|
|
2794
|
+
},
|
|
2795
|
+
resolveUser: async () => {
|
|
2796
|
+
const teamId = args.installation.teamId;
|
|
2797
|
+
const userId = parseActorUserId(message.author.userId);
|
|
2798
|
+
if (!teamId || !userId) return void 0;
|
|
2799
|
+
return (await readActorIdentity(createSlackActor(teamId, userId, null)))?.user;
|
|
2800
|
+
},
|
|
2801
|
+
text: stripLeadingBotMention(parseContent(message).topLevelText, {
|
|
2802
|
+
botUserId: args.adapter.botUserId,
|
|
2803
|
+
stripLeadingSlackMentionToken: true
|
|
2804
|
+
})
|
|
2805
|
+
});
|
|
2806
|
+
};
|
|
2807
|
+
try {
|
|
2890
2808
|
await persist();
|
|
2891
|
-
|
|
2809
|
+
} catch (error) {
|
|
2810
|
+
if (error instanceof SlackEventPersistenceError && error.saved) args.runAfterUnlock(closeAnswered);
|
|
2811
|
+
throw error;
|
|
2892
2812
|
}
|
|
2893
|
-
|
|
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
|
-
});
|
|
2813
|
+
args.runAfterUnlock(closeAnswered);
|
|
2905
2814
|
}
|
|
2906
2815
|
async function handleSlackEvent(args) {
|
|
2907
2816
|
const event = args.body.event;
|
|
@@ -2979,6 +2888,7 @@ async function handleSlackEvent(args) {
|
|
|
2979
2888
|
setSpanAttributes({ "app.slack.membership": member ? "verified" : "unverified" });
|
|
2980
2889
|
if (!member) return;
|
|
2981
2890
|
const message = adapter.parseMessage(event);
|
|
2891
|
+
let afterUnlock;
|
|
2982
2892
|
if (!(await withLock(state, `slack:ingress:${normalizeMessageThreadId(message).threadId}`, () => routeParsedMessage({
|
|
2983
2893
|
adapter,
|
|
2984
2894
|
event,
|
|
@@ -2989,11 +2899,14 @@ async function handleSlackEvent(args) {
|
|
|
2989
2899
|
receivedAtMs,
|
|
2990
2900
|
allowedBotUserIds: args.services.allowedBotUserIds ?? [],
|
|
2991
2901
|
allowedDomains: args.services.allowedDomains ?? [],
|
|
2902
|
+
runAfterUnlock: (task) => {
|
|
2903
|
+
afterUnlock = task;
|
|
2904
|
+
},
|
|
2992
2905
|
state
|
|
2993
2906
|
}), {
|
|
2994
2907
|
keepAlive: true,
|
|
2995
2908
|
waitMs: 1e4
|
|
2996
|
-
})).acquired) throw new Error("Could not acquire Slack ingress lock");
|
|
2909
|
+
}).finally(() => afterUnlock?.())).acquired) throw new Error("Could not acquire Slack ingress lock");
|
|
2997
2910
|
}
|
|
2998
2911
|
}
|
|
2999
2912
|
}));
|
|
@@ -3005,6 +2918,7 @@ async function handleSlackEvent(args) {
|
|
|
3005
2918
|
*/
|
|
3006
2919
|
async function persistSlackMentionWithLock(args) {
|
|
3007
2920
|
const { message, threadId } = normalizeMessageThreadId(args.message);
|
|
2921
|
+
await bindSlackAuthorIdentity(message, args.installation);
|
|
3008
2922
|
try {
|
|
3009
2923
|
if (!(await withLock(args.state, `slack:ingress:${threadId}`, () => persistSlackMessage({
|
|
3010
2924
|
adapter: args.adapter,
|
|
@@ -6223,6 +6137,7 @@ function createBetterAuth(config) {
|
|
|
6223
6137
|
hd: hostedDomain,
|
|
6224
6138
|
prompt: "select_account",
|
|
6225
6139
|
disableIdTokenSignIn: true,
|
|
6140
|
+
overrideUserInfoOnSignIn: true,
|
|
6226
6141
|
async getUserInfo(token) {
|
|
6227
6142
|
if (!token.idToken) return null;
|
|
6228
6143
|
const claims = readGoogleClaims(token.idToken);
|
|
@@ -6232,7 +6147,7 @@ function createBetterAuth(config) {
|
|
|
6232
6147
|
user: {
|
|
6233
6148
|
email: claims.email,
|
|
6234
6149
|
emailVerified: claims.email_verified === true,
|
|
6235
|
-
image: claims.picture,
|
|
6150
|
+
image: claims.picture ?? null,
|
|
6236
6151
|
name: claims.name
|
|
6237
6152
|
},
|
|
6238
6153
|
data: claims
|
|
@@ -6264,7 +6179,8 @@ function createBetterAuth(config) {
|
|
|
6264
6179
|
await recordGoogleSignIn(getSqlExecutor(), {
|
|
6265
6180
|
email,
|
|
6266
6181
|
subject: google.accountId,
|
|
6267
|
-
displayName: created.user.name || void 0
|
|
6182
|
+
displayName: created.user.name || void 0,
|
|
6183
|
+
avatarUrl: parseAvatarUrl(created.user.image, GOOGLE_IDENTITY_PROVIDER)
|
|
6268
6184
|
});
|
|
6269
6185
|
}) }
|
|
6270
6186
|
});
|
|
@@ -6663,7 +6579,10 @@ async function createApp(options) {
|
|
|
6663
6579
|
validatePluginRegistrations(configuredPlugins?.registrations ?? []);
|
|
6664
6580
|
validatePluginEgressCredentialHooks(configuredPlugins?.registrations ?? []);
|
|
6665
6581
|
}
|
|
6666
|
-
pluginRoutes = getPluginRoutes({
|
|
6582
|
+
pluginRoutes = getPluginRoutes({
|
|
6583
|
+
events,
|
|
6584
|
+
showReviewItem: createSlackReviewItemShow(getProductionSlackAdapter)
|
|
6585
|
+
});
|
|
6667
6586
|
if (dashboard && !dashboard.disabled) pluginApiRoutes = getPluginApiRoutes();
|
|
6668
6587
|
} catch (error) {
|
|
6669
6588
|
restoreRuntimeConfig$1();
|
|
@@ -6681,6 +6600,7 @@ async function createApp(options) {
|
|
|
6681
6600
|
attachmentStorage,
|
|
6682
6601
|
bindMessageAgent: (request) => bindMessageAgent(request, { queue: conversationWorkQueue }),
|
|
6683
6602
|
bindSpawnAgent: (request) => bindSpawnAgent(request, { queue: conversationWorkQueue }),
|
|
6603
|
+
conversationWorkQueue,
|
|
6684
6604
|
tracePropagation
|
|
6685
6605
|
});
|
|
6686
6606
|
const runtimeServiceOverrides = {
|