@tuturuuu/ai 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +76 -0
  2. package/package.json +106 -0
  3. package/src/api-key-hash.ts +28 -0
  4. package/src/calendar/events.ts +34 -0
  5. package/src/calendar/route.ts +114 -0
  6. package/src/chat/credit-source.ts +1 -0
  7. package/src/chat/google/chat-request-schema.ts +150 -0
  8. package/src/chat/google/default-system-instruction.ts +198 -0
  9. package/src/chat/google/message-file-processing.ts +212 -0
  10. package/src/chat/google/mira-step-preparation.ts +221 -0
  11. package/src/chat/google/new/route.ts +368 -0
  12. package/src/chat/google/route-auth.ts +81 -0
  13. package/src/chat/google/route-chat-resolution.ts +98 -0
  14. package/src/chat/google/route-credits.ts +61 -0
  15. package/src/chat/google/route-message-preparation.ts +331 -0
  16. package/src/chat/google/route-mira-runtime.ts +206 -0
  17. package/src/chat/google/route.ts +632 -0
  18. package/src/chat/google/stream-finish-persistence.ts +722 -0
  19. package/src/chat/google/summary/route.ts +153 -0
  20. package/src/chat/mira-render-ui-policy.ts +540 -0
  21. package/src/chat/mira-system-instruction.ts +484 -0
  22. package/src/chat-sdk/adapters.ts +389 -0
  23. package/src/chat-sdk/registry.ts +197 -0
  24. package/src/chat-sdk.ts +33 -0
  25. package/src/core.ts +3 -0
  26. package/src/credits/cap-output-tokens.ts +90 -0
  27. package/src/credits/check-credits.ts +232 -0
  28. package/src/credits/constants.ts +30 -0
  29. package/src/credits/index.ts +46 -0
  30. package/src/credits/model-mapping.ts +92 -0
  31. package/src/credits/reservations.ts +514 -0
  32. package/src/credits/resolve-plan-model.ts +219 -0
  33. package/src/credits/sync-gateway-models.ts +351 -0
  34. package/src/credits/types.ts +109 -0
  35. package/src/credits/use-ai-credits.ts +3 -0
  36. package/src/embeddings/metered.ts +283 -0
  37. package/src/executions/route.ts +137 -0
  38. package/src/generate/route.ts +411 -0
  39. package/src/hooks.ts +7 -0
  40. package/src/meetings/summary/route.ts +7 -0
  41. package/src/meetings/transcription/route.ts +134 -0
  42. package/src/memory/client.ts +158 -0
  43. package/src/memory/config.ts +38 -0
  44. package/src/memory/index.ts +32 -0
  45. package/src/memory/ingest.ts +51 -0
  46. package/src/memory/middleware.ts +35 -0
  47. package/src/memory/operations.ts +480 -0
  48. package/src/memory/scope.ts +102 -0
  49. package/src/memory/settings.ts +121 -0
  50. package/src/memory/types.ts +101 -0
  51. package/src/memory/workspace.ts +36 -0
  52. package/src/memory.ts +1 -0
  53. package/src/mind/patch.ts +146 -0
  54. package/src/mind/route.ts +687 -0
  55. package/src/mind/tools.ts +1500 -0
  56. package/src/mind/types.ts +20 -0
  57. package/src/object/core.ts +3 -0
  58. package/src/object/flashcards/route.ts +140 -0
  59. package/src/object/quizzes/explanation/route.ts +145 -0
  60. package/src/object/quizzes/route.ts +142 -0
  61. package/src/object/types.ts +187 -0
  62. package/src/object/year-plan/route.ts +196 -0
  63. package/src/react.ts +1 -0
  64. package/src/scheduling/algorithm.ts +791 -0
  65. package/src/scheduling/default.ts +36 -0
  66. package/src/scheduling/duration-optimizer.ts +689 -0
  67. package/src/scheduling/index.ts +79 -0
  68. package/src/scheduling/priority-calculator.ts +187 -0
  69. package/src/scheduling/recurrence-calculator.ts +621 -0
  70. package/src/scheduling/templates.ts +892 -0
  71. package/src/scheduling/types.ts +136 -0
  72. package/src/scheduling/web-adapter.ts +308 -0
  73. package/src/scheduling.ts +6 -0
  74. package/src/supported-actions.ts +1 -0
  75. package/src/supported-providers.ts +6 -0
  76. package/src/tools/context-builder.ts +372 -0
  77. package/src/tools/core.ts +1 -0
  78. package/src/tools/definitions/calendar.ts +106 -0
  79. package/src/tools/definitions/finance.ts +197 -0
  80. package/src/tools/definitions/image.ts +74 -0
  81. package/src/tools/definitions/memory.ts +83 -0
  82. package/src/tools/definitions/meta.ts +154 -0
  83. package/src/tools/definitions/render-ui.ts +81 -0
  84. package/src/tools/definitions/tasks.ts +343 -0
  85. package/src/tools/definitions/time-tracking.ts +381 -0
  86. package/src/tools/definitions/workspace-context.ts +45 -0
  87. package/src/tools/definitions/workspace-user-chat.ts +111 -0
  88. package/src/tools/executors/calendar.ts +371 -0
  89. package/src/tools/executors/chat.ts +15 -0
  90. package/src/tools/executors/finance.ts +638 -0
  91. package/src/tools/executors/helpers/encryption.ts +107 -0
  92. package/src/tools/executors/image.ts +247 -0
  93. package/src/tools/executors/markitdown.ts +684 -0
  94. package/src/tools/executors/memory.ts +277 -0
  95. package/src/tools/executors/parallel-checks.ts +176 -0
  96. package/src/tools/executors/qr.ts +170 -0
  97. package/src/tools/executors/scope-helpers.ts +192 -0
  98. package/src/tools/executors/search.ts +149 -0
  99. package/src/tools/executors/settings.ts +40 -0
  100. package/src/tools/executors/tasks.ts +1087 -0
  101. package/src/tools/executors/theme.ts +23 -0
  102. package/src/tools/executors/timer/timer-categories-executor.ts +110 -0
  103. package/src/tools/executors/timer/timer-category-mutations.ts +240 -0
  104. package/src/tools/executors/timer/timer-goal-mutations.ts +323 -0
  105. package/src/tools/executors/timer/timer-goals-executor.ts +272 -0
  106. package/src/tools/executors/timer/timer-helpers.ts +372 -0
  107. package/src/tools/executors/timer/timer-mutation-schemas.ts +160 -0
  108. package/src/tools/executors/timer/timer-mutation-types.ts +212 -0
  109. package/src/tools/executors/timer/timer-mutations.ts +19 -0
  110. package/src/tools/executors/timer/timer-queries.ts +18 -0
  111. package/src/tools/executors/timer/timer-session-lifecycle.ts +299 -0
  112. package/src/tools/executors/timer/timer-session-mutations.ts +10 -0
  113. package/src/tools/executors/timer/timer-session-queries.ts +153 -0
  114. package/src/tools/executors/timer/timer-session-updates.ts +200 -0
  115. package/src/tools/executors/timer/timer-sessions-executor.ts +91 -0
  116. package/src/tools/executors/timer/timer-stats-executor.ts +157 -0
  117. package/src/tools/executors/timer.ts +22 -0
  118. package/src/tools/executors/user.ts +60 -0
  119. package/src/tools/executors/workspace.ts +135 -0
  120. package/src/tools/json-render-catalog.ts +875 -0
  121. package/src/tools/mira-tool-definitions.ts +55 -0
  122. package/src/tools/mira-tool-dispatcher.ts +265 -0
  123. package/src/tools/mira-tool-metadata.ts +164 -0
  124. package/src/tools/mira-tool-names.ts +95 -0
  125. package/src/tools/mira-tool-render-ui.ts +54 -0
  126. package/src/tools/mira-tool-types.ts +17 -0
  127. package/src/tools/mira-tools.ts +167 -0
  128. package/src/tools/normalize-render-ui-input.ts +321 -0
  129. package/src/tools/workspace-context.ts +233 -0
  130. package/src/types.ts +38 -0
