@sentry/junior 0.139.0 → 0.141.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.
Files changed (77) hide show
  1. package/dist/{agent-hooks-MJXMD7JP.js → agent-hooks-HIRVKUQJ.js} +10 -10
  2. package/dist/api/conversations/detail.d.ts +1 -0
  3. package/dist/api/conversations/event-list.d.ts +1 -0
  4. package/dist/api/schema/conversation.d.ts +4 -0
  5. package/dist/api/schema/task.d.ts +4 -0
  6. package/dist/api/schema.js +1 -1
  7. package/dist/api.js +20 -20
  8. package/dist/app.js +117 -36
  9. package/dist/{catalog-runtime-GCCFYPIK.js → catalog-runtime-XVLED5UH.js} +5 -5
  10. package/dist/chat/agent/repository-context.d.ts +1 -0
  11. package/dist/chat/conversations/history.d.ts +2 -0
  12. package/dist/chat/conversations/projection.d.ts +8 -0
  13. package/dist/chat/conversations/store.d.ts +5 -0
  14. package/dist/chat/conversations/structured-events.d.ts +11 -0
  15. package/dist/chat/runtime/thread-state.d.ts +3 -1
  16. package/dist/chat/scheduled-tasks/telemetry.d.ts +7 -0
  17. package/dist/chat/scheduled-tasks/tool-support.d.ts +10 -2
  18. package/dist/chat/scheduled-tasks/tools/create.d.ts +4 -2
  19. package/dist/chat/scheduled-tasks/tools/delete.d.ts +4 -2
  20. package/dist/chat/scheduled-tasks/tools/list.d.ts +4 -2
  21. package/dist/chat/scheduled-tasks/tools/run-now.d.ts +4 -2
  22. package/dist/chat/scheduled-tasks/tools/update.d.ts +4 -2
  23. package/dist/chat/scheduled-tasks/types.d.ts +1 -1
  24. package/dist/chat/services/guardian-action-policy.d.ts +1 -1
  25. package/dist/chat/slack/dashboard-link.d.ts +2 -0
  26. package/dist/chat/state/turn-session-keys.d.ts +2 -2
  27. package/dist/chat/state/turn-session.d.ts +18 -13
  28. package/dist/{chunk-GI52BW74.js → chunk-2DOVDDZJ.js} +3 -3
  29. package/dist/{chunk-UDBUS533.js → chunk-3H42HMA2.js} +1 -1
  30. package/dist/{chunk-U7CMWQ7Z.js → chunk-43OPSFUY.js} +1 -1
  31. package/dist/{chunk-J3S57AXY.js → chunk-44NWPKY3.js} +1 -1
  32. package/dist/{chunk-DW4PMHNW.js → chunk-5LPWHC7Q.js} +148 -87
  33. package/dist/{chunk-QTBKPZDA.js → chunk-5MFCEKR6.js} +19 -3
  34. package/dist/{chunk-GWQSZT4C.js → chunk-6FRAWWGR.js} +2 -2
  35. package/dist/{chunk-MXTVUV3I.js → chunk-6U44QGXL.js} +1 -1
  36. package/dist/{chunk-IIESAYDL.js → chunk-7ULXCNOZ.js} +17 -8
  37. package/dist/{chunk-AEQISMMU.js → chunk-A2O7SGK5.js} +15 -17
  38. package/dist/{chunk-75I3UBIL.js → chunk-BBLO66XT.js} +29 -29
  39. package/dist/{chunk-WQRX57EA.js → chunk-DBKS7JR2.js} +3 -3
  40. package/dist/{chunk-U27DSXKB.js → chunk-DK3GQWJK.js} +6 -6
  41. package/dist/{chunk-5GSZWRE2.js → chunk-DKH4WGZU.js} +8 -8
  42. package/dist/{chunk-6SU2DT27.js → chunk-DVIJ6DP6.js} +2 -2
  43. package/dist/{chunk-6OHTDR4F.js → chunk-EYD523BV.js} +1 -1
  44. package/dist/{chunk-4V4QIYJH.js → chunk-FWXSPJRN.js} +1 -1
  45. package/dist/{chunk-G52UXKGO.js → chunk-FZFJZZR3.js} +4 -4
  46. package/dist/{chunk-WZH4JV7R.js → chunk-H4WNQFBH.js} +5 -5
  47. package/dist/{chunk-CDQ4YIZM.js → chunk-HLXXQI5Q.js} +55 -1
  48. package/dist/{chunk-3T2JAGRH.js → chunk-HN4UZTG7.js} +2 -2
  49. package/dist/{chunk-MXVD2BDS.js → chunk-HQAFIN6O.js} +1 -1
  50. package/dist/{chunk-J6EJQCHY.js → chunk-LIVSCWI5.js} +15 -15
  51. package/dist/{chunk-CXH25EL4.js → chunk-LMGKSDO4.js} +1 -1
  52. package/dist/{chunk-MQ5RYATN.js → chunk-NFL4FRIU.js} +4 -4
  53. package/dist/{chunk-C2N6MNO4.js → chunk-OFQBDHVG.js} +1 -1
  54. package/dist/{chunk-ZYQSPQYR.js → chunk-OHO46E7F.js} +50 -19
  55. package/dist/{chunk-YGZ2OLXL.js → chunk-PGJUJCOQ.js} +1 -1
  56. package/dist/{chunk-PJW6U46K.js → chunk-PIQKV7IR.js} +212 -149
  57. package/dist/{chunk-2ECYPYKP.js → chunk-UFEU4UX6.js} +1 -1
  58. package/dist/{chunk-ZQCGQMF2.js → chunk-UONUDOJP.js} +7 -7
  59. package/dist/{chunk-YCTDA7BD.js → chunk-YWM6MJT4.js} +1 -1
  60. package/dist/cli/chat.js +31 -31
  61. package/dist/cli/check.js +6 -6
  62. package/dist/cli/plugins.js +13 -13
  63. package/dist/cli/snapshot-create.js +9 -9
  64. package/dist/cli/upgrade.js +7 -7
  65. package/dist/{db-UXPPGHDF.js → db-PSMQZR4P.js} +7 -7
  66. package/dist/instrumentation.js +4 -4
  67. package/dist/nitro.js +2 -2
  68. package/dist/{oauth-callback-server-4ZYMD5UA.js → oauth-callback-server-XZUK2AT6.js} +22 -22
  69. package/dist/{runner-MZSEONRZ.js → runner-5EKJCQWP.js} +14 -14
  70. package/dist/{skills-IMVPXSQ7.js → skills-2PRM42SE.js} +6 -6
  71. package/dist/spawn-UGTLRTFP.js +38 -0
  72. package/dist/{validation-ZKCY2BVR.js → validation-XLXAIRTR.js} +6 -6
  73. package/dist/version.js +1 -1
  74. package/dist/{work-GG3XDYRX.js → work-CNTNEQ2Q.js} +17 -17
  75. package/dist/{worker-23AUELCJ.js → worker-BGW7CKZ7.js} +10 -10
  76. package/package.json +5 -5
  77. package/dist/spawn-S5LSVOCE.js +0 -38
