@sentry/junior 0.96.0 → 0.97.1

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 (135) hide show
  1. package/dist/{agent-hooks-5URSMY3O.js → agent-hooks-XSUIVRQS.js} +8 -6
  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 +101 -367
  28. package/dist/build/virtual-config.d.ts +2 -2
  29. package/dist/{catalog-runtime-MSMAYYIK.js → catalog-runtime-PFHVMHDR.js} +3 -2
  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/model-profile.d.ts +14 -0
  41. package/dist/chat/pi/transcript.d.ts +5 -3
  42. package/dist/chat/resource-events/store.d.ts +2 -2
  43. package/dist/chat/services/context-compaction.d.ts +15 -0
  44. package/dist/chat/services/turn-result.d.ts +1 -0
  45. package/dist/chat/services/turn-session-record.d.ts +6 -6
  46. package/dist/chat/state/turn-session.d.ts +16 -5
  47. package/dist/chat/task-execution/store.d.ts +2 -2
  48. package/dist/chat/tools/handoff/tool.d.ts +45 -0
  49. package/dist/chat/tools/types.d.ts +7 -2
  50. package/dist/chat/usage.d.ts +25 -25
  51. package/dist/{chunk-RITD7E5L.js → chunk-35BNLDOJ.js} +338 -577
  52. package/dist/{chunk-PMNN6ST4.js → chunk-3ECW2K2O.js} +7 -2
  53. package/dist/{chunk-5C6XTTFI.js → chunk-3F4OPKGF.js} +89 -55
  54. package/dist/chunk-3V7OFJZC.js +264 -0
  55. package/dist/chunk-4ZNGQH7C.js +25 -0
  56. package/dist/{chunk-S5KZ5LPG.js → chunk-5HLDPVYS.js} +14 -447
  57. package/dist/{chunk-DZENG5ML.js → chunk-6U26PYI5.js} +24 -14
  58. package/dist/chunk-AUUCAFDE.js +546 -0
  59. package/dist/{chunk-6APU57E6.js → chunk-B3IT5END.js} +41 -260
  60. package/dist/chunk-CEA3A3UA.js +86 -0
  61. package/dist/{chunk-YDT7SNCN.js → chunk-D5KZYS4T.js} +1 -1
  62. package/dist/{chunk-YDVEH3SB.js → chunk-EEZCY5WX.js} +78 -28
  63. package/dist/{chunk-2NAZZPPS.js → chunk-EOWXRY5E.js} +1 -1
  64. package/dist/{chunk-GQ3GK22G.js → chunk-FBHZJFHI.js} +2 -2
  65. package/dist/{chunk-CZEX6KIQ.js → chunk-G3E7SCME.js} +0 -23
  66. package/dist/chunk-GUAP3H7O.js +319 -0
  67. package/dist/{chunk-BYZWPRJA.js → chunk-H66UCBPW.js} +6 -4
  68. package/dist/{chunk-L7CDEIVJ.js → chunk-LMJPRYHP.js} +4 -2
  69. package/dist/chunk-LUAE4MGW.js +199 -0
  70. package/dist/{chunk-GY34VGP5.js → chunk-LVA4I4H7.js} +3 -1
  71. package/dist/chunk-LVUKF5CE.js +63 -0
  72. package/dist/{chunk-AAZXTVJT.js → chunk-NG2AV7IB.js} +2 -72
  73. package/dist/chunk-ON6YKIQ7.js +260 -0
  74. package/dist/chunk-PDO5BLNM.js +22 -0
  75. package/dist/chunk-QNVHH5PU.js +20 -0
  76. package/dist/{chunk-P3YFQLEN.js → chunk-T533JLM3.js} +8 -10
  77. package/dist/chunk-UAMKJPDF.js +11 -0
  78. package/dist/chunk-VFH4ZKZT.js +66 -0
  79. package/dist/{chunk-UKHVMPX5.js → chunk-WGXMTFNU.js} +15 -17
  80. package/dist/{chunk-MNTINMWR.js → chunk-WJOSZOON.js} +184 -300
  81. package/dist/chunk-WTYEKPXU.js +451 -0
  82. package/dist/{chunk-IYM2SIVG.js → chunk-XIRPQQVE.js} +605 -363
  83. package/dist/cli/chat.js +24 -21
  84. package/dist/cli/check.js +4 -3
  85. package/dist/cli/init.js +12 -0
  86. package/dist/cli/plugins.js +12 -9
  87. package/dist/cli/snapshot-warmup.js +8 -6
  88. package/dist/cli/upgrade.js +265 -137
  89. package/dist/db/db.d.ts +4 -0
  90. package/dist/db/schema/conversations.d.ts +128 -0
  91. package/dist/db/schema.d.ts +129 -60
  92. package/dist/{db-2D6RMG67.js → db-BWXYIKFQ.js} +3 -3
  93. package/dist/detail-GA6NXWQJ.js +43 -0
  94. package/dist/discovery-RMHYSRL7.js +43 -0
  95. package/dist/handlers/health.d.ts +3 -0
  96. package/dist/instrumentation.js +1 -1
  97. package/dist/{legacy-import-VZ2MEGP7.js → legacy-import-3NQJVGQL.js} +4 -4
  98. package/dist/{api/people/list.js → list-A3WFRIYX.js} +26 -16
  99. package/dist/list-UXJI5Q5X.js +27 -0
  100. package/dist/nitro.d.ts +1 -1
  101. package/dist/nitro.js +2 -1
  102. package/dist/plugin-conversations-DDNGC35A.js +36 -0
  103. package/dist/{api/people/profile.js → profile-4RYDXWTF.js} +33 -18
  104. package/dist/reporting/plugin-conversations.d.ts +3 -0
  105. package/dist/reporting-schema.d.ts +140 -0
  106. package/dist/reporting.d.ts +12 -81
  107. package/dist/{runner-JZBRQP4F.js → runner-JALSYH2P.js} +17 -12
  108. package/dist/skills-MAZXZ2KE.js +26 -0
  109. package/dist/stats-XKXH3PTY.js +217 -0
  110. package/dist/subagent-TZ55XY37.js +48 -0
  111. package/dist/usage-schema.d.ts +25 -0
  112. package/dist/{validation-6XOOQGME.js → validation-FMEAEKCY.js} +4 -3
  113. package/migrations/0000_initial.sql +115 -0
  114. package/migrations/0001_conversation_metrics.sql +4 -0
  115. package/migrations/README.md +12 -30
  116. package/migrations/meta/0000_snapshot.json +1 -33
  117. package/migrations/meta/0001_snapshot.json +972 -0
  118. package/migrations/meta/_journal.json +9 -2
  119. package/package.json +13 -17
  120. package/dist/api/people/types.d.ts +0 -85
  121. package/dist/chat/advisor-request.d.ts +0 -4
  122. package/dist/chat/conversations/sql/migrations.d.ts +0 -22
  123. package/dist/chat/tools/advisor/session-store.d.ts +0 -9
  124. package/dist/chat/tools/advisor/tool.d.ts +0 -72
  125. package/dist/chunk-RAIB6WSG.js +0 -142
  126. package/dist/chunk-WM6KHPBQ.js +0 -48
  127. package/dist/db/schema/migrations.d.ts +0 -58
  128. package/dist/reporting/conversations/context.d.ts +0 -8
  129. package/dist/reporting/conversations/details.d.ts +0 -6
  130. package/dist/reporting/conversations/index.d.ts +0 -4
  131. package/dist/reporting/conversations/statistics.d.ts +0 -4
  132. package/dist/reporting/conversations/summaries.d.ts +0 -20
  133. package/dist/reporting/conversations/types.d.ts +0 -191
  134. package/dist/reporting/conversations.d.ts +0 -1
  135. package/dist/reporting.js +0 -1155
