@sentry/junior 0.140.0 → 0.142.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 (83) hide show
  1. package/dist/{agent-hooks-BFTDRFUO.js → agent-hooks-WDJQQAPH.js} +10 -10
  2. package/dist/api/conversations/detail.d.ts +1 -0
  3. package/dist/api/conversations/event-list.d.ts +1 -0
  4. package/dist/api/schema/conversation.d.ts +4 -0
  5. package/dist/api/schema/task.d.ts +8 -0
  6. package/dist/api/schema.js +1 -1
  7. package/dist/api.js +35 -23
  8. package/dist/app.js +63 -92
  9. package/dist/{catalog-runtime-RK664S5T.js → catalog-runtime-CLHTYBHB.js} +5 -5
  10. package/dist/chat/agent/repository-context.d.ts +1 -0
  11. package/dist/chat/conversations/history.d.ts +2 -0
  12. package/dist/chat/conversations/projection.d.ts +8 -0
  13. package/dist/chat/conversations/store.d.ts +5 -0
  14. package/dist/chat/conversations/structured-events.d.ts +11 -0
  15. package/dist/chat/event-tasks/types.d.ts +7 -1
  16. package/dist/chat/runtime/thread-state.d.ts +3 -1
  17. package/dist/chat/runtime/turn.d.ts +0 -4
  18. package/dist/chat/scheduled-tasks/tools/create.d.ts +1 -0
  19. package/dist/chat/scheduled-tasks/types.d.ts +5 -0
  20. package/dist/chat/services/conversation-memory.d.ts +2 -1
  21. package/dist/chat/services/guardian-action-policy.d.ts +1 -1
  22. package/dist/chat/services/short-title.d.ts +25 -0
  23. package/dist/chat/state/conversation.d.ts +6 -17
  24. package/dist/chat/state/turn-session.d.ts +3 -4
  25. package/dist/chat/tools/create-event-task.d.ts +1 -0
  26. package/dist/{chunk-MYVCHWDG.js → chunk-4EZV6URQ.js} +107 -37
  27. package/dist/{chunk-557HLSNH.js → chunk-4L7PKEHM.js} +5 -1
  28. package/dist/{chunk-WTGLUX4K.js → chunk-5ITSZIAP.js} +1 -1
  29. package/dist/{chunk-3CUBAGA3.js → chunk-5QVVW3FY.js} +7 -7
  30. package/dist/{chunk-XX2QNQN4.js → chunk-6IMKBHCG.js} +81 -47
  31. package/dist/{chunk-3B7O3GNU.js → chunk-7R3CGEMF.js} +3 -3
  32. package/dist/{chunk-S3FAOKQU.js → chunk-A646AKNB.js} +29 -29
  33. package/dist/{chunk-BMFRFSTM.js → chunk-B2H7NI5C.js} +165 -535
  34. package/dist/{chunk-AA2EPMUF.js → chunk-CA4WLRA3.js} +4 -4
  35. package/dist/{chunk-D3X2PI3D.js → chunk-CBMIVCPM.js} +2 -2
  36. package/dist/chunk-DRTWANQF.js +67 -0
  37. package/dist/{chunk-CDQ4YIZM.js → chunk-HLXXQI5Q.js} +55 -1
  38. package/dist/{chunk-TKTZ4L4Z.js → chunk-HVTWCMDS.js} +1 -1
  39. package/dist/{chunk-CPPTBHQN.js → chunk-JIWZ7T4C.js} +1 -1
  40. package/dist/{chunk-UXMRN2ZX.js → chunk-LGY7YX5O.js} +1 -1
  41. package/dist/{chunk-YB363QGA.js → chunk-LL3BGP7J.js} +1 -1
  42. package/dist/{chunk-TGIKZJ3Y.js → chunk-LXLBYA6N.js} +2 -2
  43. package/dist/{chunk-XROWZSOY.js → chunk-N3H7G5K6.js} +1 -1
  44. package/dist/{chunk-J5H65GY2.js → chunk-NWO5IB7V.js} +1 -1
  45. package/dist/{chunk-YWM6MJT4.js → chunk-OGQGJAD7.js} +2 -0
  46. package/dist/{chunk-VRDHAITB.js → chunk-OQAPYAXH.js} +3 -3
  47. package/dist/{chunk-4PIT6O7A.js → chunk-PWDCFIQG.js} +6 -6
  48. package/dist/{chunk-OGNL2QY7.js → chunk-QDRMQI5W.js} +4 -4
  49. package/dist/{chunk-5KAZMR5U.js → chunk-R7E476CH.js} +6 -6
  50. package/dist/{chunk-HEFBGCCU.js → chunk-RYYBUI34.js} +2 -2
  51. package/dist/{chunk-WSWM6A3R.js → chunk-SCHH6264.js} +19 -3
  52. package/dist/{chunk-I3OZR3HG.js → chunk-SF6YKONJ.js} +1 -1
  53. package/dist/{chunk-DMDOKRPC.js → chunk-T4NFQ5SG.js} +5 -5
  54. package/dist/{chunk-5YAWB2AX.js → chunk-VJMBLWYR.js} +15 -17
  55. package/dist/{chunk-A6BI25J3.js → chunk-WJEW7UNC.js} +341 -16
  56. package/dist/{chunk-N2I7W2VS.js → chunk-WYLSMTWU.js} +1 -1
  57. package/dist/{chunk-NPL66ZWL.js → chunk-XAW6IN6M.js} +1 -1
  58. package/dist/chunk-XFHSZNOX.js +75 -0
  59. package/dist/{chunk-Z2A7BDHT.js → chunk-ZPNUI4L3.js} +23 -26
  60. package/dist/cli/chat.js +33 -31
  61. package/dist/cli/check.js +6 -6
  62. package/dist/cli/plugins.js +13 -13
  63. package/dist/cli/snapshot-create.js +9 -9
  64. package/dist/cli/upgrade.js +7 -7
  65. package/dist/db/schema/event-tasks.d.ts +20 -52
  66. package/dist/db/schema/scheduled-tasks.d.ts +17 -0
  67. package/dist/db/schema.d.ts +36 -52
  68. package/dist/{db-QOGYDDQM.js → db-6N4CD5AI.js} +7 -7
  69. package/dist/instrumentation.js +4 -4
  70. package/dist/nitro.js +2 -2
  71. package/dist/{oauth-callback-server-CT4RMGCP.js → oauth-callback-server-G4K2X56R.js} +24 -22
  72. package/dist/{runner-PHMLHNLX.js → runner-DEIHVRUE.js} +25 -26
  73. package/dist/{skills-AYRM4QGF.js → skills-FZVJ6ZFW.js} +6 -6
  74. package/dist/spawn-WD4F67SZ.js +38 -0
  75. package/dist/{validation-M5JNGRGL.js → validation-EOLSG7B6.js} +6 -6
  76. package/dist/version.js +1 -1
  77. package/dist/{work-LZWE6HK4.js → work-AS3IBMLA.js} +17 -17
  78. package/dist/{worker-KOGPXFYK.js → worker-VGGNGOUU.js} +10 -10
  79. package/migrations/0023_task_title_columns.sql +2 -0
  80. package/migrations/meta/0023_snapshot.json +2198 -0
  81. package/migrations/meta/_journal.json +7 -0
  82. package/package.json +4 -4
  83. package/dist/spawn-OGRQFUNK.js +0 -38
