@sentry/junior 0.94.0 → 0.96.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 (127) hide show
  1. package/dist/{agent-hooks-ZG7IDOIN.js → agent-hooks-5URSMY3O.js} +10 -11
  2. package/dist/api/people/list.js +8 -8
  3. package/dist/api/people/profile.js +8 -8
  4. package/dist/api/people/shared.d.ts +2 -2
  5. package/dist/api-reference.d.ts +2 -2
  6. package/dist/app.js +434 -199
  7. package/dist/{catalog-runtime-NZHMSMYC.js → catalog-runtime-MSMAYYIK.js} +4 -4
  8. package/dist/chat/advisor-request.d.ts +4 -0
  9. package/dist/chat/agent/request.d.ts +2 -0
  10. package/dist/chat/agent/resume.d.ts +2 -0
  11. package/dist/chat/conversations/history.d.ts +128 -0
  12. package/dist/chat/conversations/legacy-import.d.ts +38 -0
  13. package/dist/chat/conversations/messages.d.ts +39 -0
  14. package/dist/chat/conversations/projection.d.ts +94 -0
  15. package/dist/chat/conversations/retention.d.ts +36 -0
  16. package/dist/chat/conversations/sql/conversation-row.d.ts +14 -0
  17. package/dist/chat/conversations/sql/history.d.ts +4 -0
  18. package/dist/chat/conversations/sql/legacy-history-import.d.ts +55 -0
  19. package/dist/chat/conversations/sql/messages.d.ts +4 -0
  20. package/dist/chat/conversations/sql/migrations.d.ts +14 -3
  21. package/dist/chat/conversations/sql/purge.d.ts +53 -0
  22. package/dist/chat/conversations/sql/store.d.ts +7 -2
  23. package/dist/chat/conversations/store.d.ts +19 -0
  24. package/dist/chat/conversations/visible-compactions.d.ts +11 -0
  25. package/dist/chat/conversations/visible-messages.d.ts +47 -0
  26. package/dist/chat/db.d.ts +12 -1
  27. package/dist/chat/identities/sql.d.ts +1 -1
  28. package/dist/chat/logging.d.ts +4 -3
  29. package/dist/chat/plugins/auth/oauth-request.d.ts +2 -0
  30. package/dist/chat/resource-events/notification.d.ts +2 -0
  31. package/dist/chat/resource-events/store.d.ts +2 -1
  32. package/dist/chat/runtime/agent-run-outcome.d.ts +3 -0
  33. package/dist/chat/runtime/reply-executor.d.ts +8 -0
  34. package/dist/chat/runtime/thread-state.d.ts +2 -0
  35. package/dist/chat/sandbox/resources.d.ts +4 -0
  36. package/dist/chat/sentry.d.ts +1 -1
  37. package/dist/chat/services/mcp-auth-orchestration.d.ts +8 -0
  38. package/dist/chat/services/plugin-auth-orchestration.d.ts +12 -0
  39. package/dist/chat/services/turn-session-record.d.ts +14 -2
  40. package/dist/chat/sleep.d.ts +2 -0
  41. package/dist/chat/state/conversation.d.ts +7 -4
  42. package/dist/chat/state/session-log.d.ts +23 -1
  43. package/dist/chat/state/turn-session.d.ts +9 -1
  44. package/dist/chat/tool-support/private-trace-result.d.ts +4 -0
  45. package/dist/chat/tool-support/zod-tool.d.ts +1 -0
  46. package/dist/chat/tools/advisor/tool.d.ts +9 -4
  47. package/dist/chat/tools/definition.d.ts +2 -0
  48. package/dist/chat/tools/execution/tool-error-handler.d.ts +2 -2
  49. package/dist/chat/tools/system-time.d.ts +8 -0
  50. package/dist/chat/usage.d.ts +27 -13
  51. package/dist/chat/xml.d.ts +2 -0
  52. package/dist/{chunk-TNUUATT7.js → chunk-2NAZZPPS.js} +2 -2
  53. package/dist/{chunk-NYWPISSO.js → chunk-2XXEKR44.js} +1 -1
  54. package/dist/chunk-5C6XTTFI.js +1037 -0
  55. package/dist/{chunk-3DA7X2U3.js → chunk-6GWA276C.js} +15 -0
  56. package/dist/{chunk-LFLTJQVR.js → chunk-7FBGKXPE.js} +4 -0
  57. package/dist/{chunk-LNCREA5Z.js → chunk-AAZXTVJT.js} +4 -128
  58. package/dist/{chunk-GHGPTPBL.js → chunk-B7PUBQQM.js} +1 -1
  59. package/dist/{chunk-6H4PP63X.js → chunk-BYZWPRJA.js} +24 -14
  60. package/dist/chunk-CM5EZD5F.js +17 -0
  61. package/dist/{chunk-G3E7SCME.js → chunk-CZEX6KIQ.js} +23 -0
  62. package/dist/{chunk-YJ4OPVNA.js → chunk-DZENG5ML.js} +1 -1
  63. package/dist/{chunk-QGEWC27H.js → chunk-GQ3GK22G.js} +5 -7
  64. package/dist/{chunk-YYBX2BD5.js → chunk-GY34VGP5.js} +1 -1
  65. package/dist/{chunk-S6QKIGRM.js → chunk-I35CTGPO.js} +71 -29
  66. package/dist/{chunk-KRMANDHI.js → chunk-IYM2SIVG.js} +1489 -355
  67. package/dist/{chunk-BTH37NCU.js → chunk-L7CDEIVJ.js} +12 -4
  68. package/dist/chunk-MNTINMWR.js +865 -0
  69. package/dist/{chunk-MAVOJ54A.js → chunk-P3YFQLEN.js} +25 -388
  70. package/dist/{chunk-YTNPU7I2.js → chunk-PMNN6ST4.js} +2 -2
  71. package/dist/{chunk-PFXC67GJ.js → chunk-RAIB6WSG.js} +6 -80
  72. package/dist/{chunk-NFXSLTYG.js → chunk-RITD7E5L.js} +864 -62
  73. package/dist/{chunk-UUB3D2XI.js → chunk-S5KZ5LPG.js} +8 -10
  74. package/dist/{chunk-HDNWZMUN.js → chunk-UKHVMPX5.js} +112 -103
  75. package/dist/chunk-WM6KHPBQ.js +48 -0
  76. package/dist/{chunk-MC4ZZE4Q.js → chunk-YDT7SNCN.js} +1 -1
  77. package/dist/{chunk-NAPITCZ6.js → chunk-YDVEH3SB.js} +251 -6
  78. package/dist/cli/chat.js +25 -24
  79. package/dist/cli/check.js +5 -5
  80. package/dist/cli/main.js +1 -1
  81. package/dist/cli/plugins.js +12 -13
  82. package/dist/cli/snapshot-warmup.js +8 -9
  83. package/dist/cli/upgrade.js +79 -18
  84. package/dist/db/schema/agent-steps.d.ts +134 -0
  85. package/dist/db/schema/conversation-messages.d.ts +153 -0
  86. package/dist/{chat/conversations/sql → db}/schema/conversations.d.ts +34 -0
  87. package/dist/{chat/conversations/sql → db}/schema.d.ts +319 -8
  88. package/dist/db-2D6RMG67.js +24 -0
  89. package/dist/deployment.d.ts +2 -0
  90. package/dist/handlers/retention.d.ts +6 -0
  91. package/dist/instrumentation.js +17 -4
  92. package/dist/legacy-import-VZ2MEGP7.js +17 -0
  93. package/dist/nitro.js +14 -4
  94. package/dist/reporting/conversations/activity.d.ts +40 -0
  95. package/dist/reporting/conversations/context.d.ts +8 -0
  96. package/dist/reporting/conversations/details.d.ts +6 -0
  97. package/dist/reporting/conversations/index.d.ts +4 -0
  98. package/dist/reporting/conversations/shared.d.ts +9 -0
  99. package/dist/reporting/conversations/statistics.d.ts +4 -0
  100. package/dist/reporting/conversations/summaries.d.ts +20 -0
  101. package/dist/reporting/conversations/transcript.d.ts +28 -0
  102. package/dist/reporting/conversations/types.d.ts +191 -0
  103. package/dist/reporting/conversations.d.ts +1 -178
  104. package/dist/reporting.d.ts +5 -4
  105. package/dist/reporting.js +703 -837
  106. package/dist/{runner-XAZPJNAQ.js → runner-JZBRQP4F.js} +36 -42
  107. package/dist/{sentry-EGFOV3DH.js → sentry-JMWTS32N.js} +11 -1
  108. package/dist/{validation-KYAWETI4.js → validation-6XOOQGME.js} +5 -5
  109. package/migrations/README.md +32 -0
  110. package/migrations/meta/0000_snapshot.json +978 -0
  111. package/migrations/meta/_journal.json +13 -0
  112. package/package.json +10 -7
  113. package/dist/chat/sql/schema.d.ts +0 -1049
  114. package/dist/chat/state/conversation-details.d.ts +0 -47
  115. package/dist/chunk-7STN2ZSK.js +0 -250
  116. package/dist/chunk-LE5ANBUZ.js +0 -1040
  117. package/dist/chunk-QL66APYJ.js +0 -1377
  118. package/dist/db-YDN6AFJH.js +0 -18
  119. /package/dist/{chat/sql → db}/db.d.ts +0 -0
  120. /package/dist/{chat/sql → db}/executor.d.ts +0 -0
  121. /package/dist/{chat/sql → db}/neon.d.ts +0 -0
  122. /package/dist/{chat/sql → db}/postgres.d.ts +0 -0
  123. /package/dist/{chat/conversations/sql → db}/schema/destinations.d.ts +0 -0
  124. /package/dist/{chat/conversations/sql → db}/schema/identities.d.ts +0 -0
  125. /package/dist/{chat/conversations/sql → db}/schema/migrations.d.ts +0 -0
  126. /package/dist/{chat/conversations/sql → db}/schema/timestamps.d.ts +0 -0
  127. /package/dist/{chat/conversations/sql → db}/schema/users.d.ts +0 -0
