@sentry/junior 0.268.0 → 0.270.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +2 -9
  2. package/dist/{adapter-04AcD2SO.js → adapter-BQNTKVTF.js} +3 -49
  3. package/dist/{admin-DIU1QyG3.js → admin-CKVEoXa4.js} +1 -1
  4. package/dist/{agent-runner-CAYfFmU7.js → agent-runner-MSQSMFkq.js} +4538 -3251
  5. package/dist/api/schema.d.ts +2 -3
  6. package/dist/api/schema.js +7 -7
  7. package/dist/api.d.ts +3 -1
  8. package/dist/api.js +190 -301
  9. package/dist/{app-z6Uuyq3j.d.ts → app-Bz8t4P8p.d.ts} +9 -3
  10. package/dist/app.d.ts +1 -1
  11. package/dist/app.js +129 -209
  12. package/dist/{automation-CmeFBSEh.js → automation-Dwh_xcqM.js} +74 -74
  13. package/dist/{briefs-DQbV2jNr.js → briefs-DNFzFFVx.js} +5 -5
  14. package/dist/{catalog-runtime-BD9GSpc6.js → catalog-runtime-Bdym_wKy.js} +1 -1
  15. package/dist/cli/chat.js +16 -26
  16. package/dist/cli/check.js +3 -3
  17. package/dist/cli/main.js +5 -3
  18. package/dist/cli/plugins.js +4 -4
  19. package/dist/cli/snapshot-create.js +4 -4
  20. package/dist/cli/upgrade.d.ts +1 -1
  21. package/dist/cli/upgrade.js +3 -3
  22. package/dist/{client-C1yDYjoS.js → client-B2MjENki.js} +31 -16
  23. package/dist/{config-DrTeF80T.js → config-Dm3pWRqY.js} +3 -3
  24. package/dist/{connections-D46f8vvi.js → connections-0BBhiD-p.js} +10 -10
  25. package/dist/{conversation-DSo310Ps.js → conversation-AhOVzN_k.js} +11 -86
  26. package/dist/{conversation-privacy-CxlOCiUo.js → conversation-privacy-C1pJ89rs.js} +1 -1
  27. package/dist/{credential-sync-sm9fegLY.js → credential-sync-BRiWYs6_.js} +15 -14
  28. package/dist/{credentialed-lukuD-cc.js → credentialed-BeBaJMZ_.js} +565 -83
  29. package/dist/{store-xMuuXRE0.d.ts → db-BYOuu6v2.d.ts} +4 -0
  30. package/dist/{executor-4vhvsMZJ.js → executor-BB6eJkD4.js} +6 -6
  31. package/dist/instrumentation.js +2 -2
  32. package/dist/{interruption-marker-CkncDT8d.js → interruption-marker-CdblrIQK.js} +1 -1
  33. package/dist/{job-queue-In9QKz-I.js → job-queue-DiaXoSDg.js} +2 -2
  34. package/dist/{list-BkgnXEEB.js → list-BTDRxkOg.js} +331 -662
  35. package/dist/locks-D-0h111u.js +48 -0
  36. package/dist/{logging-DLSpkSSr.js → logging-C6EdT6PP.js} +1 -1
  37. package/dist/{history-C84mlAwO.js → media-U6Tuz6Mi.js} +84 -2
  38. package/dist/{message-BObyg59s.js → message-DsjiWRVg.js} +4 -4
  39. package/dist/{model-profile-Bg8EoCKD.js → model-profile-B998sjVd.js} +9 -2
  40. package/dist/nitro.d.ts +1 -1
  41. package/dist/nitro.js +5 -3
  42. package/dist/{oauth-callback-server-B-WbSdoH.js → oauth-callback-server-CjFFVGqa.js} +2 -2
  43. package/dist/{prompt-BW9jFsqZ.js → prompt-BPSdXYXV.js} +1 -1
  44. package/dist/{registry-BgecKva0.js → registry-CndmkP2P.js} +1 -1
  45. package/dist/reporting-schema-CZREhYc-.js +104 -0
  46. package/dist/{web-message-id-DlHNANtd.js → reporting-window-DRCi1Ls_.js} +139 -7
  47. package/dist/{resolve-Cpa4Bu1O.js → resolve-BkAA1wH7.js} +3 -3
  48. package/dist/{result-D3TSmZZ8.js → result-9TJTpuYP.js} +30 -11
  49. package/dist/{runner-DS5OKhEp.js → runner-BmKLSyJm.js} +12 -11
  50. package/dist/{sandbox-egress-signals-CnDjY5rx.js → sandbox-egress-signals-CjLaogMo.js} +1 -1
  51. package/dist/{schema-0050HFnB.js → schema-DNLJ_MzW.js} +36 -20
  52. package/dist/{schema-ZngqcOWM.d.ts → schema-WayPSHFu.d.ts} +149 -12
  53. package/dist/{service-account-CKV2WTY7.js → service-account-D6e9cVmH.js} +4 -3
  54. package/dist/{service-account-DGjnDw9y.js → service-account-DlhYl-Mu.js} +3 -3
  55. package/dist/{session-stop-Dam1EI7B.js → session-stop-MZRgYqYH.js} +24 -16
  56. package/dist/{skills-CfAnfImD.js → skills-BggTR_ue.js} +2 -2
  57. package/dist/{spawn-cmq9p4Ly.js → spawn-DmtlcAT_.js} +2 -2
  58. package/dist/{store-zPEoJPBB.js → store-BeWGgaMA.js} +3 -3
  59. package/dist/{store-C5PN02QO.js → store-Byarin7b.js} +4 -4
  60. package/dist/{task-queue-_mf28dSu.js → task-queue-Dt1_ZoI_.js} +3 -3
  61. package/dist/task-runner-DyKqAPpm.js +269 -0
  62. package/dist/{thread-state-BbbPh0Sn.js → thread-state-BHBLMvgb.js} +5 -5
  63. package/dist/{turn-failure-response-BKKmnMB5.js → turn-failure-response-DWXy_0oJ.js} +9 -9
  64. package/dist/{turn-lifecycle-oP0kVeGz.js → turn-lifecycle-AiXkVqCB.js} +1 -1
  65. package/dist/{tasks-SB9z-VTU.js → turn-session-routing-B9KLBhaT.js} +939 -120
  66. package/dist/{validation--JsAGLwc.js → validation-BW60Vtx_.js} +1 -1
  67. package/dist/{version-jHwJp4hC.js → version-CivPYmkH.js} +1 -1
  68. package/dist/version.js +1 -1
  69. package/dist/{viewer-CpXTGlep.js → viewer-BTgAfdUg.js} +216 -27
  70. package/dist/{work-3N-GHY9m.js → work-Bjm52fHo.js} +17 -36
  71. package/dist/{worker-CCdbcItd.js → worker-CMbgtHLu.js} +15 -7
  72. package/migrations/0069_system_identity.sql +25 -0
  73. package/migrations/0070_review_item_foreign_keys.sql +5 -0
  74. package/migrations/AGENTS.md +17 -0
  75. package/migrations/meta/0069_snapshot.json +3979 -0
  76. package/migrations/meta/0070_snapshot.json +3997 -0
  77. package/migrations/meta/_journal.json +15 -1
  78. package/package.json +5 -4
  79. package/dist/db-BU4LQD8s.d.ts +0 -6
  80. package/dist/history-BgI33Kie.d.ts +0 -78
  81. package/dist/reporting-window-DVCD_10C.js +0 -227
  82. package/dist/task-runner-DMI2prDO.js +0 -1073
  83. package/migrations/README.md +0 -30