@@ -1,11 +1,16 @@
1
1
  import {
2
2
  recordTaskExecution
3
- } from "./chunk-3B7O3GNU.js";
3
+ } from "./chunk-7R3CGEMF.js";
4
4
  import {
5
5
  pluginTaskId,
6
6
  pluginTaskParamsSchema,
7
7
  sendVercelPluginTask
8
8
  } from "./chunk-5I6ORJUY.js";
9
+ import {
10
+ calculateContextCompactionTargetTokens,
11
+ estimateTextTokens,
12
+ getConversationContextCompactionTriggerTokens
13
+ } from "./chunk-DRTWANQF.js";
9
14
  import {
10
15
  buildDeterministicTurnId,
11
16
  clearPendingAuth,
@@ -17,18 +22,20 @@ import {
17
22
  instructionTextForProjection,
18
23
  isToolResultError,
19
24
  isToolResultMessage,
20
- markConversationMessage,
21
25
  markTurnClosed,
22
26
  markTurnCompleted,
23
27
  mergeArtifactsState,
24
28
  normalizeToolNameFromResult,
25
29
  persistThreadStateById,
26
- stripRuntimeTurnContext,
27
- updateConversationStats
28
- } from "./chunk-BMFRFSTM.js";
30
+ stripRuntimeTurnContext
31
+ } from "./chunk-B2H7NI5C.js";
29
32
  import {
30
33
  JUNIOR_THREAD_STATE_TTL_MS
31
34
  } from "./chunk-3Y47VMHV.js";
