@sentry/junior 0.233.0 → 0.235.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.
Files changed (58) hide show
  1. package/dist/{agent-hooks-DATy_Hnt.js → agent-hooks-DS7k0ZWY.js} +17 -10
  2. package/dist/{agent-runner-BKOtZjez.js → agent-runner-BlDI1zV2.js} +354 -813
  3. package/dist/api/schema.d.ts +528 -2
  4. package/dist/api/schema.js +4 -4
  5. package/dist/api.js +350 -55
  6. package/dist/{app-xk2-Id1T.d.ts → app-pGsR__aT.d.ts} +1 -1
  7. package/dist/app.d.ts +1 -1
  8. package/dist/app.js +33 -21
  9. package/dist/{briefs-ClOTHmQ-.js → briefs-C3jhszOz.js} +4 -4
  10. package/dist/{catalog-runtime-xFtmw3oA.js → catalog-runtime-B9u_3-GW.js} +1 -1
  11. package/dist/{checkpoint-zkEB448J.js → checkpoint-DLcJ5mKL.js} +7 -7
  12. package/dist/cli/chat.js +13 -13
  13. package/dist/cli/check.js +3 -3
  14. package/dist/cli/main.js +1 -1
  15. package/dist/cli/plugins.js +3 -3
  16. package/dist/cli/snapshot-create.js +3 -3
  17. package/dist/cli/upgrade.js +3 -3
  18. package/dist/{client-CJUZHY9Y.js → client-BSnNHO0R.js} +2 -2
  19. package/dist/{config-XtycpE-i.js → config-Bmw4xTPK.js} +2 -2
  20. package/dist/{conversation-CPjHYOV5.js → conversation-C_aYrISI.js} +1 -0
  21. package/dist/{conversation-privacy-B30pEcsR.js → conversation-privacy-BV2dtba2.js} +1 -1
  22. package/dist/{credential-sync-vufd6gwK.js → credential-sync-CukzQJ1x.js} +13 -13
  23. package/dist/{executor-BGDb_cM-.js → executor-B9ksWZCv.js} +33 -1
  24. package/dist/{images-zuEwjVKU.js → images-CEXcQ0Id.js} +3 -3
  25. package/dist/instrumentation.js +2 -2
  26. package/dist/{job-queue-C5JaRRcE.js → job-queue-CY1L2YRn.js} +1 -1
  27. package/dist/{logging-BS563NYn.js → logging-F--48Q7Q.js} +1 -1
  28. package/dist/nitro.d.ts +1 -1
  29. package/dist/nitro.js +3 -3
  30. package/dist/{oauth-authorization-DF2dSmNh.js → oauth-authorization-LasSG3Qc.js} +1 -1
  31. package/dist/{oauth-callback-server-CW9COQ9L.js → oauth-callback-server-D07ZzVMs.js} +2 -2
  32. package/dist/{pending-auth-8Kmti8S3.js → pending-auth-DrG9Mkje.js} +1 -1
  33. package/dist/{profile-C4_njQYA.js → profile-DZ2DUdd1.js} +4 -4
  34. package/dist/{prompt-3D0sSbTC.js → prompt-BM_5mAU3.js} +1 -1
  35. package/dist/{registry-BhiLWAY6.js → registry-_JLY0x7b.js} +1 -1
  36. package/dist/{resolve-ZDwJ6a3N.js → resolve-Cuoj3MML.js} +2 -2
  37. package/dist/{runner-D1xeORYM.js → runner-BfelmbMv.js} +9 -9
  38. package/dist/{sandbox-egress-signals-Dx1PzQpy.js → sandbox-egress-signals-D5QUIO7Z.js} +1 -1
  39. package/dist/{schema-DuGfOm4u.js → schema-CrdDxGbx.js} +26 -117
  40. package/dist/{skills-CN-ye6on.js → skills-DAegjk5Y.js} +2 -2
  41. package/dist/{spawn-B8KYOBcU.js → spawn-DCfV7zGK.js} +2 -2
  42. package/dist/{task-queue-DPaZtxld.js → task-queue-GcuFtzor.js} +3 -3
  43. package/dist/{task-runner-D23tSETM.js → task-runner-B0-P_3aq.js} +16 -13
  44. package/dist/{thread-state-BbxSiDa9.js → thread-state-TezcEhuH.js} +5 -5
  45. package/dist/{turn-failure-response-c8irQDMB.js → turn-failure-response-Drhj_-t4.js} +8 -8
  46. package/dist/{turn-lifecycle-DSVG3u_p.js → turn-lifecycle-BpIW3zOx.js} +1 -1
  47. package/dist/{turn-session-routing-B2hNxu_N.js → turn-session-routing-Dg8GDgyc.js} +1 -1
  48. package/dist/types-Du-HbEun.js +621 -0
  49. package/dist/{validation-BrLB5qbC.js → validation-DAkYeKDT.js} +1 -1
  50. package/dist/{version-B2rspCmP.js → version-9CB4Z-J4.js} +1 -1
  51. package/dist/version.js +1 -1
  52. package/dist/{web-authorization-CVSTvY_D.js → web-authorization-Cu33voNg.js} +6 -6
  53. package/dist/{web-input-zUQoZMZw.js → web-input-B3k0J7WB.js} +212 -164
  54. package/dist/web-message-id-CVVCTWUb.js +464 -0
  55. package/dist/{work-BXbJVOZI.js → work-PmkvcY9l.js} +7 -7
  56. package/dist/{worker-ClkQ9S9C.js → worker-COcaq2J6.js} +5 -5
  57. package/package.json +5 -5
  58. package/dist/web-message-id-xPI_EFSC.js +0 -239
