@sentry/junior 0.93.0 → 0.95.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-hooks-ZG7IDOIN.js → agent-hooks-FTQ5EGPO.js} +9 -10
- package/dist/api/people/list.js +7 -7
- package/dist/api/people/profile.js +7 -7
- package/dist/api/people/shared.d.ts +2 -2
- package/dist/api-reference.d.ts +1 -1
- package/dist/app.js +474 -231
- package/dist/{catalog-runtime-NZHMSMYC.js → catalog-runtime-2D7IVKUT.js} +3 -3
- package/dist/chat/advisor-request.d.ts +4 -0
- package/dist/chat/agent/request.d.ts +2 -0
- package/dist/chat/agent/resume.d.ts +2 -0
- package/dist/chat/conversations/history.d.ts +128 -0
- package/dist/chat/conversations/legacy-import.d.ts +38 -0
- package/dist/chat/conversations/messages.d.ts +39 -0
- package/dist/chat/conversations/projection.d.ts +94 -0
- package/dist/chat/conversations/retention.d.ts +36 -0
- package/dist/chat/conversations/sql/conversation-row.d.ts +14 -0
- package/dist/chat/conversations/sql/history.d.ts +4 -0
- package/dist/chat/conversations/sql/legacy-history-import.d.ts +55 -0
- package/dist/chat/conversations/sql/messages.d.ts +4 -0
- package/dist/chat/conversations/sql/migrations.d.ts +14 -3
- package/dist/chat/conversations/sql/purge.d.ts +53 -0
- package/dist/chat/conversations/sql/store.d.ts +7 -2
- package/dist/chat/conversations/store.d.ts +19 -0
- package/dist/chat/conversations/visible-compactions.d.ts +11 -0
- package/dist/chat/conversations/visible-messages.d.ts +47 -0
- package/dist/chat/db.d.ts +12 -1
- package/dist/chat/egress/credentialed.d.ts +1 -1
- package/dist/chat/identities/sql.d.ts +1 -1
- package/dist/chat/logging.d.ts +2 -1
- package/dist/chat/resource-events/store.d.ts +2 -1
- package/dist/chat/runtime/reply-executor.d.ts +8 -0
- package/dist/chat/runtime/thread-state.d.ts +2 -0
- package/dist/chat/sandbox/egress/schemas.d.ts +4 -0
- package/dist/chat/sandbox/egress/session.d.ts +2 -2
- package/dist/chat/sandbox/resources.d.ts +4 -0
- package/dist/chat/services/mcp-auth-orchestration.d.ts +8 -0
- package/dist/chat/services/plugin-auth-orchestration.d.ts +12 -0
- package/dist/chat/services/turn-session-record.d.ts +14 -2
- package/dist/chat/sleep.d.ts +2 -0
- package/dist/chat/state/conversation.d.ts +7 -4
- package/dist/chat/state/session-log.d.ts +23 -1
- package/dist/chat/state/turn-session.d.ts +6 -0
- package/dist/chat/tool-support/private-trace-result.d.ts +4 -0
- package/dist/chat/tool-support/zod-tool.d.ts +1 -0
- package/dist/chat/tools/advisor/tool.d.ts +9 -4
- package/dist/chat/tools/definition.d.ts +2 -0
- package/dist/chat/tools/execution/tool-error-handler.d.ts +2 -2
- package/dist/chat/tools/system-time.d.ts +8 -0
- package/dist/chat/xml.d.ts +2 -0
- package/dist/{chunk-NYWPISSO.js → chunk-2XXEKR44.js} +1 -1
- package/dist/{chunk-QGEWC27H.js → chunk-5XMNOD3S.js} +5 -7
- package/dist/{chunk-NFXSLTYG.js → chunk-6ONME5IG.js} +864 -62
- package/dist/{chunk-LFLTJQVR.js → chunk-7FBGKXPE.js} +4 -0
- package/dist/{chunk-MC4ZZE4Q.js → chunk-AYP4ERVZ.js} +1 -1
- package/dist/{chunk-GHGPTPBL.js → chunk-B7PUBQQM.js} +1 -1
- package/dist/chunk-CM5EZD5F.js +17 -0
- package/dist/chunk-CRRBJ3JP.js +1037 -0
- package/dist/{chunk-G3E7SCME.js → chunk-CZEX6KIQ.js} +23 -0
- package/dist/{chunk-TNUUATT7.js → chunk-E3E2XNCN.js} +2 -2
- package/dist/{chunk-LNCREA5Z.js → chunk-EKNJM5IG.js} +3 -127
- package/dist/{chunk-NAPITCZ6.js → chunk-GUE7HTNR.js} +251 -6
- package/dist/{chunk-BTH37NCU.js → chunk-GVOUCI2O.js} +1 -1
- package/dist/{chunk-YYBX2BD5.js → chunk-GY34VGP5.js} +1 -1
- package/dist/{chunk-JJUJ4CO2.js → chunk-HCXXB35T.js} +1489 -360
- package/dist/{chunk-YTNPU7I2.js → chunk-HDTO3A74.js} +2 -2
- package/dist/{chunk-YJ4OPVNA.js → chunk-HZNJLKKI.js} +1 -1
- package/dist/{chunk-HDNWZMUN.js → chunk-KDPCGVIT.js} +116 -51
- package/dist/chunk-N4RNJ32C.js +48 -0
- package/dist/{chunk-UUB3D2XI.js → chunk-NSCHU54X.js} +8 -10
- package/dist/{chunk-PFXC67GJ.js → chunk-RAIB6WSG.js} +6 -80
- package/dist/chunk-WAGQ377B.js +724 -0
- package/dist/{chunk-6H4PP63X.js → chunk-WCMQJE4F.js} +24 -14
- package/dist/{chunk-S6QKIGRM.js → chunk-WPOJ443W.js} +15 -25
- package/dist/{chunk-MAVOJ54A.js → chunk-XX4N4E6C.js} +25 -388
- package/dist/cli/chat.js +24 -23
- package/dist/cli/check.js +4 -4
- package/dist/cli/plugins.js +11 -12
- package/dist/cli/snapshot-warmup.js +7 -8
- package/dist/cli/upgrade.js +78 -17
- package/dist/db/schema/agent-steps.d.ts +134 -0
- package/dist/db/schema/conversation-messages.d.ts +153 -0
- package/dist/{chat/conversations/sql → db}/schema/conversations.d.ts +34 -0
- package/dist/{chat/conversations/sql → db}/schema.d.ts +319 -8
- package/dist/db-W55B74OP.js +24 -0
- package/dist/deployment.d.ts +2 -0
- package/dist/handlers/retention.d.ts +6 -0
- package/dist/instrumentation.js +16 -3
- package/dist/legacy-import-ZPLGLAFD.js +17 -0
- package/dist/nitro.js +14 -4
- package/dist/reporting/conversations/activity.d.ts +40 -0
- package/dist/reporting/conversations/context.d.ts +8 -0
- package/dist/reporting/conversations/details.d.ts +6 -0
- package/dist/reporting/conversations/index.d.ts +4 -0
- package/dist/reporting/conversations/shared.d.ts +9 -0
- package/dist/reporting/conversations/statistics.d.ts +4 -0
- package/dist/reporting/conversations/summaries.d.ts +17 -0
- package/dist/reporting/conversations/transcript.d.ts +28 -0
- package/dist/reporting/conversations/types.d.ts +178 -0
- package/dist/reporting/conversations.d.ts +1 -178
- package/dist/reporting.d.ts +4 -3
- package/dist/reporting.js +603 -827
- package/dist/{runner-XAZPJNAQ.js → runner-OOSBDYRK.js} +35 -41
- package/dist/{validation-KYAWETI4.js → validation-QCGRFRFZ.js} +4 -4
- package/migrations/README.md +32 -0
- package/migrations/meta/0000_snapshot.json +978 -0
- package/migrations/meta/_journal.json +13 -0
- package/package.json +9 -6
- package/dist/chat/sql/schema.d.ts +0 -1049
- package/dist/chat/state/conversation-details.d.ts +0 -47
- package/dist/chunk-7STN2ZSK.js +0 -250
- package/dist/chunk-LE5ANBUZ.js +0 -1040
- package/dist/chunk-QL66APYJ.js +0 -1377
- package/dist/db-YDN6AFJH.js +0 -18
- /package/dist/{chat/sql → db}/db.d.ts +0 -0
- /package/dist/{chat/sql → db}/executor.d.ts +0 -0
- /package/dist/{chat/sql → db}/neon.d.ts +0 -0
- /package/dist/{chat/sql → db}/postgres.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/destinations.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/identities.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/migrations.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/timestamps.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/users.d.ts +0 -0
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
-
SANDBOX_WORKSPACE_ROOT
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
getStateAdapter
|
|
6
|
-
} from "./chunk-7STN2ZSK.js";
|
|
2
|
+
SANDBOX_WORKSPACE_ROOT,
|
|
3
|
+
sleep
|
|
4
|
+
} from "./chunk-CZEX6KIQ.js";
|
|
7
5
|
import {
|
|
6
|
+
getStateAdapter,
|
|
8
7
|
toOptionalTrimmed
|
|
9
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GUE7HTNR.js";
|
|
10
9
|
import {
|
|
11
10
|
pluginCatalogRuntime
|
|
12
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-GVOUCI2O.js";
|
|
13
12
|
import {
|
|
14
13
|
withSpan
|
|
15
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-WPOJ443W.js";
|
|
16
15
|
|
|
17
16
|
// src/chat/sandbox/runtime-dependency-snapshots.ts
|
|
18
17
|
import { createHash } from "crypto";
|
|
@@ -134,6 +133,19 @@ function createSandboxInstance(sandbox) {
|
|
|
134
133
|
};
|
|
135
134
|
}
|
|
136
135
|
|
|
136
|
+
// src/chat/sandbox/resources.ts
|
|
137
|
+
function getSandboxResources() {
|
|
138
|
+
const value = process.env.SANDBOX_VCPUS?.trim();
|
|
139
|
+
if (!value || !/^\d+$/.test(value)) {
|
|
140
|
+
return void 0;
|
|
141
|
+
}
|
|
142
|
+
const vcpus = Number(value);
|
|
143
|
+
if (!Number.isSafeInteger(vcpus) || vcpus <= 0) {
|
|
144
|
+
return void 0;
|
|
145
|
+
}
|
|
146
|
+
return { vcpus };
|
|
147
|
+
}
|
|
148
|
+
|
|
137
149
|
// src/chat/sandbox/runtime-dependency-snapshots.ts
|
|
138
150
|
var SNAPSHOT_CACHE_PREFIX = "junior:sandbox_snapshot_profile";
|
|
139
151
|
var SNAPSHOT_LOCK_PREFIX = "junior:sandbox_snapshot_lock";
|
|
@@ -142,11 +154,6 @@ var SNAPSHOT_CACHE_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
|
142
154
|
var SNAPSHOT_BUILD_LOCK_TTL_MS = 10 * 60 * 1e3;
|
|
143
155
|
var SNAPSHOT_WAIT_FOR_LOCK_MS = SNAPSHOT_BUILD_LOCK_TTL_MS + 30 * 1e3;
|
|
144
156
|
var DEFAULT_FLOATING_DEP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
145
|
-
function sleep(ms) {
|
|
146
|
-
return new Promise((resolve) => {
|
|
147
|
-
setTimeout(resolve, ms);
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
157
|
function profileCacheKey(profileHash) {
|
|
151
158
|
return `${SNAPSHOT_CACHE_PREFIX}:${profileHash}`;
|
|
152
159
|
}
|
|
@@ -461,11 +468,13 @@ async function createDependencySnapshot(profile, runtime, timeoutMs) {
|
|
|
461
468
|
},
|
|
462
469
|
async () => {
|
|
463
470
|
const sandboxCredentials = getVercelSandboxCredentials();
|
|
471
|
+
const resources = getSandboxResources();
|
|
464
472
|
const sandbox = createSandboxInstance(
|
|
465
473
|
await Sandbox.create({
|
|
466
474
|
timeout: timeoutMs,
|
|
467
475
|
runtime,
|
|
468
|
-
...sandboxCredentials ?? {}
|
|
476
|
+
...sandboxCredentials ?? {},
|
|
477
|
+
...resources ? { resources } : {}
|
|
469
478
|
})
|
|
470
479
|
);
|
|
471
480
|
try {
|
|
@@ -681,6 +690,7 @@ export {
|
|
|
681
690
|
buildNonInteractiveShellScript,
|
|
682
691
|
runNonInteractiveCommand,
|
|
683
692
|
getVercelSandboxCredentials,
|
|
693
|
+
getSandboxResources,
|
|
684
694
|
createSandboxInstance,
|
|
685
695
|
getRuntimeDependencyProfileHash,
|
|
686
696
|
resolveRuntimeDependencySnapshot,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
getDeploymentTelemetryAttributes,
|
|
15
15
|
parseSlackTeamId
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-7FBGKXPE.js";
|
|
17
17
|
|
|
18
18
|
// src/chat/logging.ts
|
|
19
19
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -1114,6 +1114,13 @@ function normalizeSpanAttributes(attributes) {
|
|
|
1114
1114
|
}
|
|
1115
1115
|
return normalized;
|
|
1116
1116
|
}
|
|
1117
|
+
function setAttributesOnSpan(span, attributes) {
|
|
1118
|
+
for (const [key, value] of Object.entries(
|
|
1119
|
+
normalizeSpanAttributes(attributes)
|
|
1120
|
+
)) {
|
|
1121
|
+
span.setAttribute(key, value);
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1117
1124
|
function logInfo(eventName, context = {}, attributes = {}, body) {
|
|
1118
1125
|
log.info(eventName, { ...toSpanAttributes(context), ...attributes }, body);
|
|
1119
1126
|
}
|
|
@@ -1157,7 +1164,7 @@ async function withSpan(name, op, context, callback, attributes = {}) {
|
|
|
1157
1164
|
...normalizedAttributes
|
|
1158
1165
|
}
|
|
1159
1166
|
},
|
|
1160
|
-
callback
|
|
1167
|
+
(span) => callback((attributes2) => setAttributesOnSpan(span, attributes2))
|
|
1161
1168
|
);
|
|
1162
1169
|
});
|
|
1163
1170
|
}
|
|
@@ -1177,32 +1184,20 @@ function getTracePropagationHeaders() {
|
|
|
1177
1184
|
return headers;
|
|
1178
1185
|
}
|
|
1179
1186
|
function setSpanAttributes(attributes) {
|
|
1180
|
-
const
|
|
1181
|
-
const span = sentry.getActiveSpan?.();
|
|
1187
|
+
const span = (void 0)();
|
|
1182
1188
|
if (!span) {
|
|
1183
1189
|
return;
|
|
1184
1190
|
}
|
|
1185
|
-
|
|
1186
|
-
if (typeof setAttribute !== "function") {
|
|
1187
|
-
return;
|
|
1188
|
-
}
|
|
1189
|
-
for (const [key, value] of Object.entries(
|
|
1190
|
-
normalizeSpanAttributes(attributes)
|
|
1191
|
-
)) {
|
|
1192
|
-
setAttribute.call(span, key, value);
|
|
1193
|
-
}
|
|
1191
|
+
setAttributesOnSpan(span, attributes);
|
|
1194
1192
|
}
|
|
1195
1193
|
function setSpanStatus(status) {
|
|
1196
|
-
const
|
|
1197
|
-
const span = sentry.getActiveSpan?.();
|
|
1194
|
+
const span = (void 0)();
|
|
1198
1195
|
if (!span) {
|
|
1199
1196
|
return;
|
|
1200
1197
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
}
|
|
1205
|
-
setStatus.call(span, status === "ok" ? "ok" : "internal_error");
|
|
1198
|
+
span.setStatus(
|
|
1199
|
+
status === "ok" ? { code: 1 } : { code: 2, message: "internal_error" }
|
|
1200
|
+
);
|
|
1206
1201
|
}
|
|
1207
1202
|
function getActiveTraceId() {
|
|
1208
1203
|
const sentry = sentry_exports;
|
|
@@ -1376,10 +1371,6 @@ var storedSlackActorSchema = z.object({
|
|
|
1376
1371
|
slackUserName: exactStoredStringSchema.optional(),
|
|
1377
1372
|
teamId: exactStoredStringSchema.optional()
|
|
1378
1373
|
}).strict();
|
|
1379
|
-
function parseActor(value) {
|
|
1380
|
-
const result = actorSchema.safeParse(value);
|
|
1381
|
-
return result.success ? result.data : void 0;
|
|
1382
|
-
}
|
|
1383
1374
|
function isUserActor(actor) {
|
|
1384
1375
|
return Boolean(actor && "userId" in actor);
|
|
1385
1376
|
}
|
|
@@ -1557,7 +1548,6 @@ export {
|
|
|
1557
1548
|
extractGenAiUsageSummary,
|
|
1558
1549
|
extractGenAiUsageAttributes,
|
|
1559
1550
|
storedSlackActorSchema,
|
|
1560
|
-
parseActor,
|
|
1561
1551
|
isUserActor,
|
|
1562
1552
|
parseActorUserId,
|
|
1563
1553
|
isActorUserId,
|
|
@@ -5,409 +5,54 @@ import {
|
|
|
5
5
|
} from "./chunk-KNFROR7R.js";
|
|
6
6
|
import {
|
|
7
7
|
clearPendingAuth,
|
|
8
|
+
getInterruptionMarker,
|
|
8
9
|
getPersistedThreadState,
|
|
9
10
|
markTurnCompleted,
|
|
10
11
|
mergeArtifactsState
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KDPCGVIT.js";
|
|
12
13
|
import {
|
|
13
14
|
coerceThreadConversationState
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-RAIB6WSG.js";
|
|
15
16
|
import {
|
|
16
|
-
getAgentTurnSessionRecord
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
getAgentTurnSessionRecord
|
|
18
|
+
} from "./chunk-WAGQ377B.js";
|
|
19
|
+
import {
|
|
20
|
+
generateConversationId,
|
|
21
|
+
hydrateConversationMessages,
|
|
22
|
+
markConversationMessage,
|
|
23
|
+
normalizeConversationText,
|
|
24
|
+
updateConversationStats,
|
|
25
|
+
upsertConversationMessage
|
|
26
|
+
} from "./chunk-CRRBJ3JP.js";
|
|
19
27
|
import {
|
|
20
28
|
createPluginEmbedder,
|
|
21
29
|
createPluginModel,
|
|
22
30
|
getPlugins
|
|
23
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-NSCHU54X.js";
|
|
24
32
|
import {
|
|
25
33
|
createPluginLogger,
|
|
26
34
|
createPluginState
|
|
27
|
-
} from "./chunk-
|
|
28
|
-
import {
|
|
29
|
-
getStateAdapter
|
|
30
|
-
} from "./chunk-7STN2ZSK.js";
|
|
35
|
+
} from "./chunk-E3E2XNCN.js";
|
|
31
36
|
import {
|
|
32
37
|
getDb
|
|
33
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-6ONME5IG.js";
|
|
34
39
|
import {
|
|
35
40
|
GEN_AI_PROVIDER_NAME,
|
|
36
41
|
botConfig,
|
|
37
|
-
escapeXml,
|
|
38
42
|
getPiMessageRole,
|
|
43
|
+
getStateAdapter,
|
|
39
44
|
instructionTextForProjection,
|
|
40
45
|
isToolResultError,
|
|
41
46
|
isToolResultMessage,
|
|
42
47
|
normalizeToolNameFromResult,
|
|
43
|
-
resolveGatewayModel,
|
|
44
48
|
stripRuntimeTurnContext
|
|
45
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-GUE7HTNR.js";
|
|
46
50
|
import {
|
|
47
|
-
buildTurnFailureResponse
|
|
48
|
-
|
|
49
|
-
setSpanAttributes
|
|
50
|
-
} from "./chunk-S6QKIGRM.js";
|
|
51
|
+
buildTurnFailureResponse
|
|
52
|
+
} from "./chunk-WPOJ443W.js";
|
|
51
53
|
import {
|
|
52
54
|
parseSlackMessageTs
|
|
53
|
-
} from "./chunk-
|
|
54
|
-
|
|
55
|
-
// src/chat/services/context-budget.ts
|
|
56
|
-
var COMPACTION_TRIGGER_INPUT_RATIO = 0.75;
|
|
57
|
-
var COMPACTION_OUTPUT_RESERVE_RATIO = 0.25;
|
|
58
|
-
var COMPACTION_TARGET_RATIO = 0.8;
|
|
59
|
-
var FALLBACK_CONTEXT_WINDOW_TOKENS = 4e5;
|
|
60
|
-
var FALLBACK_MAX_OUTPUT_TOKENS = 128e3;
|
|
61
|
-
function positiveInteger(value, fallback) {
|
|
62
|
-
return Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
|
|
63
|
-
}
|
|
64
|
-
function estimateTextTokens(text) {
|
|
65
|
-
return Math.ceil(text.length / 4);
|
|
66
|
-
}
|
|
67
|
-
function calculateContextCompactionTriggerTokens(model) {
|
|
68
|
-
const contextWindow = positiveInteger(
|
|
69
|
-
model.contextWindow,
|
|
70
|
-
FALLBACK_CONTEXT_WINDOW_TOKENS
|
|
71
|
-
);
|
|
72
|
-
const maxTokens = positiveInteger(
|
|
73
|
-
model.maxTokens,
|
|
74
|
-
FALLBACK_MAX_OUTPUT_TOKENS
|
|
75
|
-
);
|
|
76
|
-
const outputReserve = Math.min(
|
|
77
|
-
maxTokens,
|
|
78
|
-
Math.floor(contextWindow * COMPACTION_OUTPUT_RESERVE_RATIO)
|
|
79
|
-
);
|
|
80
|
-
const usableInputTokens = Math.max(1, contextWindow - outputReserve);
|
|
81
|
-
return Math.max(
|
|
82
|
-
1,
|
|
83
|
-
Math.floor(usableInputTokens * COMPACTION_TRIGGER_INPUT_RATIO)
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
function calculateContextCompactionTargetTokens(triggerTokens) {
|
|
87
|
-
return Math.max(1, Math.floor(triggerTokens * COMPACTION_TARGET_RATIO));
|
|
88
|
-
}
|
|
89
|
-
function getAgentContextCompactionTriggerTokens() {
|
|
90
|
-
const model = resolveGatewayModel(botConfig.modelId);
|
|
91
|
-
return calculateContextCompactionTriggerTokens({
|
|
92
|
-
contextWindow: botConfig.modelContextWindowTokens ?? model.contextWindow,
|
|
93
|
-
maxTokens: model.maxTokens
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
function getConversationContextCompactionTriggerTokens() {
|
|
97
|
-
const model = resolveGatewayModel(botConfig.fastModelId);
|
|
98
|
-
return calculateContextCompactionTriggerTokens({
|
|
99
|
-
contextWindow: model.contextWindow,
|
|
100
|
-
maxTokens: model.maxTokens
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// src/chat/services/conversation-memory.ts
|
|
105
|
-
var CONTEXT_MIN_LIVE_MESSAGES = 12;
|
|
106
|
-
var CONTEXT_COMPACTION_BATCH_SIZE = 24;
|
|
107
|
-
var CONTEXT_MAX_COMPACTIONS = 16;
|
|
108
|
-
var CONTEXT_MAX_MESSAGE_CHARS = 3200;
|
|
109
|
-
var SLACK_USER_ID_DISPLAY_PATTERN = /^[UW][A-Z0-9]{5,}$/;
|
|
110
|
-
function generateConversationId(prefix) {
|
|
111
|
-
return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
|
112
|
-
}
|
|
113
|
-
function normalizeConversationText(text) {
|
|
114
|
-
return text.trim().replace(/\s+/g, " ").slice(0, CONTEXT_MAX_MESSAGE_CHARS);
|
|
115
|
-
}
|
|
116
|
-
function buildImageContextSuffix(message, conversation) {
|
|
117
|
-
const byFileId = conversation?.vision.byFileId;
|
|
118
|
-
const imageFileIds = message.meta?.imageFileIds ?? [];
|
|
119
|
-
if (!byFileId || imageFileIds.length === 0) {
|
|
120
|
-
return "";
|
|
121
|
-
}
|
|
122
|
-
const summaries = imageFileIds.map((fileId) => byFileId[fileId]?.summary?.trim()).filter((summary) => Boolean(summary));
|
|
123
|
-
if (summaries.length === 0) {
|
|
124
|
-
return "";
|
|
125
|
-
}
|
|
126
|
-
return ` [image context: ${summaries.join(" | ")}]`;
|
|
127
|
-
}
|
|
128
|
-
function renderConversationMessageLine(message, conversation) {
|
|
129
|
-
const displayName = conversationAuthorDisplayName(message);
|
|
130
|
-
const markers = [];
|
|
131
|
-
if (message.meta?.replied === false) {
|
|
132
|
-
markers.push(
|
|
133
|
-
`assistant skipped: ${message.meta?.skippedReason ?? "no-reply route"}`
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
if (message.meta?.explicitMention) {
|
|
137
|
-
markers.push("explicit mention");
|
|
138
|
-
}
|
|
139
|
-
const markerSuffix = markers.length > 0 ? ` (${markers.join("; ")})` : "";
|
|
140
|
-
const imageContext = buildImageContextSuffix(message, conversation);
|
|
141
|
-
return `[${message.role}] ${displayName}: ${message.text}${imageContext}${markerSuffix}`;
|
|
142
|
-
}
|
|
143
|
-
function conversationAuthorDisplayName(message) {
|
|
144
|
-
const author = message.author;
|
|
145
|
-
const fullName = authorDisplayField(author?.fullName, author?.userId);
|
|
146
|
-
const userName = authorDisplayField(author?.userName, author?.userId);
|
|
147
|
-
return fullName ?? userName ?? (message.role === "assistant" ? botConfig.userName : message.role);
|
|
148
|
-
}
|
|
149
|
-
function authorDisplayField(value, userId) {
|
|
150
|
-
if (!value || value === userId || SLACK_USER_ID_DISPLAY_PATTERN.test(value)) {
|
|
151
|
-
return void 0;
|
|
152
|
-
}
|
|
153
|
-
return value;
|
|
154
|
-
}
|
|
155
|
-
function updateConversationStats(conversation) {
|
|
156
|
-
const contextText = buildConversationContext(conversation);
|
|
157
|
-
conversation.stats.estimatedContextTokens = estimateTextTokens(
|
|
158
|
-
contextText ?? ""
|
|
159
|
-
);
|
|
160
|
-
conversation.stats.totalMessageCount = conversation.messages.length;
|
|
161
|
-
conversation.stats.updatedAtMs = Date.now();
|
|
162
|
-
}
|
|
163
|
-
function upsertConversationMessage(conversation, message) {
|
|
164
|
-
const existingIndex = conversation.messages.findIndex(
|
|
165
|
-
(entry) => entry.id === message.id
|
|
166
|
-
);
|
|
167
|
-
if (existingIndex >= 0) {
|
|
168
|
-
conversation.messages[existingIndex] = {
|
|
169
|
-
...conversation.messages[existingIndex],
|
|
170
|
-
...message,
|
|
171
|
-
meta: {
|
|
172
|
-
...conversation.messages[existingIndex]?.meta,
|
|
173
|
-
...message.meta
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
updateConversationStats(conversation);
|
|
177
|
-
return message.id;
|
|
178
|
-
}
|
|
179
|
-
conversation.messages.push(message);
|
|
180
|
-
updateConversationStats(conversation);
|
|
181
|
-
return message.id;
|
|
182
|
-
}
|
|
183
|
-
function markConversationMessage(conversation, messageId, patch) {
|
|
184
|
-
if (!messageId) return;
|
|
185
|
-
const messageIndex = conversation.messages.findIndex(
|
|
186
|
-
(entry) => entry.id === messageId
|
|
187
|
-
);
|
|
188
|
-
if (messageIndex < 0) return;
|
|
189
|
-
const current = conversation.messages[messageIndex];
|
|
190
|
-
conversation.messages[messageIndex] = {
|
|
191
|
-
...current,
|
|
192
|
-
meta: {
|
|
193
|
-
...current.meta ?? {},
|
|
194
|
-
...patch
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
updateConversationStats(conversation);
|
|
198
|
-
}
|
|
199
|
-
function buildConversationContext(conversation, options = {}) {
|
|
200
|
-
const messages = conversation.messages.filter(
|
|
201
|
-
(entry) => entry.id !== options.excludeMessageId
|
|
202
|
-
);
|
|
203
|
-
if (messages.length === 0 && conversation.compactions.length === 0) {
|
|
204
|
-
return void 0;
|
|
205
|
-
}
|
|
206
|
-
const lines = [];
|
|
207
|
-
if (conversation.compactions.length > 0) {
|
|
208
|
-
lines.push("<thread-compactions>");
|
|
209
|
-
for (const [index, compaction] of conversation.compactions.entries()) {
|
|
210
|
-
lines.push(
|
|
211
|
-
` <compaction index="${index + 1}" covered_messages="${compaction.coveredMessageIds.length}" created_at="${new Date(compaction.createdAtMs).toISOString()}">`,
|
|
212
|
-
compaction.summary,
|
|
213
|
-
" </compaction>"
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
lines.push("</thread-compactions>");
|
|
217
|
-
}
|
|
218
|
-
if (messages.length > 0) {
|
|
219
|
-
if (lines.length > 0) {
|
|
220
|
-
lines.push("");
|
|
221
|
-
}
|
|
222
|
-
lines.push("<thread-transcript>");
|
|
223
|
-
for (const [index, message] of messages.entries()) {
|
|
224
|
-
const author = escapeXml(conversationAuthorDisplayName(message));
|
|
225
|
-
const actorIdAttr = message.author?.userId ? ` actor_id="${escapeXml(message.author.userId)}"` : "";
|
|
226
|
-
const ts = new Date(message.createdAtMs).toISOString();
|
|
227
|
-
const slackTsAttr = message.meta?.slackTs ? ` slack_ts="${escapeXml(message.meta.slackTs)}"` : "";
|
|
228
|
-
lines.push(
|
|
229
|
-
` <message index="${index + 1}" ts="${ts}" role="${message.role}" author="${author}"${actorIdAttr}${slackTsAttr}>`,
|
|
230
|
-
renderConversationMessageLine(message, conversation),
|
|
231
|
-
" </message>"
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
lines.push("</thread-transcript>");
|
|
235
|
-
}
|
|
236
|
-
return lines.join("\n");
|
|
237
|
-
}
|
|
238
|
-
function pruneCompactions(compactions) {
|
|
239
|
-
if (compactions.length <= CONTEXT_MAX_COMPACTIONS) {
|
|
240
|
-
return compactions;
|
|
241
|
-
}
|
|
242
|
-
const overflowCount = compactions.length - CONTEXT_MAX_COMPACTIONS + 1;
|
|
243
|
-
const merged = compactions.slice(0, overflowCount);
|
|
244
|
-
const mergedSummary = merged.map((entry) => entry.summary).join("\n").slice(0, 3500);
|
|
245
|
-
const mergedIds = merged.flatMap((entry) => entry.coveredMessageIds).slice(0, 500);
|
|
246
|
-
const compacted = {
|
|
247
|
-
id: generateConversationId("compaction"),
|
|
248
|
-
createdAtMs: Date.now(),
|
|
249
|
-
summary: mergedSummary,
|
|
250
|
-
coveredMessageIds: mergedIds
|
|
251
|
-
};
|
|
252
|
-
return [compacted, ...compactions.slice(overflowCount)];
|
|
253
|
-
}
|
|
254
|
-
async function summarizeConversationChunk(messages, conversation, context, deps) {
|
|
255
|
-
const transcript = messages.map((message) => renderConversationMessageLine(message, conversation)).join("\n");
|
|
256
|
-
try {
|
|
257
|
-
const result = await deps.completeText({
|
|
258
|
-
modelId: botConfig.fastModelId,
|
|
259
|
-
temperature: 0,
|
|
260
|
-
messages: [
|
|
261
|
-
{
|
|
262
|
-
role: "user",
|
|
263
|
-
content: [
|
|
264
|
-
"Summarize the following older Slack thread transcript segment for future assistant turns.",
|
|
265
|
-
"Keep the summary factual and concise. Do not invent details.",
|
|
266
|
-
"",
|
|
267
|
-
"Output exactly three XML sections in this order:",
|
|
268
|
-
"<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>",
|
|
269
|
-
"<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>",
|
|
270
|
-
"<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>",
|
|
271
|
-
"",
|
|
272
|
-
"Do not output any text outside the three sections.",
|
|
273
|
-
"",
|
|
274
|
-
transcript
|
|
275
|
-
].join("\n"),
|
|
276
|
-
timestamp: Date.now()
|
|
277
|
-
}
|
|
278
|
-
],
|
|
279
|
-
metadata: {
|
|
280
|
-
modelId: botConfig.fastModelId,
|
|
281
|
-
threadId: context.threadId ?? "",
|
|
282
|
-
channelId: context.channelId ?? "",
|
|
283
|
-
actorId: context.actorId ?? "",
|
|
284
|
-
runId: context.runId ?? ""
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
const summary = result.text.trim();
|
|
288
|
-
if (summary.length > 0) {
|
|
289
|
-
return summary.slice(0, 3500);
|
|
290
|
-
}
|
|
291
|
-
} catch (error) {
|
|
292
|
-
logWarn(
|
|
293
|
-
"conversation_compaction_summary_failed",
|
|
294
|
-
{
|
|
295
|
-
slackThreadId: context.threadId,
|
|
296
|
-
slackUserId: context.actorId,
|
|
297
|
-
slackChannelId: context.channelId,
|
|
298
|
-
runId: context.runId,
|
|
299
|
-
assistantUserName: botConfig.userName,
|
|
300
|
-
modelId: botConfig.fastModelId
|
|
301
|
-
},
|
|
302
|
-
{
|
|
303
|
-
"exception.message": error instanceof Error ? error.message : String(error),
|
|
304
|
-
"app.compaction_messages_covered": messages.length
|
|
305
|
-
},
|
|
306
|
-
"Compaction summarization failed; using fallback summary"
|
|
307
|
-
);
|
|
308
|
-
}
|
|
309
|
-
return transcript.slice(0, 2800);
|
|
310
|
-
}
|
|
311
|
-
async function generateThreadTitleWithDeps(sourceText, deps) {
|
|
312
|
-
const result = await deps.completeText({
|
|
313
|
-
modelId: botConfig.fastModelId,
|
|
314
|
-
temperature: 0,
|
|
315
|
-
messages: [
|
|
316
|
-
{
|
|
317
|
-
role: "user",
|
|
318
|
-
content: [
|
|
319
|
-
"Generate a concise 5-8 word Slack conversation title from the first user message below.",
|
|
320
|
-
"Capture the user's main request.",
|
|
321
|
-
"Reply with ONLY the title, with no quotes or trailing punctuation.",
|
|
322
|
-
"",
|
|
323
|
-
`First user message: ${sourceText.slice(0, 500)}`
|
|
324
|
-
].join("\n"),
|
|
325
|
-
timestamp: Date.now()
|
|
326
|
-
}
|
|
327
|
-
],
|
|
328
|
-
metadata: {
|
|
329
|
-
modelId: botConfig.fastModelId
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
return result.text.trim().slice(0, 60);
|
|
333
|
-
}
|
|
334
|
-
function getThreadTitleSourceMessage(conversation) {
|
|
335
|
-
let firstMessage;
|
|
336
|
-
for (const message of conversation.messages) {
|
|
337
|
-
if (!isHumanConversationMessage(message)) {
|
|
338
|
-
continue;
|
|
339
|
-
}
|
|
340
|
-
if (!firstMessage) {
|
|
341
|
-
firstMessage = message;
|
|
342
|
-
continue;
|
|
343
|
-
}
|
|
344
|
-
if (message.createdAtMs < firstMessage.createdAtMs) {
|
|
345
|
-
firstMessage = message;
|
|
346
|
-
continue;
|
|
347
|
-
}
|
|
348
|
-
if (message.createdAtMs === firstMessage.createdAtMs && message.id < firstMessage.id) {
|
|
349
|
-
firstMessage = message;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
return firstMessage;
|
|
353
|
-
}
|
|
354
|
-
async function compactConversationIfNeededWithDeps(conversation, context, deps) {
|
|
355
|
-
updateConversationStats(conversation);
|
|
356
|
-
let estimatedTokens = conversation.stats.estimatedContextTokens;
|
|
357
|
-
setSpanAttributes({
|
|
358
|
-
"app.context_tokens_estimated": estimatedTokens
|
|
359
|
-
});
|
|
360
|
-
const triggerTokens = getConversationContextCompactionTriggerTokens();
|
|
361
|
-
const targetTokens = calculateContextCompactionTargetTokens(triggerTokens);
|
|
362
|
-
while (estimatedTokens > triggerTokens && conversation.messages.length > CONTEXT_MIN_LIVE_MESSAGES) {
|
|
363
|
-
const compactCount = Math.min(
|
|
364
|
-
CONTEXT_COMPACTION_BATCH_SIZE,
|
|
365
|
-
conversation.messages.length - CONTEXT_MIN_LIVE_MESSAGES
|
|
366
|
-
);
|
|
367
|
-
if (compactCount <= 0) {
|
|
368
|
-
break;
|
|
369
|
-
}
|
|
370
|
-
const compactedChunk = conversation.messages.slice(0, compactCount);
|
|
371
|
-
const summary = await summarizeConversationChunk(
|
|
372
|
-
compactedChunk,
|
|
373
|
-
conversation,
|
|
374
|
-
context,
|
|
375
|
-
deps
|
|
376
|
-
);
|
|
377
|
-
conversation.compactions.push({
|
|
378
|
-
id: generateConversationId("compaction"),
|
|
379
|
-
createdAtMs: Date.now(),
|
|
380
|
-
summary,
|
|
381
|
-
coveredMessageIds: compactedChunk.map((entry) => entry.id)
|
|
382
|
-
});
|
|
383
|
-
conversation.compactions = pruneCompactions(conversation.compactions);
|
|
384
|
-
conversation.messages = conversation.messages.slice(compactCount);
|
|
385
|
-
conversation.stats.compactedMessageCount += compactCount;
|
|
386
|
-
updateConversationStats(conversation);
|
|
387
|
-
estimatedTokens = conversation.stats.estimatedContextTokens;
|
|
388
|
-
setSpanAttributes({
|
|
389
|
-
"app.compaction_messages_covered": compactCount,
|
|
390
|
-
"app.compaction.trigger_tokens": triggerTokens,
|
|
391
|
-
"app.compaction.target_tokens": targetTokens,
|
|
392
|
-
"app.context_tokens_estimated": estimatedTokens
|
|
393
|
-
});
|
|
394
|
-
if (estimatedTokens <= targetTokens) {
|
|
395
|
-
break;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
function createConversationMemoryService(deps) {
|
|
400
|
-
return {
|
|
401
|
-
compactConversationIfNeeded: async (conversation, context) => await compactConversationIfNeededWithDeps(conversation, context, deps),
|
|
402
|
-
generateThreadTitle: async (sourceText) => await generateThreadTitleWithDeps(sourceText, deps)
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
function isHumanConversationMessage(message) {
|
|
406
|
-
return message.role === "user" && message.author?.isBot !== true;
|
|
407
|
-
}
|
|
408
|
-
function getConversationMessageSlackTs(message) {
|
|
409
|
-
return parseSlackMessageTs(message.meta?.slackTs);
|
|
410
|
-
}
|
|
55
|
+
} from "./chunk-7FBGKXPE.js";
|
|
411
56
|
|
|
412
57
|
// src/chat/services/turn-failure-response.ts
|
|
413
58
|
function requireTurnFailureEventId(eventId, eventName) {
|
|
@@ -652,6 +297,10 @@ async function loadConversationContextTranscriptEntries(record) {
|
|
|
652
297
|
}
|
|
653
298
|
const state = await getPersistedThreadState(record.conversationId);
|
|
654
299
|
const conversation = coerceThreadConversationState(state);
|
|
300
|
+
await hydrateConversationMessages({
|
|
301
|
+
conversation,
|
|
302
|
+
conversationId: record.conversationId
|
|
303
|
+
});
|
|
655
304
|
const entries = [];
|
|
656
305
|
for (const message of conversation.messages) {
|
|
657
306
|
if (message.role !== "user") {
|
|
@@ -849,18 +498,6 @@ function buildDeliveredTurnStatePatch(args) {
|
|
|
849
498
|
}
|
|
850
499
|
|
|
851
500
|
export {
|
|
852
|
-
estimateTextTokens,
|
|
853
|
-
getAgentContextCompactionTriggerTokens,
|
|
854
|
-
generateConversationId,
|
|
855
|
-
normalizeConversationText,
|
|
856
|
-
updateConversationStats,
|
|
857
|
-
upsertConversationMessage,
|
|
858
|
-
markConversationMessage,
|
|
859
|
-
buildConversationContext,
|
|
860
|
-
getThreadTitleSourceMessage,
|
|
861
|
-
createConversationMemoryService,
|
|
862
|
-
isHumanConversationMessage,
|
|
863
|
-
getConversationMessageSlackTs,
|
|
864
501
|
requireTurnFailureEventId,
|
|
865
502
|
getAgentTurnDiagnosticsAttributes,
|
|
866
503
|
finalizeFailedTurnReply,
|