@sentry/junior 0.132.0 → 0.134.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/dist/{agent-hooks-ONXOJDR6.js → agent-hooks-HGXNYOOD.js} +9 -9
  2. package/dist/api/schema/task.d.ts +60 -0
  3. package/dist/api/schema.d.ts +2 -2
  4. package/dist/api/schema.js +3 -1
  5. package/dist/api.js +90 -20
  6. package/dist/app.js +110 -39
  7. package/dist/{catalog-runtime-BATAY4R7.js → catalog-runtime-P6QHU6XE.js} +5 -5
  8. package/dist/chat/agent/prompt.d.ts +7 -5
  9. package/dist/chat/agent/repository-context.d.ts +20 -0
  10. package/dist/chat/agent/sandbox.d.ts +8 -0
  11. package/dist/chat/agent/tools.d.ts +3 -0
  12. package/dist/chat/config.d.ts +2 -0
  13. package/dist/chat/conversations/projection.d.ts +3 -1
  14. package/dist/chat/conversations/sql/bindings.d.ts +13 -0
  15. package/dist/chat/conversations/sql/store.d.ts +3 -0
  16. package/dist/chat/conversations/store.d.ts +15 -0
  17. package/dist/chat/plugins/agent-hooks.d.ts +2 -2
  18. package/dist/chat/repository-instructions.d.ts +44 -0
  19. package/dist/chat/runtime/reply-executor.d.ts +1 -0
  20. package/dist/chat/runtime/slack-runtime.d.ts +2 -0
  21. package/dist/chat/sandbox/noninteractive-command.d.ts +2 -0
  22. package/dist/chat/sandbox/sandbox.d.ts +3 -0
  23. package/dist/chat/sandbox/session.d.ts +1 -0
  24. package/dist/chat/services/context-compaction.d.ts +1 -0
  25. package/dist/chat/slack/dispatch-turn.d.ts +1 -0
  26. package/dist/chat/slack/reply.d.ts +1 -1
  27. package/dist/chat/slack/tools/user-lookup.d.ts +2 -6
  28. package/dist/chat/tasks/execution-stats.d.ts +29 -0
  29. package/dist/chat/tasks/registered.d.ts +3 -0
  30. package/dist/chat/tools/index.d.ts +2 -0
  31. package/dist/chat/tools/sandbox/bash.d.ts +1 -0
  32. package/dist/chat/tools/system-time.d.ts +11 -1
  33. package/dist/{chunk-O2UXPUVQ.js → chunk-52DIKFJV.js} +14 -6
  34. package/dist/{chunk-GOEZU33G.js → chunk-6T3AYZT7.js} +1 -1
  35. package/dist/{chunk-GPXVDJML.js → chunk-7GKQ7UIO.js} +449 -39
  36. package/dist/{chunk-QVEXYYFM.js → chunk-7UTBPDXK.js} +24 -1
  37. package/dist/{chunk-U76PS7AT.js → chunk-AS3I7OIL.js} +2 -2
  38. package/dist/{chunk-HX236W2U.js → chunk-CDQ4YIZM.js} +9 -0
  39. package/dist/{chunk-ODIP5CEM.js → chunk-FDNAUM7X.js} +32 -32
  40. package/dist/{chunk-GTKNPQNN.js → chunk-FL466XX5.js} +36 -24
  41. package/dist/{chunk-2425Q4OR.js → chunk-GSP5SMZJ.js} +1 -1
  42. package/dist/{chunk-XN656LB4.js → chunk-KWGJG4HO.js} +6 -12
  43. package/dist/{chunk-ISNRPCPG.js → chunk-LKK4XMUV.js} +1 -1
  44. package/dist/{chunk-G3WYA2RS.js → chunk-MFERLE3G.js} +1 -1
  45. package/dist/{chunk-ZMV2YBT6.js → chunk-NF2TNZPD.js} +788 -674
  46. package/dist/chunk-NOA34AJY.js +122 -0
  47. package/dist/{chunk-JYQAE2ZU.js → chunk-NYWSCJVW.js} +1 -1
  48. package/dist/{chunk-KB2M27DL.js → chunk-QLEKAO7O.js} +130 -40
  49. package/dist/{chunk-BKE47OOW.js → chunk-S6DMTEOM.js} +2 -2
  50. package/dist/{chunk-ALDPUN3Z.js → chunk-TR6UEEYD.js} +8 -6
  51. package/dist/{chunk-WEJIS7OC.js → chunk-U3ZI7CCW.js} +1 -1
  52. package/dist/{chunk-B7IY6SVJ.js → chunk-VEGF62FV.js} +1 -1
  53. package/dist/{chunk-SKWIIUS7.js → chunk-VGXJMECA.js} +7 -7
  54. package/dist/{chunk-V44FFBO3.js → chunk-VP6NCPRS.js} +1 -1
  55. package/dist/{chunk-WYQP7QSB.js → chunk-VPYKNCTN.js} +101 -61
  56. package/dist/{chunk-NNHUGGO4.js → chunk-XG5PHKPM.js} +19 -3
  57. package/dist/{chunk-AW5Z3T7V.js → chunk-YNLQQ622.js} +9 -8
  58. package/dist/cli/chat.js +25 -25
  59. package/dist/cli/check.js +6 -6
  60. package/dist/cli/init.js +1 -1
  61. package/dist/cli/plugins.js +12 -12
  62. package/dist/cli/snapshot-create.js +9 -9
  63. package/dist/cli/upgrade.js +9 -8
  64. package/dist/db/executor.d.ts +2 -1
  65. package/dist/db/neon.d.ts +1 -0
  66. package/dist/db/postgres.d.ts +1 -0
  67. package/dist/db/schema/conversation-bindings.d.ts +110 -0
  68. package/dist/db/schema/task-executions.d.ts +110 -0
  69. package/dist/db/schema.d.ts +221 -1
  70. package/dist/{db-QFFZACXF.js → db-GFK4NHWJ.js} +7 -7
  71. package/dist/instrumentation.js +4 -4
  72. package/dist/nitro.js +2 -2
  73. package/dist/{oauth-callback-server-5WXLD533.js → oauth-callback-server-HUJLAQ5N.js} +19 -18
  74. package/dist/{runner-Y3LTUNAA.js → runner-T77AFAH4.js} +13 -12
  75. package/dist/{skills-7M5C24GM.js → skills-3KUFJOOR.js} +6 -6
  76. package/dist/{validation-MRILMYDI.js → validation-FMWDHKYU.js} +6 -6
  77. package/dist/version.js +1 -1
  78. package/migrations/0018_curvy_excalibur.sql +12 -0
  79. package/migrations/0019_lowly_valkyrie.sql +14 -0
  80. package/migrations/meta/0018_snapshot.json +1756 -0
  81. package/migrations/meta/0019_snapshot.json +1904 -0
  82. package/migrations/meta/_journal.json +15 -1
  83. package/package.json +5 -5
