Commit Graph

3 Commits

Author SHA1 Message Date
Keysat 91b5b04d97 v1.2.0:7 — add SparkControl AI provider + fix base-URL footgun
CI / proof-of-work (Next.js app) (push) Waiting to run
CI / start9/0.4 (StartOS package code) (push) Waiting to run
SparkControl is a self-hosted local-inference gateway with an OpenAI-compatible API, reached over the internal same-box StartOS address (http://spark-control.startos:9999/v1, plain HTTP). It takes no API key, so generateOpenAIStyle gained a { requireApiKey } option and now omits the Authorization header when no key is set. The Settings form auto-detects the loaded vLLM model via SparkControl's /api/endpoints probe, mirroring the Ollama auto-detect; it's $0 in the cost UI. Custom-URL => admin-only + SSRF-guarded, same as Ollama.

Also fixes a config footgun behind the empty-response report: a custom base URL could ride along to a fixed-URL provider (claude/openai/gemini) whose form field is hidden, get stored, and be silently ignored (the provider always hits its hardcoded endpoint). Both config write paths now null baseUrl for non-custom-URL providers, and the form clears it on provider change.

No schema/data change (AIConfigProfile.provider is free-text). 259 tests pass; built + sideloaded to immense-voyage.local with a clean non-root launch.
2026-06-19 14:47:30 -05:00
Keysat 988a3cca9a v1.1.0:8 — admin-gate whole-DB routes + AI custom-URL providers; SSRF guard
CI / proof-of-work (Next.js app) (push) Has been cancelled
CI / start9/0.4 (StartOS package code) (push) Has been cancelled
Multi-user authorization hardening from a full security evaluation (EVALUATION.md):

- P0: /api/settings/{export,import}-db are now admin-only. Previously any signed-in user could download the whole instance DB (all bcrypt hashes + plaintext AI keys) or replace it wholesale. Per-user CSV export/import stays open.

- AI custom-URL providers (Ollama, OpenAI-compatible) are now admin-only, and every server fetch to a user-supplied URL passes through assertSafeProviderUrl (blocks link-local/cloud-metadata; private LAN allowed by design). Fixed-URL cloud providers stay per-user. Removed the dead legacy /api/ai/config route.

- Dev: fixed broken quick-start (added npm run create-admin; rewrote README; dropped dead CLAUDE_API_KEY) and the export-db 0-byte path resolution (resolveDatabasePath now matches Prisma).

ExVer bumped to 1.1.0:8 (no schema/data migration). Tests 197 pass, build green, tsc clean.
2026-06-12 23:15:09 -05:00
Keysat 7a62690a4a v1.1.0:4 — multi-config AI, background generation, ollama auto-detect, system prompt overhaul
User-feedback-driven release after testing v1.1.0:3. Nine themes:

1. Multi-config persistence
   - New AIConfigProfile table (per-user). Save N configs, toggle one
     active. Switching providers no longer wipes the previous setup.
   - UserPreferences gains activeAIConfigId; legacy single-config
     columns are mirrored from the active profile so existing reads
     keep working without conditional logic.
   - Idempotent boot migration lifts any existing single-config row
     into a default profile.

2. Ollama auto-detect
   - The "Add config" form probes /api/tags on the StartOS internal
     addresses (ollama.startos / ollama.embassy on :11434). If
     reachable: URL pre-fills, model field becomes a dropdown of
     installed models. Fixes the copy-paste UX.

3. Curated model dropdowns for major providers
   - Claude: Opus 4.7, Sonnet 4.6 (1M ctx), Haiku 4.5
   - OpenAI: GPT-5.5, 5.4, 5.4-mini, 5.4-nano
   - Gemini: 3.1-pro-preview, 2.5-pro, 2.5-flash, etc.
   - "Other (type your own)" stays for niche models.
   - Fixes "I tried gemini-3.0-pro and got 404."

4. Background generation
   - lib/ai/generationRunner.ts: detached runner with in-memory
     pub/sub bus. POST /api/ai/generate kicks it off and returns
     immediately. SSE stream attaches by id. The runner survives
     request cancellation; navigating away no longer kills it.
   - New AIGeneration columns: progressText (in-flight stream),
     durationMs (final wall-clock).
   - Generate UI shows a banner explaining background-safety.
   - History detail page polls progress + renders partial JSON
     live for cross-process resume (page refresh, new tab).

5. System prompt overhaul
   - lib/ai/systemPromptBase.ts: structural contract prepended to
     every template. Forces JSON-only output, library-exerciseId
     usage (kills "exerciseId doesn't belong to this user" errors),
     and per-resistance-exercise suggestedWeight (with-history vs
     without-history variants).
   - aiExerciseSchema + ProgramExercise gain suggestedWeight +
     suggestedWeightUnit. Starting a workout from a ProgramDay
     pre-populates SetLog.weight from the suggestion.

6. Test connection improvements
   - Latency in seconds (was ms — confusing for slow Ollama).
   - Stale "✓ Connected" clears on form change.
   - Per-config Test (no need to activate first).
   - Generous maxOutputTokens for thinking models.
   - Gemini surfaces finishReason on empty response (e.g. "blocked
     by safety filter") instead of generic "empty response."
   - Test endpoint accepts a draft body so you can verify before
     saving + before activating.

7. History detail view
   - Click row → full program tree + exact prompts sent. Apply from
     here without re-generating. Pending rows poll for progress.

8. Sidebar sub-navigation
   - AI: Generate / History / Templates
   - Settings: General / Password / Sessions / AI integration /
     Export / Instance (admin) / Danger zone, with anchor scroll.

9. API key UX
   - "Key saved" indicator on saved configs (was confusing to see
     an empty input after a successful save).

Schema migrations (additive, idempotent in entrypoint):
  - AIConfigProfile table created
  - UserPreferences.activeAIConfigId
  - AIGeneration.progressText + durationMs
  - ProgramExercise.suggestedWeight + suggestedWeightUnit

Tests: 16 new (systemPromptBase, modelMenu, generationRunner). 177
total pass.
2026-05-11 08:09:01 -05:00