@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,3 +1,25 @@
|
|
|
1
|
+
// src/chat/sleep.ts
|
|
2
|
+
function sleep(ms, signal) {
|
|
3
|
+
if (!signal) {
|
|
4
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5
|
+
}
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
if (signal.aborted) {
|
|
8
|
+
reject(signal.reason);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const timeoutId = setTimeout(() => {
|
|
12
|
+
signal.removeEventListener("abort", onAbort);
|
|
13
|
+
resolve();
|
|
14
|
+
}, ms);
|
|
15
|
+
const onAbort = () => {
|
|
16
|
+
clearTimeout(timeoutId);
|
|
17
|
+
reject(signal.reason);
|
|
18
|
+
};
|
|
19
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
1
23
|
// src/chat/sandbox/paths.ts
|
|
2
24
|
function normalizeWorkspaceRoot(input) {
|
|
3
25
|
const candidate = (input ?? "").trim();
|
|
@@ -20,6 +42,7 @@ function sandboxSkillFile(skillName) {
|
|
|
20
42
|
}
|
|
21
43
|
|
|
22
44
|
export {
|
|
45
|
+
sleep,
|
|
23
46
|
SANDBOX_WORKSPACE_ROOT,
|
|
24
47
|
SANDBOX_SKILLS_ROOT,
|
|
25
48
|
SANDBOX_DATA_ROOT,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getStateAdapter
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-GUE7HTNR.js";
|
|
4
4
|
import {
|
|
5
5
|
logException,
|
|
6
6
|
logInfo,
|
|
7
7
|
logWarn
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-WPOJ443W.js";
|
|
9
9
|
|
|
10
10
|
// src/chat/plugins/logging.ts
|
|
11
11
|
function createPluginLogger(plugin) {
|
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
normalizeSlackConversationId
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import {
|
|
5
|
-
getStateAdapter
|
|
6
|
-
} from "./chunk-7STN2ZSK.js";
|
|
3
|
+
} from "./chunk-NSCHU54X.js";
|
|
7
4
|
import {
|
|
8
5
|
parseSlackThreadId
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import {
|
|
11
|
-
parseStoredSlackActor
|
|
12
|
-
} from "./chunk-S6QKIGRM.js";
|
|
13
|
-
import {
|
|
14
|
-
isRecord,
|
|
15
|
-
toOptionalNumber
|
|
16
|
-
} from "./chunk-OB42YVAE.js";
|
|
6
|
+
} from "./chunk-GY34VGP5.js";
|
|
17
7
|
import {
|
|
18
8
|
getClient
|
|
19
9
|
} from "./chunk-3DA7X2U3.js";
|
|
@@ -164,116 +154,6 @@ function formatSlackConversationRedactedLabel(context) {
|
|
|
164
154
|
return formatSlackConversationTypeLabel(context.type);
|
|
165
155
|
}
|
|
166
156
|
|
|
167
|
-
// src/chat/state/conversation-details.ts
|
|
168
|
-
import { THREAD_STATE_TTL_MS } from "chat";
|
|
169
|
-
var CONVERSATION_PREFIX = "junior:conversation";
|
|
170
|
-
var CONVERSATION_DETAILS_TTL_MS = THREAD_STATE_TTL_MS;
|
|
171
|
-
function conversationContextKey(conversationId) {
|
|
172
|
-
return `${CONVERSATION_PREFIX}:${conversationId}:context`;
|
|
173
|
-
}
|
|
174
|
-
function conversationTitleKey(conversationId) {
|
|
175
|
-
return `${CONVERSATION_PREFIX}:${conversationId}:title`;
|
|
176
|
-
}
|
|
177
|
-
function parseOriginActor(value) {
|
|
178
|
-
return parseStoredSlackActor(value);
|
|
179
|
-
}
|
|
180
|
-
function parseOriginSurface(value) {
|
|
181
|
-
if (value === "slack" || value === "api" || value === "scheduler" || value === "internal") {
|
|
182
|
-
return value;
|
|
183
|
-
}
|
|
184
|
-
return void 0;
|
|
185
|
-
}
|
|
186
|
-
function storedContextFromInput(context) {
|
|
187
|
-
return {
|
|
188
|
-
...context.channelName ? { channelName: context.channelName } : {},
|
|
189
|
-
...context.originSurface ? { originSurface: context.originSurface } : {},
|
|
190
|
-
...context.originActor ? { originActor: context.originActor } : {},
|
|
191
|
-
startedAtMs: context.startedAtMs
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
function parseContext(value) {
|
|
195
|
-
if (!isRecord(value)) return void 0;
|
|
196
|
-
const startedAtMs = toOptionalNumber(value.startedAtMs);
|
|
197
|
-
if (startedAtMs === void 0) return void 0;
|
|
198
|
-
return {
|
|
199
|
-
...typeof value.channelName === "string" && value.channelName.trim() ? { channelName: value.channelName.trim() } : {},
|
|
200
|
-
...parseOriginSurface(value.originSurface) ? { originSurface: parseOriginSurface(value.originSurface) } : {},
|
|
201
|
-
...parseOriginActor(value.originActor) ? { originActor: parseOriginActor(value.originActor) } : {},
|
|
202
|
-
startedAtMs
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
function parseTitle(value) {
|
|
206
|
-
if (!isRecord(value)) return void 0;
|
|
207
|
-
const displayTitle = typeof value.displayTitle === "string" && value.displayTitle.trim() ? value.displayTitle.trim() : void 0;
|
|
208
|
-
if (!displayTitle) return void 0;
|
|
209
|
-
return {
|
|
210
|
-
displayTitle,
|
|
211
|
-
...typeof value.titleSourceMessageId === "string" ? { titleSourceMessageId: value.titleSourceMessageId } : {}
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
async function initConversationContext(conversationId, context) {
|
|
215
|
-
const stateAdapter = getStateAdapter();
|
|
216
|
-
await stateAdapter.connect();
|
|
217
|
-
const key = conversationContextKey(conversationId);
|
|
218
|
-
const inserted = await stateAdapter.setIfNotExists(
|
|
219
|
-
key,
|
|
220
|
-
storedContextFromInput(context),
|
|
221
|
-
CONVERSATION_DETAILS_TTL_MS
|
|
222
|
-
);
|
|
223
|
-
if (inserted) return;
|
|
224
|
-
const existing = parseContext(await stateAdapter.get(key));
|
|
225
|
-
if (!existing) {
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
await stateAdapter.set(key, existing, CONVERSATION_DETAILS_TTL_MS);
|
|
229
|
-
}
|
|
230
|
-
async function setConversationTitle(conversationId, title) {
|
|
231
|
-
const stateAdapter = getStateAdapter();
|
|
232
|
-
await stateAdapter.connect();
|
|
233
|
-
await stateAdapter.set(
|
|
234
|
-
conversationTitleKey(conversationId),
|
|
235
|
-
{
|
|
236
|
-
displayTitle: title.displayTitle,
|
|
237
|
-
...title.titleSourceMessageId ? { titleSourceMessageId: title.titleSourceMessageId } : {}
|
|
238
|
-
},
|
|
239
|
-
CONVERSATION_DETAILS_TTL_MS
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
async function getConversationDetails(conversationId) {
|
|
243
|
-
const stateAdapter = getStateAdapter();
|
|
244
|
-
await stateAdapter.connect();
|
|
245
|
-
const [rawContext, rawTitle] = await Promise.all([
|
|
246
|
-
stateAdapter.get(conversationContextKey(conversationId)),
|
|
247
|
-
stateAdapter.get(conversationTitleKey(conversationId))
|
|
248
|
-
]);
|
|
249
|
-
const context = parseContext(rawContext);
|
|
250
|
-
const title = parseTitle(rawTitle);
|
|
251
|
-
if (!context && !title) return void 0;
|
|
252
|
-
return {
|
|
253
|
-
conversationId,
|
|
254
|
-
...title?.displayTitle ? { displayTitle: title.displayTitle } : {},
|
|
255
|
-
...title?.titleSourceMessageId ? { titleSourceMessageId: title.titleSourceMessageId } : {},
|
|
256
|
-
...context?.channelName ? { channelName: context.channelName } : {},
|
|
257
|
-
...context?.originSurface ? { originSurface: context.originSurface } : {},
|
|
258
|
-
...context?.originActor ? { originActor: context.originActor } : {},
|
|
259
|
-
...context?.startedAtMs !== void 0 ? { startedAtMs: context.startedAtMs } : {}
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
async function getConversationDetailsForIds(conversationIds) {
|
|
263
|
-
const uniqueIds = [...new Set(conversationIds)].filter(Boolean);
|
|
264
|
-
const entries = await Promise.all(
|
|
265
|
-
uniqueIds.map(async (id) => {
|
|
266
|
-
const details = await getConversationDetails(id);
|
|
267
|
-
return details ? [id, details] : void 0;
|
|
268
|
-
})
|
|
269
|
-
);
|
|
270
|
-
const result = /* @__PURE__ */ new Map();
|
|
271
|
-
for (const entry of entries) {
|
|
272
|
-
if (entry) result.set(entry[0], entry[1]);
|
|
273
|
-
}
|
|
274
|
-
return result;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
157
|
export {
|
|
278
158
|
GET,
|
|
279
159
|
buildSentryConversationUrl,
|
|
@@ -282,9 +162,5 @@ export {
|
|
|
282
162
|
resolveSlackChannelTypeFromMessage,
|
|
283
163
|
resolveSlackConversationContext,
|
|
284
164
|
resolveSlackConversationContextFromThreadId,
|
|
285
|
-
formatSlackConversationRedactedLabel
|
|
286
|
-
initConversationContext,
|
|
287
|
-
setConversationTitle,
|
|
288
|
-
getConversationDetails,
|
|
289
|
-
getConversationDetailsForIds
|
|
165
|
+
formatSlackConversationRedactedLabel
|
|
290
166
|
};
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
toGenAiMessageMetadata,
|
|
7
7
|
toGenAiMessagesTraceAttributes,
|
|
8
8
|
toGenAiTextMetadata
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-GY34VGP5.js";
|
|
10
10
|
import {
|
|
11
11
|
extractGenAiUsageAttributes,
|
|
12
12
|
logException,
|
|
@@ -14,12 +14,15 @@ import {
|
|
|
14
14
|
serializeGenAiAttribute,
|
|
15
15
|
setSpanAttributes,
|
|
16
16
|
withSpan
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-WPOJ443W.js";
|
|
18
18
|
|
|
19
19
|
// src/chat/xml.ts
|
|
20
20
|
function escapeXml(value) {
|
|
21
21
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
22
22
|
}
|
|
23
|
+
function unescapeXml(value) {
|
|
24
|
+
return value.replaceAll(""", '"').replaceAll("'", "'").replaceAll(">", ">").replaceAll("<", "<").replaceAll("&", "&");
|
|
25
|
+
}
|
|
23
26
|
|
|
24
27
|
// src/chat/current-instruction.ts
|
|
25
28
|
var CURRENT_INSTRUCTION_TAG = "current-instruction";
|
|
@@ -28,9 +31,6 @@ var CURRENT_INSTRUCTION_OPEN_BARE = `<${CURRENT_INSTRUCTION_TAG}>`;
|
|
|
28
31
|
var CURRENT_INSTRUCTION_OPEN_ATTR_PREFIX = `<${CURRENT_INSTRUCTION_TAG} `;
|
|
29
32
|
var CURRENT_INSTRUCTION_CLOSE = `
|
|
30
33
|
</${CURRENT_INSTRUCTION_TAG}>`;
|
|
31
|
-
function unescapeXml(value) {
|
|
32
|
-
return value.replaceAll(""", '"').replaceAll("'", "'").replaceAll(">", ">").replaceAll("<", "<").replaceAll("&", "&");
|
|
33
|
-
}
|
|
34
34
|
function isCurrentInstructionOpeningTag(value) {
|
|
35
35
|
return value === CURRENT_INSTRUCTION_OPEN_BARE || value.startsWith(CURRENT_INSTRUCTION_OPEN_ATTR_PREFIX) && value.endsWith(">");
|
|
36
36
|
}
|
|
@@ -795,9 +795,249 @@ function setSlackReactionConfig(overrides) {
|
|
|
795
795
|
}
|
|
796
796
|
}
|
|
797
797
|
|
|
798
|
+
// src/chat/state/adapter.ts
|
|
799
|
+
import { createMemoryState } from "@chat-adapter/state-memory";
|
|
800
|
+
import { createRedisState } from "@chat-adapter/state-redis";
|
|
801
|
+
|
|
802
|
+
// src/chat/state/locks.ts
|
|
803
|
+
var ACTIVE_LOCK_TTL_MS = 9e4;
|
|
804
|
+
async function acquireActiveLock(state, threadId) {
|
|
805
|
+
return await state.acquireLock(threadId, ACTIVE_LOCK_TTL_MS);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// src/chat/state/adapter.ts
|
|
809
|
+
var ACTIVE_LOCK_HEARTBEAT_MS = 3e4;
|
|
810
|
+
var stateAdapter;
|
|
811
|
+
var redisStateAdapter;
|
|
812
|
+
function createPrefixedStateAdapter(base, prefix) {
|
|
813
|
+
const prefixed = (value) => `${prefix}:${value}`;
|
|
814
|
+
const unprefixed = (value) => value.startsWith(`${prefix}:`) ? value.slice(prefix.length + 1) : value;
|
|
815
|
+
const prefixLock = (lock) => ({
|
|
816
|
+
...lock,
|
|
817
|
+
threadId: prefixed(lock.threadId)
|
|
818
|
+
});
|
|
819
|
+
const unprefixLock = (lock) => ({
|
|
820
|
+
...lock,
|
|
821
|
+
threadId: unprefixed(lock.threadId)
|
|
822
|
+
});
|
|
823
|
+
return {
|
|
824
|
+
appendToList: (key, value, options) => base.appendToList(prefixed(key), value, options),
|
|
825
|
+
connect: () => base.connect(),
|
|
826
|
+
disconnect: () => base.disconnect(),
|
|
827
|
+
subscribe: (threadId) => base.subscribe(prefixed(threadId)),
|
|
828
|
+
unsubscribe: (threadId) => base.unsubscribe(prefixed(threadId)),
|
|
829
|
+
isSubscribed: (threadId) => base.isSubscribed(prefixed(threadId)),
|
|
830
|
+
acquireLock: async (threadId, ttlMs) => {
|
|
831
|
+
const lock = await base.acquireLock(prefixed(threadId), ttlMs);
|
|
832
|
+
return lock ? unprefixLock(lock) : null;
|
|
833
|
+
},
|
|
834
|
+
releaseLock: (lock) => base.releaseLock(prefixLock(lock)),
|
|
835
|
+
extendLock: async (lock, ttlMs) => {
|
|
836
|
+
const prefixedLock = prefixLock(lock);
|
|
837
|
+
const extended = await base.extendLock(prefixedLock, ttlMs);
|
|
838
|
+
if (extended) {
|
|
839
|
+
lock.expiresAt = prefixedLock.expiresAt;
|
|
840
|
+
}
|
|
841
|
+
return extended;
|
|
842
|
+
},
|
|
843
|
+
forceReleaseLock: (threadId) => base.forceReleaseLock(prefixed(threadId)),
|
|
844
|
+
enqueue: (threadId, entry, maxSize) => base.enqueue(prefixed(threadId), entry, maxSize),
|
|
845
|
+
dequeue: (threadId) => base.dequeue(prefixed(threadId)),
|
|
846
|
+
queueDepth: (threadId) => base.queueDepth(prefixed(threadId)),
|
|
847
|
+
get: (key) => base.get(prefixed(key)),
|
|
848
|
+
getList: (key) => base.getList(prefixed(key)),
|
|
849
|
+
set: (key, value, ttlMs) => base.set(prefixed(key), value, ttlMs),
|
|
850
|
+
setIfNotExists: (key, value, ttlMs) => base.setIfNotExists(prefixed(key), value, ttlMs),
|
|
851
|
+
delete: (key) => base.delete(prefixed(key))
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
function createQueuedStateAdapter(base, options) {
|
|
855
|
+
const heartbeats = /* @__PURE__ */ new Map();
|
|
856
|
+
const shouldHeartbeatLock = (ttlMs) => ttlMs === ACTIVE_LOCK_TTL_MS;
|
|
857
|
+
const heartbeatKey = (lock) => `${lock.threadId}:${lock.token}`;
|
|
858
|
+
const stopHeartbeatByKey = (key) => {
|
|
859
|
+
const heartbeat = heartbeats.get(key);
|
|
860
|
+
if (!heartbeat) {
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
863
|
+
clearInterval(heartbeat.timer);
|
|
864
|
+
heartbeats.delete(key);
|
|
865
|
+
};
|
|
866
|
+
const stopHeartbeat = (lock) => {
|
|
867
|
+
stopHeartbeatByKey(heartbeatKey(lock));
|
|
868
|
+
};
|
|
869
|
+
const stopHeartbeatsForThread = (threadId) => {
|
|
870
|
+
for (const [key, heartbeat] of heartbeats) {
|
|
871
|
+
if (heartbeat.lock.threadId === threadId) {
|
|
872
|
+
stopHeartbeatByKey(key);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
const stopAllHeartbeats = () => {
|
|
877
|
+
for (const key of heartbeats.keys()) {
|
|
878
|
+
stopHeartbeatByKey(key);
|
|
879
|
+
}
|
|
880
|
+
};
|
|
881
|
+
const runHeartbeat = async (key) => {
|
|
882
|
+
const heartbeat = heartbeats.get(key);
|
|
883
|
+
if (!heartbeat || heartbeat.inFlight) {
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
heartbeat.inFlight = true;
|
|
887
|
+
try {
|
|
888
|
+
if (Date.now() - heartbeat.startedAtMs >= options.activeLockMaxAgeMs) {
|
|
889
|
+
stopHeartbeatByKey(key);
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
const extended = await base.extendLock(heartbeat.lock, heartbeat.ttlMs);
|
|
893
|
+
if (!extended) {
|
|
894
|
+
stopHeartbeatByKey(key);
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
heartbeat.lock.expiresAt = Date.now() + heartbeat.ttlMs;
|
|
898
|
+
} catch {
|
|
899
|
+
} finally {
|
|
900
|
+
const current = heartbeats.get(key);
|
|
901
|
+
if (current === heartbeat) {
|
|
902
|
+
current.inFlight = false;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
};
|
|
906
|
+
const startOrUpdateHeartbeat = (lock, ttlMs) => {
|
|
907
|
+
const key = heartbeatKey(lock);
|
|
908
|
+
const existing = heartbeats.get(key);
|
|
909
|
+
if (existing) {
|
|
910
|
+
existing.ttlMs = ttlMs;
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
const timer = setInterval(() => {
|
|
914
|
+
void runHeartbeat(key);
|
|
915
|
+
}, ACTIVE_LOCK_HEARTBEAT_MS);
|
|
916
|
+
timer.unref?.();
|
|
917
|
+
heartbeats.set(key, {
|
|
918
|
+
inFlight: false,
|
|
919
|
+
lock,
|
|
920
|
+
startedAtMs: Date.now(),
|
|
921
|
+
timer,
|
|
922
|
+
ttlMs
|
|
923
|
+
});
|
|
924
|
+
};
|
|
925
|
+
const acquireLock = async (threadId, ttlMs) => {
|
|
926
|
+
const lock = await base.acquireLock(threadId, ttlMs);
|
|
927
|
+
if (lock && shouldHeartbeatLock(ttlMs)) {
|
|
928
|
+
startOrUpdateHeartbeat(lock, ttlMs);
|
|
929
|
+
}
|
|
930
|
+
return lock;
|
|
931
|
+
};
|
|
932
|
+
return {
|
|
933
|
+
appendToList: (key, value, options2) => base.appendToList(key, value, options2),
|
|
934
|
+
connect: () => base.connect(),
|
|
935
|
+
disconnect: async () => {
|
|
936
|
+
stopAllHeartbeats();
|
|
937
|
+
await base.disconnect();
|
|
938
|
+
},
|
|
939
|
+
subscribe: (threadId) => base.subscribe(threadId),
|
|
940
|
+
unsubscribe: (threadId) => base.unsubscribe(threadId),
|
|
941
|
+
isSubscribed: (threadId) => base.isSubscribed(threadId),
|
|
942
|
+
acquireLock,
|
|
943
|
+
releaseLock: async (lock) => {
|
|
944
|
+
stopHeartbeat(lock);
|
|
945
|
+
await base.releaseLock(lock);
|
|
946
|
+
},
|
|
947
|
+
extendLock: async (lock, ttlMs) => {
|
|
948
|
+
const extended = await base.extendLock(lock, ttlMs);
|
|
949
|
+
if (extended) {
|
|
950
|
+
lock.expiresAt = Date.now() + ttlMs;
|
|
951
|
+
if (shouldHeartbeatLock(ttlMs)) {
|
|
952
|
+
startOrUpdateHeartbeat(lock, ttlMs);
|
|
953
|
+
} else {
|
|
954
|
+
stopHeartbeat(lock);
|
|
955
|
+
}
|
|
956
|
+
} else {
|
|
957
|
+
stopHeartbeat(lock);
|
|
958
|
+
}
|
|
959
|
+
return extended;
|
|
960
|
+
},
|
|
961
|
+
forceReleaseLock: async (threadId) => {
|
|
962
|
+
stopHeartbeatsForThread(threadId);
|
|
963
|
+
await base.forceReleaseLock(threadId);
|
|
964
|
+
},
|
|
965
|
+
enqueue: (threadId, entry, maxSize) => base.enqueue(threadId, entry, maxSize),
|
|
966
|
+
dequeue: (threadId) => base.dequeue(threadId),
|
|
967
|
+
queueDepth: (threadId) => base.queueDepth(threadId),
|
|
968
|
+
get: (key) => base.get(key),
|
|
969
|
+
getList: (key) => base.getList(key),
|
|
970
|
+
set: (key, value, ttlMs) => base.set(key, value, ttlMs),
|
|
971
|
+
setIfNotExists: (key, value, ttlMs) => base.setIfNotExists(key, value, ttlMs),
|
|
972
|
+
delete: (key) => base.delete(key)
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
function withOptionalPrefix(base, prefix) {
|
|
976
|
+
return prefix ? createPrefixedStateAdapter(base, prefix) : base;
|
|
977
|
+
}
|
|
978
|
+
function createStateAdapter() {
|
|
979
|
+
const config = getChatConfig();
|
|
980
|
+
const activeLockMaxAgeMs = config.bot.turnTimeoutMs + ACTIVE_LOCK_TTL_MS;
|
|
981
|
+
if (config.state.adapter === "memory") {
|
|
982
|
+
redisStateAdapter = void 0;
|
|
983
|
+
return createQueuedStateAdapter(
|
|
984
|
+
withOptionalPrefix(createMemoryState(), config.state.keyPrefix),
|
|
985
|
+
{ activeLockMaxAgeMs }
|
|
986
|
+
);
|
|
987
|
+
}
|
|
988
|
+
if (!config.state.redisUrl) {
|
|
989
|
+
throw new Error("REDIS_URL is required for durable Slack thread state");
|
|
990
|
+
}
|
|
991
|
+
const redisState = createRedisState({
|
|
992
|
+
url: config.state.redisUrl
|
|
993
|
+
});
|
|
994
|
+
redisStateAdapter = redisState;
|
|
995
|
+
return createQueuedStateAdapter(
|
|
996
|
+
withOptionalPrefix(redisState, config.state.keyPrefix),
|
|
997
|
+
{ activeLockMaxAgeMs }
|
|
998
|
+
);
|
|
999
|
+
}
|
|
1000
|
+
function getOptionalRedisStateAdapter() {
|
|
1001
|
+
getStateAdapter();
|
|
1002
|
+
return redisStateAdapter;
|
|
1003
|
+
}
|
|
1004
|
+
async function getConnectedStateContext() {
|
|
1005
|
+
const adapter = getStateAdapter();
|
|
1006
|
+
await adapter.connect();
|
|
1007
|
+
return {
|
|
1008
|
+
redisStateAdapter: getOptionalRedisStateAdapter(),
|
|
1009
|
+
stateAdapter: adapter
|
|
1010
|
+
};
|
|
1011
|
+
}
|
|
1012
|
+
async function getDefaultRedisStateAdapterFor(adapter) {
|
|
1013
|
+
if (adapter !== stateAdapter) {
|
|
1014
|
+
return void 0;
|
|
1015
|
+
}
|
|
1016
|
+
const context = await getConnectedStateContext();
|
|
1017
|
+
return context.stateAdapter === adapter ? context.redisStateAdapter : void 0;
|
|
1018
|
+
}
|
|
1019
|
+
function getStateAdapter() {
|
|
1020
|
+
if (!stateAdapter) {
|
|
1021
|
+
stateAdapter = createStateAdapter();
|
|
1022
|
+
}
|
|
1023
|
+
return stateAdapter;
|
|
1024
|
+
}
|
|
1025
|
+
async function disconnectStateAdapter() {
|
|
1026
|
+
if (!stateAdapter) {
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
try {
|
|
1030
|
+
await stateAdapter.disconnect();
|
|
1031
|
+
} finally {
|
|
1032
|
+
stateAdapter = void 0;
|
|
1033
|
+
redisStateAdapter = void 0;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
798
1037
|
export {
|
|
799
1038
|
toOptionalTrimmed,
|
|
800
1039
|
escapeXml,
|
|
1040
|
+
unescapeXml,
|
|
801
1041
|
renderCurrentInstruction,
|
|
802
1042
|
unwrapCurrentInstruction,
|
|
803
1043
|
TURN_CONTEXT_TAG,
|
|
@@ -834,5 +1074,10 @@ export {
|
|
|
834
1074
|
getSlackClientSecret,
|
|
835
1075
|
getRuntimeMetadata,
|
|
836
1076
|
getSlackReactionConfig,
|
|
837
|
-
setSlackReactionConfig
|
|
1077
|
+
setSlackReactionConfig,
|
|
1078
|
+
acquireActiveLock,
|
|
1079
|
+
getConnectedStateContext,
|
|
1080
|
+
getDefaultRedisStateAdapterFor,
|
|
1081
|
+
getStateAdapter,
|
|
1082
|
+
disconnectStateAdapter
|
|
838
1083
|
};
|