@sentry/junior 0.88.0 → 0.90.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 (158) hide show
  1. package/README.md +16 -5
  2. package/dist/{agent-hooks-RIJ5TSWP.js → agent-hooks-MXAF7RQL.js} +10 -10
  3. package/dist/api/people/list.js +8 -8
  4. package/dist/api/people/profile.js +8 -8
  5. package/dist/api-reference.d.ts +1 -1
  6. package/dist/app.js +716 -732
  7. package/dist/{catalog-runtime-MW7XERSU.js → catalog-runtime-DXE6NXHT.js} +5 -5
  8. package/dist/chat/agent/index.d.ts +4 -0
  9. package/dist/chat/agent/prompt.d.ts +78 -0
  10. package/dist/chat/{respond.d.ts → agent/request.d.ts} +98 -55
  11. package/dist/chat/agent/resume.d.ts +65 -0
  12. package/dist/chat/agent/sandbox.d.ts +15 -0
  13. package/dist/chat/agent/session.d.ts +20 -0
  14. package/dist/chat/agent/skills.d.ts +26 -0
  15. package/dist/chat/agent/tools.d.ts +78 -0
  16. package/dist/chat/agent-dispatch/runner.d.ts +3 -5
  17. package/dist/chat/app/production.d.ts +3 -1
  18. package/dist/chat/app/services.d.ts +1 -4
  19. package/dist/chat/logging.d.ts +2 -0
  20. package/dist/chat/mcp/tool-manager.d.ts +1 -6
  21. package/dist/chat/pi/messages.d.ts +18 -2
  22. package/dist/chat/pi/transcript.d.ts +31 -0
  23. package/dist/chat/plugins/agent-hooks.d.ts +2 -2
  24. package/dist/chat/prompt.d.ts +1 -1
  25. package/dist/chat/runtime/agent-continue-runner.d.ts +5 -5
  26. package/dist/chat/runtime/agent-run-outcome.d.ts +21 -0
  27. package/dist/chat/runtime/agent-runner.d.ts +11 -0
  28. package/dist/chat/runtime/delivered-turn-state.d.ts +2 -2
  29. package/dist/chat/runtime/generated-artifacts.d.ts +16 -0
  30. package/dist/chat/runtime/reply-executor.d.ts +2 -2
  31. package/dist/chat/runtime/slack-resume.d.ts +21 -12
  32. package/dist/chat/runtime/turn.d.ts +5 -39
  33. package/dist/chat/services/reply-delivery-plan.d.ts +0 -8
  34. package/dist/chat/services/turn-failure-response.d.ts +4 -4
  35. package/dist/chat/services/turn-result.d.ts +4 -7
  36. package/dist/chat/slack/channel.d.ts +9 -5
  37. package/dist/chat/slack/client.d.ts +3 -1
  38. package/dist/chat/slack/context.d.ts +17 -5
  39. package/dist/chat/slack/id-param.d.ts +25 -0
  40. package/dist/chat/slack/ids.d.ts +18 -4
  41. package/dist/chat/slack/outbound.d.ts +16 -0
  42. package/dist/chat/slack/output.d.ts +3 -3
  43. package/dist/chat/slack/reply.d.ts +4 -7
  44. package/dist/chat/slack/timestamp-param.d.ts +25 -0
  45. package/dist/chat/slack/tools/canvas/context.d.ts +18 -0
  46. package/dist/chat/slack/tools/canvas/create.d.ts +4 -0
  47. package/dist/chat/slack/tools/canvas/edit.d.ts +3 -0
  48. package/dist/chat/slack/tools/canvas/read.d.ts +6 -0
  49. package/dist/chat/slack/tools/canvas/write.d.ts +3 -0
  50. package/dist/chat/{tools/slack → slack/tools}/channel-access.d.ts +4 -3
  51. package/dist/chat/{tools → slack/tools}/channel-capabilities.d.ts +2 -0
  52. package/dist/chat/slack/tools/channel-list-messages.d.ts +3 -0
  53. package/dist/chat/{tools/slack → slack/tools}/context.d.ts +5 -4
  54. package/dist/chat/slack/tools/list/add-items.d.ts +3 -0
  55. package/dist/chat/{tools/slack/lists.d.ts → slack/tools/list/api.d.ts} +2 -1
  56. package/dist/chat/slack/tools/list/create.d.ts +3 -0
  57. package/dist/chat/slack/tools/list/get-items.d.ts +3 -0
  58. package/dist/chat/slack/tools/list/update-item.d.ts +3 -0
  59. package/dist/chat/slack/tools/message-add-reaction.d.ts +4 -0
  60. package/dist/chat/slack/tools/send-message.d.ts +11 -0
  61. package/dist/chat/{tools/slack → slack/tools}/slack-message-url.d.ts +5 -5
  62. package/dist/chat/slack/tools/thread-read.d.ts +6 -0
  63. package/dist/chat/slack/tools/user-lookup.d.ts +2 -0
  64. package/dist/chat/slack/users.d.ts +2 -1
  65. package/dist/chat/{services → slack}/vision-context.d.ts +4 -2
  66. package/dist/chat/state/session-log.d.ts +1 -1
  67. package/dist/chat/tool-exposure.d.ts +10 -0
  68. package/dist/chat/tool-support/catalog-tool-call.d.ts +10 -0
  69. package/dist/chat/{tools/execution → tool-support}/normalize-result.d.ts +4 -1
  70. package/dist/chat/{tools/agent-tools.d.ts → tool-support/pi-tool-adapter.d.ts} +3 -9
  71. package/dist/chat/tool-support/schema-summary.d.ts +2 -0
  72. package/dist/chat/{tools → tool-support}/skill/mcp-tool-summary.d.ts +0 -6
  73. package/dist/chat/tool-support/structured-result.d.ts +73 -0
  74. package/dist/chat/tool-support/text-range-result.d.ts +58 -0
  75. package/dist/chat/tool-support/tool-execution-report.d.ts +7 -0
  76. package/dist/chat/tool-support/zod-tool.d.ts +27 -0
  77. package/dist/chat/tools/advisor/tool.d.ts +9 -18
  78. package/dist/chat/tools/definition.d.ts +56 -9
  79. package/dist/chat/tools/execute-tool.d.ts +3 -0
  80. package/dist/chat/tools/index.d.ts +3 -2
  81. package/dist/chat/tools/resource-events.d.ts +3 -13
  82. package/dist/chat/tools/runtime/report-progress.d.ts +1 -3
  83. package/dist/chat/tools/sandbox/bash.d.ts +1 -4
  84. package/dist/chat/tools/sandbox/edit-file.d.ts +25 -7
  85. package/dist/chat/tools/sandbox/file-uploads.d.ts +30 -0
  86. package/dist/chat/tools/sandbox/file-utils.d.ts +10 -1
  87. package/dist/chat/tools/sandbox/find-files.d.ts +12 -11
  88. package/dist/chat/tools/sandbox/grep.d.ts +18 -12
  89. package/dist/chat/tools/sandbox/list-dir.d.ts +15 -7
  90. package/dist/chat/tools/sandbox/read-file.d.ts +2 -31
  91. package/dist/chat/tools/sandbox/write-file.d.ts +1 -4
  92. package/dist/chat/tools/search-tools.d.ts +4 -0
  93. package/dist/chat/tools/skill/call-mcp-tool.d.ts +1 -4
  94. package/dist/chat/tools/skill/load-skill.d.ts +4 -5
  95. package/dist/chat/tools/skill/search-mcp-tools.d.ts +1 -5
  96. package/dist/chat/tools/system-time.d.ts +1 -1
  97. package/dist/chat/tools/types.d.ts +15 -5
  98. package/dist/chat/tools/web/fetch-content.d.ts +4 -2
  99. package/dist/chat/tools/web/fetch-tool.d.ts +4 -4
  100. package/dist/chat/tools/web/image-generate.d.ts +4 -3
  101. package/dist/chat/tools/web/search.d.ts +1 -4
  102. package/dist/{chunk-4IXHIV37.js → chunk-2S7M37HY.js} +6 -8
  103. package/dist/{chunk-L7OHKDOX.js → chunk-3MPOMK3K.js} +58 -7
  104. package/dist/{chunk-V6XDCS3X.js → chunk-5GBUZI6M.js} +4 -4
  105. package/dist/{chunk-7ES37H6U.js → chunk-AN2437E3.js} +4 -4
  106. package/dist/chunk-AOISHLSF.js +747 -0
  107. package/dist/{chunk-NYJLQI42.js → chunk-BKSZL4QO.js} +11257 -11957
  108. package/dist/{chunk-XS6NLQPA.js → chunk-DACFZ5CI.js} +474 -33
  109. package/dist/chunk-GCWD2VHP.js +1216 -0
  110. package/dist/chunk-GHGPTPBL.js +53 -0
  111. package/dist/{chunk-S35CPNPT.js → chunk-HXL2ZV74.js} +40 -216
  112. package/dist/{chunk-PBV4ZIVM.js → chunk-IRRMABQD.js} +1 -1
  113. package/dist/{chunk-2DPZRS3B.js → chunk-IX76WFJV.js} +8 -8
  114. package/dist/{chunk-66NX7MNW.js → chunk-KC42JAAQ.js} +1 -1
  115. package/dist/chunk-LFLTJQVR.js +90 -0
  116. package/dist/{chunk-IATAYWFU.js → chunk-NW7AXDA5.js} +2 -2
  117. package/dist/{chunk-F22AM3OW.js → chunk-NYWPISSO.js} +1 -1
  118. package/dist/chunk-OB42YVAE.js +16 -0
  119. package/dist/chunk-ONFOWI2D.js +955 -0
  120. package/dist/chunk-PHZHJTCK.js +1062 -0
  121. package/dist/{chunk-6UPQ5GTJ.js → chunk-QCKGI74V.js} +7 -7
  122. package/dist/{chunk-YPAE5RH3.js → chunk-RS6ANWVT.js} +1 -1
  123. package/dist/{chunk-C5NCV3OB.js → chunk-TYUXD3FN.js} +1 -1
  124. package/dist/{chunk-KBFQXJL4.js → chunk-XP7F4LYB.js} +5 -7
  125. package/dist/{chunk-VMBZFPZM.js → chunk-ZUK7BL63.js} +187 -9
  126. package/dist/cli/chat.js +55 -40
  127. package/dist/cli/check.js +6 -6
  128. package/dist/cli/init.js +30 -36
  129. package/dist/cli/plugins.js +16 -16
  130. package/dist/cli/snapshot-warmup.js +9 -9
  131. package/dist/cli/upgrade.js +21 -21
  132. package/dist/db-CXI7PR5U.js +18 -0
  133. package/dist/handlers/agent-dispatch.d.ts +3 -3
  134. package/dist/handlers/mcp-oauth-callback.d.ts +3 -3
  135. package/dist/handlers/oauth-callback.d.ts +3 -3
  136. package/dist/instrumentation.js +6 -5
  137. package/dist/nitro.js +3 -7
  138. package/dist/reporting.js +23 -25
  139. package/dist/{runner-BCRF2FCI.js → runner-FKL3RAHA.js} +89 -77
  140. package/dist/{validation-FMJO3L5P.js → validation-I7GD2YWS.js} +6 -6
  141. package/package.json +6 -6
  142. package/dist/chat/respond-helpers.d.ts +0 -82
  143. package/dist/chat/services/attachment-claims.d.ts +0 -2
  144. package/dist/chat/services/channel-intent.d.ts +0 -2
  145. package/dist/chat/tools/sandbox/attach-file.d.ts +0 -7
  146. package/dist/chat/tools/slack/canvas-tools.d.ts +0 -30
  147. package/dist/chat/tools/slack/channel-list-messages.d.ts +0 -9
  148. package/dist/chat/tools/slack/channel-post-message.d.ts +0 -5
  149. package/dist/chat/tools/slack/list-tools.d.ts +0 -21
  150. package/dist/chat/tools/slack/message-add-reaction.d.ts +0 -5
  151. package/dist/chat/tools/slack/thread-read.d.ts +0 -12
  152. package/dist/chat/tools/slack/user-lookup.d.ts +0 -8
  153. package/dist/chunk-AHLSXMOU.js +0 -506
  154. package/dist/chunk-FTMXFBDC.js +0 -49
  155. package/dist/chunk-KBSLCOGE.js +0 -2226
  156. package/dist/chunk-KQKIA4CU.js +0 -186
  157. package/dist/db-37HOGLI7.js +0 -18
  158. /package/dist/chat/{tools/slack/canvases.d.ts → slack/tools/canvas/api.d.ts} +0 -0
