@sentry/junior 0.91.0 → 0.92.1

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 (128) hide show
  1. package/dist/{agent-hooks-MXAF7RQL.js → agent-hooks-KL7I3ZRC.js} +7 -7
  2. package/dist/api/people/list.d.ts +3 -3
  3. package/dist/api/people/list.js +15 -15
  4. package/dist/api/people/list.query.d.ts +2 -2
  5. package/dist/api/people/profile.d.ts +3 -3
  6. package/dist/api/people/profile.js +12 -12
  7. package/dist/api/people/profile.query.d.ts +2 -2
  8. package/dist/api/people/shared.d.ts +13 -13
  9. package/dist/api/people/types.d.ts +12 -12
  10. package/dist/api-reference.d.ts +1 -1
  11. package/dist/app.js +365 -265
  12. package/dist/{catalog-runtime-DXE6NXHT.js → catalog-runtime-NZHMSMYC.js} +2 -2
  13. package/dist/chat/actor.d.ts +75 -0
  14. package/dist/chat/agent/prompt.d.ts +2 -2
  15. package/dist/chat/agent/request.d.ts +13 -13
  16. package/dist/chat/agent/resume.d.ts +5 -4
  17. package/dist/chat/agent/tools.d.ts +4 -2
  18. package/dist/chat/capabilities/jr-rpc-command.d.ts +1 -1
  19. package/dist/chat/conversation-privacy.d.ts +11 -0
  20. package/dist/chat/conversations/sql/migrations.d.ts +1 -1
  21. package/dist/chat/conversations/sql/schema/conversations.d.ts +2 -19
  22. package/dist/chat/conversations/sql/schema.d.ts +2 -19
  23. package/dist/chat/conversations/sql/store.d.ts +3 -3
  24. package/dist/chat/conversations/store.d.ts +4 -4
  25. package/dist/chat/credentials/context.d.ts +4 -4
  26. package/dist/chat/logging.d.ts +2 -2
  27. package/dist/chat/no-reply.d.ts +1 -1
  28. package/dist/chat/oauth-flow.d.ts +1 -1
  29. package/dist/chat/pi/messages.d.ts +2 -2
  30. package/dist/chat/pi/transcript.d.ts +15 -0
  31. package/dist/chat/plugins/agent-hooks.d.ts +5 -3
  32. package/dist/chat/plugins/credential-hooks.d.ts +2 -8
  33. package/dist/chat/prompt.d.ts +3 -6
  34. package/dist/chat/runtime/reply-executor.d.ts +1 -1
  35. package/dist/chat/runtime/turn-input.d.ts +1 -1
  36. package/dist/chat/sandbox/egress/schemas.d.ts +2 -2
  37. package/dist/chat/sandbox/egress/session.d.ts +1 -1
  38. package/dist/chat/services/context-compaction.d.ts +1 -1
  39. package/dist/chat/services/conversation-memory.d.ts +1 -1
  40. package/dist/chat/services/mcp-auth-orchestration.d.ts +1 -1
  41. package/dist/chat/services/message-actor-identity.d.ts +4 -4
  42. package/dist/chat/services/pending-auth.d.ts +2 -2
  43. package/dist/chat/services/plugin-auth-orchestration.d.ts +1 -1
  44. package/dist/chat/services/provider-default-config.d.ts +1 -1
  45. package/dist/chat/services/subscribed-decision.d.ts +1 -1
  46. package/dist/chat/services/turn-result.d.ts +1 -1
  47. package/dist/chat/services/turn-session-record.d.ts +11 -8
  48. package/dist/chat/services/turn-thinking-level.d.ts +1 -1
  49. package/dist/chat/slack/assistant-thread/title.d.ts +1 -1
  50. package/dist/chat/slack/tools/canvas/create.d.ts +41 -1
  51. package/dist/chat/slack/tools/canvas/edit.d.ts +60 -1
  52. package/dist/chat/slack/tools/canvas/read.d.ts +60 -1
  53. package/dist/chat/slack/tools/canvas/write.d.ts +41 -1
  54. package/dist/chat/slack/tools/channel-list-messages.d.ts +45 -1
  55. package/dist/chat/slack/tools/context.d.ts +3 -3
  56. package/dist/chat/slack/tools/list/add-items.d.ts +42 -1
  57. package/dist/chat/slack/tools/list/create.d.ts +40 -1
  58. package/dist/chat/slack/tools/list/get-items.d.ts +40 -1
  59. package/dist/chat/slack/tools/list/update-item.d.ts +46 -1
  60. package/dist/chat/slack/tools/message-add-reaction.d.ts +40 -1
  61. package/dist/chat/slack/tools/send-message.d.ts +45 -1
  62. package/dist/chat/slack/tools/thread-read.d.ts +44 -1
  63. package/dist/chat/slack/tools/user-lookup.d.ts +45 -1
  64. package/dist/chat/slack/user.d.ts +3 -3
  65. package/dist/chat/slack/vision-context.d.ts +2 -2
  66. package/dist/chat/sql/schema.d.ts +2 -19
  67. package/dist/chat/state/conversation-details.d.ts +4 -4
  68. package/dist/chat/state/conversation.d.ts +1 -1
  69. package/dist/chat/state/session-log.d.ts +140 -26
  70. package/dist/chat/state/turn-session.d.ts +18 -5
  71. package/dist/chat/task-execution/slack-work.d.ts +2 -2
  72. package/dist/chat/task-execution/state.d.ts +4 -4
  73. package/dist/chat/tool-support/zod-tool.d.ts +16 -4
  74. package/dist/chat/tools/advisor/tool.d.ts +41 -1
  75. package/dist/chat/tools/definition.d.ts +10 -0
  76. package/dist/chat/tools/execute-tool.d.ts +41 -1
  77. package/dist/chat/tools/resource-events.d.ts +124 -3
  78. package/dist/chat/tools/runtime/report-progress.d.ts +40 -1
  79. package/dist/chat/tools/sandbox/bash.d.ts +41 -1
  80. package/dist/chat/tools/sandbox/edit-file.d.ts +44 -1
  81. package/dist/chat/tools/sandbox/find-files.d.ts +42 -1
  82. package/dist/chat/tools/sandbox/grep.d.ts +46 -1
  83. package/dist/chat/tools/sandbox/list-dir.d.ts +41 -1
  84. package/dist/chat/tools/sandbox/read-file.d.ts +42 -1
  85. package/dist/chat/tools/sandbox/write-file.d.ts +41 -1
  86. package/dist/chat/tools/search-tools.d.ts +102 -1
  87. package/dist/chat/tools/skill/call-mcp-tool.d.ts +10 -1
  88. package/dist/chat/tools/skill/load-skill.d.ts +40 -1
  89. package/dist/chat/tools/skill/search-mcp-tools.d.ts +100 -1
  90. package/dist/chat/tools/system-time.d.ts +38 -1
  91. package/dist/chat/tools/types.d.ts +4 -4
  92. package/dist/chat/tools/web/fetch-tool.d.ts +41 -1
  93. package/dist/chat/tools/web/image-generate.d.ts +62 -1
  94. package/dist/chat/tools/web/search.d.ts +41 -1
  95. package/dist/{chunk-HXL2ZV74.js → chunk-3F54A3YM.js} +82 -11
  96. package/dist/{chunk-ZGDTBSQ7.js → chunk-56SIBIVF.js} +930 -660
  97. package/dist/{chunk-DACFZ5CI.js → chunk-7K3JALTQ.js} +18 -12
  98. package/dist/{chunk-IRRMABQD.js → chunk-APIVR44P.js} +10 -10
  99. package/dist/{chunk-XP7F4LYB.js → chunk-BTH37NCU.js} +4 -4
  100. package/dist/{chunk-5GBUZI6M.js → chunk-H7KUZAMZ.js} +4 -4
  101. package/dist/{chunk-PIB4EOW6.js → chunk-IWKVXO3F.js} +19 -72
  102. package/dist/{chunk-TYUXD3FN.js → chunk-MC4ZZE4Q.js} +1 -1
  103. package/dist/{chunk-2S7M37HY.js → chunk-NIFONS4W.js} +86 -47
  104. package/dist/{chunk-AOISHLSF.js → chunk-O6ZYIHFC.js} +143 -20
  105. package/dist/{chunk-GCWD2VHP.js → chunk-OQQU3SD6.js} +285 -124
  106. package/dist/{chunk-NW7AXDA5.js → chunk-OZJXGX4U.js} +2 -2
  107. package/dist/{chunk-KC42JAAQ.js → chunk-PFXC67GJ.js} +3 -3
  108. package/dist/{chunk-QCKGI74V.js → chunk-PGR4WGZW.js} +10 -10
  109. package/dist/{chunk-ZUK7BL63.js → chunk-S6QKIGRM.js} +66 -54
  110. package/dist/{chunk-IX76WFJV.js → chunk-TF5VLGA7.js} +10 -10
  111. package/dist/{chunk-AN2437E3.js → chunk-YTNPU7I2.js} +2 -2
  112. package/dist/{chunk-3MPOMK3K.js → chunk-YYBX2BD5.js} +61 -3
  113. package/dist/{chunk-ONFOWI2D.js → chunk-Z4FOYQXW.js} +16 -15
  114. package/dist/{chunk-RS6ANWVT.js → chunk-ZATRYQLR.js} +1 -1
  115. package/dist/cli/chat.js +20 -20
  116. package/dist/cli/check.js +3 -3
  117. package/dist/cli/plugins.js +9 -9
  118. package/dist/cli/snapshot-warmup.js +6 -6
  119. package/dist/cli/upgrade.js +9 -9
  120. package/dist/{db-CXI7PR5U.js → db-GCK43OO3.js} +4 -4
  121. package/dist/instrumentation.js +1 -1
  122. package/dist/reporting/conversations.d.ts +3 -3
  123. package/dist/reporting.d.ts +1 -1
  124. package/dist/reporting.js +48 -50
  125. package/dist/{runner-FKL3RAHA.js → runner-Y73GZ2VE.js} +20 -18
  126. package/dist/{validation-I7GD2YWS.js → validation-KYAWETI4.js} +3 -3
  127. package/package.json +6 -6
  128. package/dist/chat/requester.d.ts +0 -68
package/dist/app.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  scheduleSessionCompletedPluginTasks,
18
18
  updateConversationStats,
19
19
  upsertConversationMessage
