@sentry/junior 0.225.0 → 0.227.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-CRuRcOg9.js → agent-hooks-bEwEJhlg.js} +231 -17
- package/dist/{agent-runner-Cad1RtWn.js → agent-runner-BGDSjciH.js} +2899 -159
- package/dist/api/schema.d.ts +417 -15
- package/dist/api/schema.js +4 -4
- package/dist/api.js +57 -32
- package/dist/{app-BbSD6EtD.d.ts → app-CjRIKZb5.d.ts} +1 -1
- package/dist/app.d.ts +1 -1
- package/dist/app.js +971 -7685
- package/dist/{briefs-BtnkPWT5.js → briefs-BkM_ZW4B.js} +4 -4
- package/dist/{catalog-runtime-pv4grNNb.js → catalog-runtime-Cw9V2jpn.js} +1 -1
- package/dist/{checkpoint-6fkAdB3g.js → checkpoint-oZYD3-Ar.js} +77 -11
- package/dist/cli/chat.js +13 -13
- package/dist/cli/check.js +3 -3
- package/dist/cli/main.js +1 -1
- package/dist/cli/plugins.js +3 -3
- package/dist/cli/snapshot-create.js +3 -3
- package/dist/cli/upgrade.js +3 -3
- package/dist/{client-ihmkx60d.js → client-Pcxo3lGn.js} +2 -2
- package/dist/{config-DMg679BW.js → config-CYvEow1F.js} +2 -2
- package/dist/{context-Bplcgypl.js → context-0Et9iVSB.js} +1 -1
- package/dist/{conversation-Bygi39Xj.js → conversation-BnhOMfEB.js} +113 -25
- package/dist/{conversation-privacy-ZYy05Y3q.js → conversation-privacy-hQmyZbOC.js} +1 -1
- package/dist/{credential-sync-DCB2SwnQ.js → credential-sync-CUGbiiCM.js} +15 -135
- package/dist/{executor-B9R4cHte.js → executor-BXMlFrV6.js} +1 -1
- package/dist/history-nukv1YN8.d.ts +127 -0
- package/dist/images-8siTAUNW.js +82 -0
- package/dist/instrumentation.js +2 -2
- package/dist/{vercel-queue-DIkVcfK4.js → job-queue-AI0_QAgc.js} +61 -2
- package/dist/{logging-CcTvYQ8A.js → logging-BPBx6WF-.js} +1 -1
- package/dist/nitro.d.ts +1 -1
- package/dist/nitro.js +3 -4
- package/dist/{oauth-authorization-BS4vPJmu.js → oauth-authorization-Cq1GaLIP.js} +1 -1
- package/dist/{oauth-callback-server-DnlQsGBJ.js → oauth-callback-server-CnF03VYh.js} +2 -2
- package/dist/pending-auth-CHUjr_6d.js +59 -0
- package/dist/{profile-CV97YuiL.js → profile-upzC-wN1.js} +4 -4
- package/dist/{prompt-CL8zxsmm.js → prompt-CZIQcPHy.js} +1 -1
- package/dist/{registry-C8I4IejN.js → registry-DM5aMhjm.js} +2 -2
- package/dist/{resolve-DXVAzYa3.js → resolve-sF6Lg7Ay.js} +2 -2
- package/dist/{runner-Die1RJ_z.js → runner-Bu2wYpK8.js} +10 -10
- package/dist/{sandbox-egress-signals-BZepyVh1.js → sandbox-egress-signals-Dgerhizb.js} +1 -1
- package/dist/{schema-BE4uso4i.js → schema-BSiwcvjm.js} +2 -2
- package/dist/{skills-DUcDEgDI.js → skills-CAI5s___.js} +2 -2
- package/dist/{spawn-o15i3tJu.js → spawn-DRK9TBgY.js} +2 -2
- package/dist/{task-queue-D3PLY59C.js → task-queue-iuDAqfZg.js} +3 -4
- package/dist/{task-runner-BMl2aM2v.js → task-runner-S3QtH38c.js} +381 -12
- package/dist/{thread-state-CAR6gdAm.js → thread-state-C_arVuaN.js} +5 -5
- package/dist/{turn-failure-response-CZyoUMkD.js → turn-failure-response-DarwGYgC.js} +9 -10
- package/dist/{turn-lifecycle-DPDHKi2U.js → turn-lifecycle-CdiIejXH.js} +1 -1
- package/dist/{turn-session-routing-Jkmmxpp-.js → turn-session-routing-DyLGd_wU.js} +1 -1
- package/dist/{validation-BcGGxOa6.js → validation-BMig74Zp.js} +1 -1
- package/dist/{version-DYcuOFQb.js → version-lhQSfLjx.js} +1 -1
- package/dist/version.js +1 -1
- package/dist/web-authorization-r2lKYKJ2.js +162 -0
- package/dist/web-input-BU-Fu7iq.js +7784 -0
- package/dist/{reporting-window-DbUqng0P.js → web-message-id-xPI_EFSC.js} +11 -1
- package/dist/{work-Bm90pR9P.js → work-B9koS8sW.js} +7 -8
- package/dist/{worker-BvHr6JhE.js → worker-C_iJSRgG.js} +5 -6
- package/package.json +5 -4
- package/dist/execution-stats-CR9CYpyj.js +0 -373
- package/dist/history-yaSjGMD_.d.ts +0 -65
- package/dist/job-queue-D2SiTrnt.js +0 -63
- package/dist/short-title-3wYH3ipl.js +0 -71
- package/dist/stats-DawHjcTw.js +0 -2758
- package/dist/web-authorization-B09B8A8R.js +0 -38
- package/dist/web-input-CGE58TpK.js +0 -899
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
|
|
2
|
-
import { a as embedTexts, r as completeObject } from "./client-
|
|
3
|
-
import { F as normalizeIdentityEmail, I as isRecord$2, d as logException, f as logInfo, p as logWarn, v as setSpanAttributes, w as withSpan, y as setSpanStatus } from "./logging-
|
|
2
|
+
import { a as embedTexts, r as completeObject } from "./client-Pcxo3lGn.js";
|
|
3
|
+
import { F as normalizeIdentityEmail, I as isRecord$2, d as logException, f as logInfo, p as logWarn, v as setSpanAttributes, w as withSpan, y as setSpanStatus } from "./logging-BPBx6WF-.js";
|
|
4
4
|
import { a as getClient$1 } from "./sentry-CgWZM_kV.js";
|
|
5
|
-
import { t as canExposeConversationPayload } from "./conversation-privacy-
|
|
6
|
-
import { a as getChatConfig, n as botConfig, s as getSlackBotToken } from "./config-
|
|
5
|
+
import { t as canExposeConversationPayload } from "./conversation-privacy-hQmyZbOC.js";
|
|
6
|
+
import { a as getChatConfig, n as botConfig, s as getSlackBotToken } from "./config-CYvEow1F.js";
|
|
7
7
|
import { r as defaultModelId } from "./model-profile-BwU8mqwD.js";
|
|
8
|
-
import {
|
|
8
|
+
import { b as parseSlackMessageTs, c as isActorUserId, h as parseSlackTeamId, m as parseSlackChannelReferenceId, u as parseActorUserId } from "./context-0Et9iVSB.js";
|
|
9
9
|
import { n as juniorDestinations } from "./destinations-BeBiJeEM.js";
|
|
10
|
-
import { C as juniorCodeRepositories, D as juniorIdentities, E as juniorConversations, O as juniorUsers, S as juniorCodeChanges, T as conversationReadColumns, _ as CONVERSATION_METRICS, g as juniorConversationBriefs, h as juniorConversationBindings, i as juniorWorkspaces, m as juniorConversationParticipants, n as juniorSnapshots, r as juniorWorkspaceRepos, t as createJuniorSqlExecutor, v as juniorConversationMetrics, x as juniorConversationAnnotations, y as juniorConversationEvents } from "./executor-
|
|
11
|
-
import { C as conversationReportEventSchema,
|
|
12
|
-
import { N as SANDBOX_WORKSPACE_ROOT, k as sleep$1, l as isSandboxMissingError, n as hash, v as getVercelSandboxCredentials, w as getStateAdapter, x as runNonInteractiveCommand } from "./profile-
|
|
13
|
-
import { n as briefEntriesFromReportEvents, s as generateBrief, t as BRIEF_PROMPT } from "./prompt-
|
|
10
|
+
import { C as juniorCodeRepositories, D as juniorIdentities, E as juniorConversations, O as juniorUsers, S as juniorCodeChanges, T as conversationReadColumns, _ as CONVERSATION_METRICS, g as juniorConversationBriefs, h as juniorConversationBindings, i as juniorWorkspaces, m as juniorConversationParticipants, n as juniorSnapshots, r as juniorWorkspaceRepos, t as createJuniorSqlExecutor, v as juniorConversationMetrics, w as juniorAttachments, x as juniorConversationAnnotations, y as juniorConversationEvents } from "./executor-BXMlFrV6.js";
|
|
11
|
+
import { C as conversationReportEventSchema, H as conversationBriefSchema, I as readMessageAttachments, K as conversationEventDataSchema, N as readMessageCards, Q as encodeHistoryPayload, U as parseBriefInput, X as historyReplacementSchema, Y as decodeStoredConversationEvent, Z as newConversationEventSchema, rt as usageSchema } from "./conversation-BnhOMfEB.js";
|
|
12
|
+
import { C as getDefaultRedisStateAdapterFor, N as SANDBOX_WORKSPACE_ROOT, k as sleep$1, l as isSandboxMissingError, n as hash, v as getVercelSandboxCredentials, w as getStateAdapter, x as runNonInteractiveCommand } from "./profile-upzC-wN1.js";
|
|
13
|
+
import { n as briefEntriesFromReportEvents, s as generateBrief, t as BRIEF_PROMPT } from "./prompt-CZIQcPHy.js";
|
|
14
14
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
15
15
|
import { z } from "zod";
|
|
16
16
|
import { createHash, createHmac, randomUUID, timingSafeEqual } from "node:crypto";
|
|
@@ -1189,15 +1189,16 @@ function eventUnarchivesConversation(data) {
|
|
|
1189
1189
|
/** Split validated event data into column-lifted and JSON payload fields. */
|
|
1190
1190
|
function insertFromEvent(conversationId, seq, historyVersion, event, actorIdentityId) {
|
|
1191
1191
|
const stripped = stripPayloadAuthorIdentityId(event.data);
|
|
1192
|
-
const
|
|
1192
|
+
const data = conversationEventDataSchema.parse(stripped);
|
|
1193
|
+
const encoded = encodeHistoryPayload(data);
|
|
1193
1194
|
return {
|
|
1194
1195
|
conversationId,
|
|
1195
1196
|
seq,
|
|
1196
1197
|
historyVersion,
|
|
1197
|
-
schemaVersion:
|
|
1198
|
+
schemaVersion: encoded.schemaVersion,
|
|
1198
1199
|
idempotencyKey: event.idempotencyKey ?? null,
|
|
1199
|
-
type,
|
|
1200
|
-
payload: sanitizePostgresJson(payload),
|
|
1200
|
+
type: data.type,
|
|
1201
|
+
payload: sanitizePostgresJson(encoded.payload),
|
|
1201
1202
|
actorIdentityId: actorIdentityId ?? null,
|
|
1202
1203
|
createdAt: new Date(event.createdAtMs)
|
|
1203
1204
|
};
|
|
@@ -1733,8 +1734,9 @@ async function annotateToolResult(conversationId, plugin, result) {
|
|
|
1733
1734
|
const details = isRecord$2(result.details) ? result.details : result;
|
|
1734
1735
|
if (details.timed_out === true || details.isError === true || !Array.isArray(details.objectAnnotations)) return result;
|
|
1735
1736
|
const cards = await saveObjectAnnotations(conversationId, plugin, details.objectAnnotations);
|
|
1737
|
+
const { objectAnnotations: _annotations, ...rest } = details;
|
|
1736
1738
|
const annotated = {
|
|
1737
|
-
...
|
|
1739
|
+
...rest,
|
|
1738
1740
|
objectCards: cards
|
|
1739
1741
|
};
|
|
1740
1742
|
if (isRecord$2(result.details)) return {
|
|
@@ -1806,6 +1808,63 @@ const briefUpdatedEvent = defineConversationEvent({
|
|
|
1806
1808
|
}
|
|
1807
1809
|
});
|
|
1808
1810
|
//#endregion
|
|
1811
|
+
//#region src/chat/slack/attachments.ts
|
|
1812
|
+
/** Save the vision summary for a stored Slack attachment. */
|
|
1813
|
+
async function recordSlackAttachment(args) {
|
|
1814
|
+
await args.db.db().update(juniorAttachments).set({ visionSummary: args.visionSummary }).where(and(eq(juniorAttachments.id, args.attachmentId), eq(juniorAttachments.conversationId, args.conversationId), isNull(juniorAttachments.deleteRequestedAt)));
|
|
1815
|
+
}
|
|
1816
|
+
/** Read a saved vision summary for one live attachment. */
|
|
1817
|
+
async function readAttachmentVisionSummary(args) {
|
|
1818
|
+
const [row] = await args.db.db().select({ visionSummary: juniorAttachments.visionSummary }).from(juniorAttachments).where(and(eq(juniorAttachments.id, args.attachmentId), eq(juniorAttachments.conversationId, args.conversationId), isNull(juniorAttachments.deleteRequestedAt)));
|
|
1819
|
+
return row?.visionSummary;
|
|
1820
|
+
}
|
|
1821
|
+
/** Match live conversation attachments to Slack file ids. */
|
|
1822
|
+
async function matchSlackAttachments(args) {
|
|
1823
|
+
if (args.providerIds.length === 0) return [];
|
|
1824
|
+
return await args.db.db().select({
|
|
1825
|
+
id: juniorAttachments.id,
|
|
1826
|
+
providerId: juniorAttachments.providerId,
|
|
1827
|
+
bytes: juniorAttachments.bytes,
|
|
1828
|
+
contentType: juniorAttachments.contentType,
|
|
1829
|
+
filename: juniorAttachments.filename
|
|
1830
|
+
}).from(juniorAttachments).where(and(eq(juniorAttachments.conversationId, args.conversationId), eq(juniorAttachments.provider, "slack"), inArray(juniorAttachments.providerId, args.providerIds), isNull(juniorAttachments.deleteRequestedAt)));
|
|
1831
|
+
}
|
|
1832
|
+
/** Read the Slack file identity retained by the Chat SDK. */
|
|
1833
|
+
function getSlackFileId(attachment) {
|
|
1834
|
+
const metadataId = attachment.fetchMetadata?.fileId;
|
|
1835
|
+
if (metadataId) return metadataId;
|
|
1836
|
+
return (attachment.url ?? attachment.fetchMetadata?.url ?? "").match(/(?:^|[-/])(F[A-Z0-9]+)(?:[-/]|$)/i)?.[1];
|
|
1837
|
+
}
|
|
1838
|
+
//#endregion
|
|
1839
|
+
//#region src/api/conversations/message-attachments.ts
|
|
1840
|
+
/** Resolve saved Slack file references without exposing private storage details. */
|
|
1841
|
+
async function hydrateMessageAttachments(db, conversationId, events) {
|
|
1842
|
+
const messages = events.flatMap((event) => event.data.type === "message" ? [event.data] : []);
|
|
1843
|
+
const ids = [...new Set(messages.flatMap((message) => slackFileIds(message.meta)))];
|
|
1844
|
+
if (!ids.length) return;
|
|
1845
|
+
const attachments = await matchSlackAttachments({
|
|
1846
|
+
db,
|
|
1847
|
+
conversationId,
|
|
1848
|
+
providerIds: ids
|
|
1849
|
+
});
|
|
1850
|
+
const byFileId = new Map(attachments.map(({ providerId, ...attachment }) => [providerId, attachment]));
|
|
1851
|
+
for (const message of messages) {
|
|
1852
|
+
const stored = readMessageAttachments(message.meta?.attachments);
|
|
1853
|
+
const matched = slackFileIds(message.meta).flatMap((id) => {
|
|
1854
|
+
const attachment = byFileId.get(id);
|
|
1855
|
+
return attachment ? [attachment] : [];
|
|
1856
|
+
});
|
|
1857
|
+
if (matched.length) message.meta = {
|
|
1858
|
+
...message.meta,
|
|
1859
|
+
attachments: [...stored, ...matched]
|
|
1860
|
+
};
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
function slackFileIds(meta) {
|
|
1864
|
+
const ids = meta?.slackFileIds ?? meta?.imageFileIds;
|
|
1865
|
+
return Array.isArray(ids) ? ids.filter((id) => typeof id === "string") : [];
|
|
1866
|
+
}
|
|
1867
|
+
//#endregion
|
|
1809
1868
|
//#region src/chat/sentry-links.ts
|
|
1810
1869
|
function getSentryOrgSlug() {
|
|
1811
1870
|
return process.env.SENTRY_ORG_SLUG?.trim() || void 0;
|
|
@@ -2056,7 +2115,10 @@ function reportEventData(args) {
|
|
|
2056
2115
|
...typeof data.meta?.explicitMention === "boolean" ? { explicitMention: data.meta.explicitMention } : void 0,
|
|
2057
2116
|
...args.canExposePayload && typeof data.meta?.trustedSummary === "string" ? { trustedSummary: data.meta.trustedSummary } : void 0,
|
|
2058
2117
|
...args.canExposePayload && (data.meta?.cards || data.meta?.objectCards) ? { cards: readMessageCards(data.meta) } : void 0,
|
|
2059
|
-
...args.canExposePayload ? {
|
|
2118
|
+
...args.canExposePayload ? {
|
|
2119
|
+
text: data.text,
|
|
2120
|
+
...data.meta?.attachments ? { attachments: readMessageAttachments(data.meta.attachments) } : void 0
|
|
2121
|
+
} : { redacted: true }
|
|
2060
2122
|
};
|
|
2061
2123
|
}
|
|
2062
2124
|
case "message_handled": return {
|
|
@@ -2286,6 +2348,7 @@ async function projectConversationEventRows(executor, args) {
|
|
|
2286
2348
|
toolCallIds: toolResultIds,
|
|
2287
2349
|
types: ["tool_execution_started"]
|
|
2288
2350
|
});
|
|
2351
|
+
if (args.canExposePayload) await hydrateMessageAttachments(executor, args.conversationId, events);
|
|
2289
2352
|
return projectConversationReportEventPage({
|
|
2290
2353
|
canExposePayload: args.canExposePayload,
|
|
2291
2354
|
events,
|
|
@@ -3077,6 +3140,78 @@ function getDashboardTaskLink(taskId) {
|
|
|
3077
3140
|
/** Retain expiring conversation/runtime state long enough for resume and dashboard history. */
|
|
3078
3141
|
const JUNIOR_THREAD_STATE_TTL_MS = 6048e5;
|
|
3079
3142
|
//#endregion
|
|
3143
|
+
//#region src/chat/events/timer-index.ts
|
|
3144
|
+
const DUE_KEY = "junior:watches:due";
|
|
3145
|
+
const CLAIM_MS = 12e4;
|
|
3146
|
+
const BATCH_SIZE = 25;
|
|
3147
|
+
const entriesSchema = z.array(z.object({
|
|
3148
|
+
id: z.string(),
|
|
3149
|
+
atMs: z.number()
|
|
3150
|
+
}));
|
|
3151
|
+
/** Keep timer index operations atomic in Redis and the local memory adapter. */
|
|
3152
|
+
async function updateTimerIndex(state, operation) {
|
|
3153
|
+
const redis = await getDefaultRedisStateAdapterFor(state);
|
|
3154
|
+
if (redis) {
|
|
3155
|
+
const prefix = getChatConfig().state.keyPrefix;
|
|
3156
|
+
const key = prefix ? `${prefix}:${DUE_KEY}` : DUE_KEY;
|
|
3157
|
+
const client = redis.getClient();
|
|
3158
|
+
if (operation.kind === "add") {
|
|
3159
|
+
await client.sendCommand([
|
|
3160
|
+
"ZADD",
|
|
3161
|
+
key,
|
|
3162
|
+
String(operation.atMs),
|
|
3163
|
+
operation.id
|
|
3164
|
+
]);
|
|
3165
|
+
return [];
|
|
3166
|
+
}
|
|
3167
|
+
if (operation.kind === "remove") {
|
|
3168
|
+
await client.sendCommand([
|
|
3169
|
+
"ZREM",
|
|
3170
|
+
key,
|
|
3171
|
+
operation.id
|
|
3172
|
+
]);
|
|
3173
|
+
return [];
|
|
3174
|
+
}
|
|
3175
|
+
return await client.sendCommand([
|
|
3176
|
+
"EVAL",
|
|
3177
|
+
`local ids = redis.call('ZRANGEBYSCORE', KEYS[1], '-inf', ARGV[1], 'LIMIT', 0, ARGV[3])
|
|
3178
|
+
for _, id in ipairs(ids) do
|
|
3179
|
+
redis.call('ZADD', KEYS[1], ARGV[2], id)
|
|
3180
|
+
end
|
|
3181
|
+
return ids`,
|
|
3182
|
+
"1",
|
|
3183
|
+
key,
|
|
3184
|
+
String(operation.nowMs),
|
|
3185
|
+
String(operation.nowMs + CLAIM_MS),
|
|
3186
|
+
String(BATCH_SIZE)
|
|
3187
|
+
]);
|
|
3188
|
+
}
|
|
3189
|
+
const lock = await state.acquireLock(`${DUE_KEY}:lock`, 1e4);
|
|
3190
|
+
if (!lock) throw new Error("Could not acquire timer index lock");
|
|
3191
|
+
try {
|
|
3192
|
+
let entries = entriesSchema.parse(await state.get(DUE_KEY) ?? []);
|
|
3193
|
+
let ids = [];
|
|
3194
|
+
if (operation.kind === "claim") {
|
|
3195
|
+
ids = entries.filter((entry) => entry.atMs <= operation.nowMs).sort((a, b) => a.atMs - b.atMs).slice(0, BATCH_SIZE).map((entry) => entry.id);
|
|
3196
|
+
const claimed = new Set(ids);
|
|
3197
|
+
entries = entries.map((entry) => claimed.has(entry.id) ? {
|
|
3198
|
+
...entry,
|
|
3199
|
+
atMs: operation.nowMs + CLAIM_MS
|
|
3200
|
+
} : entry);
|
|
3201
|
+
} else {
|
|
3202
|
+
entries = entries.filter((entry) => entry.id !== operation.id);
|
|
3203
|
+
if (operation.kind === "add") entries.push({
|
|
3204
|
+
id: operation.id,
|
|
3205
|
+
atMs: operation.atMs
|
|
3206
|
+
});
|
|
3207
|
+
}
|
|
3208
|
+
await state.set(DUE_KEY, entries);
|
|
3209
|
+
return ids;
|
|
3210
|
+
} finally {
|
|
3211
|
+
await state.releaseLock(lock);
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
3214
|
+
//#endregion
|
|
3080
3215
|
//#region src/chat/events/store.ts
|
|
3081
3216
|
const EVENT_PREFIX = "junior:resource_event_subscription:v5";
|
|
3082
3217
|
const INDEX_LOCK_TTL_MS = 1e4;
|
|
@@ -3095,6 +3230,7 @@ const subscriptionSchema = z.object({
|
|
|
3095
3230
|
createdAtMs: z.number().finite(),
|
|
3096
3231
|
events: z.array(eventTypeSchema).min(1),
|
|
3097
3232
|
expiresAtMs: z.number().finite(),
|
|
3233
|
+
firesAtMs: z.number().finite().optional(),
|
|
3098
3234
|
id: z.string().min(1),
|
|
3099
3235
|
intent: z.string().min(1),
|
|
3100
3236
|
label: z.string().min(1),
|
|
@@ -3252,6 +3388,70 @@ async function createWatch(input, options = {}) {
|
|
|
3252
3388
|
await addToIndex(state, conversationIndexKey(input.conversationId), id, nowMs);
|
|
3253
3389
|
return parsed;
|
|
3254
3390
|
}
|
|
3391
|
+
/** Create a retry-stable timer without keeping a process open. */
|
|
3392
|
+
async function createTimerWatch(input) {
|
|
3393
|
+
const state = getStateAdapter();
|
|
3394
|
+
await state.connect();
|
|
3395
|
+
const identifier = digest(`${input.conversationId}\0${input.toolCallId}`);
|
|
3396
|
+
const selector = {
|
|
3397
|
+
conversationId: input.conversationId,
|
|
3398
|
+
namespace: "junior",
|
|
3399
|
+
identifier,
|
|
3400
|
+
events: ["timer.fired"]
|
|
3401
|
+
};
|
|
3402
|
+
const id = buildSubscriptionId(selector);
|
|
3403
|
+
return await withSubscriptionLock(state, id, async () => {
|
|
3404
|
+
const existing = parseSubscription(await state.get(subscriptionKey(id)));
|
|
3405
|
+
if (existing) return existing;
|
|
3406
|
+
const nowMs = Date.now();
|
|
3407
|
+
const firesAtMs = nowMs + input.afterMs;
|
|
3408
|
+
const expiresAtMs = firesAtMs + 864e5;
|
|
3409
|
+
const record = subscriptionSchema.parse({
|
|
3410
|
+
...selector,
|
|
3411
|
+
id,
|
|
3412
|
+
firesAtMs,
|
|
3413
|
+
expiresAtMs,
|
|
3414
|
+
resourceType: "timer",
|
|
3415
|
+
label: "Timer",
|
|
3416
|
+
intent: input.intent,
|
|
3417
|
+
status: "active",
|
|
3418
|
+
createdAtMs: nowMs,
|
|
3419
|
+
updatedAtMs: nowMs
|
|
3420
|
+
});
|
|
3421
|
+
await withIndexLock(state, conversationIndexKey(input.conversationId), async () => {
|
|
3422
|
+
const key = conversationIndexKey(input.conversationId);
|
|
3423
|
+
const ids = [.../* @__PURE__ */ new Set([...await readSubscriptionIdIndex(state, key), id])];
|
|
3424
|
+
await state.set(key, ids, Math.max(ttlUntil(expiresAtMs, nowMs), await indexTtlMs(state, ids, nowMs)));
|
|
3425
|
+
await state.set(resourceIndexKey("junior", identifier), [id], ttlUntil(expiresAtMs, nowMs));
|
|
3426
|
+
await updateTimerIndex(state, {
|
|
3427
|
+
kind: "add",
|
|
3428
|
+
id,
|
|
3429
|
+
atMs: firesAtMs
|
|
3430
|
+
});
|
|
3431
|
+
await state.set(subscriptionKey(id), record, ttlUntil(expiresAtMs, nowMs));
|
|
3432
|
+
});
|
|
3433
|
+
return record;
|
|
3434
|
+
});
|
|
3435
|
+
}
|
|
3436
|
+
/** Claim live timer Watches and discard stale due-index entries. */
|
|
3437
|
+
async function takeDueTimerWatches(nowMs) {
|
|
3438
|
+
const state = getStateAdapter();
|
|
3439
|
+
await state.connect();
|
|
3440
|
+
const watches = [];
|
|
3441
|
+
for (const id of await updateTimerIndex(state, {
|
|
3442
|
+
kind: "claim",
|
|
3443
|
+
nowMs
|
|
3444
|
+
})) await withSubscriptionLock(state, id, async () => {
|
|
3445
|
+
const watch = parseSubscription(await state.get(subscriptionKey(id)));
|
|
3446
|
+
if (watch && activeAt(watch, nowMs) && watch.firesAtMs !== void 0) {
|
|
3447
|
+
if (watch.firesAtMs <= nowMs) watches.push(watch);
|
|
3448
|
+
} else await updateTimerIndex(state, {
|
|
3449
|
+
kind: "remove",
|
|
3450
|
+
id
|
|
3451
|
+
});
|
|
3452
|
+
});
|
|
3453
|
+
return watches;
|
|
3454
|
+
}
|
|
3255
3455
|
/** List active subscriptions bound to one conversation. */
|
|
3256
3456
|
async function listWatches(input) {
|
|
3257
3457
|
const state = input.state ?? getStateAdapter();
|
|
@@ -3268,6 +3468,7 @@ async function cancelWatch(input) {
|
|
|
3268
3468
|
const current = parseSubscription(await state.get(subscriptionKey(input.id)));
|
|
3269
3469
|
if (!current || current.conversationId !== input.conversationId) return;
|
|
3270
3470
|
const nowMs = input.nowMs ?? Date.now();
|
|
3471
|
+
if (current.status === "completed") return current;
|
|
3271
3472
|
const next = {
|
|
3272
3473
|
...current,
|
|
3273
3474
|
status: "cancelled",
|
|
@@ -3276,6 +3477,10 @@ async function cancelWatch(input) {
|
|
|
3276
3477
|
await state.set(subscriptionKey(input.id), next, JUNIOR_THREAD_STATE_TTL_MS);
|
|
3277
3478
|
await removeFromIndex(state, resourceIndexKey(current.namespace, current.identifier), input.id, nowMs);
|
|
3278
3479
|
await removeFromIndex(state, conversationIndexKey(current.conversationId), input.id, nowMs);
|
|
3480
|
+
if (current.firesAtMs !== void 0) await updateTimerIndex(state, {
|
|
3481
|
+
kind: "remove",
|
|
3482
|
+
id: input.id
|
|
3483
|
+
});
|
|
3279
3484
|
return next;
|
|
3280
3485
|
});
|
|
3281
3486
|
}
|
|
@@ -3356,6 +3561,10 @@ async function deliverWatch(input) {
|
|
|
3356
3561
|
await removeFromIndex(state, resourceIndexKey(current.namespace, current.identifier), current.id, nowMs);
|
|
3357
3562
|
await removeFromIndex(state, conversationIndexKey(current.conversationId), current.id, nowMs);
|
|
3358
3563
|
}
|
|
3564
|
+
if (input.terminal && current.firesAtMs !== void 0) await updateTimerIndex(state, {
|
|
3565
|
+
kind: "remove",
|
|
3566
|
+
id: current.id
|
|
3567
|
+
});
|
|
3359
3568
|
return delivered;
|
|
3360
3569
|
}, input.waitDeadlineMs);
|
|
3361
3570
|
}
|
|
@@ -3769,7 +3978,12 @@ async function withSlackRetries(task, maxAttempts = 3, context = {}) {
|
|
|
3769
3978
|
* is workspace-scoped and no installation token can be resolved, so a write
|
|
3770
3979
|
* never goes out with another workspace's credentials.
|
|
3771
3980
|
*/
|
|
3772
|
-
function getSlackClient() {
|
|
3981
|
+
function getSlackClient(options) {
|
|
3982
|
+
if (options) return new WebClient(resolveSlackToken(), {
|
|
3983
|
+
retryConfig: { retries: 0 },
|
|
3984
|
+
rejectRateLimitedCalls: true,
|
|
3985
|
+
timeout: options.timeoutMs
|
|
3986
|
+
});
|
|
3773
3987
|
return getClient();
|
|
3774
3988
|
}
|
|
3775
3989
|
/**
|
|
@@ -5437,4 +5651,4 @@ function createPluginHookRunner(input = {}) {
|
|
|
5437
5651
|
};
|
|
5438
5652
|
}
|
|
5439
5653
|
//#endregion
|
|
5440
|
-
export { resolveViewerUser as $,
|
|
5654
|
+
export { resolveViewerUser as $, getDb as $t, tryWorkspaceRepoCheckoutPath as A, conversationNotArchivedForUser as At, downloadPrivateSlackFile as B, resolveRootVisibility as Bt, invalidateReadySnapshot as C, readConversationAccessFromSql as Ct, SANDBOX_RUNTIME as D, conversationHasParticipantEmail as Dt, setWorkspaceSnapshotBuild as E, conversationArchivedForUser as Et, bindSlackDirectCredentialSubject as F, buildSentryConversationUrl as Ft, isDmChannel as G, JUNIOR_NATIVE_EVENT_NAMESPACE as Gt, getHeaderString as H, createPluginAnnotations as Ht, verifyEventAutomationCredentialSubject as I, getSlackFileId as It, withSlackRetries as J, authenticationUnlinkedEvent as Jt, normalizeSlackConversationId as K, agentsInstructionsUpdatedEvent as Kt, verifyScheduledAutomationCredentialSubject as L, matchSlackAttachments as Lt, resolveChannelCapabilities as M, createPluginConversationEvents as Mt, bindEventAutomationCredentialSubject as N, readLatestConversationBrief as Nt, deleteWorkspaceSnapshotBuilders as O, conversationHasParticipantUser as Ot, bindScheduledAutomationCredentialSubject as P, readConversationEventPage as Pt, readActorIdentity as Q, getConversationStore as Qt, verifySlackDirectCredentialSubject as R, readAttachmentVisionSummary as Rt, WorkspaceValidationError as S, createPluginLogger as St, setWorkspaceSnapshot as T, conversationArchivedForEmail as Tt, getSlackClient as U, listConversationAnnotations as Ut, getFilePermalink as V, saveObjectAnnotations as Vt, isConversationScopedChannel as W, listConversationAnnotationsById as Wt, runWithWorkspaceTeamId as X, getConversationEventStore as Xt, getWorkspaceTeamId as Y, db_exports as Yt, findUserByEmail as Z, getConversationMessageSearchStore as Zt, deleteWorkspace as _, parseDestination as _n, getDashboardTaskLink as _t, getPluginRoutes as a, bindProviderConversation as an, STOP_WATCHING_TOOL_NAME as at, listWorkspaces as b, createPluginEmbedder as bt, getPluginTools as c, agentTurnCostUsd as cn, collectEventMatchKeys as ct, setPlugins as d, hasAgentTurnUsage as dn, deliverWatch as dt, getSqlExecutor as en, updateViewerDisplayName as et, validatePlugins as f, resolveRootConversationId as fn, findMatchingWatches as ft, createWorkspace as g, createSlackDestination as gn, getDashboardConversationLink as gt, setBriefsConfig as h, upsertLinkedIdentity as hn, JUNIOR_THREAD_STATE_TTL_MS as ht, getPluginApiRoutes as i, locationFromRow as in, RESOURCE_WATCH_TOOL_SOURCE as it, workspaceRepoCheckoutPath as j, viewerConversationMembership as jt, getWorkspaceSnapshotBuilder as k, conversationNotArchivedForEmail as kt, getPluginUserPromptContributions as l, agentTurnTotalTokens as ln, createTimerWatch as lt, registration_exports as m, upsertIdentity as mn, takeDueTimerWatches as mt, applyPluginFormatMarkdown as n, withConversationEventLock as nn, RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS as nt, getPluginSlackConversationLink as o, parseSessionSource as on, cancelSubscriptions as ot, coreTaskRegistrations as p, deleteProviderIdentityForSlackUser as pn, listWatches as pt, runWithSlackInstallationToken as q, authenticationLinkedEvent as qt, createPluginHookRunner as r, withConversationMutationLock as rn, RESOURCE_SUBSCRIPTION_MAX_TTL_MS as rt, getPluginSystemPromptContributions as s, addAgentTurnUsage as sn, cancelWatch as st, agent_hooks_exports as t, createSqlConversationEventStore as tn, getSlackToolContext as tt, getPlugins as u, agentTurnUsageSchema as un, createWatch as ut, getWorkspace as v, requireSlackDestination as vn, setDashboardConversationLinkOptions as vt, loadSnapshotsForProfile as w, conversationArchiveTimes as wt, updateWorkspace as x, createPluginModel as xt, getWorkspaceByName as y, sameDestination as yn, createPluginState as yt, SlackActionError as z, recordSlackAttachment as zt };
|