Add LLM client interface with LiteLLM adapter (A5/A11)
PR 2 of the steps-3/4 plan. - llm.py: LLMClient protocol — complete(events, tools, model) -> canonical events — present from the first real LLM call. LiteLLMClient renders requests via the A10 renderer, targets the proxy's OpenAI-compatible route, and maps provider tool-call IDs to locally-minted canonical IDs at the boundary - RoleMap (A11): executor/planner/delegate/consultant resolved from env; pinned() returns the mapping to record at task start - Config strictly from env: NISSE_LLM_BASE_URL, NISSE_LLM_TOKEN; envfile.py is a minimal .env loader where real env wins; .env now gitignored with a committed .env.example documenting all variables (Matrix ones included for the upcoming transport PR) - Live smoke test against the proxy is integration-marked and skips without credentials — CI stays credential-free per operator decision; the test runs locally once .env exists - httpx added as nisse-dev's HTTP client Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e185bb7c88
commit
0c2021fced
8 files changed
+462
-2
No files matched your search
@@ -0,0 +1,22 @@
|
||||
"""Minimal .env loader (spec A5: config from env/.env, nothing hardcoded).
|
||||
|
||||
Deliberately tiny: KEY=VALUE lines, comments and blanks ignored, existing
|
||||
environment variables never overridden (real env wins over the file).
|
||||
"""
|
||||
|
||||
import os
|
||||
from collections.abc import MutableMapping
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def load_env_file(path: Path, env: MutableMapping[str, str] = os.environ) -> None:
|
||||
if not path.exists():
|
||||
return
|
||||
for line in path.read_text().splitlines():
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
key, value = line.split("=", 1)
|
||||
key = key.strip()
|
||||
if key and key not in env:
|
||||
env[key] = value.strip()
|
||||
Reference in new issue
Block a user