🧭 NeXuS Compass — 2026-07-28 — Universal API Proxy + NeXuS Web Server¶
Theme: Built the sovereign serving+key layer. One portable pure-Python HTTPS server that
serves any app AND fronts every AI provider through one /api/* proxy that injects keys
server-side (no key ever in the browser). Grew it into a universal API server (declare any
provider from an env file). Loaded all of Anon's keys. Started wiring the web char-gen to it.
Prev compass: NEXUS_COMPASS_2026-07-24_ai-home-web-and-python-chargens.md.
Export of this session: ~/Projects/adv-ai-nexus/advanced-ai-character-generator-terminal-access/2026-07-28-214801-created-api-universal-proxy.txt
⭐ What shipped (DONE + verified)¶
1. Security — Pollinations key rotated ✅¶
- Anon revoked leaked
sk_jOK7…at enter.pollinations.ai. Keepersk_6ZnG…(namebackend-rotten-cicada) validated live (no rate limit). 9 plaintext copies in~/Projects/beta/ai-character-generator/now inert → beta archive unblocked.
2. NeXuS Web Server — the deliverable¶
~/Projects/nexus-web-server/nexus_web_server.py— one file, pure stdlib (no node/npm/pip). Own Fossil~/museum/nexus-web-server.fossil(commits7a158386c2,4ce3ea5b74,2783886d0b; models-endpoint + CSP fix still UNCOMMITTED).- Two jobs, split: (A) STATIC serve
--root(per-app SPA fallback, multi-app landing); (B) PROXY/api/*injects keys fromnexus.env/.local.envserver-side. - Retired node from char-gen production:
launch.shnow calls$NEXUS_WEB_SERVER --root dist --cert … --key …; Python-first, node/npm now OPTIONAL (dev/build).server-production.jskept as fallback. In-project server copies archived (.migrated/.superseded). - Portable/versatile:
--root <dir>(default ./dist), serves any app folder,--env,--cert/--key.
3. UNIVERSAL API SERVER (the leap)¶
- Dynamic providers from the env file — no code edit: scan for
PROVIDER_<ID>_BASE_URL(+_API_KEYoptional → keyed/keyless,_KIND,_LABEL). Registered on the fly, appears in/api/providers, callable at/api/llm/<id>/v1/chat/completions. No restart. - Secure
.local.env: precedenceprocess-env > .local.env > nexus.env > legacy. Guards: never web-served (static 404s any.env/.key/.pem/dotfile even inside docroot); auto-.gitignore (startup appends secret patterns to a.gitignorein the folder, append-only); never logged/returned; chmod-600 warning. Template.local.env.example. - Routes:
/api/health,/api/providers(sanitized),/api/models/{image,text}(Pollinations),/api/models/provider/{id}(NEW — live per-provider/models, normalized),/api/pollinations/image(streamed),/api/llm(body-style) +/api/llm/{provider}/v1/chat/completions(vanilla OpenAI body). - CSP fix: added
worker-src 'self' blob:(app web-workers were being blocked).
4. All of Anon's API keys loaded → ~/.config/nexus/secrets/nexus.env (chmod 600, backed up)¶
From /home/user/API/hackenstacks-apis.txt (masked-parse; skipped 2FA/backup codes, Porkbun,
GitHub tokens, model-name lists):
- Built-in keyed: MISTRAL_API_KEY, GROQ_API_KEY, OPENROUTER_API_KEY.
- Stored (wire later): GEMINI_API_KEY/GOOGLE_API_KEY, HUGGINGFACE_API_KEY,
STABILITY_API_KEY, IMAGEROUTER_API_KEY.
- Dynamic providers (live): deepseek, together, hyperbolic, cerebras, google
(Gemini via its OpenAI-compat endpoint), grok (free via Pollinations).
- 12 providers now READY (only openai lacks a key). Pollinations kept the good sk_6ZnG…
(ignored the corrupted 6sk_… in the file).
- Live /models verified: mistral 60, google 57, cerebras 3, deepseek 2, pollinations 157.
5. Web char-gen wiring (partial — see PENDING)¶
services/nexusProxy.ts(NEW): fetch interceptor (OpenCharactersnew Proxy(fetch)idea) — rewrites cloud chat hosts → same-origin/api/llm/<provider>and strips the client key. Installed first-thing inindex.tsx. Verified live in log:[nexus-proxy] gen.pollinations.ai/… → /api/llm/pollinations (key server-side).- Terminal bridges (
fileSystemService.tscallAichat/callOllama) → proxy. - Summarizer (
geminiService.ts generateContent) → proxy;default/aihordefall back to Pollinations, not Gemini (killed theDefault Gemini API key not configurederror). - Terminal awareness in the TEXT system prompt (
buildSystemInstruction, whenterminalEnabled) for ALL providers — fixes non-Gemini characters (A.I.M.E on AI Horde) wrongly claiming "I can't browse." An assertive version is written (counters strong personas + "paste it yourself" deferral). - Proven: connected to A.I.M.E through the proxy with her real persona — she emitted
search latest AI buzzinstead of refusing. In the live app she now emitssearch …too.
6. Docs¶
~/Projects/nexus-web-server/docs/nexus-web-server_HELP.md— visual manual + 100% requirements checklist (Python ≥3.8 stdlib-only, cert, root, port; keys conditional; node only to rebuild JS).~/claude/docs/pollinations-api-reference.mdrefreshed from newest upstream capture (~/claude/pollinations/latest-pollinations-llm-info.md): 3D/video/voice/embeddings, prompt caching, safety redaction, media storage, BYOP OAuth; refreshed model lists;pk_= BYOP App Key.
⏳ PENDING — "B" not finished + a live bug¶
B (server-driven UI) — half done¶
- ✅ Server
/api/models/provider/{id}built. - ❌
geminiService.ts streamChatResponsedispatch: new dynamic providers (deepseek/google/grok/together/hyperbolic/cerebras) currently fall through to AI Horde — must route ALL OpenAI-compatible services through/api/llm/{service}(makestreamOpenAIChatResponsetarget the proxy URL fromconfig.service, drop client auth). gemini→SDK, aihorde/default→AIHorde. - ❌ UI dropdowns: replace hardcoded
API_PRESETSinCharacterForm.tsx(chat + summary) and the image provider inPluginManager.tsxwith a fetch of/api/providers(+key_presentreadiness) and models from/api/models/provider/{id}(or/api/models/{text,image}). Remove the key + endpoint input fields (add a "managed server-side" note). Single source of truth = server (kills the API_PRESETS dual-source-of-truth — the [[feedback_dankshell_owns_settings]] trap).
Live A.I.M.E bug (diagnosed, NOT fixed)¶
- Symptom: she emits
search …, but results don't display; auto-summary loops (Auto-summarizing: 50 → 44 → 37 messages) and the terminalsearchsits at approval. - Mechanics (
components/ChatInterface.tsx):autoSummarizeIfNeeded(L201) fires every turn oncemessages.length >= L1_THRESHOLD, trims the lastL1_THRESHOLDmsgs (L257) → likely eats the terminal output/response. Terminalsearchneeds approval viapermissionManager.checkPermission(L407) → modal. - Fixes to try: (a) auto-approve safe read-only terminal cmds (
search/curl/http) or set always-approve; (b) make auto-summary non-destructive / not fire mid terminal-loop / raise threshold / guard re-entrancy so it doesn't trim the just-produced result.
Rebuild pending¶
- Latest source edits (assertive terminal instruction, generateContent proxy, terminal bridges) are only
partly in the running bundle. Running build =
index-DY9YfE47.js. Neednpm run buildto bake the assertive terminal awareness + confirm everything.
🔧 UNCOMMITTED (review + commit next session)¶
- nexus-web-server.fossil:
nexus_web_server.pyEDITED (models endpoint + CSP +.local.env+ dynamic providers — earlier.local.env/dynamic already committed2783886d0b; models+CSP not yet). - nexus-ai-home.fossil (char-gen):
services/nexusProxy.ts(new),index.tsx,launch.sh,services/fileSystemService.ts,services/geminiService.ts— all EDITED, uncommitted.dist/rebuilt. Backups made for each (.bak-*).
🚦 NEXT SESSION order¶
- Fix
streamChatResponsedispatch → route all OpenAI-compat (incl dynamic) via/api/llm/{service}. npm run build; verify deepseek/google/grok/mistral chat + summarizer via the new keys.- B UI: server-driven provider/model dropdowns in CharacterForm + PluginManager; strip key/endpoint fields.
- Fix A.I.M.E auto-summary vs terminal-result display + terminal auto-approve for read-only cmds.
- Commit everything (both repos) with detailed messages; update reports.
- (Deferred) archive beta dir; Fossilize
nexus-charcard.
🗝️ Gotchas / notes¶
- Server reads secrets on-demand → adding a key to
nexus.envneeds no restart; adding a route (code) does need a restart. Launch it withrun_in_background: true+ noexec(exec/&get reaped). curl -I(HEAD) is NOT implemented → check headers withcurl -D - … -o /dev/null(a GET).- fish shell prints
exit 144noise on piped/pkill commands — output still valid. - Provider ids must match server registry; grok = Pollinations-backed (no xAI key on file); AI Horde
file entry was just
z→ uses keyless anon0000000000.