@@ -0,0 +1,621 @@
1
+ import { z } from "zod";
2
+ import { actorUserIdSchema, destinationVisibilitySchema, eventMatchSchema, eventTypeSchema, slackDestinationSchema, taskOutcomeSchema } from "@sentry/junior-plugin-api";
3
+ //#region src/chat/task-outcomes-schema.ts
4
+ const taskMessageDestinationInputSchema = z.enum(["current_conversation", "task_creator"]).describe("Where to send the message. Use current_conversation for posts, digests, summaries, and channel reminders. Use task_creator only when the user asks for a direct reminder or notification.");
5
+ /** Input accepted by task authoring tools before a user becomes a DM Destination. */
6
+ const taskOutcomeInputSchema = z.object({
7
+ action: z.literal("send_message"),
8
+ destination: taskMessageDestinationInputSchema
9
+ }).strict();
10
+ /** Validate the persisted Slack creator identity for an event automation. */
11
+ const eventAutomationPrincipalSchema = z.object({
12
+ slackUserId: actorUserIdSchema,
13
+ fullName: z.string().optional(),
14
+ userName: z.string().optional()
15
+ }).strict();
16
+ /** Validate one persisted event-automation selector and its presentation metadata. */
17
+ const eventAutomationTriggerSchema = z.object({
18
+ events: z.array(eventTypeSchema).min(1),
19
+ label: z.string().min(1),
20
+ match: eventMatchSchema.optional(),
21
+ namespace: z.string().min(1),
22
+ identifier: z.string().min(1).max(300),
23
+ resourceType: z.string().min(1)
24
+ }).strict();
25
+ /** Event automations target a Slack channel or DM, never a message thread. */
26
+ const eventAutomationDestinationSchema = slackDestinationSchema.omit({ threadTs: true });
27
+ const eventAutomationOutcomeSchema = taskOutcomeSchema.extend({ destination: eventAutomationDestinationSchema });
28
+ /** Validate one persisted event automation. */
29
+ const eventAutomationSchema = z.object({
30
+ id: z.string().min(1),
31
+ createdAtMs: z.number().finite(),
32
+ createdBy: eventAutomationPrincipalSchema,
33
+ credentialMode: z.enum(["system", "creator"]),
34
+ destination: eventAutomationDestinationSchema,
35
+ destinationVisibility: destinationVisibilitySchema,
36
+ /** Explicit visible effects after successful work. An empty list is silent. */
37
+ outcomes: z.array(eventAutomationOutcomeSchema).max(5),
38
+ task: z.object({ text: z.string().min(1) }).strict(),
39
+ trigger: eventAutomationTriggerSchema
40
+ }).strict();
41
+ //#endregion
42
+ //#region src/chat/scheduled-automations/cadence.ts
43
+ const FORMATTERS = /* @__PURE__ */ new Map();
44
+ function getFormatter(timezone) {
45
+ const existing = FORMATTERS.get(timezone);
46
+ if (existing) return existing;
47
+ const formatter = new Intl.DateTimeFormat("en-US", {
48
+ timeZone: timezone,
49
+ hour12: false,
50
+ year: "numeric",
51
+ month: "2-digit",
52
+ day: "2-digit",
53
+ hour: "2-digit",
54
+ minute: "2-digit",
55
+ second: "2-digit"
56
+ });
57
+ FORMATTERS.set(timezone, formatter);
58
+ return formatter;
59
+ }
60
+ function normalizeHour(hour) {
61
+ return hour === 24 ? 0 : hour;
62
+ }
63
+ function getLocalDateWeekday(date) {
64
+ return new Date(Date.UTC(date.year, date.month - 1, date.day)).getUTCDay();
65
+ }
66
+ function getWeekStart(date) {
67
+ return addDays(date, -((getLocalDateWeekday(date) + 6) % 7));
68
+ }
69
+ /** Resolve a UTC timestamp into calendar parts for a named time zone. */
70
+ function getZonedDateTimeParts(timestampMs, timezone) {
71
+ const parts = getFormatter(timezone).formatToParts(new Date(timestampMs));
72
+ const values = new Map(parts.map((part) => [part.type, part.value]));
73
+ const year = Number(values.get("year"));
74
+ const month = Number(values.get("month"));
75
+ const day = Number(values.get("day"));
76
+ return {
77
+ year,
78
+ month,
79
+ day,
80
+ hour: normalizeHour(Number(values.get("hour"))),
81
+ minute: Number(values.get("minute")),
82
+ second: Number(values.get("second")),
83
+ weekday: getLocalDateWeekday({
84
+ year,
85
+ month,
86
+ day
87
+ })
88
+ };
89
+ }
90
+ function getTimeZoneOffsetMs(timestampMs, timezone) {
91
+ const parts = getZonedDateTimeParts(timestampMs, timezone);
92
+ return Date.UTC(parts.year, parts.month - 1, parts.day, parts.hour, parts.minute, parts.second) - timestampMs;
93
+ }
94
+ function localDateTimeToTimestampMs(args) {
95
+ const localAsUtcMs = Date.UTC(args.date.year, args.date.month - 1, args.date.day, args.time.hour, args.time.minute, 0);
96
+ const offsets = /* @__PURE__ */ new Set();
97
+ for (const probeDeltaMs of [
98
+ -1296e5,
99
+ -432e5,
100
+ 0,
101
+ 432e5,
102
+ 1296e5
103
+ ]) offsets.add(getTimeZoneOffsetMs(localAsUtcMs + probeDeltaMs, args.timezone));
104
+ const matches = [...offsets].map((offsetMs) => localAsUtcMs - offsetMs).filter((timestampMs) => {
105
+ const parts = getZonedDateTimeParts(timestampMs, args.timezone);
106
+ return parts.year === args.date.year && parts.month === args.date.month && parts.day === args.date.day && parts.hour === args.time.hour && parts.minute === args.time.minute;
107
+ });
108
+ if (matches.length === 0) return;
109
+ return Math.min(...matches);
110
+ }
111
+ /** Resolve local time, rejecting DST gaps and choosing the earlier instant in a fold. */
112
+ function resolveLocalScheduleAtMs(args) {
113
+ const date = parseLocalDate(args.date);
114
+ if (!date) return;
115
+ return localDateTimeToTimestampMs({
116
+ date,
117
+ time: args.time,
118
+ timezone: args.timezone
119
+ });
120
+ }
121
+ function daysBetween(left, right) {
122
+ return Math.floor((Date.UTC(right.year, right.month - 1, right.day) - Date.UTC(left.year, left.month - 1, left.day)) / 864e5);
123
+ }
124
+ function weeklyRecurrenceMatchesDate(date, start, recurrence) {
125
+ if (compareDate(date, start) < 0) return false;
126
+ return normalizeWeekdays(recurrence.weekdays).includes(getLocalDateWeekday(date)) && Math.floor(daysBetween(getWeekStart(start), getWeekStart(date)) / 7) % recurrence.interval === 0;
127
+ }
128
+ function greatestCommonDivisor(left, right) {
129
+ let a = Math.abs(left);
130
+ let b = Math.abs(right);
131
+ while (b !== 0) [a, b] = [b, a % b];
132
+ return a;
133
+ }
134
+ function findNextRunAtMs(args) {
135
+ const start = parseLocalDate(args.recurrence.startDate);
136
+ const interval = args.recurrence.interval;
137
+ if (!start || !Number.isInteger(interval) || interval <= 0) return;
138
+ const searchFrom = compareDate(args.searchFrom, start) < 0 ? start : args.searchFrom;
139
+ if (args.recurrence.frequency === "daily") {
140
+ const offsetDays = daysBetween(start, searchFrom);
141
+ let candidateDate = addDays(start, Math.ceil(offsetDays / interval) * interval);
142
+ const gregorianCycleDays = 146097;
143
+ const candidateCount = gregorianCycleDays / greatestCommonDivisor(gregorianCycleDays, interval);
144
+ for (let attempts = 0; attempts < candidateCount; attempts += 1) {
145
+ const candidate = buildCandidate({
146
+ date: candidateDate,
147
+ recurrence: args.recurrence,
148
+ timezone: args.timezone
149
+ });
150
+ if (candidate !== void 0 && candidate > args.afterMs) return candidate;
151
+ candidateDate = addDays(candidateDate, interval);
152
+ }
153
+ return;
154
+ }
155
+ if (args.recurrence.frequency === "weekly") {
156
+ if (normalizeWeekdays(args.recurrence.weekdays).length === 0) return;
157
+ let candidateDate = searchFrom;
158
+ const gregorianCycleDays = 146097;
159
+ const cadenceDays = interval * 7;
160
+ const searchDays = gregorianCycleDays * cadenceDays / greatestCommonDivisor(gregorianCycleDays, cadenceDays);
161
+ for (let attempts = 0; attempts < searchDays; attempts += 1) {
162
+ if (weeklyRecurrenceMatchesDate(candidateDate, start, args.recurrence)) {
163
+ const candidate = buildCandidate({
164
+ date: candidateDate,
165
+ recurrence: args.recurrence,
166
+ timezone: args.timezone
167
+ });
168
+ if (candidate !== void 0 && candidate > args.afterMs) return candidate;
169
+ }
170
+ candidateDate = addDays(candidateDate, 1);
171
+ }
172
+ return;
173
+ }
174
+ if (args.recurrence.frequency === "monthly") {
175
+ const startMonth = start.year * 12 + start.month - 1;
176
+ const searchMonth = searchFrom.year * 12 + searchFrom.month - 1;
177
+ let candidateMonth = startMonth + Math.ceil((searchMonth - startMonth) / interval) * interval;
178
+ const gregorianCycleMonths = 4800;
179
+ const candidateCount = gregorianCycleMonths / greatestCommonDivisor(gregorianCycleMonths, interval);
180
+ for (let attempts = 0; attempts < candidateCount; attempts += 1) {
181
+ const candidateDate = {
182
+ year: Math.floor(candidateMonth / 12),
183
+ month: candidateMonth % 12 + 1,
184
+ day: args.recurrence.dayOfMonth ?? 0
185
+ };
186
+ if (compareDate(candidateDate, searchFrom) >= 0) {
187
+ const candidate = buildCandidate({
188
+ date: candidateDate,
189
+ recurrence: args.recurrence,
190
+ timezone: args.timezone
191
+ });
192
+ if (candidate !== void 0 && candidate > args.afterMs) return candidate;
193
+ }
194
+ candidateMonth += interval;
195
+ }
196
+ return;
197
+ }
198
+ let candidateYear = start.year + Math.ceil((searchFrom.year - start.year) / interval) * interval;
199
+ const candidateCount = 400 / greatestCommonDivisor(400, interval);
200
+ for (let attempts = 0; attempts < candidateCount; attempts += 1) {
201
+ const candidateDate = {
202
+ year: candidateYear,
203
+ month: args.recurrence.month ?? 0,
204
+ day: args.recurrence.dayOfMonth ?? 0
205
+ };
206
+ if (compareDate(candidateDate, searchFrom) >= 0) {
207
+ const candidate = buildCandidate({
208
+ date: candidateDate,
209
+ recurrence: args.recurrence,
210
+ timezone: args.timezone
211
+ });
212
+ if (candidate !== void 0 && candidate > args.afterMs) return candidate;
213
+ }
214
+ candidateYear += interval;
215
+ }
216
+ }
217
+ /** Compute the first recurring calendar occurrence strictly after a timestamp. */
218
+ function getFirstRunAtMs(args) {
219
+ return findNextRunAtMs({
220
+ ...args,
221
+ searchFrom: getLocalDate(args.afterMs, args.timezone)
222
+ });
223
+ }
224
+ function compareDate(left, right) {
225
+ return Date.UTC(left.year, left.month - 1, left.day) - Date.UTC(right.year, right.month - 1, right.day);
226
+ }
227
+ function addDays(date, days) {
228
+ const next = new Date(Date.UTC(date.year, date.month - 1, date.day + days));
229
+ return {
230
+ year: next.getUTCFullYear(),
231
+ month: next.getUTCMonth() + 1,
232
+ day: next.getUTCDate()
233
+ };
234
+ }
235
+ function daysInMonth(year, month) {
236
+ return new Date(Date.UTC(year, month, 0)).getUTCDate();
237
+ }
238
+ function parseLocalDate(value) {
239
+ const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
240
+ if (!match) return;
241
+ const year = Number(match[1]);
242
+ const month = Number(match[2]);
243
+ const day = Number(match[3]);
244
+ if (!Number.isInteger(year) || !Number.isInteger(month) || !Number.isInteger(day) || month < 1 || month > 12 || day < 1 || day > daysInMonth(year, month)) return;
245
+ return {
246
+ year,
247
+ month,
248
+ day
249
+ };
250
+ }
251
+ function getLocalDate(timestampMs, timezone) {
252
+ const parts = getZonedDateTimeParts(timestampMs, timezone);
253
+ return {
254
+ year: parts.year,
255
+ month: parts.month,
256
+ day: parts.day
257
+ };
258
+ }
259
+ function normalizeWeekdays(values) {
260
+ return [...new Set((values ?? []).filter((value) => value >= 0 && value <= 6))].sort((a, b) => a - b);
261
+ }
262
+ function buildCandidate(args) {
263
+ return localDateTimeToTimestampMs({
264
+ date: args.date,
265
+ time: args.recurrence.time,
266
+ timezone: args.timezone
267
+ });
268
+ }
269
+ /** Return the next fire time after a completed run, when the task recurs. */
270
+ function getNextRunAtMs(task, scheduledForMs, afterMs = scheduledForMs) {
271
+ if (task.schedule.kind !== "recurring") return;
272
+ const recurrence = task.schedule.recurrence;
273
+ if (!recurrence || !Number.isFinite(recurrence.interval) || recurrence.interval <= 0) return;
274
+ const timezone = task.schedule.timezone;
275
+ const afterDate = getLocalDate(afterMs, timezone);
276
+ const nextScheduledDate = addDays(getLocalDate(scheduledForMs, timezone), 1);
277
+ return findNextRunAtMs({
278
+ afterMs,
279
+ recurrence,
280
+ searchFrom: compareDate(afterDate, nextScheduledDate) < 0 ? nextScheduledDate : afterDate,
281
+ timezone
282
+ });
283
+ }
284
+ //#endregion
285
+ //#region src/chat/scheduled-automations/schedule-intent.ts
286
+ /**
287
+ * Owns model-facing schedule intent and materializes it against the trusted
288
+ * server clock into the canonical schedule persisted by core.
289
+ */
290
+ const localDateSchema = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Use a local date in YYYY-MM-DD format.");
291
+ const localTimeSchema = z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "Use local time in HH:MM format.");
292
+ const timezoneSchema = z.string().min(1).max(80).describe("IANA timezone, for example America/Los_Angeles. Omit or use null for the scheduler default.").nullable().optional();
293
+ const weekdaySchema = z.enum([
294
+ "sunday",
295
+ "monday",
296
+ "tuesday",
297
+ "wednesday",
298
+ "thursday",
299
+ "friday",
300
+ "saturday"
301
+ ]);
302
+ const oneOffScheduleIntentSchema = z.object({
303
+ kind: z.literal("one_off").describe("A schedule that runs once."),
304
+ timezone: timezoneSchema,
305
+ timing: z.discriminatedUnion("type", [z.object({
306
+ type: z.literal("after").describe("Run after a relative delay from the server clock."),
307
+ value: z.number().int().positive().max(1e5),
308
+ unit: z.enum([
309
+ "second",
310
+ "minute",
311
+ "hour",
312
+ "day",
313
+ "week"
314
+ ])
315
+ }).strict(), z.object({
316
+ type: z.literal("at").describe("Run at an explicit local calendar date and time."),
317
+ date: localDateSchema.describe("Requested local calendar date in YYYY-MM-DD format."),
318
+ time: localTimeSchema.describe("Requested local wall-clock time in HH:MM format.")
319
+ }).strict()]).describe("Relative delay or explicit local time for the one-off run.")
320
+ }).strict();
321
+ const recurringScheduleIntentSchema = z.object({
322
+ kind: z.literal("recurring").describe("A repeating calendar schedule."),
323
+ frequency: z.enum([
324
+ "daily",
325
+ "weekly",
326
+ "monthly",
327
+ "yearly"
328
+ ]).describe("Recurring tasks can run at most once per day."),
329
+ interval: z.number().int().positive().max(365).describe("Repeat every N frequency units. Defaults to 1.").nullable().optional(),
330
+ time: localTimeSchema.describe("Local wall-clock time for each occurrence in HH:MM format."),
331
+ weekdays: z.array(weekdaySchema).min(1).max(7).describe("Required for weekly schedules.").nullable().optional(),
332
+ dayOfMonth: z.number().int().min(1).max(31).describe("Required for monthly and yearly schedules.").nullable().optional(),
333
+ month: z.number().int().min(1).max(12).describe("Required for yearly schedules, where January is 1.").nullable().optional(),
334
+ startDate: localDateSchema.describe("Optional local calendar date that anchors the recurrence. Omit to start with the next matching occurrence.").nullable().optional(),
335
+ timezone: timezoneSchema
336
+ }).strict().superRefine((schedule, context) => {
337
+ if (schedule.frequency === "weekly" && schedule.weekdays == null) context.addIssue({
338
+ code: "custom",
339
+ message: "Weekly schedules require weekdays.",
340
+ path: ["weekdays"]
341
+ });
342
+ if ((schedule.frequency === "monthly" || schedule.frequency === "yearly") && schedule.dayOfMonth == null) context.addIssue({
343
+ code: "custom",
344
+ message: `${schedule.frequency} schedules require dayOfMonth.`,
345
+ path: ["dayOfMonth"]
346
+ });
347
+ if (schedule.frequency === "yearly" && schedule.month == null) context.addIssue({
348
+ code: "custom",
349
+ message: "Yearly schedules require month.",
350
+ path: ["month"]
351
+ });
352
+ if (schedule.frequency !== "weekly" && schedule.weekdays != null) context.addIssue({
353
+ code: "custom",
354
+ message: "weekdays applies only to weekly schedules.",
355
+ path: ["weekdays"]
356
+ });
357
+ if (schedule.frequency !== "monthly" && schedule.frequency !== "yearly" && schedule.dayOfMonth != null) context.addIssue({
358
+ code: "custom",
359
+ message: "dayOfMonth applies only to monthly or yearly schedules.",
360
+ path: ["dayOfMonth"]
361
+ });
362
+ if (schedule.frequency !== "yearly" && schedule.month != null) context.addIssue({
363
+ code: "custom",
364
+ message: "month applies only to yearly schedules.",
365
+ path: ["month"]
366
+ });
367
+ });
368
+ const scheduleIntentSchema = z.union([oneOffScheduleIntentSchema, recurringScheduleIntentSchema]);
369
+ const WEEKDAY_INDEX = {
370
+ sunday: 0,
371
+ monday: 1,
372
+ tuesday: 2,
373
+ wednesday: 3,
374
+ thursday: 4,
375
+ friday: 5,
376
+ saturday: 6
377
+ };
378
+ const DURATION_MS = {
379
+ second: 1e3,
380
+ minute: 6e4,
381
+ hour: 36e5,
382
+ day: 864e5,
383
+ week: 6048e5
384
+ };
385
+ function parseLocalTime(value) {
386
+ const [hour, minute] = value.split(":").map(Number);
387
+ return {
388
+ hour,
389
+ minute
390
+ };
391
+ }
392
+ function localDateAt(timestampMs, timezone) {
393
+ const parts = getZonedDateTimeParts(timestampMs, timezone);
394
+ return [
395
+ parts.year,
396
+ parts.month,
397
+ parts.day
398
+ ].map((value, index) => index === 0 ? String(value).padStart(4, "0") : String(value).padStart(2, "0")).join("-");
399
+ }
400
+ function isValidTimeZone(timezone) {
401
+ try {
402
+ new Intl.DateTimeFormat("en-US", { timeZone: timezone }).format();
403
+ return true;
404
+ } catch {
405
+ return false;
406
+ }
407
+ }
408
+ function plural(value, unit) {
409
+ return value === 1 ? unit : `${unit}s`;
410
+ }
411
+ function formatWeekdays(weekdays) {
412
+ const labels = weekdays.map((weekday) => `${weekday[0].toUpperCase()}${weekday.slice(1)}`);
413
+ if (labels.length < 2) return labels[0] ?? "";
414
+ return `${labels.slice(0, -1).join(", ")} and ${labels.at(-1)}`;
415
+ }
416
+ function recurringDescription(schedule, timezone) {
417
+ const interval = schedule.interval ?? 1;
418
+ const cadenceUnit = {
419
+ daily: "day",
420
+ weekly: "week",
421
+ monthly: "month",
422
+ yearly: "year"
423
+ }[schedule.frequency];
424
+ const cadence = interval === 1 ? cadenceUnit : `${interval} ${cadenceUnit}s`;
425
+ let detail = "";
426
+ if (schedule.frequency === "weekly") detail = ` on ${formatWeekdays(schedule.weekdays)}`;
427
+ else if (schedule.frequency === "monthly") detail = ` on day ${schedule.dayOfMonth}`;
428
+ else if (schedule.frequency === "yearly") detail = ` on ${String(schedule.month).padStart(2, "0")}-${String(schedule.dayOfMonth).padStart(2, "0")}`;
429
+ return `Every ${cadence}${detail} at ${schedule.time} (${timezone})`;
430
+ }
431
+ var ScheduleIntentError = class extends Error {};
432
+ /** Materialize model-interpreted schedule intent against the trusted server clock. */
433
+ function compileScheduleIntent(args) {
434
+ const timezone = args.intent.timezone ?? args.defaultTimezone;
435
+ if (!isValidTimeZone(timezone)) throw new ScheduleIntentError("timezone must be a valid IANA time zone.");
436
+ if (args.intent.kind === "one_off") {
437
+ if (args.intent.timing.type === "after") return {
438
+ nextRunAtMs: args.nowMs + args.intent.timing.value * DURATION_MS[args.intent.timing.unit],
439
+ schedule: {
440
+ description: `In ${args.intent.timing.value} ${plural(args.intent.timing.value, args.intent.timing.unit)}`,
441
+ kind: "one_off",
442
+ timezone
443
+ }
444
+ };
445
+ const nextRunAtMs = resolveLocalScheduleAtMs({
446
+ date: args.intent.timing.date,
447
+ time: parseLocalTime(args.intent.timing.time),
448
+ timezone
449
+ });
450
+ if (nextRunAtMs === void 0) throw new ScheduleIntentError("The requested local date or time does not exist in that timezone.");
451
+ if (nextRunAtMs <= args.nowMs) throw new ScheduleIntentError("The requested one-off schedule must be in the future.");
452
+ return {
453
+ nextRunAtMs,
454
+ schedule: {
455
+ description: `Once on ${args.intent.timing.date} at ${args.intent.timing.time} (${timezone})`,
456
+ kind: "one_off",
457
+ timezone
458
+ }
459
+ };
460
+ }
461
+ const recurrence = {
462
+ frequency: args.intent.frequency,
463
+ interval: args.intent.interval ?? 1,
464
+ startDate: args.intent.startDate ?? localDateAt(args.nowMs, timezone),
465
+ time: parseLocalTime(args.intent.time),
466
+ ...args.intent.frequency === "weekly" ? { weekdays: [...new Set(args.intent.weekdays.map((weekday) => WEEKDAY_INDEX[weekday]))].sort((left, right) => left - right) } : void 0,
467
+ ...args.intent.frequency === "monthly" || args.intent.frequency === "yearly" ? { dayOfMonth: args.intent.dayOfMonth ?? void 0 } : void 0,
468
+ ...args.intent.frequency === "yearly" ? { month: args.intent.month ?? void 0 } : void 0
469
+ };
470
+ const searchRecurrence = args.intent.startDate ? recurrence : {
471
+ ...recurrence,
472
+ interval: 1
473
+ };
474
+ const nextRunAtMs = getFirstRunAtMs({
475
+ afterMs: args.nowMs,
476
+ recurrence: searchRecurrence,
477
+ timezone
478
+ });
479
+ if (nextRunAtMs === void 0) throw new ScheduleIntentError("The recurring schedule has no valid future occurrence.");
480
+ const materializedRecurrence = args.intent.startDate ? recurrence : {
481
+ ...recurrence,
482
+ startDate: localDateAt(nextRunAtMs, timezone)
483
+ };
484
+ return {
485
+ nextRunAtMs,
486
+ schedule: {
487
+ description: recurringDescription(args.intent, timezone),
488
+ kind: "recurring",
489
+ recurrence: materializedRecurrence,
490
+ timezone
491
+ }
492
+ };
493
+ }
494
+ //#endregion
495
+ //#region src/chat/automations/edit-schema.ts
496
+ const automationTitleSchema = z.string().trim().min(1).max(60);
497
+ const automationInstructionSchema = z.string().trim().min(1).max(4e3);
498
+ const automationEditFieldsSchema = z.object({
499
+ title: automationTitleSchema.optional(),
500
+ instruction: automationInstructionSchema.optional(),
501
+ credentialMode: z.enum(["system", "creator"]).optional(),
502
+ outcomes: z.array(z.union([taskOutcomeInputSchema, taskOutcomeSchema])).max(5).optional()
503
+ });
504
+ const scheduledAutomationEditSchema = automationEditFieldsSchema.extend({
505
+ schedule: scheduleIntentSchema.optional(),
506
+ status: z.enum(["active", "blocked"]).optional()
507
+ }).strict();
508
+ const eventAutomationEditSchema = automationEditFieldsSchema.extend({ trigger: eventAutomationTriggerSchema.extend({
509
+ identifier: z.string().trim().min(1).max(300),
510
+ label: z.string().trim().min(1).max(500)
511
+ }).optional() }).strict();
512
+ //#endregion
513
+ //#region src/chat/scheduled-automations/types.ts
514
+ /** Durable scheduled-automation domain types owned by Junior core. */
515
+ const scheduledAutomationStatusSchema = z.enum([
516
+ "active",
517
+ "blocked",
518
+ "paused",
519
+ "completed",
520
+ "deleted"
521
+ ]);
522
+ const scheduledAutomationCredentialModeSchema = z.enum(["system", "creator"]);
523
+ const scheduledRunStatusSchema = z.enum([
524
+ "pending",
525
+ "running",
526
+ "completed",
527
+ "failed",
528
+ "blocked",
529
+ "skipped"
530
+ ]);
531
+ const scheduledAutomationPrincipalSchema = z.object({
532
+ slackUserId: actorUserIdSchema,
533
+ fullName: z.string().optional(),
534
+ userName: z.string().optional()
535
+ }).strict();
536
+ const scheduledAutomationRecurrenceSchema = z.object({
537
+ dayOfMonth: z.number().optional(),
538
+ frequency: z.enum([
539
+ "daily",
540
+ "weekly",
541
+ "monthly",
542
+ "yearly"
543
+ ]),
544
+ interval: z.number(),
545
+ month: z.number().optional(),
546
+ startDate: z.string(),
547
+ time: z.object({
548
+ hour: z.number(),
549
+ minute: z.number()
550
+ }).strict(),
551
+ weekdays: z.array(z.number()).optional()
552
+ }).strict();
553
+ const scheduledAutomationScheduleSchema = z.object({
554
+ description: z.string(),
555
+ kind: z.enum(["one_off", "recurring"]),
556
+ recurrence: scheduledAutomationRecurrenceSchema.optional(),
557
+ timezone: z.string()
558
+ }).strict();
559
+ const scheduledAutomationExecutionActorSchema = z.object({
560
+ platform: z.literal("system"),
561
+ name: z.string()
562
+ }).strict();
563
+ /** Scheduled automations target a Slack conversation, never one message thread. */
564
+ const scheduledAutomationDestinationSchema = slackDestinationSchema.omit({ threadTs: true });
565
+ const scheduledAutomationOutcomeSchema = z.object({
566
+ action: z.literal("send_message"),
567
+ destination: scheduledAutomationDestinationSchema
568
+ }).strict();
569
+ /** Validate the current scheduled-automation domain shape. */
570
+ const scheduledAutomationSchema = z.object({
571
+ id: z.string(),
572
+ conversationAccess: z.object({
573
+ audience: z.enum([
574
+ "direct",
575
+ "group",
576
+ "channel"
577
+ ]),
578
+ visibility: z.enum(["private", "public"])
579
+ }).strict(),
580
+ createdAtMs: z.number(),
581
+ createdBy: scheduledAutomationPrincipalSchema,
582
+ /** Authoritative provider identity that created the task. */
583
+ creatorIdentityId: z.string(),
584
+ /** Selects system credentials or task-bound creator credential delegation. */
585
+ credentialMode: scheduledAutomationCredentialModeSchema,
586
+ destination: scheduledAutomationDestinationSchema,
587
+ executionActor: scheduledAutomationExecutionActorSchema.optional(),
588
+ lastRunAtMs: z.number().optional(),
589
+ nextRunAtMs: z.number().optional(),
590
+ originalRequest: z.string().optional(),
591
+ runNowAtMs: z.number().optional(),
592
+ schedule: scheduledAutomationScheduleSchema,
593
+ status: scheduledAutomationStatusSchema,
594
+ statusReason: z.string().optional(),
595
+ /** Explicit visible effects after successful work. An empty list is silent. */
596
+ outcomes: z.array(scheduledAutomationOutcomeSchema).max(5),
597
+ task: z.object({ text: z.string() }).strict(),
598
+ /** SQL-backed short display title generated from the task instruction. */
599
+ title: z.string().optional(),
600
+ updatedAtMs: z.number()
601
+ }).strict();
602
+ /** Validate the current scheduled-run domain shape. */
603
+ const scheduledRunSchema = z.object({
604
+ id: z.string(),
605
+ attempt: z.number(),
606
+ claimedAtMs: z.number(),
607
+ completedAtMs: z.number().optional(),
608
+ dispatchId: z.string().optional(),
609
+ errorMessage: z.string().optional(),
610
+ resultMessageTs: z.string().optional(),
611
+ scheduledForMs: z.number(),
612
+ startedAtMs: z.number().optional(),
613
+ status: scheduledRunStatusSchema,
614
+ taskId: z.string()
615
+ }).strict();
616
+ const SCHEDULED_AUTOMATION_SYSTEM_ACTOR = Object.freeze({
617
+ platform: "system",
618
+ name: "scheduled-automation"
619
+ });
620
+ //#endregion
621
+ export { automationTitleSchema as a, ScheduleIntentError as c, getFirstRunAtMs as d, getNextRunAtMs as f, taskOutcomeInputSchema as g, eventAutomationTriggerSchema as h, automationInstructionSchema as i, compileScheduleIntent as l, eventAutomationSchema as m, scheduledAutomationSchema as n, eventAutomationEditSchema as o, getZonedDateTimeParts as p, scheduledRunSchema as r, scheduledAutomationEditSchema as s, SCHEDULED_AUTOMATION_SYSTEM_ACTOR as t, scheduleIntentSchema as u };
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
2
- import { n as pluginCatalogRuntime } from "./catalog-runtime-xFtmw3oA.js";
2
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-B9u_3-GW.js";
3
3
  import { isDeepStrictEqual } from "node:util";
