Skip to content
Draft
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
12 changes: 6 additions & 6 deletions .claude/skills/changelog-writer/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ bifrost/
│ ├── maxim/version
│ ├── mocker/version
│ ├── otel/version
│ ├── semanticcache/version
│ ├── localcache/version
│ └── telemetry/version
├── transports/
│ ├── version # Plain text: "1.5.0"
Expand All @@ -353,9 +353,9 @@ This is the canonical order for plugins:
1. governance
2. jsonparser
3. litellmcompat
4. logging
5. maxim
6. mocker
7. otel
8. semanticcache
4. localcache
5. logging
6. maxim
7. mocker
8. otel
9. telemetry
2 changes: 1 addition & 1 deletion .claude/skills/docs-writer/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Parse the feature name and map it to codebase areas. Common feature-to-directory
| mcp | `ui/app/workspace/mcp-registry/` | `handlers/mcp.go` | `mcp` | `docs/mcp/` |
| plugins | `ui/app/workspace/plugins/` | `handlers/plugins.go` | `plugins` | `docs/features/plugins/` |
| logs / observability | `ui/app/workspace/logs/` | `handlers/logging.go` | `client.enable_logging` | `docs/features/observability/` |
| semantic-caching | `ui/app/workspace/config/caching/` | `handlers/cache.go` | `plugins.semantic_cache` + `vector_store` | `docs/features/semantic-caching.mdx` |
| local-caching | `ui/app/workspace/config/caching/` | `handlers/cache.go` + `handlers/local_cache.go` | `client.enable_local_cache` + `local_cache` + `vector_store` | `docs/features/local-caching.mdx` |
| guardrails | `ui/app/workspace/guardrails/` | Enterprise | `guardrails_config` | `docs/enterprise/guardrails.mdx` |
| clustering | `ui/app/workspace/cluster/` | Enterprise | `cluster_config` | `docs/enterprise/clustering.mdx` |
| load-balancing | `ui/app/workspace/adaptive-routing/` | Enterprise | `load_balancer_config` | `docs/enterprise/adaptive-load-balancing.mdx` |
Expand Down
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ updates:
open-pull-requests-limit: 0

- package-ecosystem: gomod
directory: /plugins/semanticcache
directory: /plugins/localcache
schedule:
interval: daily
open-pull-requests-limit: 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"$schema": "https://www.getbifrost.ai/schema",
"client": {
"enable_local_cache": true
},
"vector_store": {
"enabled": true,
"type": "weaviate",
Expand All @@ -8,14 +11,8 @@
"host": "localhost:9000"
}
},
"plugins": [
{
"enabled": true,
"name": "semantic_cache",
"config": {
"dimension": 1,
"vector_store_namespace": "test"
}
}
]
}
"local_cache": {
"dimension": 1,
"vector_store_namespace": "test"
}
}
2 changes: 1 addition & 1 deletion .github/workflows/scripts/setup-go-workspace.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ go work use ./plugins/maxim
go work use ./plugins/mocker
go work use ./plugins/otel
go work use ./plugins/prompts
go work use ./plugins/semanticcache
go work use ./plugins/localcache
go work use ./plugins/telemetry
go work use ./transports
go work use ./cli
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scripts/test-bifrost-http.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ CONFIGS_TO_TEST=(
"withconfigstorelogsstoresqlite"
"withdynamicplugin"
"withobservability"
"withsemanticcache"
"withlocalcache"
"withpostgresmcpclientsinconfig"
)

Expand Down
114 changes: 59 additions & 55 deletions .github/workflows/scripts/validate-helm-config-fields.sh
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,8 @@ assert_field_value 'auth_config.is_enabled' '.auth_config.is_enabled' 'true'
assert_field_value 'auth_config.disable_auth_on_inference' '.auth_config.disable_auth_on_inference' 'false'

