@sentry/junior 0.260.0 → 0.262.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.
Files changed (67) hide show
  1. package/dist/{adapter-Dj5BTJRd.js → adapter-t-Y9RHML.js} +2 -2
  2. package/dist/{admin-tzkZDqrH.js → admin-BCqeFndQ.js} +1 -1
  3. package/dist/{agent-hooks-V4Hfc2tB.js → agent-hooks-9q2zdKHL.js} +73 -20
  4. package/dist/{agent-invocations-Qfz7dWgU.js → agent-invocations-CxKldAeB.js} +1 -0
  5. package/dist/{agent-runner-DvTUyGTY.js → agent-runner-Cx6NO5LE.js} +115 -37
  6. package/dist/api/schema.js +1 -1
  7. package/dist/api.js +42 -41
  8. package/dist/{app-BsBUs3rF.d.ts → app-Bo0kB987.d.ts} +6 -1
  9. package/dist/app.d.ts +1 -1
  10. package/dist/app.js +59 -63
  11. package/dist/{assistant-reply-CEOMzsWy.js → assistant-reply-B2qUBAwL.js} +1 -1
  12. package/dist/{briefs-BSCkyYqs.js → briefs-DsGH2Vym.js} +2 -2
  13. package/dist/{catalog-runtime-Bpcs2b2L.js → catalog-runtime-CfwKT0sn.js} +1 -1
  14. package/dist/cli/chat.js +15 -17
  15. package/dist/cli/check.js +3 -3
  16. package/dist/cli/init.js +1 -1
  17. package/dist/cli/main.js +3 -3
  18. package/dist/cli/plugins.js +4 -4
  19. package/dist/cli/snapshot-create.js +4 -4
  20. package/dist/cli/upgrade.js +3 -3
  21. package/dist/{client-JeyzRwsT.js → client-DpfjZgNk.js} +2 -2
  22. package/dist/{config-ULs6Zl9b.js → config-BiCtNiu5.js} +2 -2
  23. package/dist/{connections-CZ7HhEmN.js → connections-D9IKbfk-.js} +10 -10
  24. package/dist/{conversation-privacy-BQSlZXgV.js → conversation-privacy-CBUI0frD.js} +1 -1
  25. package/dist/{credential-sync-BKcv5rBe.js → credential-sync-Bu6ZOuOk.js} +14 -14
  26. package/dist/{executor-BoGNVEDn.js → executor-O8xqLDN6.js} +4 -3
  27. package/dist/{images-BBmDXQCB.js → images-AM1exvU0.js} +2 -2
  28. package/dist/instrumentation.js +2 -2
  29. package/dist/{job-queue-CbdVyaCo.js → job-queue-DmarAQGI.js} +1 -1
  30. package/dist/{logging-DSMmkHXG.js → logging-dZN1Bvtu.js} +1 -1
  31. package/dist/{message-zaj5gBbS.js → message-C_g2S8kv.js} +3 -3
  32. package/dist/nitro.d.ts +1 -1
  33. package/dist/nitro.js +3 -3
  34. package/dist/{oauth-callback-server-yYFG8Own.js → oauth-callback-server-DvvOvr4q.js} +2 -2
  35. package/dist/{profile-ByWkAY7L.js → profile-BP2N5uDY.js} +13 -6
  36. package/dist/{registry-BL-osYWN.js → registry-BUje_knT.js} +1 -1
  37. package/dist/{resolve-HuPG2VMB.js → resolve-DftZiYNU.js} +4 -4
  38. package/dist/{result-DS7V4a3-.js → result-CRMRT9CE.js} +16 -11
  39. package/dist/{runner-Cba_OfGl.js → runner-4mmL2Pt1.js} +10 -10
  40. package/dist/{sandbox-egress-signals-C7NcPzea.js → sandbox-egress-signals-1ysv0z5A.js} +1 -1
  41. package/dist/{schema-OzL8Zw4H.js → schema-XuTZukI9.js} +1 -1
  42. package/dist/{service-account-DqwHhwJA.js → service-account-B1sH3P7d.js} +3 -3
  43. package/dist/{service-account-Ko1Xs--F.js → service-account-Del2I_x3.js} +3 -3
  44. package/dist/{session-stop-HfKx-pky.js → session-stop-ZuyOHxdK.js} +11 -11
  45. package/dist/{skills-D6_bcAuW.js → skills-lPeepA2b.js} +2 -2
  46. package/dist/{spawn-BWqK6EwM.js → spawn-DovpdlrW.js} +3 -2
  47. package/dist/{store-DzRbd5VT.js → store-dZynGGFW.js} +6 -6
  48. package/dist/{task-queue-9LICOzcL.js → task-queue-CmMCtzHO.js} +3 -3
  49. package/dist/{task-runner-DGnd_B5X.js → task-runner-BRgJ5e0s.js} +19 -11
  50. package/dist/{tasks-CjrS098O.js → tasks-Bh2qYaed.js} +45 -28
  51. package/dist/{thread-state-CqkYowEz.js → thread-state-DA37FsAT.js} +5 -5
  52. package/dist/{turn-failure-response-BkKmGqFt.js → turn-failure-response-BLcscQ-f.js} +7 -7
  53. package/dist/{turn-lifecycle-DYv8IV6w.js → turn-lifecycle-D0e887FM.js} +1 -1
  54. package/dist/{turn-session-routing-TaVhKmdz.js → turn-session-routing-DdbSbJS6.js} +1 -1
  55. package/dist/{validation-BrXMYPyo.js → validation-DtcovXqq.js} +1 -1
  56. package/dist/{version-Ct049vav.js → version-JcDaJ75p.js} +1 -1
  57. package/dist/version.js +1 -1
  58. package/dist/{viewer-C-J0ewlH.js → viewer-oMTUVAcR.js} +4 -4
  59. package/dist/{web-input-C_xB3RXp.js → web-input-FQ5wgqYn.js} +26 -26
  60. package/dist/{work-D829Ue7k.js → work-BiIKfayl.js} +40 -10
  61. package/dist/{worker-BRTYzlpk.js → worker-BZ7l75NM.js} +5 -5
  62. package/migrations/0062_plugin_report_index.sql +20 -0
  63. package/migrations/0063_agent_invocation_type.sql +1 -0
  64. package/migrations/meta/0062_snapshot.json +3499 -0
  65. package/migrations/meta/0063_snapshot.json +3505 -0
  66. package/migrations/meta/_journal.json +14 -0
  67. package/package.json +10 -10
package/dist/api.js CHANGED
@@ -1,30 +1,30 @@
1
- import { D as AutomationConflictError, E as sameDefinitionValue, L as loadTurnProjection, O as automationRevision, S as automationDefinition, T as readAutomationVersion, a as saveScheduledAutomation, bn as createUserTokenStore, k as requireAutomationRevision, rr as piMessageFromHistoryItem, v as saveEventAutomation, y as setEventAutomationStatus } from "./tasks-CjrS098O.js";
2
- import { p as escapeXml } from "./client-JeyzRwsT.js";
3
- import { f as logException, m as logWarn, p as logInfo } from "./logging-DSMmkHXG.js";
1
+ import { D as AutomationConflictError, E as sameDefinitionValue, L as loadTurnProjection, O as automationRevision, S as automationDefinition, T as readAutomationVersion, a as saveScheduledAutomation, k as requireAutomationRevision, nr as piMessageFromHistoryItem, v as saveEventAutomation, y as setEventAutomationStatus, yn as createUserTokenStore } from "./tasks-Bh2qYaed.js";
2
+ import { p as escapeXml } from "./client-DpfjZgNk.js";
3
+ import { f as logException, m as logWarn, p as logInfo } from "./logging-dZN1Bvtu.js";
4
4
  import { d as parseSlackTeamId, g as parseSlackMessageTs, l as parseSlackChannelId } from "./actor-tlxzqaRe.js";
5
- import { C as addAgentTurnUsage, D as hasAgentTurnUsage, E as agentTurnUsageSchema, O as resolveRootConversationId, S as parseSessionSource, c as getConversationEventStore, d as getDb, f as getSqlExecutor, h as loadConversationSlackTenantIds, i as resolveViewerUser, m as withConversationEventLock, o as updateViewerDisplayName, t as findUserByEmail, u as getConversationStore, v as locationFromRow } from "./viewer-C-J0ewlH.js";
6
- import { c as juniorIdentities, d as juniorDestinations, l as juniorUsers, o as conversationReadColumns, s as juniorConversations } from "./agent-invocations-Qfz7dWgU.js";
7
- import { f as juniorConversationBriefs, g as juniorApiTokens, h as juniorConversationEvents, m as juniorConversationMetrics, u as juniorConversationParticipants, v as juniorCodeChanges, y as juniorCodeRepositories } from "./executor-BoGNVEDn.js";
5
+ import { C as addAgentTurnUsage, D as hasAgentTurnUsage, E as agentTurnUsageSchema, O as resolveRootConversationId, S as parseSessionSource, c as getConversationEventStore, d as getDb, f as getSqlExecutor, h as loadConversationSlackTenantIds, i as resolveViewerUser, m as withConversationEventLock, o as updateViewerDisplayName, t as findUserByEmail, u as getConversationStore, v as locationFromRow } from "./viewer-oMTUVAcR.js";
6
+ import { c as juniorIdentities, d as juniorDestinations, l as juniorUsers, o as conversationReadColumns, s as juniorConversations } from "./agent-invocations-CxKldAeB.js";
7
+ import { f as juniorConversationBriefs, g as juniorApiTokens, h as juniorConversationEvents, m as juniorConversationMetrics, u as juniorConversationParticipants, v as juniorCodeChanges, y as juniorCodeRepositories } from "./executor-O8xqLDN6.js";
8
8
  import { d as contextProvenance } from "./history-AY8rs-FR.js";