package/dist/app.js CHANGED
@@ -1,81 +1,23 @@
1
1
  import {
2
- AuthorizationFlowDisabledError,
3
- PluginCredentialFailureError,
4
- SANDBOX_EGRESS_PROXY_PATH,
5
- TurnInputCommitLostError,
6
- TurnInputDeferredError,
7
- addReactionToMessage,
8
- appendSlackLegacyAttachmentText,
9
- applyPendingAuthUpdate,
10
2
  buildConversationContext,
11
3
  buildDeliveredTurnStatePatch,
12
- buildDeterministicTurnId,
13
- buildSteeringPiMessage,
14
- clearPendingAuth,
15
- coerceThreadArtifactsState,
16
- completeDeliveredTurn,
17
4
  createConversationMemoryService,
18
- createUserTokenStore,
19
- deleteMcpAuthSession,
20
- deliverResourceEventSubscription,
21
5
  estimateTextTokens,
22
- executeCredentialedEgressRequest,
23
6
  finalizeFailedTurnReply,
24
- finalizeMcpAuthorization,
25
- findMatchingResourceEventSubscriptions,
26
- formatProviderLabel,
27
- generateAssistantReply,
28
7
  generateConversationId,
29
8
  getAgentContextCompactionTriggerTokens,
30
9
  getAgentTurnDiagnosticsAttributes,
31
- getChannelConfigurationService,
32
- getChannelConfigurationServiceById,
33
- getConfigDefaults,
34
10
  getConversationMessageSlackTs,
35
- getConversationPendingAuth,
36
- getMcpStoredOAuthCredentials,
37
- getPersistedSandboxState,
38
- getPersistedThreadState,
39
11
  getThreadTitleSourceMessage,
40
- isAuthResumeRetryableTurnError,
41
- isCooperativeTurnYieldError,
42
12
  isHumanConversationMessage,
43
- isPendingAuthLatestRequest,
44
- isRetryableTurnError,
45
- isTurnInputCommitLostError,
46
- isTurnInputDeferredError,
47
- listThreadReplies,
48
13
  markConversationMessage,
49
- markTurnClosed,
50
- markTurnFailed,
51
- mergeArtifactsState,
52
14
  normalizeConversationText,
53
- normalizeSandboxEgressTracePropagationDomains,
54
- parseOAuthStatePayload,
55
- parseSandboxEgressCredentialToken,
56
- persistCompletedSessionRecord,
57
- persistThreadState,
58
- persistThreadStateById,
59
- persistYieldSessionRecord,
60
- postSlackMessage,
61
15
  processPluginTask,
62
- removeReactionFromMessage,
63
- renderSlackLegacyAttachmentText,
64
16
  requireTurnFailureEventId,
65
- resolveBaseUrl,
66
- resolvePluginOAuthAccount,
67
- resolveSandboxEgressProviderForHost,
68
17
  scheduleSessionCompletedPluginTasks,
69
- setConfigDefaults,
70
- shouldEmitDevAgentTrace,
71
- shouldPropagateSandboxEgressTrace,
72
- startActiveTurn,
73
- startOAuthFlow,
74
- unlinkProvider,
75
18
  updateConversationStats,
76
- uploadFilesToThread,
77
19
  upsertConversationMessage
78
- } from "./chunk-NYJLQI42.js";
20
+ } from "./chunk-AOISHLSF.js";
79
21
  import {
80
22
  CONVERSATION_WORK_CHECK_IN_INTERVAL_MS,
81
23
  CONVERSATION_WORK_STALE_ENQUEUE_MS,
@@ -99,17 +41,12 @@ import {
99
41
  requestConversationContinuation,
100
42
  requestConversationWork,
101
43
  startConversationWork
102
- } from "./chunk-2DPZRS3B.js";
103
- import {
104
- JUNIOR_THREAD_STATE_TTL_MS,
105
- coerceThreadConversationState
106
- } from "./chunk-66NX7MNW.js";
107
- import "./chunk-V6XDCS3X.js";
44
+ } from "./chunk-IX76WFJV.js";
108
45
  import {
109
46
  getVercelConversationWorkQueue,
110
47
  resolveConversationWorkQueueTopic,
111
48
  verifyConversationQueueMessage
112
- } from "./chunk-F22AM3OW.js";
49
+ } from "./chunk-NYWPISSO.js";
113
50
  import {
114
51
  PLUGIN_TASK_QUEUE_TOPIC,
115
52
  createVercelQueueClient,
@@ -123,25 +60,11 @@ import {
123
60
  resolveSlackChannelTypeFromMessage,
124
61
  resolveSlackConversationContext,
125
62
  setConversationTitle
126
- } from "./chunk-6UPQ5GTJ.js";
127
- import {
128
- abandonAgentTurnSessionRecord,
129
- buildSlackOutputMessage,
130
- commitMessages,
131
- failAgentTurnSessionRecord,
132
- getAgentTurnSessionRecord,
133
- listAgentTurnSessionSummariesForConversation,
134
- loadProjection,
135
- normalizeSlackStatusText,
136
- recordAgentTurnSessionSummary,
137
- recordAuthorizationCompleted,
138
- splitSlackReplyText,
139
- truncateStatusText
140
- } from "./chunk-KBSLCOGE.js";
63
+ } from "./chunk-QCKGI74V.js";
141
64
  import {
142
65
  validatePluginEgressCredentialHooks,
143
66
  validatePluginRegistrations
144
- } from "./chunk-C5NCV3OB.js";
67
+ } from "./chunk-TYUXD3FN.js";
145
68
  import {
146
69
  defineJuniorPlugins,
147
70
  pluginCatalogConfigFromEnv,
@@ -149,51 +72,126 @@ import {
149
72
  pluginRuntimeRegistrationsFromPluginSet
150
73
  } from "./chunk-SG5WAA7H.js";
151
74
  import {
75
+ AuthorizationFlowDisabledError,
76
+ PluginCredentialFailureError,
77
+ SANDBOX_EGRESS_PROXY_PATH,
78
+ addReactionToMessage,
79
+ appendSlackLegacyAttachmentText,
80
+ buildSteeringPiMessage,
81
+ createAgentRunner,
82
+ createUserTokenStore,
83
+ deleteMcpAuthSession,
84
+ deliverResourceEventSubscription,
85
+ executeAgentRun,
86
+ executeCredentialedEgressRequest,
87
+ finalizeMcpAuthorization,
88
+ findMatchingResourceEventSubscriptions,
89
+ formatProviderLabel,
90
+ getConfigDefaults,
91
+ getMcpStoredOAuthCredentials,
92
+ listThreadReplies,
93
+ normalizeSandboxEgressTracePropagationDomains,
94
+ parseOAuthStatePayload,
95
+ parseSandboxEgressCredentialToken,
96
+ postSlackMessage,
97
+ removeReactionFromMessage,
98
+ renderSlackLegacyAttachmentText,
99
+ resolveBaseUrl,
100
+ resolvePluginOAuthAccount,
101
+ resolveSandboxEgressProviderForHost,
102
+ setConfigDefaults,
103
+ shouldEmitDevAgentTrace,
104
+ shouldPropagateSandboxEgressTrace,
105
+ startOAuthFlow,
106
+ unlinkProvider
107
+ } from "./chunk-BKSZL4QO.js";
108
+ import {
109
+ CooperativeTurnYieldError,
110
+ TurnInputCommitLostError,
111
+ TurnInputDeferredError,
112
+ applyPendingAuthUpdate,
113
+ buildDeterministicTurnId,
114
+ clearPendingAuth,
115
+ coerceThreadArtifactsState,
116
+ completeDeliveredTurn,
117
+ getChannelConfigurationService,
118
+ getChannelConfigurationServiceById,
119
+ getConversationPendingAuth,
120
+ getPersistedSandboxState,
121
+ getPersistedThreadState,
122
+ isCooperativeTurnYieldError,
123
+ isPendingAuthLatestRequest,
124
+ isTurnInputCommitLostError,
125
+ isTurnInputDeferredError,
126
+ markTurnClosed,
127
+ markTurnFailed,
128
+ mergeArtifactsState,
129
+ persistCompletedSessionRecord,
130
+ persistThreadState,
131
+ persistThreadStateById,
132
+ persistYieldSessionRecord,
133
+ startActiveTurn
134
+ } from "./chunk-ONFOWI2D.js";
135
+ import {
136
+ JUNIOR_THREAD_STATE_TTL_MS,
137
+ coerceThreadConversationState
138
+ } from "./chunk-KC42JAAQ.js";
139
+ import "./chunk-5GBUZI6M.js";
140
+ import {
141
+ buildSlackOutputMessage,
142
+ normalizeSlackStatusText,
143
+ splitSlackReplyText,
144
+ truncateStatusText,
145
+ unwrapCurrentInstruction
146
+ } from "./chunk-PHZHJTCK.js";
147
+ import {
148
+ abandonAgentTurnSessionRecord,
149
+ commitMessages,
150
+ escapeXml,
151
+ failAgentTurnSessionRecord,
152
+ getAgentTurnSessionRecord,
153
+ listAgentTurnSessionSummariesForConversation,
154
+ loadProjection,
155
+ recordAgentTurnSessionSummary,
156
+ recordAuthorizationCompleted
157
+ } from "./chunk-GCWD2VHP.js";
158
+ import {
159
+ SlackActionError,
152
160
  bindSlackDirectCredentialSubject,
161
+ downloadPrivateSlackFile,
162
+ getHeaderString,
153
163
  getPluginApiRoutes,
154
164
  getPluginRoutes,
155
165
  getPluginSlackConversationLink,
156
166
  getPlugins,
157
- parseSlackMessageTs,
167
+ getSlackClient,
168
+ getWorkspaceTeamId,
169
+ isDmChannel,
170
+ normalizeSlackConversationId,
171
+ runWithSlackInstallationToken,
172
+ runWithWorkspaceTeamId,
158
173
  setPlugins,
159
174
  validatePlugins,
160
175
  verifySlackDirectCredentialSubject
161
- } from "./chunk-XS6NLQPA.js";
176
+ } from "./chunk-DACFZ5CI.js";
162
177
  import {
163
178
  createPluginLogger,
164
179
  createPluginState
165
- } from "./chunk-IATAYWFU.js";
180
+ } from "./chunk-NW7AXDA5.js";
166
181
  import "./chunk-G3E7SCME.js";
167
182
  import {
168
183
  acquireActiveLock,
169
184
  getStateAdapter
170
- } from "./chunk-YPAE5RH3.js";
185
+ } from "./chunk-RS6ANWVT.js";
171
186
  import {
172
187
  getConversationStore,
173
188
  getDb
174
- } from "./chunk-4IXHIV37.js";
175
- import {
176
- SlackActionError,
177
- createSlackDestination,
178
- destinationKey,
179
- downloadPrivateSlackFile,
180
- getHeaderString,
181
- getSlackClient,
182
- getWorkspaceTeamId,
183
- isDmChannel,
184
- normalizeSlackConversationId,
185
- parseDestination,
186
- requireSlackDestination,
187
- runWithSlackInstallationToken,
188
- runWithWorkspaceTeamId,
189
- sameDestination
190
- } from "./chunk-AHLSXMOU.js";
189
+ } from "./chunk-2S7M37HY.js";
191
190
  import {
192
191
  FUNCTION_TIMEOUT_BUFFER_SECONDS,
193
192
  botConfig,
194
193
  completeObject,
195
194
  completeText,
196
- escapeXml,
197
195
  getChatConfig,
198
196
  getRuntimeMetadata,
199
197
  getSlackBotToken,
@@ -205,57 +203,66 @@ import {
205
203
  normalizeSlackEmojiName,
206
204
  setSlackReactionConfig,
207
205
  stripRuntimeTurnContext,
208
- trimTrailingAssistantMessages,
209
- unwrapCurrentInstruction
210
- } from "./chunk-S35CPNPT.js";
206
+ trimTrailingAssistantMessages
207
+ } from "./chunk-HXL2ZV74.js";
211
208
  import {
212
209
  parseSlackThreadId,
210
+ readSlackRawMessageContext,
213
211
  resolveSlackChannelIdFromMessage,
214
212
  resolveSlackChannelIdFromThreadId
215
- } from "./chunk-L7OHKDOX.js";
213
+ } from "./chunk-3MPOMK3K.js";
214
+ import {
215
+ createSlackDestination,
216
+ destinationKey,
217
+ parseDestination,
218
+ requireSlackDestination,
219
+ sameDestination
220
+ } from "./chunk-GHGPTPBL.js";
216
221
  import {
217
222
  discoverSkills
218
- } from "./chunk-7ES37H6U.js";
223
+ } from "./chunk-AN2437E3.js";
219
224
  import {
220
225
  buildOAuthTokenRequest,
221
226
  hasRequiredOAuthScope,
222
227
  parseOAuthTokenResponse,
223
228
  pluginCatalogRuntime
224
- } from "./chunk-KBFQXJL4.js";
225
- import {
226
- createRequester,
227
- createSlackRequester,
228
- createSlackResumeRequester,
229
- isActorUserId,
230
- parseActorUserId,
231
- toStoredSlackRequester
232
- } from "./chunk-KQKIA4CU.js";
233
- import {
234
- homeDir
235
- } from "./chunk-6APU57E6.js";
229
+ } from "./chunk-XP7F4LYB.js";
236
230
  import {
237
231
  buildTurnFailureResponse,
238
232
  createChatSdkLogger,
239
233
  createRequestContext,
234
+ createRequester,
235
+ createSlackRequester,
236
+ createSlackResumeRequester,
240
237
  getActiveTraceId,
238
+ isActorUserId,
241
239
  logError,
242
240
  logException,
243
241
  logInfo,
244
242
  logWarn,
243
+ parseActorUserId,
245
244
  setSentryUser,
246
245
  setSpanAttributes,
247
246
  setSpanStatus,
248
247
  setTags,
248
+ toStoredSlackRequester,
249
249
  withContext,
250
250
  withSpan
251
- } from "./chunk-VMBZFPZM.js";
251
+ } from "./chunk-ZUK7BL63.js";
252
252
  import {
253
- JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE,
254
253
  toOptionalString
255
- } from "./chunk-FTMXFBDC.js";
254
+ } from "./chunk-OB42YVAE.js";
256
255
  import {
257
256
  continueTrace
258
257
  } from "./chunk-3DA7X2U3.js";
