|
4 | 4 |
|
5 | 5 | VT Code applies the **Context-Generic Programming** pattern from the |
6 | 6 | [RustLab 2025 talk](https://contextgeneric.dev/blog/rustlab-2025-coherence/) to |
7 | | -its tool runtime system. The pattern solves a concrete architectural problem: |
8 | | -the same tool implementation needs to behave differently (approval policy, |
9 | | -sandbox enforcement, logging, caching, retry) depending on the execution |
10 | | -context (interactive session, CI pipeline, benchmarks) — without adapter |
11 | | -explosion. |
| 7 | +its tool runtime system and LLM provider construction path. The pattern solves |
| 8 | +two concrete architectural problems: |
| 9 | + |
| 10 | +- The same tool implementation needs to behave differently (approval policy, |
| 11 | + sandbox enforcement, logging, caching, retry) depending on the execution |
| 12 | + context (interactive session, CI pipeline, benchmarks) without adapter |
| 13 | + explosion. |
| 14 | +- The same LLM provider metadata and construction rules were duplicated across |
| 15 | + factory registration, zero-sized provider config types, and the external |
| 16 | + `vtcode-llm` adapter layer. |
12 | 17 |
|
13 | 18 | ## Core Concepts |
14 | 19 |
|
@@ -259,6 +264,62 @@ Wrapping is idempotent: registrations created via `from_cgp_tool()` / |
259 | 264 | `register_cgp_tool()` are marked as already CGP-wrapped, and |
260 | 265 | `enable_cgp_pipeline()` skips them instead of nesting another facade layer. |
261 | 266 |
|
| 267 | +## LLM Provider Construction (Phase 8) |
| 268 | + |
| 269 | +Phase 8 applies the same CGP pattern to provider construction without changing |
| 270 | +the runtime string-keyed lookup model. |
| 271 | + |
| 272 | +### LLM components |
| 273 | + |
| 274 | +| Component | Purpose | |
| 275 | +|-----------------------------|--------------------------------------| |
| 276 | +| `ProviderMetadataComponent` | Provider key, display name, defaults | |
| 277 | +| `ProviderBuildComponent` | Build `Box<dyn LLMProvider>` | |
| 278 | + |
| 279 | +### LLM consumer traits |
| 280 | + |
| 281 | +| Trait | Purpose | |
| 282 | +|-----------------------|-----------------------------------------------| |
| 283 | +| `CanDescribeProvider` | Blanket metadata API for provider contexts | |
| 284 | +| `CanBuildProvider` | Blanket factory API for provider construction | |
| 285 | + |
| 286 | +### LLM contexts |
| 287 | + |
| 288 | +The zero-sized provider config types in |
| 289 | +`vtcode-core/src/llm/provider_config.rs` are the CGP contexts: |
| 290 | + |
| 291 | +- `GeminiProviderConfig` |
| 292 | +- `OpenAIProviderConfig` |
| 293 | +- `AnthropicProviderConfig` |
| 294 | +- `HuggingFaceProviderConfig` |
| 295 | +- `LiteLLMProviderConfig` |
| 296 | +- `DeepSeekProviderConfig` |
| 297 | +- `MinimaxProviderConfig` |
| 298 | +- `OpenRouterProviderConfig` |
| 299 | +- `OpenResponsesProviderConfig` |
| 300 | +- `MoonshotProviderConfig` |
| 301 | +- `OllamaProviderConfig` |
| 302 | +- `LmStudioProviderConfig` |
| 303 | +- `ZAIProviderConfig` |
| 304 | + |
| 305 | +Each context is wired once in `vtcode-core/src/llm/cgp.rs`, then consumed by: |
| 306 | + |
| 307 | +- `register_builtin_cgp_providers(...)` and `LLMFactory::register_cgp_provider::<Ctx>()` |
| 308 | + for built-in and custom registration |
| 309 | +- `ProviderBuilder<T>` and the legacy core `ProviderConfig` trait as metadata |
| 310 | + shims over `CanDescribeProvider` |
| 311 | +- `create_provider_unified(...)` as a compatibility shim over the canonical |
| 312 | + factory path |
| 313 | + |
| 314 | +This keeps public entrypoints stable while removing the old |
| 315 | +`BuiltinProvider`/`impl_builtin_provider!` registration split. |
| 316 | +The zero-sized provider config types now serve directly as the metadata |
| 317 | +providers too, so there is no extra descriptor-to-metadata adapter layer. |
| 318 | + |
| 319 | +`vtcode-llm` uses the same `HasComponent` substrate for its |
| 320 | +`FactoryConfigProjectionComponent`, so the external config adapter does not |
| 321 | +carry a second parallel lookup trait. |
| 322 | + |
262 | 323 | The active CGP mode now persists in `ToolRegistry`. Any later |
263 | 324 | `register_tool()` call, including post-startup skill activation, is wrapped |
264 | 325 | through the same mode automatically. This closes the earlier gap where |
|
0 commit comments