@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/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, Ur as isExperimentalFeatureEnabled, ct as AutomationConflictError, ft as automationEventCatalog, j as readAutomationTitlesByConversationId } from "./turn-session-routing-BqO0qXLk.js";
|
|
2
|
+
import { p as escapeXml } from "./client-Cqf4TboL.js";
|
|
3
|
+
import { m as logInfo, p as logException } from "./logging-n7knse-O.js";
|
|
4
|
+
import { C as getSqlExecutor, 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-DSbD6DF6.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 { l as
|
|
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-CNS7ONt-.js";
|
|
7
|
+
import { t as INPUT_IMAGE_TYPES } from "./media-85PDJxO_.js";
|
|
8
|
+
import { n as pluginCatalogRuntime } from "./catalog-runtime-BsoSmTM0.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-CrDrPUtY.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-BU-OW7HP.js";
|
|
11
|
+
import { r as getStateAdapter } from "./adapter-2-CG25be.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-CTpD_PGk.js";
|
|
13
|
+
import { h as getChildAgentLabel } from "./store-1DVhoKOL.js";
|
|
14
|
+
import { d as getEventCatalog } from "./session-stop-BQW_iFcd.js";
|
|
15
|
+
import { a as fillUtcSixHours, 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, x as userCustomizationSchema, y as webMessageId } from "./reporting-window-CVarfId9.js";
|
|
16
|
+
import { s as getSandboxResources, t as getCachedSnapshot } from "./resolve-CUIBcdPd.js";
|
|
17
|
+
import { a as getVercelConversationWorkQueue } from "./job-queue-DI-k-Bbk.js";
|
|
18
|
+
import { E as steerWebPendingMessages, a as cancelHumanFacingPendingMessages, g as getConversationWorkState, h as getConversation } from "./store-DCo2n5iJ.js";
|
|
19
|
+
import { n as finishServiceAccountSignIn, o as serviceAccountPlugins, r as getServiceAccountStatus, s as startServiceAccountSignIn, t as disconnectServiceAccount } from "./service-account-DHvlLnZw.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-p87hg_AV.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, 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-CGoQdXTp.js";
|
|
23
|
+
import { d as legacyWebMailboxMetadataSchema } from "./result-BemsOMOO.js";
|
|
24
|
+
import { a as startConnection, l as getWebAuthorization, n as isConnectableProvider, r as listConnections, t as disconnectConnection, u as htmlCallbackResponse } from "./connections-upFXLmhG.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-ChnFo5f2.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
|
}
|
|
@@ -2694,7 +2696,7 @@ async function readPeoplePluginReports(args) {
|
|
|
2694
2696
|
reports: [],
|
|
2695
2697
|
source: "plugins"
|
|
2696
2698
|
});
|
|
2697
|
-
const { getPluginProfileReports } = await import("./credentialed-
|
|
2699
|
+
const { getPluginProfileReports } = await import("./credentialed-BU-OW7HP.js").then((n) => n.a);
|
|
2698
2700
|
return pluginOperationalReportFeedSchema.parse({
|
|
2699
2701
|
generatedAt: new Date(nowMs).toISOString(),
|
|
2700
2702
|
reports: await getPluginProfileReports({
|
|
@@ -2903,6 +2905,23 @@ function spendWindow(nowMs) {
|
|
|
2903
2905
|
thirtyDayStart
|
|
2904
2906
|
};
|
|
2905
2907
|
}
|
|
2908
|
+
/**
|
|
2909
|
+
* Read a cheap change marker for one viewer's spend window.
|
|
2910
|
+
*
|
|
2911
|
+
* Writes that record Conversation metrics also move `updated_at` forward, so
|
|
2912
|
+
* the marker changes when spend can change. The spend cache TTL bounds changes
|
|
2913
|
+
* that the marker misses, such as a day that leaves the window.
|
|
2914
|
+
*/
|
|
2915
|
+
async function readPersonalSpendVersion(email, nowMs = Date.now()) {
|
|
2916
|
+
const normalizedEmail = normalizeEmail$1(email);
|
|
2917
|
+
if (!normalizedEmail) return "";
|
|
2918
|
+
const { end, thirtyDayStart } = spendWindow(nowMs);
|
|
2919
|
+
const [row] = await getDb().select({
|
|
2920
|
+
conversations: sql`count(*)::int`,
|
|
2921
|
+
updatedAt: sql`max(${juniorConversations.updatedAt})::text`
|
|
2922
|
+
}).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)));
|
|
2923
|
+
return `${row?.conversations ?? 0}:${row?.updatedAt ?? ""}`;
|
|
2924
|
+
}
|
|
2906
2925
|
/** Read one viewer's rolling model spend with one bounded aggregate query. */
|
|
2907
2926
|
async function readPersonalSpendFromSql(email, nowMs = Date.now()) {
|
|
2908
2927
|
const normalizedEmail = normalizeEmail$1(email);
|
|
@@ -2935,19 +2954,27 @@ async function readPersonalSpendFromSql(email, nowMs = Date.now()) {
|
|
|
2935
2954
|
}
|
|
2936
2955
|
// src/api/people/spend.ts
|
|
2937
2956
|
const PERSONAL_SPEND_CACHE_TTL_MS = 3e5;
|
|
2938
|
-
/**
|
|
2957
|
+
/**
|
|
2958
|
+
* Create an app-scoped personal-spend reader.
|
|
2959
|
+
*
|
|
2960
|
+
* A cached report stays valid for five minutes, or until the viewer's spend
|
|
2961
|
+
* version changes. The dashboard can poll often and still see a finished Turn
|
|
2962
|
+
* without a full aggregate query on every poll.
|
|
2963
|
+
*/
|
|
2939
2964
|
function createPersonalSpendReader() {
|
|
2940
2965
|
const cache = /* @__PURE__ */ new Map();
|
|
2941
2966
|
return async function readPersonalSpend(email) {
|
|
2942
2967
|
const normalizedEmail = email.trim().toLowerCase();
|
|
2943
2968
|
const nowMs = Date.now();
|
|
2969
|
+
const version = await readPersonalSpendVersion(normalizedEmail, nowMs);
|
|
2944
2970
|
const cached = cache.get(normalizedEmail);
|
|
2945
|
-
if (cached && cached.expiresAtMs > nowMs) return cached.report;
|
|
2971
|
+
if (cached && cached.expiresAtMs > nowMs && cached.version === version) return cached.report;
|
|
2946
2972
|
cache.delete(normalizedEmail);
|
|
2947
2973
|
const report = readPersonalSpendFromSql(normalizedEmail, nowMs);
|
|
2948
2974
|
const entry = {
|
|
2949
2975
|
expiresAtMs: nowMs + PERSONAL_SPEND_CACHE_TTL_MS,
|
|
2950
|
-
report
|
|
2976
|
+
report,
|
|
2977
|
+
version
|
|
2951
2978
|
};
|
|
2952
2979
|
cache.set(normalizedEmail, entry);
|
|
2953
2980
|
try {
|
|
@@ -2963,6 +2990,17 @@ function createPersonalSpendReader() {
|
|
|
2963
2990
|
function createPeopleRoutes() {
|
|
2964
2991
|
const app = new Hono();
|
|
2965
2992
|
const readPersonalSpend = createPersonalSpendReader();
|
|
2993
|
+
app.get("/avatars/:identityId", requireViewer, validateRequest("param", avatarParamsSchema, "Invalid route parameters."), async (context) => {
|
|
2994
|
+
const { identityId } = context.req.valid("param");
|
|
2995
|
+
const image = await readAvatarImage(getDb(), getStateAdapter(), identityId);
|
|
2996
|
+
if (!image) throwApiError(404, "Avatar not found.");
|
|
2997
|
+
return new Response(Buffer.from(image.data, "base64"), { headers: {
|
|
2998
|
+
"cache-control": "private, max-age=86400",
|
|
2999
|
+
"content-security-policy": "default-src 'none'; sandbox",
|
|
3000
|
+
"content-type": image.contentType,
|
|
3001
|
+
"x-content-type-options": "nosniff"
|
|
3002
|
+
} });
|
|
3003
|
+
});
|
|
2966
3004
|
app.get("/me/spend", requireViewer, async (context) => {
|
|
2967
3005
|
const viewer = context.get("viewer");
|
|
2968
3006
|
return jsonResponse(personalSpendReportSchema, await readPersonalSpend(viewer.email));
|
|
@@ -3206,233 +3244,6 @@ function createUserPageRoutes() {
|
|
|
3206
3244
|
});
|
|
3207
3245
|
return app;
|
|
3208
3246
|
}
|
|
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
3247
|
// src/chat/automations/editor.ts
|
|
3437
3248
|
/** Read-only editor support. Core owns schedules; plugins own Event choices. */
|
|
3438
3249
|
/**
|
|
@@ -3634,7 +3445,39 @@ function createUserCustomizationRoutes() {
|
|
|
3634
3445
|
return app;
|
|
3635
3446
|
}
|
|
3636
3447
|
// src/api/review-items/routes.ts
|
|
3637
|
-
const
|
|
3448
|
+
const ARCHIVED_LIMIT = 50;
|
|
3449
|
+
const cursorSchema = z.object({
|
|
3450
|
+
conversationId: z.string().min(1).optional(),
|
|
3451
|
+
id: z.string().min(1),
|
|
3452
|
+
query: z.string().min(1).optional(),
|
|
3453
|
+
updatedAtMs: z.number().int(),
|
|
3454
|
+
version: z.literal(1)
|
|
3455
|
+
}).strict();
|
|
3456
|
+
/**
|
|
3457
|
+
* Encode the last open item of a page as the cursor of the next page. The
|
|
3458
|
+
* cursor names its list, so it cannot page through a different list.
|
|
3459
|
+
*/
|
|
3460
|
+
function encodeCursor(item, filters) {
|
|
3461
|
+
return Buffer.from(JSON.stringify({
|
|
3462
|
+
...filters,
|
|
3463
|
+
id: item.id,
|
|
3464
|
+
updatedAtMs: item.updatedAt.getTime(),
|
|
3465
|
+
version: 1
|
|
3466
|
+
}), "utf8").toString("base64url");
|
|
3467
|
+
}
|
|
3468
|
+
/** Decode a cursor of the same list, or return undefined. */
|
|
3469
|
+
function decodeCursor(cursor, filters) {
|
|
3470
|
+
try {
|
|
3471
|
+
const parsed = cursorSchema.parse(JSON.parse(Buffer.from(cursor, "base64url").toString("utf8")));
|
|
3472
|
+
if (parsed.conversationId !== filters.conversationId || parsed.query !== filters.query) return;
|
|
3473
|
+
return {
|
|
3474
|
+
id: parsed.id,
|
|
3475
|
+
updatedAt: new Date(parsed.updatedAtMs)
|
|
3476
|
+
};
|
|
3477
|
+
} catch {
|
|
3478
|
+
return;
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3638
3481
|
const ERROR_STATUS = {
|
|
3639
3482
|
conflict: 409,
|
|
3640
3483
|
forbidden: 403,
|
|
@@ -3677,26 +3520,40 @@ function createReviewItemRoutes(services) {
|
|
|
3677
3520
|
app.get("/", requireViewer, validateRequest("query", reviewItemListQuerySchema, "Invalid review item query."), async (context) => {
|
|
3678
3521
|
const viewer = context.get("viewer");
|
|
3679
3522
|
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,
|
|
3523
|
+
const filters = {
|
|
3685
3524
|
...query.conversationId ? { conversationId: query.conversationId } : void 0,
|
|
3686
3525
|
...query.q ? { query: query.q } : void 0
|
|
3526
|
+
};
|
|
3527
|
+
const after = query.cursor ? decodeCursor(query.cursor, filters) : void 0;
|
|
3528
|
+
if (query.cursor && !after) return jsonResponse(apiErrorSchema, { error: "Invalid review item cursor." }, { status: 400 });
|
|
3529
|
+
const db = getDb();
|
|
3530
|
+
const reader = reviewItemReaderForUser(viewer);
|
|
3531
|
+
const open = await searchReviewItems(db, reader, {
|
|
3532
|
+
...filters,
|
|
3533
|
+
limit: query.limit + 1,
|
|
3534
|
+
statuses: ["open"],
|
|
3535
|
+
...after ? { after } : void 0
|
|
3536
|
+
});
|
|
3537
|
+
const page = open.slice(0, query.limit);
|
|
3538
|
+
const last = page.at(-1);
|
|
3539
|
+
const archived = filters.query && !after ? await searchReviewItems(db, reader, {
|
|
3540
|
+
...filters,
|
|
3541
|
+
limit: 51,
|
|
3542
|
+
statuses: ["done", "dismissed"]
|
|
3543
|
+
}) : [];
|
|
3544
|
+
return jsonResponse(reviewItemListSchema, {
|
|
3545
|
+
items: [...page, ...archived.slice(0, ARCHIVED_LIMIT)].map((item) => reviewItemPayload(item, viewer)),
|
|
3546
|
+
...archived.length > ARCHIVED_LIMIT ? { moreArchived: true } : void 0,
|
|
3547
|
+
...open.length > query.limit && last ? { nextCursor: encodeCursor(last, filters) } : void 0
|
|
3687
3548
|
});
|
|
3688
|
-
return jsonResponse(reviewItemListSchema, { items: items.map((item) => reviewItemPayload(item, viewer)) });
|
|
3689
3549
|
});
|
|
3690
3550
|
app.get("/count", requireViewer, async (context) => {
|
|
3691
3551
|
const viewer = context.get("viewer");
|
|
3692
|
-
return jsonResponse(reviewItemCountSchema, {
|
|
3693
|
-
assignee: { userId: viewer.id },
|
|
3694
|
-
statuses: ["open"]
|
|
3695
|
-
}) });
|
|
3552
|
+
return jsonResponse(reviewItemCountSchema, { needsViewer: await countReviewItemsNeedingUser(getDb(), viewer.id) });
|
|
3696
3553
|
});
|
|
3697
3554
|
app.get("/waiting-conversations", requireViewer, async (context) => {
|
|
3698
3555
|
const viewer = context.get("viewer");
|
|
3699
|
-
return jsonResponse(reviewItemWaitingConversationsSchema, { conversationIds: await listWaitingConversationIds(getDb(), viewer) });
|
|
3556
|
+
return jsonResponse(reviewItemWaitingConversationsSchema, { conversationIds: await listWaitingConversationIds(getDb(), viewer.id) });
|
|
3700
3557
|
});
|
|
3701
3558
|
app.get("/:id", requireViewer, validateRequest("param", reviewItemParamsSchema, "Invalid review item."), async (context) => {
|
|
3702
3559
|
const viewer = context.get("viewer");
|
|
@@ -3714,9 +3571,8 @@ function createReviewItemRoutes(services) {
|
|
|
3714
3571
|
try {
|
|
3715
3572
|
const item = await actOnReviewItem({
|
|
3716
3573
|
action: body.action,
|
|
3717
|
-
|
|
3574
|
+
delivery: services.delivery,
|
|
3718
3575
|
id,
|
|
3719
|
-
queue: services.queue,
|
|
3720
3576
|
user: viewer,
|
|
3721
3577
|
...body.action === "submit" ? { answer: {
|
|
3722
3578
|
...body.answer,
|
|
@@ -3854,7 +3710,7 @@ function readDescriptionText(home) {
|
|
|
3854
3710
|
}
|
|
3855
3711
|
/** Read discovered skill names for authenticated runtime diagnostics. */
|
|
3856
3712
|
async function readSkillReports() {
|
|
3857
|
-
const { discoverSkills } = await import("./skills-
|
|
3713
|
+
const { discoverSkills } = await import("./skills-DmJJIuLF.js").then((n) => n.o);
|
|
3858
3714
|
const skills = await discoverSkills();
|
|
3859
3715
|
return skillReportsSchema.parse(skills.map((skill) => ({
|
|
3860
3716
|
name: skill.name,
|
|
@@ -3863,7 +3719,7 @@ async function readSkillReports() {
|
|
|
3863
3719
|
}
|
|
3864
3720
|
/** Read safe configured plugin metadata for authenticated runtime diagnostics. */
|
|
3865
3721
|
async function readPlugins() {
|
|
3866
|
-
const { pluginCatalogRuntime } = await import("./catalog-runtime-
|
|
3722
|
+
const { pluginCatalogRuntime } = await import("./catalog-runtime-BsoSmTM0.js").then((n) => n.t);
|
|
3867
3723
|
return pluginsSchema.parse(pluginCatalogRuntime.getProviders().map((plugin) => ({
|
|
3868
3724
|
configKeys: plugin.manifest.configKeys ?? [],
|
|
3869
3725
|
description: plugin.manifest.description,
|
|
@@ -3875,7 +3731,7 @@ async function readPlugins() {
|
|
|
3875
3731
|
async function readRuntimeInfoReport() {
|
|
3876
3732
|
const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
|
|
3877
3733
|
import("./package-discovery-DJBompdd.js").then((n) => n.r),
|
|
3878
|
-
import("./catalog-runtime-
|
|
3734
|
+
import("./catalog-runtime-BsoSmTM0.js").then((n) => n.t),
|
|
3879
3735
|
readPlugins(),
|
|
3880
3736
|
readSkillReports()
|
|
3881
3737
|
]);
|
|
@@ -3892,7 +3748,7 @@ async function readRuntimeInfoReport() {
|
|
|
3892
3748
|
/** Read sanitized operational summaries contributed by plugins. */
|
|
3893
3749
|
async function readPluginOperationalReportFeed() {
|
|
3894
3750
|
const nowMs = Date.now();
|
|
3895
|
-
const { getPluginOperationalReports } = await import("./credentialed-
|
|
3751
|
+
const { getPluginOperationalReports } = await import("./credentialed-BU-OW7HP.js").then((n) => n.a);
|
|
3896
3752
|
return pluginOperationalReportFeedSchema.parse({
|
|
3897
3753
|
source: "plugins",
|
|
3898
3754
|
generatedAt: new Date(nowMs).toISOString(),
|
|
@@ -3914,7 +3770,10 @@ function createJuniorApi(options = {}) {
|
|
|
3914
3770
|
attachmentStorage: getAttachmentStorage(),
|
|
3915
3771
|
queue
|
|
3916
3772
|
}));
|
|
3917
|
-
app.route("/api/review-items", createReviewItemRoutes({
|
|
3773
|
+
app.route("/api/review-items", createReviewItemRoutes({ delivery: {
|
|
3774
|
+
queue,
|
|
3775
|
+
show: createSlackReviewItemShow(getProductionSlackAdapter)
|
|
3776
|
+
} }));
|
|
3918
3777
|
app.route("/api/code", createCodeRoutes());
|
|
3919
3778
|
app.route("/api/connections", createConnectionRoutes());
|
|
3920
3779
|
app.route("/api/personal-tokens", createPersonalTokenRoutes());
|
|
@@ -3936,4 +3795,4 @@ function createJuniorApi(options = {}) {
|
|
|
3936
3795
|
});
|
|
3937
3796
|
return app;
|
|
3938
3797
|
}
|
|
3939
|
-
export { authenticatePersonalToken, createJuniorApi, isAllowedSignInEmail, jsonResponse, resolveViewerUser, updateViewerDisplayName };
|
|
3798
|
+
export { authenticatePersonalToken, createJuniorApi, isAllowedSignInEmail, jsonResponse, readViewerAvatarUrl, resolveViewerUser, updateViewerDisplayName };
|
|
@@ -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-BzOCzVb1.js";
|
|
3
|
+
import "./schema-jK4-1u_H.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,6 +8,7 @@ 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";
|
|
@@ -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-BrMMzjYm.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 };
|