@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,192 @@
1
+ import { verifyWorkspaceMembershipType } from '@tuturuuu/utils/workspace-helper';
2
+ import type { MiraToolContext } from '../mira-tools';
3
+ import { getWorkspaceContextWorkspaceId } from '../workspace-context';
4
+
5
+ function normalizeRelation<T>(value: T | T[] | null | undefined): T | null {
6
+ if (!value) return null;
7
+ return Array.isArray(value) ? (value[0] ?? null) : value;
8
+ }
9
+
10
+ export type TaskScope = {
11
+ id: string;
12
+ boardId: string | null;
13
+ listId: string | null;
14
+ };
15
+
16
+ export async function hasWorkspaceBoardAccess(
17
+ ctx: MiraToolContext,
18
+ boardId: string
19
+ ): Promise<boolean> {
20
+ const { data, error } = await ctx.supabase
21
+ .from('workspace_boards')
22
+ .select('id')
23
+ .eq('id', boardId)
24
+ .eq('ws_id', getWorkspaceContextWorkspaceId(ctx))
25
+ .maybeSingle();
26
+
27
+ if (error) {
28
+ throw new Error(error.message);
29
+ }
30
+
31
+ return Boolean(data);
32
+ }
33
+
34
+ export async function hasTaskListAccess(
35
+ ctx: MiraToolContext,
36
+ listId: string
37
+ ): Promise<boolean> {
38
+ const { data, error } = await ctx.supabase
39
+ .from('task_lists')
40
+ .select('id, workspace_boards!inner(ws_id)')
41
+ .eq('id', listId)
42
+ .maybeSingle();
43
+
44
+ if (error) {
45
+ throw new Error(error.message);
46
+ }
47
+
48
+ const board = normalizeRelation(
49
+ data?.workspace_boards as { ws_id: string } | { ws_id: string }[] | null
50
+ );
51
+
52
+ return board?.ws_id === getWorkspaceContextWorkspaceId(ctx);
53
+ }
54
+
55
+ export async function hasTaskAccess(
56
+ ctx: MiraToolContext,
57
+ taskId: string
58
+ ): Promise<boolean> {
59
+ return Boolean(await getTaskScope(ctx, taskId));
60
+ }
61
+
62
+ export async function getTaskScope(
63
+ ctx: MiraToolContext,
64
+ taskId: string
65
+ ): Promise<TaskScope | null> {
66
+ const { data, error } = await ctx.supabase
67
+ .from('tasks')
68
+ .select('id, board_id, list_id')
69
+ .eq('id', taskId)
70
+ .maybeSingle();
71
+
72
+ if (error) {
73
+ throw new Error(error.message);
74
+ }
75
+
76
+ if (!data) {
77
+ return null;
78
+ }
79
+
80
+ const taskScope: TaskScope = {
81
+ id: data.id,
82
+ boardId: data.board_id ?? null,
83
+ listId: data.list_id ?? null,
84
+ };
85
+
86
+ if (taskScope.boardId) {
87
+ if (await hasWorkspaceBoardAccess(ctx, taskScope.boardId)) {
88
+ return taskScope;
89
+ }
90
+ return null;
91
+ }
92
+
93
+ if (taskScope.listId) {
94
+ if (await hasTaskListAccess(ctx, taskScope.listId)) {
95
+ return taskScope;
96
+ }
97
+ }
98
+
99
+ return null;
100
+ }
101
+
102
+ export async function hasProjectAccess(
103
+ ctx: MiraToolContext,
104
+ projectId: string
105
+ ): Promise<boolean> {
106
+ const { data, error } = await ctx.supabase
107
+ .from('task_projects')
108
+ .select('id')
109
+ .eq('id', projectId)
110
+ .eq('ws_id', getWorkspaceContextWorkspaceId(ctx))
111
+ .maybeSingle();
112
+
113
+ if (error) {
114
+ throw new Error(error.message);
115
+ }
116
+
117
+ return Boolean(data);
118
+ }
119
+
120
+ export async function hasWalletAccess(
121
+ ctx: MiraToolContext,
122
+ walletId: string
123
+ ): Promise<boolean> {
124
+ const { data, error } = await ctx.supabase
125
+ .schema('private')
126
+ .from('workspace_wallets')
127
+ .select('id')
128
+ .eq('id', walletId)
129
+ .eq('ws_id', getWorkspaceContextWorkspaceId(ctx))
130
+ .maybeSingle();
131
+
132
+ if (error) {
133
+ throw new Error(error.message);
134
+ }
135
+
136
+ return Boolean(data);
137
+ }
138
+
139
+ export async function hasTransactionCategoryAccess(
140
+ ctx: MiraToolContext,
141
+ categoryId: string
142
+ ): Promise<boolean> {
143
+ const { data, error } = await ctx.supabase
144
+ .from('transaction_categories')
145
+ .select('id')
146
+ .eq('id', categoryId)
147
+ .eq('ws_id', getWorkspaceContextWorkspaceId(ctx))
148
+ .maybeSingle();
149
+
150
+ if (error) {
151
+ throw new Error(error.message);
152
+ }
153
+
154
+ return Boolean(data);
155
+ }
156
+
157
+ export async function hasTimeTrackingCategoryAccess(
158
+ ctx: MiraToolContext,
159
+ categoryId: string
160
+ ): Promise<boolean> {
161
+ const { data, error } = await ctx.supabase
162
+ .from('time_tracking_categories')
163
+ .select('id')
164
+ .eq('id', categoryId)
165
+ .eq('ws_id', getWorkspaceContextWorkspaceId(ctx))
166
+ .maybeSingle();
167
+
168
+ if (error) {
169
+ throw new Error(error.message);
170
+ }
171
+
172
+ return Boolean(data);
173
+ }
174
+
175
+ export async function isWorkspaceMember(
176
+ ctx: MiraToolContext,
177
+ userId: string,
178
+ workspaceId = getWorkspaceContextWorkspaceId(ctx)
179
+ ): Promise<boolean> {
180
+ const result = await verifyWorkspaceMembershipType({
181
+ wsId: workspaceId,
182
+ userId,
183
+ supabase: ctx.supabase,
184
+ requiredType: 'MEMBER',
185
+ });
186
+
187
+ if (result.error === 'membership_lookup_failed') {
188
+ throw new Error('Membership lookup failed');
189
+ }
190
+
191
+ return result.ok;
192
+ }
@@ -0,0 +1,149 @@
1
+ import { google } from '@ai-sdk/google';
2
+ import { generateText, stepCountIs } from 'ai';
3
+ import { z } from 'zod';
4
+ import { withAiMemory } from '../../memory';
5
+ import type { MiraToolContext } from '../mira-tools';
6
+
7
+ const SEARCH_WRAPPER_MODEL = 'gemini-3.1-flash-lite';
8
+
9
+ type SearchSource = {
10
+ sourceId?: string;
11
+ title?: string;
12
+ url?: string;
13
+ };
14
+
15
+ type ToolStepLike = {
16
+ toolCalls?: Array<{ toolName?: string }>;
17
+ toolResults?: Array<{ toolName?: string }>;
18
+ };
19
+
20
+ const SearchArgsSchema = z.object({
21
+ query: z
22
+ .string()
23
+ .transform((value) => value.trim())
24
+ .refine((value) => value.length > 0, {
25
+ message: 'Missing required `query`.',
26
+ })
27
+ .transform((value) => value.slice(0, 500)),
28
+ });
29
+
30
+ function hasGoogleSearchCallInSteps(steps: unknown): boolean {
31
+ if (!Array.isArray(steps)) return false;
32
+
33
+ return steps.some((step) => {
34
+ if (!step || typeof step !== 'object') return false;
35
+ const typedStep = step as ToolStepLike;
36
+ const called = (typedStep.toolCalls ?? []).some(
37
+ (toolCall) => toolCall.toolName === 'google_search'
38
+ );
39
+ const hasResult = (typedStep.toolResults ?? []).some(
40
+ (toolResult) => toolResult.toolName === 'google_search'
41
+ );
42
+ return called || hasResult;
43
+ });
44
+ }
45
+
46
+ function normalizeSources(value: unknown): SearchSource[] {
47
+ if (!Array.isArray(value)) return [];
48
+
49
+ const normalized: SearchSource[] = [];
50
+
51
+ for (const item of value) {
52
+ if (!item || typeof item !== 'object') continue;
53
+
54
+ const source = item as Record<string, unknown>;
55
+ const sourceId =
56
+ typeof source.sourceId === 'string' ? source.sourceId : undefined;
57
+ const title = typeof source.title === 'string' ? source.title : undefined;
58
+ const url = typeof source.url === 'string' ? source.url : undefined;
59
+
60
+ if (!sourceId && !title && !url) continue;
61
+
62
+ normalized.push({ sourceId, title, url });
63
+ }
64
+
65
+ return normalized;
66
+ }
67
+
68
+ async function runGoogleSearchWrapper(
69
+ query: string,
70
+ forceTool: boolean,
71
+ ctx: MiraToolContext
72
+ ) {
73
+ const prompt = forceTool
74
+ ? `You must call the google_search tool before producing the final answer.\nSearch the web for the query below and provide an accurate, concise answer with key points and cited sources.\n\nQuery: ${query}`
75
+ : `Search the web for the query below and provide an accurate, concise answer with key points and cited sources.\n\nQuery: ${query}`;
76
+
77
+ return generateText({
78
+ model: await withAiMemory({
79
+ addMemory: 'never',
80
+ customId: ctx.chatId ? `${ctx.chatId}-google-search` : query,
81
+ model: google(SEARCH_WRAPPER_MODEL),
82
+ product: 'mira',
83
+ source: 'mira_google_search_tool',
84
+ surface: 'mira_google_search_tool',
85
+ userId: ctx.userId,
86
+ wsId: ctx.workspaceContext?.wsId ?? ctx.wsId,
87
+ }),
88
+ tools: {
89
+ google_search: google.tools.googleSearch({}),
90
+ },
91
+ prompt,
92
+ stopWhen: stepCountIs(4),
93
+ ...(forceTool ? { toolChoice: 'required' as const } : {}),
94
+ });
95
+ }
96
+
97
+ export async function executeGoogleSearch(
98
+ args: Record<string, unknown>,
99
+ ctx: MiraToolContext
100
+ ) {
101
+ const parsed = SearchArgsSchema.safeParse(args);
102
+ if (!parsed.success) {
103
+ return {
104
+ ok: false,
105
+ error: parsed.error.issues[0]?.message ?? 'Invalid `query`.',
106
+ };
107
+ }
108
+
109
+ const { query } = parsed.data;
110
+
111
+ try {
112
+ let result = await runGoogleSearchWrapper(query, false, ctx);
113
+ let sources = normalizeSources((result as { sources?: unknown }).sources);
114
+ let wasToolCalled = hasGoogleSearchCallInSteps(
115
+ (result as { steps?: unknown }).steps
116
+ );
117
+
118
+ if (!wasToolCalled) {
119
+ result = await runGoogleSearchWrapper(query, true, ctx);
120
+ sources = normalizeSources((result as { sources?: unknown }).sources);
121
+ wasToolCalled = hasGoogleSearchCallInSteps(
122
+ (result as { steps?: unknown }).steps
123
+ );
124
+ }
125
+
126
+ if (!wasToolCalled && sources.length === 0) {
127
+ return {
128
+ ok: false,
129
+ query,
130
+ error: 'Failed to invoke google_search tool for web-grounded results.',
131
+ };
132
+ }
133
+
134
+ return {
135
+ ok: true,
136
+ query,
137
+ answer: result.text,
138
+ sources,
139
+ sourceCount: sources.length,
140
+ };
141
+ } catch (error) {
142
+ console.error('executeGoogleSearch provider error:', error);
143
+ return {
144
+ ok: false,
145
+ query,
146
+ error: 'Search provider error. Please try again.',
147
+ };
148
+ }
149
+ }
@@ -0,0 +1,40 @@
1
+ import type { MiraToolContext } from '../mira-tools';
2
+
3
+ export async function executeUpdateMySettings(
4
+ args: Record<string, unknown>,
5
+ ctx: MiraToolContext
6
+ ) {
7
+ const updates: Record<string, string> = {};
8
+ const fields = [
9
+ 'name',
10
+ 'tone',
11
+ 'personality',
12
+ 'boundaries',
13
+ 'vibe',
14
+ 'chat_tone',
15
+ ] as const;
16
+
17
+ for (const field of fields) {
18
+ const value = args[field];
19
+ if (typeof value === 'string') {
20
+ updates[field] = value;
21
+ }
22
+ }
23
+
24
+ if (Object.keys(updates).length === 0) {
25
+ return { success: true, message: 'No settings to update' };
26
+ }
27
+
28
+ const { error } = await ctx.supabase
29
+ .from('mira_soul')
30
+ .upsert({ user_id: ctx.userId, ...updates }, { onConflict: 'user_id' });
31
+
32
+ if (error) return { error: error.message };
33
+
34
+ const changedFields = Object.keys(updates).join(', ');
35
+ return {
36
+ success: true,
37
+ message: `Settings updated: ${changedFields}`,
38
+ updated: updates,
39
+ };
40
+ }