@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
package/dist/api.js
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { p as escapeXml } from "./client-
|
|
3
|
-
import { m as logInfo, p as logException } from "./logging-
|
|
4
|
-
import {
|
|
1
|
+
import { F as conversationRangeColumns, N as conversationActiveDaysColumn, P as conversationAggregateColumns, Wr as isExperimentalFeatureEnabled, ct as AutomationConflictError, ft as automationEventCatalog, j as readAutomationTitlesByConversationId } from "./turn-session-routing-B9KLBhaT.js";
|
|
2
|
+
import { p as escapeXml } from "./client-B2MjENki.js";
|
|
3
|
+
import { m as logInfo, p as logException } from "./logging-C6EdT6PP.js";
|
|
4
|
+
import { C as getSqlExecutor, E as loadConversationSlackTenantIds, J as resolveRootConversationId, K as agentTurnUsageSchema, S as getDb, c as readViewerAvatarUrl, d as updateViewerDisplayName, l as resolveViewerUser, m as readAvatarImage, q as hasAgentTurnUsage, t as findUserByEmail, x as getConversationStore } from "./viewer-BTgAfdUg.js";
|
|
5
5
|
import { c as juniorIdentities, d as juniorDestinations, l as juniorUsers, s as juniorConversations } from "./agent-invocations-C1RNOCs8.js";
|
|
6
|
-
import { C as juniorCodeRepositories, S as juniorCodeChanges, b as juniorApiTokens, m as juniorConversationParticipants, v as juniorConversationMetrics, y as juniorConversationEvents } from "./executor-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { A as createConversationMessageBodySchema,
|
|
13
|
-
import { h as getChildAgentLabel } from "./store-
|
|
14
|
-
import { d as getEventCatalog } from "./session-stop-
|
|
15
|
-
import {
|
|
16
|
-
import { s as getSandboxResources, t as getCachedSnapshot } from "./resolve-
|
|
17
|
-
import { a as getVercelConversationWorkQueue } from "./job-queue-
|
|
18
|
-
import { E as steerWebPendingMessages, a as cancelHumanFacingPendingMessages, g as getConversationWorkState, h as getConversation } from "./store-
|
|
19
|
-
import { n as finishServiceAccountSignIn, o as serviceAccountPlugins, r as getServiceAccountStatus, s as startServiceAccountSignIn, t as disconnectServiceAccount } from "./service-account-
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import { a as
|
|
26
|
-
import { A as personParamsSchema, B as connectionListSchema, C as createdPersonalTokenSchema, D as revokePersonalTokenResponseSchema, E as personalTokenParamsSchema, F as locationParamsSchema, I as activityDays$1, J as codeOverviewReportSchema, L as activityHours$1, N as locationDetailReportSchema, O as actorDirectoryReportSchema, P as locationDirectoryReportSchema, R as activitySixHours$1, S as createPersonalTokenBodySchema, U as disconnectConnectionResponseSchema, V as connectionParamsSchema, W as startConnectionResponseSchema, X as codeRepositoryParamsSchema, Y as codePersonReportSchema, Z as codeRepositoryReportSchema, _ as disconnectServiceAccountResponseSchema, a as workspaceBodySchema, at as apiErrorSchema, d as reviewItemCountSchema, et as conversationWatchesReportSchema, f as reviewItemListQuerySchema, g as reviewItemWaitingConversationsSchema, h as reviewItemSchema, i as deleteWorkspaceResponseSchema, it as conversationStatsReportSchema, j as personalSpendReportSchema, k as actorProfileReportSchema, l as workspaceSchema, m as reviewItemParamsSchema, n as statsReportSchema, nt as conversationChildAgentsReportSchema, o as workspaceListSchema, p as reviewItemListSchema, rt as stopConversationTurnResponseSchema, s as workspaceParamsSchema, u as reviewItemActionSchema, v as serviceAccountListSchema, w as personalTokenListSchema, x as startServiceAccountSignInResponseSchema, y as serviceAccountParamsSchema } from "./schema-0050HFnB.js";
|
|
6
|
+
import { C as juniorCodeRepositories, S as juniorCodeChanges, b as juniorApiTokens, m as juniorConversationParticipants, v as juniorConversationMetrics, y as juniorConversationEvents } from "./executor-BB6eJkD4.js";
|
|
7
|
+
import { t as INPUT_IMAGE_TYPES } from "./media-U6Tuz6Mi.js";
|
|
8
|
+
import { n as pluginCatalogRuntime } from "./catalog-runtime-Bdym_wKy.js";
|
|
9
|
+
import { $ as listOwnedWatches, B as changeViewerAutomationLifecycle, Dt as readUserCustomization, G as readConversationSourceTask, H as readViewerAutomationEdit, J as readViewerAutomationSummary, K as readViewerAutomationExecutions, Ot as saveUserCustomization, St as conversationSubtreeColumns, U as updateViewerAutomation, V as deleteViewerTask, W as ViewerTaskNotFoundError, X as readViewerAutomations, Y as readViewerAutomationVersions, Z as AutomationEditError, at as createAndEnqueueConversation, ct as webActorFromEmail, ft as readLiveAttachment, m as readStats, nt as acceptsWebMessages, q as readViewerAutomationRuns, rt as appendAndEnqueueWebMessage, ut as decodeInputImages, x as createSlackReviewItemShow, xt as conversationSubtree, yt as listChildAgents, z as activateViewerAutomationVersion } from "./agent-runner-MSQSMFkq.js";
|
|
10
|
+
import { $t as workspaceRepoCheckoutPath, Ar as lookupSlackUser, D as listWaitingConversationIds, Er as listConversationAnnotations, F as isOnlyAssignee, G as deleteWorkspace, J as listWorkspaces, K as getWorkspace, M as canActOnReviewItem, O as searchReviewItems, W as createWorkspace, X as updateWorkspace, Y as listWorkspacesByRepository, Z as WorkspaceValidationError, Zt as SANDBOX_RUNTIME, _r as readConversationEventPage, ar as createPluginLogger, gr as readLatestConversationBrief, jr as createPluginCache, n as createUserTokenStore, nt as create, or as readConversationAccessFromSql, p as getPlugins, rt as hash, vr as buildSentryConversationUrl, x as countReviewItemsNeedingUser, z as reviewItemReaderForUser } from "./credentialed-BeBaJMZ_.js";
|
|
11
|
+
import { r as getStateAdapter } from "./adapter-BQNTKVTF.js";
|
|
12
|
+
import { A as createConversationMessageBodySchema, M as forkConversationResponseSchema, N as steerConversationPendingMessagesBodySchema, P as steerConversationPendingMessagesResponseSchema, W as readMessageAttachments, _ as conversationParamsSchema, a as cancelConversationPendingMessagesBodySchema, c as conversationAttachmentParamsSchema, d as conversationDetailReportSchema, g as conversationFeedSchema, h as conversationFeedQuerySchema, i as archiveConversationResponseSchema, j as forkConversationBodySchema, k as createConversationBodySchema, m as conversationEventsQuerySchema, o as cancelConversationPendingMessagesResponseSchema, p as conversationEventPageSchema, r as archiveConversationBodySchema, t as acceptedConversationMessageSchema, u as conversationDetailQuerySchema, x as conversationPendingMessagesReportSchema } from "./conversation-AhOVzN_k.js";
|
|
13
|
+
import { h as getChildAgentLabel } from "./store-Byarin7b.js";
|
|
14
|
+
import { d as getEventCatalog } from "./session-stop-MZRgYqYH.js";
|
|
15
|
+
import { S as userCustomizationSchema, a as fillUtcSixHours, b as webMessageId, c as trailingUtcDayWindow, d as utcDayKey, f as utcHourKey, i as fillUtcHours, l as trailingUtcHourWindow, n as HOUR_MS$1, o as startOfUtcHour, r as fillUtcDays, s as sumUtcHoursIntoSixHours, t as DAY_MS$1, u as trailingUtcSixHourWindow } from "./reporting-window-DRCi1Ls_.js";
|
|
16
|
+
import { s as getSandboxResources, t as getCachedSnapshot } from "./resolve-BkAA1wH7.js";
|
|
17
|
+
import { a as getVercelConversationWorkQueue } from "./job-queue-DiaXoSDg.js";
|
|
18
|
+
import { E as steerWebPendingMessages, a as cancelHumanFacingPendingMessages, g as getConversationWorkState, h as getConversation } from "./store-BeWGgaMA.js";
|
|
19
|
+
import { n as finishServiceAccountSignIn, o as serviceAccountPlugins, r as getServiceAccountStatus, s as startServiceAccountSignIn, t as disconnectServiceAccount } from "./service-account-D6e9cVmH.js";
|
|
20
|
+
import { N as ScheduleIntentError, P as compileScheduleIntent, _ as automationSummarySchema, b as automationVersionListSchema, c as automationLifecycleSchema, d as automationParamsSchema, f as automationRunListSchema, g as automationSchedulePreviewSchema, h as automationScheduleIntentSchema, i as automationExecutionListSchema, l as automationListQuerySchema, n as automationEditSchema, r as automationEventCatalogSchema, t as automationEditErrorSchema, u as automationListSchema, v as automationUpdateSchema, x as automationVersionParamsSchema, y as automationVersionActivateSchema } from "./automation-Dwh_xcqM.js";
|
|
21
|
+
import { c as runtimeInfoReportSchema, n as pluginOperationalReportFeedSchema, s as pluginsSchema, t as healthReportSchema, u as skillReportsSchema } from "./reporting-schema-CZREhYc-.js";
|
|
22
|
+
import { B as actOnReviewItem, C as isAllowedSignInEmail, H as readReviewItemForUser, J as readHealthReport, N as stopConversationTurn, O as clearSlackPendingReactions, R as parseContent, V as closeReviewItemsAnsweredByReply, W as getAttachmentStorage, a as resolveMentions, c as readConversationAuxiliaryCostsFromSql, d as notCopiedByFork, f as childAgentTotalsReport, g as resolveSlackTeamDomains, h as conversationSummaryFromStoredConversation, i as attachConversationMentions, l as ConversationForkError, m as conversationEventHistory, n as readConversationRecordFromSql, o as readFirstHumanMessageTexts, p as readConversationTreeMetricsFromSql, r as readConversationParticipants, s as listConversationSidebarAnnotations, t as readConversationFeed, u as forkConversation, y as getProductionSlackAdapter, z as ReviewItemActionError } from "./list-BTDRxkOg.js";
|
|
23
|
+
import { d as legacyWebMailboxMetadataSchema } from "./result-9TJTpuYP.js";
|
|
24
|
+
import { a as startConnection, l as getWebAuthorization, n as isConnectableProvider, r as listConnections, t as disconnectConnection, u as htmlCallbackResponse } from "./connections-0BBhiD-p.js";
|
|
25
|
+
import { A as avatarParamsSchema, C as createdPersonalTokenSchema, D as revokePersonalTokenResponseSchema, E as personalTokenParamsSchema, F as locationDirectoryReportSchema, G as startConnectionResponseSchema, H as connectionParamsSchema, I as locationParamsSchema, L as activityDays$1, M as personalSpendReportSchema, O as actorDirectoryReportSchema, P as locationDetailReportSchema, Q as codeRepositoryReportSchema, R as activityHours$1, S as createPersonalTokenBodySchema, V as connectionListSchema, W as disconnectConnectionResponseSchema, X as codePersonReportSchema, Y as codeOverviewReportSchema, Z as codeRepositoryParamsSchema, _ as disconnectServiceAccountResponseSchema, a as workspaceBodySchema, at as conversationStatsReportSchema, d as reviewItemCountSchema, f as reviewItemListQuerySchema, g as reviewItemWaitingConversationsSchema, h as reviewItemSchema, i as deleteWorkspaceResponseSchema, it as stopConversationTurnResponseSchema, j as personParamsSchema, k as actorProfileReportSchema, l as workspaceSchema, m as reviewItemParamsSchema, n as statsReportSchema, o as workspaceListSchema, ot as apiErrorSchema, p as reviewItemListSchema, rt as conversationChildAgentsReportSchema, s as workspaceParamsSchema, tt as conversationWatchesReportSchema, u as reviewItemActionSchema, v as serviceAccountListSchema, w as personalTokenListSchema, x as startServiceAccountSignInResponseSchema, y as serviceAccountParamsSchema, z as activitySixHours$1 } from "./schema-DNLJ_MzW.js";
|
|
27
26
|
import { Hono } from "hono";
|
|
28
27
|
import path from "node:path";
|
|
29
28
|
import { z } from "zod";
|
|
@@ -272,31 +271,34 @@ async function appendConversationMessageForViewer(viewer, conversationId, body,
|
|
|
272
271
|
attachmentStorage: services.attachmentStorage,
|
|
273
272
|
queue: services.queue
|
|
274
273
|
});
|
|
275
|
-
const
|
|
274
|
+
const closeAnswered = () => closeReviewItemsAnsweredByReply({
|
|
275
|
+
conversationId,
|
|
276
|
+
delivery: {
|
|
277
|
+
queue: services.queue,
|
|
278
|
+
show: createSlackReviewItemShow(getProductionSlackAdapter)
|
|
279
|
+
},
|
|
280
|
+
resolveUser: async () => viewer,
|
|
281
|
+
text: body.message
|
|
282
|
+
});
|
|
276
283
|
try {
|
|
277
|
-
|
|
278
|
-
|
|
284
|
+
let accepted;
|
|
285
|
+
try {
|
|
286
|
+
accepted = await append();
|
|
287
|
+
} catch (error) {
|
|
279
288
|
const state = getStateAdapter();
|
|
280
289
|
await state.connect();
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
},
|
|
294
|
-
note: () => webUserInputAnswerNote(viewer.displayName ?? viewer.email),
|
|
295
|
-
persist: append,
|
|
296
|
-
state,
|
|
297
|
-
threadTs: conversation.location?.threadTs ?? (conversation.sessionSource?.kind === "slack" ? conversation.sessionSource.threadTs : void 0)
|
|
298
|
-
});
|
|
299
|
-
});
|
|
290
|
+
const [messageId, work] = await Promise.all([webMessageId({
|
|
291
|
+
conversationId,
|
|
292
|
+
idempotencyKey: body.idempotencyKey
|
|
293
|
+
}), getConversationWorkState({
|
|
294
|
+
conversationId,
|
|
295
|
+
state
|
|
296
|
+
})]);
|
|
297
|
+
if (work?.execution.inboundMessageIds.includes(messageId)) await closeAnswered();
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
300
|
+
await closeAnswered();
|
|
301
|
+
return accepted;
|
|
300
302
|
} catch (error) {
|
|
301
303
|
throwApiError(500, "Unable to append message.", error);
|
|
302
304
|
}
|
|
@@ -749,12 +751,29 @@ const slackMailboxAuthorSchema = z.object({
|
|
|
749
751
|
}).passthrough();
|
|
750
752
|
const slackMailboxMessageSchema = z.object({
|
|
751
753
|
author: slackMailboxAuthorSchema,
|
|
752
|
-
id: z.string().min(1)
|
|
754
|
+
id: z.string().min(1),
|
|
755
|
+
raw: z.unknown().optional()
|
|
753
756
|
}).passthrough();
|
|
754
757
|
const slackMailboxMetadataSchema = z.object({
|
|
755
758
|
message: slackMailboxMessageSchema,
|
|
756
759
|
platform: z.literal("slack")
|
|
757
760
|
}).passthrough();
|
|
761
|
+
/**
|
|
762
|
+
* Project Slack text the way the Turn stores it in history. The SDK text
|
|
763
|
+
* turns `<@U123>` into a bare `@U123` or `@name`, which the dashboard
|
|
764
|
+
* cannot render as a mention.
|
|
765
|
+
*/
|
|
766
|
+
function slackDisplayText(message, sdkText) {
|
|
767
|
+
return parseContent({
|
|
768
|
+
attachments: [],
|
|
769
|
+
formatted: {
|
|
770
|
+
type: "root",
|
|
771
|
+
children: []
|
|
772
|
+
},
|
|
773
|
+
raw: message.raw,
|
|
774
|
+
text: sdkText
|
|
775
|
+
}).text;
|
|
776
|
+
}
|
|
758
777
|
function isoFromMs(value) {
|
|
759
778
|
return new Date(value).toISOString();
|
|
760
779
|
}
|
|
@@ -805,7 +824,7 @@ async function projectPendingMessage(message, canExposePayload) {
|
|
|
805
824
|
const metadata = slackMailboxMetadataSchema.safeParse(message.input.metadata);
|
|
806
825
|
if (!metadata.success) return void 0;
|
|
807
826
|
if (metadata.data.message.author.isMe === true) return void 0;
|
|
808
|
-
const text = message.input.text.trim();
|
|
827
|
+
const text = slackDisplayText(metadata.data.message, message.input.text).trim();
|
|
809
828
|
if (!text) return void 0;
|
|
810
829
|
if (!canExposePayload) return {
|
|
811
830
|
createdAt: isoFromMs(message.createdAtMs),
|
|
@@ -831,6 +850,19 @@ async function projectPendingMessage(message, canExposePayload) {
|
|
|
831
850
|
};
|
|
832
851
|
}
|
|
833
852
|
}
|
|
853
|
+
async function attachPendingMentions(conversationId, messages) {
|
|
854
|
+
if (!messages.some((message) => message.text?.includes("<@"))) return messages;
|
|
855
|
+
const executor = getSqlExecutor();
|
|
856
|
+
const tenantId = (await loadConversationSlackTenantIds(executor, [conversationId])).get(conversationId);
|
|
857
|
+
const mentions = await resolveMentions(executor, messages.map((message) => ({
|
|
858
|
+
tenantId,
|
|
859
|
+
texts: [message.text]
|
|
860
|
+
})));
|
|
861
|
+
return messages.map((message, index) => mentions[index].length > 0 ? {
|
|
862
|
+
...message,
|
|
863
|
+
mentions: mentions[index]
|
|
864
|
+
} : message);
|
|
865
|
+
}
|
|
834
866
|
/**
|
|
835
867
|
* Read accepted mailbox messages that have not reached durable history yet.
|
|
836
868
|
*
|
|
@@ -848,7 +880,7 @@ async function readConversationPendingMessages(conversationId, options = {}) {
|
|
|
848
880
|
conversationId
|
|
849
881
|
}) : void 0;
|
|
850
882
|
const work = await getConversation({ conversationId });
|
|
851
|
-
const messages = (await Promise.all((work?.execution.pendingMessages ?? []).map((message) => projectPendingMessage(message, canExposePayload)))).filter((message) => Boolean(message));
|
|
883
|
+
const messages = await attachPendingMentions(conversationId, (await Promise.all((work?.execution.pendingMessages ?? []).map((message) => projectPendingMessage(message, canExposePayload)))).filter((message) => Boolean(message)));
|
|
852
884
|
return conversationPendingMessagesReportSchema.parse({
|
|
853
885
|
...authorization ? { authorization: {
|
|
854
886
|
authorizationUrl: authorization.authorizationUrl,
|
|
@@ -2694,7 +2726,7 @@ async function readPeoplePluginReports(args) {
|
|
|
2694
2726
|
reports: [],
|
|
2695
2727
|
source: "plugins"
|
|
2696
2728
|
});
|
|
2697
|
-
const { getPluginProfileReports } = await import("./credentialed-
|
|
2729
|
+
const { getPluginProfileReports } = await import("./credentialed-BeBaJMZ_.js").then((n) => n.a);
|
|
2698
2730
|
return pluginOperationalReportFeedSchema.parse({
|
|
2699
2731
|
generatedAt: new Date(nowMs).toISOString(),
|
|
2700
2732
|
reports: await getPluginProfileReports({
|
|
@@ -2903,6 +2935,23 @@ function spendWindow(nowMs) {
|
|
|
2903
2935
|
thirtyDayStart
|
|
2904
2936
|
};
|
|
2905
2937
|
}
|
|
2938
|
+
/**
|
|
2939
|
+
* Read a cheap change marker for one viewer's spend window.
|
|
2940
|
+
*
|
|
2941
|
+
* Writes that record Conversation metrics also move `updated_at` forward, so
|
|
2942
|
+
* the marker changes when spend can change. The spend cache TTL bounds changes
|
|
2943
|
+
* that the marker misses, such as a day that leaves the window.
|
|
2944
|
+
*/
|
|
2945
|
+
async function readPersonalSpendVersion(email, nowMs = Date.now()) {
|
|
2946
|
+
const normalizedEmail = normalizeEmail$1(email);
|
|
2947
|
+
if (!normalizedEmail) return "";
|
|
2948
|
+
const { end, thirtyDayStart } = spendWindow(nowMs);
|
|
2949
|
+
const [row] = await getDb().select({
|
|
2950
|
+
conversations: sql`count(*)::int`,
|
|
2951
|
+
updatedAt: sql`max(${juniorConversations.updatedAt})::text`
|
|
2952
|
+
}).from(juniorConversations).innerJoin(juniorIdentities, eq(juniorIdentities.id, juniorConversations.actorIdentityId)).innerJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).where(and(verifiedActorWhere(normalizedEmail), gte(juniorConversations.lastActivityAt, thirtyDayStart), lte(juniorConversations.lastActivityAt, end)));
|
|
2953
|
+
return `${row?.conversations ?? 0}:${row?.updatedAt ?? ""}`;
|
|
2954
|
+
}
|
|
2906
2955
|
/** Read one viewer's rolling model spend with one bounded aggregate query. */
|
|
2907
2956
|
async function readPersonalSpendFromSql(email, nowMs = Date.now()) {
|
|
2908
2957
|
const normalizedEmail = normalizeEmail$1(email);
|
|
@@ -2935,19 +2984,27 @@ async function readPersonalSpendFromSql(email, nowMs = Date.now()) {
|
|
|
2935
2984
|
}
|
|
2936
2985
|
// src/api/people/spend.ts
|
|
2937
2986
|
const PERSONAL_SPEND_CACHE_TTL_MS = 3e5;
|
|
2938
|
-
/**
|
|
2987
|
+
/**
|
|
2988
|
+
* Create an app-scoped personal-spend reader.
|
|
2989
|
+
*
|
|
2990
|
+
* A cached report stays valid for five minutes, or until the viewer's spend
|
|
2991
|
+
* version changes. The dashboard can poll often and still see a finished Turn
|
|
2992
|
+
* without a full aggregate query on every poll.
|
|
2993
|
+
*/
|
|
2939
2994
|
function createPersonalSpendReader() {
|
|
2940
2995
|
const cache = /* @__PURE__ */ new Map();
|
|
2941
2996
|
return async function readPersonalSpend(email) {
|
|
2942
2997
|
const normalizedEmail = email.trim().toLowerCase();
|
|
2943
2998
|
const nowMs = Date.now();
|
|
2999
|
+
const version = await readPersonalSpendVersion(normalizedEmail, nowMs);
|
|
2944
3000
|
const cached = cache.get(normalizedEmail);
|
|
2945
|
-
if (cached && cached.expiresAtMs > nowMs) return cached.report;
|
|
3001
|
+
if (cached && cached.expiresAtMs > nowMs && cached.version === version) return cached.report;
|
|
2946
3002
|
cache.delete(normalizedEmail);
|
|
2947
3003
|
const report = readPersonalSpendFromSql(normalizedEmail, nowMs);
|
|
2948
3004
|
const entry = {
|
|
2949
3005
|
expiresAtMs: nowMs + PERSONAL_SPEND_CACHE_TTL_MS,
|
|
2950
|
-
report
|
|
3006
|
+
report,
|
|
3007
|
+
version
|
|
2951
3008
|
};
|
|
2952
3009
|
cache.set(normalizedEmail, entry);
|
|
2953
3010
|
try {
|
|
@@ -2963,6 +3020,17 @@ function createPersonalSpendReader() {
|
|
|
2963
3020
|
function createPeopleRoutes() {
|
|
2964
3021
|
const app = new Hono();
|
|
2965
3022
|
const readPersonalSpend = createPersonalSpendReader();
|
|
3023
|
+
app.get("/avatars/:identityId", requireViewer, validateRequest("param", avatarParamsSchema, "Invalid route parameters."), async (context) => {
|
|
3024
|
+
const { identityId } = context.req.valid("param");
|
|
3025
|
+
const image = await readAvatarImage(getDb(), getStateAdapter(), identityId);
|
|
3026
|
+
if (!image) throwApiError(404, "Avatar not found.");
|
|
3027
|
+
return new Response(Buffer.from(image.data, "base64"), { headers: {
|
|
3028
|
+
"cache-control": "private, max-age=86400",
|
|
3029
|
+
"content-security-policy": "default-src 'none'; sandbox",
|
|
3030
|
+
"content-type": image.contentType,
|
|
3031
|
+
"x-content-type-options": "nosniff"
|
|
3032
|
+
} });
|
|
3033
|
+
});
|
|
2966
3034
|
app.get("/me/spend", requireViewer, async (context) => {
|
|
2967
3035
|
const viewer = context.get("viewer");
|
|
2968
3036
|
return jsonResponse(personalSpendReportSchema, await readPersonalSpend(viewer.email));
|
|
@@ -3206,233 +3274,6 @@ function createUserPageRoutes() {
|
|
|
3206
3274
|
});
|
|
3207
3275
|
return app;
|
|
3208
3276
|
}
|
|
3209
|
-
// src/chat/automations/edit.ts
|
|
3210
|
-
/**
|
|
3211
|
-
* Web edits. Owners and public Destination readers can edit. Creator-only
|
|
3212
|
-
* rules still apply, and lifecycle actions stay creator-only.
|
|
3213
|
-
*/
|
|
3214
|
-
/** Owners and public Destination readers can edit. Others get not found. */
|
|
3215
|
-
async function requireEditableAutomation(user, id) {
|
|
3216
|
-
const candidate = await resolveViewerTaskCandidate(user, id);
|
|
3217
|
-
if (!candidate) throw new ViewerTaskNotFoundError();
|
|
3218
|
-
return candidate;
|
|
3219
|
-
}
|
|
3220
|
-
/** Lifecycle actions are creator-only. Others get not found. */
|
|
3221
|
-
async function requireOwnedAutomation(user, id) {
|
|
3222
|
-
const candidate = await requireEditableAutomation(user, id);
|
|
3223
|
-
if (!candidate.ownedByViewer) throw new ViewerTaskNotFoundError();
|
|
3224
|
-
return candidate;
|
|
3225
|
-
}
|
|
3226
|
-
/** Record the viewer's Slack identity in the Automation workspace as the editor. */
|
|
3227
|
-
function viewerEditor(user, automation) {
|
|
3228
|
-
if (automation.ownedByViewer) return automation.task.createdBy;
|
|
3229
|
-
const identity = user.identities.find((candidate) => candidate.provider === "slack" && candidate.providerTenantId === automation.task.destination.teamId);
|
|
3230
|
-
if (!identity) return void 0;
|
|
3231
|
-
const editor = { slackUserId: identity.providerSubjectId };
|
|
3232
|
-
if (identity.displayName) editor.fullName = identity.displayName;
|
|
3233
|
-
if (identity.handle) editor.userName = identity.handle;
|
|
3234
|
-
return editor;
|
|
3235
|
-
}
|
|
3236
|
-
function editView(automation, ownedByViewer) {
|
|
3237
|
-
const { task } = automation;
|
|
3238
|
-
const common = {
|
|
3239
|
-
ownedByViewer,
|
|
3240
|
-
id: task.id,
|
|
3241
|
-
revision: automationRevision(task),
|
|
3242
|
-
title: task.title ?? null,
|
|
3243
|
-
instruction: task.task.text,
|
|
3244
|
-
credentialMode: task.credentialMode,
|
|
3245
|
-
outcomes: task.outcomes,
|
|
3246
|
-
destination: task.destination,
|
|
3247
|
-
createdBy: task.createdBy
|
|
3248
|
-
};
|
|
3249
|
-
if (automation.kind === "scheduled") {
|
|
3250
|
-
const status = automation.task.status;
|
|
3251
|
-
if (status === "deleted") throw new ViewerTaskNotFoundError();
|
|
3252
|
-
return {
|
|
3253
|
-
...common,
|
|
3254
|
-
kind: "scheduled",
|
|
3255
|
-
status,
|
|
3256
|
-
schedule: automation.task.schedule,
|
|
3257
|
-
nextRunAtMs: automation.task.nextRunAtMs
|
|
3258
|
-
};
|
|
3259
|
-
}
|
|
3260
|
-
return {
|
|
3261
|
-
...common,
|
|
3262
|
-
kind: "event",
|
|
3263
|
-
status: automation.task.status === "deleted" ? "active" : automation.task.status,
|
|
3264
|
-
trigger: automation.task.trigger
|
|
3265
|
-
};
|
|
3266
|
-
}
|
|
3267
|
-
/** Load exact editable values by ID, independent of list filters. */
|
|
3268
|
-
async function readViewerAutomationEdit(user, id) {
|
|
3269
|
-
const automation = await requireEditableAutomation(user, id);
|
|
3270
|
-
return editView(automation, automation.ownedByViewer);
|
|
3271
|
-
}
|
|
3272
|
-
/** Save a partial edit against the read revision, without dispatching work. */
|
|
3273
|
-
async function updateViewerAutomation(user, id, input) {
|
|
3274
|
-
const current = await requireEditableAutomation(user, id);
|
|
3275
|
-
if (input.kind !== current.kind) throw new AutomationEditError("The trigger type cannot change.", "kind");
|
|
3276
|
-
requireAutomationRevision(current.task, input.revision);
|
|
3277
|
-
return saveViewerEdit(user, current, input);
|
|
3278
|
-
}
|
|
3279
|
-
/** `restored` carries version values that edit input cannot express, such as a cleared title. */
|
|
3280
|
-
async function saveViewerEdit(user, current, input, restored) {
|
|
3281
|
-
const isCreator = current.ownedByViewer;
|
|
3282
|
-
const editedBy = viewerEditor(user, current);
|
|
3283
|
-
if (input.kind === "scheduled" && current.kind === "scheduled") {
|
|
3284
|
-
const next = await editScheduledAutomation(current.task, input, isCreator, Date.now());
|
|
3285
|
-
return editView({
|
|
3286
|
-
kind: "scheduled",
|
|
3287
|
-
task: await saveScheduledAutomation(getDb(), restored ? {
|
|
3288
|
-
...next,
|
|
3289
|
-
...restored
|
|
3290
|
-
} : next, input.revision, editedBy)
|
|
3291
|
-
}, isCreator);
|
|
3292
|
-
}
|
|
3293
|
-
if (input.kind === "event" && current.kind === "event") {
|
|
3294
|
-
const next = await editEventAutomation(current.task, input, isCreator, getEventCatalog());
|
|
3295
|
-
const task = await saveEventAutomation(getDb(), restored ? {
|
|
3296
|
-
...next,
|
|
3297
|
-
title: restored.title
|
|
3298
|
-
} : next, input.revision, editedBy);
|
|
3299
|
-
if (!task) throw new ViewerTaskNotFoundError();
|
|
3300
|
-
return editView({
|
|
3301
|
-
kind: "event",
|
|
3302
|
-
task
|
|
3303
|
-
}, isCreator);
|
|
3304
|
-
}
|
|
3305
|
-
throw new ViewerTaskNotFoundError();
|
|
3306
|
-
}
|
|
3307
|
-
function scheduleIntent(schedule) {
|
|
3308
|
-
const recurrence = schedule.recurrence;
|
|
3309
|
-
if (schedule.kind !== "recurring" || !recurrence) throw new AutomationEditError("A one-time Schedule cannot be restored. Set a new time in the editor.", "schedule");
|
|
3310
|
-
return {
|
|
3311
|
-
kind: "recurring",
|
|
3312
|
-
frequency: recurrence.frequency,
|
|
3313
|
-
interval: recurrence.interval,
|
|
3314
|
-
time: `${String(recurrence.time.hour).padStart(2, "0")}:${String(recurrence.time.minute).padStart(2, "0")}`,
|
|
3315
|
-
weekdays: recurrence.weekdays?.map((day) => weekdaySchema.options[day]),
|
|
3316
|
-
dayOfMonth: recurrence.dayOfMonth,
|
|
3317
|
-
month: recurrence.month,
|
|
3318
|
-
startDate: recurrence.startDate,
|
|
3319
|
-
timezone: schedule.timezone
|
|
3320
|
-
};
|
|
3321
|
-
}
|
|
3322
|
-
/**
|
|
3323
|
-
* Turn saved outcomes back into edit input. Messages to the Automation
|
|
3324
|
-
* Destination or the creator DM are always allowed again. Other stored
|
|
3325
|
-
* Destinations must still be on the Automation.
|
|
3326
|
-
*/
|
|
3327
|
-
async function restorableOutcomes(current, outcomes) {
|
|
3328
|
-
const { task } = current;
|
|
3329
|
-
let creatorDm;
|
|
3330
|
-
const restored = [];
|
|
3331
|
-
for (const outcome of outcomes) {
|
|
3332
|
-
if (sameDefinitionValue(outcome.destination, task.destination)) {
|
|
3333
|
-
restored.push({
|
|
3334
|
-
action: outcome.action,
|
|
3335
|
-
destination: "current_conversation"
|
|
3336
|
-
});
|
|
3337
|
-
continue;
|
|
3338
|
-
}
|
|
3339
|
-
if (current.ownedByViewer && !task.outcomes.some((stored) => sameDefinitionValue(stored, outcome))) {
|
|
3340
|
-
creatorDm ??= (await resolveTaskOutcomes([{
|
|
3341
|
-
action: "send_message",
|
|
3342
|
-
destination: "task_creator"
|
|
3343
|
-
}], task.destination, task.createdBy.slackUserId))[0].destination;
|
|
3344
|
-
if (sameDefinitionValue(outcome.destination, creatorDm)) {
|
|
3345
|
-
restored.push({
|
|
3346
|
-
action: outcome.action,
|
|
3347
|
-
destination: "task_creator"
|
|
3348
|
-
});
|
|
3349
|
-
continue;
|
|
3350
|
-
}
|
|
3351
|
-
}
|
|
3352
|
-
restored.push(outcome);
|
|
3353
|
-
}
|
|
3354
|
-
return restored;
|
|
3355
|
-
}
|
|
3356
|
-
/**
|
|
3357
|
-
* Make a saved version active. This saves its definition as a new version
|
|
3358
|
-
* through the same edit rules, so history is never rewritten.
|
|
3359
|
-
*/
|
|
3360
|
-
async function activateViewerAutomationVersion(user, id, input) {
|
|
3361
|
-
const current = await requireEditableAutomation(user, id);
|
|
3362
|
-
requireAutomationRevision(current.task, input.revision);
|
|
3363
|
-
const saved = await readAutomationVersion(getDb(), id, input.version);
|
|
3364
|
-
if (!saved) throw new AutomationEditError("This version does not exist.", "version");
|
|
3365
|
-
const { definition } = saved;
|
|
3366
|
-
if (sameDefinitionValue(definition, automationDefinition(current.task))) return editView(current, current.ownedByViewer);
|
|
3367
|
-
if (!sameDefinitionValue(definition.destination, current.task.destination)) throw new AutomationEditError("This version delivers to another Destination. Move the automation from Slack instead.", "destination");
|
|
3368
|
-
const fields = {};
|
|
3369
|
-
if (definition.instruction !== current.task.task.text) fields.instruction = definition.instruction;
|
|
3370
|
-
if (definition.credentialMode !== current.task.credentialMode) fields.credentialMode = definition.credentialMode;
|
|
3371
|
-
if (!sameDefinitionValue(definition.outcomes, current.task.outcomes)) fields.outcomes = await restorableOutcomes(current, definition.outcomes);
|
|
3372
|
-
const title = definition.title ?? void 0;
|
|
3373
|
-
if (saved.kind === "scheduled" && current.kind === "scheduled") {
|
|
3374
|
-
const update = {
|
|
3375
|
-
kind: "scheduled",
|
|
3376
|
-
revision: input.revision,
|
|
3377
|
-
...fields
|
|
3378
|
-
};
|
|
3379
|
-
const restored = { title };
|
|
3380
|
-
const { schedule } = saved.definition;
|
|
3381
|
-
if (!sameDefinitionValue(schedule, current.task.schedule)) {
|
|
3382
|
-
update.schedule = scheduleIntent(schedule);
|
|
3383
|
-
restored.schedule = schedule;
|
|
3384
|
-
}
|
|
3385
|
-
return saveViewerEdit(user, current, update, restored);
|
|
3386
|
-
}
|
|
3387
|
-
if (saved.kind === "event" && current.kind === "event") {
|
|
3388
|
-
const update = {
|
|
3389
|
-
kind: "event",
|
|
3390
|
-
revision: input.revision,
|
|
3391
|
-
...fields
|
|
3392
|
-
};
|
|
3393
|
-
if (!sameDefinitionValue(saved.definition.trigger, current.task.trigger)) update.trigger = saved.definition.trigger;
|
|
3394
|
-
return saveViewerEdit(user, current, update, { title });
|
|
3395
|
-
}
|
|
3396
|
-
throw new ViewerTaskNotFoundError();
|
|
3397
|
-
}
|
|
3398
|
-
/** Pause or resume future triggers. Already-claimed work can finish. */
|
|
3399
|
-
async function changeViewerAutomationLifecycle(user, id, input) {
|
|
3400
|
-
const current = await requireOwnedAutomation(user, id);
|
|
3401
|
-
requireAutomationRevision(current.task, input.revision);
|
|
3402
|
-
const status = current.task.status;
|
|
3403
|
-
if (status === "completed") throw new AutomationEditError("Completed Automations cannot be restarted.");
|
|
3404
|
-
if (input.action === "pause" && status === "paused") return editView(current, true);
|
|
3405
|
-
if (input.action === "resume" && status !== "paused" && status !== "blocked") throw new AutomationEditError("Only paused or blocked Automations can be resumed.");
|
|
3406
|
-
if (current.kind === "event") return editView({
|
|
3407
|
-
kind: "event",
|
|
3408
|
-
task: await setEventAutomationStatus(getDb(), id, input.action === "pause" ? "paused" : "active", input.revision)
|
|
3409
|
-
}, true);
|
|
3410
|
-
const nowMs = Date.now();
|
|
3411
|
-
const next = {
|
|
3412
|
-
...current.task,
|
|
3413
|
-
updatedAtMs: nowMs,
|
|
3414
|
-
runNowAtMs: void 0
|
|
3415
|
-
};
|
|
3416
|
-
if (input.action === "pause") {
|
|
3417
|
-
next.status = "paused";
|
|
3418
|
-
if (status === "blocked") next.statusReason ??= "A requirement blocked this Automation. Inspect its executions before resuming.";
|
|
3419
|
-
} else {
|
|
3420
|
-
next.status = status === "paused" && next.statusReason ? "blocked" : "active";
|
|
3421
|
-
if (next.status === "active") {
|
|
3422
|
-
next.nextRunAtMs = next.schedule.recurrence ? getFirstRunAtMs({
|
|
3423
|
-
afterMs: nowMs,
|
|
3424
|
-
recurrence: next.schedule.recurrence,
|
|
3425
|
-
timezone: next.schedule.timezone
|
|
3426
|
-
}) : next.nextRunAtMs;
|
|
3427
|
-
if (!next.nextRunAtMs || next.nextRunAtMs <= nowMs) throw new AutomationEditError("This Schedule has no future occurrence. Set a future Schedule before resuming.", "schedule");
|
|
3428
|
-
next.statusReason = void 0;
|
|
3429
|
-
}
|
|
3430
|
-
}
|
|
3431
|
-
return editView({
|
|
3432
|
-
kind: "scheduled",
|
|
3433
|
-
task: await saveScheduledAutomation(getDb(), next, input.revision)
|
|
3434
|
-
}, true);
|
|
3435
|
-
}
|
|
3436
3277
|
// src/chat/automations/editor.ts
|
|
3437
3278
|
/** Read-only editor support. Core owns schedules; plugins own Event choices. */
|
|
3438
3279
|
/**
|
|
@@ -3634,7 +3475,39 @@ function createUserCustomizationRoutes() {
|
|
|
3634
3475
|
return app;
|
|
3635
3476
|
}
|
|
3636
3477
|
// src/api/review-items/routes.ts
|
|
3637
|
-
const
|
|
3478
|
+
const ARCHIVED_LIMIT = 50;
|
|
3479
|
+
const cursorSchema = z.object({
|
|
3480
|
+
conversationId: z.string().min(1).optional(),
|
|
3481
|
+
id: z.string().min(1),
|
|
3482
|
+
query: z.string().min(1).optional(),
|
|
3483
|
+
updatedAtMs: z.number().int(),
|
|
3484
|
+
version: z.literal(1)
|
|
3485
|
+
}).strict();
|
|
3486
|
+
/**
|
|
3487
|
+
* Encode the last open item of a page as the cursor of the next page. The
|
|
3488
|
+
* cursor names its list, so it cannot page through a different list.
|
|
3489
|
+
*/
|
|
3490
|
+
function encodeCursor(item, filters) {
|
|
3491
|
+
return Buffer.from(JSON.stringify({
|
|
3492
|
+
...filters,
|
|
3493
|
+
id: item.id,
|
|
3494
|
+
updatedAtMs: item.updatedAt.getTime(),
|
|
3495
|
+
version: 1
|
|
3496
|
+
}), "utf8").toString("base64url");
|
|
3497
|
+
}
|
|
3498
|
+
/** Decode a cursor of the same list, or return undefined. */
|
|
3499
|
+
function decodeCursor(cursor, filters) {
|
|
3500
|
+
try {
|
|
3501
|
+
const parsed = cursorSchema.parse(JSON.parse(Buffer.from(cursor, "base64url").toString("utf8")));
|
|
3502
|
+
if (parsed.conversationId !== filters.conversationId || parsed.query !== filters.query) return;
|
|
3503
|
+
return {
|
|
3504
|
+
id: parsed.id,
|
|
3505
|
+
updatedAt: new Date(parsed.updatedAtMs)
|
|
3506
|
+
};
|
|
3507
|
+
} catch {
|
|
3508
|
+
return;
|
|
3509
|
+
}
|
|
3510
|
+
}
|
|
3638
3511
|
const ERROR_STATUS = {
|
|
3639
3512
|
conflict: 409,
|
|
3640
3513
|
forbidden: 403,
|
|
@@ -3677,26 +3550,40 @@ function createReviewItemRoutes(services) {
|
|
|
3677
3550
|
app.get("/", requireViewer, validateRequest("query", reviewItemListQuerySchema, "Invalid review item query."), async (context) => {
|
|
3678
3551
|
const viewer = context.get("viewer");
|
|
3679
3552
|
const query = context.req.valid("query");
|
|
3680
|
-
const
|
|
3681
|
-
const items = await searchReviewItems(getDb(), reviewItemReaderForUser(viewer), {
|
|
3682
|
-
limit: LIST_LIMIT,
|
|
3683
|
-
statuses: query.archived === "true" ? ["done", "dismissed"] : ["open"],
|
|
3684
|
-
...view === "mine" ? { assignee: { userId: viewer.id } } : view === "everyone" ? { assignee: { everyone: true } } : void 0,
|
|
3553
|
+
const filters = {
|
|
3685
3554
|
...query.conversationId ? { conversationId: query.conversationId } : void 0,
|
|
3686
3555
|
...query.q ? { query: query.q } : void 0
|
|
3556
|
+
};
|
|
3557
|
+
const after = query.cursor ? decodeCursor(query.cursor, filters) : void 0;
|
|
3558
|
+
if (query.cursor && !after) return jsonResponse(apiErrorSchema, { error: "Invalid review item cursor." }, { status: 400 });
|
|
3559
|
+
const db = getDb();
|
|
3560
|
+
const reader = reviewItemReaderForUser(viewer);
|
|
3561
|
+
const open = await searchReviewItems(db, reader, {
|
|
3562
|
+
...filters,
|
|
3563
|
+
limit: query.limit + 1,
|
|
3564
|
+
statuses: ["open"],
|
|
3565
|
+
...after ? { after } : void 0
|
|
3566
|
+
});
|
|
3567
|
+
const page = open.slice(0, query.limit);
|
|
3568
|
+
const last = page.at(-1);
|
|
3569
|
+
const archived = filters.query && !after ? await searchReviewItems(db, reader, {
|
|
3570
|
+
...filters,
|
|
3571
|
+
limit: 51,
|
|
3572
|
+
statuses: ["done", "dismissed"]
|
|
3573
|
+
}) : [];
|
|
3574
|
+
return jsonResponse(reviewItemListSchema, {
|
|
3575
|
+
items: [...page, ...archived.slice(0, ARCHIVED_LIMIT)].map((item) => reviewItemPayload(item, viewer)),
|
|
3576
|
+
...archived.length > ARCHIVED_LIMIT ? { moreArchived: true } : void 0,
|
|
3577
|
+
...open.length > query.limit && last ? { nextCursor: encodeCursor(last, filters) } : void 0
|
|
3687
3578
|
});
|
|
3688
|
-
return jsonResponse(reviewItemListSchema, { items: items.map((item) => reviewItemPayload(item, viewer)) });
|
|
3689
3579
|
});
|
|
3690
3580
|
app.get("/count", requireViewer, async (context) => {
|
|
3691
3581
|
const viewer = context.get("viewer");
|
|
3692
|
-
return jsonResponse(reviewItemCountSchema, {
|
|
3693
|
-
assignee: { userId: viewer.id },
|
|
3694
|
-
statuses: ["open"]
|
|
3695
|
-
}) });
|
|
3582
|
+
return jsonResponse(reviewItemCountSchema, { needsViewer: await countReviewItemsNeedingUser(getDb(), viewer.id) });
|
|
3696
3583
|
});
|
|
3697
3584
|
app.get("/waiting-conversations", requireViewer, async (context) => {
|
|
3698
3585
|
const viewer = context.get("viewer");
|
|
3699
|
-
return jsonResponse(reviewItemWaitingConversationsSchema, { conversationIds: await listWaitingConversationIds(getDb(), viewer) });
|
|
3586
|
+
return jsonResponse(reviewItemWaitingConversationsSchema, { conversationIds: await listWaitingConversationIds(getDb(), viewer.id) });
|
|
3700
3587
|
});
|
|
3701
3588
|
app.get("/:id", requireViewer, validateRequest("param", reviewItemParamsSchema, "Invalid review item."), async (context) => {
|
|
3702
3589
|
const viewer = context.get("viewer");
|
|
@@ -3714,9 +3601,8 @@ function createReviewItemRoutes(services) {
|
|
|
3714
3601
|
try {
|
|
3715
3602
|
const item = await actOnReviewItem({
|
|
3716
3603
|
action: body.action,
|
|
3717
|
-
|
|
3604
|
+
delivery: services.delivery,
|
|
3718
3605
|
id,
|
|
3719
|
-
queue: services.queue,
|
|
3720
3606
|
user: viewer,
|
|
3721
3607
|
...body.action === "submit" ? { answer: {
|
|
3722
3608
|
...body.answer,
|
|
@@ -3854,7 +3740,7 @@ function readDescriptionText(home) {
|
|
|
3854
3740
|
}
|
|
3855
3741
|
/** Read discovered skill names for authenticated runtime diagnostics. */
|
|
3856
3742
|
async function readSkillReports() {
|
|
3857
|
-
const { discoverSkills } = await import("./skills-
|
|
3743
|
+
const { discoverSkills } = await import("./skills-BggTR_ue.js").then((n) => n.o);
|
|
3858
3744
|
const skills = await discoverSkills();
|
|
3859
3745
|
return skillReportsSchema.parse(skills.map((skill) => ({
|
|
3860
3746
|
name: skill.name,
|
|
@@ -3863,7 +3749,7 @@ async function readSkillReports() {
|
|
|
3863
3749
|
}
|
|
3864
3750
|
/** Read safe configured plugin metadata for authenticated runtime diagnostics. */
|
|
3865
3751
|
async function readPlugins() {
|
|
3866
|
-
const { pluginCatalogRuntime } = await import("./catalog-runtime-
|
|
3752
|
+
const { pluginCatalogRuntime } = await import("./catalog-runtime-Bdym_wKy.js").then((n) => n.t);
|
|
3867
3753
|
return pluginsSchema.parse(pluginCatalogRuntime.getProviders().map((plugin) => ({
|
|
3868
3754
|
configKeys: plugin.manifest.configKeys ?? [],
|
|
3869
3755
|
description: plugin.manifest.description,
|
|
@@ -3875,7 +3761,7 @@ async function readPlugins() {
|
|
|
3875
3761
|
async function readRuntimeInfoReport() {
|
|
3876
3762
|
const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
|
|
3877
3763
|
import("./package-discovery-DJBompdd.js").then((n) => n.r),
|
|
3878
|
-
import("./catalog-runtime-
|
|
3764
|
+
import("./catalog-runtime-Bdym_wKy.js").then((n) => n.t),
|
|
3879
3765
|
readPlugins(),
|
|
3880
3766
|
readSkillReports()
|
|
3881
3767
|
]);
|
|
@@ -3892,7 +3778,7 @@ async function readRuntimeInfoReport() {
|
|
|
3892
3778
|
/** Read sanitized operational summaries contributed by plugins. */
|
|
3893
3779
|
async function readPluginOperationalReportFeed() {
|
|
3894
3780
|
const nowMs = Date.now();
|
|
3895
|
-
const { getPluginOperationalReports } = await import("./credentialed-
|
|
3781
|
+
const { getPluginOperationalReports } = await import("./credentialed-BeBaJMZ_.js").then((n) => n.a);
|
|
3896
3782
|
return pluginOperationalReportFeedSchema.parse({
|
|
3897
3783
|
source: "plugins",
|
|
3898
3784
|
generatedAt: new Date(nowMs).toISOString(),
|
|
@@ -3914,7 +3800,10 @@ function createJuniorApi(options = {}) {
|
|
|
3914
3800
|
attachmentStorage: getAttachmentStorage(),
|
|
3915
3801
|
queue
|
|
3916
3802
|
}));
|
|
3917
|
-
app.route("/api/review-items", createReviewItemRoutes({
|
|
3803
|
+
app.route("/api/review-items", createReviewItemRoutes({ delivery: {
|
|
3804
|
+
queue,
|
|
3805
|
+
show: createSlackReviewItemShow(getProductionSlackAdapter)
|
|
3806
|
+
} }));
|
|
3918
3807
|
app.route("/api/code", createCodeRoutes());
|
|
3919
3808
|
app.route("/api/connections", createConnectionRoutes());
|
|
3920
3809
|
app.route("/api/personal-tokens", createPersonalTokenRoutes());
|
|
@@ -3936,4 +3825,4 @@ function createJuniorApi(options = {}) {
|
|
|
3936
3825
|
});
|
|
3937
3826
|
return app;
|
|
3938
3827
|
}
|
|
3939
|
-
export { authenticatePersonalToken, createJuniorApi, isAllowedSignInEmail, jsonResponse, resolveViewerUser, updateViewerDisplayName };
|
|
3828
|
+
export { authenticatePersonalToken, createJuniorApi, isAllowedSignInEmail, jsonResponse, readViewerAvatarUrl, resolveViewerUser, updateViewerDisplayName };
|