botnote 0.1.23 → 0.1.25

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.
@@ -0,0 +1,381 @@
1
+ import { and, eq, or } from "drizzle-orm";
2
+ import rrulePkg from "rrule";
3
+ import { entities, recurrenceExceptions, recurrenceRules } from "../db/schema.js";
4
+ import { normalizeDueAt } from "./dates.js";
5
+ const { RRule } = rrulePkg;
6
+ const WEEKDAYS = {
7
+ MO: RRule.MO,
8
+ TU: RRule.TU,
9
+ WE: RRule.WE,
10
+ TH: RRule.TH,
11
+ FR: RRule.FR,
12
+ SA: RRule.SA,
13
+ SU: RRule.SU
14
+ };
15
+ const FREQUENCIES = {
16
+ hourly: RRule.HOURLY,
17
+ daily: RRule.DAILY,
18
+ weekly: RRule.WEEKLY,
19
+ monthly: RRule.MONTHLY,
20
+ yearly: RRule.YEARLY
21
+ };
22
+ function metadataObject(value) {
23
+ if (!value || typeof value !== "object" || Array.isArray(value))
24
+ return {};
25
+ return { ...value };
26
+ }
27
+ function recurrenceMarker(e) {
28
+ const metadata = metadataObject(e.metadata);
29
+ if (!metadata.recurrence || typeof metadata.recurrence !== "object")
30
+ return null;
31
+ return metadata.recurrence;
32
+ }
33
+ function withRecurrenceMetadata(e, marker) {
34
+ return {
35
+ ...metadataObject(e.metadata),
36
+ recurrence: marker
37
+ };
38
+ }
39
+ function normalizeRRuleText(raw) {
40
+ const lines = raw
41
+ .split(/\r?\n/)
42
+ .map((line) => line.trim())
43
+ .filter(Boolean);
44
+ const rruleLine = lines.find((line) => line.toUpperCase().startsWith("RRULE:")) ?? lines[0];
45
+ if (!rruleLine)
46
+ throw new Error("recurrence rule is empty");
47
+ return rruleLine.replace(/^RRULE:/i, "");
48
+ }
49
+ function rruleLine(rule) {
50
+ const line = rule
51
+ .toString()
52
+ .split(/\r?\n/)
53
+ .find((part) => part.startsWith("RRULE:"));
54
+ if (!line)
55
+ throw new Error("rrule did not produce an RRULE line");
56
+ return line.slice("RRULE:".length);
57
+ }
58
+ function buildRRuleFromInput(input, dtstart) {
59
+ if (input.rrule)
60
+ return normalizeRRuleText(input.rrule);
61
+ if (!input.preset)
62
+ throw new Error("recurrence preset is required");
63
+ const options = {
64
+ freq: FREQUENCIES[input.preset],
65
+ interval: input.interval,
66
+ dtstart
67
+ };
68
+ if (input.byWeekday?.length) {
69
+ options.byweekday = input.byWeekday.map((day) => WEEKDAYS[day]);
70
+ }
71
+ if (input.byMonthDay?.length)
72
+ options.bymonthday = input.byMonthDay;
73
+ if (input.bySetPos != null)
74
+ options.bysetpos = input.bySetPos;
75
+ if (input.byMonth?.length)
76
+ options.bymonth = input.byMonth;
77
+ if (input.until)
78
+ options.until = input.until;
79
+ if (input.count)
80
+ options.count = input.count;
81
+ return rruleLine(new RRule(options));
82
+ }
83
+ function buildRRule(rule, dtstart = rule.dtstart) {
84
+ const parsed = RRule.parseString(rule.rrule);
85
+ return new RRule({ ...parsed, dtstart });
86
+ }
87
+ function maxDate(a, b) {
88
+ return a.getTime() >= b.getTime() ? a : b;
89
+ }
90
+ function countLimit(rule) {
91
+ return buildRRule(rule).options.count ?? null;
92
+ }
93
+ function computeNextOccurrenceAt(rule, occurrence, completedAt) {
94
+ const count = countLimit(rule);
95
+ if (count != null && rule.generatedCount >= count)
96
+ return null;
97
+ const anchor = rule.anchor === "completion" ? "completion" : "scheduled";
98
+ const dtstart = anchor === "completion" ? completedAt : rule.dtstart;
99
+ const rrule = buildRRule(rule, dtstart);
100
+ const scheduledBase = occurrence.dueAt ?? rule.dtstart;
101
+ const cursor = anchor === "completion" ? completedAt : maxDate(scheduledBase, completedAt);
102
+ const next = rrule.after(cursor, false);
103
+ return next ? normalizeDueAt(next) : null;
104
+ }
105
+ async function fetchEntity(db, id) {
106
+ const rows = await db.select().from(entities).where(eq(entities.id, id)).limit(1);
107
+ const row = rows[0];
108
+ if (!row)
109
+ throw new Error(`entity ${id} not found`);
110
+ return row;
111
+ }
112
+ async function findRuleForTask(db, task, includeDisabled = true) {
113
+ const marker = recurrenceMarker(task);
114
+ const cond = marker?.ruleId
115
+ ? eq(recurrenceRules.id, marker.ruleId)
116
+ : or(eq(recurrenceRules.currentOccurrenceId, task.id), eq(recurrenceRules.seriesId, task.id));
117
+ const where = includeDisabled ? cond : and(cond, eq(recurrenceRules.enabled, true));
118
+ const rows = await db.select().from(recurrenceRules).where(where).limit(1);
119
+ return rows[0] ?? null;
120
+ }
121
+ export async function getRecurrenceForTask(db, taskId) {
122
+ const task = await fetchEntity(db, taskId);
123
+ const rule = await findRuleForTask(db, task);
124
+ if (!rule)
125
+ return null;
126
+ const currentOccurrence = rule.currentOccurrenceId
127
+ ? await fetchEntity(db, rule.currentOccurrenceId).catch(() => null)
128
+ : null;
129
+ return { rule, currentOccurrence };
130
+ }
131
+ export async function createRecurrenceRule(db, taskId, input) {
132
+ const task = await fetchEntity(db, taskId);
133
+ if (task.kind !== "task")
134
+ throw new Error("recurrence can only be attached to tasks");
135
+ if (!task.dueAt)
136
+ throw new Error("recurring tasks require a first due date");
137
+ if (task.status === "done" || task.status === "rejected") {
138
+ throw new Error("recurrence cannot be attached to a terminal task");
139
+ }
140
+ const existingRule = await findRuleForTask(db, task);
141
+ const seriesId = existingRule?.seriesId ?? recurrenceMarker(task)?.seriesId ?? task.id;
142
+ const dtstart = input.dtstart ? normalizeDueAt(input.dtstart) : task.dueAt;
143
+ const rrule = buildRRuleFromInput(input, dtstart);
144
+ const nextOccurrenceAt = buildRRule({ rrule, dtstart }).after(dtstart, false);
145
+ let rule;
146
+ if (existingRule) {
147
+ const [updated] = await db
148
+ .update(recurrenceRules)
149
+ .set({
150
+ currentOccurrenceId: task.id,
151
+ enabled: true,
152
+ rrule,
153
+ dtstart,
154
+ timezone: input.timezone,
155
+ allDay: input.allDay,
156
+ anchor: input.anchor,
157
+ maxInstancesAhead: 1,
158
+ nextOccurrenceAt: nextOccurrenceAt ? normalizeDueAt(nextOccurrenceAt) : null,
159
+ endedAt: null
160
+ })
161
+ .where(eq(recurrenceRules.id, existingRule.id))
162
+ .returning();
163
+ if (!updated)
164
+ throw new Error(`recurrence rule ${existingRule.id} not found`);
165
+ rule = updated;
166
+ }
167
+ else {
168
+ const [inserted] = await db
169
+ .insert(recurrenceRules)
170
+ .values({
171
+ seriesId,
172
+ currentOccurrenceId: task.id,
173
+ enabled: true,
174
+ rrule,
175
+ dtstart,
176
+ timezone: input.timezone,
177
+ allDay: input.allDay,
178
+ anchor: input.anchor,
179
+ maxInstancesAhead: 1,
180
+ generatedCount: 1,
181
+ lastOccurrenceAt: null,
182
+ nextOccurrenceAt: nextOccurrenceAt ? normalizeDueAt(nextOccurrenceAt) : null,
183
+ endedAt: null
184
+ })
185
+ .returning();
186
+ if (!inserted)
187
+ throw new Error("recurrence rule insert returned no row");
188
+ rule = inserted;
189
+ }
190
+ await db
191
+ .update(entities)
192
+ .set({
193
+ metadata: withRecurrenceMetadata(task, {
194
+ ruleId: rule.id,
195
+ seriesId: rule.seriesId,
196
+ role: "occurrence",
197
+ occurrenceAt: (task.dueAt ?? rule.dtstart).toISOString(),
198
+ occurrenceIndex: 1
199
+ })
200
+ })
201
+ .where(eq(entities.id, task.id));
202
+ return rule;
203
+ }
204
+ export async function updateRecurrenceRule(db, ruleId, input) {
205
+ const rows = await db.select().from(recurrenceRules).where(eq(recurrenceRules.id, ruleId)).limit(1);
206
+ const current = rows[0];
207
+ if (!current)
208
+ throw new Error(`recurrence rule ${ruleId} not found`);
209
+ const currentOccurrence = current.currentOccurrenceId
210
+ ? await fetchEntity(db, current.currentOccurrenceId)
211
+ : null;
212
+ const dtstart = input.dtstart
213
+ ? normalizeDueAt(input.dtstart)
214
+ : currentOccurrence?.dueAt ?? current.dtstart;
215
+ const nextRRuleInput = {
216
+ rrule: input.rrule ?? current.rrule,
217
+ preset: input.preset,
218
+ interval: input.interval ?? 1,
219
+ byWeekday: input.byWeekday,
220
+ byMonthDay: input.byMonthDay,
221
+ bySetPos: input.bySetPos,
222
+ byMonth: input.byMonth,
223
+ until: input.until,
224
+ count: input.count,
225
+ dtstart,
226
+ timezone: input.timezone ?? current.timezone,
227
+ allDay: input.allDay ?? current.allDay,
228
+ anchor: input.anchor ?? (current.anchor === "completion" ? "completion" : "scheduled")
229
+ };
230
+ const rrule = input.rrule || input.preset ? buildRRuleFromInput(nextRRuleInput, dtstart) : current.rrule;
231
+ const nextOccurrenceAt = buildRRule({ rrule, dtstart }).after(dtstart, false);
232
+ const [updated] = await db
233
+ .update(recurrenceRules)
234
+ .set({
235
+ enabled: input.enabled ?? current.enabled,
236
+ rrule,
237
+ dtstart,
238
+ timezone: input.timezone ?? current.timezone,
239
+ allDay: input.allDay ?? current.allDay,
240
+ anchor: input.anchor ?? current.anchor,
241
+ nextOccurrenceAt: nextOccurrenceAt ? normalizeDueAt(nextOccurrenceAt) : null,
242
+ endedAt: input.enabled === true ? null : current.endedAt
243
+ })
244
+ .where(eq(recurrenceRules.id, ruleId))
245
+ .returning();
246
+ if (!updated)
247
+ throw new Error(`recurrence rule ${ruleId} not found`);
248
+ return updated;
249
+ }
250
+ async function insertNextOccurrence(db, rule, occurrence, nextDueAt) {
251
+ const occurrenceIndex = rule.generatedCount + 1;
252
+ const idempotencyKey = `recurrence:${rule.id}:${nextDueAt.toISOString()}`;
253
+ const metadata = {
254
+ ...metadataObject(occurrence.metadata),
255
+ recurrence: {
256
+ ruleId: rule.id,
257
+ seriesId: rule.seriesId,
258
+ role: "occurrence",
259
+ occurrenceAt: nextDueAt.toISOString(),
260
+ occurrenceIndex
261
+ }
262
+ };
263
+ const values = {
264
+ kind: "task",
265
+ projectId: occurrence.projectId,
266
+ title: occurrence.title,
267
+ body: occurrence.body,
268
+ tags: occurrence.tags,
269
+ status: "open",
270
+ parentId: occurrence.parentId,
271
+ actorKind: "system",
272
+ metadata,
273
+ dueAt: nextDueAt,
274
+ priority: occurrence.priority,
275
+ pinned: false,
276
+ completedAt: null,
277
+ idempotencyKey
278
+ };
279
+ const inserted = await db
280
+ .insert(entities)
281
+ .values(values)
282
+ .onConflictDoNothing()
283
+ .returning();
284
+ if (inserted[0])
285
+ return inserted[0];
286
+ const rows = await db.select().from(entities).where(eq(entities.idempotencyKey, idempotencyKey));
287
+ const existing = rows[0];
288
+ if (!existing)
289
+ throw new Error("recurrence idempotent insert returned no row");
290
+ return existing;
291
+ }
292
+ async function advanceRuleFromOccurrence(db, rule, occurrence, completedAt) {
293
+ if (!rule.enabled)
294
+ return null;
295
+ const nextDueAt = computeNextOccurrenceAt(rule, occurrence, completedAt);
296
+ if (!nextDueAt) {
297
+ await db
298
+ .update(recurrenceRules)
299
+ .set({
300
+ enabled: false,
301
+ currentOccurrenceId: null,
302
+ lastOccurrenceAt: occurrence.dueAt ?? rule.dtstart,
303
+ nextOccurrenceAt: null,
304
+ endedAt: completedAt
305
+ })
306
+ .where(eq(recurrenceRules.id, rule.id));
307
+ return null;
308
+ }
309
+ const next = await insertNextOccurrence(db, rule, occurrence, nextDueAt);
310
+ await db
311
+ .update(recurrenceRules)
312
+ .set({
313
+ currentOccurrenceId: next.id,
314
+ generatedCount: Math.max(rule.generatedCount + 1, rule.generatedCount),
315
+ lastOccurrenceAt: occurrence.dueAt ?? rule.dtstart,
316
+ nextOccurrenceAt: nextDueAt
317
+ })
318
+ .where(eq(recurrenceRules.id, rule.id));
319
+ return next;
320
+ }
321
+ export async function advanceRecurrenceOnCompletion(db, occurrence, completedAt = occurrence.completedAt ?? new Date()) {
322
+ if (occurrence.kind !== "task")
323
+ return null;
324
+ const rule = await findRuleForTask(db, occurrence, false);
325
+ if (!rule)
326
+ return null;
327
+ if (rule.currentOccurrenceId && rule.currentOccurrenceId !== occurrence.id)
328
+ return null;
329
+ return advanceRuleFromOccurrence(db, rule, occurrence, completedAt);
330
+ }
331
+ export async function skipOccurrence(db, taskId, input = {}) {
332
+ const task = await fetchEntity(db, taskId);
333
+ if (task.kind !== "task")
334
+ throw new Error("only tasks can be skipped");
335
+ const rule = await findRuleForTask(db, task, false);
336
+ if (!rule)
337
+ throw new Error("task is not an active recurring occurrence");
338
+ if (rule.currentOccurrenceId && rule.currentOccurrenceId !== task.id) {
339
+ throw new Error("only the current recurring occurrence can be skipped");
340
+ }
341
+ await db.insert(recurrenceExceptions).values({
342
+ ruleId: rule.id,
343
+ occurrenceAt: task.dueAt ?? rule.dtstart,
344
+ action: "skipped",
345
+ entityId: task.id,
346
+ metadata: { reason: input.reason ?? null, actorKind: input.actorKind ?? "human" }
347
+ });
348
+ const [skipped] = await db
349
+ .update(entities)
350
+ .set({
351
+ status: "rejected",
352
+ updatedAt: new Date(),
353
+ metadata: {
354
+ ...metadataObject(task.metadata),
355
+ recurrence: recurrenceMarker(task),
356
+ skippedAt: new Date().toISOString(),
357
+ skipReason: input.reason ?? null
358
+ }
359
+ })
360
+ .where(eq(entities.id, task.id))
361
+ .returning();
362
+ if (!skipped)
363
+ throw new Error(`entity ${task.id} not found`);
364
+ const next = await advanceRuleFromOccurrence(db, rule, skipped, new Date());
365
+ return { skipped, next, rule };
366
+ }
367
+ export async function stopRecurrence(db, ruleId, _input = {}) {
368
+ const [updated] = await db
369
+ .update(recurrenceRules)
370
+ .set({
371
+ enabled: false,
372
+ nextOccurrenceAt: null,
373
+ endedAt: new Date()
374
+ })
375
+ .where(eq(recurrenceRules.id, ruleId))
376
+ .returning();
377
+ if (!updated)
378
+ throw new Error(`recurrence rule ${ruleId} not found`);
379
+ return updated;
380
+ }
381
+ //# sourceMappingURL=recurrence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recurrence.js","sourceRoot":"","sources":["../../src/service/recurrence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,QAAQ,MAAM,OAAO,CAAC;AAE7B,OAAO,EACL,QAAQ,EACR,oBAAoB,EACpB,eAAe,EAGhB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;AAK3B,MAAM,QAAQ,GAAwC;IACpD,EAAE,EAAE,KAAK,CAAC,EAAE;IACZ,EAAE,EAAE,KAAK,CAAC,EAAE;IACZ,EAAE,EAAE,KAAK,CAAC,EAAE;IACZ,EAAE,EAAE,KAAK,CAAC,EAAE;IACZ,EAAE,EAAE,KAAK,CAAC,EAAE;IACZ,EAAE,EAAE,KAAK,CAAC,EAAE;IACZ,EAAE,EAAE,KAAK,CAAC,EAAE;CACb,CAAC;AAEF,MAAM,WAAW,GAA8B;IAC7C,MAAM,EAAE,KAAK,CAAC,MAAM;IACpB,KAAK,EAAE,KAAK,CAAC,KAAK;IAClB,MAAM,EAAE,KAAK,CAAC,MAAM;IACpB,OAAO,EAAE,KAAK,CAAC,OAAO;IACtB,MAAM,EAAE,KAAK,CAAC,MAAM;CACrB,CAAC;AAmBF,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC3E,OAAO,EAAE,GAAI,KAAiC,EAAE,CAAC;AACnD,CAAC;AAED,SAAS,gBAAgB,CAAC,CAAS;IACjC,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAuB,CAAC;IAClE,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,OAAO,QAAQ,CAAC,UAAU,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACjF,OAAO,QAAQ,CAAC,UAAU,CAAC;AAC7B,CAAC;AAED,SAAS,sBAAsB,CAC7B,CAAS,EACT,MAAwB;IAExB,OAAO;QACL,GAAG,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC7B,UAAU,EAAE,MAAM;KACnB,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAW;IACrC,MAAM,KAAK,GAAG,GAAG;SACd,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5F,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC5D,OAAO,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,SAAS,CAAC,IAAgC;IACjD,MAAM,IAAI,GAAG,IAAI;SACd,QAAQ,EAAE;SACV,KAAK,CAAC,OAAO,CAAC;SACd,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7C,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAClE,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAsB,EAAE,OAAa;IAChE,IAAI,KAAK,CAAC,KAAK;QAAE,OAAO,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxD,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAEpE,MAAM,OAAO,GAA2C;QACtD,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC;QAC/B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO;KACR,CAAC;IACF,IAAI,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;QAC5B,OAAO,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,EAAE,MAAM;QAAE,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;IACpE,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI;QAAE,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC9D,IAAI,KAAK,CAAC,OAAO,EAAE,MAAM;QAAE,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC3D,IAAI,KAAK,CAAC,KAAK;QAAE,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC7C,IAAI,KAAK,CAAC,KAAK;QAAE,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAE7C,OAAO,SAAS,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,UAAU,CAAC,IAA+C,EAAE,OAAO,GAAG,IAAI,CAAC,OAAO;IACzF,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7C,OAAO,IAAI,KAAK,CAAC,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,OAAO,CAAC,CAAO,EAAE,CAAO;IAC/B,OAAO,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,UAAU,CAAC,IAAoB;IACtC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC;AAChD,CAAC;AAED,SAAS,uBAAuB,CAC9B,IAAoB,EACpB,UAAkB,EAClB,WAAiB;IAEjB,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC,cAAc,IAAI,KAAK;QAAE,OAAO,IAAI,CAAC;IAE/D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC;IACzE,MAAM,OAAO,GAAG,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;IACrE,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,aAAa,GAAG,UAAU,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC;IACvD,MAAM,MAAM,GAAG,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IAC3F,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACxC,OAAO,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5C,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,EAAkB,EAAE,EAAU;IACvD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClF,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IACpD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,EAAkB,EAClB,IAAY,EACZ,eAAe,GAAG,IAAI;IAEtB,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,MAAM,EAAE,MAAM;QACzB,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC;QACvC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,mBAAmB,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,CAAE,CAAC;IACjG,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IACpF,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3E,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,EAAkB,EAClB,MAAc;IAEd,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC7C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,iBAAiB,GAAG,IAAI,CAAC,mBAAmB;QAChD,CAAC,CAAC,MAAM,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,mBAAmB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;QACnE,CAAC,CAAC,IAAI,CAAC;IACT,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,EAAkB,EAClB,MAAc,EACd,KAAsB;IAEtB,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAC3C,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACtF,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC7E,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,YAAY,EAAE,QAAQ,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,QAAQ,IAAI,IAAI,CAAC,EAAE,CAAC;IACvF,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IAC5E,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAClD,MAAM,gBAAgB,GAAG,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAE9E,IAAI,IAAoB,CAAC;IACzB,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE;aACvB,MAAM,CAAC,eAAe,CAAC;aACvB,GAAG,CAAC;YACH,mBAAmB,EAAE,IAAI,CAAC,EAAE;YAC5B,OAAO,EAAE,IAAI;YACb,KAAK;YACL,OAAO;YACP,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,iBAAiB,EAAE,CAAC;YACpB,gBAAgB,EAAE,gBAAgB,CAAC,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI;YAC5E,OAAO,EAAE,IAAI;SACd,CAAC;aACD,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;aAC9C,SAAS,EAAE,CAAC;QACf,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,YAAY,CAAC,EAAE,YAAY,CAAC,CAAC;QAC9E,IAAI,GAAG,OAAO,CAAC;IACjB,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE;aACxB,MAAM,CAAC,eAAe,CAAC;aACvB,MAAM,CAAC;YACN,QAAQ;YACR,mBAAmB,EAAE,IAAI,CAAC,EAAE;YAC5B,OAAO,EAAE,IAAI;YACb,KAAK;YACL,OAAO;YACP,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,iBAAiB,EAAE,CAAC;YACpB,cAAc,EAAE,CAAC;YACjB,gBAAgB,EAAE,IAAI;YACtB,gBAAgB,EAAE,gBAAgB,CAAC,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI;YAC5E,OAAO,EAAE,IAAI;SACd,CAAC;aACD,SAAS,EAAE,CAAC;QACf,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QACzE,IAAI,GAAG,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,EAAE;SACL,MAAM,CAAC,QAAQ,CAAC;SAChB,GAAG,CAAC;QACH,QAAQ,EAAE,sBAAsB,CAAC,IAAI,EAAE;YACrC,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,YAAY;YAClB,YAAY,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE;YACxD,eAAe,EAAE,CAAC;SACnB,CAAC;KACH,CAAC;SACD,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAEnC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,EAAkB,EAClB,MAAc,EACd,KAA4B;IAE5B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACpG,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,YAAY,CAAC,CAAC;IACrE,MAAM,iBAAiB,GAAG,OAAO,CAAC,mBAAmB;QACnD,CAAC,CAAC,MAAM,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,mBAAmB,CAAC;QACpD,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO;QAC3B,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,CAAE;QAChC,CAAC,CAAC,iBAAiB,EAAE,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAChD,MAAM,cAAc,GAAoB;QACtC,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK;QACnC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,CAAC;QAC7B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO;QACP,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ;QAC5C,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM;QACtC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC;KACvF,CAAC;IACF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IACzG,MAAM,gBAAgB,GAAG,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAE9E,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE;SACvB,MAAM,CAAC,eAAe,CAAC;SACvB,GAAG,CAAC;QACH,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO;QACzC,KAAK;QACL,OAAO;QACP,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ;QAC5C,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM;QACtC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM;QACtC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI;QAC5E,OAAO,EAAE,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;KACzD,CAAC;SACD,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;SACrC,SAAS,EAAE,CAAC;IACf,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,YAAY,CAAC,CAAC;IACrE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,oBAAoB,CACjC,EAAkB,EAClB,IAAoB,EACpB,UAAkB,EAClB,SAAe;IAEf,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;IAChD,MAAM,cAAc,GAAG,cAAc,IAAI,CAAC,EAAE,IAAI,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;IAC1E,MAAM,QAAQ,GAAG;QACf,GAAG,cAAc,CAAC,UAAU,CAAC,QAAQ,CAAC;QACtC,UAAU,EAAE;YACV,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,YAAY;YAClB,YAAY,EAAE,SAAS,CAAC,WAAW,EAAE;YACrC,eAAe;SACW;KAC7B,CAAC;IAEF,MAAM,MAAM,GAAG;QACb,IAAI,EAAE,MAAM;QACZ,SAAS,EAAE,UAAU,CAAC,SAAS;QAC/B,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,UAAU,CAAC,QAAQ;QAC7B,SAAS,EAAE,QAAQ;QACnB,QAAQ;QACR,KAAK,EAAE,SAAS;QAChB,QAAQ,EAAE,UAAU,CAAC,QAAQ;QAC7B,MAAM,EAAE,KAAK;QACb,WAAW,EAAE,IAAI;QACjB,cAAc;KACf,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,EAAE;SACtB,MAAM,CAAC,QAAQ,CAAC;SAChB,MAAM,CAAC,MAAM,CAAC;SACd,mBAAmB,EAAE;SACrB,SAAS,EAAE,CAAC;IACf,IAAI,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC;IACjG,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAC/E,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,yBAAyB,CACtC,EAAkB,EAClB,IAAoB,EACpB,UAAkB,EAClB,WAAiB;IAEjB,IAAI,CAAC,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,SAAS,GAAG,uBAAuB,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IACzE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,EAAE;aACL,MAAM,CAAC,eAAe,CAAC;aACvB,GAAG,CAAC;YACH,OAAO,EAAE,KAAK;YACd,mBAAmB,EAAE,IAAI;YACzB,gBAAgB,EAAE,UAAU,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO;YAClD,gBAAgB,EAAE,IAAI;YACtB,OAAO,EAAE,WAAW;SACrB,CAAC;aACD,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,oBAAoB,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IACzE,MAAM,EAAE;SACL,MAAM,CAAC,eAAe,CAAC;SACvB,GAAG,CAAC;QACH,mBAAmB,EAAE,IAAI,CAAC,EAAE;QAC5B,cAAc,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC;QACtE,gBAAgB,EAAE,UAAU,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO;QAClD,gBAAgB,EAAE,SAAS;KAC5B,CAAC;SACD,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,EAAkB,EAClB,UAAkB,EAClB,WAAW,GAAG,UAAU,CAAC,WAAW,IAAI,IAAI,IAAI,EAAE;IAElD,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAC5C,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,IAAI,IAAI,CAAC,mBAAmB,IAAI,IAAI,CAAC,mBAAmB,KAAK,UAAU,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IACxF,OAAO,yBAAyB,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,EAAkB,EAClB,MAAc,EACd,QAAiD,EAAE;IAEnD,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAC3C,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACpD,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IACzE,IAAI,IAAI,CAAC,mBAAmB,IAAI,IAAI,CAAC,mBAAmB,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,MAAM,CAAC;QAC3C,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,YAAY,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO;QACxC,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,IAAI,CAAC,EAAE;QACjB,QAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,OAAO,EAAE;KAClF,CAAC,CAAC;IAEH,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE;SACvB,MAAM,CAAC,QAAQ,CAAC;SAChB,GAAG,CAAC;QACH,MAAM,EAAE,UAAU;QAClB,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,QAAQ,EAAE;YACR,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;YAChC,UAAU,EAAE,gBAAgB,CAAC,IAAI,CAAC;YAClC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;SACjC;KACF,CAAC;SACD,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;SAC/B,SAAS,EAAE,CAAC;IACf,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;IAE7D,MAAM,IAAI,GAAG,MAAM,yBAAyB,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;IAC5E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,EAAkB,EAClB,MAAc,EACd,SAA8B,EAAE;IAEhC,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE;SACvB,MAAM,CAAC,eAAe,CAAC;SACvB,GAAG,CAAC;QACH,OAAO,EAAE,KAAK;QACd,gBAAgB,EAAE,IAAI;QACtB,OAAO,EAAE,IAAI,IAAI,EAAE;KACpB,CAAC;SACD,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;SACrC,SAAS,EAAE,CAAC;IACf,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,YAAY,CAAC,CAAC;IACrE,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -3,6 +3,9 @@ export declare const EntityKindEnum: z.ZodEnum<["task", "note"]>;
3
3
  export declare const ActorKindEnum: z.ZodEnum<["human", "agent", "system"]>;