9
- import { n as pluginCatalogRuntime } from "./catalog-runtime-Bpcs2b2L.js";
10
- import { F as AutomationEditError, I as eventAutomationTriggerAvailable, P as editEventAutomation, R as resolveTaskOutcomes, S as readLiveAttachment, T as parseSlackThreadId, U as listChildAgents, _t as conversationSubtreeColumns, gt as conversationSubtree, j as editScheduledAutomation, m as readStats, rt as getChildAgentLabel } from "./agent-runner-DvTUyGTY.js";
11
- import { At as conversationHasParticipantUser, C as WorkspaceValidationError, Dt as conversationArchivedForEmail, Et as conversationArchiveTimes, Ft as readLatestConversationBrief, Gt as listConversationAnnotations, It as readConversationEventPage, Kt as listConversationAnnotationsById, Lt as buildSentryConversationUrl, M as workspaceRepoCheckoutPath, Mt as conversationNotArchivedForUser, Nt as viewerConversationMembership, O as SANDBOX_RUNTIME, Ot as conversationArchivedForUser, S as updateWorkspace, Tt as readConversationAccessFromSql, Yt as lookupSlackUser, _ as deleteWorkspace, b as listWorkspaces, ct as getSlackClient, g as createWorkspace, jt as conversationNotArchivedForEmail, kt as conversationHasParticipantEmail, pt as withSlackRetries, u as getPlugins, v as getWorkspace, wt as createPluginLogger, x as listWorkspacesByRepository } from "./agent-hooks-V4Hfc2tB.js";
9
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-CfwKT0sn.js";
10
+ import { F as AutomationEditError, I as eventAutomationTriggerAvailable, P as editEventAutomation, R as resolveTaskOutcomes, S as readLiveAttachment, T as parseSlackThreadId, U as listChildAgents, bt as conversationSubtreeColumns, it as getChildAgentLabel, j as editScheduledAutomation, m as readStats, yt as conversationSubtree } from "./agent-runner-Cx6NO5LE.js";
11
+ import { At as conversationIsMemberRoot, C as WorkspaceValidationError, Dt as conversationArchivedForEmail, Et as conversationArchiveTimes, Ft as readLatestConversationBrief, Gt as listConversationAnnotations, It as readConversationEventPage, Kt as listConversationAnnotationsById, Lt as buildSentryConversationUrl, M as workspaceRepoCheckoutPath, Mt as conversationNotArchivedForUser, Nt as viewerConversationMembership, O as SANDBOX_RUNTIME, Ot as conversationArchivedForUser, S as updateWorkspace, Tt as readConversationAccessFromSql, Xt as createPluginCache, Yt as lookupSlackUser, _ as deleteWorkspace, b as listWorkspaces, ct as getSlackClient, g as createWorkspace, jt as conversationNotArchivedForEmail, kt as conversationHasParticipantUser, pt as withSlackRetries, u as getPlugins, v as getWorkspace, wt as createPluginLogger, x as listWorkspacesByRepository } from "./agent-hooks-9q2zdKHL.js";
12
12
  import { t as getFirstRunAtMs } from "./cadence-R7Em4RjE.js";
13
13
  import { A as forkConversationResponseSchema, B as readMessageAttachments, D as createConversationBodySchema, O as createConversationMessageBodySchema, V as INPUT_IMAGE_TYPES, _ as conversationParamsSchema, a as cancelConversationPendingMessagesBodySchema, c as conversationAttachmentParamsSchema, d as conversationDetailReportSchema, g as conversationFeedSchema, h as conversationFeedQuerySchema, i as archiveConversationResponseSchema, k as forkConversationBodySchema, m as conversationEventsQuerySchema, o as cancelConversationPendingMessagesResponseSchema, p as conversationEventPageSchema, r as archiveConversationBodySchema, t as acceptedConversationMessageSchema, u as conversationDetailQuerySchema, x as conversationPendingMessagesReportSchema } from "./conversation-CvuKJ3tA.js";
