@sentry/junior 0.181.0 → 0.182.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-IQUW6ERD.js → agent-hooks-3S25UIHO.js} +11 -11
- package/dist/api.js +125 -51
- package/dist/app-adapter.d.ts +85 -0
- package/dist/app.d.ts +6 -1
- package/dist/app.js +343 -487
- package/dist/{catalog-runtime-PMQWNIXA.js → catalog-runtime-ESLMBQBV.js} +4 -4
- package/dist/chat/api-turns/adapter-conversations.d.ts +15 -0
- package/dist/chat/api-turns/stop.d.ts +12 -0
- package/dist/chat/api-turns/work.d.ts +9 -1
- package/dist/chat/app/conversation-work.d.ts +1 -1
- package/dist/chat/event-tasks/tool-support.d.ts +7 -1
- package/dist/chat/event-tasks/types.d.ts +1 -0
- package/dist/chat/experimental.d.ts +1 -1
- package/dist/chat/resource-events/catalog.d.ts +11 -1
- package/dist/chat/resource-events/store.d.ts +5 -1
- package/dist/chat/services/subscribed-decision.d.ts +2 -1
- package/dist/chat/tools/create-event-task.d.ts +3 -0
- package/dist/chat/tools/delete-event-task.d.ts +2 -0
- package/dist/chat/tools/list-event-tasks.d.ts +2 -0
- package/dist/chat/tools/list-resource-event-subscriptions.d.ts +2 -0
- package/dist/chat/tools/search-resource-event-types.d.ts +10 -0
- package/dist/chat/tools/update-event-task.d.ts +3 -0
- package/dist/chat/tools/watch-resource-events.d.ts +3 -0
- package/dist/{chunk-D6ZD7VXP.js → chunk-2CEOXDG2.js} +20 -11
- package/dist/{chunk-VRS6WDK5.js → chunk-2LYHWMR4.js} +1 -1
- package/dist/{chunk-IKKETMQC.js → chunk-3ENUMZNG.js} +3 -3
- package/dist/{chunk-IJ6SS4WB.js → chunk-3NFHI2NA.js} +1 -1
- package/dist/{chunk-GREV5PJK.js → chunk-3THPTNN6.js} +4 -4
- package/dist/{chunk-KKSVCHDO.js → chunk-44BQ3TSK.js} +1 -1
- package/dist/{chunk-4IX32NSL.js → chunk-4DZ62L36.js} +1 -1
- package/dist/{chunk-RNMASWLP.js → chunk-6TSWXBTQ.js} +3 -3
- package/dist/{chunk-PBKZQAUA.js → chunk-A7THOQ6N.js} +58 -32
- package/dist/{chunk-DSA6WTRP.js → chunk-BDDWVY32.js} +19 -19
- package/dist/{chunk-TJHSAHQN.js → chunk-BZD4ADQH.js} +3 -2
- package/dist/{chunk-EU7KJDOG.js → chunk-CVBIM4Z3.js} +1 -1
- package/dist/{chunk-LZOQFC5F.js → chunk-D6OHGAIO.js} +5 -5
- package/dist/{chunk-KQZX24QQ.js → chunk-DZR3L74W.js} +3 -3
- package/dist/{chunk-3KCQEG6W.js → chunk-GGYA5NPN.js} +9 -9
- package/dist/{chunk-EM7EECT5.js → chunk-JIOKUIAS.js} +2 -2
- package/dist/{chunk-3X55QRAG.js → chunk-KGMHUDVF.js} +6 -6
- package/dist/{chunk-3KSSALN4.js → chunk-LB4FWMCV.js} +92 -8
- package/dist/{chunk-XYTJUHRZ.js → chunk-LHQK5XCU.js} +2 -2
- package/dist/{chunk-LCNPXLE7.js → chunk-LT4QYGKM.js} +7 -7
- package/dist/{chunk-TDT2R77B.js → chunk-MJISSOWB.js} +1 -1
- package/dist/{chunk-FWILPBVQ.js → chunk-PQES5LB5.js} +5 -5
- package/dist/{chunk-GWFRPQNP.js → chunk-QHALFHZA.js} +9 -9
- package/dist/{chunk-PPYDHUEL.js → chunk-S35OZMSL.js} +130 -200
- package/dist/{chunk-ETJTXYHY.js → chunk-SVFSYQMT.js} +1 -1
- package/dist/{chunk-NQTA72Q3.js → chunk-SXOZIG5X.js} +6 -6
- package/dist/{chunk-Q2KY27IX.js → chunk-TEFNHMO2.js} +63 -7
- package/dist/{chunk-KMBU4PJP.js → chunk-UKIHNBBD.js} +3 -3
- package/dist/{chunk-EBMRB6Z6.js → chunk-UQP54CXZ.js} +1 -1
- package/dist/{chunk-GPA3ZSYY.js → chunk-UUMBHORH.js} +1 -1
- package/dist/{chunk-LG5MYY6U.js → chunk-V5UZCCNW.js} +6 -6
- package/dist/{chunk-HZHUMCNV.js → chunk-VHMAFMHB.js} +1 -1
- package/dist/{chunk-HEBMSITT.js → chunk-WOIALVN2.js} +1 -1
- package/dist/{chunk-HJ27A6YB.js → chunk-YHL2L2ZZ.js} +1 -1
- package/dist/{chunk-PL57B6NC.js → chunk-Z7ALSQS3.js} +1 -1
- package/dist/cli/chat.js +34 -34
- package/dist/cli/check.js +5 -5
- package/dist/cli/plugins.js +12 -12
- package/dist/cli/snapshot-create.js +9 -9
- package/dist/cli/upgrade.js +6 -6
- package/dist/{db-QNPVCQPT.js → db-NYIWZ4L5.js} +6 -6
- package/dist/{experimental-SIJSRDJD.js → experimental-P5FZM4CU.js} +1 -1
- package/dist/instrumentation.js +3 -3
- package/dist/nitro.js +6 -6
- package/dist/{oauth-callback-server-KYMPJOTC.js → oauth-callback-server-A2YTPVVX.js} +26 -26
- package/dist/{runner-3RS2D2ZR.js → runner-VKAEU52J.js} +18 -18
- package/dist/{skills-5B3Y6XX6.js → skills-52GMXUTY.js} +5 -5
- package/dist/spawn-GSS4EBLR.js +37 -0
- package/dist/task-runner-DUGDWF5O.js +32 -0
- package/dist/{validation-Q65QD27B.js → validation-VD2YQX2W.js} +5 -5
- package/dist/version.js +1 -1
- package/dist/{work-DCMQWAAP.js → work-ZWBTGEQP.js} +18 -18
- package/dist/worker-XUWD5WS7.js +22 -0
- package/package.json +6 -5
- package/dist/api/acp/route.d.ts +0 -13
- package/dist/spawn-VYARS3DU.js +0 -37
- package/dist/task-runner-4IXKKZHL.js +0 -32
- package/dist/worker-QL3CHLZL.js +0 -22
package/dist/app.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
processConversationWork
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3THPTNN6.js";
|
|
4
4
|
import {
|
|
5
5
|
bindSpawnAgent
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-VHMAFMHB.js";
|
|
7
7
|
import {
|
|
8
8
|
createAgentInvocationWorker,
|
|
9
9
|
enqueueAgentInvocation,
|
|
10
10
|
listPendingAgentInvocationMailboxAppends,
|
|
11
11
|
routeAgentInvocationWork
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-LT4QYGKM.js";
|
|
13
13
|
import {
|
|
14
14
|
GET as GET2,
|
|
15
15
|
GET2 as GET3,
|
|
@@ -36,25 +36,25 @@ import {
|
|
|
36
36
|
startSlackProcessingReaction,
|
|
37
37
|
stripLeadingBotMention,
|
|
38
38
|
wakePausedTurn
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-BDDWVY32.js";
|
|
40
40
|
import "./chunk-FA6POGLH.js";
|
|
41
41
|
import {
|
|
42
42
|
GET,
|
|
43
43
|
apiTurnIdForMessage,
|
|
44
44
|
appendAndEnqueueApiConversationMessage,
|
|
45
|
-
authenticatePersonalToken,
|
|
46
45
|
conversationVisibilityFromSlackChannelType,
|
|
47
46
|
createApiTurnCancellation,
|
|
48
47
|
createApiTurnWorker,
|
|
49
48
|
createVercelAttachmentStorage,
|
|
49
|
+
getAuthPausedApiTurnId,
|
|
50
50
|
readConversationAccessFromSql,
|
|
51
51
|
recordApiConversationActivity,
|
|
52
52
|
resolveSlackChannelTypeFromMessage,
|
|
53
53
|
resolveSlackConversationContext,
|
|
54
54
|
routeApiTurnWork,
|
|
55
55
|
webActorFromEmail
|
|
56
|
-
} from "./chunk-
|
|
57
|
-
import "./chunk-
|
|
56
|
+
} from "./chunk-S35OZMSL.js";
|
|
57
|
+
import "./chunk-CVBIM4Z3.js";
|
|
58
58
|
import {
|
|
59
59
|
buildDeliveredTurnStatePatch,
|
|
60
60
|
completeAuthPauseTurn,
|
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
getTurnUserSlackMessageTs,
|
|
66
66
|
persistAuthPauseTurnState,
|
|
67
67
|
requireTurnFailureEventId
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-D6OHGAIO.js";
|
|
69
69
|
import {
|
|
70
70
|
claimDispatchMailboxAppend,
|
|
71
71
|
confirmDispatchMailboxAppend,
|
|
@@ -85,7 +85,7 @@ import {
|
|
|
85
85
|
recordTaskExecution,
|
|
86
86
|
resolveTurnSessionRouting,
|
|
87
87
|
scheduleSessionCompletedPluginTasks
|
|
88
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-QHALFHZA.js";
|
|
89
89
|
import {
|
|
90
90
|
ConversationTurnLifecycleService
|
|
91
91
|
} from "./chunk-M3QYTBQ6.js";
|
|
@@ -97,17 +97,17 @@ import {
|
|
|
97
97
|
persistThreadRuntimeState,
|
|
98
98
|
persistThreadState,
|
|
99
99
|
persistThreadStateById
|
|
100
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-PQES5LB5.js";
|
|
101
101
|
import "./chunk-UTL3MHPC.js";
|
|
102
102
|
import {
|
|
103
103
|
createVercelPluginTaskCallback,
|
|
104
104
|
queueCallback,
|
|
105
105
|
registerVercelPluginTaskDevConsumer
|
|
106
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-DZR3L74W.js";
|
|
107
107
|
import {
|
|
108
108
|
validatePluginEgressCredentialHooks,
|
|
109
109
|
validatePluginRegistrations
|
|
110
|
-
} from "./chunk-
|
|
110
|
+
} from "./chunk-3NFHI2NA.js";
|
|
111
111
|
import {
|
|
112
112
|
defineJuniorPlugins,
|
|
113
113
|
pluginCatalogConfigFromEnv,
|
|
@@ -155,11 +155,11 @@ import {
|
|
|
155
155
|
unpublishedArtifactHeaders,
|
|
156
156
|
verifySlackSignature,
|
|
157
157
|
withNormalizedThreadId
|
|
158
|
-
} from "./chunk-
|
|
158
|
+
} from "./chunk-A7THOQ6N.js";
|
|
159
159
|
import {
|
|
160
160
|
AuthorizationFlowDisabledError,
|
|
161
161
|
PluginCredentialFailureError
|
|
162
|
-
} from "./chunk-
|
|
162
|
+
} from "./chunk-KGMHUDVF.js";
|
|
163
163
|
import "./chunk-6Y5B5PEX.js";
|
|
164
164
|
import "./chunk-DIB4GX3G.js";
|
|
165
165
|
import {
|
|
@@ -168,7 +168,7 @@ import {
|
|
|
168
168
|
deleteMcpAuthSessionsForUserProvider,
|
|
169
169
|
deleteMcpServerSessionId,
|
|
170
170
|
deleteMcpStoredOAuthCredentials
|
|
171
|
-
} from "./chunk-
|
|
171
|
+
} from "./chunk-GGYA5NPN.js";
|
|
172
172
|
import {
|
|
173
173
|
RetryableDeliveryError
|
|
174
174
|
} from "./chunk-RF6J3DIO.js";
|
|
@@ -176,12 +176,12 @@ import {
|
|
|
176
176
|
formatProviderLabel,
|
|
177
177
|
postSlackMessage,
|
|
178
178
|
startOAuthFlow
|
|
179
|
-
} from "./chunk-
|
|
179
|
+
} from "./chunk-V5UZCCNW.js";
|
|
180
180
|
import {
|
|
181
181
|
getExperimentalFeatures,
|
|
182
182
|
isExperimentalFeatureEnabled,
|
|
183
183
|
setExperimentalFeatures
|
|
184
|
-
} from "./chunk-
|
|
184
|
+
} from "./chunk-2LYHWMR4.js";
|
|
185
185
|
import {
|
|
186
186
|
collectAttachmentGarbage,
|
|
187
187
|
findMatchingEventTasks,
|
|
@@ -196,21 +196,25 @@ import {
|
|
|
196
196
|
scheduledRunId,
|
|
197
197
|
scheduledRunSchema,
|
|
198
198
|
withScheduledTaskLock
|
|
199
|
-
} from "./chunk-
|
|
199
|
+
} from "./chunk-LB4FWMCV.js";
|
|
200
200
|
import {
|
|
201
201
|
parseSlackThreadId
|
|
202
|
-
} from "./chunk-
|
|
202
|
+
} from "./chunk-MJISSOWB.js";
|
|
203
203
|
import {
|
|
204
204
|
CONVERSATION_WORK_STALE_ENQUEUE_MS,
|
|
205
205
|
appendAndEnqueueInboundMessage,
|
|
206
206
|
clearExpiredConversationLease,
|
|
207
207
|
ensureConversationWake,
|
|
208
|
+
getConversation,
|
|
208
209
|
getConversationWorkState,
|
|
209
210
|
hasRunnableConversationWork,
|
|
211
|
+
hasRunnableConversationWork2,
|
|
210
212
|
isInvalidConversationRecordError,
|
|
211
213
|
listActiveConversationIds,
|
|
212
|
-
removeActiveConversation
|
|
213
|
-
|
|
214
|
+
removeActiveConversation,
|
|
215
|
+
requestConversationWork,
|
|
216
|
+
stopConversationWork
|
|
217
|
+
} from "./chunk-TEFNHMO2.js";
|
|
214
218
|
import {
|
|
215
219
|
ConversationTurnBoundaryError,
|
|
216
220
|
CooperativeTurnYieldError,
|
|
@@ -228,7 +232,7 @@ import {
|
|
|
228
232
|
markTurnCompleted,
|
|
229
233
|
markTurnFailed,
|
|
230
234
|
startActiveTurn
|
|
231
|
-
} from "./chunk-
|
|
235
|
+
} from "./chunk-YHL2L2ZZ.js";
|
|
232
236
|
import {
|
|
233
237
|
abandonTurnRecord,
|
|
234
238
|
appendThreadContextMessages,
|
|
@@ -264,11 +268,11 @@ import {
|
|
|
264
268
|
trimTrailingAssistantMessages,
|
|
265
269
|
turnHasReply,
|
|
266
270
|
upsertConversationMessage
|
|
267
|
-
} from "./chunk-
|
|
271
|
+
} from "./chunk-SXOZIG5X.js";
|
|
268
272
|
import {
|
|
269
273
|
getSandboxResourceConfig,
|
|
270
274
|
setSandboxResourceConfig
|
|
271
|
-
} from "./chunk-
|
|
275
|
+
} from "./chunk-3ENUMZNG.js";
|
|
272
276
|
import "./chunk-PDO5BLNM.js";
|
|
273
277
|
import "./chunk-UIE3R5XU.js";
|
|
274
278
|
import {
|
|
@@ -287,7 +291,7 @@ import {
|
|
|
287
291
|
import "./chunk-7H2VZTWN.js";
|
|
288
292
|
import {
|
|
289
293
|
getTurnRequestDeadline
|
|
290
|
-
} from "./chunk-
|
|
294
|
+
} from "./chunk-UUMBHORH.js";
|
|
291
295
|
import {
|
|
292
296
|
SlackActionError,
|
|
293
297
|
bindEventTaskCredentialSubject,
|
|
@@ -305,7 +309,6 @@ import {
|
|
|
305
309
|
getWorkspaceTeamId,
|
|
306
310
|
isDmChannel,
|
|
307
311
|
normalizeSlackConversationId,
|
|
308
|
-
resolveViewerUser,
|
|
309
312
|
runWithWorkspaceTeamId,
|
|
310
313
|
setDashboardConversationLinkOptions,
|
|
311
314
|
setPlugins,
|
|
@@ -313,7 +316,7 @@ import {
|
|
|
313
316
|
verifyEventTaskCredentialSubject,
|
|
314
317
|
verifyScheduledTaskCredentialSubject,
|
|
315
318
|
verifySlackDirectCredentialSubject
|
|
316
|
-
} from "./chunk-
|
|
319
|
+
} from "./chunk-2CEOXDG2.js";
|
|
317
320
|
import "./chunk-3Y47VMHV.js";
|
|
318
321
|
import {
|
|
319
322
|
contextProvenance,
|
|
@@ -326,7 +329,7 @@ import {
|
|
|
326
329
|
requireSlackDestination,
|
|
327
330
|
withConversationEventLock,
|
|
328
331
|
withConversationMutationLock
|
|
329
|
-
} from "./chunk-
|
|
332
|
+
} from "./chunk-6TSWXBTQ.js";
|
|
330
333
|
import {
|
|
331
334
|
juniorAgentBindings,
|
|
332
335
|
juniorAgentInvocations,
|
|
@@ -334,15 +337,13 @@ import {
|
|
|
334
337
|
juniorConversations,
|
|
335
338
|
juniorSchedulerRuns,
|
|
336
339
|
juniorSchedulerTasks
|
|
337
|
-
} from "./chunk-
|
|
338
|
-
import
|
|
339
|
-
sleep
|
|
340
|
-
} from "./chunk-KMBU4PJP.js";
|
|
340
|
+
} from "./chunk-44BQ3TSK.js";
|
|
341
|
+
import "./chunk-UKIHNBBD.js";
|
|
341
342
|
import {
|
|
342
343
|
acquireActiveLock,
|
|
343
344
|
getStateAdapter,
|
|
344
345
|
withActiveLock
|
|
345
|
-
} from "./chunk-
|
|
346
|
+
} from "./chunk-Z7ALSQS3.js";
|
|
346
347
|
import {
|
|
347
348
|
juniorDestinations
|
|
348
349
|
} from "./chunk-VFUK3X5B.js";
|
|
@@ -363,13 +364,13 @@ import {
|
|
|
363
364
|
modelIdForProfile,
|
|
364
365
|
setProfiles,
|
|
365
366
|
setSlackReactionConfig
|
|
366
|
-
} from "./chunk-
|
|
367
|
-
import "./chunk-
|
|
368
|
-
import "./chunk-
|
|
367
|
+
} from "./chunk-LHQK5XCU.js";
|
|
368
|
+
import "./chunk-SVFSYQMT.js";
|
|
369
|
+
import "./chunk-JIOKUIAS.js";
|
|
369
370
|
import {
|
|
370
371
|
pluginCatalogRuntime
|
|
371
|
-
} from "./chunk-
|
|
372
|
-
import "./chunk-
|
|
372
|
+
} from "./chunk-WOIALVN2.js";
|
|
373
|
+
import "./chunk-4DZ62L36.js";
|
|
373
374
|
import {
|
|
374
375
|
credentialContextForActor
|
|
375
376
|
} from "./chunk-CEMMLV5L.js";
|
|
@@ -404,13 +405,13 @@ import {
|
|
|
404
405
|
withContext,
|
|
405
406
|
withLogContext,
|
|
406
407
|
withSpan
|
|
407
|
-
} from "./chunk-
|
|
408
|
+
} from "./chunk-UQP54CXZ.js";
|
|
408
409
|
import {
|
|
409
410
|
continueTrace
|
|
410
411
|
} from "./chunk-PEQXYSSE.js";
|
|
411
412
|
import {
|
|
412
413
|
JUNIOR_VERSION
|
|
413
|
-
} from "./chunk-
|
|
414
|
+
} from "./chunk-BZD4ADQH.js";
|
|
414
415
|
|
|
415
416
|
// src/app.ts
|
|
416
417
|
import { createRequire } from "module";
|
|
@@ -514,7 +515,7 @@ async function recoverConversationWork(args) {
|
|
|
514
515
|
}
|
|
515
516
|
return;
|
|
516
517
|
}
|
|
517
|
-
if (work.execution.lease || !
|
|
518
|
+
if (work.execution.lease || !hasRunnableConversationWork2(work)) {
|
|
518
519
|
return;
|
|
519
520
|
}
|
|
520
521
|
const wake = await ensureConversationWake({
|
|
@@ -4044,17 +4045,9 @@ async function decideSubscribedThreadReply(args) {
|
|
|
4044
4045
|
if (preflightDecision) {
|
|
4045
4046
|
return preflightDecision;
|
|
4046
4047
|
}
|
|
4047
|
-
const evidence = buildRouterEvidence(args.input);
|
|
4048
4048
|
if (!text && !args.input.hasAttachments) {
|
|
4049
4049
|
return { shouldReply: false, reason: "empty_message" /* EmptyMessage */ };
|
|
4050
4050
|
}
|
|
4051
|
-
if (!args.input.isExplicitMention && !args.input.hasAttachments && isAcknowledgmentOnly(text)) {
|
|
4052
|
-
return {
|
|
4053
|
-
shouldReply: false,
|
|
4054
|
-
reason: "side_conversation" /* SideConversation */,
|
|
4055
|
-
reasonDetail: "acknowledgment"
|
|
4056
|
-
};
|
|
4057
|
-
}
|
|
4058
4051
|
if (args.input.isExplicitMention) {
|
|
4059
4052
|
if (isThreadOptOutInstruction(rawText, text)) {
|
|
4060
4053
|
return {
|
|
@@ -4069,6 +4062,21 @@ async function decideSubscribedThreadReply(args) {
|
|
|
4069
4062
|
reason: "explicit_mention" /* ExplicitMention */
|
|
4070
4063
|
};
|
|
4071
4064
|
}
|
|
4065
|
+
if (!isExperimentalFeatureEnabled("passive-routing")) {
|
|
4066
|
+
return {
|
|
4067
|
+
shouldReply: false,
|
|
4068
|
+
reason: "passive_disabled" /* PassiveDisabled */,
|
|
4069
|
+
reasonDetail: "passive-routing"
|
|
4070
|
+
};
|
|
4071
|
+
}
|
|
4072
|
+
if (!args.input.hasAttachments && isAcknowledgmentOnly(text)) {
|
|
4073
|
+
return {
|
|
4074
|
+
shouldReply: false,
|
|
4075
|
+
reason: "side_conversation" /* SideConversation */,
|
|
4076
|
+
reasonDetail: "acknowledgment"
|
|
4077
|
+
};
|
|
4078
|
+
}
|
|
4079
|
+
const evidence = buildRouterEvidence(args.input);
|
|
4072
4080
|
if (evidence.assistantWasLastSpeaker && evidence.humanMessagesSinceLastAssistant === 0 && !evidence.currentMessageHasAttachments && (evidence.currentMessageHasDirectedFollowUpCue || evidence.currentMessageIsTerseClarification)) {
|
|
4073
4081
|
return {
|
|
4074
4082
|
shouldReply: true,
|
|
@@ -4745,6 +4753,31 @@ function createSlackTurnRuntime(deps) {
|
|
|
4745
4753
|
});
|
|
4746
4754
|
return;
|
|
4747
4755
|
}
|
|
4756
|
+
if (!isResourceEventNotification && !turnIsExplicitMention && !isExperimentalFeatureEnabled("passive-routing")) {
|
|
4757
|
+
const decision2 = await deps.decideSubscribedReply({
|
|
4758
|
+
rawText: combinedText.rawText,
|
|
4759
|
+
text: combinedText.userText,
|
|
4760
|
+
hasAttachments: content.hasAttachments || queuedMessages.some(
|
|
4761
|
+
(queued) => queued.message.attachments.length > 0
|
|
4762
|
+
),
|
|
4763
|
+
isExplicitMention: false,
|
|
4764
|
+
context: threadContext
|
|
4765
|
+
});
|
|
4766
|
+
await maybeHandleThreadOptOutDecision({
|
|
4767
|
+
thread,
|
|
4768
|
+
decision: decision2,
|
|
4769
|
+
beforeFirstResponsePost: hooks.beforeFirstResponsePost
|
|
4770
|
+
});
|
|
4771
|
+
await skipSubscribedMessage({
|
|
4772
|
+
thread,
|
|
4773
|
+
message,
|
|
4774
|
+
decision: decision2,
|
|
4775
|
+
context: threadContext,
|
|
4776
|
+
ack: hooks.ack,
|
|
4777
|
+
text: combinedText
|
|
4778
|
+
});
|
|
4779
|
+
return;
|
|
4780
|
+
}
|
|
4748
4781
|
const preparedState = await deps.prepareTurnState({
|
|
4749
4782
|
thread,
|
|
4750
4783
|
message,
|
|
@@ -8118,416 +8151,203 @@ async function ingestEventTasks(input, options) {
|
|
|
8118
8151
|
return { dispatched };
|
|
8119
8152
|
}
|
|
8120
8153
|
|
|
8121
|
-
// src/api/
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
user.email ?? email,
|
|
8145
|
-
user.displayName ? { fullName: user.displayName } : void 0
|
|
8146
|
-
),
|
|
8147
|
-
user
|
|
8148
|
-
};
|
|
8149
|
-
}
|
|
8150
|
-
function rejectUnsupportedMcpServers(mcpServers) {
|
|
8151
|
-
if (mcpServers.length > 0) {
|
|
8152
|
-
throw acp.RequestError.invalidParams(
|
|
8153
|
-
{ field: "mcpServers" },
|
|
8154
|
-
"Junior does not accept client MCP servers"
|
|
8155
|
-
);
|
|
8156
|
-
}
|
|
8157
|
-
}
|
|
8158
|
-
async function requireOwnedSession(sessionId, user) {
|
|
8159
|
-
if (!sessionId.startsWith(ACP_CONVERSATION_PREFIX)) {
|
|
8160
|
-
throw acp.RequestError.resourceNotFound(sessionId);
|
|
8154
|
+
// src/chat/api-turns/stop.ts
|
|
8155
|
+
async function stopApiConversationTurn(args) {
|
|
8156
|
+
const nowMs = args.nowMs ?? Date.now();
|
|
8157
|
+
const stop = async () => await stopConversationWork({
|
|
8158
|
+
conversationId: args.conversationId,
|
|
8159
|
+
conversationStore: args.conversationStore,
|
|
8160
|
+
nowMs,
|
|
8161
|
+
state: args.state
|
|
8162
|
+
});
|
|
8163
|
+
let result = await stop();
|
|
8164
|
+
if (result.status === "no_work" && await getAuthPausedApiTurnId(args.conversationId)) {
|
|
8165
|
+
const conversation = await getConversation({
|
|
8166
|
+
conversationId: args.conversationId,
|
|
8167
|
+
state: args.state
|
|
8168
|
+
});
|
|
8169
|
+
await requestConversationWork({
|
|
8170
|
+
conversationId: args.conversationId,
|
|
8171
|
+
conversationStore: args.conversationStore,
|
|
8172
|
+
destination: conversation?.destination,
|
|
8173
|
+
nowMs,
|
|
8174
|
+
state: args.state
|
|
8175
|
+
});
|
|
8176
|
+
result = await stop();
|
|
8161
8177
|
}
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8178
|
+
if (result.status === "requested") {
|
|
8179
|
+
await ensureConversationWake({
|
|
8180
|
+
conversationId: args.conversationId,
|
|
8181
|
+
conversationStore: args.conversationStore,
|
|
8182
|
+
idempotencyKey: `api-stop:${args.conversationId}:${result.runId}`,
|
|
8183
|
+
nowMs,
|
|
8184
|
+
queue: args.queue,
|
|
8185
|
+
replaceExistingWake: true,
|
|
8186
|
+
state: args.state
|
|
8187
|
+
});
|
|
8165
8188
|
}
|
|
8189
|
+
return result;
|
|
8166
8190
|
}
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
|
|
8191
|
+
|
|
8192
|
+
// src/chat/api-turns/adapter-conversations.ts
|
|
8193
|
+
var EVENT_PAGE_SIZE = 50;
|
|
8194
|
+
function actorFromUser(user) {
|
|
8195
|
+
return webActorFromEmail(
|
|
8196
|
+
user.email,
|
|
8197
|
+
user.displayName ? { fullName: user.displayName } : void 0
|
|
8198
|
+
);
|
|
8199
|
+
}
|
|
8200
|
+
async function hasConversationAccess(conversationId, user) {
|
|
8201
|
+
const access = (await readConversationAccessFromSql(getDb(), [conversationId], user)).get(conversationId);
|
|
8202
|
+
return Boolean(access?.isParticipant);
|
|
8203
|
+
}
|
|
8204
|
+
async function turnTerminalIsReady(args) {
|
|
8205
|
+
const conversation = await getConversation({
|
|
8206
|
+
conversationId: args.conversationId,
|
|
8207
|
+
state: args.state
|
|
8208
|
+
});
|
|
8209
|
+
if (conversation?.execution.pendingMessages.some(
|
|
8210
|
+
(message) => message.inboundMessageId === args.messageId
|
|
8211
|
+
)) {
|
|
8212
|
+
return false;
|
|
8189
8213
|
}
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
throw acp.RequestError.invalidParams(
|
|
8193
|
-
{ field: "prompt" },
|
|
8194
|
-
`Junior accepts at most ${MAX_PROMPT_TEXT_LENGTH} prompt characters`
|
|
8195
|
-
);
|
|
8214
|
+
if (!conversation || !hasRunnableConversationWork(conversation)) {
|
|
8215
|
+
return true;
|
|
8196
8216
|
}
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8217
|
+
const later = await args.eventStore.query(args.conversationId, {
|
|
8218
|
+
afterSeq: args.terminalSeq,
|
|
8219
|
+
limit: 1,
|
|
8220
|
+
types: ["turn_started"]
|
|
8221
|
+
});
|
|
8222
|
+
return later.events.some(
|
|
8223
|
+
(event) => event.data.type === "turn_started" && event.data.turnId !== args.turnId
|
|
8224
|
+
);
|
|
8202
8225
|
}
|
|
8203
|
-
async function
|
|
8226
|
+
async function latestEventCursor(eventStore, conversationId) {
|
|
8204
8227
|
const page = await eventStore.query(conversationId, { limit: 1 });
|
|
8205
8228
|
return page.events.at(-1)?.seq ?? 0;
|
|
8206
8229
|
}
|
|
8207
|
-
|
|
8208
|
-
|
|
8209
|
-
|
|
8210
|
-
|
|
8211
|
-
|
|
8212
|
-
sessionId,
|
|
8213
|
-
update: {
|
|
8214
|
-
sessionUpdate: message.role === "user" ? "user_message_chunk" : "agent_message_chunk",
|
|
8215
|
-
content: { type: "text", text: message.text },
|
|
8216
|
-
messageId: message.id
|
|
8217
|
-
}
|
|
8218
|
-
});
|
|
8219
|
-
}
|
|
8220
|
-
}
|
|
8221
|
-
async function waitForTurn(args) {
|
|
8222
|
-
let cursor = args.afterSeq;
|
|
8223
|
-
const assistantPrefix = `${args.turnId}:assistant:`;
|
|
8224
|
-
const sentMessageIds = /* @__PURE__ */ new Set();
|
|
8225
|
-
while (true) {
|
|
8226
|
-
if (args.signal.aborted) {
|
|
8227
|
-
throw acp.RequestError.requestCancelled();
|
|
8228
|
-
}
|
|
8229
|
-
const page = await args.eventStore.query(args.sessionId, {
|
|
8230
|
-
afterSeq: cursor,
|
|
8231
|
-
limit: EVENT_PAGE_SIZE,
|
|
8232
|
-
types: ["message", "turn_completed", "turn_failed"]
|
|
8233
|
-
});
|
|
8234
|
-
if (page.events.length === 0) {
|
|
8235
|
-
try {
|
|
8236
|
-
await sleep(EVENT_POLL_INTERVAL_MS, args.signal);
|
|
8237
|
-
} catch (error) {
|
|
8238
|
-
if (args.signal.aborted) {
|
|
8239
|
-
throw acp.RequestError.requestCancelled();
|
|
8240
|
-
}
|
|
8241
|
-
throw error;
|
|
8242
|
-
}
|
|
8243
|
-
continue;
|
|
8244
|
-
}
|
|
8245
|
-
for (const event of page.events) {
|
|
8246
|
-
cursor = event.seq;
|
|
8247
|
-
const data = event.data;
|
|
8248
|
-
if (data.type === "message" && data.role === "assistant" && data.messageId.startsWith(assistantPrefix) && !sentMessageIds.has(data.messageId)) {
|
|
8249
|
-
sentMessageIds.add(data.messageId);
|
|
8250
|
-
await args.client.notify(acp.methods.client.session.update, {
|
|
8251
|
-
sessionId: args.sessionId,
|
|
8252
|
-
update: {
|
|
8253
|
-
sessionUpdate: "agent_message_chunk",
|
|
8254
|
-
content: { type: "text", text: data.text },
|
|
8255
|
-
messageId: data.messageId
|
|
8256
|
-
}
|
|
8257
|
-
});
|
|
8258
|
-
continue;
|
|
8259
|
-
}
|
|
8260
|
-
if (data.type === "turn_completed" && data.turnId === args.turnId) {
|
|
8261
|
-
args.cancellation.finish(args.sessionId, args.cancellationSignal);
|
|
8262
|
-
return {
|
|
8263
|
-
stopReason: data.outcome === "cancelled" ? "cancelled" : "end_turn"
|
|
8264
|
-
};
|
|
8265
|
-
}
|
|
8266
|
-
if (data.type === "turn_failed" && data.turnId === args.turnId) {
|
|
8267
|
-
args.cancellation.finish(args.sessionId, args.cancellationSignal);
|
|
8268
|
-
throw acp.RequestError.internalError(
|
|
8269
|
-
{ failureCode: data.failureCode },
|
|
8270
|
-
"Junior Turn failed"
|
|
8271
|
-
);
|
|
8230
|
+
function createAdapterConversations(options) {
|
|
8231
|
+
return {
|
|
8232
|
+
async cancel({ conversationId, user }) {
|
|
8233
|
+
if (!await hasConversationAccess(conversationId, user)) {
|
|
8234
|
+
return "not_found";
|
|
8272
8235
|
}
|
|
8273
|
-
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
name,
|
|
8281
|
-
{
|
|
8282
|
-
actorId: authenticated.actor.userId,
|
|
8283
|
-
conversationId,
|
|
8284
|
-
platform: "acp",
|
|
8285
|
-
userId: authenticated.actor.userId
|
|
8236
|
+
await stopApiConversationTurn({
|
|
8237
|
+
conversationId,
|
|
8238
|
+
conversationStore: options.conversationStore,
|
|
8239
|
+
queue: options.queue,
|
|
8240
|
+
state: options.state
|
|
8241
|
+
});
|
|
8242
|
+
return "cancelled";
|
|
8286
8243
|
},
|
|
8287
|
-
async ()
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
}
|
|
8297
|
-
|
|
8298
|
-
}
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
return acp.agent({ name: "junior" }).onRequest(
|
|
8303
|
-
acp.methods.agent.initialize,
|
|
8304
|
-
() => runAcpOperation(authenticated, "initialize", void 0, () => ({
|
|
8305
|
-
protocolVersion: acp.PROTOCOL_VERSION,
|
|
8306
|
-
agentCapabilities: {
|
|
8307
|
-
loadSession: true,
|
|
8308
|
-
promptCapabilities: {
|
|
8309
|
-
image: false,
|
|
8310
|
-
audio: false,
|
|
8311
|
-
embeddedContext: false
|
|
8312
|
-
}
|
|
8313
|
-
},
|
|
8314
|
-
authMethods: [],
|
|
8315
|
-
agentInfo: { name: "junior", version: JUNIOR_VERSION }
|
|
8316
|
-
}))
|
|
8317
|
-
).onRequest(acp.methods.agent.session.new, async (context) => {
|
|
8318
|
-
return await runAcpOperation(
|
|
8319
|
-
authenticated,
|
|
8320
|
-
"session_new",
|
|
8321
|
-
void 0,
|
|
8322
|
-
async () => {
|
|
8323
|
-
rejectUnsupportedMcpServers(context.params.mcpServers);
|
|
8324
|
-
const sessionId = `${ACP_CONVERSATION_PREFIX}${randomUUID()}`;
|
|
8325
|
-
await recordApiConversationActivity({
|
|
8326
|
-
actor: authenticated.actor,
|
|
8327
|
-
conversationId: sessionId,
|
|
8328
|
-
conversationStore,
|
|
8329
|
-
nowMs: Date.now(),
|
|
8330
|
-
rootVisibility: "private"
|
|
8331
|
-
});
|
|
8332
|
-
return { sessionId };
|
|
8333
|
-
}
|
|
8334
|
-
);
|
|
8335
|
-
}).onRequest(acp.methods.agent.session.load, async (context) => {
|
|
8336
|
-
return await runAcpOperation(
|
|
8337
|
-
authenticated,
|
|
8338
|
-
"session_load",
|
|
8339
|
-
context.params.sessionId,
|
|
8340
|
-
async () => {
|
|
8341
|
-
rejectUnsupportedMcpServers(context.params.mcpServers);
|
|
8342
|
-
await requireOwnedSession(
|
|
8343
|
-
context.params.sessionId,
|
|
8344
|
-
authenticated.user
|
|
8345
|
-
);
|
|
8346
|
-
await replaySession(
|
|
8347
|
-
eventStore,
|
|
8348
|
-
context.params.sessionId,
|
|
8349
|
-
context.client
|
|
8350
|
-
);
|
|
8351
|
-
return {};
|
|
8244
|
+
async create({ conversationId, user }) {
|
|
8245
|
+
await recordApiConversationActivity({
|
|
8246
|
+
actor: actorFromUser(user),
|
|
8247
|
+
conversationId,
|
|
8248
|
+
conversationStore: options.conversationStore,
|
|
8249
|
+
nowMs: Date.now(),
|
|
8250
|
+
rootVisibility: "private"
|
|
8251
|
+
});
|
|
8252
|
+
},
|
|
8253
|
+
async hasAccess({ conversationId, user }) {
|
|
8254
|
+
return await hasConversationAccess(conversationId, user);
|
|
8255
|
+
},
|
|
8256
|
+
async prompt({ conversationId, idempotencyKey, text, user }) {
|
|
8257
|
+
if (!await hasConversationAccess(conversationId, user)) {
|
|
8258
|
+
return { status: "not_found" };
|
|
8352
8259
|
}
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
|
|
8358
|
-
|
|
8359
|
-
async () => {
|
|
8360
|
-
await requireOwnedSession(
|
|
8361
|
-
context.params.sessionId,
|
|
8362
|
-
authenticated.user
|
|
8363
|
-
);
|
|
8364
|
-
const text = promptText(context.params.prompt);
|
|
8365
|
-
const currentSeq = await latestEventSeq(
|
|
8366
|
-
eventStore,
|
|
8367
|
-
context.params.sessionId
|
|
8368
|
-
);
|
|
8369
|
-
const cancellationSignal = options.cancellation.begin(
|
|
8370
|
-
context.params.sessionId
|
|
8371
|
-
);
|
|
8372
|
-
if (!cancellationSignal) {
|
|
8373
|
-
throw acp.RequestError.invalidParams(
|
|
8374
|
-
{ field: "sessionId" },
|
|
8375
|
-
"This ACP session already has an active prompt"
|
|
8376
|
-
);
|
|
8377
|
-
}
|
|
8378
|
-
const recordDisconnect = () => options.cancellation.disconnect(
|
|
8379
|
-
context.params.sessionId,
|
|
8380
|
-
cancellationSignal
|
|
8381
|
-
);
|
|
8382
|
-
if (context.signal.aborted) {
|
|
8383
|
-
recordDisconnect();
|
|
8384
|
-
} else {
|
|
8385
|
-
context.signal.addEventListener("abort", recordDisconnect, {
|
|
8386
|
-
once: true
|
|
8387
|
-
});
|
|
8388
|
-
}
|
|
8389
|
-
let accepted;
|
|
8390
|
-
try {
|
|
8391
|
-
accepted = await appendAndEnqueueApiConversationMessage(
|
|
8392
|
-
{
|
|
8393
|
-
actor: authenticated.actor,
|
|
8394
|
-
conversationId: context.params.sessionId,
|
|
8395
|
-
idempotencyKey: `${connectionNonce}:${requestIdKey(context.requestId)}`,
|
|
8396
|
-
message: text
|
|
8397
|
-
},
|
|
8398
|
-
{
|
|
8399
|
-
conversationStore,
|
|
8400
|
-
queue: options.queue,
|
|
8401
|
-
state: options.state
|
|
8402
|
-
}
|
|
8403
|
-
);
|
|
8404
|
-
} catch (error) {
|
|
8405
|
-
options.cancellation.finish(
|
|
8406
|
-
context.params.sessionId,
|
|
8407
|
-
cancellationSignal
|
|
8408
|
-
);
|
|
8409
|
-
throw error;
|
|
8410
|
-
}
|
|
8411
|
-
const afterSeq = accepted.status === "duplicate" ? 0 : currentSeq;
|
|
8412
|
-
return await waitForTurn({
|
|
8413
|
-
afterSeq,
|
|
8414
|
-
cancellation: options.cancellation,
|
|
8415
|
-
cancellationSignal,
|
|
8416
|
-
client: context.client,
|
|
8417
|
-
eventStore,
|
|
8418
|
-
sessionId: context.params.sessionId,
|
|
8419
|
-
signal: context.signal,
|
|
8420
|
-
turnId: apiTurnIdForMessage(accepted.messageId)
|
|
8421
|
-
});
|
|
8260
|
+
const currentCursor = await latestEventCursor(
|
|
8261
|
+
options.eventStore,
|
|
8262
|
+
conversationId
|
|
8263
|
+
);
|
|
8264
|
+
if (await getAuthPausedApiTurnId(conversationId)) {
|
|
8265
|
+
return { status: "active" };
|
|
8422
8266
|
}
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
);
|
|
8434
|
-
if (!options.cancellation.cancel(context.params.sessionId)) {
|
|
8435
|
-
return;
|
|
8436
|
-
}
|
|
8437
|
-
const nowMs = Date.now();
|
|
8438
|
-
await ensureConversationWake({
|
|
8439
|
-
conversationId: context.params.sessionId,
|
|
8440
|
-
conversationStore,
|
|
8441
|
-
idempotencyKey: `acp-cancel:${context.params.sessionId}:${nowMs}`,
|
|
8442
|
-
nowMs,
|
|
8267
|
+
const admission = await appendAndEnqueueApiConversationMessage(
|
|
8268
|
+
{
|
|
8269
|
+
actor: actorFromUser(user),
|
|
8270
|
+
conversationId,
|
|
8271
|
+
idempotencyKey,
|
|
8272
|
+
message: text
|
|
8273
|
+
},
|
|
8274
|
+
{
|
|
8275
|
+
conversationStore: options.conversationStore,
|
|
8276
|
+
exclusive: true,
|
|
8443
8277
|
queue: options.queue,
|
|
8444
|
-
replaceExistingWake: true,
|
|
8445
8278
|
state: options.state
|
|
8446
|
-
}
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
8457
|
-
|
|
8458
|
-
|
|
8459
|
-
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
|
|
8466
|
-
|
|
8467
|
-
|
|
8468
|
-
|
|
8469
|
-
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
|
|
8475
|
-
|
|
8476
|
-
|
|
8477
|
-
|
|
8478
|
-
|
|
8479
|
-
|
|
8480
|
-
|
|
8481
|
-
|
|
8482
|
-
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8501
|
-
|
|
8502
|
-
});
|
|
8503
|
-
const responseConnectionId = response.headers.get(ACP_CONNECTION_ID_HEADER);
|
|
8504
|
-
if (response.ok && responseConnectionId && !connectionId) {
|
|
8505
|
-
if (await initializationSucceeded(response)) {
|
|
8506
|
-
connectionActors.set(responseConnectionId, authenticated.actor.userId);
|
|
8507
|
-
} else {
|
|
8508
|
-
await server.handleRequest(
|
|
8509
|
-
new Request(request.url, {
|
|
8510
|
-
method: "DELETE",
|
|
8511
|
-
headers: { [ACP_CONNECTION_ID_HEADER]: responseConnectionId }
|
|
8512
|
-
})
|
|
8513
|
-
);
|
|
8514
|
-
const headers = new Headers(response.headers);
|
|
8515
|
-
headers.delete(ACP_CONNECTION_ID_HEADER);
|
|
8516
|
-
return new Response(response.body, {
|
|
8517
|
-
headers,
|
|
8518
|
-
status: response.status,
|
|
8519
|
-
statusText: response.statusText
|
|
8520
|
-
});
|
|
8279
|
+
}
|
|
8280
|
+
);
|
|
8281
|
+
if (admission.status === "active") return { status: "active" };
|
|
8282
|
+
return {
|
|
8283
|
+
afterCursor: admission.status === "duplicate" ? 0 : currentCursor,
|
|
8284
|
+
messageId: admission.messageId,
|
|
8285
|
+
status: "accepted",
|
|
8286
|
+
turnId: apiTurnIdForMessage(admission.messageId)
|
|
8287
|
+
};
|
|
8288
|
+
},
|
|
8289
|
+
async readMessages(conversationId) {
|
|
8290
|
+
const history = await options.eventStore.loadMessageHistory(conversationId);
|
|
8291
|
+
return projectConversationMessages(history).filter(
|
|
8292
|
+
(message) => message.role !== "system"
|
|
8293
|
+
).map(({ id, role, text }) => ({ id, role, text }));
|
|
8294
|
+
},
|
|
8295
|
+
async readTurn({ afterCursor, conversationId, messageId, turnId }) {
|
|
8296
|
+
const page = await options.eventStore.query(conversationId, {
|
|
8297
|
+
afterSeq: afterCursor,
|
|
8298
|
+
limit: EVENT_PAGE_SIZE,
|
|
8299
|
+
types: ["message", "turn_completed", "turn_failed"]
|
|
8300
|
+
});
|
|
8301
|
+
const cursor = page.events.at(-1)?.seq ?? afterCursor;
|
|
8302
|
+
const assistantPrefix = `${turnId}:assistant:`;
|
|
8303
|
+
const messages = page.events.flatMap((event) => {
|
|
8304
|
+
const data = event.data;
|
|
8305
|
+
return data.type === "message" && data.role === "assistant" && data.messageId.startsWith(assistantPrefix) ? [
|
|
8306
|
+
{
|
|
8307
|
+
id: data.messageId,
|
|
8308
|
+
role: "assistant",
|
|
8309
|
+
text: data.text
|
|
8310
|
+
}
|
|
8311
|
+
] : [];
|
|
8312
|
+
});
|
|
8313
|
+
let terminal;
|
|
8314
|
+
const terminalEvent = await options.eventStore.loadByIdempotencyKey(
|
|
8315
|
+
conversationId,
|
|
8316
|
+
`turn:${turnId}:terminal`
|
|
8317
|
+
);
|
|
8318
|
+
if (terminalEvent && terminalEvent.seq <= cursor && await turnTerminalIsReady({
|
|
8319
|
+
conversationId,
|
|
8320
|
+
eventStore: options.eventStore,
|
|
8321
|
+
messageId,
|
|
8322
|
+
state: options.state,
|
|
8323
|
+
terminalSeq: terminalEvent.seq,
|
|
8324
|
+
turnId
|
|
8325
|
+
})) {
|
|
8326
|
+
const data = terminalEvent.data;
|
|
8327
|
+
if (data.type === "turn_completed" && data.turnId === turnId) {
|
|
8328
|
+
terminal = {
|
|
8329
|
+
outcome: data.outcome === "cancelled" ? "cancelled" : "completed",
|
|
8330
|
+
status: "completed"
|
|
8331
|
+
};
|
|
8332
|
+
} else if (data.type === "turn_failed" && data.turnId === turnId) {
|
|
8333
|
+
terminal = { failureCode: data.failureCode, status: "failed" };
|
|
8334
|
+
}
|
|
8521
8335
|
}
|
|
8336
|
+
const turnPage = { cursor, messages };
|
|
8337
|
+
if (terminal) turnPage.terminal = terminal;
|
|
8338
|
+
return turnPage;
|
|
8522
8339
|
}
|
|
8523
|
-
if (request.method === "DELETE" && response.ok && connectionId) {
|
|
8524
|
-
connectionActors.delete(connectionId);
|
|
8525
|
-
}
|
|
8526
|
-
return response;
|
|
8527
8340
|
};
|
|
8528
8341
|
}
|
|
8529
8342
|
|
|
8530
8343
|
// src/app.ts
|
|
8344
|
+
function resolveAdapterBaseURL(dashboard) {
|
|
8345
|
+
const configured = dashboard?.baseURL?.trim() || process.env.JUNIOR_BASE_URL?.trim();
|
|
8346
|
+
if (configured) return configured;
|
|
8347
|
+
const vercelURL = process.env.VERCEL_PROJECT_PRODUCTION_URL?.trim() || process.env.VERCEL_URL?.trim();
|
|
8348
|
+
if (!vercelURL) return void 0;
|
|
8349
|
+
return /^https?:\/\//.test(vercelURL) ? vercelURL : `https://${vercelURL}`;
|
|
8350
|
+
}
|
|
8531
8351
|
var DASHBOARD_PACKAGE_NAME = "@sentry/junior-dashboard";
|
|
8532
8352
|
async function defaultWaitUntil() {
|
|
8533
8353
|
try {
|
|
@@ -8625,6 +8445,7 @@ async function createDashboardRouteRegistrations(args) {
|
|
|
8625
8445
|
}
|
|
8626
8446
|
const createDashboardApp = args.createDashboardApp ?? await loadDashboardAppFactory();
|
|
8627
8447
|
return dashboardRouteRegistrations({
|
|
8448
|
+
authenticatedRoutes: args.authenticatedRoutes,
|
|
8628
8449
|
dashboard: args.dashboard,
|
|
8629
8450
|
createDashboardApp,
|
|
8630
8451
|
pluginRoutes: args.pluginRoutes
|
|
@@ -8672,7 +8493,7 @@ function normalizeDashboardPath(path, fallback) {
|
|
|
8672
8493
|
const withSlash = value.startsWith("/") ? value : `/${value}`;
|
|
8673
8494
|
return stripTrailingSlashes(withSlash);
|
|
8674
8495
|
}
|
|
8675
|
-
function dashboardHostRoutePaths(dashboard) {
|
|
8496
|
+
function dashboardHostRoutePaths(dashboard, authenticatedRoutes = []) {
|
|
8676
8497
|
const basePath = normalizeDashboardPath(dashboard.basePath, "/");
|
|
8677
8498
|
const authPath = normalizeDashboardPath(dashboard.authPath, "/api/auth");
|
|
8678
8499
|
const pagePath = (suffix) => basePath === "/" ? `/${suffix}` : `${basePath}/${suffix}`;
|
|
@@ -8732,6 +8553,7 @@ function dashboardHostRoutePaths(dashboard) {
|
|
|
8732
8553
|
"/api/workspaces/*",
|
|
8733
8554
|
"/api/config",
|
|
8734
8555
|
"/api/me",
|
|
8556
|
+
...authenticatedRoutes.map((route) => route.path),
|
|
8735
8557
|
authPath,
|
|
8736
8558
|
`${authPath}/*`
|
|
8737
8559
|
];
|
|
@@ -8782,35 +8604,43 @@ function routePatternOverlaps(ownedPath, routePath) {
|
|
|
8782
8604
|
(example) => routePatternMatchesConcretePath(routePath, example)
|
|
8783
8605
|
);
|
|
8784
8606
|
}
|
|
8785
|
-
function dashboardOwnedRoutePath(routePath, dashboard) {
|
|
8786
|
-
return dashboardHostRoutePaths(dashboard).some(
|
|
8607
|
+
function dashboardOwnedRoutePath(routePath, dashboard, authenticatedRoutes = []) {
|
|
8608
|
+
return dashboardHostRoutePaths(dashboard, authenticatedRoutes).some(
|
|
8787
8609
|
(path) => routePatternOverlaps(path, routePath)
|
|
8788
8610
|
);
|
|
8789
8611
|
}
|
|
8790
8612
|
function dashboardRouteRegistrations(args) {
|
|
8791
8613
|
let app;
|
|
8792
8614
|
const fetch2 = (request) => {
|
|
8793
|
-
|
|
8615
|
+
const dashboardOptions = {
|
|
8794
8616
|
...args.dashboard,
|
|
8795
8617
|
agentName: botConfig.userName,
|
|
8618
|
+
authenticatedRoutes: args.authenticatedRoutes,
|
|
8796
8619
|
pluginRoutes: args.pluginRoutes
|
|
8797
|
-
}
|
|
8620
|
+
};
|
|
8621
|
+
app ??= args.createDashboardApp(dashboardOptions);
|
|
8798
8622
|
if (!app || typeof app.fetch !== "function") {
|
|
8799
8623
|
throw new Error("createDashboardApp() must return an app with fetch()");
|
|
8800
8624
|
}
|
|
8801
8625
|
return app.fetch(request);
|
|
8802
8626
|
};
|
|
8803
|
-
return dashboardHostRoutePaths(args.dashboard).map(
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8627
|
+
return dashboardHostRoutePaths(args.dashboard, args.authenticatedRoutes).map(
|
|
8628
|
+
(path) => ({
|
|
8629
|
+
handler: fetch2,
|
|
8630
|
+
path
|
|
8631
|
+
})
|
|
8632
|
+
);
|
|
8807
8633
|
}
|
|
8808
8634
|
function validateDashboardRouteOwnership(args) {
|
|
8809
8635
|
if (!args.dashboard || args.dashboard.disabled) {
|
|
8810
8636
|
return;
|
|
8811
8637
|
}
|
|
8812
8638
|
for (const route of args.routes) {
|
|
8813
|
-
if (dashboardOwnedRoutePath(
|
|
8639
|
+
if (dashboardOwnedRoutePath(
|
|
8640
|
+
route.path,
|
|
8641
|
+
args.dashboard,
|
|
8642
|
+
args.authenticatedRoutes
|
|
8643
|
+
)) {
|
|
8814
8644
|
throw new Error(
|
|
8815
8645
|
`Plugin "${route.pluginName}" route "${route.path}" conflicts with core dashboard routes`
|
|
8816
8646
|
);
|
|
@@ -8820,11 +8650,11 @@ function validateDashboardRouteOwnership(args) {
|
|
|
8820
8650
|
function mountRoutes(app, routes) {
|
|
8821
8651
|
for (const route of routes) {
|
|
8822
8652
|
const handler = (c) => route.handler(c.req.raw);
|
|
8823
|
-
const
|
|
8824
|
-
const explicitMethods =
|
|
8653
|
+
const methods = typeof route.method === "string" ? [route.method] : route.method ?? ["ALL"];
|
|
8654
|
+
const explicitMethods = methods.filter(
|
|
8825
8655
|
(method) => method !== "ALL"
|
|
8826
8656
|
);
|
|
8827
|
-
if (
|
|
8657
|
+
if (methods.includes("ALL")) {
|
|
8828
8658
|
app.all(route.path, handler);
|
|
8829
8659
|
} else if (explicitMethods.length > 0) {
|
|
8830
8660
|
app.on(explicitMethods, route.path, handler);
|
|
@@ -8858,6 +8688,17 @@ async function createApp(options) {
|
|
|
8858
8688
|
const previousSandboxResources = getSandboxResourceConfig();
|
|
8859
8689
|
const previousExperimentalFeatures = getExperimentalFeatures();
|
|
8860
8690
|
const previousDashboardLinkOptions = setDashboardConversationLinkOptions(dashboard);
|
|
8691
|
+
const restoreRuntimeConfig = () => {
|
|
8692
|
+
pluginCatalogRuntime.setConfig(previousPluginCatalogConfig);
|
|
8693
|
+
setPlugins(previousPlugins);
|
|
8694
|
+
setConfigDefaults(previousConfigDefaults);
|
|
8695
|
+
botConfig.defaultProfile = previousDefaultProfile;
|
|
8696
|
+
botConfig.profiles = previousModelProfiles;
|
|
8697
|
+
setSlackReactionConfig(previousSlackReactionConfig);
|
|
8698
|
+
setSandboxResourceConfig(previousSandboxResources);
|
|
8699
|
+
setExperimentalFeatures(previousExperimentalFeatures);
|
|
8700
|
+
setDashboardConversationLinkOptions(previousDashboardLinkOptions);
|
|
8701
|
+
};
|
|
8861
8702
|
let pluginRoutes = [];
|
|
8862
8703
|
let pluginApiRoutes = [];
|
|
8863
8704
|
const resolveResourceEventTeamId = createResourceEventTeamIdResolver();
|
|
@@ -8909,20 +8750,11 @@ async function createApp(options) {
|
|
|
8909
8750
|
);
|
|
8910
8751
|
}
|
|
8911
8752
|
pluginRoutes = getPluginRoutes({ resourceEvents });
|
|
8912
|
-
validateDashboardRouteOwnership({ dashboard, routes: pluginRoutes });
|
|
8913
8753
|
if (dashboard && !dashboard.disabled) {
|
|
8914
8754
|
pluginApiRoutes = getPluginApiRoutes();
|
|
8915
8755
|
}
|
|
8916
8756
|
} catch (error) {
|
|
8917
|
-
|
|
8918
|
-
setPlugins(previousPlugins);
|
|
8919
|
-
setConfigDefaults(previousConfigDefaults);
|
|
8920
|
-
botConfig.defaultProfile = previousDefaultProfile;
|
|
8921
|
-
botConfig.profiles = previousModelProfiles;
|
|
8922
|
-
setSlackReactionConfig(previousSlackReactionConfig);
|
|
8923
|
-
setSandboxResourceConfig(previousSandboxResources);
|
|
8924
|
-
setExperimentalFeatures(previousExperimentalFeatures);
|
|
8925
|
-
setDashboardConversationLinkOptions(previousDashboardLinkOptions);
|
|
8757
|
+
restoreRuntimeConfig();
|
|
8926
8758
|
throw error;
|
|
8927
8759
|
}
|
|
8928
8760
|
const waitUntil = options?.waitUntil ?? await defaultWaitUntil();
|
|
@@ -8938,6 +8770,54 @@ async function createApp(options) {
|
|
|
8938
8770
|
replyExecutor: { agentRunner },
|
|
8939
8771
|
sandbox: { tracePropagation }
|
|
8940
8772
|
};
|
|
8773
|
+
let conversationWorkOptions;
|
|
8774
|
+
const getConversationWorkOptions = () => {
|
|
8775
|
+
conversationWorkOptions ??= options?.conversationWork ?? createProductionConversationWorkOptions({
|
|
8776
|
+
agentRunner,
|
|
8777
|
+
services: runtimeServiceOverrides
|
|
8778
|
+
});
|
|
8779
|
+
return conversationWorkOptions;
|
|
8780
|
+
};
|
|
8781
|
+
let adapterRoutes = [];
|
|
8782
|
+
let authenticatedRoutes = [];
|
|
8783
|
+
try {
|
|
8784
|
+
const adapterOutputs = await Promise.all(
|
|
8785
|
+
(options?.adapters ?? []).map(async (adapter) => {
|
|
8786
|
+
const work = getConversationWorkOptions();
|
|
8787
|
+
const state = work.state ?? getStateAdapter();
|
|
8788
|
+
return await adapter({
|
|
8789
|
+
agentName: botConfig.userName,
|
|
8790
|
+
baseURL: resolveAdapterBaseURL(dashboard),
|
|
8791
|
+
conversations: createAdapterConversations({
|
|
8792
|
+
conversationStore: work.conversationStore,
|
|
8793
|
+
eventStore: getConversationEventStore(),
|
|
8794
|
+
queue: work.queue ?? getVercelConversationWorkQueue(),
|
|
8795
|
+
state
|
|
8796
|
+
}),
|
|
8797
|
+
reportError: (error, event, attributes) => void logException(error, event, attributes),
|
|
8798
|
+
state,
|
|
8799
|
+
version: JUNIOR_VERSION
|
|
8800
|
+
});
|
|
8801
|
+
})
|
|
8802
|
+
);
|
|
8803
|
+
adapterRoutes = adapterOutputs.flatMap((output) => output.routes ?? []);
|
|
8804
|
+
authenticatedRoutes = adapterOutputs.flatMap(
|
|
8805
|
+
(output) => output.authenticatedRoutes ?? []
|
|
8806
|
+
);
|
|
8807
|
+
if (authenticatedRoutes.length > 0 && (!dashboard || dashboard.disabled)) {
|
|
8808
|
+
throw new Error(
|
|
8809
|
+
"createApp() adapters with authenticated routes require an enabled dashboard"
|
|
8810
|
+
);
|
|
8811
|
+
}
|
|
8812
|
+
validateDashboardRouteOwnership({
|
|
8813
|
+
authenticatedRoutes,
|
|
8814
|
+
dashboard,
|
|
8815
|
+
routes: pluginRoutes
|
|
8816
|
+
});
|
|
8817
|
+
} catch (error) {
|
|
8818
|
+
restoreRuntimeConfig();
|
|
8819
|
+
throw error;
|
|
8820
|
+
}
|
|
8941
8821
|
const slackWebhookServices = createProductionSlackWebhookServices({
|
|
8942
8822
|
services: runtimeServiceOverrides
|
|
8943
8823
|
});
|
|
@@ -8954,9 +8834,11 @@ async function createApp(options) {
|
|
|
8954
8834
|
);
|
|
8955
8835
|
});
|
|
8956
8836
|
mountRoutes(app, pluginRoutes);
|
|
8837
|
+
mountRoutes(app, adapterRoutes);
|
|
8957
8838
|
mountRoutes(
|
|
8958
8839
|
app,
|
|
8959
8840
|
await createDashboardRouteRegistrations({
|
|
8841
|
+
authenticatedRoutes,
|
|
8960
8842
|
dashboard,
|
|
8961
8843
|
createDashboardApp: virtualConfig?.createDashboardApp,
|
|
8962
8844
|
pluginRoutes: pluginApiRoutes
|
|
@@ -8994,32 +8876,6 @@ async function createApp(options) {
|
|
|
8994
8876
|
});
|
|
8995
8877
|
let agentContinuePOST;
|
|
8996
8878
|
let pluginTaskPOST;
|
|
8997
|
-
let conversationWorkOptions;
|
|
8998
|
-
const getConversationWorkOptions = () => {
|
|
8999
|
-
conversationWorkOptions ??= options?.conversationWork ?? createProductionConversationWorkOptions({
|
|
9000
|
-
agentRunner,
|
|
9001
|
-
services: runtimeServiceOverrides
|
|
9002
|
-
});
|
|
9003
|
-
return conversationWorkOptions;
|
|
9004
|
-
};
|
|
9005
|
-
if (isExperimentalFeatureEnabled("acp")) {
|
|
9006
|
-
const work = getConversationWorkOptions();
|
|
9007
|
-
const cancellation = work.apiTurnCancellation;
|
|
9008
|
-
if (!cancellation) {
|
|
9009
|
-
throw new Error("Experimental ACP requires API Turn cancellation wiring");
|
|
9010
|
-
}
|
|
9011
|
-
const handleAcpRequest = createAcpHttpHandler({
|
|
9012
|
-
cancellation,
|
|
9013
|
-
conversationStore: work.conversationStore,
|
|
9014
|
-
queue: work.queue ?? getVercelConversationWorkQueue(),
|
|
9015
|
-
state: work.state
|
|
9016
|
-
});
|
|
9017
|
-
app.on(
|
|
9018
|
-
["GET", "POST", "DELETE"],
|
|
9019
|
-
"/api/acp",
|
|
9020
|
-
(c) => handleAcpRequest(c.req.raw)
|
|
9021
|
-
);
|
|
9022
|
-
}
|
|
9023
8879
|
if (process.env.NODE_ENV === "development") {
|
|
9024
8880
|
registerVercelConversationWorkDevConsumer(getConversationWorkOptions());
|
|
9025
8881
|
registerVercelPluginTaskDevConsumer();
|