@@ -1,6 +1,7 @@
1
- import { B as isRecord, b as setSpanAttributes, h as logWarn } from "./logging-DLSpkSSr.js";
2
- import { c as fetchWithBoundedOAuthErrorBodies, i as resolvePluginHeaderEnvRefs } from "./registry-BgecKva0.js";
3
- import { a as MUTATION_LOCK_TTL_MS, c as withLock, i as getStateAdapter, s as fenceLock } from "./adapter-04AcD2SO.js";
1
+ import { B as isRecord, b as setSpanAttributes, h as logWarn } from "./logging-C6EdT6PP.js";
2
+ import { c as fetchWithBoundedOAuthErrorBodies, i as resolvePluginHeaderEnvRefs } from "./registry-CndmkP2P.js";
3
+ import { a as withLock, i as fenceLock, n as MUTATION_LOCK_TTL_MS } from "./locks-D-0h111u.js";
4
+ import { r as getStateAdapter } from "./adapter-BQNTKVTF.js";
4
5
  import { AsyncLocalStorage } from "node:async_hooks";
5
6
  import { randomUUID } from "node:crypto";
6
7
  import { UnauthorizedError, auth } from "@modelcontextprotocol/sdk/client/auth.js";
@@ -1,6 +1,6 @@
1
- import { n as pluginCatalogRuntime } from "./catalog-runtime-BD9GSpc6.js";
2
- import { t as disconnectStateAdapter } from "./adapter-04AcD2SO.js";
3
- import { n as finishServiceAccountSignIn, o as serviceAccountPlugins, r as getServiceAccountStatus, s as startServiceAccountSignIn, t as disconnectServiceAccount } from "./service-account-CKV2WTY7.js";
1
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-Bdym_wKy.js";
2
+ import { t as disconnectStateAdapter } from "./adapter-BQNTKVTF.js";
3
+ import { n as finishServiceAccountSignIn, o as serviceAccountPlugins, r as getServiceAccountStatus, s as startServiceAccountSignIn, t as disconnectServiceAccount } from "./service-account-D6e9cVmH.js";
4
4
  import { CLI_USAGE } from "./cli/run.js";
5
5
  import { createServer } from "node:http";
6
6
  // src/cli/service-account.ts
@@ -1,16 +1,16 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
- import { F as eventCatalogEntry, Gn as isToolResultError, I as eventGuidance, Kn as isToolResultMessage, M as CORE_EVENT_NAMESPACE, Un as isAssistantMessage, qn as normalizeToolNameFromResult } from "./tasks-SB9z-VTU.js";
3
- import { n as botConfig } from "./config-DrTeF80T.js";
4
- import { h as logWarn, m as logInfo, p as logException } from "./logging-DLSpkSSr.js";
5
- import { h as getSqlExecutor, p as getConversationStore } from "./viewer-CpXTGlep.js";
2
+ import { Cr as isAssistantMessage, Dr as normalizeToolNameFromResult, Er as isToolResultMessage, Tr as isToolResultError, dt as CORE_EVENT_NAMESPACE, ht as eventGuidance, mt as eventCatalogEntry } from "./turn-session-routing-B9KLBhaT.js";
3
+ import { n as botConfig } from "./config-Dm3pWRqY.js";
4
+ import { h as logWarn, m as logInfo, p as logException } from "./logging-C6EdT6PP.js";
5
+ import { C as getSqlExecutor, j as SYSTEM_IDENTITY_ID, x as getConversationStore } from "./viewer-BTgAfdUg.js";
6
6
  import { s as juniorConversations } from "./agent-invocations-C1RNOCs8.js";