14
- import { n as hash, t as create } from "./profile-ByWkAY7L.js";
15
- import { d as getEventCatalog, x as automationEventCatalog } from "./session-stop-HfKx-pky.js";
16
- import { d as getSandboxResources, t as getCachedSnapshot } from "./resolve-HuPG2VMB.js";
17
- import { a as getVercelConversationWorkQueue } from "./job-queue-CbdVyaCo.js";
18
- import { a as cancelHumanFacingPendingMessages, h as getConversation } from "./store-DzRbd5VT.js";
19
- import { n as finishServiceAccountSignIn, o as serviceAccountPlugins, r as getServiceAccountStatus, s as startServiceAccountSignIn, t as disconnectServiceAccount } from "./service-account-Ko1Xs--F.js";
14
+ import { n as hash, t as create } from "./profile-BP2N5uDY.js";
15
+ import { d as getEventCatalog, x as automationEventCatalog } from "./session-stop-ZuyOHxdK.js";
16
+ import { d as getSandboxResources, t as getCachedSnapshot } from "./resolve-DftZiYNU.js";
17
+ import { a as getVercelConversationWorkQueue } from "./job-queue-DmarAQGI.js";
18
+ import { a as cancelHumanFacingPendingMessages, h as getConversation } from "./store-dZynGGFW.js";
19
+ import { n as finishServiceAccountSignIn, o as serviceAccountPlugins, r as getServiceAccountStatus, s as startServiceAccountSignIn, t as disconnectServiceAccount } from "./service-account-Del2I_x3.js";
20
20
  import { M as compileScheduleIntent, P as weekdaySchema, _ as automationSummarySchema, b as automationVersionListSchema, c as automationLifecycleSchema, d as automationParamsSchema, f as automationRunListSchema, g as automationSchedulePreviewSchema, h as automationScheduleIntentSchema, i as automationExecutionListSchema, j as ScheduleIntentError, 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-DrpcA-SX.js";
21
21
  import { C as skillReportsSchema, a as fillUtcHours, b as pluginsSchema, c as sumUtcHoursIntoSixHours, d as trailingUtcSixHourWindow, f as utcDayKey, h as pluginOperationalReportFeedSchema, i as fillUtcDays, l as trailingUtcDayWindow, m as healthReportSchema, n as DAY_MS$1, o as fillUtcSixHours, p as utcHourKey, r as HOUR_MS$1, s as startOfUtcHour, u as trailingUtcHourWindow, x as runtimeInfoReportSchema } from "./web-message-id-CJSUiksE.js";
22
- import { B as readHealthReport, I as createVercelAttachmentStorage, _ as readViewerAutomationRuns, a as recordWebConversationActivity, b as readViewerAutomations, d as resolveSlackConversationContextFromThreadId, g as readViewerAutomationExecutions, h as readConversationSourceTask, i as createConversationId, k as stopConversationTurn, l as getProductionSlackAdapter, m as deleteViewerTask, o as webActorFromEmail, p as ViewerTaskNotFoundError, r as createAndEnqueueConversation, t as appendAndEnqueueWebMessage, u as formatSlackConversationRedactedLabel, v as readViewerAutomationSummary, w as clearSlackPendingReactions, x as resolveViewerTaskCandidate, y as readViewerAutomationVersions } from "./web-input-C_xB3RXp.js";
23
- import { F as conversationAggregateColumns, I as conversationRangeColumns, M as readAutomationTitlesByConversationId, P as conversationActiveDaysColumn } from "./task-runner-DGnd_B5X.js";
24
- import { d as legacyWebMailboxMetadataSchema } from "./result-DS7V4a3-.js";
25
- import { a as startConnection, l as getWebAuthorization, n as isConnectableProvider, r as listConnections, t as disconnectConnection, u as htmlCallbackResponse } from "./connections-CZ7HhEmN.js";
26
- import { t as decodeInputImages } from "./images-BBmDXQCB.js";
27
- import { A as activityHours$1, C as personParamsSchema, D as locationDirectoryReportSchema, E as locationDetailReportSchema, H as codePersonReportSchema, I as disconnectConnectionResponseSchema, J as stopConversationTurnResponseSchema, L as startConnectionResponseSchema, N as connectionListSchema, O as locationParamsSchema, P as connectionParamsSchema, S as actorProfileReportSchema, U as codeRepositoryParamsSchema, V as codeOverviewReportSchema, W as codeRepositoryReportSchema, X as apiErrorSchema, Y as conversationStatsReportSchema, _ as personalTokenListSchema, a as workspaceBodySchema, b as revokePersonalTokenResponseSchema, d as serviceAccountListSchema, f as serviceAccountParamsSchema, g as createdPersonalTokenSchema, h as createPersonalTokenBodySchema, i as deleteWorkspaceResponseSchema, j as activitySixHours$1, k as activityDays$1, l as workspaceSchema, m as startServiceAccountSignInResponseSchema, n as statsReportSchema, o as workspaceListSchema, q as conversationChildAgentsReportSchema, s as workspaceParamsSchema, u as disconnectServiceAccountResponseSchema, w as personalSpendReportSchema, x as actorDirectoryReportSchema, y as personalTokenParamsSchema } from "./schema-OzL8Zw4H.js";
22
+ import { B as readHealthReport, I as createVercelAttachmentStorage, _ as readViewerAutomationRuns, a as recordWebConversationActivity, b as readViewerAutomations, d as resolveSlackConversationContextFromThreadId, g as readViewerAutomationExecutions, h as readConversationSourceTask, i as createConversationId, k as stopConversationTurn, l as getProductionSlackAdapter, m as deleteViewerTask, o as webActorFromEmail, p as ViewerTaskNotFoundError, r as createAndEnqueueConversation, t as appendAndEnqueueWebMessage, u as formatSlackConversationRedactedLabel, v as readViewerAutomationSummary, w as clearSlackPendingReactions, x as resolveViewerTaskCandidate, y as readViewerAutomationVersions } from "./web-input-FQ5wgqYn.js";
23
+ import { F as conversationAggregateColumns, I as conversationRangeColumns, M as readAutomationTitlesByConversationId, P as conversationActiveDaysColumn } from "./task-runner-BRgJ5e0s.js";
24
+ import { d as legacyWebMailboxMetadataSchema } from "./result-CRMRT9CE.js";
25
+ import { a as startConnection, l as getWebAuthorization, n as isConnectableProvider, r as listConnections, t as disconnectConnection, u as htmlCallbackResponse } from "./connections-D9IKbfk-.js";
26
+ import { t as decodeInputImages } from "./images-AM1exvU0.js";
27
+ import { A as activityHours$1, C as personParamsSchema, D as locationDirectoryReportSchema, E as locationDetailReportSchema, H as codePersonReportSchema, I as disconnectConnectionResponseSchema, J as stopConversationTurnResponseSchema, L as startConnectionResponseSchema, N as connectionListSchema, O as locationParamsSchema, P as connectionParamsSchema, S as actorProfileReportSchema, U as codeRepositoryParamsSchema, V as codeOverviewReportSchema, W as codeRepositoryReportSchema, X as apiErrorSchema, Y as conversationStatsReportSchema, _ as personalTokenListSchema, a as workspaceBodySchema, b as revokePersonalTokenResponseSchema, d as serviceAccountListSchema, f as serviceAccountParamsSchema, g as createdPersonalTokenSchema, h as createPersonalTokenBodySchema, i as deleteWorkspaceResponseSchema, j as activitySixHours$1, k as activityDays$1, l as workspaceSchema, m as startServiceAccountSignInResponseSchema, n as statsReportSchema, o as workspaceListSchema, q as conversationChildAgentsReportSchema, s as workspaceParamsSchema, u as disconnectServiceAccountResponseSchema, w as personalSpendReportSchema, x as actorDirectoryReportSchema, y as personalTokenParamsSchema } from "./schema-XuTZukI9.js";
28
28
  import { Hono } from "hono";
29
29
  import path from "node:path";
30
30
  import { z } from "zod";
@@ -629,7 +629,8 @@ async function listConversationSidebarAnnotations(conversationIds, annotationsBy
629
629
  conversationIds,
630
630
  db: getDb(),
631
631
  log: createPluginLogger(plugin.manifest.name),
632
- plugin: { name: plugin.manifest.name }
632
+ plugin: { name: plugin.manifest.name },
633
+ cache: createPluginCache(plugin.manifest.name)
633
634
  });
634
635
  for (const [conversationId, annotations] of Object.entries(result.annotationsByConversationId)) {
635
636
  if (!candidates.has(conversationId)) continue;
@@ -1199,7 +1200,8 @@ async function listConversationWork(conversationIds) {
1199
1200
  conversationIds,
1200
1201
  db: getDb(),
1201
1202
  log: createPluginLogger(plugin.manifest.name),
1202
- plugin: { name: plugin.manifest.name }
1203
+ plugin: { name: plugin.manifest.name },
1204
+ cache: createPluginCache(plugin.manifest.name)
1203
1205
  });
