Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
409 changes: 237 additions & 172 deletions bun.lock

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions packages/server/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"@activepieces/shared": "workspace:*",
"@ai-sdk/amazon-bedrock": "3.0.97",
"@ai-sdk/anthropic": "^3.0.0",
"@ai-sdk/mcp": "1.0.11",
"@ai-sdk/azure": "^3.0.0",
"@ai-sdk/google": "^3.0.0",
"@ai-sdk/google-vertex": "^3.0.0",
Expand All @@ -25,7 +26,6 @@
"@aws-sdk/s3-request-presigner": "3.894.0",
"@bull-board/api": "6.10.1",
"@bull-board/fastify": "6.10.1",
"@e2b/code-interpreter": "2.1.0",
"@electric-sql/pglite": "0.3.14",
"@fastify/basic-auth": "6.2.0",
"@fastify/cors": "11.0.1",
Expand Down Expand Up @@ -103,7 +103,6 @@
"redis-memory-server": "0.15.0",
"redlock": "5.0.0-beta.2",
"samlify": "2.10.0",
"sandbox-agent": "0.4.2",
"semver": "7.6.0",
"simple-git": "3.33.0",
"socket.io": "4.8.1",
Expand Down
6 changes: 6 additions & 0 deletions packages/server/api/src/app/ai/ai-provider-entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const AIProviderEncrypted = z.object({
provider: z.nativeEnum(AIProviderName),
auth: EncryptedObject,
config: AIProviderConfig,
enabledForChat: z.boolean().default(false),
})
type AIProviderEncrypted = z.infer<typeof AIProviderEncrypted>

Expand Down Expand Up @@ -43,6 +44,11 @@ export const AIProviderEntity = new EntitySchema<AIProviderSchema>({
type: String,
nullable: false,
},
enabledForChat: {
type: Boolean,
nullable: false,
default: false,
},
},
indices: [
{
Expand Down
58 changes: 47 additions & 11 deletions packages/server/api/src/app/ai/ai-provider-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,13 @@ export const aiProviderService = (log: FastifyBaseLogger) => ({
}
const configuredProviders = await aiProviderRepo().findBy({ platformId })

const formattedProviders: AIProviderWithoutSensitiveData[] = await Promise.all(configuredProviders.map(async p => {
return {
id: p.id,
name: p.displayName,
provider: p.provider,
config: p.config,
}
return configuredProviders.map((p): AIProviderWithoutSensitiveData => ({
id: p.id,
name: p.displayName,
provider: p.provider,
config: p.config,
enabledForChat: p.enabledForChat ?? false,
}))
return formattedProviders
},

async listModels(platformId: PlatformId, provider: AIProviderName): Promise<AIProviderModel[]> {
Expand Down Expand Up @@ -103,12 +101,23 @@ export const aiProviderService = (log: FastifyBaseLogger) => ({
platformId,
id: providerId,
})
if (isNil(aiProvider) || aiProvider.provider === AIProviderName.ACTIVEPIECES) {
if (isNil(aiProvider)) {
throw new ActivepiecesError({
code: ErrorCode.ENTITY_NOT_FOUND,
params: { entityId: providerId, entityType: 'AIProvider' },
})
}

if (aiProvider.provider === AIProviderName.ACTIVEPIECES) {
if (request.enabledForChat === true) {
await aiProviderRepo().manager.transaction(async (manager) => {
await manager.update(AIProviderEntity, { platformId }, { enabledForChat: false })
await manager.update(AIProviderEntity, providerId, { enabledForChat: true })
})
}
return
}

const config = request.config ?? aiProvider.config
if (!isNil(request.auth)) {
await this.validateProviderCredentials(aiProvider.provider, request.auth, config)
Expand All @@ -119,11 +128,38 @@ export const aiProviderService = (log: FastifyBaseLogger) => ({
}

const encryptedAuth = !isNil(request.auth) ? await encryptUtils.encryptObject(request.auth) : undefined
await aiProviderRepo().update(providerId, {
const updates = {
...spreadIfDefined('auth', encryptedAuth),
...spreadIfDefined('config', request.config),
...spreadIfDefined('enabledForChat', request.enabledForChat),
displayName: request.displayName,
})
}

if (request.enabledForChat === true) {
await aiProviderRepo().manager.transaction(async (manager) => {
await manager.update(AIProviderEntity, { platformId }, { enabledForChat: false })
await manager.update(AIProviderEntity, providerId, updates)
})
}
else {
await aiProviderRepo().update(providerId, updates)
}
},

async getChatProvider({ platformId }: { platformId: PlatformId }): Promise<GetProviderConfigResponse | null> {
const chatProvider = await aiProviderRepo().findOneBy({ platformId, enabledForChat: true })
if (isNil(chatProvider)) {
return null
}
let auth = await encryptUtils.decryptObject<AIProviderAuthConfig>(chatProvider.auth)
if (chatProvider.provider === AIProviderName.ACTIVEPIECES) {
const doesHaveKeys = !isNil(auth) && 'apiKey' in auth && !isNil(auth.apiKey) && auth.apiKey !== ''
if (!doesHaveKeys) {
const enriched = await enrichWithKeysIfNeeded(chatProvider, platformId, log)
auth = enriched.auth
}
}
return { provider: chatProvider.provider, auth, config: chatProvider.config, platformId }
},

async delete(platformId: PlatformId, providerId: string): Promise<void> {
Expand Down
Loading
Loading