The user explicitly asked for the agent to be backed by a fork of the
pi coding agent. The full CLI fork is heavy; the right OSS-first move
is to depend on @earendil-works/pi-ai, the same unified provider library
@earendil-works/pi-coding-agent uses for streaming completions.
What this commit does:
- llm-proxy/server.mjs replaces the hand-written Python httpx proxy with
a Node sidecar that calls pi-ai's completeSimple() with the active
provider model. Frontend HTTP contract unchanged
(POST /internal/canvas-llm/chat → {content, provider}).
- Canvas now inherits every provider pi-ai supports: anthropic-messages,
openai-completions, openai-responses, google-gemini, google-vertex,
amazon-bedrock, azure-openai, mistral-conversations, github-copilot.
- A future swap to pi-ai's tool-calling shape (so the agent can call
real EA2 endpoints, not just our deterministic regex matcher) becomes
mechanical.
- Health endpoint surfaces which providers have keys configured.
- 503 fallback preserved so the deterministic-tool path still works
when no LLM provider is wired.
Image published: gitea.flow-master.ai/shad/canvas-llm-proxy:sha-pi-ai-0.2.0
Digest: sha256:9bc3f3896d2f1346bf210392e0885d5e2a3be77260fafa48be61e4f61c97b085
Old Python sidecar (main.py, requirements.txt, Dockerfile) retained
for one release so deployers can roll back.
Oracle round-8 polish caveat: the 503 body still named OPENAI_API_KEY
and ANTHROPIC_API_KEY in the 'hint' field. Buyer-visible in devtools
even though no UI renders it. Replaced with the same buyer-safe copy
the Agent OFF pill uses: 'natural language replies are not enabled in
this environment'.
Image bumped to canvas-llm-proxy:sha-002. Live verified.
Closes the 'fork Pi coding agent' integration loop with a tiny
broker that mirrors the @earendil-works/pi-ai request shape:
POST /internal/canvas-llm/chat
body: { messages: [{role, content}], max_tokens }
The proxy speaks to OpenAI or Anthropic depending on which env key
is set. With no key, returns 503 so the frontend's deterministic
fallback in routeAgentInput fires gracefully.
- llm-proxy/main.py: FastAPI + httpx (~150 LOC). System messages get
split out for Anthropic (separate 'system' field) and inlined for
OpenAI.
- llm-proxy/Dockerfile: python:3.12-slim, uvicorn on :8080.
- Deployment + Service in demo namespace (verified Running).
- nginx.conf: /internal/canvas-llm/ proxies to the in-cluster service.
Provider keys are set to empty in the manifest by design: customer
flip is a single 'kubectl set env' or sealed-secret update.