package/dist/app.js CHANGED
@@ -50,7 +50,7 @@ import {
50
50
  startConversationWork,
51
51
  startSlackProcessingReaction,
52
52
  stripLeadingBotMention
53
- } from "./chunk-GTKNPQNN.js";
53
+ } from "./chunk-FL466XX5.js";
54
54
  import "./chunk-FA6POGLH.js";
55
55
  import {
56
56
  ConversationTurnLifecycleService,
@@ -65,14 +65,17 @@ import {
65
65
  processPluginTask,
66
66
  requireTurnFailureEventId,
67
67
  scheduleSessionCompletedPluginTasks
68
- } from "./chunk-O2UXPUVQ.js";
68
+ } from "./chunk-52DIKFJV.js";
69
69
  import {
70
70
  GET,
71
71
  conversationVisibilityFromSlackChannelType,
72
72
  resolveSlackChannelTypeFromMessage,
73
73
  resolveSlackConversationContext
74
- } from "./chunk-U76PS7AT.js";
74
+ } from "./chunk-AS3I7OIL.js";
75
75
  import "./chunk-4CODA7P5.js";
76
+ import {
77
+ recordTaskExecution
78
+ } from "./chunk-NOA34AJY.js";
76
79
  import "./chunk-UTL3MHPC.js";
77
80
  import {
78
81
  ConversationQueueMessageRejectedError,
@@ -90,7 +93,7 @@ import {
90
93
  import {
91
94
  validatePluginEgressCredentialHooks,
92
95
  validatePluginRegistrations
93
- } from "./chunk-JYQAE2ZU.js";
96
+ } from "./chunk-NYWSCJVW.js";
94
97
  import {
95
98
  defineJuniorPlugins,
96
99
  pluginCatalogConfigFromEnv,
@@ -125,7 +128,7 @@ import {
125
128
  setConfigDefaults,
126
129
  shouldEmitDevAgentTrace,
127
130
  shouldPropagateSandboxEgressTrace
128
- } from "./chunk-ZMV2YBT6.js";
131
+ } from "./chunk-NF2TNZPD.js";
129
132
  import "./chunk-DIB4GX3G.js";
130
133
  import {
131
134
  RetryableDeliveryError,
@@ -136,7 +139,7 @@ import {
136
139
  formatProviderLabel,
137
140
  postSlackMessage,
138
141
  startOAuthFlow
139
- } from "./chunk-SKWIIUS7.js";
142
+ } from "./chunk-VGXJMECA.js";
140
143
  import {
141
144
  ConversationTurnBoundaryError,
142
145
  CooperativeTurnYieldError,
@@ -192,20 +195,20 @@ import {
192
195
  trimTrailingAssistantMessages,
193
196
  updateConversationStats,
194
197
  upsertConversationMessage
195
- } from "./chunk-GPXVDJML.js";
198
+ } from "./chunk-7GKQ7UIO.js";
196
199
  import "./chunk-EPBBYMNE.js";
197
200
  import {
198
201
  getSandboxResourceConfig,
199
202
  setSandboxResourceConfig
200
- } from "./chunk-AW5Z3T7V.js";
203
+ } from "./chunk-YNLQQ622.js";
201
204
  import {
202
205
  createSchedulerSqlStore,
203
206
  findMatchingEventTasks
204
- } from "./chunk-XN656LB4.js";
207
+ } from "./chunk-KWGJG4HO.js";
205
208
  import {
206
209
  parseSlackThreadId
207
- } from "./chunk-G3WYA2RS.js";
208
- import "./chunk-HX236W2U.js";
210
+ } from "./chunk-MFERLE3G.js";
211
+ import "./chunk-CDQ4YIZM.js";
209
212
  import "./chunk-PDO5BLNM.js";