@@ -1,22 +1,25 @@
1
1
  import {
2
2
  ToolInputError
3
- } from "./chunk-CDQ4YIZM.js";
3
+ } from "./chunk-HLXXQI5Q.js";
4
4
  import {
5
5
  canRouteResourceEvents,
6
6
  getPlugins
7
- } from "./chunk-IIESAYDL.js";
7
+ } from "./chunk-7ULXCNOZ.js";
8
8
  import {
9
9
  getDb
10
- } from "./chunk-QTBKPZDA.js";
10
+ } from "./chunk-5MFCEKR6.js";
11
11
  import {
12
12
  juniorEventTasks,
13
13
  juniorSchedulerRuns,
14
14
  juniorSchedulerTasks,
15
15
  juniorStats
16
- } from "./chunk-UDBUS533.js";
16
+ } from "./chunk-3H42HMA2.js";
17
17
  import {
18
18
  juniorDestinations
19
19
  } from "./chunk-VFUK3X5B.js";
20
+ import {
21
+ logInfo
22
+ } from "./chunk-UFEU4UX6.js";
20
23
 
21
24
  // src/chat/event-tasks/store.ts
22
25
  import { and, asc, desc, eq, inArray, or, sql } from "drizzle-orm";
@@ -698,6 +701,41 @@ function getNextRunAtMs(task, scheduledForMs, afterMs = scheduledForMs) {
698
701
  });
699
702
  }
700
703
 
