@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,121 @@
1
+ import OpenAI from 'openai'
2
+ import { Prisma, Thread } from '@prisma/client'
3
+ import { handleFunction } from '@/lib/functions/handleFunction'
4
+ import { handleComputerCall } from '@/lib/computerCalls/handleComputerCall'
5
+ import { LogRequestMethod, LogRequestRoute, LogLevel } from '@prisma/client'
6
+ import { createLog } from '@/lib/logs/createLog'
7
+
8
+ export const handleToolCall =
9
+ ({
10
+ assistant,
11
+ thread,
12
+ }: {
13
+ assistant: Prisma.AssistantGetPayload<{
14
+ include: {
15
+ tools: {
16
+ include: {
17
+ computerUseTool: {
18
+ include: {
19
+ mcpServer: {
20
+ include: {
21
+ stdioTransport: true
22
+ sseTransport: true
23
+ httpTransport: true
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }
30
+ mcpServers: {
31
+ include: {
32
+ computerUseTool: true
33
+ stdioTransport: true
34
+ httpTransport: true
35
+ sseTransport: true
36
+ }
37
+ }
38
+ functions: {
39
+ include: {
40
+ handler: {
41
+ include: {
42
+ requestHandler: true
43
+ firecrawlHandler: true
44
+ replicateHandler: true
45
+ clientToolHandler: true
46
+ assistantHandler: true
47
+ createTaskHandler: true
48
+ listTasksHandler: true
49
+ updateTaskHandler: true
50
+ deleteTaskHandler: true
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }>
57
+ thread: Thread
58
+ }) =>
59
+ async ({
60
+ toolCall,
61
+ controller,
62
+ run,
63
+ }: {
64
+ toolCall: OpenAI.Beta.Threads.Runs.RequiredActionFunctionToolCall
65
+ controller: ReadableStreamDefaultController
66
+ run: OpenAI.Beta.Threads.Runs.Run
67
+ }) => {
68
+ if (toolCall.type === 'function') {
69
+ if (!toolCall.function) {
70
+ createLog({
71
+ log: {
72
+ requestMethod: LogRequestMethod.POST,
73
+ requestRoute: LogRequestRoute.MESSAGES,
74
+ level: LogLevel.ERROR,
75
+ status: 500,
76
+ message: 'No function specified.',
77
+ workspaceId: assistant.workspaceId,
78
+ assistantId: assistant.id,
79
+ threadId: thread.id,
80
+ },
81
+ })
82
+
83
+ return {
84
+ tool_call_id: toolCall.id,
85
+ output: 'No function specified',
86
+ }
87
+ }
88
+
89
+ return handleFunction({
90
+ assistant,
91
+ toolCall,
92
+ controller,
93
+ run,
94
+ thread,
95
+ })
96
+ } else if (toolCall.type === 'computer_call') {
97
+ return handleComputerCall({
98
+ assistant,
99
+ toolCall,
100
+ thread,
101
+ })
102
+ } else {
103
+ createLog({
104
+ log: {
105
+ requestMethod: LogRequestMethod.POST,
106
+ requestRoute: LogRequestRoute.MESSAGES,
107
+ level: LogLevel.ERROR,
108
+ status: 500,
109
+ message: `Unknown tool call type: ${toolCall.type}`,
110
+ workspaceId: assistant.workspaceId,
111
+ assistantId: assistant.id,
112
+ threadId: thread.id,
113
+ },
114
+ })
115
+
116
+ return {
117
+ tool_call_id: toolCall.id,
118
+ output: `Unknown tool call type: ${toolCall.type}`,
119
+ }
120
+ }
121
+ }
@@ -0,0 +1,8 @@
1
+ import type OpenAI from 'openai'
2
+ import { textContent } from '@/lib/messages/textContent'
3
+
4
+ export const messagesToOutput = ({
5
+ messages,
6
+ }: {
7
+ messages: OpenAI.Beta.Threads.Messages.Message[]
8
+ }) => messages.map((message) => textContent({ message })).join('\n\n')
@@ -0,0 +1,106 @@
1
+ import type OpenAI from 'openai'
2
+ import { validate } from 'uuid'
3
+ import { enqueueJson } from '@superinterface/react/utils'
4
+ import { prisma } from '@/lib/prisma'
5
+
6
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
+ const deltaContent = ({ data }: { data: any }) => {
8
+ return (
9
+ data.delta.content
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ .map((content: any) => {
12
+ if (content.type === 'text') {
13
+ return content.text.value
14
+ }
15
+
16
+ return ''
17
+ })
18
+ .join('\n\n')
19
+ )
20
+ }
21
+
22
+ export const streamOutput = async ({
23
+ toolCall,
24
+ run,
25
+ messageResponse,
26
+ onThreadMessageCompleted = () => {},
27
+ onThreadRunStepCompleted = () => {},
28
+ controller,
29
+ }: {
30
+ toolCall: OpenAI.Beta.Threads.Runs.RequiredActionFunctionToolCall
31
+ run: OpenAI.Beta.Threads.Runs.Run
32
+ controller: ReadableStreamDefaultController
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
+ messageResponse: ReadableStream<any>
35
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
+ onThreadMessageCompleted?: ({ message }: { message: any }) => void
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ onThreadRunStepCompleted?: ({ runStep }: { runStep: any }) => void
39
+ }) => {
40
+ // TODO figure out how to stream non-prisma runs
41
+ if (!validate(run.id)) {
42
+ return
43
+ }
44
+
45
+ // TODO: get real run step id somehow
46
+ const latestRunStep = await prisma.runStep.findFirst({
47
+ where: {
48
+ runId: run.id,
49
+ },
50
+ orderBy: {
51
+ createdAt: 'desc',
52
+ },
53
+ })
54
+
55
+ const index =
56
+ run.required_action?.submit_tool_outputs.tool_calls.findIndex(
57
+ (tc) => tc.id === toolCall.id,
58
+ ) ?? 0
59
+
60
+ // @ts-expect-error unclear type
61
+ for await (const value of messageResponse) {
62
+ const data = JSON.parse(Buffer.from(value).toString('utf-8'))
63
+
64
+ if (data.event === 'thread.message.delta') {
65
+ enqueueJson({
66
+ controller,
67
+ value: {
68
+ event: 'thread.run.step.delta',
69
+ data: {
70
+ object: 'thread.run.step.delta',
71
+ run_id: run.id,
72
+ // TODO: proper id
73
+ id: latestRunStep?.id ?? '1',
74
+ delta: {
75
+ step_details: {
76
+ type: 'tool_calls',
77
+ tool_calls: [
78
+ {
79
+ id: toolCall.id,
80
+ type: 'function',
81
+ index,
82
+ function: {
83
+ output: deltaContent({ data: data.data }),
84
+ },
85
+ },
86
+ ],
87
+ },
88
+ },
89
+ },
90
+ },
91
+ })
92
+ }
93
+
94
+ if (data.event === 'thread.message.completed') {
95
+ onThreadMessageCompleted({
96
+ message: data.data,
97
+ })
98
+ }
99
+
100
+ if (data.event === 'thread.run.step.completed') {
101
+ onThreadRunStepCompleted({
102
+ runStep: data.data,
103
+ })
104
+ }
105
+ }
106
+ }
@@ -0,0 +1,316 @@
1
+ import type { Prisma, Thread } from '@prisma/client'
2
+ import {
3
+ TransportType,
4
+ ToolType,
5
+ ImageGenerationToolSize,
6
+ } from '@prisma/client'
7
+ import { flat } from 'radash'
8
+ import { map } from 'p-iteration'
9
+ import type OpenAI from 'openai'
10
+ import { modelProviderConfigs } from '@/lib/modelProviders/modelProviderConfigs'
11
+ import { isOpenaiAssistantsStorageProvider } from '@/lib/storageProviders/isOpenaiAssistantsStorageProvider'
12
+ import { connectMcpServer } from '@/lib/mcpServers/connectMcpServer'
13
+ import type { ModelProviderConfig } from '@/types'
14
+ import { closeMcpConnection } from '@/lib/mcpServers/closeMcpConnection'
15
+ import { isResponsesStorageProvider } from '@/lib/storageProviders/isResponsesStorageProvider'
16
+ import { url } from '@/lib/mcpServers/url'
17
+ import { headers } from '@/lib/mcpServers/headers'
18
+
19
+ const serializeImageGenerationToolSize = ({
20
+ tool,
21
+ }: {
22
+ tool: Prisma.ToolGetPayload<{
23
+ include: { imageGenerationTool: true }
24
+ }>
25
+ }) => {
26
+ if (tool.imageGenerationTool!.size === ImageGenerationToolSize.AUTO) {
27
+ return 'auto'
28
+ } else if (
29
+ tool.imageGenerationTool!.size === ImageGenerationToolSize.SIZE_1024_1024
30
+ ) {
31
+ return '1024x1024'
32
+ } else if (
33
+ tool.imageGenerationTool!.size === ImageGenerationToolSize.SIZE_1024_1536
34
+ ) {
35
+ return '1024x1536'
36
+ } else if (
37
+ tool.imageGenerationTool!.size === ImageGenerationToolSize.SIZE_1536_1024
38
+ ) {
39
+ return '1536x1024'
40
+ }
41
+ }
42
+
43
+ const nativeTools = ({
44
+ assistant,
45
+ }: {
46
+ assistant: Prisma.AssistantGetPayload<{
47
+ include: {
48
+ tools: {
49
+ include: {
50
+ fileSearchTool: true
51
+ webSearchTool: true
52
+ imageGenerationTool: true
53
+ codeInterpreterTool: true
54
+ computerUseTool: true
55
+ }
56
+ }
57
+ }
58
+ }>
59
+ modelProviderConfig: ModelProviderConfig
60
+ }): OpenAI.Beta.Assistants.AssistantTool[] => {
61
+ if (
62
+ !isOpenaiAssistantsStorageProvider({
63
+ storageProviderType: assistant.storageProviderType,
64
+ }) &&
65
+ !isResponsesStorageProvider({
66
+ storageProviderType: assistant.storageProviderType,
67
+ })
68
+ ) {
69
+ return []
70
+ }
71
+
72
+ return assistant.tools
73
+ .map((tool) => {
74
+ if (tool.type === ToolType.FILE_SEARCH) {
75
+ if (
76
+ isOpenaiAssistantsStorageProvider({
77
+ storageProviderType: assistant.storageProviderType,
78
+ })
79
+ ) {
80
+ return {
81
+ type: 'file_search' as const,
82
+ }
83
+ }
84
+
85
+ return {
86
+ type: 'file_search' as const,
87
+ file_search: {
88
+ vector_store_ids: tool.fileSearchTool!.vectorStoreIds,
89
+ max_num_results: tool.fileSearchTool!.maxNumResults,
90
+ },
91
+ }
92
+ } else if (tool.type === ToolType.CODE_INTERPRETER) {
93
+ if (
94
+ isOpenaiAssistantsStorageProvider({
95
+ storageProviderType: assistant.storageProviderType,
96
+ })
97
+ ) {
98
+ return {
99
+ type: 'code_interpreter' as const,
100
+ }
101
+ }
102
+
103
+ return {
104
+ type: 'code_interpreter' as const,
105
+ code_interpreter: {
106
+ container: {
107
+ type: 'auto' as const,
108
+ },
109
+ },
110
+ }
111
+ } else if (tool.type === ToolType.IMAGE_GENERATION) {
112
+ return {
113
+ type: 'image_generation' as const,
114
+ image_generation: {
115
+ quality: tool.imageGenerationTool!.quality.toLowerCase() as
116
+ | 'auto'
117
+ | 'low'
118
+ | 'medium'
119
+ | 'high',
120
+ output_format:
121
+ tool.imageGenerationTool!.outputFormat.toLowerCase() as
122
+ | 'png'
123
+ | 'jpeg'
124
+ | 'webp',
125
+ size: serializeImageGenerationToolSize({ tool }),
126
+ partial_images: tool.imageGenerationTool!.partialImages,
127
+ },
128
+ }
129
+ } else if (tool.type === ToolType.WEB_SEARCH) {
130
+ return {
131
+ type: 'web_search' as const,
132
+ }
133
+ } else if (tool.type === ToolType.COMPUTER_USE) {
134
+ if (!tool.computerUseTool!.mcpServerId) {
135
+ return null
136
+ }
137
+
138
+ return {
139
+ type: 'computer_use_preview',
140
+ computer_use_preview: {
141
+ environment: tool.computerUseTool!.environment.toLowerCase(),
142
+ display_width: tool.computerUseTool!.displayWidth,
143
+ display_height: tool.computerUseTool!.displayHeight,
144
+ },
145
+ }
146
+ }
147
+
148
+ return null
149
+ })
150
+ .filter(Boolean) as OpenAI.Beta.Assistants.AssistantTool[]
151
+ }
152
+
153
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
154
+ const serializeTool = ({ tool }: { tool: any }) => ({
155
+ name: tool.name,
156
+ description: tool.description,
157
+ parameters: tool.inputSchema,
158
+ })
159
+
160
+ const mcpServerToolsAsFunction = ({
161
+ mcpServers,
162
+ thread,
163
+ assistant,
164
+ }: {
165
+ mcpServers: Prisma.McpServerGetPayload<{
166
+ include: {
167
+ stdioTransport: true
168
+ httpTransport: true
169
+ sseTransport: true
170
+ computerUseTool: true
171
+ }
172
+ }>[]
173
+ thread: Thread
174
+ assistant: Prisma.AssistantGetPayload<{
175
+ include: {
176
+ mcpServers: {
177
+ include: {
178
+ stdioTransport: true
179
+ httpTransport: true
180
+ sseTransport: true
181
+ computerUseTool: true
182
+ }
183
+ }
184
+ }
185
+ }>
186
+ }) =>
187
+ map(mcpServers, async (mcpServer) => {
188
+ const { mcpConnection } = await connectMcpServer({
189
+ mcpServer,
190
+ thread,
191
+ assistant,
192
+ })
193
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
194
+ const listToolsResponse = (await mcpConnection.client.listTools()) as any
195
+
196
+ await closeMcpConnection({
197
+ mcpConnection,
198
+ })
199
+
200
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
201
+ return listToolsResponse.tools.map((tool: any) => ({
202
+ type: 'function',
203
+ function: serializeTool({ tool }),
204
+ })) as OpenAI.Beta.Assistants.AssistantTool[]
205
+ })
206
+
207
+ const mcpServerTools = async ({
208
+ assistant,
209
+ thread,
210
+ }: {
211
+ assistant: Prisma.AssistantGetPayload<{
212
+ include: {
213
+ mcpServers: {
214
+ include: {
215
+ stdioTransport: true
216
+ httpTransport: true
217
+ sseTransport: true
218
+ computerUseTool: true
219
+ }
220
+ }
221
+ }
222
+ }>
223
+ thread: Thread
224
+ }) => {
225
+ const nonComputerUseMcpServers = assistant.mcpServers.filter(
226
+ (mcpServer) => !mcpServer.computerUseTool,
227
+ )
228
+
229
+ if (
230
+ isResponsesStorageProvider({
231
+ storageProviderType: assistant.storageProviderType,
232
+ }) &&
233
+ assistant.modelSlug.match('computer-use')
234
+ ) {
235
+ const httpMcpServers = nonComputerUseMcpServers.filter(
236
+ (mcpServer) => mcpServer.transportType === TransportType.HTTP,
237
+ )
238
+
239
+ const nativeMcpServerTools = httpMcpServers.map((mcpServer) => ({
240
+ type: 'mcp',
241
+ mcp: {
242
+ server_label: `mcp-server-${mcpServer.id}`,
243
+ server_url: url({ thread, mcpServer, assistant }),
244
+ headers: headers({ thread, mcpServer, assistant }),
245
+ require_approval: 'never',
246
+ },
247
+ }))
248
+
249
+ return [
250
+ ...nativeMcpServerTools,
251
+ ...(await mcpServerToolsAsFunction({
252
+ mcpServers: nonComputerUseMcpServers,
253
+ thread,
254
+ assistant,
255
+ })),
256
+ ]
257
+ }
258
+
259
+ const result = await mcpServerToolsAsFunction({
260
+ mcpServers: nonComputerUseMcpServers,
261
+ thread,
262
+ assistant,
263
+ })
264
+
265
+ return flat(result)
266
+ }
267
+
268
+ export const tools = async ({
269
+ assistant,
270
+ thread,
271
+ }: {
272
+ assistant: Prisma.AssistantGetPayload<{
273
+ include: {
274
+ tools: {
275
+ include: {
276
+ fileSearchTool: true
277
+ webSearchTool: true
278
+ imageGenerationTool: true
279
+ codeInterpreterTool: true
280
+ computerUseTool: true
281
+ }
282
+ }
283
+ functions: true
284
+ modelProvider: true
285
+ mcpServers: {
286
+ include: {
287
+ computerUseTool: true
288
+ stdioTransport: true
289
+ httpTransport: true
290
+ sseTransport: true
291
+ }
292
+ }
293
+ }
294
+ }>
295
+ thread: Thread
296
+ }) => {
297
+ const modelProviderConfig = modelProviderConfigs.find(
298
+ (config) => config.type === assistant.modelProvider.type,
299
+ )
300
+
301
+ if (!modelProviderConfig) return {}
302
+ if (!modelProviderConfig.isFunctionCallingAvailable) {
303
+ return {}
304
+ }
305
+
306
+ return {
307
+ tools: [
308
+ ...(await mcpServerTools({ assistant, thread })),
309
+ ...assistant.functions.map((fn) => ({
310
+ type: 'function' as const,
311
+ function: fn.openapiSpec as unknown as OpenAI.FunctionDefinition,
312
+ })),
313
+ ...nativeTools({ assistant, modelProviderConfig }),
314
+ ] as OpenAI.Beta.Assistants.AssistantTool[],
315
+ }
316
+ }
@@ -0,0 +1,5 @@
1
+ import { Client } from '@upstash/qstash'
2
+
3
+ export const qstash = new Client({
4
+ token: process.env.QSTASH_TOKEN,
5
+ })
@@ -0,0 +1,5 @@
1
+ import { Client } from '@upstash/workflow'
2
+
3
+ export const upstashWorkflowClient = new Client({
4
+ token: process.env.QSTASH_TOKEN,
5
+ })
@@ -0,0 +1,12 @@
1
+ import type { Workspace } from '@prisma/client'
2
+
3
+ export const serializeApiWorkspace = ({
4
+ workspace,
5
+ }: {
6
+ workspace: Workspace
7
+ }) => ({
8
+ id: workspace.id,
9
+ name: workspace.name,
10
+ createdAt: workspace.createdAt.toISOString(),
11
+ updatedAt: workspace.updatedAt.toISOString(),
12
+ })
@@ -0,0 +1,133 @@
1
+ import type { OpenAI } from 'openai'
2
+ import type {
3
+ StorageProviderType,
4
+ ModelProviderType,
5
+ FirecrawlHandlerType,
6
+ ReplicateHandlerType,
7
+ ClientToolHandlerType,
8
+ HandlerType,
9
+ MethodType,
10
+ } from '@prisma/client'
11
+ import type { Client } from '@modelcontextprotocol/sdk/client/index.js'
12
+ import type { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
13
+
14
+ export type ModelProviderConfig = {
15
+ slug: string
16
+ type: ModelProviderType
17
+ name: string
18
+ logoUrl: string
19
+ iconUrl: string
20
+ dashboardUrl: string
21
+ description: string
22
+ modelSlugs: string[]
23
+ storageProviderTypes: StorageProviderType[]
24
+ isFunctionCallingAvailable: boolean
25
+ }
26
+
27
+ export type McpConnection = {
28
+ client: Client
29
+ transport: SSEClientTransport
30
+ }
31
+
32
+ export type RecurrenceRule = {
33
+ frequency: 'daily' | 'weekly' | 'monthly' | 'yearly'
34
+ byDay?: string[]
35
+ byMonth?: number[]
36
+ byHour?: number[]
37
+ byMinute?: number[]
38
+ bySecond?: number[]
39
+ until?: string
40
+ count?: number
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ [key: string]: any
43
+ }
44
+
45
+ export type HandlerInput = {
46
+ type: HandlerType
47
+ requestHandler?: {
48
+ method: MethodType
49
+ url: string
50
+ headers: string
51
+ body: string
52
+ } | null
53
+ firecrawlHandler?: {
54
+ type: FirecrawlHandlerType
55
+ apiKey: string
56
+ body: string
57
+ } | null
58
+ assistantHandler?: {
59
+ assistantId: string
60
+ } | null
61
+ replicateHandler?: {
62
+ type: ReplicateHandlerType
63
+ identifier: string
64
+ apiKey: string
65
+ body: string
66
+ } | null
67
+ clientToolHandler?: {
68
+ type: ClientToolHandlerType
69
+ name: string
70
+ arguments: string
71
+ } | null
72
+ createTaskHandler?: {
73
+ keyTemplate: string
74
+ } | null
75
+ listTasksHandler?: {
76
+ keyTemplate: string
77
+ } | null
78
+ updateTaskHandler?: {
79
+ keyTemplate: string
80
+ } | null
81
+ deleteTaskHandler?: {
82
+ keyTemplate: string
83
+ } | null
84
+ }
85
+
86
+ declare global {
87
+ namespace PrismaJson {
88
+ type MessageContent = OpenAI.Beta.Threads.Messages.MessageContent
89
+ type MessageIncompleteDetails =
90
+ OpenAI.Beta.Threads.Messages.Message['incomplete_details']
91
+ type MessageMetadata = OpenAI.Beta.Threads.Messages.Message['metadata']
92
+ type MessageToolCalls = OpenAI.Beta.Threads.Runs.ToolCall
93
+ type MessageAttachment = OpenAI.Beta.Threads.Messages.Message.Attachment
94
+
95
+ type RunRequiredAction = OpenAI.Beta.Threads.Runs.Run['required_action']
96
+ type RunLastError = OpenAI.Beta.Threads.Runs.Run['last_error']
97
+ type RunTools = OpenAI.Beta.Threads.Runs.Run['tools']
98
+ type RunMetadata = OpenAI.Beta.Threads.Runs.Run['metadata']
99
+ type RunUsage = OpenAI.Beta.Threads.Runs.Run['usage']
100
+ type RunTruncationStrategy =
101
+ OpenAI.Beta.Threads.Runs.Run['truncation_strategy']
102
+ type RunResponseFormat = OpenAI.Beta.Threads.Runs.Run['response_format']
103
+
104
+ type RunStepStepDetails =
105
+ | OpenAI.Beta.Threads.Runs.MessageCreationStepDetails
106
+ | OpenAI.Beta.Threads.Runs.ToolCallsStepDetails
107
+ type RunStepLastErrorMessage =
108
+ OpenAI.Beta.Threads.Runs.RunStep['last_error']
109
+ type RunStepMetadata = OpenAI.Beta.Threads.Runs.RunStep['metadata']
110
+ type RunStepUsage = OpenAI.Beta.Threads.Runs.RunStep['usage']
111
+
112
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
+ type OpenapiSpec = Record<string, any>
114
+ type RequestHandlerHeaders = Record<string, string>
115
+ type RequestHandlerBody = Record<string, string>
116
+
117
+ type FirecrawlHandlerBody = Record<string, string>
118
+ type ReplicateHandlerBody = Record<string, string>
119
+ type ClientToolHandlerArguments = Record<string, string>
120
+
121
+ type HttpTransportHeaders = Record<string, string>
122
+ type SseTransportHeaders = Record<string, string>
123
+
124
+ type ThreadMetadata = Record<string, string>
125
+ type TaskSchedule = {
126
+ start: string
127
+ due?: string
128
+ recurrenceRules?: RecurrenceRule[]
129
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
+ [key: string]: any
131
+ }
132
+ }
133
+ }