@sentry/junior 0.95.0 → 0.97.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 (144) hide show
  1. package/dist/{agent-hooks-FTQ5EGPO.js → agent-hooks-XSUIVRQS.js} +10 -8
  2. package/dist/{reporting → api}/conversations/activity.d.ts +1 -1
  3. package/dist/api/conversations/detail-projection.d.ts +10 -0
  4. package/dist/api/conversations/detail.d.ts +3 -0
  5. package/dist/api/conversations/detail.query.d.ts +3 -0
  6. package/dist/api/conversations/list.d.ts +3 -0
  7. package/dist/api/conversations/list.query.d.ts +94 -0
  8. package/dist/api/conversations/projection.d.ts +14 -0
  9. package/dist/api/conversations/schema.d.ts +683 -0
  10. package/dist/{reporting → api}/conversations/shared.d.ts +1 -5
  11. package/dist/api/conversations/stats.d.ts +3 -0
  12. package/dist/api/conversations/stats.query.d.ts +3 -0
  13. package/dist/api/conversations/subagent.d.ts +3 -0
  14. package/dist/{reporting → api}/conversations/transcript.d.ts +4 -4
  15. package/dist/api/people/list.d.ts +1 -2
  16. package/dist/api/people/list.query.d.ts +3 -4
  17. package/dist/api/people/profile.d.ts +1 -2
  18. package/dist/api/people/profile.query.d.ts +3 -4
  19. package/dist/api/people/schema.d.ts +193 -0
  20. package/dist/api/people/shared.d.ts +31 -9
  21. package/dist/api/schema.d.ts +20 -0
  22. package/dist/api/schema.js +50 -0
  23. package/dist/api-reference.d.ts +4 -3
  24. package/dist/api.d.ts +3 -0
  25. package/dist/api.js +156 -0
  26. package/dist/app.d.ts +1 -4
  27. package/dist/app.js +108 -370
  28. package/dist/build/virtual-config.d.ts +2 -2
  29. package/dist/{catalog-runtime-2D7IVKUT.js → catalog-runtime-PFHVMHDR.js} +5 -4
  30. package/dist/chat/agent/resume.d.ts +3 -1
  31. package/dist/chat/agent/tools.d.ts +2 -1
  32. package/dist/chat/config.d.ts +1 -8
  33. package/dist/chat/conversations/history.d.ts +241 -27
  34. package/dist/chat/conversations/legacy-advisor-session.d.ts +7 -0
  35. package/dist/chat/conversations/legacy-import.d.ts +2 -2
  36. package/dist/chat/conversations/projection.d.ts +19 -3
  37. package/dist/chat/conversations/sql/legacy-history-import.d.ts +1 -1
  38. package/dist/chat/conversations/sql/store.d.ts +15 -9
  39. package/dist/chat/conversations/store.d.ts +9 -4
  40. package/dist/chat/logging.d.ts +2 -2
  41. package/dist/chat/model-profile.d.ts +14 -0
  42. package/dist/chat/pi/transcript.d.ts +5 -3
  43. package/dist/chat/plugins/auth/oauth-request.d.ts +2 -0
  44. package/dist/chat/resource-events/notification.d.ts +2 -0
  45. package/dist/chat/resource-events/store.d.ts +2 -2
  46. package/dist/chat/runtime/agent-run-outcome.d.ts +3 -0
  47. package/dist/chat/sentry.d.ts +1 -1
  48. package/dist/chat/services/context-compaction.d.ts +15 -0
  49. package/dist/chat/services/turn-result.d.ts +1 -0
  50. package/dist/chat/services/turn-session-record.d.ts +6 -6
  51. package/dist/chat/state/turn-session.d.ts +18 -5
  52. package/dist/chat/task-execution/store.d.ts +2 -2
  53. package/dist/chat/tools/handoff/tool.d.ts +45 -0
  54. package/dist/chat/tools/types.d.ts +7 -2
  55. package/dist/chat/usage.d.ts +27 -13
  56. package/dist/{chunk-6ONME5IG.js → chunk-35BNLDOJ.js} +339 -578
  57. package/dist/{chunk-HDTO3A74.js → chunk-3ECW2K2O.js} +8 -3
  58. package/dist/{chunk-CRRBJ3JP.js → chunk-3F4OPKGF.js} +90 -56
  59. package/dist/chunk-3V7OFJZC.js +264 -0
  60. package/dist/chunk-4ZNGQH7C.js +25 -0
  61. package/dist/{chunk-NSCHU54X.js → chunk-5HLDPVYS.js} +15 -448
  62. package/dist/{chunk-3DA7X2U3.js → chunk-6GWA276C.js} +15 -0
  63. package/dist/{chunk-HZNJLKKI.js → chunk-6U26PYI5.js} +24 -14
  64. package/dist/chunk-AUUCAFDE.js +546 -0
  65. package/dist/{chunk-6APU57E6.js → chunk-B3IT5END.js} +41 -260
  66. package/dist/chunk-CEA3A3UA.js +86 -0
  67. package/dist/{chunk-AYP4ERVZ.js → chunk-D5KZYS4T.js} +1 -1
  68. package/dist/{chunk-GUE7HTNR.js → chunk-EEZCY5WX.js} +79 -29
  69. package/dist/{chunk-E3E2XNCN.js → chunk-EOWXRY5E.js} +2 -2
  70. package/dist/{chunk-5XMNOD3S.js → chunk-FBHZJFHI.js} +3 -3
  71. package/dist/{chunk-CZEX6KIQ.js → chunk-G3E7SCME.js} +0 -23
  72. package/dist/chunk-GUAP3H7O.js +319 -0
  73. package/dist/{chunk-WCMQJE4F.js → chunk-H66UCBPW.js} +7 -5
  74. package/dist/{chunk-WPOJ443W.js → chunk-I35CTGPO.js} +58 -6
  75. package/dist/{chunk-GVOUCI2O.js → chunk-LMJPRYHP.js} +16 -6
  76. package/dist/chunk-LUAE4MGW.js +199 -0
  77. package/dist/{chunk-GY34VGP5.js → chunk-LVA4I4H7.js} +3 -1
  78. package/dist/chunk-LVUKF5CE.js +63 -0
  79. package/dist/{chunk-EKNJM5IG.js → chunk-NG2AV7IB.js} +2 -72
  80. package/dist/chunk-ON6YKIQ7.js +260 -0
  81. package/dist/chunk-PDO5BLNM.js +22 -0
  82. package/dist/chunk-QNVHH5PU.js +20 -0
  83. package/dist/{chunk-XX4N4E6C.js → chunk-T533JLM3.js} +9 -11
  84. package/dist/chunk-UAMKJPDF.js +11 -0
  85. package/dist/chunk-VFH4ZKZT.js +66 -0
  86. package/dist/{chunk-KDPCGVIT.js → chunk-WGXMTFNU.js} +17 -75
  87. package/dist/{chunk-WAGQ377B.js → chunk-WJOSZOON.js} +288 -263
  88. package/dist/chunk-WTYEKPXU.js +451 -0
  89. package/dist/{chunk-HCXXB35T.js → chunk-XIRPQQVE.js} +613 -369
  90. package/dist/cli/chat.js +26 -23
  91. package/dist/cli/check.js +6 -5
  92. package/dist/cli/init.js +12 -0
  93. package/dist/cli/main.js +1 -1
  94. package/dist/cli/plugins.js +14 -11
  95. package/dist/cli/snapshot-warmup.js +10 -8
  96. package/dist/cli/upgrade.js +267 -139
  97. package/dist/db/db.d.ts +4 -0
  98. package/dist/db/schema/conversations.d.ts +128 -0
  99. package/dist/db/schema.d.ts +129 -60
  100. package/dist/{db-W55B74OP.js → db-BWXYIKFQ.js} +5 -5
  101. package/dist/detail-GA6NXWQJ.js +43 -0
  102. package/dist/discovery-RMHYSRL7.js +43 -0
  103. package/dist/handlers/health.d.ts +3 -0
  104. package/dist/instrumentation.js +2 -2
  105. package/dist/{legacy-import-ZPLGLAFD.js → legacy-import-3NQJVGQL.js} +6 -6
  106. package/dist/{api/people/list.js → list-A3WFRIYX.js} +26 -16
  107. package/dist/list-UXJI5Q5X.js +27 -0
  108. package/dist/nitro.d.ts +1 -1
  109. package/dist/nitro.js +2 -1
  110. package/dist/plugin-conversations-DDNGC35A.js +36 -0
  111. package/dist/{api/people/profile.js → profile-4RYDXWTF.js} +33 -18
  112. package/dist/reporting/plugin-conversations.d.ts +3 -0
  113. package/dist/reporting-schema.d.ts +140 -0
  114. package/dist/reporting.d.ts +12 -81
  115. package/dist/{runner-OOSBDYRK.js → runner-JALSYH2P.js} +19 -14
  116. package/dist/{sentry-EGFOV3DH.js → sentry-JMWTS32N.js} +11 -1
  117. package/dist/skills-MAZXZ2KE.js +26 -0
  118. package/dist/stats-XKXH3PTY.js +217 -0
  119. package/dist/subagent-TZ55XY37.js +48 -0
  120. package/dist/usage-schema.d.ts +25 -0
  121. package/dist/{validation-QCGRFRFZ.js → validation-FMEAEKCY.js} +6 -5
  122. package/migrations/0000_initial.sql +115 -0
  123. package/migrations/0001_conversation_metrics.sql +4 -0
  124. package/migrations/README.md +12 -30
  125. package/migrations/meta/0000_snapshot.json +1 -33
  126. package/migrations/meta/0001_snapshot.json +972 -0
  127. package/migrations/meta/_journal.json +9 -2
  128. package/package.json +14 -18
  129. package/dist/api/people/types.d.ts +0 -85
  130. package/dist/chat/advisor-request.d.ts +0 -4
  131. package/dist/chat/conversations/sql/migrations.d.ts +0 -22
  132. package/dist/chat/tools/advisor/session-store.d.ts +0 -9
  133. package/dist/chat/tools/advisor/tool.d.ts +0 -72
  134. package/dist/chunk-N4RNJ32C.js +0 -48
  135. package/dist/chunk-RAIB6WSG.js +0 -142
  136. package/dist/db/schema/migrations.d.ts +0 -58
  137. package/dist/reporting/conversations/context.d.ts +0 -8
  138. package/dist/reporting/conversations/details.d.ts +0 -6
  139. package/dist/reporting/conversations/index.d.ts +0 -4
  140. package/dist/reporting/conversations/statistics.d.ts +0 -4
  141. package/dist/reporting/conversations/summaries.d.ts +0 -17
  142. package/dist/reporting/conversations/types.d.ts +0 -178
  143. package/dist/reporting/conversations.d.ts +0 -1
  144. package/dist/reporting.js +0 -1065