###############################################################################
# 6. Plugins (telemetry, logging, governance, maxim, semantic_cache, otel, datadog, custom)
# 6. Plugins (telemetry, logging, governance, maxim, otel, datadog, custom) +
# top-level local_cache block (no longer a plugins[] entry as of v1.5.0)
###############################################################################
echo ""
echo -e "${CYAN}🔌 6/10 - Plugins Configuration${NC}"
Expand All @@ -596,6 +597,9 @@ cat > "$TMPDIR/values-plugins.yaml" << 'VALS'
image:
tag: v1.0.0
bifrost:
client:
# Loads the local cache plugin (direct + semantic) at boot.
enableLocalCache: true
plugins:
telemetry:
enabled: true
Expand Down Expand Up @@ -627,22 +631,6 @@ bifrost:
secretRef:
name: ""
key: "api-key"
semanticCache:
enabled: true
config:
provider: "openai"
keys:
- "sk-embed-key"
embedding_model: "text-embedding-3-small"
dimension: 1536
threshold: 0.85
ttl: "10m"
conversation_history_threshold: 5
cache_by_model: true
cache_by_provider: false
exclude_system_prompt: true
cleanup_on_shutdown: true
vector_store_namespace: "bifrost-cache"
otel:
enabled: true
config:
Expand Down Expand Up @@ -674,6 +662,22 @@ bifrost:
version: 2
config:
key1: "val1"
# Local cache plugin configuration (top-level, sibling of bifrost / vectorStore)
localCache:
keys:
- "sk-embed-key"
config:
provider: "openai"
embedding_model: "text-embedding-3-small"
dimension: 1536
threshold: 0.85
ttl: "10m"
conversation_history_threshold: 5
cache_by_model: true
cache_by_provider: false
exclude_system_prompt: true
cleanup_on_shutdown: true
vector_store_namespace: "bifrost-cache"
vectorStore:
enabled: true
type: weaviate
Expand Down Expand Up @@ -702,48 +706,48 @@ assert_field_value 'plugins: maxim name' '.plugins.[3].name' '"maxim"'
assert_field_value 'plugins: maxim api_key' '.plugins.[3].config.api_key' '"maxim-key-123"'
assert_field_value 'plugins: maxim log_repo_id' '.plugins.[3].config.log_repo_id' '"repo-456"'

# Semantic cache plugin
assert_field_value 'plugins: semantic_cache name' '.plugins.[4].name' '"semantic_cache"'
assert_field_value 'plugins: semantic_cache provider' '.plugins.[4].config.provider' '"openai"'
assert_field 'plugins: semantic_cache keys' '.plugins.[4].config.keys'
assert_field_value 'plugins: semantic_cache embedding_model' '.plugins.[4].config.embedding_model' '"text-embedding-3-small"'
assert_field_value 'plugins: semantic_cache dimension' '.plugins.[4].config.dimension' '1536'
assert_field_value 'plugins: semantic_cache threshold' '.plugins.[4].config.threshold' '0.85'
assert_field_value 'plugins: semantic_cache ttl' '.plugins.[4].config.ttl' '"10m"'
assert_field_value 'plugins: semantic_cache conversation_history_threshold' '.plugins.[4].config.conversation_history_threshold' '5'
assert_field_value 'plugins: semantic_cache cache_by_model' '.plugins.[4].config.cache_by_model' 'true'
assert_field_value 'plugins: semantic_cache cache_by_provider' '.plugins.[4].config.cache_by_provider' 'false'
assert_field_value 'plugins: semantic_cache exclude_system_prompt' '.plugins.[4].config.exclude_system_prompt' 'true'
assert_field_value 'plugins: semantic_cache cleanup_on_shutdown' '.plugins.[4].config.cleanup_on_shutdown' 'true'
assert_field_value 'plugins: semantic_cache vector_store_namespace' '.plugins.[4].config.vector_store_namespace' '"bifrost-cache"'

# OTEL plugin
assert_field_value 'plugins: otel name' '.plugins.[5].name' '"otel"'
assert_field_value 'plugins: otel service_name' '.plugins.[5].config.service_name' '"bifrost-test"'
assert_field_value 'plugins: otel collector_url' '.plugins.[5].config.collector_url' '"otel-collector:4317"'
assert_field_value 'plugins: otel trace_type' '.plugins.[5].config.trace_type' '"genai_extension"'
assert_field_value 'plugins: otel protocol' '.plugins.[5].config.protocol' '"grpc"'
assert_field_value 'plugins: otel metrics_enabled' '.plugins.[5].config.metrics_enabled' 'true'
assert_field_value 'plugins: otel metrics_endpoint' '.plugins.[5].config.metrics_endpoint' '"otel-collector:4317"'
assert_field_value 'plugins: otel metrics_push_interval' '.plugins.[5].config.metrics_push_interval' '30'
assert_field 'plugins: otel headers' '.plugins.[5].config.headers'
assert_field_value 'plugins: otel tls_ca_cert' '.plugins.[5].config.tls_ca_cert' '"/certs/ca.pem"'
assert_field_value 'plugins: otel insecure' '.plugins.[5].config.insecure' 'true'
# Local cache (top-level block, not a plugins[] entry as of v1.5.0)
assert_field_value 'client.enable_local_cache' '.client.enable_local_cache' 'true'
assert_field_value 'local_cache provider' '.local_cache.provider' '"openai"'
assert_field 'local_cache keys' '.local_cache.keys'
assert_field_value 'local_cache embedding_model' '.local_cache.embedding_model' '"text-embedding-3-small"'
assert_field_value 'local_cache dimension' '.local_cache.dimension' '1536'
assert_field_value 'local_cache threshold' '.local_cache.threshold' '0.85'
assert_field_value 'local_cache ttl' '.local_cache.ttl' '"10m"'
assert_field_value 'local_cache conversation_history_threshold' '.local_cache.conversation_history_threshold' '5'
assert_field_value 'local_cache cache_by_model' '.local_cache.cache_by_model' 'true'
assert_field_value 'local_cache cache_by_provider' '.local_cache.cache_by_provider' 'false'
assert_field_value 'local_cache exclude_system_prompt' '.local_cache.exclude_system_prompt' 'true'
assert_field_value 'local_cache cleanup_on_shutdown' '.local_cache.cleanup_on_shutdown' 'true'
assert_field_value 'local_cache vector_store_namespace' '.local_cache.vector_store_namespace' '"bifrost-cache"'

