Skip to content
Open
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
44 changes: 44 additions & 0 deletions alembic/versions/d5e1a2c3f4b6_add_custom_provider_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""add custom provider type

Adds an explicit ``type`` discriminator to ``agent_custom_provider`` so
discovery and validation dispatch on a stored value instead of inferring from
display name or base URL. The column is a plain string (mirroring
``agent_catalog.model_provider``), not a DB enum, so new types can ship
without an enum migration.

Additive and backfilled by the server default: existing providers read back as
``generic_openai_compatible``, which preserves today's ``GET {base_url}/models``
discovery behavior.

Revision ID: d5e1a2c3f4b6
Revises: c6a8d4f3b2e1
Create Date: 2026-07-22 00:00:00.000000
"""

from collections.abc import Sequence

import sqlalchemy as sa

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "d5e1a2c3f4b6"
down_revision: str | None = "c6a8d4f3b2e1"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
op.add_column(
"agent_custom_provider",
sa.Column(
"type",
sa.String(length=120),
nullable=False,
server_default="generic_openai_compatible",
),
)


def downgrade() -> None:
op.drop_column("agent_custom_provider", "type")
25 changes: 25 additions & 0 deletions frontend/src/client/schemas.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1480,6 +1480,10 @@ export const $AgentCustomProviderCreate = {
],
title: "Base Url",
},
type: {
$ref: "#/components/schemas/CustomProviderType",
default: "generic_openai_compatible",
},
passthrough: {
type: "boolean",
title: "Passthrough",
Expand Down Expand Up @@ -1583,6 +1587,9 @@ export const $AgentCustomProviderRead = {
],
title: "Base Url",
},
type: {
$ref: "#/components/schemas/CustomProviderType",
},
passthrough: {
type: "boolean",
title: "Passthrough",
Expand Down Expand Up @@ -1617,6 +1624,7 @@ export const $AgentCustomProviderRead = {
"organization_id",
"display_name",
"base_url",
"type",
"passthrough",
"api_key_header",
"last_refreshed_at",
Expand Down Expand Up @@ -1651,6 +1659,16 @@ export const $AgentCustomProviderUpdate = {
],
title: "Base Url",
},
type: {
anyOf: [
{
$ref: "#/components/schemas/CustomProviderType",
},
{
type: "null",
},
],
},
passthrough: {
anyOf: [
{
Expand Down Expand Up @@ -11509,6 +11527,13 @@ export const $CustomOAuthProviderCreate = {
description: "Request payload for creating a custom OAuth provider.",
} as const

export const $CustomProviderType = {
type: "string",
enum: ["generic_openai_compatible", "litellm", "ollama"],
title: "CustomProviderType",
description: "Explicit provider type driving discovery and validation.",
} as const

export const $DSLConfig_Input = {
properties: {
scheduler: {
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/client/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ export type AgentChannelTokenUpdate = {
export type AgentCustomProviderCreate = {
display_name: string
base_url?: string | null
type?: CustomProviderType
passthrough?: boolean
api_key_header?: string | null
api_key?: string | null
Expand All @@ -433,6 +434,7 @@ export type AgentCustomProviderRead = {
organization_id: string
display_name: string
base_url: string | null
type: CustomProviderType
passthrough: boolean
api_key_header: string | null
last_refreshed_at: string | null
Expand All @@ -444,6 +446,7 @@ export type AgentCustomProviderRead = {
export type AgentCustomProviderUpdate = {
display_name?: string | null
base_url?: string | null
type?: CustomProviderType | null
passthrough?: boolean | null
api_key_header?: string | null
api_key?: string | null
Expand Down Expand Up @@ -3330,6 +3333,14 @@ export type CustomOAuthProviderCreate = {
client_secret?: string | null
}

/**
* Explicit provider type driving discovery and validation.
*/
export type CustomProviderType =
| "generic_openai_compatible"
| "litellm"
| "ollama"

/**
* This is the runtime configuration for the workflow.
*
Expand Down
32 changes: 32 additions & 0 deletions frontend/src/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,11 @@ export const providerIcons: Record<
<VllmIcon {...rest} />
</div>
),
litellm: ({ className, ...rest }) => (
<div className={className}>
<LiteLLMIcon {...rest} />
</div>
),
"manual-custom-source": ({ className, ...rest }) => (
<div className={className}>
<Sparkles {...rest} />
Expand Down Expand Up @@ -1479,6 +1484,33 @@ export function VllmIcon({ className, ...rest }: IconProps) {
)
}

export function LiteLLMIcon({ className, ...rest }: IconProps) {
// Official LiteLLM mark (selfh.st/icons, CC BY 4.0). Presented on a subtle
// tinted circle to match OllamaIcon; no dark background rect.
return (
<svg
viewBox="0 0 512 512"
role="img"
xmlns="http://www.w3.org/2000/svg"
className={cn("rounded-full bg-sky-400/20 p-[3px]", className)}
{...rest}
>
<path
fill="#d2d3d4"
d="M511.9 82.5c-.8-.1-1.4-.1-1.9-.1c-81.6 0-163.2 0-244.8.1c-8.5 0-16.6 2-24.4 5.4c-15.7 6.9-27.4 18.8-39 30.7c10.8 0 21.6.1 32.4.1h126.3c1.5 0 2.9 0 4.9 1l-11.7 11.7c-18.7 18.6-37.5 37.1-56.1 55.8c-3.4 3.4-6.8 4.9-11.7 4.9c-50.7-.2-101.3-.1-152-.1c-1.8 0-3.6-.1-5.5-.1c-18.4 9.3-36.9 18.7-55.3 28c0 49.8 0 99.7-.1 149.5c0 1.8-.1 3.6-.2 5.5c36.8 0 73.5-.1 110.3-.1c12.5-12.5 24.9-25.1 37.4-37.6c10.7-10.7 21.5-21.4 32.1-32.2c2.3-2.4 4.7-3.4 8.1-3.4c81.6.1 163.2 0 244.7 0c2.1 0 4.2-.1 6.3-.1c.1-.8.1-1.7.1-2.5V85c.2-.8.1-1.6.1-2.5"
/>
<path
fill="#6da7da"
d="M183.2 374.8c12.5-12.5 24.9-25.1 37.4-37.6c10.7-10.7 21.5-21.4 32.1-32.2c2.3-2.4 4.7-3.4 8.1-3.4c81.6.1 163.2 0 244.7 0c2.1 0 4.2-.1 6.3-.1c0 24.4.1 48.8.1 73.2c-1.8 0-3.6.1-5.5.1H296.7c-19.8 0-39.6 0-59.4.1c-18 0-36.1-.1-54.1-.1M30.5 243.1C4.4 260.5-4 286.2 1.7 316.2c6.5 34.3 36.1 58 71.2 58.7c.1-1.8.2-3.6.2-5.5c0-49.8.1-99.7.1-149.5c-14.4 7.6-29.3 14.3-42.7 23.2m137.9-91.5c-13.4 13.4-26.6 26.8-40 40.2c1.8 0 3.6.1 5.5.1c50.7 0 101.3-.1 152 .1c4.9 0 8.3-1.4 11.7-4.9c17.2-17.4 34.7-34.6 52.1-51.9H184.8z"
/>
<path
fill="#306599"
d="M511.8 411.3c0 6.1 0 12.2.1 18.3H24c-1.7 0-3.4-.1-5-.1c18-18.2 35.9-36.4 53.9-54.6c36.8 0 73.6-.1 110.4-.1c18.1.1 36.1.1 54.2.2c19.8 0 39.6-.1 59.4-.1h209.7c1.8 0 3.6-.1 5.5-.1c-.2 12.1-.2 24.3-.3 36.5M365.4 119.6c-2-1-3.4-1-4.9-1H234.2c-10.8 0-21.6-.1-32.4-.1c-5.6 5.6-11.3 11.2-17 16.8h164.8c1.3-1.3 2.7-2.6 4-4c4-3.8 7.9-7.8 11.8-11.7"
/>
</svg>
)
}

export function GoogleSheetsIcon({ className, ...rest }: IconProps) {
return (
<svg
Expand Down
Loading
Loading