package/dist/app.js CHANGED
@@ -5,7 +5,15 @@ import {
5
5
  processPluginTask,
6
6
  requireTurnFailureEventId,
7
7
  scheduleSessionCompletedPluginTasks
8
- } from "./chunk-XX4N4E6C.js";
8
+ } from "./chunk-T533JLM3.js";
9
+ import {
10
+ buildSentryConversationUrl
11
+ } from "./chunk-LVUKF5CE.js";
12
+ import {
13
+ conversationVisibilityFromSlackChannelType,
14
+ resolveSlackChannelTypeFromMessage,
15
+ resolveSlackConversationContext
16
+ } from "./chunk-NG2AV7IB.js";
9
17
  import {
10
18
  CONVERSATION_WORK_CHECK_IN_INTERVAL_MS,
11
19
  CONVERSATION_WORK_STALE_ENQUEUE_MS,
@@ -29,7 +37,11 @@ import {
29
37
  requestConversationContinuation,
30
38
  requestConversationWork,
31
39
  startConversationWork
32
- } from "./chunk-5XMNOD3S.js";
40
+ } from "./chunk-FBHZJFHI.js";
41
+ import {
42
+ GET
43
+ } from "./chunk-QNVHH5PU.js";
44
+ import "./chunk-CEA3A3UA.js";
33
45
  import {
34
46
  getVercelConversationWorkQueue,
35
47
  resolveConversationWorkQueueTopic,
@@ -40,17 +52,10 @@ import {
40
52
  createVercelQueueClient,
41
53
  verifyPluginTaskQueueMessage
42
54
  } from "./chunk-KNFROR7R.js";
43
- import {
44
- GET,
45
- buildSentryConversationUrl,
46
- conversationVisibilityFromSlackChannelType,
47
- resolveSlackChannelTypeFromMessage,
48
- resolveSlackConversationContext
49
- } from "./chunk-EKNJM5IG.js";
50
55
  import {
51
56
  validatePluginEgressCredentialHooks,
52
57
  validatePluginRegistrations
53
- } from "./chunk-AYP4ERVZ.js";
58
+ } from "./chunk-D5KZYS4T.js";
54
59
  import {
55
60
  defineJuniorPlugins,
56
61
  pluginCatalogConfigFromEnv,
@@ -66,6 +71,7 @@ import {
66
71
  buildSlackOutputMessage,
67
72
  buildSteeringPiMessage,
68
73
  createAgentRunner,
74
+ createContextCompactor,
69
75
  createUserTokenStore,
70
76
  deleteMcpAuthSession,
71
77
  deleteMcpAuthSessionsForUserProvider,
@@ -98,7 +104,7 @@ import {
98
104
  splitSlackReplyText,
99
105
  startOAuthFlow,
100
106
  truncateStatusText
101
- } from "./chunk-HCXXB35T.js";
107
+ } from "./chunk-XIRPQQVE.js";
102
108
  import {
103
109
  CooperativeTurnYieldError,
104
110
  TurnInputCommitLostError,
@@ -127,31 +133,26 @@ import {
127
133
  persistWithRetry,
128
134
  persistYieldSessionRecord,
129
135
  startActiveTurn
130
- } from "./chunk-KDPCGVIT.js";
131
- import {
132
- coerceThreadConversationState
133
- } from "./chunk-RAIB6WSG.js";
134
- import "./chunk-WCMQJE4F.js";
135
- import "./chunk-CM5EZD5F.js";
136
- import "./chunk-N4RNJ32C.js";
136
+ } from "./chunk-WGXMTFNU.js";
137
137
  import {
138
+ JUNIOR_THREAD_STATE_TTL_MS,
138
139
  abandonAgentTurnSessionRecord,
139
- commitMessages,
140
+ coerceThreadConversationState,
140
141
  failAgentTurnSessionRecord,
141
142
  getAgentTurnSessionRecord,
142
143
  listAgentTurnSessionSummariesForConversation,
144
+ recordAgentTurnSessionSummary
145
+ } from "./chunk-WJOSZOON.js";
146
+ import {
147
+ commitMessages,
148
+ loadConversationProjection,
143
149
  loadProjection,
144
- loadProjectionWithProvenance,
145
- recordAgentTurnSessionSummary,
146
150
  recordAuthorizationCompleted
147
- } from "./chunk-WAGQ377B.js";
151
+ } from "./chunk-GUAP3H7O.js";
148
152
  import {
149
- JUNIOR_THREAD_STATE_TTL_MS,
150
153
  buildConversationContext,
151
154
  createConversationMemoryService,
152
- estimateTextTokens,
153
155
  generateConversationId,
154
- getAgentContextCompactionTriggerTokens,
155
156
  getConversationMessageSlackTs,
156
157
  getThreadTitleSourceMessage,
157
158
  hydrateConversationMessages,
@@ -162,36 +163,37 @@ import {
162
163
  persistConversationMessages,
163
164
  updateConversationStats,
164
165
  upsertConversationMessage
165
- } from "./chunk-CRRBJ3JP.js";
166
+ } from "./chunk-3F4OPKGF.js";
167
+ import "./chunk-H66UCBPW.js";
168
+ import "./chunk-PDO5BLNM.js";
169
+ import "./chunk-CM5EZD5F.js";
166
170
  import {
167
- SlackActionError,
168
171
  bindSlackDirectCredentialSubject,
169
- downloadPrivateSlackFile,
170
- getHeaderString,
171
172
  getPluginApiRoutes,
172
173
  getPluginRoutes,
173
174
  getPluginSlackConversationLink,
174
175
  getPlugins,
176
+ setPlugins,
177
+ validatePlugins,
178
+ verifySlackDirectCredentialSubject
179
+ } from "./chunk-5HLDPVYS.js";
180
+ import {
181
+ SlackActionError,
182
+ downloadPrivateSlackFile,
183
+ getHeaderString,
175
184
  getSlackClient,
176
185
  getWorkspaceTeamId,
177
186
  isDmChannel,
178
187
  normalizeSlackConversationId,
179
188
  runWithSlackInstallationToken,
180
- runWithWorkspaceTeamId,
181
- setPlugins,
182
- validatePlugins,
183
- verifySlackDirectCredentialSubject
184
- } from "./chunk-NSCHU54X.js";
189
+ runWithWorkspaceTeamId
190
+ } from "./chunk-WTYEKPXU.js";
185
191
  import {
186
192
  createPluginLogger,
187
193
  createPluginState
188
- } from "./chunk-E3E2XNCN.js";
189
- import {
190
- sleep
191
- } from "./chunk-CZEX6KIQ.js";
194
+ } from "./chunk-EOWXRY5E.js";
192
195
  import {
193
196
  contextProvenance,
194
- getAgentStepStore,
195
197
  getConversationStore,
196
198
  getDb,
197
199
  getSqlExecutor,
@@ -200,9 +202,14 @@ import {
200
202
  juniorConversationMessages,
201
203
  juniorConversations,
202
204
  juniorDestinations
203
- } from "./chunk-6ONME5IG.js";
205
+ } from "./chunk-35BNLDOJ.js";
206
+ import "./chunk-G3E7SCME.js";
207
+ import {
208
+ sleep
209
+ } from "./chunk-4ZNGQH7C.js";
204
210
  import {
205
211
  FUNCTION_TIMEOUT_BUFFER_SECONDS,
212
+ STANDARD_MODEL_PROFILE,
206
213
  acquireActiveLock,
207
214
  botConfig,
208
215
  completeObject,
@@ -217,18 +224,19 @@ import {
217
224
  getSlackSigningSecret,
218
225
  getStateAdapter,
219
226
  isProviderRetryError,
227
+ modelIdForProfile,
220
228
  normalizeSlackEmojiName,
229
+ retainRuntimeTurnContext,
221
230
  setSlackReactionConfig,
222
231
  stripRuntimeTurnContext,
223
- trimTrailingAssistantMessages,
224
- unwrapCurrentInstruction
225
- } from "./chunk-GUE7HTNR.js";
232
+ trimTrailingAssistantMessages
233
+ } from "./chunk-EEZCY5WX.js";
226
234
  import {
227
235
  parseSlackThreadId,
228
236
  readSlackRawMessageContext,
229
237
  resolveSlackChannelIdFromMessage,
230
238
  resolveSlackChannelIdFromThreadId
231
- } from "./chunk-GY34VGP5.js";
239
+ } from "./chunk-LVA4I4H7.js";
232
240
  import {
233
241
  createSlackDestination,
234
242
  destinationKey,
@@ -238,13 +246,13 @@ import {
238
246
  } from "./chunk-B7PUBQQM.js";
239
247
  import {
240
248
  discoverSkills
241
- } from "./chunk-HDTO3A74.js";
249
+ } from "./chunk-3ECW2K2O.js";
242
250
  import {
243
251
  buildOAuthTokenRequest,
244
252
  hasRequiredOAuthScope,
245
253
  parseOAuthTokenResponse,
246
254
  pluginCatalogRuntime
247
- } from "./chunk-GVOUCI2O.js";
255
+ } from "./chunk-LMJPRYHP.js";
248
256
  import {
249
257
  buildTurnFailureResponse,
250
258
  createActor,
@@ -266,21 +274,22 @@ import {
266
274
  setTags,
267
275
  withContext,
268
276
  withSpan
269
- } from "./chunk-WPOJ443W.js";
277
+ } from "./chunk-I35CTGPO.js";
270
278
  import {
271
279
  toOptionalString
272
280
  } from "./chunk-OB42YVAE.js";
