@sentry/junior 0.93.0 → 0.95.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 (122) hide show
  1. package/dist/{agent-hooks-ZG7IDOIN.js → agent-hooks-FTQ5EGPO.js} +9 -10
  2. package/dist/api/people/list.js +7 -7
  3. package/dist/api/people/profile.js +7 -7
  4. package/dist/api/people/shared.d.ts +2 -2
  5. package/dist/api-reference.d.ts +1 -1
  6. package/dist/app.js +474 -231
  7. package/dist/{catalog-runtime-NZHMSMYC.js → catalog-runtime-2D7IVKUT.js} +3 -3
  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/egress/credentialed.d.ts +1 -1
  28. package/dist/chat/identities/sql.d.ts +1 -1
  29. package/dist/chat/logging.d.ts +2 -1
  30. package/dist/chat/resource-events/store.d.ts +2 -1
  31. package/dist/chat/runtime/reply-executor.d.ts +8 -0
  32. package/dist/chat/runtime/thread-state.d.ts +2 -0
  33. package/dist/chat/sandbox/egress/schemas.d.ts +4 -0
  34. package/dist/chat/sandbox/egress/session.d.ts +2 -2
  35. package/dist/chat/sandbox/resources.d.ts +4 -0
  36. package/dist/chat/services/mcp-auth-orchestration.d.ts +8 -0
  37. package/dist/chat/services/plugin-auth-orchestration.d.ts +12 -0
  38. package/dist/chat/services/turn-session-record.d.ts +14 -2
  39. package/dist/chat/sleep.d.ts +2 -0
  40. package/dist/chat/state/conversation.d.ts +7 -4
  41. package/dist/chat/state/session-log.d.ts +23 -1
  42. package/dist/chat/state/turn-session.d.ts +6 -0
  43. package/dist/chat/tool-support/private-trace-result.d.ts +4 -0
  44. package/dist/chat/tool-support/zod-tool.d.ts +1 -0
  45. package/dist/chat/tools/advisor/tool.d.ts +9 -4
  46. package/dist/chat/tools/definition.d.ts +2 -0
  47. package/dist/chat/tools/execution/tool-error-handler.d.ts +2 -2
  48. package/dist/chat/tools/system-time.d.ts +8 -0
  49. package/dist/chat/xml.d.ts +2 -0
  50. package/dist/{chunk-NYWPISSO.js → chunk-2XXEKR44.js} +1 -1
  51. package/dist/{chunk-QGEWC27H.js → chunk-5XMNOD3S.js} +5 -7
  52. package/dist/{chunk-NFXSLTYG.js → chunk-6ONME5IG.js} +864 -62
  53. package/dist/{chunk-LFLTJQVR.js → chunk-7FBGKXPE.js} +4 -0
  54. package/dist/{chunk-MC4ZZE4Q.js → chunk-AYP4ERVZ.js} +1 -1
  55. package/dist/{chunk-GHGPTPBL.js → chunk-B7PUBQQM.js} +1 -1
  56. package/dist/chunk-CM5EZD5F.js +17 -0
  57. package/dist/chunk-CRRBJ3JP.js +1037 -0
  58. package/dist/{chunk-G3E7SCME.js → chunk-CZEX6KIQ.js} +23 -0
  59. package/dist/{chunk-TNUUATT7.js → chunk-E3E2XNCN.js} +2 -2
  60. package/dist/{chunk-LNCREA5Z.js → chunk-EKNJM5IG.js} +3 -127
  61. package/dist/{chunk-NAPITCZ6.js → chunk-GUE7HTNR.js} +251 -6
  62. package/dist/{chunk-BTH37NCU.js → chunk-GVOUCI2O.js} +1 -1
  63. package/dist/{chunk-YYBX2BD5.js → chunk-GY34VGP5.js} +1 -1
  64. package/dist/{chunk-JJUJ4CO2.js → chunk-HCXXB35T.js} +1489 -360
  65. package/dist/{chunk-YTNPU7I2.js → chunk-HDTO3A74.js} +2 -2
  66. package/dist/{chunk-YJ4OPVNA.js → chunk-HZNJLKKI.js} +1 -1
  67. package/dist/{chunk-HDNWZMUN.js → chunk-KDPCGVIT.js} +116 -51
  68. package/dist/chunk-N4RNJ32C.js +48 -0
  69. package/dist/{chunk-UUB3D2XI.js → chunk-NSCHU54X.js} +8 -10
  70. package/dist/{chunk-PFXC67GJ.js → chunk-RAIB6WSG.js} +6 -80
  71. package/dist/chunk-WAGQ377B.js +724 -0
  72. package/dist/{chunk-6H4PP63X.js → chunk-WCMQJE4F.js} +24 -14
  73. package/dist/{chunk-S6QKIGRM.js → chunk-WPOJ443W.js} +15 -25
  74. package/dist/{chunk-MAVOJ54A.js → chunk-XX4N4E6C.js} +25 -388
  75. package/dist/cli/chat.js +24 -23
  76. package/dist/cli/check.js +4 -4
  77. package/dist/cli/plugins.js +11 -12
  78. package/dist/cli/snapshot-warmup.js +7 -8
  79. package/dist/cli/upgrade.js +78 -17
  80. package/dist/db/schema/agent-steps.d.ts +134 -0
  81. package/dist/db/schema/conversation-messages.d.ts +153 -0
  82. package/dist/{chat/conversations/sql → db}/schema/conversations.d.ts +34 -0
  83. package/dist/{chat/conversations/sql → db}/schema.d.ts +319 -8
  84. package/dist/db-W55B74OP.js +24 -0
  85. package/dist/deployment.d.ts +2 -0
  86. package/dist/handlers/retention.d.ts +6 -0
  87. package/dist/instrumentation.js +16 -3
  88. package/dist/legacy-import-ZPLGLAFD.js +17 -0
  89. package/dist/nitro.js +14 -4
  90. package/dist/reporting/conversations/activity.d.ts +40 -0
  91. package/dist/reporting/conversations/context.d.ts +8 -0
  92. package/dist/reporting/conversations/details.d.ts +6 -0
  93. package/dist/reporting/conversations/index.d.ts +4 -0
  94. package/dist/reporting/conversations/shared.d.ts +9 -0
  95. package/dist/reporting/conversations/statistics.d.ts +4 -0
  96. package/dist/reporting/conversations/summaries.d.ts +17 -0
  97. package/dist/reporting/conversations/transcript.d.ts +28 -0
  98. package/dist/reporting/conversations/types.d.ts +178 -0
  99. package/dist/reporting/conversations.d.ts +1 -178
  100. package/dist/reporting.d.ts +4 -3
  101. package/dist/reporting.js +603 -827
  102. package/dist/{runner-XAZPJNAQ.js → runner-OOSBDYRK.js} +35 -41
  103. package/dist/{validation-KYAWETI4.js → validation-QCGRFRFZ.js} +4 -4
  104. package/migrations/README.md +32 -0
  105. package/migrations/meta/0000_snapshot.json +978 -0
  106. package/migrations/meta/_journal.json +13 -0
  107. package/package.json +9 -6
  108. package/dist/chat/sql/schema.d.ts +0 -1049
  109. package/dist/chat/state/conversation-details.d.ts +0 -47
  110. package/dist/chunk-7STN2ZSK.js +0 -250
  111. package/dist/chunk-LE5ANBUZ.js +0 -1040
  112. package/dist/chunk-QL66APYJ.js +0 -1377
  113. package/dist/db-YDN6AFJH.js +0 -18
  114. /package/dist/{chat/sql → db}/db.d.ts +0 -0
  115. /package/dist/{chat/sql → db}/executor.d.ts +0 -0
  116. /package/dist/{chat/sql → db}/neon.d.ts +0 -0
  117. /package/dist/{chat/sql → db}/postgres.d.ts +0 -0
  118. /package/dist/{chat/conversations/sql → db}/schema/destinations.d.ts +0 -0
  119. /package/dist/{chat/conversations/sql → db}/schema/identities.d.ts +0 -0
  120. /package/dist/{chat/conversations/sql → db}/schema/migrations.d.ts +0 -0
  121. /package/dist/{chat/conversations/sql → db}/schema/timestamps.d.ts +0 -0
  122. /package/dist/{chat/conversations/sql → db}/schema/users.d.ts +0 -0
