@superinterface/server 1.0.0

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 (217) hide show
  1. package/README.md +36 -0
  2. package/eslint.config.mjs +31 -0
  3. package/next.config.ts +7 -0
  4. package/package.json +176 -0
  5. package/prisma/Account.prisma +18 -0
  6. package/prisma/ApiKey.prisma +13 -0
  7. package/prisma/Assistant.prisma +32 -0
  8. package/prisma/AssistantHandler.prisma +12 -0
  9. package/prisma/Avatar.prisma +10 -0
  10. package/prisma/ClientToolHandler.prisma +13 -0
  11. package/prisma/CodeInterpreterTool.prisma +7 -0
  12. package/prisma/ComputerUseTool.prisma +12 -0
  13. package/prisma/CreateTaskHandler.prisma +10 -0
  14. package/prisma/DeleteTaskHandler.prisma +10 -0
  15. package/prisma/FileSearchTool.prisma +9 -0
  16. package/prisma/FirecrawlHandler.prisma +13 -0
  17. package/prisma/Function.prisma +13 -0
  18. package/prisma/Handler.prisma +19 -0
  19. package/prisma/HttpTransport.prisma +12 -0
  20. package/prisma/IconAvatar.prisma +8 -0
  21. package/prisma/ImageAvatar.prisma +8 -0
  22. package/prisma/ImageGenerationTool.prisma +11 -0
  23. package/prisma/InitialMessage.prisma +17 -0
  24. package/prisma/Invitation.prisma +15 -0
  25. package/prisma/ListTasksHandler.prisma +10 -0
  26. package/prisma/Log.prisma +21 -0
  27. package/prisma/McpServer.prisma +14 -0
  28. package/prisma/Message.prisma +30 -0
  29. package/prisma/ModelProvider.prisma +15 -0
  30. package/prisma/Organization.prisma +10 -0
  31. package/prisma/OrganizationApiKey.prisma +12 -0
  32. package/prisma/OrganizationInvitation.prisma +15 -0
  33. package/prisma/OrganizationUserRole.prisma +14 -0
  34. package/prisma/ReplicateHandler.prisma +14 -0
  35. package/prisma/RequestHandler.prisma +15 -0
  36. package/prisma/Run.prisma +36 -0
  37. package/prisma/RunStep.prisma +30 -0
  38. package/prisma/Session.prisma +7 -0
  39. package/prisma/SseTransport.prisma +12 -0
  40. package/prisma/StdioTransport.prisma +11 -0
  41. package/prisma/Task.prisma +15 -0
  42. package/prisma/Thread.prisma +20 -0
  43. package/prisma/Tool.prisma +13 -0
  44. package/prisma/UpdateTaskHandler.prisma +10 -0
  45. package/prisma/User.prisma +16 -0
  46. package/prisma/UserRole.prisma +14 -0
  47. package/prisma/VerificationToken.prisma +7 -0
  48. package/prisma/WebSearchTool.prisma +7 -0
  49. package/prisma/Workspace.prisma +14 -0
  50. package/prisma/enums/ApiKeyType.prisma +4 -0
  51. package/prisma/enums/AvatarType.prisma +5 -0
  52. package/prisma/enums/ClientToolHandlerType.prisma +3 -0
  53. package/prisma/enums/ComputerUseToolEnvironment.prisma +6 -0
  54. package/prisma/enums/FirecrawlHandlerType.prisma +6 -0
  55. package/prisma/enums/HandlerType.prisma +11 -0
  56. package/prisma/enums/IconAvatarName.prisma +14 -0
  57. package/prisma/enums/ImageGenerationToolOutputFormat.prisma +5 -0
  58. package/prisma/enums/ImageGenerationToolQuality.prisma +6 -0
  59. package/prisma/enums/ImageGenerationToolSize.prisma +6 -0
  60. package/prisma/enums/LogLevel.prisma +5 -0
  61. package/prisma/enums/LogRequestMethod.prisma +7 -0
  62. package/prisma/enums/LogRequestRoute.prisma +6 -0
  63. package/prisma/enums/MessageRole.prisma +4 -0
  64. package/prisma/enums/MessageStatus.prisma +5 -0
  65. package/prisma/enums/MethodType.prisma +7 -0
  66. package/prisma/enums/ModelProviderType.prisma +13 -0
  67. package/prisma/enums/OrganizationUserRoleType.prisma +3 -0
  68. package/prisma/enums/ReplicateHandlerType.prisma +3 -0
  69. package/prisma/enums/RunStatus.prisma +10 -0
  70. package/prisma/enums/RunStepStatus.prisma +7 -0
  71. package/prisma/enums/RunStepType.prisma +4 -0
  72. package/prisma/enums/StorageProviderType.prisma +7 -0
  73. package/prisma/enums/ToolType.prisma +7 -0
  74. package/prisma/enums/TransportType.prisma +5 -0
  75. package/prisma/enums/TruncationType.prisma +5 -0
  76. package/prisma/enums/UserRoleType.prisma +3 -0
  77. package/prisma/migrations/20251006235143_initial_setup/migration.sql +986 -0
  78. package/prisma/migrations/20251007163926_add_truncation_type/migration.sql +6 -0
  79. package/prisma/migrations/20251007190703_add_organizations/migration.sql +97 -0
  80. package/prisma/migrations/migration_lock.toml +3 -0
  81. package/prisma/schema.prisma +13 -0
  82. package/prisma.config.ts +6 -0
  83. package/scripts/cli.ts +84 -0
  84. package/scripts/commands/organizations/api-keys/create.ts +159 -0
  85. package/scripts/commands/organizations/create.ts +82 -0
  86. package/scripts/utils/env.ts +31 -0
  87. package/scripts/utils/errors.ts +6 -0
  88. package/src/app/api/api-keys/[apiKeyId]/route.ts +178 -0
  89. package/src/app/api/api-keys/route.ts +147 -0
  90. package/src/app/api/assistants/[assistantId]/functions/[functionId]/route.ts +245 -0
  91. package/src/app/api/assistants/[assistantId]/functions/route.ts +157 -0
  92. package/src/app/api/assistants/[assistantId]/initial-messages/route.ts +127 -0
  93. package/src/app/api/assistants/[assistantId]/mcp-servers/[mcpServerId]/route.ts +243 -0
  94. package/src/app/api/assistants/[assistantId]/mcp-servers/route.ts +163 -0
  95. package/src/app/api/assistants/[assistantId]/route.ts +336 -0
  96. package/src/app/api/assistants/route.ts +196 -0
  97. package/src/app/api/files/[fileId]/contents/route.ts +145 -0
  98. package/src/app/api/files/route.ts +117 -0
  99. package/src/app/api/messages/lib/getWorkspaceId.ts +12 -0
  100. package/src/app/api/messages/lib/initialMessagesResponse.ts +90 -0
  101. package/src/app/api/messages/lib/serializeThread.ts +22 -0
  102. package/src/app/api/messages/route.ts +710 -0
  103. package/src/app/api/providers/[modelProviderId]/assistants/route.ts +68 -0
  104. package/src/app/api/providers/[modelProviderId]/models/route.ts +68 -0
  105. package/src/app/api/providers/[modelProviderId]/route.ts +202 -0
  106. package/src/app/api/providers/route.ts +105 -0
  107. package/src/app/api/tasks/[taskId]/route.ts +213 -0
  108. package/src/app/api/tasks/callback/route.ts +280 -0
  109. package/src/app/api/tasks/route.ts +121 -0
  110. package/src/app/api/threads/runs/submit-client-tool-outputs/route.ts +54 -0
  111. package/src/app/api/workspaces/[workspaceId]/route.ts +137 -0
  112. package/src/app/api/workspaces/route.ts +139 -0
  113. package/src/app/layout.tsx +9 -0
  114. package/src/app/page.tsx +3 -0
  115. package/src/lib/apiKeys/formatApiKeyName.ts +13 -0
  116. package/src/lib/apiKeys/getApiKey.ts +25 -0
  117. package/src/lib/apiKeys/serializeApiKey.ts +11 -0
  118. package/src/lib/apiKeys/workspaceAccessWhere.ts +21 -0
  119. package/src/lib/assistants/assistantClientAdapter/buildGetOpenaiAssistant.ts +96 -0
  120. package/src/lib/assistants/assistantClientAdapter/index.ts +165 -0
  121. package/src/lib/assistants/formatName.ts +9 -0
  122. package/src/lib/assistants/serializeApiAssistant.ts +40 -0
  123. package/src/lib/assistants/serializeAssistant.ts +31 -0
  124. package/src/lib/assistants/storageAssistantId.ts +29 -0
  125. package/src/lib/avatars/defaultAvatar.ts +15 -0
  126. package/src/lib/avatars/serializeAvatar.ts +26 -0
  127. package/src/lib/cache/cacheHeaders.ts +5 -0
  128. package/src/lib/computerCalls/handleComputerCall/index.ts +173 -0
  129. package/src/lib/errors/index.ts +10 -0
  130. package/src/lib/errors/serializeError.ts +11 -0
  131. package/src/lib/functions/createFunction.ts +32 -0
  132. package/src/lib/functions/functionSchema.ts +201 -0
  133. package/src/lib/functions/handleFunction/getFunction.ts +43 -0
  134. package/src/lib/functions/handleFunction/handleAssistant.ts +399 -0
  135. package/src/lib/functions/handleFunction/handleClientTool.ts +127 -0
  136. package/src/lib/functions/handleFunction/handleFirecrawl.ts +212 -0
  137. package/src/lib/functions/handleFunction/handleReplicate.ts +109 -0
  138. package/src/lib/functions/handleFunction/handleRequest.ts +272 -0
  139. package/src/lib/functions/handleFunction/index.ts +474 -0
  140. package/src/lib/functions/handleFunction/tasks/handleCreateTask.ts +58 -0
  141. package/src/lib/functions/handleFunction/tasks/handleDeleteTask.ts +62 -0
  142. package/src/lib/functions/handleFunction/tasks/handleListTasks.ts +53 -0
  143. package/src/lib/functions/handleFunction/tasks/handleUpdateTask.ts +70 -0
  144. package/src/lib/functions/interpolateFunctionValue.ts +26 -0
  145. package/src/lib/functions/serializeApiFunction.ts +32 -0
  146. package/src/lib/functions/updateFunction.ts +42 -0
  147. package/src/lib/handlers/handlerPrismaInput.tsx +141 -0
  148. package/src/lib/handlers/serializeApiHandler.ts +94 -0
  149. package/src/lib/iconAvatars/serializeIconAvatar.ts +9 -0
  150. package/src/lib/imageAvatars/serializeImageAvatar.ts +9 -0
  151. package/src/lib/initialMessages/schema.ts +11 -0
  152. package/src/lib/initialMessages/serializeApiInitialMessage.ts +15 -0
  153. package/src/lib/initialMessages/updateInitialMessages.ts +33 -0
  154. package/src/lib/logs/createLog.ts +17 -0
  155. package/src/lib/mcpServers/closeMcpConnection.ts +16 -0
  156. package/src/lib/mcpServers/connectMcpServer.ts +117 -0
  157. package/src/lib/mcpServers/getToolCallMcpServer.ts +62 -0
  158. package/src/lib/mcpServers/headers.ts +113 -0
  159. package/src/lib/mcpServers/mcpServerSchema.ts +77 -0
  160. package/src/lib/mcpServers/serializeApiMcpServer.ts +51 -0
  161. package/src/lib/mcpServers/url.ts +98 -0
  162. package/src/lib/messages/content.ts +60 -0
  163. package/src/lib/messages/textContent.ts +13 -0
  164. package/src/lib/metadata/serializeMetadata.ts +34 -0
  165. package/src/lib/misc/isJSON.ts +9 -0
  166. package/src/lib/misc/merge/customizer.ts +8 -0
  167. package/src/lib/misc/merge/index.ts +6 -0
  168. package/src/lib/modelProviders/buildAzureOpenaiClientAdapter.ts +33 -0
  169. package/src/lib/modelProviders/buildOpenaiClient.ts +14 -0
  170. package/src/lib/modelProviders/buildOpenaiClientAdapter.ts +30 -0
  171. package/src/lib/modelProviders/clientAdapter.ts +121 -0
  172. package/src/lib/modelProviders/isModelProviderValid.ts +23 -0
  173. package/src/lib/modelProviders/modelProviderConfigs.ts +221 -0
  174. package/src/lib/modelProviders/serializeModelProvider.ts +19 -0
  175. package/src/lib/models/getModels.ts +27 -0
  176. package/src/lib/models/serializeApiModel.ts +5 -0
  177. package/src/lib/openai/getOpenaiAssistants.ts +30 -0
  178. package/src/lib/organizationApiKeys/getOrganizationApiKey.ts +23 -0
  179. package/src/lib/prisma/index.ts +29 -0
  180. package/src/lib/redis/index.ts +3 -0
  181. package/src/lib/runs/createRunOpts.ts +80 -0
  182. package/src/lib/storageProviders/getStorageProviderAssistants.ts +19 -0
  183. package/src/lib/storageProviders/getStorageProviderType.ts +21 -0
  184. package/src/lib/storageProviders/isOpenaiAssistantsStorageProvider.ts +8 -0
  185. package/src/lib/storageProviders/isResponsesStorageProvider.ts +8 -0
  186. package/src/lib/storageProviders/openaiAssistantsStorageProviderTypes.ts +6 -0
  187. package/src/lib/storageProviders/responsesStorageProviderTypes.ts +6 -0
  188. package/src/lib/storageProviders/serializeApiStorageProviderAssistant.ts +14 -0
  189. package/src/lib/tasks/cancelScheduledTask.ts +13 -0
  190. package/src/lib/tasks/getNextOccurrence.ts +77 -0
  191. package/src/lib/tasks/getTaskToolKey.ts +49 -0
  192. package/src/lib/tasks/parseTaskToolArgs.ts +101 -0
  193. package/src/lib/tasks/scheduleSchema.ts +34 -0
  194. package/src/lib/tasks/scheduleTask.ts +37 -0
  195. package/src/lib/tasks/schemas.ts +25 -0
  196. package/src/lib/tasks/serializeTask.ts +14 -0
  197. package/src/lib/tasks/validateSchedule.ts +23 -0
  198. package/src/lib/themes/defaultTheme.ts +7 -0
  199. package/src/lib/themes/serializeAccentColor.ts +9 -0
  200. package/src/lib/themes/serializeTheme/index.ts +25 -0
  201. package/src/lib/themes/serializeTheme/serializeScaling.ts +14 -0
  202. package/src/lib/threads/createThread/index.ts +185 -0
  203. package/src/lib/threads/createThread/initialMessages.ts +36 -0
  204. package/src/lib/threads/managedOpenaiThreadId.ts +72 -0
  205. package/src/lib/threads/storageThreadId.ts +49 -0
  206. package/src/lib/threads/validThreadId.ts +10 -0
  207. package/src/lib/toolCalls/handleToolCall.ts +121 -0
  208. package/src/lib/toolCalls/messagesToOutput.ts +8 -0
  209. package/src/lib/toolCalls/streamOutput.ts +106 -0
  210. package/src/lib/tools/tools/index.ts +316 -0
  211. package/src/lib/upstash/qstash.ts +5 -0
  212. package/src/lib/upstash/upstashWorkflowClient.ts +5 -0
  213. package/src/lib/workspaces/serializeApiWorkspace.ts +12 -0
  214. package/src/types/index.ts +133 -0
  215. package/tsconfig.build.json +13 -0
  216. package/tsconfig.json +27 -0
  217. package/types/prisma.d.ts +4 -0