# OTEL plugin (was index [5] when local_cache lived in plugins[]; now [4])
assert_field_value 'plugins: otel name' '.plugins.[4].name' '"otel"'
assert_field_value 'plugins: otel service_name' '.plugins.[4].config.service_name' '"bifrost-test"'
assert_field_value 'plugins: otel collector_url' '.plugins.[4].config.collector_url' '"otel-collector:4317"'
assert_field_value 'plugins: otel trace_type' '.plugins.[4].config.trace_type' '"genai_extension"'
assert_field_value 'plugins: otel protocol' '.plugins.[4].config.protocol' '"grpc"'
assert_field_value 'plugins: otel metrics_enabled' '.plugins.[4].config.metrics_enabled' 'true'
assert_field_value 'plugins: otel metrics_endpoint' '.plugins.[4].config.metrics_endpoint' '"otel-collector:4317"'
assert_field_value 'plugins: otel metrics_push_interval' '.plugins.[4].config.metrics_push_interval' '30'
assert_field 'plugins: otel headers' '.plugins.[4].config.headers'
assert_field_value 'plugins: otel tls_ca_cert' '.plugins.[4].config.tls_ca_cert' '"/certs/ca.pem"'
assert_field_value 'plugins: otel insecure' '.plugins.[4].config.insecure' 'true'

# Datadog plugin
assert_field_value 'plugins: datadog name' '.plugins.[6].name' '"datadog"'
assert_field_value 'plugins: datadog service_name' '.plugins.[6].config.service_name' '"bifrost-dd"'
assert_field_value 'plugins: datadog agent_addr' '.plugins.[6].config.agent_addr' '"dd-agent:8126"'
assert_field_value 'plugins: datadog env' '.plugins.[6].config.env' '"staging"'
assert_field_value 'plugins: datadog version' '.plugins.[6].config.version' '"1.0.0"'
assert_field 'plugins: datadog custom_tags' '.plugins.[6].config.custom_tags'
assert_field_value 'plugins: datadog enable_traces' '.plugins.[6].config.enable_traces' 'true'
assert_field_value 'plugins: datadog name' '.plugins.[5].name' '"datadog"'
assert_field_value 'plugins: datadog service_name' '.plugins.[5].config.service_name' '"bifrost-dd"'
assert_field_value 'plugins: datadog agent_addr' '.plugins.[5].config.agent_addr' '"dd-agent:8126"'
assert_field_value 'plugins: datadog env' '.plugins.[5].config.env' '"staging"'
assert_field_value 'plugins: datadog version' '.plugins.[5].config.version' '"1.0.0"'
assert_field 'plugins: datadog custom_tags' '.plugins.[5].config.custom_tags'
assert_field_value 'plugins: datadog enable_traces' '.plugins.[5].config.enable_traces' 'true'

# Custom plugin
assert_field_value 'plugins: custom name' '.plugins.[7].name' '"my-plugin"'
assert_field_value 'plugins: custom path' '.plugins.[7].path' '"/plugins/my-plugin.so"'
assert_field_value 'plugins: custom version' '.plugins.[7].version' '2'
assert_field 'plugins: custom config' '.plugins.[7].config'
assert_field_value 'plugins: custom name' '.plugins.[6].name' '"my-plugin"'
assert_field_value 'plugins: custom path' '.plugins.[6].path' '"/plugins/my-plugin.so"'
assert_field_value 'plugins: custom version' '.plugins.[6].version' '2'
assert_field 'plugins: custom config' '.plugins.[6].config'

