forge-openclaw-plugin 0.2.18 → 0.2.19
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/README.md +36 -4
- package/dist/assets/{board-2KevHCI0.js → board-8L3uX7_O.js} +2 -2
- package/dist/assets/{board-2KevHCI0.js.map → board-8L3uX7_O.js.map} +1 -1
- package/dist/assets/index-Cj1IBH_w.js +36 -0
- package/dist/assets/index-Cj1IBH_w.js.map +1 -0
- package/dist/assets/index-DQT6EbuS.css +1 -0
- package/dist/assets/{motion-q19HPmWs.js → motion-1GAqqi8M.js} +2 -2
- package/dist/assets/{motion-q19HPmWs.js.map → motion-1GAqqi8M.js.map} +1 -1
- package/dist/assets/{table-BDMHBY4a.js → table-DBGlgRjk.js} +2 -2
- package/dist/assets/{table-BDMHBY4a.js.map → table-DBGlgRjk.js.map} +1 -1
- package/dist/assets/{ui-CQ_AsFs8.js → ui-iTluWjC4.js} +2 -2
- package/dist/assets/{ui-CQ_AsFs8.js.map → ui-iTluWjC4.js.map} +1 -1
- package/dist/assets/{vendor-5HifrnRK.js → vendor-BvM2F9Dp.js} +139 -84
- package/dist/assets/vendor-BvM2F9Dp.js.map +1 -0
- package/dist/assets/{viz-CQzkRnTu.js → viz-CNeunkfu.js} +2 -2
- package/dist/assets/{viz-CQzkRnTu.js.map → viz-CNeunkfu.js.map} +1 -1
- package/dist/index.html +8 -8
- package/dist/openclaw/parity.js +1 -0
- package/dist/openclaw/routes.js +7 -0
- package/dist/openclaw/tools.js +183 -16
- package/dist/server/app.js +2509 -263
- package/dist/server/managers/platform/secrets-manager.js +44 -1
- package/dist/server/managers/runtime.js +3 -1
- package/dist/server/openapi.js +2037 -172
- package/dist/server/repositories/calendar.js +1101 -0
- package/dist/server/repositories/deleted-entities.js +10 -2
- package/dist/server/repositories/notes.js +161 -28
- package/dist/server/repositories/projects.js +45 -13
- package/dist/server/repositories/rewards.js +114 -6
- package/dist/server/repositories/settings.js +47 -5
- package/dist/server/repositories/task-runs.js +46 -10
- package/dist/server/repositories/tasks.js +25 -9
- package/dist/server/repositories/weekly-reviews.js +109 -0
- package/dist/server/repositories/work-adjustments.js +105 -0
- package/dist/server/services/calendar-runtime.js +1301 -0
- package/dist/server/services/entity-crud.js +94 -3
- package/dist/server/services/projects.js +32 -8
- package/dist/server/services/reviews.js +15 -1
- package/dist/server/services/work-time.js +27 -0
- package/dist/server/types.js +934 -49
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/server/migrations/006_work_adjustments.sql +14 -0
- package/server/migrations/007_weekly_review_closures.sql +17 -0
- package/server/migrations/008_calendar_execution.sql +147 -0
- package/server/migrations/009_true_calendar_events.sql +195 -0
- package/server/migrations/010_calendar_selection_state.sql +6 -0
- package/server/migrations/011_calendar_timezone_backfill.sql +11 -0
- package/server/migrations/012_work_block_ranges.sql +7 -0
- package/server/migrations/013_microsoft_local_auth_settings.sql +8 -0
- package/server/migrations/014_note_tags_and_ephemeral.sql +8 -0
- package/skills/forge-openclaw/SKILL.md +117 -11
- package/dist/assets/index-CDYW4WDH.js +0 -36
- package/dist/assets/index-CDYW4WDH.js.map +0 -1
- package/dist/assets/index-yroQr6YZ.css +0 -1
- package/dist/assets/vendor-5HifrnRK.js.map +0 -1
package/dist/server/types.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
export const taskStatusSchema = z.enum([
|
|
2
|
+
export const taskStatusSchema = z.enum([
|
|
3
|
+
"backlog",
|
|
4
|
+
"focus",
|
|
5
|
+
"in_progress",
|
|
6
|
+
"blocked",
|
|
7
|
+
"done"
|
|
8
|
+
]);
|
|
3
9
|
export const taskPrioritySchema = z.enum(["low", "medium", "high", "critical"]);
|
|
4
10
|
export const taskEffortSchema = z.enum(["light", "deep", "marathon"]);
|
|
5
11
|
export const taskEnergySchema = z.enum(["low", "steady", "high"]);
|
|
@@ -8,13 +14,68 @@ export const goalHorizonSchema = z.enum(["quarter", "year", "lifetime"]);
|
|
|
8
14
|
export const projectStatusSchema = z.enum(["active", "paused", "completed"]);
|
|
9
15
|
export const tagKindSchema = z.enum(["value", "category", "execution"]);
|
|
10
16
|
export const taskDueFilterSchema = z.enum(["overdue", "today", "week"]);
|
|
11
|
-
export const taskRunStatusSchema = z.enum([
|
|
17
|
+
export const taskRunStatusSchema = z.enum([
|
|
18
|
+
"active",
|
|
19
|
+
"completed",
|
|
20
|
+
"released",
|
|
21
|
+
"timed_out"
|
|
22
|
+
]);
|
|
12
23
|
export const taskTimerModeSchema = z.enum(["planned", "unlimited"]);
|
|
13
|
-
export const timeAccountingModeSchema = z.enum([
|
|
24
|
+
export const timeAccountingModeSchema = z.enum([
|
|
25
|
+
"split",
|
|
26
|
+
"parallel",
|
|
27
|
+
"primary_only"
|
|
28
|
+
]);
|
|
14
29
|
export const habitFrequencySchema = z.enum(["daily", "weekly"]);
|
|
15
30
|
export const habitPolaritySchema = z.enum(["positive", "negative"]);
|
|
16
31
|
export const habitStatusSchema = z.enum(["active", "paused", "archived"]);
|
|
17
32
|
export const habitCheckInStatusSchema = z.enum(["done", "missed"]);
|
|
33
|
+
export const calendarProviderSchema = z.enum([
|
|
34
|
+
"google",
|
|
35
|
+
"apple",
|
|
36
|
+
"caldav",
|
|
37
|
+
"microsoft"
|
|
38
|
+
]);
|
|
39
|
+
export const calendarConnectionStatusSchema = z.enum([
|
|
40
|
+
"connected",
|
|
41
|
+
"needs_attention",
|
|
42
|
+
"error"
|
|
43
|
+
]);
|
|
44
|
+
export const calendarOwnershipSchema = z.enum(["external", "forge"]);
|
|
45
|
+
export const calendarEventOriginSchema = z.enum([
|
|
46
|
+
"native",
|
|
47
|
+
"google",
|
|
48
|
+
"apple",
|
|
49
|
+
"caldav",
|
|
50
|
+
"microsoft",
|
|
51
|
+
"derived"
|
|
52
|
+
]);
|
|
53
|
+
export const calendarAvailabilitySchema = z.enum(["busy", "free"]);
|
|
54
|
+
export const calendarEventStatusSchema = z.enum([
|
|
55
|
+
"confirmed",
|
|
56
|
+
"tentative",
|
|
57
|
+
"cancelled"
|
|
58
|
+
]);
|
|
59
|
+
export const workBlockKindSchema = z.enum([
|
|
60
|
+
"main_activity",
|
|
61
|
+
"secondary_activity",
|
|
62
|
+
"third_activity",
|
|
63
|
+
"rest",
|
|
64
|
+
"holiday",
|
|
65
|
+
"custom"
|
|
66
|
+
]);
|
|
67
|
+
export const calendarTimeboxStatusSchema = z.enum([
|
|
68
|
+
"planned",
|
|
69
|
+
"active",
|
|
70
|
+
"completed",
|
|
71
|
+
"cancelled"
|
|
72
|
+
]);
|
|
73
|
+
export const calendarTimeboxSourceSchema = z.enum([
|
|
74
|
+
"manual",
|
|
75
|
+
"suggested",
|
|
76
|
+
"live_run"
|
|
77
|
+
]);
|
|
78
|
+
export const workAdjustmentEntityTypeSchema = z.enum(["task", "project"]);
|
|
18
79
|
export const activityEntityTypeSchema = z.enum([
|
|
19
80
|
"task",
|
|
20
81
|
"habit",
|
|
@@ -38,19 +99,69 @@ export const activityEntityTypeSchema = z.enum([
|
|
|
38
99
|
"approval_request",
|
|
39
100
|
"agent_action",
|
|
40
101
|
"reward",
|
|
41
|
-
"session"
|
|
102
|
+
"session",
|
|
103
|
+
"calendar_connection",
|
|
104
|
+
"calendar",
|
|
105
|
+
"calendar_event",
|
|
106
|
+
"work_block",
|
|
107
|
+
"work_block_template",
|
|
108
|
+
"task_timebox"
|
|
109
|
+
]);
|
|
110
|
+
export const activitySourceSchema = z.enum([
|
|
111
|
+
"ui",
|
|
112
|
+
"openclaw",
|
|
113
|
+
"agent",
|
|
114
|
+
"system"
|
|
115
|
+
]);
|
|
116
|
+
export const agentTrustLevelSchema = z.enum([
|
|
117
|
+
"standard",
|
|
118
|
+
"trusted",
|
|
119
|
+
"autonomous"
|
|
120
|
+
]);
|
|
121
|
+
export const autonomyModeSchema = z.enum([
|
|
122
|
+
"approval_required",
|
|
123
|
+
"scoped_write",
|
|
124
|
+
"autonomous"
|
|
125
|
+
]);
|
|
126
|
+
export const approvalModeSchema = z.enum([
|
|
127
|
+
"approval_by_default",
|
|
128
|
+
"high_impact_only",
|
|
129
|
+
"none"
|
|
42
130
|
]);
|
|
43
|
-
export const activitySourceSchema = z.enum(["ui", "openclaw", "agent", "system"]);
|
|
44
|
-
export const agentTrustLevelSchema = z.enum(["standard", "trusted", "autonomous"]);
|
|
45
|
-
export const autonomyModeSchema = z.enum(["approval_required", "scoped_write", "autonomous"]);
|
|
46
|
-
export const approvalModeSchema = z.enum(["approval_by_default", "high_impact_only", "none"]);
|
|
47
131
|
export const insightOriginSchema = z.enum(["system", "user", "agent"]);
|
|
48
|
-
export const insightStatusSchema = z.enum([
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
132
|
+
export const insightStatusSchema = z.enum([
|
|
133
|
+
"open",
|
|
134
|
+
"accepted",
|
|
135
|
+
"dismissed",
|
|
136
|
+
"snoozed",
|
|
137
|
+
"applied",
|
|
138
|
+
"expired"
|
|
139
|
+
]);
|
|
140
|
+
export const insightVisibilitySchema = z.enum([
|
|
141
|
+
"visible",
|
|
142
|
+
"pending_review",
|
|
143
|
+
"archived"
|
|
144
|
+
]);
|
|
145
|
+
export const insightFeedbackTypeSchema = z.enum([
|
|
146
|
+
"accepted",
|
|
147
|
+
"dismissed",
|
|
148
|
+
"applied",
|
|
149
|
+
"snoozed"
|
|
150
|
+
]);
|
|
151
|
+
export const approvalRequestStatusSchema = z.enum([
|
|
152
|
+
"pending",
|
|
153
|
+
"approved",
|
|
154
|
+
"rejected",
|
|
155
|
+
"cancelled",
|
|
156
|
+
"executed"
|
|
157
|
+
]);
|
|
52
158
|
export const actionRiskLevelSchema = z.enum(["low", "medium", "high"]);
|
|
53
|
-
export const agentActionStatusSchema = z.enum([
|
|
159
|
+
export const agentActionStatusSchema = z.enum([
|
|
160
|
+
"pending_approval",
|
|
161
|
+
"approved",
|
|
162
|
+
"rejected",
|
|
163
|
+
"executed"
|
|
164
|
+
]);
|
|
54
165
|
export const crudEntityTypeSchema = z.enum([
|
|
55
166
|
"goal",
|
|
56
167
|
"project",
|
|
@@ -59,6 +170,9 @@ export const crudEntityTypeSchema = z.enum([
|
|
|
59
170
|
"tag",
|
|
60
171
|
"note",
|
|
61
172
|
"insight",
|
|
173
|
+
"calendar_event",
|
|
174
|
+
"work_block_template",
|
|
175
|
+
"task_timebox",
|
|
62
176
|
"psyche_value",
|
|
63
177
|
"behavior_pattern",
|
|
64
178
|
"behavior",
|
|
@@ -97,7 +211,12 @@ export const rewardRuleFamilySchema = z.enum([
|
|
|
97
211
|
export const appLocaleSchema = z.enum(["en", "fr"]);
|
|
98
212
|
const trimmedString = z.string().trim();
|
|
99
213
|
const nonEmptyTrimmedString = trimmedString.min(1);
|
|
100
|
-
const rewardConfigValueSchema = z.union([
|
|
214
|
+
const rewardConfigValueSchema = z.union([
|
|
215
|
+
z.string(),
|
|
216
|
+
z.number(),
|
|
217
|
+
z.boolean(),
|
|
218
|
+
z.null()
|
|
219
|
+
]);
|
|
101
220
|
function isValidDateOnly(value) {
|
|
102
221
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
103
222
|
return false;
|
|
@@ -111,9 +230,15 @@ function isValidDateOnly(value) {
|
|
|
111
230
|
candidate.getUTCMonth() === month - 1 &&
|
|
112
231
|
candidate.getUTCDate() === day);
|
|
113
232
|
}
|
|
233
|
+
function isValidDateTime(value) {
|
|
234
|
+
return !Number.isNaN(Date.parse(value));
|
|
235
|
+
}
|
|
114
236
|
const dateOnlySchema = trimmedString.refine(isValidDateOnly, {
|
|
115
237
|
message: "Expected a valid date in YYYY-MM-DD format"
|
|
116
238
|
});
|
|
239
|
+
const dateTimeSchema = trimmedString.refine(isValidDateTime, {
|
|
240
|
+
message: "Expected a valid ISO date-time string"
|
|
241
|
+
});
|
|
117
242
|
const uniqueStringArraySchema = z
|
|
118
243
|
.array(nonEmptyTrimmedString)
|
|
119
244
|
.superRefine((values, context) => {
|
|
@@ -130,6 +255,31 @@ const uniqueStringArraySchema = z
|
|
|
130
255
|
seen.add(value);
|
|
131
256
|
});
|
|
132
257
|
});
|
|
258
|
+
const integerMinuteSchema = z
|
|
259
|
+
.number()
|
|
260
|
+
.int()
|
|
261
|
+
.min(0)
|
|
262
|
+
.max(24 * 60);
|
|
263
|
+
export const calendarSchedulingRulesSchema = z.object({
|
|
264
|
+
allowWorkBlockKinds: z.array(workBlockKindSchema).default([]),
|
|
265
|
+
blockWorkBlockKinds: z.array(workBlockKindSchema).default([]),
|
|
266
|
+
allowCalendarIds: uniqueStringArraySchema.default([]),
|
|
267
|
+
blockCalendarIds: uniqueStringArraySchema.default([]),
|
|
268
|
+
allowEventTypes: uniqueStringArraySchema.default([]),
|
|
269
|
+
blockEventTypes: uniqueStringArraySchema.default([]),
|
|
270
|
+
allowEventKeywords: uniqueStringArraySchema.default([]),
|
|
271
|
+
blockEventKeywords: uniqueStringArraySchema.default([]),
|
|
272
|
+
allowAvailability: z.array(calendarAvailabilitySchema).default([]),
|
|
273
|
+
blockAvailability: z.array(calendarAvailabilitySchema).default([])
|
|
274
|
+
});
|
|
275
|
+
export const calendarContextConflictSchema = z.object({
|
|
276
|
+
kind: z.enum(["external_event", "work_block"]),
|
|
277
|
+
id: z.string(),
|
|
278
|
+
title: z.string(),
|
|
279
|
+
reason: z.string(),
|
|
280
|
+
startsAt: z.string(),
|
|
281
|
+
endsAt: z.string()
|
|
282
|
+
});
|
|
133
283
|
export const tagSchema = z.object({
|
|
134
284
|
id: z.string(),
|
|
135
285
|
name: nonEmptyTrimmedString,
|
|
@@ -140,15 +290,65 @@ export const tagSchema = z.object({
|
|
|
140
290
|
export const taskTimeSummarySchema = z.object({
|
|
141
291
|
totalTrackedSeconds: z.number().int().nonnegative(),
|
|
142
292
|
totalCreditedSeconds: z.number().nonnegative(),
|
|
293
|
+
liveTrackedSeconds: z.number().int().nonnegative().default(0),
|
|
294
|
+
liveCreditedSeconds: z.number().nonnegative().default(0),
|
|
295
|
+
manualAdjustedSeconds: z.number().int().default(0),
|
|
143
296
|
activeRunCount: z.number().int().nonnegative(),
|
|
144
297
|
hasCurrentRun: z.boolean(),
|
|
145
298
|
currentRunId: z.string().nullable()
|
|
146
299
|
});
|
|
300
|
+
export const workAdjustmentSchema = z.object({
|
|
301
|
+
id: z.string(),
|
|
302
|
+
entityType: workAdjustmentEntityTypeSchema,
|
|
303
|
+
entityId: z.string(),
|
|
304
|
+
requestedDeltaMinutes: z
|
|
305
|
+
.number()
|
|
306
|
+
.int()
|
|
307
|
+
.refine((value) => value !== 0, {
|
|
308
|
+
message: "requestedDeltaMinutes must not be zero"
|
|
309
|
+
}),
|
|
310
|
+
appliedDeltaMinutes: z.number().int(),
|
|
311
|
+
note: z.string(),
|
|
312
|
+
actor: z.string().nullable(),
|
|
313
|
+
source: activitySourceSchema,
|
|
314
|
+
createdAt: z.string()
|
|
315
|
+
});
|
|
316
|
+
export const workAdjustmentTargetSummarySchema = z.object({
|
|
317
|
+
entityType: workAdjustmentEntityTypeSchema,
|
|
318
|
+
entityId: z.string(),
|
|
319
|
+
title: z.string(),
|
|
320
|
+
time: taskTimeSummarySchema
|
|
321
|
+
});
|
|
322
|
+
export const workAdjustmentResultSchema = z.object({
|
|
323
|
+
adjustment: workAdjustmentSchema,
|
|
324
|
+
target: workAdjustmentTargetSummarySchema,
|
|
325
|
+
reward: z.lazy(() => rewardLedgerEventSchema).nullable(),
|
|
326
|
+
metrics: z.lazy(() => xpMetricsPayloadSchema)
|
|
327
|
+
});
|
|
147
328
|
export const noteLinkSchema = z.object({
|
|
148
329
|
entityType: crudEntityTypeSchema,
|
|
149
330
|
entityId: nonEmptyTrimmedString,
|
|
150
331
|
anchorKey: trimmedString.nullable().default(null)
|
|
151
332
|
});
|
|
333
|
+
const noteTagSchema = nonEmptyTrimmedString.max(80);
|
|
334
|
+
const uniqueNoteTagArraySchema = z
|
|
335
|
+
.array(noteTagSchema)
|
|
336
|
+
.max(24)
|
|
337
|
+
.superRefine((values, context) => {
|
|
338
|
+
const seen = new Set();
|
|
339
|
+
values.forEach((value, index) => {
|
|
340
|
+
const normalized = value.toLowerCase();
|
|
341
|
+
if (seen.has(normalized)) {
|
|
342
|
+
context.addIssue({
|
|
343
|
+
code: z.ZodIssueCode.custom,
|
|
344
|
+
path: [index],
|
|
345
|
+
message: `Duplicate note tag '${value}' is not allowed`
|
|
346
|
+
});
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
seen.add(normalized);
|
|
350
|
+
});
|
|
351
|
+
});
|
|
152
352
|
export const noteSchema = z.object({
|
|
153
353
|
id: z.string(),
|
|
154
354
|
contentMarkdown: nonEmptyTrimmedString,
|
|
@@ -157,7 +357,9 @@ export const noteSchema = z.object({
|
|
|
157
357
|
source: activitySourceSchema,
|
|
158
358
|
createdAt: z.string(),
|
|
159
359
|
updatedAt: z.string(),
|
|
160
|
-
links: z.array(noteLinkSchema).min(1)
|
|
360
|
+
links: z.array(noteLinkSchema).min(1),
|
|
361
|
+
tags: uniqueNoteTagArraySchema.default([]),
|
|
362
|
+
destroyAt: dateTimeSchema.nullable().default(null)
|
|
161
363
|
});
|
|
162
364
|
export const noteSummarySchema = z.object({
|
|
163
365
|
count: z.number().int().nonnegative(),
|
|
@@ -185,6 +387,18 @@ export const projectSchema = z.object({
|
|
|
185
387
|
status: projectStatusSchema,
|
|
186
388
|
targetPoints: z.number().int().nonnegative(),
|
|
187
389
|
themeColor: z.string(),
|
|
390
|
+
schedulingRules: calendarSchedulingRulesSchema.default({
|
|
391
|
+
allowWorkBlockKinds: [],
|
|
392
|
+
blockWorkBlockKinds: [],
|
|
393
|
+
allowCalendarIds: [],
|
|
394
|
+
blockCalendarIds: [],
|
|
395
|
+
allowEventTypes: [],
|
|
396
|
+
blockEventTypes: [],
|
|
397
|
+
allowEventKeywords: [],
|
|
398
|
+
blockEventKeywords: [],
|
|
399
|
+
allowAvailability: [],
|
|
400
|
+
blockAvailability: []
|
|
401
|
+
}),
|
|
188
402
|
createdAt: z.string(),
|
|
189
403
|
updatedAt: z.string()
|
|
190
404
|
});
|
|
@@ -202,6 +416,14 @@ export const taskSchema = z.object({
|
|
|
202
416
|
energy: taskEnergySchema,
|
|
203
417
|
points: z.number().int().nonnegative(),
|
|
204
418
|
sortOrder: z.number().int().nonnegative(),
|
|
419
|
+
plannedDurationSeconds: z
|
|
420
|
+
.number()
|
|
421
|
+
.int()
|
|
422
|
+
.min(60)
|
|
423
|
+
.max(86_400)
|
|
424
|
+
.nullable()
|
|
425
|
+
.default(null),
|
|
426
|
+
schedulingRules: calendarSchedulingRulesSchema.nullable().default(null),
|
|
205
427
|
completedAt: z.string().nullable(),
|
|
206
428
|
createdAt: z.string(),
|
|
207
429
|
updatedAt: z.string(),
|
|
@@ -209,6 +431,9 @@ export const taskSchema = z.object({
|
|
|
209
431
|
time: taskTimeSummarySchema.default({
|
|
210
432
|
totalTrackedSeconds: 0,
|
|
211
433
|
totalCreditedSeconds: 0,
|
|
434
|
+
liveTrackedSeconds: 0,
|
|
435
|
+
liveCreditedSeconds: 0,
|
|
436
|
+
manualAdjustedSeconds: 0,
|
|
212
437
|
activeRunCount: 0,
|
|
213
438
|
hasCurrentRun: false,
|
|
214
439
|
currentRunId: null
|
|
@@ -235,8 +460,192 @@ export const taskRunSchema = z.object({
|
|
|
235
460
|
completedAt: z.string().nullable(),
|
|
236
461
|
releasedAt: z.string().nullable(),
|
|
237
462
|
timedOutAt: z.string().nullable(),
|
|
463
|
+
overrideReason: trimmedString.nullable().default(null),
|
|
238
464
|
updatedAt: z.string()
|
|
239
465
|
});
|
|
466
|
+
export const calendarConnectionSchema = z.object({
|
|
467
|
+
id: z.string(),
|
|
468
|
+
provider: calendarProviderSchema,
|
|
469
|
+
label: nonEmptyTrimmedString,
|
|
470
|
+
accountLabel: trimmedString,
|
|
471
|
+
status: calendarConnectionStatusSchema,
|
|
472
|
+
config: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()])),
|
|
473
|
+
forgeCalendarId: z.string().nullable(),
|
|
474
|
+
lastSyncedAt: z.string().nullable(),
|
|
475
|
+
lastSyncError: trimmedString.nullable(),
|
|
476
|
+
createdAt: z.string(),
|
|
477
|
+
updatedAt: z.string()
|
|
478
|
+
});
|
|
479
|
+
export const calendarDiscoveryCalendarSchema = z.object({
|
|
480
|
+
url: nonEmptyTrimmedString.url(),
|
|
481
|
+
displayName: nonEmptyTrimmedString,
|
|
482
|
+
description: trimmedString,
|
|
483
|
+
color: z.string(),
|
|
484
|
+
timezone: trimmedString,
|
|
485
|
+
isPrimary: z.boolean(),
|
|
486
|
+
canWrite: z.boolean(),
|
|
487
|
+
selectedByDefault: z.boolean(),
|
|
488
|
+
isForgeCandidate: z.boolean()
|
|
489
|
+
});
|
|
490
|
+
export const calendarDiscoveryPayloadSchema = z.object({
|
|
491
|
+
provider: calendarProviderSchema,
|
|
492
|
+
accountLabel: trimmedString,
|
|
493
|
+
serverUrl: nonEmptyTrimmedString.url(),
|
|
494
|
+
principalUrl: z.string().nullable(),
|
|
495
|
+
homeUrl: z.string().nullable(),
|
|
496
|
+
calendars: z.array(calendarDiscoveryCalendarSchema)
|
|
497
|
+
});
|
|
498
|
+
export const calendarSchema = z.object({
|
|
499
|
+
id: z.string(),
|
|
500
|
+
connectionId: z.string(),
|
|
501
|
+
remoteId: nonEmptyTrimmedString,
|
|
502
|
+
title: nonEmptyTrimmedString,
|
|
503
|
+
description: trimmedString,
|
|
504
|
+
color: z.string(),
|
|
505
|
+
timezone: nonEmptyTrimmedString,
|
|
506
|
+
isPrimary: z.boolean(),
|
|
507
|
+
canWrite: z.boolean(),
|
|
508
|
+
selectedForSync: z.boolean(),
|
|
509
|
+
forgeManaged: z.boolean(),
|
|
510
|
+
lastSyncedAt: z.string().nullable(),
|
|
511
|
+
createdAt: z.string(),
|
|
512
|
+
updatedAt: z.string()
|
|
513
|
+
});
|
|
514
|
+
export const calendarEventSourceSchema = z.object({
|
|
515
|
+
id: z.string(),
|
|
516
|
+
provider: calendarProviderSchema,
|
|
517
|
+
connectionId: z.string().nullable(),
|
|
518
|
+
calendarId: z.string().nullable(),
|
|
519
|
+
remoteCalendarId: trimmedString.nullable(),
|
|
520
|
+
remoteEventId: nonEmptyTrimmedString,
|
|
521
|
+
remoteUid: trimmedString.nullable(),
|
|
522
|
+
recurrenceInstanceId: trimmedString.nullable(),
|
|
523
|
+
isMasterRecurring: z.boolean(),
|
|
524
|
+
remoteHref: trimmedString.nullable(),
|
|
525
|
+
remoteEtag: trimmedString.nullable(),
|
|
526
|
+
syncState: z.enum([
|
|
527
|
+
"pending_create",
|
|
528
|
+
"pending_update",
|
|
529
|
+
"pending_delete",
|
|
530
|
+
"synced",
|
|
531
|
+
"error",
|
|
532
|
+
"deleted"
|
|
533
|
+
]),
|
|
534
|
+
lastSyncedAt: z.string().nullable(),
|
|
535
|
+
createdAt: z.string(),
|
|
536
|
+
updatedAt: z.string()
|
|
537
|
+
});
|
|
538
|
+
export const calendarEventLinkSchema = z.object({
|
|
539
|
+
id: z.string(),
|
|
540
|
+
entityType: crudEntityTypeSchema,
|
|
541
|
+
entityId: nonEmptyTrimmedString,
|
|
542
|
+
relationshipType: nonEmptyTrimmedString.default("context"),
|
|
543
|
+
createdAt: z.string(),
|
|
544
|
+
updatedAt: z.string()
|
|
545
|
+
});
|
|
546
|
+
export const calendarEventSchema = z.object({
|
|
547
|
+
id: z.string(),
|
|
548
|
+
connectionId: z.string().nullable(),
|
|
549
|
+
calendarId: z.string().nullable(),
|
|
550
|
+
remoteId: trimmedString.nullable(),
|
|
551
|
+
ownership: calendarOwnershipSchema,
|
|
552
|
+
originType: calendarEventOriginSchema,
|
|
553
|
+
status: calendarEventStatusSchema,
|
|
554
|
+
title: nonEmptyTrimmedString,
|
|
555
|
+
description: trimmedString,
|
|
556
|
+
location: trimmedString,
|
|
557
|
+
startAt: z.string(),
|
|
558
|
+
endAt: z.string(),
|
|
559
|
+
timezone: nonEmptyTrimmedString,
|
|
560
|
+
isAllDay: z.boolean(),
|
|
561
|
+
availability: calendarAvailabilitySchema,
|
|
562
|
+
eventType: trimmedString,
|
|
563
|
+
categories: z.array(z.string()).default([]),
|
|
564
|
+
sourceMappings: z.array(calendarEventSourceSchema).default([]),
|
|
565
|
+
links: z.array(calendarEventLinkSchema).default([]),
|
|
566
|
+
remoteUpdatedAt: z.string().nullable(),
|
|
567
|
+
deletedAt: z.string().nullable(),
|
|
568
|
+
createdAt: z.string(),
|
|
569
|
+
updatedAt: z.string()
|
|
570
|
+
});
|
|
571
|
+
export const workBlockTemplateSchema = z
|
|
572
|
+
.object({
|
|
573
|
+
id: z.string(),
|
|
574
|
+
title: nonEmptyTrimmedString,
|
|
575
|
+
kind: workBlockKindSchema,
|
|
576
|
+
color: z.string(),
|
|
577
|
+
timezone: nonEmptyTrimmedString,
|
|
578
|
+
weekDays: z.array(z.number().int().min(0).max(6)).min(1).max(7),
|
|
579
|
+
startMinute: integerMinuteSchema,
|
|
580
|
+
endMinute: integerMinuteSchema,
|
|
581
|
+
startsOn: dateOnlySchema.nullable().default(null),
|
|
582
|
+
endsOn: dateOnlySchema.nullable().default(null),
|
|
583
|
+
blockingState: z.enum(["allowed", "blocked"]),
|
|
584
|
+
createdAt: z.string(),
|
|
585
|
+
updatedAt: z.string()
|
|
586
|
+
})
|
|
587
|
+
.superRefine((value, context) => {
|
|
588
|
+
if (value.endMinute <= value.startMinute) {
|
|
589
|
+
context.addIssue({
|
|
590
|
+
code: z.ZodIssueCode.custom,
|
|
591
|
+
path: ["endMinute"],
|
|
592
|
+
message: "endMinute must be greater than startMinute"
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
if (value.startsOn && value.endsOn && value.endsOn < value.startsOn) {
|
|
596
|
+
context.addIssue({
|
|
597
|
+
code: z.ZodIssueCode.custom,
|
|
598
|
+
path: ["endsOn"],
|
|
599
|
+
message: "endsOn must be on or after startsOn"
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
export const workBlockInstanceSchema = z.object({
|
|
604
|
+
id: z.string(),
|
|
605
|
+
templateId: z.string(),
|
|
606
|
+
dateKey: dateOnlySchema,
|
|
607
|
+
startAt: z.string(),
|
|
608
|
+
endAt: z.string(),
|
|
609
|
+
title: nonEmptyTrimmedString,
|
|
610
|
+
kind: workBlockKindSchema,
|
|
611
|
+
color: z.string(),
|
|
612
|
+
blockingState: z.enum(["allowed", "blocked"]),
|
|
613
|
+
calendarEventId: z.string().nullable(),
|
|
614
|
+
createdAt: z.string(),
|
|
615
|
+
updatedAt: z.string()
|
|
616
|
+
});
|
|
617
|
+
export const taskTimeboxSchema = z.object({
|
|
618
|
+
id: z.string(),
|
|
619
|
+
taskId: z.string(),
|
|
620
|
+
projectId: z.string().nullable(),
|
|
621
|
+
connectionId: z.string().nullable(),
|
|
622
|
+
calendarId: z.string().nullable(),
|
|
623
|
+
remoteEventId: z.string().nullable(),
|
|
624
|
+
linkedTaskRunId: z.string().nullable(),
|
|
625
|
+
status: calendarTimeboxStatusSchema,
|
|
626
|
+
source: calendarTimeboxSourceSchema,
|
|
627
|
+
title: nonEmptyTrimmedString,
|
|
628
|
+
startsAt: z.string(),
|
|
629
|
+
endsAt: z.string(),
|
|
630
|
+
overrideReason: trimmedString.nullable(),
|
|
631
|
+
createdAt: z.string(),
|
|
632
|
+
updatedAt: z.string()
|
|
633
|
+
});
|
|
634
|
+
export const calendarOverviewPayloadSchema = z.object({
|
|
635
|
+
generatedAt: z.string(),
|
|
636
|
+
providers: z.array(z.object({
|
|
637
|
+
provider: calendarProviderSchema,
|
|
638
|
+
label: z.string(),
|
|
639
|
+
supportsDedicatedForgeCalendar: z.boolean(),
|
|
640
|
+
connectionHelp: z.string()
|
|
641
|
+
})),
|
|
642
|
+
connections: z.array(calendarConnectionSchema),
|
|
643
|
+
calendars: z.array(calendarSchema),
|
|
644
|
+
events: z.array(calendarEventSchema),
|
|
645
|
+
workBlockTemplates: z.array(workBlockTemplateSchema),
|
|
646
|
+
workBlockInstances: z.array(workBlockInstanceSchema),
|
|
647
|
+
timeboxes: z.array(taskTimeboxSchema)
|
|
648
|
+
});
|
|
240
649
|
export const habitCheckInSchema = z.object({
|
|
241
650
|
id: z.string(),
|
|
242
651
|
habitId: z.string(),
|
|
@@ -308,7 +717,12 @@ export const dashboardStatsSchema = z.object({
|
|
|
308
717
|
overdueTasks: z.number().int().nonnegative(),
|
|
309
718
|
dueThisWeek: z.number().int().nonnegative()
|
|
310
719
|
});
|
|
311
|
-
export const executionBucketToneSchema = z.enum([
|
|
720
|
+
export const executionBucketToneSchema = z.enum([
|
|
721
|
+
"urgent",
|
|
722
|
+
"accent",
|
|
723
|
+
"neutral",
|
|
724
|
+
"success"
|
|
725
|
+
]);
|
|
312
726
|
export const dashboardExecutionBucketSchema = z.object({
|
|
313
727
|
id: z.enum(["overdue", "due_soon", "focus_now", "recently_completed"]),
|
|
314
728
|
label: z.string(),
|
|
@@ -340,7 +754,12 @@ export const gamificationProfileSchema = z.object({
|
|
|
340
754
|
topGoalId: z.string().nullable(),
|
|
341
755
|
topGoalTitle: z.string().nullable()
|
|
342
756
|
});
|
|
343
|
-
export const achievementTierSchema = z.enum([
|
|
757
|
+
export const achievementTierSchema = z.enum([
|
|
758
|
+
"bronze",
|
|
759
|
+
"silver",
|
|
760
|
+
"gold",
|
|
761
|
+
"platinum"
|
|
762
|
+
]);
|
|
344
763
|
export const achievementSignalSchema = z.object({
|
|
345
764
|
id: z.string(),
|
|
346
765
|
title: z.string(),
|
|
@@ -434,7 +853,16 @@ export const todayQuestSchema = z.object({
|
|
|
434
853
|
completed: z.boolean()
|
|
435
854
|
});
|
|
436
855
|
export const todayTimelineBucketSchema = z.object({
|
|
437
|
-
id: z.enum([
|
|
856
|
+
id: z.enum([
|
|
857
|
+
"completed",
|
|
858
|
+
"active",
|
|
859
|
+
"upcoming",
|
|
860
|
+
"deferred",
|
|
861
|
+
"in_progress",
|
|
862
|
+
"ready",
|
|
863
|
+
"blocked",
|
|
864
|
+
"done"
|
|
865
|
+
]),
|
|
438
866
|
label: z.string(),
|
|
439
867
|
tasks: z.array(taskSchema)
|
|
440
868
|
});
|
|
@@ -450,7 +878,9 @@ export const todayContextSchema = z.object({
|
|
|
450
878
|
dueHabits: z.array(habitSchema),
|
|
451
879
|
dailyQuests: z.array(todayQuestSchema),
|
|
452
880
|
milestoneRewards: z.array(milestoneRewardSchema),
|
|
453
|
-
recentHabitRewards: z
|
|
881
|
+
recentHabitRewards: z
|
|
882
|
+
.array(z.lazy(() => rewardLedgerEventSchema))
|
|
883
|
+
.default([]),
|
|
454
884
|
momentum: z.object({
|
|
455
885
|
streakDays: z.number().int().nonnegative(),
|
|
456
886
|
momentumScore: z.number().int().min(0).max(100),
|
|
@@ -539,6 +969,9 @@ export const weeklyReviewCalibrationSchema = z.object({
|
|
|
539
969
|
export const weeklyReviewPayloadSchema = z.object({
|
|
540
970
|
generatedAt: z.string(),
|
|
541
971
|
windowLabel: z.string(),
|
|
972
|
+
weekKey: z.string(),
|
|
973
|
+
weekStartDate: z.string(),
|
|
974
|
+
weekEndDate: z.string(),
|
|
542
975
|
momentumSummary: z.object({
|
|
543
976
|
totalXp: z.number().int().nonnegative(),
|
|
544
977
|
focusHours: z.number().int().nonnegative(),
|
|
@@ -552,8 +985,31 @@ export const weeklyReviewPayloadSchema = z.object({
|
|
|
552
985
|
title: z.string(),
|
|
553
986
|
summary: z.string(),
|
|
554
987
|
rewardXp: z.number().int().nonnegative()
|
|
988
|
+
}),
|
|
989
|
+
completion: z.object({
|
|
990
|
+
finalized: z.boolean(),
|
|
991
|
+
finalizedAt: z.string().nullable(),
|
|
992
|
+
finalizedBy: z.string().nullable()
|
|
555
993
|
})
|
|
556
994
|
});
|
|
995
|
+
export const weeklyReviewClosureSchema = z.object({
|
|
996
|
+
id: z.string(),
|
|
997
|
+
weekKey: z.string(),
|
|
998
|
+
weekStartDate: z.string(),
|
|
999
|
+
weekEndDate: z.string(),
|
|
1000
|
+
windowLabel: z.string(),
|
|
1001
|
+
actor: z.string().nullable(),
|
|
1002
|
+
source: activitySourceSchema,
|
|
1003
|
+
rewardId: z.string(),
|
|
1004
|
+
activityEventId: z.string(),
|
|
1005
|
+
createdAt: z.string()
|
|
1006
|
+
});
|
|
1007
|
+
export const finalizeWeeklyReviewResultSchema = z.object({
|
|
1008
|
+
review: weeklyReviewPayloadSchema,
|
|
1009
|
+
closure: weeklyReviewClosureSchema,
|
|
1010
|
+
reward: z.lazy(() => rewardLedgerEventSchema),
|
|
1011
|
+
metrics: z.lazy(() => xpMetricsPayloadSchema)
|
|
1012
|
+
});
|
|
557
1013
|
export const notificationPreferencesSchema = z.object({
|
|
558
1014
|
goalDriftAlerts: z.boolean(),
|
|
559
1015
|
dailyQuestReminders: z.boolean(),
|
|
@@ -564,6 +1020,17 @@ export const executionSettingsSchema = z.object({
|
|
|
564
1020
|
maxActiveTasks: z.number().int().min(1).max(8),
|
|
565
1021
|
timeAccountingMode: timeAccountingModeSchema
|
|
566
1022
|
});
|
|
1023
|
+
export const microsoftCalendarAuthSettingsSchema = z.object({
|
|
1024
|
+
clientId: z.string(),
|
|
1025
|
+
tenantId: z.string(),
|
|
1026
|
+
redirectUri: z.string(),
|
|
1027
|
+
usesClientSecret: z.literal(false),
|
|
1028
|
+
readOnly: z.literal(true),
|
|
1029
|
+
authMode: z.literal("public_client_pkce"),
|
|
1030
|
+
isConfigured: z.boolean(),
|
|
1031
|
+
isReadyForSignIn: z.boolean(),
|
|
1032
|
+
setupMessage: z.string()
|
|
1033
|
+
});
|
|
567
1034
|
export const agentTokenSummarySchema = z.object({
|
|
568
1035
|
id: z.string(),
|
|
569
1036
|
label: z.string(),
|
|
@@ -746,13 +1213,27 @@ export const updateRewardRuleSchema = z.object({
|
|
|
746
1213
|
export const createManualRewardGrantSchema = z.object({
|
|
747
1214
|
entityType: rewardableEntityTypeSchema,
|
|
748
1215
|
entityId: nonEmptyTrimmedString,
|
|
749
|
-
deltaXp: z
|
|
1216
|
+
deltaXp: z
|
|
1217
|
+
.number()
|
|
1218
|
+
.int()
|
|
1219
|
+
.refine((value) => value !== 0, {
|
|
750
1220
|
message: "deltaXp must not be zero"
|
|
751
1221
|
}),
|
|
752
1222
|
reasonTitle: nonEmptyTrimmedString,
|
|
753
1223
|
reasonSummary: trimmedString.default(""),
|
|
754
1224
|
metadata: z.record(z.string(), rewardConfigValueSchema).default({})
|
|
755
1225
|
});
|
|
1226
|
+
export const createWorkAdjustmentSchema = z.object({
|
|
1227
|
+
entityType: workAdjustmentEntityTypeSchema,
|
|
1228
|
+
entityId: nonEmptyTrimmedString,
|
|
1229
|
+
deltaMinutes: z
|
|
1230
|
+
.number()
|
|
1231
|
+
.int()
|
|
1232
|
+
.refine((value) => value !== 0, {
|
|
1233
|
+
message: "deltaMinutes must not be zero"
|
|
1234
|
+
}),
|
|
1235
|
+
note: trimmedString.default("")
|
|
1236
|
+
});
|
|
756
1237
|
export const settingsPayloadSchema = z.object({
|
|
757
1238
|
profile: z.object({
|
|
758
1239
|
operatorName: z.string(),
|
|
@@ -771,6 +1252,9 @@ export const settingsPayloadSchema = z.object({
|
|
|
771
1252
|
tokenCount: z.number().int().nonnegative(),
|
|
772
1253
|
psycheAuthRequired: z.boolean()
|
|
773
1254
|
}),
|
|
1255
|
+
calendarProviders: z.object({
|
|
1256
|
+
microsoft: microsoftCalendarAuthSettingsSchema
|
|
1257
|
+
}),
|
|
774
1258
|
agents: z.array(agentIdentitySchema),
|
|
775
1259
|
agentTokens: z.array(agentTokenSummarySchema)
|
|
776
1260
|
});
|
|
@@ -796,28 +1280,103 @@ export const createNoteLinkSchema = z.object({
|
|
|
796
1280
|
entityId: nonEmptyTrimmedString,
|
|
797
1281
|
anchorKey: trimmedString.nullable().default(null)
|
|
798
1282
|
});
|
|
1283
|
+
const repeatedTrimmedStringQuerySchema = z.preprocess((value) => {
|
|
1284
|
+
if (value === undefined || value === null || value === "") {
|
|
1285
|
+
return [];
|
|
1286
|
+
}
|
|
1287
|
+
return Array.isArray(value) ? value : [value];
|
|
1288
|
+
}, z.array(trimmedString));
|
|
1289
|
+
const repeatedUnknownQuerySchema = z.preprocess((value) => {
|
|
1290
|
+
if (value === undefined || value === null || value === "") {
|
|
1291
|
+
return [];
|
|
1292
|
+
}
|
|
1293
|
+
return Array.isArray(value) ? value : [value];
|
|
1294
|
+
}, z.array(z.unknown()));
|
|
1295
|
+
const noteLinkedEntityFilterSchema = z.object({
|
|
1296
|
+
entityType: crudEntityTypeSchema,
|
|
1297
|
+
entityId: nonEmptyTrimmedString
|
|
1298
|
+
});
|
|
1299
|
+
function parseLinkedEntityQueryValue(raw) {
|
|
1300
|
+
const separatorIndex = raw.indexOf(":");
|
|
1301
|
+
if (separatorIndex <= 0 || separatorIndex >= raw.length - 1) {
|
|
1302
|
+
throw new Error("Expected linked entity filters in entityType:entityId format");
|
|
1303
|
+
}
|
|
1304
|
+
return {
|
|
1305
|
+
entityType: raw.slice(0, separatorIndex),
|
|
1306
|
+
entityId: raw.slice(separatorIndex + 1)
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
799
1309
|
export const createNoteSchema = z.object({
|
|
800
1310
|
contentMarkdown: nonEmptyTrimmedString,
|
|
801
1311
|
author: trimmedString.nullable().default(null),
|
|
802
|
-
links: z.array(createNoteLinkSchema).min(1)
|
|
1312
|
+
links: z.array(createNoteLinkSchema).min(1),
|
|
1313
|
+
tags: uniqueNoteTagArraySchema.default([]),
|
|
1314
|
+
destroyAt: dateTimeSchema.nullable().default(null)
|
|
803
1315
|
});
|
|
804
1316
|
export const nestedCreateNoteSchema = z.object({
|
|
805
1317
|
contentMarkdown: nonEmptyTrimmedString,
|
|
806
1318
|
author: trimmedString.nullable().default(null),
|
|
807
|
-
links: z.array(createNoteLinkSchema).default([])
|
|
1319
|
+
links: z.array(createNoteLinkSchema).default([]),
|
|
1320
|
+
tags: uniqueNoteTagArraySchema.default([]),
|
|
1321
|
+
destroyAt: dateTimeSchema.nullable().default(null)
|
|
808
1322
|
});
|
|
809
1323
|
export const updateNoteSchema = z.object({
|
|
810
1324
|
contentMarkdown: nonEmptyTrimmedString.optional(),
|
|
811
1325
|
author: trimmedString.nullable().optional(),
|
|
812
|
-
links: z.array(createNoteLinkSchema).min(1).optional()
|
|
1326
|
+
links: z.array(createNoteLinkSchema).min(1).optional(),
|
|
1327
|
+
tags: uniqueNoteTagArraySchema.optional(),
|
|
1328
|
+
destroyAt: dateTimeSchema.nullable().optional()
|
|
813
1329
|
});
|
|
814
|
-
export const notesListQuerySchema = z
|
|
1330
|
+
export const notesListQuerySchema = z
|
|
1331
|
+
.object({
|
|
815
1332
|
linkedEntityType: crudEntityTypeSchema.optional(),
|
|
816
1333
|
linkedEntityId: nonEmptyTrimmedString.optional(),
|
|
817
1334
|
anchorKey: trimmedString.nullable().optional(),
|
|
818
1335
|
author: trimmedString.optional(),
|
|
819
1336
|
query: trimmedString.optional(),
|
|
1337
|
+
linkedTo: repeatedUnknownQuerySchema.transform((values, context) => values.map((value, index) => {
|
|
1338
|
+
try {
|
|
1339
|
+
if (typeof value === "string") {
|
|
1340
|
+
return noteLinkedEntityFilterSchema.parse(parseLinkedEntityQueryValue(value));
|
|
1341
|
+
}
|
|
1342
|
+
return noteLinkedEntityFilterSchema.parse(value);
|
|
1343
|
+
}
|
|
1344
|
+
catch (error) {
|
|
1345
|
+
context.addIssue({
|
|
1346
|
+
code: z.ZodIssueCode.custom,
|
|
1347
|
+
path: ["linkedTo", index],
|
|
1348
|
+
message: error instanceof Error ? error.message : "Invalid linkedTo filter"
|
|
1349
|
+
});
|
|
1350
|
+
return {
|
|
1351
|
+
entityType: "goal",
|
|
1352
|
+
entityId: "__invalid__"
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
})),
|
|
1356
|
+
tags: repeatedTrimmedStringQuerySchema,
|
|
1357
|
+
textTerms: repeatedTrimmedStringQuerySchema,
|
|
1358
|
+
updatedFrom: dateOnlySchema.optional(),
|
|
1359
|
+
updatedTo: dateOnlySchema.optional(),
|
|
820
1360
|
limit: z.coerce.number().int().positive().max(200).optional()
|
|
1361
|
+
})
|
|
1362
|
+
.superRefine((value, context) => {
|
|
1363
|
+
if (value.linkedEntityType !== undefined &&
|
|
1364
|
+
value.linkedEntityId === undefined) {
|
|
1365
|
+
context.addIssue({
|
|
1366
|
+
code: z.ZodIssueCode.custom,
|
|
1367
|
+
path: ["linkedEntityId"],
|
|
1368
|
+
message: "linkedEntityId is required when linkedEntityType is provided"
|
|
1369
|
+
});
|
|
1370
|
+
}
|
|
1371
|
+
if (value.updatedFrom &&
|
|
1372
|
+
value.updatedTo &&
|
|
1373
|
+
value.updatedTo < value.updatedFrom) {
|
|
1374
|
+
context.addIssue({
|
|
1375
|
+
code: z.ZodIssueCode.custom,
|
|
1376
|
+
path: ["updatedTo"],
|
|
1377
|
+
message: "updatedTo must be on or after updatedFrom"
|
|
1378
|
+
});
|
|
1379
|
+
}
|
|
821
1380
|
});
|
|
822
1381
|
export const taskListQuerySchema = z.object({
|
|
823
1382
|
status: taskStatusSchema.optional(),
|
|
@@ -846,6 +1405,254 @@ export const projectListQuerySchema = z.object({
|
|
|
846
1405
|
status: projectStatusSchema.optional(),
|
|
847
1406
|
limit: z.coerce.number().int().positive().max(100).optional()
|
|
848
1407
|
});
|
|
1408
|
+
export const calendarOverviewQuerySchema = z.object({
|
|
1409
|
+
from: z.string().datetime().optional(),
|
|
1410
|
+
to: z.string().datetime().optional()
|
|
1411
|
+
});
|
|
1412
|
+
export const createCalendarConnectionSchema = z.discriminatedUnion("provider", [
|
|
1413
|
+
z.object({
|
|
1414
|
+
provider: z.literal("google"),
|
|
1415
|
+
label: nonEmptyTrimmedString,
|
|
1416
|
+
username: nonEmptyTrimmedString,
|
|
1417
|
+
clientId: nonEmptyTrimmedString,
|
|
1418
|
+
clientSecret: nonEmptyTrimmedString,
|
|
1419
|
+
refreshToken: nonEmptyTrimmedString,
|
|
1420
|
+
selectedCalendarUrls: z.array(nonEmptyTrimmedString.url()).min(1),
|
|
1421
|
+
forgeCalendarUrl: nonEmptyTrimmedString.url().nullable().optional(),
|
|
1422
|
+
createForgeCalendar: z.boolean().optional().default(false)
|
|
1423
|
+
}),
|
|
1424
|
+
z.object({
|
|
1425
|
+
provider: z.literal("apple"),
|
|
1426
|
+
label: nonEmptyTrimmedString,
|
|
1427
|
+
username: nonEmptyTrimmedString,
|
|
1428
|
+
password: nonEmptyTrimmedString,
|
|
1429
|
+
selectedCalendarUrls: z.array(nonEmptyTrimmedString.url()).min(1),
|
|
1430
|
+
forgeCalendarUrl: nonEmptyTrimmedString.url().nullable().optional(),
|
|
1431
|
+
createForgeCalendar: z.boolean().optional().default(false)
|
|
1432
|
+
}),
|
|
1433
|
+
z.object({
|
|
1434
|
+
provider: z.literal("caldav"),
|
|
1435
|
+
label: nonEmptyTrimmedString,
|
|
1436
|
+
serverUrl: nonEmptyTrimmedString.url(),
|
|
1437
|
+
username: nonEmptyTrimmedString,
|
|
1438
|
+
password: nonEmptyTrimmedString,
|
|
1439
|
+
selectedCalendarUrls: z.array(nonEmptyTrimmedString.url()).min(1),
|
|
1440
|
+
forgeCalendarUrl: nonEmptyTrimmedString.url().nullable().optional(),
|
|
1441
|
+
createForgeCalendar: z.boolean().optional().default(false)
|
|
1442
|
+
}),
|
|
1443
|
+
z.object({
|
|
1444
|
+
provider: z.literal("microsoft"),
|
|
1445
|
+
label: nonEmptyTrimmedString,
|
|
1446
|
+
authSessionId: nonEmptyTrimmedString,
|
|
1447
|
+
selectedCalendarUrls: z.array(nonEmptyTrimmedString.url()).min(1)
|
|
1448
|
+
})
|
|
1449
|
+
]);
|
|
1450
|
+
export const discoverCalendarConnectionSchema = z.discriminatedUnion("provider", [
|
|
1451
|
+
z.object({
|
|
1452
|
+
provider: z.literal("google"),
|
|
1453
|
+
username: nonEmptyTrimmedString,
|
|
1454
|
+
clientId: nonEmptyTrimmedString,
|
|
1455
|
+
clientSecret: nonEmptyTrimmedString,
|
|
1456
|
+
refreshToken: nonEmptyTrimmedString
|
|
1457
|
+
}),
|
|
1458
|
+
z.object({
|
|
1459
|
+
provider: z.literal("apple"),
|
|
1460
|
+
username: nonEmptyTrimmedString,
|
|
1461
|
+
password: nonEmptyTrimmedString
|
|
1462
|
+
}),
|
|
1463
|
+
z.object({
|
|
1464
|
+
provider: z.literal("caldav"),
|
|
1465
|
+
serverUrl: nonEmptyTrimmedString.url(),
|
|
1466
|
+
username: nonEmptyTrimmedString,
|
|
1467
|
+
password: nonEmptyTrimmedString
|
|
1468
|
+
})
|
|
1469
|
+
]);
|
|
1470
|
+
export const startMicrosoftCalendarOauthSchema = z.object({
|
|
1471
|
+
label: nonEmptyTrimmedString.optional()
|
|
1472
|
+
});
|
|
1473
|
+
export const testMicrosoftCalendarOauthConfigurationSchema = z.object({
|
|
1474
|
+
clientId: nonEmptyTrimmedString.regex(/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/, "Microsoft client IDs must use the standard app registration GUID format."),
|
|
1475
|
+
tenantId: trimmedString.default("common"),
|
|
1476
|
+
redirectUri: nonEmptyTrimmedString.url()
|
|
1477
|
+
});
|
|
1478
|
+
export const microsoftCalendarOauthSessionSchema = z.object({
|
|
1479
|
+
sessionId: nonEmptyTrimmedString,
|
|
1480
|
+
status: z.enum(["pending", "authorized", "error", "consumed", "expired"]),
|
|
1481
|
+
authUrl: z.string().url().nullable(),
|
|
1482
|
+
accountLabel: z.string().nullable(),
|
|
1483
|
+
error: z.string().nullable(),
|
|
1484
|
+
discovery: calendarDiscoveryPayloadSchema.nullable()
|
|
1485
|
+
});
|
|
1486
|
+
export const updateCalendarConnectionSchema = z.object({
|
|
1487
|
+
label: nonEmptyTrimmedString.optional(),
|
|
1488
|
+
selectedCalendarUrls: z.array(nonEmptyTrimmedString.url()).optional()
|
|
1489
|
+
});
|
|
1490
|
+
const workBlockTemplateMutationShape = {
|
|
1491
|
+
title: nonEmptyTrimmedString,
|
|
1492
|
+
kind: workBlockKindSchema.default("custom"),
|
|
1493
|
+
color: z
|
|
1494
|
+
.string()
|
|
1495
|
+
.regex(/^#[0-9a-fA-F]{6}$/)
|
|
1496
|
+
.default("#60a5fa"),
|
|
1497
|
+
timezone: nonEmptyTrimmedString.default("UTC"),
|
|
1498
|
+
weekDays: z.array(z.number().int().min(0).max(6)).min(1).max(7),
|
|
1499
|
+
startMinute: integerMinuteSchema,
|
|
1500
|
+
endMinute: integerMinuteSchema,
|
|
1501
|
+
startsOn: dateOnlySchema.nullable().optional(),
|
|
1502
|
+
endsOn: dateOnlySchema.nullable().optional(),
|
|
1503
|
+
blockingState: z.enum(["allowed", "blocked"]).default("blocked")
|
|
1504
|
+
};
|
|
1505
|
+
export const createWorkBlockTemplateSchema = z
|
|
1506
|
+
.object(workBlockTemplateMutationShape)
|
|
1507
|
+
.superRefine((value, context) => {
|
|
1508
|
+
if (value.endMinute <= value.startMinute) {
|
|
1509
|
+
context.addIssue({
|
|
1510
|
+
code: z.ZodIssueCode.custom,
|
|
1511
|
+
path: ["endMinute"],
|
|
1512
|
+
message: "endMinute must be greater than startMinute"
|
|
1513
|
+
});
|
|
1514
|
+
}
|
|
1515
|
+
if (value.startsOn && value.endsOn && value.endsOn < value.startsOn) {
|
|
1516
|
+
context.addIssue({
|
|
1517
|
+
code: z.ZodIssueCode.custom,
|
|
1518
|
+
path: ["endsOn"],
|
|
1519
|
+
message: "endsOn must be on or after startsOn"
|
|
1520
|
+
});
|
|
1521
|
+
}
|
|
1522
|
+
});
|
|
1523
|
+
export const updateWorkBlockTemplateSchema = z
|
|
1524
|
+
.object({
|
|
1525
|
+
title: nonEmptyTrimmedString.optional(),
|
|
1526
|
+
kind: workBlockKindSchema.optional(),
|
|
1527
|
+
color: z
|
|
1528
|
+
.string()
|
|
1529
|
+
.regex(/^#[0-9a-fA-F]{6}$/)
|
|
1530
|
+
.optional(),
|
|
1531
|
+
timezone: nonEmptyTrimmedString.optional(),
|
|
1532
|
+
weekDays: z.array(z.number().int().min(0).max(6)).min(1).max(7).optional(),
|
|
1533
|
+
startMinute: integerMinuteSchema.optional(),
|
|
1534
|
+
endMinute: integerMinuteSchema.optional(),
|
|
1535
|
+
startsOn: dateOnlySchema.nullable().optional(),
|
|
1536
|
+
endsOn: dateOnlySchema.nullable().optional(),
|
|
1537
|
+
blockingState: z.enum(["allowed", "blocked"]).optional()
|
|
1538
|
+
})
|
|
1539
|
+
.superRefine((value, context) => {
|
|
1540
|
+
if (value.startMinute !== undefined &&
|
|
1541
|
+
value.endMinute !== undefined &&
|
|
1542
|
+
value.endMinute <= value.startMinute) {
|
|
1543
|
+
context.addIssue({
|
|
1544
|
+
code: z.ZodIssueCode.custom,
|
|
1545
|
+
path: ["endMinute"],
|
|
1546
|
+
message: "endMinute must be greater than startMinute"
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
if (value.startsOn !== undefined &&
|
|
1550
|
+
value.endsOn !== undefined &&
|
|
1551
|
+
value.startsOn &&
|
|
1552
|
+
value.endsOn &&
|
|
1553
|
+
value.endsOn < value.startsOn) {
|
|
1554
|
+
context.addIssue({
|
|
1555
|
+
code: z.ZodIssueCode.custom,
|
|
1556
|
+
path: ["endsOn"],
|
|
1557
|
+
message: "endsOn must be on or after startsOn"
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
});
|
|
1561
|
+
export const createTaskTimeboxSchema = z
|
|
1562
|
+
.object({
|
|
1563
|
+
taskId: nonEmptyTrimmedString,
|
|
1564
|
+
projectId: nonEmptyTrimmedString.nullable().optional(),
|
|
1565
|
+
title: nonEmptyTrimmedString,
|
|
1566
|
+
startsAt: z.string().datetime(),
|
|
1567
|
+
endsAt: z.string().datetime(),
|
|
1568
|
+
source: calendarTimeboxSourceSchema.default("manual"),
|
|
1569
|
+
status: calendarTimeboxStatusSchema.default("planned"),
|
|
1570
|
+
overrideReason: trimmedString.nullable().default(null)
|
|
1571
|
+
})
|
|
1572
|
+
.superRefine((value, context) => {
|
|
1573
|
+
if (Date.parse(value.endsAt) <= Date.parse(value.startsAt)) {
|
|
1574
|
+
context.addIssue({
|
|
1575
|
+
code: z.ZodIssueCode.custom,
|
|
1576
|
+
path: ["endsAt"],
|
|
1577
|
+
message: "endsAt must be after startsAt"
|
|
1578
|
+
});
|
|
1579
|
+
}
|
|
1580
|
+
});
|
|
1581
|
+
export const updateTaskTimeboxSchema = z.object({
|
|
1582
|
+
title: nonEmptyTrimmedString.optional(),
|
|
1583
|
+
startsAt: z.string().datetime().optional(),
|
|
1584
|
+
endsAt: z.string().datetime().optional(),
|
|
1585
|
+
status: calendarTimeboxStatusSchema.optional(),
|
|
1586
|
+
overrideReason: trimmedString.nullable().optional()
|
|
1587
|
+
});
|
|
1588
|
+
export const recommendTaskTimeboxesSchema = z.object({
|
|
1589
|
+
taskId: nonEmptyTrimmedString,
|
|
1590
|
+
from: z.string().datetime().optional(),
|
|
1591
|
+
to: z.string().datetime().optional(),
|
|
1592
|
+
limit: z.coerce.number().int().positive().max(12).optional()
|
|
1593
|
+
});
|
|
1594
|
+
export const updateCalendarEventSchema = z
|
|
1595
|
+
.object({
|
|
1596
|
+
title: nonEmptyTrimmedString.optional(),
|
|
1597
|
+
description: trimmedString.optional(),
|
|
1598
|
+
location: trimmedString.optional(),
|
|
1599
|
+
startAt: z.string().datetime().optional(),
|
|
1600
|
+
endAt: z.string().datetime().optional(),
|
|
1601
|
+
timezone: nonEmptyTrimmedString.optional(),
|
|
1602
|
+
isAllDay: z.boolean().optional(),
|
|
1603
|
+
availability: calendarAvailabilitySchema.optional(),
|
|
1604
|
+
eventType: trimmedString.optional(),
|
|
1605
|
+
categories: z.array(trimmedString).optional(),
|
|
1606
|
+
preferredCalendarId: nonEmptyTrimmedString.nullable().optional(),
|
|
1607
|
+
links: z
|
|
1608
|
+
.array(z.object({
|
|
1609
|
+
entityType: crudEntityTypeSchema,
|
|
1610
|
+
entityId: nonEmptyTrimmedString,
|
|
1611
|
+
relationshipType: nonEmptyTrimmedString.default("context")
|
|
1612
|
+
}))
|
|
1613
|
+
.optional()
|
|
1614
|
+
})
|
|
1615
|
+
.superRefine((value, context) => {
|
|
1616
|
+
if (value.startAt !== undefined &&
|
|
1617
|
+
value.endAt !== undefined &&
|
|
1618
|
+
Date.parse(value.endAt) <= Date.parse(value.startAt)) {
|
|
1619
|
+
context.addIssue({
|
|
1620
|
+
code: z.ZodIssueCode.custom,
|
|
1621
|
+
path: ["endAt"],
|
|
1622
|
+
message: "endAt must be after startAt"
|
|
1623
|
+
});
|
|
1624
|
+
}
|
|
1625
|
+
});
|
|
1626
|
+
export const createCalendarEventSchema = z
|
|
1627
|
+
.object({
|
|
1628
|
+
title: nonEmptyTrimmedString,
|
|
1629
|
+
description: trimmedString.default(""),
|
|
1630
|
+
location: trimmedString.default(""),
|
|
1631
|
+
startAt: z.string().datetime(),
|
|
1632
|
+
endAt: z.string().datetime(),
|
|
1633
|
+
timezone: nonEmptyTrimmedString.default("UTC"),
|
|
1634
|
+
isAllDay: z.boolean().default(false),
|
|
1635
|
+
availability: calendarAvailabilitySchema.default("busy"),
|
|
1636
|
+
eventType: trimmedString.default(""),
|
|
1637
|
+
categories: z.array(trimmedString).default([]),
|
|
1638
|
+
preferredCalendarId: nonEmptyTrimmedString.nullable().optional(),
|
|
1639
|
+
links: z
|
|
1640
|
+
.array(z.object({
|
|
1641
|
+
entityType: crudEntityTypeSchema,
|
|
1642
|
+
entityId: nonEmptyTrimmedString,
|
|
1643
|
+
relationshipType: nonEmptyTrimmedString.default("context")
|
|
1644
|
+
}))
|
|
1645
|
+
.default([])
|
|
1646
|
+
})
|
|
1647
|
+
.superRefine((value, context) => {
|
|
1648
|
+
if (Date.parse(value.endAt) <= Date.parse(value.startAt)) {
|
|
1649
|
+
context.addIssue({
|
|
1650
|
+
code: z.ZodIssueCode.custom,
|
|
1651
|
+
path: ["endAt"],
|
|
1652
|
+
message: "endAt must be after startAt"
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
});
|
|
849
1656
|
export const habitListQuerySchema = z.object({
|
|
850
1657
|
status: habitStatusSchema.optional(),
|
|
851
1658
|
polarity: habitPolaritySchema.optional(),
|
|
@@ -858,7 +1665,10 @@ export const createGoalSchema = z.object({
|
|
|
858
1665
|
horizon: goalHorizonSchema.default("year"),
|
|
859
1666
|
status: goalStatusSchema.default("active"),
|
|
860
1667
|
targetPoints: z.number().int().min(25).max(10000).default(400),
|
|
861
|
-
themeColor: z
|
|
1668
|
+
themeColor: z
|
|
1669
|
+
.string()
|
|
1670
|
+
.regex(/^#[0-9a-fA-F]{6}$/)
|
|
1671
|
+
.default("#c8a46b"),
|
|
862
1672
|
tagIds: uniqueStringArraySchema.default([]),
|
|
863
1673
|
notes: z.array(nestedCreateNoteSchema).default([])
|
|
864
1674
|
});
|
|
@@ -866,7 +1676,10 @@ export const updateGoalSchema = createGoalSchema.partial();
|
|
|
866
1676
|
export const createTagSchema = z.object({
|
|
867
1677
|
name: nonEmptyTrimmedString,
|
|
868
1678
|
kind: tagKindSchema.default("category"),
|
|
869
|
-
color: z
|
|
1679
|
+
color: z
|
|
1680
|
+
.string()
|
|
1681
|
+
.regex(/^#[0-9a-fA-F]{6}$/)
|
|
1682
|
+
.default("#71717a"),
|
|
870
1683
|
description: trimmedString.default("")
|
|
871
1684
|
});
|
|
872
1685
|
export const updateTagSchema = createTagSchema.partial();
|
|
@@ -876,7 +1689,22 @@ export const createProjectSchema = z.object({
|
|
|
876
1689
|
description: trimmedString.default(""),
|
|
877
1690
|
status: projectStatusSchema.default("active"),
|
|
878
1691
|
targetPoints: z.number().int().min(25).max(10000).default(240),
|
|
879
|
-
themeColor: z
|
|
1692
|
+
themeColor: z
|
|
1693
|
+
.string()
|
|
1694
|
+
.regex(/^#[0-9a-fA-F]{6}$/)
|
|
1695
|
+
.default("#c0c1ff"),
|
|
1696
|
+
schedulingRules: calendarSchedulingRulesSchema.default({
|
|
1697
|
+
allowWorkBlockKinds: [],
|
|
1698
|
+
blockWorkBlockKinds: [],
|
|
1699
|
+
allowCalendarIds: [],
|
|
1700
|
+
blockCalendarIds: [],
|
|
1701
|
+
allowEventTypes: [],
|
|
1702
|
+
blockEventTypes: [],
|
|
1703
|
+
allowEventKeywords: [],
|
|
1704
|
+
blockEventKeywords: [],
|
|
1705
|
+
allowAvailability: [],
|
|
1706
|
+
blockAvailability: []
|
|
1707
|
+
}),
|
|
880
1708
|
notes: z.array(nestedCreateNoteSchema).default([])
|
|
881
1709
|
});
|
|
882
1710
|
export const updateProjectSchema = createProjectSchema.partial();
|
|
@@ -892,6 +1720,14 @@ export const taskMutationShape = {
|
|
|
892
1720
|
effort: taskEffortSchema.default("deep"),
|
|
893
1721
|
energy: taskEnergySchema.default("steady"),
|
|
894
1722
|
points: z.number().int().min(5).max(500).default(40),
|
|
1723
|
+
plannedDurationSeconds: z
|
|
1724
|
+
.number()
|
|
1725
|
+
.int()
|
|
1726
|
+
.min(60)
|
|
1727
|
+
.max(86_400)
|
|
1728
|
+
.nullable()
|
|
1729
|
+
.default(null),
|
|
1730
|
+
schedulingRules: calendarSchedulingRulesSchema.nullable().default(null),
|
|
895
1731
|
sortOrder: z.number().int().nonnegative().optional(),
|
|
896
1732
|
tagIds: uniqueStringArraySchema.default([]),
|
|
897
1733
|
notes: z.array(nestedCreateNoteSchema).default([])
|
|
@@ -918,7 +1754,9 @@ const habitMutationShape = {
|
|
|
918
1754
|
rewardXp: z.number().int().min(1).max(100).default(12),
|
|
919
1755
|
penaltyXp: z.number().int().min(1).max(100).default(8)
|
|
920
1756
|
};
|
|
921
|
-
export const createHabitSchema = z
|
|
1757
|
+
export const createHabitSchema = z
|
|
1758
|
+
.object(habitMutationShape)
|
|
1759
|
+
.superRefine((value, context) => {
|
|
922
1760
|
if (value.frequency === "weekly" && value.weekDays.length === 0) {
|
|
923
1761
|
context.addIssue({
|
|
924
1762
|
code: z.ZodIssueCode.custom,
|
|
@@ -927,7 +1765,8 @@ export const createHabitSchema = z.object(habitMutationShape).superRefine((value
|
|
|
927
1765
|
});
|
|
928
1766
|
}
|
|
929
1767
|
});
|
|
930
|
-
export const updateHabitSchema = z
|
|
1768
|
+
export const updateHabitSchema = z
|
|
1769
|
+
.object({
|
|
931
1770
|
title: nonEmptyTrimmedString.optional(),
|
|
932
1771
|
description: trimmedString.optional(),
|
|
933
1772
|
status: habitStatusSchema.optional(),
|
|
@@ -947,8 +1786,11 @@ export const updateHabitSchema = z.object({
|
|
|
947
1786
|
linkedBehaviorId: nonEmptyTrimmedString.nullable().optional(),
|
|
948
1787
|
rewardXp: z.number().int().min(1).max(100).optional(),
|
|
949
1788
|
penaltyXp: z.number().int().min(1).max(100).optional()
|
|
950
|
-
})
|
|
951
|
-
|
|
1789
|
+
})
|
|
1790
|
+
.superRefine((value, context) => {
|
|
1791
|
+
if (value.frequency === "weekly" &&
|
|
1792
|
+
value.weekDays !== undefined &&
|
|
1793
|
+
value.weekDays.length === 0) {
|
|
952
1794
|
context.addIssue({
|
|
953
1795
|
code: z.ZodIssueCode.custom,
|
|
954
1796
|
path: ["weekDays"],
|
|
@@ -968,6 +1810,14 @@ export const updateTaskSchema = z.object({
|
|
|
968
1810
|
effort: taskEffortSchema.optional(),
|
|
969
1811
|
energy: taskEnergySchema.optional(),
|
|
970
1812
|
points: z.number().int().min(5).max(500).optional(),
|
|
1813
|
+
plannedDurationSeconds: z
|
|
1814
|
+
.number()
|
|
1815
|
+
.int()
|
|
1816
|
+
.min(60)
|
|
1817
|
+
.max(86_400)
|
|
1818
|
+
.nullable()
|
|
1819
|
+
.optional(),
|
|
1820
|
+
schedulingRules: calendarSchedulingRulesSchema.nullable().optional(),
|
|
971
1821
|
sortOrder: z.number().int().nonnegative().optional(),
|
|
972
1822
|
tagIds: uniqueStringArraySchema.optional(),
|
|
973
1823
|
notes: z.array(nestedCreateNoteSchema).optional()
|
|
@@ -978,22 +1828,33 @@ export const tagSuggestionRequestSchema = z.object({
|
|
|
978
1828
|
goalId: nonEmptyTrimmedString.nullable().default(null),
|
|
979
1829
|
selectedTagIds: uniqueStringArraySchema.default([])
|
|
980
1830
|
});
|
|
981
|
-
export const taskRunClaimSchema = z
|
|
1831
|
+
export const taskRunClaimSchema = z
|
|
1832
|
+
.object({
|
|
982
1833
|
actor: nonEmptyTrimmedString,
|
|
983
1834
|
timerMode: taskTimerModeSchema.default("unlimited"),
|
|
984
|
-
plannedDurationSeconds: z.coerce
|
|
1835
|
+
plannedDurationSeconds: z.coerce
|
|
1836
|
+
.number()
|
|
1837
|
+
.int()
|
|
1838
|
+
.min(60)
|
|
1839
|
+
.max(86_400)
|
|
1840
|
+
.nullable()
|
|
1841
|
+
.default(null),
|
|
985
1842
|
isCurrent: z.coerce.boolean().default(true),
|
|
986
1843
|
leaseTtlSeconds: z.coerce.number().int().min(1).max(14400).default(900),
|
|
987
|
-
note: trimmedString.default("")
|
|
988
|
-
|
|
989
|
-
|
|
1844
|
+
note: trimmedString.default(""),
|
|
1845
|
+
overrideReason: trimmedString.optional()
|
|
1846
|
+
})
|
|
1847
|
+
.superRefine((value, context) => {
|
|
1848
|
+
if (value.timerMode === "planned" &&
|
|
1849
|
+
value.plannedDurationSeconds === null) {
|
|
990
1850
|
context.addIssue({
|
|
991
1851
|
code: z.ZodIssueCode.custom,
|
|
992
1852
|
path: ["plannedDurationSeconds"],
|
|
993
1853
|
message: "plannedDurationSeconds is required when timerMode is planned"
|
|
994
1854
|
});
|
|
995
1855
|
}
|
|
996
|
-
if (value.timerMode === "unlimited" &&
|
|
1856
|
+
if (value.timerMode === "unlimited" &&
|
|
1857
|
+
value.plannedDurationSeconds !== null) {
|
|
997
1858
|
context.addIssue({
|
|
998
1859
|
code: z.ZodIssueCode.custom,
|
|
999
1860
|
path: ["plannedDurationSeconds"],
|
|
@@ -1004,7 +1865,8 @@ export const taskRunClaimSchema = z.object({
|
|
|
1004
1865
|
export const taskRunHeartbeatSchema = z.object({
|
|
1005
1866
|
actor: nonEmptyTrimmedString.optional(),
|
|
1006
1867
|
leaseTtlSeconds: z.coerce.number().int().min(1).max(14400).default(900),
|
|
1007
|
-
note: trimmedString.optional()
|
|
1868
|
+
note: trimmedString.optional(),
|
|
1869
|
+
overrideReason: trimmedString.optional()
|
|
1008
1870
|
});
|
|
1009
1871
|
export const taskRunFinishSchema = z.object({
|
|
1010
1872
|
actor: nonEmptyTrimmedString.optional(),
|
|
@@ -1034,6 +1896,17 @@ export const updateSettingsSchema = z.object({
|
|
|
1034
1896
|
security: z
|
|
1035
1897
|
.object({
|
|
1036
1898
|
psycheAuthRequired: z.boolean().optional()
|
|
1899
|
+
})
|
|
1900
|
+
.optional(),
|
|
1901
|
+
calendarProviders: z
|
|
1902
|
+
.object({
|
|
1903
|
+
microsoft: z
|
|
1904
|
+
.object({
|
|
1905
|
+
clientId: trimmedString.optional(),
|
|
1906
|
+
tenantId: trimmedString.optional(),
|
|
1907
|
+
redirectUri: trimmedString.optional()
|
|
1908
|
+
})
|
|
1909
|
+
.optional()
|
|
1037
1910
|
})
|
|
1038
1911
|
.optional()
|
|
1039
1912
|
});
|
|
@@ -1101,7 +1974,9 @@ export const resolveApprovalRequestSchema = z.object({
|
|
|
1101
1974
|
export const createSessionEventSchema = z.object({
|
|
1102
1975
|
sessionId: nonEmptyTrimmedString,
|
|
1103
1976
|
eventType: nonEmptyTrimmedString,
|
|
1104
|
-
metrics: z
|
|
1977
|
+
metrics: z
|
|
1978
|
+
.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()]))
|
|
1979
|
+
.default({})
|
|
1105
1980
|
});
|
|
1106
1981
|
export const removeActivityEventSchema = z.object({
|
|
1107
1982
|
reason: trimmedString.default("Removed from the visible archive.")
|
|
@@ -1116,41 +1991,50 @@ const crudEntityLinkSchema = z.object({
|
|
|
1116
1991
|
});
|
|
1117
1992
|
export const batchCreateEntitiesSchema = z.object({
|
|
1118
1993
|
atomic: z.boolean().default(false),
|
|
1119
|
-
operations: z
|
|
1994
|
+
operations: z
|
|
1995
|
+
.array(z.object({
|
|
1120
1996
|
entityType: crudEntityTypeSchema,
|
|
1121
1997
|
clientRef: trimmedString.optional(),
|
|
1122
1998
|
data: z.record(z.string(), z.unknown())
|
|
1123
|
-
}))
|
|
1999
|
+
}))
|
|
2000
|
+
.min(1)
|
|
1124
2001
|
});
|
|
1125
2002
|
export const batchUpdateEntitiesSchema = z.object({
|
|
1126
2003
|
atomic: z.boolean().default(false),
|
|
1127
|
-
operations: z
|
|
2004
|
+
operations: z
|
|
2005
|
+
.array(z.object({
|
|
1128
2006
|
entityType: crudEntityTypeSchema,
|
|
1129
2007
|
id: nonEmptyTrimmedString,
|
|
1130
2008
|
clientRef: trimmedString.optional(),
|
|
1131
2009
|
patch: z.record(z.string(), z.unknown())
|
|
1132
|
-
}))
|
|
2010
|
+
}))
|
|
2011
|
+
.min(1)
|
|
1133
2012
|
});
|
|
1134
2013
|
export const batchDeleteEntitiesSchema = z.object({
|
|
1135
2014
|
atomic: z.boolean().default(false),
|
|
1136
|
-
operations: z
|
|
2015
|
+
operations: z
|
|
2016
|
+
.array(z.object({
|
|
1137
2017
|
entityType: crudEntityTypeSchema,
|
|
1138
2018
|
id: nonEmptyTrimmedString,
|
|
1139
2019
|
clientRef: trimmedString.optional(),
|
|
1140
2020
|
mode: deleteModeSchema.default("soft"),
|
|
1141
2021
|
reason: trimmedString.default("")
|
|
1142
|
-
}))
|
|
2022
|
+
}))
|
|
2023
|
+
.min(1)
|
|
1143
2024
|
});
|
|
1144
2025
|
export const batchRestoreEntitiesSchema = z.object({
|
|
1145
2026
|
atomic: z.boolean().default(false),
|
|
1146
|
-
operations: z
|
|
2027
|
+
operations: z
|
|
2028
|
+
.array(z.object({
|
|
1147
2029
|
entityType: crudEntityTypeSchema,
|
|
1148
2030
|
id: nonEmptyTrimmedString,
|
|
1149
2031
|
clientRef: trimmedString.optional()
|
|
1150
|
-
}))
|
|
2032
|
+
}))
|
|
2033
|
+
.min(1)
|
|
1151
2034
|
});
|
|
1152
2035
|
export const batchSearchEntitiesSchema = z.object({
|
|
1153
|
-
searches: z
|
|
2036
|
+
searches: z
|
|
2037
|
+
.array(z.object({
|
|
1154
2038
|
entityTypes: z.array(crudEntityTypeSchema).optional(),
|
|
1155
2039
|
query: trimmedString.optional(),
|
|
1156
2040
|
ids: uniqueStringArraySchema.optional(),
|
|
@@ -1159,7 +2043,8 @@ export const batchSearchEntitiesSchema = z.object({
|
|
|
1159
2043
|
includeDeleted: z.boolean().default(false),
|
|
1160
2044
|
limit: z.number().int().positive().max(200).default(25),
|
|
1161
2045
|
clientRef: trimmedString.optional()
|
|
1162
|
-
}))
|
|
2046
|
+
}))
|
|
2047
|
+
.min(1)
|
|
1163
2048
|
});
|
|
1164
2049
|
export const uncompleteTaskSchema = z.object({
|
|
1165
2050
|
status: taskStatusSchema.exclude(["done"]).default("focus")
|