210
213
  import "./chunk-UIE3R5XU.js";
211
214
  import {
@@ -232,7 +235,7 @@ import {
232
235
  verifyEventTaskCredentialSubject,
233
236
  verifyScheduledTaskCredentialSubject,
234
237
  verifySlackDirectCredentialSubject
235
- } from "./chunk-ALDPUN3Z.js";
238
+ } from "./chunk-TR6UEEYD.js";
236
239
  import {
237
240
  contextProvenance,
238
241
  createSlackDestination,
@@ -243,16 +246,16 @@ import {
243
246
  instructionProvenanceFor,
244
247
  requireSlackDestination,
245
248
  withConversationEventLock
246
- } from "./chunk-WYQP7QSB.js";
249
+ } from "./chunk-VPYKNCTN.js";
247
250
  import {
248
251
  juniorConversationEvents,
249
252
  juniorConversations
250
- } from "./chunk-KB2M27DL.js";
253
+ } from "./chunk-QLEKAO7O.js";
251
254
  import {
252
255
  acquireActiveLock,
253
256
  getStateAdapter,
254
257
  sleep
255
- } from "./chunk-ODIP5CEM.js";
258
+ } from "./chunk-FDNAUM7X.js";
256
259
  import {
257
260
  STANDARD_MODEL_PROFILE,
258
261
  botConfig,
@@ -270,16 +273,16 @@ import {
270
273
  modelIdForProfile,
271
274
  setSlackReactionConfig,
272
275
  standardModelId
273
- } from "./chunk-NNHUGGO4.js";
276
+ } from "./chunk-XG5PHKPM.js";
274
277
  import {
275
278
  juniorDestinations
276
279
  } from "./chunk-VFUK3X5B.js";
277
- import "./chunk-ISNRPCPG.js";
278
- import "./chunk-BKE47OOW.js";
280
+ import "./chunk-LKK4XMUV.js";
281
+ import "./chunk-S6DMTEOM.js";
279
282
  import {
280
283
  pluginCatalogRuntime
281
- } from "./chunk-B7IY6SVJ.js";
282
- import "./chunk-V44FFBO3.js";
284
+ } from "./chunk-VEGF62FV.js";
285
+ import "./chunk-VP6NCPRS.js";
283
286
  import {
284
287
  credentialSubjectSchema
285
288
  } from "./chunk-77VDLF3Z.js";
@@ -311,7 +314,7 @@ import {
311
314
  withContext,
312
315
  withLogContext,
313
316
  withSpan
314
- } from "./chunk-GOEZU33G.js";
317
+ } from "./chunk-6T3AYZT7.js";
315
318
  import {
316
319
  continueTrace
317
320
  } from "./chunk-6GWA276C.js";
@@ -319,10 +322,10 @@ import "./chunk-OOUNJNMR.js";
319
322
  import "./chunk-H4HBKISO.js";
320
323
  import {
321
324
  JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE
322
- } from "./chunk-WEJIS7OC.js";
325
+ } from "./chunk-U3ZI7CCW.js";
323
326
  import {
324
327
  JUNIOR_VERSION
325
- } from "./chunk-2425Q4OR.js";
328
+ } from "./chunk-GSP5SMZJ.js";
326
329
  import "./chunk-MLKGABMK.js";
327
330
 
328
331
  // src/app.ts
@@ -697,7 +700,8 @@ async function markDispatchBlocked(id, errorMessage, resultMessageTs) {
697
700
  );
698
701
  }
