@sentry/junior 0.175.0 → 0.176.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-DOXAOEHI.js → agent-hooks-ZPCHKYXI.js} +12 -12
- package/dist/api.js +26 -26
- package/dist/app.js +256 -342
- package/dist/{catalog-runtime-OTFZT3R2.js → catalog-runtime-3Z2Y5IP6.js} +5 -5
- package/dist/chat/agent-dispatch/heartbeat.d.ts +1 -1
- package/dist/chat/agent-dispatch/store.d.ts +3 -16
- package/dist/chat/resource-events/catalog.d.ts +2 -2
- package/dist/chat/resource-events/notification.d.ts +1 -1
- package/dist/{chunk-DVWHUWTB.js → chunk-2N7YRFMW.js} +12 -12
- package/dist/{chunk-XL24YNNO.js → chunk-5JB5JJO5.js} +1 -1
- package/dist/{chunk-YMBCD6FB.js → chunk-64EGCW34.js} +6 -6
- package/dist/{chunk-HHAR5IDU.js → chunk-665JOQEP.js} +6 -6
- package/dist/{chunk-RMANRIHC.js → chunk-6NQJQP7O.js} +5 -5
- package/dist/{chunk-WNQBHYAQ.js → chunk-AJEZETLT.js} +1 -1
- package/dist/{chunk-2WCXOLNX.js → chunk-B65VEBJV.js} +2 -2
- package/dist/{chunk-CSV5XEQN.js → chunk-B6IOTX7W.js} +1 -1
- package/dist/{chunk-T3RN2B3T.js → chunk-B7U2QBMT.js} +13 -55
- package/dist/{chunk-WHKREAVX.js → chunk-BNGK2J6X.js} +1 -1
- package/dist/{chunk-2AEUOTQL.js → chunk-CI4JX64I.js} +1 -1
- package/dist/{chunk-YUUMDYLN.js → chunk-CNC65LIX.js} +1 -1
- package/dist/{chunk-KGKKBFOI.js → chunk-COFZR2CO.js} +1 -1
- package/dist/{chunk-JLHYNMXZ.js → chunk-CTYWFV6L.js} +6 -6
- package/dist/{chunk-RG6JSBDJ.js → chunk-CUA5SZR5.js} +1 -1
- package/dist/{chunk-4CVWSS6Q.js → chunk-DVHYQDGM.js} +1 -1
- package/dist/{chunk-UQURHDWJ.js → chunk-FNOLPLXJ.js} +4 -4
- package/dist/{chunk-DSZNZ7AW.js → chunk-GYRGJVWR.js} +18 -18
- package/dist/{chunk-NBE6DME6.js → chunk-H7KTMGNI.js} +1 -1
- package/dist/{chunk-I7F7WVUW.js → chunk-IPOB6IL5.js} +6 -6
- package/dist/{chunk-46BUAC7H.js → chunk-JHCAX7XY.js} +3 -3
- package/dist/{chunk-K4SGLRWX.js → chunk-JIZ3RFER.js} +6 -6
- package/dist/{chunk-HVI3ZLMV.js → chunk-KYHHJ6LS.js} +1 -1
- package/dist/{chunk-PQV33DEV.js → chunk-OKXHYVKE.js} +4 -4
- package/dist/{chunk-2XWTVTLS.js → chunk-PS3ZPRL2.js} +1 -1
- package/dist/{chunk-TYSWSX3M.js → chunk-Q374NKGS.js} +8 -8
- package/dist/{chunk-GBDCHVNI.js → chunk-RSIHA3XC.js} +5 -5
- package/dist/{chunk-VMVTHLJM.js → chunk-SBIQ5MZW.js} +1 -1
- package/dist/{chunk-V7QS3Z53.js → chunk-SGLLADGQ.js} +17 -17
- package/dist/{chunk-6KKCC7CG.js → chunk-VUAHVGPY.js} +4 -4
- package/dist/{chunk-GLYH4OBP.js → chunk-VVLQGGJJ.js} +1 -1
- package/dist/{chunk-RAV6B2TQ.js → chunk-Z2YZ6QLG.js} +2 -2
- package/dist/cli/chat.js +30 -30
- package/dist/cli/check.js +6 -6
- package/dist/cli/plugins.js +13 -13
- package/dist/cli/snapshot-create.js +10 -10
- package/dist/cli/upgrade.js +7 -7
- package/dist/{db-B7NVPW7Y.js → db-63K2IY36.js} +7 -7
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +2 -2
- package/dist/{oauth-callback-server-TMTQK74Z.js → oauth-callback-server-JZXBDXGO.js} +23 -23
- package/dist/{runner-HROVFS4C.js → runner-3KWZJVK6.js} +15 -15
- package/dist/{skills-77LC6PFU.js → skills-TFQQ3WSE.js} +6 -6
- package/dist/spawn-3GVQNWFH.js +37 -0
- package/dist/{validation-EL4J4FYB.js → validation-RKLSF2UH.js} +6 -6
- package/dist/version.js +1 -1
- package/dist/{work-5UQRXUOD.js → work-RKDS3J2X.js} +18 -18
- package/dist/worker-5RJNDPYW.js +24 -0
- package/package.json +5 -5
- package/dist/chat/agent-dispatch/signing.d.ts +0 -14
- package/dist/handlers/agent-dispatch.d.ts +0 -12
- package/dist/spawn-JBWVVXIL.js +0 -37
- package/dist/worker-3FBM4GWV.js +0 -24
package/dist/app.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
processConversationWork
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VUAHVGPY.js";
|
|
4
4
|
import {
|
|
5
5
|
bindSpawnAgent
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-BNGK2J6X.js";
|
|
7
7
|
import {
|
|
8
8
|
createAgentInvocationWorker,
|
|
9
9
|
enqueueAgentInvocation,
|
|
10
10
|
listPendingAgentInvocationMailboxAppends,
|
|
11
11
|
routeAgentInvocationWork
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-CTYWFV6L.js";
|
|
13
13
|
import {
|
|
14
14
|
GET as GET2,
|
|
15
15
|
GET2 as GET3,
|
|
@@ -36,12 +36,12 @@ import {
|
|
|
36
36
|
startSlackProcessingReaction,
|
|
37
37
|
stripLeadingBotMention,
|
|
38
38
|
wakePausedTurn
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-SGLLADGQ.js";
|
|
40
40
|
import "./chunk-FA6POGLH.js";
|
|
41
41
|
import {
|
|
42
42
|
getTurnRequestDeadline,
|
|
43
43
|
runWithTurnRequestDeadline
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-PS3ZPRL2.js";
|
|
45
45
|
import {
|
|
46
46
|
GET,
|
|
47
47
|
apiTurnIdForMessage,
|
|
@@ -58,8 +58,8 @@ import {
|
|
|
58
58
|
resolveSlackConversationContext,
|
|
59
59
|
routeApiTurnWork,
|
|
60
60
|
webActorFromEmail
|
|
61
|
-
} from "./chunk-
|
|
62
|
-
import "./chunk-
|
|
61
|
+
} from "./chunk-2N7YRFMW.js";
|
|
62
|
+
import "./chunk-VVLQGGJJ.js";
|
|
63
63
|
import {
|
|
64
64
|
CONVERSATION_WORK_STALE_ENQUEUE_MS,
|
|
65
65
|
appendAndEnqueueInboundMessage,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
isInvalidConversationRecordError,
|
|
71
71
|
listActiveConversationIds,
|
|
72
72
|
removeActiveConversation
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-OKXHYVKE.js";
|
|
74
74
|
import {
|
|
75
75
|
buildDeliveredTurnStatePatch,
|
|
76
76
|
claimDispatchMailboxAppend,
|
|
@@ -81,7 +81,6 @@ import {
|
|
|
81
81
|
getAgentTurnDiagnosticsAttributes,
|
|
82
82
|
getDispatchConversationId,
|
|
83
83
|
getDispatchInputMessageId,
|
|
84
|
-
getDispatchInputMessageIds,
|
|
85
84
|
getDispatchRecord,
|
|
86
85
|
getDispatchTurnId,
|
|
87
86
|
getPluginDispatchProjection,
|
|
@@ -101,7 +100,7 @@ import {
|
|
|
101
100
|
requireTurnFailureEventId,
|
|
102
101
|
resolveTurnSessionRouting,
|
|
103
102
|
scheduleSessionCompletedPluginTasks
|
|
104
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-B7U2QBMT.js";
|
|
105
104
|
import {
|
|
106
105
|
ConversationTurnLifecycleService,
|
|
107
106
|
coerceThreadConversationState,
|
|
@@ -111,7 +110,7 @@ import {
|
|
|
111
110
|
persistThreadRuntimeState,
|
|
112
111
|
persistThreadState,
|
|
113
112
|
persistThreadStateById
|
|
114
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-6NQJQP7O.js";
|
|
115
114
|
import "./chunk-UTL3MHPC.js";
|
|
116
115
|
import {
|
|
117
116
|
getVercelConversationWorkQueue,
|
|
@@ -130,7 +129,7 @@ import {
|
|
|
130
129
|
import {
|
|
131
130
|
validatePluginEgressCredentialHooks,
|
|
132
131
|
validatePluginRegistrations
|
|
133
|
-
} from "./chunk-
|
|
132
|
+
} from "./chunk-COFZR2CO.js";
|
|
134
133
|
import {
|
|
135
134
|
defineJuniorPlugins,
|
|
136
135
|
pluginCatalogConfigFromEnv,
|
|
@@ -162,11 +161,11 @@ import {
|
|
|
162
161
|
shouldEmitDevAgentTrace,
|
|
163
162
|
shouldPropagateSandboxEgressTrace,
|
|
164
163
|
unpublishedArtifactHeaders
|
|
165
|
-
} from "./chunk-
|
|
164
|
+
} from "./chunk-GYRGJVWR.js";
|
|
166
165
|
import {
|
|
167
166
|
AuthorizationFlowDisabledError,
|
|
168
167
|
PluginCredentialFailureError
|
|
169
|
-
} from "./chunk-
|
|
168
|
+
} from "./chunk-RSIHA3XC.js";
|
|
170
169
|
import "./chunk-DIB4GX3G.js";
|
|
171
170
|
import {
|
|
172
171
|
createAgentRunner,
|
|
@@ -174,7 +173,7 @@ import {
|
|
|
174
173
|
deleteMcpAuthSessionsForUserProvider,
|
|
175
174
|
deleteMcpServerSessionId,
|
|
176
175
|
deleteMcpStoredOAuthCredentials
|
|
177
|
-
} from "./chunk-
|
|
176
|
+
} from "./chunk-Q374NKGS.js";
|
|
178
177
|
import {
|
|
179
178
|
RetryableDeliveryError
|
|
180
179
|
} from "./chunk-RF6J3DIO.js";
|
|
@@ -182,7 +181,7 @@ import {
|
|
|
182
181
|
formatProviderLabel,
|
|
183
182
|
postSlackMessage,
|
|
184
183
|
startOAuthFlow
|
|
185
|
-
} from "./chunk-
|
|
184
|
+
} from "./chunk-665JOQEP.js";
|
|
186
185
|
import "./chunk-6ZWRNC4D.js";
|
|
187
186
|
import {
|
|
188
187
|
getExperimentalFeatures,
|
|
@@ -198,10 +197,10 @@ import {
|
|
|
198
197
|
requestAttachmentDeletion,
|
|
199
198
|
resourceEventGuidance,
|
|
200
199
|
scheduledTaskRunAttributes
|
|
201
|
-
} from "./chunk-
|
|
200
|
+
} from "./chunk-IPOB6IL5.js";
|
|
202
201
|
import {
|
|
203
202
|
parseSlackThreadId
|
|
204
|
-
} from "./chunk-
|
|
203
|
+
} from "./chunk-AJEZETLT.js";
|
|
205
204
|
import {
|
|
206
205
|
ConversationTurnBoundaryError,
|
|
207
206
|
CooperativeTurnYieldError,
|
|
@@ -253,11 +252,11 @@ import {
|
|
|
253
252
|
trimTrailingAssistantMessages,
|
|
254
253
|
turnHasReply,
|
|
255
254
|
upsertConversationMessage
|
|
256
|
-
} from "./chunk-
|
|
255
|
+
} from "./chunk-64EGCW34.js";
|
|
257
256
|
import {
|
|
258
257
|
getSandboxResourceConfig,
|
|
259
258
|
setSandboxResourceConfig
|
|
260
|
-
} from "./chunk-
|
|
259
|
+
} from "./chunk-FNOLPLXJ.js";
|
|
261
260
|
import "./chunk-PDO5BLNM.js";
|
|
262
261
|
import "./chunk-UIE3R5XU.js";
|
|
263
262
|
import {
|
|
@@ -288,7 +287,7 @@ import {
|
|
|
288
287
|
verifyEventTaskCredentialSubject,
|
|
289
288
|
verifyScheduledTaskCredentialSubject,
|
|
290
289
|
verifySlackDirectCredentialSubject
|
|
291
|
-
} from "./chunk-
|
|
290
|
+
} from "./chunk-JIZ3RFER.js";
|
|
292
291
|
import "./chunk-3Y47VMHV.js";
|
|
293
292
|
import {
|
|
294
293
|
contextProvenance,
|
|
@@ -302,21 +301,21 @@ import {
|
|
|
302
301
|
requireSlackDestination,
|
|
303
302
|
withConversationEventLock,
|
|
304
303
|
withConversationMutationLock
|
|
305
|
-
} from "./chunk-
|
|
304
|
+
} from "./chunk-JHCAX7XY.js";
|
|
306
305
|
import {
|
|
307
306
|
juniorAgentBindings,
|
|
308
307
|
juniorAgentInvocations,
|
|
309
308
|
juniorConversationEvents,
|
|
310
309
|
juniorConversations
|
|
311
|
-
} from "./chunk-
|
|
310
|
+
} from "./chunk-CUA5SZR5.js";
|
|
312
311
|
import {
|
|
313
312
|
sleep
|
|
314
|
-
} from "./chunk-
|
|
313
|
+
} from "./chunk-CNC65LIX.js";
|
|
315
314
|
import {
|
|
316
315
|
acquireActiveLock,
|
|
317
316
|
getStateAdapter,
|
|
318
317
|
withActiveLock
|
|
319
|
-
} from "./chunk-
|
|
318
|
+
} from "./chunk-B6IOTX7W.js";
|
|
320
319
|
import {
|
|
321
320
|
STANDARD_MODEL_PROFILE,
|
|
322
321
|
botConfig,
|
|
@@ -334,16 +333,16 @@ import {
|
|
|
334
333
|
modelIdForProfile,
|
|
335
334
|
setSlackReactionConfig,
|
|
336
335
|
standardModelId
|
|
337
|
-
} from "./chunk-
|
|
336
|
+
} from "./chunk-Z2YZ6QLG.js";
|
|
338
337
|
import {
|
|
339
338
|
juniorDestinations
|
|
340
339
|
} from "./chunk-VFUK3X5B.js";
|
|
341
|
-
import "./chunk-
|
|
342
|
-
import "./chunk-
|
|
340
|
+
import "./chunk-H7KTMGNI.js";
|
|
341
|
+
import "./chunk-B65VEBJV.js";
|
|
343
342
|
import {
|
|
344
343
|
pluginCatalogRuntime
|
|
345
|
-
} from "./chunk-
|
|
346
|
-
import "./chunk-
|
|
344
|
+
} from "./chunk-5JB5JJO5.js";
|
|
345
|
+
import "./chunk-CI4JX64I.js";
|
|
347
346
|
import {
|
|
348
347
|
credentialContextForActor
|
|
349
348
|
} from "./chunk-CGA4ERJ5.js";
|
|
@@ -375,7 +374,7 @@ import {
|
|
|
375
374
|
withContext,
|
|
376
375
|
withLogContext,
|
|
377
376
|
withSpan
|
|
378
|
-
} from "./chunk-
|
|
377
|
+
} from "./chunk-SBIQ5MZW.js";
|
|
379
378
|
import {
|
|
380
379
|
continueTrace
|
|
381
380
|
} from "./chunk-6GWA276C.js";
|
|
@@ -383,10 +382,10 @@ import "./chunk-OOUNJNMR.js";
|
|
|
383
382
|
import "./chunk-H4HBKISO.js";
|
|
384
383
|
import {
|
|
385
384
|
JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE
|
|
386
|
-
} from "./chunk-
|
|
385
|
+
} from "./chunk-KYHHJ6LS.js";
|
|
387
386
|
import {
|
|
388
387
|
JUNIOR_VERSION
|
|
389
|
-
} from "./chunk-
|
|
388
|
+
} from "./chunk-DVHYQDGM.js";
|
|
390
389
|
import "./chunk-MLKGABMK.js";
|
|
391
390
|
|
|
392
391
|
// src/app.ts
|
|
@@ -394,65 +393,139 @@ import { createRequire } from "module";
|
|
|
394
393
|
import { pathToFileURL } from "url";
|
|
395
394
|
import { Hono } from "hono";
|
|
396
395
|
|
|
397
|
-
// src/
|
|
398
|
-
import {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
var
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
var DISPATCH_SIGNATURE_HEADER = "x-junior-dispatch-signature";
|
|
405
|
-
var legacyDispatchCallbackSchema = z.object({
|
|
406
|
-
expectedVersion: z.number().int().positive(),
|
|
407
|
-
id: z.string().min(1)
|
|
408
|
-
}).strict();
|
|
409
|
-
function getDispatchSecret() {
|
|
410
|
-
return process.env.JUNIOR_SECRET?.trim() || void 0;
|
|
411
|
-
}
|
|
412
|
-
function buildSignedPayload(timestamp, body) {
|
|
413
|
-
return `${DISPATCH_HMAC_CONTEXT}:${timestamp}:${body}`;
|
|
414
|
-
}
|
|
415
|
-
function signBody(secret, timestamp, body) {
|
|
416
|
-
const digest = createHmac("sha256", secret).update(buildSignedPayload(timestamp, body)).digest("hex");
|
|
417
|
-
return `${DISPATCH_SIGNATURE_VERSION}=${digest}`;
|
|
418
|
-
}
|
|
419
|
-
function timingSafeMatch(expected, actual) {
|
|
420
|
-
const expectedBuffer = Buffer.from(expected);
|
|
421
|
-
const actualBuffer = Buffer.from(actual);
|
|
422
|
-
if (expectedBuffer.length !== actualBuffer.length) {
|
|
423
|
-
return false;
|
|
424
|
-
}
|
|
425
|
-
return timingSafeEqual(expectedBuffer, actualBuffer);
|
|
396
|
+
// src/handlers/heartbeat.ts
|
|
397
|
+
import { timingSafeEqual } from "crypto";
|
|
398
|
+
|
|
399
|
+
// src/chat/task-execution/heartbeat.ts
|
|
400
|
+
var DEFAULT_RECOVERY_LIMIT = 25;
|
|
401
|
+
function heartbeatIdempotencyKey(reason, conversationId, nowMs) {
|
|
402
|
+
return `heartbeat:${reason}:${conversationId}:${nowMs}`;
|
|
426
403
|
}
|
|
427
|
-
async function
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
if (!timestamp || !signature || !secret) {
|
|
432
|
-
return void 0;
|
|
433
|
-
}
|
|
434
|
-
const parsedTimestamp = Number.parseInt(timestamp, 10);
|
|
435
|
-
if (!Number.isFinite(parsedTimestamp) || Math.abs(Date.now() - parsedTimestamp) > DISPATCH_MAX_SKEW_MS) {
|
|
436
|
-
return void 0;
|
|
437
|
-
}
|
|
438
|
-
const body = await request.text();
|
|
439
|
-
const expectedSignature = signBody(secret, timestamp, body);
|
|
440
|
-
if (!timingSafeMatch(expectedSignature, signature)) {
|
|
441
|
-
return void 0;
|
|
404
|
+
async function recoverConversationWork(args) {
|
|
405
|
+
if (!getChatConfig().conversationWorkEnabled) {
|
|
406
|
+
logWarn("conversation.work.recovery.disabled");
|
|
407
|
+
return { expiredLeaseCount: 0, pendingCount: 0 };
|
|
442
408
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
|
|
409
|
+
const result = {
|
|
410
|
+
expiredLeaseCount: 0,
|
|
411
|
+
pendingCount: 0
|
|
412
|
+
};
|
|
413
|
+
const staleBeforeMs = args.nowMs - CONVERSATION_WORK_STALE_ENQUEUE_MS;
|
|
414
|
+
const ids = await listActiveConversationIds({
|
|
415
|
+
limit: args.limit ?? DEFAULT_RECOVERY_LIMIT,
|
|
416
|
+
staleBeforeMs,
|
|
417
|
+
state: args.state
|
|
418
|
+
});
|
|
419
|
+
for (const conversationId of ids) {
|
|
420
|
+
await withLogContext({ conversationId }, async () => {
|
|
421
|
+
let work;
|
|
422
|
+
try {
|
|
423
|
+
work = await getConversationWorkState({
|
|
424
|
+
conversationId,
|
|
425
|
+
state: args.state
|
|
426
|
+
});
|
|
427
|
+
} catch (error) {
|
|
428
|
+
logException(error, "conversation.work.recovery.failed");
|
|
429
|
+
if (isInvalidConversationRecordError(error)) {
|
|
430
|
+
await removeActiveConversation({
|
|
431
|
+
conversationId,
|
|
432
|
+
state: args.state
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
try {
|
|
438
|
+
if (!work) {
|
|
439
|
+
await removeActiveConversation({
|
|
440
|
+
conversationId,
|
|
441
|
+
state: args.state
|
|
442
|
+
});
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
if (work.execution.status === "idle") {
|
|
446
|
+
await removeActiveConversation({
|
|
447
|
+
conversationId,
|
|
448
|
+
state: args.state
|
|
449
|
+
});
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
if (work.execution.lease && work.execution.lease.expiresAtMs <= args.nowMs) {
|
|
453
|
+
const recovery = await clearExpiredConversationLease({
|
|
454
|
+
conversationId,
|
|
455
|
+
nowMs: args.nowMs,
|
|
456
|
+
state: args.state
|
|
457
|
+
});
|
|
458
|
+
if (recovery === "not_expired") {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
if (recovery === "stopped") {
|
|
462
|
+
logException(
|
|
463
|
+
new Error(
|
|
464
|
+
"Conversation work stopped after repeated failed attempts"
|
|
465
|
+
),
|
|
466
|
+
"conversation.work.retry.exhausted",
|
|
467
|
+
{
|
|
468
|
+
"app.run.id": work.execution.runId ?? "unknown",
|
|
469
|
+
"app.worker.last_progress_at_ms": work.execution.lastProgressAtMs ?? work.createdAtMs,
|
|
470
|
+
"app.worker.retry_count": (work.execution.retryCount ?? 0) + 1
|
|
471
|
+
}
|
|
472
|
+
);
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
const wake2 = await ensureConversationWake({
|
|
476
|
+
conversationId,
|
|
477
|
+
idempotencyKey: heartbeatIdempotencyKey(
|
|
478
|
+
"lease",
|
|
479
|
+
conversationId,
|
|
480
|
+
args.nowMs
|
|
481
|
+
),
|
|
482
|
+
nowMs: args.nowMs,
|
|
483
|
+
queue: args.queue,
|
|
484
|
+
replaceExistingWake: true,
|
|
485
|
+
state: args.state
|
|
486
|
+
});
|
|
487
|
+
if (wake2.status === "enqueued") {
|
|
488
|
+
result.expiredLeaseCount += 1;
|
|
489
|
+
logInfo("conversation.work.lease_expired.requeued");
|
|
490
|
+
}
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
if (work.execution.lease || !hasRunnableConversationWork(work)) {
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
const wake = await ensureConversationWake({
|
|
497
|
+
conversationId,
|
|
498
|
+
idempotencyKey: heartbeatIdempotencyKey(
|
|
499
|
+
"pending",
|
|
500
|
+
conversationId,
|
|
501
|
+
args.nowMs
|
|
502
|
+
),
|
|
503
|
+
nowMs: args.nowMs,
|
|
504
|
+
queue: args.queue,
|
|
505
|
+
state: args.state
|
|
506
|
+
});
|
|
507
|
+
if (wake.status === "enqueued") {
|
|
508
|
+
result.pendingCount += 1;
|
|
509
|
+
logInfo("conversation.work.pending.requeued");
|
|
510
|
+
}
|
|
511
|
+
} catch (error) {
|
|
512
|
+
logException(error, "conversation.work.recovery.failed");
|
|
513
|
+
}
|
|
514
|
+
});
|
|
448
515
|
}
|
|
516
|
+
return result;
|
|
449
517
|
}
|
|
450
518
|
|
|
519
|
+
// src/chat/scheduled-tasks/heartbeat.ts
|
|
520
|
+
import {
|
|
521
|
+
createSlackSource
|
|
522
|
+
} from "@sentry/junior-plugin-api";
|
|
523
|
+
|
|
451
524
|
// src/chat/agent-dispatch/work.ts
|
|
452
|
-
import { z
|
|
453
|
-
var agentDispatchMailboxMetadataSchema =
|
|
454
|
-
dispatchId:
|
|
455
|
-
kind:
|
|
525
|
+
import { z } from "zod";
|
|
526
|
+
var agentDispatchMailboxMetadataSchema = z.object({
|
|
527
|
+
dispatchId: z.string().min(1),
|
|
528
|
+
kind: z.literal("agent_dispatch")
|
|
456
529
|
}).strict();
|
|
457
530
|
var AGENT_DISPATCH_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
458
531
|
function buildDispatchRoutingContext(dispatch2) {
|
|
@@ -496,7 +569,7 @@ function buildAgentDispatchInboundMessage(dispatch2, nowMs = Date.now()) {
|
|
|
496
569
|
}
|
|
497
570
|
async function enqueueAgentDispatch(dispatch2, options) {
|
|
498
571
|
const nowMs = options.nowMs ?? Date.now();
|
|
499
|
-
const claimedDispatch = await claimDispatchMailboxAppend(dispatch2.id
|
|
572
|
+
const claimedDispatch = await claimDispatchMailboxAppend(dispatch2.id);
|
|
500
573
|
if (!claimedDispatch) {
|
|
501
574
|
return;
|
|
502
575
|
}
|
|
@@ -576,22 +649,11 @@ async function resolveAgentDispatchId(context) {
|
|
|
576
649
|
);
|
|
577
650
|
}
|
|
578
651
|
const durableDispatchId = durableDispatchIds.values().next().value;
|
|
579
|
-
if (durableDispatchId) {
|
|
580
|
-
const dispatch3 = await getDispatchRecord(durableDispatchId);
|
|
581
|
-
if (dispatch3 && !isTerminalDispatchStatus(dispatch3.status)) {
|
|
582
|
-
return durableDispatchId;
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
const prefix = "agent-dispatch:";
|
|
586
|
-
if (!context.conversationId.startsWith(prefix)) {
|
|
652
|
+
if (!durableDispatchId) {
|
|
587
653
|
return void 0;
|
|
588
654
|
}
|
|
589
|
-
const
|
|
590
|
-
|
|
591
|
-
if (!dispatch2) {
|
|
592
|
-
return void 0;
|
|
593
|
-
}
|
|
594
|
-
return isTerminalDispatchStatus(dispatch2.status) ? void 0 : dispatch2.id;
|
|
655
|
+
const dispatch2 = await getDispatchRecord(durableDispatchId);
|
|
656
|
+
return dispatch2 && !isTerminalDispatchStatus(dispatch2.status) ? durableDispatchId : void 0;
|
|
595
657
|
}
|
|
596
658
|
function createAgentDispatchWorkRouter(options) {
|
|
597
659
|
return async (context) => {
|
|
@@ -805,161 +867,6 @@ function createAgentDispatchConversationWorker(options) {
|
|
|
805
867
|
};
|
|
806
868
|
}
|
|
807
869
|
|
|
808
|
-
// src/handlers/agent-dispatch.ts
|
|
809
|
-
async function POST(request, waitUntil, options) {
|
|
810
|
-
const payload = await verifyDispatchCallbackRequest(request);
|
|
811
|
-
if (!payload) {
|
|
812
|
-
return new Response("Unauthorized", { status: 401 });
|
|
813
|
-
}
|
|
814
|
-
waitUntil(
|
|
815
|
-
(async () => {
|
|
816
|
-
const dispatch2 = await getDispatchRecord(payload.id);
|
|
817
|
-
if (!dispatch2) {
|
|
818
|
-
throw new Error(`Dispatch record is missing for ${payload.id}`);
|
|
819
|
-
}
|
|
820
|
-
if (isTerminalDispatchStatus(dispatch2.status)) {
|
|
821
|
-
return;
|
|
822
|
-
}
|
|
823
|
-
await enqueueAgentDispatch(dispatch2, {
|
|
824
|
-
queue: options.conversationWorkQueue
|
|
825
|
-
});
|
|
826
|
-
})().catch((error) => {
|
|
827
|
-
logException(error, "agent.dispatch.callback.failed", {
|
|
828
|
-
"app.dispatch.id": payload.id
|
|
829
|
-
});
|
|
830
|
-
})
|
|
831
|
-
);
|
|
832
|
-
return new Response("Accepted", { status: 202 });
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
// src/handlers/heartbeat.ts
|
|
836
|
-
import { timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
837
|
-
|
|
838
|
-
// src/chat/task-execution/heartbeat.ts
|
|
839
|
-
var DEFAULT_RECOVERY_LIMIT = 25;
|
|
840
|
-
function heartbeatIdempotencyKey(reason, conversationId, nowMs) {
|
|
841
|
-
return `heartbeat:${reason}:${conversationId}:${nowMs}`;
|
|
842
|
-
}
|
|
843
|
-
async function recoverConversationWork(args) {
|
|
844
|
-
if (!getChatConfig().conversationWorkEnabled) {
|
|
845
|
-
logWarn("conversation.work.recovery.disabled");
|
|
846
|
-
return { expiredLeaseCount: 0, pendingCount: 0 };
|
|
847
|
-
}
|
|
848
|
-
const result = {
|
|
849
|
-
expiredLeaseCount: 0,
|
|
850
|
-
pendingCount: 0
|
|
851
|
-
};
|
|
852
|
-
const staleBeforeMs = args.nowMs - CONVERSATION_WORK_STALE_ENQUEUE_MS;
|
|
853
|
-
const ids = await listActiveConversationIds({
|
|
854
|
-
limit: args.limit ?? DEFAULT_RECOVERY_LIMIT,
|
|
855
|
-
staleBeforeMs,
|
|
856
|
-
state: args.state
|
|
857
|
-
});
|
|
858
|
-
for (const conversationId of ids) {
|
|
859
|
-
await withLogContext({ conversationId }, async () => {
|
|
860
|
-
let work;
|
|
861
|
-
try {
|
|
862
|
-
work = await getConversationWorkState({
|
|
863
|
-
conversationId,
|
|
864
|
-
state: args.state
|
|
865
|
-
});
|
|
866
|
-
} catch (error) {
|
|
867
|
-
logException(error, "conversation.work.recovery.failed");
|
|
868
|
-
if (isInvalidConversationRecordError(error)) {
|
|
869
|
-
await removeActiveConversation({
|
|
870
|
-
conversationId,
|
|
871
|
-
state: args.state
|
|
872
|
-
});
|
|
873
|
-
}
|
|
874
|
-
return;
|
|
875
|
-
}
|
|
876
|
-
try {
|
|
877
|
-
if (!work) {
|
|
878
|
-
await removeActiveConversation({
|
|
879
|
-
conversationId,
|
|
880
|
-
state: args.state
|
|
881
|
-
});
|
|
882
|
-
return;
|
|
883
|
-
}
|
|
884
|
-
if (work.execution.status === "idle") {
|
|
885
|
-
await removeActiveConversation({
|
|
886
|
-
conversationId,
|
|
887
|
-
state: args.state
|
|
888
|
-
});
|
|
889
|
-
return;
|
|
890
|
-
}
|
|
891
|
-
if (work.execution.lease && work.execution.lease.expiresAtMs <= args.nowMs) {
|
|
892
|
-
const recovery = await clearExpiredConversationLease({
|
|
893
|
-
conversationId,
|
|
894
|
-
nowMs: args.nowMs,
|
|
895
|
-
state: args.state
|
|
896
|
-
});
|
|
897
|
-
if (recovery === "not_expired") {
|
|
898
|
-
return;
|
|
899
|
-
}
|
|
900
|
-
if (recovery === "stopped") {
|
|
901
|
-
logException(
|
|
902
|
-
new Error(
|
|
903
|
-
"Conversation work stopped after repeated failed attempts"
|
|
904
|
-
),
|
|
905
|
-
"conversation.work.retry.exhausted",
|
|
906
|
-
{
|
|
907
|
-
"app.run.id": work.execution.runId ?? "unknown",
|
|
908
|
-
"app.worker.last_progress_at_ms": work.execution.lastProgressAtMs ?? work.createdAtMs,
|
|
909
|
-
"app.worker.retry_count": (work.execution.retryCount ?? 0) + 1
|
|
910
|
-
}
|
|
911
|
-
);
|
|
912
|
-
return;
|
|
913
|
-
}
|
|
914
|
-
const wake2 = await ensureConversationWake({
|
|
915
|
-
conversationId,
|
|
916
|
-
idempotencyKey: heartbeatIdempotencyKey(
|
|
917
|
-
"lease",
|
|
918
|
-
conversationId,
|
|
919
|
-
args.nowMs
|
|
920
|
-
),
|
|
921
|
-
nowMs: args.nowMs,
|
|
922
|
-
queue: args.queue,
|
|
923
|
-
replaceExistingWake: true,
|
|
924
|
-
state: args.state
|
|
925
|
-
});
|
|
926
|
-
if (wake2.status === "enqueued") {
|
|
927
|
-
result.expiredLeaseCount += 1;
|
|
928
|
-
logInfo("conversation.work.lease_expired.requeued");
|
|
929
|
-
}
|
|
930
|
-
return;
|
|
931
|
-
}
|
|
932
|
-
if (work.execution.lease || !hasRunnableConversationWork(work)) {
|
|
933
|
-
return;
|
|
934
|
-
}
|
|
935
|
-
const wake = await ensureConversationWake({
|
|
936
|
-
conversationId,
|
|
937
|
-
idempotencyKey: heartbeatIdempotencyKey(
|
|
938
|
-
"pending",
|
|
939
|
-
conversationId,
|
|
940
|
-
args.nowMs
|
|
941
|
-
),
|
|
942
|
-
nowMs: args.nowMs,
|
|
943
|
-
queue: args.queue,
|
|
944
|
-
state: args.state
|
|
945
|
-
});
|
|
946
|
-
if (wake.status === "enqueued") {
|
|
947
|
-
result.pendingCount += 1;
|
|
948
|
-
logInfo("conversation.work.pending.requeued");
|
|
949
|
-
}
|
|
950
|
-
} catch (error) {
|
|
951
|
-
logException(error, "conversation.work.recovery.failed");
|
|
952
|
-
}
|
|
953
|
-
});
|
|
954
|
-
}
|
|
955
|
-
return result;
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
// src/chat/scheduled-tasks/heartbeat.ts
|
|
959
|
-
import {
|
|
960
|
-
createSlackSource
|
|
961
|
-
} from "@sentry/junior-plugin-api";
|
|
962
|
-
|
|
963
870
|
// src/chat/agent-dispatch/validation.ts
|
|
964
871
|
import {
|
|
965
872
|
dispatchOptionsSchema,
|
|
@@ -1727,7 +1634,7 @@ function verifyHeartbeatRequest(request) {
|
|
|
1727
1634
|
}
|
|
1728
1635
|
const actual = Buffer.from(authorization.slice("Bearer ".length));
|
|
1729
1636
|
const expected = Buffer.from(secret);
|
|
1730
|
-
return actual.length === expected.length &&
|
|
1637
|
+
return actual.length === expected.length && timingSafeEqual(actual, expected);
|
|
1731
1638
|
}
|
|
1732
1639
|
async function GET4(request, waitUntil, options = {}) {
|
|
1733
1640
|
if (!verifyHeartbeatRequest(request)) {
|
|
@@ -1748,7 +1655,7 @@ async function GET4(request, waitUntil, options = {}) {
|
|
|
1748
1655
|
}
|
|
1749
1656
|
|
|
1750
1657
|
// src/handlers/retention.ts
|
|
1751
|
-
import { timingSafeEqual as
|
|
1658
|
+
import { timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
1752
1659
|
|
|
1753
1660
|
// src/chat/conversations/sql/purge.ts
|
|
1754
1661
|
import { and, asc, eq as eq2, inArray, isNull, or, sql } from "drizzle-orm";
|
|
@@ -2046,7 +1953,7 @@ function verifyRetentionRequest(request) {
|
|
|
2046
1953
|
}
|
|
2047
1954
|
const actual = Buffer.from(authorization.slice("Bearer ".length));
|
|
2048
1955
|
const expected = Buffer.from(secret);
|
|
2049
|
-
return actual.length === expected.length &&
|
|
1956
|
+
return actual.length === expected.length && timingSafeEqual2(actual, expected);
|
|
2050
1957
|
}
|
|
2051
1958
|
async function GET5(request, options = {}) {
|
|
2052
1959
|
if (!verifyRetentionRequest(request)) {
|
|
@@ -2444,7 +2351,7 @@ import {
|
|
|
2444
2351
|
Message,
|
|
2445
2352
|
ThreadImpl
|
|
2446
2353
|
} from "chat";
|
|
2447
|
-
import { z as
|
|
2354
|
+
import { z as z2 } from "zod";
|
|
2448
2355
|
|
|
2449
2356
|
// src/chat/ingress/message-router.ts
|
|
2450
2357
|
function normalizeIncomingSlackThreadId(threadId, message) {
|
|
@@ -2635,17 +2542,17 @@ function stripLeadingSteeringOverride(text) {
|
|
|
2635
2542
|
}
|
|
2636
2543
|
|
|
2637
2544
|
// src/chat/task-execution/slack-work.ts
|
|
2638
|
-
var slackConversationRouteSchema =
|
|
2545
|
+
var slackConversationRouteSchema = z2.enum(["mention", "subscribed"]);
|
|
2639
2546
|
function hasSteeringOverride(text) {
|
|
2640
2547
|
return stripLeadingSteeringOverride(text) !== text;
|
|
2641
2548
|
}
|
|
2642
|
-
var serializedDateSchema =
|
|
2643
|
-
var mdastPointSchema =
|
|
2644
|
-
column:
|
|
2645
|
-
line:
|
|
2646
|
-
offset:
|
|
2549
|
+
var serializedDateSchema = z2.iso.datetime();
|
|
2550
|
+
var mdastPointSchema = z2.object({
|
|
2551
|
+
column: z2.number().int().positive(),
|
|
2552
|
+
line: z2.number().int().positive(),
|
|
2553
|
+
offset: z2.number().int().nonnegative().optional()
|
|
2647
2554
|
}).strict();
|
|
2648
|
-
var mdastPositionSchema =
|
|
2555
|
+
var mdastPositionSchema = z2.object({
|
|
2649
2556
|
end: mdastPointSchema,
|
|
2650
2557
|
start: mdastPointSchema
|
|
2651
2558
|
}).strict();
|
|
@@ -2757,7 +2664,7 @@ function isFormattedContentNode(value) {
|
|
|
2757
2664
|
return false;
|
|
2758
2665
|
}
|
|
2759
2666
|
}
|
|
2760
|
-
var formattedContentSchema =
|
|
2667
|
+
var formattedContentSchema = z2.custom(
|
|
2761
2668
|
(value) => {
|
|
2762
2669
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2763
2670
|
return false;
|
|
@@ -2767,79 +2674,79 @@ var formattedContentSchema = z3.custom(
|
|
|
2767
2674
|
},
|
|
2768
2675
|
"must be a valid formatted-content root"
|
|
2769
2676
|
);
|
|
2770
|
-
var serializedMessageSchema =
|
|
2771
|
-
_type:
|
|
2772
|
-
attachments:
|
|
2773
|
-
|
|
2774
|
-
type:
|
|
2775
|
-
url:
|
|
2776
|
-
name:
|
|
2777
|
-
mimeType:
|
|
2778
|
-
size:
|
|
2779
|
-
width:
|
|
2780
|
-
height:
|
|
2781
|
-
fetchMetadata:
|
|
2677
|
+
var serializedMessageSchema = z2.object({
|
|
2678
|
+
_type: z2.literal("chat:Message"),
|
|
2679
|
+
attachments: z2.array(
|
|
2680
|
+
z2.object({
|
|
2681
|
+
type: z2.enum(["image", "file", "video", "audio"]),
|
|
2682
|
+
url: z2.string().optional(),
|
|
2683
|
+
name: z2.string().optional(),
|
|
2684
|
+
mimeType: z2.string().optional(),
|
|
2685
|
+
size: z2.number().finite().optional(),
|
|
2686
|
+
width: z2.number().finite().optional(),
|
|
2687
|
+
height: z2.number().finite().optional(),
|
|
2688
|
+
fetchMetadata: z2.record(z2.string(), z2.string()).optional()
|
|
2782
2689
|
}).strict()
|
|
2783
2690
|
),
|
|
2784
|
-
author:
|
|
2785
|
-
userId:
|
|
2786
|
-
userName:
|
|
2787
|
-
fullName:
|
|
2788
|
-
isBot:
|
|
2789
|
-
isMe:
|
|
2691
|
+
author: z2.object({
|
|
2692
|
+
userId: z2.string(),
|
|
2693
|
+
userName: z2.string(),
|
|
2694
|
+
fullName: z2.string(),
|
|
2695
|
+
isBot: z2.union([z2.boolean(), z2.literal("unknown")]),
|
|
2696
|
+
isMe: z2.boolean()
|
|
2790
2697
|
}).strict(),
|
|
2791
2698
|
formatted: formattedContentSchema,
|
|
2792
|
-
id:
|
|
2793
|
-
isMention:
|
|
2794
|
-
links:
|
|
2795
|
-
|
|
2796
|
-
url:
|
|
2797
|
-
title:
|
|
2798
|
-
description:
|
|
2799
|
-
imageUrl:
|
|
2800
|
-
siteName:
|
|
2699
|
+
id: z2.string().min(1),
|
|
2700
|
+
isMention: z2.boolean().optional(),
|
|
2701
|
+
links: z2.array(
|
|
2702
|
+
z2.object({
|
|
2703
|
+
url: z2.string(),
|
|
2704
|
+
title: z2.string().optional(),
|
|
2705
|
+
description: z2.string().optional(),
|
|
2706
|
+
imageUrl: z2.string().optional(),
|
|
2707
|
+
siteName: z2.string().optional()
|
|
2801
2708
|
}).strict()
|
|
2802
2709
|
).optional(),
|
|
2803
|
-
metadata:
|
|
2710
|
+
metadata: z2.object({
|
|
2804
2711
|
dateSent: serializedDateSchema,
|
|
2805
|
-
edited:
|
|
2712
|
+
edited: z2.boolean(),
|
|
2806
2713
|
editedAt: serializedDateSchema.optional()
|
|
2807
2714
|
}).strict(),
|
|
2808
|
-
raw:
|
|
2809
|
-
text:
|
|
2810
|
-
threadId:
|
|
2715
|
+
raw: z2.unknown(),
|
|
2716
|
+
text: z2.string(),
|
|
2717
|
+
threadId: z2.string().min(1)
|
|
2811
2718
|
}).strict();
|
|
2812
|
-
var serializedThreadSchema =
|
|
2813
|
-
_type:
|
|
2814
|
-
adapterName:
|
|
2815
|
-
channelId:
|
|
2816
|
-
channelVisibility:
|
|
2719
|
+
var serializedThreadSchema = z2.object({
|
|
2720
|
+
_type: z2.literal("chat:Thread"),
|
|
2721
|
+
adapterName: z2.literal("slack"),
|
|
2722
|
+
channelId: z2.string().min(1),
|
|
2723
|
+
channelVisibility: z2.enum(["private", "workspace", "external", "unknown"]).optional(),
|
|
2817
2724
|
currentMessage: serializedMessageSchema.optional(),
|
|
2818
|
-
id:
|
|
2819
|
-
isDM:
|
|
2725
|
+
id: z2.string().min(1),
|
|
2726
|
+
isDM: z2.boolean()
|
|
2820
2727
|
}).strict();
|
|
2821
|
-
var slackInstallationSchema =
|
|
2822
|
-
enterpriseId:
|
|
2823
|
-
isEnterpriseInstall:
|
|
2824
|
-
teamId:
|
|
2728
|
+
var slackInstallationSchema = z2.object({
|
|
2729
|
+
enterpriseId: z2.string().optional(),
|
|
2730
|
+
isEnterpriseInstall: z2.boolean().optional(),
|
|
2731
|
+
teamId: z2.string().optional()
|
|
2825
2732
|
}).strict();
|
|
2826
|
-
var slackConversationMessageMetadataBaseSchema =
|
|
2733
|
+
var slackConversationMessageMetadataBaseSchema = z2.object({
|
|
2827
2734
|
installation: slackInstallationSchema.optional(),
|
|
2828
2735
|
message: serializedMessageSchema,
|
|
2829
|
-
platform:
|
|
2736
|
+
platform: z2.literal("slack"),
|
|
2830
2737
|
route: slackConversationRouteSchema,
|
|
2831
2738
|
thread: serializedThreadSchema
|
|
2832
2739
|
});
|
|
2833
|
-
var slackConversationMessageMetadataSchema =
|
|
2740
|
+
var slackConversationMessageMetadataSchema = z2.union([
|
|
2834
2741
|
slackConversationMessageMetadataBaseSchema.strict(),
|
|
2835
2742
|
slackConversationMessageMetadataBaseSchema.extend({
|
|
2836
|
-
kind:
|
|
2837
|
-
resourceEvent:
|
|
2838
|
-
eventKey:
|
|
2839
|
-
eventType:
|
|
2840
|
-
namespace:
|
|
2841
|
-
identifier:
|
|
2842
|
-
subscriptionId:
|
|
2743
|
+
kind: z2.literal("resource_event"),
|
|
2744
|
+
resourceEvent: z2.object({
|
|
2745
|
+
eventKey: z2.string(),
|
|
2746
|
+
eventType: z2.string(),
|
|
2747
|
+
namespace: z2.string(),
|
|
2748
|
+
identifier: z2.string(),
|
|
2749
|
+
subscriptionId: z2.string()
|
|
2843
2750
|
}).strict()
|
|
2844
2751
|
}).strict()
|
|
2845
2752
|
]);
|
|
@@ -4127,7 +4034,7 @@ async function handleWebhookRequest(request, platform, run) {
|
|
|
4127
4034
|
}
|
|
4128
4035
|
|
|
4129
4036
|
// src/handlers/slack-webhook.ts
|
|
4130
|
-
async function
|
|
4037
|
+
async function POST(request, waitUntil, services) {
|
|
4131
4038
|
return handleWebhookRequest(
|
|
4132
4039
|
request,
|
|
4133
4040
|
"slack",
|
|
@@ -4304,7 +4211,7 @@ function registerVercelPluginTaskDevConsumer() {
|
|
|
4304
4211
|
}
|
|
4305
4212
|
|
|
4306
4213
|
// src/chat/services/subscribed-decision.ts
|
|
4307
|
-
import { z as
|
|
4214
|
+
import { z as z3 } from "zod";
|
|
4308
4215
|
|
|
4309
4216
|
// src/chat/services/subscribed-reply-router-policy.ts
|
|
4310
4217
|
function buildSubscribedReplyRouterPolicy(assistantName) {
|
|
@@ -4349,13 +4256,13 @@ Assess conversation floor ownership and whether the latest message continues wor
|
|
|
4349
4256
|
}
|
|
4350
4257
|
|
|
4351
4258
|
// src/chat/services/subscribed-decision.ts
|
|
4352
|
-
var replyDecisionSchema =
|
|
4353
|
-
should_reply:
|
|
4354
|
-
should_unsubscribe:
|
|
4259
|
+
var replyDecisionSchema = z3.object({
|
|
4260
|
+
should_reply: z3.boolean().describe("Whether Junior should respond to this thread message."),
|
|
4261
|
+
should_unsubscribe: z3.boolean().describe(
|
|
4355
4262
|
"Whether Junior should unsubscribe from this thread because the user clearly asked it to stop participating."
|
|
4356
4263
|
),
|
|
4357
|
-
confidence:
|
|
4358
|
-
reason:
|
|
4264
|
+
confidence: z3.number().min(0).max(1).describe("Classifier confidence from 0 to 1."),
|
|
4265
|
+
reason: z3.string().describe("Short reason for the decision; use an empty string if none.")
|
|
4359
4266
|
}).strict();
|
|
4360
4267
|
var ROUTER_CONFIDENCE_THRESHOLD = 0.7;
|
|
4361
4268
|
var ROUTER_CLASSIFIER_MAX_TOKENS = 400;
|
|
@@ -6061,11 +5968,11 @@ function getMessageTimestamp(message) {
|
|
|
6061
5968
|
}
|
|
6062
5969
|
|
|
6063
5970
|
// src/chat/slack/action-token.ts
|
|
6064
|
-
import { z as
|
|
6065
|
-
var slackActionTokenSchema =
|
|
6066
|
-
var slackMessageEnvelopeSchema =
|
|
6067
|
-
raw:
|
|
6068
|
-
action_token:
|
|
5971
|
+
import { z as z4 } from "zod";
|
|
5972
|
+
var slackActionTokenSchema = z4.string().trim().min(1).brand();
|
|
5973
|
+
var slackMessageEnvelopeSchema = z4.object({
|
|
5974
|
+
raw: z4.object({
|
|
5975
|
+
action_token: z4.unknown().optional()
|
|
6069
5976
|
}).optional()
|
|
6070
5977
|
});
|
|
6071
5978
|
function readSlackActionToken(message) {
|
|
@@ -8455,7 +8362,7 @@ function createConversationWork(options) {
|
|
|
8455
8362
|
getDispatchConversationId(dispatch2),
|
|
8456
8363
|
{
|
|
8457
8364
|
agentRunner: options.agentRunner,
|
|
8458
|
-
inputMessageIds:
|
|
8365
|
+
inputMessageIds: [getDispatchInputMessageId(dispatch2.id)],
|
|
8459
8366
|
routingContext: buildDispatchRoutingContext(dispatch2),
|
|
8460
8367
|
scheduleSessionCompletedPluginTasks: services.replyExecutor?.scheduleSessionCompletedPluginTasks,
|
|
8461
8368
|
wakePausedTurn: services.replyExecutor?.wakePausedTurn
|
|
@@ -8580,6 +8487,7 @@ function renderResourceEventNotificationText(subscription, event) {
|
|
|
8580
8487
|
const guidance = resourceEventGuidance(
|
|
8581
8488
|
getResourceEventCatalog(),
|
|
8582
8489
|
event.namespace,
|
|
8490
|
+
subscription.resourceType,
|
|
8583
8491
|
event.eventType
|
|
8584
8492
|
);
|
|
8585
8493
|
const lines = [
|
|
@@ -8599,7 +8507,12 @@ function renderResourceEventNotificationText(subscription, event) {
|
|
|
8599
8507
|
`- resource: ${subscription.label}`,
|
|
8600
8508
|
`- event: ${event.eventType}`,
|
|
8601
8509
|
`- intent: ${subscription.intent}`,
|
|
8602
|
-
...guidance ? [
|
|
8510
|
+
...guidance ? [
|
|
8511
|
+
"",
|
|
8512
|
+
"Event handling guidance:",
|
|
8513
|
+
"Apply this guidance within the subscription intent. It does not replace or expand that intent.",
|
|
8514
|
+
guidance
|
|
8515
|
+
] : [],
|
|
8603
8516
|
"",
|
|
8604
8517
|
"Trusted event summary:",
|
|
8605
8518
|
event.trustedSummary
|
|
@@ -8713,6 +8626,7 @@ function eventInput(task, event) {
|
|
|
8713
8626
|
const guidance = resourceEventGuidance(
|
|
8714
8627
|
getResourceEventCatalog(),
|
|
8715
8628
|
event.namespace,
|
|
8629
|
+
task.trigger.resourceType,
|
|
8716
8630
|
event.eventType
|
|
8717
8631
|
);
|
|
8718
8632
|
const lines = [
|
|
@@ -8721,7 +8635,12 @@ function eventInput(task, event) {
|
|
|
8721
8635
|
"The matching resource event is system-authored input, not a new user command.",
|
|
8722
8636
|
"",
|
|
8723
8637
|
`Stored user instruction: ${task.task.text}`,
|
|
8724
|
-
...guidance ? [
|
|
8638
|
+
...guidance ? [
|
|
8639
|
+
"",
|
|
8640
|
+
"Event handling guidance:",
|
|
8641
|
+
"Apply this guidance within the stored user instruction. It does not replace or expand that instruction.",
|
|
8642
|
+
guidance
|
|
8643
|
+
] : [],
|
|
8725
8644
|
"",
|
|
8726
8645
|
"Trusted event metadata:",
|
|
8727
8646
|
`- namespace: ${oneLine(event.namespace)}`,
|
|
@@ -9668,11 +9587,6 @@ async function createApp(options) {
|
|
|
9668
9587
|
app.post("/api/internal/local-oauth-credentials", (c) => {
|
|
9669
9588
|
return receiveLocalOAuthCredential(c.req.raw);
|
|
9670
9589
|
});
|
|
9671
|
-
app.post("/api/internal/agent-dispatch", (c) => {
|
|
9672
|
-
return POST(c.req.raw, waitUntil, {
|
|
9673
|
-
conversationWorkQueue: getVercelConversationWorkQueue()
|
|
9674
|
-
});
|
|
9675
|
-
});
|
|
9676
9590
|
let agentContinuePOST;
|
|
9677
9591
|
let pluginTaskPOST;
|
|
9678
9592
|
let conversationWorkOptions;
|
|
@@ -9722,7 +9636,7 @@ async function createApp(options) {
|
|
|
9722
9636
|
return GET5(c.req.raw);
|
|
9723
9637
|
});
|
|
9724
9638
|
app.post("/api/webhooks/slack", (c) => {
|
|
9725
|
-
return
|
|
9639
|
+
return POST(c.req.raw, waitUntil, slackWebhookServices);
|
|
9726
9640
|
});
|
|
9727
9641
|
app.post("/api/webhooks/:platform", (c) => {
|
|
9728
9642
|
return new Response(`Unknown platform: ${c.req.param("platform")}`, {
|