release api/v1.2.0
Webber through the boilerroom wrapper: flavor-adaptive tool_choice, session identity at rank 20, and the sanitized-client wiring fix that makes the choke point real. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [1.2.0] - 2026-09-13
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Backend adaptation at the provider choke point (workspace T-137):
|
||||||
|
the local backend's flavor is probed once — the boilerroom wrapper
|
||||||
|
names itself on `/health`, a bare llama-server serves `/props`,
|
||||||
|
Ollama answers neither — and every completion adapts. The agents'
|
||||||
|
`tool_choice: "required"` survives only on Ollama, where it is a
|
||||||
|
useful advisory nudge; llama-server enforces it per request, which
|
||||||
|
through the wrapper is an unbreakable tool loop. Through the wrapper
|
||||||
|
every completion carries webber's session identity —
|
||||||
|
`session: webber`, `eviction_order: 20` per the decided ranking
|
||||||
|
(tatlock phases 40, experts 35, librarian 30; lower parks sooner),
|
||||||
|
configurable via `BACKEND_SESSION_NAME`/`BACKEND_SESSION_RANK` —
|
||||||
|
and the wrapper's `balancing`/`compaction_due` body signals are
|
||||||
|
logged. A transport failure during the probe answers "ollama"
|
||||||
|
without caching, so a backend that was down at first call is
|
||||||
|
re-probed rather than misclassified forever.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- The sanitized OpenAI client was never used: the provider assigned
|
||||||
|
`self._openai_client`, an attribute nobody reads —
|
||||||
|
`OllamaProvider.client` serves `self._client`. Every completion
|
||||||
|
bypassed the null-content sanitizer since the class was introduced;
|
||||||
|
exposed 2026-09-13 when the wrapper 503'd a session-less request
|
||||||
|
that the choke point should have named. The sanitized client now
|
||||||
|
goes through the constructor's official `openai_client` parameter,
|
||||||
|
and a wiring test pins `provider.client` to the sanitized type.
|
||||||
|
|
||||||
## [1.1.0] - 2026-08-11
|
## [1.1.0] - 2026-08-11
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "webber-api"
|
name = "webber-api"
|
||||||
version = "1.1.0"
|
version = "1.2.0"
|
||||||
description = "Webber API - Multi-Agent AI Development Server"
|
description = "Webber API - Multi-Agent AI Development Server"
|
||||||
authors = [
|
authors = [
|
||||||
{name = "jpmschweitzer"}
|
{name = "jpmschweitzer"}
|
||||||
|
|||||||
@@ -82,7 +82,11 @@ def test_body_signals_are_logged(monkeypatch):
|
|||||||
monkeypatch.setattr(provider, "logger", StubLogger())
|
monkeypatch.setattr(provider, "logger", StubLogger())
|
||||||
|
|
||||||
class Busy:
|
class Busy:
|
||||||
model_extra = {"balancing": [{"parked": "librarian"}], "compaction_due": True}
|
def __init__(self):
|
||||||
|
self.model_extra = {
|
||||||
|
"balancing": [{"parked": "librarian"}],
|
||||||
|
"compaction_due": True,
|
||||||
|
}
|
||||||
|
|
||||||
provider._log_wrapper_signals(Busy())
|
provider._log_wrapper_signals(Busy())
|
||||||
assert any(kind == "info" and "parked" in msg for kind, msg in calls)
|
assert any(kind == "info" and "parked" in msg for kind, msg in calls)
|
||||||
@@ -91,7 +95,8 @@ def test_body_signals_are_logged(monkeypatch):
|
|||||||
calls.clear()
|
calls.clear()
|
||||||
|
|
||||||
class Quiet:
|
class Quiet:
|
||||||
model_extra = {"balancing": [], "compaction_due": False}
|
def __init__(self):
|
||||||
|
self.model_extra = {"balancing": [], "compaction_due": False}
|
||||||
|
|
||||||
provider._log_wrapper_signals(Quiet())
|
provider._log_wrapper_signals(Quiet())
|
||||||
assert calls == []
|
assert calls == []
|
||||||
|
|||||||
Reference in New Issue
Block a user