docs(ai_client): document Result API + deprecation
This commit is contained in:
+88
-2
@@ -174,7 +174,13 @@ ai_client.clear_comms_log() # Clear
|
||||
ai_client.get_token_stats(md_content) # Estimate token usage
|
||||
```
|
||||
|
||||
### Provider Error Taxonomy
|
||||
### Provider Error Taxonomy — Legacy (Pre-Refactor)
|
||||
|
||||
> **As of 2026-06-11:** This section describes the pre-refactor exception-based
|
||||
> pattern. The `ProviderError` class is **removed** in the
|
||||
> `data_oriented_error_handling_20260606` track. See the new
|
||||
> [Data-Oriented Error Handling (Fleury Pattern)](#data-oriented-error-handling-fleury-pattern)
|
||||
> section below for the current convention.
|
||||
|
||||
```python
|
||||
class ProviderError(Exception):
|
||||
@@ -186,7 +192,12 @@ class ProviderError(Exception):
|
||||
"""Returns a user-friendly error message."""
|
||||
```
|
||||
|
||||
`ProviderError` is raised by provider-specific `_send_*` functions on failure. The caller (typically `app_controller.py`) catches it and surfaces the error to the user via `app.ai_status`.
|
||||
`ProviderError` was raised by provider-specific `_send_*` functions on failure.
|
||||
The caller (typically `app_controller.py`) caught it and surfaced the error to
|
||||
the user via `app.ai_status`. Post-refactor, the same flow uses `ErrorInfo`
|
||||
dataclasses inside `Result[str]` returns — see the new section below.
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
@@ -426,6 +437,81 @@ def test_send_routes_to_provider(monkeypatch):
|
||||
|
||||
Gated by env var (e.g., `RUN_REAL_AI_TESTS=1`). Hits the real API. Not in default CI.
|
||||
|
||||
## Data-Oriented Error Handling (Fleury Pattern)
|
||||
|
||||
The provider layer follows the "errors are just cases" framework
|
||||
(Ryan Fleury, [The Easiest Way To Handle
|
||||
Errors](https://www.dgtlgrove.com/p/the-easiest-way-to-handle-errors)). The
|
||||
canonical reference is
|
||||
[`conductor/code_styleguides/error_handling.md`](../conductor/code_styleguides/error_handling.md).
|
||||
|
||||
### Result-Based Returns
|
||||
|
||||
All `_send_<vendor>_result()` functions (8 vendors: Gemini, Anthropic,
|
||||
DeepSeek, MiniMax, Gemini CLI, Qwen, Llama, Grok — plus the
|
||||
`_send_llama_native` Ollama adapter) return `Result[str, ErrorInfo]`. SDK
|
||||
exceptions are caught at the boundary (`src/openai_compatible.py`,
|
||||
`src/qwen_adapter.py`) and converted to `ErrorInfo` dataclasses. The
|
||||
`_classify_<vendor>_error()` functions return `ErrorInfo` (not raise
|
||||
`ProviderError`, which has been removed).
|
||||
|
||||
The 12 canonical `ErrorKind` values: `NETWORK`, `AUTH`, `QUOTA`,
|
||||
`RATE_LIMIT`, `BALANCE`, `PERMISSION`, `NOT_FOUND`, `INVALID_INPUT`,
|
||||
`NOT_READY`, `UNKNOWN`, `CONFIG`, `INTERNAL`. Each has exactly one
|
||||
meaning — do not overload `UNKNOWN` when a new failure mode surfaces
|
||||
(Lottes's anti-pattern). `ErrorInfo.source` is one of
|
||||
`"ai_client.<vendor>"` (e.g., `"ai_client.gemini"`,
|
||||
`"ai_client.anthropic"`) for diagnostic routing.
|
||||
|
||||
### Public API
|
||||
|
||||
- **`ai_client.send_result(...)`** — the new public API. Returns
|
||||
`Result[str, ErrorInfo]`. Mirrors the `send()` signature (13+
|
||||
parameters including 8 callbacks). Internally calls
|
||||
`_send_<vendor>_result()` for the active provider.
|
||||
- **`ai_client.send(...)`** — **deprecated.** Emits `DeprecationWarning`
|
||||
at runtime (via `typing_extensions.deprecated`; cached per call site to
|
||||
avoid log spam). Returns `str` (the response text) for backward compat.
|
||||
Errors are logged to the comms log via the deprecated path's comms entry
|
||||
but not returned. Will be removed in the `public_api_migration_20260606`
|
||||
follow-up track.
|
||||
|
||||
### Example
|
||||
|
||||
```python
|
||||
from src import ai_client
|
||||
from src.result_types import ErrorKind
|
||||
|
||||
r = ai_client.send_result("system prompt", "user message")
|
||||
if not r.ok:
|
||||
for err in r.errors:
|
||||
log.error(err.ui_message())
|
||||
# err.kind is one of ErrorKind.*; err.source is "ai_client.<vendor>"
|
||||
# use r.data regardless (it's the zero-initialized "" on failure)
|
||||
print(r.data)
|
||||
```
|
||||
|
||||
### Migration Notes for Existing Callers
|
||||
|
||||
- The `app_controller._api_generate` path and the MMA worker dispatch
|
||||
(`multi_agent_conductor.py:591`) call `ai_client.send()`. They will
|
||||
continue to work during the deprecation window; migration to
|
||||
`send_result()` is the work of the `public_api_migration_20260606`
|
||||
follow-up track.
|
||||
- Tests that mock `ai_client._send_<vendor>` should be updated to mock
|
||||
`_send_<vendor>_result()` (or `send_result()` at the public API level).
|
||||
- `tests/conftest.py` adds a `filterwarnings` entry to silence the
|
||||
`DeprecationWarning` from `send()` during the transition; new tests
|
||||
for the new API should assert the warning is **not** emitted by
|
||||
`send_result()`.
|
||||
|
||||
### See Also (in-doc)
|
||||
|
||||
- [`conductor/code_styleguides/error_handling.md`](../conductor/code_styleguides/error_handling.md) — canonical styleguide (5 patterns, data model, decision tree, anti-patterns)
|
||||
- [`conductor/tracks/data_oriented_error_handling_20260606/spec.md`](../conductor/tracks/data_oriented_error_handling_20260606/spec.md) — the spec that introduced this pattern
|
||||
- [`docs/guide_mcp_client.md`](guide_mcp_client.md#data-oriented-error-handling-fleury-pattern) — same pattern in the MCP tool layer
|
||||
- [`docs/guide_rag.md`](guide_rag.md#data-oriented-error-handling-fleury-pattern) — same pattern in the RAG engine
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
Reference in New Issue
Block a user