package/dist/app.js CHANGED
@@ -5,7 +5,15 @@ import {
5
5
  processPluginTask,
6
6
  requireTurnFailureEventId,
7
7
  scheduleSessionCompletedPluginTasks
8
- } from "./chunk-P3YFQLEN.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-GQ3GK22G.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-AAZXTVJT.js";
50
55
  import {
51
56
  validatePluginEgressCredentialHooks,
52
57
  validatePluginRegistrations
53
- } from "./chunk-YDT7SNCN.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-IYM2SIVG.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-UKHVMPX5.js";
131
- import {
132
- coerceThreadConversationState
133
- } from "./chunk-RAIB6WSG.js";
134
- import "./chunk-BYZWPRJA.js";
135
- import "./chunk-CM5EZD5F.js";
136
- import "./chunk-WM6KHPBQ.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-MNTINMWR.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-5C6XTTFI.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-S5KZ5LPG.js";
189
+ runWithWorkspaceTeamId
190
+ } from "./chunk-WTYEKPXU.js";
185
191
  import {
186
192
  createPluginLogger,
187
193
  createPluginState
188
- } from "./chunk-2NAZZPPS.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-RITD7E5L.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-YDVEH3SB.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-PMNN6ST4.js";
249
+ } from "./chunk-3ECW2K2O.js";
242
250
  import {
243
251
  buildOAuthTokenRequest,
244
252
  hasRequiredOAuthScope,
245
253
  parseOAuthTokenResponse,
246
254
  pluginCatalogRuntime
247
- } from "./chunk-L7CDEIVJ.js";
255
+ } from "./chunk-LMJPRYHP.js";
248
256
  import {
249
257
  buildTurnFailureResponse,
250
258
  createActor,
@@ -273,14 +281,15 @@ import {
273
281
  import {
274
282
  continueTrace
275
283
  } from "./chunk-6GWA276C.js";
276
- import {
277
- homeDir
278
- } from "./chunk-6APU57E6.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
@@ -306,7 +315,7 @@ function normalizeDashboardPath(path2, fallback) {
306
315
  return stripTrailingSlashes(withSlash);
307
316
  }
308
317
  function resolveDashboardBaseURL(config) {
309
- const explicit = config.baseURL ?? process.env.BETTER_AUTH_URL ?? process.env.JUNIOR_BASE_URL;
318
+ const explicit = config.baseURL ?? process.env.JUNIOR_BASE_URL;
310
319
  if (explicit?.trim()) {
311
320
  return stripTrailingSlashes(withHttps(explicit.trim()));
312
321
  }
@@ -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,
@@ -4231,6 +4241,7 @@ async function resumeSlackTurn(args) {
4231
4241
  conversationId: replyContext.routing.correlation.conversationId,
4232
4242
  sessionId: replyContext.routing.correlation.turnId,
4233
4243
  allMessages: reply.piMessages,
4244
+ modelId: reply.diagnostics.modelId,
4234
4245
  currentDurationMs: reply.diagnostics.durationMs,
4235
4246
  currentUsage: reply.diagnostics.usage,
4236
4247
  destination: replyContext.routing.destination,
@@ -4242,8 +4253,7 @@ async function resumeSlackTurn(args) {
4242
4253
  actorId: isUserActor(replyContext.routing.actor) ? replyContext.routing.actor.userId : void 0,
4243
4254
  channelId: runArgs.channelId,
4244
4255
  runId: replyContext.routing.correlation.runId,
4245
- assistantUserName: botConfig.userName,
4246
- modelId: reply.diagnostics.modelId
4256
+ assistantUserName: botConfig.userName
4247
4257
  }
4248
4258
  });
4249
4259
  }
@@ -4502,13 +4512,13 @@ async function persistCompletedReplyState(channelId, threadTs, sessionId, reply)
4502
4512
  const conversation = coerceThreadConversationState(currentState);
4503
4513
  await hydrateConversationMessages({ conversation, conversationId: threadId });
4504
4514
  const artifacts = coerceThreadArtifactsState(currentState);
4505
- const userMessage2 = getTurnUserMessage(conversation, sessionId);
4515
+ const userMessage = getTurnUserMessage(conversation, sessionId);
4506
4516
  const statePatch = buildDeliveredTurnStatePatch({
4507
4517
  artifacts,
4508
4518
  conversation,
4509
4519
  reply,
4510
4520
  sessionId,
4511
- userMessageId: userMessage2?.id
4521
+ userMessageId: userMessage?.id
4512
4522
  });
4513
4523
  await persistThreadStateById(threadId, {
4514
4524
  ...statePatch
@@ -4579,7 +4589,7 @@ async function resumeAuthorizedMcpTurn(args) {
4579
4589
  actorId: authSession.userId
4580
4590
  });
4581
4591
  const resolvedSessionId = pendingAuth?.sessionId ?? authSession.sessionId;
4582
- const userMessage2 = getTurnUserMessage(conversation, resolvedSessionId);
4592
+ const userMessage = getTurnUserMessage(conversation, resolvedSessionId);
4583
4593
  if (pendingAuth) {
4584
4594
  if (!isPendingAuthLatestRequest(conversation, pendingAuth)) {
4585
4595
  clearPendingAuth(conversation, pendingAuth.sessionId);
@@ -4594,14 +4604,14 @@ async function resumeAuthorizedMcpTurn(args) {
4594
4604
  } else if (conversation.processing.activeTurnId !== authSession.sessionId) {
4595
4605
  return;
4596
4606
  }
4597
- if (!userMessage2) {
4607
+ if (!userMessage) {
4598
4608
  return;
4599
4609
  }
4600
4610
  await resumeAuthorizedRequest({
4601
- messageText: userMessage2.text,
4611
+ messageText: userMessage.text,
4602
4612
  channelId: authSession.channelId,
4603
4613
  threadTs: authSession.threadTs,
4604
- messageTs: getTurnUserSlackMessageTs(userMessage2),
4614
+ messageTs: getTurnUserSlackMessageTs(userMessage),
4605
4615
  lockKey: threadId,
4606
4616
  connectedText: "",
4607
4617
  agentRunner,
@@ -5019,13 +5029,13 @@ async function persistCompletedOAuthReplyState(args) {
5019
5029
  conversationId: args.conversationId
5020
5030
  });
5021
5031
  const artifacts = coerceThreadArtifactsState(currentState);
5022
- const userMessage2 = getTurnUserMessage(conversation, args.sessionId);
5032
+ const userMessage = getTurnUserMessage(conversation, args.sessionId);
5023
5033
  const statePatch = buildDeliveredTurnStatePatch({
5024
5034
  artifacts,
5025
5035
  conversation,
5026
5036
  reply: args.reply,
5027
5037
  sessionId: args.sessionId,
5028
- userMessageId: userMessage2?.id
5038
+ userMessageId: userMessage?.id
5029
5039
  });
5030
5040
  await persistThreadStateById(args.conversationId, {
5031
5041
  ...statePatch
@@ -5105,7 +5115,7 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
5105
5115
  ...stored.scope ? { scope: stored.scope } : {}
5106
5116
  });
5107
5117
  const resolvedSessionId = pendingAuth?.sessionId ?? stored.resumeSessionId;
5108
- const userMessage2 = resolvedSessionId ? getTurnUserMessage(conversation, resolvedSessionId) : void 0;
5118
+ const userMessage = resolvedSessionId ? getTurnUserMessage(conversation, resolvedSessionId) : void 0;
5109
5119
  if (pendingAuth) {
5110
5120
  if (!isPendingAuthLatestRequest(conversation, pendingAuth)) {
5111
5121
  clearPendingAuth(conversation, pendingAuth.sessionId);
@@ -5133,17 +5143,17 @@ async function resumeOAuthSessionRecordTurn(stored, options) {
5133
5143
  if (sessionRecord.state !== "awaiting_resume" || sessionRecord.resumeReason !== "auth") {
5134
5144
  return true;
5135
5145
  }
5136
- if (!userMessage2?.author?.userId) {
5146
+ if (!userMessage?.author?.userId) {
5137
5147
  return false;
5138
5148
  }
5139
5149
  if (!pendingAuth && conversation.processing.activeTurnId !== stored.resumeSessionId) {
5140
5150
  return true;
5141
5151
  }
5142
5152
  await resumeSlackTurn({
5143
- messageText: pendingAuth ? userMessage2.text : stored.pendingMessage ?? userMessage2.text,
5153
+ messageText: pendingAuth ? userMessage.text : stored.pendingMessage ?? userMessage.text,
5144
5154
  channelId: stored.channelId,
5145
5155
  threadTs: stored.threadTs,
5146
- messageTs: getTurnUserSlackMessageTs(userMessage2),
5156
+ messageTs: getTurnUserSlackMessageTs(userMessage),
5147
5157
  lockKey: stored.resumeConversationId,
5148
5158
  initialText: "",
5149
5159
  agentRunner: options.agentRunner,
@@ -8538,293 +8548,6 @@ function createSlackTurnRuntime(deps) {
8538
8548
  };
8539
8549
  }
8540
8550
 
8541
- // src/chat/services/context-compaction.ts
8542
- import {
8543
- estimateContextTokens,
8544
- estimateTokens
8545
- } from "@earendil-works/pi-agent-core";
8546
- var RETAINED_USER_MESSAGE_TOKENS = 2e4;
8547
- var MAX_SUMMARY_INPUT_CHARS = 8e4;
8548
- var MAX_VISIBLE_CONTEXT_CHARS = 2e4;
8549
- var MAX_SUMMARY_CHARS = 6e3;
8550
- var MAX_RENDERED_MESSAGE_CHARS = 4e3;
8551
- var COMPACTION_SUMMARY_PREFIX = "Context handoff summary for future Junior turns:";
8552
- var OMITTED_OLDER_CONTEXT_NOTICE = "[older context omitted]";
8553
- function textPart(value) {
8554
- if (value && typeof value === "object" && value.type === "text" && typeof value.text === "string") {
8555
- return value.text;
8556
- }
8557
- return void 0;
8558
- }
8559
- function messageText(message) {
8560
- const content = message.content;
8561
- const unwrapTask = message.role === "user";
8562
- const displayText = (text) => unwrapTask ? unwrapCurrentInstruction(text) ?? text : text;
8563
- if (!Array.isArray(content)) {
8564
- return typeof content === "string" ? displayText(content) : "";
8565
- }
8566
- return content.map(textPart).filter((text) => Boolean(text)).map(displayText).join("\n").trim();
8567
- }
8568
- function sanitizeText(text) {
8569
- return text.replace(
8570
- /<data_base64>[\s\S]*?<\/data_base64>/g,
8571
- "<data_base64>[omitted]</data_base64>"
8572
- ).replace(
8573
- /data:image\/[a-z0-9.+-]+;base64,[a-z0-9+/=]+/gi,
8574
- "[image data omitted]"
8575
- ).replaceAll("\0", " ").trim();
8576
- }
8577
- function truncateToTokenBudget(text, maxTokens) {
8578
- const maxChars = Math.max(0, maxTokens * 4);
8579
- if (text.length <= maxChars) {
8580
- return text;
8581
- }
8582
- return `${text.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
8583
- }
8584
- function isCompactionSummary(text) {
8585
- return text.trimStart().startsWith(COMPACTION_SUMMARY_PREFIX);
8586
- }
8587
- function isPayloadHeavy(text) {
8588
- return /<data_base64>[\s\S]*?<\/data_base64>|data:image\/[a-z0-9.+-]+;base64,/i.test(
8589
- text
8590
- );
8591
- }
8592
- function userMessage(text) {
8593
- return {
8594
- role: "user",
8595
- content: [{ type: "text", text }],
8596
- timestamp: Date.now()
8597
- };
8598
- }
8599
- function piMessageTimestamp(message) {
8600
- const timestamp = message.timestamp;
8601
- return typeof timestamp === "number" ? timestamp : Date.now();
8602
- }
8603
- function selectRetainedUserMessageEntries(messages, maxTokens = RETAINED_USER_MESSAGE_TOKENS) {
8604
- const selected = [];
8605
- let remaining = maxTokens;
8606
- for (let sourceIndex = messages.length - 1; sourceIndex >= 0; sourceIndex -= 1) {
8607
- const stripped = stripRuntimeTurnContext([messages[sourceIndex]]);
8608
- const message = stripped[0];
8609
- if (!message || message.role !== "user" || remaining <= 0) {
8610
- continue;
8611
- }
8612
- const text = sanitizeText(messageText(message));
8613
- if (!text || isCompactionSummary(text) || isPayloadHeavy(text)) {
8614
- continue;
8615
- }
8616
- const tokens = estimateTextTokens(text);
8617
- if (tokens <= remaining) {
8618
- selected.push({ message: userMessage(text), sourceIndex });
8619
- remaining -= tokens;
8620
- continue;
8621
- }
8622
- const truncated = truncateToTokenBudget(text, remaining);
8623
- if (truncated) {
8624
- selected.push({ message: userMessage(truncated), sourceIndex });
8625
- }
8626
- break;
8627
- }
8628
- return selected.reverse();
8629
- }
8630
- function renderMessageForSummary(message) {
8631
- const role = message.role;
8632
- if (typeof role !== "string") {
8633
- return void 0;
8634
- }
8635
- const text = sanitizeText(messageText(message));
8636
- if (!text) {
8637
- return void 0;
8638
- }
8639
- const trimmed = text.length > MAX_RENDERED_MESSAGE_CHARS ? `${text.slice(0, MAX_RENDERED_MESSAGE_CHARS).trimEnd()}...` : text;
8640
- return `[${role}] ${trimmed}`;
8641
- }
8642
- function keepTail(text, maxChars) {
8643
- if (text.length <= maxChars) {
8644
- return text;
8645
- }
8646
- const prefix = `${OMITTED_OLDER_CONTEXT_NOTICE}
8647
- `;
8648
- return `${prefix}${text.slice(Math.max(0, text.length - maxChars + prefix.length))}`;
8649
- }
8650
- function renderSummaryInput(piMessages, conversationContext) {
8651
- const lines = [];
8652
- const visibleContext = conversationContext?.trim();
8653
- if (visibleContext) {
8654
- lines.push(
8655
- "<visible-thread-context>",
8656
- keepTail(visibleContext, MAX_VISIBLE_CONTEXT_CHARS),
8657
- "</visible-thread-context>",
8658
- ""
8659
- );
8660
- }
8661
- const renderedPiMessages = stripRuntimeTurnContext(piMessages).map(renderMessageForSummary).filter((line) => Boolean(line));
8662
- if (renderedPiMessages.length > 0) {
8663
- const piEnvelopeChars = "<pi-history>\n</pi-history>".length + 2;
8664
- const piHistory = keepTail(
8665
- renderedPiMessages.join("\n"),
8666
- Math.max(
8667
- 1,
8668
- MAX_SUMMARY_INPUT_CHARS - lines.join("\n").length - piEnvelopeChars
8669
- )
8670
- );
8671
- lines.push("<pi-history>", piHistory, "</pi-history>");
8672
- }
8673
- return keepTail(lines.join("\n"), MAX_SUMMARY_INPUT_CHARS);
8674
- }
8675
- async function summarizeContext(args, deps) {
8676
- const source = renderSummaryInput(args.piMessages, args.conversationContext);
8677
- const result = await deps.completeText({
8678
- modelId: botConfig.fastModelId,
8679
- messageAttributeMode: "metadata",
8680
- temperature: 0,
8681
- messages: [
8682
- {
8683
- role: "user",
8684
- content: [
8685
- "You are performing a CONTEXT CHECKPOINT COMPACTION for Junior.",
8686
- "Create a concise handoff summary for another model that will continue this Slack thread.",
8687
- "",
8688
- "Include:",
8689
- "- Current outstanding asks",
8690
- "- Key decisions, completed work, and outcomes",
8691
- "- Durable constraints, user preferences, IDs, URLs, artifacts, canvas links, sandbox references, and auth state",
8692
- "- Clear next steps and unresolved blockers",
8693
- "",
8694
- "Do not invent details. Do not include raw secrets or credentials.",
8695
- "",
8696
- source
8697
- ].join("\n"),
8698
- timestamp: Date.now()
8699
- }
8700
- ],
8701
- metadata: {
8702
- modelId: botConfig.fastModelId,
8703
- threadId: args.metadata?.threadId ?? "",
8704
- channelId: args.metadata?.channelId ?? "",
8705
- actorId: args.metadata?.actorId ?? "",
8706
- runId: args.metadata?.runId ?? ""
8707
- }
8708
- });
8709
- const summary = result.text.trim();
8710
- if (!summary) {
8711
- throw new Error("Compaction summary was empty");
8712
- }
8713
- return summary.slice(0, MAX_SUMMARY_CHARS);
8714
- }
8715
- function estimateHistoryTokens(messages) {
8716
- const stripped = stripRuntimeTurnContext(messages);
8717
- const usageEstimate = estimateContextTokens(stripped).tokens;
8718
- const structuralEstimate = stripped.reduce(
8719
- (total, message) => total + estimateTokens(message),
8720
- 0
8721
- );
8722
- return Math.max(usageEstimate, structuralEstimate);
8723
- }
8724
- function buildReplacementProvenance(args) {
8725
- return [
8726
- ...args.retained.map(
8727
- (entry) => args.sourceProvenance[entry.sourceIndex] ?? contextProvenance
8728
- ),
8729
- contextProvenance
8730
- ];
8731
- }
8732
- function loadCompactionSource(messages) {
8733
- if (messages.length > 0) {
8734
- return {
8735
- estimatedTokens: estimateHistoryTokens(messages),
8736
- messages
8737
- };
8738
- }
8739
- return { reason: "missing_context" };
8740
- }
8741
- async function maybeCompactWithDeps(args, deps) {
8742
- const source = loadCompactionSource(args.piMessages);
8743
- if ("reason" in source) {
8744
- return { compacted: false, reason: source.reason };
8745
- }
8746
- const triggerTokens = deps.autoCompactionTriggerTokens ?? getAgentContextCompactionTriggerTokens();
8747
- if (source.estimatedTokens <= triggerTokens) {
8748
- return { compacted: false, reason: "below_threshold" };
8749
- }
8750
- args.onCompactionStart?.();
8751
- let summary;
8752
- try {
8753
- summary = await summarizeContext(
8754
- {
8755
- conversationContext: args.conversationContext,
8756
- piMessages: source.messages,
8757
- metadata: args.metadata
8758
- },
8759
- deps
8760
- );
8761
- } catch (error) {
8762
- logWarn(
8763
- "context_compaction_summary_failed",
8764
- {
8765
- slackThreadId: args.metadata?.threadId,
8766
- slackUserId: args.metadata?.actorId,
8767
- slackChannelId: args.metadata?.channelId,
8768
- runId: args.metadata?.runId,
8769
- assistantUserName: botConfig.userName,
8770
- modelId: botConfig.fastModelId
8771
- },
8772
- {
8773
- "exception.message": error instanceof Error ? error.message : String(error)
8774
- },
8775
- "Context compaction failed; continuing with prior history"
8776
- );
8777
- return { compacted: false, reason: "summary_failed" };
8778
- }
8779
- return await writeCompactedThreadContext(args, source.messages, summary, {
8780
- estimatedTokens: source.estimatedTokens,
8781
- triggerTokens
8782
- });
8783
- }
8784
- async function writeCompactedThreadContext(args, sourceMessages, summary, context) {
8785
- const stepStore = getAgentStepStore();
8786
- const sourceProjection = await loadProjectionWithProvenance({
8787
- conversationId: args.conversationId
8788
- });
8789
- const retained = selectRetainedUserMessageEntries(
8790
- trimTrailingAssistantMessages(sourceProjection.messages)
8791
- );
8792
- const replacement = [
8793
- ...retained.map((entry) => entry.message),
8794
- userMessage(`${COMPACTION_SUMMARY_PREFIX}
8795
- ${summary}`)
8796
- ];
8797
- const replacementProvenance = buildReplacementProvenance({
8798
- retained,
8799
- sourceProvenance: sourceProjection.provenance
8800
- });
8801
- await stepStore.startEpoch(args.conversationId, {
8802
- reason: "compaction",
8803
- messages: replacement.map((message, index) => ({
8804
- message,
8805
- createdAtMs: piMessageTimestamp(message),
8806
- provenance: replacementProvenance[index]
8807
- }))
8808
- });
8809
- updateConversationStats(args.conversation);
8810
- setSpanAttributes({
8811
- "app.compaction.input_messages": sourceMessages.length,
8812
- "app.compaction.retained_messages": replacement.length - 1,
8813
- "app.compaction.summary_chars": summary.length,
8814
- ...context.triggerTokens !== void 0 ? { "app.compaction.trigger_tokens": context.triggerTokens } : {},
8815
- "app.context_tokens_estimated": context.estimatedTokens
8816
- });
8817
- return {
8818
- compacted: true,
8819
- piMessages: replacement
8820
- };
8821
- }
8822
- function createContextCompactor(deps) {
8823
- return {
8824
- maybeCompact: async (args) => await maybeCompactWithDeps(args, deps)
8825
- };
8826
- }
8827
-
8828
8551
  // src/chat/services/subscribed-reply-policy.ts
8829
8552
  function createSubscribedReplyPolicy(deps) {
8830
8553
  return async (args) => {
@@ -9889,7 +9612,7 @@ function createReplyToThread(deps) {
9889
9612
  return false;
9890
9613
  }
9891
9614
  try {
9892
- const projection = await loadProjectionWithProvenance({
9615
+ const projection = await loadConversationProjection({
9893
9616
  conversationId
9894
9617
  });
9895
9618
  const appendedKeys = new Set(
@@ -9904,6 +9627,7 @@ function createReplyToThread(deps) {
9904
9627
  }
9905
9628
  await commitMessages({
9906
9629
  conversationId,
9630
+ modelId: modelIdForProfile(botConfig, projection.modelProfile),
9907
9631
  messages: [
9908
9632
  ...projection.messages,
9909
9633
  ...missing.map((pair) => pair.message)
@@ -10580,13 +10304,13 @@ function createReplyToThread(deps) {
10580
10304
  sessionId: turnId,
10581
10305
  sliceId: 1,
10582
10306
  messages: reply.piMessages,
10307
+ modelId: reply.diagnostics.modelId,
10583
10308
  logContext: {
10584
10309
  threadId,
10585
10310
  actorId: slackActorId,
10586
10311
  channelId,
10587
10312
  runId,
10588
- assistantUserName: botConfig.userName,
10589
- modelId: reply.diagnostics.modelId
10313
+ assistantUserName: botConfig.userName
10590
10314
  },
10591
10315
  actor: executionActor,
10592
10316
  surface: "slack"
@@ -11219,7 +10943,7 @@ async function persistCompletedReplyState2(args) {
11219
10943
  conversationId: args.sessionRecord.conversationId
11220
10944
  });
11221
10945
  const artifacts = coerceThreadArtifactsState(currentState);
11222
- const userMessage2 = getTurnUserMessage(
10946
+ const userMessage = getTurnUserMessage(
11223
10947
  conversation,
11224
10948
  args.sessionRecord.sessionId
11225
10949
  );
@@ -11228,7 +10952,7 @@ async function persistCompletedReplyState2(args) {
11228
10952
  conversation,
11229
10953
  reply: args.reply,
11230
10954
  sessionId: args.sessionRecord.sessionId,
11231
- userMessageId: userMessage2?.id
10955
+ userMessageId: userMessage?.id
11232
10956
  });
11233
10957
  await persistThreadStateById(args.sessionRecord.conversationId, {
11234
10958
  ...statePatch
@@ -11370,8 +11094,8 @@ async function continueSlackAgentRun(payload, options) {
11370
11094
  conversationId: payload.conversationId
11371
11095
  });
11372
11096
  const artifacts = coerceThreadArtifactsState(currentState);
11373
- const userMessage2 = getTurnUserMessage(conversation, payload.sessionId);
11374
- if (!userMessage2?.author?.userId) {
11097
+ const userMessage = getTurnUserMessage(conversation, payload.sessionId);
11098
+ if (!userMessage?.author?.userId) {
11375
11099
  throw new Error(
11376
11100
  `Unable to locate the persisted user message for agent continuation session "${payload.sessionId}"`
11377
11101
  );
@@ -11383,7 +11107,7 @@ async function continueSlackAgentRun(payload, options) {
11383
11107
  thread.channelId
11384
11108
  );
11385
11109
  const conversationContext = buildConversationContext(conversation, {
11386
- excludeMessageId: userMessage2.id
11110
+ excludeMessageId: userMessage.id
11387
11111
  });
11388
11112
  const sandbox = getPersistedSandboxState(currentState);
11389
11113
  const destination = requireSlackDestination(
@@ -11400,7 +11124,7 @@ async function continueSlackAgentRun(payload, options) {
11400
11124
  conversationId: payload.conversationId,
11401
11125
  sessionRecordActor: activeSessionRecord.actor,
11402
11126
  teamId: destination.teamId,
11403
- userId: userMessage2.author.userId
11127
+ userId: userMessage.author.userId
11404
11128
  });
11405
11129
  if (!actor) {
11406
11130
  await failStrandedSessionWithFallback({
@@ -11427,8 +11151,8 @@ async function continueSlackAgentRun(payload, options) {
11427
11151
  return false;
11428
11152
  }
11429
11153
  return {
11430
- messageText: userMessage2.text,
11431
- messageTs: getTurnUserSlackMessageTs(userMessage2),
11154
+ messageText: userMessage.text,
11155
+ messageTs: getTurnUserSlackMessageTs(userMessage),
11432
11156
  replyContext: {
11433
11157
  input: {
11434
11158
  conversationContext,
@@ -11437,7 +11161,7 @@ async function continueSlackAgentRun(payload, options) {
11437
11161
  piMessages: await loadProjection({
11438
11162
  conversationId: payload.conversationId
11439
11163
  }),
11440
- ...getTurnUserReplyAttachmentContext(userMessage2)
11164
+ ...getTurnUserReplyAttachmentContext(userMessage)
11441
11165
  },
11442
11166
  routing: {
11443
11167
  credentialContext,
@@ -11589,6 +11313,15 @@ async function recoverStrandedRunningSession(args) {
11589
11313
  if (!sessionRecord || sessionRecord.state !== "running") {
11590
11314
  return false;
11591
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;
11592
11325
  const parked = await persistYieldSessionRecord({
11593
11326
  channelName: sessionRecord.channelName,
11594
11327
  conversationId: args.conversationId,
@@ -11596,9 +11329,10 @@ async function recoverStrandedRunningSession(args) {
11596
11329
  currentSliceId: sessionRecord.sliceId,
11597
11330
  destination: sessionRecord.destination,
11598
11331
  source: sessionRecord.source,
11599
- messages: sessionRecord.piMessages,
11332
+ messages: recoveryMessages,
11600
11333
  errorMessage: "Recovered running session after hard worker death",
11601
- logContext: { modelId: botConfig.modelId },
11334
+ logContext: {},
11335
+ modelId,
11602
11336
  actor: sessionRecord.actor,
11603
11337
  surface: sessionRecord.surface
11604
11338
  });