704
+ // src/chat/scheduled-tasks/telemetry.ts
705
+ function scheduledTaskAttributes(task, extras = {}) {
706
+ return {
707
+ "app.task.id": task.id,
708
+ "app.task.type": "scheduled",
709
+ "app.task.status": task.status,
710
+ "app.task.schedule.kind": task.schedule.kind,
711
+ "app.task.schedule.timezone": task.schedule.timezone,
712
+ "app.task.credential_mode": task.credentialMode,
713
+ "app.task.destination.channel_id": task.destination.channelId,
714
+ "app.task.destination.team_id": task.destination.teamId,
715
+ "app.task.destination.visibility": task.conversationAccess.visibility,
716
+ "app.task.destination.audience": task.conversationAccess.audience,
717
+ "messaging.destination.name": task.destination.channelId,
718
+ ...typeof task.nextRunAtMs === "number" ? { "app.task.next_run_at": new Date(task.nextRunAtMs).toISOString() } : {},
719
+ ...extras
720
+ };
721
+ }
722
+ function scheduledTaskRunAttributes(task, run, extras = {}) {
723
+ return scheduledTaskAttributes(task, {
724
+ "app.task.run.id": run.id,
725
+ "app.task.run.status": run.status,
726
+ "app.task.run.scheduled_for": new Date(run.scheduledForMs).toISOString(),
727
+ ...run.dispatchId ? { "app.dispatch.id": run.dispatchId } : {},
728
+ ...run.resultMessageTs ? { "app.task.result_message_ts": run.resultMessageTs } : {},
729
+ ...extras
730
+ });
731
+ }
732
+ function logScheduledTaskRunSkipped(task, run, extras = {}) {
733
+ logInfo(
734
+ "scheduled_task.run.skipped",
735
+ scheduledTaskRunAttributes(task, run, extras)
736
+ );
737
+ }
738
+
701
739
  // src/chat/scheduled-tasks/types.ts
702
740
  import { z as z5 } from "zod";
703
741
  var scheduledTaskCredentialModeSchema = z5.enum(["system", "creator"]);