273
281
  import {
274
282
  continueTrace
275
- } from "./chunk-3DA7X2U3.js";
276
- import {
277
- homeDir
278
- } from "./chunk-6APU57E6.js";
283
+ } from "./chunk-6GWA276C.js";
284
+ import "./chunk-B3IT5END.js";
279
285
  import {
280
286
  JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE,
281
287
  parseSlackChannelId,
282
288
  parseSlackMessageTs
283
289
  } from "./chunk-7FBGKXPE.js";
290
+ import {
291
+ homeDir
292
+ } from "./chunk-3V7OFJZC.js";
284
293
  import "./chunk-MLKGABMK.js";
285
294
 
286
295
  // src/app.ts
@@ -1138,6 +1147,7 @@ async function runAgentDispatchSlice(callback, deps) {
1138
1147
  sessionId: turnId,
1139
1148
  sliceId: 1,
1140
1149
  messages: reply.piMessages,
1150
+ modelId: reply.diagnostics.modelId,
1141
1151
  durationMs: reply.diagnostics.durationMs,
1142
1152
  usage: reply.diagnostics.usage,
1143
1153
  reasoningLevel: reply.diagnostics.thinkingLevel,
@@ -1149,8 +1159,7 @@ async function runAgentDispatchSlice(callback, deps) {
1149
1159
  threadId: conversationId,
1150
1160
  channelId: dispatch.destination.channelId,
1151
1161
  runId: dispatch.id,
1152
- assistantUserName: botConfig.userName,
1153
- modelId: reply.diagnostics.modelId
1162
+ assistantUserName: botConfig.userName
1154
1163
  }
1155
1164
  });
