Pluggable model adapters for KOPITIAM's Semantic Runtime.
This crate defines the [ModelAdapter] trait — the sole boundary through
which a model (local Qwen, Claude, GPT, Gemini, ...) is invoked anywhere
in the platform. Per the Semantic Runtime's dependency rule, only
kopitiam-workflow depends on this crate; everything else in the
platform (kopitiam-knowledge, kopitiam-index, kopitiam-search,
kopitiam-workspace, kopitiam-translation) stays model-agnostic.
What lives here is the shape of a request/response
([CompletionRequest], [CompletionResponse], [Message]), one
deterministic stub adapter ([EchoAdapter], always available) so
kopitiam-workflow has something real to compile and test against with
no weights and no network, and — behind the default-on local Cargo
feature — [LocalAdapter], a real, offline, on-CPU adapter backed by
kopitiam-runtime's Qwen inference stack. See [local]'s module docs
for the full local-vs-cloud architecture and why depending on
kopitiam-runtime from here does not violate the Semantic Runtime's
dependency rule.
Two other pieces round out the boundary for a live chat UI:
- Streaming — alongside the blocking [
ModelAdapter::complete], every adapter can [ModelAdapter::stream] its reply token-by-token over a channel of [StreamChunk]s, so a UI renders tokens as they land instead of freezing on a slow generation. [EchoAdapter] and [LocalAdapter] do this on a real background thread (the AID-0028 actor discipline, std threads +mpsc, no async runtime). - Cloud scaffold — [
CloudAdapter] + [CloudStub] for Claude/GPT/Gemini ([CloudVendor]), gated on an API key from the environment. Key-detection and the "no key → [CloudUnavailable]" path are real; the network layer itself is a deliberate follow-up.