Fix Garmin connect race, surface tool error content, add dev start scripts

- GarminConnection now flushes Profile's pending debounced autosave before
  connecting, avoiding a race where Connect fires with stale credentials.
- client.go reads res.Content before checking IsError so tool error
  messages actually include mcp-garmin's response text.
- seedsample: update kind lookups to match current taxonomy names
  ("Easy Run" -> "Easy", "Interval" -> "Intervals").
- Add backend/start.sh and frontend/start.sh dev launch scripts, and
  check in CLAUDE.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Christophe Vila
2026-07-21 18:33:49 +02:00
parent 518bccf5ab
commit 2fab788208
8 changed files with 155 additions and 63 deletions

View File

@@ -43,9 +43,9 @@ func main() {
// gap between disjoint ranges. The taxonomy migration already seeded
// these rows (by fixed name) -- update their rules in place rather than
// creating new ones, since names are unique.
easyID := mustFindKindID(ctx, db, "Easy Run")
easyID := mustFindKindID(ctx, db, "Easy")
must(db.UpdateWorkoutKind(ctx, store.WorkoutKind{
ID: easyID, Name: "Easy Run", Description: "Easy conversational runs", Color: "#22c55e",
ID: easyID, Name: "Easy", Description: "Easy conversational runs", Color: "#22c55e",
RuleJSON: `{"match":"all","conditions":[
{"metric":"avg_pace_sec_per_km","op":"between","value":[330,420]},
{"metric":"avg_hr_pct_max","op":"<=","value":0.85}
@@ -63,9 +63,9 @@ func main() {
IsActive: true,
}))
intervalID := mustFindKindID(ctx, db, "Interval")
intervalID := mustFindKindID(ctx, db, "Intervals")
must(db.UpdateWorkoutKind(ctx, store.WorkoutKind{
ID: intervalID, Name: "Interval", Description: "Structured work/rest intervals", Color: "#ef4444",
ID: intervalID, Name: "Intervals", Description: "Structured work/rest intervals", Color: "#ef4444",
RuleJSON: `{"match":"all","conditions":[{"metric":"lap_interval_pattern","op":"==","value":true}]}`,
IsActive: true,
}))

View File

@@ -146,15 +146,15 @@ func (c *mcpClient) callTool(ctx context.Context, name string, args map[string]a
if err != nil {
return "", fmt.Errorf("call tool %s: %w", name, err)
}
if res.IsError {
return "", fmt.Errorf("tool %s returned an error result", name)
}
var out strings.Builder
for _, content := range res.Content {
if tc, ok := content.(mcp.TextContent); ok {
out.WriteString(tc.Text)
}
}
if res.IsError {
return "", fmt.Errorf("tool %s returned an error result: %s", name, out.String())
}
return out.String(), nil
}

9
backend/start.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")"
export MCP_GARMIN_PYTHON="${MCP_GARMIN_PYTHON:-/Users/cvila/Dev/scm/scm.vilanet.fr/kriss/mcp-garmin/.venv/bin/python3}"
export MCP_GARMIN_SERVER="${MCP_GARMIN_SERVER:-/Users/cvila/Dev/scm/scm.vilanet.fr/kriss/mcp-garmin/server.py}"
export SMARTRUN_DB_PATH="${SMARTRUN_DB_PATH:-smartrun.db}"
exec go run ./cmd/smartrund