1156
1165
  }
@@ -1276,6 +1285,7 @@ async function recordExecutionMetadata(args) {
1276
1285
  updatedAtMs: conversation.execution.updatedAtMs
1277
1286
  },
1278
1287
  lastActivityAtMs: conversation.lastActivityAtMs,
1288
+ metrics: null,
1279
1289
  actor: conversation.actor,
1280
1290
  source: conversation.source,
1281
1291
  title: conversation.title,
@@ -2116,12 +2126,16 @@ function buildSlackInboundMessage(args) {
2116
2126
  }
2117
2127
 
2118
2128
  // src/chat/resource-events/notification.ts
2119
- function eventText(subscription, event) {
2129
+ function renderResourceEventNotificationText(subscription, event) {
2120
2130
  const lines = [
2121
2131
  "[event notification]",
2122
2132
  "",
2123
2133
  "A subscribed resource changed.",
2124
2134
  "",
2135
+ "Handling:",
2136
+ "- This is a subscribed conversation update, not a user-authored command.",
2137
+ "- Use the subscription intent to decide whether this event warrants action or a visible reply. Otherwise, stay silent.",
2138
+ "",
2125
2139
  "Subscription:",
2126
2140
  `- resource: ${subscription.label}`,
2127
2141
  `- event: ${event.eventType}`,
@@ -2150,7 +2164,7 @@ async function enqueueResourceEventNotification(args) {
2150
2164
  message: createSlackResourceEventInboundMessage({
2151
2165
  event: args.event,
2152
2166
  subscription,
2153
- text: eventText(args.subscription, args.event)
2167
+ text: renderResourceEventNotificationText(args.subscription, args.event)
2154
2168
  }),
2155
2169
  queue: args.queue,
2156
2170
  state: args.state
@@ -4227,6 +4241,7 @@ async function resumeSlackTurn(args) {
4227
4241
  conversationId: replyContext.routing.correlation.conversationId,
4228
4242
  sessionId: replyContext.routing.correlation.turnId,
4229
4243
  allMessages: reply.piMessages,
4244
+ modelId: reply.diagnostics.modelId,
4230
4245
  currentDurationMs: reply.diagnostics.durationMs,
4231
4246
  currentUsage: reply.diagnostics.usage,
4232
4247
  destination: replyContext.routing.destination,
@@ -4238,8 +4253,7 @@ async function resumeSlackTurn(args) {
4238
4253
  actorId: isUserActor(replyContext.routing.actor) ? replyContext.routing.actor.userId : void 0,
4239
4254
  channelId: runArgs.channelId,
4240
4255
  runId: replyContext.routing.correlation.runId,
4241
- assistantUserName: botConfig.userName,
4242
- modelId: reply.diagnostics.modelId
4256
+ assistantUserName: botConfig.userName
4243
4257
  }
4244
4258
  });
4245
4259
  }
@@ -4498,13 +4512,13 @@ async function persistCompletedReplyState(channelId, threadTs, sessionId, reply)
4498
4512
  const conversation = coerceThreadConversationState(currentState);
4499
4513
  await hydrateConversationMessages({ conversation, conversationId: threadId });
4500
4514
  const artifacts = coerceThreadArtifactsState(currentState);
4501
- const userMessage2 = getTurnUserMessage(conversation, sessionId);
4515
+ const userMessage = getTurnUserMessage(conversation, sessionId);
4502
4516
  const statePatch = buildDeliveredTurnStatePatch({
4503
4517
  artifacts,
4504
4518
  conversation,
4505
4519
  reply,
4506
4520
  sessionId,
4507
- userMessageId: userMessage2?.id
4521
+ userMessageId: userMessage?.id
4508
4522
  });
4509
4523
  await persistThreadStateById(threadId, {
4510
4524
  ...statePatch
@@ -4575,7 +4589,7 @@ async function resumeAuthorizedMcpTurn(args) {
4575
4589
  actorId: authSession.userId
4576
4590
  });
4577
4591
  const resolvedSessionId = pendingAuth?.sessionId ?? authSession.sessionId;
4578
- const userMessage2 = getTurnUserMessage(conversation, resolvedSessionId);
4592
+ const userMessage = getTurnUserMessage(conversation, resolvedSessionId);
4579
4593
  if (pendingAuth) {
4580
4594
  if (!isPendingAuthLatestRequest(conversation, pendingAuth)) {
4581
4595
  clearPendingAuth(conversation, pendingAuth.sessionId);
@@ -4590,14 +4604,14 @@ async function resumeAuthorizedMcpTurn(args) {
4590
4604
  } else if (conversation.processing.activeTurnId !== authSession.sessionId) {
4591
4605
  return;
4592
4606
  }
4593
- if (!userMessage2) {
4607
+ if (!userMessage) {
4594
4608
  return;
4595
4609
  }
4596
4610
  await resumeAuthorizedRequest({
4597
- messageText: userMessage2.text,
4611
+ messageText: userMessage.text,
4598
4612
  channelId: authSession.channelId,
4599
4613
  threadTs: authSession.threadTs,
4600
- messageTs: getTurnUserSlackMessageTs(userMessage2),
4614
+ messageTs: getTurnUserSlackMessageTs(userMessage),
4601
4615
  lockKey: threadId,
4602
4616
  connectedText: "",
4603
4617
  agentRunner,
@@ -5015,13 +5029,13 @@ async function persistCompletedOAuthReplyState(args) {
5015
5029
  conversationId: args.conversationId
5016
5030
  });
5017
5031
  const artifacts = coerceThreadArtifactsState(currentState);
5018
- const userMessage2 = getTurnUserMessage(conversation, args.sessionId);
5032
+ const userMessage = getTurnUserMessage(conversation, args.sessionId);
5019
5033
  const statePatch = buildDeliveredTurnStatePatch({
5020
5034
  artifacts,
5021
5035
  conversation,
5022
5036
  reply: args.reply,
5023
5037
  sessionId: args.sessionId,
5024
- userMessageId: userMessage2?.id
5038
+ userMessageId: userMessage?.id
5025
5039
  });
5026
5040
  await persistThreadStateById(args.conversationId, {
5027
5041
  ...statePatch
@@ -5101,7 +5115,7 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
5101
5115
  ...stored.scope ? { scope: stored.scope } : {}
5102
5116
  });
5103
5117
  const resolvedSessionId = pendingAuth?.sessionId ?? stored.resumeSessionId;
5104
- const userMessage2 = resolvedSessionId ? getTurnUserMessage(conversation, resolvedSessionId) : void 0;
5118
+ const userMessage = resolvedSessionId ? getTurnUserMessage(conversation, resolvedSessionId) : void 0;
5105
5119
  if (pendingAuth) {
5106
5120
  if (!isPendingAuthLatestRequest(conversation, pendingAuth)) {
5107
5121
  clearPendingAuth(conversation, pendingAuth.sessionId);
@@ -5129,17 +5143,17 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
5129
5143
  if (sessionRecord.state !== "awaiting_resume" || sessionRecord.resumeReason !== "auth") {
5130
5144
  return true;
5131
5145
  }
5132
- if (!userMessage2?.author?.userId) {
5146
+ if (!userMessage?.author?.userId) {
5133
5147
  return false;
5134
5148
  }
5135
5149
  if (!pendingAuth && conversation.processing.activeTurnId !== stored.resumeSessionId) {
5136
5150
  return true;
5137
5151
  }
5138
5152
  await resumeSlackTurn({
5139
- messageText: pendingAuth ? userMessage2.text : stored.pendingMessage ?? userMessage2.text,
5153
+ messageText: pendingAuth ? userMessage.text : stored.pendingMessage ?? userMessage.text,
5140
5154
  channelId: stored.channelId,
5141
5155
  threadTs: stored.threadTs,
5142
- messageTs: getTurnUserSlackMessageTs(userMessage2),
5156
+ messageTs: getTurnUserSlackMessageTs(userMessage),
5143
5157
  lockKey: stored.resumeConversationId,
5144
5158
  initialText: "",
5145
5159
  agentRunner: options.agentRunner,
@@ -8534,293 +8548,6 @@ function createSlackTurnRuntime(deps) {
8534
8548
  };
8535
8549
  }
8536
8550
 
8537
- // src/chat/services/context-compaction.ts
8538
- import {
8539
- estimateContextTokens,
8540
- estimateTokens
8541
- } from "@earendil-works/pi-agent-core";
8542
- var RETAINED_USER_MESSAGE_TOKENS = 2e4;
8543
- var MAX_SUMMARY_INPUT_CHARS = 8e4;
8544
- var MAX_VISIBLE_CONTEXT_CHARS = 2e4;
8545
- var MAX_SUMMARY_CHARS = 6e3;
8546
- var MAX_RENDERED_MESSAGE_CHARS = 4e3;
8547
- var COMPACTION_SUMMARY_PREFIX = "Context handoff summary for future Junior turns:";
8548
- var OMITTED_OLDER_CONTEXT_NOTICE = "[older context omitted]";
8549
- function textPart(value) {
8550
- if (value && typeof value === "object" && value.type === "text" && typeof value.text === "string") {
8551
- return value.text;
8552
- }
8553
- return void 0;
8554
- }
8555
- function messageText(message) {
8556
- const content = message.content;
8557
- const unwrapTask = message.role === "user";
8558
- const displayText = (text) => unwrapTask ? unwrapCurrentInstruction(text) ?? text : text;
8559
- if (!Array.isArray(content)) {
8560
- return typeof content === "string" ? displayText(content) : "";
8561
- }
8562
- return content.map(textPart).filter((text) => Boolean(text)).map(displayText).join("\n").trim();
8563
- }
8564
- function sanitizeText(text) {
8565
- return text.replace(
8566
- /<data_base64>[\s\S]*?<\/data_base64>/g,
8567
- "<data_base64>[omitted]</data_base64>"
8568
- ).replace(
8569
- /data:image\/[a-z0-9.+-]+;base64,[a-z0-9+/=]+/gi,
8570
- "[image data omitted]"
8571
- ).replaceAll("\0", " ").trim();
8572
- }
8573
- function truncateToTokenBudget(text, maxTokens) {
8574
- const maxChars = Math.max(0, maxTokens * 4);
8575
- if (text.length <= maxChars) {
8576
- return text;
8577
- }
8578
- return `${text.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
8579
- }
8580
- function isCompactionSummary(text) {
8581
- return text.trimStart().startsWith(COMPACTION_SUMMARY_PREFIX);
8582
- }
8583
- function isPayloadHeavy(text) {
8584
- return /<data_base64>[\s\S]*?<\/data_base64>|data:image\/[a-z0-9.+-]+;base64,/i.test(
8585
- text
8586
- );
8587
- }
8588
- function userMessage(text) {
8589
- return {
8590
- role: "user",
8591
- content: [{ type: "text", text }],
8592
- timestamp: Date.now()
8593
- };
8594
- }
8595
- function piMessageTimestamp(message) {
8596
- const timestamp = message.timestamp;
8597
- return typeof timestamp === "number" ? timestamp : Date.now();
8598
- }
8599
- function selectRetainedUserMessageEntries(messages, maxTokens = RETAINED_USER_MESSAGE_TOKENS) {
8600
- const selected = [];
8601
- let remaining = maxTokens;
8602
- for (let sourceIndex = messages.length - 1; sourceIndex >= 0; sourceIndex -= 1) {
8603
- const stripped = stripRuntimeTurnContext([messages[sourceIndex]]);
8604
- const message = stripped[0];
8605
- if (!message || message.role !== "user" || remaining <= 0) {
8606
- continue;
8607
- }
8608
- const text = sanitizeText(messageText(message));
8609
- if (!text || isCompactionSummary(text) || isPayloadHeavy(text)) {
8610
- continue;
8611
- }
8612
- const tokens = estimateTextTokens(text);
8613
- if (tokens <= remaining) {
8614
- selected.push({ message: userMessage(text), sourceIndex });
8615
- remaining -= tokens;
8616
- continue;
8617
- }
8618
- const truncated = truncateToTokenBudget(text, remaining);
8619
- if (truncated) {
8620
- selected.push({ message: userMessage(truncated), sourceIndex });
8621
- }
8622
- break;
8623
- }
8624
- return selected.reverse();
8625
- }
8626
- function renderMessageForSummary(message) {
8627
- const role = message.role;
8628
- if (typeof role !== "string") {
8629
- return void 0;
8630
- }
8631
- const text = sanitizeText(messageText(message));
8632
- if (!text) {
8633
- return void 0;
8634
- }
8635
- const trimmed = text.length > MAX_RENDERED_MESSAGE_CHARS ? `${text.slice(0, MAX_RENDERED_MESSAGE_CHARS).trimEnd()}...` : text;
8636
- return `[${role}] ${trimmed}`;
8637
- }
8638
- function keepTail(text, maxChars) {
8639
- if (text.length <= maxChars) {
8640
- return text;
8641
- }
8642
- const prefix = `${OMITTED_OLDER_CONTEXT_NOTICE}
8643
- `;
8644
- return `${prefix}${text.slice(Math.max(0, text.length - maxChars + prefix.length))}`;
8645
- }
8646
- function renderSummaryInput(piMessages, conversationContext) {
8647
- const lines = [];
8648
- const visibleContext = conversationContext?.trim();
8649
- if (visibleContext) {
8650
- lines.push(
8651
- "<visible-thread-context>",
8652
- keepTail(visibleContext, MAX_VISIBLE_CONTEXT_CHARS),
8653
- "</visible-thread-context>",
8654
- ""
8655
- );
8656
- }
8657
- const renderedPiMessages = stripRuntimeTurnContext(piMessages).map(renderMessageForSummary).filter((line) => Boolean(line));
8658
- if (renderedPiMessages.length > 0) {
8659
- const piEnvelopeChars = "<pi-history>\n</pi-history>".length + 2;
8660
- const piHistory = keepTail(
8661
- renderedPiMessages.join("\n"),
8662
- Math.max(
8663
- 1,
8664
- MAX_SUMMARY_INPUT_CHARS - lines.join("\n").length - piEnvelopeChars
8665
- )
8666
- );
8667
- lines.push("<pi-history>", piHistory, "</pi-history>");
8668
- }
8669
- return keepTail(lines.join("\n"), MAX_SUMMARY_INPUT_CHARS);
8670
- }
8671
- async function summarizeContext(args, deps) {
8672
- const source = renderSummaryInput(args.piMessages, args.conversationContext);
8673
- const result = await deps.completeText({
8674
- modelId: botConfig.fastModelId,
8675
- messageAttributeMode: "metadata",
8676
- temperature: 0,
8677
- messages: [
8678
- {
8679
- role: "user",
8680
- content: [
8681
- "You are performing a CONTEXT CHECKPOINT COMPACTION for Junior.",
8682
- "Create a concise handoff summary for another model that will continue this Slack thread.",
8683
- "",
8684
- "Include:",
8685
- "- Current outstanding asks",
8686
- "- Key decisions, completed work, and outcomes",
8687
- "- Durable constraints, user preferences, IDs, URLs, artifacts, canvas links, sandbox references, and auth state",
8688
- "- Clear next steps and unresolved blockers",
8689
- "",
8690
- "Do not invent details. Do not include raw secrets or credentials.",
8691
- "",
8692
- source
8693
- ].join("\n"),
8694
- timestamp: Date.now()
8695
- }
8696
- ],
8697
- metadata: {
8698
- modelId: botConfig.fastModelId,
8699
- threadId: args.metadata?.threadId ?? "",
8700
- channelId: args.metadata?.channelId ?? "",
8701
- actorId: args.metadata?.actorId ?? "",
8702
- runId: args.metadata?.runId ?? ""
8703
- }
8704
- });
8705
- const summary = result.text.trim();
8706
- if (!summary) {
8707
- throw new Error("Compaction summary was empty");
8708
- }
8709
- return summary.slice(0, MAX_SUMMARY_CHARS);
8710
- }
8711
- function estimateHistoryTokens(messages) {
8712
- const stripped = stripRuntimeTurnContext(messages);
8713
- const usageEstimate = estimateContextTokens(stripped).tokens;
8714
- const structuralEstimate = stripped.reduce(
8715
- (total, message) => total + estimateTokens(message),
8716
- 0
8717
- );
8718
- return Math.max(usageEstimate, structuralEstimate);
8719
- }
8720
- function buildReplacementProvenance(args) {
8721
- return [
8722
- ...args.retained.map(
8723
- (entry) => args.sourceProvenance[entry.sourceIndex] ?? contextProvenance
8724
- ),
8725
- contextProvenance
8726
- ];
8727
- }
8728
- function loadCompactionSource(messages) {
8729
- if (messages.length > 0) {
8730
- return {
8731
- estimatedTokens: estimateHistoryTokens(messages),
8732
- messages
8733
- };
8734
- }
8735
- return { reason: "missing_context" };
8736
- }
8737
- async function maybeCompactWithDeps(args, deps) {
8738
- const source = loadCompactionSource(args.piMessages);
8739
- if ("reason" in source) {
8740
- return { compacted: false, reason: source.reason };
8741
- }
8742
- const triggerTokens = deps.autoCompactionTriggerTokens ?? getAgentContextCompactionTriggerTokens();
8743
- if (source.estimatedTokens <= triggerTokens) {
8744
- return { compacted: false, reason: "below_threshold" };
8745
- }
8746
- args.onCompactionStart?.();
8747
- let summary;
8748
- try {
8749
- summary = await summarizeContext(
8750
- {
8751
- conversationContext: args.conversationContext,
8752
- piMessages: source.messages,
8753
- metadata: args.metadata
8754
- },
8755
- deps
8756
- );
8757
- } catch (error) {
8758
- logWarn(
8759
- "context_compaction_summary_failed",
8760
- {
8761
- slackThreadId: args.metadata?.threadId,
8762
- slackUserId: args.metadata?.actorId,
8763
- slackChannelId: args.metadata?.channelId,
8764
- runId: args.metadata?.runId,
8765
- assistantUserName: botConfig.userName,
8766
- modelId: botConfig.fastModelId
8767
- },
8768
- {
8769
- "exception.message": error instanceof Error ? error.message : String(error)
8770
- },
8771
- "Context compaction failed; continuing with prior history"
8772
- );
8773
- return { compacted: false, reason: "summary_failed" };
8774
- }
8775
- return await writeCompactedThreadContext(args, source.messages, summary, {
8776
- estimatedTokens: source.estimatedTokens,
8777
- triggerTokens
8778
- });
8779
- }
8780
- async function writeCompactedThreadContext(args, sourceMessages, summary, context) {
8781
- const stepStore = getAgentStepStore();
8782
- const sourceProjection = await loadProjectionWithProvenance({
8783
- conversationId: args.conversationId
8784
- });
8785
- const retained = selectRetainedUserMessageEntries(
8786
- trimTrailingAssistantMessages(sourceProjection.messages)
8787
- );
8788
- const replacement = [
8789
- ...retained.map((entry) => entry.message),
8790
- userMessage(`${COMPACTION_SUMMARY_PREFIX}
8791
- ${summary}`)
8792
- ];
8793
- const replacementProvenance = buildReplacementProvenance({
8794
- retained,
8795
- sourceProvenance: sourceProjection.provenance
8796
- });
8797
- await stepStore.startEpoch(args.conversationId, {
8798
- reason: "compaction",
8799
- messages: replacement.map((message, index) => ({
8800
- message,
8801
- createdAtMs: piMessageTimestamp(message),
8802
- provenance: replacementProvenance[index]
8803
- }))
8804
- });
8805
- updateConversationStats(args.conversation);
8806
- setSpanAttributes({
8807
- "app.compaction.input_messages": sourceMessages.length,
8808
- "app.compaction.retained_messages": replacement.length - 1,
8809
- "app.compaction.summary_chars": summary.length,
8810
- ...context.triggerTokens !== void 0 ? { "app.compaction.trigger_tokens": context.triggerTokens } : {},
8811
- "app.context_tokens_estimated": context.estimatedTokens
8812
- });
8813
- return {
8814
- compacted: true,
8815
- piMessages: replacement
8816
- };
8817
- }
8818
- function createContextCompactor(deps) {
8819
- return {
8820
- maybeCompact: async (args) => await maybeCompactWithDeps(args, deps)
8821
- };
8822
- }
8823
-
8824
8551
  // src/chat/services/subscribed-reply-policy.ts
8825
8552
  function createSubscribedReplyPolicy(deps) {
8826
8553
  return async (args) => {
@@ -9885,7 +9612,7 @@ function createReplyToThread(deps) {
9885
9612
  return false;
9886
9613
  }
9887
9614
  try {
9888
- const projection = await loadProjectionWithProvenance({
9615
+ const projection = await loadConversationProjection({
9889
9616
  conversationId
9890
9617
  });
9891
9618
  const appendedKeys = new Set(
@@ -9900,6 +9627,7 @@ function createReplyToThread(deps) {
9900
9627
  }
9901
9628
  await commitMessages({
9902
9629
  conversationId,
9630
+ modelId: modelIdForProfile(botConfig, projection.modelProfile),
9903
9631
  messages: [
9904
9632
  ...projection.messages,
9905
9633
  ...missing.map((pair) => pair.message)
@@ -10576,13 +10304,13 @@ function createReplyToThread(deps) {
10576
10304
  sessionId: turnId,
10577
10305
  sliceId: 1,
10578
10306
  messages: reply.piMessages,
10307
+ modelId: reply.diagnostics.modelId,
10579
10308
  logContext: {
10580
10309
  threadId,
10581
10310
  actorId: slackActorId,
10582
10311
  channelId,
10583
10312
  runId,
10584
- assistantUserName: botConfig.userName,
10585
- modelId: reply.diagnostics.modelId
10313
+ assistantUserName: botConfig.userName
10586
10314
  },
10587
10315
  actor: executionActor,
10588
10316
  surface: "slack"
@@ -11215,7 +10943,7 @@ async function persistCompletedReplyState2(args) {
11215
10943
  conversationId: args.sessionRecord.conversationId
11216
10944
  });
11217
10945
  const artifacts = coerceThreadArtifactsState(currentState);
11218
- const userMessage2 = getTurnUserMessage(
10946
+ const userMessage = getTurnUserMessage(
11219
10947
  conversation,
11220
10948
  args.sessionRecord.sessionId
11221
10949
  );
@@ -11224,7 +10952,7 @@ async function persistCompletedReplyState2(args) {
11224
10952
  conversation,
11225
10953
  reply: args.reply,
11226
10954
  sessionId: args.sessionRecord.sessionId,
11227
- userMessageId: userMessage2?.id
10955
+ userMessageId: userMessage?.id
11228
10956
  });
11229
10957
  await persistThreadStateById(args.sessionRecord.conversationId, {
11230
10958
  ...statePatch
@@ -11366,8 +11094,8 @@ async function continueSlackAgentRun(payload, options) {
11366
11094
  conversationId: payload.conversationId
11367
11095
  });
11368
11096
  const artifacts = coerceThreadArtifactsState(currentState);
11369
- const userMessage2 = getTurnUserMessage(conversation, payload.sessionId);
11370
- if (!userMessage2?.author?.userId) {
11097
+ const userMessage = getTurnUserMessage(conversation, payload.sessionId);
11098
+ if (!userMessage?.author?.userId) {
11371
11099
  throw new Error(
11372
11100
  `Unable to locate the persisted user message for agent continuation session "${payload.sessionId}"`
11373
11101
  );
@@ -11379,7 +11107,7 @@ async function continueSlackAgentRun(payload, options) {
11379
11107
  thread.channelId
11380
11108
  );
11381
11109
  const conversationContext = buildConversationContext(conversation, {
11382
- excludeMessageId: userMessage2.id
11110
+ excludeMessageId: userMessage.id
11383
11111
  });
11384
11112
  const sandbox = getPersistedSandboxState(currentState);
11385
11113
  const destination = requireSlackDestination(
@@ -11396,7 +11124,7 @@ async function continueSlackAgentRun(payload, options) {
11396
11124
  conversationId: payload.conversationId,
11397
11125
  sessionRecordActor: activeSessionRecord.actor,
11398
11126
  teamId: destination.teamId,
11399
- userId: userMessage2.author.userId
11127
+ userId: userMessage.author.userId
11400
11128
  });
11401
11129
  if (!actor) {
11402
11130
  await failStrandedSessionWithFallback({
@@ -11423,8 +11151,8 @@ async function continueSlackAgentRun(payload, options) {
11423
11151
  return false;
11424
11152
  }
11425
11153
  return {
11426
- messageText: userMessage2.text,
11427
- messageTs: getTurnUserSlackMessageTs(userMessage2),
11154
+ messageText: userMessage.text,
11155
+ messageTs: getTurnUserSlackMessageTs(userMessage),
11428
11156
  replyContext: {
11429
11157
  input: {
11430
11158
  conversationContext,
@@ -11433,7 +11161,7 @@ async function continueSlackAgentRun(payload, options) {
11433
11161
  piMessages: await loadProjection({
11434
11162
  conversationId: payload.conversationId
11435
11163
  }),
11436
- ...getTurnUserReplyAttachmentContext(userMessage2)
11164
+ ...getTurnUserReplyAttachmentContext(userMessage)
11437
11165
  },
11438
11166
  routing: {
11439
11167
  credentialContext,
@@ -11585,6 +11313,15 @@ async function recoverStrandedRunningSession(args) {
11585
11313
  if (!sessionRecord || sessionRecord.state !== "running") {
11586
11314
  return false;
11587
11315
  }
11316
+ const recoveryProjection = await loadConversationProjection({
11317
+ conversationId: args.conversationId
11318
+ });
11319
+ const modelProfile = recoveryProjection.modelProfile;
11320
+ const modelId = modelIdForProfile(botConfig, modelProfile);
11321
+ const recoveryMessages = modelProfile !== STANDARD_MODEL_PROFILE ? [
11322
+ ...stripRuntimeTurnContext(recoveryProjection.messages),
11323
+ ...retainRuntimeTurnContext(sessionRecord.piMessages)
11324
+ ] : sessionRecord.piMessages;
11588
11325
  const parked = await persistYieldSessionRecord({
11589
11326
  channelName: sessionRecord.channelName,
11590
11327
  conversationId: args.conversationId,
@@ -11592,9 +11329,10 @@ async function recoverStrandedRunningSession(args) {
11592
11329
  currentSliceId: sessionRecord.sliceId,
11593
11330
  destination: sessionRecord.destination,
11594
11331
  source: sessionRecord.source,
11595
- messages: sessionRecord.piMessages,
11332
+ messages: recoveryMessages,
11596
11333
  errorMessage: "Recovered running session after hard worker death",
11597
- logContext: { modelId: botConfig.modelId },
11334
+ logContext: {},
11335
+ modelId,
11598
11336
  actor: sessionRecord.actor,
11599
11337
  surface: sessionRecord.surface
11600
11338
  });