@sentry/junior 0.138.0 → 0.139.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-SCR74Q3E.js → agent-hooks-MJXMD7JP.js} +10 -10
- package/dist/api/schema/task.d.ts +100 -1
- package/dist/api/schema.d.ts +2 -2
- package/dist/api/schema.js +9 -1
- package/dist/api.js +198 -54
- package/dist/app.js +288 -602
- package/dist/{catalog-runtime-IU3QF4GG.js → catalog-runtime-GCCFYPIK.js} +6 -6
- package/dist/chat/agent/request.d.ts +12 -2
- package/dist/chat/credentials/context.d.ts +14 -0
- package/dist/chat/resource-events/actor.d.ts +23 -0
- package/dist/chat/state/turn-session.d.ts +1 -3
- package/dist/chat/tasks/execution-stats.d.ts +34 -3
- package/dist/chat/tasks/read.d.ts +3 -1
- package/dist/{chunk-JNNJZURV.js → chunk-2ECYPYKP.js} +1 -1
- package/dist/chunk-3T2JAGRH.js +115 -0
- package/dist/{chunk-PB3CXNVL.js → chunk-4V4QIYJH.js} +1 -1
- package/dist/{chunk-FEUNPTGV.js → chunk-5GSZWRE2.js} +434 -12
- package/dist/{chunk-QS527AV5.js → chunk-6OHTDR4F.js} +1 -1
- package/dist/{chunk-TCS76X5D.js → chunk-6SU2DT27.js} +2 -2
- package/dist/{chunk-BYW4B4PR.js → chunk-75I3UBIL.js} +2 -2
- package/dist/{chunk-ZBSMCXKV.js → chunk-AEQISMMU.js} +7 -6
- package/dist/{chunk-KDCHVT25.js → chunk-C2N6MNO4.js} +9 -2
- package/dist/{chunk-KFRHRSCJ.js → chunk-CXH25EL4.js} +2 -2
- package/dist/{chunk-TDJCLNDH.js → chunk-DW4PMHNW.js} +3 -3
- package/dist/{chunk-A7WCHXZV.js → chunk-G52UXKGO.js} +4 -4
- package/dist/chunk-GI52BW74.js +207 -0
- package/dist/{chunk-ZXNTJJIE.js → chunk-GWQSZT4C.js} +2 -2
- package/dist/{chunk-EPBBYMNE.js → chunk-HUO3UTAQ.js} +1 -1
- package/dist/{chunk-5MXWHTCK.js → chunk-IIESAYDL.js} +6 -6
- package/dist/{chunk-YU5QUF67.js → chunk-J3S57AXY.js} +1 -1
- package/dist/{chunk-E5UYAIKJ.js → chunk-J6EJQCHY.js} +17 -19
- package/dist/{chunk-5LTJ4ITU.js → chunk-MQ5RYATN.js} +4 -4
- package/dist/{chunk-BOLJOV5T.js → chunk-MXTVUV3I.js} +1 -1
- package/dist/{chunk-FNLBTB4K.js → chunk-MXVD2BDS.js} +1 -1
- package/dist/{chunk-TUUDXEXU.js → chunk-PJW6U46K.js} +12 -15
- package/dist/{chunk-SIPKWSXK.js → chunk-QTBKPZDA.js} +3 -3
- package/dist/{chunk-77VDLF3Z.js → chunk-RUIXF3YQ.js} +10 -0
- package/dist/{chunk-SD3OFRWY.js → chunk-U27DSXKB.js} +6 -6
- package/dist/{chunk-C7ZVPO4Z.js → chunk-U7CMWQ7Z.js} +1 -1
- package/dist/{chunk-DCLLQGS6.js → chunk-UDBUS533.js} +8 -3
- package/dist/{chunk-HIWJWWMT.js → chunk-WQRX57EA.js} +3 -3
- package/dist/{chunk-LPVUNO2W.js → chunk-WZH4JV7R.js} +7 -7
- package/dist/{chunk-HCIVH3JS.js → chunk-YCTDA7BD.js} +28 -0
- package/dist/{chunk-VPZFVJND.js → chunk-YGZ2OLXL.js} +1 -1
- package/dist/{chunk-N7WARMC6.js → chunk-ZQCGQMF2.js} +7 -7
- package/dist/{chunk-RZIBSCYC.js → chunk-ZYQSPQYR.js} +25 -22
- package/dist/cli/chat.js +33 -33
- package/dist/cli/check.js +7 -7
- package/dist/cli/plugins.js +14 -14
- package/dist/cli/snapshot-create.js +10 -10
- package/dist/cli/upgrade.js +8 -8
- package/dist/db/schema/task-executions.d.ts +23 -2
- package/dist/db/schema.d.ts +20 -1
- package/dist/{db-UO2IWXGA.js → db-UXPPGHDF.js} +7 -7
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +2 -2
- package/dist/{oauth-callback-server-MAQI43LX.js → oauth-callback-server-4ZYMD5UA.js} +22 -21
- package/dist/{runner-PIUQEXKE.js → runner-MZSEONRZ.js} +18 -16
- package/dist/{sandbox-egress-signals-A5HWIQH4.js → sandbox-egress-signals-EKPAVWQL.js} +2 -2
- package/dist/{skills-4ARJADHQ.js → skills-IMVPXSQ7.js} +7 -7
- package/dist/spawn-S5LSVOCE.js +38 -0
- package/dist/{validation-S3EE3HWL.js → validation-ZKCY2BVR.js} +7 -7
- package/dist/version.js +1 -1
- package/dist/{work-UARRUAW3.js → work-GG3XDYRX.js} +18 -18
- package/dist/{worker-DOCIRVD3.js → worker-23AUELCJ.js} +10 -10
- package/migrations/0022_task_execution_status.sql +3 -0
- package/migrations/meta/0022_snapshot.json +2186 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +5 -5
- package/dist/chunk-ELKW5FIB.js +0 -233
- package/dist/spawn-G2AWPMCT.js +0 -38
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
recordTaskExecution
|
|
3
|
+
} from "./chunk-GI52BW74.js";
|
|
1
4
|
import {
|
|
2
5
|
pluginTaskId,
|
|
3
6
|
pluginTaskParamsSchema,
|
|
@@ -22,7 +25,10 @@ import {
|
|
|
22
25
|
persistThreadStateById,
|
|
23
26
|
stripRuntimeTurnContext,
|
|
24
27
|
updateConversationStats
|
|
25
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-PJW6U46K.js";
|
|
29
|
+
import {
|
|
30
|
+
JUNIOR_THREAD_STATE_TTL_MS
|
|
31
|
+
} from "./chunk-3Y47VMHV.js";
|
|
26
32
|
import {
|
|
27
33
|
createPluginConversationEvents,
|
|
28
34
|
createPluginEmbedder,
|
|
@@ -30,26 +36,30 @@ import {
|
|
|
30
36
|
createPluginModel,
|
|
31
37
|
createPluginState,
|
|
32
38
|
getPlugins
|
|
33
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-IIESAYDL.js";
|
|
34
40
|
import {
|
|
41
|
+
getConversationStore,
|
|
35
42
|
getDb,
|
|
36
43
|
sameActorIdentity
|
|
37
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-QTBKPZDA.js";
|
|
38
45
|
import {
|
|
39
46
|
getStateAdapter
|
|
40
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-MXTVUV3I.js";
|
|
41
48
|
import {
|
|
42
49
|
ProviderError,
|
|
43
50
|
findProviderError,
|
|
44
51
|
getProviderErrorAttributes,
|
|
45
52
|
getProviderErrorUserMessage
|
|
46
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-75I3UBIL.js";
|
|
54
|
+
import {
|
|
55
|
+
credentialSubjectSchema
|
|
56
|
+
} from "./chunk-RUIXF3YQ.js";
|
|
47
57
|
import {
|
|
48
58
|
parseSlackMessageTs
|
|
49
59
|
} from "./chunk-F3B2YJ76.js";
|
|
50
60
|
import {
|
|
51
61
|
buildTurnFailureResponse
|
|
52
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-2ECYPYKP.js";
|
|
53
63
|
|
|
54
64
|
// src/chat/runtime/delivered-turn-state.ts
|
|
55
65
|
function buildDeliveredTurnStatePatch(args) {
|
|
@@ -85,7 +95,7 @@ import {
|
|
|
85
95
|
|
|
86
96
|
// src/chat/services/turn-session-routing.ts
|
|
87
97
|
async function resolveTurnSessionRouting(args) {
|
|
88
|
-
const conversationStore = args.conversationStore ?? (await import("./db-
|
|
98
|
+
const conversationStore = args.conversationStore ?? (await import("./db-UXPPGHDF.js")).getConversationStore();
|
|
89
99
|
const conversation = await conversationStore.get({
|
|
90
100
|
conversationId: args.conversationId
|
|
91
101
|
});
|
|
@@ -100,6 +110,397 @@ async function resolveTurnSessionRouting(args) {
|
|
|
100
110
|
};
|
|
101
111
|
}
|
|
102
112
|
|
|
113
|
+
// src/chat/agent-dispatch/store.ts
|
|
114
|
+
import { createHash } from "crypto";
|
|
115
|
+
import {
|
|
116
|
+
destinationSchema,
|
|
117
|
+
destinationVisibilitySchema,
|
|
118
|
+
isSlackDestination,
|
|
119
|
+
replyAttributionSchema,
|
|
120
|
+
sourceSchema
|
|
121
|
+
} from "@sentry/junior-plugin-api";
|
|
122
|
+
import { z } from "zod";
|
|
123
|
+
var DISPATCH_PREFIX = "junior:agent_dispatch";
|
|
124
|
+
var DISPATCH_LOCK_TTL_MS = 10 * 60 * 1e3;
|
|
125
|
+
var DISPATCH_MAILBOX_APPEND_INDEX_LOCK_TTL_MS = 1e4;
|
|
126
|
+
var DISPATCH_MAILBOX_APPEND_INDEX_MAX_LENGTH = 1e4;
|
|
127
|
+
var nonEmptyExactStringSchema = z.string().min(1).refine(
|
|
128
|
+
(value) => value === value.trim() && value.toLowerCase() !== "unknown"
|
|
129
|
+
);
|
|
130
|
+
var pendingDispatchMailboxAppendIndexSchema = z.array(
|
|
131
|
+
nonEmptyExactStringSchema
|
|
132
|
+
);
|
|
133
|
+
var dispatchStatusSchema = z.enum([
|
|
134
|
+
"pending",
|
|
135
|
+
"running",
|
|
136
|
+
"awaiting_resume",
|
|
137
|
+
"completed",
|
|
138
|
+
"failed",
|
|
139
|
+
"blocked"
|
|
140
|
+
]);
|
|
141
|
+
var dispatchActorSchema = z.object({
|
|
142
|
+
platform: z.literal("system"),
|
|
143
|
+
name: nonEmptyExactStringSchema
|
|
144
|
+
}).strict();
|
|
145
|
+
var dispatchRecordSchema = z.object({
|
|
146
|
+
actor: dispatchActorSchema,
|
|
147
|
+
createdAtMs: z.number().finite(),
|
|
148
|
+
credentialSubject: credentialSubjectSchema.optional(),
|
|
149
|
+
destination: destinationSchema,
|
|
150
|
+
destinationVisibility: destinationVisibilitySchema,
|
|
151
|
+
errorMessage: z.string().optional(),
|
|
152
|
+
id: nonEmptyExactStringSchema,
|
|
153
|
+
idempotencyKey: z.string().min(1),
|
|
154
|
+
input: z.string().min(1),
|
|
155
|
+
metadata: z.record(z.string(), z.string()).optional(),
|
|
156
|
+
plugin: nonEmptyExactStringSchema,
|
|
157
|
+
replyAttribution: replyAttributionSchema.optional(),
|
|
158
|
+
resultMessageTs: z.string().optional(),
|
|
159
|
+
source: sourceSchema,
|
|
160
|
+
status: dispatchStatusSchema,
|
|
161
|
+
updatedAtMs: z.number().finite()
|
|
162
|
+
}).strict().superRefine((record, ctx) => {
|
|
163
|
+
if (!isSlackDestination(record.destination)) {
|
|
164
|
+
ctx.addIssue({
|
|
165
|
+
code: z.ZodIssueCode.custom,
|
|
166
|
+
message: "Dispatch destination platform must be slack",
|
|
167
|
+
path: ["destination"]
|
|
168
|
+
});
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const subject = record.credentialSubject;
|
|
172
|
+
if (!subject) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (subject.allowedWhen === "private-direct-conversation") {
|
|
176
|
+
if (!record.destination.channelId.startsWith("D")) {
|
|
177
|
+
ctx.addIssue({
|
|
178
|
+
code: z.ZodIssueCode.custom,
|
|
179
|
+
message: "Dispatch credentialSubject requires a private direct Slack destination",
|
|
180
|
+
path: ["credentialSubject"]
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (subject.binding.type !== "slack-direct-conversation" || subject.binding.teamId !== record.destination.teamId || subject.binding.channelId !== record.destination.channelId) {
|
|
185
|
+
ctx.addIssue({
|
|
186
|
+
code: z.ZodIssueCode.custom,
|
|
187
|
+
message: "Dispatch credentialSubject binding must match destination",
|
|
188
|
+
path: ["credentialSubject", "binding"]
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (subject.binding.type !== subject.allowedWhen || subject.binding.plugin !== record.plugin || subject.binding.taskId !== subject.taskId) {
|
|
194
|
+
ctx.addIssue({
|
|
195
|
+
code: z.ZodIssueCode.custom,
|
|
196
|
+
message: "Dispatch credentialSubject binding must match task",
|
|
197
|
+
path: ["credentialSubject", "binding"]
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
var storedDispatchRecordSchema = dispatchRecordSchema.extend({
|
|
202
|
+
attempt: z.number().int().nonnegative().optional(),
|
|
203
|
+
lastCallbackAtMs: z.number().finite().optional(),
|
|
204
|
+
leaseExpiresAtMs: z.number().finite().optional(),
|
|
205
|
+
maxAttempts: z.number().int().positive().optional(),
|
|
206
|
+
version: z.number().int().positive().optional()
|
|
207
|
+
});
|
|
208
|
+
function getDispatchStorageKey(id) {
|
|
209
|
+
return `${DISPATCH_PREFIX}:record:${id}`;
|
|
210
|
+
}
|
|
211
|
+
function dispatchLockKey(id) {
|
|
212
|
+
return `${DISPATCH_PREFIX}:lock:${id}`;
|
|
213
|
+
}
|
|
214
|
+
function pendingDispatchMailboxAppendIndexKey() {
|
|
215
|
+
return `${DISPATCH_PREFIX}:incomplete`;
|
|
216
|
+
}
|
|
217
|
+
function pendingDispatchMailboxAppendIndexLockKey() {
|
|
218
|
+
return `${DISPATCH_PREFIX}:incomplete:lock`;
|
|
219
|
+
}
|
|
220
|
+
function normalizeMetadata(metadata) {
|
|
221
|
+
if (!metadata) {
|
|
222
|
+
return void 0;
|
|
223
|
+
}
|
|
224
|
+
const entries = Object.entries(metadata).filter(
|
|
225
|
+
(entry) => typeof entry[0] === "string" && typeof entry[1] === "string"
|
|
226
|
+
);
|
|
227
|
+
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
228
|
+
}
|
|
229
|
+
function buildDispatchId(plugin, idempotencyKey) {
|
|
230
|
+
const digest = createHash("sha256").update(plugin).update("\0").update(idempotencyKey).digest("hex").slice(0, 32);
|
|
231
|
+
return `dispatch_${digest}`;
|
|
232
|
+
}
|
|
233
|
+
function parseDispatchRecord(value) {
|
|
234
|
+
const parsed = parseStoredDispatchRecord(value);
|
|
235
|
+
return parsed?.record;
|
|
236
|
+
}
|
|
237
|
+
function parseStoredDispatchRecord(value) {
|
|
238
|
+
const parsed = storedDispatchRecordSchema.safeParse(value);
|
|
239
|
+
if (!parsed.success) {
|
|
240
|
+
return void 0;
|
|
241
|
+
}
|
|
242
|
+
const {
|
|
243
|
+
attempt: _attempt,
|
|
244
|
+
lastCallbackAtMs: _lastCallbackAtMs,
|
|
245
|
+
leaseExpiresAtMs: _leaseExpiresAtMs,
|
|
246
|
+
maxAttempts: _maxAttempts,
|
|
247
|
+
version: _version,
|
|
248
|
+
...record
|
|
249
|
+
} = parsed.data;
|
|
250
|
+
return {
|
|
251
|
+
...typeof parsed.data.leaseExpiresAtMs === "number" ? { legacyLeaseExpiresAtMs: parsed.data.leaseExpiresAtMs } : {},
|
|
252
|
+
record
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function getDispatchConversationId(dispatch) {
|
|
256
|
+
return `agent-dispatch:${dispatch.id}`;
|
|
257
|
+
}
|
|
258
|
+
function getDispatchInputMessageId(dispatchId) {
|
|
259
|
+
return `agent-dispatch:${dispatchId}`;
|
|
260
|
+
}
|
|
261
|
+
function getLegacyDispatchInputMessageId(dispatchId) {
|
|
262
|
+
return `dispatch:${dispatchId}:user`;
|
|
263
|
+
}
|
|
264
|
+
function getDispatchInputMessageIds(dispatchId) {
|
|
265
|
+
return [
|
|
266
|
+
getDispatchInputMessageId(dispatchId),
|
|
267
|
+
getLegacyDispatchInputMessageId(dispatchId)
|
|
268
|
+
];
|
|
269
|
+
}
|
|
270
|
+
function getDispatchTurnId(dispatchId) {
|
|
271
|
+
return `dispatch:${dispatchId}`;
|
|
272
|
+
}
|
|
273
|
+
function toDispatchProjection(record) {
|
|
274
|
+
return {
|
|
275
|
+
id: record.id,
|
|
276
|
+
status: record.status,
|
|
277
|
+
...record.resultMessageTs ? { resultMessageTs: record.resultMessageTs } : {},
|
|
278
|
+
...record.errorMessage ? { errorMessage: record.errorMessage } : {}
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function isTerminalDispatchStatus(status) {
|
|
282
|
+
return status === "completed" || status === "failed" || status === "blocked";
|
|
283
|
+
}
|
|
284
|
+
async function withDispatchLock(dispatchId, task) {
|
|
285
|
+
const state = getStateAdapter();
|
|
286
|
+
await state.connect();
|
|
287
|
+
const lock = await state.acquireLock(
|
|
288
|
+
dispatchLockKey(dispatchId),
|
|
289
|
+
DISPATCH_LOCK_TTL_MS
|
|
290
|
+
);
|
|
291
|
+
if (!lock) {
|
|
292
|
+
throw new Error(`Could not acquire dispatch lock for ${dispatchId}`);
|
|
293
|
+
}
|
|
294
|
+
try {
|
|
295
|
+
return await task(state);
|
|
296
|
+
} finally {
|
|
297
|
+
await state.releaseLock(lock);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
async function putRecord(state, record) {
|
|
301
|
+
const parsed = dispatchRecordSchema.safeParse(record);
|
|
302
|
+
if (!parsed.success) {
|
|
303
|
+
throw new Error(
|
|
304
|
+
`Dispatch record is invalid: ${parsed.error.issues.map((issue) => `${issue.path.join(".") || "<root>"} ${issue.message}`).join("; ")}`
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
const next = parsed.data;
|
|
308
|
+
await state.set(
|
|
309
|
+
getDispatchStorageKey(next.id),
|
|
310
|
+
next,
|
|
311
|
+
JUNIOR_THREAD_STATE_TTL_MS
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
async function updatePendingDispatchMailboxAppendIndex(state, update) {
|
|
315
|
+
const lock = await state.acquireLock(
|
|
316
|
+
pendingDispatchMailboxAppendIndexLockKey(),
|
|
317
|
+
DISPATCH_MAILBOX_APPEND_INDEX_LOCK_TTL_MS
|
|
318
|
+
);
|
|
319
|
+
if (!lock) {
|
|
320
|
+
throw new Error("Could not acquire dispatch mailbox append index lock");
|
|
321
|
+
}
|
|
322
|
+
try {
|
|
323
|
+
const stored = await state.get(pendingDispatchMailboxAppendIndexKey());
|
|
324
|
+
const ids = stored === void 0 || stored === null ? [] : pendingDispatchMailboxAppendIndexSchema.parse(stored);
|
|
325
|
+
const next = [...new Set(update([...new Set(ids)]))].slice(
|
|
326
|
+
-DISPATCH_MAILBOX_APPEND_INDEX_MAX_LENGTH
|
|
327
|
+
);
|
|
328
|
+
if (next.length === ids.length && next.every((id, index) => id === ids[index])) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
await state.set(
|
|
332
|
+
pendingDispatchMailboxAppendIndexKey(),
|
|
333
|
+
next,
|
|
334
|
+
JUNIOR_THREAD_STATE_TTL_MS
|
|
335
|
+
);
|
|
336
|
+
} finally {
|
|
337
|
+
await state.releaseLock(lock);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
async function getDispatchRecord(id) {
|
|
341
|
+
const state = getStateAdapter();
|
|
342
|
+
await state.connect();
|
|
343
|
+
return parseDispatchRecord(await state.get(getDispatchStorageKey(id)));
|
|
344
|
+
}
|
|
345
|
+
async function createOrGetDispatch(args) {
|
|
346
|
+
const id = buildDispatchId(args.plugin, args.options.idempotencyKey);
|
|
347
|
+
return await withDispatchLock(id, async (state) => {
|
|
348
|
+
const existing = parseDispatchRecord(
|
|
349
|
+
await state.get(getDispatchStorageKey(id))
|
|
350
|
+
);
|
|
351
|
+
if (existing) {
|
|
352
|
+
return { record: existing, status: "already_exists" };
|
|
353
|
+
}
|
|
354
|
+
const metadata = normalizeMetadata(args.options.metadata);
|
|
355
|
+
const record = {
|
|
356
|
+
actor: { platform: "system", name: args.plugin },
|
|
357
|
+
createdAtMs: args.nowMs,
|
|
358
|
+
...args.options.credentialSubject ? { credentialSubject: args.options.credentialSubject } : {},
|
|
359
|
+
destination: args.options.destination,
|
|
360
|
+
destinationVisibility: args.options.destinationVisibility,
|
|
361
|
+
id,
|
|
362
|
+
idempotencyKey: args.options.idempotencyKey,
|
|
363
|
+
input: args.options.input,
|
|
364
|
+
...metadata ? { metadata } : {},
|
|
365
|
+
plugin: args.plugin,
|
|
366
|
+
...args.options.replyAttribution ? { replyAttribution: args.options.replyAttribution } : {},
|
|
367
|
+
status: "pending",
|
|
368
|
+
source: args.options.source,
|
|
369
|
+
updatedAtMs: args.nowMs
|
|
370
|
+
};
|
|
371
|
+
await updatePendingDispatchMailboxAppendIndex(
|
|
372
|
+
state,
|
|
373
|
+
(ids) => ids.includes(id) ? ids : [...ids, id]
|
|
374
|
+
);
|
|
375
|
+
await putRecord(state, record);
|
|
376
|
+
return { record, status: "created" };
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
async function transitionDispatch(id, transition) {
|
|
380
|
+
return await withDispatchLock(id, async (state) => {
|
|
381
|
+
const current = parseDispatchRecord(
|
|
382
|
+
await state.get(getDispatchStorageKey(id))
|
|
383
|
+
);
|
|
384
|
+
if (!current) {
|
|
385
|
+
return void 0;
|
|
386
|
+
}
|
|
387
|
+
const transitioned = transition(current);
|
|
388
|
+
if (transitioned === current) {
|
|
389
|
+
return current;
|
|
390
|
+
}
|
|
391
|
+
const next = {
|
|
392
|
+
...transitioned,
|
|
393
|
+
updatedAtMs: Date.now()
|
|
394
|
+
};
|
|
395
|
+
await putRecord(state, next);
|
|
396
|
+
return next;
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
async function markDispatchRunning(id) {
|
|
400
|
+
return await transitionDispatch(
|
|
401
|
+
id,
|
|
402
|
+
(record) => isTerminalDispatchStatus(record.status) ? record : { ...record, status: "running", errorMessage: void 0 }
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
async function markDispatchAwaitingResume(id) {
|
|
406
|
+
return await transitionDispatch(
|
|
407
|
+
id,
|
|
408
|
+
(record) => isTerminalDispatchStatus(record.status) ? record : {
|
|
409
|
+
...record,
|
|
410
|
+
status: "awaiting_resume"
|
|
411
|
+
}
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
async function recordEventTaskExecution(previous, next, status) {
|
|
415
|
+
if (!next || next.status !== status || previous?.status === status) return;
|
|
416
|
+
if (next.plugin !== "junior") return;
|
|
417
|
+
const eventTaskId = next.metadata?.eventTaskId;
|
|
418
|
+
if (!eventTaskId) return;
|
|
419
|
+
const conversationId = getDispatchConversationId(next);
|
|
420
|
+
const conversation = await getConversationStore().get({ conversationId });
|
|
421
|
+
await recordTaskExecution("event", eventTaskId, {
|
|
422
|
+
...conversation ? { conversationId } : {},
|
|
423
|
+
executionId: next.id,
|
|
424
|
+
nowMs: next.updatedAtMs,
|
|
425
|
+
status
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
async function markDispatchBlocked(id, errorMessage, resultMessageTs) {
|
|
429
|
+
const previous = await getDispatchRecord(id);
|
|
430
|
+
const next = await transitionDispatch(
|
|
431
|
+
id,
|
|
432
|
+
(record) => isTerminalDispatchStatus(record.status) ? record : {
|
|
433
|
+
...record,
|
|
434
|
+
errorMessage,
|
|
435
|
+
...resultMessageTs ? { resultMessageTs } : {},
|
|
436
|
+
status: "blocked"
|
|
437
|
+
}
|
|
438
|
+
);
|
|
439
|
+
await recordEventTaskExecution(previous, next, "blocked");
|
|
440
|
+
return next;
|
|
441
|
+
}
|
|
442
|
+
async function markDispatchCompleted(id, resultMessageTs) {
|
|
443
|
+
const previous = await getDispatchRecord(id);
|
|
444
|
+
const next = await transitionDispatch(
|
|
445
|
+
id,
|
|
446
|
+
(record) => isTerminalDispatchStatus(record.status) ? record : {
|
|
447
|
+
...record,
|
|
448
|
+
errorMessage: void 0,
|
|
449
|
+
...resultMessageTs ? { resultMessageTs } : {},
|
|
450
|
+
status: "completed"
|
|
451
|
+
}
|
|
452
|
+
);
|
|
453
|
+
await recordEventTaskExecution(previous, next, "completed");
|
|
454
|
+
return next;
|
|
455
|
+
}
|
|
456
|
+
async function markDispatchFailed(id, errorMessage, resultMessageTs) {
|
|
457
|
+
const previous = await getDispatchRecord(id);
|
|
458
|
+
const next = await transitionDispatch(
|
|
459
|
+
id,
|
|
460
|
+
(record) => isTerminalDispatchStatus(record.status) ? record : {
|
|
461
|
+
...record,
|
|
462
|
+
errorMessage,
|
|
463
|
+
...resultMessageTs ? { resultMessageTs } : {},
|
|
464
|
+
status: "failed"
|
|
465
|
+
}
|
|
466
|
+
);
|
|
467
|
+
await recordEventTaskExecution(previous, next, "failed");
|
|
468
|
+
return next;
|
|
469
|
+
}
|
|
470
|
+
async function confirmDispatchMailboxAppend(id) {
|
|
471
|
+
const state = getStateAdapter();
|
|
472
|
+
await state.connect();
|
|
473
|
+
await updatePendingDispatchMailboxAppendIndex(
|
|
474
|
+
state,
|
|
475
|
+
(ids) => ids.filter((candidate) => candidate !== id)
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
async function listPendingDispatchMailboxAppends() {
|
|
479
|
+
const state = getStateAdapter();
|
|
480
|
+
await state.connect();
|
|
481
|
+
const stored = await state.get(pendingDispatchMailboxAppendIndexKey());
|
|
482
|
+
return stored === void 0 || stored === null ? [] : [...new Set(pendingDispatchMailboxAppendIndexSchema.parse(stored))];
|
|
483
|
+
}
|
|
484
|
+
async function claimDispatchMailboxAppend(id, nowMs) {
|
|
485
|
+
return await withDispatchLock(id, async (state) => {
|
|
486
|
+
const stored = parseStoredDispatchRecord(
|
|
487
|
+
await state.get(getDispatchStorageKey(id))
|
|
488
|
+
);
|
|
489
|
+
if (!stored || stored.legacyLeaseExpiresAtMs && stored.legacyLeaseExpiresAtMs > nowMs) {
|
|
490
|
+
return void 0;
|
|
491
|
+
}
|
|
492
|
+
await putRecord(state, stored.record);
|
|
493
|
+
return stored.record;
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
async function getPluginDispatchProjection(args) {
|
|
497
|
+
const record = await getDispatchRecord(args.id);
|
|
498
|
+
if (!record || record.plugin !== args.plugin) {
|
|
499
|
+
return void 0;
|
|
500
|
+
}
|
|
501
|
+
return toDispatchProjection(record);
|
|
502
|
+
}
|
|
503
|
+
|
|
103
504
|
// src/chat/plugins/task-runner.ts
|
|
104
505
|
var PLUGIN_TASK_LOCK_TTL_MS = 5 * 60 * 1e3;
|
|
105
506
|
function isRecord(value) {
|
|
@@ -229,7 +630,7 @@ function messageExistedAtRunCompletion(message, completedAtMs) {
|
|
|
229
630
|
const messageTimestampMs = conversationMessageTimestampMs(message);
|
|
230
631
|
return messageTimestampMs !== void 0 && messageTimestampMs <= completedAtMs;
|
|
231
632
|
}
|
|
232
|
-
async function loadConversationContextTranscriptEntries(record, source) {
|
|
633
|
+
async function loadConversationContextTranscriptEntries(record, source, runActor) {
|
|
233
634
|
if (source.platform !== "slack" || isPrivateSource(source)) {
|
|
234
635
|
return [];
|
|
235
636
|
}
|
|
@@ -260,7 +661,7 @@ async function loadConversationContextTranscriptEntries(record, source) {
|
|
|
260
661
|
authority: "context",
|
|
261
662
|
...author ? { actor: author } : {}
|
|
262
663
|
},
|
|
263
|
-
isRunActor: sameActorIdentity(author,
|
|
664
|
+
isRunActor: sameActorIdentity(author, runActor)
|
|
264
665
|
});
|
|
265
666
|
}
|
|
266
667
|
return entries;
|
|
@@ -295,13 +696,18 @@ async function loadPluginRun(params) {
|
|
|
295
696
|
const routing = await resolveTurnSessionRouting({
|
|
296
697
|
conversationId: params.conversationId
|
|
297
698
|
});
|
|
699
|
+
const runActor = record.actors[0] ?? (record.dispatchId ? (await getDispatchRecord(record.dispatchId))?.actor : void 0);
|
|
298
700
|
const runEntries = turnMessagesWithProvenance(record).map(
|
|
299
|
-
({ message, provenance }) => runTranscriptEntry(message, provenance,
|
|
701
|
+
({ message, provenance }) => runTranscriptEntry(message, provenance, runActor)
|
|
300
702
|
).filter((entry) => Boolean(entry));
|
|
301
703
|
const runMessageTexts = new Set(
|
|
302
704
|
runEntries.filter((entry) => entry.type === "message").map((entry) => entry.text)
|
|
303
705
|
);
|
|
304
|
-
const contextEntries = (await loadConversationContextTranscriptEntries(
|
|
706
|
+
const contextEntries = (await loadConversationContextTranscriptEntries(
|
|
707
|
+
record,
|
|
708
|
+
routing.source,
|
|
709
|
+
runActor
|
|
710
|
+
)).filter(
|
|
305
711
|
(entry) => entry.type !== "message" || !runMessageTexts.has(entry.text)
|
|
306
712
|
);
|
|
307
713
|
return pluginRunContextSchema.parse({
|
|
@@ -311,7 +717,7 @@ async function loadPluginRun(params) {
|
|
|
311
717
|
// Derived from the full run provenance on the record, not the sliced or
|
|
312
718
|
// stripped transcript, so it reflects every committed instruction actor.
|
|
313
719
|
actors: record.actors,
|
|
314
|
-
...
|
|
720
|
+
...runActor ? { actor: runActor } : {},
|
|
315
721
|
runId: record.sessionId,
|
|
316
722
|
source: routing.source,
|
|
317
723
|
transcript: [...contextEntries, ...runEntries]
|
|
@@ -548,6 +954,22 @@ async function persistAuthPauseTurnState(args) {
|
|
|
548
954
|
}
|
|
549
955
|
|
|
550
956
|
export {
|
|
957
|
+
getDispatchConversationId,
|
|
958
|
+
getDispatchInputMessageId,
|
|
959
|
+
getDispatchInputMessageIds,
|
|
960
|
+
getDispatchTurnId,
|
|
961
|
+
isTerminalDispatchStatus,
|
|
962
|
+
getDispatchRecord,
|
|
963
|
+
createOrGetDispatch,
|
|
964
|
+
markDispatchRunning,
|
|
965
|
+
markDispatchAwaitingResume,
|
|
966
|
+
markDispatchBlocked,
|
|
967
|
+
markDispatchCompleted,
|
|
968
|
+
markDispatchFailed,
|
|
969
|
+
confirmDispatchMailboxAppend,
|
|
970
|
+
listPendingDispatchMailboxAppends,
|
|
971
|
+
claimDispatchMailboxAppend,
|
|
972
|
+
getPluginDispatchProjection,
|
|
551
973
|
buildDeliveredTurnStatePatch,
|
|
552
974
|
getTurnUserMessage,
|
|
553
975
|
getTurnUserMessageId,
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-EM225ITJ.js";
|
|
4
4
|
import {
|
|
5
5
|
getSlackBotToken
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-75I3UBIL.js";
|
|
7
7
|
import {
|
|
8
8
|
parseSlackChannelReferenceId
|
|
9
9
|
} from "./chunk-F3B2YJ76.js";
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
setSpanAttributes,
|
|
13
13
|
setSpanStatus,
|
|
14
14
|
withSpan
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-2ECYPYKP.js";
|
|
16
16
|
|
|
17
17
|
// src/chat/slack/client.ts
|
|
18
18
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
toCanonicalInputMessage,
|
|
4
4
|
toCanonicalOutputMessage,
|
|
5
5
|
toGenAiMessagesTraceAttributes
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-YGZ2OLXL.js";
|
|
7
7
|
import {
|
|
8
8
|
extractGenAiUsageAttributes,
|
|
9
9
|
logException,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
normalizeGenAiFinishReason,
|
|
12
12
|
serializeGenAiAttribute,
|
|
13
13
|
withSpan
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-2ECYPYKP.js";
|
|
15
15
|
|
|
16
16
|
// src/chat/services/provider-error.ts
|
|
17
17
|
var ProviderError = class extends Error {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
appendAndEnqueueInboundMessage
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-MQ5RYATN.js";
|
|
4
4
|
import {
|
|
5
5
|
ConversationTurnLifecycleService
|
|
6
6
|
} from "./chunk-Q6QZTTLS.js";
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
agentBindingSchema,
|
|
13
13
|
agentInvocationSchema,
|
|
14
14
|
createAgentInvocationSchema
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-WZH4JV7R.js";
|
|
16
16
|
import {
|
|
17
17
|
TurnInputCommitLostError,
|
|
18
18
|
coerceThreadArtifactsState,
|
|
@@ -28,16 +28,16 @@ import {
|
|
|
28
28
|
persistCompletedSessionRecord,
|
|
29
29
|
persistThreadStateById,
|
|
30
30
|
persistYieldSessionRecord
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-PJW6U46K.js";
|
|
32
32
|
import {
|
|
33
33
|
getConversationEventStore,
|
|
34
34
|
getConversationStore,
|
|
35
35
|
getSqlExecutor
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-QTBKPZDA.js";
|
|
37
37
|
import {
|
|
38
38
|
juniorAgentBindings,
|
|
39
39
|
juniorAgentInvocations
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-UDBUS533.js";
|
|
41
41
|
|
|
42
42
|
// src/chat/agent-invocations/work.ts
|
|
43
43
|
import { z } from "zod";
|
|
@@ -442,7 +442,8 @@ async function recoverRunningSession(invocation) {
|
|
|
442
442
|
errorMessage: "Recovered running agent invocation after worker loss",
|
|
443
443
|
messages: session.piMessages,
|
|
444
444
|
modelId: session.modelId,
|
|
445
|
-
actor
|
|
445
|
+
// Execution actor lives on the parent invocation record, not Redis.
|
|
446
|
+
actor: invocation.actor,
|
|
446
447
|
reasoningLevel: session.reasoningLevel,
|
|
447
448
|
sessionId: session.sessionId,
|
|
448
449
|
surface: session.surface
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
JUNIOR_VERSION
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-U7CMWQ7Z.js";
|
|
4
4
|
|
|
5
5
|
// src/deployment.ts
|
|
6
6
|
var JUNIOR_HEARTBEAT_ROUTE = "/api/internal/heartbeat";
|
|
@@ -15,7 +15,14 @@ function toOptionalTrimmed(value) {
|
|
|
15
15
|
return trimmed ? trimmed : void 0;
|
|
16
16
|
}
|
|
17
17
|
function getDeploymentServiceVersion() {
|
|
18
|
-
|
|
18
|
+
const configuredRelease = toOptionalTrimmed(process.env.SENTRY_RELEASE);
|
|
19
|
+
if (configuredRelease) {
|
|
20
|
+
return configuredRelease;
|
|
21
|
+
}
|
|
22
|
+
const deploymentRevision = toOptionalTrimmed(
|
|
23
|
+
process.env.VERCEL_GIT_COMMIT_SHA
|
|
24
|
+
);
|
|
25
|
+
return deploymentRevision ? `${JUNIOR_VERSION}+${deploymentRevision}` : void 0;
|
|
19
26
|
}
|
|
20
27
|
function getDeploymentTelemetryAttributes() {
|
|
21
28
|
const attributes = {};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
credentialUserSubjectId
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RUIXF3YQ.js";
|
|
4
4
|
import {
|
|
5
5
|
logInfo,
|
|
6
6
|
logWarn,
|
|
7
7
|
setSpanAttributes
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-2ECYPYKP.js";
|
|
9
9
|
import {
|
|
10
10
|
discoverInstalledPluginPackageContent,
|
|
11
11
|
normalizePluginPackageNames
|
|
@@ -4,16 +4,16 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
canRouteResourceEvents,
|
|
6
6
|
getPlugins
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-IIESAYDL.js";
|
|
8
8
|
import {
|
|
9
9
|
getDb
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QTBKPZDA.js";
|
|
11
11
|
import {
|
|
12
12
|
juniorEventTasks,
|
|
13
13
|
juniorSchedulerRuns,
|
|
14
14
|
juniorSchedulerTasks,
|
|
15
15
|
juniorStats
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-UDBUS533.js";
|
|
17
17
|
import {
|
|
18
18
|
juniorDestinations
|
|
19
19
|
} from "./chunk-VFUK3X5B.js";
|