20
- } from "./chunk-AOISHLSF.js";
20
+ } from "./chunk-O6ZYIHFC.js";
21
21
  import {
22
22
  CONVERSATION_WORK_CHECK_IN_INTERVAL_MS,
23
23
  CONVERSATION_WORK_STALE_ENQUEUE_MS,
@@ -41,7 +41,7 @@ import {
41
41
  requestConversationContinuation,
42
42
  requestConversationWork,
43
43
  startConversationWork
44
- } from "./chunk-IX76WFJV.js";
44
+ } from "./chunk-TF5VLGA7.js";
45
45
  import {
46
46
  getVercelConversationWorkQueue,
47
47
  resolveConversationWorkQueueTopic,
@@ -60,11 +60,11 @@ import {
60
60
  resolveSlackChannelTypeFromMessage,
61
61
  resolveSlackConversationContext,
62
62
  setConversationTitle
63
- } from "./chunk-QCKGI74V.js";
63
+ } from "./chunk-PGR4WGZW.js";
64
64
  import {
65
65
  validatePluginEgressCredentialHooks,
66
66
  validatePluginRegistrations
67
- } from "./chunk-TYUXD3FN.js";
67
+ } from "./chunk-MC4ZZE4Q.js";
68
68
  import {
69
69
  defineJuniorPlugins,
70
70
  pluginCatalogConfigFromEnv,
@@ -81,6 +81,9 @@ import {
81
81
  createAgentRunner,
82
82
  createUserTokenStore,
83
83
  deleteMcpAuthSession,
84
+ deleteMcpAuthSessionsForUserProvider,
85
+ deleteMcpServerSessionId,
86
+ deleteMcpStoredOAuthCredentials,
84
87
  deliverResourceEventSubscription,
85
88
  executeAgentRun,
86
89
  executeCredentialedEgressRequest,
@@ -102,9 +105,8 @@ import {
102
105
  setConfigDefaults,
103
106
  shouldEmitDevAgentTrace,
104
107
  shouldPropagateSandboxEgressTrace,
105
- startOAuthFlow,
106
- unlinkProvider
107
- } from "./chunk-ZGDTBSQ7.js";
108
+ startOAuthFlow
109
+ } from "./chunk-56SIBIVF.js";
108
110
  import {
109
111
  CooperativeTurnYieldError,
110
112
  TurnInputCommitLostError,
@@ -131,32 +133,33 @@ import {
131
133
  persistThreadStateById,
132
134
  persistYieldSessionRecord,
133
135
  startActiveTurn
134
- } from "./chunk-ONFOWI2D.js";
136
+ } from "./chunk-Z4FOYQXW.js";
135
137
  import {
136
138
  JUNIOR_THREAD_STATE_TTL_MS,
137
139
  coerceThreadConversationState
138
- } from "./chunk-KC42JAAQ.js";
139
- import "./chunk-5GBUZI6M.js";
140
+ } from "./chunk-PFXC67GJ.js";
141
+ import "./chunk-H7KUZAMZ.js";
140
142
  import {
141
143
  buildSlackOutputMessage,
142
144
  escapeSlackMrkdwnText,
143
145
  formatSlackLink,
144
146
  normalizeSlackStatusText,
145
147
  splitSlackReplyText,
146
- truncateStatusText,
147
- unwrapCurrentInstruction
148
- } from "./chunk-PIB4EOW6.js";
148
+ truncateStatusText
149
+ } from "./chunk-IWKVXO3F.js";
149
150
  import {
150
151
  abandonAgentTurnSessionRecord,
151
152
  commitMessages,
152
- escapeXml,
153
+ contextProvenance,
153
154
  failAgentTurnSessionRecord,
154
155
  getAgentTurnSessionRecord,
156
+ instructionProvenanceFor,
155
157
  listAgentTurnSessionSummariesForConversation,
156
158
  loadProjection,
159
+ loadProjectionWithProvenance,
157
160
  recordAgentTurnSessionSummary,
158
161
  recordAuthorizationCompleted
159
- } from "./chunk-GCWD2VHP.js";
162
+ } from "./chunk-OQQU3SD6.js";
160
163
  import {
161
164
  SlackActionError,
162
165
  bindSlackDirectCredentialSubject,
@@ -175,25 +178,26 @@ import {
175
178
  setPlugins,
176
179
  validatePlugins,
177
180
  verifySlackDirectCredentialSubject
178
- } from "./chunk-DACFZ5CI.js";
181
+ } from "./chunk-7K3JALTQ.js";
179
182
  import {
180
183
  createPluginLogger,
181
184
  createPluginState
182
- } from "./chunk-NW7AXDA5.js";
185
+ } from "./chunk-OZJXGX4U.js";
183
186
  import "./chunk-G3E7SCME.js";
184
187
  import {
185
188
  acquireActiveLock,
186
189
  getStateAdapter
187
- } from "./chunk-RS6ANWVT.js";
190
+ } from "./chunk-ZATRYQLR.js";
188
191
  import {
189
192
  getConversationStore,
190
193
  getDb
191
- } from "./chunk-2S7M37HY.js";
194
+ } from "./chunk-NIFONS4W.js";
192
195
  import {
193
196
  FUNCTION_TIMEOUT_BUFFER_SECONDS,
194
197
  botConfig,
195
198
  completeObject,
196
199
  completeText,
200
+ escapeXml,
197
201
  getChatConfig,
198
202
  getRuntimeMetadata,
199
203
  getSlackBotToken,
@@ -205,14 +209,15 @@ import {
205
209
  normalizeSlackEmojiName,
206
210
  setSlackReactionConfig,
207
211
  stripRuntimeTurnContext,
208
- trimTrailingAssistantMessages
209
- } from "./chunk-HXL2ZV74.js";
212
+ trimTrailingAssistantMessages,
213
+ unwrapCurrentInstruction
214
+ } from "./chunk-3F54A3YM.js";
210
215
  import {
211
216
  parseSlackThreadId,
212
217
  readSlackRawMessageContext,
213
218
  resolveSlackChannelIdFromMessage,
214
219
  resolveSlackChannelIdFromThreadId
215
- } from "./chunk-3MPOMK3K.js";
220
+ } from "./chunk-YYBX2BD5.js";
216
221
  import {
217
222
  createSlackDestination,
218
223
  destinationKey,
@@ -222,22 +227,23 @@ import {
222
227
  } from "./chunk-GHGPTPBL.js";
223
228
  import {
224
229
  discoverSkills
225
- } from "./chunk-AN2437E3.js";
230
+ } from "./chunk-YTNPU7I2.js";
226
231
  import {
227
232
  buildOAuthTokenRequest,
228
233
  hasRequiredOAuthScope,
229
234
  parseOAuthTokenResponse,
230
235
  pluginCatalogRuntime
231
- } from "./chunk-XP7F4LYB.js";
236
+ } from "./chunk-BTH37NCU.js";
232
237
  import {
233
238
  buildTurnFailureResponse,
239
+ createActor,
234
240
  createChatSdkLogger,
235
241
  createRequestContext,
236
- createRequester,
237
- createSlackRequester,
238
- createSlackResumeRequester,
242
+ createSlackActor,
243
+ createSlackResumeActor,
239
244
  getActiveTraceId,
240
245
  isActorUserId,
246
+ isUserActor,
241
247
  logError,
242
248
  logException,
243
249
  logInfo,
@@ -247,10 +253,10 @@ import {
247
253
  setSpanAttributes,
248
254
  setSpanStatus,
249
255
  setTags,
250
- toStoredSlackRequester,
256
+ toStoredSlackActor,
251
257
  withContext,
252
258
  withSpan
253
- } from "./chunk-ZUK7BL63.js";
259
+ } from "./chunk-S6QKIGRM.js";
254
260
  import {
255
261
  toOptionalString
256
262
  } from "./chunk-OB42YVAE.js";
@@ -584,8 +590,8 @@ var dispatchStatusSchema = z.enum([
584
590
  "blocked"
585
591
  ]);
586
592
  var dispatchActorSchema = z.object({
587
- type: z.literal("system"),
588
- id: nonEmptyExactStringSchema
593
+ platform: z.literal("system"),
594
+ name: nonEmptyExactStringSchema
589
595
  }).strict();
