trainbud 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +11 -0
- package/CHANGELOG.md +675 -0
- package/LICENSE +21 -0
- package/QUICKSTART.md +182 -0
- package/README.md +322 -0
- package/dist/appDb.d.ts +83 -0
- package/dist/appDb.d.ts.map +1 -0
- package/dist/appDb.js +239 -0
- package/dist/appDb.js.map +1 -0
- package/dist/check.d.ts +12 -0
- package/dist/check.d.ts.map +1 -0
- package/dist/check.js +230 -0
- package/dist/check.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +457 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +61 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +241 -0
- package/dist/config.js.map +1 -0
- package/dist/dashboard.d.ts +8 -0
- package/dist/dashboard.d.ts.map +1 -0
- package/dist/dashboard.js +1004 -0
- package/dist/dashboard.js.map +1 -0
- package/dist/dashboardCharts.d.ts +99 -0
- package/dist/dashboardCharts.d.ts.map +1 -0
- package/dist/dashboardCharts.js +317 -0
- package/dist/dashboardCharts.js.map +1 -0
- package/dist/dashboardData.d.ts +89 -0
- package/dist/dashboardData.d.ts.map +1 -0
- package/dist/dashboardData.js +228 -0
- package/dist/dashboardData.js.map +1 -0
- package/dist/detect/baseline.d.ts +17 -0
- package/dist/detect/baseline.d.ts.map +1 -0
- package/dist/detect/baseline.js +62 -0
- package/dist/detect/baseline.js.map +1 -0
- package/dist/detect/countdown.d.ts +30 -0
- package/dist/detect/countdown.d.ts.map +1 -0
- package/dist/detect/countdown.js +79 -0
- package/dist/detect/countdown.js.map +1 -0
- package/dist/detect/detectors.d.ts +20 -0
- package/dist/detect/detectors.d.ts.map +1 -0
- package/dist/detect/detectors.js +291 -0
- package/dist/detect/detectors.js.map +1 -0
- package/dist/detect/findings.d.ts +29 -0
- package/dist/detect/findings.d.ts.map +1 -0
- package/dist/detect/findings.js +2 -0
- package/dist/detect/findings.js.map +1 -0
- package/dist/detect/forecast.d.ts +33 -0
- package/dist/detect/forecast.d.ts.map +1 -0
- package/dist/detect/forecast.js +122 -0
- package/dist/detect/forecast.js.map +1 -0
- package/dist/detect/index.d.ts +50 -0
- package/dist/detect/index.d.ts.map +1 -0
- package/dist/detect/index.js +114 -0
- package/dist/detect/index.js.map +1 -0
- package/dist/detect/sleepQuality.d.ts +21 -0
- package/dist/detect/sleepQuality.d.ts.map +1 -0
- package/dist/detect/sleepQuality.js +164 -0
- package/dist/detect/sleepQuality.js.map +1 -0
- package/dist/detect/trimp.d.ts +22 -0
- package/dist/detect/trimp.d.ts.map +1 -0
- package/dist/detect/trimp.js +77 -0
- package/dist/detect/trimp.js.map +1 -0
- package/dist/detect/week.d.ts +31 -0
- package/dist/detect/week.d.ts.map +1 -0
- package/dist/detect/week.js +184 -0
- package/dist/detect/week.js.map +1 -0
- package/dist/garmin/auth.d.ts +10 -0
- package/dist/garmin/auth.d.ts.map +1 -0
- package/dist/garmin/auth.js +81 -0
- package/dist/garmin/auth.js.map +1 -0
- package/dist/garmin/cache.d.ts +42 -0
- package/dist/garmin/cache.d.ts.map +1 -0
- package/dist/garmin/cache.js +141 -0
- package/dist/garmin/cache.js.map +1 -0
- package/dist/garmin/client.d.ts +22 -0
- package/dist/garmin/client.d.ts.map +1 -0
- package/dist/garmin/client.js +237 -0
- package/dist/garmin/client.js.map +1 -0
- package/dist/garmin/daily.d.ts +24 -0
- package/dist/garmin/daily.d.ts.map +1 -0
- package/dist/garmin/daily.js +96 -0
- package/dist/garmin/daily.js.map +1 -0
- package/dist/garmin/garminApiTypes.d.ts +70 -0
- package/dist/garmin/garminApiTypes.d.ts.map +1 -0
- package/dist/garmin/garminApiTypes.js +3 -0
- package/dist/garmin/garminApiTypes.js.map +1 -0
- package/dist/garmin/garminConnect.d.ts +17 -0
- package/dist/garmin/garminConnect.d.ts.map +1 -0
- package/dist/garmin/garminConnect.js +5 -0
- package/dist/garmin/garminConnect.js.map +1 -0
- package/dist/garmin/partial.d.ts +32 -0
- package/dist/garmin/partial.d.ts.map +1 -0
- package/dist/garmin/partial.js +38 -0
- package/dist/garmin/partial.js.map +1 -0
- package/dist/garmin/rawApi.d.ts +59 -0
- package/dist/garmin/rawApi.d.ts.map +1 -0
- package/dist/garmin/rawApi.js +113 -0
- package/dist/garmin/rawApi.js.map +1 -0
- package/dist/garmin/types.d.ts +85 -0
- package/dist/garmin/types.d.ts.map +1 -0
- package/dist/garmin/types.js +11 -0
- package/dist/garmin/types.js.map +1 -0
- package/dist/history/capture.d.ts +12 -0
- package/dist/history/capture.d.ts.map +1 -0
- package/dist/history/capture.js +63 -0
- package/dist/history/capture.js.map +1 -0
- package/dist/history/context.d.ts +51 -0
- package/dist/history/context.d.ts.map +1 -0
- package/dist/history/context.js +122 -0
- package/dist/history/context.js.map +1 -0
- package/dist/history/fallback.d.ts +72 -0
- package/dist/history/fallback.d.ts.map +1 -0
- package/dist/history/fallback.js +185 -0
- package/dist/history/fallback.js.map +1 -0
- package/dist/history/ingest.d.ts +44 -0
- package/dist/history/ingest.d.ts.map +1 -0
- package/dist/history/ingest.js +347 -0
- package/dist/history/ingest.js.map +1 -0
- package/dist/history/scheduler.d.ts +20 -0
- package/dist/history/scheduler.d.ts.map +1 -0
- package/dist/history/scheduler.js +54 -0
- package/dist/history/scheduler.js.map +1 -0
- package/dist/history/schema.d.ts +41 -0
- package/dist/history/schema.d.ts.map +1 -0
- package/dist/history/schema.js +91 -0
- package/dist/history/schema.js.map +1 -0
- package/dist/history/store.d.ts +112 -0
- package/dist/history/store.d.ts.map +1 -0
- package/dist/history/store.js +282 -0
- package/dist/history/store.js.map +1 -0
- package/dist/httpServer.d.ts +55 -0
- package/dist/httpServer.d.ts.map +1 -0
- package/dist/httpServer.js +1027 -0
- package/dist/httpServer.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/mcpConfig.d.ts +56 -0
- package/dist/mcpConfig.d.ts.map +1 -0
- package/dist/mcpConfig.js +106 -0
- package/dist/mcpConfig.js.map +1 -0
- package/dist/pairApi.d.ts +14 -0
- package/dist/pairApi.d.ts.map +1 -0
- package/dist/pairApi.js +38 -0
- package/dist/pairApi.js.map +1 -0
- package/dist/paths.d.ts +45 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +105 -0
- package/dist/paths.js.map +1 -0
- package/dist/profile.d.ts +123 -0
- package/dist/profile.d.ts.map +1 -0
- package/dist/profile.js +327 -0
- package/dist/profile.js.map +1 -0
- package/dist/promptApi.d.ts +43 -0
- package/dist/promptApi.d.ts.map +1 -0
- package/dist/promptApi.js +328 -0
- package/dist/promptApi.js.map +1 -0
- package/dist/promptSuggestions.d.ts +16 -0
- package/dist/promptSuggestions.d.ts.map +1 -0
- package/dist/promptSuggestions.js +141 -0
- package/dist/promptSuggestions.js.map +1 -0
- package/dist/selfTest.d.ts +53 -0
- package/dist/selfTest.d.ts.map +1 -0
- package/dist/selfTest.js +225 -0
- package/dist/selfTest.js.map +1 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +67 -0
- package/dist/server.js.map +1 -0
- package/dist/setup.d.ts +2 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +210 -0
- package/dist/setup.js.map +1 -0
- package/dist/toolErrors.d.ts +2 -0
- package/dist/toolErrors.d.ts.map +1 -0
- package/dist/toolErrors.js +18 -0
- package/dist/toolErrors.js.map +1 -0
- package/dist/tools/activities.d.ts +18 -0
- package/dist/tools/activities.d.ts.map +1 -0
- package/dist/tools/activities.js +182 -0
- package/dist/tools/activities.js.map +1 -0
- package/dist/tools/bodyComposition.d.ts +10 -0
- package/dist/tools/bodyComposition.d.ts.map +1 -0
- package/dist/tools/bodyComposition.js +139 -0
- package/dist/tools/bodyComposition.js.map +1 -0
- package/dist/tools/context.d.ts +8 -0
- package/dist/tools/context.d.ts.map +1 -0
- package/dist/tools/context.js +148 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/findings.d.ts +7 -0
- package/dist/tools/findings.d.ts.map +1 -0
- package/dist/tools/findings.js +51 -0
- package/dist/tools/findings.js.map +1 -0
- package/dist/tools/heartRate.d.ts +10 -0
- package/dist/tools/heartRate.d.ts.map +1 -0
- package/dist/tools/heartRate.js +105 -0
- package/dist/tools/heartRate.js.map +1 -0
- package/dist/tools/index.d.ts +66 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +101 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/payloads.d.ts +148 -0
- package/dist/tools/payloads.d.ts.map +1 -0
- package/dist/tools/payloads.js +2 -0
- package/dist/tools/payloads.js.map +1 -0
- package/dist/tools/recovery.d.ts +31 -0
- package/dist/tools/recovery.d.ts.map +1 -0
- package/dist/tools/recovery.js +350 -0
- package/dist/tools/recovery.js.map +1 -0
- package/dist/tools/sleep.d.ts +10 -0
- package/dist/tools/sleep.d.ts.map +1 -0
- package/dist/tools/sleep.js +124 -0
- package/dist/tools/sleep.js.map +1 -0
- package/dist/tools/stress.d.ts +11 -0
- package/dist/tools/stress.d.ts.map +1 -0
- package/dist/tools/stress.js +108 -0
- package/dist/tools/stress.js.map +1 -0
- package/dist/tools/trainingInsights.d.ts +15 -0
- package/dist/tools/trainingInsights.d.ts.map +1 -0
- package/dist/tools/trainingInsights.js +79 -0
- package/dist/tools/trainingInsights.js.map +1 -0
- package/dist/tools/types.d.ts +12 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/vo2Max.d.ts +11 -0
- package/dist/tools/vo2Max.d.ts.map +1 -0
- package/dist/tools/vo2Max.js +110 -0
- package/dist/tools/vo2Max.js.map +1 -0
- package/dist/tools/week.d.ts +12 -0
- package/dist/tools/week.d.ts.map +1 -0
- package/dist/tools/week.js +74 -0
- package/dist/tools/week.js.map +1 -0
- package/dist/usage.d.ts +104 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +247 -0
- package/dist/usage.js.map +1 -0
- package/dist/utils/batch.d.ts +2 -0
- package/dist/utils/batch.d.ts.map +1 -0
- package/dist/utils/batch.js +18 -0
- package/dist/utils/batch.js.map +1 -0
- package/dist/utils/helpers.d.ts +32 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +188 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/jsonFile.d.ts +19 -0
- package/dist/utils/jsonFile.d.ts.map +1 -0
- package/dist/utils/jsonFile.js +24 -0
- package/dist/utils/jsonFile.js.map +1 -0
- package/dist/utils/logger.d.ts +4 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +97 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/secretFile.d.ts +15 -0
- package/dist/utils/secretFile.d.ts.map +1 -0
- package/dist/utils/secretFile.js +47 -0
- package/dist/utils/secretFile.js.map +1 -0
- package/dist/utils/stdio.d.ts +10 -0
- package/dist/utils/stdio.d.ts.map +1 -0
- package/dist/utils/stdio.js +70 -0
- package/dist/utils/stdio.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +7 -0
- package/dist/version.js.map +1 -0
- package/dist/watchApi.d.ts +264 -0
- package/dist/watchApi.d.ts.map +1 -0
- package/dist/watchApi.js +333 -0
- package/dist/watchApi.js.map +1 -0
- package/package.json +77 -0
package/dist/appDb.js
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import Database from "better-sqlite3";
|
|
2
|
+
import { randomInt } from "node:crypto";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { appConfig } from "./config.js";
|
|
6
|
+
import { restrictExistingFile } from "./utils/secretFile.js";
|
|
7
|
+
// SECTION: App DB — settings, pair tokens, prompt jobs
|
|
8
|
+
const DB_PATH = path.resolve(path.dirname(appConfig.cachePath), "app.db");
|
|
9
|
+
let _db = null;
|
|
10
|
+
export const APP_DB_SCHEMA = `
|
|
11
|
+
CREATE TABLE IF NOT EXISTS settings (
|
|
12
|
+
key TEXT PRIMARY KEY,
|
|
13
|
+
value TEXT NOT NULL
|
|
14
|
+
);
|
|
15
|
+
CREATE TABLE IF NOT EXISTS pair_tokens (
|
|
16
|
+
code TEXT PRIMARY KEY,
|
|
17
|
+
created_at INTEGER NOT NULL,
|
|
18
|
+
expires_at INTEGER NOT NULL,
|
|
19
|
+
approved_at INTEGER
|
|
20
|
+
);
|
|
21
|
+
CREATE TABLE IF NOT EXISTS prompt_jobs (
|
|
22
|
+
id TEXT PRIMARY KEY,
|
|
23
|
+
prompt TEXT NOT NULL,
|
|
24
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
25
|
+
result TEXT,
|
|
26
|
+
error TEXT,
|
|
27
|
+
created_at INTEGER NOT NULL,
|
|
28
|
+
completed_at INTEGER
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
-- Usage. cost_usd is nullable ON PURPOSE: a model this build has no
|
|
32
|
+
-- published price for records its tokens and leaves the cost unknown,
|
|
33
|
+
-- because a call priced at zero is a monthly cap that can never trip.
|
|
34
|
+
-- The schema lives here rather than in usage.ts so that opening the
|
|
35
|
+
-- database does not have to import the module that writes to it.
|
|
36
|
+
CREATE TABLE IF NOT EXISTS ai_usage (
|
|
37
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
38
|
+
at INTEGER NOT NULL,
|
|
39
|
+
kind TEXT NOT NULL,
|
|
40
|
+
model TEXT NOT NULL,
|
|
41
|
+
source TEXT NOT NULL,
|
|
42
|
+
input_tokens INTEGER NOT NULL,
|
|
43
|
+
output_tokens INTEGER NOT NULL,
|
|
44
|
+
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
|
|
45
|
+
cache_write_tokens INTEGER NOT NULL DEFAULT 0,
|
|
46
|
+
cost_usd REAL
|
|
47
|
+
);
|
|
48
|
+
CREATE INDEX IF NOT EXISTS ai_usage_at ON ai_usage(at);
|
|
49
|
+
|
|
50
|
+
CREATE TABLE IF NOT EXISTS feature_usage (
|
|
51
|
+
name TEXT NOT NULL,
|
|
52
|
+
day TEXT NOT NULL,
|
|
53
|
+
count INTEGER NOT NULL,
|
|
54
|
+
PRIMARY KEY (name, day)
|
|
55
|
+
);
|
|
56
|
+
`;
|
|
57
|
+
function getDb() {
|
|
58
|
+
if (_db)
|
|
59
|
+
return _db;
|
|
60
|
+
fs.mkdirSync(path.dirname(DB_PATH), { recursive: true });
|
|
61
|
+
_db = new Database(DB_PATH);
|
|
62
|
+
// This database holds the Anthropic API key the dashboard saves, in the clear.
|
|
63
|
+
// better-sqlite3 creates the file, so it never went through writeSecretFile
|
|
64
|
+
// and landed 0644 like any other SQLite file -- readable by every account on
|
|
65
|
+
// the machine, while .env and session.json next to it are 0600.
|
|
66
|
+
restrictExistingFile(DB_PATH);
|
|
67
|
+
_db.exec(APP_DB_SCHEMA);
|
|
68
|
+
// Reconciling used to happen here, which meant every process that opened this
|
|
69
|
+
// file reclaimed every other process's in-flight work. See
|
|
70
|
+
// reconcileStalePromptJobs.
|
|
71
|
+
prunePromptJobs(_db);
|
|
72
|
+
return _db;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The open handle, for modules that own their own tables.
|
|
76
|
+
*
|
|
77
|
+
* `usage.ts` needs to read and write two tables of its own; routing that
|
|
78
|
+
* through a per-statement wrapper here would put its SQL in a file that has
|
|
79
|
+
* nothing to do with metering. The connection stays owned in one place -- this
|
|
80
|
+
* hands out the handle, not a second one.
|
|
81
|
+
*/
|
|
82
|
+
export function getAppDb() {
|
|
83
|
+
return getDb();
|
|
84
|
+
}
|
|
85
|
+
// Settings
|
|
86
|
+
export function getSetting(key) {
|
|
87
|
+
const row = getDb().prepare("SELECT value FROM settings WHERE key = ?").get(key);
|
|
88
|
+
return row?.value ?? null;
|
|
89
|
+
}
|
|
90
|
+
export function setSetting(key, value) {
|
|
91
|
+
getDb()
|
|
92
|
+
.prepare("INSERT INTO settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value")
|
|
93
|
+
.run(key, value);
|
|
94
|
+
}
|
|
95
|
+
export function deleteSetting(key) {
|
|
96
|
+
getDb().prepare("DELETE FROM settings WHERE key = ?").run(key);
|
|
97
|
+
}
|
|
98
|
+
/** Setting keys starting with `prefix`, used to prune dated cache entries. */
|
|
99
|
+
export function listSettingKeys(prefix) {
|
|
100
|
+
const rows = getDb()
|
|
101
|
+
.prepare("SELECT key FROM settings WHERE key LIKE ?")
|
|
102
|
+
.all(`${prefix}%`);
|
|
103
|
+
return rows.map((row) => row.key);
|
|
104
|
+
}
|
|
105
|
+
// Pair tokens
|
|
106
|
+
const PAIR_TOKEN_TTL_SECONDS = 5 * 60;
|
|
107
|
+
/**
|
|
108
|
+
* A pair code is a bearer credential in disguise: /api/pair is unauthenticated
|
|
109
|
+
* by design, and /api/pair/<code>/status hands out the API key as soon as that
|
|
110
|
+
* code is approved. Math.random() was the source here, which means an attacker
|
|
111
|
+
* who mints a handful of codes from the open endpoint can recover the PRNG
|
|
112
|
+
* state and predict the code the real watch is displaying. randomInt draws from
|
|
113
|
+
* the CSPRNG, uniformly and without modulo bias, and zero-padding keeps the
|
|
114
|
+
* full six-digit space (including 000042) in play.
|
|
115
|
+
*/
|
|
116
|
+
export function generatePairCode() {
|
|
117
|
+
return randomInt(0, 1_000_000).toString().padStart(6, "0");
|
|
118
|
+
}
|
|
119
|
+
export function createPairToken() {
|
|
120
|
+
const db = getDb();
|
|
121
|
+
const now = Math.floor(Date.now() / 1000);
|
|
122
|
+
const expiresAt = now + PAIR_TOKEN_TTL_SECONDS;
|
|
123
|
+
// Clean expired tokens
|
|
124
|
+
db.prepare("DELETE FROM pair_tokens WHERE expires_at < ?").run(now);
|
|
125
|
+
let code = generatePairCode();
|
|
126
|
+
let attempts = 0;
|
|
127
|
+
while (attempts < 10) {
|
|
128
|
+
const existing = db.prepare("SELECT code FROM pair_tokens WHERE code = ?").get(code);
|
|
129
|
+
if (!existing)
|
|
130
|
+
break;
|
|
131
|
+
code = generatePairCode();
|
|
132
|
+
attempts++;
|
|
133
|
+
}
|
|
134
|
+
const token = { code, created_at: now, expires_at: expiresAt, approved_at: null };
|
|
135
|
+
db.prepare("INSERT INTO pair_tokens (code, created_at, expires_at, approved_at) VALUES (?, ?, ?, NULL)")
|
|
136
|
+
.run(code, now, expiresAt);
|
|
137
|
+
return token;
|
|
138
|
+
}
|
|
139
|
+
export function getPairToken(code) {
|
|
140
|
+
const row = getDb()
|
|
141
|
+
.prepare("SELECT code, created_at, expires_at, approved_at FROM pair_tokens WHERE code = ?")
|
|
142
|
+
.get(code);
|
|
143
|
+
return row ?? null;
|
|
144
|
+
}
|
|
145
|
+
export function approvePairToken(code) {
|
|
146
|
+
const now = Math.floor(Date.now() / 1000);
|
|
147
|
+
const token = getPairToken(code);
|
|
148
|
+
if (!token || token.expires_at < now)
|
|
149
|
+
return false;
|
|
150
|
+
getDb()
|
|
151
|
+
.prepare("UPDATE pair_tokens SET approved_at = ? WHERE code = ?")
|
|
152
|
+
.run(now, code);
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
export function deletePairToken(code) {
|
|
156
|
+
getDb().prepare("DELETE FROM pair_tokens WHERE code = ?").run(code);
|
|
157
|
+
}
|
|
158
|
+
export function listPendingPairTokens() {
|
|
159
|
+
const now = Math.floor(Date.now() / 1000);
|
|
160
|
+
return getDb()
|
|
161
|
+
.prepare("SELECT code, created_at, expires_at, approved_at FROM pair_tokens WHERE expires_at > ? AND approved_at IS NULL ORDER BY created_at DESC")
|
|
162
|
+
.all(now);
|
|
163
|
+
}
|
|
164
|
+
// Prompt jobs
|
|
165
|
+
/** Kept long enough to answer "what did it say earlier today", not forever. */
|
|
166
|
+
const PROMPT_JOB_TTL_SECONDS = 7 * 24 * 60 * 60;
|
|
167
|
+
/**
|
|
168
|
+
* How old an unfinished job has to be before it counts as wreckage.
|
|
169
|
+
*
|
|
170
|
+
* The watch polls a job id for about thirty seconds and then gives up, so
|
|
171
|
+
* anything younger than that is, or was until moments ago, an answer somebody
|
|
172
|
+
* is waiting for. Five minutes leaves room for a slow model call as well.
|
|
173
|
+
*/
|
|
174
|
+
export const STALE_PROMPT_JOB_SECONDS = 5 * 60;
|
|
175
|
+
/**
|
|
176
|
+
* A job the process died in the middle of is not still running.
|
|
177
|
+
*
|
|
178
|
+
* THIS USED TO RUN INSIDE `getDb()`, so the first time ANY process opened
|
|
179
|
+
* app.db it flipped every pending and running row to
|
|
180
|
+
* "The server stopped before this answer came back." -- including the rows
|
|
181
|
+
* belonging to a `serve` that was, at that moment, waiting on Anthropic. Every
|
|
182
|
+
* entry point opens this file, so asking a question on the watch and then
|
|
183
|
+
* running `trainbud doctor`, `status`, `findings` or a backfill killed the live
|
|
184
|
+
* answer from another process, and the watch drew "AI unavailable".
|
|
185
|
+
*
|
|
186
|
+
* Two changes, and both are needed. It is called once, from `serve` at startup,
|
|
187
|
+
* so a CLI command no longer writes to a server's table at all. And it will not
|
|
188
|
+
* touch a job younger than STALE_PROMPT_JOB_SECONDS, which is what protects a
|
|
189
|
+
* second server on the same box, and a restart racing an answer that is still
|
|
190
|
+
* in flight.
|
|
191
|
+
*/
|
|
192
|
+
export function reconcileStalePromptJobs(db, now = Math.floor(Date.now() / 1000)) {
|
|
193
|
+
db.prepare(`UPDATE prompt_jobs
|
|
194
|
+
SET status = 'error',
|
|
195
|
+
error = 'The server stopped before this answer came back.',
|
|
196
|
+
completed_at = ?
|
|
197
|
+
WHERE status IN ('pending', 'running')
|
|
198
|
+
AND created_at < ?`).run(now, now - STALE_PROMPT_JOB_SECONDS);
|
|
199
|
+
prunePromptJobs(db, now);
|
|
200
|
+
}
|
|
201
|
+
/** Drop rows past the retention window. Safe from any process. */
|
|
202
|
+
function prunePromptJobs(db, now = Math.floor(Date.now() / 1000)) {
|
|
203
|
+
db.prepare("DELETE FROM prompt_jobs WHERE created_at < ?").run(now - PROMPT_JOB_TTL_SECONDS);
|
|
204
|
+
}
|
|
205
|
+
/** Called once by `serve`, which is the only process that owns these jobs. */
|
|
206
|
+
export function reconcilePromptJobsOnStartup() {
|
|
207
|
+
reconcileStalePromptJobs(getDb());
|
|
208
|
+
}
|
|
209
|
+
export function createPromptJob(id, prompt) {
|
|
210
|
+
const now = Math.floor(Date.now() / 1000);
|
|
211
|
+
const job = { id, prompt, status: "pending", result: null, error: null, created_at: now, completed_at: null };
|
|
212
|
+
const db = getDb();
|
|
213
|
+
// Prune on write rather than on a timer: this table only grows when a job is
|
|
214
|
+
// created, so this is the one place that needs to care, and it costs a single
|
|
215
|
+
// indexed delete on a table with a handful of rows.
|
|
216
|
+
db.prepare("DELETE FROM prompt_jobs WHERE created_at < ?").run(now - PROMPT_JOB_TTL_SECONDS);
|
|
217
|
+
db.prepare("INSERT INTO prompt_jobs (id, prompt, status, result, error, created_at, completed_at) VALUES (?, ?, 'pending', NULL, NULL, ?, NULL)")
|
|
218
|
+
.run(id, prompt, now);
|
|
219
|
+
return job;
|
|
220
|
+
}
|
|
221
|
+
export function getPromptJob(id) {
|
|
222
|
+
const row = getDb()
|
|
223
|
+
.prepare("SELECT id, prompt, status, result, error, created_at, completed_at FROM prompt_jobs WHERE id = ?")
|
|
224
|
+
.get(id);
|
|
225
|
+
return row ?? null;
|
|
226
|
+
}
|
|
227
|
+
export function updatePromptJob(id, update) {
|
|
228
|
+
const now = Math.floor(Date.now() / 1000);
|
|
229
|
+
getDb()
|
|
230
|
+
.prepare("UPDATE prompt_jobs SET status = ?, result = ?, error = ?, completed_at = ? WHERE id = ?")
|
|
231
|
+
.run(update.status, update.result ?? null, update.error ?? null, update.status === "done" || update.status === "error" ? now : null, id);
|
|
232
|
+
}
|
|
233
|
+
export function closeAppDb() {
|
|
234
|
+
if (_db) {
|
|
235
|
+
_db.close();
|
|
236
|
+
_db = null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=appDb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appDb.js","sourceRoot":"","sources":["../src/appDb.ts"],"names":[],"mappings":"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"}
|
package/dist/check.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ToolCheckResult {
|
|
2
|
+
name: string;
|
|
3
|
+
ok: boolean;
|
|
4
|
+
summary: string;
|
|
5
|
+
/** Non-fatal findings are reported but do not fail the command. */
|
|
6
|
+
warning?: boolean;
|
|
7
|
+
section?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function checkSetup(): ToolCheckResult[];
|
|
10
|
+
export declare function runLiveCheck(): Promise<ToolCheckResult[]>;
|
|
11
|
+
export declare function printLiveCheckResults(results: ToolCheckResult[]): void;
|
|
12
|
+
//# sourceMappingURL=check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAWD,wBAAgB,UAAU,IAAI,eAAe,EAAE,CAsE9C;AAkJD,wBAAsB,YAAY,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAqB/D;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI,CAsCtE"}
|
package/dist/check.js
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { DateTime } from "luxon";
|
|
3
|
+
import { assertGarminCredentials, appConfig, deprecatedEnvNames, getEnvFilePath } from "./config.js";
|
|
4
|
+
import { executeTool, listRegisteredToolNames } from "./tools/index.js";
|
|
5
|
+
import { configureLogger } from "./utils/logger.js";
|
|
6
|
+
import { getDataDir, getLegacyDataDir } from "./paths.js";
|
|
7
|
+
import { isAiConfigured } from "./promptApi.js";
|
|
8
|
+
// -----------------------------------------------------------------------------
|
|
9
|
+
// Setup checks
|
|
10
|
+
//
|
|
11
|
+
// The tool checks below only prove the Connect API works. They say nothing about
|
|
12
|
+
// the parts that actually strand people: no API key, no public URL, state left
|
|
13
|
+
// in the pre-rename directory. Those are checked first so `trainbud check`
|
|
14
|
+
// diagnoses the whole stack rather than one layer of it.
|
|
15
|
+
// -----------------------------------------------------------------------------
|
|
16
|
+
export function checkSetup() {
|
|
17
|
+
const results = [];
|
|
18
|
+
const add = (name, ok, summary, warning = false) => {
|
|
19
|
+
results.push({ name, ok, summary, warning, section: "Setup" });
|
|
20
|
+
};
|
|
21
|
+
const envPath = getEnvFilePath();
|
|
22
|
+
add(".env file", fs.existsSync(envPath), fs.existsSync(envPath) ? envPath : `missing — run "trainbud setup"`);
|
|
23
|
+
const hasCredentials = !!appConfig.garminEmail && !!appConfig.garminPassword;
|
|
24
|
+
add("Connect credentials", hasCredentials, hasCredentials ? appConfig.garminEmail : "GARMIN_EMAIL / GARMIN_PASSWORD not set");
|
|
25
|
+
const hasApiKey = appConfig.mcpApiKey.length > 0;
|
|
26
|
+
add("API key", hasApiKey, hasApiKey ? `set (${appConfig.mcpApiKey.length} chars)` : `TRAINBUD_API_KEY not set — run "trainbud setup"`);
|
|
27
|
+
const dataDir = getDataDir();
|
|
28
|
+
let writable;
|
|
29
|
+
try {
|
|
30
|
+
fs.mkdirSync(dataDir, { recursive: true });
|
|
31
|
+
fs.accessSync(dataDir, fs.constants.W_OK);
|
|
32
|
+
writable = true;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
writable = false;
|
|
36
|
+
}
|
|
37
|
+
add("Data directory", writable, writable ? dataDir : `not writable: ${dataDir}`);
|
|
38
|
+
const legacyDir = getLegacyDataDir();
|
|
39
|
+
const legacyPresent = fs.existsSync(legacyDir);
|
|
40
|
+
add("Legacy directory", true, legacyPresent
|
|
41
|
+
? `${legacyDir} still present — safe to delete once everything works`
|
|
42
|
+
: "none", legacyPresent);
|
|
43
|
+
const deprecated = deprecatedEnvNames();
|
|
44
|
+
add("Env var names", true, deprecated.length > 0 ? `using old names: ${deprecated.join(", ")}` : "current", deprecated.length > 0);
|
|
45
|
+
const publicUrl = appConfig.publicUrl;
|
|
46
|
+
add("Public URL", true, publicUrl.length > 0 ? publicUrl : "not set — the watch cannot reach this server without it", publicUrl.length === 0);
|
|
47
|
+
// isAiConfigured(), not appConfig.anthropicApiKey. The dashboard writes the
|
|
48
|
+
// key to the settings table, which is the route the setup guide tells users
|
|
49
|
+
// to take, and reading the environment alone reported every one of those keys
|
|
50
|
+
// as missing. resolveAnthropicKey() was written for exactly this and this
|
|
51
|
+
// call site never used it.
|
|
52
|
+
const aiKey = isAiConfigured();
|
|
53
|
+
add("AI features", true, aiKey ? "key present" : "no key — AI cards stay empty (optional)", !aiKey);
|
|
54
|
+
return results;
|
|
55
|
+
}
|
|
56
|
+
function buildDefaultToolChecks() {
|
|
57
|
+
const endDate = DateTime.now().toISODate();
|
|
58
|
+
const startDate = DateTime.now().minus({ days: 30 }).toISODate();
|
|
59
|
+
return [
|
|
60
|
+
{ name: "get_latest_activity", args: {} },
|
|
61
|
+
{
|
|
62
|
+
name: "get_activities_range",
|
|
63
|
+
args: {
|
|
64
|
+
start_date: startDate,
|
|
65
|
+
end_date: endDate,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{ name: "get_sleep_data", args: { nights: 7 } },
|
|
69
|
+
{ name: "get_heart_rate_trends", args: { days: 30 } },
|
|
70
|
+
{ name: "get_recovery_status", args: {} },
|
|
71
|
+
{ name: "get_body_composition", args: { days: 30 } },
|
|
72
|
+
{ name: "get_stress_levels", args: { days: 7 } },
|
|
73
|
+
{ name: "get_vo2_max_trends", args: { days: 30 } },
|
|
74
|
+
{ name: "get_training_insights", args: { days: 7 } },
|
|
75
|
+
];
|
|
76
|
+
}
|
|
77
|
+
function summarizeToolResult(name, text) {
|
|
78
|
+
const normalized = text.trim();
|
|
79
|
+
const noDataPattern = /^No .+ found/i;
|
|
80
|
+
// "No VO2 max data found" means the watch does not record that metric, not
|
|
81
|
+
// that the tool is broken. Reporting it as a failure made `check` exit 1 for a
|
|
82
|
+
// perfectly healthy setup, so it is advisory instead.
|
|
83
|
+
if (noDataPattern.test(normalized)) {
|
|
84
|
+
return {
|
|
85
|
+
ok: true,
|
|
86
|
+
warning: true,
|
|
87
|
+
summary: `${normalized.split("\n")[0] ?? normalized} (not a fault — this metric is absent)`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (name === "get_latest_activity") {
|
|
91
|
+
const activityLine = normalized.split("\n").find((line) => line.startsWith("Activity:"));
|
|
92
|
+
const dateLine = normalized.split("\n").find((line) => line.startsWith("Date:"));
|
|
93
|
+
const distanceLine = normalized.split("\n").find((line) => line.startsWith("Distance:"));
|
|
94
|
+
const parts = [activityLine, distanceLine, dateLine].filter(Boolean);
|
|
95
|
+
return {
|
|
96
|
+
ok: true,
|
|
97
|
+
summary: parts.length > 0 ? parts.join(", ") : "Latest activity retrieved",
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (name === "get_activities_range") {
|
|
101
|
+
const countMatch = normalized.match(/(\d+) activit/i);
|
|
102
|
+
return {
|
|
103
|
+
ok: true,
|
|
104
|
+
summary: countMatch ? `${countMatch[1]} activities found` : "Activities retrieved",
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (name === "get_sleep_data") {
|
|
108
|
+
const nightsMatch = normalized.match(/(\d+) nights?/i);
|
|
109
|
+
return {
|
|
110
|
+
ok: true,
|
|
111
|
+
summary: nightsMatch ? `${nightsMatch[1]} nights retrieved` : "Sleep data retrieved",
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (name === "get_heart_rate_trends") {
|
|
115
|
+
const daysMatch = normalized.match(/(\d+) days/i);
|
|
116
|
+
return {
|
|
117
|
+
ok: true,
|
|
118
|
+
summary: daysMatch ? `${daysMatch[1]}-day trend loaded` : "Heart rate trends loaded",
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (name === "get_recovery_status") {
|
|
122
|
+
const scoreMatch = normalized.match(/Recovery score:\s*(\d+)/i);
|
|
123
|
+
const recommendationMatch = normalized.match(/Recommendation:\s*(.+)/i);
|
|
124
|
+
if (scoreMatch) {
|
|
125
|
+
const recommendation = recommendationMatch?.[1]?.trim();
|
|
126
|
+
return {
|
|
127
|
+
ok: true,
|
|
128
|
+
summary: recommendation
|
|
129
|
+
? `Score: ${scoreMatch[1]} (${recommendation})`
|
|
130
|
+
: `Score: ${scoreMatch[1]}`,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return { ok: true, summary: "Recovery status retrieved" };
|
|
134
|
+
}
|
|
135
|
+
if (name === "get_body_composition") {
|
|
136
|
+
const daysMatch = normalized.match(/(\d+) recorded days/i);
|
|
137
|
+
return {
|
|
138
|
+
ok: true,
|
|
139
|
+
summary: daysMatch ? `${daysMatch[1]} recorded days` : "Body composition retrieved",
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (name === "get_stress_levels") {
|
|
143
|
+
const daysMatch = normalized.match(/(\d+) recorded days/i);
|
|
144
|
+
return {
|
|
145
|
+
ok: true,
|
|
146
|
+
summary: daysMatch ? `${daysMatch[1]} stress days loaded` : "Stress data retrieved",
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
if (name === "get_vo2_max_trends") {
|
|
150
|
+
const daysMatch = normalized.match(/(\d+) recorded days/i);
|
|
151
|
+
return {
|
|
152
|
+
ok: true,
|
|
153
|
+
summary: daysMatch ? `${daysMatch[1]} VO2 entries loaded` : "VO2 max trends loaded",
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (name === "get_training_insights") {
|
|
157
|
+
return {
|
|
158
|
+
ok: true,
|
|
159
|
+
summary: "Training insights summary generated",
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
const firstLine = normalized.split("\n")[0] ?? normalized;
|
|
163
|
+
return {
|
|
164
|
+
ok: true,
|
|
165
|
+
summary: firstLine.length > 72 ? `${firstLine.slice(0, 69)}...` : firstLine,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
async function runToolCheck(check) {
|
|
169
|
+
try {
|
|
170
|
+
const result = await executeTool(check.name, check.args);
|
|
171
|
+
const { ok, summary, warning } = summarizeToolResult(check.name, result.text);
|
|
172
|
+
return { name: check.name, ok, summary, warning };
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
176
|
+
return {
|
|
177
|
+
name: check.name,
|
|
178
|
+
ok: false,
|
|
179
|
+
summary: message,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
export async function runLiveCheck() {
|
|
184
|
+
const results = checkSetup();
|
|
185
|
+
// Without credentials the tool checks can only fail, and their errors would
|
|
186
|
+
// bury the setup finding that actually explains why.
|
|
187
|
+
if (!appConfig.garminEmail || !appConfig.garminPassword) {
|
|
188
|
+
return results;
|
|
189
|
+
}
|
|
190
|
+
assertGarminCredentials();
|
|
191
|
+
configureLogger(appConfig.logPath);
|
|
192
|
+
const registered = new Set(listRegisteredToolNames());
|
|
193
|
+
const checks = buildDefaultToolChecks().filter((check) => registered.has(check.name));
|
|
194
|
+
for (const check of checks) {
|
|
195
|
+
const result = await runToolCheck(check);
|
|
196
|
+
results.push({ ...result, section: "Tools" });
|
|
197
|
+
}
|
|
198
|
+
return results;
|
|
199
|
+
}
|
|
200
|
+
export function printLiveCheckResults(results) {
|
|
201
|
+
console.log("TrainBud check");
|
|
202
|
+
let currentSection = "";
|
|
203
|
+
for (const result of results) {
|
|
204
|
+
const section = result.section ?? "Checks";
|
|
205
|
+
if (section !== currentSection) {
|
|
206
|
+
console.log("");
|
|
207
|
+
console.log(`${section}`);
|
|
208
|
+
currentSection = section;
|
|
209
|
+
}
|
|
210
|
+
const icon = !result.ok ? "✗" : result.warning ? "!" : "✓";
|
|
211
|
+
console.log(` ${result.name.padEnd(26, " ")}${icon} ${result.summary}`);
|
|
212
|
+
}
|
|
213
|
+
console.log("");
|
|
214
|
+
const failed = results.filter((result) => !result.ok);
|
|
215
|
+
const warned = results.filter((result) => result.ok && result.warning);
|
|
216
|
+
const total = results.length;
|
|
217
|
+
if (failed.length === 0 && warned.length === 0) {
|
|
218
|
+
console.log(`All ${total} checks passed. TrainBud is ready to use.`);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (failed.length === 0) {
|
|
222
|
+
console.log(`${total - warned.length}/${total} clean, ${warned.length} advisory (!). Nothing is broken — the notes above are optional setup.`);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
console.log(`${total - failed.length}/${total} passed, ${failed.length} failed (✗). Fix those first:`);
|
|
226
|
+
for (const result of failed) {
|
|
227
|
+
console.log(` - ${result.name}: ${result.summary}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AA2V1D,wBAAgB,gBAAgB,IAAI,OAAO,CAqN1C"}
|