forge-openclaw-plugin 0.2.15 → 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 +39 -4
- package/dist/assets/{board-C_m78kvK.js → board-8L3uX7_O.js} +2 -2
- package/dist/assets/{board-C_m78kvK.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-CpZvZumD.js → motion-1GAqqi8M.js} +2 -2
- package/dist/assets/{motion-CpZvZumD.js.map → motion-1GAqqi8M.js.map} +1 -1
- package/dist/assets/{table-DtyXTw03.js → table-DBGlgRjk.js} +2 -2
- package/dist/assets/{table-DtyXTw03.js.map → table-DBGlgRjk.js.map} +1 -1
- package/dist/assets/{ui-BXbpiKyS.js → ui-iTluWjC4.js} +2 -2
- package/dist/assets/{ui-BXbpiKyS.js.map → ui-iTluWjC4.js.map} +1 -1
- package/dist/assets/{vendor-QBH6qVEe.js → vendor-BvM2F9Dp.js} +151 -81
- package/dist/assets/vendor-BvM2F9Dp.js.map +1 -0
- package/dist/assets/{viz-w-IMeueL.js → viz-CNeunkfu.js} +2 -2
- package/dist/assets/{viz-w-IMeueL.js.map → viz-CNeunkfu.js.map} +1 -1
- package/dist/index.html +8 -8
- package/dist/openclaw/local-runtime.js +142 -9
- package/dist/openclaw/parity.js +1 -0
- package/dist/openclaw/plugin-entry-shared.js +7 -1
- package/dist/openclaw/routes.js +7 -0
- package/dist/openclaw/tools.js +198 -16
- package/dist/server/app.js +2615 -251
- package/dist/server/managers/platform/secrets-manager.js +44 -1
- package/dist/server/managers/runtime.js +3 -1
- package/dist/server/openapi.js +2212 -170
- package/dist/server/repositories/calendar.js +1101 -0
- package/dist/server/repositories/deleted-entities.js +10 -2
- package/dist/server/repositories/habits.js +358 -0
- package/dist/server/repositories/notes.js +161 -28
- package/dist/server/repositories/projects.js +45 -13
- package/dist/server/repositories/rewards.js +176 -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/context.js +16 -6
- package/dist/server/services/dashboard.js +6 -3
- package/dist/server/services/entity-crud.js +116 -3
- package/dist/server/services/gamification.js +66 -18
- package/dist/server/services/insights.js +2 -1
- package/dist/server/services/projects.js +32 -8
- package/dist/server/services/reviews.js +17 -2
- package/dist/server/services/work-time.js +27 -0
- package/dist/server/types.js +1069 -45
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/server/migrations/003_habits.sql +30 -0
- package/server/migrations/004_habit_links.sql +8 -0
- package/server/migrations/005_habit_psyche_links.sql +24 -0
- 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 +130 -10
- package/skills/forge-openclaw/cron_jobs.md +395 -0
- package/dist/assets/index-BWtLtXwb.js +0 -36
- package/dist/assets/index-BWtLtXwb.js.map +0 -1
- package/dist/assets/index-Dp5GXY_z.css +0 -1
- package/dist/assets/vendor-QBH6qVEe.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,11 +14,71 @@ 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
|
+
]);
|
|
29
|
+
export const habitFrequencySchema = z.enum(["daily", "weekly"]);
|
|
30
|
+
export const habitPolaritySchema = z.enum(["positive", "negative"]);
|
|
31
|
+
export const habitStatusSchema = z.enum(["active", "paused", "archived"]);
|
|
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"]);
|
|
14
79
|
export const activityEntityTypeSchema = z.enum([
|
|
15
80
|
"task",
|
|
81
|
+
"habit",
|
|
16
82
|
"goal",
|
|
17
83
|
"project",
|
|
18
84
|
"domain",
|
|
@@ -33,26 +99,80 @@ export const activityEntityTypeSchema = z.enum([
|
|
|
33
99
|
"approval_request",
|
|
34
100
|
"agent_action",
|
|
35
101
|
"reward",
|
|
36
|
-
"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"
|
|
37
130
|
]);
|
|
38
|
-
export const activitySourceSchema = z.enum(["ui", "openclaw", "agent", "system"]);
|
|
39
|
-
export const agentTrustLevelSchema = z.enum(["standard", "trusted", "autonomous"]);
|
|
40
|
-
export const autonomyModeSchema = z.enum(["approval_required", "scoped_write", "autonomous"]);
|
|
41
|
-
export const approvalModeSchema = z.enum(["approval_by_default", "high_impact_only", "none"]);
|
|
42
131
|
export const insightOriginSchema = z.enum(["system", "user", "agent"]);
|
|
43
|
-
export const insightStatusSchema = z.enum([
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
+
]);
|
|
47
158
|
export const actionRiskLevelSchema = z.enum(["low", "medium", "high"]);
|
|
48
|
-
export const agentActionStatusSchema = z.enum([
|
|
159
|
+
export const agentActionStatusSchema = z.enum([
|
|
160
|
+
"pending_approval",
|
|
161
|
+
"approved",
|
|
162
|
+
"rejected",
|
|
163
|
+
"executed"
|
|
164
|
+
]);
|
|
49
165
|
export const crudEntityTypeSchema = z.enum([
|
|
50
166
|
"goal",
|
|
51
167
|
"project",
|
|
52
168
|
"task",
|
|
169
|
+
"habit",
|
|
53
170
|
"tag",
|
|
54
171
|
"note",
|
|
55
172
|
"insight",
|
|
173
|
+
"calendar_event",
|
|
174
|
+
"work_block_template",
|
|
175
|
+
"task_timebox",
|
|
56
176
|
"psyche_value",
|
|
57
177
|
"behavior_pattern",
|
|
58
178
|
"behavior",
|
|
@@ -63,6 +183,22 @@ export const crudEntityTypeSchema = z.enum([
|
|
|
63
183
|
"emotion_definition",
|
|
64
184
|
"trigger_report"
|
|
65
185
|
]);
|
|
186
|
+
export const rewardableEntityTypeSchema = z.enum([
|
|
187
|
+
"system",
|
|
188
|
+
"goal",
|
|
189
|
+
"project",
|
|
190
|
+
"task",
|
|
191
|
+
"habit",
|
|
192
|
+
"tag",
|
|
193
|
+
"note",
|
|
194
|
+
"insight",
|
|
195
|
+
"psyche_value",
|
|
196
|
+
"behavior_pattern",
|
|
197
|
+
"behavior",
|
|
198
|
+
"belief_entry",
|
|
199
|
+
"mode_profile",
|
|
200
|
+
"trigger_report"
|
|
201
|
+
]);
|
|
66
202
|
export const deleteModeSchema = z.enum(["soft", "hard"]);
|
|
67
203
|
export const rewardRuleFamilySchema = z.enum([
|
|
68
204
|
"completion",
|
|
@@ -75,7 +211,12 @@ export const rewardRuleFamilySchema = z.enum([
|
|
|
75
211
|
export const appLocaleSchema = z.enum(["en", "fr"]);
|
|
76
212
|
const trimmedString = z.string().trim();
|
|
77
213
|
const nonEmptyTrimmedString = trimmedString.min(1);
|
|
78
|
-
const rewardConfigValueSchema = z.union([
|
|
214
|
+
const rewardConfigValueSchema = z.union([
|
|
215
|
+
z.string(),
|
|
216
|
+
z.number(),
|
|
217
|
+
z.boolean(),
|
|
218
|
+
z.null()
|
|
219
|
+
]);
|
|
79
220
|
function isValidDateOnly(value) {
|
|
80
221
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
81
222
|
return false;
|
|
@@ -89,9 +230,15 @@ function isValidDateOnly(value) {
|
|
|
89
230
|
candidate.getUTCMonth() === month - 1 &&
|
|
90
231
|
candidate.getUTCDate() === day);
|
|
91
232
|
}
|
|
233
|
+
function isValidDateTime(value) {
|
|
234
|
+
return !Number.isNaN(Date.parse(value));
|
|
235
|
+
}
|
|
92
236
|
const dateOnlySchema = trimmedString.refine(isValidDateOnly, {
|
|
93
237
|
message: "Expected a valid date in YYYY-MM-DD format"
|
|
94
238
|
});
|
|
239
|
+
const dateTimeSchema = trimmedString.refine(isValidDateTime, {
|
|
240
|
+
message: "Expected a valid ISO date-time string"
|
|
241
|
+
});
|
|
95
242
|
const uniqueStringArraySchema = z
|
|
96
243
|
.array(nonEmptyTrimmedString)
|
|
97
244
|
.superRefine((values, context) => {
|
|
@@ -108,6 +255,31 @@ const uniqueStringArraySchema = z
|
|
|
108
255
|
seen.add(value);
|
|
109
256
|
});
|
|
110
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
|
+
});
|
|
111
283
|
export const tagSchema = z.object({
|
|
112
284
|
id: z.string(),
|
|
113
285
|
name: nonEmptyTrimmedString,
|
|
@@ -118,15 +290,65 @@ export const tagSchema = z.object({
|
|
|
118
290
|
export const taskTimeSummarySchema = z.object({
|
|
119
291
|
totalTrackedSeconds: z.number().int().nonnegative(),
|
|
120
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),
|
|
121
296
|
activeRunCount: z.number().int().nonnegative(),
|
|
122
297
|
hasCurrentRun: z.boolean(),
|
|
123
298
|
currentRunId: z.string().nullable()
|
|
124
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
|
+
});
|
|
125
328
|
export const noteLinkSchema = z.object({
|
|
126
329
|
entityType: crudEntityTypeSchema,
|
|
127
330
|
entityId: nonEmptyTrimmedString,
|
|
128
331
|
anchorKey: trimmedString.nullable().default(null)
|
|
129
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
|
+
});
|
|
130
352
|
export const noteSchema = z.object({
|
|
131
353
|
id: z.string(),
|
|
132
354
|
contentMarkdown: nonEmptyTrimmedString,
|
|
@@ -135,7 +357,9 @@ export const noteSchema = z.object({
|
|
|
135
357
|
source: activitySourceSchema,
|
|
136
358
|
createdAt: z.string(),
|
|
137
359
|
updatedAt: z.string(),
|
|
138
|
-
links: z.array(noteLinkSchema).min(1)
|
|
360
|
+
links: z.array(noteLinkSchema).min(1),
|
|
361
|
+
tags: uniqueNoteTagArraySchema.default([]),
|
|
362
|
+
destroyAt: dateTimeSchema.nullable().default(null)
|
|
139
363
|
});
|
|
140
364
|
export const noteSummarySchema = z.object({
|
|
141
365
|
count: z.number().int().nonnegative(),
|
|
@@ -163,6 +387,18 @@ export const projectSchema = z.object({
|
|
|
163
387
|
status: projectStatusSchema,
|
|
164
388
|
targetPoints: z.number().int().nonnegative(),
|
|
165
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
|
+
}),
|
|
166
402
|
createdAt: z.string(),
|
|
167
403
|
updatedAt: z.string()
|
|
168
404
|
});
|
|
@@ -180,6 +416,14 @@ export const taskSchema = z.object({
|
|
|
180
416
|
energy: taskEnergySchema,
|
|
181
417
|
points: z.number().int().nonnegative(),
|
|
182
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),
|
|
183
427
|
completedAt: z.string().nullable(),
|
|
184
428
|
createdAt: z.string(),
|
|
185
429
|
updatedAt: z.string(),
|
|
@@ -187,6 +431,9 @@ export const taskSchema = z.object({
|
|
|
187
431
|
time: taskTimeSummarySchema.default({
|
|
188
432
|
totalTrackedSeconds: 0,
|
|
189
433
|
totalCreditedSeconds: 0,
|
|
434
|
+
liveTrackedSeconds: 0,
|
|
435
|
+
liveCreditedSeconds: 0,
|
|
436
|
+
manualAdjustedSeconds: 0,
|
|
190
437
|
activeRunCount: 0,
|
|
191
438
|
hasCurrentRun: false,
|
|
192
439
|
currentRunId: null
|
|
@@ -213,8 +460,234 @@ export const taskRunSchema = z.object({
|
|
|
213
460
|
completedAt: z.string().nullable(),
|
|
214
461
|
releasedAt: z.string().nullable(),
|
|
215
462
|
timedOutAt: z.string().nullable(),
|
|
463
|
+
overrideReason: trimmedString.nullable().default(null),
|
|
464
|
+
updatedAt: z.string()
|
|
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(),
|
|
216
569
|
updatedAt: z.string()
|
|
217
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
|
+
});
|
|
649
|
+
export const habitCheckInSchema = z.object({
|
|
650
|
+
id: z.string(),
|
|
651
|
+
habitId: z.string(),
|
|
652
|
+
dateKey: z.string(),
|
|
653
|
+
status: habitCheckInStatusSchema,
|
|
654
|
+
note: z.string(),
|
|
655
|
+
deltaXp: z.number().int(),
|
|
656
|
+
createdAt: z.string(),
|
|
657
|
+
updatedAt: z.string()
|
|
658
|
+
});
|
|
659
|
+
export const habitSchema = z.object({
|
|
660
|
+
id: z.string(),
|
|
661
|
+
title: nonEmptyTrimmedString,
|
|
662
|
+
description: trimmedString,
|
|
663
|
+
status: habitStatusSchema,
|
|
664
|
+
polarity: habitPolaritySchema,
|
|
665
|
+
frequency: habitFrequencySchema,
|
|
666
|
+
targetCount: z.number().int().positive(),
|
|
667
|
+
weekDays: z.array(z.number().int().min(0).max(6)).default([]),
|
|
668
|
+
linkedGoalIds: uniqueStringArraySchema.default([]),
|
|
669
|
+
linkedProjectIds: uniqueStringArraySchema.default([]),
|
|
670
|
+
linkedTaskIds: uniqueStringArraySchema.default([]),
|
|
671
|
+
linkedValueIds: uniqueStringArraySchema.default([]),
|
|
672
|
+
linkedPatternIds: uniqueStringArraySchema.default([]),
|
|
673
|
+
linkedBehaviorIds: uniqueStringArraySchema.default([]),
|
|
674
|
+
linkedBeliefIds: uniqueStringArraySchema.default([]),
|
|
675
|
+
linkedModeIds: uniqueStringArraySchema.default([]),
|
|
676
|
+
linkedReportIds: uniqueStringArraySchema.default([]),
|
|
677
|
+
linkedBehaviorId: z.string().nullable(),
|
|
678
|
+
linkedBehaviorTitle: z.string().nullable(),
|
|
679
|
+
linkedBehaviorTitles: z.array(z.string()).default([]),
|
|
680
|
+
rewardXp: z.number().int().positive(),
|
|
681
|
+
penaltyXp: z.number().int().positive(),
|
|
682
|
+
createdAt: z.string(),
|
|
683
|
+
updatedAt: z.string(),
|
|
684
|
+
lastCheckInAt: z.string().nullable(),
|
|
685
|
+
lastCheckInStatus: habitCheckInStatusSchema.nullable(),
|
|
686
|
+
streakCount: z.number().int().nonnegative(),
|
|
687
|
+
completionRate: z.number().min(0).max(100),
|
|
688
|
+
dueToday: z.boolean(),
|
|
689
|
+
checkIns: z.array(habitCheckInSchema).default([])
|
|
690
|
+
});
|
|
218
691
|
export const activityEventSchema = z.object({
|
|
219
692
|
id: z.string(),
|
|
220
693
|
entityType: activityEntityTypeSchema,
|
|
@@ -244,7 +717,12 @@ export const dashboardStatsSchema = z.object({
|
|
|
244
717
|
overdueTasks: z.number().int().nonnegative(),
|
|
245
718
|
dueThisWeek: z.number().int().nonnegative()
|
|
246
719
|
});
|
|
247
|
-
export const executionBucketToneSchema = z.enum([
|
|
720
|
+
export const executionBucketToneSchema = z.enum([
|
|
721
|
+
"urgent",
|
|
722
|
+
"accent",
|
|
723
|
+
"neutral",
|
|
724
|
+
"success"
|
|
725
|
+
]);
|
|
248
726
|
export const dashboardExecutionBucketSchema = z.object({
|
|
249
727
|
id: z.enum(["overdue", "due_soon", "focus_now", "recently_completed"]),
|
|
250
728
|
label: z.string(),
|
|
@@ -276,7 +754,12 @@ export const gamificationProfileSchema = z.object({
|
|
|
276
754
|
topGoalId: z.string().nullable(),
|
|
277
755
|
topGoalTitle: z.string().nullable()
|
|
278
756
|
});
|
|
279
|
-
export const achievementTierSchema = z.enum([
|
|
757
|
+
export const achievementTierSchema = z.enum([
|
|
758
|
+
"bronze",
|
|
759
|
+
"silver",
|
|
760
|
+
"gold",
|
|
761
|
+
"platinum"
|
|
762
|
+
]);
|
|
280
763
|
export const achievementSignalSchema = z.object({
|
|
281
764
|
id: z.string(),
|
|
282
765
|
title: z.string(),
|
|
@@ -314,6 +797,7 @@ export const dashboardPayloadSchema = z.object({
|
|
|
314
797
|
goals: z.array(dashboardGoalSchema),
|
|
315
798
|
projects: z.array(projectSummarySchema),
|
|
316
799
|
tasks: z.array(taskSchema),
|
|
800
|
+
habits: z.array(habitSchema),
|
|
317
801
|
tags: z.array(tagSchema),
|
|
318
802
|
suggestedTags: z.array(tagSchema),
|
|
319
803
|
owners: z.array(z.string()),
|
|
@@ -354,6 +838,7 @@ export const overviewContextSchema = z.object({
|
|
|
354
838
|
projects: z.array(projectSummarySchema),
|
|
355
839
|
activeGoals: z.array(dashboardGoalSchema),
|
|
356
840
|
topTasks: z.array(taskSchema),
|
|
841
|
+
dueHabits: z.array(habitSchema),
|
|
357
842
|
recentEvidence: z.array(activityEventSchema),
|
|
358
843
|
achievements: z.array(achievementSignalSchema),
|
|
359
844
|
domainBalance: z.array(contextDomainBalanceSchema),
|
|
@@ -368,7 +853,16 @@ export const todayQuestSchema = z.object({
|
|
|
368
853
|
completed: z.boolean()
|
|
369
854
|
});
|
|
370
855
|
export const todayTimelineBucketSchema = z.object({
|
|
371
|
-
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
|
+
]),
|
|
372
866
|
label: z.string(),
|
|
373
867
|
tasks: z.array(taskSchema)
|
|
374
868
|
});
|
|
@@ -381,8 +875,12 @@ export const todayContextSchema = z.object({
|
|
|
381
875
|
sessionLabel: z.string()
|
|
382
876
|
}),
|
|
383
877
|
timeline: z.array(todayTimelineBucketSchema),
|
|
878
|
+
dueHabits: z.array(habitSchema),
|
|
384
879
|
dailyQuests: z.array(todayQuestSchema),
|
|
385
880
|
milestoneRewards: z.array(milestoneRewardSchema),
|
|
881
|
+
recentHabitRewards: z
|
|
882
|
+
.array(z.lazy(() => rewardLedgerEventSchema))
|
|
883
|
+
.default([]),
|
|
386
884
|
momentum: z.object({
|
|
387
885
|
streakDays: z.number().int().nonnegative(),
|
|
388
886
|
momentumScore: z.number().int().min(0).max(100),
|
|
@@ -471,6 +969,9 @@ export const weeklyReviewCalibrationSchema = z.object({
|
|
|
471
969
|
export const weeklyReviewPayloadSchema = z.object({
|
|
472
970
|
generatedAt: z.string(),
|
|
473
971
|
windowLabel: z.string(),
|
|
972
|
+
weekKey: z.string(),
|
|
973
|
+
weekStartDate: z.string(),
|
|
974
|
+
weekEndDate: z.string(),
|
|
474
975
|
momentumSummary: z.object({
|
|
475
976
|
totalXp: z.number().int().nonnegative(),
|
|
476
977
|
focusHours: z.number().int().nonnegative(),
|
|
@@ -484,8 +985,31 @@ export const weeklyReviewPayloadSchema = z.object({
|
|
|
484
985
|
title: z.string(),
|
|
485
986
|
summary: z.string(),
|
|
486
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()
|
|
487
993
|
})
|
|
488
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
|
+
});
|
|
489
1013
|
export const notificationPreferencesSchema = z.object({
|
|
490
1014
|
goalDriftAlerts: z.boolean(),
|
|
491
1015
|
dailyQuestReminders: z.boolean(),
|
|
@@ -496,6 +1020,17 @@ export const executionSettingsSchema = z.object({
|
|
|
496
1020
|
maxActiveTasks: z.number().int().min(1).max(8),
|
|
497
1021
|
timeAccountingMode: timeAccountingModeSchema
|
|
498
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
|
+
});
|
|
499
1034
|
export const agentTokenSummarySchema = z.object({
|
|
500
1035
|
id: z.string(),
|
|
501
1036
|
label: z.string(),
|
|
@@ -656,6 +1191,7 @@ export const operatorContextPayloadSchema = z.object({
|
|
|
656
1191
|
generatedAt: z.string(),
|
|
657
1192
|
activeProjects: z.array(projectSummarySchema),
|
|
658
1193
|
focusTasks: z.array(taskSchema),
|
|
1194
|
+
dueHabits: z.array(habitSchema),
|
|
659
1195
|
currentBoard: z.object({
|
|
660
1196
|
backlog: z.array(taskSchema),
|
|
661
1197
|
focus: z.array(taskSchema),
|
|
@@ -675,15 +1211,29 @@ export const updateRewardRuleSchema = z.object({
|
|
|
675
1211
|
config: z.record(z.string(), rewardConfigValueSchema).optional()
|
|
676
1212
|
});
|
|
677
1213
|
export const createManualRewardGrantSchema = z.object({
|
|
678
|
-
entityType:
|
|
1214
|
+
entityType: rewardableEntityTypeSchema,
|
|
679
1215
|
entityId: nonEmptyTrimmedString,
|
|
680
|
-
deltaXp: z
|
|
1216
|
+
deltaXp: z
|
|
1217
|
+
.number()
|
|
1218
|
+
.int()
|
|
1219
|
+
.refine((value) => value !== 0, {
|
|
681
1220
|
message: "deltaXp must not be zero"
|
|
682
1221
|
}),
|
|
683
1222
|
reasonTitle: nonEmptyTrimmedString,
|
|
684
1223
|
reasonSummary: trimmedString.default(""),
|
|
685
1224
|
metadata: z.record(z.string(), rewardConfigValueSchema).default({})
|
|
686
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
|
+
});
|
|
687
1237
|
export const settingsPayloadSchema = z.object({
|
|
688
1238
|
profile: z.object({
|
|
689
1239
|
operatorName: z.string(),
|
|
@@ -702,6 +1252,9 @@ export const settingsPayloadSchema = z.object({
|
|
|
702
1252
|
tokenCount: z.number().int().nonnegative(),
|
|
703
1253
|
psycheAuthRequired: z.boolean()
|
|
704
1254
|
}),
|
|
1255
|
+
calendarProviders: z.object({
|
|
1256
|
+
microsoft: microsoftCalendarAuthSettingsSchema
|
|
1257
|
+
}),
|
|
705
1258
|
agents: z.array(agentIdentitySchema),
|
|
706
1259
|
agentTokens: z.array(agentTokenSummarySchema)
|
|
707
1260
|
});
|
|
@@ -727,28 +1280,103 @@ export const createNoteLinkSchema = z.object({
|
|
|
727
1280
|
entityId: nonEmptyTrimmedString,
|
|
728
1281
|
anchorKey: trimmedString.nullable().default(null)
|
|
729
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
|
+
}
|
|
730
1309
|
export const createNoteSchema = z.object({
|
|
731
1310
|
contentMarkdown: nonEmptyTrimmedString,
|
|
732
1311
|
author: trimmedString.nullable().default(null),
|
|
733
|
-
links: z.array(createNoteLinkSchema).min(1)
|
|
1312
|
+
links: z.array(createNoteLinkSchema).min(1),
|
|
1313
|
+
tags: uniqueNoteTagArraySchema.default([]),
|
|
1314
|
+
destroyAt: dateTimeSchema.nullable().default(null)
|
|
734
1315
|
});
|
|
735
1316
|
export const nestedCreateNoteSchema = z.object({
|
|
736
1317
|
contentMarkdown: nonEmptyTrimmedString,
|
|
737
1318
|
author: trimmedString.nullable().default(null),
|
|
738
|
-
links: z.array(createNoteLinkSchema).default([])
|
|
1319
|
+
links: z.array(createNoteLinkSchema).default([]),
|
|
1320
|
+
tags: uniqueNoteTagArraySchema.default([]),
|
|
1321
|
+
destroyAt: dateTimeSchema.nullable().default(null)
|
|
739
1322
|
});
|
|
740
1323
|
export const updateNoteSchema = z.object({
|
|
741
1324
|
contentMarkdown: nonEmptyTrimmedString.optional(),
|
|
742
1325
|
author: trimmedString.nullable().optional(),
|
|
743
|
-
links: z.array(createNoteLinkSchema).min(1).optional()
|
|
1326
|
+
links: z.array(createNoteLinkSchema).min(1).optional(),
|
|
1327
|
+
tags: uniqueNoteTagArraySchema.optional(),
|
|
1328
|
+
destroyAt: dateTimeSchema.nullable().optional()
|
|
744
1329
|
});
|
|
745
|
-
export const notesListQuerySchema = z
|
|
1330
|
+
export const notesListQuerySchema = z
|
|
1331
|
+
.object({
|
|
746
1332
|
linkedEntityType: crudEntityTypeSchema.optional(),
|
|
747
1333
|
linkedEntityId: nonEmptyTrimmedString.optional(),
|
|
748
1334
|
anchorKey: trimmedString.nullable().optional(),
|
|
749
1335
|
author: trimmedString.optional(),
|
|
750
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(),
|
|
751
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
|
+
}
|
|
752
1380
|
});
|
|
753
1381
|
export const taskListQuerySchema = z.object({
|
|
754
1382
|
status: taskStatusSchema.optional(),
|
|
@@ -777,13 +1405,270 @@ export const projectListQuerySchema = z.object({
|
|
|
777
1405
|
status: projectStatusSchema.optional(),
|
|
778
1406
|
limit: z.coerce.number().int().positive().max(100).optional()
|
|
779
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
|
+
});
|
|
1656
|
+
export const habitListQuerySchema = z.object({
|
|
1657
|
+
status: habitStatusSchema.optional(),
|
|
1658
|
+
polarity: habitPolaritySchema.optional(),
|
|
1659
|
+
dueToday: z.coerce.boolean().optional(),
|
|
1660
|
+
limit: z.coerce.number().int().positive().max(100).optional()
|
|
1661
|
+
});
|
|
780
1662
|
export const createGoalSchema = z.object({
|
|
781
1663
|
title: nonEmptyTrimmedString,
|
|
782
1664
|
description: trimmedString.default(""),
|
|
783
1665
|
horizon: goalHorizonSchema.default("year"),
|
|
784
1666
|
status: goalStatusSchema.default("active"),
|
|
785
1667
|
targetPoints: z.number().int().min(25).max(10000).default(400),
|
|
786
|
-
themeColor: z
|
|
1668
|
+
themeColor: z
|
|
1669
|
+
.string()
|
|
1670
|
+
.regex(/^#[0-9a-fA-F]{6}$/)
|
|
1671
|
+
.default("#c8a46b"),
|
|
787
1672
|
tagIds: uniqueStringArraySchema.default([]),
|
|
788
1673
|
notes: z.array(nestedCreateNoteSchema).default([])
|
|
789
1674
|
});
|
|
@@ -791,7 +1676,10 @@ export const updateGoalSchema = createGoalSchema.partial();
|
|
|
791
1676
|
export const createTagSchema = z.object({
|
|
792
1677
|
name: nonEmptyTrimmedString,
|
|
793
1678
|
kind: tagKindSchema.default("category"),
|
|
794
|
-
color: z
|
|
1679
|
+
color: z
|
|
1680
|
+
.string()
|
|
1681
|
+
.regex(/^#[0-9a-fA-F]{6}$/)
|
|
1682
|
+
.default("#71717a"),
|
|
795
1683
|
description: trimmedString.default("")
|
|
796
1684
|
});
|
|
797
1685
|
export const updateTagSchema = createTagSchema.partial();
|
|
@@ -801,7 +1689,22 @@ export const createProjectSchema = z.object({
|
|
|
801
1689
|
description: trimmedString.default(""),
|
|
802
1690
|
status: projectStatusSchema.default("active"),
|
|
803
1691
|
targetPoints: z.number().int().min(25).max(10000).default(240),
|
|
804
|
-
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
|
+
}),
|
|
805
1708
|
notes: z.array(nestedCreateNoteSchema).default([])
|
|
806
1709
|
});
|
|
807
1710
|
export const updateProjectSchema = createProjectSchema.partial();
|
|
@@ -817,11 +1720,84 @@ export const taskMutationShape = {
|
|
|
817
1720
|
effort: taskEffortSchema.default("deep"),
|
|
818
1721
|
energy: taskEnergySchema.default("steady"),
|
|
819
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),
|
|
820
1731
|
sortOrder: z.number().int().nonnegative().optional(),
|
|
821
1732
|
tagIds: uniqueStringArraySchema.default([]),
|
|
822
1733
|
notes: z.array(nestedCreateNoteSchema).default([])
|
|
823
1734
|
};
|
|
824
1735
|
export const createTaskSchema = z.object(taskMutationShape);
|
|
1736
|
+
const habitMutationShape = {
|
|
1737
|
+
title: nonEmptyTrimmedString,
|
|
1738
|
+
description: trimmedString.default(""),
|
|
1739
|
+
status: habitStatusSchema.default("active"),
|
|
1740
|
+
polarity: habitPolaritySchema.default("positive"),
|
|
1741
|
+
frequency: habitFrequencySchema.default("daily"),
|
|
1742
|
+
targetCount: z.number().int().min(1).max(14).default(1),
|
|
1743
|
+
weekDays: z.array(z.number().int().min(0).max(6)).max(7).default([]),
|
|
1744
|
+
linkedGoalIds: uniqueStringArraySchema.default([]),
|
|
1745
|
+
linkedProjectIds: uniqueStringArraySchema.default([]),
|
|
1746
|
+
linkedTaskIds: uniqueStringArraySchema.default([]),
|
|
1747
|
+
linkedValueIds: uniqueStringArraySchema.default([]),
|
|
1748
|
+
linkedPatternIds: uniqueStringArraySchema.default([]),
|
|
1749
|
+
linkedBehaviorIds: uniqueStringArraySchema.default([]),
|
|
1750
|
+
linkedBeliefIds: uniqueStringArraySchema.default([]),
|
|
1751
|
+
linkedModeIds: uniqueStringArraySchema.default([]),
|
|
1752
|
+
linkedReportIds: uniqueStringArraySchema.default([]),
|
|
1753
|
+
linkedBehaviorId: nonEmptyTrimmedString.nullable().default(null),
|
|
1754
|
+
rewardXp: z.number().int().min(1).max(100).default(12),
|
|
1755
|
+
penaltyXp: z.number().int().min(1).max(100).default(8)
|
|
1756
|
+
};
|
|
1757
|
+
export const createHabitSchema = z
|
|
1758
|
+
.object(habitMutationShape)
|
|
1759
|
+
.superRefine((value, context) => {
|
|
1760
|
+
if (value.frequency === "weekly" && value.weekDays.length === 0) {
|
|
1761
|
+
context.addIssue({
|
|
1762
|
+
code: z.ZodIssueCode.custom,
|
|
1763
|
+
path: ["weekDays"],
|
|
1764
|
+
message: "Select at least one weekday for weekly habits"
|
|
1765
|
+
});
|
|
1766
|
+
}
|
|
1767
|
+
});
|
|
1768
|
+
export const updateHabitSchema = z
|
|
1769
|
+
.object({
|
|
1770
|
+
title: nonEmptyTrimmedString.optional(),
|
|
1771
|
+
description: trimmedString.optional(),
|
|
1772
|
+
status: habitStatusSchema.optional(),
|
|
1773
|
+
polarity: habitPolaritySchema.optional(),
|
|
1774
|
+
frequency: habitFrequencySchema.optional(),
|
|
1775
|
+
targetCount: z.number().int().min(1).max(14).optional(),
|
|
1776
|
+
weekDays: z.array(z.number().int().min(0).max(6)).max(7).optional(),
|
|
1777
|
+
linkedGoalIds: uniqueStringArraySchema.optional(),
|
|
1778
|
+
linkedProjectIds: uniqueStringArraySchema.optional(),
|
|
1779
|
+
linkedTaskIds: uniqueStringArraySchema.optional(),
|
|
1780
|
+
linkedValueIds: uniqueStringArraySchema.optional(),
|
|
1781
|
+
linkedPatternIds: uniqueStringArraySchema.optional(),
|
|
1782
|
+
linkedBehaviorIds: uniqueStringArraySchema.optional(),
|
|
1783
|
+
linkedBeliefIds: uniqueStringArraySchema.optional(),
|
|
1784
|
+
linkedModeIds: uniqueStringArraySchema.optional(),
|
|
1785
|
+
linkedReportIds: uniqueStringArraySchema.optional(),
|
|
1786
|
+
linkedBehaviorId: nonEmptyTrimmedString.nullable().optional(),
|
|
1787
|
+
rewardXp: z.number().int().min(1).max(100).optional(),
|
|
1788
|
+
penaltyXp: z.number().int().min(1).max(100).optional()
|
|
1789
|
+
})
|
|
1790
|
+
.superRefine((value, context) => {
|
|
1791
|
+
if (value.frequency === "weekly" &&
|
|
1792
|
+
value.weekDays !== undefined &&
|
|
1793
|
+
value.weekDays.length === 0) {
|
|
1794
|
+
context.addIssue({
|
|
1795
|
+
code: z.ZodIssueCode.custom,
|
|
1796
|
+
path: ["weekDays"],
|
|
1797
|
+
message: "Select at least one weekday for weekly habits"
|
|
1798
|
+
});
|
|
1799
|
+
}
|
|
1800
|
+
});
|
|
825
1801
|
export const updateTaskSchema = z.object({
|
|
826
1802
|
title: nonEmptyTrimmedString.optional(),
|
|
827
1803
|
description: trimmedString.optional(),
|
|
@@ -834,6 +1810,14 @@ export const updateTaskSchema = z.object({
|
|
|
834
1810
|
effort: taskEffortSchema.optional(),
|
|
835
1811
|
energy: taskEnergySchema.optional(),
|
|
836
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(),
|
|
837
1821
|
sortOrder: z.number().int().nonnegative().optional(),
|
|
838
1822
|
tagIds: uniqueStringArraySchema.optional(),
|
|
839
1823
|
notes: z.array(nestedCreateNoteSchema).optional()
|
|
@@ -844,22 +1828,33 @@ export const tagSuggestionRequestSchema = z.object({
|
|
|
844
1828
|
goalId: nonEmptyTrimmedString.nullable().default(null),
|
|
845
1829
|
selectedTagIds: uniqueStringArraySchema.default([])
|
|
846
1830
|
});
|
|
847
|
-
export const taskRunClaimSchema = z
|
|
1831
|
+
export const taskRunClaimSchema = z
|
|
1832
|
+
.object({
|
|
848
1833
|
actor: nonEmptyTrimmedString,
|
|
849
1834
|
timerMode: taskTimerModeSchema.default("unlimited"),
|
|
850
|
-
plannedDurationSeconds: z.coerce
|
|
1835
|
+
plannedDurationSeconds: z.coerce
|
|
1836
|
+
.number()
|
|
1837
|
+
.int()
|
|
1838
|
+
.min(60)
|
|
1839
|
+
.max(86_400)
|
|
1840
|
+
.nullable()
|
|
1841
|
+
.default(null),
|
|
851
1842
|
isCurrent: z.coerce.boolean().default(true),
|
|
852
1843
|
leaseTtlSeconds: z.coerce.number().int().min(1).max(14400).default(900),
|
|
853
|
-
note: trimmedString.default("")
|
|
854
|
-
|
|
855
|
-
|
|
1844
|
+
note: trimmedString.default(""),
|
|
1845
|
+
overrideReason: trimmedString.optional()
|
|
1846
|
+
})
|
|
1847
|
+
.superRefine((value, context) => {
|
|
1848
|
+
if (value.timerMode === "planned" &&
|
|
1849
|
+
value.plannedDurationSeconds === null) {
|
|
856
1850
|
context.addIssue({
|
|
857
1851
|
code: z.ZodIssueCode.custom,
|
|
858
1852
|
path: ["plannedDurationSeconds"],
|
|
859
1853
|
message: "plannedDurationSeconds is required when timerMode is planned"
|
|
860
1854
|
});
|
|
861
1855
|
}
|
|
862
|
-
if (value.timerMode === "unlimited" &&
|
|
1856
|
+
if (value.timerMode === "unlimited" &&
|
|
1857
|
+
value.plannedDurationSeconds !== null) {
|
|
863
1858
|
context.addIssue({
|
|
864
1859
|
code: z.ZodIssueCode.custom,
|
|
865
1860
|
path: ["plannedDurationSeconds"],
|
|
@@ -870,7 +1865,8 @@ export const taskRunClaimSchema = z.object({
|
|
|
870
1865
|
export const taskRunHeartbeatSchema = z.object({
|
|
871
1866
|
actor: nonEmptyTrimmedString.optional(),
|
|
872
1867
|
leaseTtlSeconds: z.coerce.number().int().min(1).max(14400).default(900),
|
|
873
|
-
note: trimmedString.optional()
|
|
1868
|
+
note: trimmedString.optional(),
|
|
1869
|
+
overrideReason: trimmedString.optional()
|
|
874
1870
|
});
|
|
875
1871
|
export const taskRunFinishSchema = z.object({
|
|
876
1872
|
actor: nonEmptyTrimmedString.optional(),
|
|
@@ -880,6 +1876,11 @@ export const taskRunFinishSchema = z.object({
|
|
|
880
1876
|
export const taskRunFocusSchema = z.object({
|
|
881
1877
|
actor: nonEmptyTrimmedString.optional()
|
|
882
1878
|
});
|
|
1879
|
+
export const createHabitCheckInSchema = z.object({
|
|
1880
|
+
dateKey: dateOnlySchema.default(new Date().toISOString().slice(0, 10)),
|
|
1881
|
+
status: habitCheckInStatusSchema,
|
|
1882
|
+
note: trimmedString.default("")
|
|
1883
|
+
});
|
|
883
1884
|
export const updateSettingsSchema = z.object({
|
|
884
1885
|
profile: z
|
|
885
1886
|
.object({
|
|
@@ -895,6 +1896,17 @@ export const updateSettingsSchema = z.object({
|
|
|
895
1896
|
security: z
|
|
896
1897
|
.object({
|
|
897
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()
|
|
898
1910
|
})
|
|
899
1911
|
.optional()
|
|
900
1912
|
});
|
|
@@ -962,7 +1974,9 @@ export const resolveApprovalRequestSchema = z.object({
|
|
|
962
1974
|
export const createSessionEventSchema = z.object({
|
|
963
1975
|
sessionId: nonEmptyTrimmedString,
|
|
964
1976
|
eventType: nonEmptyTrimmedString,
|
|
965
|
-
metrics: z
|
|
1977
|
+
metrics: z
|
|
1978
|
+
.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()]))
|
|
1979
|
+
.default({})
|
|
966
1980
|
});
|
|
967
1981
|
export const removeActivityEventSchema = z.object({
|
|
968
1982
|
reason: trimmedString.default("Removed from the visible archive.")
|
|
@@ -977,41 +1991,50 @@ const crudEntityLinkSchema = z.object({
|
|
|
977
1991
|
});
|
|
978
1992
|
export const batchCreateEntitiesSchema = z.object({
|
|
979
1993
|
atomic: z.boolean().default(false),
|
|
980
|
-
operations: z
|
|
1994
|
+
operations: z
|
|
1995
|
+
.array(z.object({
|
|
981
1996
|
entityType: crudEntityTypeSchema,
|
|
982
1997
|
clientRef: trimmedString.optional(),
|
|
983
1998
|
data: z.record(z.string(), z.unknown())
|
|
984
|
-
}))
|
|
1999
|
+
}))
|
|
2000
|
+
.min(1)
|
|
985
2001
|
});
|
|
986
2002
|
export const batchUpdateEntitiesSchema = z.object({
|
|
987
2003
|
atomic: z.boolean().default(false),
|
|
988
|
-
operations: z
|
|
2004
|
+
operations: z
|
|
2005
|
+
.array(z.object({
|
|
989
2006
|
entityType: crudEntityTypeSchema,
|
|
990
2007
|
id: nonEmptyTrimmedString,
|
|
991
2008
|
clientRef: trimmedString.optional(),
|
|
992
2009
|
patch: z.record(z.string(), z.unknown())
|
|
993
|
-
}))
|
|
2010
|
+
}))
|
|
2011
|
+
.min(1)
|
|
994
2012
|
});
|
|
995
2013
|
export const batchDeleteEntitiesSchema = z.object({
|
|
996
2014
|
atomic: z.boolean().default(false),
|
|
997
|
-
operations: z
|
|
2015
|
+
operations: z
|
|
2016
|
+
.array(z.object({
|
|
998
2017
|
entityType: crudEntityTypeSchema,
|
|
999
2018
|
id: nonEmptyTrimmedString,
|
|
1000
2019
|
clientRef: trimmedString.optional(),
|
|
1001
2020
|
mode: deleteModeSchema.default("soft"),
|
|
1002
2021
|
reason: trimmedString.default("")
|
|
1003
|
-
}))
|
|
2022
|
+
}))
|
|
2023
|
+
.min(1)
|
|
1004
2024
|
});
|
|
1005
2025
|
export const batchRestoreEntitiesSchema = z.object({
|
|
1006
2026
|
atomic: z.boolean().default(false),
|
|
1007
|
-
operations: z
|
|
2027
|
+
operations: z
|
|
2028
|
+
.array(z.object({
|
|
1008
2029
|
entityType: crudEntityTypeSchema,
|
|
1009
2030
|
id: nonEmptyTrimmedString,
|
|
1010
2031
|
clientRef: trimmedString.optional()
|
|
1011
|
-
}))
|
|
2032
|
+
}))
|
|
2033
|
+
.min(1)
|
|
1012
2034
|
});
|
|
1013
2035
|
export const batchSearchEntitiesSchema = z.object({
|
|
1014
|
-
searches: z
|
|
2036
|
+
searches: z
|
|
2037
|
+
.array(z.object({
|
|
1015
2038
|
entityTypes: z.array(crudEntityTypeSchema).optional(),
|
|
1016
2039
|
query: trimmedString.optional(),
|
|
1017
2040
|
ids: uniqueStringArraySchema.optional(),
|
|
@@ -1020,7 +2043,8 @@ export const batchSearchEntitiesSchema = z.object({
|
|
|
1020
2043
|
includeDeleted: z.boolean().default(false),
|
|
1021
2044
|
limit: z.number().int().positive().max(200).default(25),
|
|
1022
2045
|
clientRef: trimmedString.optional()
|
|
1023
|
-
}))
|
|
2046
|
+
}))
|
|
2047
|
+
.min(1)
|
|
1024
2048
|
});
|
|
1025
2049
|
export const uncompleteTaskSchema = z.object({
|
|
1026
2050
|
status: taskStatusSchema.exclude(["done"]).default("focus")
|