@sentry/junior 0.184.0 → 0.186.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-XTZVALGQ.js → agent-hooks-4B3Z4WRK.js} +13 -11
- package/dist/api/acp/schema.d.ts +20 -2
- package/dist/api/code/overview.d.ts +39 -0
- package/dist/api/locations/detail.d.ts +1 -1
- package/dist/api/people/code.d.ts +22 -0
- package/dist/api/schema/code.d.ts +46 -0
- package/dist/api/schema/conversation.d.ts +108 -20
- package/dist/api/schema/location.d.ts +1 -1
- package/dist/api/schema/person.d.ts +1 -1
- package/dist/api/schema.d.ts +4 -4
- package/dist/api/schema.js +12 -1
- package/dist/api.js +368 -78
- package/dist/app.js +1412 -538
- package/dist/{catalog-runtime-5357XR4F.js → catalog-runtime-AFJCAOHC.js} +4 -4
- package/dist/chat/api-turns/accepted-reply.d.ts +11 -0
- package/dist/chat/api-turns/cancellation.d.ts +3 -5
- package/dist/chat/api-turns/mailbox-input.d.ts +7 -0
- package/dist/chat/api-turns/routing.d.ts +18 -3
- package/dist/chat/api-turns/work.d.ts +4 -9
- package/dist/chat/app/conversation-work.d.ts +1 -1
- package/dist/chat/app/factory.d.ts +4 -0
- package/dist/chat/app/services.d.ts +4 -3
- package/dist/chat/conversations/history.d.ts +83 -9
- package/dist/chat/conversations/turn-lifecycle.d.ts +6 -3
- package/dist/chat/providers/slack/input.d.ts +32 -0
- package/dist/chat/{runtime → providers/slack}/processing-reaction.d.ts +6 -8
- package/dist/chat/{runtime/slack-resume.d.ts → providers/slack/resume.d.ts} +16 -19
- package/dist/chat/providers/slack/runtime.d.ts +1 -12
- package/dist/chat/providers/slack/turn.d.ts +10 -25
- package/dist/chat/resource-events/actor.d.ts +7 -2
- package/dist/chat/resource-events/app-publisher.d.ts +18 -0
- package/dist/chat/resource-events/catalog.d.ts +19 -0
- package/dist/chat/resource-events/ingest.d.ts +0 -1
- package/dist/chat/resource-events/notification.d.ts +28 -3
- package/dist/chat/resource-events/runtime-catalog.d.ts +7 -2
- package/dist/chat/resource-events/store.d.ts +2 -14
- package/dist/chat/resource-events/tool-support.d.ts +0 -5
- package/dist/chat/resource-events/workspace.d.ts +7 -3
- package/dist/chat/runtime/turn-execution.d.ts +7 -2
- package/dist/chat/sandbox/egress/credentials.d.ts +5 -4
- package/dist/chat/sandbox/egress/session.d.ts +10 -11
- package/dist/chat/sandbox/errors.d.ts +1 -1
- package/dist/chat/sandbox/ref.d.ts +1 -1
- package/dist/chat/sandbox/snapshot/events.d.ts +8 -1
- package/dist/chat/sandbox/snapshot/not-ready-error.d.ts +6 -1
- package/dist/chat/scheduled-tasks/tool-support.d.ts +5 -5
- package/dist/chat/scheduled-tasks/tools/create.d.ts +2 -2
- package/dist/chat/scheduled-tasks/tools/delete.d.ts +2 -2
- package/dist/chat/scheduled-tasks/tools/list.d.ts +2 -2
- package/dist/chat/scheduled-tasks/tools/run-now.d.ts +2 -2
- package/dist/chat/scheduled-tasks/tools/update.d.ts +2 -2
- package/dist/chat/scheduled-tasks/types.d.ts +1 -1
- package/dist/chat/sentry-links.d.ts +2 -0
- package/dist/chat/services/provider-retry.d.ts +2 -0
- package/dist/chat/services/turn-failure-response.d.ts +4 -0
- package/dist/chat/services/turn-session-routing.d.ts +20 -5
- package/dist/chat/task-execution/paused-turn.d.ts +0 -2
- package/dist/chat/task-execution/slack-resource-event.d.ts +47 -0
- package/dist/chat/task-execution/slack-work.d.ts +0 -21
- 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-wake.d.ts +12 -0
- package/dist/chat/tool-support/action-review.d.ts +1 -1
- package/dist/chat/tools/event-tasks.d.ts +1 -1
- package/dist/chat/tools/resource-events.d.ts +2 -2
- package/dist/chat/tools/search-conversation-events.d.ts +1 -1
- package/dist/chat/tools/types.d.ts +1 -1
- package/dist/chat/tools/watch-resource-events.d.ts +2 -2
- package/dist/{chunk-Z3QAXJR7.js → chunk-2IBDVE62.js} +12 -9
- package/dist/{chunk-4RONS3WR.js → chunk-2U7EPTRZ.js} +11 -5
- package/dist/{chunk-3S7ULUWW.js → chunk-3CVEE6LA.js} +1 -1
- package/dist/{chunk-IZDYYYGP.js → chunk-43LODHJM.js} +24 -384
- package/dist/{chunk-LHXIZLFF.js → chunk-64WF2GQ3.js} +1 -1
- package/dist/{chunk-YKX6MTLU.js → chunk-7EOWT62G.js} +1 -1
- package/dist/{chunk-UBOIHNTH.js → chunk-7EU4YSZ4.js} +362 -188
- package/dist/{chunk-UF6BUA5W.js → chunk-ACGWTJ74.js} +3 -3
- package/dist/{chunk-6UDPINOX.js → chunk-AD64YMEC.js} +19 -44
- package/dist/{chunk-MLSQX2EX.js → chunk-BRKB5R7P.js} +1 -1
- package/dist/{chunk-E57WPXWY.js → chunk-CM6RTYSO.js} +5 -5
- package/dist/{chunk-MAPJFUMV.js → chunk-CV5CPRVG.js} +3 -3
- package/dist/chunk-D4YV5TDV.js +45 -0
- package/dist/{chunk-HIPUIPJM.js → chunk-DHYZ4VKG.js} +383 -254
- package/dist/{chunk-DUKIDPF6.js → chunk-DOP3FIQC.js} +1 -1
- package/dist/{chunk-BT53RIGJ.js → chunk-EWRPUXE3.js} +12 -50
- package/dist/{chunk-BHYRYYLY.js → chunk-FFYDRLXW.js} +1 -1
- package/dist/chunk-GFBR4S3Q.js +406 -0
- package/dist/chunk-GQMQCY7H.js +58 -0
- package/dist/{chunk-JNO2GUDS.js → chunk-GSB3NTNS.js} +926 -1856
- package/dist/{chunk-2ZQPVX7C.js → chunk-H7X2G2KS.js} +25 -12
- package/dist/{chunk-WQFEWULF.js → chunk-HKFLRIBD.js} +2 -2
- package/dist/{chunk-SHJK75Z2.js → chunk-HWXP6RHG.js} +38 -4
- package/dist/{chunk-RF6J3DIO.js → chunk-INQHUE72.js} +84 -1
- package/dist/{chunk-4CNDGK25.js → chunk-JFPY6XFF.js} +911 -993
- package/dist/{chunk-6WGC3SO4.js → chunk-MCLWOBPN.js} +80 -18
- package/dist/{chunk-PJPRXO2T.js → chunk-NRMAOGRS.js} +1 -1
- package/dist/{chunk-ACPDVEJO.js → chunk-O6GQO7VP.js} +201 -218
- package/dist/{chunk-M5YWNMTE.js → chunk-OZG7E22Y.js} +24 -6
- package/dist/{chunk-WVIA7V3M.js → chunk-PFAZSRGR.js} +29 -1
- package/dist/{chunk-LCP4EDKR.js → chunk-PZZOGHVR.js} +14 -4
- package/dist/{chunk-QABCY33S.js → chunk-QBL2AVFF.js} +2 -2
- package/dist/{chunk-FKEZZMXS.js → chunk-QU3URVWG.js} +9 -94
- package/dist/{chunk-M3QYTBQ6.js → chunk-STOCCPWH.js} +11 -2
- package/dist/{chunk-K7VDC2QW.js → chunk-TXLBLGNQ.js} +6 -6
- package/dist/{chunk-JA43DV4Y.js → chunk-VOGOTEW7.js} +1 -1
- package/dist/{chunk-HUXFMDBZ.js → chunk-VQIWBJOP.js} +1 -1
- package/dist/{chunk-JM2COLGC.js → chunk-VQZYIVYN.js} +6 -6
- package/dist/{chunk-BCHYQS4B.js → chunk-VXL2LBPK.js} +1 -1
- package/dist/{chunk-6VOYP4M6.js → chunk-YXSBZRP7.js} +1 -1
- package/dist/cli/chat.js +35 -33
- package/dist/cli/check.js +5 -5
- package/dist/cli/plugins.js +14 -12
- package/dist/cli/snapshot-create.js +10 -9
- package/dist/cli/upgrade.js +7 -6
- package/dist/{db-MA52H62H.js → db-7XL4UPAE.js} +8 -6
- package/dist/instrumentation.js +3 -3
- package/dist/nitro.js +7 -6
- package/dist/{oauth-callback-server-DXGHKN6S.js → oauth-callback-server-RAOYHWDI.js} +30 -27
- package/dist/{runner-4IXUAQNK.js → runner-KMPBWRPM.js} +24 -19
- package/dist/{skills-X3DY7AXO.js → skills-IPCALGLQ.js} +5 -5
- package/dist/spawn-OSOWTMBG.js +41 -0
- package/dist/task-runner-IQNBA3RY.js +34 -0
- package/dist/{validation-Z6JXSTJS.js → validation-BSRCCX6N.js} +5 -5
- package/dist/version.js +1 -1
- package/dist/{work-OKWRFBDW.js → work-T6UFTOJY.js} +24 -19
- package/dist/worker-L35OG7VA.js +24 -0
- package/package.json +5 -5
- package/dist/spawn-43WGS6CH.js +0 -37
- package/dist/task-runner-VDRKITPV.js +0 -32
- package/dist/worker-B236AE72.js +0 -22
package/dist/app.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
processConversationWork
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2U7EPTRZ.js";
|
|
4
4
|
import {
|
|
5
5
|
bindSpawnAgent
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QBL2AVFF.js";
|
|
7
7
|
import {
|
|
8
8
|
createAgentInvocationWorker,
|
|
9
9
|
enqueueAgentInvocation,
|
|
10
10
|
listPendingAgentInvocationMailboxAppends,
|
|
11
11
|
routeAgentInvocationWork
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-EWRPUXE3.js";
|
|
13
13
|
import {
|
|
14
14
|
GET as GET2,
|
|
15
15
|
GET2 as GET3,
|
|
16
16
|
buildAuthPauseResponse,
|
|
17
17
|
buildSlackOutputMessage,
|
|
18
|
+
createPausedTurns,
|
|
18
19
|
createSlackAdapterAssistantStatusSession,
|
|
19
20
|
getAssistantThreadContext,
|
|
20
21
|
getChannelId,
|
|
@@ -33,10 +34,10 @@ import {
|
|
|
33
34
|
sendSlackReply,
|
|
34
35
|
shouldKeepProcessingReactionForToolInvocation,
|
|
35
36
|
splitSlackReplyText,
|
|
36
|
-
|
|
37
|
+
startProcessingReaction,
|
|
37
38
|
stripLeadingBotMention,
|
|
38
39
|
wakePausedTurn
|
|
39
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-O6GQO7VP.js";
|
|
40
41
|
import "./chunk-FA6POGLH.js";
|
|
41
42
|
import {
|
|
42
43
|
GET,
|
|
@@ -47,14 +48,19 @@ import {
|
|
|
47
48
|
createApiTurnWorker,
|
|
48
49
|
createVercelAttachmentStorage,
|
|
49
50
|
getAuthPausedApiTurnId,
|
|
51
|
+
lookupSlackUser,
|
|
50
52
|
readConversationAccessFromSql,
|
|
51
53
|
recordApiConversationActivity,
|
|
52
54
|
resolveSlackChannelTypeFromMessage,
|
|
53
55
|
resolveSlackConversationContext,
|
|
54
56
|
routeApiTurnWork,
|
|
55
57
|
webActorFromEmail
|
|
56
|
-
} from "./chunk-
|
|
57
|
-
import "./chunk-
|
|
58
|
+
} from "./chunk-7EU4YSZ4.js";
|
|
59
|
+
import "./chunk-PZZOGHVR.js";
|
|
60
|
+
import {
|
|
61
|
+
AgentRunError,
|
|
62
|
+
executeTurn
|
|
63
|
+
} from "./chunk-GQMQCY7H.js";
|
|
58
64
|
import {
|
|
59
65
|
buildDeliveredTurnStatePatch,
|
|
60
66
|
completeAuthPauseTurn,
|
|
@@ -65,7 +71,7 @@ import {
|
|
|
65
71
|
getTurnUserSlackMessageTs,
|
|
66
72
|
persistAuthPauseTurnState,
|
|
67
73
|
requireTurnFailureEventId
|
|
68
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-OZG7E22Y.js";
|
|
69
75
|
import {
|
|
70
76
|
claimDispatchMailboxAppend,
|
|
71
77
|
confirmDispatchMailboxAppend,
|
|
@@ -83,12 +89,13 @@ import {
|
|
|
83
89
|
markDispatchFailed,
|
|
84
90
|
markDispatchRunning,
|
|
85
91
|
recordTaskExecution,
|
|
92
|
+
resolveConversationRouting,
|
|
86
93
|
resolveTurnSessionRouting,
|
|
87
94
|
scheduleSessionCompletedPluginTasks
|
|
88
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-MCLWOBPN.js";
|
|
89
96
|
import {
|
|
90
|
-
|
|
91
|
-
} from "./chunk-
|
|
97
|
+
getTurnLifecycle
|
|
98
|
+
} from "./chunk-STOCCPWH.js";
|
|
92
99
|
import {
|
|
93
100
|
coerceThreadConversationState,
|
|
94
101
|
getLocationConfigurationService,
|
|
@@ -97,17 +104,17 @@ import {
|
|
|
97
104
|
persistThreadRuntimeState,
|
|
98
105
|
persistThreadState,
|
|
99
106
|
persistThreadStateById
|
|
100
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-CM6RTYSO.js";
|
|
101
108
|
import "./chunk-UTL3MHPC.js";
|
|
102
109
|
import {
|
|
103
110
|
createVercelPluginTaskCallback,
|
|
104
111
|
queueCallback,
|
|
105
112
|
registerVercelPluginTaskDevConsumer
|
|
106
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-ACGWTJ74.js";
|
|
107
114
|
import {
|
|
108
115
|
validatePluginEgressCredentialHooks,
|
|
109
116
|
validatePluginRegistrations
|
|
110
|
-
} from "./chunk-
|
|
117
|
+
} from "./chunk-VQIWBJOP.js";
|
|
111
118
|
import {
|
|
112
119
|
defineJuniorPlugins,
|
|
113
120
|
pluginCatalogConfigFromEnv,
|
|
@@ -115,28 +122,20 @@ import {
|
|
|
115
122
|
pluginRuntimeRegistrationsFromPluginSet
|
|
116
123
|
} from "./chunk-CM5HNV2W.js";
|
|
117
124
|
import {
|
|
118
|
-
RESOURCE_EVENT_SYSTEM_ACTOR,
|
|
119
125
|
SANDBOX_EGRESS_PROXY_PATH,
|
|
120
|
-
buildSlackInboundMessage,
|
|
121
126
|
buildSteeringPiMessage,
|
|
122
127
|
clearSandboxEgressSignals,
|
|
123
128
|
consumeSandboxEgressAuthRequiredSignal,
|
|
124
129
|
consumeSandboxEgressPermissionDeniedSignal,
|
|
125
130
|
createContextCompactor,
|
|
126
|
-
createSlackConversationWorker,
|
|
127
|
-
ensureSlackMessageActorIdentity,
|
|
128
131
|
executeAgentRun,
|
|
129
132
|
executeCredentialedEgressRequest,
|
|
130
133
|
getConfigDefaults,
|
|
131
|
-
getMessageActorIdentity,
|
|
132
134
|
getNextRunAtMs,
|
|
133
135
|
ingestResourceEvent,
|
|
134
|
-
isResourceEventConversationMessage,
|
|
135
|
-
isResourceEventSlackMessage,
|
|
136
136
|
latestReportedProgress,
|
|
137
137
|
listThreadReplies,
|
|
138
138
|
logScheduledTaskRunSkipped,
|
|
139
|
-
normalizeIncomingSlackThreadId,
|
|
140
139
|
normalizeSandboxEgressTracePropagationDomains,
|
|
141
140
|
parseSandboxEgressCredentialToken,
|
|
142
141
|
processWorkspaceSnapshotJob,
|
|
@@ -146,50 +145,41 @@ import {
|
|
|
146
145
|
renderBlockText,
|
|
147
146
|
resolveDestinationVisibility,
|
|
148
147
|
resolveSandboxEgressProviderForHost,
|
|
149
|
-
runWithSlackInstallation,
|
|
150
148
|
scheduledTaskRunAttributes,
|
|
151
149
|
setConfigDefaults,
|
|
152
150
|
shouldEmitDevAgentTrace,
|
|
153
151
|
shouldPropagateSandboxEgressTrace,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
verifySlackSignature,
|
|
157
|
-
withNormalizedThreadId
|
|
158
|
-
} from "./chunk-JNO2GUDS.js";
|
|
152
|
+
unpublishedArtifactHeaders
|
|
153
|
+
} from "./chunk-GSB3NTNS.js";
|
|
159
154
|
import {
|
|
160
155
|
AuthorizationFlowDisabledError,
|
|
161
156
|
PluginCredentialFailureError
|
|
162
|
-
} from "./chunk-
|
|
157
|
+
} from "./chunk-TXLBLGNQ.js";
|
|
163
158
|
import "./chunk-6Y5B5PEX.js";
|
|
164
159
|
import "./chunk-DIB4GX3G.js";
|
|
165
160
|
import {
|
|
166
|
-
createAgentRunner,
|
|
167
161
|
createUserTokenStore,
|
|
168
162
|
deleteMcpAuthSessionsForUserProvider,
|
|
169
163
|
deleteMcpServerSessionId,
|
|
170
164
|
deleteMcpStoredOAuthCredentials
|
|
171
|
-
} from "./chunk-
|
|
172
|
-
import {
|
|
173
|
-
RetryableDeliveryError
|
|
174
|
-
} from "./chunk-RF6J3DIO.js";
|
|
165
|
+
} from "./chunk-QU3URVWG.js";
|
|
175
166
|
import {
|
|
176
167
|
formatProviderLabel,
|
|
177
168
|
postSlackMessage,
|
|
178
169
|
startOAuthFlow
|
|
179
|
-
} from "./chunk-
|
|
180
|
-
import {
|
|
181
|
-
getExperimentalFeatures,
|
|
182
|
-
isExperimentalFeatureEnabled,
|
|
183
|
-
setExperimentalFeatures
|
|
184
|
-
} from "./chunk-2LYHWMR4.js";
|
|
170
|
+
} from "./chunk-VQZYIVYN.js";
|
|
185
171
|
import {
|
|
172
|
+
RESOURCE_EVENT_AUTHOR_ID,
|
|
173
|
+
RESOURCE_EVENT_SYSTEM_ACTOR,
|
|
186
174
|
collectAttachmentGarbage,
|
|
187
175
|
collectEventTaskMatchKeys,
|
|
188
176
|
findMatchingEventTasks,
|
|
189
177
|
getResourceEventCatalog,
|
|
178
|
+
isResourceEventConversationMessage,
|
|
179
|
+
isResourceEventMailboxMetadata,
|
|
180
|
+
isResourceEventSlackMessage,
|
|
190
181
|
listScheduledTasks,
|
|
191
182
|
listScheduledTasksForTeam,
|
|
192
|
-
lookupSlackUser,
|
|
193
183
|
readScheduledTask,
|
|
194
184
|
requestAttachmentDeletion,
|
|
195
185
|
resourceEventGuidance,
|
|
@@ -197,10 +187,14 @@ import {
|
|
|
197
187
|
scheduledRunId,
|
|
198
188
|
scheduledRunSchema,
|
|
199
189
|
withScheduledTaskLock
|
|
200
|
-
} from "./chunk-
|
|
190
|
+
} from "./chunk-DHYZ4VKG.js";
|
|
201
191
|
import {
|
|
202
192
|
parseSlackThreadId
|
|
203
|
-
} from "./chunk-
|
|
193
|
+
} from "./chunk-7EOWT62G.js";
|
|
194
|
+
import {
|
|
195
|
+
RetryableDeliveryError,
|
|
196
|
+
createAgentRunner
|
|
197
|
+
} from "./chunk-INQHUE72.js";
|
|
204
198
|
import {
|
|
205
199
|
CONVERSATION_WORK_STALE_ENQUEUE_MS,
|
|
206
200
|
appendAndEnqueueInboundMessage,
|
|
@@ -215,7 +209,7 @@ import {
|
|
|
215
209
|
removeActiveConversation,
|
|
216
210
|
requestConversationWork,
|
|
217
211
|
stopConversationWork
|
|
218
|
-
} from "./chunk-
|
|
212
|
+
} from "./chunk-2IBDVE62.js";
|
|
219
213
|
import {
|
|
220
214
|
ConversationTurnBoundaryError,
|
|
221
215
|
CooperativeTurnYieldError,
|
|
@@ -233,7 +227,7 @@ import {
|
|
|
233
227
|
markTurnCompleted,
|
|
234
228
|
markTurnFailed,
|
|
235
229
|
startActiveTurn
|
|
236
|
-
} from "./chunk-
|
|
230
|
+
} from "./chunk-VOGOTEW7.js";
|
|
237
231
|
import {
|
|
238
232
|
abandonTurnRecord,
|
|
239
233
|
appendThreadContextMessages,
|
|
@@ -269,11 +263,16 @@ import {
|
|
|
269
263
|
trimTrailingAssistantMessages,
|
|
270
264
|
turnHasReply,
|
|
271
265
|
upsertConversationMessage
|
|
272
|
-
} from "./chunk-
|
|
266
|
+
} from "./chunk-H7X2G2KS.js";
|
|
267
|
+
import {
|
|
268
|
+
getExperimentalFeatures,
|
|
269
|
+
isExperimentalFeatureEnabled,
|
|
270
|
+
setExperimentalFeatures
|
|
271
|
+
} from "./chunk-2LYHWMR4.js";
|
|
273
272
|
import {
|
|
274
273
|
getSandboxResourceConfig,
|
|
275
274
|
setSandboxResourceConfig
|
|
276
|
-
} from "./chunk-
|
|
275
|
+
} from "./chunk-CV5CPRVG.js";
|
|
277
276
|
import "./chunk-PDO5BLNM.js";
|
|
278
277
|
import "./chunk-UIE3R5XU.js";
|
|
279
278
|
import {
|
|
@@ -292,7 +291,7 @@ import {
|
|
|
292
291
|
import "./chunk-7H2VZTWN.js";
|
|
293
292
|
import {
|
|
294
293
|
getTurnRequestDeadline
|
|
295
|
-
} from "./chunk-
|
|
294
|
+
} from "./chunk-BRKB5R7P.js";
|
|
296
295
|
import {
|
|
297
296
|
SlackActionError,
|
|
298
297
|
bindEventTaskCredentialSubject,
|
|
@@ -302,7 +301,6 @@ import {
|
|
|
302
301
|
collectResourceEventMatchKeys,
|
|
303
302
|
createPluginLogger,
|
|
304
303
|
createPluginState,
|
|
305
|
-
createResourceEventTeamIdResolver,
|
|
306
304
|
downloadPrivateSlackFile,
|
|
307
305
|
getPluginApiRoutes,
|
|
308
306
|
getPluginRoutes,
|
|
@@ -311,6 +309,7 @@ import {
|
|
|
311
309
|
getWorkspaceTeamId,
|
|
312
310
|
isDmChannel,
|
|
313
311
|
normalizeSlackConversationId,
|
|
312
|
+
runWithSlackInstallationToken,
|
|
314
313
|
runWithWorkspaceTeamId,
|
|
315
314
|
setDashboardConversationLinkOptions,
|
|
316
315
|
setPlugins,
|
|
@@ -318,20 +317,19 @@ import {
|
|
|
318
317
|
verifyEventTaskCredentialSubject,
|
|
319
318
|
verifyScheduledTaskCredentialSubject,
|
|
320
319
|
verifySlackDirectCredentialSubject
|
|
321
|
-
} from "./chunk-
|
|
320
|
+
} from "./chunk-JFPY6XFF.js";
|
|
322
321
|
import "./chunk-3Y47VMHV.js";
|
|
323
322
|
import {
|
|
324
|
-
|
|
323
|
+
createSlackDestination,
|
|
325
324
|
deleteProviderIdentityForSlackUser,
|
|
326
325
|
getConversationEventStore,
|
|
327
326
|
getConversationStore,
|
|
328
327
|
getDb,
|
|
329
328
|
getSqlExecutor,
|
|
330
|
-
instructionProvenanceFor,
|
|
331
329
|
requireSlackDestination,
|
|
332
330
|
withConversationEventLock,
|
|
333
331
|
withConversationMutationLock
|
|
334
|
-
} from "./chunk-
|
|
332
|
+
} from "./chunk-43LODHJM.js";
|
|
335
333
|
import {
|
|
336
334
|
juniorAgentBindings,
|
|
337
335
|
juniorAgentInvocations,
|
|
@@ -339,13 +337,17 @@ import {
|
|
|
339
337
|
juniorConversations,
|
|
340
338
|
juniorSchedulerRuns,
|
|
341
339
|
juniorSchedulerTasks
|
|
342
|
-
} from "./chunk-
|
|
343
|
-
import "./chunk-
|
|
340
|
+
} from "./chunk-VXL2LBPK.js";
|
|
341
|
+
import "./chunk-HWXP6RHG.js";
|
|
344
342
|
import {
|
|
345
343
|
acquireActiveLock,
|
|
346
344
|
getStateAdapter,
|
|
347
345
|
withActiveLock
|
|
348
|
-
} from "./chunk-
|
|
346
|
+
} from "./chunk-DOP3FIQC.js";
|
|
347
|
+
import {
|
|
348
|
+
contextProvenance,
|
|
349
|
+
instructionProvenanceFor
|
|
350
|
+
} from "./chunk-GFBR4S3Q.js";
|
|
349
351
|
import {
|
|
350
352
|
juniorDestinations
|
|
351
353
|
} from "./chunk-VFUK3X5B.js";
|
|
@@ -354,7 +356,6 @@ import {
|
|
|
354
356
|
completeObject,
|
|
355
357
|
completeText,
|
|
356
358
|
configureFunctionMaxDurationSeconds,
|
|
357
|
-
defaultModelId,
|
|
358
359
|
escapeXml,
|
|
359
360
|
getChatConfig,
|
|
360
361
|
getSlackBotToken,
|
|
@@ -363,16 +364,19 @@ import {
|
|
|
363
364
|
getSlackReactionConfig,
|
|
364
365
|
getSlackSigningSecret,
|
|
365
366
|
isProviderRetryError,
|
|
366
|
-
modelIdForProfile,
|
|
367
367
|
setProfiles,
|
|
368
368
|
setSlackReactionConfig
|
|
369
|
-
} from "./chunk-
|
|
370
|
-
import
|
|
371
|
-
|
|
369
|
+
} from "./chunk-AD64YMEC.js";
|
|
370
|
+
import {
|
|
371
|
+
defaultModelId,
|
|
372
|
+
modelIdForProfile
|
|
373
|
+
} from "./chunk-D4YV5TDV.js";
|
|
374
|
+
import "./chunk-FFYDRLXW.js";
|
|
375
|
+
import "./chunk-HKFLRIBD.js";
|
|
372
376
|
import {
|
|
373
377
|
pluginCatalogRuntime
|
|
374
|
-
} from "./chunk-
|
|
375
|
-
import "./chunk-
|
|
378
|
+
} from "./chunk-NRMAOGRS.js";
|
|
379
|
+
import "./chunk-64WF2GQ3.js";
|
|
376
380
|
import {
|
|
377
381
|
credentialContextForActor
|
|
378
382
|
} from "./chunk-CEMMLV5L.js";
|
|
@@ -380,6 +384,7 @@ import {
|
|
|
380
384
|
createActor,
|
|
381
385
|
createSlackActor,
|
|
382
386
|
createSlackResumeActor,
|
|
387
|
+
isActorUserId,
|
|
383
388
|
parseActorUserId,
|
|
384
389
|
parseSlackChannelId,
|
|
385
390
|
parseSlackMessageTs
|
|
@@ -407,13 +412,13 @@ import {
|
|
|
407
412
|
withContext,
|
|
408
413
|
withLogContext,
|
|
409
414
|
withSpan
|
|
410
|
-
} from "./chunk-
|
|
415
|
+
} from "./chunk-3CVEE6LA.js";
|
|
411
416
|
import {
|
|
412
417
|
continueTrace
|
|
413
418
|
} from "./chunk-PEQXYSSE.js";
|
|
414
419
|
import {
|
|
415
420
|
JUNIOR_VERSION
|
|
416
|
-
} from "./chunk-
|
|
421
|
+
} from "./chunk-YXSBZRP7.js";
|
|
417
422
|
|
|
418
423
|
// src/app.ts
|
|
419
424
|
import { createRequire } from "module";
|
|
@@ -2741,9 +2746,831 @@ async function GET6(request) {
|
|
|
2741
2746
|
// src/chat/ingress/slack-webhook.ts
|
|
2742
2747
|
import {
|
|
2743
2748
|
ChannelImpl,
|
|
2744
|
-
ThreadImpl
|
|
2749
|
+
ThreadImpl as ThreadImpl3
|
|
2745
2750
|
} from "chat";
|
|
2746
2751
|
|
|
2752
|
+
// src/chat/task-execution/slack-work.ts
|
|
2753
|
+
import {
|
|
2754
|
+
Message as Message3,
|
|
2755
|
+
ThreadImpl as ThreadImpl2
|
|
2756
|
+
} from "chat";
|
|
2757
|
+
import { z as z3 } from "zod";
|
|
2758
|
+
|
|
2759
|
+
// src/chat/ingress/message-router.ts
|
|
2760
|
+
import { Message } from "chat";
|
|
2761
|
+
function withNormalizedThreadId(message, threadId) {
|
|
2762
|
+
if (message.threadId === threadId) {
|
|
2763
|
+
return message;
|
|
2764
|
+
}
|
|
2765
|
+
return new Message({
|
|
2766
|
+
attachments: message.attachments,
|
|
2767
|
+
author: message.author,
|
|
2768
|
+
formatted: message.formatted,
|
|
2769
|
+
id: message.id,
|
|
2770
|
+
isMention: message.isMention,
|
|
2771
|
+
links: message.links,
|
|
2772
|
+
metadata: message.metadata,
|
|
2773
|
+
raw: message.raw,
|
|
2774
|
+
text: message.text,
|
|
2775
|
+
threadId
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
function normalizeIncomingSlackThreadId(threadId, message) {
|
|
2779
|
+
if (!threadId.startsWith("slack:")) {
|
|
2780
|
+
return threadId;
|
|
2781
|
+
}
|
|
2782
|
+
if (!message || typeof message !== "object") {
|
|
2783
|
+
return threadId;
|
|
2784
|
+
}
|
|
2785
|
+
const raw = message.raw;
|
|
2786
|
+
if (!raw || typeof raw !== "object") {
|
|
2787
|
+
return threadId;
|
|
2788
|
+
}
|
|
2789
|
+
const channelId = nonEmptyString(raw.channel);
|
|
2790
|
+
const threadTs = nonEmptyString(raw.thread_ts) ?? nonEmptyString(raw.ts);
|
|
2791
|
+
if (!channelId || !threadTs) {
|
|
2792
|
+
return threadId;
|
|
2793
|
+
}
|
|
2794
|
+
return `slack:${channelId}:${threadTs}`;
|
|
2795
|
+
}
|
|
2796
|
+
function nonEmptyString(value) {
|
|
2797
|
+
if (typeof value !== "string") return void 0;
|
|
2798
|
+
const trimmed = value.trim();
|
|
2799
|
+
return trimmed || void 0;
|
|
2800
|
+
}
|
|
2801
|
+
|
|
2802
|
+
// src/chat/slack/attachment-fetchers.ts
|
|
2803
|
+
function rehydrateAttachmentFetchers(message, downloadPrivateSlackFile2 = downloadPrivateSlackFile) {
|
|
2804
|
+
for (const attachment of message.attachments) {
|
|
2805
|
+
if (!attachment.fetchData && attachment.url) {
|
|
2806
|
+
attachment.fetchData = () => downloadPrivateSlackFile2(attachment.url);
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
// src/chat/slack/adapter-context.ts
|
|
2812
|
+
var initializedAdapters = /* @__PURE__ */ new WeakSet();
|
|
2813
|
+
async function getConnectedState(stateAdapter) {
|
|
2814
|
+
const state = stateAdapter ?? getStateAdapter();
|
|
2815
|
+
await state.connect();
|
|
2816
|
+
return state;
|
|
2817
|
+
}
|
|
2818
|
+
async function ensureSlackAdapterInitialized(args) {
|
|
2819
|
+
if (initializedAdapters.has(args.adapter)) {
|
|
2820
|
+
return;
|
|
2821
|
+
}
|
|
2822
|
+
const state = await getConnectedState(args.state);
|
|
2823
|
+
await args.adapter.initialize({
|
|
2824
|
+
getState: () => state
|
|
2825
|
+
});
|
|
2826
|
+
const internals = args.adapter;
|
|
2827
|
+
if (internals.defaultBotTokenProvider && !args.adapter.botUserId) {
|
|
2828
|
+
throw new Error("Slack adapter initialized without a resolved bot user id");
|
|
2829
|
+
}
|
|
2830
|
+
initializedAdapters.add(args.adapter);
|
|
2831
|
+
}
|
|
2832
|
+
function verifySlackSignature(args) {
|
|
2833
|
+
const internals = args.adapter;
|
|
2834
|
+
const verifySignature = internals.verifySignature;
|
|
2835
|
+
if (!verifySignature) {
|
|
2836
|
+
throw new Error("Slack adapter does not expose signature verification");
|
|
2837
|
+
}
|
|
2838
|
+
return verifySignature.call(
|
|
2839
|
+
args.adapter,
|
|
2840
|
+
args.body,
|
|
2841
|
+
args.request.headers.get("x-slack-request-timestamp"),
|
|
2842
|
+
args.request.headers.get("x-slack-signature")
|
|
2843
|
+
);
|
|
2844
|
+
}
|
|
2845
|
+
async function runWithSlackInstallation(args) {
|
|
2846
|
+
await ensureSlackAdapterInitialized({
|
|
2847
|
+
adapter: args.adapter,
|
|
2848
|
+
state: args.state
|
|
2849
|
+
});
|
|
2850
|
+
const internals = args.adapter;
|
|
2851
|
+
if (internals.defaultBotTokenProvider) {
|
|
2852
|
+
return await args.task();
|
|
2853
|
+
}
|
|
2854
|
+
const installationId = args.installation.isEnterpriseInstall ? args.installation.enterpriseId : args.installation.teamId;
|
|
2855
|
+
if (!installationId) {
|
|
2856
|
+
throw new Error("Slack installation context is missing team id");
|
|
2857
|
+
}
|
|
2858
|
+
if (!internals.resolveTokenForTeam || !internals.requestContext) {
|
|
2859
|
+
throw new Error("Slack adapter cannot resolve workspace installations");
|
|
2860
|
+
}
|
|
2861
|
+
const tokenContext = await internals.resolveTokenForTeam.call(
|
|
2862
|
+
args.adapter,
|
|
2863
|
+
installationId,
|
|
2864
|
+
args.installation.isEnterpriseInstall
|
|
2865
|
+
);
|
|
2866
|
+
if (!tokenContext) {
|
|
2867
|
+
throw new Error(
|
|
2868
|
+
`Slack installation token was not found for ${installationId}`
|
|
2869
|
+
);
|
|
2870
|
+
}
|
|
2871
|
+
return await internals.requestContext.run(
|
|
2872
|
+
{
|
|
2873
|
+
...tokenContext,
|
|
2874
|
+
enterpriseId: args.installation.enterpriseId,
|
|
2875
|
+
isEnterpriseInstall: args.installation.isEnterpriseInstall
|
|
2876
|
+
},
|
|
2877
|
+
() => runWithSlackInstallationToken(tokenContext.token, args.task)
|
|
2878
|
+
);
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
// src/chat/services/message-actor-identity.ts
|
|
2882
|
+
var messageActors = /* @__PURE__ */ new WeakMap();
|
|
2883
|
+
function canonicalUserId(author, actor) {
|
|
2884
|
+
const authorUserId = parseActorUserId(author.userId);
|
|
2885
|
+
if (authorUserId && authorUserId !== actor.userId) {
|
|
2886
|
+
throw new Error("Message actor user id mismatch");
|
|
2887
|
+
}
|
|
2888
|
+
const userId = authorUserId ?? actor.userId;
|
|
2889
|
+
if (!userId) {
|
|
2890
|
+
throw new Error("Message actor requires a user id");
|
|
2891
|
+
}
|
|
2892
|
+
return userId;
|
|
2893
|
+
}
|
|
2894
|
+
function actorFromAuthor(author) {
|
|
2895
|
+
const userId = parseActorUserId(author.userId);
|
|
2896
|
+
return userId ? { userId } : void 0;
|
|
2897
|
+
}
|
|
2898
|
+
function applyActorToAuthor(author, actor) {
|
|
2899
|
+
if (!isActorUserId(actor.userId)) {
|
|
2900
|
+
throw new Error("Message actor requires a user id");
|
|
2901
|
+
}
|
|
2902
|
+
author.userId = actor.userId;
|
|
2903
|
+
author.userName = actor.userName ?? "";
|
|
2904
|
+
author.fullName = actor.fullName ?? "";
|
|
2905
|
+
}
|
|
2906
|
+
function bindMessageActorIdentity(message, actor) {
|
|
2907
|
+
const userId = canonicalUserId(message.author, actor);
|
|
2908
|
+
const currentActor = createActor(actor, {
|
|
2909
|
+
platform: actor.platform,
|
|
2910
|
+
...actor.platform === "slack" ? { teamId: actor.teamId } : void 0,
|
|
2911
|
+
userId
|
|
2912
|
+
});
|
|
2913
|
+
if (!currentActor) {
|
|
2914
|
+
throw new Error("Message actor requires a user id");
|
|
2915
|
+
}
|
|
2916
|
+
messageActors.set(message, currentActor);
|
|
2917
|
+
applyActorToAuthor(message.author, currentActor);
|
|
2918
|
+
return currentActor;
|
|
2919
|
+
}
|
|
2920
|
+
function getMessageActorIdentity(message) {
|
|
2921
|
+
return messageActors.get(message) ?? actorFromAuthor(message.author);
|
|
2922
|
+
}
|
|
2923
|
+
async function ensureSlackMessageActorIdentity(message, teamId, lookupSlackUser2) {
|
|
2924
|
+
const existing = messageActors.get(message);
|
|
2925
|
+
if (existing) {
|
|
2926
|
+
if (existing.platform !== "slack") {
|
|
2927
|
+
throw new Error("Slack message actor identity requires a Slack actor");
|
|
2928
|
+
}
|
|
2929
|
+
return existing;
|
|
2930
|
+
}
|
|
2931
|
+
const userId = parseActorUserId(message.author.userId);
|
|
2932
|
+
if (!userId) {
|
|
2933
|
+
throw new Error("Slack message actor identity requires a user id");
|
|
2934
|
+
}
|
|
2935
|
+
const actor = bindMessageActorIdentity(
|
|
2936
|
+
message,
|
|
2937
|
+
createSlackActor(teamId, userId, await lookupSlackUser2(teamId, userId))
|
|
2938
|
+
);
|
|
2939
|
+
if (actor.platform !== "slack") {
|
|
2940
|
+
throw new Error("Slack message actor identity requires a Slack actor");
|
|
2941
|
+
}
|
|
2942
|
+
return actor;
|
|
2943
|
+
}
|
|
2944
|
+
|
|
2945
|
+
// src/chat/task-execution/slack-resource-event.ts
|
|
2946
|
+
import { Message as Message2, ThreadImpl } from "chat";
|
|
2947
|
+
async function resolveSlackResourceEventThread(args) {
|
|
2948
|
+
const routing = await resolveConversationRouting({
|
|
2949
|
+
conversationId: args.conversationId,
|
|
2950
|
+
conversationStore: args.conversationStore
|
|
2951
|
+
});
|
|
2952
|
+
const destination = requireSlackDestination(
|
|
2953
|
+
routing?.destination ?? args.destination,
|
|
2954
|
+
"Slack resource-event turn"
|
|
2955
|
+
);
|
|
2956
|
+
const threadTs = routing?.source?.platform === "slack" ? routing.source.threadTs?.trim() : void 0;
|
|
2957
|
+
if (!threadTs) {
|
|
2958
|
+
throw new Error(
|
|
2959
|
+
`Conversation ${args.conversationId} is missing a Slack thread for resource-event delivery`
|
|
2960
|
+
);
|
|
2961
|
+
}
|
|
2962
|
+
return { destination, threadTs };
|
|
2963
|
+
}
|
|
2964
|
+
function isPlainResourceEventRecord(record) {
|
|
2965
|
+
return record.source === "resource_event" && isResourceEventMailboxMetadata(record.input.metadata) && !hasSlackConversationMetadata(record.input.metadata);
|
|
2966
|
+
}
|
|
2967
|
+
function hasSlackConversationMetadata(value) {
|
|
2968
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2969
|
+
return false;
|
|
2970
|
+
}
|
|
2971
|
+
const record = value;
|
|
2972
|
+
return record.platform === "slack" && typeof record.thread === "object" && record.thread !== null && typeof record.message === "object" && record.message !== null;
|
|
2973
|
+
}
|
|
2974
|
+
function buildResourceEventSlackMessage(args) {
|
|
2975
|
+
if (!isResourceEventMailboxMetadata(args.record.input.metadata)) {
|
|
2976
|
+
throw new Error(
|
|
2977
|
+
"Resource-event Slack turn requires resource-event metadata"
|
|
2978
|
+
);
|
|
2979
|
+
}
|
|
2980
|
+
const event = args.record.input.metadata.resourceEvent;
|
|
2981
|
+
const messageId = `resource-event-${event.subscriptionId}-${event.eventKey}`;
|
|
2982
|
+
const threadId = `slack:${args.channelId}:${args.threadTs}`;
|
|
2983
|
+
return new Message2({
|
|
2984
|
+
id: messageId,
|
|
2985
|
+
threadId,
|
|
2986
|
+
text: args.record.input.text,
|
|
2987
|
+
author: {
|
|
2988
|
+
userId: RESOURCE_EVENT_AUTHOR_ID,
|
|
2989
|
+
userName: "junior-event",
|
|
2990
|
+
fullName: "Junior event",
|
|
2991
|
+
isBot: true,
|
|
2992
|
+
isMe: false
|
|
2993
|
+
},
|
|
2994
|
+
isMention: false,
|
|
2995
|
+
attachments: [],
|
|
2996
|
+
metadata: {
|
|
2997
|
+
dateSent: new Date(args.record.createdAtMs),
|
|
2998
|
+
edited: false
|
|
2999
|
+
},
|
|
3000
|
+
formatted: { type: "root", children: [] },
|
|
3001
|
+
raw: {
|
|
3002
|
+
channel: args.channelId,
|
|
3003
|
+
event_type: "resource_event",
|
|
3004
|
+
resource_event_type: event.eventType,
|
|
3005
|
+
thread_ts: args.threadTs,
|
|
3006
|
+
type: "message",
|
|
3007
|
+
user: RESOURCE_EVENT_AUTHOR_ID
|
|
3008
|
+
}
|
|
3009
|
+
});
|
|
3010
|
+
}
|
|
3011
|
+
function buildResourceEventSlackThread(args) {
|
|
3012
|
+
const threadId = normalizeIncomingSlackThreadId(
|
|
3013
|
+
`slack:${args.channelId}:${args.threadTs}`,
|
|
3014
|
+
args.message
|
|
3015
|
+
);
|
|
3016
|
+
const message = withNormalizedThreadId(args.message, threadId);
|
|
3017
|
+
return new ThreadImpl({
|
|
3018
|
+
adapter: args.adapter,
|
|
3019
|
+
stateAdapter: args.state,
|
|
3020
|
+
id: threadId,
|
|
3021
|
+
channelId: args.channelId,
|
|
3022
|
+
currentMessage: message,
|
|
3023
|
+
initialMessage: message,
|
|
3024
|
+
isDM: args.channelId.startsWith("D"),
|
|
3025
|
+
isSubscribedContext: true
|
|
3026
|
+
});
|
|
3027
|
+
}
|
|
3028
|
+
|
|
3029
|
+
// src/chat/slack/message-control.ts
|
|
3030
|
+
var LEADING_MENTION_BEFORE_STEERING_RE = /^(\s*(?:<@[^>]+>|@[A-Za-z0-9._-]+\b)[\s,:-]*)!!\s*/;
|
|
3031
|
+
function stripLeadingSteeringOverride(text) {
|
|
3032
|
+
return text.replace(LEADING_MENTION_BEFORE_STEERING_RE, "$1").replace(/^\s*!!\s*/, "");
|
|
3033
|
+
}
|
|
3034
|
+
|
|
3035
|
+
// src/chat/task-execution/slack-work.ts
|
|
3036
|
+
var slackConversationRouteSchema = z3.enum(["mention", "subscribed"]);
|
|
3037
|
+
function hasSteeringOverride(text) {
|
|
3038
|
+
return stripLeadingSteeringOverride(text) !== text;
|
|
3039
|
+
}
|
|
3040
|
+
var serializedDateSchema = z3.iso.datetime();
|
|
3041
|
+
var mdastPointSchema = z3.object({
|
|
3042
|
+
column: z3.number().int().positive(),
|
|
3043
|
+
line: z3.number().int().positive(),
|
|
3044
|
+
offset: z3.number().int().nonnegative().optional()
|
|
3045
|
+
}).strict();
|
|
3046
|
+
var mdastPositionSchema = z3.object({
|
|
3047
|
+
end: mdastPointSchema,
|
|
3048
|
+
start: mdastPointSchema
|
|
3049
|
+
}).strict();
|
|
3050
|
+
function isOptionalNullableString(value) {
|
|
3051
|
+
return value === void 0 || value === null || typeof value === "string";
|
|
3052
|
+
}
|
|
3053
|
+
function isOptionalNullableBoolean(value) {
|
|
3054
|
+
return value === void 0 || value === null || typeof value === "boolean";
|
|
3055
|
+
}
|
|
3056
|
+
function hasValidMdastBase(node, fields) {
|
|
3057
|
+
const allowed = /* @__PURE__ */ new Set(["data", "position", "type", ...fields]);
|
|
3058
|
+
return Object.keys(node).every((key) => allowed.has(key)) && (node.data === void 0 || typeof node.data === "object" && node.data !== null && !Array.isArray(node.data)) && (node.position === void 0 || mdastPositionSchema.safeParse(node.position).success);
|
|
3059
|
+
}
|
|
3060
|
+
var mdastPhrasingTypes = /* @__PURE__ */ new Set([
|
|
3061
|
+
"break",
|
|
3062
|
+
"delete",
|
|
3063
|
+
"emphasis",
|
|
3064
|
+
"footnoteReference",
|
|
3065
|
+
"html",
|
|
3066
|
+
"image",
|
|
3067
|
+
"imageReference",
|
|
3068
|
+
"inlineCode",
|
|
3069
|
+
"link",
|
|
3070
|
+
"linkReference",
|
|
3071
|
+
"strong",
|
|
3072
|
+
"text"
|
|
3073
|
+
]);
|
|
3074
|
+
var mdastBlockOrDefinitionTypes = /* @__PURE__ */ new Set([
|
|
3075
|
+
"blockquote",
|
|
3076
|
+
"code",
|
|
3077
|
+
"definition",
|
|
3078
|
+
"footnoteDefinition",
|
|
3079
|
+
"heading",
|
|
3080
|
+
"html",
|
|
3081
|
+
"list",
|
|
3082
|
+
"paragraph",
|
|
3083
|
+
"table",
|
|
3084
|
+
"thematicBreak"
|
|
3085
|
+
]);
|
|
3086
|
+
var mdastListItemTypes = /* @__PURE__ */ new Set(["listItem"]);
|
|
3087
|
+
var mdastTableCellTypes = /* @__PURE__ */ new Set(["tableCell"]);
|
|
3088
|
+
var mdastTableRowTypes = /* @__PURE__ */ new Set(["tableRow"]);
|
|
3089
|
+
function hasMdastChildren(node, allowedTypes) {
|
|
3090
|
+
return Array.isArray(node.children) && node.children.every(
|
|
3091
|
+
(child) => isFormattedContentNode(child) && (!allowedTypes || typeof child === "object" && child !== null && !Array.isArray(child) && allowedTypes.has(String(child.type)))
|
|
3092
|
+
);
|
|
3093
|
+
}
|
|
3094
|
+
function isFormattedContentNode(value) {
|
|
3095
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3096
|
+
return false;
|
|
3097
|
+
}
|
|
3098
|
+
const node = value;
|
|
3099
|
+
switch (node.type) {
|
|
3100
|
+
case "break":
|
|
3101
|
+
case "thematicBreak":
|
|
3102
|
+
return hasValidMdastBase(node, []);
|
|
3103
|
+
case "html":
|
|
3104
|
+
case "inlineCode":
|
|
3105
|
+
case "text":
|
|
3106
|
+
case "yaml":
|
|
3107
|
+
return hasValidMdastBase(node, ["value"]) && typeof node.value === "string";
|
|
3108
|
+
case "code":
|
|
3109
|
+
return hasValidMdastBase(node, ["lang", "meta", "value"]) && typeof node.value === "string" && isOptionalNullableString(node.lang) && isOptionalNullableString(node.meta);
|
|
3110
|
+
case "delete":
|
|
3111
|
+
case "emphasis":
|
|
3112
|
+
case "paragraph":
|
|
3113
|
+
case "strong":
|
|
3114
|
+
case "tableCell":
|
|
3115
|
+
return hasValidMdastBase(node, ["children"]) && hasMdastChildren(node, mdastPhrasingTypes);
|
|
3116
|
+
case "blockquote":
|
|
3117
|
+
return hasValidMdastBase(node, ["children"]) && hasMdastChildren(node, mdastBlockOrDefinitionTypes);
|
|
3118
|
+
case "tableRow":
|
|
3119
|
+
return hasValidMdastBase(node, ["children"]) && hasMdastChildren(node, mdastTableCellTypes);
|
|
3120
|
+
case "heading":
|
|
3121
|
+
return hasValidMdastBase(node, ["children", "depth"]) && hasMdastChildren(node, mdastPhrasingTypes) && Number.isInteger(node.depth) && Number(node.depth) >= 1 && Number(node.depth) <= 6;
|
|
3122
|
+
case "list":
|
|
3123
|
+
return hasValidMdastBase(node, ["children", "ordered", "spread", "start"]) && hasMdastChildren(node, mdastListItemTypes) && isOptionalNullableBoolean(node.ordered) && isOptionalNullableBoolean(node.spread) && (node.start === void 0 || node.start === null || typeof node.start === "number" && Number.isFinite(node.start));
|
|
3124
|
+
case "listItem":
|
|
3125
|
+
return hasValidMdastBase(node, ["checked", "children", "spread"]) && hasMdastChildren(node, mdastBlockOrDefinitionTypes) && isOptionalNullableBoolean(node.checked) && isOptionalNullableBoolean(node.spread);
|
|
3126
|
+
case "table":
|
|
3127
|
+
return hasValidMdastBase(node, ["align", "children"]) && hasMdastChildren(node, mdastTableRowTypes) && (node.align === void 0 || node.align === null || Array.isArray(node.align) && node.align.every(
|
|
3128
|
+
(align) => align === null || align === "center" || align === "left" || align === "right"
|
|
3129
|
+
));
|
|
3130
|
+
case "definition":
|
|
3131
|
+
return hasValidMdastBase(node, ["identifier", "label", "title", "url"]) && typeof node.identifier === "string" && typeof node.url === "string" && isOptionalNullableString(node.label) && isOptionalNullableString(node.title);
|
|
3132
|
+
case "footnoteDefinition":
|
|
3133
|
+
return hasValidMdastBase(node, ["children", "identifier", "label"]) && hasMdastChildren(node, mdastBlockOrDefinitionTypes) && typeof node.identifier === "string" && isOptionalNullableString(node.label);
|
|
3134
|
+
case "footnoteReference":
|
|
3135
|
+
return hasValidMdastBase(node, ["identifier", "label"]) && typeof node.identifier === "string" && isOptionalNullableString(node.label);
|
|
3136
|
+
case "image":
|
|
3137
|
+
return hasValidMdastBase(node, ["alt", "title", "url"]) && typeof node.url === "string" && isOptionalNullableString(node.alt) && isOptionalNullableString(node.title);
|
|
3138
|
+
case "imageReference":
|
|
3139
|
+
return hasValidMdastBase(node, [
|
|
3140
|
+
"alt",
|
|
3141
|
+
"identifier",
|
|
3142
|
+
"label",
|
|
3143
|
+
"referenceType"
|
|
3144
|
+
]) && typeof node.identifier === "string" && isOptionalNullableString(node.alt) && isOptionalNullableString(node.label) && (node.referenceType === "collapsed" || node.referenceType === "full" || node.referenceType === "shortcut");
|
|
3145
|
+
case "link":
|
|
3146
|
+
return hasValidMdastBase(node, ["children", "title", "url"]) && hasMdastChildren(node, mdastPhrasingTypes) && typeof node.url === "string" && isOptionalNullableString(node.title);
|
|
3147
|
+
case "linkReference":
|
|
3148
|
+
return hasValidMdastBase(node, [
|
|
3149
|
+
"children",
|
|
3150
|
+
"identifier",
|
|
3151
|
+
"label",
|
|
3152
|
+
"referenceType"
|
|
3153
|
+
]) && hasMdastChildren(node, mdastPhrasingTypes) && typeof node.identifier === "string" && isOptionalNullableString(node.label) && (node.referenceType === "collapsed" || node.referenceType === "full" || node.referenceType === "shortcut");
|
|
3154
|
+
default:
|
|
3155
|
+
return false;
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
var formattedContentSchema = z3.custom(
|
|
3159
|
+
(value) => {
|
|
3160
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3161
|
+
return false;
|
|
3162
|
+
}
|
|
3163
|
+
const root = value;
|
|
3164
|
+
return root.type === "root" && hasValidMdastBase(root, ["children"]) && hasMdastChildren(root);
|
|
3165
|
+
},
|
|
3166
|
+
"must be a valid formatted-content root"
|
|
3167
|
+
);
|
|
3168
|
+
var serializedMessageSchema = z3.object({
|
|
3169
|
+
_type: z3.literal("chat:Message"),
|
|
3170
|
+
attachments: z3.array(
|
|
3171
|
+
z3.object({
|
|
3172
|
+
type: z3.enum(["image", "file", "video", "audio"]),
|
|
3173
|
+
url: z3.string().optional(),
|
|
3174
|
+
name: z3.string().optional(),
|
|
3175
|
+
mimeType: z3.string().optional(),
|
|
3176
|
+
size: z3.number().finite().optional(),
|
|
3177
|
+
width: z3.number().finite().optional(),
|
|
3178
|
+
height: z3.number().finite().optional(),
|
|
3179
|
+
fetchMetadata: z3.record(z3.string(), z3.string()).optional()
|
|
3180
|
+
}).strict()
|
|
3181
|
+
),
|
|
3182
|
+
author: z3.object({
|
|
3183
|
+
userId: z3.string(),
|
|
3184
|
+
userName: z3.string(),
|
|
3185
|
+
fullName: z3.string(),
|
|
3186
|
+
isBot: z3.union([z3.boolean(), z3.literal("unknown")]),
|
|
3187
|
+
isMe: z3.boolean()
|
|
3188
|
+
}).strict(),
|
|
3189
|
+
formatted: formattedContentSchema,
|
|
3190
|
+
id: z3.string().min(1),
|
|
3191
|
+
isMention: z3.boolean().optional(),
|
|
3192
|
+
links: z3.array(
|
|
3193
|
+
z3.object({
|
|
3194
|
+
url: z3.string(),
|
|
3195
|
+
title: z3.string().optional(),
|
|
3196
|
+
description: z3.string().optional(),
|
|
3197
|
+
imageUrl: z3.string().optional(),
|
|
3198
|
+
siteName: z3.string().optional()
|
|
3199
|
+
}).strict()
|
|
3200
|
+
).optional(),
|
|
3201
|
+
metadata: z3.object({
|
|
3202
|
+
dateSent: serializedDateSchema,
|
|
3203
|
+
edited: z3.boolean(),
|
|
3204
|
+
editedAt: serializedDateSchema.optional()
|
|
3205
|
+
}).strict(),
|
|
3206
|
+
raw: z3.unknown(),
|
|
3207
|
+
text: z3.string(),
|
|
3208
|
+
threadId: z3.string().min(1)
|
|
3209
|
+
}).strict();
|
|
3210
|
+
var serializedThreadSchema = z3.object({
|
|
3211
|
+
_type: z3.literal("chat:Thread"),
|
|
3212
|
+
adapterName: z3.literal("slack"),
|
|
3213
|
+
channelId: z3.string().min(1),
|
|
3214
|
+
channelVisibility: z3.enum(["private", "workspace", "external", "unknown"]).optional(),
|
|
3215
|
+
currentMessage: serializedMessageSchema.optional(),
|
|
3216
|
+
id: z3.string().min(1),
|
|
3217
|
+
isDM: z3.boolean()
|
|
3218
|
+
}).strict();
|
|
3219
|
+
var slackInstallationSchema = z3.object({
|
|
3220
|
+
enterpriseId: z3.string().optional(),
|
|
3221
|
+
isEnterpriseInstall: z3.boolean().optional(),
|
|
3222
|
+
teamId: z3.string().optional()
|
|
3223
|
+
}).strict();
|
|
3224
|
+
var slackConversationMessageMetadataBaseSchema = z3.object({
|
|
3225
|
+
installation: slackInstallationSchema.optional(),
|
|
3226
|
+
message: serializedMessageSchema,
|
|
3227
|
+
platform: z3.literal("slack"),
|
|
3228
|
+
route: slackConversationRouteSchema,
|
|
3229
|
+
thread: serializedThreadSchema
|
|
3230
|
+
});
|
|
3231
|
+
var slackConversationMessageMetadataSchema = z3.union([
|
|
3232
|
+
slackConversationMessageMetadataBaseSchema.strict(),
|
|
3233
|
+
slackConversationMessageMetadataBaseSchema.extend({
|
|
3234
|
+
kind: z3.literal("resource_event"),
|
|
3235
|
+
resourceEvent: z3.object({
|
|
3236
|
+
eventKey: z3.string(),
|
|
3237
|
+
eventType: z3.string(),
|
|
3238
|
+
namespace: z3.string(),
|
|
3239
|
+
identifier: z3.string(),
|
|
3240
|
+
subscriptionId: z3.string()
|
|
3241
|
+
}).strict()
|
|
3242
|
+
}).strict()
|
|
3243
|
+
]);
|
|
3244
|
+
function requireSlackAuthorId(message) {
|
|
3245
|
+
const authorId = parseActorUserId(message.author.userId);
|
|
3246
|
+
if (!authorId) {
|
|
3247
|
+
throw new Error("Slack message requires an actor user id");
|
|
3248
|
+
}
|
|
3249
|
+
return authorId;
|
|
3250
|
+
}
|
|
3251
|
+
function getConnectedState2(stateAdapter) {
|
|
3252
|
+
return stateAdapter ?? getStateAdapter();
|
|
3253
|
+
}
|
|
3254
|
+
function parseSlackMetadata(value) {
|
|
3255
|
+
const parsed = slackConversationMessageMetadataSchema.safeParse(value);
|
|
3256
|
+
return parsed.success ? parsed.data : void 0;
|
|
3257
|
+
}
|
|
3258
|
+
function compareInboundMessages(left, right) {
|
|
3259
|
+
return left.createdAtMs - right.createdAtMs || left.receivedAtMs - right.receivedAtMs || left.inboundMessageId.localeCompare(right.inboundMessageId);
|
|
3260
|
+
}
|
|
3261
|
+
function routeForRecords(records) {
|
|
3262
|
+
return records.some((record) => {
|
|
3263
|
+
if (isPlainResourceEventRecord(record)) {
|
|
3264
|
+
return false;
|
|
3265
|
+
}
|
|
3266
|
+
const metadata = parseSlackMetadata(record.input.metadata);
|
|
3267
|
+
if (!metadata) {
|
|
3268
|
+
throw new Error("Conversation mailbox record is not Slack metadata");
|
|
3269
|
+
}
|
|
3270
|
+
return metadata.route === "mention";
|
|
3271
|
+
}) ? "mention" : "subscribed";
|
|
3272
|
+
}
|
|
3273
|
+
function restoreMessage(args) {
|
|
3274
|
+
if (isPlainResourceEventRecord(args.record)) {
|
|
3275
|
+
if (!args.threadTs) {
|
|
3276
|
+
throw new Error(
|
|
3277
|
+
"Resource-event Slack turn requires a thread timestamp"
|
|
3278
|
+
);
|
|
3279
|
+
}
|
|
3280
|
+
return buildResourceEventSlackMessage({
|
|
3281
|
+
channelId: args.channelId,
|
|
3282
|
+
record: args.record,
|
|
3283
|
+
threadTs: args.threadTs
|
|
3284
|
+
});
|
|
3285
|
+
}
|
|
3286
|
+
const metadata = parseSlackMetadata(args.record.input.metadata);
|
|
3287
|
+
if (!metadata) {
|
|
3288
|
+
throw new Error("Conversation mailbox record is not a Slack message");
|
|
3289
|
+
}
|
|
3290
|
+
const message = Message3.fromJSON(metadata.message);
|
|
3291
|
+
message.attachments = message.attachments.map(
|
|
3292
|
+
(attachment) => args.adapter.rehydrateAttachment(attachment)
|
|
3293
|
+
);
|
|
3294
|
+
rehydrateAttachmentFetchers(message);
|
|
3295
|
+
return message;
|
|
3296
|
+
}
|
|
3297
|
+
async function bindSlackActorIdentities(args) {
|
|
3298
|
+
const byAuthorId = /* @__PURE__ */ new Map();
|
|
3299
|
+
for (const message of args.messages) {
|
|
3300
|
+
if (isResourceEventSlackMessage(message)) {
|
|
3301
|
+
continue;
|
|
3302
|
+
}
|
|
3303
|
+
const authorId = requireSlackAuthorId(message);
|
|
3304
|
+
byAuthorId.set(authorId, [...byAuthorId.get(authorId) ?? [], message]);
|
|
3305
|
+
}
|
|
3306
|
+
await Promise.all(
|
|
3307
|
+
[...byAuthorId].map(async ([authorId, messages]) => {
|
|
3308
|
+
const profile = await args.lookupSlackUser(args.teamId, authorId);
|
|
3309
|
+
await Promise.all(
|
|
3310
|
+
messages.map(
|
|
3311
|
+
(message) => ensureSlackMessageActorIdentity(
|
|
3312
|
+
message,
|
|
3313
|
+
args.teamId,
|
|
3314
|
+
async () => profile
|
|
3315
|
+
)
|
|
3316
|
+
)
|
|
3317
|
+
);
|
|
3318
|
+
})
|
|
3319
|
+
);
|
|
3320
|
+
}
|
|
3321
|
+
function restoreThread(args) {
|
|
3322
|
+
const threadId = normalizeIncomingSlackThreadId(
|
|
3323
|
+
args.threadJson.id,
|
|
3324
|
+
args.message
|
|
3325
|
+
);
|
|
3326
|
+
const message = withNormalizedThreadId(args.message, threadId);
|
|
3327
|
+
return new ThreadImpl2({
|
|
3328
|
+
adapter: args.adapter,
|
|
3329
|
+
stateAdapter: args.state,
|
|
3330
|
+
id: threadId,
|
|
3331
|
+
channelId: args.threadJson.channelId,
|
|
3332
|
+
channelVisibility: args.threadJson.channelVisibility,
|
|
3333
|
+
currentMessage: message,
|
|
3334
|
+
initialMessage: message,
|
|
3335
|
+
isDM: args.threadJson.isDM,
|
|
3336
|
+
isSubscribedContext: args.isSubscribedContext
|
|
3337
|
+
});
|
|
3338
|
+
}
|
|
3339
|
+
function getInstallation(records) {
|
|
3340
|
+
for (let index = records.length - 1; index >= 0; index -= 1) {
|
|
3341
|
+
const metadata = parseSlackMetadata(records[index]?.input.metadata);
|
|
3342
|
+
if (metadata?.installation) {
|
|
3343
|
+
return metadata.installation;
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
return {};
|
|
3347
|
+
}
|
|
3348
|
+
function getPendingRecords(work) {
|
|
3349
|
+
if (!work) {
|
|
3350
|
+
return [];
|
|
3351
|
+
}
|
|
3352
|
+
return work.execution.pendingMessages.sort(compareInboundMessages);
|
|
3353
|
+
}
|
|
3354
|
+
function createSlackConversationWorker(options) {
|
|
3355
|
+
const crossActorMidRunMode = options.crossActorMidRunMode ?? botConfig.crossActorMidRunMode;
|
|
3356
|
+
return async (context) => {
|
|
3357
|
+
const adapter = options.getSlackAdapter();
|
|
3358
|
+
const actorLookup = options.lookupSlackUser ?? lookupSlackUser;
|
|
3359
|
+
const state = getConnectedState2(options.state);
|
|
3360
|
+
await state.connect();
|
|
3361
|
+
const records = getPendingRecords({
|
|
3362
|
+
execution: { pendingMessages: [...context.attempt.messages] }
|
|
3363
|
+
});
|
|
3364
|
+
if (records.length === 0) {
|
|
3365
|
+
const destination = requireSlackDestination(
|
|
3366
|
+
context.destination,
|
|
3367
|
+
"Slack paused-turn recovery"
|
|
3368
|
+
);
|
|
3369
|
+
try {
|
|
3370
|
+
await runWithSlackInstallation({
|
|
3371
|
+
adapter,
|
|
3372
|
+
installation: { teamId: destination.teamId },
|
|
3373
|
+
state,
|
|
3374
|
+
task: async () => {
|
|
3375
|
+
await options.runNextPausedTurn(context.conversationId, {
|
|
3376
|
+
shouldYield: context.shouldYield
|
|
3377
|
+
});
|
|
3378
|
+
}
|
|
3379
|
+
});
|
|
3380
|
+
} catch (error) {
|
|
3381
|
+
if (isCooperativeTurnYieldError(error)) {
|
|
3382
|
+
return { status: "yielded" };
|
|
3383
|
+
}
|
|
3384
|
+
throw error;
|
|
3385
|
+
}
|
|
3386
|
+
return { status: "completed" };
|
|
3387
|
+
}
|
|
3388
|
+
const latestRecord = records[records.length - 1];
|
|
3389
|
+
if (!latestRecord) {
|
|
3390
|
+
return { status: "completed" };
|
|
3391
|
+
}
|
|
3392
|
+
const hasPlainResourceEvent = records.some(isPlainResourceEventRecord);
|
|
3393
|
+
const publishExternally = hasPlainResourceEvent ? true : latestRecord.publishExternally ?? context.publishExternally;
|
|
3394
|
+
const latestMetadata = isPlainResourceEventRecord(latestRecord) ? void 0 : parseSlackMetadata(latestRecord.input.metadata);
|
|
3395
|
+
if (!isPlainResourceEventRecord(latestRecord) && !latestMetadata) {
|
|
3396
|
+
throw new Error(
|
|
3397
|
+
"Latest conversation mailbox record is not Slack metadata"
|
|
3398
|
+
);
|
|
3399
|
+
}
|
|
3400
|
+
if (!await context.checkIn()) {
|
|
3401
|
+
return { status: "lost_lease" };
|
|
3402
|
+
}
|
|
3403
|
+
const resourceEventThread = hasPlainResourceEvent ? await resolveSlackResourceEventThread({
|
|
3404
|
+
conversationId: context.conversationId,
|
|
3405
|
+
conversationStore: options.conversationStore,
|
|
3406
|
+
destination: context.destination
|
|
3407
|
+
}) : void 0;
|
|
3408
|
+
const turnResult = await runWithSlackInstallation({
|
|
3409
|
+
adapter,
|
|
3410
|
+
installation: resourceEventThread ? { teamId: resourceEventThread.destination.teamId } : getInstallation(records),
|
|
3411
|
+
state,
|
|
3412
|
+
task: async () => {
|
|
3413
|
+
const destination = resourceEventThread?.destination ?? requireSlackDestination(
|
|
3414
|
+
context.destination,
|
|
3415
|
+
"Slack conversation work"
|
|
3416
|
+
);
|
|
3417
|
+
const threadTs = resourceEventThread?.threadTs;
|
|
3418
|
+
const messages = records.map(
|
|
3419
|
+
(record) => restoreMessage({
|
|
3420
|
+
adapter,
|
|
3421
|
+
channelId: destination.channelId,
|
|
3422
|
+
record,
|
|
3423
|
+
...threadTs ? { threadTs } : void 0
|
|
3424
|
+
})
|
|
3425
|
+
);
|
|
3426
|
+
await bindSlackActorIdentities({
|
|
3427
|
+
lookupSlackUser: actorLookup,
|
|
3428
|
+
messages,
|
|
3429
|
+
teamId: destination.teamId
|
|
3430
|
+
});
|
|
3431
|
+
const latestMessage = messages[messages.length - 1];
|
|
3432
|
+
if (!latestMessage) {
|
|
3433
|
+
return;
|
|
3434
|
+
}
|
|
3435
|
+
const route = routeForRecords(records);
|
|
3436
|
+
const thread = isPlainResourceEventRecord(latestRecord) && threadTs ? buildResourceEventSlackThread({
|
|
3437
|
+
adapter,
|
|
3438
|
+
channelId: destination.channelId,
|
|
3439
|
+
message: latestMessage,
|
|
3440
|
+
state,
|
|
3441
|
+
threadTs
|
|
3442
|
+
}) : restoreThread({
|
|
3443
|
+
adapter,
|
|
3444
|
+
isSubscribedContext: route === "subscribed",
|
|
3445
|
+
message: latestMessage,
|
|
3446
|
+
state,
|
|
3447
|
+
threadJson: latestMetadata.thread
|
|
3448
|
+
});
|
|
3449
|
+
const skipped = messages.slice(0, -1);
|
|
3450
|
+
const messageContext = {
|
|
3451
|
+
skipped,
|
|
3452
|
+
totalSinceLastHandler: messages.length
|
|
3453
|
+
};
|
|
3454
|
+
const activeAuthorId = isResourceEventSlackMessage(latestMessage) ? RESOURCE_EVENT_AUTHOR_ID : requireSlackAuthorId(latestMessage);
|
|
3455
|
+
let initialMessagesAcked = false;
|
|
3456
|
+
const ack = async () => {
|
|
3457
|
+
if (initialMessagesAcked) {
|
|
3458
|
+
return;
|
|
3459
|
+
}
|
|
3460
|
+
try {
|
|
3461
|
+
await context.attempt.ack();
|
|
3462
|
+
initialMessagesAcked = true;
|
|
3463
|
+
} catch {
|
|
3464
|
+
throw new TurnInputCommitLostError(
|
|
3465
|
+
`Conversation work lease lost before Slack inbox ack for ${context.conversationId}`
|
|
3466
|
+
);
|
|
3467
|
+
}
|
|
3468
|
+
};
|
|
3469
|
+
const drainSteeringMessages = async (accept) => {
|
|
3470
|
+
await context.attempt.drain(async (pendingRecords) => {
|
|
3471
|
+
const candidates = pendingRecords.filter(
|
|
3472
|
+
(record) => isPlainResourceEventRecord(record) ? publishExternally : record.publishExternally === publishExternally
|
|
3473
|
+
).map((record) => ({
|
|
3474
|
+
inboundMessageId: record.inboundMessageId,
|
|
3475
|
+
message: restoreMessage({
|
|
3476
|
+
adapter,
|
|
3477
|
+
channelId: destination.channelId,
|
|
3478
|
+
record,
|
|
3479
|
+
...threadTs ? { threadTs } : void 0
|
|
3480
|
+
})
|
|
3481
|
+
})).filter(
|
|
3482
|
+
(candidate) => crossActorMidRunMode === "steer" || isResourceEventSlackMessage(candidate.message) || requireSlackAuthorId(candidate.message) === activeAuthorId || hasSteeringOverride(candidate.message.text)
|
|
3483
|
+
);
|
|
3484
|
+
return candidates.length > 0 ? await accept(candidates) : [];
|
|
3485
|
+
});
|
|
3486
|
+
};
|
|
3487
|
+
try {
|
|
3488
|
+
if (route === "mention") {
|
|
3489
|
+
await options.runtime.handleNewMention(thread, latestMessage, {
|
|
3490
|
+
conversationId: context.conversationId,
|
|
3491
|
+
destination,
|
|
3492
|
+
publishExternally,
|
|
3493
|
+
messageContext,
|
|
3494
|
+
drainSteeringMessages,
|
|
3495
|
+
ack,
|
|
3496
|
+
isFinalAttempt: context.attempt.isFinalAttempt,
|
|
3497
|
+
shouldYield: context.shouldYield
|
|
3498
|
+
});
|
|
3499
|
+
} else {
|
|
3500
|
+
await options.runtime.handleSubscribedMessage(
|
|
3501
|
+
thread,
|
|
3502
|
+
latestMessage,
|
|
3503
|
+
{
|
|
3504
|
+
conversationId: context.conversationId,
|
|
3505
|
+
destination,
|
|
3506
|
+
publishExternally,
|
|
3507
|
+
messageContext,
|
|
3508
|
+
drainSteeringMessages,
|
|
3509
|
+
ack,
|
|
3510
|
+
isFinalAttempt: context.attempt.isFinalAttempt,
|
|
3511
|
+
shouldYield: context.shouldYield
|
|
3512
|
+
}
|
|
3513
|
+
);
|
|
3514
|
+
}
|
|
3515
|
+
} catch (error) {
|
|
3516
|
+
if (isTurnInputDeferredError(error)) {
|
|
3517
|
+
return { status: "deferred" };
|
|
3518
|
+
}
|
|
3519
|
+
if (isCooperativeTurnYieldError(error)) {
|
|
3520
|
+
return { status: "yielded" };
|
|
3521
|
+
}
|
|
3522
|
+
if (isTurnInputCommitLostError(error)) {
|
|
3523
|
+
return { status: "lost_lease" };
|
|
3524
|
+
}
|
|
3525
|
+
throw error;
|
|
3526
|
+
}
|
|
3527
|
+
}
|
|
3528
|
+
});
|
|
3529
|
+
if (turnResult?.status === "deferred" || turnResult?.status === "yielded" || turnResult?.status === "lost_lease") {
|
|
3530
|
+
return turnResult;
|
|
3531
|
+
}
|
|
3532
|
+
return { status: "completed" };
|
|
3533
|
+
};
|
|
3534
|
+
}
|
|
3535
|
+
function buildSlackInboundMessage(args) {
|
|
3536
|
+
const authorId = requireSlackAuthorId(args.message);
|
|
3537
|
+
const destination = createSlackDestination({
|
|
3538
|
+
channelId: args.thread.channelId,
|
|
3539
|
+
teamId: args.installation?.teamId
|
|
3540
|
+
});
|
|
3541
|
+
if (!destination) {
|
|
3542
|
+
throw new Error("Slack inbound message requires destination context");
|
|
3543
|
+
}
|
|
3544
|
+
const hasInterruptOverride = hasSteeringOverride(args.message.text);
|
|
3545
|
+
return {
|
|
3546
|
+
conversationId: args.conversationId,
|
|
3547
|
+
destination,
|
|
3548
|
+
inboundMessageId: [
|
|
3549
|
+
"slack",
|
|
3550
|
+
args.installation?.teamId ?? args.installation?.enterpriseId ?? "unknown",
|
|
3551
|
+
args.conversationId,
|
|
3552
|
+
args.message.id
|
|
3553
|
+
].join(":"),
|
|
3554
|
+
delivery: args.message.isMention || hasInterruptOverride ? "interrupt" : "defer",
|
|
3555
|
+
source: "slack",
|
|
3556
|
+
createdAtMs: args.message.metadata.dateSent.getTime(),
|
|
3557
|
+
receivedAtMs: args.receivedAtMs,
|
|
3558
|
+
publishExternally: true,
|
|
3559
|
+
input: {
|
|
3560
|
+
text: args.message.text || " ",
|
|
3561
|
+
authorId,
|
|
3562
|
+
attachments: args.message.attachments,
|
|
3563
|
+
metadata: {
|
|
3564
|
+
platform: "slack",
|
|
3565
|
+
route: args.route,
|
|
3566
|
+
installation: args.installation,
|
|
3567
|
+
thread: serializedThreadSchema.parse(args.thread.toJSON()),
|
|
3568
|
+
message: args.message.toJSON()
|
|
3569
|
+
}
|
|
3570
|
+
}
|
|
3571
|
+
};
|
|
3572
|
+
}
|
|
3573
|
+
|
|
2747
3574
|
// src/chat/ingress/bot-mention.ts
|
|
2748
3575
|
function escapeRegExp(value) {
|
|
2749
3576
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -2810,7 +3637,7 @@ function textMentionsBot(text, botUserId) {
|
|
|
2810
3637
|
}
|
|
2811
3638
|
|
|
2812
3639
|
// src/chat/ingress/message-changed.ts
|
|
2813
|
-
import { Message } from "chat";
|
|
3640
|
+
import { Message as Message4 } from "chat";
|
|
2814
3641
|
function getEditedMentionMessageId(messageTs) {
|
|
2815
3642
|
return `${messageTs}:message_changed_mention`;
|
|
2816
3643
|
}
|
|
@@ -2877,7 +3704,7 @@ function extractMessageChangedMention(body, botUserId, adapter) {
|
|
|
2877
3704
|
...sourceTeam ? { source_team: sourceTeam } : void 0,
|
|
2878
3705
|
...botId ? { bot_id: botId } : void 0
|
|
2879
3706
|
};
|
|
2880
|
-
const message = new
|
|
3707
|
+
const message = new Message4({
|
|
2881
3708
|
id: getEditedMentionMessageId(messageTs),
|
|
2882
3709
|
threadId,
|
|
2883
3710
|
text: newText,
|
|
@@ -3116,7 +3943,7 @@ function normalizeMessageThreadId(message) {
|
|
|
3116
3943
|
}
|
|
3117
3944
|
async function buildThread(args) {
|
|
3118
3945
|
const normalized = normalizeMessageThreadId(args.message);
|
|
3119
|
-
return new
|
|
3946
|
+
return new ThreadImpl3({
|
|
3120
3947
|
adapter: args.adapter,
|
|
3121
3948
|
stateAdapter: args.state,
|
|
3122
3949
|
id: normalized.threadId,
|
|
@@ -3745,7 +4572,7 @@ function registerVercelWorkspaceSnapshotJobDevConsumer() {
|
|
|
3745
4572
|
}
|
|
3746
4573
|
|
|
3747
4574
|
// src/chat/services/subscribed-decision.ts
|
|
3748
|
-
import { z as
|
|
4575
|
+
import { z as z4 } from "zod";
|
|
3749
4576
|
|
|
3750
4577
|
// src/chat/services/subscribed-reply-router-policy.ts
|
|
3751
4578
|
function buildSubscribedReplyRouterPolicy(assistantName) {
|
|
@@ -3790,13 +4617,13 @@ Assess conversation floor ownership and whether the latest message continues wor
|
|
|
3790
4617
|
}
|
|
3791
4618
|
|
|
3792
4619
|
// src/chat/services/subscribed-decision.ts
|
|
3793
|
-
var replyDecisionSchema =
|
|
3794
|
-
should_reply:
|
|
3795
|
-
should_unsubscribe:
|
|
4620
|
+
var replyDecisionSchema = z4.object({
|
|
4621
|
+
should_reply: z4.boolean().describe("Whether Junior should respond to this thread message."),
|
|
4622
|
+
should_unsubscribe: z4.boolean().describe(
|
|
3796
4623
|
"Whether Junior should unsubscribe from this thread because the user clearly asked it to stop participating."
|
|
3797
4624
|
),
|
|
3798
|
-
confidence:
|
|
3799
|
-
reason:
|
|
4625
|
+
confidence: z4.number().min(0).max(1).describe("Classifier confidence from 0 to 1."),
|
|
4626
|
+
reason: z4.string().describe("Short reason for the decision; use an empty string if none.")
|
|
3800
4627
|
}).strict();
|
|
3801
4628
|
var ROUTER_CONFIDENCE_THRESHOLD = 0.7;
|
|
3802
4629
|
var ROUTER_CLASSIFIER_MAX_TOKENS = 400;
|
|
@@ -4218,9 +5045,10 @@ function shouldRethrowTurnControlError(error) {
|
|
|
4218
5045
|
function getQueuedMessages(context, options) {
|
|
4219
5046
|
return (context?.skipped ?? []).map((message) => {
|
|
4220
5047
|
const content = parseContent(message);
|
|
4221
|
-
const stripped =
|
|
5048
|
+
const stripped = stripLeadingBotMention(
|
|
4222
5049
|
stripLeadingSteeringOverride(content.topLevelText),
|
|
4223
5050
|
{
|
|
5051
|
+
botUserId: options.botUserId,
|
|
4224
5052
|
stripLeadingSlackMentionToken: options.explicitMention || Boolean(message.isMention)
|
|
4225
5053
|
}
|
|
4226
5054
|
);
|
|
@@ -4283,6 +5111,7 @@ function shouldPublishExternally(publishExternally) {
|
|
|
4283
5111
|
return publishExternally !== false;
|
|
4284
5112
|
}
|
|
4285
5113
|
function createSlackTurnRuntime(deps) {
|
|
5114
|
+
const turnLifecycle = getTurnLifecycle();
|
|
4286
5115
|
const logContext = (args) => buildLogContext(deps, args);
|
|
4287
5116
|
const maybeHandleThreadOptOutDecision = async (args) => {
|
|
4288
5117
|
if (!args.decision?.shouldUnsubscribe) {
|
|
@@ -4295,11 +5124,11 @@ function createSlackTurnRuntime(deps) {
|
|
|
4295
5124
|
return true;
|
|
4296
5125
|
};
|
|
4297
5126
|
const failConversationTurn = async (args) => {
|
|
4298
|
-
const conversationId =
|
|
5127
|
+
const conversationId = getThreadId(args.thread, args.message) ?? getRunId(args.thread, args.message);
|
|
4299
5128
|
if (!conversationId) {
|
|
4300
5129
|
return;
|
|
4301
5130
|
}
|
|
4302
|
-
await
|
|
5131
|
+
await turnLifecycle.fail({
|
|
4303
5132
|
conversationId,
|
|
4304
5133
|
createdAtMs: deps.now(),
|
|
4305
5134
|
eventId: args.eventId,
|
|
@@ -4328,7 +5157,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4328
5157
|
const processingReactionByMessage = /* @__PURE__ */ new Map();
|
|
4329
5158
|
return {
|
|
4330
5159
|
start: async (context, targetMessage) => {
|
|
4331
|
-
const channelId =
|
|
5160
|
+
const channelId = getChannelId(thread, targetMessage);
|
|
4332
5161
|
const messageTs = getMessageTs(targetMessage);
|
|
4333
5162
|
const reactionKey = channelId && messageTs ? `${channelId}:${messageTs}` : void 0;
|
|
4334
5163
|
if (reactionKey) {
|
|
@@ -4337,10 +5166,9 @@ function createSlackTurnRuntime(deps) {
|
|
|
4337
5166
|
return existing;
|
|
4338
5167
|
}
|
|
4339
5168
|
}
|
|
4340
|
-
const started = await
|
|
5169
|
+
const started = await startProcessingReaction({
|
|
4341
5170
|
thread,
|
|
4342
|
-
message: targetMessage
|
|
4343
|
-
logException: deps.logException
|
|
5171
|
+
message: targetMessage
|
|
4344
5172
|
});
|
|
4345
5173
|
processingReactions.push(started);
|
|
4346
5174
|
if (reactionKey) {
|
|
@@ -4356,7 +5184,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4356
5184
|
try {
|
|
4357
5185
|
await args.thread.post(buildTurnFailureResponse(args.eventId));
|
|
4358
5186
|
} catch (postError) {
|
|
4359
|
-
|
|
5187
|
+
logException(postError, args.postFailureEventName, {
|
|
4360
5188
|
"app.slack.reply_stage": "error_fallback_post",
|
|
4361
5189
|
"app.error.original_event_id": args.eventId,
|
|
4362
5190
|
...getSlackErrorObservabilityAttributes(postError)
|
|
@@ -4367,15 +5195,16 @@ function createSlackTurnRuntime(deps) {
|
|
|
4367
5195
|
const decideSteeringMessage = async (thread, candidate, conversationContext) => {
|
|
4368
5196
|
const { message } = candidate;
|
|
4369
5197
|
const context = {
|
|
4370
|
-
threadId:
|
|
5198
|
+
threadId: getThreadId(thread, message),
|
|
4371
5199
|
actorId: message.author.userId,
|
|
4372
|
-
channelId:
|
|
4373
|
-
runId:
|
|
5200
|
+
channelId: getChannelId(thread, message),
|
|
5201
|
+
runId: getRunId(thread, message)
|
|
4374
5202
|
};
|
|
4375
5203
|
const content = parseContent(message);
|
|
4376
|
-
const strippedUserText =
|
|
5204
|
+
const strippedUserText = stripLeadingBotMention(
|
|
4377
5205
|
stripLeadingSteeringOverride(content.topLevelText),
|
|
4378
5206
|
{
|
|
5207
|
+
botUserId: deps.getBotUserId(),
|
|
4379
5208
|
stripLeadingSlackMentionToken: Boolean(message.isMention)
|
|
4380
5209
|
}
|
|
4381
5210
|
);
|
|
@@ -4407,7 +5236,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4407
5236
|
runId: args.context.runId
|
|
4408
5237
|
}),
|
|
4409
5238
|
() => {
|
|
4410
|
-
|
|
5239
|
+
logWarn("subscribed_message.reply.skipped", {
|
|
4411
5240
|
"app.decision.reason": args.decision.reason
|
|
4412
5241
|
});
|
|
4413
5242
|
}
|
|
@@ -4503,7 +5332,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4503
5332
|
}
|
|
4504
5333
|
} catch (error) {
|
|
4505
5334
|
withLogContext(args.context, () => {
|
|
4506
|
-
|
|
5335
|
+
logException(error, "agent.turn.steering_flush.failed");
|
|
4507
5336
|
});
|
|
4508
5337
|
}
|
|
4509
5338
|
};
|
|
@@ -4520,18 +5349,18 @@ function createSlackTurnRuntime(deps) {
|
|
|
4520
5349
|
thread,
|
|
4521
5350
|
pending: skippedSteeringMessages,
|
|
4522
5351
|
context: logContext({
|
|
4523
|
-
threadId:
|
|
5352
|
+
threadId: getThreadId(thread, message),
|
|
4524
5353
|
actorId: message.author.userId,
|
|
4525
5354
|
actorUserName: actorUserName(message),
|
|
4526
|
-
channelId:
|
|
4527
|
-
runId:
|
|
5355
|
+
channelId: getChannelId(thread, message),
|
|
5356
|
+
runId: getRunId(thread, message)
|
|
4528
5357
|
})
|
|
4529
5358
|
});
|
|
4530
5359
|
};
|
|
4531
5360
|
try {
|
|
4532
|
-
const threadId =
|
|
4533
|
-
const channelId =
|
|
4534
|
-
const runId =
|
|
5361
|
+
const threadId = getThreadId(thread, message);
|
|
5362
|
+
const channelId = getChannelId(thread, message);
|
|
5363
|
+
const runId = getRunId(thread, message);
|
|
4535
5364
|
const context = logContext({
|
|
4536
5365
|
threadId,
|
|
4537
5366
|
channelId,
|
|
@@ -4544,11 +5373,11 @@ function createSlackTurnRuntime(deps) {
|
|
|
4544
5373
|
processingReaction,
|
|
4545
5374
|
hooks
|
|
4546
5375
|
);
|
|
4547
|
-
await
|
|
5376
|
+
await withSpan("chat.turn", "chat.turn", context, async () => {
|
|
4548
5377
|
await thread.subscribe();
|
|
4549
5378
|
const queuedMessages = getQueuedMessages(hooks.messageContext, {
|
|
4550
|
-
|
|
4551
|
-
|
|
5379
|
+
botUserId: deps.getBotUserId(),
|
|
5380
|
+
explicitMention: true
|
|
4552
5381
|
});
|
|
4553
5382
|
let queuedProcessingReactionsStarted = false;
|
|
4554
5383
|
const startQueuedProcessingReactions = async () => {
|
|
@@ -4568,6 +5397,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4568
5397
|
await startQueuedProcessingReactions();
|
|
4569
5398
|
};
|
|
4570
5399
|
const drainSteeringMessages = createAcceptedSteeringDrain(hooks, {
|
|
5400
|
+
botUserId: deps.getBotUserId(),
|
|
4571
5401
|
explicitMention: true,
|
|
4572
5402
|
onAcceptedForProcessing: async (messages) => {
|
|
4573
5403
|
await Promise.all(
|
|
@@ -4586,8 +5416,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4586
5416
|
conversationContext: drainContext?.conversationContext,
|
|
4587
5417
|
messages,
|
|
4588
5418
|
thread
|
|
4589
|
-
})
|
|
4590
|
-
stripLeadingBotMention: deps.stripLeadingBotMention
|
|
5419
|
+
})
|
|
4591
5420
|
});
|
|
4592
5421
|
await deps.executeSlackTurn(thread, message, {
|
|
4593
5422
|
explicitMention: true,
|
|
@@ -4606,11 +5435,11 @@ function createSlackTurnRuntime(deps) {
|
|
|
4606
5435
|
});
|
|
4607
5436
|
} catch (error) {
|
|
4608
5437
|
const failureLogContext = logContext({
|
|
4609
|
-
threadId:
|
|
5438
|
+
threadId: getThreadId(thread, message),
|
|
4610
5439
|
actorId: message.author.userId,
|
|
4611
5440
|
actorUserName: actorUserName(message),
|
|
4612
|
-
channelId:
|
|
4613
|
-
runId:
|
|
5441
|
+
channelId: getChannelId(thread, message),
|
|
5442
|
+
runId: getRunId(thread, message)
|
|
4614
5443
|
});
|
|
4615
5444
|
const classifiedFailure = getConversationTurnBoundaryError(error);
|
|
4616
5445
|
const failureCause = classifiedFailure?.cause ?? error;
|
|
@@ -4623,7 +5452,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4623
5452
|
const failureCode = classifiedFailure?.failureCode ?? "agent_run_failed";
|
|
4624
5453
|
if (failureCause instanceof SlackActionError && failureCause.code === "read_only_channel") {
|
|
4625
5454
|
withLogContext(failureLogContext, () => {
|
|
4626
|
-
|
|
5455
|
+
logWarn("mention.handler.skipped", {
|
|
4627
5456
|
"app.decision.reason": "read_only_channel"
|
|
4628
5457
|
});
|
|
4629
5458
|
});
|
|
@@ -4631,7 +5460,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4631
5460
|
}
|
|
4632
5461
|
const eventId = classifiedFailure?.eventId ?? withLogContext(
|
|
4633
5462
|
failureLogContext,
|
|
4634
|
-
() =>
|
|
5463
|
+
() => logException(failureCause, "mention.handler.failed")
|
|
4635
5464
|
);
|
|
4636
5465
|
if (!acked && hooks.isFinalAttempt === false) {
|
|
4637
5466
|
return;
|
|
@@ -4669,11 +5498,11 @@ function createSlackTurnRuntime(deps) {
|
|
|
4669
5498
|
thread,
|
|
4670
5499
|
pending: skippedSteeringMessages,
|
|
4671
5500
|
context: logContext({
|
|
4672
|
-
threadId:
|
|
5501
|
+
threadId: getThreadId(thread, message),
|
|
4673
5502
|
actorId: message.author.userId,
|
|
4674
5503
|
actorUserName: actorUserName(message),
|
|
4675
|
-
channelId:
|
|
4676
|
-
runId:
|
|
5504
|
+
channelId: getChannelId(thread, message),
|
|
5505
|
+
runId: getRunId(thread, message)
|
|
4677
5506
|
})
|
|
4678
5507
|
});
|
|
4679
5508
|
await processingReactions.stopAll();
|
|
@@ -4692,18 +5521,18 @@ function createSlackTurnRuntime(deps) {
|
|
|
4692
5521
|
thread,
|
|
4693
5522
|
pending: skippedSteeringMessages,
|
|
4694
5523
|
context: logContext({
|
|
4695
|
-
threadId:
|
|
5524
|
+
threadId: getThreadId(thread, message),
|
|
4696
5525
|
actorId: message.author.userId,
|
|
4697
5526
|
actorUserName: actorUserName(message),
|
|
4698
|
-
channelId:
|
|
4699
|
-
runId:
|
|
5527
|
+
channelId: getChannelId(thread, message),
|
|
5528
|
+
runId: getRunId(thread, message)
|
|
4700
5529
|
})
|
|
4701
5530
|
});
|
|
4702
5531
|
};
|
|
4703
5532
|
try {
|
|
4704
|
-
const threadId =
|
|
4705
|
-
const channelId =
|
|
4706
|
-
const runId =
|
|
5533
|
+
const threadId = getThreadId(thread, message);
|
|
5534
|
+
const channelId = getChannelId(thread, message);
|
|
5535
|
+
const runId = getRunId(thread, message);
|
|
4707
5536
|
const isResourceEventNotification = isResourceEventSlackMessage(message);
|
|
4708
5537
|
const actorId = isResourceEventNotification ? void 0 : message.author.userId;
|
|
4709
5538
|
const turnContext = logContext({
|
|
@@ -4713,11 +5542,12 @@ function createSlackTurnRuntime(deps) {
|
|
|
4713
5542
|
channelId,
|
|
4714
5543
|
runId
|
|
4715
5544
|
});
|
|
4716
|
-
await
|
|
5545
|
+
await withSpan("chat.turn", "chat.turn", turnContext, async () => {
|
|
4717
5546
|
const content = parseContent(message);
|
|
4718
|
-
const strippedUserText =
|
|
5547
|
+
const strippedUserText = stripLeadingBotMention(
|
|
4719
5548
|
stripLeadingSteeringOverride(content.topLevelText),
|
|
4720
5549
|
{
|
|
5550
|
+
botUserId: deps.getBotUserId(),
|
|
4721
5551
|
stripLeadingSlackMentionToken: Boolean(message.isMention)
|
|
4722
5552
|
}
|
|
4723
5553
|
);
|
|
@@ -4732,8 +5562,8 @@ function createSlackTurnRuntime(deps) {
|
|
|
4732
5562
|
runId
|
|
4733
5563
|
};
|
|
4734
5564
|
const queuedMessages = getQueuedMessages(hooks.messageContext, {
|
|
4735
|
-
|
|
4736
|
-
|
|
5565
|
+
botUserId: deps.getBotUserId(),
|
|
5566
|
+
explicitMention: Boolean(message.isMention)
|
|
4737
5567
|
});
|
|
4738
5568
|
const combinedText = combineTurnText(queuedMessages, currentText);
|
|
4739
5569
|
const turnIsExplicitMention = Boolean(message.isMention) || queuedMessages.some((queued) => queued.explicitMention);
|
|
@@ -4833,6 +5663,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4833
5663
|
}
|
|
4834
5664
|
const conversationContext = deps.getPreparedConversationContext(preparedState);
|
|
4835
5665
|
const drainSteeringMessages = createAcceptedSteeringDrain(hooks, {
|
|
5666
|
+
botUserId: deps.getBotUserId(),
|
|
4836
5667
|
explicitMention: Boolean(message.isMention),
|
|
4837
5668
|
onAcceptedForProcessing: async (messages) => {
|
|
4838
5669
|
await Promise.all(
|
|
@@ -4851,8 +5682,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4851
5682
|
conversationContext: drainContext?.conversationContext ?? conversationContext,
|
|
4852
5683
|
messages,
|
|
4853
5684
|
thread
|
|
4854
|
-
})
|
|
4855
|
-
stripLeadingBotMention: deps.stripLeadingBotMention
|
|
5685
|
+
})
|
|
4856
5686
|
});
|
|
4857
5687
|
processingReaction = await processingReactions.start(
|
|
4858
5688
|
turnContext,
|
|
@@ -4897,11 +5727,11 @@ function createSlackTurnRuntime(deps) {
|
|
|
4897
5727
|
});
|
|
4898
5728
|
} catch (error) {
|
|
4899
5729
|
const failureLogContext = logContext({
|
|
4900
|
-
threadId:
|
|
5730
|
+
threadId: getThreadId(thread, message),
|
|
4901
5731
|
actorId: message.author.userId,
|
|
4902
5732
|
actorUserName: actorUserName(message),
|
|
4903
|
-
channelId:
|
|
4904
|
-
runId:
|
|
5733
|
+
channelId: getChannelId(thread, message),
|
|
5734
|
+
runId: getRunId(thread, message)
|
|
4905
5735
|
});
|
|
4906
5736
|
const classifiedFailure = getConversationTurnBoundaryError(error);
|
|
4907
5737
|
const failureCause = classifiedFailure?.cause ?? error;
|
|
@@ -4914,7 +5744,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4914
5744
|
const failureCode = classifiedFailure?.failureCode ?? "agent_run_failed";
|
|
4915
5745
|
if (failureCause instanceof SlackActionError && failureCause.code === "read_only_channel") {
|
|
4916
5746
|
withLogContext(failureLogContext, () => {
|
|
4917
|
-
|
|
5747
|
+
logWarn("subscribed_message.handler.skipped", {
|
|
4918
5748
|
"app.decision.reason": "read_only_channel"
|
|
4919
5749
|
});
|
|
4920
5750
|
});
|
|
@@ -4922,10 +5752,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4922
5752
|
}
|
|
4923
5753
|
const eventId = classifiedFailure?.eventId ?? withLogContext(
|
|
4924
5754
|
failureLogContext,
|
|
4925
|
-
() =>
|
|
4926
|
-
failureCause,
|
|
4927
|
-
"subscribed_message.handler.failed"
|
|
4928
|
-
)
|
|
5755
|
+
() => logException(failureCause, "subscribed_message.handler.failed")
|
|
4929
5756
|
);
|
|
4930
5757
|
if (!acked && hooks.isFinalAttempt === false) {
|
|
4931
5758
|
return;
|
|
@@ -4963,11 +5790,11 @@ function createSlackTurnRuntime(deps) {
|
|
|
4963
5790
|
thread,
|
|
4964
5791
|
pending: skippedSteeringMessages,
|
|
4965
5792
|
context: logContext({
|
|
4966
|
-
threadId:
|
|
5793
|
+
threadId: getThreadId(thread, message),
|
|
4967
5794
|
actorId: message.author.userId,
|
|
4968
5795
|
actorUserName: actorUserName(message),
|
|
4969
|
-
channelId:
|
|
4970
|
-
runId:
|
|
5796
|
+
channelId: getChannelId(thread, message),
|
|
5797
|
+
runId: getRunId(thread, message)
|
|
4971
5798
|
})
|
|
4972
5799
|
});
|
|
4973
5800
|
await processingReactions.stopAll();
|
|
@@ -4990,7 +5817,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
4990
5817
|
sourceChannelId: event.context?.channelId
|
|
4991
5818
|
});
|
|
4992
5819
|
} catch (error) {
|
|
4993
|
-
|
|
5820
|
+
logException(error, "assistant.thread.initialization.failed");
|
|
4994
5821
|
}
|
|
4995
5822
|
}
|
|
4996
5823
|
);
|
|
@@ -5011,7 +5838,7 @@ function createSlackTurnRuntime(deps) {
|
|
|
5011
5838
|
sourceChannelId: event.context?.channelId
|
|
5012
5839
|
});
|
|
5013
5840
|
} catch (error) {
|
|
5014
|
-
|
|
5841
|
+
logException(error, "assistant.context.refresh.failed");
|
|
5015
5842
|
}
|
|
5016
5843
|
}
|
|
5017
5844
|
);
|
|
@@ -5493,24 +6320,14 @@ function createJuniorRuntimeServices(overrides = {}) {
|
|
|
5493
6320
|
listThreadReplies: overrides.visionContext?.listThreadReplies ?? listThreadReplies,
|
|
5494
6321
|
downloadFile: overrides.visionContext?.downloadFile ?? downloadPrivateSlackFile
|
|
5495
6322
|
});
|
|
5496
|
-
const agentRunner = overrides.
|
|
6323
|
+
const agentRunner = overrides.agentRunner ?? createAgentRunner(executeAgentRun, {
|
|
5497
6324
|
bindSpawnAgent: (request) => bindSpawnAgent(request, { queue: getVercelConversationWorkQueue }),
|
|
5498
6325
|
tracePropagation: overrides.sandbox?.tracePropagation
|
|
5499
6326
|
});
|
|
5500
6327
|
return {
|
|
5501
6328
|
conversationMemory,
|
|
5502
6329
|
contextCompactor,
|
|
5503
|
-
|
|
5504
|
-
contextCompactor: overrides.replyExecutor?.contextCompactor ?? contextCompactor,
|
|
5505
|
-
agentRunner,
|
|
5506
|
-
getPausedTurnRequest: overrides.replyExecutor?.getPausedTurnRequest ?? getPausedTurnRequest,
|
|
5507
|
-
lookupSlackUser: overrides.replyExecutor?.lookupSlackUser ?? lookupSlackUser,
|
|
5508
|
-
wakePausedTurn: overrides.replyExecutor?.wakePausedTurn ?? wakePausedTurn,
|
|
5509
|
-
scheduleSessionCompletedPluginTasks: overrides.replyExecutor?.scheduleSessionCompletedPluginTasks ?? (async (params) => {
|
|
5510
|
-
await scheduleSessionCompletedPluginTasks(params);
|
|
5511
|
-
}),
|
|
5512
|
-
turnLifecycle: overrides.replyExecutor?.turnLifecycle ?? new ConversationTurnLifecycleService(getConversationEventStore())
|
|
5513
|
-
},
|
|
6330
|
+
executeTurn: async (run, saveResult, timeoutMs) => await executeTurn(agentRunner, run, saveResult, timeoutMs),
|
|
5514
6331
|
subscribedReplyPolicy: createSubscribedReplyPolicy({
|
|
5515
6332
|
completeObject: overrides.subscribedReplyPolicy?.completeObject ?? completeObject
|
|
5516
6333
|
}),
|
|
@@ -5534,11 +6351,11 @@ function getMessageTimestamp(message) {
|
|
|
5534
6351
|
}
|
|
5535
6352
|
|
|
5536
6353
|
// src/chat/slack/action-token.ts
|
|
5537
|
-
import { z as
|
|
5538
|
-
var slackActionTokenSchema =
|
|
5539
|
-
var slackMessageEnvelopeSchema =
|
|
5540
|
-
raw:
|
|
5541
|
-
action_token:
|
|
6354
|
+
import { z as z5 } from "zod";
|
|
6355
|
+
var slackActionTokenSchema = z5.string().trim().min(1).brand();
|
|
6356
|
+
var slackMessageEnvelopeSchema = z5.object({
|
|
6357
|
+
raw: z5.object({
|
|
6358
|
+
action_token: z5.unknown().optional()
|
|
5542
6359
|
}).optional()
|
|
5543
6360
|
});
|
|
5544
6361
|
function readSlackActionToken(message) {
|
|
@@ -5616,11 +6433,8 @@ async function maybeApplyProviderDefaultConfigRequest(args) {
|
|
|
5616
6433
|
};
|
|
5617
6434
|
}
|
|
5618
6435
|
|
|
5619
|
-
// src/chat/providers/slack/
|
|
5620
|
-
|
|
5621
|
-
await persistWithRetry(() => persistThreadRuntimeState(thread, patch));
|
|
5622
|
-
}
|
|
5623
|
-
function parkedInputKey(message) {
|
|
6436
|
+
// src/chat/providers/slack/input.ts
|
|
6437
|
+
function steeringMessageKey(message) {
|
|
5624
6438
|
if (message.role !== "user") {
|
|
5625
6439
|
return void 0;
|
|
5626
6440
|
}
|
|
@@ -5629,19 +6443,19 @@ function parkedInputKey(message) {
|
|
|
5629
6443
|
return `${message.timestamp}:${text}`;
|
|
5630
6444
|
}
|
|
5631
6445
|
function renderRecentThreadMessageLines(conversationContext, messages) {
|
|
5632
|
-
const
|
|
6446
|
+
const messagesForContext = messages.filter((queued) => {
|
|
5633
6447
|
if (queued.explicitMention) {
|
|
5634
6448
|
return false;
|
|
5635
6449
|
}
|
|
5636
|
-
const slackTs =
|
|
6450
|
+
const slackTs = inboundMessageActor(queued)?.slackTs;
|
|
5637
6451
|
return !slackTs || !conversationContext?.includes(`slack_ts="${slackTs}"`);
|
|
5638
6452
|
});
|
|
5639
|
-
if (
|
|
6453
|
+
if (messagesForContext.length === 0) {
|
|
5640
6454
|
return [];
|
|
5641
6455
|
}
|
|
5642
6456
|
const lines = [];
|
|
5643
|
-
for (const queued of
|
|
5644
|
-
const actor =
|
|
6457
|
+
for (const queued of messagesForContext) {
|
|
6458
|
+
const actor = inboundMessageActor(queued);
|
|
5645
6459
|
const author = escapeXml(actor?.authorName ?? "user");
|
|
5646
6460
|
const attrs = [
|
|
5647
6461
|
`role="user"`,
|
|
@@ -5658,14 +6472,13 @@ function renderRecentThreadMessageLines(conversationContext, messages) {
|
|
|
5658
6472
|
}
|
|
5659
6473
|
return lines;
|
|
5660
6474
|
}
|
|
5661
|
-
function
|
|
5662
|
-
const baseContext = options?.includeConversationContext === false ? void 0 : conversationContext;
|
|
6475
|
+
function appendRecentMessagesToContext(conversationContext, messages) {
|
|
5663
6476
|
return appendThreadContextMessages(
|
|
5664
|
-
|
|
6477
|
+
conversationContext,
|
|
5665
6478
|
renderRecentThreadMessageLines(conversationContext, messages)
|
|
5666
6479
|
);
|
|
5667
6480
|
}
|
|
5668
|
-
function
|
|
6481
|
+
function inboundMessageActor(queued) {
|
|
5669
6482
|
const actor = getMessageActorIdentity(queued.message);
|
|
5670
6483
|
const authorId = actor?.userId ?? parseActorUserId(queued.message.author.userId);
|
|
5671
6484
|
const authorName = actor?.fullName ?? actor?.userName;
|
|
@@ -5676,7 +6489,7 @@ function queuedInstructionActor(queued) {
|
|
|
5676
6489
|
...slackTs ? { slackTs } : void 0
|
|
5677
6490
|
};
|
|
5678
6491
|
}
|
|
5679
|
-
function
|
|
6492
|
+
function inboundMessageProvenance(queued, teamId) {
|
|
5680
6493
|
if (isResourceEventSlackMessage(queued.message)) {
|
|
5681
6494
|
return contextProvenance;
|
|
5682
6495
|
}
|
|
@@ -5703,12 +6516,57 @@ async function resolveChannelName(thread) {
|
|
|
5703
6516
|
return void 0;
|
|
5704
6517
|
}
|
|
5705
6518
|
}
|
|
5706
|
-
function
|
|
6519
|
+
function collectAttachments(message, batchedMessages) {
|
|
5707
6520
|
return [
|
|
5708
|
-
...(
|
|
6521
|
+
...(batchedMessages ?? []).flatMap((queued) => queued.message.attachments),
|
|
5709
6522
|
...message.attachments
|
|
5710
6523
|
];
|
|
5711
6524
|
}
|
|
6525
|
+
async function saveSteeringMessages(args) {
|
|
6526
|
+
if (args.messages.length === 0) {
|
|
6527
|
+
return true;
|
|
6528
|
+
}
|
|
6529
|
+
const state = getStateAdapter();
|
|
6530
|
+
await state.connect();
|
|
6531
|
+
const lock = await acquireActiveLock(state, args.conversationId);
|
|
6532
|
+
if (!lock) {
|
|
6533
|
+
return false;
|
|
6534
|
+
}
|
|
6535
|
+
try {
|
|
6536
|
+
const projection = await loadConversationProjection({
|
|
6537
|
+
conversationId: args.conversationId
|
|
6538
|
+
});
|
|
6539
|
+
const savedKeys = new Set(
|
|
6540
|
+
projection.messages.map(steeringMessageKey).filter((key) => key !== void 0)
|
|
6541
|
+
);
|
|
6542
|
+
const missing = args.messages.filter((entry) => {
|
|
6543
|
+
const key = steeringMessageKey(entry.message);
|
|
6544
|
+
return key === void 0 || !savedKeys.has(key);
|
|
6545
|
+
});
|
|
6546
|
+
if (missing.length === 0) {
|
|
6547
|
+
return true;
|
|
6548
|
+
}
|
|
6549
|
+
await commitMessages({
|
|
6550
|
+
conversationId: args.conversationId,
|
|
6551
|
+
messages: [
|
|
6552
|
+
...projection.messages,
|
|
6553
|
+
...missing.map((entry) => entry.message)
|
|
6554
|
+
],
|
|
6555
|
+
provenance: [
|
|
6556
|
+
...projection.provenance,
|
|
6557
|
+
...missing.map((entry) => entry.provenance)
|
|
6558
|
+
]
|
|
6559
|
+
});
|
|
6560
|
+
return true;
|
|
6561
|
+
} finally {
|
|
6562
|
+
await state.releaseLock(lock);
|
|
6563
|
+
}
|
|
6564
|
+
}
|
|
6565
|
+
|
|
6566
|
+
// src/chat/providers/slack/turn.ts
|
|
6567
|
+
async function persistThreadRuntimeStateWithRetry(thread, patch) {
|
|
6568
|
+
await persistWithRetry(() => persistThreadRuntimeState(thread, patch));
|
|
6569
|
+
}
|
|
5712
6570
|
async function loadPiMessagesForTurn(args) {
|
|
5713
6571
|
if (!args.conversationId) {
|
|
5714
6572
|
return {};
|
|
@@ -5742,6 +6600,7 @@ function shouldPublishExternally2(publishExternally) {
|
|
|
5742
6600
|
return publishExternally !== false;
|
|
5743
6601
|
}
|
|
5744
6602
|
function createSlackTurn(deps) {
|
|
6603
|
+
const turnLifecycle = getTurnLifecycle();
|
|
5745
6604
|
return async function executeSlackTurn(thread, message, options) {
|
|
5746
6605
|
if (message.author.isMe) {
|
|
5747
6606
|
return;
|
|
@@ -5810,7 +6669,7 @@ function createSlackTurn(deps) {
|
|
|
5810
6669
|
(queued) => ensureSlackMessageActorIdentity(
|
|
5811
6670
|
queued.message,
|
|
5812
6671
|
teamId,
|
|
5813
|
-
|
|
6672
|
+
lookupSlackUser
|
|
5814
6673
|
)
|
|
5815
6674
|
)
|
|
5816
6675
|
);
|
|
@@ -5827,7 +6686,7 @@ function createSlackTurn(deps) {
|
|
|
5827
6686
|
executionActor = await ensureSlackMessageActorIdentity(
|
|
5828
6687
|
message,
|
|
5829
6688
|
teamId,
|
|
5830
|
-
|
|
6689
|
+
lookupSlackUser
|
|
5831
6690
|
);
|
|
5832
6691
|
if (executionActor) {
|
|
5833
6692
|
credentialContext = credentialContextForActor(executionActor);
|
|
@@ -5905,8 +6764,8 @@ function createSlackTurn(deps) {
|
|
|
5905
6764
|
queuedMessages.map(async (queued) => {
|
|
5906
6765
|
const attachments = queued.message.attachments;
|
|
5907
6766
|
return {
|
|
5908
|
-
actor:
|
|
5909
|
-
provenance:
|
|
6767
|
+
actor: inboundMessageActor(queued),
|
|
6768
|
+
provenance: inboundMessageProvenance(queued, teamId),
|
|
5910
6769
|
text: queued.userText,
|
|
5911
6770
|
timestampMs: queued.message.metadata.dateSent.getTime(),
|
|
5912
6771
|
omittedImageAttachmentCount: !isVisionEnabled() && hasPotentialImageAttachment(attachments) ? countPotentialImageAttachments(attachments) : 0,
|
|
@@ -5922,51 +6781,11 @@ function createSlackTurn(deps) {
|
|
|
5922
6781
|
})
|
|
5923
6782
|
);
|
|
5924
6783
|
};
|
|
5925
|
-
const
|
|
5926
|
-
if (!conversationId || pairs.length === 0) {
|
|
5927
|
-
return true;
|
|
5928
|
-
}
|
|
5929
|
-
const stateAdapter = getStateAdapter();
|
|
5930
|
-
await stateAdapter.connect();
|
|
5931
|
-
const lock = await acquireActiveLock(stateAdapter, conversationId);
|
|
5932
|
-
if (!lock) {
|
|
5933
|
-
return false;
|
|
5934
|
-
}
|
|
5935
|
-
try {
|
|
5936
|
-
const projection = await loadConversationProjection({
|
|
5937
|
-
conversationId
|
|
5938
|
-
});
|
|
5939
|
-
const appendedKeys = new Set(
|
|
5940
|
-
projection.messages.map(parkedInputKey).filter((key) => key !== void 0)
|
|
5941
|
-
);
|
|
5942
|
-
const missing = pairs.filter((pair) => {
|
|
5943
|
-
const key = parkedInputKey(pair.message);
|
|
5944
|
-
return key === void 0 || !appendedKeys.has(key);
|
|
5945
|
-
});
|
|
5946
|
-
if (missing.length === 0) {
|
|
5947
|
-
return true;
|
|
5948
|
-
}
|
|
5949
|
-
await commitMessages({
|
|
5950
|
-
conversationId,
|
|
5951
|
-
messages: [
|
|
5952
|
-
...projection.messages,
|
|
5953
|
-
...missing.map((pair) => pair.message)
|
|
5954
|
-
],
|
|
5955
|
-
provenance: [
|
|
5956
|
-
...projection.provenance,
|
|
5957
|
-
...missing.map((pair) => pair.provenance)
|
|
5958
|
-
]
|
|
5959
|
-
});
|
|
5960
|
-
return true;
|
|
5961
|
-
} finally {
|
|
5962
|
-
await stateAdapter.releaseLock(lock);
|
|
5963
|
-
}
|
|
5964
|
-
};
|
|
5965
|
-
const appendParkedTurnInput = async (parkedSessionId) => {
|
|
6784
|
+
const saveMessagesForPausedTurn = async (pausedTurnId) => {
|
|
5966
6785
|
if (!conversationId) {
|
|
5967
6786
|
return true;
|
|
5968
6787
|
}
|
|
5969
|
-
const
|
|
6788
|
+
const messagesForPausedTurn = [
|
|
5970
6789
|
...options.queuedMessages ?? [],
|
|
5971
6790
|
{
|
|
5972
6791
|
explicitMention: Boolean(
|
|
@@ -5977,18 +6796,21 @@ function createSlackTurn(deps) {
|
|
|
5977
6796
|
userText: currentText.userText
|
|
5978
6797
|
}
|
|
5979
6798
|
].filter(
|
|
5980
|
-
// Redelivery of the
|
|
6799
|
+
// Redelivery of the paused Turn's own message must not duplicate
|
|
5981
6800
|
// the prompt that already started the session.
|
|
5982
|
-
(queued) => buildDeterministicTurnId(queued.message.id) !==
|
|
6801
|
+
(queued) => buildDeterministicTurnId(queued.message.id) !== pausedTurnId
|
|
5983
6802
|
);
|
|
5984
|
-
if (
|
|
6803
|
+
if (messagesForPausedTurn.length === 0) {
|
|
5985
6804
|
return true;
|
|
5986
6805
|
}
|
|
5987
|
-
const
|
|
6806
|
+
const steeringMessages = (await resolveSteeringMessages(messagesForPausedTurn)).map((steering) => ({
|
|
5988
6807
|
message: buildSteeringPiMessage(steering),
|
|
5989
6808
|
provenance: steering.provenance
|
|
5990
6809
|
}));
|
|
5991
|
-
return
|
|
6810
|
+
return saveSteeringMessages({
|
|
6811
|
+
conversationId,
|
|
6812
|
+
messages: steeringMessages
|
|
6813
|
+
});
|
|
5992
6814
|
};
|
|
5993
6815
|
if (preparedState.userMessageAlreadyReplied) {
|
|
5994
6816
|
const deliveredMessage = [...preparedState.conversation.messages].reverse().find(
|
|
@@ -6005,16 +6827,16 @@ function createSlackTurn(deps) {
|
|
|
6005
6827
|
return;
|
|
6006
6828
|
}
|
|
6007
6829
|
if (conversationId && activeTurnId) {
|
|
6008
|
-
const pausedTurn = await deps.
|
|
6830
|
+
const pausedTurn = await deps.pausedTurns.get({
|
|
6009
6831
|
conversationId,
|
|
6010
6832
|
turnId: activeTurnId
|
|
6011
6833
|
});
|
|
6012
6834
|
if (pausedTurn) {
|
|
6013
|
-
if (!await
|
|
6835
|
+
if (!await saveMessagesForPausedTurn(pausedTurn.turnId)) {
|
|
6014
6836
|
throw new TurnInputDeferredError();
|
|
6015
6837
|
}
|
|
6016
6838
|
try {
|
|
6017
|
-
await deps.
|
|
6839
|
+
await deps.pausedTurns.wake(pausedTurn);
|
|
6018
6840
|
} catch (error) {
|
|
6019
6841
|
logException(error, "agent.continue.schedule.failed", {
|
|
6020
6842
|
"app.ai.resume_session_version": pausedTurn.expectedVersion,
|
|
@@ -6039,6 +6861,7 @@ function createSlackTurn(deps) {
|
|
|
6039
6861
|
await abandonTurnRecord({
|
|
6040
6862
|
conversationId,
|
|
6041
6863
|
turnId: activeTurnId,
|
|
6864
|
+
// TODO(dcramer): Rename this legacy text in Slack and Conversation API Turn records together.
|
|
6042
6865
|
errorMessage: "Auth-parked session superseded by a new user message"
|
|
6043
6866
|
});
|
|
6044
6867
|
markTurnClosed({
|
|
@@ -6108,7 +6931,7 @@ function createSlackTurn(deps) {
|
|
|
6108
6931
|
nextTurnId: turnId
|
|
6109
6932
|
});
|
|
6110
6933
|
if (conversationId && preparedState.userMessageId) {
|
|
6111
|
-
await
|
|
6934
|
+
await turnLifecycle.start({
|
|
6112
6935
|
conversationId,
|
|
6113
6936
|
createdAtMs: Date.now(),
|
|
6114
6937
|
inputMessageIds: [
|
|
@@ -6168,7 +6991,7 @@ function createSlackTurn(deps) {
|
|
|
6168
6991
|
if (actor?.userName) {
|
|
6169
6992
|
setTags({ userName: actor.userName });
|
|
6170
6993
|
}
|
|
6171
|
-
const turnAttachments =
|
|
6994
|
+
const turnAttachments = collectAttachments(
|
|
6172
6995
|
message,
|
|
6173
6996
|
options.queuedMessages
|
|
6174
6997
|
);
|
|
@@ -6197,7 +7020,6 @@ function createSlackTurn(deps) {
|
|
|
6197
7020
|
let runResultHandled = false;
|
|
6198
7021
|
let assistantMessageDelivered = false;
|
|
6199
7022
|
let acceptedDeliveryId;
|
|
6200
|
-
let lifecycleTerminalized = false;
|
|
6201
7023
|
let turnCompletionNotified = false;
|
|
6202
7024
|
const recordDispatchOutcome = async (dispatchOutcome, state) => {
|
|
6203
7025
|
const dispatchId = options.execution?.dispatch?.id;
|
|
@@ -6222,7 +7044,6 @@ function createSlackTurn(deps) {
|
|
|
6222
7044
|
};
|
|
6223
7045
|
let turnWakeError;
|
|
6224
7046
|
let boundaryFailureCode = "agent_run_failed";
|
|
6225
|
-
let finalizedFailureEventId;
|
|
6226
7047
|
let terminalDispatchFailureOutcome;
|
|
6227
7048
|
const notifyTurnCompleted = async () => {
|
|
6228
7049
|
if (turnCompletionNotified) {
|
|
@@ -6354,7 +7175,7 @@ function createSlackTurn(deps) {
|
|
|
6354
7175
|
});
|
|
6355
7176
|
let piMessages = loadedPiMessages.piMessages;
|
|
6356
7177
|
if (conversationId && loadedPiMessages.canCompact && piMessages?.length) {
|
|
6357
|
-
const compaction = await deps.
|
|
7178
|
+
const compaction = await deps.contextCompactor.maybeCompact({
|
|
6358
7179
|
conversation: preparedState.conversation,
|
|
6359
7180
|
conversationContext: preparedState.conversationContext,
|
|
6360
7181
|
conversationId,
|
|
@@ -6379,7 +7200,7 @@ function createSlackTurn(deps) {
|
|
|
6379
7200
|
}
|
|
6380
7201
|
}
|
|
6381
7202
|
const hasDurablePromptHistory = Boolean(piMessages?.length);
|
|
6382
|
-
const
|
|
7203
|
+
const batchedSteeringMessages = (await resolveSteeringMessages(
|
|
6383
7204
|
(options.queuedMessages ?? []).filter(
|
|
6384
7205
|
(queued) => queued.explicitMention
|
|
6385
7206
|
)
|
|
@@ -6387,20 +7208,23 @@ function createSlackTurn(deps) {
|
|
|
6387
7208
|
message: buildSteeringPiMessage(steering),
|
|
6388
7209
|
provenance: steering.provenance
|
|
6389
7210
|
}));
|
|
6390
|
-
if (!await
|
|
7211
|
+
if (!await saveSteeringMessages({
|
|
7212
|
+
conversationId,
|
|
7213
|
+
messages: batchedSteeringMessages
|
|
7214
|
+
})) {
|
|
6391
7215
|
shouldPersistFailureState = false;
|
|
6392
7216
|
throw new TurnInputDeferredError();
|
|
6393
7217
|
}
|
|
6394
|
-
if (
|
|
7218
|
+
if (batchedSteeringMessages.length > 0) {
|
|
6395
7219
|
const presentKeys = new Set(
|
|
6396
|
-
(piMessages ?? []).map(
|
|
7220
|
+
(piMessages ?? []).map(steeringMessageKey).filter((key) => key !== void 0)
|
|
6397
7221
|
);
|
|
6398
|
-
const
|
|
6399
|
-
const key =
|
|
7222
|
+
const newSteeringMessages = batchedSteeringMessages.map((entry) => entry.message).filter((batchedMessage) => {
|
|
7223
|
+
const key = steeringMessageKey(batchedMessage);
|
|
6400
7224
|
return key === void 0 || !presentKeys.has(key);
|
|
6401
7225
|
});
|
|
6402
|
-
if (
|
|
6403
|
-
piMessages = [...piMessages ?? [], ...
|
|
7226
|
+
if (newSteeringMessages.length > 0) {
|
|
7227
|
+
piMessages = [...piMessages ?? [], ...newSteeringMessages];
|
|
6404
7228
|
}
|
|
6405
7229
|
}
|
|
6406
7230
|
status.update();
|
|
@@ -6420,7 +7244,7 @@ function createSlackTurn(deps) {
|
|
|
6420
7244
|
const toolChannelId = channelId;
|
|
6421
7245
|
const activeInstructionAuthorId = actor?.userId ?? parseActorUserId(message.author.userId);
|
|
6422
7246
|
const activeInstructionAuthorName = actor?.fullName ?? actor?.userName;
|
|
6423
|
-
const promptConversationContext =
|
|
7247
|
+
const promptConversationContext = appendRecentMessagesToContext(
|
|
6424
7248
|
preparedState.conversationContext,
|
|
6425
7249
|
options.queuedMessages ?? []
|
|
6426
7250
|
);
|
|
@@ -6435,7 +7259,7 @@ function createSlackTurn(deps) {
|
|
|
6435
7259
|
);
|
|
6436
7260
|
return acceptedMessages ?? await resolveSteeringMessages(drained);
|
|
6437
7261
|
} : void 0;
|
|
6438
|
-
const
|
|
7262
|
+
const run = {
|
|
6439
7263
|
conversationId,
|
|
6440
7264
|
turnId,
|
|
6441
7265
|
...runId ? { runId } : void 0,
|
|
@@ -6507,7 +7331,121 @@ function createSlackTurn(deps) {
|
|
|
6507
7331
|
});
|
|
6508
7332
|
}
|
|
6509
7333
|
}
|
|
6510
|
-
}
|
|
7334
|
+
};
|
|
7335
|
+
let completedResult;
|
|
7336
|
+
const saveResult = async (result) => {
|
|
7337
|
+
let finalResult = result;
|
|
7338
|
+
setTags({ modelId: finalResult.diagnostics.modelId });
|
|
7339
|
+
const diagnosticsAttributes = getAgentTurnDiagnosticsAttributes(finalResult);
|
|
7340
|
+
setSpanAttributes(diagnosticsAttributes);
|
|
7341
|
+
let failureEventId;
|
|
7342
|
+
let failureReason;
|
|
7343
|
+
if (finalResult.diagnostics.outcome !== "success") {
|
|
7344
|
+
const finalized = finalizeFailedTurnReplyWithEvent({
|
|
7345
|
+
reply: finalResult,
|
|
7346
|
+
logException
|
|
7347
|
+
});
|
|
7348
|
+
finalResult = finalized.reply;
|
|
7349
|
+
failureEventId = finalized.eventId;
|
|
7350
|
+
failureReason = finalized.failureReason;
|
|
7351
|
+
await deliverAssistantMessage(finalResult.text);
|
|
7352
|
+
}
|
|
7353
|
+
const turnResult = finalResult.diagnostics.outcome === "success" ? { outcome: "completed" } : {
|
|
7354
|
+
errorMessage: finalResult.diagnostics.errorMessage ?? `Agent turn ended with ${finalResult.diagnostics.outcome}.`,
|
|
7355
|
+
outcome: "failed"
|
|
7356
|
+
};
|
|
7357
|
+
runResultHandled = true;
|
|
7358
|
+
shouldPersistFailureState = false;
|
|
7359
|
+
boundaryFailureCode = "agent_run_failed";
|
|
7360
|
+
const completedState = buildDeliveredTurnStatePatch({
|
|
7361
|
+
conversation: preparedState.conversation,
|
|
7362
|
+
reply: finalResult,
|
|
7363
|
+
sessionId: turnId,
|
|
7364
|
+
userMessageId: preparedState.userMessageId
|
|
7365
|
+
});
|
|
7366
|
+
let saveFailed = false;
|
|
7367
|
+
let saveFailureEventId;
|
|
7368
|
+
try {
|
|
7369
|
+
if (conversationId && finalResult.piMessages?.length) {
|
|
7370
|
+
await saveTurnCheckpoint({
|
|
7371
|
+
mode: "completed",
|
|
7372
|
+
channelName,
|
|
7373
|
+
conversationId,
|
|
7374
|
+
turnId,
|
|
7375
|
+
durationMs: finalResult.diagnostics.durationMs,
|
|
7376
|
+
usage: finalResult.diagnostics.usage,
|
|
7377
|
+
destination,
|
|
7378
|
+
destinationVisibility,
|
|
7379
|
+
source,
|
|
7380
|
+
sliceId: 1,
|
|
7381
|
+
dispatchOutcome: finalResult.diagnostics.outcome === "success" ? "completed" : "failed",
|
|
7382
|
+
...options.execution?.dispatch && turnResult.errorMessage ? { errorMessage: turnResult.errorMessage } : void 0,
|
|
7383
|
+
...acceptedDeliveryId ? { resultMessageId: acceptedDeliveryId } : void 0,
|
|
7384
|
+
messages: finalResult.piMessages,
|
|
7385
|
+
actor: executionActor,
|
|
7386
|
+
surface: options.execution?.surface ?? "slack",
|
|
7387
|
+
dispatchId: options.execution?.dispatch?.id
|
|
7388
|
+
});
|
|
7389
|
+
} else if (conversationId) {
|
|
7390
|
+
await recordTurnSummary({
|
|
7391
|
+
channelName,
|
|
7392
|
+
conversationId,
|
|
7393
|
+
cumulativeDurationMs: finalResult.diagnostics.durationMs,
|
|
7394
|
+
cumulativeUsage: finalResult.diagnostics.usage,
|
|
7395
|
+
turnId,
|
|
7396
|
+
sliceId: 1,
|
|
7397
|
+
startedAtMs: message.metadata.dateSent.getTime(),
|
|
7398
|
+
state: "completed",
|
|
7399
|
+
actor: executionActor,
|
|
7400
|
+
destination,
|
|
7401
|
+
destinationVisibility,
|
|
7402
|
+
source,
|
|
7403
|
+
surface: options.execution?.surface ?? "slack",
|
|
7404
|
+
dispatchId: options.execution?.dispatch?.id,
|
|
7405
|
+
dispatchOutcome: finalResult.diagnostics.outcome === "success" ? "completed" : "failed",
|
|
7406
|
+
...acceptedDeliveryId ? { resultMessageId: acceptedDeliveryId } : void 0,
|
|
7407
|
+
traceId: getActiveTraceId()
|
|
7408
|
+
});
|
|
7409
|
+
}
|
|
7410
|
+
await persistWithRetry(
|
|
7411
|
+
() => persistConversationMessages({
|
|
7412
|
+
conversation: completedState.conversation,
|
|
7413
|
+
conversationId
|
|
7414
|
+
})
|
|
7415
|
+
);
|
|
7416
|
+
await persistThreadRuntimeStateWithRetry(thread, completedState);
|
|
7417
|
+
} catch (saveError) {
|
|
7418
|
+
saveFailed = true;
|
|
7419
|
+
saveFailureEventId = logException(
|
|
7420
|
+
saveError,
|
|
7421
|
+
"slack.reply.post_delivery_commit.failed",
|
|
7422
|
+
messageTs ? { "messaging.message.id": messageTs } : {}
|
|
7423
|
+
);
|
|
7424
|
+
}
|
|
7425
|
+
preparedState.conversation = completedState.conversation;
|
|
7426
|
+
persistedAtLeastOnce = true;
|
|
7427
|
+
options.onTurnOutcome?.(turnResult);
|
|
7428
|
+
completedResult = finalResult;
|
|
7429
|
+
if (saveFailed) {
|
|
7430
|
+
return {
|
|
7431
|
+
...saveFailureEventId ? { eventId: saveFailureEventId } : void 0,
|
|
7432
|
+
failureCode: "persistence_failed",
|
|
7433
|
+
outcome: "failed"
|
|
7434
|
+
};
|
|
7435
|
+
}
|
|
7436
|
+
if (finalResult.diagnostics.outcome === "success") {
|
|
7437
|
+
return {
|
|
7438
|
+
outcome: assistantMessageDelivered ? "success" : "no_reply"
|
|
7439
|
+
};
|
|
7440
|
+
}
|
|
7441
|
+
return {
|
|
7442
|
+
...failureEventId ? { eventId: failureEventId } : void 0,
|
|
7443
|
+
failureCode: "model_execution_failed",
|
|
7444
|
+
...failureReason ? { failureReason } : void 0,
|
|
7445
|
+
outcome: "failed"
|
|
7446
|
+
};
|
|
7447
|
+
};
|
|
7448
|
+
const outcome = await deps.executeTurn(run, saveResult);
|
|
6511
7449
|
if (outcome.status === "awaiting_auth") {
|
|
6512
7450
|
await recordDispatchOutcome("blocked", "failed");
|
|
6513
7451
|
options.onTurnOutcome?.({ outcome: "blocked" });
|
|
@@ -6530,14 +7468,13 @@ function createSlackTurn(deps) {
|
|
|
6530
7468
|
conversation: preparedState.conversation
|
|
6531
7469
|
});
|
|
6532
7470
|
if (conversationId) {
|
|
6533
|
-
await
|
|
7471
|
+
await turnLifecycle.fail({
|
|
6534
7472
|
conversationId,
|
|
6535
7473
|
createdAtMs: Date.now(),
|
|
6536
7474
|
...authFailureEventId ? { eventId: authFailureEventId } : void 0,
|
|
6537
7475
|
failureCode: "agent_run_failed",
|
|
6538
7476
|
turnId
|
|
6539
7477
|
});
|
|
6540
|
-
lifecycleTerminalized = true;
|
|
6541
7478
|
}
|
|
6542
7479
|
persistedAtLeastOnce = true;
|
|
6543
7480
|
shouldPersistFailureState = false;
|
|
@@ -6570,7 +7507,7 @@ function createSlackTurn(deps) {
|
|
|
6570
7507
|
);
|
|
6571
7508
|
}
|
|
6572
7509
|
try {
|
|
6573
|
-
await deps.
|
|
7510
|
+
await deps.pausedTurns.wake({
|
|
6574
7511
|
conversationId,
|
|
6575
7512
|
destination,
|
|
6576
7513
|
turnId,
|
|
@@ -6588,134 +7525,26 @@ function createSlackTurn(deps) {
|
|
|
6588
7525
|
}
|
|
6589
7526
|
return;
|
|
6590
7527
|
}
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
const diagnosticsAttributes = getAgentTurnDiagnosticsAttributes(reply);
|
|
6594
|
-
setSpanAttributes(diagnosticsAttributes);
|
|
6595
|
-
if (reply.diagnostics.outcome !== "success") {
|
|
6596
|
-
const finalized = finalizeFailedTurnReplyWithEvent({
|
|
6597
|
-
reply,
|
|
6598
|
-
logException
|
|
6599
|
-
});
|
|
6600
|
-
reply = finalized.reply;
|
|
6601
|
-
finalizedFailureEventId = finalized.eventId;
|
|
6602
|
-
await deliverAssistantMessage(reply.text);
|
|
6603
|
-
}
|
|
6604
|
-
const turnResult = reply.diagnostics.outcome === "success" ? { outcome: "completed" } : {
|
|
6605
|
-
errorMessage: reply.diagnostics.errorMessage ?? `Agent turn ended with ${reply.diagnostics.outcome}.`,
|
|
6606
|
-
outcome: "failed"
|
|
6607
|
-
};
|
|
6608
|
-
runResultHandled = true;
|
|
6609
|
-
shouldPersistFailureState = false;
|
|
6610
|
-
boundaryFailureCode = "agent_run_failed";
|
|
6611
|
-
const completedState = buildDeliveredTurnStatePatch({
|
|
6612
|
-
conversation: preparedState.conversation,
|
|
6613
|
-
reply,
|
|
6614
|
-
sessionId: turnId,
|
|
6615
|
-
userMessageId: preparedState.userMessageId
|
|
6616
|
-
});
|
|
6617
|
-
try {
|
|
6618
|
-
if (conversationId && reply.piMessages?.length) {
|
|
6619
|
-
await saveTurnCheckpoint({
|
|
6620
|
-
mode: "completed",
|
|
6621
|
-
channelName,
|
|
6622
|
-
conversationId,
|
|
6623
|
-
turnId,
|
|
6624
|
-
durationMs: reply.diagnostics.durationMs,
|
|
6625
|
-
usage: reply.diagnostics.usage,
|
|
6626
|
-
destination,
|
|
6627
|
-
destinationVisibility,
|
|
6628
|
-
source,
|
|
6629
|
-
sliceId: 1,
|
|
6630
|
-
dispatchOutcome: reply.diagnostics.outcome === "success" ? "completed" : "failed",
|
|
6631
|
-
...options.execution?.dispatch && turnResult.errorMessage ? { errorMessage: turnResult.errorMessage } : void 0,
|
|
6632
|
-
...acceptedDeliveryId ? { resultMessageId: acceptedDeliveryId } : void 0,
|
|
6633
|
-
messages: reply.piMessages,
|
|
6634
|
-
actor: executionActor,
|
|
6635
|
-
surface: options.execution?.surface ?? "slack",
|
|
6636
|
-
dispatchId: options.execution?.dispatch?.id
|
|
6637
|
-
});
|
|
6638
|
-
} else if (conversationId) {
|
|
6639
|
-
await recordTurnSummary({
|
|
6640
|
-
channelName,
|
|
6641
|
-
conversationId,
|
|
6642
|
-
cumulativeDurationMs: reply.diagnostics.durationMs,
|
|
6643
|
-
cumulativeUsage: reply.diagnostics.usage,
|
|
6644
|
-
turnId,
|
|
6645
|
-
sliceId: 1,
|
|
6646
|
-
startedAtMs: message.metadata.dateSent.getTime(),
|
|
6647
|
-
state: "completed",
|
|
6648
|
-
actor: executionActor,
|
|
6649
|
-
destination,
|
|
6650
|
-
destinationVisibility,
|
|
6651
|
-
source,
|
|
6652
|
-
surface: options.execution?.surface ?? "slack",
|
|
6653
|
-
dispatchId: options.execution?.dispatch?.id,
|
|
6654
|
-
dispatchOutcome: reply.diagnostics.outcome === "success" ? "completed" : "failed",
|
|
6655
|
-
...acceptedDeliveryId ? { resultMessageId: acceptedDeliveryId } : void 0,
|
|
6656
|
-
traceId: getActiveTraceId()
|
|
6657
|
-
});
|
|
6658
|
-
}
|
|
6659
|
-
await persistWithRetry(
|
|
6660
|
-
() => persistConversationMessages({
|
|
6661
|
-
conversation: completedState.conversation,
|
|
6662
|
-
conversationId
|
|
6663
|
-
})
|
|
6664
|
-
);
|
|
6665
|
-
await persistThreadRuntimeStateWithRetry(thread, completedState);
|
|
6666
|
-
} catch (commitError) {
|
|
6667
|
-
const persistenceEventId = logException(
|
|
6668
|
-
commitError,
|
|
6669
|
-
"slack.reply.post_delivery_commit.failed",
|
|
6670
|
-
messageTs ? { "messaging.message.id": messageTs } : {}
|
|
6671
|
-
);
|
|
6672
|
-
if (conversationId && !lifecycleTerminalized) {
|
|
6673
|
-
await deps.services.turnLifecycle.fail({
|
|
6674
|
-
conversationId,
|
|
6675
|
-
createdAtMs: Date.now(),
|
|
6676
|
-
...persistenceEventId ? { eventId: persistenceEventId } : void 0,
|
|
6677
|
-
failureCode: "persistence_failed",
|
|
6678
|
-
turnId
|
|
6679
|
-
});
|
|
6680
|
-
lifecycleTerminalized = true;
|
|
6681
|
-
}
|
|
6682
|
-
}
|
|
6683
|
-
preparedState.conversation = completedState.conversation;
|
|
6684
|
-
persistedAtLeastOnce = true;
|
|
6685
|
-
options.onTurnOutcome?.(turnResult);
|
|
6686
|
-
if (!lifecycleTerminalized && conversationId) {
|
|
6687
|
-
if (reply.diagnostics.outcome === "success") {
|
|
6688
|
-
await deps.services.turnLifecycle.complete({
|
|
6689
|
-
conversationId,
|
|
6690
|
-
createdAtMs: Date.now(),
|
|
6691
|
-
outcome: assistantMessageDelivered ? "success" : "no_reply",
|
|
6692
|
-
turnId
|
|
6693
|
-
});
|
|
6694
|
-
} else {
|
|
6695
|
-
await deps.services.turnLifecycle.fail({
|
|
6696
|
-
conversationId,
|
|
6697
|
-
createdAtMs: Date.now(),
|
|
6698
|
-
...finalizedFailureEventId ? { eventId: finalizedFailureEventId } : void 0,
|
|
6699
|
-
failureCode: "model_execution_failed",
|
|
6700
|
-
turnId
|
|
6701
|
-
});
|
|
6702
|
-
}
|
|
6703
|
-
lifecycleTerminalized = true;
|
|
7528
|
+
if (!completedResult) {
|
|
7529
|
+
throw new Error("Completed Turn did not save a result");
|
|
6704
7530
|
}
|
|
6705
7531
|
if (shouldEmitDevAgentTrace()) {
|
|
6706
7532
|
logInfo("agent.turn.completed", {
|
|
6707
|
-
"app.ai.outcome":
|
|
6708
|
-
"app.ai.tool_call_count":
|
|
6709
|
-
"app.ai.tool_error_results":
|
|
7533
|
+
"app.ai.outcome": completedResult.diagnostics.outcome,
|
|
7534
|
+
"app.ai.tool_call_count": completedResult.diagnostics.toolCalls.length,
|
|
7535
|
+
"app.ai.tool_error_results": completedResult.diagnostics.toolErrorCount
|
|
6710
7536
|
});
|
|
6711
7537
|
}
|
|
6712
7538
|
await notifyTurnCompleted();
|
|
6713
|
-
if (
|
|
7539
|
+
if (completedResult.diagnostics.outcome === "success" && conversationId) {
|
|
6714
7540
|
try {
|
|
6715
|
-
await
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
7541
|
+
await scheduleSessionCompletedPluginTasks(
|
|
7542
|
+
{
|
|
7543
|
+
conversationId,
|
|
7544
|
+
sessionId: turnId
|
|
7545
|
+
},
|
|
7546
|
+
deps.sendPluginTask ? { send: deps.sendPluginTask } : void 0
|
|
7547
|
+
);
|
|
6719
7548
|
} catch (error) {
|
|
6720
7549
|
logException(
|
|
6721
7550
|
error,
|
|
@@ -6754,8 +7583,9 @@ function createSlackTurn(deps) {
|
|
|
6754
7583
|
shouldPersistFailureState = true;
|
|
6755
7584
|
}
|
|
6756
7585
|
shouldPersistFailureState = true;
|
|
6757
|
-
const
|
|
6758
|
-
const
|
|
7586
|
+
const runFailure = error instanceof AgentRunError ? error.cause : error;
|
|
7587
|
+
const classifiedFailure = getConversationTurnBoundaryError(runFailure);
|
|
7588
|
+
const failureCause = classifiedFailure?.cause ?? runFailure;
|
|
6759
7589
|
if (failureCause instanceof AuthorizationFlowDisabledError || failureCause instanceof PluginCredentialFailureError) {
|
|
6760
7590
|
terminalDispatchFailureOutcome = "blocked";
|
|
6761
7591
|
}
|
|
@@ -7105,14 +7935,14 @@ function createPrepareTurnState(deps) {
|
|
|
7105
7935
|
}
|
|
7106
7936
|
|
|
7107
7937
|
// src/chat/slack/dispatch-turn.ts
|
|
7108
|
-
import { Message as
|
|
7938
|
+
import { Message as Message5, ThreadImpl as ThreadImpl4 } from "chat";
|
|
7109
7939
|
function createSlackDispatchTurnRunner(options) {
|
|
7110
7940
|
return async function runSlackDispatchTurn(dispatch2, hooks) {
|
|
7111
7941
|
const state = getStateAdapter();
|
|
7112
7942
|
await state.connect();
|
|
7113
7943
|
const conversationId = getDispatchConversationId(dispatch2);
|
|
7114
7944
|
const adapter = options.getSlackAdapter();
|
|
7115
|
-
const message = new
|
|
7945
|
+
const message = new Message5({
|
|
7116
7946
|
id: getDispatchInputMessageId(dispatch2.id),
|
|
7117
7947
|
threadId: conversationId,
|
|
7118
7948
|
text: dispatch2.input,
|
|
@@ -7135,7 +7965,7 @@ function createSlackDispatchTurnRunner(options) {
|
|
|
7135
7965
|
}
|
|
7136
7966
|
});
|
|
7137
7967
|
message.isMention = true;
|
|
7138
|
-
const thread = new
|
|
7968
|
+
const thread = new ThreadImpl4({
|
|
7139
7969
|
adapter,
|
|
7140
7970
|
stateAdapter: state,
|
|
7141
7971
|
id: conversationId,
|
|
@@ -7224,34 +8054,27 @@ function createSlackRuntime(options) {
|
|
|
7224
8054
|
(message) => ensureSlackMessageActorIdentity(
|
|
7225
8055
|
message,
|
|
7226
8056
|
destination.teamId,
|
|
7227
|
-
|
|
8057
|
+
lookupSlackUser
|
|
7228
8058
|
)
|
|
7229
8059
|
)
|
|
7230
8060
|
);
|
|
7231
8061
|
}
|
|
7232
8062
|
});
|
|
7233
8063
|
const executeSlackTurn = createSlackTurn({
|
|
8064
|
+
contextCompactor: services.contextCompactor,
|
|
8065
|
+
executeTurn: services.executeTurn,
|
|
7234
8066
|
getSlackAdapter: options.getSlackAdapter,
|
|
8067
|
+
pausedTurns: options.pausedTurns ?? createPausedTurns(),
|
|
7235
8068
|
prepareTurnState,
|
|
7236
8069
|
resolveUserAttachments: services.visionContext.resolveUserAttachments,
|
|
7237
|
-
|
|
8070
|
+
sendPluginTask: options.sendPluginTask
|
|
7238
8071
|
});
|
|
7239
8072
|
const runtime = createSlackTurnRuntime({
|
|
7240
8073
|
assistantUserName: botConfig.userName,
|
|
7241
8074
|
cancelEventSubscriptions: cancelSubscriptions,
|
|
8075
|
+
getBotUserId: () => options.getSlackAdapter().botUserId,
|
|
7242
8076
|
modelId: defaultModelId(botConfig),
|
|
7243
8077
|
now: options.now ?? (() => Date.now()),
|
|
7244
|
-
getThreadId,
|
|
7245
|
-
getChannelId,
|
|
7246
|
-
getRunId,
|
|
7247
|
-
stripLeadingBotMention: (text, stripOptions) => stripLeadingBotMention(text, {
|
|
7248
|
-
...stripOptions,
|
|
7249
|
-
botUserId: options.getSlackAdapter().botUserId
|
|
7250
|
-
}),
|
|
7251
|
-
withSpan,
|
|
7252
|
-
logWarn,
|
|
7253
|
-
logException,
|
|
7254
|
-
failConversationTurn: (input) => services.replyExecutor.turnLifecycle.fail(input),
|
|
7255
8078
|
prepareTurnState,
|
|
7256
8079
|
persistPreparedState: async ({ thread, preparedState }) => {
|
|
7257
8080
|
await persistThreadState(thread, {
|
|
@@ -7552,8 +8375,7 @@ async function runPausedTurnInContext(payload, options, runOptions) {
|
|
|
7552
8375
|
"Paused turn"
|
|
7553
8376
|
);
|
|
7554
8377
|
const wakePausedTurn2 = options.wakePausedTurn ?? wakePausedTurn;
|
|
7555
|
-
|
|
7556
|
-
return await resumeTurn({
|
|
8378
|
+
return await resumeSlackTurn({
|
|
7557
8379
|
messageText: "",
|
|
7558
8380
|
conversationId: payload.conversationId,
|
|
7559
8381
|
turnId: payload.turnId,
|
|
@@ -7562,7 +8384,7 @@ async function runPausedTurnInContext(payload, options, runOptions) {
|
|
|
7562
8384
|
lockKey: payload.conversationId,
|
|
7563
8385
|
// Queue continue runs under the conversation work lease already.
|
|
7564
8386
|
ownsConversationLease: true,
|
|
7565
|
-
|
|
8387
|
+
executeTurn: async (run, saveResult, timeoutMs) => await executeTurn(options.agentRunner, run, saveResult, timeoutMs),
|
|
7566
8388
|
scheduleSessionCompletedPluginTasks: options.scheduleSessionCompletedPluginTasks,
|
|
7567
8389
|
beforeStart: async () => {
|
|
7568
8390
|
let turn;
|
|
@@ -7650,7 +8472,7 @@ async function runPausedTurnInContext(payload, options, runOptions) {
|
|
|
7650
8472
|
messageTs: getTurnUserSlackMessageTs(userMessage),
|
|
7651
8473
|
inputMessageIds: [userMessage.id],
|
|
7652
8474
|
initialStatus: latestReportedProgress(turnMessages),
|
|
7653
|
-
|
|
8475
|
+
run: {
|
|
7654
8476
|
instruction: {
|
|
7655
8477
|
...conversationContext ? { context: conversationContext } : void 0,
|
|
7656
8478
|
// Attachment fields come from the turn user message context helper.
|
|
@@ -7888,24 +8710,18 @@ async function runNextPausedTurnInContext(conversationId, options, runOptions) {
|
|
|
7888
8710
|
// src/chat/app/conversation-work.ts
|
|
7889
8711
|
function createConversationWork(options) {
|
|
7890
8712
|
const apiTurnCancellation = createApiTurnCancellation();
|
|
7891
|
-
const
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
|
|
7896
|
-
getPausedTurnRequest: options.services?.replyExecutor?.getPausedTurnRequest ?? (async (request) => await getPausedTurnRequest({
|
|
7897
|
-
...request,
|
|
7898
|
-
conversationStore: options.conversationStore
|
|
7899
|
-
})),
|
|
7900
|
-
wakePausedTurn: options.services?.replyExecutor?.wakePausedTurn ?? (async (request) => await wakePausedTurn(request, {
|
|
7901
|
-
queue: options.queue,
|
|
7902
|
-
state: options.state
|
|
7903
|
-
}))
|
|
7904
|
-
}
|
|
7905
|
-
};
|
|
8713
|
+
const pausedTurns = createPausedTurns({
|
|
8714
|
+
conversationStore: options.conversationStore,
|
|
8715
|
+
queue: options.queue,
|
|
8716
|
+
...options.state ? { state: options.state } : void 0
|
|
8717
|
+
});
|
|
7906
8718
|
const runtime = createSlackRuntime({
|
|
7907
8719
|
getSlackAdapter: options.getSlackAdapter,
|
|
7908
|
-
|
|
8720
|
+
pausedTurns,
|
|
8721
|
+
services: {
|
|
8722
|
+
...options.services,
|
|
8723
|
+
agentRunner: options.agentRunner
|
|
8724
|
+
}
|
|
7909
8725
|
});
|
|
7910
8726
|
const slackWorker = createSlackConversationWorker({
|
|
7911
8727
|
getSlackAdapter: options.getSlackAdapter,
|
|
@@ -7914,8 +8730,7 @@ function createConversationWork(options) {
|
|
|
7914
8730
|
conversationId,
|
|
7915
8731
|
{
|
|
7916
8732
|
agentRunner: options.agentRunner,
|
|
7917
|
-
|
|
7918
|
-
wakePausedTurn: services.replyExecutor?.wakePausedTurn
|
|
8733
|
+
wakePausedTurn: pausedTurns.wake
|
|
7919
8734
|
},
|
|
7920
8735
|
runOptions
|
|
7921
8736
|
),
|
|
@@ -7930,28 +8745,40 @@ function createConversationWork(options) {
|
|
|
7930
8745
|
agentRunner: options.agentRunner,
|
|
7931
8746
|
inputMessageIds: [getDispatchInputMessageId(dispatch2.id)],
|
|
7932
8747
|
routingContext: buildDispatchRoutingContext(dispatch2),
|
|
7933
|
-
|
|
7934
|
-
wakePausedTurn: services.replyExecutor?.wakePausedTurn
|
|
8748
|
+
wakePausedTurn: pausedTurns.wake
|
|
7935
8749
|
},
|
|
7936
8750
|
{ shouldYield: hooks.shouldYield }
|
|
7937
8751
|
);
|
|
7938
8752
|
},
|
|
7939
8753
|
runTurn: runtime.runDispatchTurn
|
|
7940
8754
|
});
|
|
8755
|
+
const destinationWorker = async (context) => {
|
|
8756
|
+
const destination = context.destination;
|
|
8757
|
+
if (!destination) {
|
|
8758
|
+
throw new Error(
|
|
8759
|
+
`Conversation ${context.conversationId} is missing a destination`
|
|
8760
|
+
);
|
|
8761
|
+
}
|
|
8762
|
+
if (destination.platform === "slack") {
|
|
8763
|
+
return await slackWorker(context);
|
|
8764
|
+
}
|
|
8765
|
+
throw new Error(
|
|
8766
|
+
`Conversation ${context.conversationId} has a ${destination.platform} destination but no matching conversation worker`
|
|
8767
|
+
);
|
|
8768
|
+
};
|
|
7941
8769
|
const providerWorker = createAgentDispatchWorkRouter({
|
|
7942
8770
|
dispatchWorker,
|
|
7943
|
-
fallbackWorker:
|
|
8771
|
+
fallbackWorker: destinationWorker
|
|
7944
8772
|
});
|
|
7945
8773
|
return {
|
|
7946
8774
|
apiTurnCancellation,
|
|
7947
8775
|
conversationStore: options.conversationStore,
|
|
7948
8776
|
queue: options.queue,
|
|
7949
8777
|
run: routeApiTurnWork({
|
|
7950
|
-
apiTurnWorker: createApiTurnWorker(
|
|
7951
|
-
|
|
7952
|
-
|
|
7953
|
-
|
|
7954
|
-
}),
|
|
8778
|
+
apiTurnWorker: createApiTurnWorker(
|
|
8779
|
+
options.agentRunner,
|
|
8780
|
+
apiTurnCancellation
|
|
8781
|
+
),
|
|
7955
8782
|
fallbackWorker: routeAgentInvocationWork({
|
|
7956
8783
|
invocationWorker: createAgentInvocationWorker(options.agentRunner),
|
|
7957
8784
|
fallbackWorker: providerWorker
|
|
@@ -8151,6 +8978,66 @@ async function ingestEventTasks(input, options) {
|
|
|
8151
8978
|
return { dispatched };
|
|
8152
8979
|
}
|
|
8153
8980
|
|
|
8981
|
+
// src/chat/resource-events/workspace.ts
|
|
8982
|
+
function createResourceEventTeamIdResolver() {
|
|
8983
|
+
let pending;
|
|
8984
|
+
return async () => {
|
|
8985
|
+
if (!getSlackBotToken()) return void 0;
|
|
8986
|
+
pending ??= getSlackClient().auth.test().then((result) => {
|
|
8987
|
+
const teamId = result.team_id?.trim();
|
|
8988
|
+
if (!teamId) {
|
|
8989
|
+
throw new Error("Slack auth.test did not return a team id");
|
|
8990
|
+
}
|
|
8991
|
+
return teamId;
|
|
8992
|
+
}).catch((error) => {
|
|
8993
|
+
pending = void 0;
|
|
8994
|
+
throw error;
|
|
8995
|
+
});
|
|
8996
|
+
return await pending;
|
|
8997
|
+
};
|
|
8998
|
+
}
|
|
8999
|
+
|
|
9000
|
+
// src/chat/resource-events/app-publisher.ts
|
|
9001
|
+
function createResourceEventAppPublisher(args) {
|
|
9002
|
+
const resolveEventTaskTeamId = createResourceEventTeamIdResolver();
|
|
9003
|
+
return {
|
|
9004
|
+
async neededMatchKeys(input) {
|
|
9005
|
+
const work = args.conversationWork();
|
|
9006
|
+
const eventTaskTeamId = await resolveEventTaskTeamId();
|
|
9007
|
+
const [watchKeys, taskKeys] = await Promise.all([
|
|
9008
|
+
collectResourceEventMatchKeys({
|
|
9009
|
+
eventTypes: input.eventTypes,
|
|
9010
|
+
identifiers: input.identifiers,
|
|
9011
|
+
namespace: input.namespace,
|
|
9012
|
+
state: work.state
|
|
9013
|
+
}),
|
|
9014
|
+
eventTaskTeamId ? collectEventTaskMatchKeys(getDb(), {
|
|
9015
|
+
eventTypes: input.eventTypes,
|
|
9016
|
+
identifiers: input.identifiers,
|
|
9017
|
+
namespace: input.namespace,
|
|
9018
|
+
teamId: eventTaskTeamId
|
|
9019
|
+
}) : Promise.resolve([])
|
|
9020
|
+
]);
|
|
9021
|
+
return [.../* @__PURE__ */ new Set([...watchKeys, ...taskKeys])].sort();
|
|
9022
|
+
},
|
|
9023
|
+
async publish(event) {
|
|
9024
|
+
const work = args.conversationWork();
|
|
9025
|
+
const queue = work.queue ?? getVercelConversationWorkQueue();
|
|
9026
|
+
const eventTaskTeamId = await resolveEventTaskTeamId();
|
|
9027
|
+
await Promise.all([
|
|
9028
|
+
ingestResourceEvent(event, {
|
|
9029
|
+
queue,
|
|
9030
|
+
state: work.state
|
|
9031
|
+
}),
|
|
9032
|
+
eventTaskTeamId ? ingestEventTasks(event, {
|
|
9033
|
+
queue,
|
|
9034
|
+
teamId: eventTaskTeamId
|
|
9035
|
+
}) : Promise.resolve()
|
|
9036
|
+
]);
|
|
9037
|
+
}
|
|
9038
|
+
};
|
|
9039
|
+
}
|
|
9040
|
+
|
|
8154
9041
|
// src/chat/api-turns/stop.ts
|
|
8155
9042
|
async function stopApiConversationTurn(args) {
|
|
8156
9043
|
const nowMs = args.nowMs ?? Date.now();
|
|
@@ -8353,7 +9240,7 @@ import {
|
|
|
8353
9240
|
} from "crypto";
|
|
8354
9241
|
import * as acp3 from "@agentclientprotocol/sdk";
|
|
8355
9242
|
import { userSchema as userSchema2 } from "@sentry/junior-plugin-api";
|
|
8356
|
-
import { z as
|
|
9243
|
+
import { z as z8 } from "zod";
|
|
8357
9244
|
|
|
8358
9245
|
// src/api/acp/state.ts
|
|
8359
9246
|
import { setTimeout as wait } from "timers/promises";
|
|
@@ -8394,14 +9281,14 @@ async function fenceLock(state, lock, ttlMs = MUTATION_LOCK_TTL_MS) {
|
|
|
8394
9281
|
import { createHash as createHash2, randomUUID } from "crypto";
|
|
8395
9282
|
import * as acp2 from "@agentclientprotocol/sdk";
|
|
8396
9283
|
import { userSchema } from "@sentry/junior-plugin-api";
|
|
8397
|
-
import { z as
|
|
9284
|
+
import { z as z7 } from "zod";
|
|
8398
9285
|
|
|
8399
9286
|
// src/api/acp/schema.ts
|
|
8400
9287
|
import * as acp from "@agentclientprotocol/sdk";
|
|
8401
|
-
import { z as
|
|
9288
|
+
import { z as z6 } from "zod";
|
|
8402
9289
|
var ACP_SESSION_ID_PATTERN = /^local:acp:[a-f0-9]{32}$/;
|
|
8403
|
-
var metaSchema =
|
|
8404
|
-
var jsonRpcIdSchema =
|
|
9290
|
+
var metaSchema = z6.record(z6.string(), z6.unknown()).nullable();
|
|
9291
|
+
var jsonRpcIdSchema = z6.union([z6.string(), z6.number().finite(), z6.null()]);
|
|
8405
9292
|
var SESSION_HEADER_METHODS = /* @__PURE__ */ new Set([
|
|
8406
9293
|
acp.methods.agent.session.cancel,
|
|
8407
9294
|
acp.methods.agent.session.close,
|
|
@@ -8411,78 +9298,94 @@ var SESSION_HEADER_METHODS = /* @__PURE__ */ new Set([
|
|
|
8411
9298
|
acp.methods.agent.session.setConfigOption,
|
|
8412
9299
|
acp.methods.agent.session.setMode
|
|
8413
9300
|
]);
|
|
8414
|
-
var acpConnectionIdSchema =
|
|
8415
|
-
var acpSessionIdSchema =
|
|
8416
|
-
var acpCallSchema =
|
|
9301
|
+
var acpConnectionIdSchema = z6.string().uuid();
|
|
9302
|
+
var acpSessionIdSchema = z6.string().regex(ACP_SESSION_ID_PATTERN);
|
|
9303
|
+
var acpCallSchema = z6.object({
|
|
8417
9304
|
id: jsonRpcIdSchema.optional(),
|
|
8418
|
-
jsonrpc:
|
|
8419
|
-
method:
|
|
8420
|
-
params:
|
|
9305
|
+
jsonrpc: z6.literal("2.0"),
|
|
9306
|
+
method: z6.string().min(1),
|
|
9307
|
+
params: z6.unknown().optional()
|
|
8421
9308
|
}).strict();
|
|
8422
|
-
var jsonRpcErrorSchema =
|
|
8423
|
-
code:
|
|
8424
|
-
data:
|
|
8425
|
-
message:
|
|
9309
|
+
var jsonRpcErrorSchema = z6.object({
|
|
9310
|
+
code: z6.number().int(),
|
|
9311
|
+
data: z6.unknown().optional(),
|
|
9312
|
+
message: z6.string()
|
|
8426
9313
|
}).strict();
|
|
8427
|
-
var acpResponseSchema =
|
|
8428
|
-
|
|
9314
|
+
var acpResponseSchema = z6.union([
|
|
9315
|
+
z6.object({
|
|
8429
9316
|
id: jsonRpcIdSchema,
|
|
8430
|
-
jsonrpc:
|
|
8431
|
-
result:
|
|
9317
|
+
jsonrpc: z6.literal("2.0"),
|
|
9318
|
+
result: z6.unknown()
|
|
8432
9319
|
}).strict(),
|
|
8433
|
-
|
|
9320
|
+
z6.object({
|
|
8434
9321
|
error: jsonRpcErrorSchema,
|
|
8435
9322
|
id: jsonRpcIdSchema,
|
|
8436
|
-
jsonrpc:
|
|
9323
|
+
jsonrpc: z6.literal("2.0")
|
|
8437
9324
|
}).strict()
|
|
8438
9325
|
]);
|
|
8439
|
-
var acpInboundMessageSchema =
|
|
9326
|
+
var acpInboundMessageSchema = z6.union([
|
|
8440
9327
|
acpCallSchema,
|
|
8441
9328
|
acpResponseSchema
|
|
8442
9329
|
]);
|
|
8443
|
-
var implementationSchema =
|
|
9330
|
+
var implementationSchema = z6.object({
|
|
8444
9331
|
_meta: metaSchema.optional(),
|
|
8445
|
-
name:
|
|
8446
|
-
title:
|
|
8447
|
-
version:
|
|
9332
|
+
name: z6.string().min(1),
|
|
9333
|
+
title: z6.string().nullable().optional(),
|
|
9334
|
+
version: z6.string()
|
|
8448
9335
|
}).strict();
|
|
8449
|
-
var initializeParamsSchema =
|
|
9336
|
+
var initializeParamsSchema = z6.object({
|
|
8450
9337
|
_meta: metaSchema.optional(),
|
|
8451
|
-
clientCapabilities:
|
|
9338
|
+
clientCapabilities: z6.record(z6.string(), z6.unknown()).optional(),
|
|
8452
9339
|
clientInfo: implementationSchema.nullable().optional(),
|
|
8453
|
-
protocolVersion:
|
|
9340
|
+
protocolVersion: z6.number().int().min(0).max(65535)
|
|
8454
9341
|
}).strict();
|
|
8455
|
-
var authenticateParamsSchema =
|
|
9342
|
+
var authenticateParamsSchema = z6.object({
|
|
8456
9343
|
_meta: metaSchema.optional(),
|
|
8457
|
-
methodId:
|
|
9344
|
+
methodId: z6.string().min(1)
|
|
8458
9345
|
}).strict();
|
|
8459
|
-
var newSessionParamsSchema =
|
|
9346
|
+
var newSessionParamsSchema = z6.object({
|
|
8460
9347
|
_meta: metaSchema.optional(),
|
|
8461
|
-
additionalDirectories:
|
|
8462
|
-
cwd:
|
|
8463
|
-
mcpServers:
|
|
9348
|
+
additionalDirectories: z6.array(z6.string()).optional(),
|
|
9349
|
+
cwd: z6.string().min(1),
|
|
9350
|
+
mcpServers: z6.array(z6.unknown())
|
|
8464
9351
|
}).strict();
|
|
8465
9352
|
var loadSessionParamsSchema = newSessionParamsSchema.extend({
|
|
8466
9353
|
sessionId: acpSessionIdSchema
|
|
8467
9354
|
});
|
|
8468
|
-
var annotationsSchema =
|
|
9355
|
+
var annotationsSchema = z6.object({
|
|
9356
|
+
_meta: metaSchema.optional(),
|
|
9357
|
+
audience: z6.array(z6.enum(["assistant", "user"])).nullable().optional(),
|
|
9358
|
+
lastModified: z6.string().nullable().optional(),
|
|
9359
|
+
priority: z6.number().finite().nullable().optional()
|
|
9360
|
+
}).strict();
|
|
9361
|
+
var textContentBlockSchema = z6.object({
|
|
8469
9362
|
_meta: metaSchema.optional(),
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
|
|
9363
|
+
annotations: annotationsSchema.nullable().optional(),
|
|
9364
|
+
text: z6.string(),
|
|
9365
|
+
type: z6.literal("text")
|
|
8473
9366
|
}).strict();
|
|
8474
|
-
var
|
|
9367
|
+
var resourceLinkContentBlockSchema = z6.object({
|
|
8475
9368
|
_meta: metaSchema.optional(),
|
|
8476
9369
|
annotations: annotationsSchema.nullable().optional(),
|
|
8477
|
-
|
|
8478
|
-
|
|
9370
|
+
description: z6.string().nullable().optional(),
|
|
9371
|
+
mimeType: z6.string().nullable().optional(),
|
|
9372
|
+
name: z6.string(),
|
|
9373
|
+
size: z6.number().finite().nullable().optional(),
|
|
9374
|
+
title: z6.string().nullable().optional(),
|
|
9375
|
+
type: z6.literal("resource_link"),
|
|
9376
|
+
uri: z6.string()
|
|
8479
9377
|
}).strict();
|
|
8480
|
-
var promptParamsSchema =
|
|
9378
|
+
var promptParamsSchema = z6.object({
|
|
8481
9379
|
_meta: metaSchema.optional(),
|
|
8482
|
-
prompt:
|
|
9380
|
+
prompt: z6.array(
|
|
9381
|
+
z6.discriminatedUnion("type", [
|
|
9382
|
+
textContentBlockSchema,
|
|
9383
|
+
resourceLinkContentBlockSchema
|
|
9384
|
+
])
|
|
9385
|
+
),
|
|
8483
9386
|
sessionId: acpSessionIdSchema
|
|
8484
9387
|
}).strict();
|
|
8485
|
-
var cancelParamsSchema =
|
|
9388
|
+
var cancelParamsSchema = z6.object({
|
|
8486
9389
|
_meta: metaSchema.optional(),
|
|
8487
9390
|
sessionId: acpSessionIdSchema
|
|
8488
9391
|
}).strict();
|
|
@@ -8520,41 +9423,41 @@ var MUTATION_LOCK_OPTIONS = {
|
|
|
8520
9423
|
};
|
|
8521
9424
|
var SSE_KEEP_ALIVE_MS = 15e3;
|
|
8522
9425
|
var SSE_MAINTENANCE_INTERVAL_MS = 1e3;
|
|
8523
|
-
var jsonRpcIdSchema2 =
|
|
8524
|
-
var acpConnectionSchema =
|
|
8525
|
-
credentialHash:
|
|
8526
|
-
nonce:
|
|
9426
|
+
var jsonRpcIdSchema2 = z7.union([z7.string(), z7.number().finite(), z7.null()]);
|
|
9427
|
+
var acpConnectionSchema = z7.object({
|
|
9428
|
+
credentialHash: z7.string().length(64),
|
|
9429
|
+
nonce: z7.string().min(1),
|
|
8527
9430
|
user: userSchema.optional()
|
|
8528
9431
|
}).strict();
|
|
8529
|
-
var acpStreamRouteSchema =
|
|
8530
|
-
connectionId:
|
|
8531
|
-
sessionId:
|
|
9432
|
+
var acpStreamRouteSchema = z7.object({
|
|
9433
|
+
connectionId: z7.string().min(1),
|
|
9434
|
+
sessionId: z7.string().min(1).optional()
|
|
8532
9435
|
}).strict();
|
|
8533
|
-
var acpPromptStreamOutputSchema =
|
|
8534
|
-
afterSeq:
|
|
8535
|
-
kind:
|
|
8536
|
-
messageId:
|
|
9436
|
+
var acpPromptStreamOutputSchema = z7.object({
|
|
9437
|
+
afterSeq: z7.number().int().nonnegative(),
|
|
9438
|
+
kind: z7.literal("prompt"),
|
|
9439
|
+
messageId: z7.string().min(1),
|
|
8537
9440
|
requestId: jsonRpcIdSchema2,
|
|
8538
|
-
turnId:
|
|
9441
|
+
turnId: z7.string().min(1)
|
|
8539
9442
|
}).strict();
|
|
8540
|
-
var acpStreamOutputSchema =
|
|
8541
|
-
|
|
8542
|
-
kind:
|
|
9443
|
+
var acpStreamOutputSchema = z7.discriminatedUnion("kind", [
|
|
9444
|
+
z7.object({
|
|
9445
|
+
kind: z7.literal("message"),
|
|
8543
9446
|
message: acpInboundMessageSchema
|
|
8544
9447
|
}).strict(),
|
|
8545
|
-
|
|
9448
|
+
z7.object({ kind: z7.literal("replay") }).strict(),
|
|
8546
9449
|
acpPromptStreamOutputSchema
|
|
8547
9450
|
]);
|
|
8548
|
-
var storedAcpStreamItemSchema =
|
|
8549
|
-
id:
|
|
9451
|
+
var storedAcpStreamItemSchema = z7.object({
|
|
9452
|
+
id: z7.string().min(1),
|
|
8550
9453
|
output: acpStreamOutputSchema
|
|
8551
9454
|
}).strict();
|
|
8552
|
-
var acpRequestReceiptSchema =
|
|
8553
|
-
deliveryKey:
|
|
8554
|
-
outputs:
|
|
8555
|
-
sessionId:
|
|
9455
|
+
var acpRequestReceiptSchema = z7.object({
|
|
9456
|
+
deliveryKey: z7.string().min(1).optional(),
|
|
9457
|
+
outputs: z7.array(acpStreamOutputSchema),
|
|
9458
|
+
sessionId: z7.string().min(1).optional()
|
|
8556
9459
|
}).strict();
|
|
8557
|
-
var acpStreamCursorSchema =
|
|
9460
|
+
var acpStreamCursorSchema = z7.object({ itemId: z7.string().min(1) }).strict();
|
|
8558
9461
|
function stableHex(value) {
|
|
8559
9462
|
return createHash2("sha256").update(value).digest("hex").slice(0, 32);
|
|
8560
9463
|
}
|
|
@@ -9163,19 +10066,19 @@ function createSseBody(args) {
|
|
|
9163
10066
|
var ACP_AUTHORIZATION_TTL_MS = 10 * 60 * 1e3;
|
|
9164
10067
|
var ACP_CONNECTION_COOKIE = "junior_acp_connection";
|
|
9165
10068
|
var LOCK_WAIT_MS2 = 5e3;
|
|
9166
|
-
var jsonRpcIdSchema3 =
|
|
9167
|
-
var acpAuthorizationSchema =
|
|
9168
|
-
connectionId:
|
|
9169
|
-
credentialHash:
|
|
9170
|
-
elicitationId:
|
|
9171
|
-
expiresAtMs:
|
|
10069
|
+
var jsonRpcIdSchema3 = z8.union([z8.string(), z8.number().finite(), z8.null()]);
|
|
10070
|
+
var acpAuthorizationSchema = z8.object({
|
|
10071
|
+
connectionId: z8.string().uuid(),
|
|
10072
|
+
credentialHash: z8.string().length(64),
|
|
10073
|
+
elicitationId: z8.string().uuid(),
|
|
10074
|
+
expiresAtMs: z8.number().int().positive(),
|
|
9172
10075
|
requestId: jsonRpcIdSchema3,
|
|
9173
|
-
requestKey:
|
|
9174
|
-
userCodeHash:
|
|
10076
|
+
requestKey: z8.string().min(1),
|
|
10077
|
+
userCodeHash: z8.string().length(64)
|
|
9175
10078
|
}).strict();
|
|
9176
|
-
var acpAuthorizationPointerSchema =
|
|
9177
|
-
expiresAtMs:
|
|
9178
|
-
transactionId:
|
|
10079
|
+
var acpAuthorizationPointerSchema = z8.object({
|
|
10080
|
+
expiresAtMs: z8.number().int().positive(),
|
|
10081
|
+
transactionId: z8.string().uuid()
|
|
9179
10082
|
}).strict();
|
|
9180
10083
|
var ACP_AUTH_METHOD_ID = "junior";
|
|
9181
10084
|
var ACP_AUTH_METHOD = {
|
|
@@ -9502,7 +10405,7 @@ async function completeAcpAuthorization(args) {
|
|
|
9502
10405
|
}
|
|
9503
10406
|
async function handleAcpAuthorizationResponse(args) {
|
|
9504
10407
|
if (typeof args.response.id !== "string") return "ignored";
|
|
9505
|
-
const parsedId =
|
|
10408
|
+
const parsedId = z8.string().uuid().safeParse(args.response.id);
|
|
9506
10409
|
if (!parsedId.success) return "ignored";
|
|
9507
10410
|
const authorization = await readAuthorization(args.state, parsedId.data);
|
|
9508
10411
|
if (!authorization || authorization.connectionId !== args.connectionId) {
|
|
@@ -9619,15 +10522,30 @@ function rejectUnsupportedMcpServers(mcpServers) {
|
|
|
9619
10522
|
);
|
|
9620
10523
|
}
|
|
9621
10524
|
}
|
|
10525
|
+
function resourceLinkText(block) {
|
|
10526
|
+
return [
|
|
10527
|
+
"Resource link:",
|
|
10528
|
+
`Name: ${block.name}`,
|
|
10529
|
+
`URI: ${block.uri}`,
|
|
10530
|
+
...block.title ? [`Title: ${block.title}`] : [],
|
|
10531
|
+
...block.description ? [`Description: ${block.description}`] : [],
|
|
10532
|
+
...block.mimeType ? [`MIME type: ${block.mimeType}`] : [],
|
|
10533
|
+
...block.size !== void 0 && block.size !== null ? [`Size: ${block.size} bytes`] : []
|
|
10534
|
+
].join("\n");
|
|
10535
|
+
}
|
|
9622
10536
|
function promptText(prompt) {
|
|
9623
10537
|
if (prompt.length === 0) {
|
|
9624
10538
|
throw acp4.RequestError.invalidParams(
|
|
9625
10539
|
{ field: "prompt" },
|
|
9626
|
-
"Junior accepts one or more text blocks
|
|
10540
|
+
"Junior accepts one or more text or resource link blocks"
|
|
9627
10541
|
);
|
|
9628
10542
|
}
|
|
9629
10543
|
const blocks = [];
|
|
9630
10544
|
for (const block of prompt) {
|
|
10545
|
+
if (block.type === "resource_link") {
|
|
10546
|
+
blocks.push(resourceLinkText(block));
|
|
10547
|
+
continue;
|
|
10548
|
+
}
|
|
9631
10549
|
if (!block.text.trim()) {
|
|
9632
10550
|
throw acp4.RequestError.invalidParams(
|
|
9633
10551
|
{ field: "prompt" },
|
|
@@ -10623,53 +11541,9 @@ async function createApp(options) {
|
|
|
10623
11541
|
};
|
|
10624
11542
|
let pluginRoutes = [];
|
|
10625
11543
|
let pluginApiRoutes = [];
|
|
10626
|
-
const
|
|
10627
|
-
|
|
10628
|
-
|
|
10629
|
-
const teamId = await resolveResourceEventTeamId();
|
|
10630
|
-
if (!teamId) return [];
|
|
10631
|
-
const conversationWork = getConversationWorkOptions();
|
|
10632
|
-
const [watchKeys, taskKeys] = await Promise.all([
|
|
10633
|
-
collectResourceEventMatchKeys({
|
|
10634
|
-
eventTypes: input.eventTypes,
|
|
10635
|
-
identifiers: input.identifiers,
|
|
10636
|
-
namespace: input.namespace,
|
|
10637
|
-
state: conversationWork.state,
|
|
10638
|
-
teamId
|
|
10639
|
-
}),
|
|
10640
|
-
collectEventTaskMatchKeys(getDb(), {
|
|
10641
|
-
eventTypes: input.eventTypes,
|
|
10642
|
-
identifiers: input.identifiers,
|
|
10643
|
-
namespace: input.namespace,
|
|
10644
|
-
teamId
|
|
10645
|
-
})
|
|
10646
|
-
]);
|
|
10647
|
-
return [.../* @__PURE__ */ new Set([...watchKeys, ...taskKeys])].sort();
|
|
10648
|
-
},
|
|
10649
|
-
async publish(event) {
|
|
10650
|
-
const teamId = await resolveResourceEventTeamId();
|
|
10651
|
-
if (!teamId) {
|
|
10652
|
-
logWarn("resource_event.delivery.unavailable", {
|
|
10653
|
-
"app.resource_event.namespace": event.namespace,
|
|
10654
|
-
"app.resource_event.reason": "multi_workspace"
|
|
10655
|
-
});
|
|
10656
|
-
return;
|
|
10657
|
-
}
|
|
10658
|
-
const conversationWork = getConversationWorkOptions();
|
|
10659
|
-
const queue = conversationWork.queue ?? getVercelConversationWorkQueue();
|
|
10660
|
-
await Promise.all([
|
|
10661
|
-
ingestResourceEvent(event, {
|
|
10662
|
-
queue,
|
|
10663
|
-
state: conversationWork.state,
|
|
10664
|
-
teamId
|
|
10665
|
-
}),
|
|
10666
|
-
ingestEventTasks(event, {
|
|
10667
|
-
queue,
|
|
10668
|
-
teamId
|
|
10669
|
-
})
|
|
10670
|
-
]);
|
|
10671
|
-
}
|
|
10672
|
-
};
|
|
11544
|
+
const resourceEvents = createResourceEventAppPublisher({
|
|
11545
|
+
conversationWork: () => getConversationWorkOptions()
|
|
11546
|
+
});
|
|
10673
11547
|
let sandboxEgressTracePropagationDomains = [];
|
|
10674
11548
|
try {
|
|
10675
11549
|
sandboxEgressTracePropagationDomains = normalizeSandboxEgressTracePropagationDomains(
|
|
@@ -10710,7 +11584,7 @@ async function createApp(options) {
|
|
|
10710
11584
|
tracePropagation
|
|
10711
11585
|
});
|
|
10712
11586
|
const runtimeServiceOverrides = {
|
|
10713
|
-
|
|
11587
|
+
agentRunner,
|
|
10714
11588
|
sandbox: { tracePropagation }
|
|
10715
11589
|
};
|
|
10716
11590
|
let conversationWorkOptions;
|