590
596
  var credentialSubjectBindingSchema = z.object({
591
597
  type: z.literal("slack-direct-conversation"),
@@ -772,7 +778,7 @@ async function createOrGetDispatch(args) {
772
778
  }
773
779
  const metadata = normalizeMetadata(args.options.metadata);
774
780
  const record = {
775
- actor: { type: "system", id: args.plugin },
781
+ actor: { platform: "system", name: args.plugin },
776
782
  attempt: 0,
777
783
  createdAtMs: args.nowMs,
778
784
  ...args.options.credentialSubject ? { credentialSubject: args.options.credentialSubject } : {},
@@ -850,7 +856,7 @@ function upsertDispatchUserMessage(args) {
850
856
  ),
851
857
  createdAtMs: args.nowMs,
852
858
  author: {
853
- userName: `system:${args.dispatch.actor.id}`,
859
+ userName: `system:${args.dispatch.actor.name}`,
854
860
  isBot: true
855
861
  },
856
862
  meta: {
@@ -923,8 +929,8 @@ async function runAgentDispatchSlice(callback, deps) {
923
929
  slackThreadId: conversationId,
924
930
  slackChannelId: dispatch.destination.channelId,
925
931
  runId: dispatch.id,
926
- actorType: dispatch.actor.type,
927
- actorId: dispatch.actor.id,
932
+ actorType: dispatch.actor.platform,
933
+ actorId: dispatch.actor.name,
928
934
  assistantUserName: botConfig.userName
929
935
  };
930
936
  const destinationLockId = getDispatchDestinationLockId(dispatch.destination);
@@ -1143,6 +1149,7 @@ async function runAgentDispatchSlice(callback, deps) {
1143
1149
  usage: reply.diagnostics.usage,
1144
1150
  destination: dispatch.destination,
1145
1151
  source: dispatch.source,
1152
+ actor: dispatch.actor,
1146
1153
  surface: "api",
1147
1154
  logContext: {
1148
1155
  threadId: conversationId,
@@ -1276,7 +1283,7 @@ async function recordExecutionMetadata(args) {
1276
1283
  updatedAtMs: conversation.execution.updatedAtMs
1277
1284
  },
1278
1285
  lastActivityAtMs: conversation.lastActivityAtMs,
1279
- requester: conversation.requester,
1286
+ actor: conversation.actor,
1280
1287
  source: conversation.source,
1281
1288
  title: conversation.title,
1282
1289
  updatedAtMs: conversation.updatedAtMs
@@ -1573,53 +1580,51 @@ async function runWithSlackInstallation(args) {
1573
1580
 
1574
1581
  // src/chat/services/message-actor-identity.ts
1575
1582
  var messageActors = /* @__PURE__ */ new WeakMap();
1576
- function canonicalUserId(author, requester) {
1583
+ function canonicalUserId(author, actor) {
1577
1584
  const authorUserId = parseActorUserId(author.userId);
1578
- if (authorUserId && authorUserId !== requester.userId) {
1579
- throw new Error("Message requester user id mismatch");
1585
+ if (authorUserId && authorUserId !== actor.userId) {
1586
+ throw new Error("Message actor user id mismatch");
1580
1587
  }
1581
- const userId = authorUserId ?? requester.userId;
1588
+ const userId = authorUserId ?? actor.userId;
1582
1589
  if (!userId) {
1583
- throw new Error("Message requester requires a user id");
1590
+ throw new Error("Message actor requires a user id");
1584
1591
  }
1585
1592
  return userId;
1586
1593
  }
1587
- function requesterFromAuthor(author) {
1594
+ function actorFromAuthor(author) {
1588
1595
  const userId = parseActorUserId(author.userId);
1589
1596
  return userId ? { userId } : void 0;
1590
1597
  }
1591
- function applyRequesterToAuthor(author, requester) {
1592
- if (!isActorUserId(requester.userId)) {
1593
- throw new Error("Message requester requires a user id");
1598
+ function applyActorToAuthor(author, actor) {
1599
+ if (!isActorUserId(actor.userId)) {
1600
+ throw new Error("Message actor requires a user id");
1594
1601
  }
1595
- author.userId = requester.userId;
1596
- author.userName = requester.userName ?? "";
1597
- author.fullName = requester.fullName ?? "";
1602
+ author.userId = actor.userId;
1603
+ author.userName = actor.userName ?? "";
1604
+ author.fullName = actor.fullName ?? "";
1598
1605
  }
1599
- function bindMessageActorIdentity(message, requester) {
1600
- const userId = canonicalUserId(message.author, requester);
1601
- const actorRequester = createRequester(requester, {
1602
- platform: requester.platform,
1603
- ...requester.platform === "slack" ? { teamId: requester.teamId } : {},
1606
+ function bindMessageActorIdentity(message, actor) {
1607
+ const userId = canonicalUserId(message.author, actor);
1608
+ const currentActor = createActor(actor, {
1609
+ platform: actor.platform,
1610
+ ...actor.platform === "slack" ? { teamId: actor.teamId } : {},
1604
1611
  userId
1605
1612
  });
1606
- if (!actorRequester) {
1607
- throw new Error("Message requester requires a user id");
1613
+ if (!currentActor) {
1614
+ throw new Error("Message actor requires a user id");
1608
1615
  }
1609
- messageActors.set(message, actorRequester);
1610
- applyRequesterToAuthor(message.author, actorRequester);
1611
- return actorRequester;
1616
+ messageActors.set(message, currentActor);
1617
+ applyActorToAuthor(message.author, currentActor);
1618
+ return currentActor;
1612
1619
  }
1613
1620
  function getMessageActorIdentity(message) {
1614
- return messageActors.get(message) ?? requesterFromAuthor(message.author);
1621
+ return messageActors.get(message) ?? actorFromAuthor(message.author);
1615
1622
  }
1616
1623
  async function ensureSlackMessageActorIdentity(message, teamId, lookupSlackUser2) {
1617
1624
  const existing = messageActors.get(message);
1618
1625
  if (existing) {
1619
1626
  if (existing.platform !== "slack") {
1620
- throw new Error(
1621
- "Slack message actor identity requires a Slack requester"
1622
- );
1627
+ throw new Error("Slack message actor identity requires a Slack actor");
1623
1628
  }
1624
1629
  return existing;
1625
1630
  }
@@ -1627,14 +1632,14 @@ async function ensureSlackMessageActorIdentity(message, teamId, lookupSlackUser2
1627
1632
  if (!userId) {
1628
1633
  throw new Error("Slack message actor identity requires a user id");
1629
1634
  }
1630
- const requester = bindMessageActorIdentity(
1635
+ const actor = bindMessageActorIdentity(
1631
1636
  message,
1632
- createSlackRequester(teamId, userId, await lookupSlackUser2(teamId, userId))
1637
+ createSlackActor(teamId, userId, await lookupSlackUser2(teamId, userId))
1633
1638
  );
1634
- if (requester.platform !== "slack") {
1635
- throw new Error("Slack message actor identity requires a Slack requester");
1639
+ if (actor.platform !== "slack") {
1640
+ throw new Error("Slack message actor identity requires a Slack actor");
1636
1641
  }
1637
- return requester;
1642
+ return actor;
1638
1643
  }
1639
1644
 
1640
1645
  // src/chat/slack/user.ts
@@ -1719,8 +1724,8 @@ async function lookupSlackUser(teamId, userId) {
1719
1724
  return null;
1720
1725
  }
1721
1726
  }
1722
- async function lookupSlackRequester(teamId, userId) {
1723
- return createSlackRequester(
1727
+ async function lookupSlackActor(teamId, userId) {
1728
+ return createSlackActor(
1724
1729
  teamId,
1725
1730
  userId,
1726
1731
  await lookupSlackUser(teamId, userId)
@@ -3772,8 +3777,8 @@ function getResumeLogContext(args, lockKey) {
3772
3777
  return {
3773
3778
  conversationId: routing?.correlation?.conversationId ?? lockKey,
3774
3779
  slackThreadId: routing?.correlation?.threadId ?? lockKey,
3775
- slackUserId: routing?.requester?.userId ?? routing?.correlation?.requesterId,
3776
- slackUserName: routing?.requester?.userName,
3780
+ slackUserId: isUserActor(routing?.actor) ? routing.actor.userId : routing?.correlation?.actorId,
3781
+ slackUserName: isUserActor(routing?.actor) ? routing.actor.userName : void 0,
3777
3782
  slackChannelId: args.channelId,
3778
3783
  runId: routing?.correlation?.runId,
3779
3784
  assistantUserName: botConfig.userName,
@@ -3849,7 +3854,7 @@ function createResumeReplyContext(args, statusSession) {
3849
3854
  threadId: replyContext.routing.correlation?.threadId ?? threadId,
3850
3855
  channelId: replyContext.routing.correlation?.channelId ?? args.channelId,
3851
3856
  threadTs: replyContext.routing.correlation?.threadTs ?? args.threadTs,
3852
- requesterId: replyContext.routing.correlation?.requesterId ?? replyContext.routing.requester?.userId
3857
+ actorId: replyContext.routing.correlation?.actorId ?? (isUserActor(replyContext.routing.actor) ? replyContext.routing.actor.userId : void 0)
3853
3858
  }
3854
3859
  },
3855
3860
  policy: {
@@ -3909,18 +3914,25 @@ async function resumeSlackTurn(args) {
3909
3914
  if (preparedArgs) {
3910
3915
  runArgs = { ...args, ...preparedArgs };
3911
3916
  }
3912
- if (!runArgs.replyContext?.routing.requester?.userId) {
3917
+ const activeReplyContext = runArgs.replyContext;
3918
+ if (!activeReplyContext) {
3913
3919
  throw new Error(
3914
- "Resumed turn requires replyContext.routing.requester.userId"
3920
+ "Resumed turn requires replyContext.routing.actor.userId"
3915
3921
  );
3916
3922
  }
3917
- const credentialContext = runArgs.replyContext.routing.credentialContext;
3923
+ const resumeActor = activeReplyContext.routing.actor;
3924
+ if (!isUserActor(resumeActor)) {
3925
+ throw new Error(
3926
+ "Resumed turn requires replyContext.routing.actor.userId"
3927
+ );
3928
+ }
3929
+ const credentialContext = activeReplyContext.routing.credentialContext;
3918
3930
  if (!credentialContext) {
3919
3931
  throw new Error("Resumed turn requires replyContext.credentialContext");
3920
3932
  }
3921
- if (credentialContext.actor.type !== "user" || credentialContext.actor.userId !== runArgs.replyContext.routing.requester.userId) {
3933
+ if (!("type" in credentialContext.actor) || credentialContext.actor.userId !== resumeActor.userId) {
3922
3934
  throw new Error(
3923
- "Resumed turn credential actor must match replyContext.routing.requester.userId"
3935
+ "Resumed turn credential actor must match replyContext.routing.actor.userId"
3924
3936
  );
3925
3937
  }
3926
3938
  if (runArgs.messageTs) {
@@ -3963,7 +3975,7 @@ async function resumeSlackTurn(args) {
3963
3975
  deferredPauseKind = "auth";
3964
3976
  deferredAuthInfo = {
3965
3977
  providerDisplayName: outcome.providerDisplayName,
3966
- requesterId: runArgs.replyContext?.routing.requester?.userId
3978
+ actorId: resumeActor.userId
3967
3979
  };
3968
3980
  deferredPauseHandler = async () => {
3969
3981
  await onAuthPause({
@@ -4015,11 +4027,11 @@ async function resumeSlackTurn(args) {
4015
4027
  currentUsage: reply.diagnostics.usage,
4016
4028
  destination: replyContext.routing.destination,
4017
4029
  source: replyContext.routing.source,
4018
- requester: replyContext.routing.requester,
4030
+ actor: replyContext.routing.actor,
4019
4031
  surface: "slack",
4020
4032
  logContext: {
4021
4033
  threadId: replyContext.routing.correlation.threadId,
4022
- requesterId: replyContext.routing.requester?.userId,
4034
+ actorId: isUserActor(replyContext.routing.actor) ? replyContext.routing.actor.userId : void 0,
4023
4035
  channelId: runArgs.channelId,
4024
4036
  runId: replyContext.routing.correlation.runId,
4025
4037
  assistantUserName: botConfig.userName,
@@ -4105,7 +4117,7 @@ async function resumeSlackTurn(args) {
4105
4117
  runArgs.channelId,
4106
4118
  runArgs.threadTs,
4107
4119
  buildAuthPauseResponse(
4108
- deferredAuthInfo.requesterId,
4120
+ deferredAuthInfo.actorId,
4109
4121
  deferredAuthInfo.providerDisplayName
4110
4122
  ),
4111
4123
  footer
@@ -4349,7 +4361,7 @@ async function resumeAuthorizedMcpTurn(args) {
4349
4361
  conversation,
4350
4362
  kind: "mcp",
4351
4363
  provider,
4352
- requesterId: authSession.userId
4364
+ actorId: authSession.userId
4353
4365
  });
4354
4366
  const resolvedSessionId = pendingAuth?.sessionId ?? authSession.sessionId;
4355
4367
  const userMessage2 = getTurnUserMessage(conversation, resolvedSessionId);
@@ -4386,7 +4398,7 @@ async function resumeAuthorizedMcpTurn(args) {
4386
4398
  conversation: lockedConversation,
4387
4399
  kind: "mcp",
4388
4400
  provider,
4389
- requesterId: authSession.userId
4401
+ actorId: authSession.userId
4390
4402
  });
4391
4403
  const lockedSessionId = lockedPendingAuth?.sessionId ?? authSession.sessionId;
4392
4404
  if (lockedSessionId !== resolvedSessionId) {
@@ -4431,10 +4443,10 @@ async function resumeAuthorizedMcpTurn(args) {
4431
4443
  const lockedChannelConfiguration = getChannelConfigurationServiceById(
4432
4444
  authSession.channelId
4433
4445
  );
4434
- let requester;
4446
+ let actor;
4435
4447
  try {
4436
- requester = createSlackResumeRequester({
4437
- requester: lockedSessionRecord.requester,
4448
+ actor = createSlackResumeActor({
4449
+ actor: isUserActor(lockedSessionRecord.actor) ? lockedSessionRecord.actor : void 0,
4438
4450
  teamId: destination.teamId,
4439
4451
  userId: authSession.userId
4440
4452
  });
@@ -4443,7 +4455,7 @@ async function resumeAuthorizedMcpTurn(args) {
4443
4455
  conversationId: authSession.conversationId,
4444
4456
  expectedVersion: lockedSessionRecord.version,
4445
4457
  sessionId: lockedSessionId,
4446
- errorMessage: "Stored Slack requester identity did not match OAuth requester"
4458
+ errorMessage: "Stored Slack actor identity did not match OAuth actor"
4447
4459
  });
4448
4460
  return false;
4449
4461
  }
@@ -4460,7 +4472,7 @@ async function resumeAuthorizedMcpTurn(args) {
4460
4472
  conversationId: authSession.conversationId,
4461
4473
  kind: "mcp",
4462
4474
  provider,
4463
- requesterId: authSession.userId,
4475
+ actorId: authSession.userId,
4464
4476
  authorizationId: mcpAuthorizationId({
4465
4477
  provider,
4466
4478
  sessionId: lockedSessionId
@@ -4479,9 +4491,9 @@ async function resumeAuthorizedMcpTurn(args) {
4479
4491
  },
4480
4492
  routing: {
4481
4493
  credentialContext: {
4482
- actor: { type: "user", userId: requester.userId }
4494
+ actor: { type: "user", userId: actor.userId }
4483
4495
  },
4484
- requester,
4496
+ actor,
4485
4497
  destination,
4486
4498
  source: lockedSessionRecord.source,
4487
4499
  correlation: {
@@ -4489,7 +4501,7 @@ async function resumeAuthorizedMcpTurn(args) {
4489
4501
  turnId: lockedSessionId,
4490
4502
  channelId: authSession.channelId,
4491
4503
  threadTs: authSession.threadTs,
4492
- requesterId: requester.userId
4504
+ actorId: actor.userId
4493
4505
  },
4494
4506
  toolChannelId: authSession.toolChannelId ?? lockedArtifacts.assistantContextChannelId ?? authSession.channelId
4495
4507
  },
@@ -4860,7 +4872,7 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
4860
4872
  conversation,
4861
4873
  kind: "plugin",
4862
4874
  provider: stored.provider,
4863
- requesterId: stored.userId,
4875
+ actorId: stored.userId,
4864
4876
  ...stored.scope ? { scope: stored.scope } : {}
4865
4877
  });
4866
4878
  const resolvedSessionId = pendingAuth?.sessionId ?? stored.resumeSessionId;
@@ -4916,7 +4928,7 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
4916
4928
  conversation: lockedConversation,
4917
4929
  kind: "plugin",
4918
4930
  provider: stored.provider,
4919
- requesterId: stored.userId,
4931
+ actorId: stored.userId,
4920
4932
  ...stored.scope ? { scope: stored.scope } : {}
4921
4933
  });
4922
4934
  const lockedSessionId = lockedPendingAuth?.sessionId ?? stored.resumeSessionId;
@@ -4962,10 +4974,10 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
4962
4974
  const lockedChannelConfiguration = getChannelConfigurationServiceById(
4963
4975
  stored.channelId
4964
4976
  );
4965
- let requester;
4977
+ let actor;
4966
4978
  try {
4967
- requester = createSlackResumeRequester({
4968
- requester: lockedSessionRecord.requester,
4979
+ actor = createSlackResumeActor({
4980
+ actor: isUserActor(lockedSessionRecord.actor) ? lockedSessionRecord.actor : void 0,
4969
4981
  teamId: destination.teamId,
4970
4982
  userId: lockedUserMessage.author.userId
4971
4983
  });
@@ -4974,7 +4986,7 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
4974
4986
  conversationId: stored.resumeConversationId,
4975
4987
  expectedVersion: lockedSessionRecord.version,
4976
4988
  sessionId: lockedSessionId,
4977
- errorMessage: "Stored Slack requester identity did not match OAuth requester"
4989
+ errorMessage: "Stored Slack actor identity did not match OAuth actor"
4978
4990
  });
4979
4991
  return false;
4980
4992
  }
@@ -4991,7 +5003,7 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
4991
5003
  conversationId: stored.resumeConversationId,
4992
5004
  kind: "plugin",
4993
5005
  provider: stored.provider,
4994
- requesterId: stored.userId,
5006
+ actorId: stored.userId,
4995
5007
  authorizationId: pluginAuthorizationId({
4996
5008
  provider: stored.provider,
4997
5009
  sessionId: lockedSessionId
@@ -5012,10 +5024,10 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
5012
5024
  credentialContext: {
5013
5025
  actor: {
5014
5026
  type: "user",
5015
- userId: requester.userId
5027
+ userId: actor.userId
5016
5028
  }
5017
5029
  },
5018
- requester,
5030
+ actor,
5019
5031
  destination,
5020
5032
  source: lockedSessionRecord.source,
5021
5033
  correlation: {
@@ -5023,7 +5035,7 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
5023
5035
  turnId: lockedSessionId,
5024
5036
  channelId: stored.channelId,
5025
5037
  threadTs: stored.threadTs,
5026
- requesterId: requester.userId
5038
+ actorId: actor.userId
5027
5039
  },
5028
5040
  toolChannelId: lockedArtifacts.assistantContextChannelId ?? stored.channelId
5029
5041
  },
@@ -5116,10 +5128,7 @@ async function resumePendingOAuthMessage(stored, options) {
5116
5128
  stored.destination,
5117
5129
  "OAuth pending message resume"
5118
5130
  );
5119
- const requester = await lookupSlackRequester(
5120
- destination.teamId,
5121
- stored.userId
5122
- );
5131
+ const actor = await lookupSlackActor(destination.teamId, stored.userId);
5123
5132
  const messageTs = getTurnUserSlackMessageTs(latestUserMessage);
5124
5133
  await resumeAuthorizedRequest({
5125
5134
  messageText: stored.pendingMessage,
@@ -5137,14 +5146,14 @@ async function resumePendingOAuthMessage(stored, options) {
5137
5146
  credentialContext: {
5138
5147
  actor: { type: "user", userId: stored.userId }
5139
5148
  },
5140
- requester,
5149
+ actor,
5141
5150
  destination: stored.destination,
5142
5151
  source,
5143
5152
  correlation: {
5144
5153
  conversationId: threadId,
5145
5154
  channelId: stored.channelId,
5146
5155
  threadTs: stored.threadTs,
5147
- requesterId: stored.userId
5156
+ actorId: stored.userId
5148
5157
  }
5149
5158
  },
5150
5159
  policy: {
@@ -5326,6 +5335,23 @@ async function GET4(request, provider, waitUntil, options) {
5326
5335
  }
5327
5336
  } catch (error) {
5328
5337
  if (error instanceof ResumeTurnBusyError) {
5338
+ logWarn(
5339
+ "oauth_callback_resume_busy",
5340
+ {
5341
+ ...stored.resumeConversationId && {
5342
+ conversationId: stored.resumeConversationId
5343
+ },
5344
+ ...stored.userId && { actorId: stored.userId },
5345
+ ...stored.channelId && { channelId: stored.channelId }
5346
+ },
5347
+ {
5348
+ "app.credential.provider": stored.provider,
5349
+ ...stored.resumeSessionId && {
5350
+ "app.ai.session_id": stored.resumeSessionId
5351
+ }
5352
+ },
5353
+ "OAuth callback resume was busy; user must send another message to continue"
5354
+ );
5329
5355
  return;
5330
5356
  }
5331
5357
  throw error;
@@ -5836,17 +5862,17 @@ function isExternalSlackUser(raw) {
5836
5862
  async function postEphemeral(event, text) {
5837
5863
  await event.channel.postEphemeral(event.user, text, { fallbackToDM: false });
5838
5864
  }
5839
- function requireRequesterId(event) {
5865
+ function requireActorId(event) {
5840
5866
  const userId = parseActorUserId(event.user.userId);
5841
5867
  if (!userId) {
5842
- throw new Error("Slack slash command requires a requester user id");
5868
+ throw new Error("Slack slash command requires a actor user id");
5843
5869
  }
5844
5870
  return userId;
5845
5871
  }
5846
5872
  function getCommandName() {
5847
5873
  return getChatConfig().slack.slashCommand;
5848
5874
  }
5849
- async function handleLink(event, requesterId, provider) {
5875
+ async function handleLink(event, actorId, provider) {
5850
5876
  if (!pluginCatalogRuntime.isProvider(provider)) {
5851
5877
  await postEphemeral(event, `Unknown provider: \`${provider}\``);
5852
5878
  return;
@@ -5860,7 +5886,7 @@ async function handleLink(event, requesterId, provider) {
5860
5886
  }
5861
5887
  const raw = event.raw;
5862
5888
  const result = await startOAuthFlow(provider, {
5863
- requesterId,
5889
+ actorId,
5864
5890
  channelId: raw.channel_id
5865
5891
  });
5866
5892
  if (!result.ok) {
@@ -5879,7 +5905,7 @@ async function handleLink(event, requesterId, provider) {
5879
5905
  );
5880
5906
  }
5881
5907
  }
5882
- async function handleUnlink(event, requesterId, provider) {
5908
+ async function handleUnlink(event, actorId, provider) {
5883
5909
  if (!pluginCatalogRuntime.isProvider(provider)) {
5884
5910
  await postEphemeral(event, `Unknown provider: \`${provider}\``);
5885
5911
  return;
@@ -5892,10 +5918,10 @@ async function handleUnlink(event, requesterId, provider) {
5892
5918
  return;
5893
5919
  }
5894
5920
  const tokenStore = createUserTokenStore();
5895
- await tokenStore.delete(requesterId, provider);
5921
+ await tokenStore.delete(actorId, provider);
5896
5922
  logInfo(
5897
5923
  "slash_command_unlink",
5898
- { slackUserId: requesterId },
5924
+ { slackUserId: actorId },
5899
5925
  { "app.credential.provider": provider },
5900
5926
  `Unlinked ${formatProviderLabel(provider)} account via ${getCommandName()} slash command`
5901
5927
  );
@@ -5921,14 +5947,24 @@ async function handleSlashCommand(event) {
5921
5947
  return;
5922
5948
  }
5923
5949
  const normalized = provider.toLowerCase();
5924
- const requesterId = requireRequesterId(event);
5950
+ const actorId = requireActorId(event);
5925
5951
  if (subcommand === "link") {
5926
- await handleLink(event, requesterId, normalized);
5952
+ await handleLink(event, actorId, normalized);
5927
5953
  } else {
5928
- await handleUnlink(event, requesterId, normalized);
5954
+ await handleUnlink(event, actorId, normalized);
5929
5955
  }
5930
5956
  }
5931
5957
 
5958
+ // src/chat/credentials/unlink-provider.ts
5959
+ async function unlinkProvider(userId, provider, userTokenStore) {
5960
+ await Promise.all([
5961
+ userTokenStore.delete(userId, provider),
5962
+ deleteMcpStoredOAuthCredentials(userId, provider),
5963
+ deleteMcpServerSessionId(userId, provider),
5964
+ deleteMcpAuthSessionsForUserProvider(userId, provider)
5965
+ ]);
5966
+ }
5967
+
5932
5968
  // src/chat/ingress/slack-webhook.ts
5933
5969
  var IGNORED_MESSAGE_SUBTYPES = /* @__PURE__ */ new Set([
5934
5970
  "message_changed",
@@ -6202,7 +6238,7 @@ async function handleSlashCommandForm(args) {
6202
6238
  "Slack slash command payload"
6203
6239
  );
6204
6240
  const teamId = args.params.get("team_id") ?? void 0;
6205
- const userIdentity = createRequester(
6241
+ const userIdentity = createActor(
6206
6242
  {
6207
6243
  platform: "slack",
6208
6244
  teamId,
@@ -7424,7 +7460,7 @@ async function decideSubscribedThreadReply(args) {
7424
7460
  modelId: args.modelId,
7425
7461
  threadId: args.input.context.threadId ?? "",
7426
7462
  channelId: args.input.context.channelId ?? "",
7427
- requesterId: args.input.context.requesterId ?? "",
7463
+ actorId: args.input.context.actorId ?? "",
7428
7464
  runId: args.input.context.runId ?? ""
7429
7465
  }
7430
7466
  });
@@ -7558,15 +7594,15 @@ function buildLogContext(deps, args) {
7558
7594
  return {
7559
7595
  conversationId: args.threadId ?? args.runId,
7560
7596
  slackThreadId: args.threadId,
7561
- slackUserId: args.requesterId,
7562
- slackUserName: args.requesterUserName,
7597
+ slackUserId: args.actorId,
7598
+ slackUserName: args.actorUserName,
7563
7599
  slackChannelId: args.channelId,
7564
7600
  runId: args.runId,
7565
7601
  assistantUserName: deps.assistantUserName,
7566
7602
  modelId: deps.modelId
7567
7603
  };
7568
7604
  }
7569
- function requesterUserName(message) {
7605
+ function actorUserName(message) {
7570
7606
  return getMessageActorIdentity(message)?.userName;
7571
7607
  }
7572
7608
  function isResourceEventNotificationMessage2(message) {
@@ -7643,7 +7679,7 @@ function createSlackTurnRuntime(deps) {
7643
7679
  const { message } = candidate;
7644
7680
  const context = {
7645
7681
  threadId: deps.getThreadId(thread, message),
7646
- requesterId: message.author.userId,
7682
+ actorId: message.author.userId,
7647
7683
  channelId: deps.getChannelId(thread, message),
7648
7684
  runId: deps.getRunId(thread, message)
7649
7685
  };
@@ -7676,8 +7712,8 @@ function createSlackTurnRuntime(deps) {
7676
7712
  "subscribed_message_reply_skipped",
7677
7713
  logContext({
7678
7714
  threadId: args.context.threadId,
7679
- requesterId: args.context.requesterId,
7680
- requesterUserName: requesterUserName(args.message),
7715
+ actorId: args.context.actorId,
7716
+ actorUserName: actorUserName(args.message),
7681
7717
  channelId: args.context.channelId,
7682
7718
  runId: args.context.runId
7683
7719
  }),
@@ -7801,8 +7837,8 @@ function createSlackTurnRuntime(deps) {
7801
7837
  pending: skippedSteeringMessages,
7802
7838
  context: logContext({
7803
7839
  threadId: deps.getThreadId(thread, message),
7804
- requesterId: message.author.userId,
7805
- requesterUserName: requesterUserName(message),
7840
+ actorId: message.author.userId,
7841
+ actorUserName: actorUserName(message),
7806
7842
  channelId: deps.getChannelId(thread, message),
7807
7843
  runId: deps.getRunId(thread, message)
7808
7844
  })
@@ -7815,8 +7851,8 @@ function createSlackTurnRuntime(deps) {
7815
7851
  const context = logContext({
7816
7852
  threadId,
7817
7853
  channelId,
7818
- requesterId: message.author.userId,
7819
- requesterUserName: requesterUserName(message),
7854
+ actorId: message.author.userId,
7855
+ actorUserName: actorUserName(message),
7820
7856
  runId
7821
7857
  });
7822
7858
  processingReaction = await processingReactions.start(context, message);
@@ -7888,8 +7924,8 @@ function createSlackTurnRuntime(deps) {
7888
7924
  }
7889
7925
  const errorContext = logContext({
7890
7926
  threadId: deps.getThreadId(thread, message),
7891
- requesterId: message.author.userId,
7892
- requesterUserName: requesterUserName(message),
7927
+ actorId: message.author.userId,
7928
+ actorUserName: actorUserName(message),
7893
7929
  channelId: deps.getChannelId(thread, message),
7894
7930
  runId: deps.getRunId(thread, message)
7895
7931
  });
@@ -7901,8 +7937,8 @@ function createSlackTurnRuntime(deps) {
7901
7937
  "mention_handler_read_only_channel",
7902
7938
  logContext({
7903
7939
  threadId: deps.getThreadId(thread, message),
7904
- requesterId: message.author.userId,
7905
- requesterUserName: requesterUserName(message),
7940
+ actorId: message.author.userId,
7941
+ actorUserName: actorUserName(message),
7906
7942
  channelId: deps.getChannelId(thread, message),
7907
7943
  runId: deps.getRunId(thread, message)
7908
7944
  }),
@@ -7943,8 +7979,8 @@ function createSlackTurnRuntime(deps) {
7943
7979
  pending: skippedSteeringMessages,
7944
7980
  context: logContext({
7945
7981
  threadId: deps.getThreadId(thread, message),
7946
- requesterId: message.author.userId,
7947
- requesterUserName: requesterUserName(message),
7982
+ actorId: message.author.userId,
7983
+ actorUserName: actorUserName(message),
7948
7984
  channelId: deps.getChannelId(thread, message),
7949
7985
  runId: deps.getRunId(thread, message)
7950
7986
  })
@@ -7966,8 +8002,8 @@ function createSlackTurnRuntime(deps) {
7966
8002
  pending: skippedSteeringMessages,
7967
8003
  context: logContext({
7968
8004
  threadId: deps.getThreadId(thread, message),
7969
- requesterId: message.author.userId,
7970
- requesterUserName: requesterUserName(message),
8005
+ actorId: message.author.userId,
8006
+ actorUserName: actorUserName(message),
7971
8007
  channelId: deps.getChannelId(thread, message),
7972
8008
  runId: deps.getRunId(thread, message)
7973
8009
  })
@@ -7978,11 +8014,11 @@ function createSlackTurnRuntime(deps) {
7978
8014
  const channelId = deps.getChannelId(thread, message);
7979
8015
  const runId = deps.getRunId(thread, message);
7980
8016
  const isResourceEventNotification = isResourceEventNotificationMessage2(message);
7981
- const requesterId = isResourceEventNotification ? void 0 : message.author.userId;
8017
+ const actorId = isResourceEventNotification ? void 0 : message.author.userId;
7982
8018
  const turnContext = logContext({
7983
8019
  threadId,
7984
- requesterId,
7985
- requesterUserName: requesterUserName(message),
8020
+ actorId,
8021
+ actorUserName: actorUserName(message),
7986
8022
  channelId,
7987
8023
  runId
7988
8024
  });
@@ -8002,7 +8038,7 @@ function createSlackTurnRuntime(deps) {
8002
8038
  };
8003
8039
  const threadContext = {
8004
8040
  threadId,
8005
- requesterId,
8041
+ actorId,
8006
8042
  channelId,
8007
8043
  runId
8008
8044
  };
@@ -8148,8 +8184,8 @@ function createSlackTurnRuntime(deps) {
8148
8184
  }
8149
8185
  const errorContext = logContext({
8150
8186
  threadId: deps.getThreadId(thread, message),
8151
- requesterId: message.author.userId,
8152
- requesterUserName: requesterUserName(message),
8187
+ actorId: message.author.userId,
8188
+ actorUserName: actorUserName(message),
8153
8189
  channelId: deps.getChannelId(thread, message),
8154
8190
  runId: deps.getRunId(thread, message)
8155
8191
  });
@@ -8161,8 +8197,8 @@ function createSlackTurnRuntime(deps) {
8161
8197
  "subscribed_message_handler_read_only_channel",
8162
8198
  logContext({
8163
8199
  threadId: deps.getThreadId(thread, message),
8164
- requesterId: message.author.userId,
8165
- requesterUserName: requesterUserName(message),
8200
+ actorId: message.author.userId,
8201
+ actorUserName: actorUserName(message),
8166
8202
  channelId: deps.getChannelId(thread, message),
8167
8203
  runId: deps.getRunId(thread, message)
8168
8204
  }),
@@ -8203,8 +8239,8 @@ function createSlackTurnRuntime(deps) {
8203
8239
  pending: skippedSteeringMessages,
8204
8240
  context: logContext({
8205
8241
  threadId: deps.getThreadId(thread, message),
8206
- requesterId: message.author.userId,
8207
- requesterUserName: requesterUserName(message),
8242
+ actorId: message.author.userId,
8243
+ actorUserName: actorUserName(message),
8208
8244
  channelId: deps.getChannelId(thread, message),
8209
8245
  runId: deps.getRunId(thread, message)
8210
8246
  })
@@ -8323,12 +8359,13 @@ function userMessage(text) {
8323
8359
  timestamp: Date.now()
8324
8360
  };
8325
8361
  }
8326
- function selectRetainedUserMessages(messages, maxTokens = RETAINED_USER_MESSAGE_TOKENS) {
8327
- const stripped = stripRuntimeTurnContext(messages);
8362
+ function selectRetainedUserMessageEntries(messages, maxTokens = RETAINED_USER_MESSAGE_TOKENS) {
8328
8363
  const selected = [];
8329
8364
  let remaining = maxTokens;
8330
- for (const message of [...stripped].reverse()) {
8331
- if (message.role !== "user" || remaining <= 0) {
8365
+ for (let sourceIndex = messages.length - 1; sourceIndex >= 0; sourceIndex -= 1) {
8366
+ const stripped = stripRuntimeTurnContext([messages[sourceIndex]]);
8367
+ const message = stripped[0];
8368
+ if (!message || message.role !== "user" || remaining <= 0) {
8332
8369
  continue;
8333
8370
  }
8334
8371
  const text = sanitizeText(messageText(message));
@@ -8337,17 +8374,17 @@ function selectRetainedUserMessages(messages, maxTokens = RETAINED_USER_MESSAGE_
8337
8374
  }
8338
8375
  const tokens = estimateTextTokens(text);
8339
8376
  if (tokens <= remaining) {
8340
- selected.push(text);
8377
+ selected.push({ message: userMessage(text), sourceIndex });
8341
8378
  remaining -= tokens;
8342
8379
  continue;
8343
8380
  }
8344
8381
  const truncated = truncateToTokenBudget(text, remaining);
8345
8382
  if (truncated) {
8346
- selected.push(truncated);
8383
+ selected.push({ message: userMessage(truncated), sourceIndex });
8347
8384
  }
8348
8385
  break;
8349
8386
  }
8350
- return selected.reverse().map(userMessage);
8387
+ return selected.reverse();
8351
8388
  }
8352
8389
  function renderMessageForSummary(message) {
8353
8390
  const role = message.role;
@@ -8424,7 +8461,7 @@ async function summarizeContext(args, deps) {
8424
8461
  modelId: botConfig.fastModelId,
8425
8462
  threadId: args.metadata?.threadId ?? "",
8426
8463
  channelId: args.metadata?.channelId ?? "",
8427
- requesterId: args.metadata?.requesterId ?? "",
8464
+ actorId: args.metadata?.actorId ?? "",
8428
8465
  runId: args.metadata?.runId ?? ""
8429
8466
  }
8430
8467
  });
@@ -8443,11 +8480,12 @@ function estimateHistoryTokens(messages) {
8443
8480
  );
8444
8481
  return Math.max(usageEstimate, structuralEstimate);
8445
8482
  }
8446
- function buildReplacementHistory(args) {
8483
+ function buildReplacementProvenance(args) {
8447
8484
  return [
8448
- ...selectRetainedUserMessages(args.messages),
8449
- userMessage(`${COMPACTION_SUMMARY_PREFIX}
8450
- ${args.summary}`)
8485
+ ...args.retained.map(
8486
+ (entry) => args.sourceProvenance[entry.sourceIndex] ?? contextProvenance
8487
+ ),
8488
+ contextProvenance
8451
8489
  ];
8452
8490
  }
8453
8491
  function loadCompactionSource(messages) {
@@ -8484,7 +8522,7 @@ async function maybeCompactWithDeps(args, deps) {
8484
8522
  "context_compaction_summary_failed",
8485
8523
  {
8486
8524
  slackThreadId: args.metadata?.threadId,
8487
- slackUserId: args.metadata?.requesterId,
8525
+ slackUserId: args.metadata?.actorId,
8488
8526
  slackChannelId: args.metadata?.channelId,
8489
8527
  runId: args.metadata?.runId,
8490
8528
  assistantUserName: botConfig.userName,
@@ -8503,13 +8541,24 @@ async function maybeCompactWithDeps(args, deps) {
8503
8541
  });
8504
8542
  }
8505
8543
  async function writeCompactedThreadContext(args, sourceMessages, summary, context) {
8506
- const replacement = buildReplacementHistory({
8507
- messages: trimTrailingAssistantMessages(sourceMessages),
8508
- summary
8544
+ const sourceProjection = await loadProjectionWithProvenance({
8545
+ conversationId: args.conversationId
8509
8546
  });
8547
+ const retained = selectRetainedUserMessageEntries(
8548
+ trimTrailingAssistantMessages(sourceProjection.messages)
8549
+ );
8550
+ const replacement = [
8551
+ ...retained.map((entry) => entry.message),
8552
+ userMessage(`${COMPACTION_SUMMARY_PREFIX}
8553
+ ${summary}`)
8554
+ ];
8510
8555
  await commitMessages({
8511
8556
  conversationId: args.conversationId,
8512
8557
  messages: replacement,
8558
+ provenance: buildReplacementProvenance({
8559
+ retained,
8560
+ sourceProvenance: sourceProjection.provenance
8561
+ }),
8513
8562
  ttlMs: THREAD_STATE_TTL_MS3
8514
8563
  });
8515
8564
  updateConversationStats(args.conversation);
@@ -8544,7 +8593,7 @@ function createSubscribedReplyPolicy(deps) {
8544
8593
  "subscribed_message_classifier_failed",
8545
8594
  {
8546
8595
  slackThreadId: input.context.threadId,
8547
- slackUserId: input.context.requesterId,
8596
+ slackUserId: input.context.actorId,
8548
8597
  slackChannelId: input.context.channelId,
8549
8598
  runId: input.context.runId,
8550
8599
  assistantUserName: botConfig.userName,
@@ -8725,7 +8774,7 @@ async function resolveUserAttachmentsWithDeps(attachments, context, deps) {
8725
8774
  metadata: {
8726
8775
  threadId: context.threadId ?? "",
8727
8776
  channelId: context.channelId ?? "",
8728
- requesterId: context.requesterId ?? "",
8777
+ actorId: context.actorId ?? "",
8729
8778
  runId: context.runId ?? "",
8730
8779
  filename: attachment.name ?? ""
8731
8780
  }
@@ -8755,7 +8804,7 @@ async function resolveUserAttachmentsWithDeps(attachments, context, deps) {
8755
8804
  "attachment_skipped_size_limit",
8756
8805
  {
8757
8806
  slackThreadId: context.threadId,
8758
- slackUserId: context.requesterId,
8807
+ slackUserId: context.actorId,
8759
8808
  slackChannelId: context.channelId,
8760
8809
  runId: context.runId,
8761
8810
  assistantUserName: botConfig.userName,
@@ -8780,7 +8829,7 @@ async function resolveUserAttachmentsWithDeps(attachments, context, deps) {
8780
8829
  "image_attachment_processing_failed",
8781
8830
  {
8782
8831
  slackThreadId: context.threadId,
8783
- slackUserId: context.requesterId,
8832
+ slackUserId: context.actorId,
8784
8833
  slackChannelId: context.channelId,
8785
8834
  runId: context.runId,
8786
8835
  assistantUserName: botConfig.userName,
@@ -8799,7 +8848,7 @@ async function resolveUserAttachmentsWithDeps(attachments, context, deps) {
8799
8848
  "attachment_resolution_failed",
8800
8849
  {
8801
8850
  slackThreadId: context.threadId,
8802
- slackUserId: context.requesterId,
8851
+ slackUserId: context.actorId,
8803
8852
  slackChannelId: context.channelId,
8804
8853
  runId: context.runId,
8805
8854
  assistantUserName: botConfig.userName,
@@ -8835,7 +8884,7 @@ async function summarizeConversationImage(args, deps) {
8835
8884
  metadata: {
8836
8885
  threadId: args.context.threadId ?? "",
8837
8886
  channelId: args.context.channelId ?? "",
8838
- requesterId: args.context.requesterId ?? "",
8887
+ actorId: args.context.actorId ?? "",
8839
8888
  runId: args.context.runId ?? "",
8840
8889
  fileId: args.fileId
8841
8890
  }
@@ -8849,7 +8898,7 @@ async function summarizeConversationImage(args, deps) {
8849
8898
  "conversation_image_vision_failed",
8850
8899
  {
8851
8900
  slackThreadId: args.context.threadId,
8852
- slackUserId: args.context.requesterId,
8901
+ slackUserId: args.context.actorId,
8853
8902
  slackChannelId: args.context.channelId,
8854
8903
  runId: args.context.runId,
8855
8904
  assistantUserName: botConfig.userName,
@@ -8905,7 +8954,7 @@ async function hydrateConversationVisionContextWithDeps(conversation, context, d
8905
8954
  "conversation_image_replies_fetch_failed",
8906
8955
  {
8907
8956
  slackThreadId: context.threadId,
8908
- slackUserId: context.requesterId,
8957
+ slackUserId: context.actorId,
8909
8958
  slackChannelId: context.channelId,
8910
8959
  runId: context.runId,
8911
8960
  assistantUserName: botConfig.userName,
@@ -8972,7 +9021,7 @@ async function hydrateConversationVisionContextWithDeps(conversation, context, d
8972
9021
  "conversation_image_skipped_size_limit",
8973
9022
  {
8974
9023
  slackThreadId: context.threadId,
8975
- slackUserId: context.requesterId,
9024
+ slackUserId: context.actorId,
8976
9025
  slackChannelId: context.channelId,
8977
9026
  runId: context.runId,
8978
9027
  assistantUserName: botConfig.userName,
@@ -8999,7 +9048,7 @@ async function hydrateConversationVisionContextWithDeps(conversation, context, d
8999
9048
  "conversation_image_download_failed",
9000
9049
  {
9001
9050
  slackThreadId: context.threadId,
9002
- slackUserId: context.requesterId,
9051
+ slackUserId: context.actorId,
9003
9052
  slackChannelId: context.channelId,
9004
9053
  runId: context.runId,
9005
9054
  assistantUserName: botConfig.userName,
@@ -9019,7 +9068,7 @@ async function hydrateConversationVisionContextWithDeps(conversation, context, d
9019
9068
  "conversation_image_skipped_size_limit",
9020
9069
  {
9021
9070
  slackThreadId: context.threadId,
9022
- slackUserId: context.requesterId,
9071
+ slackUserId: context.actorId,
9023
9072
  slackChannelId: context.channelId,
9024
9073
  runId: context.runId,
9025
9074
  assistantUserName: botConfig.userName,
@@ -9062,7 +9111,7 @@ async function hydrateConversationVisionContextWithDeps(conversation, context, d
9062
9111
  "conversation_image_context_hydrated",
9063
9112
  {
9064
9113
  slackThreadId: context.threadId,
9065
- slackUserId: context.requesterId,
9114
+ slackUserId: context.actorId,
9066
9115
  slackChannelId: context.channelId,
9067
9116
  runId: context.runId,
9068
9117
  assistantUserName: botConfig.userName,
@@ -9168,7 +9217,7 @@ function maybeUpdateAssistantTitle(args) {
9168
9217
  "thread_title_generation_failed",
9169
9218
  {
9170
9219
  slackThreadId: args.threadId,
9171
- slackUserId: args.requesterId,
9220
+ slackUserId: args.actorId,
9172
9221
  slackChannelId: args.channelId,
9173
9222
  runId: args.runId,
9174
9223
  assistantUserName: args.assistantUserName,
@@ -9202,7 +9251,7 @@ function maybeUpdateAssistantTitle(args) {
9202
9251
  "thread_title_generation_permission_denied",
9203
9252
  {
9204
9253
  slackThreadId: args.threadId,
9205
- slackUserId: args.requesterId,
9254
+ slackUserId: args.actorId,
9206
9255
  slackChannelId: args.channelId,
9207
9256
  runId: args.runId,
9208
9257
  assistantUserName: args.assistantUserName,
@@ -9216,7 +9265,7 @@ function maybeUpdateAssistantTitle(args) {
9216
9265
  "thread_title_slack_update_failed",
9217
9266
  {
9218
9267
  slackThreadId: args.threadId,
9219
- slackUserId: args.requesterId,
9268
+ slackUserId: args.actorId,
9220
9269
  slackChannelId: args.channelId,
9221
9270
  runId: args.runId,
9222
9271
  assistantUserName: args.assistantUserName,
@@ -9249,7 +9298,7 @@ async function maybeApplyProviderDefaultConfigRequest(args) {
9249
9298
  await args.channelConfiguration.set({
9250
9299
  key: "github.repo",
9251
9300
  value: repo,
9252
- updatedBy: args.requesterId,
9301
+ updatedBy: args.actorId,
9253
9302
  source: "provider-default-config"
9254
9303
  });
9255
9304
  return {
@@ -9269,8 +9318,8 @@ function collectCanvasUrls(artifacts) {
9269
9318
  ].filter((url) => typeof url === "string" && url !== "")
9270
9319
  );
9271
9320
  }
9272
- function turnRequester(requester) {
9273
- return toStoredSlackRequester(requester);
9321
+ function turnActor(actor) {
9322
+ return toStoredSlackActor(actor);
9274
9323
  }
9275
9324
  function parkedInputKey(message) {
9276
9325
  if (message.role !== "user") {
@@ -9330,12 +9379,27 @@ function queuedInstructionActor(queued) {
9330
9379
  ...slackTs ? { slackTs } : {}
9331
9380
  };
9332
9381
  }
9382
+ function queuedInstructionProvenance(queued, teamId) {
9383
+ if (isResourceEventMessage(queued.message)) {
9384
+ return contextProvenance;
9385
+ }
9386
+ const identity = getMessageActorIdentity(queued.message);
9387
+ const author = identity && "platform" in identity ? identity : createActor(
9388
+ { userId: parseActorUserId(queued.message.author.userId) },
9389
+ {
9390
+ platform: "slack",
9391
+ teamId,
9392
+ userId: parseActorUserId(queued.message.author.userId)
9393
+ }
9394
+ );
9395
+ return instructionProvenanceFor(author);
9396
+ }
9333
9397
  function isResourceEventMessage(message) {
9334
9398
  const raw = message.raw && typeof message.raw === "object" ? message.raw : void 0;
9335
9399
  return raw?.event_type === "resource_event";
9336
9400
  }
9337
9401
  function resourceEventCredentialContext(message) {
9338
- return isResourceEventMessage(message) ? { actor: { type: "system", id: "resource-event" } } : void 0;
9402
+ return isResourceEventMessage(message) ? { actor: { platform: "system", name: "resource-event" } } : void 0;
9339
9403
  }
9340
9404
  async function resolveChannelName(thread) {
9341
9405
  const existingName = thread.channel.name?.trim();
@@ -9466,13 +9530,14 @@ function createReplyToThread(deps) {
9466
9530
  const credentialContext = resourceEventCredentialContext(message) ?? {
9467
9531
  actor: { type: "user", userId: message.author.userId }
9468
9532
  };
9469
- const requester = credentialContext.actor.type === "user" ? await ensureSlackMessageActorIdentity(
9533
+ const actor = "type" in credentialContext.actor ? await ensureSlackMessageActorIdentity(
9470
9534
  message,
9471
9535
  teamId,
9472
9536
  deps.services.lookupSlackUser
9473
9537
  ) : void 0;
9474
- const storedRequester = requester ? turnRequester(requester) : void 0;
9475
- const slackRequesterId = requester?.userId;
9538
+ const executionActor = "type" in credentialContext.actor ? actor : credentialContext.actor;
9539
+ const storedActor = actor ? turnActor(actor) : void 0;
9540
+ const slackActorId = actor?.userId;
9476
9541
  const preparedState = options.preparedState ?? await deps.prepareTurnState({
9477
9542
  thread,
9478
9543
  message,
@@ -9483,7 +9548,7 @@ function createReplyToThread(deps) {
9483
9548
  queuedMessages: options.queuedMessages,
9484
9549
  context: {
9485
9550
  threadId,
9486
- requesterId: slackRequesterId,
9551
+ actorId: slackActorId,
9487
9552
  channelId,
9488
9553
  runId
9489
9554
  }
@@ -9508,11 +9573,11 @@ function createReplyToThread(deps) {
9508
9573
  await options.beforeFirstResponsePost?.();
9509
9574
  };
9510
9575
  const postAuthPauseNotice = async (providerDisplayName) => {
9511
- if (!requester) {
9512
- throw new Error("Slack auth pause notice requires a requester");
9576
+ if (!actor) {
9577
+ throw new Error("Slack auth pause notice requires an actor");
9513
9578
  }
9514
9579
  const text = buildAuthPauseResponse(
9515
- requester.userId,
9580
+ actor.userId,
9516
9581
  providerDisplayName
9517
9582
  );
9518
9583
  const footer = buildSlackReplyFooter({ conversationId });
@@ -9555,6 +9620,7 @@ function createReplyToThread(deps) {
9555
9620
  const attachments = queued.message.attachments;
9556
9621
  return {
9557
9622
  actor: queuedInstructionActor(queued),
9623
+ provenance: queuedInstructionProvenance(queued, teamId),
9558
9624
  text: queued.userText,
9559
9625
  timestampMs: queued.message.metadata.dateSent.getTime(),
9560
9626
  omittedImageAttachmentCount: !isVisionEnabled() && hasPotentialImageAttachment(attachments) ? countPotentialImageAttachments(attachments) : 0,
@@ -9562,7 +9628,7 @@ function createReplyToThread(deps) {
9562
9628
  attachments,
9563
9629
  {
9564
9630
  threadId,
9565
- requesterId: isResourceEventMessage(queued.message) ? void 0 : queued.message.author.userId,
9631
+ actorId: isResourceEventMessage(queued.message) ? void 0 : queued.message.author.userId,
9566
9632
  channelId,
9567
9633
  runId,
9568
9634
  conversation: preparedState.conversation,
@@ -9573,26 +9639,8 @@ function createReplyToThread(deps) {
9573
9639
  })
9574
9640
  );
9575
9641
  };
9576
- const appendParkedTurnInput = async (parkedSessionId) => {
9577
- if (!conversationId) {
9578
- return true;
9579
- }
9580
- const parkedMessages = [
9581
- ...options.queuedMessages ?? [],
9582
- {
9583
- explicitMention: Boolean(
9584
- options.explicitMention || message.isMention
9585
- ),
9586
- message,
9587
- rawText: currentText.rawText,
9588
- userText: currentText.userText
9589
- }
9590
- ].filter(
9591
- // Redelivery of the parked turn's own message must not duplicate
9592
- // the prompt that already started the session.
9593
- (queued) => buildDeterministicTurnId(queued.message.id) !== parkedSessionId
9594
- );
9595
- if (parkedMessages.length === 0) {
9642
+ const drainParkedInputToSessionLog = async (pairs) => {
9643
+ if (!conversationId || pairs.length === 0) {
9596
9644
  return true;
9597
9645
  }
9598
9646
  const stateAdapter = getStateAdapter();
@@ -9602,13 +9650,14 @@ function createReplyToThread(deps) {
9602
9650
  return false;
9603
9651
  }
9604
9652
  try {
9605
- const piMessages = (await resolveSteeringMessages(parkedMessages)).map(buildSteeringPiMessage);
9606
- const projection = await loadProjection({ conversationId });
9653
+ const projection = await loadProjectionWithProvenance({
9654
+ conversationId
9655
+ });
9607
9656
  const appendedKeys = new Set(
9608
- projection.map(parkedInputKey).filter((key) => key !== void 0)
9657
+ projection.messages.map(parkedInputKey).filter((key) => key !== void 0)
9609
9658
  );
9610
- const missing = piMessages.filter((piMessage) => {
9611
- const key = parkedInputKey(piMessage);
9659
+ const missing = pairs.filter((pair) => {
9660
+ const key = parkedInputKey(pair.message);
9612
9661
  return key === void 0 || !appendedKeys.has(key);
9613
9662
  });
9614
9663
  if (missing.length === 0) {
@@ -9616,8 +9665,14 @@ function createReplyToThread(deps) {
9616
9665
  }
9617
9666
  await commitMessages({
9618
9667
  conversationId,
9619
- messages: [...projection, ...missing],
9620
- requester: storedRequester,
9668
+ messages: [
9669
+ ...projection.messages,
9670
+ ...missing.map((pair) => pair.message)
9671
+ ],
9672
+ provenance: [
9673
+ ...projection.provenance,
9674
+ ...missing.map((pair) => pair.provenance)
9675
+ ],
9621
9676
  ttlMs: THREAD_STATE_TTL_MS4
9622
9677
  });
9623
9678
  return true;
@@ -9625,6 +9680,34 @@ function createReplyToThread(deps) {
9625
9680
  await stateAdapter.releaseLock(lock);
9626
9681
  }
9627
9682
  };
9683
+ const appendParkedTurnInput = async (parkedSessionId) => {
9684
+ if (!conversationId) {
9685
+ return true;
9686
+ }
9687
+ const parkedMessages = [
9688
+ ...options.queuedMessages ?? [],
9689
+ {
9690
+ explicitMention: Boolean(
9691
+ options.explicitMention || message.isMention
9692
+ ),
9693
+ message,
9694
+ rawText: currentText.rawText,
9695
+ userText: currentText.userText
9696
+ }
9697
+ ].filter(
9698
+ // Redelivery of the parked turn's own message must not duplicate
9699
+ // the prompt that already started the session.
9700
+ (queued) => buildDeterministicTurnId(queued.message.id) !== parkedSessionId
9701
+ );
9702
+ if (parkedMessages.length === 0) {
9703
+ return true;
9704
+ }
9705
+ const parkedPairs = (await resolveSteeringMessages(parkedMessages)).map((steering) => ({
9706
+ message: buildSteeringPiMessage(steering),
9707
+ provenance: steering.provenance
9708
+ }));
9709
+ return drainParkedInputToSessionLog(parkedPairs);
9710
+ };
9628
9711
  if (preparedState.userMessageAlreadyReplied) {
9629
9712
  await persistThreadState(thread, {
9630
9713
  conversation: preparedState.conversation
@@ -9704,7 +9787,7 @@ function createReplyToThread(deps) {
9704
9787
  }
9705
9788
  const configReply = await maybeApplyProviderDefaultConfigRequest({
9706
9789
  channelConfiguration: preparedState.channelConfiguration,
9707
- requesterId: requester?.userId,
9790
+ actorId: actor?.userId,
9708
9791
  text: effectiveUserText
9709
9792
  });
9710
9793
  if (configReply) {
@@ -9753,7 +9836,7 @@ function createReplyToThread(deps) {
9753
9836
  startedAtMs: turnStartedAtMs,
9754
9837
  state: "running",
9755
9838
  surface: "slack",
9756
- requester,
9839
+ actor,
9757
9840
  destination,
9758
9841
  destinationVisibility,
9759
9842
  source,
@@ -9770,7 +9853,7 @@ function createReplyToThread(deps) {
9770
9853
  void initConversationContext(conversationId, {
9771
9854
  channelName,
9772
9855
  originSurface: "slack",
9773
- originRequester: storedRequester,
9856
+ originActor: storedActor,
9774
9857
  startedAtMs: turnStartedAtMs
9775
9858
  }).catch((error) => {
9776
9859
  logException(
@@ -9817,15 +9900,15 @@ function createReplyToThread(deps) {
9817
9900
  conversation: preparedState.conversation
9818
9901
  });
9819
9902
  await options.onTurnStatePersisted?.();
9820
- if (requester) {
9903
+ if (actor) {
9821
9904
  setSentryUser({
9822
- id: requester.userId,
9823
- ...requester.userName ? { username: requester.userName } : {},
9824
- ...requester.email ? { email: requester.email } : {}
9905
+ id: actor.userId,
9906
+ ...actor.userName ? { username: actor.userName } : {},
9907
+ ...actor.email ? { email: actor.email } : {}
9825
9908
  });
9826
9909
  }
9827
- if (requester?.userName) {
9828
- setTags({ slackUserName: requester.userName });
9910
+ if (actor?.userName) {
9911
+ setTags({ slackUserName: actor.userName });
9829
9912
  }
9830
9913
  const turnAttachments = collectTurnAttachments(
9831
9914
  message,
@@ -9835,7 +9918,7 @@ function createReplyToThread(deps) {
9835
9918
  turnAttachments,
9836
9919
  {
9837
9920
  threadId,
9838
- requesterId: slackRequesterId,
9921
+ actorId: slackActorId,
9839
9922
  channelId,
9840
9923
  runId,
9841
9924
  conversation: preparedState.conversation,
@@ -9891,7 +9974,7 @@ function createReplyToThread(deps) {
9891
9974
  conversationId,
9892
9975
  metadata: {
9893
9976
  threadId,
9894
- requesterId: slackRequesterId,
9977
+ actorId: slackActorId,
9895
9978
  channelId,
9896
9979
  runId
9897
9980
  },
@@ -9906,16 +9989,29 @@ function createReplyToThread(deps) {
9906
9989
  }
9907
9990
  }
9908
9991
  const hasDurablePromptHistory = Boolean(piMessages?.length);
9909
- const queuedInstructionPiMessages = (await resolveSteeringMessages(
9992
+ const batchedInstructions = (await resolveSteeringMessages(
9910
9993
  (options.queuedMessages ?? []).filter(
9911
9994
  (queued) => queued.explicitMention
9912
9995
  )
9913
- )).map(buildSteeringPiMessage);
9914
- if (queuedInstructionPiMessages.length > 0) {
9915
- piMessages = [
9916
- ...piMessages ?? [],
9917
- ...queuedInstructionPiMessages
9918
- ];
9996
+ )).map((steering) => ({
9997
+ message: buildSteeringPiMessage(steering),
9998
+ provenance: steering.provenance
9999
+ }));
10000
+ if (!await drainParkedInputToSessionLog(batchedInstructions)) {
10001
+ shouldPersistFailureState = false;
10002
+ throw new TurnInputDeferredError();
10003
+ }
10004
+ if (batchedInstructions.length > 0) {
10005
+ const presentKeys = new Set(
10006
+ (piMessages ?? []).map(parkedInputKey).filter((key) => key !== void 0)
10007
+ );
10008
+ const newlyBatched = batchedInstructions.map((entry) => entry.message).filter((batchedMessage) => {
10009
+ const key = parkedInputKey(batchedMessage);
10010
+ return key === void 0 || !presentKeys.has(key);
10011
+ });
10012
+ if (newlyBatched.length > 0) {
10013
+ piMessages = [...piMessages ?? [], ...newlyBatched];
10014
+ }
9919
10015
  }
9920
10016
  status.start();
9921
10017
  const assistantTitleTask = maybeUpdateAssistantTitle({
@@ -9927,7 +10023,7 @@ function createReplyToThread(deps) {
9927
10023
  generateThreadTitle: deps.services.generateThreadTitle,
9928
10024
  getSlackAdapter: deps.getSlackAdapter,
9929
10025
  modelId: botConfig.fastModelId,
9930
- requesterId: slackRequesterId,
10026
+ actorId: slackActorId,
9931
10027
  runId,
9932
10028
  threadId
9933
10029
  });
@@ -9980,8 +10076,8 @@ function createReplyToThread(deps) {
9980
10076
  );
9981
10077
  });
9982
10078
  const toolChannelId = preparedState.artifacts.assistantContextChannelId ?? channelId;
9983
- const activeInstructionAuthorId = requester?.userId ?? parseActorUserId(message.author.userId);
9984
- const activeInstructionAuthorName = requester?.fullName ?? requester?.userName;
10079
+ const activeInstructionAuthorId = actor?.userId ?? parseActorUserId(message.author.userId);
10080
+ const activeInstructionAuthorName = actor?.fullName ?? actor?.userName;
9985
10081
  const promptConversationContext = appendRecentThreadMessagesToContext(
9986
10082
  preparedState.conversationContext,
9987
10083
  options.queuedMessages ?? []
@@ -10014,7 +10110,7 @@ function createReplyToThread(deps) {
10014
10110
  },
10015
10111
  routing: {
10016
10112
  credentialContext,
10017
- requester,
10113
+ actor,
10018
10114
  slackConversation,
10019
10115
  source,
10020
10116
  destination,
@@ -10029,7 +10125,7 @@ function createReplyToThread(deps) {
10029
10125
  runId,
10030
10126
  channelId,
10031
10127
  channelName,
10032
- requesterId: slackRequesterId
10128
+ actorId: slackActorId
10033
10129
  },
10034
10130
  toolChannelId
10035
10131
  },
@@ -10083,7 +10179,7 @@ function createReplyToThread(deps) {
10083
10179
  }
10084
10180
  });
10085
10181
  if (outcome.status === "awaiting_auth") {
10086
- if (!requester) {
10182
+ if (!actor) {
10087
10183
  const text = `I could not act on this subscribed event because ${outcome.providerDisplayName} needs user authorization. Ask me in this thread to connect ${outcome.providerDisplayName} before retrying.`;
10088
10184
  await postThreadReply(
10089
10185
  buildSlackOutputMessage(text),
@@ -10277,13 +10373,13 @@ function createReplyToThread(deps) {
10277
10373
  messages: reply.piMessages,
10278
10374
  logContext: {
10279
10375
  threadId,
10280
- requesterId: slackRequesterId,
10376
+ actorId: slackActorId,
10281
10377
  channelId,
10282
10378
  runId,
10283
10379
  assistantUserName: botConfig.userName,
10284
10380
  modelId: reply.diagnostics.modelId
10285
10381
  },
10286
- requester,
10382
+ actor: executionActor,
10287
10383
  surface: "slack"
10288
10384
  });
10289
10385
  } else if (conversationId) {
@@ -10296,7 +10392,7 @@ function createReplyToThread(deps) {
10296
10392
  sliceId: 1,
10297
10393
  startedAtMs: message.metadata.dateSent.getTime(),
10298
10394
  state: "completed",
10299
- requester,
10395
+ actor: executionActor,
10300
10396
  destination,
10301
10397
  destinationVisibility,
10302
10398
  source,
@@ -10367,6 +10463,10 @@ function createReplyToThread(deps) {
10367
10463
  shouldPersistFailureState = false;
10368
10464
  throw error;
10369
10465
  }
10466
+ if (error instanceof TurnInputDeferredError) {
10467
+ shouldPersistFailureState = false;
10468
+ throw error;
10469
+ }
10370
10470
  if (error === agentContinueScheduleError) {
10371
10471
  shouldPersistFailureState = true;
10372
10472
  throw error;
@@ -10449,7 +10549,7 @@ function createReplyToThread(deps) {
10449
10549
  sliceId: 1,
10450
10550
  startedAtMs: message.metadata.dateSent.getTime(),
10451
10551
  state: "failed",
10452
- requester,
10552
+ actor,
10453
10553
  destination,
10454
10554
  destinationVisibility,
10455
10555
  source,
@@ -10685,7 +10785,7 @@ function createPrepareTurnState(deps) {
10685
10785
  await deps.hydrateConversationVisionContext(conversation, {
10686
10786
  threadId: args.context.threadId,
10687
10787
  channelId: args.context.channelId,
10688
- requesterId: args.context.requesterId,
10788
+ actorId: args.context.actorId,
10689
10789
  runId: args.context.runId,
10690
10790
  threadTs: getThreadTs(args.context.threadId)
10691
10791
  });
@@ -10693,7 +10793,7 @@ function createPrepareTurnState(deps) {
10693
10793
  await deps.compactConversationIfNeeded(conversation, {
10694
10794
  threadId: args.context.threadId,
10695
10795
  channelId: args.context.channelId,
10696
- requesterId: args.context.requesterId,
10796
+ actorId: args.context.actorId,
10697
10797
  runId: args.context.runId
10698
10798
  });
10699
10799
  const conversationContext = buildConversationContext(conversation, {
@@ -10977,11 +11077,11 @@ async function failContinuationStartup(args) {
10977
11077
  );
10978
11078
  }
10979
11079
  }
10980
- async function resolveContinuationRequester(args) {
10981
- const stored = args.sessionRecordRequester;
11080
+ async function resolveContinuationActor(args) {
11081
+ const stored = args.sessionRecordActor;
10982
11082
  if (stored?.platform === "slack" && stored.teamId === args.teamId && stored.userId === args.userId) {
10983
- return createSlackResumeRequester({
10984
- requester: stored,
11083
+ return createSlackResumeActor({
11084
+ actor: stored,
10985
11085
  teamId: args.teamId,
10986
11086
  userId: args.userId
10987
11087
  });
@@ -10989,12 +11089,12 @@ async function resolveContinuationRequester(args) {
10989
11089
  const work = await getConversationWorkState2({
10990
11090
  conversationId: args.conversationId
10991
11091
  });
10992
- const workRequester = work?.requester;
10993
- if (workRequester && workRequester.teamId === args.teamId && workRequester.slackUserId === args.userId) {
10994
- return createSlackRequester(args.teamId, args.userId, {
10995
- email: workRequester.email,
10996
- fullName: workRequester.fullName,
10997
- userName: workRequester.slackUserName
11092
+ const workActor = work?.actor;
11093
+ if (workActor && workActor.teamId === args.teamId && workActor.slackUserId === args.userId) {
11094
+ return createSlackActor(args.teamId, args.userId, {
11095
+ email: workActor.email,
11096
+ fullName: workActor.fullName,
11097
+ userName: workActor.slackUserName
10998
11098
  });
10999
11099
  }
11000
11100
  return void 0;
@@ -11062,16 +11162,16 @@ async function continueSlackAgentRun(payload, options) {
11062
11162
  payload.destination,
11063
11163
  "Slack continuation"
11064
11164
  );
11065
- const requester = await resolveContinuationRequester({
11165
+ const actor = await resolveContinuationActor({
11066
11166
  conversationId: payload.conversationId,
11067
- sessionRecordRequester: activeSessionRecord.requester,
11167
+ sessionRecordActor: activeSessionRecord.actor,
11068
11168
  teamId: destination.teamId,
11069
11169
  userId: userMessage2.author.userId
11070
11170
  });
11071
- if (!requester) {
11171
+ if (!actor) {
11072
11172
  await failStrandedSessionWithFallback({
11073
11173
  conversationId: payload.conversationId,
11074
- errorMessage: "Stored Slack requester missing for continuation",
11174
+ errorMessage: "Stored Slack actor missing for continuation",
11075
11175
  sessionRecord: activeSessionRecord
11076
11176
  });
11077
11177
  return false;
@@ -11098,10 +11198,10 @@ async function continueSlackAgentRun(payload, options) {
11098
11198
  credentialContext: {
11099
11199
  actor: {
11100
11200
  type: "user",
11101
- userId: requester.userId
11201
+ userId: actor.userId
11102
11202
  }
11103
11203
  },
11104
- requester,
11204
+ actor,
11105
11205
  destination: payload.destination,
11106
11206
  source: activeSessionRecord.source,
11107
11207
  correlation: {
@@ -11109,7 +11209,7 @@ async function continueSlackAgentRun(payload, options) {
11109
11209
  turnId: payload.sessionId,
11110
11210
  channelId: thread.channelId,
11111
11211
  threadTs: thread.threadTs,
11112
- requesterId: requester.userId
11212
+ actorId: actor.userId
11113
11213
  },
11114
11214
  toolChannelId: artifacts.assistantContextChannelId ?? thread.channelId
11115
11215
  },
@@ -11255,7 +11355,7 @@ async function recoverStrandedRunningSession(args) {
11255
11355
  messages: sessionRecord.piMessages,
11256
11356
  errorMessage: "Recovered running session after hard worker death",
11257
11357
  logContext: { modelId: botConfig.modelId },
11258
- requester: sessionRecord.requester,
11358
+ actor: sessionRecord.actor,
11259
11359
  surface: sessionRecord.surface
11260
11360
  });
11261
11361
  if (!parked) {