@@ -0,0 +1,865 @@
1
+ import {
2
+ ensureLegacyConversationImport
3
+ } from "./chunk-5C6XTTFI.js";
4
+ import {
5
+ contextProvenance,
6
+ getAgentStepStore,
7
+ getConversationStore,
8
+ instructionActors,
9
+ instructionProvenanceFor
10
+ } from "./chunk-RITD7E5L.js";
11
+ import {
12
+ getStateAdapter
13
+ } from "./chunk-YDVEH3SB.js";
14
+ import {
15
+ toStoredSlackActor
16
+ } from "./chunk-I35CTGPO.js";
17
+
18
+ // src/chat/conversations/projection.ts
19
+ import { isDeepStrictEqual } from "util";
20
+ function authorizationObservationMessage(entry, createdAtMs) {
21
+ const label = entry.kind === "mcp" ? "MCP authorization" : "Authorization";
22
+ return {
23
+ role: "user",
24
+ content: [
25
+ {
26
+ type: "text",
27
+ text: `${label} completed for provider "${entry.provider}". Continue the blocked request and retry the provider operation if needed.`
28
+ }
29
+ ],
30
+ timestamp: createdAtMs
31
+ };
32
+ }
33
+ function piEntryProvenance(entry) {
34
+ return entry.provenance ?? contextProvenance;
35
+ }
36
+ function projectSteps(steps, opts) {
37
+ const messages = [];
38
+ const provenance = [];
39
+ const seqs = [];
40
+ for (const step of steps) {
41
+ if (opts?.maxSeq !== void 0 && step.seq > opts.maxSeq) {
42
+ break;
43
+ }
44
+ if (step.entry.type === "pi_message") {
45
+ messages.push(step.entry.message);
46
+ provenance.push(piEntryProvenance(step.entry));
47
+ seqs.push(step.seq);
48
+ continue;
49
+ }
50
+ if (step.entry.type === "authorization_completed") {
51
+ messages.push(
52
+ authorizationObservationMessage(step.entry, step.createdAtMs)
53
+ );
54
+ provenance.push(contextProvenance);
55
+ seqs.push(step.seq);
56
+ }
57
+ }
58
+ return { messages, provenance, seqs };
59
+ }
60
+ function connectedMcpProvidersFromSteps(steps) {
61
+ const providers = /* @__PURE__ */ new Set();
62
+ for (const step of steps) {
63
+ if (step.entry.type === "mcp_provider_connected") {
64
+ providers.add(step.entry.provider);
65
+ }
66
+ }
67
+ return [...providers].sort((left, right) => left.localeCompare(right));
68
+ }
69
+ function isUserMessage(message) {
70
+ return message.role === "user";
71
+ }
72
+ function countMatchingPrefix(left, right) {
73
+ const limit = Math.min(left.length, right.length);
74
+ for (let index = 0; index < limit; index += 1) {
75
+ if (!isDeepStrictEqual(left[index], right[index])) {
76
+ return index;
77
+ }
78
+ }
79
+ return limit;
80
+ }
81
+ function resolveCommitProvenance(args) {
82
+ if (args.explicitProvenance) {
83
+ if (args.explicitProvenance.length !== args.nextMessages.length) {
84
+ throw new Error("commit provenance must align one-to-one with messages");
85
+ }
86
+ return args.explicitProvenance;
87
+ }
88
+ const matchingPrefix = args.matchingPrefix;
89
+ const provenance = args.nextMessages.map(
90
+ (_, index) => index < matchingPrefix ? args.existing.provenance[index] ?? contextProvenance : contextProvenance
91
+ );
92
+ if (args.newMessageProvenance) {
93
+ for (let index = args.nextMessages.length - 1; index >= matchingPrefix; index -= 1) {
94
+ if (isUserMessage(args.nextMessages[index])) {
95
+ provenance[index] = args.newMessageProvenance;
96
+ break;
97
+ }
98
+ }
99
+ }
100
+ if (args.trailingMessageProvenance) {
101
+ if (args.trailingMessageProvenance.length > provenance.length) {
102
+ throw new Error(
103
+ "trailing commit provenance cannot exceed committed messages"
104
+ );
105
+ }
106
+ const newMessageCount = args.nextMessages.length - matchingPrefix;
107
+ if (args.trailingMessageProvenance.length > newMessageCount) {
108
+ throw new Error(
109
+ "trailing commit provenance must align to newly committed messages"
110
+ );
111
+ }
112
+ const start = provenance.length - args.trailingMessageProvenance.length;
113
+ args.trailingMessageProvenance.forEach((entry, offset) => {
114
+ provenance[start + offset] = entry;
115
+ });
116
+ }
117
+ return provenance;
118
+ }
119
+ async function importLegacyIfNeeded(args) {
120
+ await ensureLegacyConversationImport({ conversationId: args.conversationId });
121
+ }
122
+ async function loadProjection(args) {
123
+ await importLegacyIfNeeded(args);
124
+ const steps = await getAgentStepStore().loadCurrentEpoch(args.conversationId);
125
+ return projectSteps(steps).messages;
126
+ }
127
+ async function loadProjectionWithProvenance(args) {
128
+ await importLegacyIfNeeded(args);
129
+ const steps = await getAgentStepStore().loadCurrentEpoch(args.conversationId);
130
+ const { messages, provenance } = projectSteps(steps);
131
+ return { messages, provenance };
132
+ }
133
+ async function loadTurnProjection(args) {
134
+ await importLegacyIfNeeded(args);
135
+ const stepStore = getAgentStepStore();
136
+ if (args.committedSeq < 0) {
137
+ return projectSteps(await stepStore.loadCurrentEpoch(args.conversationId));
138
+ }
139
+ const history = await stepStore.loadHistory(args.conversationId);
140
+ const committedStep = history.find((step) => step.seq === args.committedSeq);
141
+ if (!committedStep) {
142
+ return void 0;
143
+ }
144
+ const epochSteps = history.filter(
145
+ (step) => step.contextEpoch === committedStep.contextEpoch
146
+ );
147
+ return args.includeTail ? projectSteps(epochSteps) : projectSteps(epochSteps, { maxSeq: args.committedSeq });
148
+ }
149
+ async function loadConnectedMcpProviders(args) {
150
+ await importLegacyIfNeeded(args);
151
+ const steps = await getAgentStepStore().loadCurrentEpoch(args.conversationId);
152
+ return connectedMcpProvidersFromSteps(steps);
153
+ }
154
+ function messageTimestamp(message) {
155
+ const timestamp = message.timestamp;
156
+ return typeof timestamp === "number" ? timestamp : Date.now();
157
+ }
158
+ async function commitMessages(args) {
159
+ const stepStore = getAgentStepStore();
160
+ const existing = projectSteps(
161
+ await stepStore.loadCurrentEpoch(args.conversationId)
162
+ );
163
+ const matchingPrefix = countMatchingPrefix(existing.messages, args.messages);
164
+ const nextProvenance = resolveCommitProvenance({
165
+ existing,
166
+ nextMessages: args.messages,
167
+ matchingPrefix,
168
+ ...args.provenance ? { explicitProvenance: args.provenance } : {},
169
+ ...args.trailingMessageProvenance ? { trailingMessageProvenance: args.trailingMessageProvenance } : {},
170
+ ...args.newMessageProvenance ? { newMessageProvenance: args.newMessageProvenance } : {}
171
+ });
172
+ if (matchingPrefix === existing.messages.length) {
173
+ const newMessages = args.messages.slice(matchingPrefix);
174
+ await stepStore.append(
175
+ args.conversationId,
176
+ newMessages.map((message, index) => ({
177
+ entry: {
178
+ type: "pi_message",
179
+ message,
180
+ provenance: nextProvenance[matchingPrefix + index]
181
+ },
182
+ createdAtMs: messageTimestamp(message)
183
+ }))
184
+ );
185
+ } else {
186
+ await stepStore.startEpoch(args.conversationId, {
187
+ reason: "rollback",
188
+ messages: args.messages.map((message, index) => ({
189
+ message,
190
+ createdAtMs: messageTimestamp(message),
191
+ provenance: nextProvenance[index]
192
+ }))
193
+ });
194
+ }
195
+ const committed = projectSteps(
196
+ await stepStore.loadCurrentEpoch(args.conversationId)
197
+ );
198
+ return {
199
+ committedSeq: committed.seqs.at(-1) ?? -1,
200
+ messageSeqs: committed.seqs,
201
+ provenance: nextProvenance
202
+ };
203
+ }
204
+ async function recordMcpProviderConnected(args) {
205
+ const stepStore = getAgentStepStore();
206
+ const steps = await stepStore.loadCurrentEpoch(args.conversationId);
207
+ if (connectedMcpProvidersFromSteps(steps).includes(args.provider)) {
208
+ return;
209
+ }
210
+ await stepStore.append(args.conversationId, [
211
+ {
212
+ entry: { type: "mcp_provider_connected", provider: args.provider },
213
+ createdAtMs: Date.now()
214
+ }
215
+ ]);
216
+ }
217
+ async function recordAuthorizationRequested(args) {
218
+ const stepStore = getAgentStepStore();
219
+ const steps = await stepStore.loadCurrentEpoch(args.conversationId);
220
+ if (steps.some(
221
+ (step) => step.entry.type === "authorization_requested" && step.entry.authorizationId === args.authorizationId
222
+ )) {
223
+ return;
224
+ }
225
+ await stepStore.append(args.conversationId, [
226
+ {
227
+ entry: {
228
+ type: "authorization_requested",
229
+ kind: args.kind,
230
+ provider: args.provider,
231
+ actorId: args.actorId,
232
+ authorizationId: args.authorizationId,
233
+ delivery: args.delivery
234
+ },
235
+ createdAtMs: Date.now()
236
+ }
237
+ ]);
238
+ }
239
+ async function recordAuthorizationCompleted(args) {
240
+ const stepStore = getAgentStepStore();
241
+ const steps = await stepStore.loadCurrentEpoch(args.conversationId);
242
+ if (steps.some(
243
+ (step) => step.entry.type === "authorization_completed" && step.entry.authorizationId === args.authorizationId
244
+ )) {
245
+ return;
246
+ }
247
+ await stepStore.append(args.conversationId, [
248
+ {
249
+ entry: {
250
+ type: "authorization_completed",
251
+ kind: args.kind,
252
+ provider: args.provider,
253
+ actorId: args.actorId,
254
+ authorizationId: args.authorizationId
255
+ },
256
+ createdAtMs: Date.now()
257
+ }
258
+ ]);
259
+ }
260
+ async function recordToolExecutionStarted(args) {
261
+ await getAgentStepStore().append(args.conversationId, [
262
+ {
263
+ entry: {
264
+ type: "tool_execution_started",
265
+ toolCallId: args.toolCallId,
266
+ toolName: args.toolName,
267
+ ...args.args !== void 0 ? { args: args.args } : {}
268
+ },
269
+ createdAtMs: args.createdAtMs ?? Date.now()
270
+ }
271
+ ]);
272
+ }
273
+
274
+ // src/chat/usage.ts
275
+ import { z } from "zod";
276
+ var agentTurnCostSchema = z.object({
277
+ input: z.number().finite().nonnegative().optional(),
278
+ output: z.number().finite().nonnegative().optional(),
279
+ cacheRead: z.number().finite().nonnegative().optional(),
280
+ cacheWrite: z.number().finite().nonnegative().optional(),
281
+ total: z.number().finite().nonnegative().optional()
282
+ }).strict();
283
+ var agentTurnUsageSchema = z.object({
284
+ inputTokens: z.number().int().nonnegative().optional(),
285
+ outputTokens: z.number().int().nonnegative().optional(),
286
+ cachedInputTokens: z.number().int().nonnegative().optional(),
287
+ cacheCreationTokens: z.number().int().nonnegative().optional(),
288
+ reasoningTokens: z.number().int().nonnegative().optional(),
289
+ totalTokens: z.number().int().nonnegative().optional(),
290
+ cost: agentTurnCostSchema.optional()
291
+ }).strict();
292
+ var COMPONENT_USAGE_FIELDS = [
293
+ "inputTokens",
294
+ "outputTokens",
295
+ "cachedInputTokens",
296
+ "cacheCreationTokens"
297
+ ];
298
+ var COST_COMPONENT_FIELDS = [
299
+ "input",
300
+ "output",
301
+ "cacheRead",
302
+ "cacheWrite"
303
+ ];
304
+ function hasAgentTurnUsage(usage) {
305
+ return Boolean(
306
+ usage && (Object.entries(usage).some(
307
+ ([field, value]) => field !== "cost" && typeof value === "number" && Number.isFinite(value)
308
+ ) || Object.values(usage.cost ?? {}).some(
309
+ (value) => typeof value === "number" && Number.isFinite(value)
310
+ ))
311
+ );
312
+ }
313
+ function getFiniteCount(value) {
314
+ return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : void 0;
315
+ }
316
+ function getFiniteCost(value) {
317
+ return typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : void 0;
318
+ }
319
+ function addCost(left, right) {
320
+ return Math.round(((left ?? 0) + right) * 1e12) / 1e12;
321
+ }
322
+ function getComponentTotal(usage) {
323
+ let total;
324
+ for (const field of COMPONENT_USAGE_FIELDS) {
325
+ const value = getFiniteCount(usage[field]);
326
+ if (value === void 0) continue;
327
+ total = (total ?? 0) + value;
328
+ }
329
+ return total;
330
+ }
331
+ function addAgentTurnUsage(...usages) {
332
+ const components = {};
333
+ let componentTotal;
334
+ let totalOnlyTokens;
335
+ let reasoningTokens;
336
+ const cost = {};
337
+ for (const usage of usages) {
338
+ if (!usage) continue;
339
+ const reasoning = getFiniteCount(usage.reasoningTokens);
340
+ if (reasoning !== void 0) {
341
+ reasoningTokens = (reasoningTokens ?? 0) + reasoning;
342
+ }
343
+ if (usage.cost) {
344
+ for (const field of [...COST_COMPONENT_FIELDS, "total"]) {
345
+ const value = getFiniteCost(usage.cost[field]);
346
+ if (value === void 0) continue;
347
+ cost[field] = addCost(cost[field], value);
348
+ }
349
+ }
350
+ const usageComponentTotal = getComponentTotal(usage);
351
+ if (usageComponentTotal !== void 0) {
352
+ componentTotal = (componentTotal ?? 0) + usageComponentTotal;
353
+ for (const field of COMPONENT_USAGE_FIELDS) {
354
+ const value = getFiniteCount(usage[field]);
355
+ if (value === void 0) continue;
356
+ components[field] = (components[field] ?? 0) + value;
357
+ }
358
+ continue;
359
+ }
360
+ const totalTokens = getFiniteCount(usage.totalTokens);
361
+ if (totalTokens !== void 0) {
362
+ totalOnlyTokens = (totalOnlyTokens ?? 0) + totalTokens;
363
+ }
364
+ }
365
+ if (totalOnlyTokens !== void 0) {
366
+ return {
367
+ totalTokens: totalOnlyTokens + (componentTotal ?? 0),
368
+ ...reasoningTokens !== void 0 ? { reasoningTokens } : {},
369
+ ...Object.keys(cost).length > 0 ? { cost } : {}
370
+ };
371
+ }
372
+ const result = {
373
+ ...components,
374
+ ...reasoningTokens !== void 0 ? { reasoningTokens } : {},
375
+ ...Object.keys(cost).length > 0 ? { cost } : {}
376
+ };
377
+ return hasAgentTurnUsage(result) ? result : void 0;
378
+ }
379
+
380
+ // src/chat/state/turn-session.ts
381
+ import { THREAD_STATE_TTL_MS } from "chat";
382
+ import {
383
+ actorSchema,
384
+ destinationSchema,
385
+ sourceSchema
386
+ } from "@sentry/junior-plugin-api";
387
+ import { z as z2 } from "zod";
388
+ var AGENT_TURN_SESSION_PREFIX = "junior:agent_turn_session";
389
+ var AGENT_TURN_SESSION_INDEX_KEY = `${AGENT_TURN_SESSION_PREFIX}:index`;
390
+ var AGENT_TURN_SESSION_INDEX_MAX_LENGTH = 5e3;
391
+ var AGENT_TURN_SESSION_INDEX_READ_CONCURRENCY = 25;
392
+ var AGENT_TURN_SESSION_TTL_MS = THREAD_STATE_TTL_MS;
393
+ var agentTurnSessionStatusSchema = z2.enum([
394
+ "running",
395
+ "awaiting_resume",
396
+ "completed",
397
+ "failed",
398
+ "abandoned"
399
+ ]);
400
+ var agentTurnSurfaceSchema = z2.enum([
401
+ "slack",
402
+ "api",
403
+ "scheduler",
404
+ "internal"
405
+ ]);
406
+ var agentTurnResumeReasonSchema = z2.enum([
407
+ "timeout",
408
+ "auth",
409
+ "yield"
410
+ ]);
411
+ var nonNegativeNumberSchema = z2.number().finite().nonnegative();
412
+ var seqCursorSchema = z2.number().int().min(-1);
413
+ var agentTurnSessionSummarySchema = z2.object({
414
+ channelName: z2.string().min(1).optional(),
415
+ version: z2.number().int().nonnegative(),
416
+ conversationId: z2.string().min(1),
417
+ cumulativeDurationMs: nonNegativeNumberSchema,
418
+ cumulativeUsage: agentTurnUsageSchema.optional(),
419
+ destination: destinationSchema.optional(),
420
+ source: sourceSchema.optional(),
421
+ lastProgressAtMs: nonNegativeNumberSchema,
422
+ loadedSkillNames: z2.array(z2.string()).optional(),
423
+ modelId: z2.string().min(1).optional(),
424
+ reasoningLevel: z2.string().min(1).optional(),
425
+ actor: actorSchema.optional(),
426
+ resumeReason: agentTurnResumeReasonSchema.optional(),
427
+ resumedFromSliceId: z2.number().int().nonnegative().optional(),
428
+ sessionId: z2.string().min(1),
429
+ sliceId: z2.number().int().nonnegative(),
430
+ startedAtMs: nonNegativeNumberSchema,
431
+ state: agentTurnSessionStatusSchema,
432
+ surface: agentTurnSurfaceSchema.optional(),
433
+ traceId: z2.string().optional(),
434
+ updatedAtMs: nonNegativeNumberSchema
435
+ }).strict();
436
+ var storedAgentTurnSessionRecordSchema = agentTurnSessionSummarySchema.extend({
437
+ committedSeq: seqCursorSchema,
438
+ errorMessage: z2.string().optional(),
439
+ turnStartSeq: seqCursorSchema.optional()
440
+ }).strict();
441
+ function agentTurnSessionKey(conversationId, sessionId) {
442
+ return `${AGENT_TURN_SESSION_PREFIX}:${conversationId}:${sessionId}`;
443
+ }
444
+ function agentTurnSessionConversationIndexKey(conversationId) {
445
+ return `${AGENT_TURN_SESSION_PREFIX}:conversation:${conversationId}:index`;
446
+ }
447
+ function conversationExecutionFromSummary(summary) {
448
+ const status = summary.state === "completed" || summary.state === "abandoned" ? "idle" : summary.state;
449
+ return {
450
+ status,
451
+ runId: summary.sessionId,
452
+ updatedAtMs: summary.updatedAtMs
453
+ };
454
+ }
455
+ function sessionLogActor(actor) {
456
+ return actor?.platform === "slack" ? toStoredSlackActor(actor) : void 0;
457
+ }
458
+ function parseAgentTurnSessionRecord(value) {
459
+ return storedAgentTurnSessionRecordSchema.parse(value);
460
+ }
461
+ function parseAgentTurnSessionSummary(value) {
462
+ return agentTurnSessionSummarySchema.parse(value);
463
+ }
464
+ async function appendAgentTurnSessionSummary(summary, ttlMs) {
465
+ const stateAdapter = getStateAdapter();
466
+ await Promise.all([
467
+ stateAdapter.appendToList(AGENT_TURN_SESSION_INDEX_KEY, summary, {
468
+ maxLength: AGENT_TURN_SESSION_INDEX_MAX_LENGTH,
469
+ ttlMs
470
+ }),
471
+ stateAdapter.appendToList(
472
+ agentTurnSessionConversationIndexKey(summary.conversationId),
473
+ summary,
474
+ { ttlMs }
475
+ )
476
+ ]);
477
+ }
478
+ async function recordConversationActivityMetadata(args) {
479
+ const conversationStore = args.conversationStore ?? getConversationStore();
480
+ const source = args.summary.destination?.platform === "local" ? "local" : args.summary.surface;
481
+ await conversationStore.recordActivity({
482
+ activityAtMs: args.summary.updatedAtMs,
483
+ channelName: args.summary.channelName,
484
+ conversationId: args.summary.conversationId,
485
+ destination: args.summary.destination,
486
+ nowMs: args.nowMs,
487
+ actor: sessionLogActor(args.summary.actor),
488
+ source,
489
+ visibility: args.destinationVisibility
490
+ });
491
+ await conversationStore.recordExecution({
492
+ channelName: args.summary.channelName,
493
+ conversationId: args.summary.conversationId,
494
+ createdAtMs: args.summary.startedAtMs,
495
+ destination: args.summary.destination,
496
+ execution: conversationExecutionFromSummary(args.summary),
497
+ lastActivityAtMs: args.summary.updatedAtMs,
498
+ actor: sessionLogActor(args.summary.actor),
499
+ source,
500
+ updatedAtMs: args.nowMs,
501
+ visibility: args.destinationVisibility
502
+ });
503
+ }
504
+ function materializeAgentTurnSessionRecord(stored, piProjection, turnStartMessageIndex) {
505
+ return {
506
+ version: stored.version,
507
+ ...stored.channelName ? { channelName: stored.channelName } : {},
508
+ conversationId: stored.conversationId,
509
+ sessionId: stored.sessionId,
510
+ sliceId: stored.sliceId,
511
+ state: stored.state,
512
+ startedAtMs: stored.startedAtMs,
513
+ lastProgressAtMs: stored.lastProgressAtMs,
514
+ updatedAtMs: stored.updatedAtMs,
515
+ piMessages: piProjection.messages,
516
+ piMessageProvenance: piProjection.provenance,
517
+ actors: instructionActors(piProjection.provenance),
518
+ cumulativeDurationMs: stored.cumulativeDurationMs,
519
+ ...stored.destination ? { destination: stored.destination } : {},
520
+ ...stored.source ? { source: stored.source } : {},
521
+ ...stored.cumulativeUsage ? { cumulativeUsage: stored.cumulativeUsage } : {},
522
+ ...stored.resumeReason ? { resumeReason: stored.resumeReason } : {},
523
+ ...stored.errorMessage ? { errorMessage: stored.errorMessage } : {},
524
+ ...stored.loadedSkillNames ? { loadedSkillNames: stored.loadedSkillNames } : {},
525
+ ...stored.modelId ? { modelId: stored.modelId } : {},
526
+ ...stored.reasoningLevel ? { reasoningLevel: stored.reasoningLevel } : {},
527
+ ...stored.actor ? { actor: stored.actor } : {},
528
+ ...stored.resumedFromSliceId !== void 0 ? { resumedFromSliceId: stored.resumedFromSliceId } : {},
529
+ ...stored.surface ? { surface: stored.surface } : {},
530
+ ...stored.traceId ? { traceId: stored.traceId } : {},
531
+ ...turnStartMessageIndex !== void 0 ? { turnStartMessageIndex } : {}
532
+ };
533
+ }
534
+ async function getStoredAgentTurnSessionRecord(conversationId, sessionId) {
535
+ const stateAdapter = getStateAdapter();
536
+ await stateAdapter.connect();
537
+ const value = await stateAdapter.get(
538
+ agentTurnSessionKey(conversationId, sessionId)
539
+ );
540
+ return value == null ? void 0 : parseAgentTurnSessionRecord(value);
541
+ }
542
+ async function getAgentTurnSessionRecord(conversationId, sessionId) {
543
+ const parsed = await getStoredAgentTurnSessionRecord(
544
+ conversationId,
545
+ sessionId
546
+ );
547
+ if (!parsed) {
548
+ return void 0;
549
+ }
550
+ const piProjection = await loadTurnProjection({
551
+ conversationId,
552
+ committedSeq: parsed.committedSeq,
553
+ // Unfinished records include the current-epoch tail so parked input
554
+ // appended after the last safe boundary stays model-visible on resume.
555
+ includeTail: parsed.state === "running" || parsed.state === "awaiting_resume"
556
+ });
557
+ if (!piProjection) {
558
+ return void 0;
559
+ }
560
+ const turnStartMessageIndex = parsed.turnStartSeq === void 0 ? void 0 : piProjection.seqs.filter((seq) => seq <= parsed.turnStartSeq).length;
561
+ return materializeAgentTurnSessionRecord(
562
+ parsed,
563
+ piProjection,
564
+ turnStartMessageIndex
565
+ );
566
+ }
567
+ function buildStoredRecord(args) {
568
+ const nowMs = Date.now();
569
+ return {
570
+ version: (args.previousVersion ?? 0) + 1,
571
+ ...args.channelName ? { channelName: args.channelName } : {},
572
+ conversationId: args.conversationId,
573
+ sessionId: args.sessionId,
574
+ sliceId: args.sliceId,
575
+ state: args.state,
576
+ startedAtMs: args.startedAtMs ?? nowMs,
577
+ lastProgressAtMs: args.lastProgressAtMs ?? nowMs,
578
+ updatedAtMs: nowMs,
579
+ committedSeq: args.committedSeq,
580
+ ...args.turnStartSeq !== void 0 ? { turnStartSeq: args.turnStartSeq } : {},
581
+ cumulativeDurationMs: args.cumulativeDurationMs,
582
+ ...args.cumulativeUsage ? { cumulativeUsage: args.cumulativeUsage } : {},
583
+ ...args.destination ? { destination: args.destination } : {},
584
+ ...args.source ? { source: args.source } : {},
585
+ ...args.actor ? { actor: args.actor } : {},
586
+ ...args.loadedSkillNames ? { loadedSkillNames: args.loadedSkillNames } : {},
587
+ ...args.modelId ? { modelId: args.modelId } : {},
588
+ ...args.reasoningLevel ? { reasoningLevel: args.reasoningLevel } : {},
589
+ ...args.resumeReason ? { resumeReason: args.resumeReason } : {},
590
+ ...args.errorMessage ? { errorMessage: args.errorMessage } : {},
591
+ ...args.resumedFromSliceId !== void 0 ? { resumedFromSliceId: args.resumedFromSliceId } : {},
592
+ ...args.surface ? { surface: args.surface } : {},
593
+ ...args.traceId ? { traceId: args.traceId } : {}
594
+ };
595
+ }
596
+ async function setStoredRecord(args) {
597
+ const stateAdapter = getStateAdapter();
598
+ await stateAdapter.connect();
599
+ await recordConversationActivityMetadata({
600
+ conversationStore: args.conversationStore,
601
+ destinationVisibility: args.destinationVisibility,
602
+ nowMs: Date.now(),
603
+ summary: args.record
604
+ });
605
+ await stateAdapter.set(
606
+ agentTurnSessionKey(args.record.conversationId, args.record.sessionId),
607
+ args.record,
608
+ args.ttlMs
609
+ );
610
+ const {
611
+ committedSeq: _committedSeq,
612
+ errorMessage: _errorMessage,
613
+ turnStartSeq: _turnStartSeq,
614
+ ...summary
615
+ } = args.record;
616
+ await appendAgentTurnSessionSummary(summary, args.ttlMs);
617
+ return materializeAgentTurnSessionRecord(
618
+ args.record,
619
+ {
620
+ messages: [...args.piMessages],
621
+ provenance: [...args.piMessageProvenance]
622
+ },
623
+ args.turnStartMessageIndex
624
+ );
625
+ }
626
+ async function updateAgentTurnSessionState(args) {
627
+ const parsed = await getStoredAgentTurnSessionRecord(
628
+ args.existing.conversationId,
629
+ args.existing.sessionId
630
+ );
631
+ if (!parsed || parsed.version !== args.existing.version) {
632
+ return void 0;
633
+ }
634
+ return await setStoredRecord({
635
+ piMessages: args.existing.piMessages,
636
+ piMessageProvenance: args.existing.piMessageProvenance,
637
+ ttlMs: AGENT_TURN_SESSION_TTL_MS,
638
+ ...args.existing.turnStartMessageIndex !== void 0 ? { turnStartMessageIndex: args.existing.turnStartMessageIndex } : {},
639
+ record: buildStoredRecord({
640
+ conversationId: args.existing.conversationId,
641
+ sessionId: args.existing.sessionId,
642
+ sliceId: args.existing.sliceId,
643
+ state: args.state,
644
+ committedSeq: parsed.committedSeq,
645
+ ...parsed.turnStartSeq !== void 0 ? { turnStartSeq: parsed.turnStartSeq } : {},
646
+ ...parsed.channelName ? { channelName: parsed.channelName } : {},
647
+ startedAtMs: parsed.startedAtMs,
648
+ lastProgressAtMs: parsed.lastProgressAtMs,
649
+ previousVersion: parsed.version,
650
+ cumulativeDurationMs: args.existing.cumulativeDurationMs,
651
+ ...args.existing.cumulativeUsage ? { cumulativeUsage: args.existing.cumulativeUsage } : {},
652
+ ...args.existing.destination ? { destination: args.existing.destination } : {},
653
+ ...args.existing.source ? { source: args.existing.source } : {},
654
+ ...args.existing.loadedSkillNames ? { loadedSkillNames: args.existing.loadedSkillNames } : {},
655
+ ...args.existing.modelId ? { modelId: args.existing.modelId } : {},
656
+ ...args.existing.reasoningLevel ? { reasoningLevel: args.existing.reasoningLevel } : {},
657
+ ...args.existing.actor ? { actor: args.existing.actor } : {},
658
+ ...args.existing.resumeReason ? { resumeReason: args.existing.resumeReason } : {},
659
+ ...args.existing.resumedFromSliceId !== void 0 ? { resumedFromSliceId: args.existing.resumedFromSliceId } : {},
660
+ ...args.existing.surface ? { surface: args.existing.surface } : {},
661
+ ...args.existing.traceId ? { traceId: args.existing.traceId } : {},
662
+ ...args.errorMessage ?? args.existing.errorMessage ? { errorMessage: args.errorMessage ?? args.existing.errorMessage } : {}
663
+ })
664
+ });
665
+ }
666
+ async function upsertAgentTurnSessionRecord(args) {
667
+ const existingRecord = await getStoredAgentTurnSessionRecord(
668
+ args.conversationId,
669
+ args.sessionId
670
+ );
671
+ const ttlMs = Math.max(1, args.ttlMs ?? AGENT_TURN_SESSION_TTL_MS);
672
+ const instructionActor = args.actor ?? existingRecord?.actor;
673
+ const commit = await commitMessages({
674
+ conversationId: args.conversationId,
675
+ messages: args.piMessages,
676
+ ...instructionActor ? { newMessageProvenance: instructionProvenanceFor(instructionActor) } : {},
677
+ ...args.trailingMessageProvenance ? { trailingMessageProvenance: args.trailingMessageProvenance } : {}
678
+ });
679
+ const turnStartSeq = args.turnStartMessageIndex === void 0 ? existingRecord?.turnStartSeq : args.turnStartMessageIndex <= 0 ? -1 : commit.messageSeqs[args.turnStartMessageIndex - 1] ?? commit.committedSeq;
680
+ const turnStartMessageIndex = args.turnStartMessageIndex ?? (turnStartSeq === void 0 ? void 0 : commit.messageSeqs.filter((seq) => seq <= turnStartSeq).length);
681
+ return await setStoredRecord({
682
+ conversationStore: args.conversationStore,
683
+ destinationVisibility: args.destinationVisibility,
684
+ piMessages: args.piMessages,
685
+ piMessageProvenance: commit.provenance,
686
+ ttlMs,
687
+ ...turnStartMessageIndex !== void 0 ? { turnStartMessageIndex } : {},
688
+ record: buildStoredRecord({
689
+ ...args.channelName ?? existingRecord?.channelName ? { channelName: args.channelName ?? existingRecord?.channelName } : {},
690
+ conversationId: args.conversationId,
691
+ sessionId: args.sessionId,
692
+ sliceId: args.sliceId,
693
+ state: args.state,
694
+ ...existingRecord?.startedAtMs !== void 0 ? { startedAtMs: existingRecord.startedAtMs } : {},
695
+ ...args.lastProgressAtMs !== void 0 ? { lastProgressAtMs: args.lastProgressAtMs } : {},
696
+ committedSeq: commit.committedSeq,
697
+ ...turnStartSeq !== void 0 ? { turnStartSeq } : {},
698
+ previousVersion: existingRecord?.version,
699
+ cumulativeDurationMs: args.cumulativeDurationMs ?? existingRecord?.cumulativeDurationMs ?? 0,
700
+ ...args.cumulativeUsage ? { cumulativeUsage: args.cumulativeUsage } : {},
701
+ ...args.destination ?? existingRecord?.destination ? { destination: args.destination ?? existingRecord?.destination } : {},
702
+ ...args.source ?? existingRecord?.source ? { source: args.source ?? existingRecord?.source } : {},
703
+ ...args.loadedSkillNames ? { loadedSkillNames: args.loadedSkillNames } : {},
704
+ ...existingRecord?.modelId ?? args.modelId ? { modelId: existingRecord?.modelId ?? args.modelId } : {},
705
+ ...args.reasoningLevel ?? existingRecord?.reasoningLevel ? {
706
+ reasoningLevel: args.reasoningLevel ?? existingRecord?.reasoningLevel
707
+ } : {},
708
+ ...args.actor ?? existingRecord?.actor ? { actor: args.actor ?? existingRecord?.actor } : {},
709
+ ...args.resumeReason ? { resumeReason: args.resumeReason } : {},
710
+ ...args.errorMessage ? { errorMessage: args.errorMessage } : {},
711
+ ...args.resumedFromSliceId !== void 0 ? { resumedFromSliceId: args.resumedFromSliceId } : {},
712
+ ...args.surface ?? existingRecord?.surface ? { surface: args.surface ?? existingRecord?.surface } : {},
713
+ ...args.traceId ?? existingRecord?.traceId ? { traceId: args.traceId ?? existingRecord?.traceId } : {}
714
+ })
715
+ });
716
+ }
717
+ async function recordAgentTurnSessionSummary(args) {
718
+ const existing = await getStoredAgentTurnSessionRecord(
719
+ args.conversationId,
720
+ args.sessionId
721
+ );
722
+ const nowMs = Date.now();
723
+ const ttlMs = Math.max(1, args.ttlMs ?? AGENT_TURN_SESSION_TTL_MS);
724
+ const summary = {
725
+ version: existing?.version ?? 0,
726
+ ...args.channelName ?? existing?.channelName ? { channelName: args.channelName ?? existing?.channelName } : {},
727
+ conversationId: args.conversationId,
728
+ sessionId: args.sessionId,
729
+ sliceId: args.sliceId,
730
+ startedAtMs: existing?.startedAtMs ?? args.startedAtMs ?? nowMs,
731
+ lastProgressAtMs: args.lastProgressAtMs ?? nowMs,
732
+ state: args.state,
733
+ updatedAtMs: nowMs,
734
+ cumulativeDurationMs: args.cumulativeDurationMs ?? existing?.cumulativeDurationMs ?? 0,
735
+ ...args.cumulativeUsage ?? existing?.cumulativeUsage ? { cumulativeUsage: args.cumulativeUsage ?? existing?.cumulativeUsage } : {},
736
+ ...args.destination ?? existing?.destination ? { destination: args.destination ?? existing?.destination } : {},
737
+ ...args.source ?? existing?.source ? { source: args.source ?? existing?.source } : {},
738
+ ...args.actor ?? existing?.actor ? { actor: args.actor ?? existing?.actor } : {},
739
+ ...args.loadedSkillNames ? { loadedSkillNames: args.loadedSkillNames } : existing?.loadedSkillNames ? { loadedSkillNames: existing.loadedSkillNames } : {},
740
+ ...existing?.modelId ?? args.modelId ? { modelId: existing?.modelId ?? args.modelId } : {},
741
+ ...args.reasoningLevel ?? existing?.reasoningLevel ? { reasoningLevel: args.reasoningLevel ?? existing?.reasoningLevel } : {},
742
+ ...args.resumeReason ? { resumeReason: args.resumeReason } : {},
743
+ ...args.surface ?? existing?.surface ? { surface: args.surface ?? existing?.surface } : {},
744
+ ...args.traceId ?? existing?.traceId ? { traceId: args.traceId ?? existing?.traceId } : {}
745
+ };
746
+ await recordConversationActivityMetadata({
747
+ conversationStore: args.conversationStore,
748
+ destinationVisibility: args.destinationVisibility,
749
+ nowMs,
750
+ summary
751
+ });
752
+ await appendAgentTurnSessionSummary(summary, ttlMs);
753
+ }
754
+ async function readAgentTurnSessionSummariesFromIndex(key) {
755
+ const stateAdapter = getStateAdapter();
756
+ await stateAdapter.connect();
757
+ const values = await stateAdapter.getList(key);
758
+ const summaries = /* @__PURE__ */ new Map();
759
+ for (const value of [...values].reverse()) {
760
+ const summary = parseAgentTurnSessionSummary(value);
761
+ const key2 = `${summary.conversationId}:${summary.sessionId}`;
762
+ if (!summaries.has(key2)) {
763
+ summaries.set(key2, summary);
764
+ }
765
+ }
766
+ return [...summaries.values()].sort(
767
+ (left, right) => right.updatedAtMs - left.updatedAtMs
768
+ );
769
+ }
770
+ async function listAgentTurnSessionSummariesForConversation(conversationId) {
771
+ const summaries = await readAgentTurnSessionSummariesFromIndex(
772
+ agentTurnSessionConversationIndexKey(conversationId)
773
+ );
774
+ if (summaries.length > 0) {
775
+ return summaries;
776
+ }
777
+ return (await readAgentTurnSessionSummariesFromIndex(AGENT_TURN_SESSION_INDEX_KEY)).filter((summary) => summary.conversationId === conversationId);
778
+ }
779
+ async function listAgentTurnSessionSummariesForConversations(conversationIds) {
780
+ const ids = [...new Set(conversationIds)];
781
+ const globalSummaries = await readAgentTurnSessionSummariesFromIndex(
782
+ AGENT_TURN_SESSION_INDEX_KEY
783
+ );
784
+ const globalByConversation = /* @__PURE__ */ new Map();
785
+ for (const summary of globalSummaries) {
786
+ globalByConversation.set(summary.conversationId, [
787
+ ...globalByConversation.get(summary.conversationId) ?? [],
788
+ summary
789
+ ]);
790
+ }
791
+ const summariesByConversation = /* @__PURE__ */ new Map();
792
+ let nextIndex = 0;
793
+ const readNext = async () => {
794
+ while (nextIndex < ids.length) {
795
+ const conversationId = ids[nextIndex];
796
+ nextIndex += 1;
797
+ if (!conversationId) continue;
798
+ const summaries = await readAgentTurnSessionSummariesFromIndex(
799
+ agentTurnSessionConversationIndexKey(conversationId)
800
+ );
801
+ summariesByConversation.set(
802
+ conversationId,
803
+ summaries.length > 0 ? summaries : globalByConversation.get(conversationId) ?? []
804
+ );
805
+ }
806
+ };
807
+ await Promise.all(
808
+ Array.from(
809
+ {
810
+ length: Math.min(AGENT_TURN_SESSION_INDEX_READ_CONCURRENCY, ids.length)
811
+ },
812
+ readNext
813
+ )
814
+ );
815
+ return summariesByConversation;
816
+ }
817
+ async function abandonAgentTurnSessionRecord(args) {
818
+ const existing = await getAgentTurnSessionRecord(
819
+ args.conversationId,
820
+ args.sessionId
821
+ );
822
+ if (!existing || existing.state === "completed" || existing.state === "failed" || existing.state === "abandoned") {
823
+ return void 0;
824
+ }
825
+ return await updateAgentTurnSessionState({
826
+ existing,
827
+ state: "abandoned",
828
+ errorMessage: args.errorMessage ?? existing.errorMessage
829
+ });
830
+ }
831
+ async function failAgentTurnSessionRecord(args) {
832
+ const existing = await getAgentTurnSessionRecord(
833
+ args.conversationId,
834
+ args.sessionId
835
+ );
836
+ if (!existing || existing.state === "completed" || existing.state === "failed" || existing.state === "abandoned" || existing.version !== args.expectedVersion) {
837
+ return void 0;
838
+ }
839
+ return await updateAgentTurnSessionState({
840
+ existing,
841
+ state: "failed",
842
+ errorMessage: args.errorMessage ?? existing.errorMessage
843
+ });
844
+ }
845
+
846
+ export {
847
+ projectSteps,
848
+ loadProjection,
849
+ loadProjectionWithProvenance,
850
+ loadConnectedMcpProviders,
851
+ commitMessages,
852
+ recordMcpProviderConnected,
853
+ recordAuthorizationRequested,
854
+ recordAuthorizationCompleted,
855
+ recordToolExecutionStarted,
856
+ hasAgentTurnUsage,
857
+ addAgentTurnUsage,
858
+ getAgentTurnSessionRecord,
859
+ upsertAgentTurnSessionRecord,
860
+ recordAgentTurnSessionSummary,
861
+ listAgentTurnSessionSummariesForConversation,
862
+ listAgentTurnSessionSummariesForConversations,
863
+ abandonAgentTurnSessionRecord,
864
+ failAgentTurnSessionRecord
865
+ };