You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-**Shared guardrail helpers** (`internal/plugins/guardrailutil/`): common parsing and message extraction helpers used by guardrail plugins to keep config handling consistent
20
+
21
+
### Changed
22
+
23
+
-**Plugin rejection handling** (`plugin/errors.go`, `plugin/manager.go`): introduced typed `RejectionError` for intentional guardrail rejections and extended after-request lifecycle to propagate rejections (needed for output guardrails such as `schema-guard`)
24
+
-**Gateway request mutation propagation** (`gateway.go`): `Route()` now applies before-request plugin request mutations before strategy execution (enables in-place redaction plugins)
25
+
-**HTTP error mapping for guardrail rejections** (`cmd/ferrogw/main.go`): chat-completions routes now return `400 invalid_request_error` for plugin rejection errors instead of generic `500 routing_error`
26
+
-**Plugin registration** (`cmd/ferrogw/main.go`, `cmd/ferrogw-cli/main.go`): wired all new guardrail plugins into server and CLI plugin listing
27
+
-**Config examples** (`config.example.yaml`, `config.example.json`): added sample blocks for all new guardrail plugins
28
+
29
+
## [0.5.0] — 2026-03-03
30
+
31
+
### Added
32
+
33
+
-**Streaming cost tracking** (`internal/streamwrap/wrap.go`): `Meter()` wraps any `<-chan StreamChunk` in a transparent goroutine that accumulates token usage from the final chunk and emits `gateway_requests_total`, `gateway_request_duration_seconds`, `gateway_tokens_input_total`, `gateway_tokens_output_total`, and `gateway_request_cost_usd_total` Prometheus metrics plus `request.completed` event hooks on stream close; `RouteStream()` in `gateway.go` now fully mirrors `Route()` metrics coverage
34
+
-**OpenAI streaming usage** (`providers/openai.go`): `CompleteStream()` now sets `stream_options.include_usage: true` so the final SSE chunk carries token counts; `StreamChunk` gained a `Usage` field populated from the final chunk's usage data (including `reasoning_tokens` and `cached_tokens`)
35
+
-**`providers.ParseStatusCode(err)`** (`providers/provider.go`): regex-based helper extracting the HTTP status code from provider error messages formatted as `"... (NNN): ..."` — used by retry and fallback logic across all 15 providers without requiring per-provider changes
36
+
-**Per-target retry status-code filtering** (`internal/strategies/fallback.go`): `Fallback.WithTargetRetry()` now accepts an `onStatusCodes []int` slice; if non-empty, retries are only attempted when the error's status code is in the list — e.g. retry on 429/503 but fail-fast on 400/401; `shouldRetry()` helper extracts codes via `ParseStatusCode`
37
+
-**`RetryConfig` extensions** (`config.go`): new `on_status_codes` (array of ints) and `initial_backoff_ms` (int, default 100) fields on per-target retry config
38
+
-**Least-latency routing strategy** (`internal/strategies/leastlatency.go`, `internal/latency/tracker.go`): `LeastLatency` strategy selects the compatible provider with the lowest P50 latency from a thread-safe in-process sliding window (default 100 samples per provider); falls back to random selection when a provider has no recorded samples; `Route()` records every successful call's latency into a shared `*latency.Tracker` on the `Gateway` struct
39
+
-**Cost-optimized routing strategy** (`internal/strategies/costoptimized.go`): `CostOptimized` strategy estimates prompt token count (~4 chars/token heuristic on request messages), calls `models.Calculate()` for each compatible provider, and routes to the cheapest option; falls back to the first compatible provider when no catalog pricing is available
40
+
-**`ModeLatency` / `ModeCostOptimized` strategy modes** (`config.go`): two new `StrategyMode` constants (`"least-latency"`, `"cost-optimized"`) wired into `gateway.go`'s `getStrategy()` switch
41
+
-**CLI UX overhaul** (`cmd/ferrogw-cli/`): replaced hand-rolled `switch os.Args[1]` with [Cobra](https://github.com/spf13/cobra); added persistent `--gateway-url`, `--api-key`, and `--format table|json|yaml` flags; ported `validate`, `plugins`, `version` commands to `cobra.RunE`; added full `admin` command group (`admin keys list/get/create/delete/rotate`, `admin config get/history/update/rollback`, `admin logs list/stats`, `admin providers list/health`) in `admin.go`; thin admin HTTP client in `client.go`; table/JSON/YAML output formatter in `output.go`
42
+
43
+
### Changed
44
+
45
+
-**`gateway.go``RouteStream()`**: emits error metrics on provider failure (previously silent); wraps the raw provider channel with `streamwrap.Meter()` for full metrics/event parity with `Route()`
46
+
-**`gateway.go``getStrategy()`**: `ModeFallback` now wires per-target `RetryConfig` (including `OnStatusCodes` and `InitialBackoffMs`) via `fb.WithTargetRetry()`; added `ModeLatency` and `ModeCostOptimized` cases
47
+
-**`gateway.go``Route()`**: records per-provider response latency into `g.latencyTracker` on every successful call
Copy file name to clipboardExpand all lines: ROADMAP.md
+30-9Lines changed: 30 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -128,19 +128,40 @@
128
128
129
129
## v0.5.0 — Advanced Routing & Intelligence
130
130
131
-
**Status**: 📋 Planned
131
+
**Status**: ✅ Released
132
132
**Theme**: Smart routing based on cost, latency, and content.
133
133
134
+
| Feature | Description | Status |
135
+
|---|---|---|
136
+
|**CLI UX overhaul**|`ferrogw-cli` migrated to Cobra: richer admin command groups (`admin keys`, `admin config`, `admin logs`, `admin providers`), `--format table/json/yaml` output flag, shell completions via `ferrogw-cli completion`| ✅ Done |
137
+
|**Streaming cost tracking**|`RouteStream()` now wraps the SSE channel in a metering goroutine; emits Prometheus metrics (duration, tokens, cost) and event hooks on stream close, matching `Route()` behaviour | ✅ Done |
138
+
|**Retry policies**|`RetryConfig` extended with `on_status_codes` (only retry listed HTTP status codes) and `initial_backoff_ms` (configurable exponential backoff base); applied per-target in the fallback strategy | ✅ Done |
139
+
|**Least-latency routing**| New `least-latency` strategy mode; in-process rolling-window p50 tracker (`internal/latency`) records observed latency per provider; routes to fastest compatible provider, falls back to random when no samples exist | ✅ Done |
140
+
|**Cost-optimized routing**| New `cost-optimized` strategy mode; estimates prompt cost via the model catalog for each compatible provider and routes to the cheapest; falls back to first compatible provider when pricing is unavailable | ✅ Done |
141
+
142
+
---
143
+
144
+
## v0.5.5 — Intelligent Request Handling
145
+
146
+
**Status**: 📋 Planned
147
+
**Theme**: Route based on what the request says, not just what model it targets.
148
+
149
+
| Feature | Description |
150
+
|---|---|
151
+
|**Content-based routing**| Extend conditional strategy with `prompt_contains` and `prompt_regex` match keys; `X-Route-Tag` header overrides all rules via `header_routing` config map |
152
+
|**A/B testing**| New `ab-test` strategy mode; traffic split by percentage across named variants; `variant` label on all Prometheus metrics; `GET /admin/experiments` endpoint for live stats |
153
+
154
+
---
155
+
156
+
## v0.6.0 — Developer Experience
157
+
158
+
**Status**: ✅ Completed
159
+
**Release Date**: 2026-03-06
160
+
**Theme**: Server-side prompt management to eliminate client-side template sprawl.
161
+
134
162
| Feature | Description |
135
163
|---|---|
136
-
|**CLI UX overhaul**| Improve `ferrogw-cli` with richer admin command groups, clearer help output, structured output modes (`table/json/yaml`), and shell completions |
137
-
|**Streaming cost tracking**| Consume final `usage` chunk from SSE stream in `RouteStream()` and emit cost metrics/events on stream close, matching `Route()` behavior |
138
-
|**Least-latency routing**| Route to the provider with lowest p50 latency |
139
-
|**Cost-optimized routing**| Route to cheapest provider that meets quality threshold |
140
-
|**Content-based routing**| Route based on prompt content (code → Codex, chat → GPT) |
141
-
|**A/B testing**| Split traffic between models for comparison |
142
-
|**Prompt templates**| Server-side prompt template management and versioning |
143
-
|**Retry policies**| Configurable retry with status code filtering per provider |
164
+
|**Prompt templates**| First-class `PromptTemplate` entity with CRUD admin API (`/admin/templates`); `template_id` + `variables` fields in request body; Go `text/template` rendering injected into `messages` before routing; memory / SQLite / PostgreSQL backends |
0 commit comments