@@ -0,0 +1,221 @@
1
+ import { StorageProviderType, ModelProviderType } from '@prisma/client'
2
+ import { ModelProviderConfig } from '@/types'
3
+
4
+ export const modelProviderConfigs: ModelProviderConfig[] = [
5
+ {
6
+ slug: 'openai',
7
+ type: ModelProviderType.OPENAI,
8
+ name: 'OpenAI',
9
+ description: 'Assistants API, Completions API, Function calling',
10
+ iconUrl: '/images/openai-logo-square-light.svg',
11
+ logoUrl: '/images/openai-logo-light.png',
12
+ dashboardUrl: 'https://platform.openai.com/api-keys',
13
+ modelSlugs: [
14
+ 'gpt-4o-mini',
15
+ 'gpt-4o-mini-2024-07-18',
16
+ 'gpt-4o',
17
+ 'gpt-4o-2024-11-20',
18
+ 'gpt-4o-2024-05-13',
19
+ 'chatgpt-4o-latest',
20
+ 'o1-preview',
21
+ 'o1-preview-2024-09-12',
22
+ 'o1-mini',
23
+ 'o1-mini-2024-09-12',
24
+ ],
25
+ storageProviderTypes: [
26
+ StorageProviderType.SUPERINTERFACE_CLOUD,
27
+ StorageProviderType.OPENAI,
28
+ StorageProviderType.OPENAI_RESPONSES,
29
+ ],
30
+ isFunctionCallingAvailable: true,
31
+ },
32
+ {
33
+ slug: 'azure-openai',
34
+ type: ModelProviderType.AZURE_OPENAI,
35
+ name: 'Azure OpenAI',
36
+ description: 'Assistants API, Completions API, Function calling',
37
+ iconUrl: '/images/microsoft-azure-logo-square.svg',
38
+ logoUrl: '/images/microsoft-azure-logo-square.svg',
39
+ dashboardUrl: 'https://ai.azure.com/playground/assistants',
40
+ modelSlugs: [
41
+ 'gpt-4o-mini',
42
+ 'gpt-4o-mini-2024-07-18',
43
+ 'gpt-4o',
44
+ 'gpt-4o-2024-11-20',
45
+ 'gpt-4o-2024-05-13',
46
+ 'chatgpt-4o-latest',
47
+ 'o1-preview',
48
+ 'o1-preview-2024-09-12',
49
+ 'o1-mini',
50
+ 'o1-mini-2024-09-12',
51
+ ],
52
+ storageProviderTypes: [
53
+ StorageProviderType.AZURE_OPENAI,
54
+ StorageProviderType.SUPERINTERFACE_CLOUD,
55
+ // StorageProviderType.AZURE_OPENAI_RESPONSES,
56
+ ],
57
+ isFunctionCallingAvailable: true,
58
+ },
59
+ {
60
+ slug: 'anthropic',
61
+ type: ModelProviderType.ANTHROPIC,
62
+ name: 'Anthropic',
63
+ description: 'Completions API, Function calling',
64
+ iconUrl: '/images/anthropic-logo-square.png',
65
+ logoUrl: '/images/anthropic-logo-light.png',
66
+ dashboardUrl: 'https://console.anthropic.com/settings/keys',
67
+ modelSlugs: [
68
+ 'claude-3-5-sonnet-20241022',
69
+ 'claude-3-5-sonnet-20240620',
70
+ 'claude-3-opus-20240229',
71
+ 'claude-3-sonnet-20240229',
72
+ 'claude-3-5-haiku-20241022',
73
+ 'claude-3-haiku-20240307',
74
+ ],
75
+ storageProviderTypes: [StorageProviderType.SUPERINTERFACE_CLOUD],
76
+ isFunctionCallingAvailable: true,
77
+ },
78
+ {
79
+ slug: 'ollama',
80
+ type: ModelProviderType.OLLAMA,
81
+ name: 'Ollama',
82
+ description: 'Completions API, Function calling',
83
+ iconUrl: '/images/ollama-logo-square.jpg',
84
+ logoUrl: '/images/ollama-logo-light.png',
85
+ dashboardUrl: 'https://ollama.com',
86
+ modelSlugs: [
87
+ 'qwq',
88
+ 'qwen2.5-coder:32b',
89
+ 'qwen2.5-coder:14b',
90
+ 'qwen2.5-coder:7b',
91
+ 'qwen2.5-coder:3b',
92
+ 'qwen2.5-coder:1.5b',
93
+ 'qwen2.5-coder:0.5b',
94
+ 'llama3.2',
95
+ 'llama3.2:1b',
96
+ ],
97
+ storageProviderTypes: [StorageProviderType.SUPERINTERFACE_CLOUD],
98
+ isFunctionCallingAvailable: true,
99
+ },
100
+ {
101
+ slug: 'google',
102
+ type: ModelProviderType.GOOGLE,
103
+ name: 'Google',
104
+ description: 'Completions API, Function calling',
105
+ iconUrl: '/images/google-gemini-logo-square.svg',
106
+ logoUrl: '/images/google-gemini-logo-square.svg',
107
+ dashboardUrl: 'https://aistudio.google.com/apikey',
108
+ modelSlugs: ['gemini-2.0-flash-exp'],
109
+ storageProviderTypes: [StorageProviderType.SUPERINTERFACE_CLOUD],
110
+ isFunctionCallingAvailable: true,
111
+ },
112
+ {
113
+ slug: 'mistral',
114
+ type: ModelProviderType.MISTRAL,
115
+ name: 'Mistral',
116
+ description: 'Completions API, Function calling',
117
+ iconUrl: '/images/mistral-logo-square.png',
118
+ logoUrl: '/images/mistral-logo-light.svg',
119
+ dashboardUrl: 'https://console.mistral.ai/api-keys/',
120
+ modelSlugs: [
121
+ 'mistral-large-latest',
122
+ 'mistral-large-2407',
123
+ 'open-mistral-nemo',
124
+ 'open-mistral-nemo-2407',
125
+ 'open-mixtral-8x22b',
126
+ 'open-mixtral-8x7b',
127
+ 'open-mistral-7b',
128
+ ],
129
+ storageProviderTypes: [StorageProviderType.SUPERINTERFACE_CLOUD],
130
+ isFunctionCallingAvailable: true,
131
+ },
132
+ {
133
+ slug: 'groq',
134
+ type: ModelProviderType.GROQ,
135
+ name: 'Groq',
136
+ description: 'Completions API, Function calling',
137
+ iconUrl: '/images/groq-logo-square.png',
138
+ logoUrl: '/images/groq-logo-light2.png',
139
+ dashboardUrl: 'https://console.groq.com/keys',
140
+ modelSlugs: [
141
+ // 'llama-3.1-405b-reasoning',
142
+ 'meta-llama/llama-4-scout-17b-16e-instruct',
143
+ 'llama-3.1-8b-instant',
144
+ 'llama3-groq-70b-8192-tool-use-preview',
145
+ 'llama3-8b-8192',
146
+ 'llama3-70b-8192',
147
+ 'deepseek-r1-distill-llama-70b',
148
+ // 'mixtral-8x7b-32768',
149
+ 'gemma-7b-it',
150
+ ],
151
+ storageProviderTypes: [StorageProviderType.SUPERINTERFACE_CLOUD],
152
+ isFunctionCallingAvailable: true,
153
+ },
154
+ {
155
+ slug: 'humiris',
156
+ type: ModelProviderType.HUMIRIS,
157
+ name: 'Humiris',
158
+ description: 'Completions API',
159
+ iconUrl: '/images/humiris-logo-square.png',
160
+ logoUrl: '/images/humiris-logo-light2.png',
161
+ dashboardUrl: 'https://platform.humiris.ai/api-key',
162
+ modelSlugs: ['Humiris/humiris-moai'],
163
+ storageProviderTypes: [StorageProviderType.SUPERINTERFACE_CLOUD],
164
+ isFunctionCallingAvailable: false,
165
+ },
166
+ {
167
+ slug: 'together',
168
+ type: ModelProviderType.TOGETHER,
169
+ name: 'Together.ai',
170
+ description: 'Completions API, Function calling',
171
+ iconUrl: '/images/together-logo-square.png',
172
+ logoUrl: '/images/together-logo-light.png',
173
+ dashboardUrl: 'https://api.together.xyz/settings/api-keys',
174
+ modelSlugs: [
175
+ 'meta-llama/Llama-4-Scout-17B-16E-Instruct',
176
+ 'meta-llama/Llama-3-70b-chat-hf',
177
+ 'mistralai/Mixtral-8x7B-Instruct-v0.1',
178
+ 'togethercomputer/RedPajama-INCITE-Chat-3B-v1',
179
+ 'togethercomputer/CodeLlama-34b-Instruct',
180
+ ],
181
+ storageProviderTypes: [StorageProviderType.SUPERINTERFACE_CLOUD],
182
+ isFunctionCallingAvailable: true,
183
+ },
184
+ {
185
+ slug: 'perplexity',
186
+ type: ModelProviderType.PERPLEXITY,
187
+ name: 'Perplexity',
188
+ description: 'Completions API, Function calling',
189
+ iconUrl: '/images/perplexity-logo-square.png',
190
+ logoUrl: '/images/perplexity-logo-light2.png',
191
+ dashboardUrl: 'https://www.perplexity.ai/settings/api',
192
+ modelSlugs: [
193
+ 'llama-3.1-sonar-small-128k-online',
194
+ 'llama-3.1-sonar-large-128k-online',
195
+ 'llama-3.1-sonar-huge-128k-online',
196
+ 'llama-3.1-sonar-small-128k-chat',
197
+ 'llama-3.1-sonar-large-128k-chat',
198
+ 'llama-3.1-8b-instruct',
199
+ 'llama-3.1-70b-instruct',
200
+ ],
201
+ storageProviderTypes: [StorageProviderType.SUPERINTERFACE_CLOUD],
202
+ isFunctionCallingAvailable: true,
203
+ },
204
+ {
205
+ slug: 'open-router',
206
+ type: ModelProviderType.OPEN_ROUTER,
207
+ name: 'Open Router',
208
+ description: 'Completions API, Function calling',
209
+ iconUrl: '/images/open-router-logo-square-light.svg',
210
+ logoUrl: '/images/open-router-logo-light.svg',
211
+ dashboardUrl: 'https://openrouter.ai/settings/keys',
212
+ modelSlugs: [
213
+ 'openai/o1-mini',
214
+ 'openai/o1-preview',
215
+ 'openai/gpt-4o-mini',
216
+ 'qwen/qwen-2.5-72b-instruct',
217
+ ],
218
+ storageProviderTypes: [StorageProviderType.SUPERINTERFACE_CLOUD],
219
+ isFunctionCallingAvailable: true,
220
+ },
221
+ ]
@@ -0,0 +1,19 @@
1
+ import type { ModelProvider } from '@prisma/client'
2
+
3
+ export const serializeModelProvider = ({
4
+ provider,
5
+ }: {
6
+ provider: ModelProvider
7
+ }) => ({
8
+ id: provider.id,
9
+ type: provider.type,
10
+ name: provider.name,
11
+ apiKey: provider.apiKey,
12
+ endpoint: provider.endpoint,
13
+ apiVersion: provider.apiVersion,
14
+ workspaceId: provider.workspaceId,
15
+ createdAt: provider.createdAt.toISOString(),
16
+ updatedAt: provider.updatedAt.toISOString(),
17
+ })
18
+
19
+ export type SerializedModelProvider = ReturnType<typeof serializeModelProvider>
@@ -0,0 +1,27 @@
1
+ import { buildOpenaiClient } from '@/lib/modelProviders/buildOpenaiClient'
2
+ import type { ModelProvider } from '@prisma/client'
3
+
4
+ export const getModels = async ({
5
+ modelProvider,
6
+ }: {
7
+ modelProvider: ModelProvider
8
+ }) => {
9
+ const client = buildOpenaiClient({
10
+ modelProvider,
11
+ })
12
+
13
+ const models = []
14
+
15
+ try {
16
+ const list = await client.models.list()
17
+
18
+ for await (const model of list) {
19
+ models.push(model)
20
+ }
21
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
22
+ } catch (error) {
23
+ throw new Error(`Failed to load models from AI provider.`)
24
+ }
25
+
26
+ return models
27
+ }
@@ -0,0 +1,5 @@
1
+ import type OpenAI from 'openai'
2
+
3
+ export const serializeApiModel = ({ model }: { model: OpenAI.Model }) => ({
4
+ id: model.id,
5
+ })
@@ -0,0 +1,30 @@
1
+ import { ModelProvider } from '@prisma/client'
2
+ import { buildOpenaiClient } from '@/lib/modelProviders/buildOpenaiClient'
3
+ import { isModelProviderValid } from '@/lib/modelProviders/isModelProviderValid'
4
+
5
+ export const getOpenaiAssistants = async ({
6
+ modelProvider,
7
+ }: {
8
+ modelProvider: ModelProvider
9
+ }) => {
10
+ if (!isModelProviderValid({ modelProvider })) {
11
+ return []
12
+ }
13
+
14
+ const client = buildOpenaiClient({
15
+ modelProvider,
16
+ })
17
+
18
+ const assistants = []
19
+
20
+ try {
21
+ for await (const assistant of client.beta.assistants.list({ limit: 100 })) {
22
+ assistants.push(assistant)
23
+ }
24
+ } catch (e) {
25
+ console.error(e)
26
+ return assistants
27
+ }
28
+
29
+ return assistants
30
+ }
@@ -0,0 +1,23 @@
1
+ import type { OrganizationApiKey } from '@prisma/client'
2
+ import { validate } from 'uuid'
3
+ import { prisma } from '@/lib/prisma'
4
+
5
+ export const getOrganizationApiKey = async ({
6
+ authorization,
7
+ }: {
8
+ authorization: string | null
9
+ }): Promise<OrganizationApiKey | null> => {
10
+ if (!authorization) {
11
+ return null
12
+ }
13
+
14
+ const [, organizationApiKeyValue] = authorization.split('Bearer ')
15
+
16
+ if (!validate(organizationApiKeyValue)) {
17
+ return null
18
+ }
19
+
20
+ return prisma.organizationApiKey.findFirst({
21
+ where: { value: organizationApiKeyValue },
22
+ })
23
+ }
@@ -0,0 +1,29 @@
1
+ import { PrismaNeon } from '@prisma/adapter-neon'
2
+ import { PrismaClient } from '@prisma/client'
3
+
4
+ const prismaClientSingleton = () => {
5
+ const connectionString = `${process.env.DATABASE_URL}`
6
+
7
+ if (process.env.NODE_ENV === 'test') {
8
+ return new PrismaClient()
9
+ }
10
+
11
+ const adapter = new PrismaNeon({
12
+ connectionString,
13
+ })
14
+
15
+ return new PrismaClient({
16
+ adapter,
17
+ transactionOptions: {
18
+ timeout: 15000,
19
+ },
20
+ })
21
+ }
22
+
23
+ declare global {
24
+ var prisma: undefined | ReturnType<typeof prismaClientSingleton>
25
+ }
26
+
27
+ export const prisma = globalThis.prisma ?? prismaClientSingleton()
28
+
29
+ if (process.env.NODE_ENV !== 'production') globalThis.prisma = prisma
@@ -0,0 +1,3 @@
1
+ import { Redis } from '@upstash/redis'
2
+
3
+ export const redis = Redis.fromEnv()
@@ -0,0 +1,80 @@
1
+ import type { OpenAI } from 'openai'
2
+ import { Prisma, Thread, Assistant, TruncationType } from '@prisma/client'
3
+ import { storageAssistantId } from '@/lib/assistants/storageAssistantId'
4
+ import { tools } from '@/lib/tools/tools'
5
+ import { isOpenaiAssistantsStorageProvider } from '@/lib/storageProviders/isOpenaiAssistantsStorageProvider'
6
+
7
+ const instructions = ({ assistant }: { assistant: Assistant }) => {
8
+ if (assistant.instructions.length > 0) {
9
+ return {
10
+ instructions: assistant.instructions,
11
+ }
12
+ }
13
+
14
+ if (
15
+ !isOpenaiAssistantsStorageProvider({
16
+ storageProviderType: assistant.storageProviderType,
17
+ })
18
+ ) {
19
+ return {
20
+ instructions: '',
21
+ }
22
+ }
23
+
24
+ return {}
25
+ }
26
+
27
+ const truncationStrategy = ({ assistant }: { assistant: Assistant }) => {
28
+ if (assistant.truncationType === TruncationType.LAST_MESSAGES) {
29
+ return {
30
+ type: 'last_messages' as const,
31
+ last_messages: assistant.truncationLastMessagesCount,
32
+ }
33
+ } else if (assistant.truncationType === TruncationType.DISABLED) {
34
+ // @ts-expect-error - compat
35
+ return {
36
+ type: 'disabled',
37
+ } as OpenAI.Beta.Threads.Runs.Run.TruncationStrategy
38
+ } else {
39
+ return {
40
+ type: 'auto' as const,
41
+ }
42
+ }
43
+ }
44
+
45
+ export const createRunOpts = async ({
46
+ assistant,
47
+ thread,
48
+ }: {
49
+ assistant: Prisma.AssistantGetPayload<{
50
+ include: {
51
+ tools: {
52
+ include: {
53
+ fileSearchTool: true
54
+ webSearchTool: true
55
+ imageGenerationTool: true
56
+ codeInterpreterTool: true
57
+ computerUseTool: true
58
+ }
59
+ }
60
+ functions: true
61
+ modelProvider: true
62
+ mcpServers: {
63
+ include: {
64
+ computerUseTool: true
65
+ stdioTransport: true
66
+ httpTransport: true
67
+ sseTransport: true
68
+ }
69
+ }
70
+ }
71
+ }>
72
+ thread: Thread
73
+ }) => ({
74
+ stream: true,
75
+ assistant_id: storageAssistantId({ assistant }),
76
+ ...instructions({ assistant }),
77
+ model: assistant.modelSlug,
78
+ truncation_strategy: truncationStrategy({ assistant }),
79
+ ...(await tools({ assistant, thread })),
80
+ })
@@ -0,0 +1,19 @@
1
+ import { ModelProvider } from '@prisma/client'
2
+ import { getOpenaiAssistants } from '@/lib/openai/getOpenaiAssistants'
3
+ import { getStorageProviderType } from '@/lib/storageProviders/getStorageProviderType'
4
+
5
+ export const getStorageProviderAssistants = ({
6
+ modelProvider,
7
+ }: {
8
+ modelProvider: ModelProvider
9
+ }) => {
10
+ const storageProviderType = getStorageProviderType({ modelProvider })
11
+
12
+ if (!storageProviderType) {
13
+ return []
14
+ }
15
+
16
+ return getOpenaiAssistants({
17
+ modelProvider,
18
+ })
19
+ }
@@ -0,0 +1,21 @@
1
+ import {
2
+ ModelProvider,
3
+ StorageProviderType,
4
+ ModelProviderType,
5
+ } from '@prisma/client'
6
+
7
+ export const getStorageProviderType = ({
8
+ modelProvider,
9
+ }: {
10
+ modelProvider: ModelProvider
11
+ }) => {
12
+ if (modelProvider.type === ModelProviderType.OPENAI) {
13
+ return StorageProviderType.OPENAI
14
+ }
15
+
16
+ if (modelProvider.type === ModelProviderType.AZURE_OPENAI) {
17
+ return StorageProviderType.AZURE_OPENAI
18
+ }
19
+
20
+ return null
21
+ }
@@ -0,0 +1,8 @@
1
+ import { StorageProviderType } from '@prisma/client'
2
+ import { openaiAssistantsStorageProviderTypes } from '@/lib/storageProviders/openaiAssistantsStorageProviderTypes'
3
+
4
+ export const isOpenaiAssistantsStorageProvider = ({
5
+ storageProviderType,
6
+ }: {
7
+ storageProviderType: StorageProviderType
8
+ }) => openaiAssistantsStorageProviderTypes.includes(storageProviderType)
@@ -0,0 +1,8 @@
1
+ import { StorageProviderType } from '@prisma/client'
2
+ import { responsesStorageProviderTypes } from '@/lib/storageProviders/responsesStorageProviderTypes'
3
+
4
+ export const isResponsesStorageProvider = ({
5
+ storageProviderType,
6
+ }: {
7
+ storageProviderType: StorageProviderType
8
+ }) => responsesStorageProviderTypes.includes(storageProviderType)
@@ -0,0 +1,6 @@
1
+ import { StorageProviderType } from '@prisma/client'
2
+
3
+ export const openaiAssistantsStorageProviderTypes: StorageProviderType[] = [
4
+ StorageProviderType.OPENAI,
5
+ StorageProviderType.AZURE_OPENAI,
6
+ ]
@@ -0,0 +1,6 @@
1
+ import { StorageProviderType } from '@prisma/client'
2
+
3
+ export const responsesStorageProviderTypes: StorageProviderType[] = [
4
+ StorageProviderType.OPENAI_RESPONSES,
5
+ StorageProviderType.AZURE_OPENAI_RESPONSES,
6
+ ]
@@ -0,0 +1,14 @@
1
+ import type { OpenAI } from 'openai'
2
+
3
+ export const serializeApiStorageProviderAssistant = ({
4
+ storageProviderAssistant,
5
+ }: {
6
+ storageProviderAssistant: OpenAI.Beta.Assistant
7
+ }) => ({
8
+ id: storageProviderAssistant.id,
9
+ model: storageProviderAssistant.model,
10
+ name: storageProviderAssistant.name,
11
+ description: storageProviderAssistant.description,
12
+ instructions: storageProviderAssistant.instructions,
13
+ tools: storageProviderAssistant.tools,
14
+ })
@@ -0,0 +1,13 @@
1
+ import { qstash } from '@/lib/upstash/qstash'
2
+ import { type Task } from '@prisma/client'
3
+
4
+ export const cancelScheduledTask = async ({ task }: { task: Task }) => {
5
+ if (!task.qstashMessageId) return
6
+ if (process.env.NODE_ENV === 'test') return
7
+
8
+ try {
9
+ await qstash.messages.delete(task.qstashMessageId)
10
+ } catch (error) {
11
+ console.error('Failed to cancel scheduled task:', error)
12
+ }
13
+ }
@@ -0,0 +1,77 @@
1
+ import dayjs from 'dayjs'
2
+ import utc from 'dayjs/plugin/utc'
3
+ import timezone from 'dayjs/plugin/timezone'
4
+
5
+ dayjs.extend(utc)
6
+ dayjs.extend(timezone)
7
+
8
+ type TaskSchedule = PrismaJson.TaskSchedule
9
+ type Unit = 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'
10
+
11
+ const freqUnit: Record<string, Unit> = {
12
+ secondly: 'second',
13
+ minutely: 'minute',
14
+ hourly: 'hour',
15
+ daily: 'day',
16
+ weekly: 'week',
17
+ monthly: 'month',
18
+ yearly: 'year',
19
+ }
20
+
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ const fits = (d: dayjs.Dayjs, r: any) =>
23
+ (!r.byMonth || r.byMonth.includes(d.month() + 1)) &&
24
+ (!r.byDay || r.byDay.includes(d.format('dd').toUpperCase())) &&
25
+ (!r.byHour || r.byHour.includes(d.hour())) &&
26
+ (!r.byMinute || r.byMinute.includes(d.minute())) &&
27
+ (!r.bySecond || r.bySecond.includes(d.second()))
28
+
29
+ export const getNextOccurrence = ({
30
+ schedule,
31
+ now = new Date(),
32
+ }: {
33
+ schedule: TaskSchedule
34
+ now?: Date
35
+ }): string | null => {
36
+ if (!schedule || typeof schedule !== 'object') return null
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ const { start, timeZone = 'UTC', recurrenceRules = [] } = schedule as any
39
+ if (typeof start !== 'string') return null
40
+
41
+ if (!dayjs(start).isValid()) return null
42
+ const hasOffset = /([+-]\d\d:\d\d|Z)$/i.test(start)
43
+ const base = hasOffset ? dayjs(start).tz(timeZone) : dayjs.tz(start, timeZone)
44
+ const cursor = dayjs.tz(now, timeZone).add(1, 'second')
45
+
46
+ if (recurrenceRules.length === 0)
47
+ return base.isAfter(cursor) ? base.toISOString() : null
48
+
49
+ let best: dayjs.Dayjs | null = null
50
+
51
+ for (const r of recurrenceRules) {
52
+ const unit = freqUnit[r.frequency]
53
+ if (!unit) continue
54
+ const interval = Math.max(1, r.interval ?? 1)
55
+
56
+ let next = base
57
+ if (next.isBefore(cursor)) {
58
+ const diff = cursor.diff(base, unit)
59
+ const steps = Math.floor(diff / interval)
60
+ next = base.add(steps * interval, unit)
61
+ while (next.isBefore(cursor)) next = next.add(interval, unit)
62
+ }
63
+
64
+ let guard = 0
65
+ while (!fits(next, r) && guard < 5000) {
66
+ next = next.add(interval, unit)
67
+ guard++
68
+ }
69
+
70
+ if (r.until && next.isAfter(dayjs.tz(r.until, timeZone))) continue
71
+ if (r.count && base.add(interval * r.count, unit).isBefore(next)) continue
72
+
73
+ if (!best || next.isBefore(best)) best = next
74
+ }
75
+
76
+ return best ? best.toISOString() : null
77
+ }
@@ -0,0 +1,49 @@
1
+ import {
2
+ Assistant,
3
+ Thread,
4
+ LogRequestMethod,
5
+ LogRequestRoute,
6
+ LogLevel,
7
+ } from '@prisma/client'
8
+ import { createLog } from '@/lib/logs/createLog'
9
+
10
+ export const getTaskToolKey = async ({
11
+ thread,
12
+ assistant,
13
+ keyTemplate,
14
+ }: {
15
+ thread: Thread
16
+ assistant: Assistant
17
+ keyTemplate: string | null
18
+ }) => {
19
+ const missing: string[] = []
20
+ const key = (keyTemplate || '').replace(/{{\s*([\w-]+)\s*}}/g, (_, k) => {
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ if (k in (thread.metadata || {})) return String((thread.metadata as any)[k])
23
+ if (k === 'threadId') return thread.id
24
+ if (k === 'assistantId') return assistant.id
25
+ missing.push(k)
26
+ return `{{${k}}}`
27
+ })
28
+
29
+ if (missing.length) {
30
+ const message = `Missing variables in key template: ${missing.join(', ')}`
31
+
32
+ createLog({
33
+ log: {
34
+ requestMethod: LogRequestMethod.POST,
35
+ requestRoute: LogRequestRoute.MESSAGES,
36
+ level: LogLevel.ERROR,
37
+ status: 400,
38
+ message,
39
+ workspaceId: assistant.workspaceId,
40
+ assistantId: assistant.id,
41
+ threadId: thread.id,
42
+ },
43
+ })
44
+
45
+ return { ok: false as const, error: message }
46
+ }
47
+
48
+ return { ok: true as const, key }
49
+ }