@@ -0,0 +1,875 @@
1
+ import { defineCatalog } from '@json-render/core';
2
+ import { schema } from '@json-render/react/schema';
3
+ import { z } from 'zod';
4
+
5
+ export const dashboardCatalog = defineCatalog(schema, {
6
+ components: {
7
+ Card: {
8
+ props: z.object({
9
+ title: z
10
+ .string()
11
+ .optional()
12
+ .describe(
13
+ 'Card header title. Use this instead of a separate Text child for section headers.'
14
+ ),
15
+ description: z
16
+ .string()
17
+ .nullable()
18
+ .optional()
19
+ .describe('Optional subtitle below the title'),
20
+ }),
21
+ hasChildren: true,
22
+ description:
23
+ 'A styled container to group related content. Always use the `title` prop for section headers instead of adding a Text child.',
24
+ },
25
+ Stack: {
26
+ props: z.object({
27
+ direction: z
28
+ .enum(['vertical', 'horizontal'])
29
+ .optional()
30
+ .describe('Layout direction, defaults to vertical'),
31
+ gap: z.number().optional().describe('Gap between children in pixels'),
32
+ align: z
33
+ .enum(['start', 'center', 'end', 'stretch'])
34
+ .optional()
35
+ .describe('Alignment of children'),
36
+ justify: z
37
+ .enum(['start', 'center', 'end', 'between', 'around'])
38
+ .optional()
39
+ .describe('Justification of children'),
40
+ }),
41
+ hasChildren: true,
42
+ description: 'A flexible flexbox container for layout.',
43
+ },
44
+ Grid: {
45
+ props: z.object({
46
+ cols: z
47
+ .number()
48
+ .optional()
49
+ .describe('Number of columns, defaults to 1'),
50
+ gap: z.number().optional().describe('Gap between children in pixels'),
51
+ }),
52
+ hasChildren: true,
53
+ description: 'A grid container for multi-column layouts.',
54
+ },
55
+ Text: {
56
+ props: z.object({
57
+ content: z
58
+ .string()
59
+ .describe(
60
+ 'The text string to display. IMPORTANT: use "content", NOT "text".'
61
+ ),
62
+ variant: z
63
+ .enum(['h1', 'h2', 'h3', 'h4', 'p', 'small', 'tiny'])
64
+ .optional()
65
+ .describe(
66
+ 'Typography variant. Valid: h1, h2, h3, h4, p, small, tiny. Do NOT use "body".'
67
+ ),
68
+ weight: z
69
+ .enum(['normal', 'medium', 'semibold', 'bold'])
70
+ .optional()
71
+ .describe('Font weight'),
72
+ color: z
73
+ .enum(['default', 'muted', 'primary', 'success', 'warning', 'error'])
74
+ .optional()
75
+ .describe('Text color'),
76
+ align: z
77
+ .enum(['left', 'center', 'right'])
78
+ .optional()
79
+ .describe('Text alignment'),
80
+ }),
81
+ hasChildren: false,
82
+ description:
83
+ 'Renders text. The prop for the text string is `content` (NOT `text`). Example: { "content": "Hello", "variant": "p" }',
84
+ },
85
+ Icon: {
86
+ props: z.object({
87
+ name: z.string().describe('Name of the icon (e.g. "User", "Check")'),
88
+ size: z.number().optional().describe('Size in pixels, defaults to 16'),
89
+ color: z.string().optional().describe('Icon color (CSS color or hex)'),
90
+ }),
91
+ hasChildren: false,
92
+ description: 'Display an icon from the platform icon set.',
93
+ },
94
+ Badge: {
95
+ props: z.object({
96
+ label: z.string().describe('The label shown in the badge'),
97
+ variant: z
98
+ .enum([
99
+ 'default',
100
+ 'secondary',
101
+ 'outline',
102
+ 'success',
103
+ 'warning',
104
+ 'error',
105
+ ])
106
+ .optional()
107
+ .describe('Badge visual style'),
108
+ }),
109
+ hasChildren: false,
110
+ description: 'A small status indicator badge.',
111
+ },
112
+ Avatar: {
113
+ props: z.object({
114
+ src: z.string().optional().describe('URL of the image'),
115
+ fallback: z.string().optional().describe('Fallback initials'),
116
+ size: z.number().optional().describe('Size in pixels, defaults to 32'),
117
+ }),
118
+ hasChildren: false,
119
+ description: 'A circular profile image component.',
120
+ },
121
+ Separator: {
122
+ props: z.object({
123
+ orientation: z
124
+ .enum(['horizontal', 'vertical'])
125
+ .optional()
126
+ .describe('Orientation, defaults to horizontal'),
127
+ }),
128
+ hasChildren: false,
129
+ description: 'A visual line to separate content.',
130
+ },
131
+ Callout: {
132
+ props: z.object({
133
+ content: z
134
+ .string()
135
+ .describe('The callout message text. Use `content`, NOT `text`.'),
136
+ variant: z
137
+ .enum(['info', 'success', 'warning', 'error'])
138
+ .optional()
139
+ .describe('Callout style, defaults to info'),
140
+ title: z.string().optional().describe('Optional bold title'),
141
+ }),
142
+ hasChildren: false,
143
+ description:
144
+ 'A colored banner for informational messages (e.g. "No tasks today!", status updates). Use the `content` prop for the message text.',
145
+ },
146
+ ListItem: {
147
+ props: z.object({
148
+ title: z.string().describe('Primary text'),
149
+ subtitle: z
150
+ .string()
151
+ .optional()
152
+ .describe('Secondary text shown below the title'),
153
+ icon: z
154
+ .string()
155
+ .optional()
156
+ .describe(
157
+ 'Lucide icon name in PascalCase (e.g. "Calendar", "Wallet")'
158
+ ),
159
+ iconColor: z
160
+ .string()
161
+ .optional()
162
+ .describe('Custom color for the icon pill'),
163
+ trailing: z
164
+ .string()
165
+ .optional()
166
+ .describe('Optional trailing text (e.g. time, amount)'),
167
+ action: z
168
+ .string()
169
+ .optional()
170
+ .describe('Action key to trigger on click'),
171
+ }),
172
+ hasChildren: false,
173
+ description:
174
+ 'A structured row with icon, title, subtitle, and trailing text. Perfect for event lists, task items, transaction rows.',
175
+ },
176
+ Progress: {
177
+ props: z.object({
178
+ value: z.number().describe('Progress value from 0 to 100'),
179
+ label: z.string().optional().describe('Optional label'),
180
+ showValue: z
181
+ .boolean()
182
+ .optional()
183
+ .describe('Whether to show the percentage'),
184
+ color: z
185
+ .enum(['default', 'success', 'warning', 'error'])
186
+ .optional()
187
+ .describe(
188
+ 'Progress bar color. Defaults to auto: green >66, yellow >33, red ≤33'
189
+ ),
190
+ }),
191
+ hasChildren: false,
192
+ description: 'A progress bar component.',
193
+ },
194
+ Tabs: {
195
+ props: z.object({
196
+ tabs: z
197
+ .array(
198
+ z.object({
199
+ id: z.string().describe('Unique ID for the tab'),
200
+ label: z.string().describe('Display label for the tab'),
201
+ })
202
+ )
203
+ .describe('List of tabs to show'),
204
+ defaultTab: z.string().optional().describe('ID of the default tab'),
205
+ }),
206
+ hasChildren: true,
207
+ description:
208
+ 'A tabbed interface. Children should be elements that respond to the active tab state (visible when tab matches).',
209
+ },
210
+ BarChart: {
211
+ props: z.object({
212
+ data: z
213
+ .array(
214
+ z.object({
215
+ label: z.string().describe('Label for the bar'),
216
+ value: z
217
+ .number()
218
+ .describe('Value for the bar (0-100 recommended)'),
219
+ color: z
220
+ .string()
221
+ .optional()
222
+ .describe('Hex color or dynamic token'),
223
+ })
224
+ )
225
+ .describe('Data points for the chart'),
226
+ height: z.number().optional().describe('Chart height in pixels'),
227
+ }),
228
+ hasChildren: false,
229
+ description:
230
+ 'A simple vertical bar chart for visualizing lists of numbers.',
231
+ },
232
+ ArticleHeader: {
233
+ props: z.object({
234
+ eyebrow: z
235
+ .string()
236
+ .optional()
237
+ .describe('Small context label shown above the title'),
238
+ title: z.string().describe('Main article title'),
239
+ subtitle: z
240
+ .string()
241
+ .optional()
242
+ .describe('Supporting subtitle under the title'),
243
+ byline: z.string().optional().describe('Author or analyst line'),
244
+ publishedAt: z
245
+ .string()
246
+ .optional()
247
+ .describe('Published or updated date text'),
248
+ readingTime: z
249
+ .string()
250
+ .optional()
251
+ .describe('Estimated reading time (e.g. "4 min read")'),
252
+ }),
253
+ hasChildren: false,
254
+ description:
255
+ 'Hero-style heading block for blog/news content with title, subtitle, and metadata.',
256
+ },
257
+ InsightSection: {
258
+ props: z.object({
259
+ title: z.string().describe('Section heading'),
260
+ summary: z
261
+ .string()
262
+ .optional()
263
+ .describe('Optional short section summary'),
264
+ tone: z
265
+ .enum(['neutral', 'positive', 'warning', 'critical'])
266
+ .optional()
267
+ .describe('Visual emphasis style'),
268
+ }),
269
+ hasChildren: true,
270
+ description:
271
+ 'Structured section wrapper for article-like analysis. Place supporting Text/List components as children.',
272
+ },
273
+ KeyPoints: {
274
+ props: z.object({
275
+ title: z
276
+ .string()
277
+ .optional()
278
+ .describe('Optional heading for the key points block'),
279
+ points: z
280
+ .array(z.string())
281
+ .min(1)
282
+ .describe('Bullet or numbered key points'),
283
+ ordered: z
284
+ .boolean()
285
+ .optional()
286
+ .describe('Render numbered list when true'),
287
+ }),
288
+ hasChildren: false,
289
+ description:
290
+ 'Compact bullet/numbered list for takeaways, action items, or summary points.',
291
+ },
292
+ SourceList: {
293
+ props: z.object({
294
+ title: z
295
+ .string()
296
+ .optional()
297
+ .describe('Optional heading for the sources section'),
298
+ compact: z
299
+ .boolean()
300
+ .optional()
301
+ .describe(
302
+ 'Use compact 2-column source chips when true (default true)'
303
+ ),
304
+ showUrl: z
305
+ .boolean()
306
+ .optional()
307
+ .describe(
308
+ 'Show shortened URL preview under each source (default false)'
309
+ ),
310
+ sources: z
311
+ .array(
312
+ z.object({
313
+ title: z
314
+ .string()
315
+ .describe(
316
+ 'Human-readable source title (never paste full URL here)'
317
+ ),
318
+ url: z.httpUrl().describe('Source URL'),
319
+ publisher: z
320
+ .string()
321
+ .optional()
322
+ .describe(
323
+ 'Publisher/domain label like "Microsoft" or "InfoWorld"'
324
+ ),
325
+ note: z
326
+ .string()
327
+ .optional()
328
+ .describe('Optional short context note (keep concise)'),
329
+ })
330
+ )
331
+ .min(1)
332
+ .describe('List of sources'),
333
+ }),
334
+ hasChildren: false,
335
+ description:
336
+ 'Reference list with clickable links for research/news responses.',
337
+ },
338
+ Stat: {
339
+ props: z.object({
340
+ label: z.string().describe('Short label'),
341
+ value: z.string().describe('Stat value'),
342
+ icon: z.string().optional().describe('Lucide icon name'),
343
+ }),
344
+ hasChildren: false,
345
+ description: 'A compact, inline-friendly version of Metric.',
346
+ },
347
+ Metric: {
348
+ props: z.object({
349
+ title: z.string().describe('The name of the metric'),
350
+ value: z.string().describe('The value to display'),
351
+ trend: z
352
+ .enum(['up', 'down', 'neutral'])
353
+ .optional()
354
+ .describe('The trend of the metric'),
355
+ trendValue: z
356
+ .string()
357
+ .optional()
358
+ .describe('The trend value to display, e.g. "+5%"'),
359
+ }),
360
+ hasChildren: false,
361
+ description: 'A component used to display a single, prominent metric.',
362
+ },
363
+ MyTasks: {
364
+ props: z.object({
365
+ showSummary: z
366
+ .boolean()
367
+ .optional()
368
+ .describe('Whether to show the task summary cards'),
369
+ showFilters: z
370
+ .boolean()
371
+ .optional()
372
+ .describe('Whether to show the task filter bar'),
373
+ }),
374
+ hasChildren: false,
375
+ description: "A component that renders the user's current task list.",
376
+ },
377
+ TimeTrackingStats: {
378
+ props: z
379
+ .object({
380
+ period: z
381
+ .enum([
382
+ 'today',
383
+ 'this_week',
384
+ 'this_month',
385
+ 'last_7_days',
386
+ 'last_30_days',
387
+ 'custom',
388
+ ])
389
+ .optional()
390
+ .describe('Stats period preset. Defaults to last_7_days.'),
391
+ dateFrom: z
392
+ .string()
393
+ .datetime({ offset: true })
394
+ .optional()
395
+ .describe(
396
+ 'Custom period start ISO datetime (required when period=custom).'
397
+ ),
398
+ dateTo: z
399
+ .string()
400
+ .datetime({ offset: true })
401
+ .optional()
402
+ .describe(
403
+ 'Custom period end ISO datetime (required when period=custom).'
404
+ ),
405
+ showBreakdown: z
406
+ .boolean()
407
+ .optional()
408
+ .describe('Show category breakdown list (default true).'),
409
+ showDailyBreakdown: z
410
+ .boolean()
411
+ .optional()
412
+ .describe('Show daily breakdown list (default true).'),
413
+ maxItems: z
414
+ .number()
415
+ .int()
416
+ .min(1)
417
+ .max(10)
418
+ .optional()
419
+ .describe('Maximum rows for breakdown sections (default 5).'),
420
+ })
421
+ .superRefine((data, ctx) => {
422
+ if (data.period !== 'custom') return;
423
+
424
+ if (!data.dateFrom) {
425
+ ctx.addIssue({
426
+ code: z.ZodIssueCode.custom,
427
+ path: ['dateFrom'],
428
+ message: 'dateFrom is required when period is custom',
429
+ });
430
+ }
431
+
432
+ if (!data.dateTo) {
433
+ ctx.addIssue({
434
+ code: z.ZodIssueCode.custom,
435
+ path: ['dateTo'],
436
+ message: 'dateTo is required when period is custom',
437
+ });
438
+ }
439
+ }),
440
+ hasChildren: false,
441
+ description:
442
+ 'A standardized time-tracking stats dashboard that fetches and displays period metrics and breakdowns.',
443
+ },
444
+ Form: {
445
+ props: z.object({
446
+ title: z.string().describe('Form title to display'),
447
+ description: z.string().optional().describe('Form description'),
448
+ submitLabel: z
449
+ .string()
450
+ .optional()
451
+ .describe('Text for the submit button, defaults to "Submit"'),
452
+ submitAction: z
453
+ .string()
454
+ .optional()
455
+ .describe(
456
+ 'The name of the action to trigger on submit (e.g. "submit_form")'
457
+ ),
458
+ submitParams: z
459
+ .record(z.string(), z.unknown())
460
+ .optional()
461
+ .describe('Optional static params merged into submit payload'),
462
+ onSubmit: z
463
+ .unknown()
464
+ .optional()
465
+ .describe(
466
+ 'Binding for the submit action; value is validated later by action schemas at submit time.'
467
+ ),
468
+ }),
469
+ hasChildren: true,
470
+ description:
471
+ 'A form container for capturing user input. Should contain Input and other form elements, and trigger a submit action.',
472
+ },
473
+ Input: {
474
+ props: z.object({
475
+ name: z.string().describe('Field name/ID'),
476
+ label: z.string().describe('Field label shown to user'),
477
+ placeholder: z.string().optional().describe('Placeholder text'),
478
+ required: z
479
+ .boolean()
480
+ .optional()
481
+ .describe('Whether the field is required'),
482
+ type: z
483
+ .enum(['text', 'number', 'email', 'password', 'datetime-local'])
484
+ .optional()
485
+ .describe('Input type, defaults to text'),
486
+ value: z
487
+ .union([z.string(), z.number()])
488
+ .optional()
489
+ .describe(
490
+ 'Input value binding; value is validated later by action schemas at submit time.'
491
+ ),
492
+ }),
493
+ hasChildren: false,
494
+ description: 'A text or number input field for a Form.',
495
+ },
496
+ FileAttachmentInput: {
497
+ props: z.object({
498
+ name: z.string().describe('Field name/ID'),
499
+ label: z.string().describe('Field label shown to user'),
500
+ description: z.string().optional().describe('Optional helper text'),
501
+ required: z
502
+ .boolean()
503
+ .optional()
504
+ .describe('Whether at least one file is required'),
505
+ maxFiles: z
506
+ .number()
507
+ .int()
508
+ .min(1)
509
+ .max(5)
510
+ .optional()
511
+ .describe('Maximum files allowed'),
512
+ accept: z
513
+ .string()
514
+ .optional()
515
+ .describe('Accepted mime types or extensions'),
516
+ value: z
517
+ .unknown()
518
+ .optional()
519
+ .describe(
520
+ 'Attachment value binding; value is validated later by action schemas at submit time.'
521
+ ),
522
+ }),
523
+ hasChildren: false,
524
+ description:
525
+ 'An attachment picker for forms that need evidence images or file uploads.',
526
+ },
527
+ Textarea: {
528
+ props: z.object({
529
+ name: z.string().describe('Field name/ID'),
530
+ label: z.string().describe('Field label shown to user'),
531
+ placeholder: z.string().optional().describe('Placeholder text'),
532
+ required: z
533
+ .boolean()
534
+ .optional()
535
+ .describe('Whether the field is required'),
536
+ rows: z.number().optional().describe('Number of rows'),
537
+ value: z
538
+ .string()
539
+ .optional()
540
+ .describe(
541
+ 'Textarea value binding; value is validated later by action schemas at submit time.'
542
+ ),
543
+ }),
544
+ hasChildren: false,
545
+ description: 'A multi-line text input field for a Form.',
546
+ },
547
+ Checkbox: {
548
+ props: z.object({
549
+ name: z.string().describe('Field name/ID'),
550
+ label: z.string().describe('Label shown next to checkbox'),
551
+ description: z.string().optional().describe('Optional description'),
552
+ required: z
553
+ .boolean()
554
+ .optional()
555
+ .describe('Whether the field is required'),
556
+ checked: z
557
+ .unknown()
558
+ .optional()
559
+ .describe(
560
+ 'Checkbox checked binding; value is validated later by action schemas at submit time.'
561
+ ),
562
+ }),
563
+ hasChildren: false,
564
+ description: 'A single checkbox component.',
565
+ },
566
+ CheckboxGroup: {
567
+ props: z.object({
568
+ name: z.string().describe('Field name/ID'),
569
+ label: z.string().describe('Group label'),
570
+ options: z
571
+ .array(
572
+ z.object({
573
+ label: z.string(),
574
+ value: z.string(),
575
+ })
576
+ )
577
+ .describe('Options to choose from'),
578
+ required: z
579
+ .boolean()
580
+ .optional()
581
+ .describe('Whether at least one option is required'),
582
+ values: z
583
+ .unknown()
584
+ .optional()
585
+ .describe(
586
+ 'Checkbox group values binding; value is validated later by action schemas at submit time.'
587
+ ),
588
+ }),
589
+ hasChildren: false,
590
+ description: 'A group of checkboxes for multiple selection.',
591
+ },
592
+ RadioGroup: {
593
+ props: z.object({
594
+ name: z.string().describe('Field name/ID'),
595
+ label: z.string().describe('Group label'),
596
+ options: z
597
+ .array(
598
+ z.object({
599
+ label: z.string(),
600
+ value: z.string(),
601
+ })
602
+ )
603
+ .describe('Options to choose from'),
604
+ required: z
605
+ .boolean()
606
+ .optional()
607
+ .describe('Whether an option is required'),
608
+ value: z
609
+ .unknown()
610
+ .optional()
611
+ .describe(
612
+ 'Radio group value binding; value is validated later by action schemas at submit time.'
613
+ ),
614
+ }),
615
+ hasChildren: false,
616
+ description: 'A group of radio buttons for single selection.',
617
+ },
618
+ Select: {
619
+ props: z.object({
620
+ name: z.string().describe('Field name/ID'),
621
+ label: z.string().describe('Select label'),
622
+ placeholder: z.string().optional().describe('Placeholder text'),
623
+ options: z
624
+ .array(
625
+ z.object({
626
+ label: z.string(),
627
+ value: z.string(),
628
+ })
629
+ )
630
+ .describe('Options to choose from'),
631
+ required: z
632
+ .boolean()
633
+ .optional()
634
+ .describe('Whether the field is required'),
635
+ value: z
636
+ .unknown()
637
+ .optional()
638
+ .describe(
639
+ 'Select value binding; value is validated later by action schemas at submit time.'
640
+ ),
641
+ }),
642
+ hasChildren: false,
643
+ description: 'A dropdown select component.',
644
+ },
645
+ Button: {
646
+ props: z.object({
647
+ label: z.string().describe('Button text'),
648
+ variant: z
649
+ .enum([
650
+ 'default',
651
+ 'secondary',
652
+ 'destructive',
653
+ 'outline',
654
+ 'ghost',
655
+ 'link',
656
+ ])
657
+ .optional()
658
+ .describe('Button visual style'),
659
+ size: z.enum(['default', 'sm', 'lg', 'icon']).optional(),
660
+ icon: z.string().optional().describe('Lucide icon name'),
661
+ action: z.string().optional().describe('Action key to trigger'),
662
+ }),
663
+ hasChildren: false,
664
+ description:
665
+ 'A button to trigger an action within a Form or interactive component.',
666
+ },
667
+ Flashcard: {
668
+ props: z.object({
669
+ front: z.string().describe('Text for the front of the flashcard'),
670
+ back: z.string().describe('Text for the back of the flashcard'),
671
+ randomize: z
672
+ .boolean()
673
+ .optional()
674
+ .describe('Whether to randomize side on start'),
675
+ }),
676
+ hasChildren: false,
677
+ description: 'An interactive flashcard that flips when clicked.',
678
+ },
679
+ MultiFlashcard: {
680
+ props: z.object({
681
+ title: z.string().optional().describe('Title of the flashcard session'),
682
+ description: z
683
+ .string()
684
+ .optional()
685
+ .describe('Description or instructions'),
686
+ flashcards: z
687
+ .array(
688
+ z.object({
689
+ front: z.string().describe('Text for the front'),
690
+ back: z.string().describe('Text for the back'),
691
+ })
692
+ )
693
+ .describe('Array of flashcards'),
694
+ randomize: z
695
+ .boolean()
696
+ .optional()
697
+ .describe('Whether to randomize flashcard order'),
698
+ }),
699
+ hasChildren: false,
700
+ description: 'A collection of interactive flashcards with navigation.',
701
+ },
702
+ Quiz: {
703
+ props: z.object({
704
+ question: z.string().describe('The quiz question'),
705
+ options: z
706
+ .array(z.string())
707
+ .min(1)
708
+ .describe('An array of string options for the quiz'),
709
+ answer: z
710
+ .string()
711
+ .describe(
712
+ 'The correct option (must exactly match one of the options)'
713
+ ),
714
+ explanation: z
715
+ .string()
716
+ .optional()
717
+ .describe('Explanation shown after answering'),
718
+ randomize: z
719
+ .boolean()
720
+ .optional()
721
+ .describe('Whether to randomize option order'),
722
+ }),
723
+ hasChildren: false,
724
+ description: 'An interactive multiple-choice quiz question.',
725
+ },
726
+ MultiQuiz: {
727
+ props: z.object({
728
+ title: z
729
+ .string()
730
+ .optional()
731
+ .describe('Title of the multi-quiz session'),
732
+ description: z
733
+ .string()
734
+ .optional()
735
+ .describe('Description or instructions'),
736
+ quizzes: z
737
+ .array(
738
+ z.object({
739
+ question: z.string().describe('The quiz question'),
740
+ options: z
741
+ .array(z.string())
742
+ .min(1)
743
+ .describe('An array of string options'),
744
+ answer: z.string().describe('The correct option'),
745
+ explanation: z
746
+ .string()
747
+ .optional()
748
+ .describe('Explanation shown after answering'),
749
+ })
750
+ )
751
+ .min(1)
752
+ .describe('Array of quiz questions'),
753
+ randomize: z
754
+ .boolean()
755
+ .optional()
756
+ .describe('Whether to randomize quiz order'),
757
+ }),
758
+ hasChildren: false,
759
+ description:
760
+ 'An interactive multi-question quiz with navigation and scoring.',
761
+ },
762
+ },
763
+ actions: {
764
+ submit_form: {
765
+ params: z.object({
766
+ title: z.string().describe('The title of the form being submitted'),
767
+ values: z
768
+ .record(z.string(), z.unknown())
769
+ .describe('The values of the form fields'),
770
+ }),
771
+ description: 'Submit a generic form back to the assistant.',
772
+ },
773
+ log_transaction: {
774
+ params: z.object({
775
+ amount: z
776
+ .number()
777
+ .describe('Amount (positive=income, negative=expense)'),
778
+ description: z.string().nullable().describe('What was this for?'),
779
+ walletId: z
780
+ .guid()
781
+ .nullable()
782
+ .describe('Wallet UUID. If null, uses the first wallet.'),
783
+ }),
784
+ description:
785
+ 'Log a financial transaction directly from a generated UI form.',
786
+ },
787
+ create_time_tracking_request: {
788
+ params: z
789
+ .object({
790
+ wsId: z.string().describe('Workspace ID slug or UUID'),
791
+ requestId: z
792
+ .guid()
793
+ .optional()
794
+ .describe('Request UUID used for storage prefix'),
795
+ title: z.string().describe('Request title'),
796
+ description: z
797
+ .string()
798
+ .optional()
799
+ .describe('Optional request details'),
800
+ categoryId: z
801
+ .guid()
802
+ .nullable()
803
+ .optional()
804
+ .describe('Category UUID or null'),
805
+ taskId: z.guid().nullable().optional().describe('Task UUID or null'),
806
+ date: z
807
+ .string()
808
+ .optional()
809
+ .describe(
810
+ 'Optional base date (YYYY-MM-DD) when using HH:mm inputs'
811
+ ),
812
+ startTime: z
813
+ .string()
814
+ .describe(
815
+ 'Start time (ISO 8601, YYYY-MM-DD HH:mm, or HH:mm with date)'
816
+ ),
817
+ endTime: z
818
+ .string()
819
+ .describe(
820
+ 'End time (ISO 8601, YYYY-MM-DD HH:mm, or HH:mm with date)'
821
+ ),
822
+ imagePaths: z
823
+ .array(z.string())
824
+ .max(5)
825
+ .optional()
826
+ .describe('Optional pre-uploaded storage paths (max 5).'),
827
+ })
828
+ .superRefine((data, ctx) => {
829
+ const paths = data.imagePaths ?? [];
830
+ if (paths.length === 0) return;
831
+
832
+ if (!data.requestId) {
833
+ ctx.addIssue({
834
+ code: z.ZodIssueCode.custom,
835
+ path: ['requestId'],
836
+ message: 'requestId is required when imagePaths are provided',
837
+ });
838
+ return;
839
+ }
840
+
841
+ for (let index = 0; index < paths.length; index++) {
842
+ const path = paths[index];
843
+ if (!path?.startsWith(`${data.requestId}/`)) {
844
+ ctx.addIssue({
845
+ code: z.ZodIssueCode.custom,
846
+ path: ['imagePaths', index],
847
+ message: `Each image path must start with \`${data.requestId}/\` when requestId is provided`,
848
+ });
849
+ }
850
+ }
851
+ }),
852
+ description:
853
+ 'Submit a time tracking missed-entry request with optional evidence attachments.',
854
+ },
855
+ __ui_action__: {
856
+ params: z.object({
857
+ id: z
858
+ .string()
859
+ .optional()
860
+ .describe('Action identifier from Button/ListItem props.action'),
861
+ label: z
862
+ .string()
863
+ .optional()
864
+ .describe('Optional display label from the clicked component'),
865
+ source: z
866
+ .enum(['button', 'list-item', 'ui'])
867
+ .optional()
868
+ .describe('Origin of the action trigger'),
869
+ }),
870
+ description:
871
+ 'Generic follow-up action emitted when a clickable generated UI element is activated.',
872
+ },
873
+ },
874
+ // @json-render's catalog type is tied to its bundled Zod minor.
875
+ } as never);