@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,381 @@
1
+ import { z } from 'zod';
2
+ import { tool } from '../core';
3
+
4
+ const flexibleDateTimeInputSchema = z.string();
5
+
6
+ export const timeTrackingToolDefinitions = {
7
+ start_timer: tool({
8
+ description:
9
+ 'Start a time tracking session. Stops any currently running timer first.',
10
+ inputSchema: z.object({
11
+ title: z.string().describe('What are you working on?'),
12
+ description: z
13
+ .string()
14
+ .nullish()
15
+ .describe('Additional details, or null/omit'),
16
+ }),
17
+ }),
18
+
19
+ stop_timer: tool({
20
+ description: 'Stop the currently running time tracking session.',
21
+ inputSchema: z.object({
22
+ sessionId: z
23
+ .string()
24
+ .nullish()
25
+ .describe('Session UUID, or null/omit for active session'),
26
+ }),
27
+ }),
28
+
29
+ list_time_tracking_sessions: tool({
30
+ description:
31
+ 'List your time tracking sessions with cursor pagination. By default pending approval sessions are excluded.',
32
+ inputSchema: z.object({
33
+ limit: z
34
+ .number()
35
+ .int()
36
+ .min(1)
37
+ .max(50)
38
+ .optional()
39
+ .describe('Page size (default 20, max 50)'),
40
+ cursor: z
41
+ .string()
42
+ .optional()
43
+ .describe('Pagination cursor from previous response (start_time|id)'),
44
+ includePending: z
45
+ .boolean()
46
+ .optional()
47
+ .describe('Whether to include pending approval sessions'),
48
+ }),
49
+ }),
50
+
51
+ get_time_tracking_session: tool({
52
+ description:
53
+ 'Get one specific time tracking session by ID in the current workspace.',
54
+ inputSchema: z
55
+ .object({
56
+ sessionId: z.string().optional().describe('Session UUID'),
57
+ id: z
58
+ .string()
59
+ .optional()
60
+ .describe('Alias for sessionId. Use either sessionId or id.'),
61
+ })
62
+ .refine((data) => Boolean(data.sessionId || data.id), {
63
+ message: 'sessionId or id is required',
64
+ path: ['sessionId'],
65
+ }),
66
+ }),
67
+
68
+ create_time_tracking_entry: tool({
69
+ description:
70
+ 'Create a manual (stopped) time tracking entry. If approval is required, it returns requiresApproval=true with next-step guidance for the user/UI to complete approval.',
71
+ inputSchema: z.object({
72
+ title: z.string().describe('Entry title'),
73
+ description: z
74
+ .string()
75
+ .nullish()
76
+ .describe('Entry description, or null/omit'),
77
+ categoryId: z
78
+ .string()
79
+ .nullish()
80
+ .describe('Time tracking category UUID, or null/omit'),
81
+ taskId: z.string().nullish().describe('Task UUID, or null/omit'),
82
+ startTime: flexibleDateTimeInputSchema.describe(
83
+ 'Start time. Accepts ISO 8601, YYYY-MM-DD HH:mm, or HH:mm when date is provided'
84
+ ),
85
+ endTime: flexibleDateTimeInputSchema.describe(
86
+ 'End time. Accepts ISO 8601, YYYY-MM-DD HH:mm, or HH:mm when date is provided'
87
+ ),
88
+ date: z
89
+ .string()
90
+ .optional()
91
+ .describe('Date anchor (YYYY-MM-DD) required when using HH:mm inputs'),
92
+ }),
93
+ }),
94
+
95
+ update_time_tracking_session: tool({
96
+ description:
97
+ 'Update fields of an existing time tracking session. Recomputes duration when times change.',
98
+ inputSchema: z
99
+ .object({
100
+ sessionId: z.string().optional().describe('Session UUID'),
101
+ id: z
102
+ .string()
103
+ .optional()
104
+ .describe('Alias for sessionId. Use either sessionId or id.'),
105
+ title: z.string().optional().describe('Updated title'),
106
+ description: z
107
+ .string()
108
+ .nullable()
109
+ .optional()
110
+ .describe('Updated description'),
111
+ categoryId: z
112
+ .string()
113
+ .nullable()
114
+ .optional()
115
+ .describe('Updated category UUID'),
116
+ taskId: z.string().nullable().optional().describe('Updated task UUID'),
117
+ startTime: flexibleDateTimeInputSchema
118
+ .optional()
119
+ .describe(
120
+ 'Updated start time. Accepts ISO 8601, YYYY-MM-DD HH:mm, or HH:mm when date is provided'
121
+ ),
122
+ endTime: flexibleDateTimeInputSchema
123
+ .optional()
124
+ .describe(
125
+ 'Updated end time. Accepts ISO 8601, YYYY-MM-DD HH:mm, or HH:mm when date is provided'
126
+ ),
127
+ date: z
128
+ .string()
129
+ .optional()
130
+ .describe(
131
+ 'Date anchor (YYYY-MM-DD) required when using HH:mm inputs'
132
+ ),
133
+ })
134
+ .refine((data) => Boolean(data.sessionId || data.id), {
135
+ message: 'sessionId or id is required',
136
+ path: ['sessionId'],
137
+ }),
138
+ }),
139
+
140
+ delete_time_tracking_session: tool({
141
+ description: 'Delete a time tracking session by ID.',
142
+ inputSchema: z
143
+ .object({
144
+ sessionId: z.string().optional().describe('Session UUID'),
145
+ id: z
146
+ .string()
147
+ .optional()
148
+ .describe('Alias for sessionId. Use either sessionId or id.'),
149
+ })
150
+ .refine((data) => Boolean(data.sessionId || data.id), {
151
+ message: 'sessionId or id is required',
152
+ path: ['sessionId'],
153
+ }),
154
+ }),
155
+
156
+ move_time_tracking_session: tool({
157
+ description:
158
+ 'Move a stopped session to another workspace after membership checks, with category/task remapping by name.',
159
+ inputSchema: z
160
+ .object({
161
+ sessionId: z.string().optional().describe('Session UUID'),
162
+ id: z
163
+ .string()
164
+ .optional()
165
+ .describe('Alias for sessionId. Use either sessionId or id.'),
166
+ targetWorkspaceId: z.string().describe('Destination workspace UUID'),
167
+ })
168
+ .refine((data) => Boolean(data.sessionId || data.id), {
169
+ message: 'sessionId or id is required',
170
+ path: ['sessionId'],
171
+ }),
172
+ }),
173
+
174
+ get_time_tracker_stats: tool({
175
+ description:
176
+ 'Get time-tracker summary stats (today/week/month/streak) and daily activity for insights.',
177
+ inputSchema: z.object({
178
+ timezone: z
179
+ .string()
180
+ .optional()
181
+ .describe(
182
+ 'IANA timezone (defaults to your current chat timezone or UTC)'
183
+ ),
184
+ summaryOnly: z
185
+ .boolean()
186
+ .optional()
187
+ .describe('When true, skip daily activity history (default true)'),
188
+ daysBack: z
189
+ .number()
190
+ .int()
191
+ .min(1)
192
+ .max(3650)
193
+ .optional()
194
+ .describe(
195
+ 'How many days of daily activity to include when summaryOnly=false (default 365)'
196
+ ),
197
+ }),
198
+ }),
199
+
200
+ get_time_tracker_goals: tool({
201
+ description:
202
+ 'List your time-tracker goals (optionally including inactive goals) and computed daily/weekly progress.',
203
+ inputSchema: z.object({
204
+ includeInactive: z
205
+ .boolean()
206
+ .optional()
207
+ .describe('Include inactive goals (default false)'),
208
+ timezone: z
209
+ .string()
210
+ .optional()
211
+ .describe('IANA timezone used for progress calculations'),
212
+ includeProgress: z
213
+ .boolean()
214
+ .optional()
215
+ .describe(
216
+ 'Include daily/weekly progress percentages using current stats (default true)'
217
+ ),
218
+ }),
219
+ }),
220
+
221
+ list_time_tracking_categories: tool({
222
+ description:
223
+ 'List time-tracking categories in the current workspace so you can map category names to category IDs.',
224
+ inputSchema: z.object({
225
+ cursor: z
226
+ .string()
227
+ .optional()
228
+ .describe('Pagination cursor from previous response (name|id)'),
229
+ limit: z
230
+ .number()
231
+ .int()
232
+ .min(1)
233
+ .max(50)
234
+ .optional()
235
+ .describe('Page size (default 20, max 50)'),
236
+ }),
237
+ }),
238
+
239
+ create_time_tracking_category: tool({
240
+ description: 'Create a time-tracking category in the current workspace.',
241
+ inputSchema: z.object({
242
+ name: z.string().describe('Category name'),
243
+ description: z
244
+ .string()
245
+ .nullish()
246
+ .describe('Category description, or null/omit'),
247
+ color: z
248
+ .string()
249
+ .nullish()
250
+ .describe('Category color token, or null/omit (defaults to BLUE)'),
251
+ }),
252
+ }),
253
+
254
+ update_time_tracking_category: tool({
255
+ description: 'Update a time-tracking category by categoryId (or id alias).',
256
+ inputSchema: z
257
+ .object({
258
+ categoryId: z.string().optional().describe('Category UUID'),
259
+ id: z
260
+ .string()
261
+ .optional()
262
+ .describe('Alias for categoryId. Use either categoryId or id.'),
263
+ name: z.string().nullish().describe('Updated category name'),
264
+ description: z
265
+ .string()
266
+ .nullish()
267
+ .describe('Updated category description, or null to clear'),
268
+ color: z
269
+ .string()
270
+ .nullish()
271
+ .describe('Updated category color token, or null'),
272
+ })
273
+ .refine((data) => Boolean(data.categoryId || data.id), {
274
+ message: 'categoryId or id is required',
275
+ path: ['categoryId'],
276
+ })
277
+ .refine(
278
+ (data) =>
279
+ data.name !== undefined ||
280
+ data.description !== undefined ||
281
+ data.color !== undefined,
282
+ {
283
+ message: 'At least one updatable field is required',
284
+ path: ['name'],
285
+ }
286
+ ),
287
+ }),
288
+
289
+ delete_time_tracking_category: tool({
290
+ description: 'Delete a time-tracking category by categoryId (or id alias).',
291
+ inputSchema: z
292
+ .object({
293
+ categoryId: z.string().optional().describe('Category UUID'),
294
+ id: z
295
+ .string()
296
+ .optional()
297
+ .describe('Alias for categoryId. Use either categoryId or id.'),
298
+ })
299
+ .refine((data) => Boolean(data.categoryId || data.id), {
300
+ message: 'categoryId or id is required',
301
+ path: ['categoryId'],
302
+ }),
303
+ }),
304
+
305
+ create_time_tracker_goal: tool({
306
+ description:
307
+ 'Create a new time-tracker goal for the current workspace/user.',
308
+ inputSchema: z.object({
309
+ categoryId: z
310
+ .string()
311
+ .nullish()
312
+ .describe(
313
+ 'Time tracking category UUID. Use "general", null, or omit for non-category goal.'
314
+ ),
315
+ dailyGoalMinutes: z
316
+ .number()
317
+ .int()
318
+ .min(1)
319
+ .describe('Required daily target in minutes (must be > 0)'),
320
+ weeklyGoalMinutes: z
321
+ .number()
322
+ .int()
323
+ .min(1)
324
+ .nullish()
325
+ .describe('Optional weekly target in minutes. Use null/omit to clear'),
326
+ isActive: z.boolean().optional().describe('Whether goal is active'),
327
+ }),
328
+ }),
329
+
330
+ update_time_tracker_goal: tool({
331
+ description:
332
+ 'Update an existing time-tracker goal by goalId (or id alias).',
333
+ inputSchema: z
334
+ .object({
335
+ goalId: z.string().optional().describe('Goal UUID'),
336
+ id: z
337
+ .string()
338
+ .optional()
339
+ .describe('Alias for goalId. Use either goalId or id.'),
340
+ categoryId: z
341
+ .string()
342
+ .nullish()
343
+ .describe(
344
+ 'Time tracking category UUID. Use "general", null, or empty to clear.'
345
+ ),
346
+ dailyGoalMinutes: z
347
+ .number()
348
+ .int()
349
+ .min(1)
350
+ .optional()
351
+ .describe('Updated daily target in minutes (must be > 0)'),
352
+ weeklyGoalMinutes: z
353
+ .number()
354
+ .int()
355
+ .min(1)
356
+ .nullish()
357
+ .describe('Updated weekly target in minutes. Use null/omit to clear'),
358
+ isActive: z.boolean().optional().describe('Updated active flag'),
359
+ })
360
+ .refine((data) => Boolean(data.goalId || data.id), {
361
+ message: 'goalId or id is required',
362
+ path: ['goalId'],
363
+ }),
364
+ }),
365
+
366
+ delete_time_tracker_goal: tool({
367
+ description: 'Delete a time-tracker goal by goalId (or id alias).',
368
+ inputSchema: z
369
+ .object({
370
+ goalId: z.string().optional().describe('Goal UUID'),
371
+ id: z
372
+ .string()
373
+ .optional()
374
+ .describe('Alias for goalId. Use either goalId or id.'),
375
+ })
376
+ .refine((data) => Boolean(data.goalId || data.id), {
377
+ message: 'goalId or id is required',
378
+ path: ['goalId'],
379
+ }),
380
+ }),
381
+ } as const;
@@ -0,0 +1,45 @@
1
+ import { z } from 'zod';
2
+ import { tool } from '../core';
3
+
4
+ export const workspaceContextToolDefinitions = {
5
+ list_accessible_workspaces: tool({
6
+ description:
7
+ 'List all workspaces the user can access, including member counts. Use this before switching workspace context.',
8
+ inputSchema: z.object({}),
9
+ }),
10
+
11
+ get_workspace_context: tool({
12
+ description:
13
+ 'Show the current workspace context used for personal task, calendar, and finance queries. Defaults to the personal workspace.',
14
+ inputSchema: z.object({}),
15
+ }),
16
+
17
+ set_workspace_context: tool({
18
+ description:
19
+ 'Switch the current workspace context for task, calendar, and finance tools. Use `list_accessible_workspaces` first to get the target workspace ID. Use `personal` to switch back to the personal workspace.',
20
+ inputSchema: z
21
+ .object({
22
+ workspaceId: z
23
+ .string()
24
+ .trim()
25
+ .min(1)
26
+ .optional()
27
+ .describe('Target workspace ID, `internal`, or `personal`.'),
28
+ workspaceContextId: z
29
+ .string()
30
+ .trim()
31
+ .min(1)
32
+ .optional()
33
+ .describe(
34
+ 'Alias for workspaceId. Accepts a workspace UUID, `internal`, or `personal`.'
35
+ ),
36
+ })
37
+ .refine(
38
+ (value) => Boolean(value.workspaceId || value.workspaceContextId),
39
+ {
40
+ message: 'workspaceId is required.',
41
+ path: ['workspaceId'],
42
+ }
43
+ ),
44
+ }),
45
+ } as const;
@@ -0,0 +1,111 @@
1
+ import { z } from 'zod';
2
+ import { tool } from '../core';
3
+
4
+ type SettingsLikeData = {
5
+ name?: unknown;
6
+ tone?: unknown;
7
+ personality?: unknown;
8
+ boundaries?: unknown;
9
+ vibe?: unknown;
10
+ chat_tone?: unknown;
11
+ displayName?: unknown;
12
+ fullName?: unknown;
13
+ };
14
+
15
+ const hasAtLeastOneFieldProvided = (data: SettingsLikeData): boolean =>
16
+ [
17
+ data.name,
18
+ data.tone,
19
+ data.personality,
20
+ data.boundaries,
21
+ data.vibe,
22
+ data.chat_tone,
23
+ data.displayName,
24
+ data.fullName,
25
+ ].some((value) => value !== null && value !== undefined);
26
+
27
+ export const workspaceUserChatToolDefinitions = {
28
+ update_my_settings: tool({
29
+ description:
30
+ "Update YOUR OWN (the assistant's) personality. The `name` field is YOUR name, not the user's. Use `remember` for user's name.",
31
+ inputSchema: z
32
+ .object({
33
+ name: z.string().max(50).nullish().describe('New assistant name'),
34
+ tone: z
35
+ .enum([
36
+ 'balanced',
37
+ 'casual',
38
+ 'formal',
39
+ 'friendly',
40
+ 'playful',
41
+ 'professional',
42
+ 'warm',
43
+ ])
44
+ .nullish()
45
+ .describe('Communication tone'),
46
+ personality: z
47
+ .string()
48
+ .max(2000)
49
+ .nullish()
50
+ .describe('Personality description / behavioral preferences'),
51
+ boundaries: z
52
+ .string()
53
+ .max(2000)
54
+ .nullish()
55
+ .describe('Custom boundaries'),
56
+ vibe: z
57
+ .enum([
58
+ 'calm',
59
+ 'energetic',
60
+ 'friendly',
61
+ 'neutral',
62
+ 'playful',
63
+ 'warm',
64
+ 'witty',
65
+ ])
66
+ .nullish()
67
+ .describe('Energy/vibe'),
68
+ chat_tone: z
69
+ .enum(['thorough', 'concise', 'detailed', 'brief'])
70
+ .nullish()
71
+ .describe('Response verbosity'),
72
+ })
73
+ .refine((data) => hasAtLeastOneFieldProvided(data), {
74
+ message: 'At least one field must be provided',
75
+ }),
76
+ }),
77
+
78
+ set_theme: tool({
79
+ description:
80
+ 'Switch the UI theme. Use when user asks for dark mode, light mode, or system theme.',
81
+ inputSchema: z.object({
82
+ theme: z.enum(['light', 'dark', 'system']).describe('Theme to apply'),
83
+ }),
84
+ }),
85
+
86
+ list_workspace_members: tool({
87
+ description:
88
+ 'List all members of the current workspace context from `workspace_members`. Use `get_workspace_context` to inspect the active workspace first, and `list_accessible_workspaces` + `set_workspace_context` when the user names another workspace.',
89
+ inputSchema: z.object({}),
90
+ }),
91
+
92
+ update_user_name: tool({
93
+ description: "Update the user's display name or full name.",
94
+ inputSchema: z
95
+ .object({
96
+ displayName: z.string().nullish().describe('New display name'),
97
+ fullName: z.string().nullish().describe('New full name'),
98
+ })
99
+ .refine((data) => hasAtLeastOneFieldProvided(data), {
100
+ message: 'At least one field must be provided',
101
+ }),
102
+ }),
103
+
104
+ set_immersive_mode: tool({
105
+ description:
106
+ 'Enter or exit immersive fullscreen mode for the current chat.',
107
+ inputSchema: z.object({
108
+ enabled: z.boolean().describe('Whether to enable immersive mode'),
109
+ }),
110
+ }),
111
+ } as const;