###############################################################################
# 7. MCP Configuration
Expand Down
22 changes: 12 additions & 10 deletions .github/workflows/scripts/validate-helm-schema.sh
Original file line number Diff line number Diff line change
Expand Up @@ -470,18 +470,20 @@ fi
echo ""
echo "🔍 Checking required fields in plugin configs..."

# Check semantic cache plugin required fields (dimension)
# Config uses an allOf pattern on plugins array items; Helm uses conditional on semanticCache.enabled
CONFIG_SEMCACHE_REQUIRED=$(jq -r '.properties.plugins.items.allOf[] | select(.if.properties.name.const == "semantic_cache") | .then.properties.config.required // [] | sort | join(",")' "$CONFIG_SCHEMA" 2>/dev/null || echo "")
HELM_SEMCACHE_REQUIRED=$(jq -r '.properties.bifrost.properties.plugins.properties.semanticCache.then.properties.config.required // [] | sort | join(",")' "$HELM_SCHEMA" 2>/dev/null || echo "")
# Check local cache required fields (dimension). The local cache moved
# from a config_plugins entry to a top-level block in v1.5.0, so both
# schemas now expose it as `local_cache` (config.schema.json) /
# `localCache` (Helm values.schema.json) at the root, not under plugins[].
CONFIG_LOCALCACHE_REQUIRED=$(jq -r '.properties.local_cache.required // [] | sort | join(",")' "$CONFIG_SCHEMA" 2>/dev/null || echo "")
HELM_LOCALCACHE_REQUIRED=$(jq -r '.properties.localCache.properties.config.required // [] | sort | join(",")' "$HELM_SCHEMA" 2>/dev/null || echo "")

if [ "$CONFIG_SEMCACHE_REQUIRED" != "$HELM_SEMCACHE_REQUIRED" ]; then
echo "❌ Semantic cache plugin config required fields mismatch:"
echo " Config: [$CONFIG_SEMCACHE_REQUIRED]"
echo " Helm: [$HELM_SEMCACHE_REQUIRED]"
if [ "$CONFIG_LOCALCACHE_REQUIRED" != "$HELM_LOCALCACHE_REQUIRED" ]; then
echo "❌ Local cache config required fields mismatch:"
echo " Config: [$CONFIG_LOCALCACHE_REQUIRED]"
echo " Helm: [$HELM_LOCALCACHE_REQUIRED]"
ERRORS=$((ERRORS + 1))
else
echo "✅ Semantic cache plugin config required fields match: [$CONFIG_SEMCACHE_REQUIRED]"
echo "✅ Local cache config required fields match: [$CONFIG_LOCALCACHE_REQUIRED]"
fi

# Check OTEL plugin required fields (collector_url, trace_type, protocol)
Expand Down Expand Up @@ -643,7 +645,7 @@ check_property_exists "cluster.region" ".properties.bifrost.properties.cluster.p
echo ""
echo " Checking miscellaneous properties (Gap 8)..."
check_property_exists "telemetry.custom_labels" ".properties.bifrost.properties.plugins.properties.telemetry.properties.config.properties.custom_labels" "$HELM_SCHEMA"
check_property_exists "semanticCache.default_cache_key" ".properties.bifrost.properties.plugins.properties.semanticCache.properties.config.properties.default_cache_key" "$HELM_SCHEMA"
check_property_exists "localCache.config.default_cache_key" ".properties.localCache.properties.config.properties.default_cache_key" "$HELM_SCHEMA"

# Also verify these exist in config.schema.json
echo ""
Expand Down
52 changes: 29 additions & 23 deletions .github/workflows/scripts/validate-helm-templates.sh
Original file line number Diff line number Diff line change
Expand Up @@ -178,29 +178,29 @@ echo ""
echo -e "${CYAN}⚙️ 3/6 - Testing Special Configurations (7 tests)...${NC}"
echo "-----------------------------------------------------"

# semantic cache: direct mode (dimension: 1, no provider/keys)
test_template "semanticCache: direct mode (dimension: 1)" \
--set bifrost.plugins.semanticCache.enabled=true \
--set bifrost.plugins.semanticCache.config.dimension=1 \
--set bifrost.plugins.semanticCache.config.ttl=30m \
# local cache: direct mode (dimension: 1, no provider/keys)
test_template "localCache: direct mode (dimension: 1)" \
--set bifrost.client.enableLocalCache=true \
--set localCache.config.dimension=1 \
--set localCache.config.ttl=30m \
--set vectorStore.enabled=true \
--set vectorStore.type=redis \
--set vectorStore.redis.enabled=true