@@ -1,1377 +0,0 @@
1
- import {
2
- getConnectedStateContext,
3
- getStateAdapter
4
- } from "./chunk-7STN2ZSK.js";
5
- import {
6
- getConversationStore
7
- } from "./chunk-NFXSLTYG.js";
8
- import {
9
- getChatConfig
10
- } from "./chunk-NAPITCZ6.js";
11
- import {
12
- parseDestination
13
- } from "./chunk-GHGPTPBL.js";
14
- import {
15
- logWarn,
16
- parseActor,
17
- storedSlackActorSchema,
18
- toStoredSlackActor
19
- } from "./chunk-S6QKIGRM.js";
20
- import {
21
- isRecord
22
- } from "./chunk-OB42YVAE.js";
23
-
24
- // src/chat/state/session-log.ts
25
- import { isDeepStrictEqual } from "util";
26
- import { z as z2 } from "zod";
27
- import { actorSchema } from "@sentry/junior-plugin-api";
28
-
29
- // src/chat/pi/messages.ts
30
- import { z } from "zod";
31
- var piMessageSchema = z.object({
32
- role: z.string()
33
- }).passthrough().transform((value) => value);
34
- var piContentMessageSchema = z.object({
35
- content: z.array(z.unknown()),
36
- role: z.string().min(1)
37
- }).passthrough().transform((value) => value);
38
-
39
- // src/chat/state/session-log.ts
40
- var AGENT_SESSION_LOG_PREFIX = "junior:agent-session-log";
41
- var AGENT_SESSION_LOG_SCHEMA_VERSION = 2;
42
- var INITIAL_SESSION_ID = "session_0";
43
- var SESSION_ID_PREFIX = "session_";
44
- var STATE_STORE_LOCK_TTL_MS = 5e3;
45
- var schemaVersionSchema = z2.union([z2.literal(1), z2.literal(2)]);
46
- var piMessageAuthoritySchema = z2.union([
47
- z2.literal("instruction"),
48
- z2.literal("context")
49
- ]);
50
- var piMessageProvenanceSchema = z2.object({
51
- authority: piMessageAuthoritySchema,
52
- actor: actorSchema.optional()
53
- }).strict();
54
- var unattributedContextProvenance = {
55
- authority: "context"
56
- };
57
- function instructionProvenance(actor) {
58
- return actor ? { authority: "instruction", actor } : { authority: "instruction" };
59
- }
60
- function isDefaultContextProvenance(provenance) {
61
- return provenance.authority === "context" && !provenance.actor;
62
- }
63
- function legacyActorProvenance(actor) {
64
- if (actor.teamId && actor.slackUserId && actor.platform) {
65
- return instructionProvenance({
66
- platform: "slack",
67
- teamId: actor.teamId,
68
- userId: actor.slackUserId,
69
- ...actor.slackUserName ? { userName: actor.slackUserName } : {},
70
- ...actor.fullName ? { fullName: actor.fullName } : {},
71
- ...actor.email ? { email: actor.email } : {}
72
- });
73
- }
74
- return unattributedContextProvenance;
75
- }
76
- var piMessageEntrySchema = z2.object({
77
- schemaVersion: schemaVersionSchema,
78
- type: z2.literal("pi_message"),
79
- sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
80
- message: piMessageSchema,
81
- provenance: piMessageProvenanceSchema.optional(),
82
- // Legacy v1 latest-wins actor, decoded into provenance on read.
83
- actor: storedSlackActorSchema.optional()
84
- });
85
- var projectionResetEntrySchema = z2.object({
86
- schemaVersion: schemaVersionSchema,
87
- type: z2.literal("projection_reset"),
88
- sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
89
- messages: z2.array(piMessageSchema),
90
- provenance: z2.array(piMessageProvenanceSchema).optional(),
91
- // Legacy v1 latest-wins actor; v1 resets carry no per-message provenance.
92
- actor: storedSlackActorSchema.optional()
93
- });
94
- var actorRecordedEntrySchema = z2.object({
95
- schemaVersion: schemaVersionSchema,
96
- type: z2.literal("actor_recorded"),
97
- sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
98
- actor: storedSlackActorSchema
99
- });
100
- var mcpProviderConnectedEntrySchema = z2.object({
101
- schemaVersion: schemaVersionSchema,
102
- type: z2.literal("mcp_provider_connected"),
103
- sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
104
- provider: z2.string().min(1)
105
- });
106
- var authorizationKindSchema = z2.union([
107
- z2.literal("plugin"),
108
- z2.literal("mcp")
109
- ]);
110
- var authorizationRequestedEntrySchema = z2.object({
111
- schemaVersion: schemaVersionSchema,
112
- type: z2.literal("authorization_requested"),
113
- sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
114
- createdAtMs: z2.number().int().nonnegative(),
115
- kind: authorizationKindSchema,
116
- provider: z2.string().min(1),
117
- actorId: z2.string().min(1),
118
- authorizationId: z2.string().min(1),
119
- delivery: z2.union([
120
- z2.literal("private_link_sent"),
121
- z2.literal("private_link_reused")
122
- ])
123
- });
124
- var authorizationCompletedEntrySchema = z2.object({
125
- schemaVersion: schemaVersionSchema,
126
- type: z2.literal("authorization_completed"),
127
- sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
128
- createdAtMs: z2.number().int().nonnegative(),
129
- kind: authorizationKindSchema,
130
- provider: z2.string().min(1),
131
- actorId: z2.string().min(1),
132
- authorizationId: z2.string().min(1)
133
- });
134
- var transcriptRefSchema = z2.object({
135
- type: z2.literal("advisor_session"),
136
- parentConversationId: z2.string().min(1),
137
- key: z2.string().min(1)
138
- });
139
- var toolExecutionStartedEntrySchema = z2.object({
140
- schemaVersion: schemaVersionSchema,
141
- type: z2.literal("tool_execution_started"),
142
- sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
143
- createdAtMs: z2.number().int().nonnegative(),
144
- toolCallId: z2.string().min(1),
145
- toolName: z2.string().min(1),
146
- args: z2.unknown().optional()
147
- });
148
- var subagentStartedEntrySchema = z2.object({
149
- schemaVersion: schemaVersionSchema,
150
- type: z2.literal("subagent_started"),
151
- sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
152
- subagentInvocationId: z2.string().min(1),
153
- subagentKind: z2.string().min(1),
154
- parentToolCallId: z2.string().min(1).optional(),
155
- parentConversationId: z2.string().min(1),
156
- parentSessionId: z2.string().min(1).optional(),
157
- transcriptRef: transcriptRefSchema,
158
- historyMode: z2.literal("shared"),
159
- createdAtMs: z2.number().int().nonnegative()
160
- });
161
- var subagentEndedEntrySchema = z2.object({
162
- schemaVersion: schemaVersionSchema,
163
- type: z2.literal("subagent_ended"),
164
- sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
165
- subagentInvocationId: z2.string().min(1),
166
- outcome: z2.union([
167
- z2.literal("success"),
168
- z2.literal("error"),
169
- z2.literal("aborted")
170
- ]),
171
- errorCode: z2.string().min(1).optional(),
172
- transcriptEndMessageIndex: z2.number().int().nonnegative().optional(),
173
- transcriptStartMessageIndex: z2.number().int().nonnegative().optional(),
174
- createdAtMs: z2.number().int().nonnegative()
175
- });
176
- var sessionLogEntrySchema = z2.discriminatedUnion("type", [
177
- piMessageEntrySchema,
178
- projectionResetEntrySchema,
179
- actorRecordedEntrySchema,
180
- mcpProviderConnectedEntrySchema,
181
- authorizationRequestedEntrySchema,
182
- authorizationCompletedEntrySchema,
183
- toolExecutionStartedEntrySchema,
184
- subagentStartedEntrySchema,
185
- subagentEndedEntrySchema
186
- ]);
187
- function key(scope) {
188
- const prefix = getChatConfig().state.keyPrefix;
189
- return [
190
- ...prefix ? [prefix] : [],
191
- AGENT_SESSION_LOG_PREFIX,
192
- scope.conversationId
193
- ].join(":");
194
- }
195
- function rawKey(scope) {
196
- return [AGENT_SESSION_LOG_PREFIX, scope.conversationId].join(":");
197
- }
198
- function storedRecord(value) {
199
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
200
- }
201
- function migrateStoredEntry(value) {
202
- const record = storedRecord(value);
203
- if (!record) {
204
- return value;
205
- }
206
- const migrated = { ...record };
207
- if ("requester" in migrated && !("actor" in migrated)) {
208
- migrated.actor = migrated.requester;
209
- }
210
- delete migrated.requester;
211
- if (migrated.type === "requester_recorded") {
212
- migrated.type = "actor_recorded";
213
- }
214
- if ("requesterId" in migrated && !("actorId" in migrated)) {
215
- migrated.actorId = migrated.requesterId;
216
- }
217
- delete migrated.requesterId;
218
- return migrated;
219
- }
220
- function normalizeMessageCount(value) {
221
- return Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;
222
- }
223
- function countMatchingPrefix(left, right) {
224
- const limit = Math.min(left.length, right.length);
225
- for (let index = 0; index < limit; index += 1) {
226
- if (!isDeepStrictEqual(left[index], right[index])) {
227
- return index;
228
- }
229
- }
230
- return limit;
231
- }
232
- function entrySessionId(entry) {
233
- return entry.sessionId ?? INITIAL_SESSION_ID;
234
- }
235
- function isActivityEntry(entry) {
236
- return entry.type === "tool_execution_started" || entry.type === "subagent_started" || entry.type === "subagent_ended";
237
- }
238
- function latestProjectionResetIndex(entries) {
239
- for (let index = entries.length - 1; index >= 0; index -= 1) {
240
- if (entries[index]?.type === "projection_reset") {
241
- return index;
242
- }
243
- }
244
- return -1;
245
- }
246
- function currentSessionId(entries) {
247
- const resetIndex = latestProjectionResetIndex(entries);
248
- if (resetIndex < 0) {
249
- return INITIAL_SESSION_ID;
250
- }
251
- return entrySessionId(entries[resetIndex]);
252
- }
253
- function nextSessionId(entries) {
254
- const resetCount = entries.filter(
255
- (entry) => entry.type === "projection_reset"
256
- ).length;
257
- return `${SESSION_ID_PREFIX}${resetCount + 1}`;
258
- }
259
- function projectionEntries(entries, sessionId) {
260
- if (sessionId) {
261
- const sessionEntries = [];
262
- let started = false;
263
- for (const entry of entries) {
264
- const entryId = entrySessionId(entry);
265
- if (!started) {
266
- if (entryId !== sessionId) {
267
- continue;
268
- }
269
- started = true;
270
- } else if (entry.type === "projection_reset" && entryId !== sessionId) {
271
- break;
272
- }
273
- if (entryId === sessionId) {
274
- sessionEntries.push(entry);
275
- }
276
- }
277
- return sessionEntries;
278
- }
279
- const resetIndex = latestProjectionResetIndex(entries);
280
- const startIndex = resetIndex < 0 ? 0 : resetIndex;
281
- const currentId = resetIndex < 0 ? INITIAL_SESSION_ID : entrySessionId(entries[resetIndex]);
282
- return entries.slice(startIndex).filter((entry) => entrySessionId(entry) === currentId);
283
- }
284
- function piEntry(message, sessionId, provenance) {
285
- return {
286
- schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
287
- type: "pi_message",
288
- sessionId,
289
- message,
290
- // Ambient context is the decode default, so only attributed/instruction
291
- // provenance needs to be persisted on the entry.
292
- ...provenance && !isDefaultContextProvenance(provenance) ? { provenance } : {}
293
- };
294
- }
295
- function resetEntry(messages, sessionId, provenance) {
296
- if (provenance.length !== messages.length) {
297
- throw new Error(
298
- "projection_reset provenance must align one-to-one with messages"
299
- );
300
- }
301
- return {
302
- schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
303
- type: "projection_reset",
304
- sessionId,
305
- messages,
306
- provenance
307
- };
308
- }
309
- function mcpProviderConnectedEntry(provider, sessionId) {
310
- return {
311
- schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
312
- type: "mcp_provider_connected",
313
- sessionId,
314
- provider
315
- };
316
- }
317
- function authorizationObservationMessage(entry) {
318
- const label = entry.kind === "mcp" ? "MCP authorization" : "Authorization";
319
- return {
320
- role: "user",
321
- content: [
322
- {
323
- type: "text",
324
- text: `${label} completed for provider "${entry.provider}". Continue the blocked request and retry the provider operation if needed.`
325
- }
326
- ],
327
- timestamp: entry.createdAtMs
328
- };
329
- }
330
- function authorizationRequestedEntry(args) {
331
- return {
332
- schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
333
- type: "authorization_requested",
334
- sessionId: args.sessionId,
335
- createdAtMs: args.createdAtMs,
336
- kind: args.kind,
337
- provider: args.provider,
338
- actorId: args.actorId,
339
- authorizationId: args.authorizationId,
340
- delivery: args.delivery
341
- };
342
- }
343
- function authorizationCompletedEntry(args) {
344
- return {
345
- schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
346
- type: "authorization_completed",
347
- sessionId: args.sessionId,
348
- createdAtMs: args.createdAtMs,
349
- kind: args.kind,
350
- provider: args.provider,
351
- actorId: args.actorId,
352
- authorizationId: args.authorizationId
353
- };
354
- }
355
- function toolExecutionStartedEntry(args) {
356
- return {
357
- schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
358
- type: "tool_execution_started",
359
- sessionId: args.sessionId,
360
- createdAtMs: args.createdAtMs,
361
- toolCallId: args.toolCallId,
362
- toolName: args.toolName,
363
- ...args.args !== void 0 ? { args: args.args } : {}
364
- };
365
- }
366
- function subagentStartedEntry(args) {
367
- return {
368
- schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
369
- type: "subagent_started",
370
- sessionId: args.sessionId,
371
- subagentInvocationId: args.subagentInvocationId,
372
- subagentKind: args.subagentKind,
373
- ...args.parentToolCallId ? { parentToolCallId: args.parentToolCallId } : {},
374
- parentConversationId: args.parentConversationId,
375
- ...args.parentSessionId ? { parentSessionId: args.parentSessionId } : {},
376
- transcriptRef: args.transcriptRef,
377
- historyMode: args.historyMode,
378
- createdAtMs: args.createdAtMs
379
- };
380
- }
381
- function subagentEndedEntry(args) {
382
- return {
383
- schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
384
- type: "subagent_ended",
385
- sessionId: args.sessionId,
386
- subagentInvocationId: args.subagentInvocationId,
387
- outcome: args.outcome,
388
- ...args.errorCode ? { errorCode: args.errorCode } : {},
389
- ...args.transcriptEndMessageIndex !== void 0 ? { transcriptEndMessageIndex: args.transcriptEndMessageIndex } : {},
390
- ...args.transcriptStartMessageIndex !== void 0 ? { transcriptStartMessageIndex: args.transcriptStartMessageIndex } : {},
391
- createdAtMs: args.createdAtMs
392
- };
393
- }
394
- function decode(value) {
395
- if (typeof value === "string") {
396
- return decode(JSON.parse(value));
397
- }
398
- const parsed = sessionLogEntrySchema.safeParse(migrateStoredEntry(value));
399
- if (parsed.success) {
400
- return parsed.data;
401
- }
402
- return piEntry(piMessageSchema.parse(value), INITIAL_SESSION_ID);
403
- }
404
- function piEntryProvenance(entry) {
405
- if (entry.provenance) {
406
- return entry.provenance;
407
- }
408
- if (entry.actor) {
409
- return legacyActorProvenance(entry.actor);
410
- }
411
- return unattributedContextProvenance;
412
- }
413
- function project(entries, sessionId) {
414
- let messages = [];
415
- let provenance = [];
416
- for (const entry of projectionEntries(entries, sessionId)) {
417
- if (entry.type === "pi_message") {
418
- messages.push(entry.message);
419
- provenance.push(piEntryProvenance(entry));
420
- continue;
421
- }
422
- if (entry.type === "authorization_completed") {
423
- messages.push(authorizationObservationMessage(entry));
424
- provenance.push(unattributedContextProvenance);
425
- continue;
426
- }
427
- if (entry.type === "projection_reset") {
428
- const resetProvenance = entry.provenance ?? entry.messages.map(() => unattributedContextProvenance);
429
- if (resetProvenance.length !== entry.messages.length) {
430
- throw new Error(
431
- "projection_reset provenance must align one-to-one with messages"
432
- );
433
- }
434
- messages = [...entry.messages];
435
- provenance = [...resetProvenance];
436
- continue;
437
- }
438
- }
439
- return { messages, provenance };
440
- }
441
- function actorIdentityKey(actor) {
442
- if (actor.platform === "system") {
443
- return `system ${actor.name}`;
444
- }
445
- return actor.platform === "slack" ? `slack\0${actor.teamId}\0${actor.userId}` : `${actor.platform}\0${actor.userId}`;
446
- }
447
- function instructionActors(provenance) {
448
- const seen = /* @__PURE__ */ new Set();
449
- const actors = [];
450
- for (const entry of provenance) {
451
- if (entry.authority !== "instruction" || !entry.actor) {
452
- continue;
453
- }
454
- const identity = actorIdentityKey(entry.actor);
455
- if (seen.has(identity)) {
456
- continue;
457
- }
458
- seen.add(identity);
459
- actors.push(entry.actor);
460
- }
461
- return actors;
462
- }
463
- function connectedMcpProviders(entries, sessionId) {
464
- const providers = /* @__PURE__ */ new Set();
465
- for (const entry of projectionEntries(entries, sessionId)) {
466
- if (entry.type === "mcp_provider_connected") {
467
- providers.add(entry.provider);
468
- }
469
- }
470
- return [...providers].sort((left, right) => left.localeCompare(right));
471
- }
472
- function isUserMessage(message) {
473
- return message.role === "user";
474
- }
475
- function resolveCommitProvenance(args) {
476
- if (args.explicitProvenance) {
477
- if (args.explicitProvenance.length !== args.nextMessages.length) {
478
- throw new Error("commit provenance must align one-to-one with messages");
479
- }
480
- return args.explicitProvenance;
481
- }
482
- const matchingPrefix = countMatchingPrefix(
483
- args.existing.messages,
484
- args.nextMessages
485
- );
486
- const provenance = args.nextMessages.map(
487
- (_, index) => index < matchingPrefix ? args.existing.provenance[index] ?? unattributedContextProvenance : unattributedContextProvenance
488
- );
489
- if (args.newMessageProvenance) {
490
- for (let index = args.nextMessages.length - 1; index >= matchingPrefix; index -= 1) {
491
- if (isUserMessage(args.nextMessages[index])) {
492
- provenance[index] = args.newMessageProvenance;
493
- break;
494
- }
495
- }
496
- }
497
- if (args.trailingMessageProvenance) {
498
- if (args.trailingMessageProvenance.length > provenance.length) {
499
- throw new Error(
500
- "trailing commit provenance cannot exceed committed messages"
501
- );
502
- }
503
- const newMessageCount = args.nextMessages.length - matchingPrefix;
504
- if (args.trailingMessageProvenance.length > newMessageCount) {
505
- throw new Error(
506
- "trailing commit provenance must align to newly committed messages"
507
- );
508
- }
509
- const start = provenance.length - args.trailingMessageProvenance.length;
510
- args.trailingMessageProvenance.forEach((entry, offset) => {
511
- provenance[start + offset] = entry;
512
- });
513
- }
514
- return provenance;
515
- }
516
- function commitEntries(existing, nextMessages, nextProvenance, sessionId, entries) {
517
- const matchingPrefix = countMatchingPrefix(existing.messages, nextMessages);
518
- if (matchingPrefix === existing.messages.length) {
519
- const newMessages = nextMessages.slice(matchingPrefix);
520
- const newProvenance = nextProvenance.slice(matchingPrefix);
521
- return {
522
- entries: newMessages.map(
523
- (message, index) => piEntry(message, sessionId, newProvenance[index])
524
- ),
525
- sessionId
526
- };
527
- }
528
- const resetSessionId = nextSessionId(entries);
529
- return {
530
- entries: [resetEntry(nextMessages, resetSessionId, nextProvenance)],
531
- sessionId: resetSessionId
532
- };
533
- }
534
- function redisStore(redisStateAdapter) {
535
- const client = redisStateAdapter.getClient();
536
- return {
537
- async append({ entries, scope, ttlMs }) {
538
- const listKey = key(scope);
539
- if (entries.length > 0) {
540
- await client.rPush(
541
- listKey,
542
- entries.map((entry) => JSON.stringify(entry))
543
- );
544
- }
545
- await client.pExpire(listKey, Math.max(1, ttlMs));
546
- },
547
- async read(scope) {
548
- const values = await client.lRange(key(scope), 0, -1);
549
- return values.map(decode);
550
- }
551
- };
552
- }
553
- function stateStore() {
554
- const stateAdapter = getStateAdapter();
555
- return {
556
- async append({ entries, scope, ttlMs }) {
557
- const listKey = rawKey(scope);
558
- const lock = await stateAdapter.acquireLock(
559
- `${listKey}:commit`,
560
- STATE_STORE_LOCK_TTL_MS
561
- );
562
- if (!lock) {
563
- throw new Error("Could not acquire session log commit lock");
564
- }
565
- try {
566
- const existingValue = await stateAdapter.get(listKey);
567
- const existingEntries = Array.isArray(existingValue) ? existingValue.map(decode) : (await stateAdapter.getList(listKey)).map(decode);
568
- await stateAdapter.set(
569
- listKey,
570
- [...existingEntries, ...entries],
571
- Math.max(1, ttlMs)
572
- );
573
- } finally {
574
- await stateAdapter.releaseLock(lock);
575
- }
576
- },
577
- async read(scope) {
578
- const listKey = rawKey(scope);
579
- const value = await stateAdapter.get(listKey);
580
- if (Array.isArray(value)) {
581
- return value.map(decode);
582
- }
583
- const values = await stateAdapter.getList(listKey);
584
- return values.map(decode);
585
- }
586
- };
587
- }
588
- async function defaultStore() {
589
- const { redisStateAdapter, stateAdapter } = await getConnectedStateContext();
590
- if (redisStateAdapter) {
591
- return redisStore(redisStateAdapter);
592
- }
593
- await stateAdapter.connect();
594
- return stateStore();
595
- }
596
- async function loadEntries(args) {
597
- const store = args.store ?? await defaultStore();
598
- return (await store.read(args)).map(decode);
599
- }
600
- async function loadActivityEntries(args) {
601
- const entries = await loadEntries(args);
602
- return projectionEntries(entries, args.sessionId).filter(isActivityEntry);
603
- }
604
- async function loadMessagesWithProvenance(args) {
605
- const messageCount = normalizeMessageCount(args.messageCount);
606
- if (messageCount === 0) {
607
- return { messages: [], provenance: [] };
608
- }
609
- const projection = project(await loadEntries(args), args.sessionId);
610
- return projection.messages.length >= messageCount ? {
611
- messages: projection.messages.slice(0, messageCount),
612
- provenance: projection.provenance.slice(0, messageCount)
613
- } : void 0;
614
- }
615
- async function loadProjection(args) {
616
- return project(await loadEntries(args), args.sessionId).messages;
617
- }
618
- async function loadProjectionWithProvenance(args) {
619
- return project(await loadEntries(args), args.sessionId);
620
- }
621
- async function loadConnectedMcpProviders(args) {
622
- return connectedMcpProviders(await loadEntries(args));
623
- }
624
- async function recordMcpProviderConnected(args) {
625
- const store = args.store ?? await defaultStore();
626
- const entries = await store.read(args);
627
- const sessionId = currentSessionId(entries);
628
- if (connectedMcpProviders(entries).includes(args.provider)) {
629
- return;
630
- }
631
- await store.append({
632
- scope: args,
633
- entries: [mcpProviderConnectedEntry(args.provider, sessionId)],
634
- ttlMs: args.ttlMs
635
- });
636
- }
637
- async function recordAuthorizationRequested(args) {
638
- const store = args.store ?? await defaultStore();
639
- const entries = await store.read(args);
640
- const sessionId = currentSessionId(entries);
641
- if (projectionEntries(entries).some(
642
- (entry) => entry.type === "authorization_requested" && entry.authorizationId === args.authorizationId
643
- )) {
644
- return;
645
- }
646
- await store.append({
647
- scope: args,
648
- entries: [
649
- authorizationRequestedEntry({
650
- createdAtMs: Date.now(),
651
- kind: args.kind,
652
- sessionId,
653
- provider: args.provider,
654
- actorId: args.actorId,
655
- authorizationId: args.authorizationId,
656
- delivery: args.delivery
657
- })
658
- ],
659
- ttlMs: args.ttlMs
660
- });
661
- }
662
- async function recordAuthorizationCompleted(args) {
663
- const store = args.store ?? await defaultStore();
664
- const entries = await store.read(args);
665
- const sessionId = currentSessionId(entries);
666
- if (projectionEntries(entries).some(
667
- (entry) => entry.type === "authorization_completed" && entry.authorizationId === args.authorizationId
668
- )) {
669
- return;
670
- }
671
- await store.append({
672
- scope: args,
673
- entries: [
674
- authorizationCompletedEntry({
675
- createdAtMs: Date.now(),
676
- kind: args.kind,
677
- sessionId,
678
- provider: args.provider,
679
- actorId: args.actorId,
680
- authorizationId: args.authorizationId
681
- })
682
- ],
683
- ttlMs: args.ttlMs
684
- });
685
- }
686
- async function recordToolExecutionStarted(args) {
687
- const store = args.store ?? await defaultStore();
688
- const entries = await store.read(args);
689
- const sessionId = args.sessionId ?? currentSessionId(entries);
690
- await store.append({
691
- scope: args,
692
- entries: [
693
- toolExecutionStartedEntry({
694
- args: args.args,
695
- createdAtMs: args.createdAtMs ?? Date.now(),
696
- sessionId,
697
- toolCallId: args.toolCallId,
698
- toolName: args.toolName
699
- })
700
- ],
701
- ttlMs: args.ttlMs
702
- });
703
- }
704
- async function recordSubagentStarted(args) {
705
- const store = args.store ?? await defaultStore();
706
- const entries = await store.read(args);
707
- const sessionId = args.sessionId ?? currentSessionId(entries);
708
- await store.append({
709
- scope: args,
710
- entries: [
711
- subagentStartedEntry({
712
- createdAtMs: args.createdAtMs ?? Date.now(),
713
- historyMode: args.historyMode,
714
- parentConversationId: args.parentConversationId,
715
- parentSessionId: args.parentSessionId,
716
- parentToolCallId: args.parentToolCallId,
717
- sessionId,
718
- subagentInvocationId: args.subagentInvocationId,
719
- subagentKind: args.subagentKind,
720
- transcriptRef: args.transcriptRef
721
- })
722
- ],
723
- ttlMs: args.ttlMs
724
- });
725
- }
726
- async function recordSubagentEnded(args) {
727
- const store = args.store ?? await defaultStore();
728
- const entries = await store.read(args);
729
- const sessionId = args.sessionId ?? currentSessionId(entries);
730
- await store.append({
731
- scope: args,
732
- entries: [
733
- subagentEndedEntry({
734
- createdAtMs: args.createdAtMs ?? Date.now(),
735
- errorCode: args.errorCode,
736
- outcome: args.outcome,
737
- sessionId,
738
- subagentInvocationId: args.subagentInvocationId,
739
- transcriptEndMessageIndex: args.transcriptEndMessageIndex,
740
- transcriptStartMessageIndex: args.transcriptStartMessageIndex
741
- })
742
- ],
743
- ttlMs: args.ttlMs
744
- });
745
- }
746
- async function commitMessages(args) {
747
- const store = args.store ?? await defaultStore();
748
- const entries = await store.read(args);
749
- const existingProjection = project(entries);
750
- const currentId = currentSessionId(entries);
751
- const nextProvenance = resolveCommitProvenance({
752
- existing: existingProjection,
753
- nextMessages: args.messages,
754
- ...args.provenance ? { explicitProvenance: args.provenance } : {},
755
- ...args.trailingMessageProvenance ? { trailingMessageProvenance: args.trailingMessageProvenance } : {},
756
- ...args.newMessageProvenance ? { newMessageProvenance: args.newMessageProvenance } : {}
757
- });
758
- const commit = commitEntries(
759
- existingProjection,
760
- args.messages,
761
- nextProvenance,
762
- currentId,
763
- entries
764
- );
765
- await store.append({
766
- scope: args,
767
- entries: commit.entries,
768
- ttlMs: args.ttlMs
769
- });
770
- return {
771
- sessionId: commit.sessionId,
772
- provenance: nextProvenance
773
- };
774
- }
775
- function instructionProvenanceFor(actor) {
776
- return instructionProvenance(actor);
777
- }
778
- var contextProvenance = unattributedContextProvenance;
779
- function parseStoredMessageProvenance(value, expectedLength) {
780
- if (value === void 0) {
781
- return Array.from(
782
- { length: expectedLength },
783
- () => unattributedContextProvenance
784
- );
785
- }
786
- const parsed = z2.array(piMessageProvenanceSchema).safeParse(value);
787
- if (!parsed.success || parsed.data.length !== expectedLength) {
788
- return void 0;
789
- }
790
- return parsed.data;
791
- }
792
-
793
- // src/chat/state/turn-session.ts
794
- import { THREAD_STATE_TTL_MS } from "chat";
795
- import {
796
- sourceSchema
797
- } from "@sentry/junior-plugin-api";
798
- var AGENT_TURN_SESSION_PREFIX = "junior:agent_turn_session";
799
- var AGENT_TURN_SESSION_INDEX_KEY = `${AGENT_TURN_SESSION_PREFIX}:index`;
800
- var AGENT_TURN_SESSION_INDEX_MAX_LENGTH = 5e3;
801
- var AGENT_TURN_SESSION_TTL_MS = THREAD_STATE_TTL_MS;
802
- function agentTurnSessionKey(conversationId, sessionId) {
803
- return `${AGENT_TURN_SESSION_PREFIX}:${conversationId}:${sessionId}`;
804
- }
805
- function agentTurnSessionConversationIndexKey(conversationId) {
806
- return `${AGENT_TURN_SESSION_PREFIX}:conversation:${conversationId}:index`;
807
- }
808
- function toFiniteNonNegativeNumber(value) {
809
- return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : void 0;
810
- }
811
- function toNonNegativeInteger(value) {
812
- return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : void 0;
813
- }
814
- function parseAgentTurnUsage(value) {
815
- if (!isRecord(value)) {
816
- return void 0;
817
- }
818
- const usage = {};
819
- for (const field of [
820
- "inputTokens",
821
- "outputTokens",
822
- "cachedInputTokens",
823
- "cacheCreationTokens",
824
- "totalTokens"
825
- ]) {
826
- const count = toFiniteNonNegativeNumber(value[field]);
827
- if (count !== void 0) {
828
- usage[field] = count;
829
- }
830
- }
831
- return Object.keys(usage).length > 0 ? usage : void 0;
832
- }
833
- function parseStoredRecord(value) {
834
- if (isRecord(value)) {
835
- return value;
836
- }
837
- if (typeof value !== "string") {
838
- return void 0;
839
- }
840
- try {
841
- const parsed = JSON.parse(value);
842
- return isRecord(parsed) ? parsed : void 0;
843
- } catch {
844
- return void 0;
845
- }
846
- }
847
- function parseAgentTurnSessionStatus(parsed) {
848
- const status = parsed.state;
849
- if (status === "running" || status === "awaiting_resume" || status === "completed" || status === "failed" || status === "abandoned") {
850
- return status;
851
- }
852
- return void 0;
853
- }
854
- function parseAgentTurnSurface(value) {
855
- return value === "slack" || value === "api" || value === "scheduler" || value === "internal" ? value : void 0;
856
- }
857
- function conversationExecutionFromSummary(summary) {
858
- const status = summary.state === "completed" || summary.state === "abandoned" ? "idle" : summary.state;
859
- return {
860
- status,
861
- runId: summary.sessionId,
862
- updatedAtMs: summary.updatedAtMs
863
- };
864
- }
865
- function parseSource(value) {
866
- const result = sourceSchema.safeParse(value);
867
- return result.success ? result.data : void 0;
868
- }
869
- function sessionLogActor(actor) {
870
- return actor?.platform === "slack" ? toStoredSlackActor(actor) : void 0;
871
- }
872
- function parseAgentTurnSessionFields(parsed) {
873
- const status = parseAgentTurnSessionStatus(parsed);
874
- if (!status) {
875
- return void 0;
876
- }
877
- const channelName = typeof parsed.channelName === "string" && parsed.channelName.trim() ? parsed.channelName.trim() : void 0;
878
- const conversationId = parsed.conversationId;
879
- const sessionId = parsed.sessionId;
880
- const sliceId = toFiniteNonNegativeNumber(parsed.sliceId);
881
- const version = toFiniteNonNegativeNumber(parsed.version);
882
- const updatedAtMs = toFiniteNonNegativeNumber(parsed.updatedAtMs);
883
- const cumulativeDurationMs = toFiniteNonNegativeNumber(parsed.cumulativeDurationMs) ?? 0;
884
- const cumulativeUsage = parseAgentTurnUsage(parsed.cumulativeUsage);
885
- const lastProgressAtMs = toFiniteNonNegativeNumber(parsed.lastProgressAtMs);
886
- const logSessionId = typeof parsed.logSessionId === "string" ? parsed.logSessionId : void 0;
887
- const actorValue = parsed.actor !== void 0 ? parsed.actor : parsed.requester;
888
- const actor = actorValue === void 0 ? void 0 : parseActor(actorValue);
889
- const startedAtMs = toFiniteNonNegativeNumber(parsed.startedAtMs);
890
- const surface = parseAgentTurnSurface(parsed.surface);
891
- const turnStartMessageIndex = toNonNegativeInteger(
892
- parsed.turnStartMessageIndex
893
- );
894
- const destination = parsed.destination === void 0 ? void 0 : parseDestination(parsed.destination);
895
- const source = parsed.source === void 0 ? void 0 : parseSource(parsed.source);
896
- if (typeof conversationId !== "string" || typeof sessionId !== "string" || sliceId === void 0 || version === void 0 || updatedAtMs === void 0 || parsed.destination !== void 0 && !destination || parsed.source !== void 0 && !source || actorValue !== void 0 && !actor) {
897
- return void 0;
898
- }
899
- return {
900
- version,
901
- ...channelName ? { channelName } : {},
902
- conversationId,
903
- sessionId,
904
- sliceId,
905
- state: status,
906
- startedAtMs: startedAtMs ?? updatedAtMs,
907
- lastProgressAtMs: lastProgressAtMs ?? updatedAtMs,
908
- updatedAtMs,
909
- cumulativeDurationMs,
910
- ...logSessionId ? { logSessionId } : {},
911
- ...cumulativeUsage ? { cumulativeUsage } : {},
912
- ...destination ? { destination } : {},
913
- ...source ? { source } : {},
914
- ...actor ? { actor } : {},
915
- ...Array.isArray(parsed.loadedSkillNames) ? {
916
- loadedSkillNames: parsed.loadedSkillNames.filter(
917
- (value) => typeof value === "string"
918
- )
919
- } : {},
920
- ...parsed.resumeReason === "timeout" || parsed.resumeReason === "auth" || parsed.resumeReason === "yield" ? { resumeReason: parsed.resumeReason } : {},
921
- ...typeof parsed.errorMessage === "string" ? { errorMessage: parsed.errorMessage } : {},
922
- ...typeof parsed.resumedFromSliceId === "number" ? { resumedFromSliceId: parsed.resumedFromSliceId } : {},
923
- ...surface ? { surface } : {},
924
- ...turnStartMessageIndex !== void 0 ? { turnStartMessageIndex } : {},
925
- ...typeof parsed.traceId === "string" ? { traceId: parsed.traceId } : {}
926
- };
927
- }
928
- function parseAgentTurnSessionRecord(value) {
929
- const parsed = parseStoredRecord(value);
930
- if (!parsed) {
931
- return void 0;
932
- }
933
- const fields = parseAgentTurnSessionFields(parsed);
934
- const committedMessageCount = toFiniteNonNegativeNumber(
935
- parsed.committedMessageCount
936
- );
937
- if (!fields || committedMessageCount === void 0) {
938
- return void 0;
939
- }
940
- const committedMessageProvenance = parseStoredMessageProvenance(
941
- parsed.committedMessageProvenance,
942
- committedMessageCount
943
- );
944
- if (!committedMessageProvenance) {
945
- return void 0;
946
- }
947
- return {
948
- ...fields,
949
- committedMessageCount,
950
- committedMessageProvenance
951
- };
952
- }
953
- function parseAgentTurnSessionSummary(value) {
954
- const stored = parseStoredRecord(value);
955
- if (!stored) {
956
- return void 0;
957
- }
958
- const parsed = parseAgentTurnSessionFields(stored);
959
- if (!parsed) {
960
- return void 0;
961
- }
962
- const {
963
- errorMessage: _errorMessage,
964
- logSessionId: _logSessionId,
965
- turnStartMessageIndex: _turnStartMessageIndex,
966
- ...summary
967
- } = parsed;
968
- return summary;
969
- }
970
- async function appendAgentTurnSessionSummary(summary, ttlMs) {
971
- const stateAdapter = getStateAdapter();
972
- await Promise.all([
973
- stateAdapter.appendToList(AGENT_TURN_SESSION_INDEX_KEY, summary, {
974
- maxLength: AGENT_TURN_SESSION_INDEX_MAX_LENGTH,
975
- ttlMs
976
- }),
977
- stateAdapter.appendToList(
978
- agentTurnSessionConversationIndexKey(summary.conversationId),
979
- summary,
980
- { ttlMs }
981
- )
982
- ]);
983
- }
984
- async function recordConversationActivityMetadata(args) {
985
- const conversationStore = args.conversationStore ?? getConversationStore();
986
- const source = args.summary.destination?.platform === "local" ? "local" : args.summary.surface;
987
- try {
988
- await conversationStore.recordActivity({
989
- activityAtMs: args.summary.updatedAtMs,
990
- channelName: args.summary.channelName,
991
- conversationId: args.summary.conversationId,
992
- destination: args.summary.destination,
993
- nowMs: args.nowMs,
994
- actor: sessionLogActor(args.summary.actor),
995
- source,
996
- visibility: args.destinationVisibility
997
- });
998
- await conversationStore.recordExecution({
999
- channelName: args.summary.channelName,
1000
- conversationId: args.summary.conversationId,
1001
- createdAtMs: args.summary.startedAtMs,
1002
- destination: args.summary.destination,
1003
- execution: conversationExecutionFromSummary(args.summary),
1004
- lastActivityAtMs: args.summary.updatedAtMs,
1005
- actor: sessionLogActor(args.summary.actor),
1006
- source,
1007
- updatedAtMs: args.nowMs,
1008
- visibility: args.destinationVisibility
1009
- });
1010
- } catch (error) {
1011
- logWarn(
1012
- "conversation_activity_metadata_update_failed",
1013
- { conversationId: args.summary.conversationId },
1014
- {
1015
- "exception.message": error instanceof Error ? error.message : String(error)
1016
- },
1017
- "Failed to update conversation activity metadata"
1018
- );
1019
- }
1020
- }
1021
- function materializePiProjection(committedMessageCount, includeProjectionTail, sessionMessages, sessionProjection) {
1022
- if (committedMessageCount === 0) {
1023
- return sessionProjection;
1024
- }
1025
- if (includeProjectionTail && sessionProjection.messages.length >= committedMessageCount) {
1026
- return sessionProjection;
1027
- }
1028
- if (sessionMessages) {
1029
- return sessionMessages;
1030
- }
1031
- if (sessionProjection.messages.length >= committedMessageCount) {
1032
- return {
1033
- messages: sessionProjection.messages.slice(0, committedMessageCount),
1034
- provenance: sessionProjection.provenance.slice(0, committedMessageCount)
1035
- };
1036
- }
1037
- return void 0;
1038
- }
1039
- function materializeAgentTurnSessionRecord(stored, piProjection) {
1040
- return {
1041
- version: stored.version,
1042
- ...stored.channelName ? { channelName: stored.channelName } : {},
1043
- conversationId: stored.conversationId,
1044
- sessionId: stored.sessionId,
1045
- sliceId: stored.sliceId,
1046
- state: stored.state,
1047
- startedAtMs: stored.startedAtMs,
1048
- lastProgressAtMs: stored.lastProgressAtMs,
1049
- updatedAtMs: stored.updatedAtMs,
1050
- piMessages: piProjection.messages,
1051
- piMessageProvenance: piProjection.provenance,
1052
- actors: instructionActors(piProjection.provenance),
1053
- cumulativeDurationMs: stored.cumulativeDurationMs,
1054
- ...stored.destination ? { destination: stored.destination } : {},
1055
- ...stored.source ? { source: stored.source } : {},
1056
- ...stored.cumulativeUsage ? { cumulativeUsage: stored.cumulativeUsage } : {},
1057
- ...stored.resumeReason ? { resumeReason: stored.resumeReason } : {},
1058
- ...stored.errorMessage ? { errorMessage: stored.errorMessage } : {},
1059
- ...stored.loadedSkillNames ? { loadedSkillNames: stored.loadedSkillNames } : {},
1060
- ...stored.actor ? { actor: stored.actor } : {},
1061
- ...stored.resumedFromSliceId !== void 0 ? { resumedFromSliceId: stored.resumedFromSliceId } : {},
1062
- ...stored.surface ? { surface: stored.surface } : {},
1063
- ...stored.traceId ? { traceId: stored.traceId } : {},
1064
- ...stored.turnStartMessageIndex !== void 0 ? { turnStartMessageIndex: stored.turnStartMessageIndex } : {}
1065
- };
1066
- }
1067
- async function getStoredAgentTurnSessionRecord(conversationId, sessionId) {
1068
- const stateAdapter = getStateAdapter();
1069
- await stateAdapter.connect();
1070
- const value = await stateAdapter.get(
1071
- agentTurnSessionKey(conversationId, sessionId)
1072
- );
1073
- return parseAgentTurnSessionRecord(value);
1074
- }
1075
- async function getAgentTurnSessionRecord(conversationId, sessionId) {
1076
- const parsed = await getStoredAgentTurnSessionRecord(
1077
- conversationId,
1078
- sessionId
1079
- );
1080
- if (!parsed) {
1081
- return void 0;
1082
- }
1083
- const sessionMessages = await loadMessagesWithProvenance({
1084
- conversationId,
1085
- messageCount: parsed.committedMessageCount,
1086
- ...parsed.logSessionId ? { sessionId: parsed.logSessionId } : {}
1087
- });
1088
- const sessionProjection = await loadProjectionWithProvenance({
1089
- conversationId,
1090
- ...parsed.logSessionId ? { sessionId: parsed.logSessionId } : {}
1091
- });
1092
- const piProjection = materializePiProjection(
1093
- parsed.committedMessageCount,
1094
- parsed.state === "running" || parsed.state === "awaiting_resume",
1095
- sessionMessages,
1096
- sessionProjection
1097
- );
1098
- if (!piProjection) {
1099
- return void 0;
1100
- }
1101
- return materializeAgentTurnSessionRecord(parsed, piProjection);
1102
- }
1103
- function buildStoredRecord(args) {
1104
- const nowMs = Date.now();
1105
- return {
1106
- version: (args.previousVersion ?? 0) + 1,
1107
- ...args.channelName ? { channelName: args.channelName } : {},
1108
- conversationId: args.conversationId,
1109
- sessionId: args.sessionId,
1110
- sliceId: args.sliceId,
1111
- state: args.state,
1112
- startedAtMs: args.startedAtMs ?? nowMs,
1113
- lastProgressAtMs: args.lastProgressAtMs ?? nowMs,
1114
- updatedAtMs: nowMs,
1115
- committedMessageCount: args.committedMessageCount,
1116
- committedMessageProvenance: args.committedMessageProvenance,
1117
- ...args.logSessionId ? { logSessionId: args.logSessionId } : {},
1118
- cumulativeDurationMs: args.cumulativeDurationMs,
1119
- ...args.cumulativeUsage ? { cumulativeUsage: args.cumulativeUsage } : {},
1120
- ...args.destination ? { destination: args.destination } : {},
1121
- ...args.source ? { source: args.source } : {},
1122
- ...args.actor ? { actor: args.actor } : {},
1123
- ...Array.isArray(args.loadedSkillNames) ? {
1124
- loadedSkillNames: args.loadedSkillNames.filter(
1125
- (value) => typeof value === "string"
1126
- )
1127
- } : {},
1128
- ...args.resumeReason ? { resumeReason: args.resumeReason } : {},
1129
- ...args.errorMessage ? { errorMessage: args.errorMessage } : {},
1130
- ...typeof args.resumedFromSliceId === "number" ? { resumedFromSliceId: args.resumedFromSliceId } : {},
1131
- ...args.surface ? { surface: args.surface } : {},
1132
- ...args.traceId ? { traceId: args.traceId } : {},
1133
- ...args.turnStartMessageIndex !== void 0 ? { turnStartMessageIndex: args.turnStartMessageIndex } : {}
1134
- };
1135
- }
1136
- async function setStoredRecord(args) {
1137
- const stateAdapter = getStateAdapter();
1138
- await stateAdapter.connect();
1139
- await stateAdapter.set(
1140
- agentTurnSessionKey(args.record.conversationId, args.record.sessionId),
1141
- args.record,
1142
- args.ttlMs
1143
- );
1144
- const {
1145
- committedMessageCount: _committedMessageCount,
1146
- committedMessageProvenance: _committedMessageProvenance,
1147
- errorMessage: _errorMessage,
1148
- logSessionId: _logSessionId,
1149
- turnStartMessageIndex: _turnStartMessageIndex,
1150
- ...summary
1151
- } = args.record;
1152
- await appendAgentTurnSessionSummary(summary, args.ttlMs);
1153
- await recordConversationActivityMetadata({
1154
- conversationStore: args.conversationStore,
1155
- destinationVisibility: args.destinationVisibility,
1156
- nowMs: Date.now(),
1157
- summary
1158
- });
1159
- return materializeAgentTurnSessionRecord(args.record, {
1160
- messages: [...args.piMessages],
1161
- provenance: [...args.piMessageProvenance]
1162
- });
1163
- }
1164
- async function updateAgentTurnSessionState(args) {
1165
- const parsed = await getStoredAgentTurnSessionRecord(
1166
- args.existing.conversationId,
1167
- args.existing.sessionId
1168
- );
1169
- if (!parsed || parsed.version !== args.existing.version) {
1170
- return void 0;
1171
- }
1172
- return await setStoredRecord({
1173
- piMessages: args.existing.piMessages,
1174
- piMessageProvenance: args.existing.piMessageProvenance,
1175
- ttlMs: AGENT_TURN_SESSION_TTL_MS,
1176
- record: buildStoredRecord({
1177
- conversationId: args.existing.conversationId,
1178
- sessionId: args.existing.sessionId,
1179
- sliceId: args.existing.sliceId,
1180
- state: args.state,
1181
- committedMessageCount: parsed.committedMessageCount,
1182
- committedMessageProvenance: parsed.committedMessageProvenance,
1183
- ...parsed.channelName ? { channelName: parsed.channelName } : {},
1184
- startedAtMs: parsed.startedAtMs,
1185
- lastProgressAtMs: parsed.lastProgressAtMs,
1186
- previousVersion: parsed.version,
1187
- ...parsed.logSessionId ? { logSessionId: parsed.logSessionId } : {},
1188
- cumulativeDurationMs: args.existing.cumulativeDurationMs,
1189
- ...args.existing.cumulativeUsage ? { cumulativeUsage: args.existing.cumulativeUsage } : {},
1190
- ...args.existing.destination ? { destination: args.existing.destination } : {},
1191
- ...args.existing.source ? { source: args.existing.source } : {},
1192
- ...args.existing.loadedSkillNames ? { loadedSkillNames: args.existing.loadedSkillNames } : {},
1193
- ...args.existing.actor ? { actor: args.existing.actor } : {},
1194
- ...args.existing.resumeReason ? { resumeReason: args.existing.resumeReason } : {},
1195
- ...args.existing.resumedFromSliceId !== void 0 ? { resumedFromSliceId: args.existing.resumedFromSliceId } : {},
1196
- ...args.existing.surface ? { surface: args.existing.surface } : {},
1197
- ...args.existing.traceId ? { traceId: args.existing.traceId } : {},
1198
- ...args.existing.turnStartMessageIndex !== void 0 ? { turnStartMessageIndex: args.existing.turnStartMessageIndex } : {},
1199
- ...args.errorMessage ?? args.existing.errorMessage ? { errorMessage: args.errorMessage ?? args.existing.errorMessage } : {}
1200
- })
1201
- });
1202
- }
1203
- async function upsertAgentTurnSessionRecord(args) {
1204
- const existingRecord = await getStoredAgentTurnSessionRecord(
1205
- args.conversationId,
1206
- args.sessionId
1207
- );
1208
- const ttlMs = Math.max(1, args.ttlMs ?? AGENT_TURN_SESSION_TTL_MS);
1209
- const instructionActor = args.actor ?? existingRecord?.actor;
1210
- const commit = await commitMessages({
1211
- conversationId: args.conversationId,
1212
- messages: args.piMessages,
1213
- ...instructionActor ? { newMessageProvenance: instructionProvenanceFor(instructionActor) } : {},
1214
- ...args.trailingMessageProvenance ? { trailingMessageProvenance: args.trailingMessageProvenance } : {},
1215
- ttlMs
1216
- });
1217
- return await setStoredRecord({
1218
- conversationStore: args.conversationStore,
1219
- destinationVisibility: args.destinationVisibility,
1220
- piMessages: args.piMessages,
1221
- piMessageProvenance: commit.provenance,
1222
- ttlMs,
1223
- record: buildStoredRecord({
1224
- committedMessageProvenance: commit.provenance,
1225
- ...args.channelName ?? existingRecord?.channelName ? { channelName: args.channelName ?? existingRecord?.channelName } : {},
1226
- conversationId: args.conversationId,
1227
- sessionId: args.sessionId,
1228
- sliceId: args.sliceId,
1229
- state: args.state,
1230
- ...existingRecord?.startedAtMs !== void 0 ? { startedAtMs: existingRecord.startedAtMs } : {},
1231
- ...args.lastProgressAtMs !== void 0 ? { lastProgressAtMs: args.lastProgressAtMs } : {},
1232
- committedMessageCount: args.piMessages.length,
1233
- logSessionId: commit.sessionId,
1234
- previousVersion: existingRecord?.version,
1235
- cumulativeDurationMs: toFiniteNonNegativeNumber(args.cumulativeDurationMs) ?? existingRecord?.cumulativeDurationMs ?? 0,
1236
- ...args.cumulativeUsage ? { cumulativeUsage: args.cumulativeUsage } : {},
1237
- ...args.destination ?? existingRecord?.destination ? { destination: args.destination ?? existingRecord?.destination } : {},
1238
- ...args.source ?? existingRecord?.source ? { source: args.source ?? existingRecord?.source } : {},
1239
- ...args.loadedSkillNames ? { loadedSkillNames: args.loadedSkillNames } : {},
1240
- ...args.actor ?? existingRecord?.actor ? { actor: args.actor ?? existingRecord?.actor } : {},
1241
- ...args.resumeReason ? { resumeReason: args.resumeReason } : {},
1242
- ...args.errorMessage ? { errorMessage: args.errorMessage } : {},
1243
- ...args.resumedFromSliceId !== void 0 ? { resumedFromSliceId: args.resumedFromSliceId } : {},
1244
- ...args.surface ?? existingRecord?.surface ? { surface: args.surface ?? existingRecord?.surface } : {},
1245
- ...args.traceId ?? existingRecord?.traceId ? { traceId: args.traceId ?? existingRecord?.traceId } : {},
1246
- ...(args.turnStartMessageIndex ?? existingRecord?.turnStartMessageIndex) !== void 0 ? {
1247
- turnStartMessageIndex: args.turnStartMessageIndex ?? existingRecord?.turnStartMessageIndex
1248
- } : {}
1249
- })
1250
- });
1251
- }
1252
- async function recordAgentTurnSessionSummary(args) {
1253
- const existing = await getStoredAgentTurnSessionRecord(
1254
- args.conversationId,
1255
- args.sessionId
1256
- );
1257
- const nowMs = Date.now();
1258
- const ttlMs = Math.max(1, args.ttlMs ?? AGENT_TURN_SESSION_TTL_MS);
1259
- const summary = {
1260
- version: existing?.version ?? 0,
1261
- ...args.channelName ?? existing?.channelName ? { channelName: args.channelName ?? existing?.channelName } : {},
1262
- conversationId: args.conversationId,
1263
- sessionId: args.sessionId,
1264
- sliceId: args.sliceId,
1265
- startedAtMs: existing?.startedAtMs ?? args.startedAtMs ?? nowMs,
1266
- lastProgressAtMs: args.lastProgressAtMs ?? nowMs,
1267
- state: args.state,
1268
- updatedAtMs: nowMs,
1269
- cumulativeDurationMs: toFiniteNonNegativeNumber(args.cumulativeDurationMs) ?? existing?.cumulativeDurationMs ?? 0,
1270
- ...args.cumulativeUsage ?? existing?.cumulativeUsage ? { cumulativeUsage: args.cumulativeUsage ?? existing?.cumulativeUsage } : {},
1271
- ...args.destination ?? existing?.destination ? { destination: args.destination ?? existing?.destination } : {},
1272
- ...args.source ?? existing?.source ? { source: args.source ?? existing?.source } : {},
1273
- ...args.actor ?? existing?.actor ? { actor: args.actor ?? existing?.actor } : {},
1274
- ...Array.isArray(args.loadedSkillNames) ? {
1275
- loadedSkillNames: args.loadedSkillNames.filter(
1276
- (value) => typeof value === "string"
1277
- )
1278
- } : existing?.loadedSkillNames ? { loadedSkillNames: existing.loadedSkillNames } : {},
1279
- ...args.resumeReason ? { resumeReason: args.resumeReason } : {},
1280
- ...args.surface ?? existing?.surface ? { surface: args.surface ?? existing?.surface } : {},
1281
- ...args.traceId ?? existing?.traceId ? { traceId: args.traceId ?? existing?.traceId } : {}
1282
- };
1283
- await appendAgentTurnSessionSummary(summary, ttlMs);
1284
- await recordConversationActivityMetadata({
1285
- conversationStore: args.conversationStore,
1286
- destinationVisibility: args.destinationVisibility,
1287
- nowMs,
1288
- summary
1289
- });
1290
- }
1291
- async function readAgentTurnSessionSummariesFromIndex(key2) {
1292
- const stateAdapter = getStateAdapter();
1293
- await stateAdapter.connect();
1294
- const values = await stateAdapter.getList(key2);
1295
- const summaries = /* @__PURE__ */ new Map();
1296
- for (const value of [...values].reverse()) {
1297
- const summary = parseAgentTurnSessionSummary(value);
1298
- if (!summary) {
1299
- continue;
1300
- }
1301
- const key3 = `${summary.conversationId}:${summary.sessionId}`;
1302
- if (!summaries.has(key3)) {
1303
- summaries.set(key3, summary);
1304
- }
1305
- }
1306
- return [...summaries.values()].sort(
1307
- (left, right) => right.updatedAtMs - left.updatedAtMs
1308
- );
1309
- }
1310
- async function listAgentTurnSessionSummariesForConversation(conversationId) {
1311
- const summaries = await readAgentTurnSessionSummariesFromIndex(
1312
- agentTurnSessionConversationIndexKey(conversationId)
1313
- );
1314
- if (summaries.length > 0) {
1315
- return summaries;
1316
- }
1317
- return (await readAgentTurnSessionSummariesFromIndex(AGENT_TURN_SESSION_INDEX_KEY)).filter((summary) => summary.conversationId === conversationId);
1318
- }
1319
- async function abandonAgentTurnSessionRecord(args) {
1320
- const existing = await getAgentTurnSessionRecord(
1321
- args.conversationId,
1322
- args.sessionId
1323
- );
1324
- if (!existing || existing.state === "completed" || existing.state === "failed" || existing.state === "abandoned") {
1325
- return void 0;
1326
- }
1327
- return await updateAgentTurnSessionState({
1328
- existing,
1329
- state: "abandoned",
1330
- errorMessage: args.errorMessage ?? existing.errorMessage
1331
- });
1332
- }
1333
- async function failAgentTurnSessionRecord(args) {
1334
- const existing = await getAgentTurnSessionRecord(
1335
- args.conversationId,
1336
- args.sessionId
1337
- );
1338
- if (!existing || existing.state === "completed" || existing.state === "failed" || existing.state === "abandoned" || existing.version !== args.expectedVersion) {
1339
- return void 0;
1340
- }
1341
- return await updateAgentTurnSessionState({
1342
- existing,
1343
- state: "failed",
1344
- errorMessage: args.errorMessage ?? existing.errorMessage
1345
- });
1346
- }
1347
-
1348
- // src/chat/interruption-marker.ts
1349
- var INTERRUPTED_MARKER = "\n\n[Response interrupted before completion]";
1350
- function getInterruptionMarker() {
1351
- return INTERRUPTED_MARKER;
1352
- }
1353
-
1354
- export {
1355
- piContentMessageSchema,
1356
- instructionActors,
1357
- loadActivityEntries,
1358
- loadProjection,
1359
- loadProjectionWithProvenance,
1360
- loadConnectedMcpProviders,
1361
- recordMcpProviderConnected,
1362
- recordAuthorizationRequested,
1363
- recordAuthorizationCompleted,
1364
- recordToolExecutionStarted,
1365
- recordSubagentStarted,
1366
- recordSubagentEnded,
1367
- commitMessages,
1368
- instructionProvenanceFor,
1369
- contextProvenance,
1370
- getAgentTurnSessionRecord,
1371
- upsertAgentTurnSessionRecord,
1372
- recordAgentTurnSessionSummary,
1373
- listAgentTurnSessionSummariesForConversation,
1374
- abandonAgentTurnSessionRecord,
1375
- failAgentTurnSessionRecord,
1376
- getInterruptionMarker
1377
- };