@@ -762,7 +800,7 @@ var taskRecordFields = {
762
800
  schedule: taskScheduleSchema,
763
801
  // TODO(v0.131.0): Remove paused decoding and SQL list filtering after
764
802
  // v0.129.x workers can no longer overlap upgrades.
765
- status: z6.enum(["active", "blocked", "deleted", "paused"]),
803
+ status: z6.enum(["active", "blocked", "completed", "deleted", "paused"]),
766
804
  statusReason: z6.string().optional(),
767
805
  task: taskSpecSchema,
768
806
  updatedAtMs: z6.number(),
@@ -814,12 +852,15 @@ function buildRunId(taskId, scheduledForMs) {
814
852
  }
815
853
  var schedulerTaskIndexSchema = z6.array(z6.string().min(1));
816
854
  function statusAfterTerminalOccurrence(args) {
817
- if (args.blocked) {
855
+ if (args.blocked || args.outcome === "blocked") {
818
856
  return "blocked";
819
857
  }
820
858
  if (args.nextRunAtMs) {
821
859
  return args.previousStatus ?? "active";
822
860
  }
861
+ if (args.outcome === "completed") {
862
+ return "completed";
863
+ }
823
864
  return "deleted";
824
865
  }
825
866
  function isStalePendingRun(run, nowMs) {
@@ -1110,7 +1151,11 @@ async function listPublicScheduledTasksForTeams(db, teamIds, limit) {
1110
1151
  ).where(
1111
1152
  and3(
1112
1153
  inArray2(juniorSchedulerTasks.teamId, teamIds),
1113
- notInArray(juniorSchedulerTasks.status, ["deleted", "paused"]),
1154
+ notInArray(juniorSchedulerTasks.status, [
1155
+ "completed",
1156
+ "deleted",
1157
+ "paused"
1158
+ ]),
1114
1159
  eq2(juniorDestinations.visibility, "public")
1115
1160
  )
1116
1161
  ).orderBy(
@@ -1184,99 +1229,111 @@ var SqlSchedulerStore = class {
1184
1229
  return await listTasksForTeamFromSql(this.db, teamId);
1185
1230
  }
1186
1231
  async claimDueRun(args) {
1187
- return await withSqlLock(this.db, "junior:scheduler:claim", async (db) => {
1188
- const rows = await db.select({
1189
- creatorIdentityId: juniorSchedulerTasks.creatorIdentityId,
1190
- record: juniorSchedulerTasks.record
1191
- }).from(juniorSchedulerTasks).where(
1192
- and3(
1193
- eq2(juniorSchedulerTasks.status, "active"),
1194
- or2(
1195
- and3(
1196
- isNotNull(juniorSchedulerTasks.runNowAtMs),
1197
- lte2(juniorSchedulerTasks.runNowAtMs, args.nowMs)
1198
- ),
1199
- and3(
1200
- isNotNull(juniorSchedulerTasks.nextRunAtMs),
1201
- lte2(juniorSchedulerTasks.nextRunAtMs, args.nowMs)
1232
+ const skippedRuns = [];
1233
+ const claimed = await withSqlLock(
1234
+ this.db,
1235
+ "junior:scheduler:claim",
1236
+ async (db) => {
1237
+ const rows = await db.select({
1238
+ creatorIdentityId: juniorSchedulerTasks.creatorIdentityId,
1239
+ record: juniorSchedulerTasks.record
1240
+ }).from(juniorSchedulerTasks).where(
1241
+ and3(
1242
+ eq2(juniorSchedulerTasks.status, "active"),
1243
+ or2(
1244
+ and3(
1245
+ isNotNull(juniorSchedulerTasks.runNowAtMs),
1246
+ lte2(juniorSchedulerTasks.runNowAtMs, args.nowMs)
1247
+ ),
1248
+ and3(
1249
+ isNotNull(juniorSchedulerTasks.nextRunAtMs),
1250
+ lte2(juniorSchedulerTasks.nextRunAtMs, args.nowMs)
1251
+ )
1202
1252
  )
1203
1253
  )
1204
- )
1205
- ).orderBy(
1206
- asc3(juniorSchedulerTasks.createdAtMs),
1207
- asc3(juniorSchedulerTasks.id)
1208
- );
1209
- for (const row of rows) {
1210
- const task = parseSqlTaskRow(row);
1211
- if (!task) {
1212
- continue;
1213
- }
1214
- const scheduledForMs = getDueRunAtMs(task, args.nowMs);
1215
- if (scheduledForMs === void 0) {
1216
- continue;
1217
- }
1218
- const runId = buildRunId(task.id, scheduledForMs);
1219
- const incompleteRuns = await listIncompleteRunsForTasksFromSql(db, [
1220
- task
1221
- ]);
1222
- const incompleteRun = incompleteRuns.find((run2) => run2.id === runId);
1223
- const blockingRun = incompleteRuns.find(
1224
- (run2) => run2.id !== runId && !isStalePendingRun(run2, args.nowMs)
1254
+ ).orderBy(
1255
+ asc3(juniorSchedulerTasks.createdAtMs),
1256
+ asc3(juniorSchedulerTasks.id)
1225
1257
  );
1226
- if (blockingRun) {
1227
- continue;
1228
- }
1229
- if (incompleteRun) {
1230
- if (!isStalePendingRun(incompleteRun, args.nowMs)) {
1258
+ for (const row of rows) {
1259
+ const task = parseSqlTaskRow(row);
1260
+ if (!task) {
1231
1261
  continue;
1232
1262
  }
1233
- const reclaimed = {
1234
- ...incompleteRun,
1235
- attempt: incompleteRun.attempt + 1,
1236
- claimedAtMs: args.nowMs
1237
- };
1238
- await upsertSqlRun(db, reclaimed);
1239
- return reclaimed;
1240
- }
1241
- const existingRun = await getRunFromSql(db, runId);
1242
- if (existingRun) {
1243
- continue;
1244
- }
1245
- if (isMissedRunTooOld({ nowMs: args.nowMs, scheduledForMs })) {
1246
- await this.skipMissedRun(db, {
1247
- nowMs: args.nowMs,
1263
+ const scheduledForMs = getDueRunAtMs(task, args.nowMs);
1264
+ if (scheduledForMs === void 0) {
1265
+ continue;
1266
+ }
1267
+ const runId = buildRunId(task.id, scheduledForMs);
1268
+ const incompleteRuns = await listIncompleteRunsForTasksFromSql(db, [
1269
+ task
1270
+ ]);
1271
+ const incompleteRun = incompleteRuns.find((run2) => run2.id === runId);
1272
+ const blockingRun = incompleteRuns.find(
1273
+ (run2) => run2.id !== runId && !isStalePendingRun(run2, args.nowMs)
1274
+ );
1275
+ if (blockingRun) {
1276
+ continue;
1277
+ }
1278
+ if (incompleteRun) {
1279
+ if (!isStalePendingRun(incompleteRun, args.nowMs)) {
1280
+ continue;
1281
+ }
1282
+ const reclaimed = {
1283
+ ...incompleteRun,
1284
+ attempt: incompleteRun.attempt + 1,
1285
+ claimedAtMs: args.nowMs
1286
+ };
1287
+ await upsertSqlRun(db, reclaimed);
1288
+ return reclaimed;
1289
+ }
1290
+ const existingRun = await getRunFromSql(db, runId);
1291
+ if (existingRun) {
1292
+ continue;
1293
+ }
1294
+ if (isMissedRunTooOld({ nowMs: args.nowMs, scheduledForMs })) {
1295
+ const skipped = await this.skipMissedRun(db, {
1296
+ nowMs: args.nowMs,
1297
+ scheduledForMs,
1298
+ task
1299
+ });
1300
+ if (skipped) {
1301
+ skippedRuns.push(skipped);
1302
+ }
1303
+ continue;
1304
+ }
1305
+ const run = buildScheduledRun({
1306
+ claimedAtMs: args.nowMs,
1248
1307
  scheduledForMs,
1249
1308
  task
1250
1309
  });
1251
- continue;
1310
+ await upsertSqlRun(db, run);
1311
+ return run;
1252
1312
  }
1253
- const run = buildScheduledRun({
1254
- claimedAtMs: args.nowMs,
1255
- scheduledForMs,
1256
- task
1257
- });
1258
- await upsertSqlRun(db, run);
1259
- return run;
1313
+ return void 0;
1260
1314
  }
1261
- return void 0;
1262
- });
1315
+ );
1316
+ for (const skipped of skippedRuns) {
1317
+ logScheduledTaskRunSkipped(skipped.task, skipped.run, {
1318
+ "app.task.run.error": skipped.errorMessage
1319
+ });
1320
+ }
1321
+ return claimed;
1263
1322
  }
1264
1323
  async skipMissedRun(db, args) {
1265
1324
  const current = await getTaskFromSql(db, args.task.id);
1266
1325
  if (!current || current.status !== "active" || getDueRunAtMs(current, args.nowMs) !== args.scheduledForMs) {
1267
- return;
1326
+ return void 0;
1268
1327
  }
1269
1328
  const duplicateOf = await this.findStaleRecoveryCanonicalTask(db, current);
1270
1329
  const errorMessage = duplicateOf ? `Duplicate stale scheduled task was skipped without dispatch. Canonical task: ${duplicateOf.id}.` : "Scheduled occurrence was more than 24 hours late and was skipped without dispatch.";
1271
- await upsertSqlRun(
1272
- db,
1273
- buildSkippedScheduledRun({
1274
- completedAtMs: args.nowMs,
1275
- errorMessage,
1276
- scheduledForMs: args.scheduledForMs,
1277
- task: current
1278
- })
1279
- );
1330
+ const skipped = buildSkippedScheduledRun({
1331
+ completedAtMs: args.nowMs,
1332
+ errorMessage,
1333
+ scheduledForMs: args.scheduledForMs,
1334
+ task: current
1335
+ });
1336
+ await upsertSqlRun(db, skipped);
1280
1337
  const isRunNow = current.runNowAtMs === args.scheduledForMs;
1281
1338
  let nextRunAtMs;
1282
1339
  if (!duplicateOf) {
@@ -1295,6 +1352,7 @@ var SqlSchedulerStore = class {
1295
1352
  },
1296
1353
  current
1297
1354
  );
1355
+ return { errorMessage, run: skipped, task: current };
1298
1356
  }
1299
1357
  async findStaleRecoveryCanonicalTask(db, task) {
1300
1358
  const fingerprint = taskDedupeFingerprint(task);
@@ -1374,7 +1432,7 @@ var SqlSchedulerStore = class {
1374
1432
  async updateTaskAfterRun(args) {
1375
1433
  await withSqlLock(this.db, taskLockKey(args.run.taskId), async (db) => {
1376
1434
  const current = await getTaskFromSql(db, args.run.taskId);
1377
- if (!current || current.status === "deleted") {
1435
+ if (!current || current.status === "deleted" || current.status === "completed") {
1378
1436
  return;
1379
1437
  }
1380
1438
  const isRunNow = current.runNowAtMs === args.run.scheduledForMs;
@@ -1395,8 +1453,8 @@ var SqlSchedulerStore = class {
1395
1453
  nextRunAtMs: nextRunAtMs2,
1396
1454
  runNowAtMs: void 0,
1397
1455
  status: statusAfterTerminalOccurrence({
1398
- blocked: args.status === "blocked",
1399
1456
  nextRunAtMs: nextRunAtMs2,
1457
+ outcome: args.status,
1400
1458
  previousStatus: current.status
1401
1459
  }),
1402
1460
  statusReason: args.status === "blocked" ? args.errorMessage : void 0,
@@ -1426,8 +1484,8 @@ var SqlSchedulerStore = class {
1426
1484
  lastRunAtMs: args.run.scheduledForMs,
1427
1485
  nextRunAtMs,
1428
1486
  status: statusAfterTerminalOccurrence({
1429
- blocked: args.status === "blocked",
1430
- nextRunAtMs
1487
+ nextRunAtMs,
1488
+ outcome: args.status
1431
1489
  }),
1432
1490
  statusReason: args.status === "blocked" ? args.errorMessage : void 0,
1433
1491
  updatedAtMs: args.nowMs
@@ -1491,6 +1549,9 @@ export {
1491
1549
  getZonedDateTimeParts,
1492
1550
  resolveLocalScheduleAtMs,
1493
1551
  getFirstRunAtMs,
1552
+ scheduledTaskAttributes,
1553
+ scheduledTaskRunAttributes,
1554
+ logScheduledTaskRunSkipped,
1494
1555
  SCHEDULED_TASK_SYSTEM_ACTOR,
1495
1556
  listPublicScheduledTasksForTeams,
1496
1557
  createSchedulerSqlStore,
@@ -5,12 +5,12 @@ import {
5
5
  juniorConversations,
6
6
  juniorIdentities,
7
7
  juniorUsers
8
- } from "./chunk-UDBUS533.js";
8
+ } from "./chunk-3H42HMA2.js";
9
9
  import {
10
10
  TURN_REASONING_LEVELS,
11
11
  getChatConfig,
12
12
  modelProfileSchema
13
- } from "./chunk-75I3UBIL.js";
13
+ } from "./chunk-BBLO66XT.js";
14
14
  import {
15
15
  juniorDestinations
16
16
  } from "./chunk-VFUK3X5B.js";
@@ -20,7 +20,7 @@ import {
20
20
  } from "./chunk-F3B2YJ76.js";
21
21
  import {
22
22
  normalizeIdentityEmail
23
- } from "./chunk-2ECYPYKP.js";
23
+ } from "./chunk-UFEU4UX6.js";
24
24
 
25
25
  // src/chat/conversations/sql/store.ts
26
26
  import { randomUUID as randomUUID2 } from "crypto";
@@ -452,6 +452,11 @@ function conversationFromRow(readRow) {
452
452
  lastActivityAtMs: requiredMsFromDate(row.lastActivityAt),
453
453
  updatedAtMs: requiredMsFromDate(row.updatedAt),
454
454
  execution,
455
+ executionMetrics: {
456
+ durationMs: row.executionDurationMs,
457
+ ...row.metricRunId ? { runId: row.metricRunId } : {},
458
+ ...row.executionUsage ? { usage: row.executionUsage } : {}
459
+ },
455
460
  ...row.parentConversationId ? {
456
461
  lineage: {
457
462
  parentConversationId: row.parentConversationId
@@ -1479,6 +1484,17 @@ var SqlConversationEventStore = class {
1479
1484
  ).orderBy(asc2(juniorConversationEvents.seq));
1480
1485
  return rows.map(eventFromRow);
1481
1486
  }
1487
+ async loadLatestStructuredEvent(conversationId, namespace, name) {
1488
+ const [row] = await this.executor.db().select().from(juniorConversationEvents).where(
1489
+ and4(
1490
+ eq4(juniorConversationEvents.conversationId, conversationId),
1491
+ eq4(juniorConversationEvents.type, "structured_event"),
1492
+ sql4`${juniorConversationEvents.payload}->>'namespace' = ${namespace}`,
1493
+ sql4`${juniorConversationEvents.payload}->>'name' = ${name}`
1494
+ )
1495
+ ).orderBy(desc2(juniorConversationEvents.seq)).limit(1);
1496
+ return row ? eventFromRow(row) : void 0;
1497
+ }
1482
1498
  async loadLatestInstruction(conversationId) {
1483
1499
  const [row] = await this.executor.db().select().from(juniorConversationEvents).where(
1484
1500
  and4(
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-6OHTDR4F.js";
3
+ } from "./chunk-EYD523BV.js";
4
4
  import {
5
5
  logWarn
6
- } from "./chunk-2ECYPYKP.js";
6
+ } from "./chunk-UFEU4UX6.js";
7
7
  import {
8
8
  skillRoots
9
9
  } from "./chunk-H4HBKISO.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getChatConfig
3
- } from "./chunk-75I3UBIL.js";
3
+ } from "./chunk-BBLO66XT.js";
4
4
 
5
5
  // src/chat/state/adapter.ts
6
6
  import { createMemoryState } from "@chat-adapter/state-memory";
@@ -4,30 +4,30 @@ import {
4
4
  isConversationScopedChannel,
5
5
  isDmChannel,
6
6
  normalizeSlackConversationId
7
- } from "./chunk-6SU2DT27.js";
7
+ } from "./chunk-DVIJ6DP6.js";
8
8
  import {
9
9
  getConversationEventStore,
10
10
  getDb
11
- } from "./chunk-QTBKPZDA.js";
11
+ } from "./chunk-5MFCEKR6.js";
12
12
  import {
13
13
  juniorConversationAnnotations,
14
14
  juniorConversationEvents,
15
15
  juniorIdentities,
16
16
  juniorUsers
17
- } from "./chunk-UDBUS533.js";
17
+ } from "./chunk-3H42HMA2.js";
18
18
  import {
19
19
  SANDBOX_WORKSPACE_ROOT
20
20
  } from "./chunk-EM225ITJ.js";
21
21
  import {
22
22
  getStateAdapter
23
- } from "./chunk-MXTVUV3I.js";
23
+ } from "./chunk-6U44QGXL.js";
24
24
  import {
25
25
  botConfig,
26
26
  completeObject,
27
27
  embedTexts,
28
28
  getSlackBotToken,
29
29
  standardModelId
30
- } from "./chunk-75I3UBIL.js";
30
+ } from "./chunk-BBLO66XT.js";
31
31
  import {
32
32
  isActorUserId,
33
33
  parseActorUserId
@@ -42,7 +42,7 @@ import {
42
42
  logInfo,
43
43
  logWarn,
44
44
  normalizeIdentityEmail
45
- } from "./chunk-2ECYPYKP.js";
45
+ } from "./chunk-UFEU4UX6.js";
46
46
 
47
47
  // src/chat/plugins/agent-hooks.ts
48
48
  import {
@@ -416,7 +416,7 @@ function setDashboardConversationLinkOptions(options) {
416
416
  dashboardConversationLinkOptions = options?.disabled ? void 0 : options;
417
417
  return previous;
418
418
  }
419
- function getDashboardConversationLink(conversationId) {
419
+ function resolveDashboardPath(segmentPath) {
420
420
  if (!dashboardConversationLinkOptions) {
421
421
  return void 0;
422
422
  }
@@ -425,9 +425,17 @@ function getDashboardConversationLink(conversationId) {
425
425
  dashboardConversationLinkOptions.basePath,
426
426
  "/"
427
427
  );
428
- const path = basePath === "/" ? `/conversations/${encodeURIComponent(conversationId)}` : `${basePath}/conversations/${encodeURIComponent(conversationId)}`;
428
+ const path = basePath === "/" ? segmentPath : `${basePath}${segmentPath}`;
429
429
  return `${baseURL}${path}`;
430
430
  }
431
+ function getDashboardConversationLink(conversationId) {
432
+ return resolveDashboardPath(
433
+ `/conversations/${encodeURIComponent(conversationId)}`
434
+ );
435
+ }
436
+ function getDashboardTaskLink(taskId) {
437
+ return resolveDashboardPath(`/tasks/${encodeURIComponent(taskId)}`);
438
+ }
431
439
 
432
440
  // src/chat/resource-events/workspace.ts
433
441
  function canRouteResourceEvents() {
@@ -1803,6 +1811,7 @@ export {
1803
1811
  createPluginState,
1804
1812
  setDashboardConversationLinkOptions,
1805
1813
  getDashboardConversationLink,
1814
+ getDashboardTaskLink,
1806
1815
  canRouteResourceEvents,
1807
1816
  createResourceEventTeamIdResolver,
1808
1817
  getSlackToolContext,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  appendAndEnqueueInboundMessage
3
- } from "./chunk-MQ5RYATN.js";
3
+ } from "./chunk-NFL4FRIU.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-WZH4JV7R.js";
15
+ } from "./chunk-H4WNQFBH.js";
16
16
  import {
17
17
  TurnInputCommitLostError,
18
18
  coerceThreadArtifactsState,
@@ -28,16 +28,20 @@ import {
28
28
  persistCompletedSessionRecord,
29
29
  persistThreadStateById,
30
30
  persistYieldSessionRecord
31
- } from "./chunk-PJW6U46K.js";
31
+ } from "./chunk-PIQKV7IR.js";
32
32
  import {
33
33
  getConversationEventStore,
34
34
  getConversationStore,
35
35
  getSqlExecutor
36
- } from "./chunk-QTBKPZDA.js";
36
+ } from "./chunk-5MFCEKR6.js";
37
37
  import {
38
38
  juniorAgentBindings,
39
39
  juniorAgentInvocations
40
- } from "./chunk-UDBUS533.js";
40
+ } from "./chunk-3H42HMA2.js";
41
+ import {
42
+ botConfig,
43
+ modelIdForProfile
44
+ } from "./chunk-BBLO66XT.js";
41
45
 
42
46
  // src/chat/agent-invocations/work.ts
43
47
  import { z } from "zod";
@@ -427,24 +431,18 @@ async function recoverRunningSession(invocation) {
427
431
  if (!session || session.state !== "running") {
428
432
  return;
429
433
  }
430
- if (!session.modelId) {
431
- await failAgentTurnSessionRecord({
432
- conversationId: invocation.childConversationId,
433
- expectedVersion: session.version,
434
- sessionId: session.sessionId,
435
- errorMessage: `Running agent invocation session is missing its model for ${invocation.invocationId}`
436
- });
437
- return;
438
- }
434
+ const projection = await openConversationProjection({
435
+ conversationId: invocation.childConversationId
436
+ });
439
437
  const parked = await persistYieldSessionRecord({
440
438
  conversationId: invocation.childConversationId,
441
439
  currentSliceId: session.sliceId,
442
440
  errorMessage: "Recovered running agent invocation after worker loss",
443
441
  messages: session.piMessages,
444
- modelId: session.modelId,
445
- // Execution actor lives on the parent invocation record, not Redis.
442
+ modelId: modelIdForProfile(botConfig, projection.modelProfile),
443
+ // Execution actor and reasoning live on the parent invocation, not Redis.
446
444
  actor: invocation.actor,
447
- reasoningLevel: session.reasoningLevel,
445
+ reasoningLevel: invocation.reasoningLevel,
448
446
  sessionId: session.sessionId,
449
447
  surface: session.surface
450
448
  });
@@ -3,7 +3,7 @@ import {
3
3
  toCanonicalInputMessage,
4
4
  toCanonicalOutputMessage,
5
5
  toGenAiMessagesTraceAttributes
6
- } from "./chunk-YGZ2OLXL.js";
6
+ } from "./chunk-PGJUJCOQ.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-2ECYPYKP.js";
14
+ } from "./chunk-UFEU4UX6.js";
15
15
 
16
16
  // src/chat/services/provider-error.ts
17
17
  var ProviderError = class extends Error {
@@ -195,6 +195,31 @@ function getProviderErrorAttributes(error) {
195
195
  };
196
196
  }
197
197
 
198
+ // src/chat/model-profile.ts
199
+ import { z } from "zod";
200
+ var STANDARD_MODEL_PROFILE = "standard";
201
+ var DEFAULT_HANDOFF_MODEL_PROFILE = "handoff";
202
+ var modelProfileSchema = z.string().regex(/^[a-z][a-z0-9_-]*$/);
203
+ var ModelProfileNotConfiguredError = class extends Error {
204
+ constructor(profile) {
205
+ super(`Model profile "${profile}" is not configured`);
206
+ this.name = "ModelProfileNotConfiguredError";
207
+ }
208
+ };
209
+ function modelIdForProfile(config, profile) {
210
+ return profileConfig(config, profile).modelId;
211
+ }
212
+ function standardModelId(config) {
213
+ return modelIdForProfile(config, STANDARD_MODEL_PROFILE);
214
+ }
215
+ function profileConfig(config, profile) {
216
+ const profileConfig2 = Object.hasOwn(config.profiles, profile) ? config.profiles[profile] : void 0;
217
+ if (!profileConfig2) {
218
+ throw new ModelProfileNotConfiguredError(profile);
219
+ }
220
+ return profileConfig2;
221
+ }
222
+
198
223
  // src/chat/config.ts
199
224
  import { getModel as getModel2 } from "@earendil-works/pi-ai/compat";
200
225
 
@@ -652,7 +677,7 @@ function normalizeSlackEmojiName(value) {
652
677
  }
653
678
 
654
679
  // src/chat/reasoning-level.ts
655
- import { z } from "zod";
680
+ import { z as z2 } from "zod";
656
681
  var TURN_REASONING_LEVELS = [
657
682
  "none",
658
683
  "low",
@@ -661,32 +686,7 @@ var TURN_REASONING_LEVELS = [
661
686
  "xhigh"
662
687
  ];
663
688
  function parseTurnReasoningLevel(value) {
664
- return z.enum(TURN_REASONING_LEVELS).parse(value);
665
- }
666
-
667
- // src/chat/model-profile.ts
668
- import { z as z2 } from "zod";
669
- var STANDARD_MODEL_PROFILE = "standard";
670
- var DEFAULT_HANDOFF_MODEL_PROFILE = "handoff";
671
- var modelProfileSchema = z2.string().regex(/^[a-z][a-z0-9_-]*$/);
672
- var ModelProfileNotConfiguredError = class extends Error {
673
- constructor(profile) {
674
- super(`Model profile "${profile}" is not configured`);
675
- this.name = "ModelProfileNotConfiguredError";
676
- }
677
- };
678
- function modelIdForProfile(config, profile) {
679
- return profileConfig(config, profile).modelId;
680
- }
681
- function standardModelId(config) {
682
- return modelIdForProfile(config, STANDARD_MODEL_PROFILE);
683
- }
684
- function profileConfig(config, profile) {
685
- const profileConfig2 = Object.hasOwn(config.profiles, profile) ? config.profiles[profile] : void 0;
686
- if (!profileConfig2) {
687
- throw new ModelProfileNotConfiguredError(profile);
688
- }
689
- return profileConfig2;
689
+ return z2.enum(TURN_REASONING_LEVELS).parse(value);
690
690
  }
691
691
 
692
692
  // src/chat/config.ts