# semantic cache: semantic mode (dimension > 1, requires provider/keys)
test_template "semanticCache: semantic mode (dimension: 1536)" \
--set bifrost.plugins.semanticCache.enabled=true \
--set bifrost.plugins.semanticCache.config.dimension=1536 \
--set bifrost.plugins.semanticCache.config.provider=openai \
--set 'bifrost.plugins.semanticCache.config.keys[0]=sk-test' \
# local cache: semantic mode (dimension > 1, requires provider/keys)
test_template "localCache: semantic mode (dimension: 1536)" \
--set bifrost.client.enableLocalCache=true \
--set localCache.config.dimension=1536 \
--set localCache.config.provider=openai \
--set 'localCache.keys[0]=sk-test' \
--set vectorStore.enabled=true \
--set vectorStore.type=redis \
--set vectorStore.redis.enabled=true

# semantic cache: direct mode with redis + postgres
test_template "semanticCache: direct mode + postgres" \
--set bifrost.plugins.semanticCache.enabled=true \
--set bifrost.plugins.semanticCache.config.dimension=1 \
# local cache: direct mode with redis + postgres
test_template "localCache: direct mode + postgres" \
--set bifrost.client.enableLocalCache=true \
--set localCache.config.dimension=1 \
--set storage.mode=postgres \
--set postgresql.enabled=true \
--set postgresql.auth.password=testpass \
Expand Down Expand Up @@ -335,20 +335,26 @@ echo ""
echo -e "${CYAN}🔌 5/6 - Validating Plugin Names Match Go Registry...${NC}"
echo "------------------------------------------------------"

# Verify semantic cache plugin renders with correct name ("semantic_cache", not "semantic_cache")
# Go registry: plugins/semantic_cache/main.go defines PluginName = "semantic_cache"
test_name="semanticCache plugin name matches Go registry (semantic_cache)"
# Verify the local cache renders as a top-level "local_cache" block plus
# "enable_local_cache: true" on the client (the v1.5.0 shape — no longer a
# plugins[] entry). Go side: plugins/localcache/main.go defines
# PluginName = "local_cache".
test_name="localCache renders as top-level block + client.enable_local_cache toggle"
if helm template bifrost ./helm-charts/bifrost \
--set image.tag=v1.0.0 \
--set bifrost.plugins.semanticCache.enabled=true \
--set bifrost.plugins.semanticCache.config.dimension=1536 \
--set bifrost.plugins.semanticCache.config.provider=openai \
--set 'bifrost.plugins.semanticCache.config.keys[0]=sk-test' \
--set bifrost.client.enableLocalCache=true \
--set localCache.config.dimension=1536 \
--set localCache.config.provider=openai \
--set 'localCache.keys[0]=sk-test' \
--set vectorStore.enabled=true \
--set vectorStore.type=redis \
--set vectorStore.redis.enabled=true \
> /tmp/helm-template-output.yaml 2>&1; then
if grep -Eq '"name"[[:space:]]*:[[:space:]]*"semantic_cache"' /tmp/helm-template-output.yaml; then
# Both signals must be present: the top-level local_cache block and the
# enable_local_cache flag on the client. Without either, the plugin
# won't load at boot.
if grep -Eq '"local_cache"[[:space:]]*:' /tmp/helm-template-output.yaml \
&& grep -Eq '"enable_local_cache"[[:space:]]*:[[:space:]]*true' /tmp/helm-template-output.yaml; then
report_result "$test_name" 0
else
report_result "$test_name" 1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scripts/validate-schema-sync.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ if [ ! -f "$REPO_ROOT/go.work" ]; then
for mod in ./core ./framework \
./plugins/compat ./plugins/governance ./plugins/jsonparser \
./plugins/logging ./plugins/maxim ./plugins/mocker \
./plugins/otel ./plugins/prompts ./plugins/semanticcache \
./plugins/otel ./plugins/prompts ./plugins/localcache \
./plugins/telemetry \
./transports ./cli; do
if [ -f "$REPO_ROOT/$mod/go.mod" ]; then
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ bifrost/
│ ├── governance/ # Budget, rate limiting, virtual keys, routing, RBAC
│ ├── telemetry/ # Prometheus metrics, push gateway
│ ├── logging/ # Request/response audit logging
│ ├── semanticcache/ # Semantic response caching via vector store
│ ├── localcache/ # Direct & Semantic response caching via vector store
│ ├── otel/ # OpenTelemetry tracing
│ ├── mocker/ # Mock responses for testing
│ ├── jsonparser/ # JSON extraction utilities
Expand Down
Loading
Loading