7
- import "./executor-4vhvsMZJ.js";
8
- import { h as credentialSubjectSchema } from "./registry-BgecKva0.js";
9
- import { $t as verifyTimerWatchCredentialSubject, G as normalizeSlackReplyMarkdown, U as escapeSlackMrkdwnText, W as formatSlackLink, Yn as buildSentryConversationUrl, hn as getDashboardObjectIconLink, l as getPluginSlackConversationLink, mn as getDashboardConversationLink, p as getPlugins, pn as JUNIOR_THREAD_STATE_TTL_MS, tt as postSlackMessage, yn as ToolInputError } from "./credentialed-lukuD-cc.js";
10
- import { i as getStateAdapter } from "./adapter-04AcD2SO.js";
11
- import { r as EVENT_AUTHOR_ID } from "./prompt-BW9jFsqZ.js";
12
- import { i as sanitizeAssistantText, t as getInterruptionMarker } from "./interruption-marker-CkncDT8d.js";
13
- import { r as appendAndEnqueueInboundMessage } from "./store-zPEoJPBB.js";
7
+ import "./executor-BB6eJkD4.js";
8
+ import { h as credentialSubjectSchema } from "./registry-CndmkP2P.js";
9
+ import { Et as postSlackMessage, Hn as ToolInputError, In as JUNIOR_THREAD_STATE_TTL_MS, Ln as getDashboardConversationLink, Rn as getDashboardObjectIconLink, Sn as verifyTimerWatchCredentialSubject, gt as normalizeSlackReplyMarkdown, ht as formatSlackLink, l as getPluginSlackConversationLink, mt as escapeSlackMrkdwnText, p as getPlugins, vr as buildSentryConversationUrl } from "./credentialed-BeBaJMZ_.js";
10
+ import { r as getStateAdapter } from "./adapter-BQNTKVTF.js";
11
+ import { r as EVENT_AUTHOR_ID } from "./prompt-BPSdXYXV.js";
12
+ import { i as sanitizeAssistantText, t as getInterruptionMarker } from "./interruption-marker-CdblrIQK.js";
13
+ import { r as appendAndEnqueueInboundMessage } from "./store-BeWGgaMA.js";
14
14
  import { z } from "zod";
15
15
  import { eq, inArray } from "drizzle-orm";
16
16
  import { eventMatchFieldsSchema, objectFactFields, objectPresentation, objectTypeSchema } from "@sentry/junior-plugin-api";