4
4
  //#region src/chat/plugins/validation.ts
5
5
  var validation_exports = /* @__PURE__ */ __exportAll({
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.233.0";
2
+ var version = "0.235.0";
3
3
  //#endregion
4
4
  //#region src/version.ts
5
5
  /** Installed Junior package version, or `unknown` when package metadata is unavailable. */
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- import { t as JUNIOR_VERSION } from "./version-B2rspCmP.js";
1
+ import { t as JUNIOR_VERSION } from "./version-9CB4Z-J4.js";
2
2
  export { JUNIOR_VERSION };
@@ -1,9 +1,9 @@
1
- import { Ht as requestConversationWork, Mt as ensureConversationWake } from "./agent-runner-BKOtZjez.js";
2
- import { Zt as getConversationEventStore } from "./agent-hooks-DATy_Hnt.js";
3
- import { n as loadTurnCheckpoint, o as failTurnRecord, s as getTurnRecord } from "./checkpoint-zkEB448J.js";
4
- import { w as getStateAdapter } from "./profile-C4_njQYA.js";
5
- import { a as getVercelConversationWorkQueue } from "./job-queue-C5JaRRcE.js";
6
- import { n as resolveTurnSessionRouting } from "./turn-session-routing-B2hNxu_N.js";
1
+ import { It as ensureConversationWake, Kt as requestConversationWork } from "./agent-runner-BlDI1zV2.js";
2
+ import { Qt as getConversationEventStore } from "./agent-hooks-DS7k0ZWY.js";
3
+ import { n as loadTurnCheckpoint, o as failTurnRecord, s as getTurnRecord } from "./checkpoint-DLcJ5mKL.js";
4
+ import { w as getStateAdapter } from "./profile-DZ2DUdd1.js";
5
+ import { a as getVercelConversationWorkQueue } from "./job-queue-CY1L2YRn.js";
6
+ import { n as resolveTurnSessionRouting } from "./turn-session-routing-Dg8GDgyc.js";
7
7
  import { z } from "zod";
8
8
  import { randomUUID } from "node:crypto";
9
9
  //#region src/chat/task-execution/authorized-turn.ts