1204
1206
  for (const conversationId of result.conversationIds) {
1205
1207
  if (!candidates.has(conversationId)) continue;
@@ -1346,14 +1348,8 @@ async function readConversationParticipants(db, conversationIds) {
1346
1348
  const CONVERSATION_FEED_LIMIT = 50;
1347
1349
  function conversationFeedMembershipFilter(status, filter) {
1348
1350
  if (!filter) return status === "archived" ? sql`false` : void 0;
1349
- if (filter.kind === "viewer") return and(viewerConversationMembership({
1350
- actorMatch: eq(juniorIdentities.userId, filter.userId),
1351
- participantMatch: conversationHasParticipantUser(filter.userId)
1352
- }), status === "archived" ? conversationArchivedForUser(filter.userId) : status === "all" ? void 0 : conversationNotArchivedForUser(filter.userId));
1353
- return and(viewerConversationMembership({
1354
- actorMatch: eq(juniorUsers.primaryEmailNormalized, filter.email),
1355
- participantMatch: conversationHasParticipantEmail(filter.email)
1356
- }), status === "archived" ? conversationArchivedForEmail(filter.email) : status === "all" ? void 0 : conversationNotArchivedForEmail(filter.email));
1351
+ if (filter.kind === "viewer") return and(conversationIsMemberRoot({ userId: filter.userId }), status === "archived" ? conversationArchivedForUser(filter.userId) : status === "all" ? void 0 : conversationNotArchivedForUser(filter.userId));
1352
+ return and(conversationIsMemberRoot({ email: filter.email }), status === "archived" ? conversationArchivedForEmail(filter.email) : status === "all" ? void 0 : conversationNotArchivedForEmail(filter.email));
1357
1353
  }
1358
1354
  /**
1359
1355
  * Keep root conversations linked to one code repository. A code change can
@@ -2022,6 +2018,8 @@ function statsWindow(nowMs) {
2022
2018
  };
2023
2019
  }
2024
2020
  const HOUR_MS = 36e5;
2021
+ /** Keep 7d of hours so clients can roll 7d charts into 6h buckets. */
2022
+ const WINDOW_HOURS = 168;
2025
2023
  function applyMetricBuckets(rows, metrics) {
2026
2024
  const byDate = new Map(rows.map((row) => [row.date, {
2027
2025
  ...row,
@@ -2172,6 +2170,7 @@ function guardianStats(dayRows, hourRows, endMs) {
2172
2170
  }
2173
2171
  async function aggregateStats(db, start, end) {
2174
2172
  const where = statsWhere(start, end);
2173
+ const hourStart = trailingUtcHourWindow(end.getTime(), WINDOW_HOURS).start;
2175
2174
  const activityDate = sql`TO_CHAR(
2176
2175
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
2177
2176
  'YYYY-MM-DD'
@@ -2207,7 +2206,7 @@ async function aggregateStats(db, start, end) {
2207
2206
  db.select({
2208
2207
  conversations: treeAggregateColumns$1.conversations,
2209
2208
  date: activityHour
2210
- }).from(juniorConversations).innerJoin(treeConversation$1, eq(treeConversation$1.rootConversationId, juniorConversations.conversationId)).where(where).groupBy(activityHour),
2209
+ }).from(juniorConversations).innerJoin(treeConversation$1, eq(treeConversation$1.rootConversationId, juniorConversations.conversationId)).where(statsWhere(hourStart, end)).groupBy(activityHour),
2211
2210
  readConversationMetricBuckets(db, {
2212
2211
  bucket: "day",
2213
2212
  start,
@@ -2215,7 +2214,7 @@ async function aggregateStats(db, start, end) {
2215
2214
  }),
2216
2215
  readConversationMetricBuckets(db, {
2217
2216
  bucket: "hour",
2218
- start,
2217
+ start: hourStart,
2219
2218
  end
2220
2219
  })
2221
2220
  ]);
@@ -2228,6 +2227,7 @@ async function aggregateStats(db, start, end) {
2228
2227
  };
2229
2228
  }
2230
2229
  async function aggregateGuardianStats(db, start, end) {
2230
+ const hourStart = trailingUtcHourWindow(end.getTime(), WINDOW_HOURS).start;
2231
2231
  const day = sql`TO_CHAR(
2232
2232
  ${juniorConversationEvents.createdAt} AT TIME ZONE 'UTC',
2233
2233
  'YYYY-MM-DD'
@@ -2249,14 +2249,14 @@ async function aggregateGuardianStats(db, start, end) {
2249
2249
  deny: sql`COUNT(*) FILTER (WHERE ${decision} = 'deny')::integer`,
2250
2250
  requests: sql`COUNT(*)::integer`
2251
2251
  };
2252
- const where = and(eq(juniorConversationEvents.type, "guardian_action_reviewed"), gte(juniorConversationEvents.createdAt, start), lte(juniorConversationEvents.createdAt, end));
2252
+ const where = (windowStart) => and(eq(juniorConversationEvents.type, "guardian_action_reviewed"), gte(juniorConversationEvents.createdAt, windowStart), lte(juniorConversationEvents.createdAt, end));
2253
2253
  const [dayRows, hourRows] = await Promise.all([db.select({
2254
2254
  ...selectColumns,
2255
2255
  date: day
2256
- }).from(juniorConversationEvents).where(where).groupBy(day), db.select({
2256
+ }).from(juniorConversationEvents).where(where(start)).groupBy(day), db.select({
2257
2257
  ...selectColumns,
2258
2258
  date: hour
2259
- }).from(juniorConversationEvents).where(where).groupBy(hour)]);
2259
+ }).from(juniorConversationEvents).where(where(hourStart)).groupBy(hour)]);
2260
2260
  return {
2261
2261
  dayRows,
2262
2262
  hourRows
@@ -3710,7 +3710,7 @@ async function readPeoplePluginReports(args) {
3710
3710
  reports: [],
3711
3711
  source: "plugins"
3712
3712
  });
3713
- const { getPluginProfileReports } = await import("./agent-hooks-V4Hfc2tB.js").then((n) => n.t);
3713
+ const { getPluginProfileReports } = await import("./agent-hooks-9q2zdKHL.js").then((n) => n.t);
3714
3714
  return pluginOperationalReportFeedSchema.parse({
3715
3715
  generatedAt: new Date(nowMs).toISOString(),
3716
3716
  reports: await getPluginProfileReports({
@@ -4186,6 +4186,7 @@ async function readPluginUserPage(input) {
4186
4186
  db: getDb(),
4187
4187
  log: createPluginLogger(plugin.manifest.name),
4188
4188
  plugin: { name: plugin.manifest.name },
4189
+ cache: createPluginCache(plugin.manifest.name),
4189
4190
  viewer
4190
4191
  }, input.query));
4191
4192
  if (content.records.some((record) => record.actions?.some((action) => !actionBelongsToPlugin(action.href, plugin.manifest.name)))) throw new Error(`Plugin user page "${plugin.manifest.name}/${page.id}" returned an action outside its API namespace.`);
@@ -4741,7 +4742,7 @@ function readDescriptionText(home) {
4741
4742
  }
4742
4743
  /** Read discovered skill names for authenticated runtime diagnostics. */
4743
4744
  async function readSkillReports() {
4744
- const { discoverSkills } = await import("./skills-D6_bcAuW.js").then((n) => n.o);
4745
+ const { discoverSkills } = await import("./skills-lPeepA2b.js").then((n) => n.o);
4745
4746
  const skills = await discoverSkills();
4746
4747
  return skillReportsSchema.parse(skills.map((skill) => ({
4747
4748
  name: skill.name,
@@ -4750,7 +4751,7 @@ async function readSkillReports() {
4750
4751
  }
4751
4752
  /** Read safe configured plugin metadata for authenticated runtime diagnostics. */
4752
4753
  async function readPlugins() {
4753
- const { pluginCatalogRuntime } = await import("./catalog-runtime-Bpcs2b2L.js").then((n) => n.t);
4754
+ const { pluginCatalogRuntime } = await import("./catalog-runtime-CfwKT0sn.js").then((n) => n.t);
4754
4755
  return pluginsSchema.parse(pluginCatalogRuntime.getProviders().map((plugin) => ({
4755
4756
  configKeys: plugin.manifest.configKeys ?? [],
4756
4757
  description: plugin.manifest.description,
@@ -4762,7 +4763,7 @@ async function readPlugins() {
4762
4763
  async function readRuntimeInfoReport() {
4763
4764
  const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
4764
4765
  import("./package-discovery-DJBompdd.js").then((n) => n.r),
4765
- import("./catalog-runtime-Bpcs2b2L.js").then((n) => n.t),
4766
+ import("./catalog-runtime-CfwKT0sn.js").then((n) => n.t),
4766
4767
  readPlugins(),
4767
4768
  readSkillReports()
4768
4769
  ]);
@@ -4779,7 +4780,7 @@ async function readRuntimeInfoReport() {
4779
4780
  /** Read sanitized operational summaries contributed by plugins. */
4780
4781
  async function readPluginOperationalReportFeed() {
4781
4782
  const nowMs = Date.now();
4782
- const { getPluginOperationalReports } = await import("./agent-hooks-V4Hfc2tB.js").then((n) => n.t);
4783
+ const { getPluginOperationalReports } = await import("./agent-hooks-9q2zdKHL.js").then((n) => n.t);
4783
4784
  return pluginOperationalReportFeedSchema.parse({
4784
4785
  source: "plugins",
4785
4786
  generatedAt: new Date(nowMs).toISOString(),
@@ -80,7 +80,7 @@ interface RuntimeLimits {
80
80
  * Add new keys here as features graduate from private experiments; remove them
81
81
  * once they become stable defaults.
82
82
  */
83
- declare const EXPERIMENTAL_FEATURES: readonly ["operator-tools", "passive-routing", "subagents"];
83
+ declare const EXPERIMENTAL_FEATURES: readonly ["operator-tools", "passive-routing"];
84
84
  /** One known experimental feature name. */
85
85
  type ExperimentalFeature = (typeof EXPERIMENTAL_FEATURES)[number];
86
86
  /** App-level opt-ins for unstable product features. */
@@ -251,6 +251,11 @@ interface JuniorAppOptions extends BotModelConfig {
251
251
  * `JUNIOR_CROSS_ACTOR_MID_RUN_MODE` or `follow_up`.
252
252
  */
253
253
  crossActorMidRunMode?: CrossActorMidRunMode;
254
+ /**
255
+ * Slack user IDs of bots that may start a Turn from a mention or DM. Bots
256
+ * have no profile email, so `allowedDomains` blocks them otherwise.
257
+ */
258
+ allowedBotUserIds?: string[];
254
259
  };
255
260
  /** Install-wide provider defaults. Unregistered `provider.key` entries warn at startup. */
256
261
  configDefaults?: Record<string, unknown>;
package/dist/app.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { i as ModelProfileInput, n as createApp, r as JuniorDashboardOptions, t as JuniorAppOptions } from "./app-BsBUs3rF.js";
1
+ import { i as ModelProfileInput, n as createApp, r as JuniorDashboardOptions, t as JuniorAppOptions } from "./app-Bo0kB987.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, JuniorAppOptions, type JuniorDashboardOptions, type JuniorPluginInput, type JuniorPluginSet, type JuniorPluginSetOptions, type ModelProfileInput, createApp, defineJuniorPlugins };
package/dist/app.js CHANGED
@@ -1,37 +1,37 @@
1
- import { $ as projectConversationMessages, C as automationVersionOf, Cn as resolveSandboxEgressProviderForHost, Dn as clearSandboxEgressSignals, En as SANDBOX_EGRESS_PROXY_PATH, Hn as slackMention, In as resolveBaseUrl, Ln as startOAuthFlow, On as consumeSandboxEgressAuthRequiredSignal, Pn as formatProviderLabel, Tn as shouldPropagateSandboxEgressTrace, X as appendConversationMessages, Xn as slackEntitySchema, Zn as slackExternalRefIdSchema, _n as isExperimentalFeatureEnabled, ar as setConfigDefaults, b as admitEventAutomationRun, bn as createUserTokenStore, c as withScheduledAutomationLock, cn as SubscribedReplyReason, dn as getThreadStopDecision, gn as getExperimentalFeatures, i as readScheduledAutomation, ir as getConfigDefaults, jn as parseSandboxEgressCredentialToken, kn as consumeSandboxEgressPermissionDeniedSignal, l as blockEventAutomation, n as listScheduledAutomationsForTeam, nt as settleConversationTitleWork, o as saveScheduledAutomationInLock, p as findMatchingEventAutomations, s as scheduledRunId, u as collectEventAutomationMatchKeys, vn as setExperimentalFeatures, wn as normalizeSandboxEgressTracePropagationDomains, x as eventAutomationRunLimitReason, yn as executeCredentialedEgressRequest } from "./tasks-CjrS098O.js";
2
- import { C as withContext, M as JUNIOR_WORKSPACE_SNAPSHOT_JOB_CALLBACK_ROUTE, R as normalizeIdentityEmail, T as withSpan, b as setSpanStatus, f as logException, k as JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE, m as logWarn, p as logInfo, r as createRequestContext, v as setSentryUser, w as withLogContext, y as setSpanAttributes } from "./logging-DSMmkHXG.js";
1
+ import { $ as projectConversationMessages, An as parseSandboxEgressCredentialToken, C as automationVersionOf, Cn as normalizeSandboxEgressTracePropagationDomains, Dn as consumeSandboxEgressAuthRequiredSignal, En as clearSandboxEgressSignals, Fn as resolveBaseUrl, In as startOAuthFlow, Nn as formatProviderLabel, On as consumeSandboxEgressPermissionDeniedSignal, Sn as resolveSandboxEgressProviderForHost, Tn as SANDBOX_EGRESS_PROXY_PATH, Vn as slackMention, X as appendConversationMessages, Xn as slackExternalRefIdSchema, Yn as slackEntitySchema, _n as setExperimentalFeatures, b as admitEventAutomationRun, c as withScheduledAutomationLock, cn as SubscribedReplyReason, dn as getThreadStopDecision, gn as isExperimentalFeatureEnabled, hn as getExperimentalFeatures, i as readScheduledAutomation, ir as setConfigDefaults, l as blockEventAutomation, n as listScheduledAutomationsForTeam, nt as settleConversationTitleWork, o as saveScheduledAutomationInLock, p as findMatchingEventAutomations, rr as getConfigDefaults, s as scheduledRunId, u as collectEventAutomationMatchKeys, vn as executeCredentialedEgressRequest, wn as shouldPropagateSandboxEgressTrace, x as eventAutomationRunLimitReason, yn as createUserTokenStore } from "./tasks-Bh2qYaed.js";
2
+ import { C as withContext, M as JUNIOR_WORKSPACE_SNAPSHOT_JOB_CALLBACK_ROUTE, R as normalizeIdentityEmail, T as withSpan, b as setSpanStatus, f as logException, k as JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE, m as logWarn, p as logInfo, r as createRequestContext, v as setSentryUser, w as withLogContext, y as setSpanAttributes } from "./logging-dZN1Bvtu.js";
3
3
  import { n as captureMessage, r as continueTrace } from "./sentry-BBUlHih9.js";
4
- import { t as JUNIOR_VERSION } from "./version-Ct049vav.js";
5
- import { _ as snapshotRuntimeConfig, d as restoreRuntimeConfig, f as setBotModelConfig, g as setSlackReactionConfig, h as setRuntimeLimits, i as getChatConfig, m as setProfiles, n as botConfig, o as getSlackBotToken, p as setCrossActorMidRunMode, u as resetRuntimeConfig } from "./config-ULs6Zl9b.js";
4
+ import { t as JUNIOR_VERSION } from "./version-JcDaJ75p.js";
5
+ import { _ as snapshotRuntimeConfig, d as restoreRuntimeConfig, f as setBotModelConfig, g as setSlackReactionConfig, h as setRuntimeLimits, i as getChatConfig, m as setProfiles, n as botConfig, o as getSlackBotToken, p as setCrossActorMidRunMode, u as resetRuntimeConfig } from "./config-BiCtNiu5.js";
6
6
  import { _ as slackMessageTsSchema, d as parseSlackTeamId, f as parseSlackUserId, h as slackUserIdSchema, m as slackTeamIdSchema, o as parseActorUserId, p as slackChannelIdSchema } from "./actor-tlxzqaRe.js";
7
- import { N as recordGoogleSignIn, _ as withConversationMutationLock, c as getConversationEventStore, d as getDb, f as getSqlExecutor, m as withConversationEventLock, r as readActorIdentity, u as getConversationStore } from "./viewer-C-J0ewlH.js";
8
- import { a as juniorAgentInvocations, d as juniorDestinations, i as juniorAgentBindings, s as juniorConversations } from "./agent-invocations-Qfz7dWgU.js";
9
- import { a as juniorAutomationRuns, f as juniorConversationBriefs, h as juniorConversationEvents, s as juniorAutomations } from "./executor-BoGNVEDn.js";
10
- import { m as credentialLogContext } from "./registry-BL-osYWN.js";
11
- import { n as pluginCatalogRuntime } from "./catalog-runtime-Bpcs2b2L.js";
12
- import { B as stopConversationSession, C as requestAttachmentDeletion, L as effectiveTaskOutcomes, M as logScheduledAutomationRunSkipped, N as scheduledAutomationRunAttributes, T as parseSlackThreadId, V as recordSubagentEnded, _ as unpublishedArtifactHeaders, g as readPublicArtifact, h as publicArtifactHeaders, n as executeAgentRun, ot as listPendingAgentInvocationMailboxAppends, st as listPendingAgentInvocationResults, t as createAgentRunner, v as lookupSlackUserProfile, vt as processWorkspaceSnapshotJob, x as collectAttachmentGarbage, yt as ingestEvent } from "./agent-runner-DvTUyGTY.js";
13
- import { $ as bindSlackDirectCredentialSubject, Gt as listConversationAnnotations, Ht as resolveRootVisibility, Q as bindScheduledAutomationCredentialSubject, Tt as readConversationAccessFromSql, U as collectEventMatchKeys, X as takeDueTimerWatches, Z as bindEventAutomationCredentialSubject, _t as getDashboardConversationLink, a as getPluginRoutes, bt as setDashboardConversationLinkOptions, ct as getSlackClient, d as setPlugins, et as verifyEventAutomationCredentialSubject, f as validatePlugins, h as setBriefsConfig, ht as runWithWorkspaceTeamId, i as getPluginApiRoutes, mt as getWorkspaceTeamId, nt as verifySlackDirectCredentialSubject, q as findMatchingWatches, tt as verifyScheduledAutomationCredentialSubject, u as getPlugins, ut as isDmChannel, wt as createPluginLogger, xt as createPluginState, yt as getDashboardTaskLink } from "./agent-hooks-V4Hfc2tB.js";
7
+ import { N as recordGoogleSignIn, _ as withConversationMutationLock, c as getConversationEventStore, d as getDb, f as getSqlExecutor, m as withConversationEventLock, r as readActorIdentity, u as getConversationStore } from "./viewer-oMTUVAcR.js";
8
+ import { a as juniorAgentInvocations, d as juniorDestinations, i as juniorAgentBindings, s as juniorConversations } from "./agent-invocations-CxKldAeB.js";
9
+ import { a as juniorAutomationRuns, f as juniorConversationBriefs, h as juniorConversationEvents, s as juniorAutomations } from "./executor-O8xqLDN6.js";
10
+ import { m as credentialLogContext } from "./registry-BUje_knT.js";
11
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-CfwKT0sn.js";
12
+ import { B as stopConversationSession, C as requestAttachmentDeletion, L as effectiveTaskOutcomes, M as logScheduledAutomationRunSkipped, N as scheduledAutomationRunAttributes, St as ingestEvent, T as parseSlackThreadId, V as recordSubagentEnded, _ as unpublishedArtifactHeaders, ct as listPendingAgentInvocationResults, g as readPublicArtifact, h as publicArtifactHeaders, n as executeAgentRun, st as listPendingAgentInvocationMailboxAppends, t as createAgentRunner, v as lookupSlackUserProfile, x as collectAttachmentGarbage, xt as processWorkspaceSnapshotJob } from "./agent-runner-Cx6NO5LE.js";
13
+ import { $ as bindSlackDirectCredentialSubject, Gt as listConversationAnnotations, Ht as resolveRootVisibility, Q as bindScheduledAutomationCredentialSubject, Tt as readConversationAccessFromSql, U as collectEventMatchKeys, X as takeDueTimerWatches, Xt as createPluginCache, Z as bindEventAutomationCredentialSubject, Zt as createCache, _t as getDashboardConversationLink, a as getPluginRoutes, bt as setDashboardConversationLinkOptions, ct as getSlackClient, d as setPlugins, et as verifyEventAutomationCredentialSubject, f as validatePlugins, h as setBriefsConfig, ht as runWithWorkspaceTeamId, i as getPluginApiRoutes, mt as getWorkspaceTeamId, nt as verifySlackDirectCredentialSubject, q as findMatchingWatches, tt as verifyScheduledAutomationCredentialSubject, u as getPlugins, ut as isDmChannel, wt as createPluginLogger, xt as createPluginState, yt as getDashboardTaskLink } from "./agent-hooks-9q2zdKHL.js";
14
+ import { r as getStateAdapter, s as withLock$1 } from "./adapter-t-Y9RHML.js";
14
15
  import { n as getNextRunAtMs } from "./cadence-R7Em4RjE.js";
15
16
  import { M as annotationCard } from "./conversation-CvuKJ3tA.js";
16
- import { r as getStateAdapter, s as withLock$1 } from "./adapter-Dj5BTJRd.js";
17
- import { M as renderTaskInput, S as eventGuidance, d as getEventCatalog, f as SLACK_EVENT_NAMESPACE, g as slackChannelMessageRunsAutomation, h as slackChannelMessageReplyThreadTs, m as slackChannelMessageEvent } from "./session-stop-HfKx-pky.js";
18
- import { f as setSandboxResourceConfig, u as getSandboxResourceConfig } from "./resolve-HuPG2VMB.js";
19
- import { a as getVercelConversationWorkQueue, g as isConversationQueueMessageRejectedError, h as conversationQueueMessageSchema, i as verifyWorkspaceSnapshotJobMessage, o as resolveConversationWorkQueueTopic, s as verifyConversationQueueMessage, t as WORKSPACE_SNAPSHOT_JOB_QUEUE_TOPIC } from "./job-queue-CbdVyaCo.js";
20
- import { A as hasRunnableConversationWork$1, M as isInvalidConversationRecordError, O as CONVERSATION_WORK_STALE_ENQUEUE_MS, S as removeActiveConversation, _ as hasRunnableConversationWork, c as clearExpiredConversationLease, g as getConversationWorkState, h as getConversation, m as ensureConversationWake, r as appendAndEnqueueInboundMessage, v as listActiveConversationIds } from "./store-DzRbd5VT.js";
17
+ import { M as renderTaskInput, S as eventGuidance, d as getEventCatalog, f as SLACK_EVENT_NAMESPACE, g as slackChannelMessageRunsAutomation, h as slackChannelMessageReplyThreadTs, m as slackChannelMessageEvent } from "./session-stop-ZuyOHxdK.js";
18
+ import { f as setSandboxResourceConfig, u as getSandboxResourceConfig } from "./resolve-DftZiYNU.js";
19
+ import { a as getVercelConversationWorkQueue, g as isConversationQueueMessageRejectedError, h as conversationQueueMessageSchema, i as verifyWorkspaceSnapshotJobMessage, o as resolveConversationWorkQueueTopic, s as verifyConversationQueueMessage, t as WORKSPACE_SNAPSHOT_JOB_QUEUE_TOPIC } from "./job-queue-DmarAQGI.js";
20
+ import { A as hasRunnableConversationWork$1, M as isInvalidConversationRecordError, O as CONVERSATION_WORK_STALE_ENQUEUE_MS, S as removeActiveConversation, _ as hasRunnableConversationWork, c as clearExpiredConversationLease, g as getConversationWorkState, h as getConversation, m as ensureConversationWake, r as appendAndEnqueueInboundMessage, v as listActiveConversationIds } from "./store-dZynGGFW.js";
21
21
  import { D as scheduledRunSchema } from "./automation-DrpcA-SX.js";
22
- import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "./validation-BrXMYPyo.js";
22
+ import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "./validation-DtcovXqq.js";
23
23
  import { a as pluginRuntimeRegistrationsFromPluginSet, n as pluginCatalogConfigFromEnv, r as pluginCatalogConfigFromPluginSet, t as defineJuniorPlugins } from "./plugins-DOm9Y6qI.js";
24
- import { A as THREAD_OPTOUT_ACK, C as buildSlackInboundMessage, D as normalizeIncomingSlackThreadId, E as stopSlackThread, F as renderSlackObjectCard, I as createVercelAttachmentStorage, M as parseContent, N as runWithSlackInstallation, O as withNormalizedThreadId, P as verifySlackSignature, R as enqueueAgentDispatch, S as recordSkippedConversationMessage, T as isSlackMessageStopped, a as recordWebConversationActivity, c as createProductionSlackWebhookServices, f as createSlackWebApiStatusSender, j as startProcessingReaction, k as stopConversationTurn, l as getProductionSlackAdapter, n as conversationTurnIdForMessage, o as webActorFromEmail, s as createProductionConversationWorkOptions, t as appendAndEnqueueWebMessage, v as readViewerAutomationSummary, w as clearSlackPendingReactions, z as GET$3 } from "./web-input-C_xB3RXp.js";
25
- import { C as existingConversationId, N as recordAutomationExecution, c as getDispatchConversationId, d as getDispatchRecord, h as listPendingDispatchMailboxAppends, i as buildDispatchId, m as isTerminalDispatchStatus, o as confirmDispatchMailboxAppend, p as getPluginDispatchProjection, s as createOrGetDispatch, t as processPluginTask, x as notifyAutomationBlocked, y as markDispatchFailed } from "./task-runner-DGnd_B5X.js";
26
- import { o as getAuthPausedConversationTurnId, t as enqueueAgentInvocationResult } from "./result-DS7V4a3-.js";
27
- import { r as enqueueAgentInvocation } from "./work-D829Ue7k.js";
28
- import { s as coerceThreadConversationState } from "./thread-state-CqkYowEz.js";
29
- import { o as unlinkProvider } from "./connections-CZ7HhEmN.js";
30
- import { a as GET$4, i as publishAppHomeView, r as GET$5, t as receiveLocalOAuthCredential } from "./credential-sync-BKcv5rBe.js";
31
- import { a as registerVercelPluginTaskDevConsumer, n as createVercelPluginTaskCallback, s as queueCallback } from "./task-queue-9LICOzcL.js";
32
- import { t as processConversationWork } from "./worker-BRTYzlpk.js";
33
- import { t as bindMessageAgent } from "./message-zaj5gBbS.js";
34
- import { t as bindSpawnAgent } from "./spawn-BWqK6EwM.js";
24
+ import { A as THREAD_OPTOUT_ACK, C as buildSlackInboundMessage, D as normalizeIncomingSlackThreadId, E as stopSlackThread, F as renderSlackObjectCard, I as createVercelAttachmentStorage, M as parseContent, N as runWithSlackInstallation, O as withNormalizedThreadId, P as verifySlackSignature, R as enqueueAgentDispatch, S as recordSkippedConversationMessage, T as isSlackMessageStopped, a as recordWebConversationActivity, c as createProductionSlackWebhookServices, f as createSlackWebApiStatusSender, j as startProcessingReaction, k as stopConversationTurn, l as getProductionSlackAdapter, n as conversationTurnIdForMessage, o as webActorFromEmail, s as createProductionConversationWorkOptions, t as appendAndEnqueueWebMessage, v as readViewerAutomationSummary, w as clearSlackPendingReactions, z as GET$3 } from "./web-input-FQ5wgqYn.js";
25
+ import { C as existingConversationId, N as recordAutomationExecution, c as getDispatchConversationId, d as getDispatchRecord, h as listPendingDispatchMailboxAppends, i as buildDispatchId, m as isTerminalDispatchStatus, o as confirmDispatchMailboxAppend, p as getPluginDispatchProjection, s as createOrGetDispatch, t as processPluginTask, x as notifyAutomationBlocked, y as markDispatchFailed } from "./task-runner-BRgJ5e0s.js";
26
+ import { o as getAuthPausedConversationTurnId, t as enqueueAgentInvocationResult } from "./result-CRMRT9CE.js";
27
+ import { r as enqueueAgentInvocation } from "./work-BiIKfayl.js";
28
+ import { s as coerceThreadConversationState } from "./thread-state-DA37FsAT.js";
29
+ import { o as unlinkProvider } from "./connections-D9IKbfk-.js";
30
+ import { a as GET$4, i as publishAppHomeView, r as GET$5, t as receiveLocalOAuthCredential } from "./credential-sync-Bu6ZOuOk.js";
31
+ import { a as registerVercelPluginTaskDevConsumer, n as createVercelPluginTaskCallback, s as queueCallback } from "./task-queue-CmMCtzHO.js";
32
+ import { t as processConversationWork } from "./worker-BZ7l75NM.js";
33
+ import { t as bindMessageAgent } from "./message-C_g2S8kv.js";
34
+ import { t as bindSpawnAgent } from "./spawn-DovpdlrW.js";
35
35
  import { createRequire } from "node:module";
36
36
  import { Hono } from "hono";
37
37
  import { z } from "zod";
@@ -260,6 +260,7 @@ function createHeartbeatContext(args) {
260
260
  let dispatchCount = 0;
261
261
  return {
262
262
  plugin: { name: pluginName },
263
+ cache: createPluginCache(pluginName),
263
264
  nowMs: args.nowMs,
264
265
  db: getDb(),
265
266
  state: createPluginState(pluginName),
@@ -2319,34 +2320,25 @@ async function isSlackWorkspaceMember(raw, state) {
2319
2320
  const event = parsed.data;
2320
2321
  const userId = parseSlackUserId(event.user);
2321
2322
  if (!userId) return false;
2323
+ const cache = createCache(state, "core");
2322
2324
  const key = `slack:membership:${workspaceTeamId}:${userId}`;
2323
2325
  const authorTeam = parseSlackTeamId(event.user_team);
2324
2326
  if (authorTeam === workspaceTeamId) return true;
2325
2327
  if (event.user_team !== void 0 && !authorTeam && !/^E[A-Z0-9]+$/.test(event.user_team)) return false;
2326
- const explicitlyExternal = authorTeam !== void 0;
2327
- if (!explicitlyExternal) {
2328
- const cached = await state.get(key);
2329
- if (typeof cached === "boolean") return cached;
2330
- }
2331
- const result = await withLock$1(state, `${key}:lookup`, async () => {
2332
- if (explicitlyExternal) {
2333
- await state.set(key, false, NON_MEMBER_TTL_MS);
2334
- return false;
2335
- }
2336
- const cached = await state.get(key);
2337
- if (typeof cached === "boolean") return cached;
2328
+ if (authorTeam !== void 0) return await cache.getOrLoad(key, async () => ({
2329
+ value: false,
2330
+ ttlMs: NON_MEMBER_TTL_MS
2331
+ }), { refresh: true });
2332
+ return await cache.getOrLoad(key, async () => {
2338
2333
  const user = await lookupSlackUserProfile(userId);
2339
2334
  const authorTeam = parseSlackTeamId(user.team_id);
2340
- if (user.id !== userId || !authorTeam) return false;
2335
+ if (user.id !== userId || !authorTeam) return { value: false };
2341
2336
  const member = authorTeam === workspaceTeamId && !user.is_deleted;
2342
- await state.set(key, member, member ? MEMBER_TTL_MS : NON_MEMBER_TTL_MS);
2343
- return member;
2344
- }, {
2345
- keepAlive: true,
2346
- waitMs: 1e4
2337
+ return {
2338
+ value: member,
2339
+ ttlMs: member ? MEMBER_TTL_MS : NON_MEMBER_TTL_MS
2340
+ };
2347
2341
  });
2348
- if (!result.acquired) throw new Error("Could not acquire Slack membership lookup lock");
2349
- return result.value;
2350
2342
  }
2351
2343
  // src/chat/sign-in/allowlist.ts
2352
2344
  /**
@@ -2396,23 +2388,26 @@ const NOT_ALLOWED_TTL_MS = 3e4;
2396
2388
  /**
2397
2389
  * Return whether a Slack author may start a Turn. With allowed domains, the
2398
2390
  * email of the author's Slack profile must be on one of them. Slack verifies
2399
- * that email, so Junior trusts it. Without allowed domains, every author may.
2391
+ * that email, so Junior trusts it. Bots have no profile email, so the allowed
2392
+ * bot user IDs skip this check. Without allowed domains, every author may.
2400
2393
  */
2401
2394
  async function isSlackAuthorDomainAllowed(args) {
2402
2395
  if (args.allowedDomains.length === 0) return true;
2403
2396
  const userId = parseSlackUserId(args.user);
2404
2397
  if (!args.teamId || !userId) return false;
2405
- const key = `slack:allowed-domain:${args.teamId}:${userId}`;
2406
- const cached = await args.state.get(key);
2407
- if (typeof cached === "boolean") return cached;
2408
- const profile = await lookupSlackUserProfile(userId);
2409
- const email = profile.email?.toLowerCase();
2410
- const separator = email?.lastIndexOf("@") ?? -1;
2411
- const domain = separator > 0 ? email?.slice(separator + 1) : void 0;
2412
- const allowed = profile.id === userId && isAllowedDomain(domain, args.allowedDomains);
2413
- if (!allowed) logWarn("slack.allowed_domain.rejected", { "app.reason": email ? "domain_not_allowed" : "missing_email" });
2414
- await args.state.set(key, allowed, allowed ? ALLOWED_TTL_MS : NOT_ALLOWED_TTL_MS);
2415
- return allowed;
2398
+ if (args.allowedBotUserIds.includes(userId)) return true;
2399
+ return await createCache(args.state, "core").getOrLoad(`slack:allowed-domain:${args.teamId}:${userId}`, async () => {
2400
+ const profile = await lookupSlackUserProfile(userId);
2401
+ const email = profile.email?.toLowerCase();
2402
+ const separator = email?.lastIndexOf("@") ?? -1;
2403
+ const domain = separator > 0 ? email?.slice(separator + 1) : void 0;
2404
+ const allowed = profile.id === userId && isAllowedDomain(domain, args.allowedDomains);
2405
+ if (!allowed) logWarn("slack.allowed_domain.rejected", { "app.reason": email ? "domain_not_allowed" : "missing_email" });
2406
+ return {
2407
+ value: allowed,
2408
+ ttlMs: allowed ? ALLOWED_TTL_MS : NOT_ALLOWED_TTL_MS
2409
+ };
2410
+ });
2416
2411
  }
2417
2412
  // src/chat/ingress/slack-message-telemetry.ts
2418
2413
  function field(value, pattern) {
@@ -2835,6 +2830,7 @@ async function routeParsedMessage(args) {
2835
2830
  return;
2836
2831
  }
2837
2832
  if (route === "mention" && !await isSlackAuthorDomainAllowed({
2833
+ allowedBotUserIds: args.allowedBotUserIds,
2838
2834
  allowedDomains: args.allowedDomains,
2839
2835
  state: args.state,
2840
2836
  teamId: args.installation.teamId,
@@ -2956,6 +2952,7 @@ async function handleSlackEvent(args) {
2956
2952
  conversationStore: args.services.conversationStore,
2957
2953
  queue: args.services.queue,
2958
2954
  receivedAtMs,
2955
+ allowedBotUserIds: args.services.allowedBotUserIds ?? [],
2959
2956
  allowedDomains: args.services.allowedDomains ?? [],
2960
2957
  state
2961
2958
  }), {
@@ -5055,8 +5052,7 @@ function readGoogleClaims(idToken) {
5055
5052
  } catch {
5056
5053
  return;
5057
5054
  }
5058
- const parsed = googleClaimsSchema.safeParse(payload);
5059
- return parsed.success ? parsed.data : void 0;
5055
+ return googleClaimsSchema.safeParse(payload).success ? payload : void 0;
5060
5056
  }
5061
5057
  function trimSlashes(value, leading) {
5062
5058
  let start = 0;
@@ -5106,7 +5102,6 @@ function createBetterAuth(config) {
5106
5102
  if (!isAllowedDomain(claims.hd, allowedDomains)) return null;
5107
5103
  return {
5108
5104
  user: {
5109
- id: claims.sub,
5110
5105
  email: claims.email,
5111
5106
  emailVerified: claims.email_verified === true,
5112
5107
  image: claims.picture,
@@ -5593,6 +5588,7 @@ async function createApp(options) {
5593
5588
  queue: conversationWorkQueue,
5594
5589
  services: runtimeServiceOverrides
5595
5590
  }),
5591
+ allowedBotUserIds: options?.slack?.allowedBotUserIds ?? [],
5596
5592
  allowedDomains
5597
5593
  };
5598
5594
  const app = new Hono();
@@ -1,4 +1,4 @@
1
- import { Gt as extractAssistantText } from "./tasks-CjrS098O.js";
1
+ import { Gt as extractAssistantText } from "./tasks-Bh2qYaed.js";
2
2
  // src/chat/no-reply.ts
3
3
  const NO_REPLY_MARKER = "[[NO_REPLY]]";
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { i as completeObject } from "./client-JeyzRwsT.js";
1
+ import { i as completeObject } from "./client-DpfjZgNk.js";
2
2
  import { r as defaultModelId } from "./model-profile-Bg8EoCKD.js";
3
3
  import { J as parseBriefInput, W as briefCodeChangeSchema, d as conversationDetailReportSchema, p as conversationEventPageSchema } from "./conversation-CvuKJ3tA.js";
4
4
  import { n as briefEntriesFromReportEvents, s as generateBrief, t as BRIEF_PROMPT } from "./prompt-DeVax2qO.js";
@@ -267,7 +267,7 @@ async function parseRunOptions(argv) {
267
267
  * `DATABASE_URL` at import, and `briefs pull` must work with only a token.
268
268
  */
269
269
  async function configuredDefaultModelId() {
270
- const { botConfig } = await import("./config-ULs6Zl9b.js").then((n) => n.r);
270
+ const { botConfig } = await import("./config-BiCtNiu5.js").then((n) => n.r);
271
271
  return defaultModelId(botConfig);
272
272
  }
273
273
  function apiUrl(baseUrl, pathname) {
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
- import { t as createPluginCatalogRuntime } from "./registry-BL-osYWN.js";
2
+ import { t as createPluginCatalogRuntime } from "./registry-BUje_knT.js";
3
3
  // src/chat/plugins/catalog-runtime.ts
4
4
  var catalog_runtime_exports = /* @__PURE__ */ __exportAll({ pluginCatalogRuntime: () => pluginCatalogRuntime });
5
5
  const pluginCatalogRuntime = createPluginCatalogRuntime();
package/dist/cli/chat.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as executeAgentRun, t as createAgentRunner } from "../agent-runner-DvTUyGTY.js";
1
+ import { n as executeAgentRun, t as createAgentRunner } from "../agent-runner-Cx6NO5LE.js";
2
2
  import { t as loadAppPluginSet } from "../plugin-module-Cf5gVPWP.js";
3
3
  import path from "node:path";
4
4
  import { createHash, randomUUID } from "node:crypto";
@@ -99,10 +99,10 @@ async function loadLocalPluginSet() {
99
99
  async function configureLocalChatPlugins(pluginSet) {
100
100
  const [pluginsModule, agentHooksModule, catalogRuntimeModule, validationModule, databaseModule] = await Promise.all([
101
101
  import("../plugins-DOm9Y6qI.js").then((n) => n.o),
102
- import("../agent-hooks-V4Hfc2tB.js").then((n) => n.t),
103
- import("../catalog-runtime-Bpcs2b2L.js").then((n) => n.t),
104
- import("../validation-BrXMYPyo.js").then((n) => n.r),
105
- import("../viewer-C-J0ewlH.js").then((n) => n.s)
102
+ import("../agent-hooks-9q2zdKHL.js").then((n) => n.t),
103
+ import("../catalog-runtime-CfwKT0sn.js").then((n) => n.t),
104
+ import("../validation-DtcovXqq.js").then((n) => n.r),
105
+ import("../viewer-oMTUVAcR.js").then((n) => n.s)
106
106
  ]);
107
107
  const resolvedPluginSet = pluginSet === void 0 ? await loadLocalPluginSet() : pluginSet ?? void 0;
108
108
  const plugins = pluginsModule.pluginRuntimeRegistrationsFromPluginSet(resolvedPluginSet);
@@ -152,21 +152,19 @@ function localDevServerUrl() {
152
152
  async function prepareLocalChatRun(io, pluginSet) {
153
153
  defaultStateAdapterForLocalChat();
154
154
  await configureLocalChatPlugins(pluginSet);
155
- const { setExperimentalFeatures } = await import("../tasks-CjrS098O.js").then((n) => n.hn);
156
- setExperimentalFeatures({ subagents: true });
157
- const { setBriefsConfig } = await import("../agent-hooks-V4Hfc2tB.js").then((n) => n.m);
155
+ const { setBriefsConfig } = await import("../agent-hooks-9q2zdKHL.js").then((n) => n.m);
158
156
  setBriefsConfig({ enabled: true });
159
- const { runLocalAgentTurn } = await import("../runner-Cba_OfGl.js");
160
- const { startLocalOAuthCallbackServer } = await import("../oauth-callback-server-yYFG8Own.js");
157
+ const { runLocalAgentTurn } = await import("../runner-4mmL2Pt1.js");
158
+ const { startLocalOAuthCallbackServer } = await import("../oauth-callback-server-DvvOvr4q.js");
161
159
  const { createLocalOAuthState } = await import("../oauth-relay-CTygMkNx.js").then((n) => n.t);
162
- const { createLocalSandboxEgressSignalTransport } = await import("../sandbox-egress-signals-C7NcPzea.js");
163
- const { bindSpawnAgent } = await import("../spawn-BWqK6EwM.js").then((n) => n.n);
164
- const { bindMessageAgent } = await import("../message-zaj5gBbS.js").then((n) => n.n);
165
- const { createAgentInvocationWorker, routeAgentInvocationWork } = await import("../work-D829Ue7k.js").then((n) => n.a);
166
- const { startAgentInvocationsForChildInput } = await import("../result-DS7V4a3-.js").then((n) => n.r);
167
- const { skipInputBeforeConversationStop } = await import("../session-stop-HfKx-pky.js").then((n) => n.r);
160
+ const { createLocalSandboxEgressSignalTransport } = await import("../sandbox-egress-signals-1ysv0z5A.js");
161
+ const { bindSpawnAgent } = await import("../spawn-DovpdlrW.js").then((n) => n.n);
162
+ const { bindMessageAgent } = await import("../message-C_g2S8kv.js").then((n) => n.n);
163
+ const { createAgentInvocationWorker, routeAgentInvocationWork } = await import("../work-BiIKfayl.js").then((n) => n.a);
164
+ const { startAgentInvocationsForChildInput } = await import("../result-CRMRT9CE.js").then((n) => n.r);
165
+ const { skipInputBeforeConversationStop } = await import("../session-stop-ZuyOHxdK.js").then((n) => n.r);
168
166
  const { createLocalConversationWork } = await import("../conversation-work-BaT_T6EB.js");
169
- const { processConversationWork } = await import("../worker-BRTYzlpk.js").then((n) => n.n);
167
+ const { processConversationWork } = await import("../worker-BZ7l75NM.js").then((n) => n.n);
170
168
  let agentRunner;
171
169
  const localConversationWork = createLocalConversationWork(async (message) => {
172
170
  if (!agentRunner) throw new Error("Local agent runner is not ready");
package/dist/cli/check.js CHANGED
@@ -1,6 +1,6 @@
1
- import { E as JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE, N as LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION, O as JUNIOR_HEARTBEAT_ROUTE } from "../logging-DSMmkHXG.js";
2
- import { v as parseInlinePluginManifest, y as parsePluginManifest } from "../registry-BL-osYWN.js";
3
- import { i as parseSkillFile } from "../skills-D6_bcAuW.js";
1
+ import { E as JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE, N as LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION, O as JUNIOR_HEARTBEAT_ROUTE } from "../logging-dZN1Bvtu.js";
2
+ import { v as parseInlinePluginManifest, y as parsePluginManifest } from "../registry-BUje_knT.js";
3
+ import { i as parseSkillFile } from "../skills-lPeepA2b.js";
4
4
  import path from "node:path";
5
5
  import fs from "node:fs/promises";
6
6
  import { pathToFileURL } from "node:url";
package/dist/cli/init.js CHANGED
@@ -136,7 +136,7 @@ async function runInit(dir, log = console.log) {
136
136
  "@sentry/junior-memory": "latest",
137
137
  "@sentry/junior-maintenance": "latest",
138
138
  "@sentry/nitro": "10.65.0",
139
- hono: "^4.12.27"
139
+ hono: "^4.13.11"
140
140
  },
141
141
  devDependencies: {
142
142
  "@types/node": "^25.9.1",
package/dist/cli/main.js CHANGED
@@ -25,13 +25,13 @@ async function runChat(argv, pluginSet) {
25
25
  return await (await import("./chat.js")).runChat(argv, void 0, { pluginSet });
26
26
  }
27
27
  async function runAdmin(argv) {
28
- return await (await import("../admin-tzkZDqrH.js")).runAdmin(argv);
28
+ return await (await import("../admin-BCqeFndQ.js")).runAdmin(argv);
29
29
  }
30
30
  async function runServiceAccount(argv) {
31
- return await (await import("../service-account-DqwHhwJA.js")).runServiceAccount(argv);
31
+ return await (await import("../service-account-B1sH3P7d.js")).runServiceAccount(argv);
32
32
  }
33
33
  async function runBriefs(argv) {
34
- return await (await import("../briefs-BSCkyYqs.js")).runBriefs(argv);
34
+ return await (await import("../briefs-DsGH2Vym.js")).runBriefs(argv);
35
35
  }
36
36
  function topLevelCommand(argv) {
37
37
  return (argv[0] === "--" ? argv.slice(1) : argv)[0];
@@ -1,7 +1,7 @@
1
- import { d as getDb } from "../viewer-C-J0ewlH.js";
2
- import { n as pluginCatalogRuntime } from "../catalog-runtime-Bpcs2b2L.js";
3
- import { d as setPlugins, f as validatePlugins, wt as createPluginLogger } from "../agent-hooks-V4Hfc2tB.js";
4
- import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "../validation-BrXMYPyo.js";
1
+ import { d as getDb } from "../viewer-oMTUVAcR.js";
2
+ import { n as pluginCatalogRuntime } from "../catalog-runtime-CfwKT0sn.js";
3
+ import { d as setPlugins, f as validatePlugins, wt as createPluginLogger } from "../agent-hooks-9q2zdKHL.js";
4
+ import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "../validation-DtcovXqq.js";
5
5
  import { a as pluginRuntimeRegistrationsFromPluginSet, i as pluginCliRegistrationsFromPluginSet, r as pluginCatalogConfigFromPluginSet } from "../plugins-DOm9Y6qI.js";
6
6
  import { t as loadAppPluginSet } from "../plugin-module-Cf5gVPWP.js";
7
7
  import { stderr, stdout } from "node:process";