@sentry/junior 0.188.0 → 0.190.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.
- package/dist/{agent-hooks-5RQEVLQD.js → agent-hooks-3IG2FQW2.js} +11 -11
- package/dist/api/acp/conversations.d.ts +2 -2
- package/dist/api/conversations/list.d.ts +7 -0
- package/dist/api/people/shared.d.ts +54 -0
- package/dist/api.js +44 -55
- package/dist/app.d.ts +1 -1
- package/dist/app.js +1025 -349
- package/dist/{catalog-runtime-L4A6BJ3U.js → catalog-runtime-2OT7S3ZC.js} +4 -4
- package/dist/chat/actor.d.ts +7 -2
- package/dist/chat/agent/resume.d.ts +0 -2
- package/dist/chat/agent/types.d.ts +8 -9
- package/dist/chat/agent-dispatch/work.d.ts +1 -10
- package/dist/chat/agent-invocations/spawn.d.ts +1 -1
- package/dist/chat/agent-invocations/types.d.ts +44 -108
- package/dist/chat/app/conversation-work.d.ts +16 -8
- package/dist/chat/conversation-privacy.d.ts +7 -7
- package/dist/chat/conversations/destination.d.ts +12 -0
- package/dist/chat/conversations/projection.d.ts +2 -2
- package/dist/chat/conversations/sql/location.d.ts +13 -4
- package/dist/chat/{api-turns → conversations}/stop.d.ts +2 -2
- package/dist/chat/conversations/store.d.ts +4 -4
- package/dist/chat/conversations/structured-events.d.ts +1 -1
- package/dist/chat/{api-turns/authorization.d.ts → conversations/web-authorization.d.ts} +1 -0
- package/dist/chat/conversations/web-input.d.ts +98 -0
- package/dist/chat/conversations/web-mailbox.d.ts +12 -0
- package/dist/chat/event-tasks/tool-support.d.ts +1 -7
- package/dist/chat/providers/slack/runtime.d.ts +1 -0
- package/dist/chat/providers/slack/system-turn.d.ts +8 -0
- package/dist/chat/resource-events/actor.d.ts +13 -12
- package/dist/chat/resource-events/notification.d.ts +1 -1
- package/dist/chat/services/guardian-action-policy.d.ts +1 -1
- package/dist/chat/services/turn-session-routing.d.ts +2 -2
- package/dist/chat/source.d.ts +3 -3
- package/dist/chat/task-execution/assistant-message.d.ts +32 -0
- package/dist/chat/task-execution/conversation-turn.d.ts +8 -0
- package/dist/chat/{api-turns → task-execution}/mailbox-input.d.ts +1 -2
- package/dist/chat/task-execution/mailbox-turn.d.ts +52 -0
- package/dist/chat/task-execution/paused-turn.d.ts +1 -1
- package/dist/chat/task-execution/slack-work.d.ts +0 -2
- package/dist/chat/task-execution/state.d.ts +2 -2
- package/dist/chat/task-execution/store.d.ts +1 -1
- package/dist/chat/task-execution/turn-cursor.d.ts +10 -1
- package/dist/chat/tools/types.d.ts +9 -2
- package/dist/{chunk-XJIPMHKI.js → chunk-2MKHYSYL.js} +3 -3
- package/dist/{chunk-QCGNHSMA.js → chunk-2MRF22J4.js} +25 -10
- package/dist/{chunk-HCIVBCP5.js → chunk-3J3BCB4J.js} +1 -1
- package/dist/chunk-4BLFIYVK.js +703 -0
- package/dist/{chunk-NZLZ4KYZ.js → chunk-4PKEJK5B.js} +1 -1
- package/dist/{chunk-VFZAUQ5V.js → chunk-62DRKZQU.js} +5 -183
- package/dist/{chunk-QIOUTXTZ.js → chunk-663DQH5W.js} +1 -1
- package/dist/{chunk-Z5SKZE5B.js → chunk-67MMSYSE.js} +4 -12
- package/dist/{chunk-ZX7RSBQ6.js → chunk-6BXUSF7J.js} +1 -1
- package/dist/{chunk-W42ENMJW.js → chunk-6H7YU6XH.js} +1 -1
- package/dist/{chunk-WGZJ5SU4.js → chunk-7UJ6IJCK.js} +1 -1
- package/dist/{chunk-QDHJTKPE.js → chunk-7Y7XMI6P.js} +8 -6
- package/dist/{chunk-6YGFBU3A.js → chunk-BGOLRC36.js} +62 -336
- package/dist/{chunk-CVBDVIF4.js → chunk-BUJU6C2J.js} +1 -1
- package/dist/{chunk-XI4PVY2T.js → chunk-CZXZKTAI.js} +5 -5
- package/dist/chunk-DA2KGZZI.js +13 -0
- package/dist/{chunk-RMB7CERI.js → chunk-DJZGQ7OL.js} +311 -137
- package/dist/{chunk-FIUCHYT6.js → chunk-DVX6U6GI.js} +1 -1
- package/dist/{chunk-AW77HH54.js → chunk-ECOR3OXY.js} +19 -299
- package/dist/{chunk-WW2Y7JIA.js → chunk-F3K2267N.js} +51 -50
- package/dist/{chunk-W2DDJCPS.js → chunk-FVFJ57RK.js} +8 -8
- package/dist/{chunk-UVUXFRYN.js → chunk-GWCFXTB6.js} +211 -7
- package/dist/{chunk-X55FOVZO.js → chunk-HI5KXE3C.js} +3 -3
- package/dist/{chunk-ERZMACYA.js → chunk-IRQ3RSX3.js} +3 -3
- package/dist/{chunk-32XSSFZV.js → chunk-JV7U4665.js} +1 -1
- package/dist/chunk-MNHJ4WLE.js +285 -0
- package/dist/{chunk-SC67CH3C.js → chunk-OJFX2FP7.js} +14 -17
- package/dist/{chunk-IUUQWIG2.js → chunk-OKAHLUSU.js} +70 -19
- package/dist/{chunk-PSHMPRIU.js → chunk-OON4IQHH.js} +2 -2
- package/dist/{chunk-6JZGXLL2.js → chunk-OYCOLHCR.js} +5 -7
- package/dist/{chunk-3HEZWDS5.js → chunk-REVH4BZU.js} +2 -2
- package/dist/{chunk-CDSLOYOR.js → chunk-RLYJYEIY.js} +6 -6
- package/dist/{chunk-CZRWU4ZM.js → chunk-T66GV7A3.js} +2 -5
- package/dist/{chunk-Q7O74WOO.js → chunk-VWNIDTFR.js} +2 -2
- package/dist/{chunk-CIG6WI7Q.js → chunk-W2C4TPLB.js} +5 -5
- package/dist/{chunk-QIMN3FXL.js → chunk-Y4WL4OYD.js} +1 -1
- package/dist/{chunk-MQDIIFZM.js → chunk-YFU4DGZY.js} +12 -5
- package/dist/chunk-YKIAUKYH.js +311 -0
- package/dist/{chunk-QVH6FW3T.js → chunk-ZFCO2TMB.js} +7 -3
- package/dist/cli/chat.js +34 -33
- package/dist/cli/check.js +5 -5
- package/dist/cli/plugins.js +12 -12
- package/dist/cli/snapshot-create.js +9 -9
- package/dist/cli/upgrade.js +6 -6
- package/dist/db/schema/agent-invocations.d.ts +18 -42
- package/dist/db/schema/conversations.d.ts +62 -0
- package/dist/db/schema.d.ts +49 -42
- package/dist/{db-YPRZAA2T.js → db-2IFDMDDY.js} +6 -6
- package/dist/instrumentation.js +3 -3
- package/dist/nitro.js +6 -6
- package/dist/{oauth-callback-server-DBBIR3XG.js → oauth-callback-server-SZSS2KH6.js} +30 -28
- package/dist/{runner-FKVFFPLO.js → runner-2N4QU77X.js} +25 -21
- package/dist/{skills-4RBAZEMV.js → skills-VU2LZAKX.js} +5 -5
- package/dist/spawn-3K7RV4T5.js +42 -0
- package/dist/task-runner-52DYFHW3.js +36 -0
- package/dist/{validation-E6Z5LHZM.js → validation-IJGHK7NI.js} +5 -5
- package/dist/version.js +1 -1
- package/dist/{work-OFTXWOK4.js → work-DI45MLRL.js} +22 -21
- package/dist/{worker-OMWNOKTJ.js → worker-FY7KWG2M.js} +10 -10
- package/migrations/0037_conversation_location.sql +23 -0
- package/migrations/meta/0037_snapshot.json +3192 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +4 -4
- package/dist/chat/api-turns/assistant-message.d.ts +0 -12
- package/dist/chat/api-turns/cancellation.d.ts +0 -24
- package/dist/chat/api-turns/routing.d.ts +0 -51
- package/dist/chat/api-turns/work.d.ts +0 -99
- package/dist/chat/task-execution/slack-resource-event.d.ts +0 -55
- package/dist/chunk-6FGN7ZEG.js +0 -221
- package/dist/chunk-LODJKINF.js +0 -1502
- package/dist/spawn-CO7QFCNJ.js +0 -41
- package/dist/task-runner-DUGZGI7V.js +0 -34
package/dist/app.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
processConversationWork
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RLYJYEIY.js";
|
|
4
4
|
import {
|
|
5
5
|
bindSpawnAgent
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-T66GV7A3.js";
|
|
7
7
|
import {
|
|
8
8
|
createAgentInvocationWorker,
|
|
9
9
|
enqueueAgentInvocation,
|
|
10
10
|
listPendingAgentInvocationMailboxAppends,
|
|
11
|
-
|
|
12
|
-
} from "./chunk-
|
|
11
|
+
resolveAgentInvocationId
|
|
12
|
+
} from "./chunk-OJFX2FP7.js";
|
|
13
13
|
import {
|
|
14
14
|
GET as GET2,
|
|
15
15
|
GET2 as GET3,
|
|
@@ -37,30 +37,12 @@ import {
|
|
|
37
37
|
startProcessingReaction,
|
|
38
38
|
stripLeadingBotMention,
|
|
39
39
|
wakePausedTurn
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-F3K2267N.js";
|
|
41
41
|
import "./chunk-FA6POGLH.js";
|
|
42
|
-
import {
|
|
43
|
-
GET,
|
|
44
|
-
apiTurnIdForMessage,
|
|
45
|
-
appendAndEnqueueApiConversationMessage,
|
|
46
|
-
conversationVisibilityFromSlackChannelType,
|
|
47
|
-
createApiTurnCancellation,
|
|
48
|
-
createApiTurnWorker,
|
|
49
|
-
createVercelAttachmentStorage,
|
|
50
|
-
getAuthPausedApiTurnId,
|
|
51
|
-
lookupSlackUser,
|
|
52
|
-
readConversationAccessFromSql,
|
|
53
|
-
recordApiConversationActivity,
|
|
54
|
-
resolveSlackChannelTypeFromMessage,
|
|
55
|
-
resolveSlackConversationContext,
|
|
56
|
-
routeApiTurnWork,
|
|
57
|
-
webActorFromEmail
|
|
58
|
-
} from "./chunk-LODJKINF.js";
|
|
59
|
-
import "./chunk-PSHMPRIU.js";
|
|
60
42
|
import {
|
|
61
43
|
AgentRunError,
|
|
62
44
|
executeTurn
|
|
63
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-IRQ3RSX3.js";
|
|
64
46
|
import {
|
|
65
47
|
buildDeliveredTurnStatePatch,
|
|
66
48
|
completeAuthPauseTurn,
|
|
@@ -71,7 +53,7 @@ import {
|
|
|
71
53
|
getTurnUserSlackMessageTs,
|
|
72
54
|
persistAuthPauseTurnState,
|
|
73
55
|
requireTurnFailureEventId
|
|
74
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-7Y7XMI6P.js";
|
|
75
57
|
import {
|
|
76
58
|
claimDispatchMailboxAppend,
|
|
77
59
|
confirmDispatchMailboxAppend,
|
|
@@ -88,14 +70,14 @@ import {
|
|
|
88
70
|
markDispatchCompleted,
|
|
89
71
|
markDispatchFailed,
|
|
90
72
|
markDispatchRunning,
|
|
91
|
-
|
|
92
|
-
resolveConversationRouting,
|
|
73
|
+
processPluginTask,
|
|
93
74
|
resolveTurnSessionRouting,
|
|
94
75
|
scheduleSessionCompletedPluginTasks
|
|
95
|
-
} from "./chunk-
|
|
76
|
+
} from "./chunk-ECOR3OXY.js";
|
|
96
77
|
import {
|
|
78
|
+
ConversationTurnLifecycleService,
|
|
97
79
|
getTurnLifecycle
|
|
98
|
-
} from "./chunk-
|
|
80
|
+
} from "./chunk-6H7YU6XH.js";
|
|
99
81
|
import {
|
|
100
82
|
coerceThreadConversationState,
|
|
101
83
|
getLocationConfigurationService,
|
|
@@ -104,17 +86,39 @@ import {
|
|
|
104
86
|
persistThreadRuntimeState,
|
|
105
87
|
persistThreadState,
|
|
106
88
|
persistThreadStateById
|
|
107
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-W2C4TPLB.js";
|
|
90
|
+
import {
|
|
91
|
+
GET,
|
|
92
|
+
appendAndEnqueueWebMessage,
|
|
93
|
+
conversationTurnIdForMessage,
|
|
94
|
+
conversationVisibilityFromSlackChannelType,
|
|
95
|
+
createVercelAttachmentStorage,
|
|
96
|
+
legacyWebMailboxMetadataSchema,
|
|
97
|
+
lookupSlackUser,
|
|
98
|
+
readConversationAccessFromSql,
|
|
99
|
+
recordWebConversationActivity,
|
|
100
|
+
resolveConversationDestination,
|
|
101
|
+
resolveSlackChannelTypeFromMessage,
|
|
102
|
+
resolveSlackConversationContext,
|
|
103
|
+
webActorFromEmail
|
|
104
|
+
} from "./chunk-4BLFIYVK.js";
|
|
105
|
+
import {
|
|
106
|
+
createWebAuthorization,
|
|
107
|
+
deleteWebAuthorization
|
|
108
|
+
} from "./chunk-OON4IQHH.js";
|
|
109
|
+
import {
|
|
110
|
+
recordTaskExecution
|
|
111
|
+
} from "./chunk-MNHJ4WLE.js";
|
|
108
112
|
import "./chunk-UTL3MHPC.js";
|
|
109
113
|
import {
|
|
110
114
|
createVercelPluginTaskCallback,
|
|
111
115
|
queueCallback,
|
|
112
116
|
registerVercelPluginTaskDevConsumer
|
|
113
|
-
} from "./chunk-
|
|
117
|
+
} from "./chunk-CZXZKTAI.js";
|
|
114
118
|
import {
|
|
115
119
|
validatePluginEgressCredentialHooks,
|
|
116
120
|
validatePluginRegistrations
|
|
117
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-3J3BCB4J.js";
|
|
118
122
|
import {
|
|
119
123
|
defineJuniorPlugins,
|
|
120
124
|
pluginCatalogConfigFromEnv,
|
|
@@ -122,6 +126,8 @@ import {
|
|
|
122
126
|
pluginRuntimeRegistrationsFromPluginSet
|
|
123
127
|
} from "./chunk-CM5HNV2W.js";
|
|
124
128
|
import {
|
|
129
|
+
RESOURCE_EVENT_MESSAGE_AUTHOR,
|
|
130
|
+
RESOURCE_EVENT_SYSTEM_ACTOR,
|
|
125
131
|
SANDBOX_EGRESS_PROXY_PATH,
|
|
126
132
|
buildSteeringPiMessage,
|
|
127
133
|
clearSandboxEgressSignals,
|
|
@@ -133,6 +139,8 @@ import {
|
|
|
133
139
|
getConfigDefaults,
|
|
134
140
|
getNextRunAtMs,
|
|
135
141
|
ingestResourceEvent,
|
|
142
|
+
isResourceEventConversationMessage,
|
|
143
|
+
isResourceEventMailboxMetadata,
|
|
136
144
|
latestReportedProgress,
|
|
137
145
|
listThreadReplies,
|
|
138
146
|
logScheduledTaskRunSkipped,
|
|
@@ -143,18 +151,18 @@ import {
|
|
|
143
151
|
readPublicArtifact,
|
|
144
152
|
renderAttachmentText,
|
|
145
153
|
renderBlockText,
|
|
146
|
-
|
|
154
|
+
renderTaskInput,
|
|
147
155
|
resolveSandboxEgressProviderForHost,
|
|
148
156
|
scheduledTaskRunAttributes,
|
|
149
157
|
setConfigDefaults,
|
|
150
158
|
shouldEmitDevAgentTrace,
|
|
151
159
|
shouldPropagateSandboxEgressTrace,
|
|
152
160
|
unpublishedArtifactHeaders
|
|
153
|
-
} from "./chunk-
|
|
161
|
+
} from "./chunk-DJZGQ7OL.js";
|
|
154
162
|
import {
|
|
155
163
|
AuthorizationFlowDisabledError,
|
|
156
164
|
PluginCredentialFailureError
|
|
157
|
-
} from "./chunk-
|
|
165
|
+
} from "./chunk-OYCOLHCR.js";
|
|
158
166
|
import "./chunk-6Y5B5PEX.js";
|
|
159
167
|
import "./chunk-DIB4GX3G.js";
|
|
160
168
|
import {
|
|
@@ -162,63 +170,19 @@ import {
|
|
|
162
170
|
deleteMcpAuthSessionsForUserProvider,
|
|
163
171
|
deleteMcpServerSessionId,
|
|
164
172
|
deleteMcpStoredOAuthCredentials
|
|
165
|
-
} from "./chunk-
|
|
173
|
+
} from "./chunk-FVFJ57RK.js";
|
|
166
174
|
import {
|
|
175
|
+
RetryableDeliveryError,
|
|
176
|
+
createAgentRunner,
|
|
167
177
|
formatProviderLabel,
|
|
168
178
|
postSlackMessage,
|
|
169
179
|
startOAuthFlow
|
|
170
|
-
} from "./chunk-
|
|
171
|
-
import {
|
|
172
|
-
RESOURCE_EVENT_AUTHOR_ID,
|
|
173
|
-
RESOURCE_EVENT_MESSAGE_AUTHOR,
|
|
174
|
-
RESOURCE_EVENT_SYSTEM_ACTOR,
|
|
175
|
-
collectAttachmentGarbage,
|
|
176
|
-
collectEventTaskMatchKeys,
|
|
177
|
-
findMatchingEventTasks,
|
|
178
|
-
getResourceEventCatalog,
|
|
179
|
-
isResourceEventConversationMessage,
|
|
180
|
-
isResourceEventMailboxMetadata,
|
|
181
|
-
isResourceEventSlackMessage,
|
|
182
|
-
listScheduledTasks,
|
|
183
|
-
listScheduledTasksForTeam,
|
|
184
|
-
readScheduledTask,
|
|
185
|
-
renderTaskInput,
|
|
186
|
-
requestAttachmentDeletion,
|
|
187
|
-
resourceEventGuidance,
|
|
188
|
-
saveScheduledTaskInLock,
|
|
189
|
-
scheduledRunId,
|
|
190
|
-
scheduledRunSchema,
|
|
191
|
-
withScheduledTaskLock
|
|
192
|
-
} from "./chunk-VFZAUQ5V.js";
|
|
193
|
-
import {
|
|
194
|
-
parseSlackThreadId
|
|
195
|
-
} from "./chunk-CVBDVIF4.js";
|
|
196
|
-
import {
|
|
197
|
-
RetryableDeliveryError,
|
|
198
|
-
createAgentRunner
|
|
199
|
-
} from "./chunk-6FGN7ZEG.js";
|
|
200
|
-
import {
|
|
201
|
-
CONVERSATION_WORK_STALE_ENQUEUE_MS,
|
|
202
|
-
appendAndEnqueueInboundMessage,
|
|
203
|
-
clearExpiredConversationLease,
|
|
204
|
-
ensureConversationWake,
|
|
205
|
-
getConversation,
|
|
206
|
-
getConversationWorkState,
|
|
207
|
-
hasRunnableConversationWork,
|
|
208
|
-
hasRunnableConversationWork2,
|
|
209
|
-
isInvalidConversationRecordError,
|
|
210
|
-
listActiveConversationIds,
|
|
211
|
-
removeActiveConversation,
|
|
212
|
-
requestConversationWork,
|
|
213
|
-
stopConversationWork
|
|
214
|
-
} from "./chunk-MQDIIFZM.js";
|
|
180
|
+
} from "./chunk-GWCFXTB6.js";
|
|
215
181
|
import {
|
|
216
182
|
ConversationTurnBoundaryError,
|
|
217
183
|
CooperativeTurnYieldError,
|
|
218
184
|
TurnInputCommitLostError,
|
|
219
185
|
TurnInputDeferredError,
|
|
220
|
-
buildDeterministicAssistantMessageId,
|
|
221
|
-
buildDeterministicTurnId,
|
|
222
186
|
clearPendingAuth,
|
|
223
187
|
getAssistantReplyText,
|
|
224
188
|
getConversationTurnBoundaryError,
|
|
@@ -229,7 +193,7 @@ import {
|
|
|
229
193
|
markTurnCompleted,
|
|
230
194
|
markTurnFailed,
|
|
231
195
|
startActiveTurn
|
|
232
|
-
} from "./chunk-
|
|
196
|
+
} from "./chunk-67MMSYSE.js";
|
|
233
197
|
import {
|
|
234
198
|
abandonTurnRecord,
|
|
235
199
|
appendThreadContextMessages,
|
|
@@ -265,22 +229,63 @@ import {
|
|
|
265
229
|
trimTrailingAssistantMessages,
|
|
266
230
|
turnHasReply,
|
|
267
231
|
upsertConversationMessage
|
|
268
|
-
} from "./chunk-
|
|
232
|
+
} from "./chunk-BGOLRC36.js";
|
|
269
233
|
import {
|
|
270
234
|
getExperimentalFeatures,
|
|
271
235
|
isExperimentalFeatureEnabled,
|
|
272
236
|
setExperimentalFeatures
|
|
273
237
|
} from "./chunk-2LYHWMR4.js";
|
|
238
|
+
import {
|
|
239
|
+
collectAttachmentGarbage,
|
|
240
|
+
collectEventTaskMatchKeys,
|
|
241
|
+
findMatchingEventTasks,
|
|
242
|
+
getResourceEventCatalog,
|
|
243
|
+
listScheduledTasks,
|
|
244
|
+
listScheduledTasksForTeam,
|
|
245
|
+
readScheduledTask,
|
|
246
|
+
requestAttachmentDeletion,
|
|
247
|
+
resourceEventGuidance,
|
|
248
|
+
saveScheduledTaskInLock,
|
|
249
|
+
scheduledRunId,
|
|
250
|
+
scheduledRunSchema,
|
|
251
|
+
withScheduledTaskLock
|
|
252
|
+
} from "./chunk-62DRKZQU.js";
|
|
253
|
+
import {
|
|
254
|
+
parseSlackThreadId
|
|
255
|
+
} from "./chunk-BUJU6C2J.js";
|
|
256
|
+
import {
|
|
257
|
+
CONVERSATION_WORK_STALE_ENQUEUE_MS,
|
|
258
|
+
appendAndEnqueueInboundMessage,
|
|
259
|
+
clearExpiredConversationLease,
|
|
260
|
+
ensureConversationWake,
|
|
261
|
+
getConversation,
|
|
262
|
+
getConversationWorkState,
|
|
263
|
+
hasRunnableConversationWork,
|
|
264
|
+
hasRunnableConversationWork2,
|
|
265
|
+
isInvalidConversationRecordError,
|
|
266
|
+
listActiveConversationIds,
|
|
267
|
+
removeActiveConversation,
|
|
268
|
+
requestConversationWork,
|
|
269
|
+
stopConversationWork
|
|
270
|
+
} from "./chunk-YFU4DGZY.js";
|
|
271
|
+
import {
|
|
272
|
+
buildDeterministicAssistantMessageId,
|
|
273
|
+
buildDeterministicTurnId
|
|
274
|
+
} from "./chunk-DA2KGZZI.js";
|
|
275
|
+
import "./chunk-YKIAUKYH.js";
|
|
274
276
|
import {
|
|
275
277
|
getSandboxResourceConfig,
|
|
276
278
|
setSandboxResourceConfig
|
|
277
|
-
} from "./chunk-
|
|
279
|
+
} from "./chunk-2MKHYSYL.js";
|
|
278
280
|
import "./chunk-PDO5BLNM.js";
|
|
279
281
|
import "./chunk-UIE3R5XU.js";
|
|
280
282
|
import {
|
|
281
283
|
WORKSPACE_SNAPSHOT_JOB_QUEUE_TOPIC,
|
|
282
284
|
verifyWorkspaceSnapshotJobMessage
|
|
283
285
|
} from "./chunk-X6GDDWQH.js";
|
|
286
|
+
import {
|
|
287
|
+
getTurnRequestDeadline
|
|
288
|
+
} from "./chunk-7UJ6IJCK.js";
|
|
284
289
|
import {
|
|
285
290
|
getVercelConversationWorkQueue,
|
|
286
291
|
resolveConversationWorkQueueTopic,
|
|
@@ -291,9 +296,6 @@ import {
|
|
|
291
296
|
isConversationQueueMessageRejectedError
|
|
292
297
|
} from "./chunk-JAL3CH4G.js";
|
|
293
298
|
import "./chunk-7H2VZTWN.js";
|
|
294
|
-
import {
|
|
295
|
-
getTurnRequestDeadline
|
|
296
|
-
} from "./chunk-WGZJ5SU4.js";
|
|
297
299
|
import {
|
|
298
300
|
SlackActionError,
|
|
299
301
|
bindEventTaskCredentialSubject,
|
|
@@ -319,7 +321,7 @@ import {
|
|
|
319
321
|
verifyEventTaskCredentialSubject,
|
|
320
322
|
verifyScheduledTaskCredentialSubject,
|
|
321
323
|
verifySlackDirectCredentialSubject
|
|
322
|
-
} from "./chunk-
|
|
324
|
+
} from "./chunk-2MRF22J4.js";
|
|
323
325
|
import "./chunk-3Y47VMHV.js";
|
|
324
326
|
import {
|
|
325
327
|
createSlackDestination,
|
|
@@ -331,7 +333,7 @@ import {
|
|
|
331
333
|
requireSlackDestination,
|
|
332
334
|
withConversationEventLock,
|
|
333
335
|
withConversationMutationLock
|
|
334
|
-
} from "./chunk-
|
|
336
|
+
} from "./chunk-OKAHLUSU.js";
|
|
335
337
|
import {
|
|
336
338
|
juniorAgentBindings,
|
|
337
339
|
juniorAgentInvocations,
|
|
@@ -339,15 +341,14 @@ import {
|
|
|
339
341
|
juniorConversations,
|
|
340
342
|
juniorSchedulerRuns,
|
|
341
343
|
juniorSchedulerTasks
|
|
342
|
-
} from "./chunk-
|
|
343
|
-
import "./chunk-
|
|
344
|
+
} from "./chunk-ZFCO2TMB.js";
|
|
345
|
+
import "./chunk-HI5KXE3C.js";
|
|
344
346
|
import {
|
|
345
347
|
acquireActiveLock,
|
|
346
348
|
getStateAdapter,
|
|
347
349
|
withActiveLock
|
|
348
|
-
} from "./chunk-
|
|
350
|
+
} from "./chunk-6BXUSF7J.js";
|
|
349
351
|
import {
|
|
350
|
-
contextProvenance,
|
|
351
352
|
instructionProvenanceFor
|
|
352
353
|
} from "./chunk-GFBR4S3Q.js";
|
|
353
354
|
import {
|
|
@@ -368,17 +369,17 @@ import {
|
|
|
368
369
|
isProviderRetryError,
|
|
369
370
|
setProfiles,
|
|
370
371
|
setSlackReactionConfig
|
|
371
|
-
} from "./chunk-
|
|
372
|
+
} from "./chunk-VWNIDTFR.js";
|
|
372
373
|
import {
|
|
373
374
|
defaultModelId,
|
|
374
375
|
modelIdForProfile
|
|
375
376
|
} from "./chunk-D4YV5TDV.js";
|
|
376
|
-
import "./chunk-
|
|
377
|
-
import "./chunk-
|
|
377
|
+
import "./chunk-DVX6U6GI.js";
|
|
378
|
+
import "./chunk-REVH4BZU.js";
|
|
378
379
|
import {
|
|
379
380
|
pluginCatalogRuntime
|
|
380
|
-
} from "./chunk-
|
|
381
|
-
import "./chunk-
|
|
381
|
+
} from "./chunk-4PKEJK5B.js";
|
|
382
|
+
import "./chunk-663DQH5W.js";
|
|
382
383
|
import {
|
|
383
384
|
credentialContextForActor
|
|
384
385
|
} from "./chunk-CEMMLV5L.js";
|
|
@@ -414,13 +415,13 @@ import {
|
|
|
414
415
|
withContext,
|
|
415
416
|
withLogContext,
|
|
416
417
|
withSpan
|
|
417
|
-
} from "./chunk-
|
|
418
|
+
} from "./chunk-Y4WL4OYD.js";
|
|
418
419
|
import {
|
|
419
420
|
continueTrace
|
|
420
421
|
} from "./chunk-PEQXYSSE.js";
|
|
421
422
|
import {
|
|
422
423
|
JUNIOR_VERSION
|
|
423
|
-
} from "./chunk-
|
|
424
|
+
} from "./chunk-JV7U4665.js";
|
|
424
425
|
|
|
425
426
|
// src/app.ts
|
|
426
427
|
import { createRequire } from "module";
|
|
@@ -569,7 +570,6 @@ function buildDispatchRoutingContext(dispatch2) {
|
|
|
569
570
|
dispatch2.actor,
|
|
570
571
|
dispatch2.credentialSubject
|
|
571
572
|
),
|
|
572
|
-
destinationVisibility: dispatch2.destinationVisibility,
|
|
573
573
|
dispatch: {
|
|
574
574
|
actor: dispatch2.actor,
|
|
575
575
|
id: dispatch2.id,
|
|
@@ -689,12 +689,6 @@ async function resolveAgentDispatchId(context) {
|
|
|
689
689
|
const dispatch2 = await getDispatchRecord(durableDispatchId);
|
|
690
690
|
return dispatch2 && !isTerminalDispatchStatus(dispatch2.status) ? durableDispatchId : void 0;
|
|
691
691
|
}
|
|
692
|
-
function createAgentDispatchWorkRouter(options) {
|
|
693
|
-
return async (context) => {
|
|
694
|
-
const dispatchId = await resolveAgentDispatchId(context);
|
|
695
|
-
return dispatchId ? await options.dispatchWorker(context, dispatchId) : await options.fallbackWorker(context);
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
692
|
async function readDispatchTurnResult(dispatch2) {
|
|
699
693
|
const conversationId = getDispatchConversationId(dispatch2);
|
|
700
694
|
const turnId = getDispatchTurnId(dispatch2.id);
|
|
@@ -948,7 +942,7 @@ function dispatchOptionsErrorMessage(issues) {
|
|
|
948
942
|
return "Dispatch source must not include unknown fields";
|
|
949
943
|
}
|
|
950
944
|
if (hasIssueAtPath(issues, ["source"])) {
|
|
951
|
-
return "Dispatch
|
|
945
|
+
return "Dispatch Source kind is required";
|
|
952
946
|
}
|
|
953
947
|
if (hasIssueUnderPath(issues, ["source", "teamId"])) {
|
|
954
948
|
return "Dispatch source teamId must be a Slack team id";
|
|
@@ -2742,13 +2736,13 @@ async function GET6(request) {
|
|
|
2742
2736
|
// src/chat/ingress/slack-webhook.ts
|
|
2743
2737
|
import {
|
|
2744
2738
|
ChannelImpl,
|
|
2745
|
-
ThreadImpl as
|
|
2739
|
+
ThreadImpl as ThreadImpl2
|
|
2746
2740
|
} from "chat";
|
|
2747
2741
|
|
|
2748
2742
|
// src/chat/task-execution/slack-work.ts
|
|
2749
2743
|
import {
|
|
2750
|
-
Message as
|
|
2751
|
-
ThreadImpl
|
|
2744
|
+
Message as Message2,
|
|
2745
|
+
ThreadImpl
|
|
2752
2746
|
} from "chat";
|
|
2753
2747
|
import { z as z3 } from "zod";
|
|
2754
2748
|
|
|
@@ -2938,85 +2932,6 @@ async function ensureSlackMessageActorIdentity(message, teamId, lookupSlackUser2
|
|
|
2938
2932
|
return actor;
|
|
2939
2933
|
}
|
|
2940
2934
|
|
|
2941
|
-
// src/chat/task-execution/slack-resource-event.ts
|
|
2942
|
-
import { Message as Message2, ThreadImpl } from "chat";
|
|
2943
|
-
async function resolveSlackResourceEventThread(args) {
|
|
2944
|
-
const routing = await resolveConversationRouting({
|
|
2945
|
-
conversationId: args.conversationId,
|
|
2946
|
-
conversationStore: args.conversationStore
|
|
2947
|
-
});
|
|
2948
|
-
const destination = requireSlackDestination(
|
|
2949
|
-
routing?.destination ?? args.destination,
|
|
2950
|
-
"Slack resource-event turn"
|
|
2951
|
-
);
|
|
2952
|
-
const threadTs = routing?.source?.platform === "slack" ? routing.source.threadTs?.trim() : void 0;
|
|
2953
|
-
if (!threadTs) {
|
|
2954
|
-
return void 0;
|
|
2955
|
-
}
|
|
2956
|
-
return { destination, threadTs };
|
|
2957
|
-
}
|
|
2958
|
-
function isPlainResourceEventRecord(record) {
|
|
2959
|
-
return record.source === "resource_event" && isResourceEventMailboxMetadata(record.input.metadata) && !hasSlackConversationMetadata(record.input.metadata);
|
|
2960
|
-
}
|
|
2961
|
-
function hasSlackConversationMetadata(value) {
|
|
2962
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2963
|
-
return false;
|
|
2964
|
-
}
|
|
2965
|
-
const record = value;
|
|
2966
|
-
return record.platform === "slack" && typeof record.thread === "object" && record.thread !== null && typeof record.message === "object" && record.message !== null;
|
|
2967
|
-
}
|
|
2968
|
-
function buildResourceEventSlackMessage(args) {
|
|
2969
|
-
if (!isResourceEventMailboxMetadata(args.record.input.metadata)) {
|
|
2970
|
-
throw new Error(
|
|
2971
|
-
"Resource-event Slack turn requires resource-event metadata"
|
|
2972
|
-
);
|
|
2973
|
-
}
|
|
2974
|
-
const event = args.record.input.metadata.resourceEvent;
|
|
2975
|
-
const messageId = `resource-event-${event.subscriptionId}-${event.eventKey}`;
|
|
2976
|
-
const threadId = `slack:${args.channelId}:${args.threadTs}`;
|
|
2977
|
-
return new Message2({
|
|
2978
|
-
id: messageId,
|
|
2979
|
-
threadId,
|
|
2980
|
-
text: args.record.input.text,
|
|
2981
|
-
author: {
|
|
2982
|
-
...RESOURCE_EVENT_MESSAGE_AUTHOR,
|
|
2983
|
-
isMe: false
|
|
2984
|
-
},
|
|
2985
|
-
isMention: false,
|
|
2986
|
-
attachments: [],
|
|
2987
|
-
metadata: {
|
|
2988
|
-
dateSent: new Date(args.record.createdAtMs),
|
|
2989
|
-
edited: false
|
|
2990
|
-
},
|
|
2991
|
-
formatted: { type: "root", children: [] },
|
|
2992
|
-
raw: {
|
|
2993
|
-
channel: args.channelId,
|
|
2994
|
-
event_type: "resource_event",
|
|
2995
|
-
resource_event_type: event.eventType,
|
|
2996
|
-
thread_ts: args.threadTs,
|
|
2997
|
-
type: "message",
|
|
2998
|
-
user: RESOURCE_EVENT_AUTHOR_ID
|
|
2999
|
-
}
|
|
3000
|
-
});
|
|
3001
|
-
}
|
|
3002
|
-
function buildResourceEventSlackThread(args) {
|
|
3003
|
-
const threadId = normalizeIncomingSlackThreadId(
|
|
3004
|
-
`slack:${args.channelId}:${args.threadTs}`,
|
|
3005
|
-
args.message
|
|
3006
|
-
);
|
|
3007
|
-
const message = withNormalizedThreadId(args.message, threadId);
|
|
3008
|
-
return new ThreadImpl({
|
|
3009
|
-
adapter: args.adapter,
|
|
3010
|
-
stateAdapter: args.state,
|
|
3011
|
-
id: threadId,
|
|
3012
|
-
channelId: args.channelId,
|
|
3013
|
-
currentMessage: message,
|
|
3014
|
-
initialMessage: message,
|
|
3015
|
-
isDM: args.channelId.startsWith("D"),
|
|
3016
|
-
isSubscribedContext: true
|
|
3017
|
-
});
|
|
3018
|
-
}
|
|
3019
|
-
|
|
3020
2935
|
// src/chat/slack/message-control.ts
|
|
3021
2936
|
var LEADING_MENTION_BEFORE_STEERING_RE = /^(\s*(?:<@[^>]+>|@[A-Za-z0-9._-]+\b)[\s,:-]*)!!\s*/;
|
|
3022
2937
|
function stripLeadingSteeringOverride(text) {
|
|
@@ -3251,9 +3166,6 @@ function compareInboundMessages(left, right) {
|
|
|
3251
3166
|
}
|
|
3252
3167
|
function routeForRecords(records) {
|
|
3253
3168
|
return records.some((record) => {
|
|
3254
|
-
if (isPlainResourceEventRecord(record)) {
|
|
3255
|
-
return false;
|
|
3256
|
-
}
|
|
3257
3169
|
const metadata = parseSlackMetadata(record.input.metadata);
|
|
3258
3170
|
if (!metadata) {
|
|
3259
3171
|
throw new Error("Conversation mailbox record is not Slack metadata");
|
|
@@ -3262,23 +3174,11 @@ function routeForRecords(records) {
|
|
|
3262
3174
|
}) ? "mention" : "subscribed";
|
|
3263
3175
|
}
|
|
3264
3176
|
function restoreMessage(args) {
|
|
3265
|
-
if (isPlainResourceEventRecord(args.record)) {
|
|
3266
|
-
if (!args.threadTs) {
|
|
3267
|
-
throw new Error(
|
|
3268
|
-
"Resource-event Slack turn requires a thread timestamp"
|
|
3269
|
-
);
|
|
3270
|
-
}
|
|
3271
|
-
return buildResourceEventSlackMessage({
|
|
3272
|
-
channelId: args.channelId,
|
|
3273
|
-
record: args.record,
|
|
3274
|
-
threadTs: args.threadTs
|
|
3275
|
-
});
|
|
3276
|
-
}
|
|
3277
3177
|
const metadata = parseSlackMetadata(args.record.input.metadata);
|
|
3278
3178
|
if (!metadata) {
|
|
3279
3179
|
throw new Error("Conversation mailbox record is not a Slack message");
|
|
3280
3180
|
}
|
|
3281
|
-
const message =
|
|
3181
|
+
const message = Message2.fromJSON(metadata.message);
|
|
3282
3182
|
message.attachments = message.attachments.map(
|
|
3283
3183
|
(attachment) => args.adapter.rehydrateAttachment(attachment)
|
|
3284
3184
|
);
|
|
@@ -3288,9 +3188,6 @@ function restoreMessage(args) {
|
|
|
3288
3188
|
async function bindSlackActorIdentities(args) {
|
|
3289
3189
|
const byAuthorId = /* @__PURE__ */ new Map();
|
|
3290
3190
|
for (const message of args.messages) {
|
|
3291
|
-
if (isResourceEventSlackMessage(message)) {
|
|
3292
|
-
continue;
|
|
3293
|
-
}
|
|
3294
3191
|
const authorId = requireSlackAuthorId(message);
|
|
3295
3192
|
byAuthorId.set(authorId, [...byAuthorId.get(authorId) ?? [], message]);
|
|
3296
3193
|
}
|
|
@@ -3315,7 +3212,7 @@ function restoreThread(args) {
|
|
|
3315
3212
|
args.message
|
|
3316
3213
|
);
|
|
3317
3214
|
const message = withNormalizedThreadId(args.message, threadId);
|
|
3318
|
-
return new
|
|
3215
|
+
return new ThreadImpl({
|
|
3319
3216
|
adapter: args.adapter,
|
|
3320
3217
|
stateAdapter: args.state,
|
|
3321
3218
|
id: threadId,
|
|
@@ -3380,10 +3277,9 @@ function createSlackConversationWorker(options) {
|
|
|
3380
3277
|
if (!latestRecord) {
|
|
3381
3278
|
return { status: "completed" };
|
|
3382
3279
|
}
|
|
3383
|
-
const
|
|
3384
|
-
const
|
|
3385
|
-
|
|
3386
|
-
if (!isPlainResourceEventRecord(latestRecord) && !latestMetadata) {
|
|
3280
|
+
const publishExternally = latestRecord.publishExternally ?? context.publishExternally;
|
|
3281
|
+
const latestMetadata = parseSlackMetadata(latestRecord.input.metadata);
|
|
3282
|
+
if (!latestMetadata) {
|
|
3387
3283
|
throw new Error(
|
|
3388
3284
|
"Latest conversation mailbox record is not Slack metadata"
|
|
3389
3285
|
);
|
|
@@ -3391,34 +3287,19 @@ function createSlackConversationWorker(options) {
|
|
|
3391
3287
|
if (!await context.checkIn()) {
|
|
3392
3288
|
return { status: "lost_lease" };
|
|
3393
3289
|
}
|
|
3394
|
-
const resourceEventThread = hasPlainResourceEvent ? await resolveSlackResourceEventThread({
|
|
3395
|
-
conversationId: context.conversationId,
|
|
3396
|
-
conversationStore: options.conversationStore,
|
|
3397
|
-
destination: context.destination
|
|
3398
|
-
}) : void 0;
|
|
3399
|
-
if (hasPlainResourceEvent && !resourceEventThread) {
|
|
3400
|
-
logWarn("conversation.work.resource_event.missing_thread", {
|
|
3401
|
-
"app.inbound.message_count": records.length
|
|
3402
|
-
});
|
|
3403
|
-
await context.attempt.ack();
|
|
3404
|
-
return { status: "completed" };
|
|
3405
|
-
}
|
|
3406
3290
|
const turnResult = await runWithSlackInstallation({
|
|
3407
3291
|
adapter,
|
|
3408
|
-
installation:
|
|
3292
|
+
installation: getInstallation(records),
|
|
3409
3293
|
state,
|
|
3410
3294
|
task: async () => {
|
|
3411
|
-
const destination =
|
|
3295
|
+
const destination = requireSlackDestination(
|
|
3412
3296
|
context.destination,
|
|
3413
3297
|
"Slack conversation work"
|
|
3414
3298
|
);
|
|
3415
|
-
const threadTs = resourceEventThread?.threadTs;
|
|
3416
3299
|
const messages = records.map(
|
|
3417
3300
|
(record) => restoreMessage({
|
|
3418
3301
|
adapter,
|
|
3419
|
-
|
|
3420
|
-
record,
|
|
3421
|
-
...threadTs ? { threadTs } : void 0
|
|
3302
|
+
record
|
|
3422
3303
|
})
|
|
3423
3304
|
);
|
|
3424
3305
|
await bindSlackActorIdentities({
|
|
@@ -3431,13 +3312,7 @@ function createSlackConversationWorker(options) {
|
|
|
3431
3312
|
return;
|
|
3432
3313
|
}
|
|
3433
3314
|
const route = routeForRecords(records);
|
|
3434
|
-
const thread =
|
|
3435
|
-
adapter,
|
|
3436
|
-
channelId: destination.channelId,
|
|
3437
|
-
message: latestMessage,
|
|
3438
|
-
state,
|
|
3439
|
-
threadTs
|
|
3440
|
-
}) : restoreThread({
|
|
3315
|
+
const thread = restoreThread({
|
|
3441
3316
|
adapter,
|
|
3442
3317
|
isSubscribedContext: route === "subscribed",
|
|
3443
3318
|
message: latestMessage,
|
|
@@ -3449,7 +3324,7 @@ function createSlackConversationWorker(options) {
|
|
|
3449
3324
|
skipped,
|
|
3450
3325
|
totalSinceLastHandler: messages.length
|
|
3451
3326
|
};
|
|
3452
|
-
const activeAuthorId =
|
|
3327
|
+
const activeAuthorId = requireSlackAuthorId(latestMessage);
|
|
3453
3328
|
let initialMessagesAcked = false;
|
|
3454
3329
|
const ack = async () => {
|
|
3455
3330
|
if (initialMessagesAcked) {
|
|
@@ -3467,17 +3342,15 @@ function createSlackConversationWorker(options) {
|
|
|
3467
3342
|
const drainSteeringMessages = async (accept) => {
|
|
3468
3343
|
await context.attempt.drain(async (pendingRecords) => {
|
|
3469
3344
|
const candidates = pendingRecords.filter(
|
|
3470
|
-
(record) =>
|
|
3345
|
+
(record) => record.publishExternally === publishExternally
|
|
3471
3346
|
).map((record) => ({
|
|
3472
3347
|
inboundMessageId: record.inboundMessageId,
|
|
3473
3348
|
message: restoreMessage({
|
|
3474
3349
|
adapter,
|
|
3475
|
-
|
|
3476
|
-
record,
|
|
3477
|
-
...threadTs ? { threadTs } : void 0
|
|
3350
|
+
record
|
|
3478
3351
|
})
|
|
3479
3352
|
})).filter(
|
|
3480
|
-
(candidate) => crossActorMidRunMode === "steer" ||
|
|
3353
|
+
(candidate) => crossActorMidRunMode === "steer" || requireSlackAuthorId(candidate.message) === activeAuthorId || hasSteeringOverride(candidate.message.text)
|
|
3481
3354
|
);
|
|
3482
3355
|
return candidates.length > 0 ? await accept(candidates) : [];
|
|
3483
3356
|
});
|
|
@@ -3635,7 +3508,7 @@ function textMentionsBot(text, botUserId) {
|
|
|
3635
3508
|
}
|
|
3636
3509
|
|
|
3637
3510
|
// src/chat/ingress/message-changed.ts
|
|
3638
|
-
import { Message as
|
|
3511
|
+
import { Message as Message3 } from "chat";
|
|
3639
3512
|
function getEditedMentionMessageId(messageTs) {
|
|
3640
3513
|
return `${messageTs}:message_changed_mention`;
|
|
3641
3514
|
}
|
|
@@ -3702,7 +3575,7 @@ function extractMessageChangedMention(body, botUserId, adapter) {
|
|
|
3702
3575
|
...sourceTeam ? { source_team: sourceTeam } : void 0,
|
|
3703
3576
|
...botId ? { bot_id: botId } : void 0
|
|
3704
3577
|
};
|
|
3705
|
-
const message = new
|
|
3578
|
+
const message = new Message3({
|
|
3706
3579
|
id: getEditedMentionMessageId(messageTs),
|
|
3707
3580
|
threadId,
|
|
3708
3581
|
text: newText,
|
|
@@ -3941,7 +3814,7 @@ function normalizeMessageThreadId(message) {
|
|
|
3941
3814
|
}
|
|
3942
3815
|
async function buildThread(args) {
|
|
3943
3816
|
const normalized = normalizeMessageThreadId(args.message);
|
|
3944
|
-
return new
|
|
3817
|
+
return new ThreadImpl2({
|
|
3945
3818
|
adapter: args.adapter,
|
|
3946
3819
|
stateAdapter: args.state,
|
|
3947
3820
|
id: normalized.threadId,
|
|
@@ -5531,8 +5404,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
5531
5404
|
const threadId = getThreadId(thread, message);
|
|
5532
5405
|
const channelId = getChannelId(thread, message);
|
|
5533
5406
|
const runId = getRunId(thread, message);
|
|
5534
|
-
const
|
|
5535
|
-
const actorId = isResourceEventNotification ? void 0 : message.author.userId;
|
|
5407
|
+
const actorId = message.author.userId;
|
|
5536
5408
|
const turnContext = logContext({
|
|
5537
5409
|
threadId,
|
|
5538
5410
|
actorId,
|
|
@@ -5565,7 +5437,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
5565
5437
|
});
|
|
5566
5438
|
const combinedText = combineTurnText(queuedMessages, currentText);
|
|
5567
5439
|
const turnIsExplicitMention = Boolean(message.isMention) || queuedMessages.some((queued) => queued.explicitMention);
|
|
5568
|
-
const preflightDecision =
|
|
5440
|
+
const preflightDecision = getSubscribedReplyPreflightDecision({
|
|
5569
5441
|
botUserName: deps.assistantUserName,
|
|
5570
5442
|
rawText: combinedText.rawText,
|
|
5571
5443
|
text: combinedText.userText,
|
|
@@ -5583,7 +5455,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
5583
5455
|
});
|
|
5584
5456
|
return;
|
|
5585
5457
|
}
|
|
5586
|
-
if (!
|
|
5458
|
+
if (!turnIsExplicitMention && !isExperimentalFeatureEnabled("passive-routing")) {
|
|
5587
5459
|
const decision2 = await deps.decideSubscribedReply({
|
|
5588
5460
|
rawText: combinedText.rawText,
|
|
5589
5461
|
text: combinedText.userText,
|
|
@@ -5621,7 +5493,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
5621
5493
|
thread,
|
|
5622
5494
|
preparedState
|
|
5623
5495
|
});
|
|
5624
|
-
const decision =
|
|
5496
|
+
const decision = await deps.decideSubscribedReply({
|
|
5625
5497
|
rawText: combinedText.rawText,
|
|
5626
5498
|
text: combinedText.userText,
|
|
5627
5499
|
conversationContext: deps.getPreparedConversationContext(preparedState),
|
|
@@ -6431,6 +6303,21 @@ async function maybeApplyProviderDefaultConfigRequest(args) {
|
|
|
6431
6303
|
};
|
|
6432
6304
|
}
|
|
6433
6305
|
|
|
6306
|
+
// src/chat/conversations/destination-visibility.ts
|
|
6307
|
+
async function resolveDestinationVisibility(args) {
|
|
6308
|
+
if (args.visibility) {
|
|
6309
|
+
return args.visibility;
|
|
6310
|
+
}
|
|
6311
|
+
if (args.destination.platform === "local") {
|
|
6312
|
+
return "private";
|
|
6313
|
+
}
|
|
6314
|
+
return await getConversationStore().getDestinationVisibility({
|
|
6315
|
+
provider: "slack",
|
|
6316
|
+
providerDestinationId: args.destination.channelId,
|
|
6317
|
+
providerTenantId: args.destination.teamId
|
|
6318
|
+
});
|
|
6319
|
+
}
|
|
6320
|
+
|
|
6434
6321
|
// src/chat/providers/slack/input.ts
|
|
6435
6322
|
function steeringMessageKey(message) {
|
|
6436
6323
|
if (message.role !== "user") {
|
|
@@ -6488,9 +6375,6 @@ function inboundMessageActor(queued) {
|
|
|
6488
6375
|
};
|
|
6489
6376
|
}
|
|
6490
6377
|
function inboundMessageProvenance(queued, teamId) {
|
|
6491
|
-
if (isResourceEventSlackMessage(queued.message)) {
|
|
6492
|
-
return contextProvenance;
|
|
6493
|
-
}
|
|
6494
6378
|
const identity = getMessageActorIdentity(queued.message);
|
|
6495
6379
|
const author = identity && "platform" in identity ? identity : createActor(
|
|
6496
6380
|
{ userId: parseActorUserId(queued.message.author.userId) },
|
|
@@ -6650,6 +6534,15 @@ function createSlackTurn(deps) {
|
|
|
6650
6534
|
modelId: defaultModelId(botConfig)
|
|
6651
6535
|
},
|
|
6652
6536
|
async () => {
|
|
6537
|
+
await getConversationStore().recordActivity({
|
|
6538
|
+
activityAtMs: message.metadata.dateSent.getTime(),
|
|
6539
|
+
channelName,
|
|
6540
|
+
conversationId,
|
|
6541
|
+
destination,
|
|
6542
|
+
sessionSource: source,
|
|
6543
|
+
source: "slack",
|
|
6544
|
+
visibility: destinationVisibility
|
|
6545
|
+
});
|
|
6653
6546
|
const content = parseContent(message);
|
|
6654
6547
|
const strippedUserText = stripLeadingBotMention(
|
|
6655
6548
|
stripLeadingSteeringOverride(content.topLevelText),
|
|
@@ -6663,7 +6556,7 @@ function createSlackTurn(deps) {
|
|
|
6663
6556
|
userText: replaceTopLevelText(content, strippedUserText)
|
|
6664
6557
|
};
|
|
6665
6558
|
await Promise.all(
|
|
6666
|
-
(options.queuedMessages ?? []).
|
|
6559
|
+
(options.queuedMessages ?? []).map(
|
|
6667
6560
|
(queued) => ensureSlackMessageActorIdentity(
|
|
6668
6561
|
queued.message,
|
|
6669
6562
|
teamId,
|
|
@@ -6677,9 +6570,6 @@ function createSlackTurn(deps) {
|
|
|
6677
6570
|
if (options.execution) {
|
|
6678
6571
|
executionActor = options.execution.dispatch.actor;
|
|
6679
6572
|
credentialContext = options.execution.credentialContext;
|
|
6680
|
-
} else if (isResourceEventSlackMessage(message)) {
|
|
6681
|
-
executionActor = RESOURCE_EVENT_SYSTEM_ACTOR;
|
|
6682
|
-
credentialContext = credentialContextForActor(executionActor);
|
|
6683
6573
|
} else {
|
|
6684
6574
|
executionActor = await ensureSlackMessageActorIdentity(
|
|
6685
6575
|
message,
|
|
@@ -6769,7 +6659,7 @@ function createSlackTurn(deps) {
|
|
|
6769
6659
|
omittedImageAttachmentCount: !isVisionEnabled() && hasPotentialImageAttachment(attachments) ? countPotentialImageAttachments(attachments) : 0,
|
|
6770
6660
|
attachments: await deps.resolveUserAttachments(attachments, {
|
|
6771
6661
|
threadId,
|
|
6772
|
-
actorId:
|
|
6662
|
+
actorId: queued.message.author.userId,
|
|
6773
6663
|
channelId,
|
|
6774
6664
|
runId,
|
|
6775
6665
|
conversation: preparedState.conversation,
|
|
@@ -6859,8 +6749,7 @@ function createSlackTurn(deps) {
|
|
|
6859
6749
|
await abandonTurnRecord({
|
|
6860
6750
|
conversationId,
|
|
6861
6751
|
turnId: activeTurnId,
|
|
6862
|
-
|
|
6863
|
-
errorMessage: "Auth-parked session superseded by a new user message"
|
|
6752
|
+
errorMessage: "Auth-paused Turn superseded by new input"
|
|
6864
6753
|
});
|
|
6865
6754
|
markTurnClosed({
|
|
6866
6755
|
conversation: preparedState.conversation,
|
|
@@ -7277,16 +7166,15 @@ function createSlackTurn(deps) {
|
|
|
7277
7166
|
},
|
|
7278
7167
|
history: piMessages,
|
|
7279
7168
|
credentialContext,
|
|
7280
|
-
// Always set the execution
|
|
7281
|
-
// carry the system principal; interactive turns carry the Slack user.
|
|
7169
|
+
// Always set the execution Actor when known.
|
|
7282
7170
|
actor: executionActor,
|
|
7283
7171
|
slackConversation,
|
|
7284
|
-
source
|
|
7172
|
+
source,
|
|
7173
|
+
...location ? { location } : void 0,
|
|
7285
7174
|
destination,
|
|
7286
7175
|
publishExternally: shouldPublishExternally2(
|
|
7287
7176
|
options.publishExternally
|
|
7288
7177
|
),
|
|
7289
|
-
...destinationVisibility ? { destinationVisibility } : void 0,
|
|
7290
7178
|
surface: options.execution?.surface ?? "slack",
|
|
7291
7179
|
dispatch: options.execution?.dispatch,
|
|
7292
7180
|
toolChannelId,
|
|
@@ -7313,10 +7201,7 @@ function createSlackTurn(deps) {
|
|
|
7313
7201
|
});
|
|
7314
7202
|
}
|
|
7315
7203
|
},
|
|
7316
|
-
delivery:
|
|
7317
|
-
...location && shouldPublishExternally2(options.publishExternally) ? { location } : void 0,
|
|
7318
|
-
send: deliverAssistantMessage
|
|
7319
|
-
},
|
|
7204
|
+
delivery: deliverAssistantMessage,
|
|
7320
7205
|
durability: {
|
|
7321
7206
|
onInputCommitted: options.ack,
|
|
7322
7207
|
drainSteeringMessages,
|
|
@@ -7738,11 +7623,6 @@ async function persistConversationVisionCache(conversationId, vision) {
|
|
|
7738
7623
|
|
|
7739
7624
|
// src/chat/runtime/conversation-message.ts
|
|
7740
7625
|
var NON_TEXT_MESSAGE_TEXT = "[non-text message]";
|
|
7741
|
-
function resourceEventType(entry) {
|
|
7742
|
-
if (!entry.raw || typeof entry.raw !== "object") return void 0;
|
|
7743
|
-
const raw = entry.raw;
|
|
7744
|
-
return raw.event_type === "resource_event" && typeof raw.resource_event_type === "string" ? raw.resource_event_type : void 0;
|
|
7745
|
-
}
|
|
7746
7626
|
function resolveMessageText(args) {
|
|
7747
7627
|
const text = normalizeConversationText(args.text);
|
|
7748
7628
|
return text || NON_TEXT_MESSAGE_TEXT;
|
|
@@ -7767,7 +7647,6 @@ function toConversationMessage(args) {
|
|
|
7767
7647
|
},
|
|
7768
7648
|
meta: {
|
|
7769
7649
|
attachmentCount: args.entry.attachments.length,
|
|
7770
|
-
eventType: resourceEventType(args.entry),
|
|
7771
7650
|
explicitMention: args.explicitMention,
|
|
7772
7651
|
imageAttachmentCount: imageAttachmentCount > 0 ? imageAttachmentCount : void 0,
|
|
7773
7652
|
imagesHydrated: !messageHasPotentialImageAttachment,
|
|
@@ -7937,14 +7816,14 @@ function createPrepareTurnState(deps) {
|
|
|
7937
7816
|
}
|
|
7938
7817
|
|
|
7939
7818
|
// src/chat/slack/dispatch-turn.ts
|
|
7940
|
-
import { Message as
|
|
7819
|
+
import { Message as Message4, ThreadImpl as ThreadImpl3 } from "chat";
|
|
7941
7820
|
function createSlackDispatchTurnRunner(options) {
|
|
7942
7821
|
return async function runSlackDispatchTurn(dispatch2, hooks) {
|
|
7943
7822
|
const state = getStateAdapter();
|
|
7944
7823
|
await state.connect();
|
|
7945
7824
|
const conversationId = getDispatchConversationId(dispatch2);
|
|
7946
7825
|
const adapter = options.getSlackAdapter();
|
|
7947
|
-
const message = new
|
|
7826
|
+
const message = new Message4({
|
|
7948
7827
|
id: getDispatchInputMessageId(dispatch2.id),
|
|
7949
7828
|
threadId: conversationId,
|
|
7950
7829
|
text: dispatch2.input,
|
|
@@ -7967,7 +7846,7 @@ function createSlackDispatchTurnRunner(options) {
|
|
|
7967
7846
|
}
|
|
7968
7847
|
});
|
|
7969
7848
|
message.isMention = true;
|
|
7970
|
-
const thread = new
|
|
7849
|
+
const thread = new ThreadImpl3({
|
|
7971
7850
|
adapter,
|
|
7972
7851
|
stateAdapter: state,
|
|
7973
7852
|
id: conversationId,
|
|
@@ -8307,10 +8186,10 @@ async function resolveSlackResumeUserActor(args) {
|
|
|
8307
8186
|
async function resolveResumeExecutionIdentity(args) {
|
|
8308
8187
|
const routing = args.routingContext;
|
|
8309
8188
|
if (routing?.credentialContext) {
|
|
8310
|
-
const actor2 = routing.dispatch?.actor ?? routing.actor ?? (!("type" in routing.credentialContext.actor) ? routing.credentialContext.actor : void 0);
|
|
8189
|
+
const actor2 = args.actor ?? routing.dispatch?.actor ?? routing.actor ?? (!("type" in routing.credentialContext.actor) ? routing.credentialContext.actor : void 0);
|
|
8311
8190
|
return actor2 ? { actor: actor2, credentialContext: routing.credentialContext } : void 0;
|
|
8312
8191
|
}
|
|
8313
|
-
let actor = routing?.actor;
|
|
8192
|
+
let actor = args.actor ?? routing?.actor;
|
|
8314
8193
|
if (!actor && isResourceEventConversationMessage(args.userMessage)) {
|
|
8315
8194
|
actor = RESOURCE_EVENT_SYSTEM_ACTOR;
|
|
8316
8195
|
}
|
|
@@ -8400,6 +8279,7 @@ async function runPausedTurnInContext(payload, options, runOptions) {
|
|
|
8400
8279
|
return false;
|
|
8401
8280
|
}
|
|
8402
8281
|
const activeTurn = turn;
|
|
8282
|
+
const { dispatch: dispatch2, surface } = options.routingContext ?? {};
|
|
8403
8283
|
const currentState = await getPersistedThreadState(
|
|
8404
8284
|
payload.conversationId
|
|
8405
8285
|
);
|
|
@@ -8408,7 +8288,7 @@ async function runPausedTurnInContext(payload, options, runOptions) {
|
|
|
8408
8288
|
conversation,
|
|
8409
8289
|
conversationId: payload.conversationId
|
|
8410
8290
|
});
|
|
8411
|
-
const dispatchId = activeTurn.dispatchId ??
|
|
8291
|
+
const dispatchId = activeTurn.dispatchId ?? dispatch2?.id;
|
|
8412
8292
|
const dispatchUserMessage = dispatchId ? conversation.messages.find(
|
|
8413
8293
|
(message) => message.role === "user" && options.inputMessageIds?.includes(message.id)
|
|
8414
8294
|
) : void 0;
|
|
@@ -8425,6 +8305,7 @@ async function runPausedTurnInContext(payload, options, runOptions) {
|
|
|
8425
8305
|
return false;
|
|
8426
8306
|
}
|
|
8427
8307
|
const identity = await resolveResumeExecutionIdentity({
|
|
8308
|
+
actor: activeTurn.actor,
|
|
8428
8309
|
conversationId: payload.conversationId,
|
|
8429
8310
|
routingContext: options.routingContext,
|
|
8430
8311
|
teamId: destination.teamId,
|
|
@@ -8451,21 +8332,19 @@ async function runPausedTurnInContext(payload, options, runOptions) {
|
|
|
8451
8332
|
const routingDestination = routing.destination;
|
|
8452
8333
|
const turnMessages = activeTurn.turnStartMessageIndex === void 0 ? [] : activeTurn.piMessages.slice(activeTurn.turnStartMessageIndex);
|
|
8453
8334
|
const recordDispatchOutcome = async (dispatchOutcome) => {
|
|
8454
|
-
|
|
8455
|
-
if (!dispatchId2) {
|
|
8335
|
+
if (!dispatch2) {
|
|
8456
8336
|
return;
|
|
8457
8337
|
}
|
|
8458
8338
|
await recordTurnSummary({
|
|
8459
8339
|
conversationId: payload.conversationId,
|
|
8460
8340
|
destination: routingDestination,
|
|
8461
|
-
|
|
8462
|
-
dispatchId: dispatchId2,
|
|
8341
|
+
dispatchId: dispatch2.id,
|
|
8463
8342
|
dispatchOutcome,
|
|
8464
8343
|
turnId: payload.turnId,
|
|
8465
8344
|
sliceId: activeTurn.sliceId,
|
|
8466
8345
|
source,
|
|
8467
8346
|
state: "failed",
|
|
8468
|
-
surface:
|
|
8347
|
+
surface: surface ?? "slack"
|
|
8469
8348
|
});
|
|
8470
8349
|
};
|
|
8471
8350
|
return {
|
|
@@ -8481,21 +8360,24 @@ async function runPausedTurnInContext(payload, options, runOptions) {
|
|
|
8481
8360
|
...getTurnUserReplyAttachmentContext(userMessage),
|
|
8482
8361
|
text: userMessage.text
|
|
8483
8362
|
},
|
|
8484
|
-
//
|
|
8485
|
-
//
|
|
8486
|
-
//
|
|
8487
|
-
// projection so queued steering remains visible.
|
|
8363
|
+
// A dispatch reads only history saved for this Turn. Other input
|
|
8364
|
+
// must not become part of a system Turn. Other Turns read
|
|
8365
|
+
// Conversation history. This keeps queued steering visible.
|
|
8488
8366
|
history: dispatchId ? activeTurn.piMessages : await loadProjection({
|
|
8489
8367
|
conversationId: payload.conversationId
|
|
8490
8368
|
}),
|
|
8491
|
-
...options.routingContext,
|
|
8492
|
-
credentialContext,
|
|
8493
8369
|
actor,
|
|
8370
|
+
credentialContext,
|
|
8494
8371
|
destination: routingDestination,
|
|
8372
|
+
...dispatch2 ? { dispatch: dispatch2 } : void 0,
|
|
8373
|
+
...routing.location ? { location: routing.location } : void 0,
|
|
8495
8374
|
// Slack resume publishes unless the checkpoint opted out.
|
|
8496
8375
|
// Missing means legacy/in-flight Slack turns still post.
|
|
8376
|
+
// TODO(dcramer): Remove this missing-as-publish fallback after no
|
|
8377
|
+
// stored Turn checkpoint can omit publishExternally.
|
|
8497
8378
|
publishExternally: activeTurn.publishExternally !== false,
|
|
8498
8379
|
source,
|
|
8380
|
+
...surface ? { surface } : void 0,
|
|
8499
8381
|
toolChannelId: destination.channelId,
|
|
8500
8382
|
environment: {
|
|
8501
8383
|
locationConfiguration
|
|
@@ -8709,30 +8591,812 @@ async function runNextPausedTurnInContext(conversationId, options, runOptions) {
|
|
|
8709
8591
|
return false;
|
|
8710
8592
|
}
|
|
8711
8593
|
|
|
8594
|
+
// src/chat/task-execution/conversation-turn.ts
|
|
8595
|
+
import { createHash } from "crypto";
|
|
8596
|
+
|
|
8597
|
+
// src/chat/task-execution/assistant-message.ts
|
|
8598
|
+
async function commitAssistantMessage(args) {
|
|
8599
|
+
const conversationMessageId = recordDeliveredAssistantMessage({
|
|
8600
|
+
conversation: args.conversation,
|
|
8601
|
+
sessionId: args.sessionId,
|
|
8602
|
+
source: args.source,
|
|
8603
|
+
text: args.text,
|
|
8604
|
+
userMessageId: args.userMessageId
|
|
8605
|
+
});
|
|
8606
|
+
if (args.publishedMessage?.providerMessageId) {
|
|
8607
|
+
markConversationMessage(args.conversation, conversationMessageId, {
|
|
8608
|
+
slackTs: args.publishedMessage.providerMessageId
|
|
8609
|
+
});
|
|
8610
|
+
}
|
|
8611
|
+
try {
|
|
8612
|
+
await persistWithRetry(
|
|
8613
|
+
() => commitAcceptedReply({
|
|
8614
|
+
...args.agentMessage ? { agentMessage: args.agentMessage } : void 0,
|
|
8615
|
+
conversation: args.conversation,
|
|
8616
|
+
conversationMessageId,
|
|
8617
|
+
conversationId: args.conversationId,
|
|
8618
|
+
providerConversationBindings: args.publishedMessage?.providerConversationBindings
|
|
8619
|
+
})
|
|
8620
|
+
);
|
|
8621
|
+
} catch (error) {
|
|
8622
|
+
logException(
|
|
8623
|
+
new Error("Assistant message persistence failed"),
|
|
8624
|
+
"conversation.assistant.message_persist.failed",
|
|
8625
|
+
{
|
|
8626
|
+
"error.type": error instanceof Error ? error.name : typeof error
|
|
8627
|
+
}
|
|
8628
|
+
);
|
|
8629
|
+
}
|
|
8630
|
+
}
|
|
8631
|
+
|
|
8632
|
+
// src/chat/task-execution/mailbox-turn.ts
|
|
8633
|
+
import {
|
|
8634
|
+
createResourceEventSource,
|
|
8635
|
+
createLocalSource,
|
|
8636
|
+
createWebSource
|
|
8637
|
+
} from "@sentry/junior-plugin-api";
|
|
8638
|
+
function turnInputFactsFromConversationMessage(message, args) {
|
|
8639
|
+
if (isResourceEventConversationMessage(message)) {
|
|
8640
|
+
return {
|
|
8641
|
+
actor: args.savedActor ?? RESOURCE_EVENT_SYSTEM_ACTOR,
|
|
8642
|
+
author: message.author ?? RESOURCE_EVENT_MESSAGE_AUTHOR,
|
|
8643
|
+
// Stored Turns written before Source was saved can only restore the old
|
|
8644
|
+
// provider stand-in from the Conversation.
|
|
8645
|
+
source: args.savedSource ?? (args.location ? createWebSource(
|
|
8646
|
+
args.conversationId,
|
|
8647
|
+
args.visibility === "private" ? "private" : "public"
|
|
8648
|
+
) : createLocalSource(args.conversationId))
|
|
8649
|
+
};
|
|
8650
|
+
}
|
|
8651
|
+
const actor = args.savedActor ?? createActor(message.author, {
|
|
8652
|
+
platform: "web",
|
|
8653
|
+
userId: message.author?.userId
|
|
8654
|
+
});
|
|
8655
|
+
if (actor?.platform !== "web") {
|
|
8656
|
+
return void 0;
|
|
8657
|
+
}
|
|
8658
|
+
return {
|
|
8659
|
+
actor,
|
|
8660
|
+
author: message.author ?? { userId: actor.userId },
|
|
8661
|
+
source: args.savedSource?.kind === "web" ? args.savedSource : createWebSource(
|
|
8662
|
+
args.conversationId,
|
|
8663
|
+
args.visibility === "private" ? "private" : "public"
|
|
8664
|
+
)
|
|
8665
|
+
};
|
|
8666
|
+
}
|
|
8667
|
+
function sourceFromTurnInput(args) {
|
|
8668
|
+
if (args.source.kind === "web") {
|
|
8669
|
+
return createWebSource(
|
|
8670
|
+
args.conversationId,
|
|
8671
|
+
args.visibility === "private" ? "private" : "public"
|
|
8672
|
+
);
|
|
8673
|
+
}
|
|
8674
|
+
return args.source;
|
|
8675
|
+
}
|
|
8676
|
+
function hasResourceEventActor(actors) {
|
|
8677
|
+
return Boolean(
|
|
8678
|
+
actors?.some(
|
|
8679
|
+
(actor) => actor.platform === "system" && actor.name === RESOURCE_EVENT_SYSTEM_ACTOR.name
|
|
8680
|
+
)
|
|
8681
|
+
);
|
|
8682
|
+
}
|
|
8683
|
+
async function getActiveConversationTurnId(conversationId) {
|
|
8684
|
+
const summaries = await listTurnSummaries(conversationId);
|
|
8685
|
+
const active = summaries.filter(
|
|
8686
|
+
(summary) => summary.surface === "api" && !summary.dispatchId && (summary.state === "paused" || summary.state === "running")
|
|
8687
|
+
);
|
|
8688
|
+
if (active.length > 1) {
|
|
8689
|
+
throw new Error(
|
|
8690
|
+
`Conversation ${conversationId} has multiple active web turns`
|
|
8691
|
+
);
|
|
8692
|
+
}
|
|
8693
|
+
const turnId = active[0]?.turnId;
|
|
8694
|
+
if (!turnId) return void 0;
|
|
8695
|
+
const record = await getTurnRecord(conversationId, turnId);
|
|
8696
|
+
return record && (record.source?.kind === "web" || !record.source && record.surface === "api") && !record.dispatchId && (record.state === "paused" || record.state === "running") ? turnId : void 0;
|
|
8697
|
+
}
|
|
8698
|
+
async function getActiveMailboxTurnId(conversationId) {
|
|
8699
|
+
const summaries = await listTurnSummaries(conversationId);
|
|
8700
|
+
const active = (await Promise.all(
|
|
8701
|
+
summaries.filter(
|
|
8702
|
+
(summary) => !summary.dispatchId && (summary.state === "paused" || summary.state === "running")
|
|
8703
|
+
).map((summary) => getTurnRecord(conversationId, summary.turnId))
|
|
8704
|
+
)).filter(
|
|
8705
|
+
(record) => record && !record.dispatchId && (record.source?.kind === "web" || record.source?.kind === "resource_event" || !record.source && (record.surface === "api" || hasResourceEventActor(record.actors))) && (record.state === "paused" || record.state === "running")
|
|
8706
|
+
);
|
|
8707
|
+
if (active.length > 1) {
|
|
8708
|
+
throw new Error(
|
|
8709
|
+
`Conversation ${conversationId} has multiple active mailbox Turns`
|
|
8710
|
+
);
|
|
8711
|
+
}
|
|
8712
|
+
return active[0]?.turnId;
|
|
8713
|
+
}
|
|
8714
|
+
async function getAuthPausedConversationTurnId(conversationId) {
|
|
8715
|
+
const turnId = await getActiveConversationTurnId(conversationId);
|
|
8716
|
+
if (!turnId) return void 0;
|
|
8717
|
+
const record = await getTurnRecord(conversationId, turnId);
|
|
8718
|
+
return record?.state === "paused" && record.resumeReason === "auth" ? turnId : void 0;
|
|
8719
|
+
}
|
|
8720
|
+
function parseWebMessages(messages) {
|
|
8721
|
+
if (messages.length === 0) {
|
|
8722
|
+
return [];
|
|
8723
|
+
}
|
|
8724
|
+
const parsed = messages.map((message) => ({
|
|
8725
|
+
message,
|
|
8726
|
+
metadata: legacyWebMailboxMetadataSchema.safeParse(message.input.metadata)
|
|
8727
|
+
}));
|
|
8728
|
+
if (parsed.every((entry) => !entry.metadata.success)) {
|
|
8729
|
+
return [];
|
|
8730
|
+
}
|
|
8731
|
+
if (parsed.some((entry) => !entry.metadata.success)) {
|
|
8732
|
+
throw new Error("A Turn cannot combine different kinds of input");
|
|
8733
|
+
}
|
|
8734
|
+
return parsed.map((entry) => {
|
|
8735
|
+
if (!entry.metadata.success) {
|
|
8736
|
+
throw new Error("User message has invalid metadata");
|
|
8737
|
+
}
|
|
8738
|
+
const metadata = entry.metadata.data;
|
|
8739
|
+
const actor = {
|
|
8740
|
+
platform: "web",
|
|
8741
|
+
userId: metadata.authorUserId,
|
|
8742
|
+
email: metadata.authorEmail.trim().toLowerCase(),
|
|
8743
|
+
...metadata.authorFullName ? { fullName: metadata.authorFullName } : void 0,
|
|
8744
|
+
...metadata.authorUserName ? { userName: metadata.authorUserName } : void 0
|
|
8745
|
+
};
|
|
8746
|
+
return {
|
|
8747
|
+
actor,
|
|
8748
|
+
author: {
|
|
8749
|
+
email: actor.email,
|
|
8750
|
+
...actor.fullName ? { fullName: actor.fullName } : void 0,
|
|
8751
|
+
userId: actor.userId,
|
|
8752
|
+
...actor.userName ? { userName: actor.userName } : void 0
|
|
8753
|
+
},
|
|
8754
|
+
message: entry.message,
|
|
8755
|
+
source: createWebSource(entry.message.conversationId)
|
|
8756
|
+
};
|
|
8757
|
+
});
|
|
8758
|
+
}
|
|
8759
|
+
function parseResourceEventMessages(messages) {
|
|
8760
|
+
if (messages.length === 0) {
|
|
8761
|
+
return [];
|
|
8762
|
+
}
|
|
8763
|
+
if (!messages.every(
|
|
8764
|
+
(message) => message.source === "resource_event" && isResourceEventMailboxMetadata(message.input.metadata)
|
|
8765
|
+
)) {
|
|
8766
|
+
return [];
|
|
8767
|
+
}
|
|
8768
|
+
return messages.map((message) => {
|
|
8769
|
+
if (!isResourceEventMailboxMetadata(message.input.metadata)) {
|
|
8770
|
+
throw new Error("Resource event has invalid metadata");
|
|
8771
|
+
}
|
|
8772
|
+
return {
|
|
8773
|
+
actor: RESOURCE_EVENT_SYSTEM_ACTOR,
|
|
8774
|
+
author: RESOURCE_EVENT_MESSAGE_AUTHOR,
|
|
8775
|
+
message,
|
|
8776
|
+
source: createResourceEventSource({
|
|
8777
|
+
eventKey: message.input.metadata.resourceEvent.eventKey,
|
|
8778
|
+
eventType: message.input.metadata.resourceEvent.eventType,
|
|
8779
|
+
identifier: message.input.metadata.resourceEvent.identifier,
|
|
8780
|
+
namespace: message.input.metadata.resourceEvent.namespace
|
|
8781
|
+
})
|
|
8782
|
+
};
|
|
8783
|
+
});
|
|
8784
|
+
}
|
|
8785
|
+
async function resolveMailboxTurnWork(context) {
|
|
8786
|
+
const batch = parseWebMessages(context.attempt.messages);
|
|
8787
|
+
if (batch.length > 0) {
|
|
8788
|
+
return { kind: "mailbox", batch };
|
|
8789
|
+
}
|
|
8790
|
+
const resourceBatch = parseResourceEventMessages(context.attempt.messages);
|
|
8791
|
+
if (resourceBatch.length > 0) {
|
|
8792
|
+
return { kind: "mailbox", batch: resourceBatch };
|
|
8793
|
+
}
|
|
8794
|
+
if (context.attempt.messages.length > 0) {
|
|
8795
|
+
return void 0;
|
|
8796
|
+
}
|
|
8797
|
+
const turnId = await getActiveMailboxTurnId(context.conversationId);
|
|
8798
|
+
return turnId ? { kind: "resume", turnId } : void 0;
|
|
8799
|
+
}
|
|
8800
|
+
|
|
8801
|
+
// src/chat/task-execution/mailbox-input.ts
|
|
8802
|
+
function joinMailboxText(messages) {
|
|
8803
|
+
return messages.map((message) => message.input.text.trim()).filter(Boolean).join("\n\n");
|
|
8804
|
+
}
|
|
8805
|
+
|
|
8806
|
+
// src/chat/task-execution/conversation-turn.ts
|
|
8807
|
+
function stableHex(...parts) {
|
|
8808
|
+
return createHash("sha256").update(parts.join("\0")).digest("hex").slice(0, 24);
|
|
8809
|
+
}
|
|
8810
|
+
function captureConversationTurnFailure(args) {
|
|
8811
|
+
const eventId = logException(
|
|
8812
|
+
args.error,
|
|
8813
|
+
`conversation.turn.${args.failureCode}`,
|
|
8814
|
+
{
|
|
8815
|
+
conversationId: args.conversationId,
|
|
8816
|
+
...args.runId ? { runId: args.runId } : void 0,
|
|
8817
|
+
turnId: args.turnId
|
|
8818
|
+
}
|
|
8819
|
+
);
|
|
8820
|
+
return typeof eventId === "string" ? eventId : void 0;
|
|
8821
|
+
}
|
|
8822
|
+
function hasLostTurnInputCommit(error) {
|
|
8823
|
+
const cause = getConversationTurnBoundaryError(error)?.cause ?? error;
|
|
8824
|
+
return isTurnInputCommitLostError(error) || isTurnInputCommitLostError(cause);
|
|
8825
|
+
}
|
|
8826
|
+
async function completeCancelledConversationTurn(args) {
|
|
8827
|
+
const pendingAuthorization = args.conversation.processing.pendingAuth?.sessionId === args.turnId ? args.conversation.processing.pendingAuth : void 0;
|
|
8828
|
+
await abandonTurnRecord({
|
|
8829
|
+
conversationId: args.conversationId,
|
|
8830
|
+
turnId: args.turnId,
|
|
8831
|
+
errorMessage: "Turn cancelled"
|
|
8832
|
+
});
|
|
8833
|
+
clearPendingAuth(args.conversation, args.turnId);
|
|
8834
|
+
markConversationMessage(args.conversation, args.userMessageId, {
|
|
8835
|
+
replied: false,
|
|
8836
|
+
skippedReason: "turn cancelled"
|
|
8837
|
+
});
|
|
8838
|
+
markTurnClosed({
|
|
8839
|
+
conversation: args.conversation,
|
|
8840
|
+
nowMs: Date.now(),
|
|
8841
|
+
sessionId: args.turnId
|
|
8842
|
+
});
|
|
8843
|
+
if (pendingAuthorization) {
|
|
8844
|
+
await deleteWebAuthorization({
|
|
8845
|
+
actorId: pendingAuthorization.actorId,
|
|
8846
|
+
conversationId: args.conversationId
|
|
8847
|
+
});
|
|
8848
|
+
}
|
|
8849
|
+
await persistThreadStateById(args.conversationId, {
|
|
8850
|
+
conversation: args.conversation,
|
|
8851
|
+
sandboxRef: args.sandboxRef
|
|
8852
|
+
});
|
|
8853
|
+
await new ConversationTurnLifecycleService(
|
|
8854
|
+
getConversationEventStore()
|
|
8855
|
+
).complete({
|
|
8856
|
+
conversationId: args.conversationId,
|
|
8857
|
+
createdAtMs: Date.now(),
|
|
8858
|
+
outcome: "cancelled",
|
|
8859
|
+
turnId: args.turnId
|
|
8860
|
+
});
|
|
8861
|
+
await args.acknowledge();
|
|
8862
|
+
}
|
|
8863
|
+
function createConversationTurnWorker(agentRunner, publishMessage) {
|
|
8864
|
+
return async (context, resolved) => {
|
|
8865
|
+
const lifecycle = new ConversationTurnLifecycleService(
|
|
8866
|
+
getConversationEventStore()
|
|
8867
|
+
);
|
|
8868
|
+
const isResume = resolved.kind === "resume";
|
|
8869
|
+
let turnInputFacts;
|
|
8870
|
+
let text = "";
|
|
8871
|
+
let turnId = "";
|
|
8872
|
+
let userMessageId = "";
|
|
8873
|
+
let startedAtMs = Date.now();
|
|
8874
|
+
let inputMessageIds = [];
|
|
8875
|
+
const storedConversation = await getConversationStore().get({
|
|
8876
|
+
conversationId: context.conversationId
|
|
8877
|
+
});
|
|
8878
|
+
const mailboxDestination = resolved.kind === "mailbox" ? resolved.batch[0]?.message.destination : void 0;
|
|
8879
|
+
const destination = resolveConversationDestination({
|
|
8880
|
+
conversationId: context.conversationId,
|
|
8881
|
+
existing: context.destination ?? mailboxDestination ?? storedConversation?.destination
|
|
8882
|
+
});
|
|
8883
|
+
if (resolved.kind === "mailbox") {
|
|
8884
|
+
const first = resolved.batch[0];
|
|
8885
|
+
text = joinMailboxText(resolved.batch.map((entry) => entry.message));
|
|
8886
|
+
startedAtMs = first.message.createdAtMs;
|
|
8887
|
+
userMessageId = first.message.inboundMessageId;
|
|
8888
|
+
turnId = buildDeterministicTurnId(userMessageId);
|
|
8889
|
+
inputMessageIds = resolved.batch.map(
|
|
8890
|
+
(entry) => entry.message.inboundMessageId
|
|
8891
|
+
);
|
|
8892
|
+
turnInputFacts = first;
|
|
8893
|
+
} else {
|
|
8894
|
+
turnId = resolved.turnId;
|
|
8895
|
+
}
|
|
8896
|
+
const persisted = await getPersistedThreadState(context.conversationId);
|
|
8897
|
+
const conversation = coerceThreadConversationState(persisted);
|
|
8898
|
+
await hydrateConversationMessages({
|
|
8899
|
+
conversation,
|
|
8900
|
+
conversationId: context.conversationId
|
|
8901
|
+
});
|
|
8902
|
+
const savedTurn = isResume ? await getTurnRecord(context.conversationId, turnId) : void 0;
|
|
8903
|
+
let resumedResourceEvent = false;
|
|
8904
|
+
if (isResume) {
|
|
8905
|
+
const userMessage = getTurnUserMessage(conversation, turnId);
|
|
8906
|
+
if (!userMessage) {
|
|
8907
|
+
throw new Error(
|
|
8908
|
+
`Unable to locate the persisted user message for Turn "${turnId}"`
|
|
8909
|
+
);
|
|
8910
|
+
}
|
|
8911
|
+
resumedResourceEvent = isResourceEventConversationMessage(userMessage);
|
|
8912
|
+
turnInputFacts = turnInputFactsFromConversationMessage(userMessage, {
|
|
8913
|
+
conversationId: context.conversationId,
|
|
8914
|
+
location: storedConversation?.location,
|
|
8915
|
+
savedActor: savedTurn?.actor,
|
|
8916
|
+
savedSource: savedTurn?.source,
|
|
8917
|
+
visibility: storedConversation?.visibility
|
|
8918
|
+
});
|
|
8919
|
+
userMessageId = userMessage.id;
|
|
8920
|
+
text = userMessage.text;
|
|
8921
|
+
startedAtMs = userMessage.createdAtMs;
|
|
8922
|
+
inputMessageIds = [userMessageId];
|
|
8923
|
+
}
|
|
8924
|
+
if (!turnInputFacts) {
|
|
8925
|
+
throw new Error(
|
|
8926
|
+
`Resumed Turn is missing an Actor for Conversation ${context.conversationId}`
|
|
8927
|
+
);
|
|
8928
|
+
}
|
|
8929
|
+
const { actor, author } = turnInputFacts;
|
|
8930
|
+
const source = sourceFromTurnInput({
|
|
8931
|
+
conversationId: context.conversationId,
|
|
8932
|
+
source: turnInputFacts.source,
|
|
8933
|
+
visibility: storedConversation?.visibility
|
|
8934
|
+
});
|
|
8935
|
+
const webActor = actor.platform === "web" ? actor : void 0;
|
|
8936
|
+
const publish = savedTurn?.publishExternally ?? Boolean(
|
|
8937
|
+
storedConversation?.location && (source.kind === "resource_event" || resumedResourceEvent)
|
|
8938
|
+
);
|
|
8939
|
+
const surface = publish ? "slack" : "api";
|
|
8940
|
+
return await withLogContext(
|
|
8941
|
+
{
|
|
8942
|
+
conversationId: context.conversationId,
|
|
8943
|
+
platform: actor.platform,
|
|
8944
|
+
...webActor ? {
|
|
8945
|
+
userId: webActor.userId,
|
|
8946
|
+
...webActor.userName ? { userName: webActor.userName } : void 0
|
|
8947
|
+
} : void 0
|
|
8948
|
+
},
|
|
8949
|
+
async () => {
|
|
8950
|
+
let acknowledged = isResume || context.attempt.messages.length === 0;
|
|
8951
|
+
const acknowledge = async () => {
|
|
8952
|
+
if (acknowledged) {
|
|
8953
|
+
return;
|
|
8954
|
+
}
|
|
8955
|
+
try {
|
|
8956
|
+
await context.attempt.ack();
|
|
8957
|
+
} catch {
|
|
8958
|
+
throw new TurnInputCommitLostError(
|
|
8959
|
+
`Conversation work lease lost before mailbox Message acknowledgement for ${context.conversationId}`
|
|
8960
|
+
);
|
|
8961
|
+
}
|
|
8962
|
+
acknowledged = true;
|
|
8963
|
+
};
|
|
8964
|
+
let sandboxRef = getPersistedSandboxState(persisted);
|
|
8965
|
+
const initialSandboxRef = sandboxRef;
|
|
8966
|
+
const stopSignal = context.stopSignal?.();
|
|
8967
|
+
const completeCancelledTurn = async () => {
|
|
8968
|
+
try {
|
|
8969
|
+
await completeCancelledConversationTurn({
|
|
8970
|
+
acknowledge,
|
|
8971
|
+
conversation,
|
|
8972
|
+
conversationId: context.conversationId,
|
|
8973
|
+
sandboxRef,
|
|
8974
|
+
turnId,
|
|
8975
|
+
userMessageId
|
|
8976
|
+
});
|
|
8977
|
+
} catch (error) {
|
|
8978
|
+
if (hasLostTurnInputCommit(error)) {
|
|
8979
|
+
return { status: "lost_lease" };
|
|
8980
|
+
}
|
|
8981
|
+
throw error;
|
|
8982
|
+
}
|
|
8983
|
+
return { status: "completed" };
|
|
8984
|
+
};
|
|
8985
|
+
if (isResume) {
|
|
8986
|
+
if (stopSignal?.aborted) {
|
|
8987
|
+
return await completeCancelledTurn();
|
|
8988
|
+
}
|
|
8989
|
+
} else {
|
|
8990
|
+
upsertConversationMessage(conversation, {
|
|
8991
|
+
id: userMessageId,
|
|
8992
|
+
role: "user",
|
|
8993
|
+
text: normalizeConversationText(text),
|
|
8994
|
+
createdAtMs: startedAtMs,
|
|
8995
|
+
author,
|
|
8996
|
+
meta: {
|
|
8997
|
+
explicitMention: true,
|
|
8998
|
+
replied: false,
|
|
8999
|
+
...source.kind === "web" ? { source: "web" } : void 0
|
|
9000
|
+
}
|
|
9001
|
+
});
|
|
9002
|
+
await persistConversationMessages({
|
|
9003
|
+
conversation,
|
|
9004
|
+
conversationId: context.conversationId
|
|
9005
|
+
});
|
|
9006
|
+
await lifecycle.start({
|
|
9007
|
+
conversationId: context.conversationId,
|
|
9008
|
+
createdAtMs: Date.now(),
|
|
9009
|
+
inputMessageIds,
|
|
9010
|
+
surface,
|
|
9011
|
+
turnId
|
|
9012
|
+
});
|
|
9013
|
+
if (stopSignal?.aborted) {
|
|
9014
|
+
return await completeCancelledTurn();
|
|
9015
|
+
}
|
|
9016
|
+
startActiveTurn({
|
|
9017
|
+
conversation,
|
|
9018
|
+
nextTurnId: turnId
|
|
9019
|
+
});
|
|
9020
|
+
}
|
|
9021
|
+
let currentRunId;
|
|
9022
|
+
let assistantMessageDelivered = false;
|
|
9023
|
+
let failureCode = "persistence_failed";
|
|
9024
|
+
let modelFailureEventId;
|
|
9025
|
+
let modelFailureCaptureAttempted = false;
|
|
9026
|
+
let completedSuccessfully = false;
|
|
9027
|
+
const deliverAssistantMessage = async (value) => {
|
|
9028
|
+
const agentMessage = typeof value === "string" ? void 0 : value;
|
|
9029
|
+
const replyText = typeof value === "string" ? value : getAssistantReplyText(value);
|
|
9030
|
+
if (!replyText?.trim()) {
|
|
9031
|
+
return;
|
|
9032
|
+
}
|
|
9033
|
+
failureCode = "delivery_failed";
|
|
9034
|
+
const location = storedConversation?.location;
|
|
9035
|
+
if (publish && (!location || !publishMessage)) {
|
|
9036
|
+
throw new Error(
|
|
9037
|
+
`Conversation ${context.conversationId} cannot publish its system Turn`
|
|
9038
|
+
);
|
|
9039
|
+
}
|
|
9040
|
+
const publishedMessage = publish && location && publishMessage ? await publishMessage({
|
|
9041
|
+
conversationId: context.conversationId,
|
|
9042
|
+
location,
|
|
9043
|
+
text: replyText
|
|
9044
|
+
}) : void 0;
|
|
9045
|
+
await commitAssistantMessage({
|
|
9046
|
+
...agentMessage ? { agentMessage } : void 0,
|
|
9047
|
+
conversation,
|
|
9048
|
+
conversationId: context.conversationId,
|
|
9049
|
+
...publishedMessage ? { publishedMessage } : void 0,
|
|
9050
|
+
sessionId: turnId,
|
|
9051
|
+
...publishedMessage ? { source: "slack" } : source.kind === "web" ? { source: "web" } : void 0,
|
|
9052
|
+
text: replyText,
|
|
9053
|
+
userMessageId
|
|
9054
|
+
});
|
|
9055
|
+
assistantMessageDelivered = true;
|
|
9056
|
+
failureCode = "agent_run_failed";
|
|
9057
|
+
};
|
|
9058
|
+
try {
|
|
9059
|
+
if (stopSignal?.aborted) {
|
|
9060
|
+
return await completeCancelledTurn();
|
|
9061
|
+
}
|
|
9062
|
+
if (!isResume) {
|
|
9063
|
+
const pendingAuthorizationActorId = conversation.processing.pendingAuth?.actorId;
|
|
9064
|
+
const authParked = (await listTurnSummaries(context.conversationId)).filter(
|
|
9065
|
+
(summary) => summary.surface === "api" && !summary.dispatchId && summary.state === "paused" && summary.resumeReason === "auth"
|
|
9066
|
+
);
|
|
9067
|
+
for (const parked of authParked) {
|
|
9068
|
+
if (stopSignal?.aborted) {
|
|
9069
|
+
return await completeCancelledTurn();
|
|
9070
|
+
}
|
|
9071
|
+
await abandonTurnRecord({
|
|
9072
|
+
conversationId: context.conversationId,
|
|
9073
|
+
turnId: parked.turnId,
|
|
9074
|
+
errorMessage: "Auth-paused Turn superseded by new input"
|
|
9075
|
+
});
|
|
9076
|
+
markTurnClosed({
|
|
9077
|
+
conversation,
|
|
9078
|
+
nowMs: Date.now(),
|
|
9079
|
+
sessionId: parked.turnId
|
|
9080
|
+
});
|
|
9081
|
+
}
|
|
9082
|
+
if (authParked.length > 0 && pendingAuthorizationActorId) {
|
|
9083
|
+
await deleteWebAuthorization({
|
|
9084
|
+
actorId: pendingAuthorizationActorId,
|
|
9085
|
+
conversationId: context.conversationId
|
|
9086
|
+
});
|
|
9087
|
+
}
|
|
9088
|
+
}
|
|
9089
|
+
await persistThreadStateById(context.conversationId, {
|
|
9090
|
+
conversation
|
|
9091
|
+
});
|
|
9092
|
+
if (stopSignal?.aborted) {
|
|
9093
|
+
return await completeCancelledTurn();
|
|
9094
|
+
}
|
|
9095
|
+
const piMessages = await loadProjection({
|
|
9096
|
+
conversationId: context.conversationId
|
|
9097
|
+
});
|
|
9098
|
+
failureCode = "agent_run_failed";
|
|
9099
|
+
currentRunId = `conversation-run:${stableHex(turnId, String(startedAtMs))}`;
|
|
9100
|
+
setTags({ runId: currentRunId });
|
|
9101
|
+
const outcome = await executeTurn(
|
|
9102
|
+
agentRunner,
|
|
9103
|
+
{
|
|
9104
|
+
conversationId: context.conversationId,
|
|
9105
|
+
turnId,
|
|
9106
|
+
runId: currentRunId,
|
|
9107
|
+
instruction: {
|
|
9108
|
+
text,
|
|
9109
|
+
context: buildConversationContext(conversation, {
|
|
9110
|
+
excludeMessageId: userMessageId
|
|
9111
|
+
})
|
|
9112
|
+
},
|
|
9113
|
+
history: piMessages,
|
|
9114
|
+
actor,
|
|
9115
|
+
credentialContext: credentialContextForActor(actor),
|
|
9116
|
+
// TODO(dcramer): Remove AgentRun.destination after agent and tool
|
|
9117
|
+
// code reads AgentRun.location and no Run consumer needs it.
|
|
9118
|
+
destination,
|
|
9119
|
+
// TODO(dcramer): Remove AgentRun.publishExternally after the
|
|
9120
|
+
// saved Turn publish choice controls optional Delivery.
|
|
9121
|
+
publishExternally: publish,
|
|
9122
|
+
source,
|
|
9123
|
+
...storedConversation?.location ? { location: storedConversation.location } : void 0,
|
|
9124
|
+
surface,
|
|
9125
|
+
...stopSignal ? { signal: stopSignal } : void 0,
|
|
9126
|
+
...webActor ? {
|
|
9127
|
+
authorization: createWebAuthorization({
|
|
9128
|
+
actorId: webActor.userId,
|
|
9129
|
+
conversationId: context.conversationId
|
|
9130
|
+
})
|
|
9131
|
+
} : { disabledFeatures: ["interactive-auth"] },
|
|
9132
|
+
state: {
|
|
9133
|
+
pendingAuth: conversation.processing.pendingAuth,
|
|
9134
|
+
sandboxRef
|
|
9135
|
+
},
|
|
9136
|
+
delivery: deliverAssistantMessage,
|
|
9137
|
+
durability: {
|
|
9138
|
+
onInputCommitted: acknowledge,
|
|
9139
|
+
shouldYield: context.shouldYield,
|
|
9140
|
+
onSandboxRefChanged: async (nextSandboxRef) => {
|
|
9141
|
+
sandboxRef = nextSandboxRef;
|
|
9142
|
+
await persistThreadStateById(context.conversationId, {
|
|
9143
|
+
conversation,
|
|
9144
|
+
sandboxRef
|
|
9145
|
+
});
|
|
9146
|
+
},
|
|
9147
|
+
recordPendingAuth: async (pendingAuth) => {
|
|
9148
|
+
conversation.processing.pendingAuth = pendingAuth;
|
|
9149
|
+
await persistThreadStateById(context.conversationId, {
|
|
9150
|
+
conversation,
|
|
9151
|
+
sandboxRef
|
|
9152
|
+
});
|
|
9153
|
+
}
|
|
9154
|
+
}
|
|
9155
|
+
},
|
|
9156
|
+
async (result) => {
|
|
9157
|
+
if (stopSignal?.aborted) {
|
|
9158
|
+
throw stopSignal.reason ?? new DOMException("Turn cancelled", "AbortError");
|
|
9159
|
+
}
|
|
9160
|
+
modelFailureCaptureAttempted = result.diagnostics.outcome !== "success";
|
|
9161
|
+
const finalized = finalizeFailedTurnReplyWithEvent({
|
|
9162
|
+
reply: result,
|
|
9163
|
+
logException
|
|
9164
|
+
});
|
|
9165
|
+
const modelFailureReason = finalized.failureReason;
|
|
9166
|
+
const reply = finalized.reply;
|
|
9167
|
+
modelFailureEventId = finalized.eventId;
|
|
9168
|
+
if (reply.diagnostics.outcome !== "success") {
|
|
9169
|
+
await deliverAssistantMessage(reply.text);
|
|
9170
|
+
}
|
|
9171
|
+
const completedState = buildDeliveredTurnStatePatch({
|
|
9172
|
+
conversation,
|
|
9173
|
+
reply,
|
|
9174
|
+
sessionId: turnId,
|
|
9175
|
+
userMessageId
|
|
9176
|
+
});
|
|
9177
|
+
await persistThreadStateById(context.conversationId, {
|
|
9178
|
+
conversation: completedState.conversation,
|
|
9179
|
+
sandboxRef: reply.sandboxRef ?? sandboxRef
|
|
9180
|
+
});
|
|
9181
|
+
if (reply.piMessages?.length) {
|
|
9182
|
+
const latest = await getTurnRecord(
|
|
9183
|
+
context.conversationId,
|
|
9184
|
+
turnId
|
|
9185
|
+
);
|
|
9186
|
+
await saveTurnCheckpoint({
|
|
9187
|
+
mode: "completed",
|
|
9188
|
+
conversationId: context.conversationId,
|
|
9189
|
+
turnId,
|
|
9190
|
+
sliceId: latest?.sliceId ?? 1,
|
|
9191
|
+
messages: reply.piMessages,
|
|
9192
|
+
durationMs: reply.diagnostics.durationMs,
|
|
9193
|
+
usage: reply.diagnostics.usage,
|
|
9194
|
+
// TODO(dcramer): Remove checkpoint Destination after resume
|
|
9195
|
+
// reads the Conversation Location.
|
|
9196
|
+
destination,
|
|
9197
|
+
publishExternally: publish,
|
|
9198
|
+
source,
|
|
9199
|
+
actor,
|
|
9200
|
+
surface
|
|
9201
|
+
});
|
|
9202
|
+
}
|
|
9203
|
+
completedSuccessfully = reply.diagnostics.outcome === "success";
|
|
9204
|
+
return completedSuccessfully ? {
|
|
9205
|
+
outcome: assistantMessageDelivered ? "success" : "no_reply"
|
|
9206
|
+
} : {
|
|
9207
|
+
...modelFailureEventId ? { eventId: modelFailureEventId } : void 0,
|
|
9208
|
+
failureCode: "model_execution_failed",
|
|
9209
|
+
...modelFailureReason ? { failureReason: modelFailureReason } : void 0,
|
|
9210
|
+
outcome: "failed"
|
|
9211
|
+
};
|
|
9212
|
+
}
|
|
9213
|
+
);
|
|
9214
|
+
if (outcome.status !== "completed" && stopSignal?.aborted) {
|
|
9215
|
+
return await completeCancelledTurn();
|
|
9216
|
+
}
|
|
9217
|
+
if (outcome.status === "suspended") {
|
|
9218
|
+
return { status: "yielded" };
|
|
9219
|
+
}
|
|
9220
|
+
if (outcome.status === "awaiting_auth") {
|
|
9221
|
+
completeAuthPauseTurn({
|
|
9222
|
+
conversation,
|
|
9223
|
+
sessionId: turnId
|
|
9224
|
+
});
|
|
9225
|
+
await persistThreadStateById(context.conversationId, {
|
|
9226
|
+
conversation,
|
|
9227
|
+
sandboxRef
|
|
9228
|
+
});
|
|
9229
|
+
await acknowledge();
|
|
9230
|
+
return { status: "paused" };
|
|
9231
|
+
}
|
|
9232
|
+
if (completedSuccessfully) {
|
|
9233
|
+
try {
|
|
9234
|
+
await scheduleSessionCompletedPluginTasks(
|
|
9235
|
+
{
|
|
9236
|
+
conversationId: context.conversationId,
|
|
9237
|
+
sessionId: turnId
|
|
9238
|
+
},
|
|
9239
|
+
{
|
|
9240
|
+
send: async (message) => {
|
|
9241
|
+
try {
|
|
9242
|
+
await processPluginTask(message);
|
|
9243
|
+
} catch (error) {
|
|
9244
|
+
logException(
|
|
9245
|
+
error,
|
|
9246
|
+
"conversation.plugin.session_completion_task.failed",
|
|
9247
|
+
{
|
|
9248
|
+
conversationId: context.conversationId,
|
|
9249
|
+
pluginName: message.plugin,
|
|
9250
|
+
taskName: message.name,
|
|
9251
|
+
turnId
|
|
9252
|
+
}
|
|
9253
|
+
);
|
|
9254
|
+
}
|
|
9255
|
+
}
|
|
9256
|
+
}
|
|
9257
|
+
);
|
|
9258
|
+
} catch (error) {
|
|
9259
|
+
logException(
|
|
9260
|
+
error,
|
|
9261
|
+
"conversation.plugin.session_completion_task.failed",
|
|
9262
|
+
{
|
|
9263
|
+
conversationId: context.conversationId,
|
|
9264
|
+
turnId
|
|
9265
|
+
}
|
|
9266
|
+
);
|
|
9267
|
+
}
|
|
9268
|
+
}
|
|
9269
|
+
await acknowledge();
|
|
9270
|
+
return { status: "completed" };
|
|
9271
|
+
} catch (error) {
|
|
9272
|
+
const failure = error instanceof AgentRunError ? error.cause : error;
|
|
9273
|
+
if (hasLostTurnInputCommit(failure)) {
|
|
9274
|
+
return { status: "lost_lease" };
|
|
9275
|
+
}
|
|
9276
|
+
if (stopSignal?.aborted) {
|
|
9277
|
+
return await completeCancelledTurn();
|
|
9278
|
+
}
|
|
9279
|
+
if (!context.attempt.isFinalAttempt) {
|
|
9280
|
+
throw failure;
|
|
9281
|
+
}
|
|
9282
|
+
const failureEventId = modelFailureCaptureAttempted && failureCode === "agent_run_failed" ? modelFailureEventId : captureConversationTurnFailure({
|
|
9283
|
+
conversationId: context.conversationId,
|
|
9284
|
+
error: failure,
|
|
9285
|
+
failureCode,
|
|
9286
|
+
runId: currentRunId,
|
|
9287
|
+
turnId
|
|
9288
|
+
});
|
|
9289
|
+
try {
|
|
9290
|
+
markTurnFailed({
|
|
9291
|
+
conversation,
|
|
9292
|
+
nowMs: Date.now(),
|
|
9293
|
+
sessionId: turnId,
|
|
9294
|
+
userMessageId,
|
|
9295
|
+
markConversationMessage
|
|
9296
|
+
});
|
|
9297
|
+
await persistThreadStateById(context.conversationId, {
|
|
9298
|
+
conversation,
|
|
9299
|
+
sandboxRef: initialSandboxRef ?? null
|
|
9300
|
+
});
|
|
9301
|
+
} catch (persistenceError) {
|
|
9302
|
+
captureConversationTurnFailure({
|
|
9303
|
+
conversationId: context.conversationId,
|
|
9304
|
+
error: persistenceError,
|
|
9305
|
+
failureCode: "persistence_failed",
|
|
9306
|
+
runId: currentRunId,
|
|
9307
|
+
turnId
|
|
9308
|
+
});
|
|
9309
|
+
}
|
|
9310
|
+
await lifecycle.fail({
|
|
9311
|
+
conversationId: context.conversationId,
|
|
9312
|
+
createdAtMs: Date.now(),
|
|
9313
|
+
...failureEventId ? { eventId: failureEventId } : void 0,
|
|
9314
|
+
failureCode,
|
|
9315
|
+
turnId
|
|
9316
|
+
});
|
|
9317
|
+
await acknowledge();
|
|
9318
|
+
return { status: "completed" };
|
|
9319
|
+
}
|
|
9320
|
+
}
|
|
9321
|
+
);
|
|
9322
|
+
};
|
|
9323
|
+
}
|
|
9324
|
+
|
|
9325
|
+
// src/chat/providers/slack/system-turn.ts
|
|
9326
|
+
function createSlackSystemTurnPublisher(args) {
|
|
9327
|
+
return async ({ conversationId, location, text }) => {
|
|
9328
|
+
if (location.provider !== "slack") {
|
|
9329
|
+
throw new Error(
|
|
9330
|
+
`Slack system Turn cannot publish to ${location.provider} Location`
|
|
9331
|
+
);
|
|
9332
|
+
}
|
|
9333
|
+
let messageIds;
|
|
9334
|
+
try {
|
|
9335
|
+
messageIds = await runWithSlackInstallation({
|
|
9336
|
+
adapter: args.getSlackAdapter(),
|
|
9337
|
+
installation: { teamId: location.teamId },
|
|
9338
|
+
state: args.state,
|
|
9339
|
+
task: async () => await sendSlackReply({
|
|
9340
|
+
channelId: location.channelId,
|
|
9341
|
+
conversationId,
|
|
9342
|
+
text,
|
|
9343
|
+
...location.threadTs ? { threadTs: location.threadTs } : void 0
|
|
9344
|
+
})
|
|
9345
|
+
});
|
|
9346
|
+
} catch (error) {
|
|
9347
|
+
if (isRetryableSlackPostError(error)) {
|
|
9348
|
+
throw new RetryableDeliveryError(error);
|
|
9349
|
+
}
|
|
9350
|
+
throw error;
|
|
9351
|
+
}
|
|
9352
|
+
const providerMessageId = messageIds.at(-1);
|
|
9353
|
+
const providerConversationId = location.threadTs ?? messageIds[0];
|
|
9354
|
+
return {
|
|
9355
|
+
...providerMessageId ? { providerMessageId } : void 0,
|
|
9356
|
+
...providerConversationId ? {
|
|
9357
|
+
providerConversationBindings: [
|
|
9358
|
+
{
|
|
9359
|
+
provider: "slack",
|
|
9360
|
+
providerDestinationId: location.channelId,
|
|
9361
|
+
providerTenantId: location.teamId,
|
|
9362
|
+
providerConversationId
|
|
9363
|
+
}
|
|
9364
|
+
]
|
|
9365
|
+
} : void 0
|
|
9366
|
+
};
|
|
9367
|
+
};
|
|
9368
|
+
}
|
|
9369
|
+
|
|
8712
9370
|
// src/chat/app/conversation-work.ts
|
|
8713
9371
|
function createConversationWork(options) {
|
|
8714
|
-
const apiTurnCancellation = createApiTurnCancellation();
|
|
8715
9372
|
const pausedTurns = createPausedTurns({
|
|
8716
9373
|
conversationStore: options.conversationStore,
|
|
8717
9374
|
queue: options.queue,
|
|
8718
9375
|
...options.state ? { state: options.state } : void 0
|
|
8719
9376
|
});
|
|
8720
|
-
const
|
|
9377
|
+
const baseRuntime = createSlackRuntime({
|
|
8721
9378
|
getSlackAdapter: options.getSlackAdapter,
|
|
8722
9379
|
pausedTurns,
|
|
9380
|
+
...options.sendPluginTask ? { sendPluginTask: options.sendPluginTask } : void 0,
|
|
8723
9381
|
services: {
|
|
8724
9382
|
...options.services,
|
|
8725
9383
|
agentRunner: options.agentRunner
|
|
8726
9384
|
}
|
|
8727
9385
|
});
|
|
9386
|
+
const runtime = options.wrapRuntime?.(baseRuntime) ?? baseRuntime;
|
|
9387
|
+
const scheduleCompletedPluginTasks = options.sendPluginTask ? async (params) => await scheduleSessionCompletedPluginTasks(params, {
|
|
9388
|
+
send: options.sendPluginTask
|
|
9389
|
+
}) : void 0;
|
|
8728
9390
|
const slackWorker = createSlackConversationWorker({
|
|
8729
9391
|
getSlackAdapter: options.getSlackAdapter,
|
|
8730
|
-
conversationStore: options.conversationStore,
|
|
8731
9392
|
runNextPausedTurn: async (conversationId, runOptions) => await runNextPausedTurn(
|
|
8732
9393
|
conversationId,
|
|
8733
9394
|
{
|
|
8734
9395
|
agentRunner: options.agentRunner,
|
|
8735
|
-
wakePausedTurn: pausedTurns.wake
|
|
9396
|
+
wakePausedTurn: pausedTurns.wake,
|
|
9397
|
+
...scheduleCompletedPluginTasks ? {
|
|
9398
|
+
scheduleSessionCompletedPluginTasks: scheduleCompletedPluginTasks
|
|
9399
|
+
} : void 0
|
|
8736
9400
|
},
|
|
8737
9401
|
runOptions
|
|
8738
9402
|
),
|
|
@@ -8747,13 +9411,24 @@ function createConversationWork(options) {
|
|
|
8747
9411
|
agentRunner: options.agentRunner,
|
|
8748
9412
|
inputMessageIds: [getDispatchInputMessageId(dispatch2.id)],
|
|
8749
9413
|
routingContext: buildDispatchRoutingContext(dispatch2),
|
|
8750
|
-
wakePausedTurn: pausedTurns.wake
|
|
9414
|
+
wakePausedTurn: pausedTurns.wake,
|
|
9415
|
+
...scheduleCompletedPluginTasks ? {
|
|
9416
|
+
scheduleSessionCompletedPluginTasks: scheduleCompletedPluginTasks
|
|
9417
|
+
} : void 0
|
|
8751
9418
|
},
|
|
8752
9419
|
{ shouldYield: hooks.shouldYield }
|
|
8753
9420
|
);
|
|
8754
9421
|
},
|
|
8755
9422
|
runTurn: runtime.runDispatchTurn
|
|
8756
9423
|
});
|
|
9424
|
+
const invocationWorker = createAgentInvocationWorker(options.agentRunner);
|
|
9425
|
+
const conversationTurnWorker = createConversationTurnWorker(
|
|
9426
|
+
options.agentRunner,
|
|
9427
|
+
createSlackSystemTurnPublisher({
|
|
9428
|
+
getSlackAdapter: options.getSlackAdapter,
|
|
9429
|
+
state: options.state
|
|
9430
|
+
})
|
|
9431
|
+
);
|
|
8757
9432
|
const destinationWorker = async (context) => {
|
|
8758
9433
|
const destination = context.destination;
|
|
8759
9434
|
if (!destination) {
|
|
@@ -8768,24 +9443,25 @@ function createConversationWork(options) {
|
|
|
8768
9443
|
`Conversation ${context.conversationId} has a ${destination.platform} destination but no matching conversation worker`
|
|
8769
9444
|
);
|
|
8770
9445
|
};
|
|
8771
|
-
const
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
9446
|
+
const run = async (context) => {
|
|
9447
|
+
const mailboxTurn = await resolveMailboxTurnWork(context);
|
|
9448
|
+
if (mailboxTurn) {
|
|
9449
|
+
return await conversationTurnWorker(context, mailboxTurn);
|
|
9450
|
+
}
|
|
9451
|
+
const invocationId = await resolveAgentInvocationId(context);
|
|
9452
|
+
if (invocationId) {
|
|
9453
|
+
return await invocationWorker(context, invocationId);
|
|
9454
|
+
}
|
|
9455
|
+
const dispatchId = await resolveAgentDispatchId(context);
|
|
9456
|
+
if (dispatchId) {
|
|
9457
|
+
return await dispatchWorker(context, dispatchId);
|
|
9458
|
+
}
|
|
9459
|
+
return await destinationWorker(context);
|
|
9460
|
+
};
|
|
8775
9461
|
return {
|
|
8776
|
-
apiTurnCancellation,
|
|
8777
9462
|
conversationStore: options.conversationStore,
|
|
8778
9463
|
queue: options.queue,
|
|
8779
|
-
run
|
|
8780
|
-
apiTurnWorker: createApiTurnWorker(
|
|
8781
|
-
options.agentRunner,
|
|
8782
|
-
apiTurnCancellation
|
|
8783
|
-
),
|
|
8784
|
-
fallbackWorker: routeAgentInvocationWork({
|
|
8785
|
-
invocationWorker: createAgentInvocationWorker(options.agentRunner),
|
|
8786
|
-
fallbackWorker: providerWorker
|
|
8787
|
-
})
|
|
8788
|
-
}),
|
|
9464
|
+
run,
|
|
8789
9465
|
runtime,
|
|
8790
9466
|
state: options.state
|
|
8791
9467
|
};
|
|
@@ -8865,7 +9541,7 @@ async function publicArtifactGET(args) {
|
|
|
8865
9541
|
}
|
|
8866
9542
|
|
|
8867
9543
|
// src/chat/event-tasks/ingest.ts
|
|
8868
|
-
import { createHash } from "crypto";
|
|
9544
|
+
import { createHash as createHash2 } from "crypto";
|
|
8869
9545
|
import {
|
|
8870
9546
|
createSlackSource as createSlackSource3,
|
|
8871
9547
|
RESOURCE_EVENT_SUMMARY_MAX_LENGTH,
|
|
@@ -8873,7 +9549,7 @@ import {
|
|
|
8873
9549
|
resourceEventSchema
|
|
8874
9550
|
} from "@sentry/junior-plugin-api";
|
|
8875
9551
|
function eventTaskDispatchKey(taskId, namespace, eventKey) {
|
|
8876
|
-
return `event-task:${
|
|
9552
|
+
return `event-task:${createHash2("sha256").update(`${taskId}\0${namespace}\0${eventKey}`).digest("hex").slice(0, 32)}`;
|
|
8877
9553
|
}
|
|
8878
9554
|
function oneLine(value) {
|
|
8879
9555
|
return value.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim().slice(0, 512);
|
|
@@ -9014,8 +9690,8 @@ function createResourceEventAppPublisher(args) {
|
|
|
9014
9690
|
};
|
|
9015
9691
|
}
|
|
9016
9692
|
|
|
9017
|
-
// src/chat/
|
|
9018
|
-
async function
|
|
9693
|
+
// src/chat/conversations/stop.ts
|
|
9694
|
+
async function stopConversationTurn(args) {
|
|
9019
9695
|
const nowMs = args.nowMs ?? Date.now();
|
|
9020
9696
|
const stop = async () => await stopConversationWork({
|
|
9021
9697
|
conversationId: args.conversationId,
|
|
@@ -9024,7 +9700,7 @@ async function stopApiConversationTurn(args) {
|
|
|
9024
9700
|
state: args.state
|
|
9025
9701
|
});
|
|
9026
9702
|
let result = await stop();
|
|
9027
|
-
if (result.status === "no_work" && await
|
|
9703
|
+
if (result.status === "no_work" && await getAuthPausedConversationTurnId(args.conversationId)) {
|
|
9028
9704
|
const conversation = await getConversation({
|
|
9029
9705
|
conversationId: args.conversationId,
|
|
9030
9706
|
state: args.state
|
|
@@ -9042,7 +9718,7 @@ async function stopApiConversationTurn(args) {
|
|
|
9042
9718
|
await ensureConversationWake({
|
|
9043
9719
|
conversationId: args.conversationId,
|
|
9044
9720
|
conversationStore: args.conversationStore,
|
|
9045
|
-
idempotencyKey: `
|
|
9721
|
+
idempotencyKey: `conversation-stop:${args.conversationId}:${result.runId}`,
|
|
9046
9722
|
nowMs,
|
|
9047
9723
|
queue: args.queue,
|
|
9048
9724
|
replaceExistingWake: true,
|
|
@@ -9096,7 +9772,7 @@ function createAcpConversations(options) {
|
|
|
9096
9772
|
if (!await hasConversationAccess(conversationId, user)) {
|
|
9097
9773
|
return "not_found";
|
|
9098
9774
|
}
|
|
9099
|
-
await
|
|
9775
|
+
await stopConversationTurn({
|
|
9100
9776
|
conversationId,
|
|
9101
9777
|
conversationStore: options.conversationStore,
|
|
9102
9778
|
queue: options.queue,
|
|
@@ -9105,7 +9781,7 @@ function createAcpConversations(options) {
|
|
|
9105
9781
|
return "cancelled";
|
|
9106
9782
|
},
|
|
9107
9783
|
async create({ conversationId, user }) {
|
|
9108
|
-
await
|
|
9784
|
+
await recordWebConversationActivity({
|
|
9109
9785
|
actor: actorFromUser(user),
|
|
9110
9786
|
conversationId,
|
|
9111
9787
|
conversationStore: options.conversationStore,
|
|
@@ -9124,10 +9800,10 @@ function createAcpConversations(options) {
|
|
|
9124
9800
|
options.eventStore,
|
|
9125
9801
|
conversationId
|
|
9126
9802
|
);
|
|
9127
|
-
if (await
|
|
9803
|
+
if (await getAuthPausedConversationTurnId(conversationId)) {
|
|
9128
9804
|
return { status: "active" };
|
|
9129
9805
|
}
|
|
9130
|
-
const
|
|
9806
|
+
const result = await appendAndEnqueueWebMessage(
|
|
9131
9807
|
{
|
|
9132
9808
|
actor: actorFromUser(user),
|
|
9133
9809
|
conversationId,
|
|
@@ -9141,12 +9817,12 @@ function createAcpConversations(options) {
|
|
|
9141
9817
|
state: options.state
|
|
9142
9818
|
}
|
|
9143
9819
|
);
|
|
9144
|
-
if (
|
|
9820
|
+
if (result.status === "active") return { status: "active" };
|
|
9145
9821
|
return {
|
|
9146
|
-
afterCursor:
|
|
9147
|
-
messageId:
|
|
9822
|
+
afterCursor: result.status === "duplicate" ? 0 : currentCursor,
|
|
9823
|
+
messageId: result.messageId,
|
|
9148
9824
|
status: "accepted",
|
|
9149
|
-
turnId:
|
|
9825
|
+
turnId: conversationTurnIdForMessage(result.messageId)
|
|
9150
9826
|
};
|
|
9151
9827
|
},
|
|
9152
9828
|
async readMessages(conversationId) {
|
|
@@ -9204,12 +9880,12 @@ function createAcpConversations(options) {
|
|
|
9204
9880
|
}
|
|
9205
9881
|
|
|
9206
9882
|
// src/api/acp/route.ts
|
|
9207
|
-
import { createHash as
|
|
9883
|
+
import { createHash as createHash5 } from "crypto";
|
|
9208
9884
|
import * as acp4 from "@agentclientprotocol/sdk";
|
|
9209
9885
|
|
|
9210
9886
|
// src/api/acp/auth.ts
|
|
9211
9887
|
import {
|
|
9212
|
-
createHash as
|
|
9888
|
+
createHash as createHash4,
|
|
9213
9889
|
randomBytes,
|
|
9214
9890
|
randomUUID as randomUUID2,
|
|
9215
9891
|
timingSafeEqual as timingSafeEqual3
|
|
@@ -9254,7 +9930,7 @@ async function fenceLock(state, lock, ttlMs = MUTATION_LOCK_TTL_MS) {
|
|
|
9254
9930
|
}
|
|
9255
9931
|
|
|
9256
9932
|
// src/api/acp/transport.ts
|
|
9257
|
-
import { createHash as
|
|
9933
|
+
import { createHash as createHash3, randomUUID } from "crypto";
|
|
9258
9934
|
import * as acp2 from "@agentclientprotocol/sdk";
|
|
9259
9935
|
import { userSchema } from "@sentry/junior-plugin-api";
|
|
9260
9936
|
import { z as z7 } from "zod";
|
|
@@ -9434,8 +10110,8 @@ var acpRequestReceiptSchema = z7.object({
|
|
|
9434
10110
|
sessionId: z7.string().min(1).optional()
|
|
9435
10111
|
}).strict();
|
|
9436
10112
|
var acpStreamCursorSchema = z7.object({ itemId: z7.string().min(1) }).strict();
|
|
9437
|
-
function
|
|
9438
|
-
return
|
|
10113
|
+
function stableHex2(value) {
|
|
10114
|
+
return createHash3("sha256").update(value).digest("hex").slice(0, 32);
|
|
9439
10115
|
}
|
|
9440
10116
|
function connectionKey(connectionId) {
|
|
9441
10117
|
return `junior:acp:v1:connection:${connectionId}`;
|
|
@@ -9450,7 +10126,7 @@ function connectionLockKey(connectionId) {
|
|
|
9450
10126
|
return `${connectionKey(connectionId)}:lock`;
|
|
9451
10127
|
}
|
|
9452
10128
|
function streamKey(route) {
|
|
9453
|
-
const suffix = route.sessionId ? `session:${
|
|
10129
|
+
const suffix = route.sessionId ? `session:${stableHex2(route.sessionId)}` : "connection";
|
|
9454
10130
|
return `${connectionKey(route.connectionId)}:stream:${suffix}`;
|
|
9455
10131
|
}
|
|
9456
10132
|
function streamListKey(route) {
|
|
@@ -9466,7 +10142,7 @@ function streamAppendLockKey(route) {
|
|
|
9466
10142
|
return `${streamKey(route)}:append`;
|
|
9467
10143
|
}
|
|
9468
10144
|
function requestStreamItemId(requestKey2, index) {
|
|
9469
|
-
return `acp-item:${
|
|
10145
|
+
return `acp-item:${stableHex2(`${requestKey2}:${index}`)}`;
|
|
9470
10146
|
}
|
|
9471
10147
|
function parseStreamItem(value) {
|
|
9472
10148
|
return storedAcpStreamItemSchema.parse(value);
|
|
@@ -10075,7 +10751,7 @@ function authorizationPointerLockKey(connectionId) {
|
|
|
10075
10751
|
return `${authorizationPointerKey(connectionId)}:lock`;
|
|
10076
10752
|
}
|
|
10077
10753
|
function credentialHash(value) {
|
|
10078
|
-
return
|
|
10754
|
+
return createHash4("sha256").update(value).digest("hex");
|
|
10079
10755
|
}
|
|
10080
10756
|
function createUserCode() {
|
|
10081
10757
|
const value = randomBytes(6).toString("hex").toUpperCase();
|
|
@@ -10539,8 +11215,8 @@ function promptText(prompt) {
|
|
|
10539
11215
|
}
|
|
10540
11216
|
return text;
|
|
10541
11217
|
}
|
|
10542
|
-
function
|
|
10543
|
-
return
|
|
11218
|
+
function stableHex3(value, length = 32) {
|
|
11219
|
+
return createHash5("sha256").update(value).digest("hex").slice(0, length);
|
|
10544
11220
|
}
|
|
10545
11221
|
function canonicalJson(value) {
|
|
10546
11222
|
if (Array.isArray(value)) return value.map(canonicalJson);
|
|
@@ -10550,11 +11226,11 @@ function canonicalJson(value) {
|
|
|
10550
11226
|
);
|
|
10551
11227
|
}
|
|
10552
11228
|
function requestKey(call) {
|
|
10553
|
-
const id = call.id === null ? "null" : `${typeof call.id}:${
|
|
11229
|
+
const id = call.id === null ? "null" : `${typeof call.id}:${stableHex3(String(call.id))}`;
|
|
10554
11230
|
const payload = JSON.stringify(
|
|
10555
11231
|
canonicalJson({ method: call.method, params: call.params ?? null })
|
|
10556
11232
|
);
|
|
10557
|
-
return `${id}:${
|
|
11233
|
+
return `${id}:${stableHex3(payload)}`;
|
|
10558
11234
|
}
|
|
10559
11235
|
function sessionIdFromCall(call) {
|
|
10560
11236
|
if (!call) return void 0;
|
|
@@ -10607,7 +11283,7 @@ async function createSession(args) {
|
|
|
10607
11283
|
args.call.params
|
|
10608
11284
|
);
|
|
10609
11285
|
rejectUnsupportedMcpServers(params.mcpServers);
|
|
10610
|
-
const sessionId = `${ACP_CONVERSATION_PREFIX}${
|
|
11286
|
+
const sessionId = `${ACP_CONVERSATION_PREFIX}${stableHex3(
|
|
10611
11287
|
`${args.connection.nonce}:${args.requestKey}`
|
|
10612
11288
|
)}`;
|
|
10613
11289
|
await args.conversations.create({
|
|
@@ -10621,16 +11297,16 @@ async function acceptPrompt(args) {
|
|
|
10621
11297
|
promptParamsSchema,
|
|
10622
11298
|
args.call.params
|
|
10623
11299
|
);
|
|
10624
|
-
const
|
|
11300
|
+
const result = await args.conversations.prompt({
|
|
10625
11301
|
conversationId: params.sessionId,
|
|
10626
11302
|
idempotencyKey: `${args.connection.nonce}:${args.requestKey}`,
|
|
10627
11303
|
text: promptText(params.prompt),
|
|
10628
11304
|
user: args.user
|
|
10629
11305
|
});
|
|
10630
|
-
if (
|
|
11306
|
+
if (result.status === "not_found") {
|
|
10631
11307
|
throw acp4.RequestError.resourceNotFound(params.sessionId);
|
|
10632
11308
|
}
|
|
10633
|
-
if (
|
|
11309
|
+
if (result.status === "active") {
|
|
10634
11310
|
throw acp4.RequestError.invalidParams(
|
|
10635
11311
|
{ field: "sessionId" },
|
|
10636
11312
|
"This ACP session already has an active prompt"
|
|
@@ -10638,11 +11314,11 @@ async function acceptPrompt(args) {
|
|
|
10638
11314
|
}
|
|
10639
11315
|
return {
|
|
10640
11316
|
output: {
|
|
10641
|
-
afterSeq:
|
|
11317
|
+
afterSeq: result.afterCursor,
|
|
10642
11318
|
kind: "prompt",
|
|
10643
|
-
messageId:
|
|
11319
|
+
messageId: result.messageId,
|
|
10644
11320
|
requestId: args.requestId,
|
|
10645
|
-
turnId:
|
|
11321
|
+
turnId: result.turnId
|
|
10646
11322
|
},
|
|
10647
11323
|
sessionId: params.sessionId
|
|
10648
11324
|
};
|