4
4
  export declare const EdgeKindEnum: z.ZodEnum<["blocks", "references", "parent_of"]>;
5
5
  export declare const PriorityEnum: z.ZodEnum<["urgent", "high", "medium", "low", "none"]>;
6
+ export declare const RecurrenceAnchorEnum: z.ZodEnum<["scheduled", "completion"]>;
7
+ export declare const RecurrenceFrequencyEnum: z.ZodEnum<["hourly", "daily", "weekly", "monthly", "yearly"]>;
8
+ export declare const WeekdayEnum: z.ZodEnum<["MO", "TU", "WE", "TH", "FR", "SA", "SU"]>;
6
9
  export declare const CanonicalTaskStatusEnum: z.ZodEnum<["open", "in_progress", "done", "rejected"]>;
7
10
  export declare const TaskStatusEnum: z.ZodEffects<z.ZodEnum<["open", "in_progress", "done", "rejected"]>, "open" | "in_progress" | "done" | "rejected", unknown>;
8
11
  export declare const Uuid: z.ZodString;
@@ -169,6 +172,173 @@ export declare const UpdateInput: z.ZodObject<{
169
172
  pinned?: boolean | undefined;
170
173
  }>;
171
174
  export type UpdateInput = z.infer<typeof UpdateInput>;