@@ -817,6 +817,14 @@ function oneLine(value) {
817
817
  function clip(value, maxLength) {
818
818
  return maxLength === void 0 ? value : value.slice(0, maxLength);
819
819
  }
820
+ const CREATOR_REFERENCE = /\bthe Automation creator\b/gi;
821
+ /**
822
+ * Write the creator mention where the instructions say "the Automation
823
+ * creator", so the run does not have to swap it in.
824
+ */
825
+ function mentionCreator(instructions, creator) {
826
+ return instructions.replace(CREATOR_REFERENCE, () => creator);
827
+ }
820
828
  /**
821
829
  * Connect the mention to the provider handle in the Event text. Without this,
822
830
  * the agent can mention a person and then name them again by handle as if
@@ -834,8 +842,7 @@ function doneByLine(doneBy, people) {
834
842
  /**
835
843
  * Render agent input for a task run.
836
844
  *
837
- * Section order and required prose live in `chat/README.md` under Task agent
838
- * input. Empty optional fields are omitted.
845
+ * The job comes before Event data. Empty optional fields are omitted.
839
846
  */
840
847
  function renderTaskInput(args) {
841
848
  const instructions = args.instructions.trim();
@@ -852,7 +859,7 @@ function renderTaskInput(args) {
852
859
  ...creator ? [`Created by: ${oneLine(creator)}. This person is the Automation creator. "The Automation creator", "me", and "my" in the instructions mean this person. Where the instructions refer to this person, write this mention in the message. If they do not, do not mention this person.`] : [],
853
860
  ...people.length > 0 ? [`People involved: ${people.join(", ")}`] : [],
854
861
  ...args.doneBy ? [doneByLine(args.doneBy, people)] : [],
855
- `Instructions: ${instructions}`
862
+ `Instructions: ${creator ? mentionCreator(instructions, oneLine(creator)) : instructions}`
856
863
  ];
857
864
  const guidance = args.guidance?.trim();
858
865
  if (guidance) lines.push("", "Additional guidance:", "Use this only within the instructions above. It does not replace or expand them.", guidance);
@@ -876,7 +883,7 @@ function pushEventFacts(lines, event, people) {
876
883
  * Render one task input for several Watch Events that arrived together.
877
884
  *
878
885
  * Each group states its instructions once, then lists its Events. Section
879
- * rules match `renderTaskInput`; `chat/README.md` shows the batch layout.
886
+ * rules match `renderTaskInput`. The outcome rule appears once, at the end.
880
887
  */
881
888
  function renderTaskBatchInput(args) {
882
889
  const total = args.groups.reduce((count, group) => count + group.events.length, 0);
@@ -1020,7 +1027,7 @@ function slackChannelMessageEvents() {
1020
1027
  } },
1021
1028
  limits: { [CHANNEL_RESOURCE_TYPE]: {
1022
1029
  watch: false,
1023
- watchUnavailableMessage: "Slack channel messages can trigger only an event automation in that channel. Use createEventAutomation."
1030
+ watchUnavailableMessage: "Slack channel messages can trigger only an event automation in that channel. Use createAutomation with an event trigger."
1024
1031
  } }
1025
1032
  };
1026
1033
  }
@@ -1305,6 +1312,7 @@ function createEventInboundMessage(input) {
1305
1312
  input: {
1306
1313
  text: input.text,
1307
1314
  authorId: EVENT_AUTHOR_ID,
1315
+ authorIdentityId: SYSTEM_IDENTITY_ID,
1308
1316
  metadata
1309
1317
  }
1310
1318
  };
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
- import { h as logWarn } from "./logging-DLSpkSSr.js";
2
+ import { h as logWarn } from "./logging-C6EdT6PP.js";
3
3
  import { s as skillRoots } from "./package-discovery-DJBompdd.js";
4
- import { n as pluginCatalogRuntime } from "./catalog-runtime-BD9GSpc6.js";
4
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-Bdym_wKy.js";
5
5
  import path from "node:path";
6
6
  import { z } from "zod";
7
7
  import fs from "node:fs/promises";
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
- import { Bt as actorFromRun, Vt as toolInvocationDestination } from "./agent-runner-CAYfFmU7.js";
3
- import { n as createAndEnqueueAgentInvocation } from "./work-3N-GHY9m.js";
2
+ import { At as actorFromRun, jt as toolInvocationDestination } from "./agent-runner-MSQSMFkq.js";
3
+ import { n as createAndEnqueueAgentInvocation } from "./work-Bjm52fHo.js";
4
4
  // src/chat/agent-invocations/spawn.ts
5
5
  var spawn_exports = /* @__PURE__ */ __exportAll({ bindSpawnAgent: () => bindSpawnAgent });
6
6
  /** Bind a Run's Actor and credentials to new Agent invocations. */
@@ -1,6 +1,6 @@
1
- import { Cn as removeActiveConversation$1, Dn as steerWebPendingMessages$1, En as startConversationWork$1, On as stopConversationWork$1, Sn as releaseConversationWork$1, Tn as requestConversationWork$1, an as checkInConversationWork$1, bn as recordAttemptFailure$1, cn as completeConversationStop$1, dn as drainConversationMailbox$1, en as ackMessages$1, fn as getConversation$1, in as cancelHumanFacingPendingMessages$1, ln as completeConversationWork$1, nn as appendInboundMessage, on as clearConsumedConversationWake$1, pn as getConversationWorkState$1, rn as beginConversationResume$1, sn as clearExpiredConversationLease$1, tn as appendExclusiveInboundMessage, un as deadLetterAttempt$1, vn as listActiveConversationIds$1, wn as requestAnotherSlice$1, xn as recordConversationRetry$1, yn as markConversationWorkEnqueued$1 } from "./tasks-SB9z-VTU.js";
2
- import { p as getConversationStore } from "./viewer-CpXTGlep.js";
3
- import "./job-queue-In9QKz-I.js";
1
+ import { $n as recordAttemptFailure$1, Bn as clearExpiredConversationLease$1, Fn as appendInboundMessage, Gn as getConversation$1, Hn as completeConversationWork$1, In as beginConversationResume$1, Kn as getConversationWorkState$1, Ln as cancelHumanFacingPendingMessages$1, Nn as ackMessages$1, Pn as appendExclusiveInboundMessage, Qn as markConversationWorkEnqueued$1, Rn as checkInConversationWork$1, Un as deadLetterAttempt$1, Vn as completeConversationStop$1, Wn as drainConversationMailbox$1, Zn as listActiveConversationIds$1, ar as startConversationWork$1, er as recordConversationRetry$1, ir as requestConversationWork$1, nr as removeActiveConversation$1, or as steerWebPendingMessages$1, rr as requestAnotherSlice$1, sr as stopConversationWork$1, tr as releaseConversationWork$1, zn as clearConsumedConversationWake$1 } from "./turn-session-routing-B9KLBhaT.js";
2
+ import { x as getConversationStore } from "./viewer-BTgAfdUg.js";
3
+ import "./job-queue-DiaXoSDg.js";
4
4
  // src/chat/task-execution/store.ts
5
5
  function metadataStore(options) {
6
6
  return options.conversationStore ?? getConversationStore();
@@ -1,8 +1,8 @@
1
- import { l as TURN_REASONING_LEVELS, s as modelProfileSchema } from "./model-profile-Bg8EoCKD.js";
2
- import { h as getSqlExecutor, p as getConversationStore } from "./viewer-CpXTGlep.js";
1
+ import { c as modelProfileSchema, u as TURN_REASONING_LEVELS } from "./model-profile-B998sjVd.js";
2
+ import { C as getSqlExecutor, x as getConversationStore } from "./viewer-BTgAfdUg.js";
3
3
  import { a as juniorAgentInvocations, i as juniorAgentBindings, n as AGENT_INVOCATION_PARENT_MAILBOX_STATUSES, t as AGENT_INVOCATION_MAILBOX_STATUSES } from "./agent-invocations-C1RNOCs8.js";
4
- import "./executor-4vhvsMZJ.js";
5
- import { p as credentialContextSchema } from "./registry-BgecKva0.js";
4
+ import "./executor-BB6eJkD4.js";
5
+ import { p as credentialContextSchema } from "./registry-CndmkP2P.js";
6
6
  import { z } from "zod";
7
7
  import { createHash } from "node:crypto";
8
8
  import { and, asc, count, countDistinct, desc, eq, inArray, lt, ne, or, sql } from "drizzle-orm";
@@ -1,5 +1,5 @@
1
- import { h as logWarn } from "./logging-DLSpkSSr.js";
2
- import { c as QUEUE_SIGNATURE_MAX_AGE_MS, d as getQueueProvider, l as signQueueMessage, p as runWithTurnRequestDeadline, u as verifyQueueMessage } from "./job-queue-In9QKz-I.js";
1
+ import { h as logWarn } from "./logging-C6EdT6PP.js";
2
+ import { c as QUEUE_SIGNATURE_MAX_AGE_MS, d as getQueueProvider, l as signQueueMessage, p as runWithTurnRequestDeadline, u as verifyQueueMessage } from "./job-queue-DiaXoSDg.js";
3
3
  import { z } from "zod";
4
4
  import { createHash } from "node:crypto";
5
5
  // src/chat/queue/callback.ts
@@ -110,7 +110,7 @@ function pluginTaskCallback() {
110
110
  maxDeliveries: PLUGIN_TASK_MAX_DELIVERIES,
111
111
  onRejected: logPluginTaskQueueMessageRejected,
112
112
  run: async (message) => {
113
- const { processPluginTask } = await import("./task-runner-DMI2prDO.js").then((n) => n.r);
113
+ const { processPluginTask } = await import("./task-runner-DyKqAPpm.js").then((n) => n.r);
114
114
  await processPluginTask(message);
115
115
  },
116
116
  topic: PLUGIN_TASK_QUEUE_TOPIC,
@@ -0,0 +1,269 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
+ import { Dr as normalizeToolNameFromResult, Er as isToolResultMessage, Gt as hydrateConversationMessages, On as getTurnRecord, Sr as instructionTextForProjection, Tr as isToolResultError, kr as stripRuntimeTurnContext, t as resolveConversationRouting, u as getDispatchRecord, vr as getPiMessageRole } from "./turn-session-routing-B9KLBhaT.js";
3
+ import { m as parseSlackMessageTs } from "./actor-CP9K2Idu.js";
4
+ import { S as getDb, i as readActorIdentity, x as getConversationStore } from "./viewer-BTgAfdUg.js";
5
+ import { _ as sameActorIdentity } from "./media-U6Tuz6Mi.js";
6
+ import { ar as createPluginLogger, g as coreTaskRegistrations, hr as createPluginConversationEvents, ir as createPluginModel, jr as createPluginCache, nr as createPluginState, p as getPlugins, rr as createPluginEmbedder } from "./credentialed-BeBaJMZ_.js";
7
+ import { r as getStateAdapter } from "./adapter-BQNTKVTF.js";
8
+ import { o as coerceThreadConversationState, r as getPersistedThreadState } from "./thread-state-BHBLMvgb.js";
9
+ import { i as pluginTaskParamsSchema, r as pluginTaskId, s as sendVercelPluginTask } from "./task-queue-Dt1_ZoI_.js";
10
+ import { pluginRunContextSchema } from "@sentry/junior-plugin-api";
11
+ // src/chat/plugins/task-runner.ts
12
+ /**
13
+ * Plugin background-task orchestration.
14
+ *
15
+ * Core schedules tasks from completed sessions and exposes plugins only a
16
+ * bounded run projection rather than live runtime internals or queue
17
+ * payloads.
18
+ */
19
+ var task_runner_exports = /* @__PURE__ */ __exportAll({
20
+ processPluginTask: () => processPluginTask,
21
+ scheduleSessionCompletedPluginTasks: () => scheduleSessionCompletedPluginTasks
22
+ });
23
+ const PLUGIN_TASK_LOCK_TTL_MS = 3e5;
24
+ function isRecord(value) {
25
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
26
+ }
27
+ function textPart(value) {
28
+ if (isRecord(value) && value.type === "text" && typeof value.text === "string") return value.text;
29
+ }
30
+ function messageText(message) {
31
+ const content = message.content;
32
+ if (typeof content === "string") return sanitizeText(content);
33
+ if (!Array.isArray(content)) return "";
34
+ return sanitizeText(content.map(textPart).filter(Boolean).join("\n"));
35
+ }
36
+ function toolResultText(message) {
37
+ const record = message;
38
+ return sanitizeText([
39
+ messageText(message),
40
+ record.output,
41
+ record.result,
42
+ record.stdout,
43
+ record.stderr,
44
+ record.toolResult
45
+ ].filter((value) => typeof value === "string" && value.length > 0).join("\n"));
46
+ }
47
+ function sanitizeText(text) {
48
+ return text.replace(/<data_base64>[\s\S]*?<\/data_base64>/g, "<data_base64>[omitted]</data_base64>").replace(/data:image\/[a-z0-9.+-]+;base64,[a-z0-9+/=]+/gi, "[image data omitted]").replaceAll("\0", " ").trim();
49
+ }
50
+ /** Build the transcript provenance for a user message from its Pi provenance. */
51
+ function messageProvenance(provenance) {
52
+ return {
53
+ authority: provenance.authority,
54
+ ...provenance.actor ? { actor: provenance.actor } : void 0
55
+ };
56
+ }
57
+ function runTranscriptEntry(message, provenance, runActor) {
58
+ const role = getPiMessageRole(message);
59
+ if (role === "user" || role === "assistant") {
60
+ const text = role === "user" ? instructionTextForProjection(messageText(message)) : messageText(message);
61
+ if (!text) return;
62
+ if (role === "assistant") return {
63
+ type: "message",
64
+ role,
65
+ text
66
+ };
67
+ return {
68
+ type: "message",
69
+ role,
70
+ text,
71
+ provenance: messageProvenance(provenance),
72
+ isRunActor: sameActorIdentity(provenance.actor, runActor)
73
+ };
74
+ }
75
+ if (!isToolResultMessage(message)) return;
76
+ const toolName = normalizeToolNameFromResult(message);
77
+ if (!toolName) return;
78
+ const text = toolResultText(message);
79
+ return {
80
+ type: "toolResult",
81
+ toolName,
82
+ isError: isToolResultError(message),
83
+ ...text ? { text } : void 0
84
+ };
85
+ }
86
+ /**
87
+ * Slice the current turn's Pi messages with their aligned provenance and strip
88
+ * runtime turn context, keeping each surviving message paired with the exact
89
+ * provenance recorded for it. Stripping can drop or rewrite messages, so the
90
+ * pairing is applied per message rather than by post-strip index.
91
+ */
92
+ function turnMessagesWithProvenance(record) {
93
+ const startIndex = record.turnStartMessageIndex ?? 0;
94
+ const messages = record.piMessages.slice(startIndex);
95
+ const provenance = record.piMessageProvenance.slice(startIndex);
96
+ const paired = [];
97
+ for (const [index, message] of messages.entries()) for (const stripped of stripRuntimeTurnContext([message])) paired.push({
98
+ message: stripped,
99
+ provenance: provenance[index] ?? { authority: "context" }
100
+ });
101
+ return paired;
102
+ }
103
+ /** Recover the Slack context author identity from a persisted thread message. */
104
+ function slackContextAuthor(location, message) {
105
+ const userId = message.author?.userId?.trim();
106
+ if (!userId) return;
107
+ return {
108
+ platform: "slack",
109
+ teamId: location.teamId,
110
+ userId,
111
+ ...message.author?.userName ? { userName: message.author.userName } : void 0,
112
+ ...message.author?.fullName ? { fullName: message.author.fullName } : void 0
113
+ };
114
+ }
115
+ function slackTimestampMs(value) {
116
+ const timestamp = parseSlackMessageTs(value);
117
+ if (!timestamp) return;
118
+ const timestampMs = Number(timestamp) * 1e3;
119
+ return Number.isFinite(timestampMs) ? timestampMs : void 0;
120
+ }
121
+ function conversationMessageTimestampMs(message) {
122
+ if (message.meta?.slackTs !== void 0) return slackTimestampMs(message.meta.slackTs);
123
+ return Number.isFinite(message.createdAtMs) ? message.createdAtMs : void 0;
124
+ }
125
+ function messageExistedAtRunCompletion(message, completedAtMs) {
126
+ const messageTimestampMs = conversationMessageTimestampMs(message);
127
+ return messageTimestampMs !== void 0 && messageTimestampMs <= completedAtMs;
128
+ }
129
+ /**
130
+ * Project bounded public-thread context into the run transcript.
131
+ *
132
+ * Prior public Slack messages from the current Conversation are durable
133
+ * evidence a completed run may have acted on, so passive consumers can cite
134
+ * them. They are always context authority (never instruction), and private or
135
+ * local Conversations add nothing here.
136
+ */
137
+ async function loadConversationContextTranscriptEntries(record, location, visibility, runActor) {
138
+ if (location?.provider !== "slack" || visibility !== "public") return [];
139
+ const state = await getPersistedThreadState(record.conversationId);
140
+ const conversation = coerceThreadConversationState(state);
141
+ await hydrateConversationMessages({
142
+ conversation,
143
+ conversationId: record.conversationId
144
+ });
145
+ const entries = [];
146
+ for (const message of conversation.messages) {
147
+ if (message.role !== "user") continue;
148
+ if (!messageExistedAtRunCompletion(message, record.updatedAtMs)) continue;
149
+ const text = sanitizeText(message.text);
150
+ if (!text) continue;
151
+ const author = slackContextAuthor(location, message);
152
+ entries.push({
153
+ type: "message",
154
+ role: "user",
155
+ text,
156
+ provenance: {
157
+ authority: "context",
158
+ ...author ? { actor: author } : void 0
159
+ },
160
+ isRunActor: sameActorIdentity(author, runActor)
161
+ });
162
+ }
163
+ return entries;
164
+ }
165
+ async function withPluginTaskLock(taskId, callback) {
166
+ const state = getStateAdapter();
167
+ await state.connect();
168
+ const lock = await state.acquireLock(`plugin:task:${taskId}`, PLUGIN_TASK_LOCK_TTL_MS);
169
+ if (!lock) throw new Error(`Could not acquire plugin task lock for ${taskId}`);
170
+ try {
171
+ return await callback();
172
+ } finally {
173
+ await state.releaseLock(lock);
174
+ }
175
+ }
176
+ /** Load the bounded completed-run projection exposed to plugin tasks. */
177
+ async function loadPluginRun(params) {
178
+ const record = await getTurnRecord(params.conversationId, params.sessionId);
179
+ if (!record) throw new Error("Completed plugin task session record is unavailable");
180
+ if (record.state !== "completed") throw new Error("Completed plugin task session record is not completed");
181
+ const conversationStore = getConversationStore();
182
+ const routing = await resolveConversationRouting({
183
+ conversationId: params.conversationId,
184
+ conversationStore
185
+ });
186
+ if (!routing) throw new Error(`Conversation ${params.conversationId} is missing durable routing metadata`);
187
+ const source = record.source ?? routing.source;
188
+ if (!source) throw new Error("Completed plugin task session record is missing Source");
189
+ const conversation = await conversationStore.get({ conversationId: params.conversationId });
190
+ const runActor = record.actor ?? record.actors[0] ?? (record.dispatchId ? (await getDispatchRecord(record.dispatchId))?.actor : void 0);
191
+ const actorUser = runActor ? (await readActorIdentity(runActor))?.user : void 0;
192
+ const runEntries = turnMessagesWithProvenance(record).map(({ message, provenance }) => runTranscriptEntry(message, provenance, runActor)).filter((entry) => Boolean(entry));
193
+ const runMessageTexts = new Set(runEntries.filter((entry) => entry.type === "message").map((entry) => entry.text));
194
+ const contextEntries = (await loadConversationContextTranscriptEntries(record, conversation?.location, conversation?.visibility, runActor)).filter((entry) => entry.type !== "message" || !runMessageTexts.has(entry.text));
195
+ return pluginRunContextSchema.parse({
196
+ ...actorUser ? { actorUserId: actorUser.id } : void 0,
197
+ completedAtMs: record.updatedAtMs,
198
+ conversationId: record.conversationId,
199
+ destination: routing.destination,
200
+ ...routing.location ? { locationId: routing.location.id } : void 0,
201
+ actors: record.actors,
202
+ ...runActor ? { actor: runActor } : void 0,
203
+ runId: record.turnId,
204
+ source,
205
+ transcript: [...contextEntries, ...runEntries]
206
+ });
207
+ }
208
+ /** Build the plugin-facing context for one claimed task attempt. */
209
+ function taskPluginContext(plugin, message, options = {}) {
210
+ const pluginName = plugin.manifest.name;
211
+ const sessionParams = pluginTaskParamsSchema.parse(message.params);
212
+ return {
213
+ db: getDb(),
214
+ embedder: createPluginEmbedder(pluginName, { signal: options.signal }),
215
+ events: createPluginConversationEvents({
216
+ conversationId: sessionParams.conversationId,
217
+ operationId: pluginTaskId(message),
218
+ plugin,
219
+ turnId: sessionParams.sessionId
220
+ }),
221
+ id: pluginTaskId(message),
222
+ log: createPluginLogger(pluginName),
223
+ model: createPluginModel(pluginName, plugin.model, { signal: options.signal }),
224
+ name: message.name,
225
+ plugin: { name: pluginName },
226
+ cache: createPluginCache(pluginName),
227
+ run: { async load() {
228
+ return await loadPluginRun(sessionParams);
229
+ } },
230
+ state: createPluginState(pluginName)
231
+ };
232
+ }
233
+ function findPluginTask(message) {
234
+ const plugin = [...coreTaskRegistrations(), ...getPlugins()].find((candidate) => candidate.manifest.name === message.plugin);
235
+ if (!plugin?.tasks || !Object.hasOwn(plugin.tasks, message.name)) return;
236
+ return {
237
+ plugin,
238
+ task: plugin.tasks[message.name]
239
+ };
240
+ }
241
+ /** Schedule all plugin tasks interested in a completed agent-run session. */
242
+ async function scheduleSessionCompletedPluginTasks(params, options = {}) {
243
+ const coreParams = pluginTaskParamsSchema.parse(params);
244
+ const taskRegistrations = [...getPlugins(), ...coreTaskRegistrations()].flatMap((plugin) => Object.keys(plugin.tasks ?? {}).map((name) => ({
245
+ name,
246
+ plugin
247
+ })));
248
+ if (taskRegistrations.length === 0) return;
249
+ const record = await getTurnRecord(coreParams.conversationId, coreParams.sessionId);
250
+ if (!record || record.state !== "completed") throw new Error("Completed plugin task session record is not ready");
251
+ const send = options.send ?? sendVercelPluginTask;
252
+ const messages = taskRegistrations.map(({ name, plugin }) => ({
253
+ name,
254
+ params: coreParams,
255
+ plugin: plugin.manifest.name
256
+ }));
257
+ await Promise.all(messages.map(async (message) => {
258
+ await send(message);
259
+ }));
260
+ }
261
+ /** Execute one parsed plugin task request. */
262
+ async function processPluginTask(message, options = {}) {
263
+ await withPluginTaskLock(pluginTaskId(message), async () => {
264
+ const resolved = findPluginTask(message);
265
+ if (!resolved?.task) throw new Error(`Plugin task "${message.plugin}.${message.name}" is not registered`);
266
+ await resolved.task.run(taskPluginContext(resolved.plugin, message, options));
267
+ });
268
+ }
269
+ export { scheduleSessionCompletedPluginTasks as n, task_runner_exports as r, processPluginTask as t };
@@ -1,8 +1,8 @@
1
- import { fr as createDurableLocationConfigurationService, pt as persistConversationMessages } from "./tasks-SB9z-VTU.js";
2
- import { B as isRecord, H as toOptionalString, V as toOptionalNumber } from "./logging-DLSpkSSr.js";
3
- import { m as getDb } from "./viewer-CpXTGlep.js";
4
- import { pn as JUNIOR_THREAD_STATE_TTL_MS } from "./credentialed-lukuD-cc.js";
5
- import { i as getStateAdapter } from "./adapter-04AcD2SO.js";
1
+ import { Kr as createDurableLocationConfigurationService, Kt as persistConversationMessages } from "./turn-session-routing-B9KLBhaT.js";
2
+ import { B as isRecord, H as toOptionalString, V as toOptionalNumber } from "./logging-C6EdT6PP.js";
3
+ import { S as getDb } from "./viewer-BTgAfdUg.js";
4
+ import { In as JUNIOR_THREAD_STATE_TTL_MS } from "./credentialed-BeBaJMZ_.js";
5
+ import { r as getStateAdapter } from "./adapter-BQNTKVTF.js";
6
6
  // src/chat/state/conversation.ts
7
7
  function defaultConversationState() {
8
8
  return {
@@ -1,13 +1,13 @@
1
- import { Bt as clearPendingAuth, Et as markConversationMessage, ft as hydrateConversationMessages, tr as buildDeterministicTurnId } from "./tasks-SB9z-VTU.js";
2
- import { _ as getProviderErrorAttributes, g as findProviderError, m as ProviderError, v as getProviderErrorUserMessage } from "./client-C1yDYjoS.js";
3
- import { B as isRecord, t as buildTurnFailureResponse } from "./logging-DLSpkSSr.js";
1
+ import { Fr as buildDeterministicTurnId, Gt as hydrateConversationMessages, an as markConversationMessage, yn as clearPendingAuth } from "./turn-session-routing-B9KLBhaT.js";
2
+ import { _ as getProviderErrorAttributes, g as findProviderError, m as ProviderError, v as getProviderErrorUserMessage } from "./client-B2MjENki.js";
3
+ import { B as isRecord, t as buildTurnFailureResponse } from "./logging-C6EdT6PP.js";
4
4
  import { m as parseSlackMessageTs } from "./actor-CP9K2Idu.js";
5
- import { d as getConversationEventStore, m as getDb } from "./viewer-CpXTGlep.js";
6
- import { rr as listConversationAnnotations } from "./credentialed-lukuD-cc.js";
7
- import { B as removedCardSchema, V as resolveMessageCards, z as readMessageCardRefs } from "./conversation-DSo310Ps.js";
8
- import { D as parseAgentInvocationResultMessageId, J as markTurnClosed, Y as markTurnCompleted, c as getAgentInvocation, m as getAgentInvocationTurnId } from "./store-C5PN02QO.js";
9
- import { t as getInterruptionMarker } from "./interruption-marker-CkncDT8d.js";
10
- import { a as persistThreadStateById, o as coerceThreadConversationState, r as getPersistedThreadState } from "./thread-state-BbbPh0Sn.js";
5
+ import { S as getDb, y as getConversationEventStore } from "./viewer-BTgAfdUg.js";
6
+ import { Er as listConversationAnnotations } from "./credentialed-BeBaJMZ_.js";
7
+ import { B as removedCardSchema, V as resolveMessageCards, z as readMessageCardRefs } from "./conversation-AhOVzN_k.js";
8
+ import { D as parseAgentInvocationResultMessageId, J as markTurnClosed, Y as markTurnCompleted, c as getAgentInvocation, m as getAgentInvocationTurnId } from "./store-Byarin7b.js";
9
+ import { t as getInterruptionMarker } from "./interruption-marker-CdblrIQK.js";
10
+ import { a as persistThreadStateById, o as coerceThreadConversationState, r as getPersistedThreadState } from "./thread-state-BHBLMvgb.js";
11
11
  // src/chat/conversations/pending-cards.ts
12
12
  /**
13
13
  * Add the cards that tool results selected since the last visible assistant
@@ -1,4 +1,4 @@
1
- import { d as getConversationEventStore } from "./viewer-CpXTGlep.js";
1
+ import { y as getConversationEventStore } from "./viewer-BTgAfdUg.js";
2
2
  // src/chat/conversations/turn-lifecycle.ts
3
3
  /** Persist correlated turn lifecycle facts with retry-safe terminal exclusion. */
4
4
  var ConversationTurnLifecycleService = class {