258
+ import {
259
+ homeDir
260
+ } from "./chunk-6APU57E6.js";
261
+ import {
262
+ JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE,
263
+ parseSlackChannelId,
264
+ parseSlackMessageTs
265
+ } from "./chunk-LFLTJQVR.js";
259
266
  import "./chunk-MLKGABMK.js";
260
267
 
261
268
  // src/app.ts
@@ -313,9 +320,6 @@ function getDashboardConversationLink(conversationId) {
313
320
  return `${baseURL}${path2}`;
314
321
  }
315
322
 
316
- // src/chat/slack/reply.ts
317
- import { Buffer as Buffer2 } from "buffer";
318
-
319
323
  // src/chat/slack/footer.ts
320
324
  function escapeSlackMrkdwn(text) {
321
325
  return text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
@@ -362,17 +366,12 @@ function buildSlackReplyBlocks(text, footer) {
362
366
  }
363
367
 
364
368
  // src/chat/slack/reply.ts
365
- function resolveReplyDelivery(reply) {
366
- const replyHasFiles = Boolean(reply.files && reply.files.length > 0);
369
+ function shouldPostThreadReply(reply) {
367
370
  const deliveryPlan = reply.deliveryPlan ?? {
368
371
  mode: reply.deliveryMode ?? "thread",
369
- postThreadText: (reply.deliveryMode ?? "thread") !== "channel_only",
370
- attachFiles: replyHasFiles ? "inline" : "none"
371
- };
372
- return {
373
- shouldPostThreadReply: deliveryPlan.postThreadText,
374
- attachFiles: replyHasFiles && deliveryPlan.attachFiles !== "none" ? "inline" : "none"
372
+ postThreadText: (reply.deliveryMode ?? "thread") !== "channel_only"
375
373
  };
374
+ return deliveryPlan.postThreadText;
376
375
  }
377
376
  function buildReplyText(text) {
378
377
  const message = buildSlackOutputMessage(text);
@@ -388,28 +387,9 @@ function buildTextPosts(args) {
388
387
  const chunks = splitSlackReplyText(args.text);
389
388
  return chunks.map((chunk, index) => ({
390
389
  text: chunk,
391
- ...index === 0 && args.firstFiles ? { files: args.firstFiles } : {},
392
390
  stage: index === 0 ? args.firstStage ?? "thread_reply" : "thread_reply_continuation"
393
391
  }));
394
392
  }
395
- async function normalizeFileUploads(files) {
396
- return await Promise.all(
397
- files.map(async (file) => {
398
- let data;
399
- if (Buffer2.isBuffer(file.data)) {
400
- data = file.data;
401
- } else if (file.data instanceof ArrayBuffer) {
402
- data = Buffer2.from(file.data);
403
- } else {
404
- data = Buffer2.from(await file.data.arrayBuffer());
405
- }
406
- return {
407
- data,
408
- filename: file.filename
409
- };
410
- })
411
- );
412
- }
413
393
  function findLastTextPostIndex(posts) {
414
394
  for (let index = posts.length - 1; index >= 0; index -= 1) {
415
395
  if (posts[index]?.text.trim().length) {
@@ -418,56 +398,25 @@ function findLastTextPostIndex(posts) {
418
398
  }
419
399
  return -1;
420
400
  }
421
- async function uploadReplyFiles(args) {
422
- try {
423
- await uploadFilesToThread({
424
- channelId: args.channelId,
425
- threadTs: args.threadTs,
426
- files: await normalizeFileUploads(args.files)
427
- });
428
- } catch (error) {
429
- if (args.failureMode === "strict") {
430
- throw error;
431
- }
432
- }
433
- }
434
401
  function planSlackReplyPosts(args) {
435
- const replyFiles = args.reply.files && args.reply.files.length > 0 ? args.reply.files : void 0;
436
- const { shouldPostThreadReply, attachFiles } = resolveReplyDelivery(
437
- args.reply
438
- );
439
402
  const posts = [];
440
- const textPosts = shouldPostThreadReply ? buildTextPosts({
441
- text: args.reply.text,
442
- firstFiles: attachFiles === "inline" ? replyFiles : void 0
403
+ const textPosts = shouldPostThreadReply(args.reply) ? buildTextPosts({
404
+ text: args.reply.text
443
405
  }) : [];
444
406
  posts.push(...textPosts);
445
- if (attachFiles === "inline" && replyFiles && textPosts.length === 0) {
446
- posts.push({
447
- files: replyFiles,
448
- stage: "thread_reply",
449
- text: ""
450
- });
451
- } else if (shouldPostThreadReply && textPosts.length === 0) {
407
+ if (shouldPostThreadReply(args.reply) && textPosts.length === 0) {
452
408
  posts.push({
453
409
  text: buildReplyText(args.reply.text),
454
410
  stage: "thread_reply"
455
411
  });
456
412
  }
457
- if (attachFiles === "followup" && replyFiles) {
458
- posts.push({
459
- files: replyFiles,
460
- stage: "thread_reply_files_followup",
461
- text: ""
462
- });
463
- }
464
413
  return posts;
465
414
  }
466
415
  async function postSlackApiReplyPosts(args) {
467
416
  const lastTextPostIndex = findLastTextPostIndex(args.posts);
468
417
  let lastPostedMessageTs;
469
418
  for (const [index, post] of args.posts.entries()) {
470
- const hasVisibleDelivery = post.text.trim().length > 0 || post.files?.length;
419
+ const hasVisibleDelivery = post.text.trim().length > 0;
471
420
  if (hasVisibleDelivery) {
472
421
  await args.beforePost?.();
473
422
  }
@@ -485,18 +434,7 @@ async function postSlackApiReplyPosts(args) {
485
434
  messageTs = response.ts;
486
435
  lastPostedMessageTs = response.ts;
487
436
  }
488
- if (!post.files?.length) {
489
- continue;
490
- }
491
- if (!args.threadTs && !lastPostedMessageTs) {
492
- throw new Error("Slack file delivery requires a posted message thread");
493
- }
494
- await uploadReplyFiles({
495
- channelId: args.channelId,
496
- failureMode: args.fileUploadFailureMode ?? "best_effort",
497
- threadTs: args.threadTs ?? lastPostedMessageTs,
498
- files: post.files
499
- });
437
+ continue;
500
438
  } catch (error) {
501
439
  await args.onPostError?.({
502
440
  error,
@@ -892,13 +830,19 @@ function getAssistantMessageId(dispatch) {
892
830
  function buildDispatchConversationText(dispatch) {
893
831
  return `[dispatched task] ${dispatch.input}`;
894
832
  }
833
+ function shouldPostDispatchReplyText(reply) {
834
+ return reply.deliveryPlan?.postThreadText ?? (reply.deliveryMode ?? "thread") !== "channel_only";
835
+ }
895
836
  function ensureVisibleDeliveryText(reply) {
896
- if (reply.text.trim().length > 0 || !reply.files?.length) {
837
+ if (!shouldPostDispatchReplyText(reply)) {
838
+ return reply;
839
+ }
840
+ if (reply.text.trim().length > 0) {
897
841
  return reply;
898
842
  }
899
843
  return {
900
844
  ...reply,
901
- text: "Generated files are attached."
845
+ text: "The task completed without a visible response."
902
846
  };
903
847
  }
904
848
  function upsertDispatchUserMessage(args) {
@@ -954,8 +898,7 @@ function canClaimDispatch(record, nowMs) {
954
898
  }
955
899
  return true;
956
900
  }
957
- async function runAgentDispatchSlice(callback, deps = {}) {
958
- const generateAssistantReply2 = deps.generateAssistantReply ?? generateAssistantReply;
901
+ async function runAgentDispatchSlice(callback, deps) {
959
902
  const scheduleCallback = deps.scheduleCallback ?? scheduleDispatchCallback;
960
903
  const scheduleCompletedTasks = deps.scheduleSessionCompletedPluginTasks ?? scheduleSessionCompletedPluginTasks;
961
904
  const nowMs = Date.now();
@@ -1051,61 +994,91 @@ async function runAgentDispatchSlice(callback, deps = {}) {
1051
994
  const conversationContext = buildConversationContext(conversation, {
1052
995
  excludeMessageId: userMessageId
1053
996
  });
1054
- let reply = await generateAssistantReply2(dispatch.input, {
1055
- authorizationFlowMode: "disabled",
1056
- credentialContext: {
1057
- actor: dispatch.actor,
1058
- ...dispatch.credentialSubject ? { subject: dispatch.credentialSubject } : {}
1059
- },
1060
- configuration,
1061
- channelConfiguration,
1062
- conversationContext,
1063
- artifactState: artifacts,
1064
- piMessages: conversation.piMessages,
1065
- destination: dispatch.destination,
1066
- source: dispatch.source,
1067
- dispatch: {
1068
- actor: dispatch.actor,
1069
- metadata: dispatch.metadata,
1070
- plugin: dispatch.plugin
997
+ const outcome = await deps.agentRunner.run({
998
+ input: {
999
+ messageText: dispatch.input,
1000
+ conversationContext,
1001
+ piMessages: conversation.piMessages
1071
1002
  },
1072
- correlation: {
1073
- conversationId,
1074
- threadId: conversationId,
1075
- turnId,
1076
- runId: dispatch.id,
1077
- channelId: dispatch.destination.channelId,
1078
- teamId: dispatch.destination.teamId
1003
+ routing: {
1004
+ credentialContext: {
1005
+ actor: dispatch.actor,
1006
+ ...dispatch.credentialSubject ? { subject: dispatch.credentialSubject } : {}
1007
+ },
1008
+ destination: dispatch.destination,
1009
+ source: dispatch.source,
1010
+ dispatch: {
1011
+ actor: dispatch.actor,
1012
+ metadata: dispatch.metadata,
1013
+ plugin: dispatch.plugin
1014
+ },
1015
+ correlation: {
1016
+ conversationId,
1017
+ threadId: conversationId,
1018
+ turnId,
1019
+ runId: dispatch.id,
1020
+ channelId: dispatch.destination.channelId,
1021
+ teamId: dispatch.destination.teamId
1022
+ },
1023
+ surface: "api",
1024
+ toolChannelId: dispatch.destination.channelId
1079
1025
  },
1080
- surface: "api",
1081
- toolChannelId: dispatch.destination.channelId,
1082
- sandbox: {
1083
- sandboxId,
1084
- sandboxDependencyProfileHash,
1085
- tracePropagation: deps.tracePropagation
1026
+ policy: {
1027
+ authorizationFlowMode: "disabled",
1028
+ configuration,
1029
+ channelConfiguration
1086
1030
  },
1087
- onSandboxAcquired: async (sandbox) => {
1088
- sandboxId = sandbox.sandboxId;
1089
- sandboxDependencyProfileHash = sandbox.sandboxDependencyProfileHash;
1090
- await persistRuntimePatch({
1091
- threadId: conversationId,
1092
- conversation,
1093
- artifacts,
1031
+ state: {
1032
+ artifactState: artifacts,
1033
+ sandbox: {
1094
1034
  sandboxId,
1095
1035
  sandboxDependencyProfileHash
1096
- });
1036
+ }
1097
1037
  },
1098
- onArtifactStateUpdated: async (nextArtifacts2) => {
1099
- artifacts = nextArtifacts2;
1100
- await persistRuntimePatch({
1101
- threadId: conversationId,
1102
- conversation,
1103
- artifacts,
1104
- sandboxId,
1105
- sandboxDependencyProfileHash
1106
- });
1038
+ durability: {
1039
+ onSandboxAcquired: async (sandbox) => {
1040
+ sandboxId = sandbox.sandboxId;
1041
+ sandboxDependencyProfileHash = sandbox.sandboxDependencyProfileHash;
1042
+ await persistRuntimePatch({
1043
+ threadId: conversationId,
1044
+ conversation,
1045
+ artifacts,
1046
+ sandboxId,
1047
+ sandboxDependencyProfileHash
1048
+ });
1049
+ },
1050
+ onArtifactStateUpdated: async (nextArtifacts2) => {
1051
+ artifacts = nextArtifacts2;
1052
+ await persistRuntimePatch({
1053
+ threadId: conversationId,
1054
+ conversation,
1055
+ artifacts,
1056
+ sandboxId,
1057
+ sandboxDependencyProfileHash
1058
+ });
1059
+ }
1107
1060
  }
1108
1061
  });
1062
+ if (outcome.status === "awaiting_auth") {
1063
+ await markDispatch({
1064
+ dispatch,
1065
+ status: "blocked",
1066
+ errorMessage: "Dispatch requires authorization from an interactive user turn."
1067
+ });
1068
+ return;
1069
+ }
1070
+ if (outcome.status === "suspended") {
1071
+ const awaiting = await markDispatch({
1072
+ dispatch,
1073
+ status: "awaiting_resume"
1074
+ });
1075
+ await scheduleCallback({
1076
+ id: awaiting.id,
1077
+ expectedVersion: awaiting.version
1078
+ });
1079
+ return;
1080
+ }
1081
+ let reply = outcome.result;
1109
1082
  const failure = reply.diagnostics.outcome === "success" ? void 0 : reply.diagnostics.errorMessage ?? `Agent turn ended with ${reply.diagnostics.outcome}.`;
1110
1083
  if (failure) {
1111
1084
  reply = finalizeFailedTurnReply({
@@ -1123,8 +1096,7 @@ async function runAgentDispatchSlice(callback, deps = {}) {
1123
1096
  posts: planSlackReplyPosts({ reply: deliveryReply }),
1124
1097
  footer: buildSlackReplyFooter({
1125
1098
  conversationId
1126
- }),
1127
- fileUploadFailureMode: "strict"
1099
+ })
1128
1100
  });
1129
1101
  markConversationMessage(conversation, userMessageId, {
1130
1102
  replied: true,
@@ -1224,28 +1196,6 @@ async function runAgentDispatchSlice(callback, deps = {}) {
1224
1196
  });
1225
1197
  return;
1226
1198
  }
1227
- if (isRetryableTurnError(error, "mcp_auth_resume") || isRetryableTurnError(error, "plugin_auth_resume")) {
1228
- await markDispatch({
1229
- dispatch,
1230
- status: "blocked",
1231
- errorMessage: "Dispatch requires authorization from an interactive user turn."
1232
- });
1233
- return;
1234
- }
1235
- if (isRetryableTurnError(error, "agent_continue")) {
1236
- const version = error.metadata?.version;
1237
- if (typeof version === "number") {
1238
- const awaiting = await markDispatch({
1239
- dispatch,
1240
- status: "awaiting_resume"
1241
- });
1242
- await scheduleCallback({
1243
- id: awaiting.id,
1244
- expectedVersion: awaiting.version
1245
- });
1246
- return;
1247
- }
1248
- }
1249
1199
  logException(
1250
1200
  error,
1251
1201
  "agent_dispatch_run_failed",
@@ -1267,14 +1217,14 @@ async function runAgentDispatchSlice(callback, deps = {}) {
1267
1217
  }
1268
1218
 
1269
1219
  // src/handlers/agent-dispatch.ts
1270
- async function POST(request, waitUntil, options = {}) {
1220
+ async function POST(request, waitUntil, options) {
1271
1221
  const payload = await verifyDispatchCallbackRequest(request);
1272
1222
  if (!payload) {
1273
1223
  return new Response("Unauthorized", { status: 401 });
1274
1224
  }
1275
1225
  waitUntil(
1276
1226
  () => runAgentDispatchSlice(payload, {
1277
- tracePropagation: options.tracePropagation
1227
+ agentRunner: options.agentRunner
1278
1228
  }).catch((error) => {
1279
1229
  logException(
1280
1230
  error,
@@ -3529,6 +3479,12 @@ function isSlackTitlePermissionError(error) {
3529
3479
  function escapeRegExp(value) {
3530
3480
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3531
3481
  }
3482
+ function readObjectField(value, key) {
3483
+ return value[key];
3484
+ }
3485
+ function readOptionalStringField(value, key) {
3486
+ return toOptionalString(readObjectField(value, key));
3487
+ }
3532
3488
  function stripLeadingBotMention(text, options = {}) {
3533
3489
  if (!text.trim()) return text;
3534
3490
  let next = text;
@@ -3560,7 +3516,7 @@ function getThreadId(thread, _message) {
3560
3516
  return toOptionalString(thread.id);
3561
3517
  }
3562
3518
  function getRunId(thread, message) {
3563
- return toOptionalString(thread.runId) ?? toOptionalString(message.runId);
3519
+ return readOptionalStringField(thread, "runId") ?? readOptionalStringField(message, "runId");
3564
3520
  }
3565
3521
  function getChannelId(thread, message) {
3566
3522
  return resolveSlackChannelIdFromThreadId(toOptionalString(thread.id)) ?? normalizeSlackConversationId(toOptionalString(thread.channelId)) ?? resolveSlackChannelIdFromMessage(message);
@@ -3569,18 +3525,16 @@ function getThreadTs(threadId) {
3569
3525
  return parseSlackThreadId(threadId)?.threadTs;
3570
3526
  }
3571
3527
  function getAssistantThreadContext(message) {
3572
- const raw = message.raw;
3573
- const rawRecord = raw && typeof raw === "object" ? raw : void 0;
3574
- const channelId = toOptionalString(rawRecord?.channel);
3528
+ const rawContext = readSlackRawMessageContext(message);
3529
+ const channelId = rawContext?.channelId;
3575
3530
  if (channelId) {
3576
- const rawThreadTs = toOptionalString(rawRecord?.thread_ts);
3577
- const threadTs = isDmChannel(channelId) ? rawThreadTs : rawThreadTs ?? toOptionalString(rawRecord?.ts);
3531
+ const threadTs = isDmChannel(channelId) ? rawContext.threadTs : rawContext.threadTs ?? rawContext.messageTs;
3578
3532
  if (threadTs) {
3579
3533
  return { channelId, threadTs };
3580
3534
  }
3581
3535
  }
3582
3536
  const parsedThreadId = parseSlackThreadId(
3583
- toOptionalString(message.threadId)
3537
+ readOptionalStringField(message, "threadId")
3584
3538
  );
3585
3539
  if (!parsedThreadId || isDmChannel(parsedThreadId.channelId)) {
3586
3540
  return void 0;
@@ -3588,22 +3542,16 @@ function getAssistantThreadContext(message) {
3588
3542
  return parsedThreadId;
3589
3543
  }
3590
3544
  function getMessageTs(message) {
3591
- const directTs = toOptionalString(
3592
- message.ts
3593
- );
3545
+ const directTs = readOptionalStringField(message, "ts");
3594
3546
  const parsedDirectTs = parseSlackMessageTs(directTs);
3595
3547
  if (parsedDirectTs) {
3596
3548
  return parsedDirectTs;
3597
3549
  }
3598
- const raw = message.raw;
3599
- if (!raw || typeof raw !== "object") {
3550
+ const rawContext = readSlackRawMessageContext(message);
3551
+ if (!rawContext) {
3600
3552
  return void 0;
3601
3553
  }
3602
- const rawRecord = raw;
3603
- const candidates = [
3604
- rawRecord.ts,
3605
- rawRecord.message?.ts
3606
- ];
3554
+ const candidates = [rawContext.messageTs, rawContext.nestedMessageTs];
3607
3555
  for (const candidate of candidates) {
3608
3556
  const ts = parseSlackMessageTs(candidate);
3609
3557
  if (ts) {
@@ -3623,7 +3571,7 @@ function isProcessingReactionEmoji(value) {
3623
3571
  return typeof value === "string" && normalizeSlackEmojiName(value) === getChatConfig().slack.processingReactionEmoji;
3624
3572
  }
3625
3573
  function shouldKeepProcessingReactionForToolInvocation(input) {
3626
- return input.toolName === "slackMessageAddReaction" && isProcessingReactionEmoji(input.params.emoji);
3574
+ return input.toolName === "addReaction" && isProcessingReactionEmoji(input.params.emoji);
3627
3575
  }
3628
3576
  async function startSlackProcessingReaction(args) {
3629
3577
  if (args.message.author.isMe) {
@@ -3824,19 +3772,20 @@ function getDefaultLockKey(channelId, threadTs) {
3824
3772
  return `slack:${channelId}:${threadTs}`;
3825
3773
  }
3826
3774
  function getResumeLogContext(args, lockKey) {
3775
+ const routing = args.replyContext?.routing;
3827
3776
  return {
3828
- conversationId: args.replyContext?.correlation?.conversationId ?? lockKey,
3829
- slackThreadId: args.replyContext?.correlation?.threadId ?? lockKey,
3830
- slackUserId: args.replyContext?.requester?.userId ?? args.replyContext?.correlation?.requesterId,
3831
- slackUserName: args.replyContext?.requester?.userName,
3777
+ conversationId: routing?.correlation?.conversationId ?? lockKey,
3778
+ slackThreadId: routing?.correlation?.threadId ?? lockKey,
3779
+ slackUserId: routing?.requester?.userId ?? routing?.correlation?.requesterId,
3780
+ slackUserName: routing?.requester?.userName,
3832
3781
  slackChannelId: args.channelId,
3833
- runId: args.replyContext?.correlation?.runId,
3782
+ runId: routing?.correlation?.runId,
3834
3783
  assistantUserName: botConfig.userName,
3835
3784
  modelId: botConfig.modelId
3836
3785
  };
3837
3786
  }
3838
3787
  function getResumeConversationId(args, lockKey) {
3839
- return args.replyContext?.correlation?.conversationId ?? lockKey;
3788
+ return args.replyContext?.routing.correlation?.conversationId ?? lockKey;
3840
3789
  }
3841
3790
  async function postResumeFailureReply(args) {
3842
3791
  try {
@@ -3881,42 +3830,58 @@ function createResumeReplyContext(args, statusSession) {
3881
3830
  if (!replyContext) {
3882
3831
  throw new TypeError("Slack resume requires a reply context");
3883
3832
  }
3884
- if (!replyContext.source) {
3833
+ if (!replyContext.routing.source) {
3885
3834
  throw new TypeError("Slack resume requires a reply context source");
3886
3835
  }
3887
- const source = replyContext.source;
3888
- if (replyContext.destination.platform !== "slack") {
3836
+ const source = replyContext.routing.source;
3837
+ if (replyContext.routing.destination.platform !== "slack") {
3889
3838
  throw new TypeError("Slack resume requires a Slack destination");
3890
3839
  }
3891
3840
  const requestDeadline = getTurnRequestDeadline();
3892
3841
  const threadId = args.lockKey ?? getDefaultLockKey(args.channelId, args.threadTs);
3893
- const persistedChannelConfiguration = replyContext.channelConfiguration ?? (replyContext.configuration ? createReadOnlyConfigService(replyContext.configuration) : void 0);
3842
+ const persistedChannelConfiguration = replyContext.policy?.channelConfiguration ?? (replyContext.policy?.configuration ? createReadOnlyConfigService(replyContext.policy.configuration) : void 0);
3894
3843
  return {
3895
- ...replyContext,
3896
- source,
3897
- turnDeadlineAtMs: replyContext.turnDeadlineAtMs ?? requestDeadline?.deadlineAtMs,
3898
- correlation: {
3899
- ...replyContext.correlation,
3900
- threadId: replyContext.correlation?.threadId ?? threadId,
3901
- channelId: replyContext.correlation?.channelId ?? args.channelId,
3902
- threadTs: replyContext.correlation?.threadTs ?? args.threadTs,
3903
- requesterId: replyContext.correlation?.requesterId ?? replyContext.requester?.userId
3844
+ input: {
3845
+ ...replyContext.input ?? {},
3846
+ messageText: args.messageText
3904
3847
  },
3905
- channelConfiguration: persistedChannelConfiguration,
3906
- onSandboxAcquired: async (sandbox) => {
3907
- await persistThreadStateById(threadId, {
3908
- sandboxId: sandbox.sandboxId,
3909
- sandboxDependencyProfileHash: sandbox.sandboxDependencyProfileHash
3910
- });
3911
- await replyContext.onSandboxAcquired?.(sandbox);
3848
+ routing: {
3849
+ ...replyContext.routing,
3850
+ source,
3851
+ correlation: {
3852
+ ...replyContext.routing.correlation,
3853
+ threadId: replyContext.routing.correlation?.threadId ?? threadId,
3854
+ channelId: replyContext.routing.correlation?.channelId ?? args.channelId,
3855
+ threadTs: replyContext.routing.correlation?.threadTs ?? args.threadTs,
3856
+ requesterId: replyContext.routing.correlation?.requesterId ?? replyContext.routing.requester?.userId
3857
+ }
3858
+ },
3859
+ policy: {
3860
+ ...replyContext.policy,
3861
+ turnDeadlineAtMs: replyContext.policy?.turnDeadlineAtMs ?? requestDeadline?.deadlineAtMs,
3862
+ channelConfiguration: persistedChannelConfiguration
3912
3863
  },
3913
- onArtifactStateUpdated: async (artifacts) => {
3914
- await persistThreadStateById(threadId, { artifacts });
3915
- await replyContext.onArtifactStateUpdated?.(artifacts);
3864
+ state: replyContext.state,
3865
+ observers: {
3866
+ ...replyContext.observers,
3867
+ onStatus: async (nextStatus) => {
3868
+ statusSession.update(nextStatus);
3869
+ await replyContext.observers?.onStatus?.(nextStatus);
3870
+ }
3916
3871
  },
3917
- onStatus: async (nextStatus) => {
3918
- statusSession.update(nextStatus);
3919
- await replyContext.onStatus?.(nextStatus);
3872
+ durability: {
3873
+ ...replyContext.durability,
3874
+ onSandboxAcquired: async (sandbox) => {
3875
+ await persistThreadStateById(threadId, {
3876
+ sandboxId: sandbox.sandboxId,
3877
+ sandboxDependencyProfileHash: sandbox.sandboxDependencyProfileHash
3878
+ });
3879
+ await replyContext.durability?.onSandboxAcquired?.(sandbox);
3880
+ },
3881
+ onArtifactStateUpdated: async (artifacts) => {
3882
+ await persistThreadStateById(threadId, { artifacts });
3883
+ await replyContext.durability?.onArtifactStateUpdated?.(artifacts);
3884
+ }
3920
3885
  }
3921
3886
  };
3922
3887
  }
@@ -3948,16 +3913,18 @@ async function resumeSlackTurn(args) {
3948
3913
  if (preparedArgs) {
3949
3914
  runArgs = { ...args, ...preparedArgs };
3950
3915
  }
3951
- if (!runArgs.replyContext?.requester?.userId) {
3952
- throw new Error("Resumed turn requires replyContext.requester.userId");
3916
+ if (!runArgs.replyContext?.routing.requester?.userId) {
3917
+ throw new Error(
3918
+ "Resumed turn requires replyContext.routing.requester.userId"
3919
+ );
3953
3920
  }
3954
- const credentialContext = runArgs.replyContext.credentialContext;
3921
+ const credentialContext = runArgs.replyContext.routing.credentialContext;
3955
3922
  if (!credentialContext) {
3956
3923
  throw new Error("Resumed turn requires replyContext.credentialContext");
3957
3924
  }
3958
- if (credentialContext.actor.type !== "user" || credentialContext.actor.userId !== runArgs.replyContext.requester.userId) {
3925
+ if (credentialContext.actor.type !== "user" || credentialContext.actor.userId !== runArgs.replyContext.routing.requester.userId) {
3959
3926
  throw new Error(
3960
- "Resumed turn credential actor must match replyContext.requester.userId"
3927
+ "Resumed turn credential actor must match replyContext.routing.requester.userId"
3961
3928
  );
3962
3929
  }
3963
3930
  if (runArgs.messageTs) {
@@ -3976,87 +3943,119 @@ async function resumeSlackTurn(args) {
3976
3943
  );
3977
3944
  }
3978
3945
  status.start();
3979
- const generateReply = runArgs.generateReply ?? generateAssistantReply;
3980
3946
  const replyContext = createResumeReplyContext(runArgs, status);
3981
- const replyPromise = generateReply(runArgs.messageText, replyContext);
3947
+ const replyPromise = runArgs.agentRunner.run(replyContext);
3982
3948
  const replyTimeoutMs = resolveReplyTimeoutMs(runArgs.replyTimeoutMs);
3983
- let reply = typeof replyTimeoutMs === "number" ? await Promise.race([
3949
+ const outcome = typeof replyTimeoutMs === "number" ? await Promise.race([
3984
3950
  replyPromise,
3985
3951
  new Promise(
3986
3952
  (_, reject) => setTimeout(
3987
3953
  () => reject(
3988
3954
  new Error(
3989
- `generateAssistantReply timed out after ${replyTimeoutMs}ms`
3955
+ `executeAgentRun timed out after ${replyTimeoutMs}ms`
3990
3956
  )
3991
3957
  ),
3992
3958
  replyTimeoutMs
3993
3959
  )
3994
3960
  )
3995
3961
  ]) : await replyPromise;
3996
- reply = finalizeFailedTurnReply({
3997
- reply,
3998
- logException,
3999
- context: getResumeLogContext(runArgs, lockKey)
4000
- });
4001
- await status.stop();
4002
- const footer = buildSlackReplyFooter({
4003
- conversationId: getResumeConversationId(runArgs, lockKey)
4004
- });
4005
- await postSlackApiReplyPosts({
4006
- channelId: runArgs.channelId,
4007
- threadTs: runArgs.threadTs,
4008
- posts: planSlackReplyPosts({ reply }),
4009
- fileUploadFailureMode: "best_effort",
4010
- footer
4011
- });
4012
- finalReplyDelivered = true;
4013
- if (replyContext.correlation?.conversationId && replyContext.correlation.turnId && reply.piMessages?.length) {
4014
- await persistCompletedSessionRecord({
4015
- conversationId: replyContext.correlation.conversationId,
4016
- sessionId: replyContext.correlation.turnId,
4017
- allMessages: reply.piMessages,
4018
- currentDurationMs: reply.diagnostics.durationMs,
4019
- currentUsage: reply.diagnostics.usage,
4020
- destination: replyContext.destination,
4021
- source: replyContext.source,
4022
- requester: replyContext.requester,
4023
- surface: "slack",
4024
- logContext: {
4025
- threadId: replyContext.correlation.threadId,
4026
- requesterId: replyContext.requester?.userId,
4027
- channelId: runArgs.channelId,
4028
- runId: replyContext.correlation.runId,
4029
- assistantUserName: botConfig.userName,
4030
- modelId: reply.diagnostics.modelId
4031
- }
4032
- });
4033
- }
4034
- await runArgs.onSuccess?.(reply);
4035
- if (reply.diagnostics.outcome === "success" && replyContext.correlation?.conversationId && replyContext.correlation.turnId) {
4036
- try {
4037
- const params = {
4038
- conversationId: replyContext.correlation.conversationId,
4039
- sessionId: replyContext.correlation.turnId
3962
+ if (outcome.status !== "completed") {
3963
+ await status.stop();
3964
+ const onAuthPause = runArgs.onAuthPause;
3965
+ const onTimeoutPause = runArgs.onTimeoutPause;
3966
+ if (outcome.status === "awaiting_auth" && onAuthPause) {
3967
+ deferredPauseKind = "auth";
3968
+ deferredAuthInfo = {
3969
+ providerDisplayName: outcome.providerDisplayName,
3970
+ requesterId: runArgs.replyContext?.routing.requester?.userId
4040
3971
  };
4041
- if (runArgs.scheduleSessionCompletedPluginTasks) {
4042
- await runArgs.scheduleSessionCompletedPluginTasks(params);
4043
- } else {
4044
- await scheduleSessionCompletedPluginTasks(params);
3972
+ deferredPauseHandler = async () => {
3973
+ await onAuthPause({
3974
+ providerDisplayName: outcome.providerDisplayName
3975
+ });
3976
+ };
3977
+ } else if (outcome.status === "suspended" && onTimeoutPause) {
3978
+ deferredPauseKind = "timeout";
3979
+ deferredPauseHandler = async () => {
3980
+ await onTimeoutPause({ resumeVersion: outcome.resumeVersion });
3981
+ };
3982
+ } else {
3983
+ deferredFailureHandler = async () => {
3984
+ await handleResumeFailure({
3985
+ body: "Failed to resume Slack turn",
3986
+ error: new Error(
3987
+ `Resumed run ended ${outcome.status} without a pause handler`
3988
+ ),
3989
+ eventName: "slack_resume_turn_failed",
3990
+ lockKey,
3991
+ resumeArgs: runArgs
3992
+ });
3993
+ };
3994
+ }
3995
+ } else {
3996
+ let reply = outcome.result;
3997
+ reply = finalizeFailedTurnReply({
3998
+ reply,
3999
+ logException,
4000
+ context: getResumeLogContext(runArgs, lockKey)
4001
+ });
4002
+ await status.stop();
4003
+ const footer = buildSlackReplyFooter({
4004
+ conversationId: getResumeConversationId(runArgs, lockKey)
4005
+ });
4006
+ await postSlackApiReplyPosts({
4007
+ channelId: runArgs.channelId,
4008
+ threadTs: runArgs.threadTs,
4009
+ posts: planSlackReplyPosts({ reply }),
4010
+ footer
4011
+ });
4012
+ finalReplyDelivered = true;
4013
+ if (replyContext.routing.correlation?.conversationId && replyContext.routing.correlation.turnId && reply.piMessages?.length) {
4014
+ await persistCompletedSessionRecord({
4015
+ conversationId: replyContext.routing.correlation.conversationId,
4016
+ sessionId: replyContext.routing.correlation.turnId,
4017
+ allMessages: reply.piMessages,
4018
+ currentDurationMs: reply.diagnostics.durationMs,
4019
+ currentUsage: reply.diagnostics.usage,
4020
+ destination: replyContext.routing.destination,
4021
+ source: replyContext.routing.source,
4022
+ requester: replyContext.routing.requester,
4023
+ surface: "slack",
4024
+ logContext: {
4025
+ threadId: replyContext.routing.correlation.threadId,
4026
+ requesterId: replyContext.routing.requester?.userId,
4027
+ channelId: runArgs.channelId,
4028
+ runId: replyContext.routing.correlation.runId,
4029
+ assistantUserName: botConfig.userName,
4030
+ modelId: reply.diagnostics.modelId
4031
+ }
4032
+ });
4033
+ }
4034
+ await runArgs.onSuccess?.(reply);
4035
+ if (reply.diagnostics.outcome === "success" && replyContext.routing.correlation?.conversationId && replyContext.routing.correlation.turnId) {
4036
+ try {
4037
+ const params = {
4038
+ conversationId: replyContext.routing.correlation.conversationId,
4039
+ sessionId: replyContext.routing.correlation.turnId
4040
+ };
4041
+ if (runArgs.scheduleSessionCompletedPluginTasks) {
4042
+ await runArgs.scheduleSessionCompletedPluginTasks(params);
4043
+ } else {
4044
+ await scheduleSessionCompletedPluginTasks(params);
4045
+ }
4046
+ } catch (scheduleError) {
4047
+ logException(
4048
+ scheduleError,
4049
+ "plugin_session_completed_task_schedule_failed",
4050
+ getResumeLogContext(runArgs, lockKey),
4051
+ {},
4052
+ "Plugin session.completed task scheduling failed"
4053
+ );
4045
4054
  }
4046
- } catch (scheduleError) {
4047
- logException(
4048
- scheduleError,
4049
- "plugin_session_completed_task_schedule_failed",
4050
- getResumeLogContext(runArgs, lockKey),
4051
- {},
4052
- "Plugin session.completed task scheduling failed"
4053
- );
4054
4055
  }
4055
4056
  }
4056
4057
  } catch (error) {
4057
4058
  await status.stop();
4058
- const onAuthPause = runArgs.onAuthPause;
4059
- const onTimeoutPause = runArgs.onTimeoutPause;
4060
4059
  if (finalReplyDelivered) {
4061
4060
  postDeliveryCommitError = error;
4062
4061
  try {
@@ -4070,21 +4069,6 @@ async function resumeSlackTurn(args) {
4070
4069
  "Failed to terminalize resumed turn after post-delivery commit failure"
4071
4070
  );
4072
4071
  }
4073
- } else if (isAuthResumeRetryableTurnError(error) && onAuthPause) {
4074
- deferredPauseKind = "auth";
4075
- deferredAuthInfo = {
4076
- providerDisplayName: error.metadata.authProviderDisplayName,
4077
- // The try body validates requester.userId; catch scope does not retain that narrowing.
4078
- requesterId: runArgs.replyContext?.requester?.userId
4079
- };
4080
- deferredPauseHandler = async () => {
4081
- await onAuthPause(error);
4082
- };
4083
- } else if (isRetryableTurnError(error, "agent_continue") && onTimeoutPause) {
4084
- deferredPauseKind = "timeout";
4085
- deferredPauseHandler = async () => {
4086
- await onTimeoutPause(error);
4087
- };
4088
4072
  } else {
4089
4073
  deferredFailureHandler = async () => {
4090
4074
  await handleResumeFailure({
@@ -4157,7 +4141,7 @@ async function resumeAuthorizedRequest(args) {
4157
4141
  replyContext: args.replyContext,
4158
4142
  lockKey: args.lockKey,
4159
4143
  initialText: args.connectedText,
4160
- generateReply: args.generateReply,
4144
+ agentRunner: args.agentRunner,
4161
4145
  onSuccess: args.onSuccess,
4162
4146
  onFailure: args.onFailure,
4163
4147
  onAuthPause: args.onAuthPause,
@@ -4354,7 +4338,7 @@ async function persistFailedReplyState(channelId, threadTs, sessionId, expectedV
4354
4338
  });
4355
4339
  }
4356
4340
  async function resumeAuthorizedMcpTurn(args) {
4357
- const { authSession, generateReply, provider } = args;
4341
+ const { authSession, agentRunner, provider } = args;
4358
4342
  if (!authSession.channelId || !authSession.destination || !authSession.threadTs) {
4359
4343
  return;
4360
4344
  }
@@ -4397,7 +4381,7 @@ async function resumeAuthorizedMcpTurn(args) {
4397
4381
  messageTs: getTurnUserSlackMessageTs(userMessage2),
4398
4382
  lockKey: threadId,
4399
4383
  connectedText: "",
4400
- generateReply,
4384
+ agentRunner,
4401
4385
  beforeStart: async () => {
4402
4386
  const lockedState = await getPersistedThreadState(threadId);
4403
4387
  const lockedConversation = coerceThreadConversationState(lockedState);
@@ -4492,38 +4476,48 @@ async function resumeAuthorizedMcpTurn(args) {
4492
4476
  messageText: lockedUserMessage.text,
4493
4477
  messageTs: lockedMessageTs,
4494
4478
  replyContext: {
4495
- credentialContext: {
4496
- actor: { type: "user", userId: requester.userId }
4497
- },
4498
- requester,
4499
- destination,
4500
- source: lockedSessionRecord.source,
4501
- correlation: {
4502
- conversationId: authSession.conversationId,
4503
- turnId: lockedSessionId,
4504
- channelId: authSession.channelId,
4505
- threadTs: authSession.threadTs,
4506
- requesterId: requester.userId
4479
+ input: {
4480
+ conversationContext: lockedConversationContext,
4481
+ piMessages: lockedConversation.piMessages,
4482
+ ...getTurnUserReplyAttachmentContext(lockedUserMessage)
4507
4483
  },
4508
- toolChannelId: authSession.toolChannelId ?? lockedArtifacts.assistantContextChannelId ?? authSession.channelId,
4509
- conversationContext: lockedConversationContext,
4510
- artifactState: lockedArtifacts,
4511
- piMessages: lockedConversation.piMessages,
4512
- configuration: authSession.configuration,
4513
- pendingAuth: lockedPendingAuth,
4514
- channelConfiguration: lockedChannelConfiguration,
4515
- sandbox: getPersistedSandboxState(lockedState),
4516
- recordPendingAuth: async (nextPendingAuth) => {
4517
- await applyPendingAuthUpdate({
4518
- conversation: lockedConversation,
4484
+ routing: {
4485
+ credentialContext: {
4486
+ actor: { type: "user", userId: requester.userId }
4487
+ },
4488
+ requester,
4489
+ destination,
4490
+ source: lockedSessionRecord.source,
4491
+ correlation: {
4519
4492
  conversationId: authSession.conversationId,
4520
- nextPendingAuth
4521
- });
4522
- await persistThreadStateById(threadId, {
4523
- conversation: lockedConversation
4524
- });
4493
+ turnId: lockedSessionId,
4494
+ channelId: authSession.channelId,
4495
+ threadTs: authSession.threadTs,
4496
+ requesterId: requester.userId
4497
+ },
4498
+ toolChannelId: authSession.toolChannelId ?? lockedArtifacts.assistantContextChannelId ?? authSession.channelId
4499
+ },
4500
+ policy: {
4501
+ configuration: authSession.configuration,
4502
+ channelConfiguration: lockedChannelConfiguration
4525
4503
  },
4526
- ...getTurnUserReplyAttachmentContext(lockedUserMessage)
4504
+ state: {
4505
+ artifactState: lockedArtifacts,
4506
+ pendingAuth: lockedPendingAuth,
4507
+ sandbox: getPersistedSandboxState(lockedState)
4508
+ },
4509
+ durability: {
4510
+ recordPendingAuth: async (nextPendingAuth) => {
4511
+ await applyPendingAuthUpdate({
4512
+ conversation: lockedConversation,
4513
+ conversationId: authSession.conversationId,
4514
+ nextPendingAuth
4515
+ });
4516
+ await persistThreadStateById(threadId, {
4517
+ conversation: lockedConversation
4518
+ });
4519
+ }
4520
+ }
4527
4521
  },
4528
4522
  onSuccess: async (reply) => {
4529
4523
  await persistCompletedReplyState(
@@ -4559,7 +4553,7 @@ async function resumeAuthorizedMcpTurn(args) {
4559
4553
  );
4560
4554
  }
4561
4555
  },
4562
- onAuthPause: async (error) => {
4556
+ onAuthPause: async () => {
4563
4557
  await persistAuthPauseTurnState({
4564
4558
  sessionId: lockedSessionId,
4565
4559
  threadStateId: threadId
@@ -4567,35 +4561,23 @@ async function resumeAuthorizedMcpTurn(args) {
4567
4561
  logWarn(
4568
4562
  "mcp_oauth_callback_resume_reparked_for_auth",
4569
4563
  {},
4570
- {
4571
- "app.credential.provider": provider,
4572
- ...isRetryableTurnError(error) ? { "app.ai.retryable_reason": error.reason } : {}
4573
- },
4564
+ { "app.credential.provider": provider },
4574
4565
  "Resumed MCP turn requested another authorization flow"
4575
4566
  );
4576
4567
  },
4577
- onTimeoutPause: async (error) => {
4578
- if (!isRetryableTurnError(error, "agent_continue")) {
4579
- throw error;
4580
- }
4581
- const version = error.metadata?.version;
4582
- if (typeof version !== "number") {
4583
- throw new Error(
4584
- "MCP OAuth agent continuation did not include a session record version"
4585
- );
4586
- }
4568
+ onTimeoutPause: async ({ resumeVersion }) => {
4587
4569
  await scheduleAgentContinue({
4588
4570
  conversationId: authSession.conversationId,
4589
4571
  destination,
4590
4572
  sessionId: lockedSessionId,
4591
- expectedVersion: version
4573
+ expectedVersion: resumeVersion
4592
4574
  });
4593
4575
  }
4594
4576
  };
4595
4577
  }
4596
4578
  });
4597
4579
  }
4598
- async function GET3(request, provider, waitUntil, options = {}) {
4580
+ async function GET3(request, provider, waitUntil, options) {
4599
4581
  const url = new URL(request.url);
4600
4582
  const state = url.searchParams.get("state")?.trim();
4601
4583
  const code = url.searchParams.get("code")?.trim();
@@ -4625,7 +4607,7 @@ async function GET3(request, provider, waitUntil, options = {}) {
4625
4607
  waitUntil(
4626
4608
  () => resumeAuthorizedMcpTurn({
4627
4609
  authSession,
4628
- generateReply: options.generateReply,
4610
+ agentRunner: options.agentRunner,
4629
4611
  provider
4630
4612
  })
4631
4613
  );
@@ -4927,7 +4909,7 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
4927
4909
  messageTs: getTurnUserSlackMessageTs(userMessage2),
4928
4910
  lockKey: stored.resumeConversationId,
4929
4911
  initialText: "",
4930
- generateReply: options.generateReply,
4912
+ agentRunner: options.agentRunner,
4931
4913
  beforeStart: async () => {
4932
4914
  const lockedState = await getPersistedThreadState(
4933
4915
  stored.resumeConversationId
@@ -5025,40 +5007,50 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
5025
5007
  messageText: lockedPendingAuth ? lockedUserMessage.text : stored.pendingMessage ?? lockedUserMessage.text,
5026
5008
  messageTs: lockedMessageTs,
5027
5009
  replyContext: {
5028
- credentialContext: {
5029
- actor: {
5030
- type: "user",
5031
- userId: requester.userId
5032
- }
5010
+ input: {
5011
+ conversationContext: lockedConversationContext,
5012
+ piMessages: lockedConversation.piMessages,
5013
+ ...getTurnUserReplyAttachmentContext(lockedUserMessage)
5014
+ },
5015
+ routing: {
5016
+ credentialContext: {
5017
+ actor: {
5018
+ type: "user",
5019
+ userId: requester.userId
5020
+ }
5021
+ },
5022
+ requester,
5023
+ destination,
5024
+ source: lockedSessionRecord.source,
5025
+ correlation: {
5026
+ conversationId: stored.resumeConversationId,
5027
+ turnId: lockedSessionId,
5028
+ channelId: stored.channelId,
5029
+ threadTs: stored.threadTs,
5030
+ requesterId: requester.userId
5031
+ },
5032
+ toolChannelId: lockedArtifacts.assistantContextChannelId ?? stored.channelId
5033
5033
  },
5034
- requester,
5035
- destination,
5036
- source: lockedSessionRecord.source,
5037
- correlation: {
5038
- conversationId: stored.resumeConversationId,
5039
- turnId: lockedSessionId,
5040
- channelId: stored.channelId,
5041
- threadTs: stored.threadTs,
5042
- requesterId: requester.userId
5034
+ policy: {
5035
+ channelConfiguration: lockedChannelConfiguration
5043
5036
  },
5044
- toolChannelId: lockedArtifacts.assistantContextChannelId ?? stored.channelId,
5045
- artifactState: lockedArtifacts,
5046
- pendingAuth: lockedPendingAuth,
5047
- conversationContext: lockedConversationContext,
5048
- channelConfiguration: lockedChannelConfiguration,
5049
- piMessages: lockedConversation.piMessages,
5050
- sandbox: getPersistedSandboxState(lockedState),
5051
- recordPendingAuth: async (nextPendingAuth) => {
5052
- await applyPendingAuthUpdate({
5053
- conversation: lockedConversation,
5054
- conversationId: stored.resumeConversationId,
5055
- nextPendingAuth
5056
- });
5057
- await persistThreadStateById(stored.resumeConversationId, {
5058
- conversation: lockedConversation
5059
- });
5037
+ state: {
5038
+ artifactState: lockedArtifacts,
5039
+ pendingAuth: lockedPendingAuth,
5040
+ sandbox: getPersistedSandboxState(lockedState)
5060
5041
  },
5061
- ...getTurnUserReplyAttachmentContext(lockedUserMessage)
5042
+ durability: {
5043
+ recordPendingAuth: async (nextPendingAuth) => {
5044
+ await applyPendingAuthUpdate({
5045
+ conversation: lockedConversation,
5046
+ conversationId: stored.resumeConversationId,
5047
+ nextPendingAuth
5048
+ });
5049
+ await persistThreadStateById(stored.resumeConversationId, {
5050
+ conversation: lockedConversation
5051
+ });
5052
+ }
5053
+ }
5062
5054
  },
5063
5055
  onSuccess: async (reply) => {
5064
5056
  logInfo(
@@ -5098,21 +5090,12 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
5098
5090
  threadStateId: stored.resumeConversationId
5099
5091
  });
5100
5092
  },
5101
- onTimeoutPause: async (error) => {
5102
- if (!isRetryableTurnError(error, "agent_continue")) {
5103
- throw error;
5104
- }
5105
- const version = error.metadata?.version;
5106
- if (typeof version !== "number") {
5107
- throw new Error(
5108
- "OAuth agent continuation did not include a session record version"
5109
- );
5110
- }
5093
+ onTimeoutPause: async ({ resumeVersion }) => {
5111
5094
  await scheduleAgentContinue({
5112
5095
  conversationId: stored.resumeConversationId,
5113
5096
  destination,
5114
5097
  sessionId: lockedSessionId,
5115
- expectedVersion: version
5098
+ expectedVersion: resumeVersion
5116
5099
  });
5117
5100
  }
5118
5101
  };
@@ -5148,23 +5131,29 @@ async function resumePendingOAuthMessage(stored, options) {
5148
5131
  threadTs: stored.threadTs,
5149
5132
  messageTs,
5150
5133
  connectedText: "",
5151
- generateReply: options.generateReply,
5134
+ agentRunner: options.agentRunner,
5152
5135
  replyContext: {
5153
- credentialContext: {
5154
- actor: { type: "user", userId: stored.userId }
5136
+ input: {
5137
+ conversationContext,
5138
+ piMessages: conversation.piMessages
5155
5139
  },
5156
- requester,
5157
- destination: stored.destination,
5158
- source,
5159
- correlation: {
5160
- conversationId: threadId,
5161
- channelId: stored.channelId,
5162
- threadTs: stored.threadTs,
5163
- requesterId: stored.userId
5140
+ routing: {
5141
+ credentialContext: {
5142
+ actor: { type: "user", userId: stored.userId }
5143
+ },
5144
+ requester,
5145
+ destination: stored.destination,
5146
+ source,
5147
+ correlation: {
5148
+ conversationId: threadId,
5149
+ channelId: stored.channelId,
5150
+ threadTs: stored.threadTs,
5151
+ requesterId: stored.userId
5152
+ }
5164
5153
  },
5165
- conversationContext,
5166
- piMessages: conversation.piMessages,
5167
- configuration: stored.configuration
5154
+ policy: {
5155
+ configuration: stored.configuration
5156
+ }
5168
5157
  },
5169
5158
  onSuccess: async (reply) => {
5170
5159
  logInfo(
@@ -5180,7 +5169,7 @@ async function resumePendingOAuthMessage(stored, options) {
5180
5169
  }
5181
5170
  });
5182
5171
  }
5183
- async function GET4(request, provider, waitUntil, options = {}) {
5172
+ async function GET4(request, provider, waitUntil, options) {
5184
5173
  const providerConfig = pluginCatalogRuntime.getOAuthConfig(provider);
5185
5174
  if (!providerConfig) {
5186
5175
  return htmlErrorResponse(
@@ -7908,16 +7897,6 @@ function createSlackTurnRuntime(deps) {
7908
7897
  channelId: deps.getChannelId(thread, message),
7909
7898
  runId: deps.getRunId(thread, message)
7910
7899
  });
7911
- if (isRetryableTurnError(error, "mcp_auth_resume") || isRetryableTurnError(error, "plugin_auth_resume")) {
7912
- deps.logException(
7913
- error,
7914
- "mention_handler_auth_pause",
7915
- errorContext,
7916
- { "app.ai.retryable_reason": error.reason },
7917
- "onNewMention parked turn for auth resume"
7918
- );
7919
- return;
7920
- }
7921
7900
  if (error instanceof AuthorizationFlowDisabledError) {
7922
7901
  return;
7923
7902
  }
@@ -8178,16 +8157,6 @@ function createSlackTurnRuntime(deps) {
8178
8157
  channelId: deps.getChannelId(thread, message),
8179
8158
  runId: deps.getRunId(thread, message)
8180
8159
  });
8181
- if (isRetryableTurnError(error, "mcp_auth_resume") || isRetryableTurnError(error, "plugin_auth_resume")) {
8182
- deps.logException(
8183
- error,
8184
- "subscribed_message_handler_auth_pause",
8185
- errorContext,
8186
- { "app.ai.retryable_reason": error.reason },
8187
- "onSubscribedMessage parked turn for auth resume"
8188
- );
8189
- return;
8190
- }
8191
8160
  if (error instanceof AuthorizationFlowDisabledError) {
8192
8161
  return;
8193
8162
  }
@@ -8601,7 +8570,7 @@ function createSubscribedReplyPolicy(deps) {
8601
8570
  };
8602
8571
  }
8603
8572
 
8604
- // src/chat/services/vision-context.ts
8573
+ // src/chat/slack/vision-context.ts
8605
8574
  var MAX_USER_ATTACHMENTS = 3;
8606
8575
  var MAX_USER_ATTACHMENT_BYTES = 5 * 1024 * 1024;
8607
8576
  var MAX_MESSAGE_IMAGE_ATTACHMENTS = 3;
@@ -8907,6 +8876,14 @@ async function hydrateConversationVisionContextWithDeps(conversation, context, d
8907
8876
  if (!context.channelId || !context.threadTs) {
8908
8877
  return;
8909
8878
  }
8879
+ const channelId = parseSlackChannelId(context.channelId);
8880
+ if (!channelId) {
8881
+ return;
8882
+ }
8883
+ const threadTs = parseSlackMessageTs(context.threadTs);
8884
+ if (!threadTs) {
8885
+ return;
8886
+ }
8910
8887
  const messagesByTs = /* @__PURE__ */ new Map();
8911
8888
  for (const message of conversation.messages) {
8912
8889
  if (!isHumanConversationMessage(message)) continue;
@@ -8921,8 +8898,8 @@ async function hydrateConversationVisionContextWithDeps(conversation, context, d
8921
8898
  let replies;
8922
8899
  try {
8923
8900
  replies = await deps.listThreadReplies({
8924
- channelId: context.channelId,
8925
- threadTs: context.threadTs,
8901
+ channelId,
8902
+ threadTs,
8926
8903
  limit: 1e3,
8927
8904
  maxPages: 10,
8928
8905
  targetMessageTs: [...messagesByTs.keys()]
@@ -9120,15 +9097,6 @@ function createVisionContextService(deps) {
9120
9097
  }
9121
9098
 
9122
9099
  // src/chat/app/services.ts
9123
- function withSandboxTracePropagation(generateReply, tracePropagation) {
9124
- return async (messageText2, context) => await generateReply(messageText2, {
9125
- ...context,
9126
- sandbox: {
9127
- ...context?.sandbox,
9128
- tracePropagation: context?.sandbox?.tracePropagation ?? tracePropagation
9129
- }
9130
- });
9131
- }
9132
9100
  function createJuniorRuntimeServices(overrides = {}) {
9133
9101
  const conversationMemory = createConversationMemoryService({
9134
9102
  completeText: overrides.conversationMemory?.completeText ?? completeText
@@ -9147,10 +9115,9 @@ function createJuniorRuntimeServices(overrides = {}) {
9147
9115
  contextCompactor,
9148
9116
  replyExecutor: {
9149
9117
  contextCompactor: overrides.replyExecutor?.contextCompactor ?? contextCompactor,
9150
- generateAssistantReply: overrides.replyExecutor?.generateAssistantReply ?? withSandboxTracePropagation(
9151
- generateAssistantReply,
9152
- overrides.sandbox?.tracePropagation
9153
- ),
9118
+ agentRunner: overrides.replyExecutor?.agentRunner ?? createAgentRunner(executeAgentRun, {
9119
+ tracePropagation: overrides.sandbox?.tracePropagation
9120
+ }),
9154
9121
  getAwaitingAgentContinueRequest: overrides.replyExecutor?.getAwaitingAgentContinueRequest ?? getAwaitingAgentContinueRequest,
9155
9122
  lookupSlackUser: overrides.replyExecutor?.lookupSlackUser ?? lookupSlackUser,
9156
9123
  scheduleAgentContinue: overrides.replyExecutor?.scheduleAgentContinue ?? scheduleAgentContinue,
@@ -9864,7 +9831,8 @@ function createReplyToThread(deps) {
9864
9831
  let finalReplyDelivered = false;
9865
9832
  let latestArtifacts = preparedState.artifacts;
9866
9833
  let assistantTitleArtifacts = {};
9867
- const hasVisibleSlackDelivery = (post) => post.text.trim().length > 0 || Boolean(post.files?.length);
9834
+ let agentContinueScheduleError;
9835
+ const hasVisibleSlackDelivery = (post) => post.text.trim().length > 0;
9868
9836
  try {
9869
9837
  const loadedPiMessages = await loadPiMessagesForTurn({
9870
9838
  conversationId,
@@ -9967,26 +9935,22 @@ function createReplyToThread(deps) {
9967
9935
  );
9968
9936
  return acceptedMessages ?? await resolveSteeringMessages(drained);
9969
9937
  } : void 0;
9970
- let reply = await deps.services.generateAssistantReply(
9971
- effectiveUserText,
9972
- {
9973
- credentialContext,
9974
- requester,
9938
+ const outcome = await deps.services.agentRunner.run({
9939
+ input: {
9940
+ messageText: effectiveUserText,
9975
9941
  conversationContext: preparedState.conversationContext,
9976
- artifactState: preparedState.artifacts,
9977
9942
  piMessages,
9978
- pendingAuth: preparedState.conversation.processing.pendingAuth,
9979
- configuration: preparedState.configuration,
9980
- channelConfiguration: preparedState.channelConfiguration,
9981
9943
  inboundAttachmentCount: turnAttachments.length,
9982
9944
  omittedImageAttachmentCount,
9983
- userAttachments,
9945
+ userAttachments
9946
+ },
9947
+ routing: {
9948
+ credentialContext,
9949
+ requester,
9984
9950
  slackConversation,
9985
9951
  source,
9986
9952
  destination,
9987
9953
  surface: "slack",
9988
- authorizationFlowMode: message.author.isBot === true ? "disabled" : void 0,
9989
- turnDeadlineAtMs: getTurnRequestDeadline()?.deadlineAtMs,
9990
9954
  correlation: {
9991
9955
  conversationId,
9992
9956
  threadId,
@@ -9999,11 +9963,30 @@ function createReplyToThread(deps) {
9999
9963
  channelName,
10000
9964
  requesterId: slackRequesterId
10001
9965
  },
10002
- toolChannelId,
9966
+ toolChannelId
9967
+ },
9968
+ policy: {
9969
+ configuration: preparedState.configuration,
9970
+ channelConfiguration: preparedState.channelConfiguration,
9971
+ authorizationFlowMode: message.author.isBot === true ? "disabled" : void 0,
9972
+ turnDeadlineAtMs: getTurnRequestDeadline()?.deadlineAtMs
9973
+ },
9974
+ state: {
9975
+ artifactState: preparedState.artifacts,
9976
+ pendingAuth: preparedState.conversation.processing.pendingAuth,
10003
9977
  sandbox: {
10004
9978
  sandboxId: preparedState.sandboxId,
10005
9979
  sandboxDependencyProfileHash: preparedState.sandboxDependencyProfileHash
10006
- },
9980
+ }
9981
+ },
9982
+ observers: {
9983
+ onStatus: (nextStatus) => status.update(nextStatus),
9984
+ onToolInvocation: options.onToolInvocation
9985
+ },
9986
+ durability: {
9987
+ onInputCommitted: options.ack,
9988
+ drainSteeringMessages,
9989
+ shouldYield: options.shouldYield,
10007
9990
  onSandboxAcquired: async (sandbox) => {
10008
9991
  await persistThreadState(thread, {
10009
9992
  sandboxId: sandbox.sandboxId,
@@ -10028,14 +10011,98 @@ function createReplyToThread(deps) {
10028
10011
  await persistThreadState(thread, {
10029
10012
  conversation: preparedState.conversation
10030
10013
  });
10031
- },
10032
- onStatus: (nextStatus) => status.update(nextStatus),
10033
- onToolInvocation: options.onToolInvocation,
10034
- onInputCommitted: options.ack,
10035
- drainSteeringMessages,
10036
- shouldYield: options.shouldYield
10014
+ }
10037
10015
  }
10038
- );
10016
+ });
10017
+ if (outcome.status === "awaiting_auth") {
10018
+ if (!requester) {
10019
+ 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.`;
10020
+ await postThreadReply(
10021
+ buildSlackOutputMessage(text),
10022
+ "thread_reply"
10023
+ );
10024
+ markConversationMessage(
10025
+ preparedState.conversation,
10026
+ preparedState.userMessageId,
10027
+ {
10028
+ replied: true,
10029
+ skippedReason: void 0
10030
+ }
10031
+ );
10032
+ upsertConversationMessage(preparedState.conversation, {
10033
+ id: generateConversationId("assistant"),
10034
+ role: "assistant",
10035
+ text: normalizeConversationText(text),
10036
+ createdAtMs: Date.now(),
10037
+ author: {
10038
+ userName: botConfig.userName,
10039
+ isBot: true
10040
+ },
10041
+ meta: {
10042
+ replied: true
10043
+ }
10044
+ });
10045
+ markTurnClosed({
10046
+ conversation: preparedState.conversation,
10047
+ nowMs: Date.now(),
10048
+ sessionId: turnId,
10049
+ updateConversationStats
10050
+ });
10051
+ await persistThreadState(thread, {
10052
+ conversation: preparedState.conversation
10053
+ });
10054
+ persistedAtLeastOnce = true;
10055
+ shouldPersistFailureState = false;
10056
+ return;
10057
+ }
10058
+ await postAuthPauseNotice(outcome.providerDisplayName);
10059
+ completeAuthPauseTurn({
10060
+ conversation: preparedState.conversation,
10061
+ sessionId: turnId
10062
+ });
10063
+ await persistThreadState(thread, {
10064
+ conversation: preparedState.conversation
10065
+ });
10066
+ persistedAtLeastOnce = true;
10067
+ shouldPersistFailureState = false;
10068
+ return;
10069
+ }
10070
+ if (outcome.status === "suspended") {
10071
+ if (options.shouldYield?.()) {
10072
+ shouldPersistFailureState = false;
10073
+ throw new CooperativeTurnYieldError();
10074
+ }
10075
+ if (!destination || !conversationId) {
10076
+ throw new Error(
10077
+ "Agent continuation requires a destination and conversation id"
10078
+ );
10079
+ }
10080
+ try {
10081
+ await deps.services.scheduleAgentContinue({
10082
+ conversationId,
10083
+ destination,
10084
+ sessionId: turnId,
10085
+ expectedVersion: outcome.resumeVersion
10086
+ });
10087
+ shouldPersistFailureState = false;
10088
+ } catch (scheduleError) {
10089
+ logException(
10090
+ scheduleError,
10091
+ "agent_continue_schedule_failed",
10092
+ turnTraceContext,
10093
+ {
10094
+ ...messageTs ? { "messaging.message.id": messageTs } : {},
10095
+ "app.ai.resume_session_version": outcome.resumeVersion
10096
+ },
10097
+ "Failed to schedule agent continuation"
10098
+ );
10099
+ shouldPersistFailureState = true;
10100
+ agentContinueScheduleError = scheduleError;
10101
+ throw scheduleError;
10102
+ }
10103
+ return;
10104
+ }
10105
+ let reply = outcome.result;
10039
10106
  const diagnosticsContext = {
10040
10107
  slackThreadId: threadId,
10041
10108
  slackUserId: message.author.userId,
@@ -10081,7 +10148,6 @@ function createReplyToThread(deps) {
10081
10148
  channelId: slackChannelId,
10082
10149
  threadTs: slackThreadTs,
10083
10150
  posts: plannedPosts,
10084
- fileUploadFailureMode: "strict",
10085
10151
  footer: replyFooter,
10086
10152
  onPostError: ({ error, messageTs: messageTs2, stage }) => {
10087
10153
  logException(
@@ -10103,7 +10169,7 @@ function createReplyToThread(deps) {
10103
10169
  continue;
10104
10170
  }
10105
10171
  await postThreadReply(
10106
- buildSlackOutputMessage(post.text, post.files),
10172
+ buildSlackOutputMessage(post.text),
10107
10173
  post.stage
10108
10174
  );
10109
10175
  }
@@ -10229,99 +10295,13 @@ function createReplyToThread(deps) {
10229
10295
  );
10230
10296
  return;
10231
10297
  }
10232
- if (isCooperativeTurnYieldError(error)) {
10298
+ if (error instanceof CooperativeTurnYieldError) {
10233
10299
  shouldPersistFailureState = false;
10234
10300
  throw error;
10235
10301
  }
10236
- if (isAuthResumeRetryableTurnError(error)) {
10237
- if (!requester) {
10238
- const text = `I could not act on this subscribed event because ${error.metadata.authProviderDisplayName} needs user authorization. Ask me in this thread to connect ${error.metadata.authProviderDisplayName} before retrying.`;
10239
- await postThreadReply(
10240
- buildSlackOutputMessage(text),
10241
- "thread_reply"
10242
- );
10243
- markConversationMessage(
10244
- preparedState.conversation,
10245
- preparedState.userMessageId,
10246
- {
10247
- replied: true,
10248
- skippedReason: void 0
10249
- }
10250
- );
10251
- upsertConversationMessage(preparedState.conversation, {
10252
- id: generateConversationId("assistant"),
10253
- role: "assistant",
10254
- text: normalizeConversationText(text),
10255
- createdAtMs: Date.now(),
10256
- author: {
10257
- userName: botConfig.userName,
10258
- isBot: true
10259
- },
10260
- meta: {
10261
- replied: true
10262
- }
10263
- });
10264
- markTurnClosed({
10265
- conversation: preparedState.conversation,
10266
- nowMs: Date.now(),
10267
- sessionId: turnId,
10268
- updateConversationStats
10269
- });
10270
- await persistThreadState(thread, {
10271
- conversation: preparedState.conversation
10272
- });
10273
- persistedAtLeastOnce = true;
10274
- shouldPersistFailureState = false;
10275
- return;
10276
- }
10277
- await postAuthPauseNotice(error.metadata.authProviderDisplayName);
10278
- completeAuthPauseTurn({
10279
- conversation: preparedState.conversation,
10280
- sessionId: error.metadata?.sessionId ?? turnId
10281
- });
10282
- await persistThreadState(thread, {
10283
- conversation: preparedState.conversation
10284
- });
10285
- persistedAtLeastOnce = true;
10286
- shouldPersistFailureState = false;
10287
- return;
10288
- }
10289
- if (isRetryableTurnError(error, "agent_continue")) {
10290
- const conversationIdForResume = error.metadata?.conversationId;
10291
- const sessionIdForResume = error.metadata?.sessionId;
10292
- const version = error.metadata?.version;
10293
- if (conversationIdForResume && sessionIdForResume && typeof version === "number" && destination) {
10294
- try {
10295
- await deps.services.scheduleAgentContinue({
10296
- conversationId: conversationIdForResume,
10297
- destination,
10298
- sessionId: sessionIdForResume,
10299
- expectedVersion: version
10300
- });
10301
- shouldPersistFailureState = false;
10302
- } catch (scheduleError) {
10303
- logException(
10304
- scheduleError,
10305
- "agent_continue_schedule_failed",
10306
- turnTraceContext,
10307
- {
10308
- ...messageTs ? { "messaging.message.id": messageTs } : {},
10309
- "app.ai.resume_session_version": version
10310
- },
10311
- "Failed to schedule agent continuation"
10312
- );
10313
- shouldPersistFailureState = true;
10314
- throw scheduleError;
10315
- }
10316
- return;
10317
- } else {
10318
- logWarn(
10319
- "agent_continue_metadata_missing",
10320
- turnTraceContext,
10321
- messageTs ? { "messaging.message.id": messageTs } : {},
10322
- "Agent continuation could not be scheduled because retry metadata was incomplete"
10323
- );
10324
- }
10302
+ if (error === agentContinueScheduleError) {
10303
+ shouldPersistFailureState = true;
10304
+ throw error;
10325
10305
  }
10326
10306
  shouldPersistFailureState = true;
10327
10307
  const createdCanvasUrl = getCurrentTurnCanvasUrl({
@@ -10962,7 +10942,7 @@ async function failUnresumableContinuation(args) {
10962
10942
  errorMessage: args.errorMessage
10963
10943
  });
10964
10944
  }
10965
- async function continueSlackAgentRun(payload, options = {}) {
10945
+ async function continueSlackAgentRun(payload, options) {
10966
10946
  const thread = parseSlackThreadId(payload.conversationId);
10967
10947
  if (!thread) {
10968
10948
  throw new Error(
@@ -10976,7 +10956,7 @@ async function continueSlackAgentRun(payload, options = {}) {
10976
10956
  channelId: thread.channelId,
10977
10957
  threadTs: thread.threadTs,
10978
10958
  lockKey: payload.conversationId,
10979
- generateReply: options.generateReply,
10959
+ agentRunner: options.agentRunner,
10980
10960
  scheduleSessionCompletedPluginTasks: options.scheduleSessionCompletedPluginTasks,
10981
10961
  beforeStart: async () => {
10982
10962
  let sessionRecord;
@@ -11041,40 +11021,50 @@ async function continueSlackAgentRun(payload, options = {}) {
11041
11021
  messageText: userMessage2.text,
11042
11022
  messageTs: getTurnUserSlackMessageTs(userMessage2),
11043
11023
  replyContext: {
11044
- credentialContext: {
11045
- actor: {
11046
- type: "user",
11047
- userId: requester.userId
11048
- }
11049
- },
11050
- requester,
11051
- destination: payload.destination,
11052
- source: activeSessionRecord.source,
11053
- correlation: {
11054
- conversationId: payload.conversationId,
11055
- turnId: payload.sessionId,
11056
- channelId: thread.channelId,
11057
- threadTs: thread.threadTs,
11058
- requesterId: requester.userId
11024
+ input: {
11025
+ conversationContext,
11026
+ piMessages: conversation.piMessages,
11027
+ ...getTurnUserReplyAttachmentContext(userMessage2)
11059
11028
  },
11060
- toolChannelId: artifacts.assistantContextChannelId ?? thread.channelId,
11061
- artifactState: artifacts,
11062
- pendingAuth: conversation.processing.pendingAuth,
11063
- conversationContext,
11064
- channelConfiguration,
11065
- piMessages: conversation.piMessages,
11066
- sandbox,
11067
- recordPendingAuth: async (nextPendingAuth) => {
11068
- await applyPendingAuthUpdate({
11069
- conversation,
11029
+ routing: {
11030
+ credentialContext: {
11031
+ actor: {
11032
+ type: "user",
11033
+ userId: requester.userId
11034
+ }
11035
+ },
11036
+ requester,
11037
+ destination: payload.destination,
11038
+ source: activeSessionRecord.source,
11039
+ correlation: {
11070
11040
  conversationId: payload.conversationId,
11071
- nextPendingAuth
11072
- });
11073
- await persistThreadStateById(payload.conversationId, {
11074
- conversation
11075
- });
11041
+ turnId: payload.sessionId,
11042
+ channelId: thread.channelId,
11043
+ threadTs: thread.threadTs,
11044
+ requesterId: requester.userId
11045
+ },
11046
+ toolChannelId: artifacts.assistantContextChannelId ?? thread.channelId
11047
+ },
11048
+ policy: {
11049
+ channelConfiguration
11076
11050
  },
11077
- ...getTurnUserReplyAttachmentContext(userMessage2)
11051
+ state: {
11052
+ artifactState: artifacts,
11053
+ pendingAuth: conversation.processing.pendingAuth,
11054
+ sandbox
11055
+ },
11056
+ durability: {
11057
+ recordPendingAuth: async (nextPendingAuth) => {
11058
+ await applyPendingAuthUpdate({
11059
+ conversation,
11060
+ conversationId: payload.conversationId,
11061
+ nextPendingAuth
11062
+ });
11063
+ await persistThreadStateById(payload.conversationId, {
11064
+ conversation
11065
+ });
11066
+ }
11067
+ }
11078
11068
  },
11079
11069
  onSuccess: async (reply) => {
11080
11070
  await persistCompletedReplyState2({
@@ -11108,21 +11098,12 @@ async function continueSlackAgentRun(payload, options = {}) {
11108
11098
  "Continued agent run parked for auth"
11109
11099
  );
11110
11100
  },
11111
- onTimeoutPause: async (error) => {
11112
- if (!isRetryableTurnError(error, "agent_continue")) {
11113
- throw error;
11114
- }
11115
- const version = error.metadata?.version;
11116
- if (typeof version !== "number") {
11117
- throw new Error(
11118
- "Agent continuation did not include a session record version"
11119
- );
11120
- }
11101
+ onTimeoutPause: async ({ resumeVersion }) => {
11121
11102
  await scheduleAgentContinue2({
11122
11103
  conversationId: payload.conversationId,
11123
11104
  destination: payload.destination,
11124
11105
  sessionId: payload.sessionId,
11125
- expectedVersion: version
11106
+ expectedVersion: resumeVersion
11126
11107
  });
11127
11108
  }
11128
11109
  };
@@ -11240,7 +11221,7 @@ async function recoverStrandedRunningSession(args) {
11240
11221
  });
11241
11222
  return false;
11242
11223
  }
11243
- async function resumeAwaitingSlackContinuation(conversationId, options = {}) {
11224
+ async function resumeAwaitingSlackContinuation(conversationId, options) {
11244
11225
  const summaries = await listAgentTurnSessionSummariesForConversation(conversationId);
11245
11226
  const newest = summaries[0];
11246
11227
  if (newest?.state === "running") {
@@ -11278,7 +11259,7 @@ async function resumeAwaitingSlackContinuation(conversationId, options = {}) {
11278
11259
  }
11279
11260
  return false;
11280
11261
  }
11281
- async function continueSlackAgentRunWithLockRetry(payload, options = {}) {
11262
+ async function continueSlackAgentRunWithLockRetry(payload, options) {
11282
11263
  const scheduleAgentContinue2 = options.scheduleAgentContinue ?? scheduleAgentContinue;
11283
11264
  for (const [attempt, delayMs] of [
11284
11265
  ...AGENT_CONTINUE_LOCK_RETRY_DELAYS_MS,
@@ -11362,9 +11343,17 @@ function createProductionSlackWebhookServices(options) {
11362
11343
  }
11363
11344
  function createProductionConversationWorkOptions(options) {
11364
11345
  const conversationStore = getProductionConversationStore();
11346
+ const { agentRunner } = options;
11347
+ const services = {
11348
+ ...options.services,
11349
+ replyExecutor: {
11350
+ ...options.services?.replyExecutor,
11351
+ agentRunner
11352
+ }
11353
+ };
11365
11354
  const runtime = createSlackRuntime({
11366
11355
  getSlackAdapter: getProductionSlackAdapter,
11367
- services: options?.services
11356
+ services
11368
11357
  });
11369
11358
  return {
11370
11359
  conversationStore,
@@ -11373,11 +11362,8 @@ function createProductionConversationWorkOptions(options) {
11373
11362
  getSlackAdapter: getProductionSlackAdapter,
11374
11363
  conversationStore,
11375
11364
  resumeAwaitingContinuation: async (conversationId) => await resumeAwaitingSlackContinuation(conversationId, {
11376
- generateReply: withSandboxTracePropagation(
11377
- generateAssistantReply,
11378
- options?.services?.sandbox?.tracePropagation
11379
- ),
11380
- scheduleSessionCompletedPluginTasks: options?.services?.replyExecutor?.scheduleSessionCompletedPluginTasks
11365
+ agentRunner,
11366
+ scheduleSessionCompletedPluginTasks: services.replyExecutor?.scheduleSessionCompletedPluginTasks
11381
11367
  }),
11382
11368
  runtime
11383
11369
  })
@@ -11699,18 +11685,17 @@ async function createApp(options) {
11699
11685
  throw error;
11700
11686
  }
11701
11687
  const waitUntil = options?.waitUntil ?? await defaultWaitUntil();
11688
+ const tracePropagation = { domains: sandboxEgressTracePropagationDomains };
11689
+ const agentRunner = createAgentRunner(executeAgentRun, {
11690
+ tracePropagation
11691
+ });
11702
11692
  const runtimeServiceOverrides = {
11703
- sandbox: {
11704
- tracePropagation: { domains: sandboxEgressTracePropagationDomains }
11705
- }
11693
+ replyExecutor: { agentRunner },
11694
+ sandbox: { tracePropagation }
11706
11695
  };
11707
11696
  const slackWebhookServices = createProductionSlackWebhookServices({
11708
11697
  services: runtimeServiceOverrides
11709
11698
  });
11710
- const generateReplyWithTracePropagation = withSandboxTracePropagation(
11711
- generateAssistantReply,
11712
- runtimeServiceOverrides.sandbox.tracePropagation
11713
- );
11714
11699
  const app = new Hono();
11715
11700
  app.onError((err, c) => {
11716
11701
  logException(err, "unhandled_route_error");
@@ -11736,24 +11721,23 @@ async function createApp(options) {
11736
11721
  app.get("/health", () => GET());
11737
11722
  app.get("/api/oauth/callback/mcp/:provider", (c) => {
11738
11723
  return GET3(c.req.raw, c.req.param("provider"), waitUntil, {
11739
- generateReply: generateReplyWithTracePropagation
11724
+ agentRunner
11740
11725
  });
11741
11726
  });
11742
11727
  app.get("/api/oauth/callback/:provider", (c) => {
11743
11728
  return GET4(c.req.raw, c.req.param("provider"), waitUntil, {
11744
- generateReply: generateReplyWithTracePropagation
11729
+ agentRunner
11745
11730
  });
11746
11731
  });
11747
11732
  app.post("/api/internal/agent-dispatch", (c) => {
11748
- return POST(c.req.raw, waitUntil, {
11749
- tracePropagation: { domains: sandboxEgressTracePropagationDomains }
11750
- });
11733
+ return POST(c.req.raw, waitUntil, { agentRunner });
11751
11734
  });
11752
11735
  let agentContinuePOST;
11753
11736
  let pluginTaskPOST;
11754
11737
  let conversationWorkOptions;
11755
11738
  const getConversationWorkOptions = () => {
11756
11739
  conversationWorkOptions ??= options?.conversationWork ?? createProductionConversationWorkOptions({
11740
+ agentRunner,
11757
11741
  services: runtimeServiceOverrides
11758
11742
  });
11759
11743
  return conversationWorkOptions;