35
+ import {
36
+ fallbackShortTitle,
37
+ generateShortTitle
38
+ } from "./chunk-XFHSZNOX.js";
32
39
  import {
33
40
  createPluginConversationEvents,
34
41
  createPluginEmbedder,
@@ -36,21 +43,23 @@ import {
36
43
  createPluginModel,
37
44
  createPluginState,
38
45
  getPlugins
39
- } from "./chunk-4PIT6O7A.js";
46
+ } from "./chunk-PWDCFIQG.js";
40
47
  import {
41
48
  getConversationStore,
42
49
  getDb,
43
50
  sameActorIdentity
44
- } from "./chunk-WSWM6A3R.js";
51
+ } from "./chunk-SCHH6264.js";
45
52
  import {
46
53
  getStateAdapter
47
- } from "./chunk-J5H65GY2.js";
54
+ } from "./chunk-NWO5IB7V.js";
48
55
  import {
49
56
  ProviderError,
57
+ botConfig,
58
+ escapeXml,
50
59
  findProviderError,
51
60
  getProviderErrorAttributes,
52
61
  getProviderErrorUserMessage
53
- } from "./chunk-S3FAOKQU.js";
62
+ } from "./chunk-A646AKNB.js";
54
63
  import {
55
64
  credentialSubjectSchema
56
65
  } from "./chunk-RUIXF3YQ.js";
@@ -58,8 +67,315 @@ import {
58
67
  parseSlackMessageTs
59
68
  } from "./chunk-F3B2YJ76.js";
