@sentry/junior 0.141.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.
- package/dist/{agent-hooks-HIRVKUQJ.js → agent-hooks-WDJQQAPH.js} +10 -10
- package/dist/api/schema/task.d.ts +8 -0
- package/dist/api/schema.js +1 -1
- package/dist/api.js +34 -22
- package/dist/app.js +62 -91
- package/dist/{catalog-runtime-XVLED5UH.js → catalog-runtime-CLHTYBHB.js} +5 -5
- package/dist/chat/event-tasks/types.d.ts +7 -1
- package/dist/chat/runtime/turn.d.ts +0 -4
- package/dist/chat/scheduled-tasks/tools/create.d.ts +1 -0
- package/dist/chat/scheduled-tasks/types.d.ts +5 -0
- package/dist/chat/services/conversation-memory.d.ts +2 -1
- package/dist/chat/services/short-title.d.ts +25 -0
- package/dist/chat/state/conversation.d.ts +6 -17
- package/dist/chat/tools/create-event-task.d.ts +1 -0
- package/dist/{chunk-OHO46E7F.js → chunk-4EZV6URQ.js} +88 -36
- package/dist/{chunk-3H42HMA2.js → chunk-4L7PKEHM.js} +5 -1
- package/dist/{chunk-HQAFIN6O.js → chunk-5ITSZIAP.js} +1 -1
- package/dist/{chunk-UONUDOJP.js → chunk-5QVVW3FY.js} +7 -7
- package/dist/{chunk-5LPWHC7Q.js → chunk-6IMKBHCG.js} +80 -46
- package/dist/{chunk-2DOVDDZJ.js → chunk-7R3CGEMF.js} +3 -3
- package/dist/{chunk-BBLO66XT.js → chunk-A646AKNB.js} +2 -2
- package/dist/{chunk-PIQKV7IR.js → chunk-B2H7NI5C.js} +10 -451
- package/dist/{chunk-NFL4FRIU.js → chunk-CA4WLRA3.js} +4 -4
- package/dist/{chunk-6FRAWWGR.js → chunk-CBMIVCPM.js} +2 -2
- package/dist/chunk-DRTWANQF.js +67 -0
- package/dist/{chunk-44NWPKY3.js → chunk-HVTWCMDS.js} +1 -1
- package/dist/{chunk-43OPSFUY.js → chunk-JIWZ7T4C.js} +1 -1
- package/dist/{chunk-PGJUJCOQ.js → chunk-LGY7YX5O.js} +1 -1
- package/dist/{chunk-OFQBDHVG.js → chunk-LL3BGP7J.js} +1 -1
- package/dist/{chunk-HN4UZTG7.js → chunk-LXLBYA6N.js} +2 -2
- package/dist/{chunk-FWXSPJRN.js → chunk-N3H7G5K6.js} +1 -1
- package/dist/{chunk-6U44QGXL.js → chunk-NWO5IB7V.js} +1 -1
- package/dist/{chunk-YWM6MJT4.js → chunk-OGQGJAD7.js} +2 -0
- package/dist/{chunk-DBKS7JR2.js → chunk-OQAPYAXH.js} +3 -3
- package/dist/{chunk-7ULXCNOZ.js → chunk-PWDCFIQG.js} +6 -6
- package/dist/{chunk-FZFJZZR3.js → chunk-QDRMQI5W.js} +4 -4
- package/dist/{chunk-DK3GQWJK.js → chunk-R7E476CH.js} +6 -6
- package/dist/{chunk-DVIJ6DP6.js → chunk-RYYBUI34.js} +2 -2
- package/dist/{chunk-5MFCEKR6.js → chunk-SCHH6264.js} +3 -3
- package/dist/{chunk-LMGKSDO4.js → chunk-SF6YKONJ.js} +1 -1
- package/dist/{chunk-H4WNQFBH.js → chunk-T4NFQ5SG.js} +5 -5
- package/dist/{chunk-A2O7SGK5.js → chunk-VJMBLWYR.js} +6 -6
- package/dist/{chunk-DKH4WGZU.js → chunk-WJEW7UNC.js} +341 -16
- package/dist/{chunk-EYD523BV.js → chunk-WYLSMTWU.js} +1 -1
- package/dist/{chunk-UFEU4UX6.js → chunk-XAW6IN6M.js} +1 -1
- package/dist/chunk-XFHSZNOX.js +75 -0
- package/dist/{chunk-LIVSCWI5.js → chunk-ZPNUI4L3.js} +23 -26
- package/dist/cli/chat.js +32 -30
- package/dist/cli/check.js +6 -6
- package/dist/cli/plugins.js +13 -13
- package/dist/cli/snapshot-create.js +9 -9
- package/dist/cli/upgrade.js +7 -7
- package/dist/db/schema/event-tasks.d.ts +20 -52
- package/dist/db/schema/scheduled-tasks.d.ts +17 -0
- package/dist/db/schema.d.ts +36 -52
- package/dist/{db-PSMQZR4P.js → db-6N4CD5AI.js} +7 -7
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +2 -2
- package/dist/{oauth-callback-server-XZUK2AT6.js → oauth-callback-server-G4K2X56R.js} +23 -21
- package/dist/{runner-5EKJCQWP.js → runner-DEIHVRUE.js} +24 -25
- package/dist/{skills-2PRM42SE.js → skills-FZVJ6ZFW.js} +6 -6
- package/dist/{spawn-UGTLRTFP.js → spawn-WD4F67SZ.js} +17 -17
- package/dist/{validation-XLXAIRTR.js → validation-EOLSG7B6.js} +6 -6
- package/dist/version.js +1 -1
- package/dist/{work-CNTNEQ2Q.js → work-AS3IBMLA.js} +16 -16
- package/dist/{worker-BGW7CKZ7.js → worker-VGGNGOUU.js} +10 -10
- package/migrations/0023_task_title_columns.sql +2 -0
- package/migrations/meta/0023_snapshot.json +2198 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +5 -5
|
@@ -21,35 +21,28 @@ import {
|
|
|
21
21
|
instructionProvenanceFor,
|
|
22
22
|
sanitizePostgresJson,
|
|
23
23
|
withConversationEventLock
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-SCHH6264.js";
|
|
25
25
|
import {
|
|
26
26
|
SANDBOX_WORKSPACE_ROOT,
|
|
27
27
|
sleep
|
|
28
28
|
} from "./chunk-EM225ITJ.js";
|
|
29
29
|
import {
|
|
30
30
|
getStateAdapter
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-NWO5IB7V.js";
|
|
32
32
|
import {
|
|
33
33
|
botConfig,
|
|
34
|
-
escapeXml,
|
|
35
|
-
resolveGatewayModel,
|
|
36
34
|
unwrapCurrentInstruction
|
|
37
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-A646AKNB.js";
|
|
38
36
|
import {
|
|
39
37
|
toStoredSlackActor
|
|
40
38
|
} from "./chunk-HZF5P5UN.js";
|
|
41
|
-
import {
|
|
42
|
-
parseSlackMessageTs
|
|
43
|
-
} from "./chunk-F3B2YJ76.js";
|
|
44
39
|
import {
|
|
45
40
|
getActiveTraceId,
|
|
46
41
|
isRecord,
|
|
47
42
|
logException,
|
|
48
|
-
logWarn,
|
|
49
|
-
setSpanAttributes,
|
|
50
43
|
toOptionalNumber,
|
|
51
44
|
toOptionalString
|
|
52
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-XAW6IN6M.js";
|
|
53
46
|
|
|
54
47
|
// src/chat/turn-context-tag.ts
|
|
55
48
|
var TURN_CONTEXT_TAG = "runtime-turn-context";
|
|
@@ -188,392 +181,6 @@ function stripRuntimeTurnContext(messages) {
|
|
|
188
181
|
});
|
|
189
182
|
}
|
|
190
183
|
|
|
191
|
-
// src/chat/services/context-budget.ts
|
|
192
|
-
var COMPACTION_TRIGGER_RATIO = 0.9;
|
|
193
|
-
var CONTEXT_INPUT_LIMIT_RATIO = 0.95;
|
|
194
|
-
var COMPACTION_TARGET_RATIO = 0.8;
|
|
195
|
-
var FALLBACK_CONTEXT_WINDOW_TOKENS = 4e5;
|
|
196
|
-
function positiveInteger(value, fallback) {
|
|
197
|
-
return Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
|
|
198
|
-
}
|
|
199
|
-
function estimateTextTokens(text) {
|
|
200
|
-
return Math.ceil(text.length / 4);
|
|
201
|
-
}
|
|
202
|
-
function calculateContextCompactionTriggerTokens(model) {
|
|
203
|
-
const contextWindow = positiveInteger(
|
|
204
|
-
model.contextWindow,
|
|
205
|
-
FALLBACK_CONTEXT_WINDOW_TOKENS
|
|
206
|
-
);
|
|
207
|
-
return Math.max(1, Math.floor(contextWindow * COMPACTION_TRIGGER_RATIO));
|
|
208
|
-
}
|
|
209
|
-
function calculateContextInputLimitTokens(model) {
|
|
210
|
-
const contextWindow = positiveInteger(
|
|
211
|
-
model.contextWindow,
|
|
212
|
-
FALLBACK_CONTEXT_WINDOW_TOKENS
|
|
213
|
-
);
|
|
214
|
-
return Math.max(1, Math.floor(contextWindow * CONTEXT_INPUT_LIMIT_RATIO));
|
|
215
|
-
}
|
|
216
|
-
function calculateContextCompactionTargetTokens(triggerTokens) {
|
|
217
|
-
return Math.max(1, Math.floor(triggerTokens * COMPACTION_TARGET_RATIO));
|
|
218
|
-
}
|
|
219
|
-
function getModelContextBudget(modelId) {
|
|
220
|
-
const model = resolveGatewayModel(modelId);
|
|
221
|
-
const advertisedContextWindow = positiveInteger(
|
|
222
|
-
model.contextWindow,
|
|
223
|
-
FALLBACK_CONTEXT_WINDOW_TOKENS
|
|
224
|
-
);
|
|
225
|
-
return {
|
|
226
|
-
contextWindow: Math.min(
|
|
227
|
-
botConfig.contextWindowTokens,
|
|
228
|
-
advertisedContextWindow
|
|
229
|
-
)
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
function getAgentContextCompactionTriggerTokens(modelId) {
|
|
233
|
-
return calculateContextCompactionTriggerTokens(
|
|
234
|
-
getModelContextBudget(modelId)
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
function getAgentContextInputLimitTokens(modelId) {
|
|
238
|
-
return calculateContextInputLimitTokens(getModelContextBudget(modelId));
|
|
239
|
-
}
|
|
240
|
-
function getConversationContextCompactionTriggerTokens() {
|
|
241
|
-
return calculateContextCompactionTriggerTokens(
|
|
242
|
-
getModelContextBudget(botConfig.fastModelId)
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// src/chat/services/conversation-memory.ts
|
|
247
|
-
var CONTEXT_MIN_LIVE_MESSAGES = 12;
|
|
248
|
-
var CONTEXT_COMPACTION_BATCH_SIZE = 24;
|
|
249
|
-
var CONTEXT_MAX_COMPACTIONS = 16;
|
|
250
|
-
var CONTEXT_MAX_MESSAGE_CHARS = 3200;
|
|
251
|
-
var SLACK_USER_ID_DISPLAY_PATTERN = /^[UW][A-Z0-9]{5,}$/;
|
|
252
|
-
function generateConversationId(prefix) {
|
|
253
|
-
return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
|
254
|
-
}
|
|
255
|
-
function normalizeConversationText(text) {
|
|
256
|
-
return text.replace(/\r\n?/g, "\n").trim();
|
|
257
|
-
}
|
|
258
|
-
function buildImageContextSuffix(message, conversation) {
|
|
259
|
-
const byFileId = conversation?.vision.byFileId;
|
|
260
|
-
const imageFileIds = message.meta?.imageFileIds ?? [];
|
|
261
|
-
if (!byFileId || imageFileIds.length === 0) {
|
|
262
|
-
return "";
|
|
263
|
-
}
|
|
264
|
-
const summaries = imageFileIds.map((fileId) => byFileId[fileId]?.summary?.trim()).filter((summary) => Boolean(summary));
|
|
265
|
-
if (summaries.length === 0) {
|
|
266
|
-
return "";
|
|
267
|
-
}
|
|
268
|
-
return ` [image context: ${summaries.join(" | ")}]`;
|
|
269
|
-
}
|
|
270
|
-
function renderConversationMessageLine(message, conversation) {
|
|
271
|
-
const displayName = conversationAuthorDisplayName(message);
|
|
272
|
-
const text = message.text.replace(/\s+/g, " ").slice(0, CONTEXT_MAX_MESSAGE_CHARS);
|
|
273
|
-
const markers = [];
|
|
274
|
-
if (message.meta?.replied === false) {
|
|
275
|
-
markers.push(
|
|
276
|
-
`assistant skipped: ${message.meta?.skippedReason ?? "no-reply route"}`
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
if (message.meta?.explicitMention) {
|
|
280
|
-
markers.push("explicit mention");
|
|
281
|
-
}
|
|
282
|
-
const markerSuffix = markers.length > 0 ? ` (${markers.join("; ")})` : "";
|
|
283
|
-
const imageContext = buildImageContextSuffix(message, conversation);
|
|
284
|
-
return `[${message.role}] ${displayName}: ${text}${imageContext}${markerSuffix}`;
|
|
285
|
-
}
|
|
286
|
-
function conversationAuthorDisplayName(message) {
|
|
287
|
-
const author = message.author;
|
|
288
|
-
const fullName = authorDisplayField(author?.fullName, author?.userId);
|
|
289
|
-
const userName = authorDisplayField(author?.userName, author?.userId);
|
|
290
|
-
return fullName ?? userName ?? (message.role === "assistant" ? botConfig.userName : message.role);
|
|
291
|
-
}
|
|
292
|
-
function authorDisplayField(value, userId) {
|
|
293
|
-
if (!value || value === userId || SLACK_USER_ID_DISPLAY_PATTERN.test(value)) {
|
|
294
|
-
return void 0;
|
|
295
|
-
}
|
|
296
|
-
return value;
|
|
297
|
-
}
|
|
298
|
-
function updateConversationStats(conversation) {
|
|
299
|
-
const contextText = buildConversationContext(conversation);
|
|
300
|
-
conversation.stats.estimatedContextTokens = estimateTextTokens(
|
|
301
|
-
contextText ?? ""
|
|
302
|
-
);
|
|
303
|
-
conversation.stats.totalMessageCount = conversation.messages.length;
|
|
304
|
-
conversation.stats.updatedAtMs = Date.now();
|
|
305
|
-
}
|
|
306
|
-
function upsertConversationMessage(conversation, message) {
|
|
307
|
-
const existingIndex = conversation.messages.findIndex(
|
|
308
|
-
(entry) => entry.id === message.id
|
|
309
|
-
);
|
|
310
|
-
if (existingIndex >= 0) {
|
|
311
|
-
conversation.messages[existingIndex] = {
|
|
312
|
-
...conversation.messages[existingIndex],
|
|
313
|
-
...message,
|
|
314
|
-
meta: {
|
|
315
|
-
...conversation.messages[existingIndex]?.meta,
|
|
316
|
-
...message.meta
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
|
-
updateConversationStats(conversation);
|
|
320
|
-
return message.id;
|
|
321
|
-
}
|
|
322
|
-
conversation.messages.push(message);
|
|
323
|
-
updateConversationStats(conversation);
|
|
324
|
-
return message.id;
|
|
325
|
-
}
|
|
326
|
-
function recordDeliveredAssistantMessage(args) {
|
|
327
|
-
const prefix = `${args.sessionId}:assistant:`;
|
|
328
|
-
const ordinal = args.conversation.messages.filter(
|
|
329
|
-
(message) => message.id.startsWith(prefix)
|
|
330
|
-
).length + 1;
|
|
331
|
-
const messageId = `${prefix}${ordinal}`;
|
|
332
|
-
markConversationMessage(args.conversation, args.userMessageId, {
|
|
333
|
-
replied: true,
|
|
334
|
-
skippedReason: void 0
|
|
335
|
-
});
|
|
336
|
-
upsertConversationMessage(args.conversation, {
|
|
337
|
-
id: messageId,
|
|
338
|
-
role: "assistant",
|
|
339
|
-
text: normalizeConversationText(args.text),
|
|
340
|
-
createdAtMs: Date.now(),
|
|
341
|
-
author: {
|
|
342
|
-
userName: botConfig.userName,
|
|
343
|
-
isBot: true
|
|
344
|
-
},
|
|
345
|
-
meta: {
|
|
346
|
-
replied: true
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
return messageId;
|
|
350
|
-
}
|
|
351
|
-
function turnHasReply(conversation, turnId) {
|
|
352
|
-
const assistantPrefix = `${turnId}:assistant:`;
|
|
353
|
-
return conversation.messages.some(
|
|
354
|
-
(message) => message.role === "assistant" && message.id.startsWith(assistantPrefix)
|
|
355
|
-
);
|
|
356
|
-
}
|
|
357
|
-
function markConversationMessage(conversation, messageId, patch) {
|
|
358
|
-
if (!messageId) return;
|
|
359
|
-
const messageIndex = conversation.messages.findIndex(
|
|
360
|
-
(entry) => entry.id === messageId
|
|
361
|
-
);
|
|
362
|
-
if (messageIndex < 0) return;
|
|
363
|
-
const current = conversation.messages[messageIndex];
|
|
364
|
-
conversation.messages[messageIndex] = {
|
|
365
|
-
...current,
|
|
366
|
-
meta: {
|
|
367
|
-
...current.meta ?? {},
|
|
368
|
-
...patch
|
|
369
|
-
}
|
|
370
|
-
};
|
|
371
|
-
updateConversationStats(conversation);
|
|
372
|
-
}
|
|
373
|
-
function buildConversationContext(conversation, options = {}) {
|
|
374
|
-
const messages = conversation.messages.filter(
|
|
375
|
-
(entry) => entry.id !== options.excludeMessageId
|
|
376
|
-
);
|
|
377
|
-
if (messages.length === 0 && conversation.compactions.length === 0) {
|
|
378
|
-
return void 0;
|
|
379
|
-
}
|
|
380
|
-
const lines = [];
|
|
381
|
-
if (conversation.compactions.length > 0) {
|
|
382
|
-
lines.push("<thread-compactions>");
|
|
383
|
-
for (const [index, compaction] of conversation.compactions.entries()) {
|
|
384
|
-
lines.push(
|
|
385
|
-
` <compaction index="${index + 1}" covered_messages="${compaction.coveredMessageCount}" created_at="${new Date(compaction.createdAtMs).toISOString()}">`,
|
|
386
|
-
compaction.summary,
|
|
387
|
-
" </compaction>"
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
lines.push("</thread-compactions>");
|
|
391
|
-
}
|
|
392
|
-
if (messages.length > 0) {
|
|
393
|
-
if (lines.length > 0) {
|
|
394
|
-
lines.push("");
|
|
395
|
-
}
|
|
396
|
-
lines.push("<thread-transcript>");
|
|
397
|
-
for (const [index, message] of messages.entries()) {
|
|
398
|
-
const author = escapeXml(conversationAuthorDisplayName(message));
|
|
399
|
-
const actorIdAttr = message.author?.userId ? ` actor_id="${escapeXml(message.author.userId)}"` : "";
|
|
400
|
-
const ts = new Date(message.createdAtMs).toISOString();
|
|
401
|
-
const slackTsAttr = message.meta?.slackTs ? ` slack_ts="${escapeXml(message.meta.slackTs)}"` : "";
|
|
402
|
-
lines.push(
|
|
403
|
-
` <message index="${index + 1}" ts="${ts}" role="${message.role}" author="${author}"${actorIdAttr}${slackTsAttr}>`,
|
|
404
|
-
renderConversationMessageLine(message, conversation),
|
|
405
|
-
" </message>"
|
|
406
|
-
);
|
|
407
|
-
}
|
|
408
|
-
lines.push("</thread-transcript>");
|
|
409
|
-
}
|
|
410
|
-
return lines.join("\n");
|
|
411
|
-
}
|
|
412
|
-
function pruneCompactions(compactions) {
|
|
413
|
-
if (compactions.length <= CONTEXT_MAX_COMPACTIONS) {
|
|
414
|
-
return compactions;
|
|
415
|
-
}
|
|
416
|
-
const overflowCount = compactions.length - CONTEXT_MAX_COMPACTIONS + 1;
|
|
417
|
-
const merged = compactions.slice(0, overflowCount);
|
|
418
|
-
const mergedSummary = merged.map((entry) => entry.summary).join("\n").slice(0, 3500);
|
|
419
|
-
const coveredMessageCount = merged.reduce(
|
|
420
|
-
(count, entry) => count + entry.coveredMessageCount,
|
|
421
|
-
0
|
|
422
|
-
);
|
|
423
|
-
const compacted = {
|
|
424
|
-
id: generateConversationId("compaction"),
|
|
425
|
-
createdAtMs: Date.now(),
|
|
426
|
-
summary: mergedSummary,
|
|
427
|
-
coveredMessageCount
|
|
428
|
-
};
|
|
429
|
-
return [compacted, ...compactions.slice(overflowCount)];
|
|
430
|
-
}
|
|
431
|
-
async function summarizeConversationChunk(messages, conversation, context, deps) {
|
|
432
|
-
const transcript = messages.map((message) => renderConversationMessageLine(message, conversation)).join("\n");
|
|
433
|
-
try {
|
|
434
|
-
const result = await deps.completeText({
|
|
435
|
-
modelId: botConfig.fastModelId,
|
|
436
|
-
temperature: 0,
|
|
437
|
-
messages: [
|
|
438
|
-
{
|
|
439
|
-
role: "user",
|
|
440
|
-
content: [
|
|
441
|
-
"Summarize the following older Slack thread transcript segment for future assistant turns.",
|
|
442
|
-
"Keep the summary factual and concise. Do not invent details.",
|
|
443
|
-
"",
|
|
444
|
-
"Output exactly three XML sections in this order:",
|
|
445
|
-
"<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>",
|
|
446
|
-
"<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>",
|
|
447
|
-
"<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>",
|
|
448
|
-
"",
|
|
449
|
-
"Do not output any text outside the three sections.",
|
|
450
|
-
"",
|
|
451
|
-
transcript
|
|
452
|
-
].join("\n"),
|
|
453
|
-
timestamp: Date.now()
|
|
454
|
-
}
|
|
455
|
-
],
|
|
456
|
-
metadata: {
|
|
457
|
-
modelId: botConfig.fastModelId,
|
|
458
|
-
threadId: context.threadId ?? "",
|
|
459
|
-
channelId: context.channelId ?? "",
|
|
460
|
-
actorId: context.actorId ?? "",
|
|
461
|
-
runId: context.runId ?? ""
|
|
462
|
-
}
|
|
463
|
-
});
|
|
464
|
-
const summary = result.text.trim();
|
|
465
|
-
if (summary.length > 0) {
|
|
466
|
-
return summary.slice(0, 3500);
|
|
467
|
-
}
|
|
468
|
-
} catch (error) {
|
|
469
|
-
logWarn("conversation.compaction.summary.failed", {
|
|
470
|
-
"exception.message": error instanceof Error ? error.message : String(error),
|
|
471
|
-
"app.compaction_messages_covered": messages.length
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
return transcript.slice(0, 2800);
|
|
475
|
-
}
|
|
476
|
-
async function generateThreadTitleWithDeps(sourceText, deps) {
|
|
477
|
-
const result = await deps.completeText({
|
|
478
|
-
modelId: botConfig.fastModelId,
|
|
479
|
-
temperature: 0,
|
|
480
|
-
messages: [
|
|
481
|
-
{
|
|
482
|
-
role: "user",
|
|
483
|
-
content: [
|
|
484
|
-
"Generate a concise 5-8 word Slack conversation title from the first user message below.",
|
|
485
|
-
"Capture the user's main request.",
|
|
486
|
-
"Reply with ONLY the title, with no quotes or trailing punctuation.",
|
|
487
|
-
"",
|
|
488
|
-
`First user message: ${sourceText.slice(0, 500)}`
|
|
489
|
-
].join("\n"),
|
|
490
|
-
timestamp: Date.now()
|
|
491
|
-
}
|
|
492
|
-
],
|
|
493
|
-
metadata: {
|
|
494
|
-
modelId: botConfig.fastModelId
|
|
495
|
-
}
|
|
496
|
-
});
|
|
497
|
-
return result.text.trim().slice(0, 60);
|
|
498
|
-
}
|
|
499
|
-
function getThreadTitleSourceMessage(conversation) {
|
|
500
|
-
let firstMessage;
|
|
501
|
-
for (const message of conversation.messages) {
|
|
502
|
-
if (!isHumanConversationMessage(message)) {
|
|
503
|
-
continue;
|
|
504
|
-
}
|
|
505
|
-
if (!firstMessage) {
|
|
506
|
-
firstMessage = message;
|
|
507
|
-
continue;
|
|
508
|
-
}
|
|
509
|
-
if (message.createdAtMs < firstMessage.createdAtMs) {
|
|
510
|
-
firstMessage = message;
|
|
511
|
-
continue;
|
|
512
|
-
}
|
|
513
|
-
if (message.createdAtMs === firstMessage.createdAtMs && message.id < firstMessage.id) {
|
|
514
|
-
firstMessage = message;
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
return firstMessage;
|
|
518
|
-
}
|
|
519
|
-
async function compactConversationIfNeededWithDeps(conversation, context, deps) {
|
|
520
|
-
updateConversationStats(conversation);
|
|
521
|
-
let estimatedTokens = conversation.stats.estimatedContextTokens;
|
|
522
|
-
setSpanAttributes({
|
|
523
|
-
"app.context_tokens_estimated": estimatedTokens
|
|
524
|
-
});
|
|
525
|
-
const triggerTokens = getConversationContextCompactionTriggerTokens();
|
|
526
|
-
const targetTokens = calculateContextCompactionTargetTokens(triggerTokens);
|
|
527
|
-
while (estimatedTokens > triggerTokens && conversation.messages.length > CONTEXT_MIN_LIVE_MESSAGES) {
|
|
528
|
-
const compactCount = Math.min(
|
|
529
|
-
CONTEXT_COMPACTION_BATCH_SIZE,
|
|
530
|
-
conversation.messages.length - CONTEXT_MIN_LIVE_MESSAGES
|
|
531
|
-
);
|
|
532
|
-
if (compactCount <= 0) {
|
|
533
|
-
break;
|
|
534
|
-
}
|
|
535
|
-
const compactedChunk = conversation.messages.slice(0, compactCount);
|
|
536
|
-
const summary = await summarizeConversationChunk(
|
|
537
|
-
compactedChunk,
|
|
538
|
-
conversation,
|
|
539
|
-
context,
|
|
540
|
-
deps
|
|
541
|
-
);
|
|
542
|
-
conversation.compactions.push({
|
|
543
|
-
id: generateConversationId("compaction"),
|
|
544
|
-
createdAtMs: Date.now(),
|
|
545
|
-
summary,
|
|
546
|
-
coveredMessageCount: compactedChunk.length
|
|
547
|
-
});
|
|
548
|
-
conversation.compactions = pruneCompactions(conversation.compactions);
|
|
549
|
-
conversation.messages = conversation.messages.slice(compactCount);
|
|
550
|
-
conversation.stats.compactedMessageCount += compactCount;
|
|
551
|
-
updateConversationStats(conversation);
|
|
552
|
-
estimatedTokens = conversation.stats.estimatedContextTokens;
|
|
553
|
-
setSpanAttributes({
|
|
554
|
-
"app.compaction_messages_covered": compactCount,
|
|
555
|
-
"app.compaction.trigger_tokens": triggerTokens,
|
|
556
|
-
"app.compaction.target_tokens": targetTokens,
|
|
557
|
-
"app.context_tokens_estimated": estimatedTokens
|
|
558
|
-
});
|
|
559
|
-
if (estimatedTokens <= targetTokens) {
|
|
560
|
-
break;
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
function createConversationMemoryService(deps) {
|
|
565
|
-
return {
|
|
566
|
-
compactConversationIfNeeded: async (conversation, context) => await compactConversationIfNeededWithDeps(conversation, context, deps),
|
|
567
|
-
generateThreadTitle: async (sourceText) => await generateThreadTitleWithDeps(sourceText, deps)
|
|
568
|
-
};
|
|
569
|
-
}
|
|
570
|
-
function isHumanConversationMessage(message) {
|
|
571
|
-
return message.role === "user" && message.author?.isBot !== true;
|
|
572
|
-
}
|
|
573
|
-
function getConversationMessageSlackTs(message) {
|
|
574
|
-
return parseSlackMessageTs(message.meta?.slackTs);
|
|
575
|
-
}
|
|
576
|
-
|
|
577
184
|
// src/chat/conversations/messages.ts
|
|
578
185
|
import { createHash } from "crypto";
|
|
579
186
|
import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
|
|
@@ -714,7 +321,6 @@ async function hydrateConversationMessages(args) {
|
|
|
714
321
|
);
|
|
715
322
|
args.conversation.compactions = history.compaction ? projectConversationMessageSummaries([history.compaction]) : [];
|
|
716
323
|
args.conversation.messages = projectConversationMessages(history);
|
|
717
|
-
updateConversationStats(args.conversation);
|
|
718
324
|
}
|
|
719
325
|
async function persistConversationMessages(args) {
|
|
720
326
|
if (!args.conversationId || args.conversation.messages.length === 0) return;
|
|
@@ -1387,7 +993,6 @@ function isTurnInputDeferredError(error) {
|
|
|
1387
993
|
}
|
|
1388
994
|
function startActiveTurn(args) {
|
|
1389
995
|
args.conversation.processing.activeTurnId = args.nextTurnId;
|
|
1390
|
-
args.updateConversationStats(args.conversation);
|
|
1391
996
|
}
|
|
1392
997
|
function clearActiveTurn(conversation, sessionId) {
|
|
1393
998
|
if (!sessionId || conversation.processing.activeTurnId === sessionId) {
|
|
@@ -1397,12 +1002,10 @@ function clearActiveTurn(conversation, sessionId) {
|
|
|
1397
1002
|
function markTurnClosed(args) {
|
|
1398
1003
|
clearActiveTurn(args.conversation, args.sessionId);
|
|
1399
1004
|
args.conversation.processing.lastCompletedAtMs = args.nowMs;
|
|
1400
|
-
args.updateConversationStats(args.conversation);
|
|
1401
1005
|
}
|
|
1402
1006
|
function markTurnCompleted(args) {
|
|
1403
1007
|
clearActiveTurn(args.conversation, args.sessionId);
|
|
1404
1008
|
args.conversation.processing.lastCompletedAtMs = args.nowMs;
|
|
1405
|
-
args.updateConversationStats(args.conversation);
|
|
1406
1009
|
}
|
|
1407
1010
|
function markTurnFailed(args) {
|
|
1408
1011
|
clearActiveTurn(args.conversation, args.sessionId);
|
|
@@ -1411,7 +1014,6 @@ function markTurnFailed(args) {
|
|
|
1411
1014
|
replied: false,
|
|
1412
1015
|
skippedReason: "reply failed"
|
|
1413
1016
|
});
|
|
1414
|
-
args.updateConversationStats(args.conversation);
|
|
1415
1017
|
}
|
|
1416
1018
|
|
|
1417
1019
|
// src/chat/no-reply.ts
|
|
@@ -1470,7 +1072,7 @@ var RIPGREP_EXCLUDED_GLOBS = [
|
|
|
1470
1072
|
];
|
|
1471
1073
|
var DEFAULT_SEARCH_COMMAND_TIMEOUT_MS = 3e4;
|
|
1472
1074
|
var SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
1473
|
-
function
|
|
1075
|
+
function positiveInteger(value) {
|
|
1474
1076
|
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
1475
1077
|
return void 0;
|
|
1476
1078
|
}
|
|
@@ -2817,19 +2419,11 @@ async function persistYieldSessionRecord(args) {
|
|
|
2817
2419
|
|
|
2818
2420
|
// src/chat/state/conversation.ts
|
|
2819
2421
|
function defaultConversationState() {
|
|
2820
|
-
const nowMs = Date.now();
|
|
2821
2422
|
return {
|
|
2822
2423
|
schemaVersion: 1,
|
|
2823
2424
|
messages: [],
|
|
2824
2425
|
compactions: [],
|
|
2825
|
-
backfill: {},
|
|
2826
2426
|
processing: {},
|
|
2827
|
-
stats: {
|
|
2828
|
-
estimatedContextTokens: 0,
|
|
2829
|
-
totalMessageCount: 0,
|
|
2830
|
-
compactedMessageCount: 0,
|
|
2831
|
-
updatedAtMs: nowMs
|
|
2832
|
-
},
|
|
2833
2427
|
vision: {
|
|
2834
2428
|
byFileId: {}
|
|
2835
2429
|
}
|
|
@@ -2864,27 +2458,14 @@ function coerceThreadConversationState(value) {
|
|
|
2864
2458
|
}
|
|
2865
2459
|
const root = value;
|
|
2866
2460
|
const rawConversation = isRecord(root.conversation) ? root.conversation : {};
|
|
2867
|
-
const base = defaultConversationState();
|
|
2868
2461
|
const messages = [];
|
|
2869
2462
|
const compactions = [];
|
|
2870
|
-
const rawBackfill = isRecord(rawConversation.backfill) ? rawConversation.backfill : {};
|
|
2871
|
-
const backfill = {
|
|
2872
|
-
completedAtMs: toOptionalNumber(rawBackfill.completedAtMs),
|
|
2873
|
-
source: rawBackfill.source === "recent_messages" || rawBackfill.source === "thread_fetch" ? rawBackfill.source : void 0
|
|
2874
|
-
};
|
|
2875
2463
|
const rawProcessing = isRecord(rawConversation.processing) ? rawConversation.processing : {};
|
|
2876
2464
|
const processing = {
|
|
2877
2465
|
activeTurnId: toOptionalString(rawProcessing.activeTurnId),
|
|
2878
2466
|
lastCompletedAtMs: toOptionalNumber(rawProcessing.lastCompletedAtMs),
|
|
2879
2467
|
pendingAuth: coercePendingAuthState(rawProcessing.pendingAuth)
|
|
2880
2468
|
};
|
|
2881
|
-
const rawStats = isRecord(rawConversation.stats) ? rawConversation.stats : {};
|
|
2882
|
-
const stats = {
|
|
2883
|
-
estimatedContextTokens: toOptionalNumber(rawStats.estimatedContextTokens) ?? base.stats.estimatedContextTokens,
|
|
2884
|
-
totalMessageCount: toOptionalNumber(rawStats.totalMessageCount) ?? messages.length,
|
|
2885
|
-
compactedMessageCount: toOptionalNumber(rawStats.compactedMessageCount) ?? 0,
|
|
2886
|
-
updatedAtMs: toOptionalNumber(rawStats.updatedAtMs) ?? base.stats.updatedAtMs
|
|
2887
|
-
};
|
|
2888
2469
|
const rawVision = isRecord(rawConversation.vision) ? rawConversation.vision : {};
|
|
2889
2470
|
const rawVisionByFileId = isRecord(rawVision.byFileId) ? rawVision.byFileId : {};
|
|
2890
2471
|
const byFileId = {};
|
|
@@ -2903,9 +2484,7 @@ function coerceThreadConversationState(value) {
|
|
|
2903
2484
|
schemaVersion: 1,
|
|
2904
2485
|
messages,
|
|
2905
2486
|
compactions,
|
|
2906
|
-
backfill,
|
|
2907
2487
|
processing,
|
|
2908
|
-
stats,
|
|
2909
2488
|
vision: {
|
|
2910
2489
|
backfillCompletedAtMs: toOptionalNumber(rawVision.backfillCompletedAtMs),
|
|
2911
2490
|
byFileId
|
|
@@ -2913,19 +2492,13 @@ function coerceThreadConversationState(value) {
|
|
|
2913
2492
|
};
|
|
2914
2493
|
}
|
|
2915
2494
|
function buildConversationStatePatch(conversation) {
|
|
2916
|
-
const {
|
|
2917
|
-
compactions: _compactions,
|
|
2918
|
-
messages: _messages,
|
|
2919
|
-
...scratch
|
|
2920
|
-
} = conversation;
|
|
2921
2495
|
return {
|
|
2922
2496
|
conversation: {
|
|
2923
|
-
...scratch,
|
|
2924
2497
|
schemaVersion: 1,
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2498
|
+
processing: { ...conversation.processing },
|
|
2499
|
+
vision: {
|
|
2500
|
+
backfillCompletedAtMs: conversation.vision.backfillCompletedAtMs,
|
|
2501
|
+
byFileId: { ...conversation.vision.byFileId }
|
|
2929
2502
|
}
|
|
2930
2503
|
}
|
|
2931
2504
|
};
|
|
@@ -3393,20 +2966,6 @@ export {
|
|
|
3393
2966
|
historyItemFromPiMessage,
|
|
3394
2967
|
piMessageFromHistoryItem,
|
|
3395
2968
|
persistConversationMessageSummaries,
|
|
3396
|
-
estimateTextTokens,
|
|
3397
|
-
getAgentContextCompactionTriggerTokens,
|
|
3398
|
-
getAgentContextInputLimitTokens,
|
|
3399
|
-
normalizeConversationText,
|
|
3400
|
-
updateConversationStats,
|
|
3401
|
-
upsertConversationMessage,
|
|
3402
|
-
recordDeliveredAssistantMessage,
|
|
3403
|
-
turnHasReply,
|
|
3404
|
-
markConversationMessage,
|
|
3405
|
-
buildConversationContext,
|
|
3406
|
-
getThreadTitleSourceMessage,
|
|
3407
|
-
createConversationMemoryService,
|
|
3408
|
-
isHumanConversationMessage,
|
|
3409
|
-
getConversationMessageSlackTs,
|
|
3410
2969
|
hydrateConversationMessages,
|
|
3411
2970
|
persistConversationMessages,
|
|
3412
2971
|
loadProjection,
|
|
@@ -3427,7 +2986,7 @@ export {
|
|
|
3427
2986
|
MAX_TEXT_CHARS,
|
|
3428
2987
|
RIPGREP_EXCLUDED_GLOBS,
|
|
3429
2988
|
DEFAULT_SEARCH_COMMAND_TIMEOUT_MS,
|
|
3430
|
-
|
|
2989
|
+
positiveInteger,
|
|
3431
2990
|
normalizeToLf,
|
|
3432
2991
|
truncateText,
|
|
3433
2992
|
isMissingPathError,
|
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
getConversationStore,
|
|
6
6
|
parseDestination,
|
|
7
7
|
sameDestination
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-SCHH6264.js";
|
|
9
9
|
import {
|
|
10
10
|
getDefaultRedisStateAdapterFor,
|
|
11
11
|
getStateAdapter
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-NWO5IB7V.js";
|
|
13
13
|
import {
|
|
14
14
|
getChatConfig
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-A646AKNB.js";
|
|
16
16
|
import {
|
|
17
17
|
parseStoredSlackActor
|
|
18
18
|
} from "./chunk-HZF5P5UN.js";
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
isRecord,
|
|
21
21
|
toOptionalNumber,
|
|
22
22
|
toOptionalString
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-XAW6IN6M.js";
|
|
24
24
|
|
|
25
25
|
// src/chat/task-execution/state.ts
|
|
26
26
|
import { randomUUID } from "crypto";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
botConfig,
|
|
3
|
+
resolveGatewayModel
|
|
4
|
+
} from "./chunk-A646AKNB.js";
|
|
5
|
+
|
|
6
|
+
// src/chat/services/context-budget.ts
|
|
7
|
+
var COMPACTION_TRIGGER_RATIO = 0.9;
|
|
8
|
+
var CONTEXT_INPUT_LIMIT_RATIO = 0.95;
|
|
9
|
+
var COMPACTION_TARGET_RATIO = 0.8;
|
|
10
|
+
var FALLBACK_CONTEXT_WINDOW_TOKENS = 4e5;
|
|
11
|
+
function positiveInteger(value, fallback) {
|
|
12
|
+
return Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
|
|
13
|
+
}
|
|
14
|
+
function estimateTextTokens(text) {
|
|
15
|
+
return Math.ceil(text.length / 4);
|
|
16
|
+
}
|
|
17
|
+
function calculateContextCompactionTriggerTokens(model) {
|
|
18
|
+
const contextWindow = positiveInteger(
|
|
19
|
+
model.contextWindow,
|
|
20
|
+
FALLBACK_CONTEXT_WINDOW_TOKENS
|
|
21
|
+
);
|
|
22
|
+
return Math.max(1, Math.floor(contextWindow * COMPACTION_TRIGGER_RATIO));
|
|
23
|
+
}
|
|
24
|
+
function calculateContextInputLimitTokens(model) {
|
|
25
|
+
const contextWindow = positiveInteger(
|
|
26
|
+
model.contextWindow,
|
|
27
|
+
FALLBACK_CONTEXT_WINDOW_TOKENS
|
|
28
|
+
);
|
|
29
|
+
return Math.max(1, Math.floor(contextWindow * CONTEXT_INPUT_LIMIT_RATIO));
|
|
30
|
+
}
|
|
31
|
+
function calculateContextCompactionTargetTokens(triggerTokens) {
|
|
32
|
+
return Math.max(1, Math.floor(triggerTokens * COMPACTION_TARGET_RATIO));
|
|
33
|
+
}
|
|
34
|
+
function getModelContextBudget(modelId) {
|
|
35
|
+
const model = resolveGatewayModel(modelId);
|
|
36
|
+
const advertisedContextWindow = positiveInteger(
|
|
37
|
+
model.contextWindow,
|
|
38
|
+
FALLBACK_CONTEXT_WINDOW_TOKENS
|
|
39
|
+
);
|
|
40
|
+
return {
|
|
41
|
+
contextWindow: Math.min(
|
|
42
|
+
botConfig.contextWindowTokens,
|
|
43
|
+
advertisedContextWindow
|
|
44
|
+
)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function getAgentContextCompactionTriggerTokens(modelId) {
|
|
48
|
+
return calculateContextCompactionTriggerTokens(
|
|
49
|
+
getModelContextBudget(modelId)
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
function getAgentContextInputLimitTokens(modelId) {
|
|
53
|
+
return calculateContextInputLimitTokens(getModelContextBudget(modelId));
|
|
54
|
+
}
|
|
55
|
+
function getConversationContextCompactionTriggerTokens() {
|
|
56
|
+
return calculateContextCompactionTriggerTokens(
|
|
57
|
+
getModelContextBudget(botConfig.fastModelId)
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export {
|
|
62
|
+
estimateTextTokens,
|
|
63
|
+
calculateContextCompactionTargetTokens,
|
|
64
|
+
getAgentContextCompactionTriggerTokens,
|
|
65
|
+
getAgentContextInputLimitTokens,
|
|
66
|
+
getConversationContextCompactionTriggerTokens
|
|
67
|
+
};
|