Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
30583e7
chore: sync OSS code and website build
auroraix Jul 22, 2026
56ac244
chore: prompt caching support and dedicated tests
auroraix Jul 26, 2026
9d766fa
chore: anthropic sdk format synced up
auroraix Jul 26, 2026
17d28e2
chore: anthropic sdk format synced up
auroraix Jul 26, 2026
354540e
chore: Guardials input + output implementaion
auroraix Jul 26, 2026
e02dcd2
docs: rebuild marketing site
auroraix Aug 1, 2026
5ff5677
feat(dashboard): custom warm theme + fallback page + animated logo
entitybtw Aug 14, 2026
3293929
fix(dashboard): logo as img, fallback from config, remove broken toggle
entitybtw Aug 14, 2026
d5d720b
fix(dashboard): logo without bg, fallback with full CRUD
entitybtw Aug 14, 2026
4532e1b
fix(dashboard): inline SVG logo, editable fallback page
entitybtw Aug 14, 2026
9e2dae8
feat(dashboard): Catppuccin theme + live fallback.json management
entitybtw Aug 14, 2026
fa5118c
style: Catppuccin Frappe palette (medium dark, pleasant)
entitybtw Aug 14, 2026
d8d4d57
fix(fallback): use Edit3 icon for edit button (was Save icon)
entitybtw Aug 14, 2026
a252b39
style: polish Catppuccin Latte light theme
entitybtw Aug 14, 2026
4620fab
revert: restore original Catppuccin Latte light theme
entitybtw Aug 14, 2026
1733dff
feat(dashboard): Catppuccin Mocha dark + full mobile responsiveness
entitybtw Aug 14, 2026
ff43c61
feat(dashboard): proper mobile UX with bottom nav bar
entitybtw Aug 14, 2026
640b84d
Add full mobile responsive design for dashboard
entitybtw Aug 14, 2026
9928282
fix(mobile): animated burger icon, remove bottom nav, mobile auth dialog
entitybtw Aug 14, 2026
7ce05c7
fix(mobile): logo in header/sidebar, clean up sidebar, mobile auth
entitybtw Aug 14, 2026
2f7986b
fix(mobile+theme): Aurora branding, mobile theme toggle, light theme,…
entitybtw Aug 15, 2026
8d69a6d
fix(fallback+mobile): edit button per card, inline target editing, cl…
entitybtw Aug 15, 2026
71b6a99
fix(fallback+mobile): stable sort, dialog editor with dropdowns, comp…
entitybtw Aug 15, 2026
a3d9b08
fix(mobile): proper dialog sizing, compact nav buttons
entitybtw Aug 15, 2026
9955099
fix(sidebar): py-2.5 nav links for proper button height on mobile
entitybtw Aug 15, 2026
8a92645
fix: sidebar py-2 same as PC, providers button default size
entitybtw Aug 15, 2026
ea4004a
feat(providers): persist UI providers to file, add vllm type
entitybtw Aug 15, 2026
4020af0
fix(providers): mount provider-overrides.json in Docker for persistence
entitybtw Aug 15, 2026
6237d3b
fix(sidebar): mobile theme toggle buttons larger h-10, icon h-4, Moni…
entitybtw Aug 15, 2026
0c18d5a
fix(providers): prevent duplicate entries when override already in re…
entitybtw Aug 15, 2026
b7edd5b
fix(providers+fallback): override precedence over .env, dialog no hor…
entitybtw Aug 15, 2026
9d93fe9
fix(providers): apply persisted UI overrides at startup, widen fallba…
entitybtw Aug 15, 2026
7eb30d7
fix(fallback): mobile-adaptive edit dialog
entitybtw Aug 15, 2026
17e9688
fix(fallback): fullscreen mobile dialog, content stretches to screen …
entitybtw Aug 15, 2026
4e9cf2d
feat: toggle providers and fallback rules on/off
entitybtw Aug 15, 2026
5739cb7
feat(fallback): apply rule changes at runtime without restart
entitybtw Aug 15, 2026
1715dc1
fix(ui): restyle Switch with valid Tailwind classes and mobile tap ta…
entitybtw Aug 15, 2026
b91e349
feat(ui): replace all feature-toggle checkboxes with the new iOS-styl…
entitybtw Aug 15, 2026
3b48aaf
fix(fallback): preserve rule order across toggle/edit/delete
entitybtw Aug 15, 2026
d017db4
fix(ui): align provider card toggle with fallback style
entitybtw Aug 15, 2026
b140cc4
fix(ui): enlarge Switch touch target on mobile
entitybtw Aug 15, 2026
ab9fa43
fix(ui): improve search icon visibility and fix select text clipping
entitybtw Aug 15, 2026
7adbeea
feat(ui): replace all remaining checkboxes with Switch everywhere
entitybtw Aug 15, 2026
adb9e1d
fix(ui): iOS-style Switch + fix search field icon overlap
entitybtw Aug 15, 2026
439ae0b
fix(provider): openrouter model name pass-through; ui: catppuccin Swi…
entitybtw Aug 15, 2026
94d50ae
chore: stop tracking node_modules, pnpm-lock.yaml, and local session …
entitybtw Aug 16, 2026
33ffd10
feat(response-headers): configurable X-Actual-Provider/Model/Requeste…
entitybtw Aug 16, 2026
749b8de
feat(response-headers): per-header toggles and custom headers support
entitybtw Aug 16, 2026
43d150c
fix(response-headers): populate snapshot so dashboard save persists
entitybtw Aug 16, 2026
a26d201
fix(fallback): swap target values on move instead of duplicating
entitybtw Aug 16, 2026
e6b013d
fix(docker): persist dashboard settings overlay across container recr…
entitybtw Aug 16, 2026
af01e07
fix: provider toggle locking and response headers loading
entitybtw Aug 16, 2026
bead411
feat(response-headers): add Mode toggle for success/error/always resp…
entitybtw Aug 16, 2026
976e040
fix(response-headers): add headers to error responses (429, 401, etc.…
entitybtw Aug 16, 2026
eefac36
feat(providers): add bind_ip for per-provider outbound IP
entitybtw Aug 16, 2026
cf28a9f
fix(response-headers): add headers to provider errors (429) via workflow
entitybtw Aug 16, 2026
3ede869
fix(response-headers): populate Mode in dashboard settings snapshot
entitybtw Aug 16, 2026
4485cba
fix(providers): preserve API key when editing provider
entitybtw Aug 16, 2026
a3da65e
fix(providers): return api_key in provider status and load it on edit
entitybtw Aug 16, 2026
61e554b
feat(providers): live-refresh provider inventory after runtime rebuild
entitybtw Aug 16, 2026
6163d84
debug: log provider inventory sync counts
entitybtw Aug 16, 2026
694ab64
fix(providers): include api_key and bind_ip in provider status
entitybtw Aug 16, 2026
499f74c
feat(fallback): call chains by name and expose them in /v1/models
entitybtw Aug 16, 2026
9fee9fe
fix(models): expose fallback chains dynamically so UI-added chains ap…
entitybtw Aug 16, 2026
0030f88
ui: consistent mobile-friendly toggle rows via ToggleField
entitybtw Aug 16, 2026
3bf2746
Merge remote-tracking branch 'upstream/main'
entitybtw Aug 16, 2026
c8eecd6
ui: stop global mobile min-height from stretching Switch pills
entitybtw Aug 17, 2026
b1c24fb
ui: shared SearchInput fixes placeholder/icon overlap in audit logs &…
entitybtw Aug 17, 2026
d48b86a
feat: don't retry 429 on the same provider — let fallback switch imme…
entitybtw Aug 17, 2026
955625c
feat(openrouter): enforce models: list as allowlist so only listed mo…
entitybtw Aug 17, 2026
53fa1c2
ui(switch): fixed compact size on all screens — toggles small on mobi…
entitybtw Aug 17, 2026
5257abf
ui(switch): use inline minHeight to override global 44px stretch on m…
entitybtw Aug 17, 2026
1f1f534
feat(pools): full UI management with live updates and weighted LB
entitybtw Aug 17, 2026
ab5581a
fix(pools): send JSON body via apiFetch json so Content-Type is set
entitybtw Aug 17, 2026
de68b5f
feat(providers): add pool_only flag to hide models outside pools
entitybtw Aug 17, 2026
c486d11
feat(providers): support renaming providers live
entitybtw Aug 17, 2026
2d1ef6e
fix(providers): report pool_only in provider status for UI overrides
entitybtw Aug 17, 2026
b3b9225
chore: restore README and docs-assets to match upstream aurora
entitybtw Aug 17, 2026
b67a47f
Merge upstream/main to restore history link (no upstream changes to t…
entitybtw Aug 17, 2026
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
pnpm-lock.yaml
резюме/
24 changes: 24 additions & 0 deletions configs/config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,30 @@ token_saver:
audit:
enabled: true # env: TOKEN_SAVER_AUDIT_ENABLED

# ========= RESPONSE HEADERS =========
# Additional debug headers added to gateway responses
response_headers:
# Enable adding X-Actual-Provider / X-Actual-Model / X-Requested-Model / X-Fallback-Chain headers
enabled: false # env: RESPONSE_HEADERS_ENABLED
# Add headers when a fallback was used during request execution
include_fallback: true # env: RESPONSE_HEADERS_INCLUDE_FALLBACK
# Add headers when no fallback was used (normal request execution)
include_non_fallback: true # env: RESPONSE_HEADERS_INCLUDE_NON_FALLBACK
# Emit the X-Actual-Provider header (the provider that actually served the response)
actual_provider_header: true # env: RESPONSE_HEADERS_ACTUAL_PROVIDER
# Emit the X-Actual-Model header (the model that actually produced the response)
actual_model_header: true # env: RESPONSE_HEADERS_ACTUAL_MODEL
# Emit the X-Requested-Model header (the originally requested model selector)
requested_model_header: true # env: RESPONSE_HEADERS_REQUESTED_MODEL
# Emit the X-Fallback-Chain header (comma-separated models attempted before a success)
fallback_chain_header: true # env: RESPONSE_HEADERS_FALLBACK_CHAIN
# Custom response headers. Values support placeholders: {actual_provider},
# {actual_model}, {requested_model}, {fallback_chain}, {request_id}
custom_headers:
- name: X-Custom-Header
value: "{actual_model} via {actual_provider}"
enabled: true

# ========= WORKFLOWS =========
# Workflow execution and refresh
workflows:
Expand Down
12 changes: 12 additions & 0 deletions configs/dashboard-overrides.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,15 @@ token_saver:
on_error: allow
emit_headers: false
audit_enabled: false
response_headers:
enabled: false
include_fallback: true
include_non_fallback: true
actual_provider_header: true
actual_model_header: true
requested_model_header: true
fallback_chain_header: true
custom_headers:
- name: X-Custom-Header
value: "{actual_model} via {actual_provider}"
enabled: true
28 changes: 18 additions & 10 deletions configs/fallback.example.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
{
"gpt-4o": [
"azure/gpt-4o",
"gemini/gemini-2.5-pro"
],
"claude-sonnet-4": [
"openai/gpt-5-mini",
"gemini/gemini-2.5-pro"
]
}
[
{
"source": "gpt-4o",
"targets": [
"azure/gpt-4o",
"gemini/gemini-2.5-pro"
],
"enabled": true
},
{
"source": "claude-sonnet-4",
"targets": [
"openai/gpt-5-mini",
"gemini/gemini-2.5-pro"
],
"enabled": true
}
]
148 changes: 109 additions & 39 deletions configuration/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,24 @@ var bodySizeLimitRegex = regexp.MustCompile(`(?i)^(\d+)([KMG])?B?$`)

// Config holds the application configuration.
type Config struct {
Server ServerConfig `yaml:"server"`
Models ModelsConfig `yaml:"models"`
Cache CacheConfig `yaml:"cache"`
Storage StorageConfig `yaml:"storage"`
Logging LogConfig `yaml:"logging"`
Usage UsageConfig `yaml:"usage"`
Metrics MetricsConfig `yaml:"metrics"`
HTTP HTTPConfig `yaml:"http"`
Admin AdminConfig `yaml:"admin"`
Guardrails GuardrailsConfig `yaml:"guardrails"`
Fallback FallbackConfig `yaml:"fallback"`
Combos CombosConfig `yaml:"combos"`
CLITools CLIToolsConfig `yaml:"cli_tools"`
Workflows WorkflowsConfig `yaml:"workflows"`
Resilience ResilienceConfig `yaml:"resilience"`
TokenSaver TokenSaverConfig `yaml:"token_saver"`
Edition EditionConfig `yaml:"edition"`
Server ServerConfig `yaml:"server"`
Models ModelsConfig `yaml:"models"`
Cache CacheConfig `yaml:"cache"`
Storage StorageConfig `yaml:"storage"`
Logging LogConfig `yaml:"logging"`
Usage UsageConfig `yaml:"usage"`
Metrics MetricsConfig `yaml:"metrics"`
HTTP HTTPConfig `yaml:"http"`
Admin AdminConfig `yaml:"admin"`
Guardrails GuardrailsConfig `yaml:"guardrails"`
Fallback FallbackConfig `yaml:"fallback"`
Combos CombosConfig `yaml:"combos"`
CLITools CLIToolsConfig `yaml:"cli_tools"`
Workflows WorkflowsConfig `yaml:"workflows"`
Resilience ResilienceConfig `yaml:"resilience"`
TokenSaver TokenSaverConfig `yaml:"token_saver"`
Edition EditionConfig `yaml:"edition"`
ResponseHeaders ResponseHeadersConfig `yaml:"response_headers"`
}

// LoadResult is returned by Load and bundles the application config with the raw
Expand All @@ -68,6 +69,14 @@ type RawProviderConfig struct {
APIVersion string `yaml:"api_version"`
Models []RawProviderModel `yaml:"models"`
Resilience *RawResilienceConfig `yaml:"resilience"`
// BindIP optionally sets the local outbound IP address used when this
// provider's HTTP client connects to the upstream. Useful when the host
// has multiple public IPs and the upstream rate-limits per source IP.
BindIP string `yaml:"bind_ip"`
// PoolOnly, when true, hides this provider's models from the public model
// list. The provider is then only reachable through a pool that lists it as
// a member, keeping the /v1/models list uncluttered.
PoolOnly bool `yaml:"pool_only"`
}

// RawPoolConfig is the YAML-sourced provider pool definition. Pools group
Expand Down Expand Up @@ -222,8 +231,6 @@ type AdminConfig struct {
// a warning is logged and UI is forced to false.
// Default: true
UIEnabled bool `yaml:"ui_enabled" env:"ADMIN_UI_ENABLED"`


}

// GuardrailsConfig holds configuration for the request guardrails pipeline.
Expand Down Expand Up @@ -380,6 +387,65 @@ type HTTPProxyConfig struct {
CACertPEM string `yaml:"ca_cert_pem"`
}

// ResponseHeadersConfig controls the additional response headers added to
// gateway responses for debugging and monitoring purposes.
type ResponseHeadersConfig struct {
// Enabled controls whether the additional response headers are added.
// Default: false.
Enabled bool `yaml:"enabled" env:"RESPONSE_HEADERS_ENABLED"`

// Mode controls when headers are added.
// Values: "success" (only 2xx), "error" (only 4xx/5xx), "always" (all responses).
// Default: "success".
Mode string `yaml:"mode" env:"RESPONSE_HEADERS_MODE"`

// IncludeFallback controls whether headers are added when a fallback
// was used during request execution.
// Default: true.
IncludeFallback bool `yaml:"include_fallback" env:"RESPONSE_HEADERS_INCLUDE_FALLBACK"`

// IncludeNonFallback controls whether headers are added when no fallback
// was used (normal request execution).
// Default: true.
IncludeNonFallback bool `yaml:"include_non_fallback" env:"RESPONSE_HEADERS_INCLUDE_NON_FALLBACK"`

// ActualProviderHeader controls whether the X-Actual-Provider header
// (the provider that actually served the response) is added.
// Default: true.
ActualProviderHeader bool `yaml:"actual_provider_header" env:"RESPONSE_HEADERS_ACTUAL_PROVIDER"`

// ActualModelHeader controls whether the X-Actual-Model header
// (the model that actually produced the response) is added.
// Default: true.
ActualModelHeader bool `yaml:"actual_model_header" env:"RESPONSE_HEADERS_ACTUAL_MODEL"`

// RequestedModelHeader controls whether the X-Requested-Model header
// (the originally requested model selector) is added.
// Default: true.
RequestedModelHeader bool `yaml:"requested_model_header" env:"RESPONSE_HEADERS_REQUESTED_MODEL"`

// FallbackChainHeader controls whether the X-Fallback-Chain header
// (comma-separated models attempted before a success) is added.
// Default: true.
FallbackChainHeader bool `yaml:"fallback_chain_header" env:"RESPONSE_HEADERS_FALLBACK_CHAIN"`

// CustomHeaders are additional headers added verbatim to responses.
// Values support the same placeholders as the built-in headers.
// Default: none.
CustomHeaders []CustomResponseHeaderConfig `yaml:"custom_headers"`
}

// CustomResponseHeaderConfig defines a user-provided response header.
type CustomResponseHeaderConfig struct {
// Name is the HTTP header name (e.g. "X-Custom-Header").
Name string `yaml:"name"`
// Value is the header value. Supported placeholders: {actual_provider},
// {actual_model}, {requested_model}, {fallback_chain}, {request_id}.
Value string `yaml:"value"`
// Enabled controls whether this header is emitted.
Enabled bool `yaml:"enabled"`
}

// WorkflowsConfig holds runtime refresh behavior for persisted workflows.
type WorkflowsConfig struct {
// RefreshInterval controls how often the in-memory workflow snapshot
Expand Down Expand Up @@ -603,8 +669,6 @@ type MetricsConfig struct {
Endpoint string `yaml:"endpoint" env:"METRICS_ENDPOINT"`
}



// RetryConfig holds resolved retry settings for an LLM client.
// This is the canonical type shared between config and llmclient.
type RetryConfig struct {
Expand Down Expand Up @@ -657,7 +721,7 @@ func buildDefaultConfig() *Config {
BasePath: "/",
SwaggerEnabled: false,
PprofEnabled: false,
DisableRequestLogging: true,
DisableRequestLogging: true,
EnablePassthroughRoutes: true,
EnableAnthropicIngress: false,
AllowPassthroughV1Alias: true,
Expand Down Expand Up @@ -742,6 +806,16 @@ func buildDefaultConfig() *Config {
Admin: AdminConfig{EndpointsEnabled: false, UIEnabled: false},
Guardrails: GuardrailsConfig{},
TokenSaver: defaultTokenSaverConfig(),
ResponseHeaders: ResponseHeadersConfig{
Enabled: false,
Mode: "success",
IncludeFallback: true,
IncludeNonFallback: true,
ActualProviderHeader: true,
ActualModelHeader: true,
RequestedModelHeader: true,
FallbackChainHeader: true,
},
Edition: EditionConfig{
Name: EditionOSS,
},
Expand Down Expand Up @@ -841,12 +915,6 @@ func applyYAML(cfg *Config) (map[string]RawProviderConfig, map[string]RawPoolCon
rawProviders := make(map[string]RawProviderConfig)
rawPools := make(map[string]RawPoolConfig)

if data == nil {
return rawProviders, rawPools, nil
}

expanded := expandString(string(data))

// yamlTarget is a local struct that mirrors Config for YAML unmarshaling,
// using RawProviderConfig for providers so nullable resilience overrides are preserved.
type yamlTarget struct {
Expand All @@ -855,16 +923,20 @@ func applyYAML(cfg *Config) (map[string]RawProviderConfig, map[string]RawPoolCon
RawPools map[string]RawPoolConfig `yaml:"pools"`
}

target := yamlTarget{Config: cfg}
if err := yaml.Unmarshal([]byte(expanded), &target); err != nil {
return nil, nil, fmt.Errorf("failed to parse %s: %w", configPath, err)
}
if data != nil {
expanded := expandString(string(data))

if target.RawProviders != nil {
rawProviders = target.RawProviders
}
if target.RawPools != nil {
rawPools = target.RawPools
target := yamlTarget{Config: cfg}
if err := yaml.Unmarshal([]byte(expanded), &target); err != nil {
return nil, nil, fmt.Errorf("failed to parse %s: %w", configPath, err)
}

if target.RawProviders != nil {
rawProviders = target.RawProviders
}
if target.RawPools != nil {
rawPools = target.RawPools
}
}

for _, overlayPath := range dashboardOverridePaths(customPath) {
Expand Down Expand Up @@ -911,8 +983,6 @@ func dashboardOverridePaths(customPath string) []string {
}
}



func validatePublicHTTPURL(raw, field string) error {
u, err := url.Parse(strings.TrimSpace(raw))
if err != nil || u.Scheme == "" || u.Host == "" {
Expand Down
Loading