2026-04-27 โ Admin AI Assistant (Lantern Chat) โ
Outcome: Complete โ backend + UI + wiring shipped, admin build green, smoke-tested locally.
Scope โ
Add an agentic Claude-powered chat assistant to the admin portal. The assistant answers questions contextually and may, when it decides it's needed, read repo files (docs/code), grep the repo, list directories, list registered API services, or query a small allow-list of Firestore collections.
Files Added โ
Backend โ services/api/assistant/ (new Cloud Run service) โ
- services/api/assistant/package.json โ workspace
lantern-assistant-api.@anthropic-ai/sdk@^0.91.1. - services/api/assistant/Dockerfile โ Node 22-slim, bundles
repo-snapshot/+.shared-pkg/. - services/api/assistant/openapi.json โ OpenAPI 3.0 spec, served at
/openapi.json. - services/api/assistant/README.md, services/api/assistant/.gitignore
- services/api/assistant/src/index.js โ Express app. CORS via
ALLOWED_ORIGINS, JSON 256kb. Routes:/health(public),/openapi.json+/api-docsScalar (public, per CLAUDE.md rule #8),/assistant/*(admin-authed + rate-limited). - src/middleware/auth.js โ
verifyFirebaseToken+requireAdmin(mirrorsservices/api/auth/src/middleware/auth.js). - src/middleware/rateLimiter.js โ 30 turns / 5 min per user.
- src/middleware/errorHandler.js
- src/routes/health.js, src/routes/chat.js โ Zod-validated
POST /assistant/chat. - src/services/anthropic.js โ agentic loop. Default model
claude-sonnet-4-5(ASSISTANT_MODELoverrides).max_tokens2048,MAX_AGENT_ITERATIONS=8. System prompt instructs the model to prefer direct knowledge and use tools only when necessary. - src/services/tools.js โ 5 tools:
list_dir,read_file,grep_repo,list_api_services,query_firestore. - src/services/repoFs.js โ sandboxed FS helpers: allow-list of repo prefixes (
docs/,apps/,services/,packages/,tooling/,scripts/, select.github/subpaths) + specific root files; deny-list (node_modules,.git,.env*,dist,build,coverage,*.pem/*.key,service-account*.json,credentials*.json). Caps: 200 KB read, 100 grep matches, 200 dir entries.
Admin UI โ apps/admin/ โ
- src/components/LanternChat/LanternChat.jsx โ floating bubble (bottom-right) + slide-up panel. Persists last 30 messages to
localStorage(lantern-chat:messages:v1). Page context (useLocation) sent every turn. AbortController for in-flight cancel. Markdown rendering (react-markdown+remark-gfm). 4 starter suggestions. - src/components/LanternChat/LanternChat.css โ 56ร56 amber radial-gradient bubble,
lantern-glowkeyframe pulse (3.2s), 420ร640 panel, dark#0f172asurface, amber accent. Tool-call<details>collapsible. - src/components/LanternChat/index.js
- src/lib/assistantApi.js โ
sendAssistantChat()viaauthRequest. URL fromVITE_ASSISTANT_API_URL(defaults to/apiproxy โhttp://localhost:8086).
Files Modified โ
- packages/shared/services/index.js โ added
assistant-apientry (auto-surfaces in admin API Reference page; CLAUDE.md rule #8). - package.json โ added
services/api/assistantworkspace; scriptsassistant-api:dev,assistant-api:start,assistant-api:test,assistant-api:deploy:dev,logs:assistant-api,logs:assistant-api:prod. Extendedapis:dev,apis:kill,kill:portsto include 8086 (also backfilled missing 8081/8084/8085). - tooling/vscode-extension/src/config.js โ Assistant API in
PORT_MAP.apis(8086);assistant-api:dev+ log scripts inDEV_SERVER_SCRIPTS;INPUT_PROMPTSentries. - apps/admin/vite.config.mjs โ
/api/assistantproxy โenv.ASSISTANT_API_ORIGIN. - .env.local.example โ added
ASSISTANT_API_ORIGIN,VITE_ASSISTANT_API_URL, commentedASSISTANT_MODEL/ASSISTANT_MAX_TOKENS. - apps/admin/src/components/AdminDashboard.jsx โ renders
<LanternChat />for admin users only.
Architecture Notes โ
- API-first (CLAUDE.md rule #9): new HTTP service, not a Cloud Function.
- Stateless backend: full conversation passed each turn. Server runs the agentic loop, executes tool calls, feeds
tool_resultblocks back until the model returns a non-tool_usestop_reason. - Auth model: admin only. Merchant access intentionally deferred to a future phase (different system prompt + tighter tool allow-list expected).
- Rate limit: 30 chat turns / 5 minutes per user (UID-keyed in-memory window โ fine for single-instance Cloud Run; replace with Redis if we scale horizontally).
- Repo root resolution: env
ASSISTANT_REPO_ROOTโ/app/repo-snapshot(production Docker layout) โ repo root (dev). Therepo-snapshot/directory must be populated beforegcloud run deploy(the deploy script needs to copy a sanitized snapshot โ TODO before first deploy).
Verification โ
npm installclean โnode --checkon all new JS files โ- ESLint on all new code: clean (one warning auto-fixed) โ
- Boot smoke test:
/healthreturns ok withanthropic: false(no key set) โ ;/openapi.jsonserves spec โ ;POST /assistant/chatwithout auth โ401 UNAUTHORIZEDโ ; with fake bearer โ401 Invalid or expired tokenโ . npm run build -w apps/adminโ (LanternChat included in main bundle).
Outstanding / Future โ
- Smoke test against real Anthropic: requires
ANTHROPIC_API_KEYenv. Verify model idclaude-sonnet-4-5resolves; if not, override viaASSISTANT_MODEL. - Deploy script: needs a step to copy a sanitized
repo-snapshot/(excluding.env*,node_modules, secrets, build artifacts) beforegcloud run deploy. - Merchant assistant: separate system prompt + narrower tool allow-list (no
query_firestorecross-tenant; scoperead_file/grep_repoto merchant-facing docs). - Telemetry: log token usage per turn for cost tracking once we go live.
- Persistence: if we ever want cross-device chat history, move
localStoragepersistence to Firestore under the user's record.