@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,26 @@
1
+ import { Assistant, Thread } from '@prisma/client'
2
+
3
+ export const interpolateFunctionValue = ({
4
+ value,
5
+ args,
6
+ thread,
7
+ assistant,
8
+ }: {
9
+ value: string | null | undefined
10
+ args?: Record<string, unknown> | null
11
+ thread: Thread
12
+ assistant: Assistant
13
+ }) => {
14
+ const missing: string[] = []
15
+ const result = (value || '').replace(/{{\s*([\w-]+)\s*}}/g, (_, k) => {
16
+ if (args && k in args) return String(args[k] as unknown)
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ if (k in (thread.metadata || {})) return String((thread.metadata as any)[k])
19
+ if (k === 'threadId') return thread.id
20
+ if (k === 'assistantId') return assistant.id
21
+ missing.push(k)
22
+ return `{{${k}}}`
23
+ })
24
+
25
+ return { value: result, missing }
26
+ }
@@ -0,0 +1,32 @@
1
+ import { Prisma } from '@prisma/client'
2
+ import { serializeApiHandler } from '@/lib/handlers/serializeApiHandler'
3
+
4
+ export const serializeApiFunction = ({
5
+ fn,
6
+ }: {
7
+ fn: Prisma.FunctionGetPayload<{
8
+ include: {
9
+ handler: {
10
+ include: {
11
+ requestHandler: true
12
+ firecrawlHandler: true
13
+ replicateHandler: true
14
+ clientToolHandler: true
15
+ assistantHandler: true
16
+ createTaskHandler: true
17
+ listTasksHandler: true
18
+ updateTaskHandler: true
19
+ deleteTaskHandler: true
20
+ }
21
+ }
22
+ }
23
+ }>
24
+ }) => ({
25
+ id: fn.id,
26
+ openapiSpec: fn.openapiSpec,
27
+ handler: serializeApiHandler({
28
+ handler: fn.handler!,
29
+ }),
30
+ createdAt: fn.createdAt.toISOString(),
31
+ updatedAt: fn.updatedAt.toISOString(),
32
+ })
@@ -0,0 +1,42 @@
1
+ import type { Prisma } from '@prisma/client'
2
+ import type { HandlerInput } from '@/types'
3
+ import { prisma } from '@/lib/prisma'
4
+ import { handlerPrismaInput } from '@/lib/handlers/handlerPrismaInput'
5
+
6
+ export async function updateFunction<
7
+ TInclude extends Prisma.FunctionInclude,
8
+ >(params: {
9
+ fn: Prisma.FunctionGetPayload<{
10
+ include: {
11
+ assistant: true
12
+ }
13
+ }>
14
+ parsedInput: { openapiSpec: string; handler: HandlerInput }
15
+ include: TInclude
16
+ }): Promise<Prisma.FunctionGetPayload<{ include: TInclude }>> {
17
+ const { fn, parsedInput, include } = params
18
+
19
+ return prisma.$transaction(async (tx) => {
20
+ await tx.handler.deleteMany({
21
+ where: { functionId: fn.id },
22
+ })
23
+
24
+ return tx.function.update({
25
+ where: { id: fn.id },
26
+ data: {
27
+ openapiSpec: JSON.parse(parsedInput.openapiSpec),
28
+ handler: {
29
+ create: {
30
+ type: parsedInput.handler.type,
31
+ ...(await handlerPrismaInput({
32
+ parsedInput,
33
+ action: 'create',
34
+ assistant: fn.assistant,
35
+ })),
36
+ },
37
+ },
38
+ },
39
+ include,
40
+ })
41
+ })
42
+ }
@@ -0,0 +1,141 @@
1
+ import { HandlerType } from '@prisma/client'
2
+ import type { Assistant } from '@prisma/client'
3
+ import type { HandlerInput } from '@/types'
4
+ import { prisma } from '@/lib/prisma'
5
+ import { ValidationError } from '@/lib/errors'
6
+
7
+ export const handlerPrismaInput = async ({
8
+ parsedInput,
9
+ action,
10
+ assistant,
11
+ }: {
12
+ parsedInput: {
13
+ handler: HandlerInput
14
+ }
15
+ action: 'create' | 'update'
16
+ assistant: Assistant
17
+ }) => {
18
+ if (parsedInput.handler.type === HandlerType.REQUEST) {
19
+ if (!parsedInput.handler.requestHandler)
20
+ throw new ValidationError('Request handler is required.')
21
+
22
+ return {
23
+ requestHandler: {
24
+ [action]: {
25
+ method: parsedInput.handler.requestHandler.method,
26
+ url: parsedInput.handler.requestHandler.url,
27
+ headers: JSON.parse(parsedInput.handler.requestHandler.headers),
28
+ body: JSON.parse(parsedInput.handler.requestHandler.body),
29
+ },
30
+ },
31
+ }
32
+ } else if (parsedInput.handler.type === HandlerType.FIRECRAWL) {
33
+ if (!parsedInput.handler.firecrawlHandler)
34
+ throw new ValidationError('Firecrawl handler is required.')
35
+
36
+ return {
37
+ firecrawlHandler: {
38
+ [action]: {
39
+ type: parsedInput.handler.firecrawlHandler.type,
40
+ apiKey: parsedInput.handler.firecrawlHandler.apiKey,
41
+ body: JSON.parse(parsedInput.handler.firecrawlHandler.body),
42
+ },
43
+ },
44
+ }
45
+ } else if (parsedInput.handler.type === HandlerType.ASSISTANT) {
46
+ if (!parsedInput.handler.assistantHandler)
47
+ throw new ValidationError('Assistant handler is required.')
48
+
49
+ const handlerAssistant = await prisma.assistant.findFirst({
50
+ where: {
51
+ id: parsedInput.handler.assistantHandler.assistantId,
52
+ workspaceId: assistant.workspaceId,
53
+ },
54
+ })
55
+
56
+ if (!handlerAssistant) throw new ValidationError('Assistant not found.')
57
+
58
+ return {
59
+ assistantHandler: {
60
+ [action]: {
61
+ assistantId: handlerAssistant.id,
62
+ },
63
+ },
64
+ }
65
+ } else if (parsedInput.handler.type === HandlerType.REPLICATE) {
66
+ if (!parsedInput.handler.replicateHandler)
67
+ throw new ValidationError('Replicate handler is required.')
68
+
69
+ return {
70
+ replicateHandler: {
71
+ [action]: {
72
+ type: parsedInput.handler.replicateHandler.type,
73
+ apiKey: parsedInput.handler.replicateHandler.apiKey,
74
+ identifier: parsedInput.handler.replicateHandler.identifier,
75
+ body: JSON.parse(parsedInput.handler.replicateHandler.body),
76
+ },
77
+ },
78
+ }
79
+ } else if (parsedInput.handler.type === HandlerType.CLIENT_TOOL) {
80
+ if (!parsedInput.handler.clientToolHandler)
81
+ throw new ValidationError('Client tool handler is required.')
82
+
83
+ return {
84
+ clientToolHandler: {
85
+ [action]: {
86
+ type: parsedInput.handler.clientToolHandler.type,
87
+ name: parsedInput.handler.clientToolHandler.name,
88
+ arguments: JSON.parse(
89
+ parsedInput.handler.clientToolHandler.arguments,
90
+ ),
91
+ },
92
+ },
93
+ }
94
+ } else if (parsedInput.handler.type === HandlerType.CREATE_TASK) {
95
+ if (!parsedInput.handler.createTaskHandler)
96
+ throw new ValidationError('Task handler is required.')
97
+
98
+ const keyTemplate = parsedInput.handler.createTaskHandler.keyTemplate
99
+
100
+ return {
101
+ createTaskHandler: {
102
+ [action]: { keyTemplate },
103
+ },
104
+ }
105
+ } else if (parsedInput.handler.type === HandlerType.LIST_TASKS) {
106
+ if (!parsedInput.handler.listTasksHandler)
107
+ throw new ValidationError('Task handler is required.')
108
+
109
+ const keyTemplate = parsedInput.handler.listTasksHandler.keyTemplate
110
+
111
+ return {
112
+ listTasksHandler: {
113
+ [action]: { keyTemplate },
114
+ },
115
+ }
116
+ } else if (parsedInput.handler.type === HandlerType.UPDATE_TASK) {
117
+ if (!parsedInput.handler.updateTaskHandler)
118
+ throw new ValidationError('Task handler is required.')
119
+
120
+ const keyTemplate = parsedInput.handler.updateTaskHandler.keyTemplate
121
+
122
+ return {
123
+ updateTaskHandler: {
124
+ [action]: { keyTemplate },
125
+ },
126
+ }
127
+ } else if (parsedInput.handler.type === HandlerType.DELETE_TASK) {
128
+ if (!parsedInput.handler.deleteTaskHandler)
129
+ throw new ValidationError('Task handler is required.')
130
+
131
+ const keyTemplate = parsedInput.handler.deleteTaskHandler.keyTemplate
132
+
133
+ return {
134
+ deleteTaskHandler: {
135
+ [action]: { keyTemplate },
136
+ },
137
+ }
138
+ } else {
139
+ throw new ValidationError('Handler type not supported.')
140
+ }
141
+ }
@@ -0,0 +1,94 @@
1
+ import { Prisma, HandlerType } from '@prisma/client'
2
+
3
+ export const serializeApiHandler = ({
4
+ handler,
5
+ }: {
6
+ handler: Prisma.HandlerGetPayload<{
7
+ include: {
8
+ requestHandler: true
9
+ firecrawlHandler: true
10
+ replicateHandler: true
11
+ clientToolHandler: true
12
+ assistantHandler: true
13
+ createTaskHandler: true
14
+ listTasksHandler: true
15
+ updateTaskHandler: true
16
+ deleteTaskHandler: true
17
+ }
18
+ }>
19
+ }) => ({
20
+ type: handler.type,
21
+ ...(handler.type === HandlerType.REQUEST
22
+ ? {
23
+ requestHandler: {
24
+ url: handler.requestHandler!.url,
25
+ method: handler.requestHandler!.method,
26
+ headers: handler.requestHandler!.headers,
27
+ body: handler.requestHandler!.body,
28
+ },
29
+ }
30
+ : {}),
31
+ ...(handler.type === HandlerType.FIRECRAWL
32
+ ? {
33
+ firecrawlHandler: {
34
+ type: handler.firecrawlHandler!.type,
35
+ apiKey: handler.firecrawlHandler!.apiKey,
36
+ body: handler.firecrawlHandler!.body,
37
+ },
38
+ }
39
+ : {}),
40
+ ...(handler.type === HandlerType.REPLICATE
41
+ ? {
42
+ replicateHandler: {
43
+ type: handler.replicateHandler!.type,
44
+ apiKey: handler.replicateHandler!.apiKey,
45
+ identifier: handler.replicateHandler!.identifier,
46
+ body: handler.replicateHandler!.body,
47
+ },
48
+ }
49
+ : {}),
50
+ ...(handler.type === HandlerType.CLIENT_TOOL
51
+ ? {
52
+ clientToolHandler: {
53
+ type: handler.clientToolHandler!.type,
54
+ name: handler.clientToolHandler!.name,
55
+ arguments: handler.clientToolHandler!.arguments,
56
+ },
57
+ }
58
+ : {}),
59
+ ...(handler.type === HandlerType.ASSISTANT
60
+ ? {
61
+ assistantHandler: {
62
+ assistantId: handler.assistantHandler!.assistantId,
63
+ },
64
+ }
65
+ : {}),
66
+ ...(handler.type === HandlerType.LIST_TASKS
67
+ ? {
68
+ listTasksHandler: {
69
+ keyTemplate: handler.listTasksHandler!.keyTemplate,
70
+ },
71
+ }
72
+ : {}),
73
+ ...(handler.type === HandlerType.CREATE_TASK
74
+ ? {
75
+ createTaskHandler: {
76
+ keyTemplate: handler.createTaskHandler!.keyTemplate,
77
+ },
78
+ }
79
+ : {}),
80
+ ...(handler.type === HandlerType.UPDATE_TASK
81
+ ? {
82
+ updateTaskHandler: {
83
+ keyTemplate: handler.updateTaskHandler!.keyTemplate,
84
+ },
85
+ }
86
+ : {}),
87
+ ...(handler.type === HandlerType.DELETE_TASK
88
+ ? {
89
+ deleteTaskHandler: {
90
+ keyTemplate: handler.deleteTaskHandler!.keyTemplate,
91
+ },
92
+ }
93
+ : {}),
94
+ })
@@ -0,0 +1,9 @@
1
+ import { IconAvatar } from '@prisma/client'
2
+
3
+ export const serializeIconAvatar = ({
4
+ iconAvatar,
5
+ }: {
6
+ iconAvatar: IconAvatar
7
+ }) => ({
8
+ name: iconAvatar.name,
9
+ })
@@ -0,0 +1,9 @@
1
+ import { ImageAvatar } from '@prisma/client'
2
+
3
+ export const serializeImageAvatar = ({
4
+ imageAvatar,
5
+ }: {
6
+ imageAvatar: ImageAvatar
7
+ }) => ({
8
+ url: imageAvatar.url,
9
+ })
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod'
2
+ import { MessageRole } from '@prisma/client'
3
+
4
+ export const initialMessagesSchema = z.object({
5
+ initialMessages: z.array(
6
+ z.object({
7
+ content: z.string().min(1),
8
+ role: z.nativeEnum(MessageRole),
9
+ }),
10
+ ),
11
+ })
@@ -0,0 +1,15 @@
1
+ import type { InitialMessage } from '@prisma/client'
2
+
3
+ export const serializeApiInitialMessage = ({
4
+ initialMessage,
5
+ }: {
6
+ initialMessage: InitialMessage
7
+ }) => ({
8
+ id: initialMessage.id,
9
+ role: initialMessage.role,
10
+ content: initialMessage.content,
11
+ orderNumber: initialMessage.orderNumber,
12
+ assistantId: initialMessage.assistantId,
13
+ createdAt: initialMessage.createdAt.toISOString(),
14
+ updatedAt: initialMessage.updatedAt.toISOString(),
15
+ })
@@ -0,0 +1,33 @@
1
+ import { MessageRole, InitialMessage } from '@prisma/client'
2
+ import { prisma } from '@/lib/prisma'
3
+
4
+ export const updateInitialMessages = async ({
5
+ assistantId,
6
+ initialMessages,
7
+ }: {
8
+ assistantId: string
9
+ initialMessages: { role: MessageRole; content: string }[]
10
+ }) => {
11
+ const messages: InitialMessage[] = await prisma.$transaction(async (tx) => {
12
+ await tx.initialMessage.deleteMany({
13
+ where: { assistantId },
14
+ })
15
+
16
+ if (initialMessages.length === 0) {
17
+ return [] as InitialMessage[]
18
+ }
19
+
20
+ const created = await tx.initialMessage.createManyAndReturn({
21
+ data: initialMessages.map((m, index) => ({
22
+ assistantId,
23
+ role: m.role,
24
+ content: m.content,
25
+ orderNumber: index,
26
+ })),
27
+ })
28
+
29
+ return created
30
+ })
31
+
32
+ return messages.sort((a, b) => a.orderNumber - b.orderNumber)
33
+ }
@@ -0,0 +1,17 @@
1
+ import { type Prisma } from '@prisma/client'
2
+ import { waitUntil } from '@vercel/functions'
3
+ import { prisma } from '@/lib/prisma'
4
+
5
+ export const createLog = ({ log }: { log: Prisma.LogUncheckedCreateInput }) =>
6
+ waitUntil(
7
+ new Promise(async (resolve) => {
8
+ console.log('Logging error.')
9
+
10
+ await prisma.log.create({
11
+ data: log,
12
+ })
13
+
14
+ console.log('Successfully logged error.')
15
+ resolve(true)
16
+ }),
17
+ )
@@ -0,0 +1,16 @@
1
+ // import { v4 as uuidv4 } from 'uuid'
2
+ import type { McpConnection } from '@/types'
3
+
4
+ export const closeMcpConnection = async ({
5
+ mcpConnection,
6
+ }: {
7
+ mcpConnection: McpConnection
8
+ }) => {
9
+ // await mcpConnection.transport.send({
10
+ // id: `close-${uuidv4()}`,
11
+ // jsonrpc: '2.0',
12
+ // method: 'ping',
13
+ // })
14
+ await mcpConnection.client.close()
15
+ await mcpConnection.transport.close()
16
+ }
@@ -0,0 +1,117 @@
1
+ import type { Prisma, Thread, Assistant } from '@prisma/client'
2
+ import { TransportType } from '@prisma/client'
3
+ import { EventSource } from 'eventsource'
4
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js'
5
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
6
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
7
+ import type { McpConnection } from '@/types'
8
+ import { headers as getHeaders } from '@/lib/mcpServers/headers'
9
+ import { url as getUrl } from '@/lib/mcpServers/url'
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ ;(global as any).EventSource = EventSource
12
+
13
+ const fetchWithHeaders =
14
+ ({ headers }: { headers: Record<string, string> }) =>
15
+ (url: string | URL, init?: RequestInit) => {
16
+ const fetchHeaders = new Headers({
17
+ ...(init?.headers ?? {}),
18
+ ...headers,
19
+ })
20
+
21
+ return fetch(url.toString(), {
22
+ ...init,
23
+ headers: fetchHeaders,
24
+ })
25
+ }
26
+
27
+ export const getTransport = ({
28
+ mcpServer,
29
+ thread,
30
+ assistant,
31
+ }: {
32
+ mcpServer: Prisma.McpServerGetPayload<{
33
+ include: {
34
+ stdioTransport: true
35
+ httpTransport: true
36
+ sseTransport: true
37
+ }
38
+ }>
39
+ thread: Thread
40
+ assistant: Assistant
41
+ }) => {
42
+ if (mcpServer.transportType === TransportType.STDIO) {
43
+ throw new Error('STDIO transport is not supported.')
44
+ }
45
+
46
+ if (mcpServer.transportType === TransportType.HTTP) {
47
+ const headers = getHeaders({
48
+ thread,
49
+ mcpServer,
50
+ assistant,
51
+ })
52
+ const url = getUrl({ thread, mcpServer, assistant })
53
+
54
+ return new StreamableHTTPClientTransport(new URL(url), {
55
+ requestInit: {
56
+ headers,
57
+ },
58
+ })
59
+ }
60
+
61
+ if (mcpServer.transportType === TransportType.SSE) {
62
+ const url = getUrl({ thread, mcpServer, assistant })
63
+
64
+ const headers = getHeaders({
65
+ thread,
66
+ mcpServer,
67
+ assistant,
68
+ })
69
+
70
+ return new SSEClientTransport(new URL(url), {
71
+ eventSourceInit: {
72
+ fetch: fetchWithHeaders({ headers }),
73
+ },
74
+ requestInit: {
75
+ headers,
76
+ },
77
+ })
78
+ }
79
+
80
+ throw new Error(`Unknown transport type ${mcpServer.transportType}`)
81
+ }
82
+
83
+ export const connectMcpServer = async ({
84
+ mcpServer,
85
+ thread,
86
+ assistant,
87
+ }: {
88
+ mcpServer: Prisma.McpServerGetPayload<{
89
+ include: {
90
+ stdioTransport: true
91
+ httpTransport: true
92
+ sseTransport: true
93
+ }
94
+ }>
95
+ thread: Thread
96
+ assistant: Assistant
97
+ }) => {
98
+ const client = new Client(
99
+ {
100
+ name: 'superinterface-mcp-client',
101
+ version: '1.0.0',
102
+ },
103
+ {
104
+ capabilities: {},
105
+ },
106
+ )
107
+
108
+ const transport = getTransport({ mcpServer, thread, assistant })
109
+ await client.connect(transport)
110
+
111
+ return {
112
+ mcpConnection: {
113
+ client,
114
+ transport,
115
+ } as McpConnection,
116
+ }
117
+ }
@@ -0,0 +1,62 @@
1
+ import OpenAI from 'openai'
2
+ import { Prisma, Thread } from '@prisma/client'
3
+ import { forEach } from 'p-iteration'
4
+ import { connectMcpServer } from '@/lib/mcpServers/connectMcpServer'
5
+ import type { McpConnection } from '@/types'
6
+ import { closeMcpConnection } from '@/lib/mcpServers/closeMcpConnection'
7
+
8
+ export const getToolCallMcpServer = async ({
9
+ assistant,
10
+ toolCall,
11
+ thread,
12
+ }: {
13
+ assistant: Prisma.AssistantGetPayload<{
14
+ include: {
15
+ mcpServers: {
16
+ include: {
17
+ stdioTransport: true
18
+ httpTransport: true
19
+ sseTransport: true
20
+ }
21
+ }
22
+ }
23
+ }>
24
+ toolCall: OpenAI.Beta.Threads.Runs.RequiredActionFunctionToolCall
25
+ thread: Thread
26
+ }) => {
27
+ let mcpConnection: McpConnection | null = null
28
+
29
+ await forEach(assistant.mcpServers, async (mcpServer) => {
30
+ if (mcpConnection) return false
31
+
32
+ const { mcpConnection: innerMcpConnection } = await connectMcpServer({
33
+ mcpServer,
34
+ thread,
35
+ assistant,
36
+ })
37
+
38
+ const listToolsResponse =
39
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
+ (await innerMcpConnection.client.listTools()) as any
41
+
42
+ const tool = listToolsResponse.tools.find(
43
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
+ (tool: any) => tool.name === toolCall.function.name,
45
+ )
46
+
47
+ if (!tool) {
48
+ await closeMcpConnection({
49
+ mcpConnection: innerMcpConnection,
50
+ })
51
+ return false
52
+ }
53
+
54
+ mcpConnection = innerMcpConnection
55
+
56
+ return true
57
+ })
58
+
59
+ return {
60
+ mcpConnection: mcpConnection as McpConnection | null,
61
+ }
62
+ }