v1.1.0:3 — AI upgrades: history context, test connection, cost estimator, streaming preview
Four incremental upgrades to the AI program generator. No schema change, no /data migration.
1. History as context (the killer feature)
- lib/ai/historyContext.ts builds a 90-day per-exercise rollup:
frequency, recent weights, estimated 1RM (Epley), avg RPE,
days-since-last, plus a STAGNANT flag when the heaviest weight in
the new half doesn't beat the old half.
- Generate page surfaces an "Include my workout history as context"
checkbox (default on at >=10 logged workouts). When checked, the
~1-3 KB summary is appended to the system prompt so the model can
recommend things like "you've stalled bench at 245 — try paused reps."
- We deliberately don't ship raw set logs (privacy + token cost).
2. Test connection
- POST /api/ai/test sends a tiny "say hi in 3 words" prompt and
reports latency + first sample, or the error inline.
- "Test connection" button next to "Save AI config" in
Settings -> AI integration. Verifies provider/model/key/baseUrl
without going through full program generation.
3. Cost estimator
- lib/ai/pricing.ts ships a price table for major models
(Claude 3.5/3.7/4/4.5, GPT-4o/5/o1/o3/o4-mini, Gemini 1.5/2.0/2.5).
Ollama always returns 0; openai-compatible returns null.
- Generation history shows per-row cost + a 30-day rolling total
at the top of the page.
4. Streaming preview render
- lib/ai/lenientJson.ts: stack-aware partial-JSON parser that
auto-closes open strings/brackets/braces in reverse-of-opening
order, drops dangling key:value pairs and partial keywords.
Returns a best-effort snapshot of the program-so-far on each chunk.
- Generate UI now renders a live "Building program..." panel that
updates as weeks/days/exercises arrive instead of just showing
raw text and waiting for stream end.
Tests: 26 new (ai-historyContext.test.ts, ai-lenientJson.test.ts,
ai-pricing.test.ts). 161 total pass.
This commit is contained in:
@@ -8,6 +8,7 @@ import { v_1_0_0_6 } from './v1.0.0.6'
|
||||
import { v_1_0_0_7 } from './v1.0.0.7'
|
||||
import { v_1_1_0_1 } from './v1.1.0.1'
|
||||
import { v_1_1_0_2 } from './v1.1.0.2'
|
||||
import { v_1_1_0_3 } from './v1.1.0.3'
|
||||
|
||||
/**
|
||||
* Version graph for the `proof-of-work` package.
|
||||
@@ -25,9 +26,11 @@ import { v_1_1_0_2 } from './v1.1.0.2'
|
||||
* v1.1.0:1 — Programs UI (manual create / save / follow).
|
||||
* v1.1.0:2 — AI program generation, 5 providers (Claude / OpenAI /
|
||||
* OpenAI-compatible / Gemini / Ollama).
|
||||
* v1.1.0:3 — AI upgrades: history-as-context, test connection,
|
||||
* cost estimator, streaming preview render.
|
||||
*/
|
||||
export const versionGraph = VersionGraph.of({
|
||||
current: v_1_1_0_2,
|
||||
current: v_1_1_0_3,
|
||||
other: [
|
||||
v_1_0_0_1,
|
||||
v_1_0_0_2,
|
||||
@@ -37,5 +40,6 @@ export const versionGraph = VersionGraph.of({
|
||||
v_1_0_0_6,
|
||||
v_1_0_0_7,
|
||||
v_1_1_0_1,
|
||||
v_1_1_0_2,
|
||||
],
|
||||
})
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { IMPOSSIBLE, VersionInfo } from '@start9labs/start-sdk'
|
||||
|
||||
/**
|
||||
* v1.1.0:3 — AI: workout-history context, test connection,
|
||||
* cost estimator, streaming preview render.
|
||||
*
|
||||
* History context (the killer feature)
|
||||
* - lib/ai/historyContext.ts builds a compact 90-day rollup of
|
||||
* the user's training: per-exercise frequency, recent weights,
|
||||
* estimated 1RMs (Epley), avg RPE, days-since-last, plus a
|
||||
* STAGNANT flag when the heaviest weight in the new half of
|
||||
* the window doesn't beat the old half.
|
||||
* - Generate page has an "Include my workout history as context"
|
||||
* checkbox (default on if you have ≥10 logged workouts). When
|
||||
* checked, the summary is appended to the system prompt so the
|
||||
* model can recommend things like "you've stalled bench at 245
|
||||
* for 6 weeks — try paused reps."
|
||||
* - The summary is text, ~1-3 KB even for heavy users. We
|
||||
* deliberately don't ship raw set logs (privacy + token cost).
|
||||
*
|
||||
* Test connection
|
||||
* - POST /api/ai/test sends a tiny "say hi in 3 words" prompt
|
||||
* against the user's configured provider and reports
|
||||
* latency + first sample of the response, or the error inline.
|
||||
* - "Test connection" button next to "Save AI config" in
|
||||
* Settings → AI integration. Lets you verify the provider/
|
||||
* model/key/baseUrl combo without going through full program
|
||||
* generation.
|
||||
*
|
||||
* Cost estimator
|
||||
* - lib/ai/pricing.ts ships a price table for the major models
|
||||
* (Claude Sonnet/Opus/Haiku 4-5, GPT-5/4o/o3, Gemini 2.5/2.0).
|
||||
* Ollama always returns 0 (self-hosted, no per-token cost).
|
||||
* openai-compatible returns null (we don't know the gateway's
|
||||
* pricing).
|
||||
* - Generation history shows per-row cost + a 30-day rolling
|
||||
* total at the top of the page.
|
||||
*
|
||||
* Streaming preview render
|
||||
* - lib/ai/lenientJson.ts: a stack-aware partial-JSON parser
|
||||
* that auto-closes open strings/brackets/braces in
|
||||
* reverse-of-opening order, drops dangling key:value pairs
|
||||
* and partial keywords. Returns a best-effort snapshot of
|
||||
* the program-so-far on each chunk.
|
||||
* - Generate UI now renders a live "Building program..." panel
|
||||
* that updates as weeks/days/exercises arrive, instead of
|
||||
* just showing raw text and waiting for stream end.
|
||||
*
|
||||
* No schema changes. /data is untouched.
|
||||
*/
|
||||
export const v_1_1_0_3 = VersionInfo.of({
|
||||
version: '1.1.0:3',
|
||||
releaseNotes: {
|
||||
en_US:
|
||||
'AI program generation gets four upgrades: (1) include your last 90 days of workout history as context — the model designs around your actual frequency, current weights, and stagnations; (2) "Test connection" button in Settings to verify provider/model/key without a full generation; (3) per-generation USD cost + 30-day rolling total in the history page (Ollama is free, openai-compatible gateways are unknown); (4) streaming preview renders the program tree as the model writes it instead of waiting for the full response. No data migration.',
|
||||
},
|
||||
migrations: {
|
||||
up: async () => {},
|
||||
down: IMPOSSIBLE,
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user