@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.
- package/README.md +36 -0
- package/eslint.config.mjs +31 -0
- package/next.config.ts +7 -0
- package/package.json +176 -0
- package/prisma/Account.prisma +18 -0
- package/prisma/ApiKey.prisma +13 -0
- package/prisma/Assistant.prisma +32 -0
- package/prisma/AssistantHandler.prisma +12 -0
- package/prisma/Avatar.prisma +10 -0
- package/prisma/ClientToolHandler.prisma +13 -0
- package/prisma/CodeInterpreterTool.prisma +7 -0
- package/prisma/ComputerUseTool.prisma +12 -0
- package/prisma/CreateTaskHandler.prisma +10 -0
- package/prisma/DeleteTaskHandler.prisma +10 -0
- package/prisma/FileSearchTool.prisma +9 -0
- package/prisma/FirecrawlHandler.prisma +13 -0
- package/prisma/Function.prisma +13 -0
- package/prisma/Handler.prisma +19 -0
- package/prisma/HttpTransport.prisma +12 -0
- package/prisma/IconAvatar.prisma +8 -0
- package/prisma/ImageAvatar.prisma +8 -0
- package/prisma/ImageGenerationTool.prisma +11 -0
- package/prisma/InitialMessage.prisma +17 -0
- package/prisma/Invitation.prisma +15 -0
- package/prisma/ListTasksHandler.prisma +10 -0
- package/prisma/Log.prisma +21 -0
- package/prisma/McpServer.prisma +14 -0
- package/prisma/Message.prisma +30 -0
- package/prisma/ModelProvider.prisma +15 -0
- package/prisma/Organization.prisma +10 -0
- package/prisma/OrganizationApiKey.prisma +12 -0
- package/prisma/OrganizationInvitation.prisma +15 -0
- package/prisma/OrganizationUserRole.prisma +14 -0
- package/prisma/ReplicateHandler.prisma +14 -0
- package/prisma/RequestHandler.prisma +15 -0
- package/prisma/Run.prisma +36 -0
- package/prisma/RunStep.prisma +30 -0
- package/prisma/Session.prisma +7 -0
- package/prisma/SseTransport.prisma +12 -0
- package/prisma/StdioTransport.prisma +11 -0
- package/prisma/Task.prisma +15 -0
- package/prisma/Thread.prisma +20 -0
- package/prisma/Tool.prisma +13 -0
- package/prisma/UpdateTaskHandler.prisma +10 -0
- package/prisma/User.prisma +16 -0
- package/prisma/UserRole.prisma +14 -0
- package/prisma/VerificationToken.prisma +7 -0
- package/prisma/WebSearchTool.prisma +7 -0
- package/prisma/Workspace.prisma +14 -0
- package/prisma/enums/ApiKeyType.prisma +4 -0
- package/prisma/enums/AvatarType.prisma +5 -0
- package/prisma/enums/ClientToolHandlerType.prisma +3 -0
- package/prisma/enums/ComputerUseToolEnvironment.prisma +6 -0
- package/prisma/enums/FirecrawlHandlerType.prisma +6 -0
- package/prisma/enums/HandlerType.prisma +11 -0
- package/prisma/enums/IconAvatarName.prisma +14 -0
- package/prisma/enums/ImageGenerationToolOutputFormat.prisma +5 -0
- package/prisma/enums/ImageGenerationToolQuality.prisma +6 -0
- package/prisma/enums/ImageGenerationToolSize.prisma +6 -0
- package/prisma/enums/LogLevel.prisma +5 -0
- package/prisma/enums/LogRequestMethod.prisma +7 -0
- package/prisma/enums/LogRequestRoute.prisma +6 -0
- package/prisma/enums/MessageRole.prisma +4 -0
- package/prisma/enums/MessageStatus.prisma +5 -0
- package/prisma/enums/MethodType.prisma +7 -0
- package/prisma/enums/ModelProviderType.prisma +13 -0
- package/prisma/enums/OrganizationUserRoleType.prisma +3 -0
- package/prisma/enums/ReplicateHandlerType.prisma +3 -0
- package/prisma/enums/RunStatus.prisma +10 -0
- package/prisma/enums/RunStepStatus.prisma +7 -0
- package/prisma/enums/RunStepType.prisma +4 -0
- package/prisma/enums/StorageProviderType.prisma +7 -0
- package/prisma/enums/ToolType.prisma +7 -0
- package/prisma/enums/TransportType.prisma +5 -0
- package/prisma/enums/TruncationType.prisma +5 -0
- package/prisma/enums/UserRoleType.prisma +3 -0
- package/prisma/migrations/20251006235143_initial_setup/migration.sql +986 -0
- package/prisma/migrations/20251007163926_add_truncation_type/migration.sql +6 -0
- package/prisma/migrations/20251007190703_add_organizations/migration.sql +97 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +13 -0
- package/prisma.config.ts +6 -0
- package/scripts/cli.ts +84 -0
- package/scripts/commands/organizations/api-keys/create.ts +159 -0
- package/scripts/commands/organizations/create.ts +82 -0
- package/scripts/utils/env.ts +31 -0
- package/scripts/utils/errors.ts +6 -0
- package/src/app/api/api-keys/[apiKeyId]/route.ts +178 -0
- package/src/app/api/api-keys/route.ts +147 -0
- package/src/app/api/assistants/[assistantId]/functions/[functionId]/route.ts +245 -0
- package/src/app/api/assistants/[assistantId]/functions/route.ts +157 -0
- package/src/app/api/assistants/[assistantId]/initial-messages/route.ts +127 -0
- package/src/app/api/assistants/[assistantId]/mcp-servers/[mcpServerId]/route.ts +243 -0
- package/src/app/api/assistants/[assistantId]/mcp-servers/route.ts +163 -0
- package/src/app/api/assistants/[assistantId]/route.ts +336 -0
- package/src/app/api/assistants/route.ts +196 -0
- package/src/app/api/files/[fileId]/contents/route.ts +145 -0
- package/src/app/api/files/route.ts +117 -0
- package/src/app/api/messages/lib/getWorkspaceId.ts +12 -0
- package/src/app/api/messages/lib/initialMessagesResponse.ts +90 -0
- package/src/app/api/messages/lib/serializeThread.ts +22 -0
- package/src/app/api/messages/route.ts +710 -0
- package/src/app/api/providers/[modelProviderId]/assistants/route.ts +68 -0
- package/src/app/api/providers/[modelProviderId]/models/route.ts +68 -0
- package/src/app/api/providers/[modelProviderId]/route.ts +202 -0
- package/src/app/api/providers/route.ts +105 -0
- package/src/app/api/tasks/[taskId]/route.ts +213 -0
- package/src/app/api/tasks/callback/route.ts +280 -0
- package/src/app/api/tasks/route.ts +121 -0
- package/src/app/api/threads/runs/submit-client-tool-outputs/route.ts +54 -0
- package/src/app/api/workspaces/[workspaceId]/route.ts +137 -0
- package/src/app/api/workspaces/route.ts +139 -0
- package/src/app/layout.tsx +9 -0
- package/src/app/page.tsx +3 -0
- package/src/lib/apiKeys/formatApiKeyName.ts +13 -0
- package/src/lib/apiKeys/getApiKey.ts +25 -0
- package/src/lib/apiKeys/serializeApiKey.ts +11 -0
- package/src/lib/apiKeys/workspaceAccessWhere.ts +21 -0
- package/src/lib/assistants/assistantClientAdapter/buildGetOpenaiAssistant.ts +96 -0
- package/src/lib/assistants/assistantClientAdapter/index.ts +165 -0
- package/src/lib/assistants/formatName.ts +9 -0
- package/src/lib/assistants/serializeApiAssistant.ts +40 -0
- package/src/lib/assistants/serializeAssistant.ts +31 -0
- package/src/lib/assistants/storageAssistantId.ts +29 -0
- package/src/lib/avatars/defaultAvatar.ts +15 -0
- package/src/lib/avatars/serializeAvatar.ts +26 -0
- package/src/lib/cache/cacheHeaders.ts +5 -0
- package/src/lib/computerCalls/handleComputerCall/index.ts +173 -0
- package/src/lib/errors/index.ts +10 -0
- package/src/lib/errors/serializeError.ts +11 -0
- package/src/lib/functions/createFunction.ts +32 -0
- package/src/lib/functions/functionSchema.ts +201 -0
- package/src/lib/functions/handleFunction/getFunction.ts +43 -0
- package/src/lib/functions/handleFunction/handleAssistant.ts +399 -0
- package/src/lib/functions/handleFunction/handleClientTool.ts +127 -0
- package/src/lib/functions/handleFunction/handleFirecrawl.ts +212 -0
- package/src/lib/functions/handleFunction/handleReplicate.ts +109 -0
- package/src/lib/functions/handleFunction/handleRequest.ts +272 -0
- package/src/lib/functions/handleFunction/index.ts +474 -0
- package/src/lib/functions/handleFunction/tasks/handleCreateTask.ts +58 -0
- package/src/lib/functions/handleFunction/tasks/handleDeleteTask.ts +62 -0
- package/src/lib/functions/handleFunction/tasks/handleListTasks.ts +53 -0
- package/src/lib/functions/handleFunction/tasks/handleUpdateTask.ts +70 -0
- package/src/lib/functions/interpolateFunctionValue.ts +26 -0
- package/src/lib/functions/serializeApiFunction.ts +32 -0
- package/src/lib/functions/updateFunction.ts +42 -0
- package/src/lib/handlers/handlerPrismaInput.tsx +141 -0
- package/src/lib/handlers/serializeApiHandler.ts +94 -0
- package/src/lib/iconAvatars/serializeIconAvatar.ts +9 -0
- package/src/lib/imageAvatars/serializeImageAvatar.ts +9 -0
- package/src/lib/initialMessages/schema.ts +11 -0
- package/src/lib/initialMessages/serializeApiInitialMessage.ts +15 -0
- package/src/lib/initialMessages/updateInitialMessages.ts +33 -0
- package/src/lib/logs/createLog.ts +17 -0
- package/src/lib/mcpServers/closeMcpConnection.ts +16 -0
- package/src/lib/mcpServers/connectMcpServer.ts +117 -0
- package/src/lib/mcpServers/getToolCallMcpServer.ts +62 -0
- package/src/lib/mcpServers/headers.ts +113 -0
- package/src/lib/mcpServers/mcpServerSchema.ts +77 -0
- package/src/lib/mcpServers/serializeApiMcpServer.ts +51 -0
- package/src/lib/mcpServers/url.ts +98 -0
- package/src/lib/messages/content.ts +60 -0
- package/src/lib/messages/textContent.ts +13 -0
- package/src/lib/metadata/serializeMetadata.ts +34 -0
- package/src/lib/misc/isJSON.ts +9 -0
- package/src/lib/misc/merge/customizer.ts +8 -0
- package/src/lib/misc/merge/index.ts +6 -0
- package/src/lib/modelProviders/buildAzureOpenaiClientAdapter.ts +33 -0
- package/src/lib/modelProviders/buildOpenaiClient.ts +14 -0
- package/src/lib/modelProviders/buildOpenaiClientAdapter.ts +30 -0
- package/src/lib/modelProviders/clientAdapter.ts +121 -0
- package/src/lib/modelProviders/isModelProviderValid.ts +23 -0
- package/src/lib/modelProviders/modelProviderConfigs.ts +221 -0
- package/src/lib/modelProviders/serializeModelProvider.ts +19 -0
- package/src/lib/models/getModels.ts +27 -0
- package/src/lib/models/serializeApiModel.ts +5 -0
- package/src/lib/openai/getOpenaiAssistants.ts +30 -0
- package/src/lib/organizationApiKeys/getOrganizationApiKey.ts +23 -0
- package/src/lib/prisma/index.ts +29 -0
- package/src/lib/redis/index.ts +3 -0
- package/src/lib/runs/createRunOpts.ts +80 -0
- package/src/lib/storageProviders/getStorageProviderAssistants.ts +19 -0
- package/src/lib/storageProviders/getStorageProviderType.ts +21 -0
- package/src/lib/storageProviders/isOpenaiAssistantsStorageProvider.ts +8 -0
- package/src/lib/storageProviders/isResponsesStorageProvider.ts +8 -0
- package/src/lib/storageProviders/openaiAssistantsStorageProviderTypes.ts +6 -0
- package/src/lib/storageProviders/responsesStorageProviderTypes.ts +6 -0
- package/src/lib/storageProviders/serializeApiStorageProviderAssistant.ts +14 -0
- package/src/lib/tasks/cancelScheduledTask.ts +13 -0
- package/src/lib/tasks/getNextOccurrence.ts +77 -0
- package/src/lib/tasks/getTaskToolKey.ts +49 -0
- package/src/lib/tasks/parseTaskToolArgs.ts +101 -0
- package/src/lib/tasks/scheduleSchema.ts +34 -0
- package/src/lib/tasks/scheduleTask.ts +37 -0
- package/src/lib/tasks/schemas.ts +25 -0
- package/src/lib/tasks/serializeTask.ts +14 -0
- package/src/lib/tasks/validateSchedule.ts +23 -0
- package/src/lib/themes/defaultTheme.ts +7 -0
- package/src/lib/themes/serializeAccentColor.ts +9 -0
- package/src/lib/themes/serializeTheme/index.ts +25 -0
- package/src/lib/themes/serializeTheme/serializeScaling.ts +14 -0
- package/src/lib/threads/createThread/index.ts +185 -0
- package/src/lib/threads/createThread/initialMessages.ts +36 -0
- package/src/lib/threads/managedOpenaiThreadId.ts +72 -0
- package/src/lib/threads/storageThreadId.ts +49 -0
- package/src/lib/threads/validThreadId.ts +10 -0
- package/src/lib/toolCalls/handleToolCall.ts +121 -0
- package/src/lib/toolCalls/messagesToOutput.ts +8 -0
- package/src/lib/toolCalls/streamOutput.ts +106 -0
- package/src/lib/tools/tools/index.ts +316 -0
- package/src/lib/upstash/qstash.ts +5 -0
- package/src/lib/upstash/upstashWorkflowClient.ts +5 -0
- package/src/lib/workspaces/serializeApiWorkspace.ts +12 -0
- package/src/types/index.ts +133 -0
- package/tsconfig.build.json +13 -0
- package/tsconfig.json +27 -0
- package/types/prisma.d.ts +4 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { headers } from 'next/headers'
|
|
2
|
+
import { ApiKeyType } from '@prisma/client'
|
|
3
|
+
import { NextResponse, type NextRequest } from 'next/server'
|
|
4
|
+
import { cacheHeaders } from '@/lib/cache/cacheHeaders'
|
|
5
|
+
import { prisma } from '@/lib/prisma'
|
|
6
|
+
import { getApiKey } from '@/lib/apiKeys/getApiKey'
|
|
7
|
+
import { getStorageProviderAssistants } from '@/lib/storageProviders/getStorageProviderAssistants'
|
|
8
|
+
import { serializeApiStorageProviderAssistant } from '@/lib/storageProviders/serializeApiStorageProviderAssistant'
|
|
9
|
+
|
|
10
|
+
export const GET = async (
|
|
11
|
+
_request: NextRequest,
|
|
12
|
+
props: { params: Promise<{ modelProviderId: string }> },
|
|
13
|
+
) => {
|
|
14
|
+
const { modelProviderId } = await props.params
|
|
15
|
+
|
|
16
|
+
const headersList = await headers()
|
|
17
|
+
const authorization = headersList.get('authorization')
|
|
18
|
+
if (!authorization) {
|
|
19
|
+
return NextResponse.json(
|
|
20
|
+
{ error: 'No authorization header found' },
|
|
21
|
+
{ status: 400 },
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const privateApiKey = await getApiKey({
|
|
26
|
+
type: ApiKeyType.PRIVATE,
|
|
27
|
+
authorization,
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
if (!privateApiKey) {
|
|
31
|
+
return NextResponse.json({ error: 'Invalid api key' }, { status: 400 })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const provider = await prisma.modelProvider.findUnique({
|
|
35
|
+
where: {
|
|
36
|
+
id: modelProviderId,
|
|
37
|
+
workspaceId: privateApiKey.workspaceId,
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
if (!provider) {
|
|
42
|
+
return NextResponse.json({ error: 'No provider found' }, { status: 400 })
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const storageProviderAssistants = await getStorageProviderAssistants({
|
|
46
|
+
modelProvider: provider,
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
return NextResponse.json(
|
|
50
|
+
{
|
|
51
|
+
storageProviderAssistants: storageProviderAssistants.map(
|
|
52
|
+
(storageProviderAssistant) =>
|
|
53
|
+
serializeApiStorageProviderAssistant({
|
|
54
|
+
storageProviderAssistant,
|
|
55
|
+
}),
|
|
56
|
+
),
|
|
57
|
+
},
|
|
58
|
+
{ headers: cacheHeaders },
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const OPTIONS = () =>
|
|
63
|
+
NextResponse.json(
|
|
64
|
+
{},
|
|
65
|
+
{
|
|
66
|
+
headers: cacheHeaders,
|
|
67
|
+
},
|
|
68
|
+
)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { headers } from 'next/headers'
|
|
2
|
+
import { ApiKeyType } from '@prisma/client'
|
|
3
|
+
import { NextResponse, type NextRequest } from 'next/server'
|
|
4
|
+
import { cacheHeaders } from '@/lib/cache/cacheHeaders'
|
|
5
|
+
import { prisma } from '@/lib/prisma'
|
|
6
|
+
import { getApiKey } from '@/lib/apiKeys/getApiKey'
|
|
7
|
+
import { getModels } from '@/lib/models/getModels'
|
|
8
|
+
import { serializeApiModel } from '@/lib/models/serializeApiModel'
|
|
9
|
+
|
|
10
|
+
export const GET = async (
|
|
11
|
+
_request: NextRequest,
|
|
12
|
+
props: { params: Promise<{ modelProviderId: string }> },
|
|
13
|
+
) => {
|
|
14
|
+
const { modelProviderId } = await props.params
|
|
15
|
+
|
|
16
|
+
const headersList = await headers()
|
|
17
|
+
const authorization = headersList.get('authorization')
|
|
18
|
+
|
|
19
|
+
if (!authorization) {
|
|
20
|
+
return NextResponse.json(
|
|
21
|
+
{ error: 'No authorization header found' },
|
|
22
|
+
{ status: 400 },
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const privateApiKey = await getApiKey({
|
|
27
|
+
type: ApiKeyType.PRIVATE,
|
|
28
|
+
authorization,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
if (!privateApiKey) {
|
|
32
|
+
return NextResponse.json({ error: 'Invalid api key' }, { status: 400 })
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const provider = await prisma.modelProvider.findUnique({
|
|
36
|
+
where: {
|
|
37
|
+
id: modelProviderId,
|
|
38
|
+
workspaceId: privateApiKey.workspaceId,
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
if (!provider) {
|
|
43
|
+
return NextResponse.json({ error: 'No provider found' }, { status: 400 })
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const models = await getModels({
|
|
47
|
+
modelProvider: provider,
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
return NextResponse.json(
|
|
51
|
+
{
|
|
52
|
+
models: models.map((model) =>
|
|
53
|
+
serializeApiModel({
|
|
54
|
+
model,
|
|
55
|
+
}),
|
|
56
|
+
),
|
|
57
|
+
},
|
|
58
|
+
{ headers: cacheHeaders },
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const OPTIONS = () =>
|
|
63
|
+
NextResponse.json(
|
|
64
|
+
{},
|
|
65
|
+
{
|
|
66
|
+
headers: cacheHeaders,
|
|
67
|
+
},
|
|
68
|
+
)
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { headers } from 'next/headers'
|
|
2
|
+
import { ApiKeyType, ModelProviderType, Prisma } from '@prisma/client'
|
|
3
|
+
import { NextResponse, type NextRequest } from 'next/server'
|
|
4
|
+
import { z } from 'zod'
|
|
5
|
+
import { cacheHeaders } from '@/lib/cache/cacheHeaders'
|
|
6
|
+
import { prisma } from '@/lib/prisma'
|
|
7
|
+
import { serializeModelProvider } from '@/lib/modelProviders/serializeModelProvider'
|
|
8
|
+
import { getApiKey } from '@/lib/apiKeys/getApiKey'
|
|
9
|
+
import { validate } from 'uuid'
|
|
10
|
+
|
|
11
|
+
export const GET = async (
|
|
12
|
+
_request: NextRequest,
|
|
13
|
+
props: { params: Promise<{ modelProviderId: string }> },
|
|
14
|
+
) => {
|
|
15
|
+
const { modelProviderId } = await props.params
|
|
16
|
+
|
|
17
|
+
const headersList = await headers()
|
|
18
|
+
const authorization = headersList.get('authorization')
|
|
19
|
+
if (!authorization) {
|
|
20
|
+
return NextResponse.json(
|
|
21
|
+
{ error: 'No authorization header found' },
|
|
22
|
+
{ status: 400 },
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const privateApiKey = await getApiKey({
|
|
27
|
+
type: ApiKeyType.PRIVATE,
|
|
28
|
+
authorization,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
if (!privateApiKey) {
|
|
32
|
+
return NextResponse.json({ error: 'Invalid api key' }, { status: 400 })
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!validate(modelProviderId)) {
|
|
36
|
+
return NextResponse.json({ error: 'Invalid provider id' }, { status: 400 })
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const provider = await prisma.modelProvider.findFirst({
|
|
40
|
+
where: {
|
|
41
|
+
id: modelProviderId,
|
|
42
|
+
workspaceId: privateApiKey.workspaceId,
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
if (!provider) {
|
|
47
|
+
return NextResponse.json({ error: 'No provider found' }, { status: 400 })
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return NextResponse.json(
|
|
51
|
+
{
|
|
52
|
+
provider: serializeModelProvider({ provider }),
|
|
53
|
+
},
|
|
54
|
+
{ headers: cacheHeaders },
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const PATCH = async (
|
|
59
|
+
request: NextRequest,
|
|
60
|
+
props: { params: Promise<{ modelProviderId: string }> },
|
|
61
|
+
) => {
|
|
62
|
+
const { modelProviderId } = await props.params
|
|
63
|
+
|
|
64
|
+
const headersList = await headers()
|
|
65
|
+
const authorization = headersList.get('authorization')
|
|
66
|
+
if (!authorization) {
|
|
67
|
+
return NextResponse.json(
|
|
68
|
+
{ error: 'No authorization header found' },
|
|
69
|
+
{ status: 400 },
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const privateApiKey = await getApiKey({
|
|
74
|
+
authorization,
|
|
75
|
+
type: ApiKeyType.PRIVATE,
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
if (!privateApiKey) {
|
|
79
|
+
return NextResponse.json({ error: 'Invalid api key' }, { status: 400 })
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!validate(modelProviderId)) {
|
|
83
|
+
return NextResponse.json({ error: 'Invalid provider id' }, { status: 400 })
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const body = await request.json()
|
|
87
|
+
const schema = z.object({
|
|
88
|
+
type: z.nativeEnum(ModelProviderType).optional(),
|
|
89
|
+
name: z.string().optional(),
|
|
90
|
+
apiKey: z.string().optional(),
|
|
91
|
+
endpoint: z.string().optional().nullable(),
|
|
92
|
+
apiVersion: z.string().optional().nullable(),
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
const parsed = schema.safeParse(body)
|
|
96
|
+
|
|
97
|
+
if (!parsed.success) {
|
|
98
|
+
return NextResponse.json({ error: 'Invalid payload' }, { status: 400 })
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const { type, apiKey: providerKey, endpoint, apiVersion, name } = parsed.data
|
|
102
|
+
const updateData: Prisma.ModelProviderUpdateInput = {
|
|
103
|
+
...(type ? { type } : {}),
|
|
104
|
+
...(name !== undefined ? { name } : {}),
|
|
105
|
+
...(providerKey !== undefined ? { apiKey: providerKey } : {}),
|
|
106
|
+
...(endpoint !== undefined ? { endpoint } : {}),
|
|
107
|
+
...(apiVersion !== undefined ? { apiVersion } : {}),
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const existingProvider = await prisma.modelProvider.findFirst({
|
|
111
|
+
where: {
|
|
112
|
+
id: modelProviderId,
|
|
113
|
+
workspaceId: privateApiKey.workspaceId,
|
|
114
|
+
},
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
if (!existingProvider) {
|
|
118
|
+
return NextResponse.json({ error: 'No provider found' }, { status: 400 })
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const provider = await prisma.modelProvider.update({
|
|
122
|
+
where: { id: modelProviderId },
|
|
123
|
+
data: updateData,
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
return NextResponse.json(
|
|
127
|
+
{
|
|
128
|
+
provider: serializeModelProvider({ provider }),
|
|
129
|
+
},
|
|
130
|
+
{ headers: cacheHeaders },
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export const DELETE = async (
|
|
135
|
+
_request: NextRequest,
|
|
136
|
+
props: { params: Promise<{ modelProviderId: string }> },
|
|
137
|
+
) => {
|
|
138
|
+
const { modelProviderId } = await props.params
|
|
139
|
+
|
|
140
|
+
const headersList = await headers()
|
|
141
|
+
const authorization = headersList.get('authorization')
|
|
142
|
+
if (!authorization) {
|
|
143
|
+
return NextResponse.json(
|
|
144
|
+
{ error: 'No authorization header found' },
|
|
145
|
+
{ status: 400 },
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const privateApiKey = await getApiKey({
|
|
150
|
+
authorization,
|
|
151
|
+
type: ApiKeyType.PRIVATE,
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
if (!privateApiKey) {
|
|
155
|
+
return NextResponse.json({ error: 'Invalid api key' }, { status: 400 })
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!validate(modelProviderId)) {
|
|
159
|
+
return NextResponse.json({ error: 'Invalid provider id' }, { status: 400 })
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const assistantsUsingProvider = await prisma.assistant.count({
|
|
163
|
+
where: {
|
|
164
|
+
modelProviderId: modelProviderId,
|
|
165
|
+
workspaceId: privateApiKey.workspaceId,
|
|
166
|
+
},
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
if (assistantsUsingProvider > 0) {
|
|
170
|
+
return NextResponse.json({ error: 'Provider in use' }, { status: 400 })
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const existingProvider = await prisma.modelProvider.findFirst({
|
|
174
|
+
where: {
|
|
175
|
+
id: modelProviderId,
|
|
176
|
+
workspaceId: privateApiKey.workspaceId,
|
|
177
|
+
},
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
if (!existingProvider) {
|
|
181
|
+
return NextResponse.json({ error: 'No provider found' }, { status: 400 })
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const provider = await prisma.modelProvider.delete({
|
|
185
|
+
where: { id: modelProviderId },
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
return NextResponse.json(
|
|
189
|
+
{
|
|
190
|
+
provider: serializeModelProvider({ provider }),
|
|
191
|
+
},
|
|
192
|
+
{ headers: cacheHeaders },
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export const OPTIONS = () =>
|
|
197
|
+
NextResponse.json(
|
|
198
|
+
{},
|
|
199
|
+
{
|
|
200
|
+
headers: cacheHeaders,
|
|
201
|
+
},
|
|
202
|
+
)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { headers } from 'next/headers'
|
|
2
|
+
import { ApiKeyType, ModelProviderType } from '@prisma/client'
|
|
3
|
+
import { NextResponse, type NextRequest } from 'next/server'
|
|
4
|
+
import { z } from 'zod'
|
|
5
|
+
import { cacheHeaders } from '@/lib/cache/cacheHeaders'
|
|
6
|
+
import { prisma } from '@/lib/prisma'
|
|
7
|
+
import { serializeModelProvider } from '@/lib/modelProviders/serializeModelProvider'
|
|
8
|
+
import { getApiKey } from '@/lib/apiKeys/getApiKey'
|
|
9
|
+
|
|
10
|
+
export const GET = async () => {
|
|
11
|
+
const headersList = await headers()
|
|
12
|
+
const authorization = headersList.get('authorization')
|
|
13
|
+
if (!authorization) {
|
|
14
|
+
return NextResponse.json(
|
|
15
|
+
{ error: 'No authorization header found' },
|
|
16
|
+
{ status: 400 },
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const privateApiKey = await getApiKey({
|
|
21
|
+
type: ApiKeyType.PRIVATE,
|
|
22
|
+
authorization,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
if (!privateApiKey) {
|
|
26
|
+
return NextResponse.json({ error: 'Invalid api key' }, { status: 400 })
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const providers = await prisma.modelProvider.findMany({
|
|
30
|
+
where: {
|
|
31
|
+
workspaceId: privateApiKey.workspaceId,
|
|
32
|
+
},
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
return NextResponse.json(
|
|
36
|
+
{
|
|
37
|
+
providers: providers.map((p) => serializeModelProvider({ provider: p })),
|
|
38
|
+
},
|
|
39
|
+
{ headers: cacheHeaders },
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const POST = async (request: NextRequest) => {
|
|
44
|
+
const headersList = await headers()
|
|
45
|
+
const authorization = headersList.get('authorization')
|
|
46
|
+
if (!authorization) {
|
|
47
|
+
return NextResponse.json(
|
|
48
|
+
{ error: 'No authorization header found' },
|
|
49
|
+
{ status: 400 },
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const privateApiKey = await getApiKey({
|
|
54
|
+
authorization,
|
|
55
|
+
type: ApiKeyType.PRIVATE,
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
if (!privateApiKey) {
|
|
59
|
+
return NextResponse.json({ error: 'Invalid api key' }, { status: 400 })
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const body = await request.json()
|
|
63
|
+
const schema = z.object({
|
|
64
|
+
type: z.nativeEnum(ModelProviderType),
|
|
65
|
+
name: z.string().optional(),
|
|
66
|
+
apiKey: z.string().optional(),
|
|
67
|
+
endpoint: z.string().optional().nullable(),
|
|
68
|
+
apiVersion: z.string().optional().nullable(),
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const parsed = schema.safeParse(body)
|
|
72
|
+
|
|
73
|
+
if (!parsed.success) {
|
|
74
|
+
return NextResponse.json({ error: 'Invalid payload' }, { status: 400 })
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const { type, name, apiKey: providerKey, endpoint, apiVersion } = parsed.data
|
|
78
|
+
const workspaceId = privateApiKey.workspaceId
|
|
79
|
+
|
|
80
|
+
const provider = await prisma.modelProvider.create({
|
|
81
|
+
data: {
|
|
82
|
+
type: type as ModelProviderType,
|
|
83
|
+
name: name ?? '',
|
|
84
|
+
apiKey: providerKey ?? '',
|
|
85
|
+
endpoint: endpoint ?? null,
|
|
86
|
+
apiVersion: apiVersion ?? null,
|
|
87
|
+
workspaceId,
|
|
88
|
+
},
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
return NextResponse.json(
|
|
92
|
+
{
|
|
93
|
+
provider: serializeModelProvider({ provider }),
|
|
94
|
+
},
|
|
95
|
+
{ headers: cacheHeaders },
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export const OPTIONS = () =>
|
|
100
|
+
NextResponse.json(
|
|
101
|
+
{},
|
|
102
|
+
{
|
|
103
|
+
headers: cacheHeaders,
|
|
104
|
+
},
|
|
105
|
+
)
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { headers } from 'next/headers'
|
|
2
|
+
import { ApiKeyType } from '@prisma/client'
|
|
3
|
+
import { NextResponse, type NextRequest } from 'next/server'
|
|
4
|
+
import { z } from 'zod'
|
|
5
|
+
import { validate } from 'uuid'
|
|
6
|
+
import { cacheHeaders } from '@/lib/cache/cacheHeaders'
|
|
7
|
+
import { prisma } from '@/lib/prisma'
|
|
8
|
+
import { serializeTask } from '@/lib/tasks/serializeTask'
|
|
9
|
+
import { validateSchedule } from '@/lib/tasks/validateSchedule'
|
|
10
|
+
import { getApiKey } from '@/lib/apiKeys/getApiKey'
|
|
11
|
+
import { scheduleTask } from '@/lib/tasks/scheduleTask'
|
|
12
|
+
import { cancelScheduledTask } from '@/lib/tasks/cancelScheduledTask'
|
|
13
|
+
|
|
14
|
+
const updateTaskSchema = z.object({
|
|
15
|
+
title: z.string().optional(),
|
|
16
|
+
message: z.string().optional(),
|
|
17
|
+
schedule: z.any().optional(),
|
|
18
|
+
key: z.string().optional(),
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
export const GET = async (
|
|
22
|
+
_request: NextRequest,
|
|
23
|
+
props: { params: Promise<{ taskId: string }> },
|
|
24
|
+
) => {
|
|
25
|
+
const { taskId } = await props.params
|
|
26
|
+
|
|
27
|
+
const headersList = await headers()
|
|
28
|
+
const authorization = headersList.get('authorization')
|
|
29
|
+
if (!authorization) {
|
|
30
|
+
return NextResponse.json(
|
|
31
|
+
{ error: 'No authorization header found' },
|
|
32
|
+
{ status: 400 },
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const privateApiKey = await getApiKey({
|
|
37
|
+
authorization,
|
|
38
|
+
type: ApiKeyType.PRIVATE,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
if (!privateApiKey) {
|
|
42
|
+
return NextResponse.json({ error: 'Invalid api key' }, { status: 400 })
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!taskId) {
|
|
46
|
+
return NextResponse.json({ error: 'No task id found' }, { status: 400 })
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!validate(taskId)) {
|
|
50
|
+
return NextResponse.json({ error: 'Invalid task id' }, { status: 400 })
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const task = await prisma.task.findFirst({
|
|
54
|
+
where: {
|
|
55
|
+
id: taskId,
|
|
56
|
+
thread: { assistant: { workspaceId: privateApiKey.workspaceId } },
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
if (!task) {
|
|
61
|
+
return NextResponse.json({ error: 'No task found' }, { status: 400 })
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return NextResponse.json(
|
|
65
|
+
{ task: serializeTask({ task }) },
|
|
66
|
+
{ headers: cacheHeaders },
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const PATCH = async (
|
|
71
|
+
request: NextRequest,
|
|
72
|
+
props: { params: Promise<{ taskId: string }> },
|
|
73
|
+
) => {
|
|
74
|
+
const { taskId } = await props.params
|
|
75
|
+
|
|
76
|
+
const headersList = await headers()
|
|
77
|
+
const authorization = headersList.get('authorization')
|
|
78
|
+
if (!authorization) {
|
|
79
|
+
return NextResponse.json(
|
|
80
|
+
{ error: 'No authorization header found' },
|
|
81
|
+
{ status: 400 },
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const privateApiKey = await getApiKey({
|
|
86
|
+
authorization,
|
|
87
|
+
type: ApiKeyType.PRIVATE,
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
if (!privateApiKey) {
|
|
91
|
+
return NextResponse.json({ error: 'Invalid api key' }, { status: 400 })
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!taskId) {
|
|
95
|
+
return NextResponse.json({ error: 'No task id found' }, { status: 400 })
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!validate(taskId)) {
|
|
99
|
+
return NextResponse.json({ error: 'Invalid task id' }, { status: 400 })
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const parsed = updateTaskSchema.safeParse(await request.json())
|
|
103
|
+
|
|
104
|
+
if (!parsed.success) {
|
|
105
|
+
return NextResponse.json({ error: 'Invalid payload' }, { status: 400 })
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const updateData = {
|
|
109
|
+
...(parsed.data.title !== undefined ? { title: parsed.data.title } : {}),
|
|
110
|
+
...(parsed.data.message !== undefined
|
|
111
|
+
? { message: parsed.data.message }
|
|
112
|
+
: {}),
|
|
113
|
+
...(parsed.data.schedule !== undefined
|
|
114
|
+
? {
|
|
115
|
+
...(validateSchedule(parsed.data.schedule)
|
|
116
|
+
? { schedule: parsed.data.schedule }
|
|
117
|
+
: {}),
|
|
118
|
+
}
|
|
119
|
+
: {}),
|
|
120
|
+
...(parsed.data.key !== undefined ? { key: parsed.data.key } : {}),
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (
|
|
124
|
+
parsed.data.schedule !== undefined &&
|
|
125
|
+
!validateSchedule(parsed.data.schedule)
|
|
126
|
+
) {
|
|
127
|
+
return NextResponse.json({ error: 'Invalid schedule' }, { status: 400 })
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const existingTask = await prisma.task.findFirst({
|
|
131
|
+
where: {
|
|
132
|
+
id: taskId,
|
|
133
|
+
thread: { assistant: { workspaceId: privateApiKey.workspaceId } },
|
|
134
|
+
},
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
if (!existingTask) {
|
|
138
|
+
return NextResponse.json({ error: 'No task found' }, { status: 400 })
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const task = await prisma.task.update({
|
|
142
|
+
where: { id: existingTask.id },
|
|
143
|
+
data: updateData,
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
await scheduleTask({ task })
|
|
147
|
+
|
|
148
|
+
return NextResponse.json(
|
|
149
|
+
{ task: serializeTask({ task }) },
|
|
150
|
+
{ headers: cacheHeaders },
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export const DELETE = async (
|
|
155
|
+
_request: NextRequest,
|
|
156
|
+
props: { params: Promise<{ taskId: string }> },
|
|
157
|
+
) => {
|
|
158
|
+
const { taskId } = await props.params
|
|
159
|
+
|
|
160
|
+
const headersList = await headers()
|
|
161
|
+
const authorization = headersList.get('authorization')
|
|
162
|
+
if (!authorization) {
|
|
163
|
+
return NextResponse.json(
|
|
164
|
+
{ error: 'No authorization header found' },
|
|
165
|
+
{ status: 400 },
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const privateApiKey = await getApiKey({
|
|
170
|
+
authorization,
|
|
171
|
+
type: ApiKeyType.PRIVATE,
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
if (!privateApiKey) {
|
|
175
|
+
return NextResponse.json({ error: 'Invalid api key' }, { status: 400 })
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (!taskId) {
|
|
179
|
+
return NextResponse.json({ error: 'No task id found' }, { status: 400 })
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (!validate(taskId)) {
|
|
183
|
+
return NextResponse.json({ error: 'Invalid task id' }, { status: 400 })
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const existingTask = await prisma.task.findFirst({
|
|
187
|
+
where: {
|
|
188
|
+
id: taskId,
|
|
189
|
+
thread: { assistant: { workspaceId: privateApiKey.workspaceId } },
|
|
190
|
+
},
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
if (!existingTask) {
|
|
194
|
+
return NextResponse.json({ error: 'No task found' }, { status: 400 })
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
await cancelScheduledTask({ task: existingTask })
|
|
198
|
+
|
|
199
|
+
const task = await prisma.task.delete({ where: { id: existingTask.id } })
|
|
200
|
+
|
|
201
|
+
return NextResponse.json(
|
|
202
|
+
{ task: serializeTask({ task }) },
|
|
203
|
+
{ headers: cacheHeaders },
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export const OPTIONS = () =>
|
|
208
|
+
NextResponse.json(
|
|
209
|
+
{},
|
|
210
|
+
{
|
|
211
|
+
headers: cacheHeaders,
|
|
212
|
+
},
|
|
213
|
+
)
|