@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,136 @@
1
+ import type { TaskPriority } from '@tuturuuu/types/primitives/Priority';
2
+ import type dayjs from 'dayjs';
3
+
4
+ export interface DateRange {
5
+ start: dayjs.Dayjs;
6
+ end: dayjs.Dayjs;
7
+ }
8
+
9
+ export interface Event {
10
+ id: string;
11
+ name: string;
12
+ range: DateRange;
13
+ taskId: string;
14
+ partNumber?: number;
15
+ totalParts?: number;
16
+ locked?: boolean;
17
+ reason?: string;
18
+ }
19
+ export type TimeOfDayPreference = 'morning' | 'afternoon' | 'evening' | 'night';
20
+
21
+ export interface Task {
22
+ id: string;
23
+ name: string;
24
+ duration: number;
25
+ minDuration: number;
26
+ maxDuration: number;
27
+ category: 'work' | 'personal' | 'meeting';
28
+ priority: TaskPriority;
29
+ deadline?: dayjs.Dayjs;
30
+ allowSplit?: boolean;
31
+ streak?: number;
32
+ energyLoad?: 'high' | 'medium' | 'low';
33
+ isHabit?: boolean;
34
+ timePreference?: TimeOfDayPreference;
35
+ }
36
+
37
+ export type EnergyProfile =
38
+ | 'morning_person'
39
+ | 'night_owl'
40
+ | 'afternoon_peak'
41
+ | 'evening_peak';
42
+
43
+ export interface SchedulingSettings {
44
+ min_buffer?: number;
45
+ preferred_buffer?: number;
46
+ }
47
+
48
+ export interface ActiveHours {
49
+ personal: DateRange[];
50
+ work: DateRange[];
51
+ meeting: DateRange[];
52
+ }
53
+
54
+ export interface Log {
55
+ type: 'warning' | 'error';
56
+ message: string;
57
+ }
58
+
59
+ export interface ScheduleResult {
60
+ events: Event[];
61
+ logs: Log[];
62
+ }
63
+
64
+ export interface TemplateScenario {
65
+ name: string;
66
+ description: string;
67
+ tasks: Task[];
68
+ activeHours?: Partial<ActiveHours>;
69
+ }
70
+
71
+ // ============================================================================
72
+ // Web Integration Types
73
+ // These types bridge the web app task format to the scheduling algorithm
74
+ // ============================================================================
75
+
76
+ export type CalendarHoursType =
77
+ | 'work_hours'
78
+ | 'personal_hours'
79
+ | 'meeting_hours';
80
+
81
+ /**
82
+ * Input format for scheduling tasks from the web app
83
+ */
84
+ export interface WebTaskInput {
85
+ id: string;
86
+ name?: string | null;
87
+ description?: string | null;
88
+ total_duration?: number | null; // hours
89
+ is_splittable?: boolean | null;
90
+ min_split_duration_minutes?: number | null;
91
+ max_split_duration_minutes?: number | null;
92
+ calendar_hours?: CalendarHoursType | null;
93
+ priority?: TaskPriority | null;
94
+ start_date?: string | null;
95
+ end_date?: string | null; // deadline
96
+ streak?: number | null;
97
+ energy_load?: 'high' | 'medium' | 'low' | null;
98
+ is_habit?: boolean | null;
99
+ }
100
+
101
+ /**
102
+ * Existing calendar event from the web app
103
+ */
104
+ export interface WebCalendarEvent {
105
+ id?: string;
106
+ start_at: string;
107
+ end_at: string;
108
+ }
109
+
110
+ /**
111
+ * Result of scheduling with web-friendly format
112
+ */
113
+ export interface WebScheduleResult {
114
+ success: boolean;
115
+ events: Array<{
116
+ id: string;
117
+ title: string;
118
+ start_at: string;
119
+ end_at: string;
120
+ task_id: string;
121
+ partNumber?: number;
122
+ totalParts?: number;
123
+ reason?: string;
124
+ }>;
125
+ totalScheduledMinutes: number;
126
+ message: string;
127
+ warning?: string;
128
+ logs: Log[];
129
+ }
130
+
131
+ export interface SchedulingWeights {
132
+ habitIdealTimeBonus?: number;
133
+ habitPreferenceBonus?: number;
134
+ taskPreferenceBonus?: number;
135
+ taskBaseEarlyBonus?: number;
136
+ }
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Web Adapter for Task Scheduling
3
+ *
4
+ * This module bridges the web app's task format to the scheduling algorithm.
5
+ * It converts between web task format and the internal scheduler format.
6
+ */
7
+
8
+ import type { TaskPriority } from '@tuturuuu/types/primitives/Priority';
9
+ import dayjs from 'dayjs';
10
+ import { scheduleTasks } from './algorithm';
11
+ import type {
12
+ ActiveHours,
13
+ CalendarHoursType,
14
+ DateRange,
15
+ Event,
16
+ Task,
17
+ WebCalendarEvent,
18
+ WebScheduleResult,
19
+ WebTaskInput,
20
+ } from './types';
21
+
22
+ /**
23
+ * Map web calendar hours type to scheduler category
24
+ */
25
+ export function mapCalendarHoursToCategory(
26
+ calendarHours: CalendarHoursType | null | undefined
27
+ ): 'work' | 'personal' | 'meeting' {
28
+ switch (calendarHours) {
29
+ case 'personal_hours':
30
+ return 'personal';
31
+ case 'meeting_hours':
32
+ return 'meeting';
33
+ default:
34
+ return 'work';
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Convert web task format to scheduler task format
40
+ */
41
+ export function convertWebTaskToSchedulerTask(
42
+ task: WebTaskInput,
43
+ existingScheduledMinutes: number = 0
44
+ ): Task {
45
+ const totalHours = task.total_duration ?? 0;
46
+ const scheduledHours = existingScheduledMinutes / 60;
47
+ const remainingHours = Math.max(0, totalHours - scheduledHours);
48
+
49
+ // Convert minutes to hours for min/max duration
50
+ const minDurationHours = (task.min_split_duration_minutes ?? 30) / 60;
51
+ const maxDurationHours = (task.max_split_duration_minutes ?? 120) / 60;
52
+
53
+ return {
54
+ id: task.id,
55
+ name: task.name || 'Task',
56
+ duration: remainingHours,
57
+ minDuration: minDurationHours,
58
+ maxDuration: maxDurationHours,
59
+ category: mapCalendarHoursToCategory(task.calendar_hours),
60
+ priority: (task.priority as TaskPriority) ?? 'normal',
61
+ deadline: task.end_date ? dayjs(task.end_date) : undefined,
62
+ allowSplit: task.is_splittable ?? true,
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Convert multiple web tasks to scheduler tasks, sorted by deadline
68
+ */
69
+ export function convertWebTasksToSchedulerTasks(
70
+ tasks: Array<{ task: WebTaskInput; existingScheduledMinutes?: number }>
71
+ ): Task[] {
72
+ return tasks
73
+ .map(({ task, existingScheduledMinutes }) =>
74
+ convertWebTaskToSchedulerTask(task, existingScheduledMinutes ?? 0)
75
+ )
76
+ .sort((a, b) => {
77
+ // Sort by deadline (earliest first, null deadlines last)
78
+ if (!a.deadline && !b.deadline) return 0;
79
+ if (!a.deadline) return 1;
80
+ if (!b.deadline) return -1;
81
+ return a.deadline.valueOf() - b.deadline.valueOf();
82
+ });
83
+ }
84
+
85
+ /**
86
+ * Convert existing web calendar events to locked events format
87
+ */
88
+ export function convertWebEventsToLocked(events: WebCalendarEvent[]): Event[] {
89
+ return events.map((e, i) => ({
90
+ id: e.id || `existing-${i}`,
91
+ name: 'Existing Event',
92
+ range: {
93
+ start: dayjs(e.start_at),
94
+ end: dayjs(e.end_at),
95
+ },
96
+ taskId: '',
97
+ locked: true,
98
+ }));
99
+ }
100
+
101
+ /**
102
+ * Convert week time ranges to ActiveHours format
103
+ * This converts the web app's hour settings to the scheduler's format
104
+ */
105
+ export function convertHourSettingsToActiveHours(hourSettings: {
106
+ personalHours?: {
107
+ [day: string]: {
108
+ enabled: boolean;
109
+ timeBlocks: Array<{ startTime: string; endTime: string }>;
110
+ };
111
+ };
112
+ workHours?: {
113
+ [day: string]: {
114
+ enabled: boolean;
115
+ timeBlocks: Array<{ startTime: string; endTime: string }>;
116
+ };
117
+ };
118
+ meetingHours?: {
119
+ [day: string]: {
120
+ enabled: boolean;
121
+ timeBlocks: Array<{ startTime: string; endTime: string }>;
122
+ };
123
+ };
124
+ }): ActiveHours {
125
+ const convertTimeBlocks = (
126
+ hours:
127
+ | {
128
+ [day: string]: {
129
+ enabled: boolean;
130
+ timeBlocks: Array<{ startTime: string; endTime: string }>;
131
+ };
132
+ }
133
+ | undefined
134
+ ): DateRange[] => {
135
+ if (!hours) {
136
+ // Default: 9am-5pm
137
+ return [
138
+ {
139
+ start: dayjs().hour(9).minute(0).second(0).millisecond(0),
140
+ end: dayjs().hour(17).minute(0).second(0).millisecond(0),
141
+ },
142
+ ];
143
+ }
144
+
145
+ // For simplicity, we'll use the first enabled day's time blocks
146
+ // In a more complex implementation, you'd handle per-day scheduling
147
+ const ranges: DateRange[] = [];
148
+
149
+ for (const dayConfig of Object.values(hours)) {
150
+ if (dayConfig.enabled && dayConfig.timeBlocks.length > 0) {
151
+ for (const block of dayConfig.timeBlocks) {
152
+ const [startHour, startMin] = block.startTime.split(':').map(Number);
153
+ const [endHour, endMin] = block.endTime.split(':').map(Number);
154
+
155
+ ranges.push({
156
+ start: dayjs()
157
+ .hour(startHour ?? 9)
158
+ .minute(startMin ?? 0)
159
+ .second(0)
160
+ .millisecond(0),
161
+ end: dayjs()
162
+ .hour(endHour ?? 17)
163
+ .minute(endMin ?? 0)
164
+ .second(0)
165
+ .millisecond(0),
166
+ });
167
+ }
168
+ break; // Use first enabled day's config
169
+ }
170
+ }
171
+
172
+ if (ranges.length === 0) {
173
+ // Fallback to default
174
+ return [
175
+ {
176
+ start: dayjs().hour(9).minute(0).second(0).millisecond(0),
177
+ end: dayjs().hour(17).minute(0).second(0).millisecond(0),
178
+ },
179
+ ];
180
+ }
181
+
182
+ return ranges;
183
+ };
184
+
185
+ return {
186
+ personal: convertTimeBlocks(hourSettings.personalHours),
187
+ work: convertTimeBlocks(hourSettings.workHours),
188
+ meeting: convertTimeBlocks(hourSettings.meetingHours),
189
+ };
190
+ }
191
+
192
+ /**
193
+ * Schedule a single task using the AI package algorithm
194
+ */
195
+ export function scheduleWebTask(
196
+ task: WebTaskInput,
197
+ existingEvents: WebCalendarEvent[],
198
+ activeHours: ActiveHours,
199
+ existingScheduledMinutes: number = 0
200
+ ): WebScheduleResult {
201
+ const schedulerTask = convertWebTaskToSchedulerTask(
202
+ task,
203
+ existingScheduledMinutes
204
+ );
205
+ const lockedEvents = convertWebEventsToLocked(existingEvents);
206
+
207
+ const result = scheduleTasks([schedulerTask], activeHours, lockedEvents);
208
+
209
+ // Convert result to web format
210
+ const scheduledEvents = result.events.filter((e) => !e.locked);
211
+ const totalScheduledMinutes = scheduledEvents.reduce((sum, e) => {
212
+ const durationMinutes = e.range.end.diff(e.range.start, 'minute');
213
+ return sum + durationMinutes;
214
+ }, 0);
215
+
216
+ const pastDeadlineWarnings = result.logs.filter(
217
+ (log) => log.type === 'warning' && log.message.includes('past its deadline')
218
+ );
219
+
220
+ return {
221
+ success: scheduledEvents.length > 0,
222
+ events: scheduledEvents.map((e) => ({
223
+ id: e.id,
224
+ title: e.name,
225
+ start_at: e.range.start.toISOString(),
226
+ end_at: e.range.end.toISOString(),
227
+ task_id: task.id,
228
+ partNumber: e.partNumber,
229
+ totalParts: e.totalParts,
230
+ reason: e.reason,
231
+ })),
232
+ totalScheduledMinutes: existingScheduledMinutes + totalScheduledMinutes,
233
+ message:
234
+ scheduledEvents.length > 0
235
+ ? `Scheduled ${totalScheduledMinutes} minutes across ${scheduledEvents.length} event(s)`
236
+ : 'No available time slots found',
237
+ warning:
238
+ pastDeadlineWarnings.length > 0
239
+ ? 'Some events scheduled after the deadline'
240
+ : undefined,
241
+ logs: result.logs,
242
+ };
243
+ }
244
+
245
+ /**
246
+ * Schedule multiple tasks using the AI package algorithm
247
+ * Tasks are scheduled in deadline order (earliest first)
248
+ */
249
+ export function scheduleWebTasks(
250
+ tasks: Array<{ task: WebTaskInput; existingScheduledMinutes?: number }>,
251
+ existingEvents: WebCalendarEvent[],
252
+ activeHours: ActiveHours
253
+ ): WebScheduleResult[] {
254
+ const schedulerTasks = convertWebTasksToSchedulerTasks(tasks);
255
+ const lockedEvents = convertWebEventsToLocked(existingEvents);
256
+
257
+ const result = scheduleTasks(schedulerTasks, activeHours, lockedEvents);
258
+
259
+ // Group events by task ID
260
+ const eventsByTask = new Map<string, Event[]>();
261
+ for (const event of result.events) {
262
+ if (event.locked) continue;
263
+ const taskEvents = eventsByTask.get(event.taskId) || [];
264
+ taskEvents.push(event);
265
+ eventsByTask.set(event.taskId, taskEvents);
266
+ }
267
+
268
+ // Convert to web results for each task
269
+ return tasks.map(({ task, existingScheduledMinutes = 0 }) => {
270
+ const taskEvents = eventsByTask.get(task.id) || [];
271
+ const totalScheduledMinutes = taskEvents.reduce((sum, e) => {
272
+ const durationMinutes = e.range.end.diff(e.range.start, 'minute');
273
+ return sum + durationMinutes;
274
+ }, 0);
275
+
276
+ const taskLogs = result.logs.filter((log) =>
277
+ log.message.includes(task.name || task.id)
278
+ );
279
+ const pastDeadlineWarnings = taskLogs.filter(
280
+ (log) =>
281
+ log.type === 'warning' && log.message.includes('past its deadline')
282
+ );
283
+
284
+ return {
285
+ success: taskEvents.length > 0,
286
+ events: taskEvents.map((e) => ({
287
+ id: e.id,
288
+ title: e.name,
289
+ start_at: e.range.start.toISOString(),
290
+ end_at: e.range.end.toISOString(),
291
+ task_id: task.id,
292
+ partNumber: e.partNumber,
293
+ totalParts: e.totalParts,
294
+ reason: e.reason,
295
+ })),
296
+ totalScheduledMinutes: existingScheduledMinutes + totalScheduledMinutes,
297
+ message:
298
+ taskEvents.length > 0
299
+ ? `Scheduled ${totalScheduledMinutes} minutes across ${taskEvents.length} event(s)`
300
+ : 'No available time slots found',
301
+ warning:
302
+ pastDeadlineWarnings.length > 0
303
+ ? 'Some events scheduled after the deadline'
304
+ : undefined,
305
+ logs: taskLogs,
306
+ };
307
+ });
308
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Task Scheduling Module
3
+ *
4
+ * Re-exports from the scheduling directory for package exports compatibility.
5
+ */
6
+ export * from './scheduling/index';
@@ -0,0 +1 @@
1
+ export const supportedActions = ['new', 'summary'] as const;
@@ -0,0 +1,6 @@
1
+ export const supportedProviders = [
2
+ 'google',
3
+ 'google-vertex',
4
+ 'openai',
5
+ 'anthropic',
6
+ ] as const;