60
69
  import {
61
- buildTurnFailureResponse
62
- } from "./chunk-NPL66ZWL.js";
70
+ buildTurnFailureResponse,
71
+ logWarn,
72
+ setSpanAttributes
73
+ } from "./chunk-XAW6IN6M.js";
74
+
75
+ // src/chat/services/conversation-memory.ts
76
+ var CONTEXT_MIN_LIVE_MESSAGES = 12;
77
+ var CONTEXT_COMPACTION_BATCH_SIZE = 24;
78
+ var CONTEXT_MAX_COMPACTIONS = 16;
79
+ var CONTEXT_MAX_MESSAGE_CHARS = 3200;
80
+ var SLACK_USER_ID_DISPLAY_PATTERN = /^[UW][A-Z0-9]{5,}$/;
81
+ function generateConversationId(prefix) {
82
+ return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
83
+ }
84
+ function normalizeConversationText(text) {
85
+ return text.replace(/\r\n?/g, "\n").trim();
86
+ }
87
+ function buildImageContextSuffix(message, conversation) {
88
+ const byFileId = conversation?.vision.byFileId;
89
+ const imageFileIds = message.meta?.imageFileIds ?? [];
90
+ if (!byFileId || imageFileIds.length === 0) {
91
+ return "";
92
+ }
93
+ const summaries = imageFileIds.map((fileId) => byFileId[fileId]?.summary?.trim()).filter((summary) => Boolean(summary));
94
+ if (summaries.length === 0) {
95
+ return "";
96
+ }
97
+ return ` [image context: ${summaries.join(" | ")}]`;
98
+ }
99
+ function renderConversationMessageLine(message, conversation) {
100
+ const displayName = conversationAuthorDisplayName(message);
101
+ const text = message.text.replace(/\s+/g, " ").slice(0, CONTEXT_MAX_MESSAGE_CHARS);
102
+ const markers = [];
103
+ if (message.meta?.replied === false) {
104
+ markers.push(
105
+ `assistant skipped: ${message.meta?.skippedReason ?? "no-reply route"}`
106
+ );
107
+ }
108
+ if (message.meta?.explicitMention) {
109
+ markers.push("explicit mention");
110
+ }
111
+ const markerSuffix = markers.length > 0 ? ` (${markers.join("; ")})` : "";
112
+ const imageContext = buildImageContextSuffix(message, conversation);
113
+ return `[${message.role}] ${displayName}: ${text}${imageContext}${markerSuffix}`;
114
+ }
115
+ function conversationAuthorDisplayName(message) {
116
+ const author = message.author;
117
+ const fullName = authorDisplayField(author?.fullName, author?.userId);
118
+ const userName = authorDisplayField(author?.userName, author?.userId);
119
+ return fullName ?? userName ?? (message.role === "assistant" ? botConfig.userName : message.role);
120
+ }
121
+ function authorDisplayField(value, userId) {
122
+ if (!value || value === userId || SLACK_USER_ID_DISPLAY_PATTERN.test(value)) {
123
+ return void 0;
124
+ }
125
+ return value;
126
+ }
127
+ function estimateConversationContextTokens(conversation) {
128
+ return estimateTextTokens(buildConversationContext(conversation) ?? "");
129
+ }
130
+ function upsertConversationMessage(conversation, message) {
131
+ const existingIndex = conversation.messages.findIndex(
132
+ (entry) => entry.id === message.id
133
+ );
134
+ if (existingIndex >= 0) {
135
+ conversation.messages[existingIndex] = {
136
+ ...conversation.messages[existingIndex],
137
+ ...message,
138
+ meta: {
139
+ ...conversation.messages[existingIndex]?.meta,
140
+ ...message.meta
141
+ }
142
+ };
143
+ return message.id;
144
+ }
145
+ conversation.messages.push(message);
146
+ return message.id;
147
+ }
148
+ function recordDeliveredAssistantMessage(args) {
149
+ const prefix = `${args.sessionId}:assistant:`;
150
+ const ordinal = args.conversation.messages.filter(
151
+ (message) => message.id.startsWith(prefix)
152
+ ).length + 1;
153
+ const messageId = `${prefix}${ordinal}`;
154
+ markConversationMessage(args.conversation, args.userMessageId, {
155
+ replied: true,
156
+ skippedReason: void 0
157
+ });
158
+ upsertConversationMessage(args.conversation, {
159
+ id: messageId,
160
+ role: "assistant",
161
+ text: normalizeConversationText(args.text),
162
+ createdAtMs: Date.now(),
163
+ author: {
164
+ userName: botConfig.userName,
165
+ isBot: true
166
+ },
167
+ meta: {
168
+ replied: true
169
+ }
170
+ });
171
+ return messageId;
172
+ }
173
+ function turnHasReply(conversation, turnId) {
174
+ const assistantPrefix = `${turnId}:assistant:`;
175
+ return conversation.messages.some(
176
+ (message) => message.role === "assistant" && message.id.startsWith(assistantPrefix)
177
+ );
178
+ }
179
+ function markConversationMessage(conversation, messageId, patch) {
180
+ if (!messageId) return;
181
+ const messageIndex = conversation.messages.findIndex(
182
+ (entry) => entry.id === messageId
183
+ );
184
+ if (messageIndex < 0) return;
185
+ const current = conversation.messages[messageIndex];
186
+ conversation.messages[messageIndex] = {
187
+ ...current,
188
+ meta: {
189
+ ...current.meta ?? {},
190
+ ...patch
191
+ }
192
+ };
193
+ }
194
+ function buildConversationContext(conversation, options = {}) {
195
+ const messages = conversation.messages.filter(
196
+ (entry) => entry.id !== options.excludeMessageId
197
+ );
198
+ if (messages.length === 0 && conversation.compactions.length === 0) {
199
+ return void 0;
200
+ }
201
+ const lines = [];
202
+ if (conversation.compactions.length > 0) {
203
+ lines.push("<thread-compactions>");
204
+ for (const [index, compaction] of conversation.compactions.entries()) {
205
+ lines.push(
206
+ ` <compaction index="${index + 1}" covered_messages="${compaction.coveredMessageCount}" created_at="${new Date(compaction.createdAtMs).toISOString()}">`,
207
+ compaction.summary,
208
+ " </compaction>"
209
+ );
210
+ }
211
+ lines.push("</thread-compactions>");
212
+ }
213
+ if (messages.length > 0) {
214
+ if (lines.length > 0) {
215
+ lines.push("");
216
+ }
217
+ lines.push("<thread-transcript>");
218
+ for (const [index, message] of messages.entries()) {
219
+ const author = escapeXml(conversationAuthorDisplayName(message));
220
+ const actorIdAttr = message.author?.userId ? ` actor_id="${escapeXml(message.author.userId)}"` : "";
221
+ const ts = new Date(message.createdAtMs).toISOString();
222
+ const slackTsAttr = message.meta?.slackTs ? ` slack_ts="${escapeXml(message.meta.slackTs)}"` : "";
223
+ lines.push(
224
+ ` <message index="${index + 1}" ts="${ts}" role="${message.role}" author="${author}"${actorIdAttr}${slackTsAttr}>`,
225
+ renderConversationMessageLine(message, conversation),
226
+ " </message>"
227
+ );
228
+ }
229
+ lines.push("</thread-transcript>");
230
+ }
231
+ return lines.join("\n");
232
+ }
233
+ function pruneCompactions(compactions) {
234
+ if (compactions.length <= CONTEXT_MAX_COMPACTIONS) {
235
+ return compactions;
236
+ }
237
+ const overflowCount = compactions.length - CONTEXT_MAX_COMPACTIONS + 1;
238
+ const merged = compactions.slice(0, overflowCount);
239
+ const mergedSummary = merged.map((entry) => entry.summary).join("\n").slice(0, 3500);
240
+ const coveredMessageCount = merged.reduce(
241
+ (count, entry) => count + entry.coveredMessageCount,
242
+ 0
243
+ );
244
+ const compacted = {
245
+ id: generateConversationId("compaction"),
246
+ createdAtMs: Date.now(),
247
+ summary: mergedSummary,
248
+ coveredMessageCount
249
+ };
250
+ return [compacted, ...compactions.slice(overflowCount)];
251
+ }
252
+ async function summarizeConversationChunk(messages, conversation, context, deps) {
253
+ const transcript = messages.map((message) => renderConversationMessageLine(message, conversation)).join("\n");
254
+ try {
255
+ const result = await deps.completeText({
256
+ modelId: botConfig.fastModelId,
257
+ temperature: 0,
258
+ messages: [
259
+ {
260
+ role: "user",
261
+ content: [
262
+ "Summarize the following older Slack thread transcript segment for future assistant turns.",
263
+ "Keep the summary factual and concise. Do not invent details.",
264
+ "",
265
+ "Output exactly three XML sections in this order:",
266
+ "<active-asks> one bullet per outstanding user ask that has not been narrowed, answered, or replaced by a later turn. Omit the section body if none. </active-asks>",
267
+ "<resolved-or-replaced-asks> one bullet per ask that has been replaced, narrowed, answered, or already acted on in this segment. Include the replacement/outcome inline. Omit the section body if none. </resolved-or-replaced-asks>",
268
+ "<facts> one bullet per durable fact useful regardless of scope: names, ids, URLs, decisions, locations, preferences, constraints that remain true. Omit the section body if none. </facts>",
269
+ "",
270
+ "Do not output any text outside the three sections.",
271
+ "",
272
+ transcript
273
+ ].join("\n"),
274
+ timestamp: Date.now()
275
+ }
276
+ ],
277
+ metadata: {
278
+ modelId: botConfig.fastModelId,
279
+ threadId: context.threadId ?? "",
280
+ channelId: context.channelId ?? "",
281
+ actorId: context.actorId ?? "",
282
+ runId: context.runId ?? ""
283
+ }
284
+ });
285
+ const summary = result.text.trim();
286
+ if (summary.length > 0) {
287
+ return summary.slice(0, 3500);
288
+ }
289
+ } catch (error) {
290
+ logWarn("conversation.compaction.summary.failed", {
291
+ "exception.message": error instanceof Error ? error.message : String(error),
292
+ "app.compaction_messages_covered": messages.length
293
+ });
294
+ }
295
+ return transcript.slice(0, 2800);
296
+ }
297
+ async function generateThreadTitleWithDeps(sourceText, deps) {
298
+ const title = await generateShortTitle({
299
+ completeText: deps.completeText,
300
+ kind: "conversation",
301
+ sourceText
302
+ });
303
+ return title ?? fallbackShortTitle(sourceText, "Conversation");
304
+ }
305
+ function getThreadTitleSourceMessage(conversation) {
306
+ let firstMessage;
307
+ for (const message of conversation.messages) {
308
+ if (!isHumanConversationMessage(message)) {
309
+ continue;
310
+ }
311
+ if (!firstMessage) {
312
+ firstMessage = message;
313
+ continue;
314
+ }
315
+ if (message.createdAtMs < firstMessage.createdAtMs) {
316
+ firstMessage = message;
317
+ continue;
318
+ }
319
+ if (message.createdAtMs === firstMessage.createdAtMs && message.id < firstMessage.id) {
320
+ firstMessage = message;
321
+ }
322
+ }
323
+ return firstMessage;
324
+ }
325
+ async function compactConversationIfNeededWithDeps(conversation, context, deps) {
326
+ let estimatedTokens = estimateConversationContextTokens(conversation);
327
+ setSpanAttributes({
328
+ "app.context_tokens_estimated": estimatedTokens
329
+ });
330
+ const triggerTokens = getConversationContextCompactionTriggerTokens();
331
+ const targetTokens = calculateContextCompactionTargetTokens(triggerTokens);
332
+ while (estimatedTokens > triggerTokens && conversation.messages.length > CONTEXT_MIN_LIVE_MESSAGES) {
333
+ const compactCount = Math.min(
334
+ CONTEXT_COMPACTION_BATCH_SIZE,
335
+ conversation.messages.length - CONTEXT_MIN_LIVE_MESSAGES
336
+ );
337
+ if (compactCount <= 0) {
338
+ break;
339
+ }
340
+ const compactedChunk = conversation.messages.slice(0, compactCount);
341
+ const summary = await summarizeConversationChunk(
342
+ compactedChunk,
343
+ conversation,
344
+ context,
345
+ deps
346
+ );
347
+ conversation.compactions.push({
348
+ id: generateConversationId("compaction"),
349
+ createdAtMs: Date.now(),
350
+ summary,
351
+ coveredMessageCount: compactedChunk.length
352
+ });
353
+ conversation.compactions = pruneCompactions(conversation.compactions);
354
+ conversation.messages = conversation.messages.slice(compactCount);
355
+ estimatedTokens = estimateConversationContextTokens(conversation);
356
+ setSpanAttributes({
357
+ "app.compaction_messages_covered": compactCount,
358
+ "app.compaction.trigger_tokens": triggerTokens,
359
+ "app.compaction.target_tokens": targetTokens,
360
+ "app.context_tokens_estimated": estimatedTokens
361
+ });
362
+ if (estimatedTokens <= targetTokens) {
363
+ break;
364
+ }
365
+ }
366
+ }
367
+ function createConversationMemoryService(deps) {
368
+ return {
369
+ compactConversationIfNeeded: async (conversation, context) => await compactConversationIfNeededWithDeps(conversation, context, deps),
370
+ generateThreadTitle: async (sourceText) => await generateThreadTitleWithDeps(sourceText, deps)
371
+ };
372
+ }
373
+ function isHumanConversationMessage(message) {
374
+ return message.role === "user" && message.author?.isBot !== true;
375
+ }
376
+ function getConversationMessageSlackTs(message) {
377
+ return parseSlackMessageTs(message.meta?.slackTs);
378
+ }
63
379
 
