@sentry/junior 0.226.0 → 0.228.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-FUetyyLe.js → agent-hooks-DUQ3ASdp.js} +227 -12
- package/dist/{agent-runner-DEF7auSj.js → agent-runner-CIesujf5.js} +123 -77
- package/dist/api/schema.d.ts +203 -32
- package/dist/api/schema.js +3 -3
- package/dist/api.js +105 -67
- package/dist/{app-TVL42pGL.d.ts → app-BRZB3MuD.d.ts} +1 -1
- package/dist/app.d.ts +1 -1
- package/dist/app.js +275 -137
- package/dist/{briefs-Cb4T2BUI.js → briefs-BTrVMqUg.js} +4 -4
- package/dist/{catalog-runtime-BYGR3Dr4.js → catalog-runtime-NOBDOyJi.js} +1 -1
- package/dist/{checkpoint-CJe-dZFF.js → checkpoint-CzN3gXoB.js} +7 -7
- 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-C2WBBx7m.js → client-C6VUBzL_.js} +2 -2
- package/dist/{config-Bws6Rpsh.js → config-BLPaWN1Q.js} +2 -2
- package/dist/{context-Bplcgypl.js → context-0Et9iVSB.js} +1 -1
- package/dist/{conversation-DPbmIwjy.js → conversation-DOI6Y60M.js} +52 -24
- package/dist/{conversation-privacy-pCcW0a5Y.js → conversation-privacy-DJ88ECSq.js} +1 -1
- package/dist/{credential-sync-ibuNsMyl.js → credential-sync-OKs419AB.js} +14 -14
- package/dist/{executor-D36FWjcf.js → executor-DZVZBfmX.js} +1 -1
- package/dist/{history-DI9KJT3J.d.ts → history-H-SI5Dej.d.ts} +27 -1
- package/dist/images-D3x6EemU.js +82 -0
- package/dist/instrumentation.js +2 -2
- package/dist/{job-queue-2mFFDMHB.js → job-queue-BuSPM0cX.js} +1 -1
- package/dist/{logging-CvjMHRvg.js → logging-Blgn76r3.js} +1 -1
- package/dist/nitro.d.ts +1 -1
- package/dist/nitro.js +3 -3
- package/dist/{oauth-authorization-l4O1rXsL.js → oauth-authorization-t-NPqTNB.js} +1 -1
- package/dist/{oauth-callback-server-Ds8M5FFX.js → oauth-callback-server-BP7SgTcu.js} +2 -2
- package/dist/{pending-auth-DLNJbD8H.js → pending-auth-CXLwmDaG.js} +1 -1
- package/dist/{profile-dvV7PB7u.js → profile-a5xmeUHf.js} +4 -4
- package/dist/{prompt-DehgjkO5.js → prompt-9C-wUwwx.js} +1 -1
- package/dist/{registry-C6FHctIu.js → registry-BUbczT2k.js} +2 -2
- package/dist/{resolve-DqwGI9wq.js → resolve-3PhWSiEF.js} +2 -2
- package/dist/{runner-CzYEcB73.js → runner-CsnuKcsq.js} +10 -10
- package/dist/{sandbox-egress-signals-BZOv0fns.js → sandbox-egress-signals-D34sI4J6.js} +1 -1
- package/dist/{schema-BZg-xzfG.js → schema-CXmCvVLn.js} +1 -1
- package/dist/{skills-EhiVbjF4.js → skills-CLgyYrgF.js} +2 -2
- package/dist/{spawn-Ck3L0rEr.js → spawn-CS56i7Nm.js} +2 -2
- package/dist/{task-queue-TXhAWQwj.js → task-queue-C2sTDXqQ.js} +3 -3
- package/dist/{task-runner-axUJS1No.js → task-runner-uSodiP4v.js} +10 -10
- package/dist/{thread-state-CTuWhjru.js → thread-state-BurqeqMv.js} +5 -5
- package/dist/{turn-failure-response-csVoLOzx.js → turn-failure-response-Bshcqa0a.js} +9 -9
- package/dist/{turn-lifecycle-C1S6vELh.js → turn-lifecycle-foKlVl_T.js} +1 -1
- package/dist/{turn-session-routing-5RejBvit.js → turn-session-routing-DDUMJ2GY.js} +1 -1
- package/dist/{validation-q2PFxkTQ.js → validation-DZc56dXw.js} +1 -1
- package/dist/{version-ByLtIYyy.js → version-y4cRp5Y2.js} +1 -1
- package/dist/version.js +1 -1
- package/dist/{web-authorization-Biy8nsS7.js → web-authorization-BfVYx0t1.js} +6 -6
- package/dist/{web-input-DM9LaEdn.js → web-input-B6FZlrgg.js} +73 -41
- package/dist/{work-QrbHdXTc.js → work-Dy8sW9MZ.js} +7 -7
- package/dist/{worker-r17aopXW.js → worker-BH0RP7Hj.js} +5 -5
- package/package.json +5 -4
|
@@ -1,21 +1,21 @@
|
|
|
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-C6VUBzL_.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-Blgn76r3.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-DJ88ECSq.js";
|
|
6
|
+
import { a as getChatConfig, n as botConfig, s as getSlackBotToken } from "./config-BLPaWN1Q.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-DZVZBfmX.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-DOI6Y60M.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-a5xmeUHf.js";
|
|
13
|
+
import { n as briefEntriesFromReportEvents, s as generateBrief, t as BRIEF_PROMPT } from "./prompt-9C-wUwwx.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";
|
|
17
17
|
import { and, arrayContains, asc, desc, eq, exists, getTableColumns, gt, gte, inArray, isNotNull, isNull, lt, lte, max, ne, notExists, or, sql } from "drizzle-orm";
|
|
18
|
-
import { codeChangeInputSchema, conversationAnnotationInputSchema, conversationEventPresentationSchema, defineConversationEvent, destinationSchema, eventInputSchema, eventMatchSchema, eventMatches, eventTypeSchema, identitySchema, locationSchema, missingToolAnnotationKeys, normalizeEventIdentifier, objectAnnotationSchema, pluginEventsSchema, promptContextSchema, promptMessageSchema, sourceSchema, stableEventMatchKey, userSchema } from "@sentry/junior-plugin-api";
|
|
18
|
+
import { codeChangeInputSchema, conversationAnnotationInputSchema, conversationEventPresentationSchema, defineConversationEvent, destinationSchema, eventInputSchema, eventMatchSchema, eventMatches, eventTypeSchema, identitySchema, locationSchema, missingToolAnnotationKeys, normalizeEventIdentifier, objectAnnotationSchema, objectIconPath, objectTypeSchema, pluginEventsSchema, promptContextSchema, promptMessageSchema, sourceSchema, stableEventMatchKey, userSchema } from "@sentry/junior-plugin-api";
|
|
19
19
|
import { alias } from "drizzle-orm/pg-core";
|
|
20
20
|
import { WebClient } from "@slack/web-api";
|
|
21
21
|
import { Sandbox } from "@vercel/sandbox";
|
|
@@ -1808,6 +1808,63 @@ const briefUpdatedEvent = defineConversationEvent({
|
|
|
1808
1808
|
}
|
|
1809
1809
|
});
|
|
1810
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
|
|
1811
1868
|
//#region src/chat/sentry-links.ts
|
|
1812
1869
|
function getSentryOrgSlug() {
|
|
1813
1870
|
return process.env.SENTRY_ORG_SLUG?.trim() || void 0;
|
|
@@ -2054,11 +2111,15 @@ function reportEventData(args) {
|
|
|
2054
2111
|
role: data.role,
|
|
2055
2112
|
...data.meta?.source === "web" || data.meta?.source === "slack" ? { source: data.meta.source } : void 0,
|
|
2056
2113
|
...actorIdentity ? { actorIdentity } : void 0,
|
|
2114
|
+
eventObjectType: objectTypeSchema.safeParse(data.meta?.eventObjectType).data,
|
|
2057
2115
|
...typeof data.meta?.eventType === "string" ? { eventType: data.meta.eventType } : void 0,
|
|
2058
2116
|
...typeof data.meta?.explicitMention === "boolean" ? { explicitMention: data.meta.explicitMention } : void 0,
|
|
2059
2117
|
...args.canExposePayload && typeof data.meta?.trustedSummary === "string" ? { trustedSummary: data.meta.trustedSummary } : void 0,
|
|
2060
2118
|
...args.canExposePayload && (data.meta?.cards || data.meta?.objectCards) ? { cards: readMessageCards(data.meta) } : void 0,
|
|
2061
|
-
...args.canExposePayload ? {
|
|
2119
|
+
...args.canExposePayload ? {
|
|
2120
|
+
text: data.text,
|
|
2121
|
+
...data.meta?.attachments ? { attachments: readMessageAttachments(data.meta.attachments) } : void 0
|
|
2122
|
+
} : { redacted: true }
|
|
2062
2123
|
};
|
|
2063
2124
|
}
|
|
2064
2125
|
case "message_handled": return {
|
|
@@ -2288,6 +2349,7 @@ async function projectConversationEventRows(executor, args) {
|
|
|
2288
2349
|
toolCallIds: toolResultIds,
|
|
2289
2350
|
types: ["tool_execution_started"]
|
|
2290
2351
|
});
|
|
2352
|
+
if (args.canExposePayload) await hydrateMessageAttachments(executor, args.conversationId, events);
|
|
2291
2353
|
return projectConversationReportEventPage({
|
|
2292
2354
|
canExposePayload: args.canExposePayload,
|
|
2293
2355
|
events,
|
|
@@ -3074,11 +3136,90 @@ function getDashboardConversationLink(conversationId) {
|
|
|
3074
3136
|
function getDashboardTaskLink(taskId) {
|
|
3075
3137
|
return resolveDashboardPath(`/automations/${encodeURIComponent(taskId)}`);
|
|
3076
3138
|
}
|
|
3139
|
+
/** Public icon asset URL. Headless and local installs keep text-only identity. */
|
|
3140
|
+
function getDashboardObjectIconLink(icon) {
|
|
3141
|
+
if (!dashboardConversationLinkOptions) return void 0;
|
|
3142
|
+
const url = new URL(objectIconPath(icon), resolveDashboardBaseURL(dashboardConversationLinkOptions));
|
|
3143
|
+
if (url.protocol !== "https:" || url.hostname === "localhost") return void 0;
|
|
3144
|
+
return url.href;
|
|
3145
|
+
}
|
|
3077
3146
|
//#endregion
|
|
3078
3147
|
//#region src/chat/state/ttl.ts
|
|
3079
3148
|
/** Retain expiring conversation/runtime state long enough for resume and dashboard history. */
|
|
3080
3149
|
const JUNIOR_THREAD_STATE_TTL_MS = 6048e5;
|
|
3081
3150
|
//#endregion
|
|
3151
|
+
//#region src/chat/events/timer-index.ts
|
|
3152
|
+
const DUE_KEY = "junior:watches:due";
|
|
3153
|
+
const CLAIM_MS = 12e4;
|
|
3154
|
+
const BATCH_SIZE = 25;
|
|
3155
|
+
const entriesSchema = z.array(z.object({
|
|
3156
|
+
id: z.string(),
|
|
3157
|
+
atMs: z.number()
|
|
3158
|
+
}));
|
|
3159
|
+
/** Keep timer index operations atomic in Redis and the local memory adapter. */
|
|
3160
|
+
async function updateTimerIndex(state, operation) {
|
|
3161
|
+
const redis = await getDefaultRedisStateAdapterFor(state);
|
|
3162
|
+
if (redis) {
|
|
3163
|
+
const prefix = getChatConfig().state.keyPrefix;
|
|
3164
|
+
const key = prefix ? `${prefix}:${DUE_KEY}` : DUE_KEY;
|
|
3165
|
+
const client = redis.getClient();
|
|
3166
|
+
if (operation.kind === "add") {
|
|
3167
|
+
await client.sendCommand([
|
|
3168
|
+
"ZADD",
|
|
3169
|
+
key,
|
|
3170
|
+
String(operation.atMs),
|
|
3171
|
+
operation.id
|
|
3172
|
+
]);
|
|
3173
|
+
return [];
|
|
3174
|
+
}
|
|
3175
|
+
if (operation.kind === "remove") {
|
|
3176
|
+
await client.sendCommand([
|
|
3177
|
+
"ZREM",
|
|
3178
|
+
key,
|
|
3179
|
+
operation.id
|
|
3180
|
+
]);
|
|
3181
|
+
return [];
|
|
3182
|
+
}
|
|
3183
|
+
return await client.sendCommand([
|
|
3184
|
+
"EVAL",
|
|
3185
|
+
`local ids = redis.call('ZRANGEBYSCORE', KEYS[1], '-inf', ARGV[1], 'LIMIT', 0, ARGV[3])
|
|
3186
|
+
for _, id in ipairs(ids) do
|
|
3187
|
+
redis.call('ZADD', KEYS[1], ARGV[2], id)
|
|
3188
|
+
end
|
|
3189
|
+
return ids`,
|
|
3190
|
+
"1",
|
|
3191
|
+
key,
|
|
3192
|
+
String(operation.nowMs),
|
|
3193
|
+
String(operation.nowMs + CLAIM_MS),
|
|
3194
|
+
String(BATCH_SIZE)
|
|
3195
|
+
]);
|
|
3196
|
+
}
|
|
3197
|
+
const lock = await state.acquireLock(`${DUE_KEY}:lock`, 1e4);
|
|
3198
|
+
if (!lock) throw new Error("Could not acquire timer index lock");
|
|
3199
|
+
try {
|
|
3200
|
+
let entries = entriesSchema.parse(await state.get(DUE_KEY) ?? []);
|
|
3201
|
+
let ids = [];
|
|
3202
|
+
if (operation.kind === "claim") {
|
|
3203
|
+
ids = entries.filter((entry) => entry.atMs <= operation.nowMs).sort((a, b) => a.atMs - b.atMs).slice(0, BATCH_SIZE).map((entry) => entry.id);
|
|
3204
|
+
const claimed = new Set(ids);
|
|
3205
|
+
entries = entries.map((entry) => claimed.has(entry.id) ? {
|
|
3206
|
+
...entry,
|
|
3207
|
+
atMs: operation.nowMs + CLAIM_MS
|
|
3208
|
+
} : entry);
|
|
3209
|
+
} else {
|
|
3210
|
+
entries = entries.filter((entry) => entry.id !== operation.id);
|
|
3211
|
+
if (operation.kind === "add") entries.push({
|
|
3212
|
+
id: operation.id,
|
|
3213
|
+
atMs: operation.atMs
|
|
3214
|
+
});
|
|
3215
|
+
}
|
|
3216
|
+
await state.set(DUE_KEY, entries);
|
|
3217
|
+
return ids;
|
|
3218
|
+
} finally {
|
|
3219
|
+
await state.releaseLock(lock);
|
|
3220
|
+
}
|
|
3221
|
+
}
|
|
3222
|
+
//#endregion
|
|
3082
3223
|
//#region src/chat/events/store.ts
|
|
3083
3224
|
const EVENT_PREFIX = "junior:resource_event_subscription:v5";
|
|
3084
3225
|
const INDEX_LOCK_TTL_MS = 1e4;
|
|
@@ -3097,6 +3238,7 @@ const subscriptionSchema = z.object({
|
|
|
3097
3238
|
createdAtMs: z.number().finite(),
|
|
3098
3239
|
events: z.array(eventTypeSchema).min(1),
|
|
3099
3240
|
expiresAtMs: z.number().finite(),
|
|
3241
|
+
firesAtMs: z.number().finite().optional(),
|
|
3100
3242
|
id: z.string().min(1),
|
|
3101
3243
|
intent: z.string().min(1),
|
|
3102
3244
|
label: z.string().min(1),
|
|
@@ -3254,6 +3396,70 @@ async function createWatch(input, options = {}) {
|
|
|
3254
3396
|
await addToIndex(state, conversationIndexKey(input.conversationId), id, nowMs);
|
|
3255
3397
|
return parsed;
|
|
3256
3398
|
}
|
|
3399
|
+
/** Create a retry-stable timer without keeping a process open. */
|
|
3400
|
+
async function createTimerWatch(input) {
|
|
3401
|
+
const state = getStateAdapter();
|
|
3402
|
+
await state.connect();
|
|
3403
|
+
const identifier = digest(`${input.conversationId}\0${input.toolCallId}`);
|
|
3404
|
+
const selector = {
|
|
3405
|
+
conversationId: input.conversationId,
|
|
3406
|
+
namespace: "junior",
|
|
3407
|
+
identifier,
|
|
3408
|
+
events: ["timer.fired"]
|
|
3409
|
+
};
|
|
3410
|
+
const id = buildSubscriptionId(selector);
|
|
3411
|
+
return await withSubscriptionLock(state, id, async () => {
|
|
3412
|
+
const existing = parseSubscription(await state.get(subscriptionKey(id)));
|
|
3413
|
+
if (existing) return existing;
|
|
3414
|
+
const nowMs = Date.now();
|
|
3415
|
+
const firesAtMs = nowMs + input.afterMs;
|
|
3416
|
+
const expiresAtMs = firesAtMs + 864e5;
|
|
3417
|
+
const record = subscriptionSchema.parse({
|
|
3418
|
+
...selector,
|
|
3419
|
+
id,
|
|
3420
|
+
firesAtMs,
|
|
3421
|
+
expiresAtMs,
|
|
3422
|
+
resourceType: "timer",
|
|
3423
|
+
label: "Timer",
|
|
3424
|
+
intent: input.intent,
|
|
3425
|
+
status: "active",
|
|
3426
|
+
createdAtMs: nowMs,
|
|
3427
|
+
updatedAtMs: nowMs
|
|
3428
|
+
});
|
|
3429
|
+
await withIndexLock(state, conversationIndexKey(input.conversationId), async () => {
|
|
3430
|
+
const key = conversationIndexKey(input.conversationId);
|
|
3431
|
+
const ids = [.../* @__PURE__ */ new Set([...await readSubscriptionIdIndex(state, key), id])];
|
|
3432
|
+
await state.set(key, ids, Math.max(ttlUntil(expiresAtMs, nowMs), await indexTtlMs(state, ids, nowMs)));
|
|
3433
|
+
await state.set(resourceIndexKey("junior", identifier), [id], ttlUntil(expiresAtMs, nowMs));
|
|
3434
|
+
await updateTimerIndex(state, {
|
|
3435
|
+
kind: "add",
|
|
3436
|
+
id,
|
|
3437
|
+
atMs: firesAtMs
|
|
3438
|
+
});
|
|
3439
|
+
await state.set(subscriptionKey(id), record, ttlUntil(expiresAtMs, nowMs));
|
|
3440
|
+
});
|
|
3441
|
+
return record;
|
|
3442
|
+
});
|
|
3443
|
+
}
|
|
3444
|
+
/** Claim live timer Watches and discard stale due-index entries. */
|
|
3445
|
+
async function takeDueTimerWatches(nowMs) {
|
|
3446
|
+
const state = getStateAdapter();
|
|
3447
|
+
await state.connect();
|
|
3448
|
+
const watches = [];
|
|
3449
|
+
for (const id of await updateTimerIndex(state, {
|
|
3450
|
+
kind: "claim",
|
|
3451
|
+
nowMs
|
|
3452
|
+
})) await withSubscriptionLock(state, id, async () => {
|
|
3453
|
+
const watch = parseSubscription(await state.get(subscriptionKey(id)));
|
|
3454
|
+
if (watch && activeAt(watch, nowMs) && watch.firesAtMs !== void 0) {
|
|
3455
|
+
if (watch.firesAtMs <= nowMs) watches.push(watch);
|
|
3456
|
+
} else await updateTimerIndex(state, {
|
|
3457
|
+
kind: "remove",
|
|
3458
|
+
id
|
|
3459
|
+
});
|
|
3460
|
+
});
|
|
3461
|
+
return watches;
|
|
3462
|
+
}
|
|
3257
3463
|
/** List active subscriptions bound to one conversation. */
|
|
3258
3464
|
async function listWatches(input) {
|
|
3259
3465
|
const state = input.state ?? getStateAdapter();
|
|
@@ -3270,6 +3476,7 @@ async function cancelWatch(input) {
|
|
|
3270
3476
|
const current = parseSubscription(await state.get(subscriptionKey(input.id)));
|
|
3271
3477
|
if (!current || current.conversationId !== input.conversationId) return;
|
|
3272
3478
|
const nowMs = input.nowMs ?? Date.now();
|
|
3479
|
+
if (current.status === "completed") return current;
|
|
3273
3480
|
const next = {
|
|
3274
3481
|
...current,
|
|
3275
3482
|
status: "cancelled",
|
|
@@ -3278,6 +3485,10 @@ async function cancelWatch(input) {
|
|
|
3278
3485
|
await state.set(subscriptionKey(input.id), next, JUNIOR_THREAD_STATE_TTL_MS);
|
|
3279
3486
|
await removeFromIndex(state, resourceIndexKey(current.namespace, current.identifier), input.id, nowMs);
|
|
3280
3487
|
await removeFromIndex(state, conversationIndexKey(current.conversationId), input.id, nowMs);
|
|
3488
|
+
if (current.firesAtMs !== void 0) await updateTimerIndex(state, {
|
|
3489
|
+
kind: "remove",
|
|
3490
|
+
id: input.id
|
|
3491
|
+
});
|
|
3281
3492
|
return next;
|
|
3282
3493
|
});
|
|
3283
3494
|
}
|
|
@@ -3358,6 +3569,10 @@ async function deliverWatch(input) {
|
|
|
3358
3569
|
await removeFromIndex(state, resourceIndexKey(current.namespace, current.identifier), current.id, nowMs);
|
|
3359
3570
|
await removeFromIndex(state, conversationIndexKey(current.conversationId), current.id, nowMs);
|
|
3360
3571
|
}
|
|
3572
|
+
if (input.terminal && current.firesAtMs !== void 0) await updateTimerIndex(state, {
|
|
3573
|
+
kind: "remove",
|
|
3574
|
+
id: current.id
|
|
3575
|
+
});
|
|
3361
3576
|
return delivered;
|
|
3362
3577
|
}, input.waitDeadlineMs);
|
|
3363
3578
|
}
|
|
@@ -5444,4 +5659,4 @@ function createPluginHookRunner(input = {}) {
|
|
|
5444
5659
|
};
|
|
5445
5660
|
}
|
|
5446
5661
|
//#endregion
|
|
5447
|
-
export { resolveViewerUser as $,
|
|
5662
|
+
export { resolveViewerUser as $, getConversationStore as $t, tryWorkspaceRepoCheckoutPath as A, conversationNotArchivedForEmail as At, downloadPrivateSlackFile as B, recordSlackAttachment as Bt, invalidateReadySnapshot as C, createPluginLogger as Ct, SANDBOX_RUNTIME as D, conversationArchivedForUser as Dt, setWorkspaceSnapshotBuild as E, conversationArchivedForEmail as Et, bindSlackDirectCredentialSubject as F, readConversationEventPage as Ft, isDmChannel as G, listConversationAnnotationsById as Gt, getHeaderString as H, saveObjectAnnotations as Ht, verifyEventAutomationCredentialSubject as I, buildSentryConversationUrl as It, withSlackRetries as J, authenticationLinkedEvent as Jt, normalizeSlackConversationId as K, JUNIOR_NATIVE_EVENT_NAMESPACE as Kt, verifyScheduledAutomationCredentialSubject as L, getSlackFileId as Lt, resolveChannelCapabilities as M, viewerConversationMembership as Mt, bindEventAutomationCredentialSubject as N, createPluginConversationEvents as Nt, deleteWorkspaceSnapshotBuilders as O, conversationHasParticipantEmail as Ot, bindScheduledAutomationCredentialSubject as P, readLatestConversationBrief as Pt, readActorIdentity as Q, getConversationMessageSearchStore as Qt, verifySlackDirectCredentialSubject as R, matchSlackAttachments as Rt, WorkspaceValidationError as S, createPluginModel as St, setWorkspaceSnapshot as T, conversationArchiveTimes as Tt, getSlackClient as U, createPluginAnnotations as Ut, getFilePermalink as V, resolveRootVisibility as Vt, isConversationScopedChannel as W, listConversationAnnotations as Wt, runWithWorkspaceTeamId as X, db_exports as Xt, getWorkspaceTeamId as Y, authenticationUnlinkedEvent as Yt, findUserByEmail as Z, getConversationEventStore as Zt, deleteWorkspace as _, createSlackDestination as _n, getDashboardObjectIconLink as _t, getPluginRoutes as a, locationFromRow as an, STOP_WATCHING_TOOL_NAME as at, listWorkspaces as b, sameDestination as bn, createPluginState as bt, getPluginTools as c, addAgentTurnUsage as cn, collectEventMatchKeys as ct, setPlugins as d, agentTurnUsageSchema as dn, deliverWatch as dt, getDb as en, updateViewerDisplayName as et, validatePlugins as f, hasAgentTurnUsage as fn, findMatchingWatches as ft, createWorkspace as g, upsertLinkedIdentity as gn, getDashboardConversationLink as gt, setBriefsConfig as h, upsertIdentity as hn, JUNIOR_THREAD_STATE_TTL_MS as ht, getPluginApiRoutes as i, withConversationMutationLock as in, RESOURCE_WATCH_TOOL_SOURCE as it, workspaceRepoCheckoutPath as j, conversationNotArchivedForUser as jt, getWorkspaceSnapshotBuilder as k, conversationHasParticipantUser as kt, getPluginUserPromptContributions as l, agentTurnCostUsd as ln, createTimerWatch as lt, registration_exports as m, deleteProviderIdentityForSlackUser as mn, takeDueTimerWatches as mt, applyPluginFormatMarkdown as n, createSqlConversationEventStore as nn, RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS as nt, getPluginSlackConversationLink as o, bindProviderConversation as on, cancelSubscriptions as ot, coreTaskRegistrations as p, resolveRootConversationId as pn, listWatches as pt, runWithSlackInstallationToken as q, agentsInstructionsUpdatedEvent as qt, createPluginHookRunner as r, withConversationEventLock as rn, RESOURCE_SUBSCRIPTION_MAX_TTL_MS as rt, getPluginSystemPromptContributions as s, parseSessionSource as sn, cancelWatch as st, agent_hooks_exports as t, getSqlExecutor as tn, getSlackToolContext as tt, getPlugins as u, agentTurnTotalTokens as un, createWatch as ut, getWorkspace as v, parseDestination as vn, getDashboardTaskLink as vt, loadSnapshotsForProfile as w, readConversationAccessFromSql as wt, updateWorkspace as x, createPluginEmbedder as xt, getWorkspaceByName as y, requireSlackDestination as yn, setDashboardConversationLinkOptions as yt, SlackActionError as z, readAttachmentVisionSummary as zt };
|