699
702
  async function markDispatchCompleted(id, resultMessageTs) {
700
- return await transitionDispatch(
703
+ const previous = await getDispatchRecord(id);
704
+ const next = await transitionDispatch(
701
705
  id,
702
706
  (record) => isTerminalDispatchStatus(record.status) ? record : {
703
707
  ...record,
@@ -706,6 +710,17 @@ async function markDispatchCompleted(id, resultMessageTs) {
706
710
  status: "completed"
707
711
  }
708
712
  );
713
+ if (next?.status === "completed" && previous?.status !== "completed" && next.plugin === "junior") {
714
+ const eventTaskId = next.metadata?.eventTaskId;
715
+ if (eventTaskId) {
716
+ await recordTaskExecution("event", eventTaskId, {
717
+ conversationId: getDispatchConversationId(next),
718
+ executionId: next.id,
719
+ nowMs: next.updatedAtMs
720
+ });
721
+ }
722
+ }
723
+ return next;
709
724
  }
710
725
  async function markDispatchFailed(id, errorMessage, resultMessageTs) {
711
726
  return await transitionDispatch(
@@ -1583,6 +1598,14 @@ async function applyDispatchResult(args) {
1583
1598
  run: args.run,
1584
1599
  status: "completed"
1585
1600
  });
1601
+ const dispatchId = args.run.dispatchId;
1602
+ if (dispatchId) {
1603
+ await recordTaskExecution("scheduled", args.run.taskId, {
1604
+ conversationId: getDispatchConversationId({ id: dispatchId }),
1605
+ executionId: args.run.id,
1606
+ nowMs: args.nowMs
1607
+ });
1608
+ }
1586
1609
  return true;
1587
1610
  }
1588
1611
  if (args.dispatch.status === "blocked") {
@@ -2804,8 +2827,9 @@ async function lookupSlackUser(teamId, userId) {
2804
2827
  }
2805
2828
 
2806
2829
  // src/chat/slack/message-control.ts
2830
+ var LEADING_MENTION_BEFORE_STEERING_RE = /^(\s*(?:<@[^>]+>|@[A-Za-z0-9._-]+\b)[\s,:-]*)!!\s*/;
2807
2831
  function stripLeadingSteeringOverride(text) {
2808
- return text.replace(/^\s*!!\s*/, "");
2832
+ return text.replace(LEADING_MENTION_BEFORE_STEERING_RE, "$1").replace(/^\s*!!\s*/, "");
2809
2833
  }
2810
2834
 
2811
2835
  // src/chat/task-execution/slack-work.ts
@@ -3326,6 +3350,7 @@ function createSlackConversationWorker(options) {
3326
3350
  try {
3327
3351
  if (route === "mention") {
3328
3352
  await options.runtime.handleNewMention(thread, latestMessage, {
3353
+ conversationId: context.conversationId,
3329
3354
  destination: context.destination,
3330
3355
  messageContext,
3331
3356
  drainSteeringMessages,
@@ -3338,6 +3363,7 @@ function createSlackConversationWorker(options) {
3338
3363
  thread,
3339
3364
  latestMessage,
3340
3365
  {
3366
+ conversationId: context.conversationId,
3341
3367
  destination: context.destination,
3342
3368
  messageContext,
3343
3369
  drainSteeringMessages,
@@ -3720,10 +3746,32 @@ function shouldIgnoreMessage(message) {
3720
3746
  function shouldPersistBeforeAck(body) {
3721
3747
  return body.event?.type === "app_mention" || body.event?.type === "message";
3722
3748
  }
3749
+ async function resolveSlackConversationId(args) {
3750
+ const providerThread = parseSlackThreadId(args.canonicalThreadId);
3751
+ const conversationStore = args.conversationStore ?? getConversationStore();
3752
+ if (!providerThread) {
3753
+ return args.canonicalThreadId;
3754
+ }
3755
+ return await conversationStore.getConversationIdByProviderConversation({
3756
+ provider: "slack",
3757
+ providerDestinationId: providerThread.channelId,
3758
+ providerTenantId: args.installation.teamId ?? "",
3759
+ providerConversationId: providerThread.threadTs
3760
+ }) ?? args.canonicalThreadId;
3761
+ }
3723
3762
  async function persistSlackMessage(args) {
3763
+ const canonicalThreadId = normalizeIncomingSlackThreadId(
3764
+ args.message.threadId,
3765
+ args.message
3766
+ );
3767
+ const conversationId = args.conversationId ?? await resolveSlackConversationId({
3768
+ canonicalThreadId,
3769
+ conversationStore: args.conversationStore,
3770
+ installation: args.installation
3771
+ });
3724
3772
  const thread = await buildThread(args);
3725
3773
  const inbound = buildSlackInboundMessage({
3726
- conversationId: thread.id,
3774
+ conversationId,
3727
3775
  installation: args.installation,
3728
3776
  message: args.message,
3729
3777
  receivedAtMs: args.receivedAtMs,
@@ -3743,12 +3791,17 @@ async function routeParsedMessage(args) {
3743
3791
  if (shouldIgnoreMessage(args.message)) {
3744
3792
  return;
3745
3793
  }
3746
- const threadId = normalizeMessageThreadId(args.message);
3794
+ const canonicalThreadId = normalizeMessageThreadId(args.message);
3795
+ const conversationId = await resolveSlackConversationId({
3796
+ canonicalThreadId,
3797
+ conversationStore: args.conversationStore,
3798
+ installation: args.installation
3799
+ });
3747
3800
  const isMention = args.event.type === "app_mention" || textMentionsBot2(args.event, args.adapter.botUserId);
3748
3801
  if (isMention) {
3749
3802
  args.message.isMention = true;
3750
3803
  }
3751
- const route = isDmEvent(args.event) || isMention ? "mention" : await args.state.isSubscribed(threadId) ? "subscribed" : void 0;
3804
+ const route = isDmEvent(args.event) || isMention ? "mention" : await args.state.isSubscribed(canonicalThreadId) ? "subscribed" : void 0;
3752
3805
  if (!route) {
3753
3806
  return;
3754
3807
  }
@@ -3756,6 +3809,7 @@ async function routeParsedMessage(args) {
3756
3809
  adapter: args.adapter,
3757
3810
  installation: args.installation,
3758
3811
  message: args.message,
3812
+ conversationId,
3759
3813
  conversationStore: args.conversationStore,
3760
3814
  queue: args.queue,
3761
3815
  receivedAtMs: args.receivedAtMs,
@@ -5639,6 +5693,7 @@ function createSlackTurnRuntime(deps) {
5639
5693
  await deps.replyToThread(thread, message, {
5640
5694
  explicitMention: true,
5641
5695
  beforeFirstResponsePost: hooks.beforeFirstResponsePost,
5696
+ conversationId: hooks.conversationId,
5642
5697
  destination: hooks.destination,
5643
5698
  queuedMessages,
5644
5699
  ack,
@@ -5903,6 +5958,7 @@ function createSlackTurnRuntime(deps) {
5903
5958
  );
5904
5959
  await deps.replyToThread(thread, message, {
5905
5960
  explicitMention: Boolean(message.isMention),
5961
+ conversationId: hooks.conversationId,
5906
5962
  destination: hooks.destination,
5907
5963
  preparedState,
5908
5964
  beforeFirstResponsePost: hooks.beforeFirstResponsePost,
@@ -6824,8 +6880,8 @@ function createReplyToThread(deps) {
6824
6880
  destination,
6825
6881
  visibility: options.execution?.destinationVisibility ?? conversationVisibilityFromSlackChannelType(slackChannelType)
6826
6882
  });
6827
- const threadTs = getThreadTs(threadId);
6828
6883
  const assistantThreadContext = getAssistantThreadContext(message);
6884
+ const threadTs = getThreadTs(threadId) ?? assistantThreadContext?.threadTs;
6829
6885
  const messageTs = getMessageTs(message);
6830
6886
  const teamId = destination.teamId;
6831
6887
  const source = options.execution?.source ?? createSlackSource2({
@@ -6837,7 +6893,7 @@ function createReplyToThread(deps) {
6837
6893
  });
6838
6894
  const slackActionToken = readSlackActionToken(message);
6839
6895
  const runId = options.execution?.dispatch?.id ?? getRunId(thread, message);
6840
- const conversationId = threadId ?? runId;
6896
+ const conversationId = options.conversationId ?? threadId ?? runId;
6841
6897
  if (!conversationId) {
6842
6898
  throw new Error("Slack reply execution requires a conversation id");
6843
6899
  }
@@ -7289,11 +7345,11 @@ function createReplyToThread(deps) {
7289
7345
  return;
7290
7346
  }
7291
7347
  boundaryFailureCode = "delivery_failed";
7292
- let slackTs;
7348
+ let slackMessageTs2 = [];
7293
7349
  await beforeFirstResponsePost();
7294
7350
  try {
7295
7351
  if (channelId && thread.adapter.name === "slack") {
7296
- slackTs = await sendSlackReply({
7352
+ slackMessageTs2 = await sendSlackReply({
7297
7353
  channelId,
7298
7354
  conversationId,
7299
7355
  replyAttribution: options.execution?.dispatch?.replyAttribution,
@@ -7302,7 +7358,10 @@ function createReplyToThread(deps) {
7302
7358
  });
7303
7359
  } else {
7304
7360
  for (const part of splitSlackReplyText(text)) {
7305
- slackTs = (await thread.post(buildSlackOutputMessage(part))).id;
7361
+ const postedMessageTs = (await thread.post(buildSlackOutputMessage(part))).id;
7362
+ if (postedMessageTs) {
7363
+ slackMessageTs2.push(postedMessageTs);
7364
+ }
7306
7365
  }
7307
7366
  }
7308
7367
  } catch (error) {
@@ -7320,6 +7379,7 @@ function createReplyToThread(deps) {
7320
7379
  failureCode: "delivery_failed"
7321
7380
  });
7322
7381
  }
7382
+ const slackTs = slackMessageTs2.at(-1);
7323
7383
  assistantMessageDelivered = true;
7324
7384
  acceptedDeliveryId = slackTs;
7325
7385
  options.onTurnDeliveryAccepted?.(slackTs);
@@ -7337,17 +7397,26 @@ function createReplyToThread(deps) {
7337
7397
  );
7338
7398
  }
7339
7399
  try {
7400
+ const providerConversationIds = threadTs ? [threadTs] : slackMessageTs2;
7340
7401
  await persistWithRetry(
7341
- () => agentMessage && conversationId ? commitAcceptedReply({
7342
- agentMessage,
7402
+ () => commitAcceptedReply({
7403
+ ...agentMessage ? { agentMessage } : {},
7343
7404
  conversation: preparedState.conversation,
7344
7405
  conversationMessageId: recordedMessageId,
7345
- conversationId
7346
- }) : persistConversationMessages({
7347
- conversation: preparedState.conversation,
7348
- conversationId
7406
+ conversationId,
7407
+ ...options.execution?.dispatch && providerConversationIds.length > 0 ? {
7408
+ providerConversationBindings: providerConversationIds.map(
7409
+ (providerConversationId) => ({
7410
+ provider: "slack",
7411
+ providerDestinationId: destination.channelId,
7412
+ providerTenantId: destination.teamId,
7413
+ providerConversationId
7414
+ })
7415
+ )
7416
+ } : {}
7349
7417
  })
7350
7418
  );
7419
+ await options.onTurnStatePersisted?.();
7351
7420
  } catch (error) {
7352
7421
  logException(
7353
7422
  new Error("Accepted assistant message persistence failed"),
@@ -8254,6 +8323,7 @@ function createSlackDispatchTurnRunner(options) {
8254
8323
  const routing = buildDispatchRoutingContext(dispatch2);
8255
8324
  await options.replyToThread(thread, message, {
8256
8325
  ack: hooks.ack,
8326
+ conversationId,
8257
8327
  destination: dispatch2.destination,
8258
8328
  execution: {
8259
8329
  authorizationFlowMode: "disabled",
@@ -9308,6 +9378,7 @@ async function ingestEventTasks(input, options) {
9308
9378
  destination: task.destination,
9309
9379
  destinationVisibility: task.destinationVisibility,
9310
9380
  input: eventInput(task, event),
9381
+ metadata: { eventTaskId: task.id },
9311
9382
  replyAttribution: replyAttribution2(task, event),
9312
9383
  source: createSlackSource3({
9313
9384
  teamId: task.destination.teamId,
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-B7IY6SVJ.js";
4
- import "./chunk-V44FFBO3.js";
3
+ } from "./chunk-VEGF62FV.js";
4
+ import "./chunk-VP6NCPRS.js";
5
5
  import "./chunk-77VDLF3Z.js";
6
6
  import "./chunk-HZF5P5UN.js";
7
7
  import "./chunk-F3B2YJ76.js";
8
- import "./chunk-GOEZU33G.js";
8
+ import "./chunk-6T3AYZT7.js";
9
9
  import "./chunk-6GWA276C.js";
10
10
  import "./chunk-OOUNJNMR.js";
11
11
  import "./chunk-H4HBKISO.js";
12
- import "./chunk-WEJIS7OC.js";
13
- import "./chunk-2425Q4OR.js";
12
+ import "./chunk-U3ZI7CCW.js";
13
+ import "./chunk-GSP5SMZJ.js";
14
14
  import "./chunk-MLKGABMK.js";
15
15
  export {
16
16
  pluginCatalogRuntime
@@ -19,26 +19,27 @@ export type UserContentPart = {
19
19
  };
20
20
  /** User-turn content parts plus the plain-text blocks used for routing decisions. */
21
21
  export interface PromptInput {
22
+ contextContentParts: UserContentPart[];
22
23
  routerBlocks: string[];
23
24
  userContentParts: UserContentPart[];
24
25
  }
25
26
  /** Fully assembled prompt state for one run slice. */
26
27
  export interface PromptAssembly {
27
28
  baseInstructions: string;
29
+ contextContentParts: UserContentPart[];
28
30
  inputMessages: Array<{
29
31
  role: string;
30
32
  content: Record<string, unknown>[];
31
33
  }>;
32
34
  inputMessagesAttribute: string | undefined;
33
- promptContentParts: UserContentPart[];
35
+ promptTimestamp?: number;
34
36
  promptHistoryMessages: PiMessage[];
35
37
  shouldPromptAgent: boolean;
36
38
  turnContexts: PluginTurnContext[];
39
+ userContentParts: UserContentPart[];
37
40
  }
38
- /**
39
- * Keep thread text separate from the canonical active task boundary.
40
- */
41
- export declare function buildUserTurnText(userInput: string, conversationContext?: string, actor?: AgentRunInstructionActor): string;
41
+ /** Render the current actor's instruction without host-owned thread context. */
42
+ export declare function buildUserTurnText(userInput: string, actor?: AgentRunInstructionActor): string;
42
43
  /** Render an explicitly selected skill as instructions for the current turn. */
43
44
  export declare function renderExplicitSkillInstructions(skill: Skill): string;
44
45
  /** Encode a non-image attachment as base64 XML for the prompt. */
@@ -64,6 +65,7 @@ export declare function assemblePrompt(args: {
64
65
  artifactState?: ThreadArtifactsState;
65
66
  availableSkills: SkillMetadata[];
66
67
  configurationValues: Record<string, unknown>;
68
+ contextContentParts: UserContentPart[];
67
69
  conversationPrivacy?: ConversationPrivacy;
68
70
  existingSessionPiMessages?: PiMessage[];
69
71
  existingTurnStartMessageIndex?: number;
@@ -0,0 +1,20 @@
1
+ import type { AgentContext, AgentLoopTurnUpdate } from "@earendil-works/pi-agent-core";
2
+ import type { ConversationMessageProvenance } from "@/chat/conversations/provenance";
3
+ import type { UserContentPart } from "@/chat/agent/prompt";
4
+ import type { PiMessage } from "@/chat/pi/messages";
5
+ import { type RepositoryInstructions } from "@/chat/repository-instructions";
6
+ type RepositoryInstructionsContextOptions = {
7
+ capture(): Promise<RepositoryInstructions | undefined>;
8
+ hasSandbox(): boolean;
9
+ initialInstructions?: RepositoryInstructions;
10
+ restoredMessages?: PiMessage[];
11
+ restoredProvenance?: ConversationMessageProvenance[];
12
+ promptContextContentParts: UserContentPart[];
13
+ setMessages(messages: PiMessage[]): void;
14
+ shouldPromptAgent: boolean;
15
+ };
16
+ /** Track model-visible AGENTS.md state and append updates before later samples. */
17
+ export declare function createRepositoryInstructionsContext(options: RepositoryInstructionsContextOptions): {
18
+ applyUpdate(currentUpdate: AgentLoopTurnUpdate | undefined, currentContext: AgentContext): Promise<AgentLoopTurnUpdate | undefined>;
19
+ };
20
+ export {};
@@ -6,6 +6,7 @@
6
6
  * routing, and generated-artifact materialization.
7
7
  */
8
8
  import type { FileUpload } from "chat";
9
+ import type { PluginSandbox } from "@sentry/junior-plugin-api";
9
10
  import { type Actor } from "@/chat/actor";
10
11
  import type { ChannelConfigurationService } from "@/chat/configuration/types";
11
12
  import type { CredentialContext } from "@/chat/credentials/context";
@@ -13,6 +14,7 @@ import type { LogContext } from "@/chat/logging";
13
14
  import type { SandboxEgressTracePropagationConfig } from "@/chat/sandbox/egress/tracing";
14
15
  import type { SandboxEgressSignalTransport } from "@/chat/sandbox/egress/signals";
15
16
  import type { SandboxRef } from "@/chat/sandbox/ref";
17
+ import type { RepositoryInstructions } from "@/chat/repository-instructions";
16
18
  import { type SandboxTools } from "@/chat/sandbox/sandbox";
17
19
  import type { SandboxWorkspace } from "@/chat/sandbox/workspace";
18
20
  import type { Skill, SkillMetadata } from "@/chat/skills";
@@ -33,11 +35,17 @@ export interface AgentSandboxOptions {
33
35
  persistSandboxRef?(sandboxRef: SandboxRef): void | Promise<void>;
34
36
  }
35
37
  export interface AgentSandbox {
38
+ /** Resolve the AGENTS.md bundle for the selected repository directory. */
39
+ captureRepositoryInstructions(): Promise<RepositoryInstructions | undefined>;
36
40
  readonly tools: SandboxTools;
37
41
  readonly workspace: SandboxWorkspace;
38
42
  sandboxRef(): SandboxRef | undefined;
39
43
  close(): void;
40
44
  writeGeneratedArtifacts(files: FileUpload[]): Promise<GeneratedArtifactFileRef[]>;
41
45
  }
46
+ /** Adapt agent sandbox execution for plugin-owned workspace tools. */
47
+ export declare function createPluginToolSandbox(sandbox: Pick<AgentSandbox, "tools" | "workspace">, options: {
48
+ handleAuthSignal(details: unknown): Promise<void>;
49
+ }): PluginSandbox;
42
50
  /** Create run-scoped sandbox capabilities adapted to the current agent context. */
43
51
  export declare function createAgentSandbox(options: AgentSandboxOptions): AgentSandbox;
@@ -17,6 +17,7 @@ import type { AnyToolDefinition } from "@/chat/tools/definition";
17
17
  import type { ToolRuntimeContext } from "@/chat/tools/types";
18
18
  import { type ActiveMcpCatalogSummary } from "@/chat/tool-support/skill/mcp-tool-summary";
19
19
  import type { SandboxRef } from "@/chat/sandbox/ref";
20
+ import type { RepositoryInstructions } from "@/chat/repository-instructions";
20
21
  import type { PiMessage } from "@/chat/pi/messages";
21
22
  import type { LogContext } from "@/chat/logging";
22
23
  import type { ConversationPrivacy } from "@/chat/conversation-privacy";
@@ -81,6 +82,8 @@ export interface ToolWiring {
81
82
  isError?: boolean;
82
83
  }>(toolCallId: string, result: TResult): TResult;
83
84
  getSandboxRef: () => SandboxRef | undefined;
85
+ /** Resolve the AGENTS.md bundle selected by the sandbox workspace. */
86
+ captureRepositoryInstructions: () => Promise<RepositoryInstructions | undefined>;
84
87
  close(): Promise<void>;
85
88
  toolGuidance: Array<{
86
89
  name: string;
@@ -1,5 +1,6 @@
1
1
  import { type TurnReasoningLevel } from "@/chat/reasoning-level";
2
2
  import { type ExecutionProfileConfig } from "@/chat/model-profile";
3
+ export declare const DEFAULT_SQL_STATEMENT_TIMEOUT_MS = 30000;
3
4
  /**
4
5
  * Buffer between the Vercel function timeout and the agent turn timeout so
5
6
  * Junior can abort, persist, and schedule continuation before host teardown.
@@ -32,6 +33,7 @@ export interface ChatConfig {
32
33
  sql: {
33
34
  databaseUrl: string;
34
35
  driver: SqlDriver;
36
+ statementTimeoutMs: number | false;
35
37
  };
36
38
  slack: {
37
39
  botToken?: string;
@@ -2,6 +2,7 @@ import { type PiMessage } from "@/chat/pi/messages";
2
2
  import { type ConversationMessageProvenance } from "@/chat/conversations/provenance";
3
3
  import type { AuthorizationKind, ConversationEvent } from "@/chat/conversations/history";
4
4
  import type { JuniorSqlDatabase } from "@/db/db";
5
+ import { type ProviderConversationBinding } from "@/chat/conversations/sql/bindings";
5
6
  import { type PiConversationEventProjection, type PiConversationProjection } from "@/chat/pi/conversation-events";
6
7
  import type { ModelProfile } from "@/chat/model-profile";
7
8
  import type { TurnReasoningLevel } from "@/chat/reasoning-level";
@@ -73,10 +74,11 @@ export declare function commitMessages(args: {
73
74
  * produced it.
74
75
  */
75
76
  export declare function commitAcceptedReply(args: {
76
- agentMessage: AssistantMessage;
77
+ agentMessage?: AssistantMessage;
77
78
  conversation: ThreadConversationState;
78
79
  conversationMessageId: string;
79
80
  conversationId: string;
81
+ providerConversationBindings?: Array<Omit<ProviderConversationBinding, "conversationId">>;
80
82
  repliedAtMs?: number;
81
83
  }): Promise<void>;
82
84
  /** Record a successful MCP provider connection without duplicating the fact. */
@@ -0,0 +1,13 @@
1
+ import type { JuniorSqlDatabase } from "@/db/db";
2
+ export interface ProviderConversationBinding {
3
+ conversationId: string;
4
+ provider: string;
5
+ providerDestinationId: string;
6
+ providerTenantId: string;
7
+ providerConversationId: string;
8
+ }
9
+ export type ProviderConversationReference = Omit<ProviderConversationBinding, "conversationId">;
10
+ /** Resolve the durable conversation bound to provider-owned coordinates. */
11
+ export declare function getConversationIdByProviderConversation(executor: JuniorSqlDatabase, args: ProviderConversationReference): Promise<string | undefined>;
12
+ /** Bind provider coordinates to a durable conversation in the caller's SQL scope. */
13
+ export declare function bindProviderConversation(executor: JuniorSqlDatabase, args: ProviderConversationBinding): Promise<void>;
@@ -4,9 +4,12 @@ import type { StoredSlackActor } from "@/chat/actor";
4
4
  import type { JuniorSqlDatabase } from "@/db/db";
5
5
  import type { Conversation, ConversationExecution, ConversationSource, ConversationStore } from "../store";
6
6
  import type { AgentTurnUsage } from "@/chat/usage";
7
+ import { type ProviderConversationBinding, type ProviderConversationReference } from "./bindings";
7
8
  export declare class SqlStore implements ConversationStore {
8
9
  private readonly executor;
9
10
  constructor(executor: JuniorSqlDatabase);
11
+ getConversationIdByProviderConversation(args: ProviderConversationReference): Promise<string | undefined>;
12
+ bindProviderConversation(args: ProviderConversationBinding): Promise<void>;
10
13
  get(args: {
11
14
  conversationId: string;
12
15
  }): Promise<Conversation | undefined>;
@@ -51,6 +51,21 @@ export interface ConversationStore {
51
51
  get(args: {
52
52
  conversationId: string;
53
53
  }): Promise<Conversation | undefined>;
54
+ /** Resolve the durable conversation bound to one provider conversation. */
55
+ getConversationIdByProviderConversation(args: {
56
+ provider: string;
57
+ providerDestinationId: string;
58
+ providerTenantId: string;
59
+ providerConversationId: string;
60
+ }): Promise<string | undefined>;
61
+ /** Bind one provider conversation to its pre-existing durable conversation. */
62
+ bindProviderConversation(args: {
63
+ conversationId: string;
64
+ provider: string;
65
+ providerDestinationId: string;
66
+ providerTenantId: string;
67
+ providerConversationId: string;
68
+ }): Promise<void>;
54
69
  /** Read confirmed public/private visibility for one destination. */
55
70
  getDestinationVisibility(args: {
56
71
  provider: string;
@@ -1,4 +1,4 @@
1
- import type { PluginRoute, PluginOperationalReport, PluginRouteApp, ResourceEvent, SlackConversationLink, PluginRegistration } from "@sentry/junior-plugin-api";
1
+ import type { PluginRoute, PluginSandbox, PluginOperationalReport, PluginRouteApp, ResourceEvent, SlackConversationLink, PluginRegistration } from "@sentry/junior-plugin-api";
2
2
  import type { PluginPromptContributionContext } from "@/chat/plugins/prompt";
3
3
  import type { AnyToolDefinition } from "@/chat/tools/definition";
4
4
  import type { ToolRuntimeContext } from "@/chat/tools/types";
@@ -51,7 +51,7 @@ export declare function getPluginUserPromptContributions(args: {
51
51
  turnId?: string;
52
52
  }): Promise<PluginPromptContributionContext[]>;
53
53
  /** Collect turn-scoped tools exposed by plugins. */
54
- export declare function getPluginTools(context: ToolRuntimeContext): Record<string, AnyToolDefinition>;
54
+ export declare function getPluginTools(context: ToolRuntimeContext, sandbox?: PluginSandbox): Record<string, AnyToolDefinition>;
55
55
  /** Collect route handlers exposed by plugins for app-level mounting. */
56
56
  export declare function getPluginRoutes(options: {
57
57
  resourceEvents: {