64
380
  // src/chat/runtime/delivered-turn-state.ts
65
381
  function buildDeliveredTurnStatePatch(args) {
@@ -77,8 +393,7 @@ function buildDeliveredTurnStatePatch(args) {
77
393
  markTurnCompleted({
78
394
  conversation,
79
395
  nowMs: Date.now(),
80
- sessionId: args.sessionId,
81
- updateConversationStats
396
+ sessionId: args.sessionId
82
397
  });
83
398
  return {
84
399
  artifacts,
@@ -95,7 +410,7 @@ import {
95
410
 
96
411
  // src/chat/services/turn-session-routing.ts
97
412
  async function resolveTurnSessionRouting(args) {
98
- const conversationStore = args.conversationStore ?? (await import("./db-QOGYDDQM.js")).getConversationStore();
413
+ const conversationStore = args.conversationStore ?? (await import("./db-6N4CD5AI.js")).getConversationStore();
99
414
  const conversation = await conversationStore.get({
100
415
  conversationId: args.conversationId
101
416
  });
@@ -935,8 +1250,7 @@ function completeAuthPauseTurn(args) {
935
1250
  markTurnClosed({
936
1251
  conversation: args.conversation,
937
1252
  nowMs: Date.now(),
938
- sessionId: args.sessionId,
939
- updateConversationStats
1253
+ sessionId: args.sessionId
940
1254
  });
941
1255
  }
942
1256
  async function persistAuthPauseTurnState(args) {
@@ -970,6 +1284,17 @@ export {
970
1284
  listPendingDispatchMailboxAppends,
971
1285
  claimDispatchMailboxAppend,
972
1286
  getPluginDispatchProjection,
1287
+ normalizeConversationText,
1288
+ estimateConversationContextTokens,
1289
+ upsertConversationMessage,
1290
+ recordDeliveredAssistantMessage,
1291
+ turnHasReply,
1292
+ markConversationMessage,
1293
+ buildConversationContext,
1294
+ getThreadTitleSourceMessage,
1295
+ createConversationMemoryService,
1296
+ isHumanConversationMessage,
1297
+ getConversationMessageSlackTs,
973
1298
  buildDeliveredTurnStatePatch,
974
1299
  getTurnUserMessage,
975
1300
  getTurnUserMessageId,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createPluginCatalogRuntime
3
- } from "./chunk-I3OZR3HG.js";
3
+ } from "./chunk-SF6YKONJ.js";
4
4
 
5
5
  // src/chat/plugins/catalog-runtime.ts
6
6
  var pluginCatalogRuntime = createPluginCatalogRuntime();
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-6GWA276C.js";
10
10
  import {
11
11
  getDeploymentTelemetryAttributes
12
- } from "./chunk-YB363QGA.js";
12
+ } from "./chunk-LL3BGP7J.js";
13
13
 
14
14
  // src/chat/logging.ts
15
15
  import path from "path";
@@ -0,0 +1,75 @@
1
+ import {
2
+ botConfig
3
+ } from "./chunk-A646AKNB.js";
4
+ import {
5
+ logWarn
6
+ } from "./chunk-XAW6IN6M.js";
7
+
8
+ // src/chat/services/short-title.ts
9
+ var SHORT_TITLE_MAX_LENGTH = 60;
10
+ var TITLE_PROMPTS = {
11
+ conversation: [
12
+ "Generate a concise 5-8 word Slack conversation title from the first user message below.",
13
+ "Capture the user's main request.",
14
+ "Reply with ONLY the title, with no quotes or trailing punctuation."
15
+ ],
16
+ task: [
17
+ "Generate a concise 5-8 word task title from the task instruction below.",
18
+ "Capture the task's main purpose.",
19
+ "Reply with ONLY the title, with no quotes or trailing punctuation."
20
+ ]
21
+ };
22
+ function normalizeShortTitle(value) {
23
+ return value.replace(/\s+/g, " ").trim().slice(0, SHORT_TITLE_MAX_LENGTH);
24
+ }
25
+ function fallbackShortTitle(sourceText, fallback = "Untitled") {
26
+ const firstLine = sourceText.split(/\r?\n/).map((line) => line.trim()).find((line) => line.length > 0) ?? "";
27
+ return normalizeShortTitle(firstLine) || fallback;
28
+ }
29
+ async function generateShortTitle(args) {
30
+ const sourceText = args.sourceText.trim();
31
+ if (!sourceText) return void 0;
32
+ try {
33
+ const result = await args.completeText({
34
+ modelId: botConfig.fastModelId,
35
+ temperature: 0,
36
+ messages: [
37
+ {
38
+ role: "user",
39
+ content: [
40
+ ...TITLE_PROMPTS[args.kind],
41
+ "",
42
+ args.kind === "conversation" ? `First user message: ${sourceText.slice(0, 500)}` : `Task instruction: ${sourceText.slice(0, 500)}`
43
+ ].join("\n"),
44
+ timestamp: Date.now()
45
+ }
46
+ ],
47
+ metadata: {
48
+ modelId: botConfig.fastModelId
49
+ }
50
+ });
51
+ const title = normalizeShortTitle(result.text);
52
+ return title || void 0;
53
+ } catch (error) {
54
+ logWarn(`${args.kind}.title.generation.failed`, {
55
+ "exception.message": error instanceof Error ? error.message : String(error)
56
+ });
57
+ return void 0;
58
+ }
59
+ }
60
+ async function resolveTaskTitle(args) {
61
+ const explicit = normalizeShortTitle(args.title ?? "");
62
+ if (explicit) return explicit;
63
+ return generateShortTitle({
64
+ completeText: args.completeText,
65
+ kind: "task",
66
+ sourceText: args.instruction
67
+ });
68
+ }
69
+
70
+ export {
71
+ SHORT_TITLE_MAX_LENGTH,
72
+ fallbackShortTitle,
73
+ generateShortTitle,
74
+ resolveTaskTitle
75
+ };
@@ -4,8 +4,9 @@ import {
4
4
  import {
5
5
  ensureConversationWake,
6
6
  requestConversationWork
7
- } from "./chunk-AA2EPMUF.js";
7
+ } from "./chunk-CA4WLRA3.js";
8
8
  import {
9
+ buildConversationContext,
9
10
  buildDeliveredTurnStatePatch,
10
11
  finalizeFailedTurnReplyWithEvent,
11
12
  getInterruptionMarker,
@@ -13,11 +14,14 @@ import {
13
14
  getTurnUserMessageId,
14
15
  getTurnUserReplyAttachmentContext,
15
16
  getTurnUserSlackMessageTs,
17
+ markConversationMessage,
16
18
  persistAuthPauseTurnState,
19
+ recordDeliveredAssistantMessage,
17
20
  requireTurnFailureEventId,
18
21
  resolveTurnSessionRouting,
19
- scheduleSessionCompletedPluginTasks
20
- } from "./chunk-A6BI25J3.js";
22
+ scheduleSessionCompletedPluginTasks,
23
+ turnHasReply
24
+ } from "./chunk-WJEW7UNC.js";
21
25
  import {
22
26
  ConversationTurnLifecycleService
23
27
  } from "./chunk-Q6QZTTLS.js";
@@ -35,7 +39,7 @@ import {
35
39
  getMcpProviderErrorAttributes,
36
40
  getMcpStoredOAuthCredentials,
37
41
  resolvePluginOAuthAccount
38
- } from "./chunk-3CUBAGA3.js";
42
+ } from "./chunk-5QVVW3FY.js";
39
43
  import {
40
44
  RetryableDeliveryError
41
45
  } from "./chunk-R776HKPK.js";
@@ -51,11 +55,10 @@ import {
51
55
  removeReactionFromMessage,
52
56
  resolveBaseUrl,
53
57
  truncateStatusText
54
- } from "./chunk-5KAZMR5U.js";
58
+ } from "./chunk-R7E476CH.js";
55
59
  import {
56
60
  TurnSliceLimitExceededError,
57
61
  abandonAgentTurnSessionRecord,
58
- buildConversationContext,
59
62
  buildTurnLimitResponse,
60
63
  clearPendingAuth,
61
64
  coerceThreadArtifactsState,
@@ -71,43 +74,39 @@ import {
71
74
  hydrateConversationMessages,
72
75
  isPendingAuthLatestRequest,
73
76
  loadProjection,
74
- markConversationMessage,
75
77
  markTurnFailed,
76
78
  persistCompletedSessionRecord,
77
79
  persistThreadStateById,
78
80
  persistWithRetry,
79
81
  recordAgentTurnSessionSummary,
80
82
  recordAuthenticationLinked,
81
- recordAuthorizationCompleted,
82
- recordDeliveredAssistantMessage,
83
- turnHasReply,
84
- updateConversationStats
85
- } from "./chunk-BMFRFSTM.js";
83
+ recordAuthorizationCompleted
84
+ } from "./chunk-B2H7NI5C.js";
86
85
  import {
87
86
  parseSlackThreadId,
88
87
  readSlackRawMessageContext,
89
88
  resolveSlackChannelIdFromMessage,
90
89
  resolveSlackChannelIdFromThreadId
91
- } from "./chunk-WTGLUX4K.js";
90
+ } from "./chunk-5ITSZIAP.js";
92
91
  import {
93
92
  getDashboardConversationLink,
94
93
  getPluginSlackConversationLink
95
- } from "./chunk-4PIT6O7A.js";
94
+ } from "./chunk-PWDCFIQG.js";
96
95
  import {
97
96
  SlackActionError,
98
97
  getHeaderString,
99
98
  getSlackClient,
100
99
  isDmChannel,
101
100
  normalizeSlackConversationId
102
- } from "./chunk-HEFBGCCU.js";
101
+ } from "./chunk-RYYBUI34.js";
103
102
  import {
104
103
  getConversationEventStore,
105
104
  requireSlackDestination
106
- } from "./chunk-WSWM6A3R.js";
105
+ } from "./chunk-SCHH6264.js";
107
106
  import {
108
107
  acquireActiveLock,
109
108
  getStateAdapter
110
- } from "./chunk-J5H65GY2.js";
109
+ } from "./chunk-NWO5IB7V.js";
111
110
  import {
112
111
  FUNCTION_TIMEOUT_BUFFER_SECONDS,
113
112
  botConfig,
@@ -116,18 +115,18 @@ import {
116
115
  getRuntimeMetadata,
117
116
  normalizeSlackEmojiName,
118
117
  standardModelId
119
- } from "./chunk-S3FAOKQU.js";
118
+ } from "./chunk-A646AKNB.js";
120
119
  import {
121
120
  discoverSkills
122
- } from "./chunk-D3X2PI3D.js";
121
+ } from "./chunk-CBMIVCPM.js";
123
122
  import {
124
123
  pluginCatalogRuntime
125
- } from "./chunk-N2I7W2VS.js";
124
+ } from "./chunk-WYLSMTWU.js";
126
125
  import {
127
126
  buildOAuthTokenRequest,
128
127
  hasRequiredOAuthScope,
129
128
  parseOAuthTokenResponse
130
- } from "./chunk-I3OZR3HG.js";
129
+ } from "./chunk-SF6YKONJ.js";
131
130
  import {
132
131
  createSlackResumeActor,
133
132
  isUserActor
@@ -143,7 +142,7 @@ import {
143
142
  setTags,
144
143
  toOptionalString,
145
144
  withLogContext
146
- } from "./chunk-NPL66ZWL.js";
145
+ } from "./chunk-XAW6IN6M.js";
147
146
  import {
148
147
  homeDir
149
148
  } from "./chunk-H4HBKISO.js";
@@ -1925,8 +1924,7 @@ async function persistFailedReplyState(channelId, threadTs, sessionId, expectedV
1925
1924
  nowMs: Date.now(),
1926
1925
  sessionId,
1927
1926
  userMessageId: getTurnUserMessageId(conversation, sessionId),
1928
- markConversationMessage,
1929
- updateConversationStats
1927
+ markConversationMessage
1930
1928
  });
1931
1929
  await failSessionRecordBestEffort({
1932
1930
  conversationId: threadId,
@@ -2533,8 +2531,7 @@ async function persistFailedOAuthReplyState(args) {
2533
2531
  nowMs: Date.now(),
2534
2532
  sessionId: args.sessionId,
2535
2533
  userMessageId: getTurnUserMessage(conversation, args.sessionId)?.id,
2536
- markConversationMessage,
2537
- updateConversationStats
2534
+ markConversationMessage
2538
2535
  });
2539
2536
  await failSessionRecordBestEffort2({
2540
2537
  conversationId: args.conversationId,