175
+ export declare const RecurrenceInput: z.ZodEffects<z.ZodEffects<z.ZodObject<{
176
+ rrule: z.ZodOptional<z.ZodString>;
177
+ preset: z.ZodOptional<z.ZodEnum<["hourly", "daily", "weekly", "monthly", "yearly"]>>;
178
+ interval: z.ZodDefault<z.ZodNumber>;
179
+ byWeekday: z.ZodOptional<z.ZodArray<z.ZodEnum<["MO", "TU", "WE", "TH", "FR", "SA", "SU"]>, "many">>;
180
+ byMonthDay: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
181
+ bySetPos: z.ZodOptional<z.ZodNumber>;
182
+ byMonth: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
183
+ until: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
184
+ count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
185
+ dtstart: z.ZodOptional<z.ZodDate>;
186
+ timezone: z.ZodDefault<z.ZodString>;
187
+ allDay: z.ZodDefault<z.ZodBoolean>;
188
+ anchor: z.ZodDefault<z.ZodEnum<["scheduled", "completion"]>>;
189
+ }, "strip", z.ZodTypeAny, {
190
+ anchor: "scheduled" | "completion";
191
+ interval: number;
192
+ timezone: string;
193
+ allDay: boolean;
194
+ rrule?: string | undefined;
195
+ dtstart?: Date | undefined;
196
+ preset?: "hourly" | "daily" | "weekly" | "monthly" | "yearly" | undefined;
197
+ byWeekday?: ("MO" | "TU" | "WE" | "TH" | "FR" | "SA" | "SU")[] | undefined;
198
+ byMonthDay?: number[] | undefined;
199
+ byMonth?: number[] | undefined;
200
+ until?: Date | null | undefined;
201
+ count?: number | null | undefined;
202
+ bySetPos?: number | undefined;
203
+ }, {
204
+ anchor?: "scheduled" | "completion" | undefined;
205
+ rrule?: string | undefined;
206
+ dtstart?: Date | undefined;
207
+ preset?: "hourly" | "daily" | "weekly" | "monthly" | "yearly" | undefined;
208
+ interval?: number | undefined;
209
+ byWeekday?: ("MO" | "TU" | "WE" | "TH" | "FR" | "SA" | "SU")[] | undefined;
210
+ byMonthDay?: number[] | undefined;
211
+ byMonth?: number[] | undefined;
212
+ until?: Date | null | undefined;
213
+ count?: number | null | undefined;
214
+ timezone?: string | undefined;
215
+ allDay?: boolean | undefined;
216
+ bySetPos?: number | undefined;
217
+ }>, {
218
+ anchor: "scheduled" | "completion";
219
+ interval: number;
220
+ timezone: string;
221
+ allDay: boolean;
222
+ rrule?: string | undefined;
223
+ dtstart?: Date | undefined;
224
+ preset?: "hourly" | "daily" | "weekly" | "monthly" | "yearly" | undefined;
225
+ byWeekday?: ("MO" | "TU" | "WE" | "TH" | "FR" | "SA" | "SU")[] | undefined;
226
+ byMonthDay?: number[] | undefined;
227
+ byMonth?: number[] | undefined;
228
+ until?: Date | null | undefined;
229
+ count?: number | null | undefined;
230
+ bySetPos?: number | undefined;
231
+ }, {
232
+ anchor?: "scheduled" | "completion" | undefined;
233
+ rrule?: string | undefined;
234
+ dtstart?: Date | undefined;
235
+ preset?: "hourly" | "daily" | "weekly" | "monthly" | "yearly" | undefined;
236
+ interval?: number | undefined;
237
+ byWeekday?: ("MO" | "TU" | "WE" | "TH" | "FR" | "SA" | "SU")[] | undefined;
238
+ byMonthDay?: number[] | undefined;
239
+ byMonth?: number[] | undefined;
240
+ until?: Date | null | undefined;
241
+ count?: number | null | undefined;
242
+ timezone?: string | undefined;
243
+ allDay?: boolean | undefined;
244
+ bySetPos?: number | undefined;
245
+ }>, {
246
+ anchor: "scheduled" | "completion";
247
+ interval: number;
248
+ timezone: string;
249
+ allDay: boolean;
250
+ rrule?: string | undefined;
251
+ dtstart?: Date | undefined;
252
+ preset?: "hourly" | "daily" | "weekly" | "monthly" | "yearly" | undefined;
253
+ byWeekday?: ("MO" | "TU" | "WE" | "TH" | "FR" | "SA" | "SU")[] | undefined;
254
+ byMonthDay?: number[] | undefined;
255
+ byMonth?: number[] | undefined;
256
+ until?: Date | null | undefined;
257
+ count?: number | null | undefined;
258
+ bySetPos?: number | undefined;
259
+ }, {
260
+ anchor?: "scheduled" | "completion" | undefined;
261
+ rrule?: string | undefined;
262
+ dtstart?: Date | undefined;
263
+ preset?: "hourly" | "daily" | "weekly" | "monthly" | "yearly" | undefined;
264
+ interval?: number | undefined;
265
+ byWeekday?: ("MO" | "TU" | "WE" | "TH" | "FR" | "SA" | "SU")[] | undefined;
266
+ byMonthDay?: number[] | undefined;
267
+ byMonth?: number[] | undefined;
268
+ until?: Date | null | undefined;
269
+ count?: number | null | undefined;
270
+ timezone?: string | undefined;
271
+ allDay?: boolean | undefined;
272
+ bySetPos?: number | undefined;
273
+ }>;
274
+ export type RecurrenceInput = z.infer<typeof RecurrenceInput>;
275
+ export declare const UpdateRecurrenceInput: z.ZodObject<{
276
+ rrule: z.ZodOptional<z.ZodOptional<z.ZodString>>;
277
+ preset: z.ZodOptional<z.ZodOptional<z.ZodEnum<["hourly", "daily", "weekly", "monthly", "yearly"]>>>;
278
+ interval: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
279
+ byWeekday: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodEnum<["MO", "TU", "WE", "TH", "FR", "SA", "SU"]>, "many">>>;
280
+ byMonthDay: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>>;
281
+ bySetPos: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
282
+ byMonth: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>>;
283
+ until: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodDate>>>;
284
+ count: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodNumber>>>;
285
+ dtstart: z.ZodOptional<z.ZodOptional<z.ZodDate>>;
286
+ timezone: z.ZodOptional<z.ZodDefault<z.ZodString>>;
287
+ allDay: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
288
+ anchor: z.ZodOptional<z.ZodDefault<z.ZodEnum<["scheduled", "completion"]>>>;
289
+ } & {
290
+ enabled: z.ZodOptional<z.ZodBoolean>;
291
+ }, "strip", z.ZodTypeAny, {
292
+ anchor?: "scheduled" | "completion" | undefined;
293
+ rrule?: string | undefined;
294
+ dtstart?: Date | undefined;
295
+ preset?: "hourly" | "daily" | "weekly" | "monthly" | "yearly" | undefined;
296
+ interval?: number | undefined;
297
+ byWeekday?: ("MO" | "TU" | "WE" | "TH" | "FR" | "SA" | "SU")[] | undefined;
298
+ byMonthDay?: number[] | undefined;
299
+ byMonth?: number[] | undefined;
300
+ until?: Date | null | undefined;
301
+ count?: number | null | undefined;
302
+ timezone?: string | undefined;
303
+ enabled?: boolean | undefined;
304
+ allDay?: boolean | undefined;
305
+ bySetPos?: number | undefined;
306
+ }, {
307
+ anchor?: "scheduled" | "completion" | undefined;
308
+ rrule?: string | undefined;
309
+ dtstart?: Date | undefined;
310
+ preset?: "hourly" | "daily" | "weekly" | "monthly" | "yearly" | undefined;
311
+ interval?: number | undefined;
312
+ byWeekday?: ("MO" | "TU" | "WE" | "TH" | "FR" | "SA" | "SU")[] | undefined;
313
+ byMonthDay?: number[] | undefined;
314
+ byMonth?: number[] | undefined;
315
+ until?: Date | null | undefined;
316
+ count?: number | null | undefined;
317
+ timezone?: string | undefined;
318
+ enabled?: boolean | undefined;
319
+ allDay?: boolean | undefined;
320
+ bySetPos?: number | undefined;
321
+ }>;
322
+ export type UpdateRecurrenceInput = z.infer<typeof UpdateRecurrenceInput>;
323
+ export declare const StopRecurrenceInput: z.ZodObject<{
324
+ reason: z.ZodOptional<z.ZodString>;
325
+ }, "strip", z.ZodTypeAny, {
326
+ reason?: string | undefined;
327
+ }, {
328
+ reason?: string | undefined;
329
+ }>;
330
+ export type StopRecurrenceInput = z.infer<typeof StopRecurrenceInput>;
331
+ export declare const SkipOccurrenceInput: z.ZodObject<{
332
+ reason: z.ZodOptional<z.ZodString>;
333
+ actorKind: z.ZodDefault<z.ZodEnum<["human", "agent", "system"]>>;
334
+ }, "strip", z.ZodTypeAny, {
335
+ actorKind: "human" | "agent" | "system";
336
+ reason?: string | undefined;
337
+ }, {
338
+ reason?: string | undefined;
339
+ actorKind?: "human" | "agent" | "system" | undefined;
340
+ }>;
341
+ export type SkipOccurrenceInput = z.infer<typeof SkipOccurrenceInput>;
172
342
  export declare const SearchInput: z.ZodObject<{
173
343
  query: z.ZodString;
174
344
  projectId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -1,9 +1,12 @@
1
1
  import { z } from "zod";
2
- import { ACTOR_KINDS, EDGE_KINDS, ENTITY_KINDS } from "../db/schema.js";
2
+ import { ACTOR_KINDS, EDGE_KINDS, ENTITY_KINDS, RECURRENCE_ANCHORS } from "../db/schema.js";
3
3
  export const EntityKindEnum = z.enum(ENTITY_KINDS);
4
4
  export const ActorKindEnum = z.enum(ACTOR_KINDS);
5
5
  export const EdgeKindEnum = z.enum(EDGE_KINDS);
6
6
  export const PriorityEnum = z.enum(["urgent", "high", "medium", "low", "none"]);
7
+ export const RecurrenceAnchorEnum = z.enum(RECURRENCE_ANCHORS);
8
+ export const RecurrenceFrequencyEnum = z.enum(["hourly", "daily", "weekly", "monthly", "yearly"]);
9
+ export const WeekdayEnum = z.enum(["MO", "TU", "WE", "TH", "FR", "SA", "SU"]);
7
10
  export const CanonicalTaskStatusEnum = z.enum([
8
11
  "open",
9
12
  "in_progress",
@@ -72,6 +75,39 @@ export const UpdateInput = z.object({
72
75
  priority: PriorityEnum.optional(),
73
76
  pinned: z.boolean().optional()
74
77
  });
78
+ const PositiveInterval = z.number().int().min(1).max(999);
79
+ const RecurrenceFields = z.object({
80
+ rrule: z.string().min(1).max(1000).optional(),
81
+ preset: RecurrenceFrequencyEnum.optional(),
82
+ interval: PositiveInterval.default(1),
83
+ byWeekday: z.array(WeekdayEnum).optional(),
84
+ byMonthDay: z.array(z.number().int().min(1).max(31)).optional(),
85
+ bySetPos: z.number().int().min(-5).max(5).optional(),
86
+ byMonth: z.array(z.number().int().min(1).max(12)).optional(),
87
+ until: z.coerce.date().nullable().optional(),
88
+ count: z.number().int().min(1).max(10000).nullable().optional(),
89
+ dtstart: z.coerce.date().optional(),
90
+ timezone: z.string().min(1).max(80).default("UTC"),
91
+ allDay: z.boolean().default(true),
92
+ anchor: RecurrenceAnchorEnum.default("scheduled")
93
+ });
94
+ export const RecurrenceInput = RecurrenceFields
95
+ .refine((value) => value.rrule || value.preset, {
96
+ message: "Provide either rrule or preset"
97
+ })
98
+ .refine((value) => !(value.until && value.count), {
99
+ message: "Use either until or count, not both"
100
+ });
101
+ export const UpdateRecurrenceInput = RecurrenceFields.partial().extend({
102
+ enabled: z.boolean().optional()
103
+ });
104
+ export const StopRecurrenceInput = z.object({
105
+ reason: z.string().max(500).optional()
106
+ });
107
+ export const SkipOccurrenceInput = z.object({
108
+ reason: z.string().max(500).optional(),
109
+ actorKind: ActorKindEnum.default("human")
110
+ });
75
111
  export const SearchInput = z.object({
76
112
  query: z.string().min(1),
77
113
  projectId: Uuid.nullish(),