skill-calorie 0.1.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/dist/analysis/anomaly/common.d.ts +53 -0
- package/dist/analysis/anomaly/common.d.ts.map +1 -0
- package/dist/analysis/anomaly/common.js +69 -0
- package/dist/analysis/anomaly/common.js.map +1 -0
- package/dist/analysis/anomaly/diet.d.ts +8 -0
- package/dist/analysis/anomaly/diet.d.ts.map +1 -0
- package/dist/analysis/anomaly/diet.js +95 -0
- package/dist/analysis/anomaly/diet.js.map +1 -0
- package/dist/analysis/anomaly/exercise.d.ts +9 -0
- package/dist/analysis/anomaly/exercise.d.ts.map +1 -0
- package/dist/analysis/anomaly/exercise.js +116 -0
- package/dist/analysis/anomaly/exercise.js.map +1 -0
- package/dist/analysis/anomaly/index.d.ts +19 -0
- package/dist/analysis/anomaly/index.d.ts.map +1 -0
- package/dist/analysis/anomaly/index.js +51 -0
- package/dist/analysis/anomaly/index.js.map +1 -0
- package/dist/analysis/anomaly/overall.d.ts +13 -0
- package/dist/analysis/anomaly/overall.d.ts.map +1 -0
- package/dist/analysis/anomaly/overall.js +128 -0
- package/dist/analysis/anomaly/overall.js.map +1 -0
- package/dist/analysis/anomaly/overall2.d.ts +5 -0
- package/dist/analysis/anomaly/overall2.d.ts.map +1 -0
- package/dist/analysis/anomaly/overall2.js +94 -0
- package/dist/analysis/anomaly/overall2.js.map +1 -0
- package/dist/analysis/anomaly/weight.d.ts +8 -0
- package/dist/analysis/anomaly/weight.d.ts.map +1 -0
- package/dist/analysis/anomaly/weight.js +106 -0
- package/dist/analysis/anomaly/weight.js.map +1 -0
- package/dist/analysis/anomaly/weight2.d.ts +4 -0
- package/dist/analysis/anomaly/weight2.d.ts.map +1 -0
- package/dist/analysis/anomaly/weight2.js +59 -0
- package/dist/analysis/anomaly/weight2.js.map +1 -0
- package/dist/analysis/contraindications.d.ts +63 -0
- package/dist/analysis/contraindications.d.ts.map +1 -0
- package/dist/analysis/contraindications.js +121 -0
- package/dist/analysis/contraindications.js.map +1 -0
- package/dist/analysis/cross.d.ts +75 -0
- package/dist/analysis/cross.d.ts.map +1 -0
- package/dist/analysis/cross.js +283 -0
- package/dist/analysis/cross.js.map +1 -0
- package/dist/analysis/dashboard.d.ts +18 -0
- package/dist/analysis/dashboard.d.ts.map +1 -0
- package/dist/analysis/dashboard.js +48 -0
- package/dist/analysis/dashboard.js.map +1 -0
- package/dist/analysis/deficit.d.ts +44 -0
- package/dist/analysis/deficit.d.ts.map +1 -0
- package/dist/analysis/deficit.js +54 -0
- package/dist/analysis/deficit.js.map +1 -0
- package/dist/analysis/diet.d.ts +76 -0
- package/dist/analysis/diet.d.ts.map +1 -0
- package/dist/analysis/diet.js +164 -0
- package/dist/analysis/diet.js.map +1 -0
- package/dist/analysis/exercise.d.ts +98 -0
- package/dist/analysis/exercise.d.ts.map +1 -0
- package/dist/analysis/exercise.js +298 -0
- package/dist/analysis/exercise.js.map +1 -0
- package/dist/analysis/exerciseReview.d.ts +36 -0
- package/dist/analysis/exerciseReview.d.ts.map +1 -0
- package/dist/analysis/exerciseReview.js +50 -0
- package/dist/analysis/exerciseReview.js.map +1 -0
- package/dist/analysis/precision.d.ts +15 -0
- package/dist/analysis/precision.d.ts.map +1 -0
- package/dist/analysis/precision.js +38 -0
- package/dist/analysis/precision.js.map +1 -0
- package/dist/analysis/result.d.ts +15 -0
- package/dist/analysis/result.d.ts.map +1 -0
- package/dist/analysis/result.js +13 -0
- package/dist/analysis/result.js.map +1 -0
- package/dist/analysis/review.d.ts +118 -0
- package/dist/analysis/review.d.ts.map +1 -0
- package/dist/analysis/review.js +195 -0
- package/dist/analysis/review.js.map +1 -0
- package/dist/analysis/series.d.ts +42 -0
- package/dist/analysis/series.d.ts.map +1 -0
- package/dist/analysis/series.js +127 -0
- package/dist/analysis/series.js.map +1 -0
- package/dist/analysis/simulate.d.ts +43 -0
- package/dist/analysis/simulate.d.ts.map +1 -0
- package/dist/analysis/simulate.js +109 -0
- package/dist/analysis/simulate.js.map +1 -0
- package/dist/analysis/simulate2.d.ts +65 -0
- package/dist/analysis/simulate2.d.ts.map +1 -0
- package/dist/analysis/simulate2.js +173 -0
- package/dist/analysis/simulate2.js.map +1 -0
- package/dist/analysis/trend.d.ts +39 -0
- package/dist/analysis/trend.d.ts.map +1 -0
- package/dist/analysis/trend.js +48 -0
- package/dist/analysis/trend.js.map +1 -0
- package/dist/analysis/utils.d.ts +17 -0
- package/dist/analysis/utils.d.ts.map +1 -0
- package/dist/analysis/utils.js +52 -0
- package/dist/analysis/utils.js.map +1 -0
- package/dist/analysis/volatility.d.ts +43 -0
- package/dist/analysis/volatility.d.ts.map +1 -0
- package/dist/analysis/volatility.js +96 -0
- package/dist/analysis/volatility.js.map +1 -0
- package/dist/analysis/weight.d.ts +86 -0
- package/dist/analysis/weight.d.ts.map +1 -0
- package/dist/analysis/weight.js +219 -0
- package/dist/analysis/weight.js.map +1 -0
- package/dist/analysis/weightCompare.d.ts +63 -0
- package/dist/analysis/weightCompare.d.ts.map +1 -0
- package/dist/analysis/weightCompare.js +212 -0
- package/dist/analysis/weightCompare.js.map +1 -0
- package/dist/analysis/weightCompare2.d.ts +63 -0
- package/dist/analysis/weightCompare2.d.ts.map +1 -0
- package/dist/analysis/weightCompare2.js +211 -0
- package/dist/analysis/weightCompare2.js.map +1 -0
- package/dist/analysis/weightCompare3.d.ts +13 -0
- package/dist/analysis/weightCompare3.d.ts.map +1 -0
- package/dist/analysis/weightCompare3.js +199 -0
- package/dist/analysis/weightCompare3.js.map +1 -0
- package/dist/cli/cmd_read.d.ts +8 -0
- package/dist/cli/cmd_read.d.ts.map +1 -0
- package/dist/cli/cmd_read.js +719 -0
- package/dist/cli/cmd_read.js.map +1 -0
- package/dist/cli/keys.d.ts +333 -0
- package/dist/cli/keys.d.ts.map +1 -0
- package/dist/cli/keys.js +103 -0
- package/dist/cli/keys.js.map +1 -0
- package/dist/cli/write.d.ts +24 -0
- package/dist/cli/write.d.ts.map +1 -0
- package/dist/cli/write.js +832 -0
- package/dist/cli/write.js.map +1 -0
- package/dist/fetch/audit.d.ts +25 -0
- package/dist/fetch/audit.d.ts.map +1 -0
- package/dist/fetch/audit.js +46 -0
- package/dist/fetch/audit.js.map +1 -0
- package/dist/fetch/batch.d.ts +68 -0
- package/dist/fetch/batch.d.ts.map +1 -0
- package/dist/fetch/batch.js +183 -0
- package/dist/fetch/batch.js.map +1 -0
- package/dist/fetch/body.d.ts +89 -0
- package/dist/fetch/body.d.ts.map +1 -0
- package/dist/fetch/body.js +217 -0
- package/dist/fetch/body.js.map +1 -0
- package/dist/fetch/cli.d.ts +3 -0
- package/dist/fetch/cli.d.ts.map +1 -0
- package/dist/fetch/cli.js +195 -0
- package/dist/fetch/cli.js.map +1 -0
- package/dist/fetch/cross-skill.d.ts +29 -0
- package/dist/fetch/cross-skill.d.ts.map +1 -0
- package/dist/fetch/cross-skill.js +42 -0
- package/dist/fetch/cross-skill.js.map +1 -0
- package/dist/fetch/db.d.ts +5 -0
- package/dist/fetch/db.d.ts.map +1 -0
- package/dist/fetch/db.js +4 -0
- package/dist/fetch/db.js.map +1 -0
- package/dist/fetch/diet.d.ts +174 -0
- package/dist/fetch/diet.d.ts.map +1 -0
- package/dist/fetch/diet.js +239 -0
- package/dist/fetch/diet.js.map +1 -0
- package/dist/fetch/errors.d.ts +5 -0
- package/dist/fetch/errors.d.ts.map +1 -0
- package/dist/fetch/errors.js +8 -0
- package/dist/fetch/errors.js.map +1 -0
- package/dist/fetch/exercise.d.ts +72 -0
- package/dist/fetch/exercise.d.ts.map +1 -0
- package/dist/fetch/exercise.js +270 -0
- package/dist/fetch/exercise.js.map +1 -0
- package/dist/fetch/goal.d.ts +48 -0
- package/dist/fetch/goal.d.ts.map +1 -0
- package/dist/fetch/goal.js +73 -0
- package/dist/fetch/goal.js.map +1 -0
- package/dist/fetch/goalHistory.d.ts +24 -0
- package/dist/fetch/goalHistory.d.ts.map +1 -0
- package/dist/fetch/goalHistory.js +51 -0
- package/dist/fetch/goalHistory.js.map +1 -0
- package/dist/fetch/history.d.ts +28 -0
- package/dist/fetch/history.d.ts.map +1 -0
- package/dist/fetch/history.js +29 -0
- package/dist/fetch/history.js.map +1 -0
- package/dist/fetch/index.d.ts +23 -0
- package/dist/fetch/index.d.ts.map +1 -0
- package/dist/fetch/index.js +16 -0
- package/dist/fetch/index.js.map +1 -0
- package/dist/fetch/nutritionGoal.d.ts +115 -0
- package/dist/fetch/nutritionGoal.d.ts.map +1 -0
- package/dist/fetch/nutritionGoal.js +154 -0
- package/dist/fetch/nutritionGoal.js.map +1 -0
- package/dist/fetch/photos.d.ts +76 -0
- package/dist/fetch/photos.d.ts.map +1 -0
- package/dist/fetch/photos.js +193 -0
- package/dist/fetch/photos.js.map +1 -0
- package/dist/fetch/plan.d.ts +145 -0
- package/dist/fetch/plan.d.ts.map +1 -0
- package/dist/fetch/plan.js +258 -0
- package/dist/fetch/plan.js.map +1 -0
- package/dist/fetch/products.d.ts +62 -0
- package/dist/fetch/products.d.ts.map +1 -0
- package/dist/fetch/products.js +73 -0
- package/dist/fetch/products.js.map +1 -0
- package/dist/fetch/profile.d.ts +46 -0
- package/dist/fetch/profile.d.ts.map +1 -0
- package/dist/fetch/profile.js +105 -0
- package/dist/fetch/profile.js.map +1 -0
- package/dist/fetch/shapes.d.ts +41 -0
- package/dist/fetch/shapes.d.ts.map +1 -0
- package/dist/fetch/shapes.js +38 -0
- package/dist/fetch/shapes.js.map +1 -0
- package/dist/fetch/validate.d.ts +11 -0
- package/dist/fetch/validate.d.ts.map +1 -0
- package/dist/fetch/validate.js +64 -0
- package/dist/fetch/validate.js.map +1 -0
- package/dist/fetch/weight.d.ts +109 -0
- package/dist/fetch/weight.d.ts.map +1 -0
- package/dist/fetch/weight.js +210 -0
- package/dist/fetch/weight.js.map +1 -0
- package/dist/fetch/xunji-catalog.d.ts +17 -0
- package/dist/fetch/xunji-catalog.d.ts.map +1 -0
- package/dist/fetch/xunji-catalog.js +57 -0
- package/dist/fetch/xunji-catalog.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/kcal.d.ts +21 -0
- package/dist/kcal.d.ts.map +1 -0
- package/dist/kcal.js +27 -0
- package/dist/kcal.js.map +1 -0
- package/dist/migrate/migrate.d.ts +71 -0
- package/dist/migrate/migrate.d.ts.map +1 -0
- package/dist/migrate/migrate.js +450 -0
- package/dist/migrate/migrate.js.map +1 -0
- package/dist/paths.d.ts +6 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +34 -0
- package/dist/paths.js.map +1 -0
- package/dist/render/analysisPlate.d.ts +49 -0
- package/dist/render/analysisPlate.d.ts.map +1 -0
- package/dist/render/analysisPlate.js +149 -0
- package/dist/render/analysisPlate.js.map +1 -0
- package/dist/render/bodyPlate.d.ts +55 -0
- package/dist/render/bodyPlate.d.ts.map +1 -0
- package/dist/render/bodyPlate.js +97 -0
- package/dist/render/bodyPlate.js.map +1 -0
- package/dist/render/diet.d.ts +47 -0
- package/dist/render/diet.d.ts.map +1 -0
- package/dist/render/diet.js +94 -0
- package/dist/render/diet.js.map +1 -0
- package/dist/render/envelope.d.ts +60 -0
- package/dist/render/envelope.d.ts.map +1 -0
- package/dist/render/envelope.js +111 -0
- package/dist/render/envelope.js.map +1 -0
- package/dist/render/errors.d.ts +10 -0
- package/dist/render/errors.d.ts.map +1 -0
- package/dist/render/errors.js +9 -0
- package/dist/render/errors.js.map +1 -0
- package/dist/render/exercise.d.ts +20 -0
- package/dist/render/exercise.d.ts.map +1 -0
- package/dist/render/exercise.js +32 -0
- package/dist/render/exercise.js.map +1 -0
- package/dist/render/goal.d.ts +24 -0
- package/dist/render/goal.d.ts.map +1 -0
- package/dist/render/goal.js +23 -0
- package/dist/render/goal.js.map +1 -0
- package/dist/render/goalExtra.d.ts +45 -0
- package/dist/render/goalExtra.d.ts.map +1 -0
- package/dist/render/goalExtra.js +94 -0
- package/dist/render/goalExtra.js.map +1 -0
- package/dist/render/goalPlate.d.ts +66 -0
- package/dist/render/goalPlate.d.ts.map +1 -0
- package/dist/render/goalPlate.js +110 -0
- package/dist/render/goalPlate.js.map +1 -0
- package/dist/render/health.d.ts +21 -0
- package/dist/render/health.d.ts.map +1 -0
- package/dist/render/health.js +41 -0
- package/dist/render/health.js.map +1 -0
- package/dist/render/help.d.ts +18 -0
- package/dist/render/help.d.ts.map +1 -0
- package/dist/render/help.js +58 -0
- package/dist/render/help.js.map +1 -0
- package/dist/render/home.d.ts +30 -0
- package/dist/render/home.d.ts.map +1 -0
- package/dist/render/home.js +73 -0
- package/dist/render/home.js.map +1 -0
- package/dist/render/html.d.ts +66 -0
- package/dist/render/html.d.ts.map +1 -0
- package/dist/render/html.js +510 -0
- package/dist/render/html.js.map +1 -0
- package/dist/render/index.d.ts +47 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +26 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/insightPlate.d.ts +55 -0
- package/dist/render/insightPlate.d.ts.map +1 -0
- package/dist/render/insightPlate.js +97 -0
- package/dist/render/insightPlate.js.map +1 -0
- package/dist/render/library.d.ts +32 -0
- package/dist/render/library.d.ts.map +1 -0
- package/dist/render/library.js +54 -0
- package/dist/render/library.js.map +1 -0
- package/dist/render/photo.d.ts +101 -0
- package/dist/render/photo.d.ts.map +1 -0
- package/dist/render/photo.js +241 -0
- package/dist/render/photo.js.map +1 -0
- package/dist/render/planPlate.d.ts +40 -0
- package/dist/render/planPlate.d.ts.map +1 -0
- package/dist/render/planPlate.js +72 -0
- package/dist/render/planPlate.js.map +1 -0
- package/dist/render/profilePlate.d.ts +17 -0
- package/dist/render/profilePlate.d.ts.map +1 -0
- package/dist/render/profilePlate.js +18 -0
- package/dist/render/profilePlate.js.map +1 -0
- package/dist/render/ranking.d.ts +22 -0
- package/dist/render/ranking.d.ts.map +1 -0
- package/dist/render/ranking.js +63 -0
- package/dist/render/ranking.js.map +1 -0
- package/dist/render/receipt.d.ts +71 -0
- package/dist/render/receipt.d.ts.map +1 -0
- package/dist/render/receipt.js +65 -0
- package/dist/render/receipt.js.map +1 -0
- package/dist/render/weightPlate.d.ts +54 -0
- package/dist/render/weightPlate.d.ts.map +1 -0
- package/dist/render/weightPlate.js +110 -0
- package/dist/render/weightPlate.js.map +1 -0
- package/dist/schema.d.ts +25 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +281 -0
- package/dist/schema.js.map +1 -0
- package/dist/triggers/help-lookup.d.ts +28 -0
- package/dist/triggers/help-lookup.d.ts.map +1 -0
- package/dist/triggers/help-lookup.js +163 -0
- package/dist/triggers/help-lookup.js.map +1 -0
- package/dist/triggers/index.d.ts +24 -0
- package/dist/triggers/index.d.ts.map +1 -0
- package/dist/triggers/index.js +78 -0
- package/dist/triggers/index.js.map +1 -0
- package/dist/triggers/scene-01-home.d.ts +4 -0
- package/dist/triggers/scene-01-home.d.ts.map +1 -0
- package/dist/triggers/scene-01-home.js +13 -0
- package/dist/triggers/scene-01-home.js.map +1 -0
- package/dist/triggers/scene-02-diet.d.ts +4 -0
- package/dist/triggers/scene-02-diet.d.ts.map +1 -0
- package/dist/triggers/scene-02-diet.js +74 -0
- package/dist/triggers/scene-02-diet.js.map +1 -0
- package/dist/triggers/scene-03-weight.d.ts +4 -0
- package/dist/triggers/scene-03-weight.d.ts.map +1 -0
- package/dist/triggers/scene-03-weight.js +62 -0
- package/dist/triggers/scene-03-weight.js.map +1 -0
- package/dist/triggers/scene-04-exercise.d.ts +4 -0
- package/dist/triggers/scene-04-exercise.d.ts.map +1 -0
- package/dist/triggers/scene-04-exercise.js +43 -0
- package/dist/triggers/scene-04-exercise.js.map +1 -0
- package/dist/triggers/scene-05-workout.d.ts +4 -0
- package/dist/triggers/scene-05-workout.d.ts.map +1 -0
- package/dist/triggers/scene-05-workout.js +36 -0
- package/dist/triggers/scene-05-workout.js.map +1 -0
- package/dist/triggers/scene-06-goal.d.ts +4 -0
- package/dist/triggers/scene-06-goal.d.ts.map +1 -0
- package/dist/triggers/scene-06-goal.js +29 -0
- package/dist/triggers/scene-06-goal.js.map +1 -0
- package/dist/triggers/scene-07-profile.d.ts +4 -0
- package/dist/triggers/scene-07-profile.d.ts.map +1 -0
- package/dist/triggers/scene-07-profile.js +8 -0
- package/dist/triggers/scene-07-profile.js.map +1 -0
- package/dist/triggers/scene-08-body.d.ts +4 -0
- package/dist/triggers/scene-08-body.d.ts.map +1 -0
- package/dist/triggers/scene-08-body.js +17 -0
- package/dist/triggers/scene-08-body.js.map +1 -0
- package/dist/triggers/scene-09-photo.d.ts +4 -0
- package/dist/triggers/scene-09-photo.d.ts.map +1 -0
- package/dist/triggers/scene-09-photo.js +14 -0
- package/dist/triggers/scene-09-photo.js.map +1 -0
- package/dist/triggers/scene-10-analysis.d.ts +4 -0
- package/dist/triggers/scene-10-analysis.d.ts.map +1 -0
- package/dist/triggers/scene-10-analysis.js +180 -0
- package/dist/triggers/scene-10-analysis.js.map +1 -0
- package/dist/triggers/types.d.ts +66 -0
- package/dist/triggers/types.d.ts.map +1 -0
- package/dist/triggers/types.js +3 -0
- package/dist/triggers/types.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** T10 #29 · 通用 CRUD 回执 + 失败回执(对照老家 render_crud_receipt.py / render_error_receipt.py)。
|
|
2
|
+
*
|
|
3
|
+
* 收据只承载“已执行结果”的呈现数据:调用方先调 T4 fetch 写数(addPhotos/deletePhoto/
|
|
4
|
+
* updateTag/tagAdd/tagRemove),再把返回值组装进来,本层不写库、不读二进制。
|
|
5
|
+
* 失败回执对齐老家 build_error:场景/操作/原因/数据文本/建议/修正 prompt。
|
|
6
|
+
*/
|
|
7
|
+
import { CalorieRenderError } from './errors.js';
|
|
8
|
+
function nowStamp() {
|
|
9
|
+
const d = new Date();
|
|
10
|
+
const p = (n) => String(n).padStart(2, '0');
|
|
11
|
+
return d.getFullYear() + '-' + p(d.getMonth() + 1) + '-' + p(d.getDate()) + ' ' + p(d.getHours()) + ':' + p(d.getMinutes()) + ':' + p(d.getSeconds());
|
|
12
|
+
}
|
|
13
|
+
export function buildReceiptMeta(entityType, wakeWord, source) {
|
|
14
|
+
if (!entityType)
|
|
15
|
+
throw new CalorieRenderError('bad-input', 'entityType 必填');
|
|
16
|
+
if (!wakeWord)
|
|
17
|
+
throw new CalorieRenderError('bad-input', 'wakeWord 必填');
|
|
18
|
+
return { actionAt: nowStamp(), entityType, wakeWord, source };
|
|
19
|
+
}
|
|
20
|
+
export function buildCrudReceipt(input) {
|
|
21
|
+
if (!input.scene)
|
|
22
|
+
throw new CalorieRenderError('bad-input', 'scene 必填');
|
|
23
|
+
if (!input.summary)
|
|
24
|
+
throw new CalorieRenderError('bad-input', 'summary 必填(回执无摘要不返空页)');
|
|
25
|
+
if (input.op !== 'create' && input.op !== 'update' && input.op !== 'delete') {
|
|
26
|
+
throw new CalorieRenderError('bad-input', 'op 非法:' + String(input.op));
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
scene: input.scene,
|
|
30
|
+
action: input.action || input.scene,
|
|
31
|
+
op: input.op,
|
|
32
|
+
recordId: input.recordId ?? null,
|
|
33
|
+
summary: input.summary,
|
|
34
|
+
items: input.items ?? [],
|
|
35
|
+
tagDiff: input.tagDiff ?? null,
|
|
36
|
+
distance: input.distance ?? null,
|
|
37
|
+
noChange: input.noChange ?? false,
|
|
38
|
+
meta: buildReceiptMeta(input.scene, input.wakeWord, input.source),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export function buildErrorReceipt(input) {
|
|
42
|
+
const sceneName = input.sceneName || '操作失败';
|
|
43
|
+
let dataText = '—';
|
|
44
|
+
if (input.data !== undefined && input.data !== null) {
|
|
45
|
+
try {
|
|
46
|
+
dataText = typeof input.data === 'string' ? input.data : JSON.stringify(input.data, null, 2);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
dataText = String(input.data);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
sceneName,
|
|
54
|
+
op: input.op || '操作未完成',
|
|
55
|
+
sub: input.sub || '',
|
|
56
|
+
reason: input.reason || '(未知原因)',
|
|
57
|
+
dataText,
|
|
58
|
+
suggestions: input.suggestions && input.suggestions.length > 0
|
|
59
|
+
? [...input.suggestions]
|
|
60
|
+
: ['修正后重试', '更换参数/目标', '联系开发者'],
|
|
61
|
+
fixPrompt: input.fixPrompt || '// 修正 prompt 未生成',
|
|
62
|
+
meta: buildReceiptMeta(sceneName, input.wakeWord || sceneName, '错误回执(写库前校验/执行中失败)'),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=receipt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipt.js","sourceRoot":"","sources":["../../src/render/receipt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** #41 · 体重系读链 render 数据(体重盘/历史/对比/复核/波动 v2)。
|
|
2
|
+
*
|
|
3
|
+
* 数据源全复用既有取数层,不自查 DB 新口径:
|
|
4
|
+
* 盘=analysis/weight.weightTrend + weight.getWeightGoalInfo;
|
|
5
|
+
* 历史=fetch/weight.getWeightHistory(旧 weight-history 同义);
|
|
6
|
+
* 对比=analysis/weight.weightCompare;
|
|
7
|
+
* 复核=analysis/weight.weightMilestone(未设目标/无记录即阻断);
|
|
8
|
+
* 波动 v2=analysis/volatility.weightVolatilityV2(rolling/goal 双基线)。
|
|
9
|
+
* 缺失阻断不返空:空窗/无目标一律 CalorieRenderError missing-data;日期非法 bad-input。
|
|
10
|
+
*/
|
|
11
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
12
|
+
import type { WeightCompare, WeightMilestone, WeightTrend } from '../analysis/weight.js';
|
|
13
|
+
import type { WeightHistory } from '../fetch/weight.js';
|
|
14
|
+
import type { BaselineMode, VolatilityV2 } from '../analysis/volatility.js';
|
|
15
|
+
export interface WeightDashboard {
|
|
16
|
+
start: string;
|
|
17
|
+
end: string;
|
|
18
|
+
trend: WeightTrend;
|
|
19
|
+
weightGoal: number | null;
|
|
20
|
+
deadline: string | null;
|
|
21
|
+
gapKg: number | null;
|
|
22
|
+
}
|
|
23
|
+
export declare function buildWeightDashboard(db: DatabaseSync, start: string, end: string): WeightDashboard;
|
|
24
|
+
export interface WeightHistoryView {
|
|
25
|
+
range: string;
|
|
26
|
+
rows: WeightHistory['rows'];
|
|
27
|
+
change: WeightHistory['change'];
|
|
28
|
+
}
|
|
29
|
+
export declare function buildWeightHistoryView(db: DatabaseSync, opts?: {
|
|
30
|
+
days?: number;
|
|
31
|
+
startDate?: string;
|
|
32
|
+
endDate?: string;
|
|
33
|
+
}): WeightHistoryView;
|
|
34
|
+
export interface WeightCompareView {
|
|
35
|
+
start: string;
|
|
36
|
+
end: string;
|
|
37
|
+
compareStart: string;
|
|
38
|
+
compareEnd: string;
|
|
39
|
+
compare: WeightCompare;
|
|
40
|
+
}
|
|
41
|
+
export declare function buildWeightCompareView(db: DatabaseSync, start: string, end: string, compareStart: string, compareEnd: string): WeightCompareView;
|
|
42
|
+
export interface WeightReviewView {
|
|
43
|
+
today: string;
|
|
44
|
+
milestone: WeightMilestone;
|
|
45
|
+
}
|
|
46
|
+
export declare function buildWeightReviewView(db: DatabaseSync, today?: string): WeightReviewView;
|
|
47
|
+
export interface VolatilityView {
|
|
48
|
+
start: string;
|
|
49
|
+
end: string;
|
|
50
|
+
baselineMode: BaselineMode;
|
|
51
|
+
volatility: VolatilityV2;
|
|
52
|
+
}
|
|
53
|
+
export declare function buildVolatilityView(db: DatabaseSync, start: string, end: string | null | undefined, baselineMode?: BaselineMode): VolatilityView;
|
|
54
|
+
//# sourceMappingURL=weightPlate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weightPlate.d.ts","sourceRoot":"","sources":["../../src/render/weightPlate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAiB5E,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,WAAW,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,CAgBlG;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;CACjC;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,YAAY,EAChB,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACjE,iBAAiB,CAuBnB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,iBAAiB,CAcnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,eAAe,CAAC;CAC5B;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAQxF;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,YAAY,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC9B,YAAY,GAAE,YAAwB,GACrC,cAAc,CAiBhB"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { getWeightGoalInfo, weightCompare, weightMilestone, weightTrend } from '../analysis/weight.js';
|
|
2
|
+
import { getWeightHistory } from '../fetch/weight.js';
|
|
3
|
+
import { weightVolatilityV2 } from '../analysis/volatility.js';
|
|
4
|
+
import { FetchError } from '../fetch/errors.js';
|
|
5
|
+
import { CalorieRenderError } from './errors.js';
|
|
6
|
+
function assertDate(s) {
|
|
7
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(s) || Number.isNaN(Date.parse(s + 'T12:00:00Z'))) {
|
|
8
|
+
throw new CalorieRenderError('bad-input', '日期非法: ' + String(s));
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function assertRange(start, end) {
|
|
12
|
+
assertDate(start);
|
|
13
|
+
assertDate(end);
|
|
14
|
+
if (start > end)
|
|
15
|
+
throw new CalorieRenderError('bad-input', 'start 不得晚于 end');
|
|
16
|
+
}
|
|
17
|
+
export function buildWeightDashboard(db, start, end) {
|
|
18
|
+
assertRange(start, end);
|
|
19
|
+
let trendRes;
|
|
20
|
+
try {
|
|
21
|
+
trendRes = weightTrend(db, start, end);
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
if (e instanceof FetchError)
|
|
25
|
+
throw new CalorieRenderError('missing-data', e.message);
|
|
26
|
+
throw e;
|
|
27
|
+
}
|
|
28
|
+
if (trendRes.status !== 'ok' || !trendRes.data) {
|
|
29
|
+
throw new CalorieRenderError('missing-data', trendRes.message || ('无体重记录(' + start + ' ~ ' + end + ')'));
|
|
30
|
+
}
|
|
31
|
+
const info = getWeightGoalInfo(db);
|
|
32
|
+
const latest = trendRes.data.lastWeight;
|
|
33
|
+
const gapKg = info && typeof latest === 'number' ? Math.round((latest - info.weightGoal) * 10) / 10 : null;
|
|
34
|
+
return { start, end, trend: trendRes.data, weightGoal: info?.weightGoal ?? null, deadline: info?.deadline ?? null, gapKg };
|
|
35
|
+
}
|
|
36
|
+
export function buildWeightHistoryView(db, opts = {}) {
|
|
37
|
+
const { days = 30, startDate, endDate } = opts;
|
|
38
|
+
try {
|
|
39
|
+
if (startDate && endDate) {
|
|
40
|
+
assertRange(startDate, endDate);
|
|
41
|
+
const h = getWeightHistory(db, { startDate, endDate });
|
|
42
|
+
return { range: h.range, rows: h.rows, change: h.change };
|
|
43
|
+
}
|
|
44
|
+
if (startDate && !endDate) {
|
|
45
|
+
assertDate(startDate);
|
|
46
|
+
const h = getWeightHistory(db, { startDate });
|
|
47
|
+
return { range: h.range, rows: h.rows, change: h.change };
|
|
48
|
+
}
|
|
49
|
+
if (!Number.isInteger(days) || days < 1 || days > 365) {
|
|
50
|
+
throw new CalorieRenderError('bad-input', 'days 须为 1..365 整数');
|
|
51
|
+
}
|
|
52
|
+
const h = getWeightHistory(db, { days });
|
|
53
|
+
return { range: h.range, rows: h.rows, change: h.change };
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
if (e instanceof CalorieRenderError)
|
|
57
|
+
throw e;
|
|
58
|
+
if (e instanceof FetchError)
|
|
59
|
+
throw new CalorieRenderError('missing-data', e.message);
|
|
60
|
+
throw e;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function buildWeightCompareView(db, start, end, compareStart, compareEnd) {
|
|
64
|
+
assertRange(start, end);
|
|
65
|
+
assertRange(compareStart, compareEnd);
|
|
66
|
+
let res;
|
|
67
|
+
try {
|
|
68
|
+
res = weightCompare(db, start, end, compareStart, compareEnd);
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
if (e instanceof FetchError)
|
|
72
|
+
throw new CalorieRenderError('bad-input', e.message);
|
|
73
|
+
throw e;
|
|
74
|
+
}
|
|
75
|
+
if (res.status !== 'ok' || !res.data) {
|
|
76
|
+
throw new CalorieRenderError('missing-data', res.message || '对比时间段内无体重记录,无法对比');
|
|
77
|
+
}
|
|
78
|
+
return { start, end, compareStart, compareEnd, compare: res.data };
|
|
79
|
+
}
|
|
80
|
+
export function buildWeightReviewView(db, today) {
|
|
81
|
+
const t = today ?? new Date().toISOString().slice(0, 10);
|
|
82
|
+
assertDate(t);
|
|
83
|
+
const res = weightMilestone(db, t);
|
|
84
|
+
if (res.status !== 'ok' || !res.data) {
|
|
85
|
+
throw new CalorieRenderError('missing-data', res.message || '无体重目标或无体重记录');
|
|
86
|
+
}
|
|
87
|
+
return { today: t, milestone: res.data };
|
|
88
|
+
}
|
|
89
|
+
export function buildVolatilityView(db, start, end, baselineMode = 'rolling') {
|
|
90
|
+
assertDate(start);
|
|
91
|
+
if (end !== null && end !== undefined)
|
|
92
|
+
assertDate(end);
|
|
93
|
+
if (baselineMode !== 'rolling' && baselineMode !== 'goal') {
|
|
94
|
+
throw new CalorieRenderError('bad-input', 'baselineMode 非法(rolling/goal):' + String(baselineMode));
|
|
95
|
+
}
|
|
96
|
+
let res;
|
|
97
|
+
try {
|
|
98
|
+
res = weightVolatilityV2(db, start, end ?? null, baselineMode);
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
if (e instanceof FetchError)
|
|
102
|
+
throw new CalorieRenderError('bad-input', e.message);
|
|
103
|
+
throw e;
|
|
104
|
+
}
|
|
105
|
+
if (res.status !== 'ok' || !res.data) {
|
|
106
|
+
throw new CalorieRenderError('missing-data', res.message || ('记录不足(' + start + ' ~ ' + (end ?? start) + '),需要至少2条记录'));
|
|
107
|
+
}
|
|
108
|
+
return { start, end: end ?? start, baselineMode, volatility: res.data };
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=weightPlate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weightPlate.js","sourceRoot":"","sources":["../../src/render/weightPlate.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** T1 #20 · 卡路里 13 表 TS 化与迁移史收敛单线(对照老家 scripts/db.py 688 行)。
|
|
2
|
+
*
|
|
3
|
+
* 收敛决策(相对老家的增量史):
|
|
4
|
+
* - 新库直接建终态 11 张持久表;老家的 body_composition_new / body_composition_mig
|
|
5
|
+
* 只是历史重建过程的临时表,TS 线永不创建,残留则清理(见 MIGRATION cleanup-strays)。
|
|
6
|
+
* - 老迁移史收敛为一条有序幂等 MIGRATIONS:PRAGMA 列检查 / IF NOT EXISTS /
|
|
7
|
+
* 条件回填,重复运行不报错(老家 apply_migrations 语义的超集)。
|
|
8
|
+
* - intensity 列(中文低中高)终态已删除;老库残留则做一次性 difficulty 回填后保留列
|
|
9
|
+
* (SQLite 不便删列,读路径统一用 difficulty)。
|
|
10
|
+
* - 真实 DB 只读不迁:本模块默认只开显式传入路径;见 paths.assertWritablePath。
|
|
11
|
+
*/
|
|
12
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
13
|
+
export declare const SCHEMA_VERSION = 1;
|
|
14
|
+
/** 终态 DDL:11 张持久表(老家 13 表 − 2 张历史临时表)。 */
|
|
15
|
+
export declare const TABLE_DDLS: Record<string, string>;
|
|
16
|
+
export declare const INDEX_SQLS: string[];
|
|
17
|
+
export declare const TRIGGER_SQLS: string[];
|
|
18
|
+
/** 收敛单线:有序幂等迁移。老库(py 建)与新库统一走同一入口。 */
|
|
19
|
+
export declare function applyMigrations(db: DatabaseSync): void;
|
|
20
|
+
/** 建库入口:终态 DDL + 收敛迁移(幂等,可重入)。 */
|
|
21
|
+
export declare function initDb(db: DatabaseSync): void;
|
|
22
|
+
/** 开库:仅显式路径(测试传 tmp;生产见 paths.resolveDbPath)。 */
|
|
23
|
+
export declare function openDb(dbPath: string): DatabaseSync;
|
|
24
|
+
export declare function listUserTables(db: DatabaseSync): string[];
|
|
25
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,eAAO,MAAM,cAAc,IAAI,CAAC;AAIhC,0CAA0C;AAC1C,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA8F7C,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,MAAM,EAe9B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,MAAM,EAoBhC,CAAC;AAuBF,sCAAsC;AACtC,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAyGtD;AAED,kCAAkC;AAClC,wBAAgB,MAAM,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAG7C;AAED,iDAAiD;AACjD,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAInD;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,YAAY,GAAG,MAAM,EAAE,CAKzD"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/** T1 #20 · 卡路里 13 表 TS 化与迁移史收敛单线(对照老家 scripts/db.py 688 行)。
|
|
2
|
+
*
|
|
3
|
+
* 收敛决策(相对老家的增量史):
|
|
4
|
+
* - 新库直接建终态 11 张持久表;老家的 body_composition_new / body_composition_mig
|
|
5
|
+
* 只是历史重建过程的临时表,TS 线永不创建,残留则清理(见 MIGRATION cleanup-strays)。
|
|
6
|
+
* - 老迁移史收敛为一条有序幂等 MIGRATIONS:PRAGMA 列检查 / IF NOT EXISTS /
|
|
7
|
+
* 条件回填,重复运行不报错(老家 apply_migrations 语义的超集)。
|
|
8
|
+
* - intensity 列(中文低中高)终态已删除;老库残留则做一次性 difficulty 回填后保留列
|
|
9
|
+
* (SQLite 不便删列,读路径统一用 difficulty)。
|
|
10
|
+
* - 真实 DB 只读不迁:本模块默认只开显式传入路径;见 paths.assertWritablePath。
|
|
11
|
+
*/
|
|
12
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
13
|
+
import { SOURCE_CHOICES } from './kcal.js';
|
|
14
|
+
export const SCHEMA_VERSION = 1;
|
|
15
|
+
const SOURCE_IN = SOURCE_CHOICES.map((s) => `'${s}'`).join(', ');
|
|
16
|
+
/** 终态 DDL:11 张持久表(老家 13 表 − 2 张历史临时表)。 */
|
|
17
|
+
export const TABLE_DDLS = {
|
|
18
|
+
food_log: `CREATE TABLE IF NOT EXISTS food_log (
|
|
19
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
20
|
+
date TEXT NOT NULL, time TEXT, food_name TEXT NOT NULL,
|
|
21
|
+
grams INTEGER NOT NULL, calories INTEGER NOT NULL,
|
|
22
|
+
protein INTEGER DEFAULT 0, carbs INTEGER DEFAULT 0, fat INTEGER DEFAULT 0,
|
|
23
|
+
sodium_mg REAL, sugar_g REAL, fiber_g REAL,
|
|
24
|
+
note TEXT DEFAULT '', created_at TEXT DEFAULT CURRENT_TIMESTAMP)`,
|
|
25
|
+
daily_goal: `CREATE TABLE IF NOT EXISTS daily_goal (
|
|
26
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
27
|
+
calorie_goal INTEGER NOT NULL DEFAULT 1800,
|
|
28
|
+
protein_goal INTEGER DEFAULT 150, carbs_goal INTEGER DEFAULT 200, fat_goal INTEGER DEFAULT 60,
|
|
29
|
+
weight_goal REAL, goal_deadline TEXT, water_goal INTEGER DEFAULT 2000,
|
|
30
|
+
goal_paused INTEGER DEFAULT 0, exercise_goal INTEGER,
|
|
31
|
+
start_weight REAL, start_date TEXT,
|
|
32
|
+
updated_at TEXT DEFAULT CURRENT_TIMESTAMP)`,
|
|
33
|
+
exercise_log: `CREATE TABLE IF NOT EXISTS exercise_log (
|
|
34
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
35
|
+
date TEXT NOT NULL, time TEXT, exercise_type TEXT NOT NULL,
|
|
36
|
+
duration_minutes INTEGER, calories_burned INTEGER NOT NULL,
|
|
37
|
+
category TEXT, difficulty TEXT, distance_km REAL, avg_heart_rate INTEGER,
|
|
38
|
+
set_index INTEGER, load_kg REAL, reps INTEGER, updated_at TEXT,
|
|
39
|
+
steps INTEGER, max_heart_rate INTEGER,
|
|
40
|
+
is_deleted INTEGER DEFAULT 0, is_backfill INTEGER DEFAULT 0,
|
|
41
|
+
xunji_localid TEXT, xunji_title TEXT,
|
|
42
|
+
note TEXT DEFAULT '', created_at TEXT DEFAULT CURRENT_TIMESTAMP)`,
|
|
43
|
+
weight_log: `CREATE TABLE IF NOT EXISTS weight_log (
|
|
44
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
45
|
+
date TEXT NOT NULL, time TEXT, weight_kg REAL NOT NULL,
|
|
46
|
+
height_cm REAL, bmi REAL, note TEXT DEFAULT '',
|
|
47
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP)`,
|
|
48
|
+
nutrition_products: `CREATE TABLE IF NOT EXISTS nutrition_products (
|
|
49
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
50
|
+
product_name TEXT NOT NULL, brand TEXT,
|
|
51
|
+
calories REAL NOT NULL, protein REAL NOT NULL, fat REAL NOT NULL,
|
|
52
|
+
saturated_fat REAL, carbohydrates REAL NOT NULL, sugar REAL,
|
|
53
|
+
dietary_fiber REAL, sodium REAL NOT NULL,
|
|
54
|
+
source TEXT NOT NULL DEFAULT '未知', is_deprecated INTEGER NOT NULL DEFAULT 0,
|
|
55
|
+
category TEXT DEFAULT '', note TEXT DEFAULT '',
|
|
56
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP)`,
|
|
57
|
+
workout_plan_config: `CREATE TABLE IF NOT EXISTS workout_plan_config (
|
|
58
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
59
|
+
title TEXT NOT NULL, version TEXT, description TEXT,
|
|
60
|
+
total_weeks INTEGER NOT NULL, start_date TEXT NOT NULL,
|
|
61
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP)`,
|
|
62
|
+
workout_plans: `CREATE TABLE IF NOT EXISTS workout_plans (
|
|
63
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
64
|
+
week_number INTEGER NOT NULL, day_of_week INTEGER NOT NULL,
|
|
65
|
+
session_index INTEGER NOT NULL DEFAULT 1, session_label TEXT NOT NULL,
|
|
66
|
+
time_start TEXT, time_end TEXT, is_rest_day INTEGER DEFAULT 0,
|
|
67
|
+
total_sets INTEGER, movements TEXT NOT NULL DEFAULT '[]',
|
|
68
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
69
|
+
UNIQUE(week_number, day_of_week, session_index))`,
|
|
70
|
+
body_photos: `CREATE TABLE IF NOT EXISTS body_photos (
|
|
71
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
72
|
+
date TEXT NOT NULL, time TEXT NOT NULL, photo_path TEXT NOT NULL,
|
|
73
|
+
tag TEXT NOT NULL, note TEXT NOT NULL,
|
|
74
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP)`,
|
|
75
|
+
user_profile: `CREATE TABLE IF NOT EXISTS user_profile (
|
|
76
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
77
|
+
age INTEGER, gender TEXT, height_cm REAL, note TEXT DEFAULT '',
|
|
78
|
+
activity_level TEXT DEFAULT 'moderate',
|
|
79
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP)`,
|
|
80
|
+
body_composition: `CREATE TABLE IF NOT EXISTS body_composition (
|
|
81
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
82
|
+
date TEXT NOT NULL, source TEXT NOT NULL CHECK (source IN (${SOURCE_IN})),
|
|
83
|
+
age INTEGER, sex TEXT CHECK (sex IN ('male', 'female')),
|
|
84
|
+
caliper_chest_mm REAL CHECK (caliper_chest_mm > 0 AND caliper_chest_mm < 100),
|
|
85
|
+
caliper_abdominal_mm REAL CHECK (caliper_abdominal_mm > 0 AND caliper_abdominal_mm < 100),
|
|
86
|
+
caliper_thigh_mm REAL CHECK (caliper_thigh_mm > 0 AND caliper_thigh_mm < 100),
|
|
87
|
+
caliper_tricep_mm REAL CHECK (caliper_tricep_mm > 0 AND caliper_tricep_mm < 100),
|
|
88
|
+
caliper_subscapular_mm REAL CHECK (caliper_subscapular_mm > 0 AND caliper_subscapular_mm < 100),
|
|
89
|
+
caliper_suprailiac_mm REAL CHECK (caliper_suprailiac_mm > 0 AND caliper_suprailiac_mm < 100),
|
|
90
|
+
caliper_midaxillary_mm REAL CHECK (caliper_midaxillary_mm > 0 AND caliper_midaxillary_mm < 100),
|
|
91
|
+
body_fat_pct REAL NOT NULL CHECK (body_fat_pct >= 0 AND body_fat_pct <= 60),
|
|
92
|
+
calculated_at TEXT, note TEXT DEFAULT '', is_deprecated INTEGER DEFAULT 0,
|
|
93
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP)`,
|
|
94
|
+
body_measurements: `CREATE TABLE IF NOT EXISTS body_measurements (
|
|
95
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT, date TEXT NOT NULL,
|
|
96
|
+
chest_cm REAL CHECK (chest_cm IS NULL OR (chest_cm > 20 AND chest_cm < 200)),
|
|
97
|
+
waist_cm REAL CHECK (waist_cm IS NULL OR (waist_cm > 20 AND waist_cm < 200)),
|
|
98
|
+
abdomen_cm REAL CHECK (abdomen_cm IS NULL OR (abdomen_cm > 20 AND abdomen_cm < 200)),
|
|
99
|
+
hip_cm REAL CHECK (hip_cm IS NULL OR (hip_cm > 20 AND hip_cm < 200)),
|
|
100
|
+
left_thigh_cm REAL CHECK (left_thigh_cm IS NULL OR (left_thigh_cm > 10 AND left_thigh_cm < 100)),
|
|
101
|
+
right_thigh_cm REAL CHECK (right_thigh_cm IS NULL OR (right_thigh_cm > 10 AND right_thigh_cm < 100)),
|
|
102
|
+
left_calf_cm REAL CHECK (left_calf_cm IS NULL OR (left_calf_cm > 10 AND left_calf_cm < 80)),
|
|
103
|
+
right_calf_cm REAL CHECK (right_calf_cm IS NULL OR (right_calf_cm > 10 AND right_calf_cm < 80)),
|
|
104
|
+
left_arm_cm REAL CHECK (left_arm_cm IS NULL OR (left_arm_cm > 10 AND left_arm_cm < 60)),
|
|
105
|
+
right_arm_cm REAL CHECK (right_arm_cm IS NULL OR (right_arm_cm > 10 AND right_arm_cm < 60)),
|
|
106
|
+
left_forearm_cm REAL CHECK (left_forearm_cm IS NULL OR (left_forearm_cm > 10 AND left_forearm_cm < 50)),
|
|
107
|
+
right_forearm_cm REAL CHECK (right_forearm_cm IS NULL OR (right_forearm_cm > 10 AND right_forearm_cm < 50)),
|
|
108
|
+
shoulder_cm REAL CHECK (shoulder_cm IS NULL OR (shoulder_cm > 20 AND shoulder_cm < 200)),
|
|
109
|
+
note TEXT DEFAULT '', is_deprecated INTEGER DEFAULT 0,
|
|
110
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP)`,
|
|
111
|
+
};
|
|
112
|
+
export const INDEX_SQLS = [
|
|
113
|
+
'CREATE INDEX IF NOT EXISTS idx_food_log_date ON food_log(date)',
|
|
114
|
+
'CREATE INDEX IF NOT EXISTS idx_weight_date ON weight_log(date)',
|
|
115
|
+
'CREATE INDEX IF NOT EXISTS idx_exercise_date ON exercise_log(date)',
|
|
116
|
+
'CREATE INDEX IF NOT EXISTS idx_exercise_category ON exercise_log(category)',
|
|
117
|
+
'CREATE INDEX IF NOT EXISTS idx_exercise_type ON exercise_log(exercise_type)',
|
|
118
|
+
'CREATE INDEX IF NOT EXISTS idx_exercise_xunji_localid ON exercise_log(xunji_localid)',
|
|
119
|
+
'CREATE INDEX IF NOT EXISTS idx_product_name ON nutrition_products(product_name)',
|
|
120
|
+
'CREATE INDEX IF NOT EXISTS idx_product_source ON nutrition_products(source)',
|
|
121
|
+
'CREATE INDEX IF NOT EXISTS idx_wp_week_day ON workout_plans(week_number, day_of_week)',
|
|
122
|
+
'CREATE INDEX IF NOT EXISTS idx_body_photos_date ON body_photos(date)',
|
|
123
|
+
'CREATE INDEX IF NOT EXISTS idx_body_photos_tag ON body_photos(tag)',
|
|
124
|
+
'CREATE INDEX IF NOT EXISTS idx_body_composition_date ON body_composition(date)',
|
|
125
|
+
'CREATE INDEX IF NOT EXISTS idx_body_composition_source ON body_composition(source)',
|
|
126
|
+
'CREATE INDEX IF NOT EXISTS idx_body_measurements_date ON body_measurements(date)',
|
|
127
|
+
];
|
|
128
|
+
export const TRIGGER_SQLS = [
|
|
129
|
+
`CREATE TRIGGER IF NOT EXISTS user_profile_activity_level_check
|
|
130
|
+
BEFORE INSERT ON user_profile
|
|
131
|
+
WHEN (NEW.activity_level IS NOT NULL AND NEW.activity_level NOT IN
|
|
132
|
+
('sedentary', 'light', 'moderate', 'active', 'very_active'))
|
|
133
|
+
BEGIN SELECT RAISE(ABORT, 'activity_level 必须是 sedentary/light/moderate/active/very_active 之一'); END`,
|
|
134
|
+
`CREATE TRIGGER IF NOT EXISTS user_profile_activity_level_check_update
|
|
135
|
+
BEFORE UPDATE OF activity_level ON user_profile
|
|
136
|
+
WHEN (NEW.activity_level IS NOT NULL AND NEW.activity_level NOT IN
|
|
137
|
+
('sedentary', 'light', 'moderate', 'active', 'very_active'))
|
|
138
|
+
BEGIN SELECT RAISE(ABORT, 'activity_level 必须是 sedentary/light/moderate/active/very_active 之一'); END`,
|
|
139
|
+
`CREATE TRIGGER IF NOT EXISTS body_measurements_require_metric
|
|
140
|
+
BEFORE INSERT ON body_measurements
|
|
141
|
+
WHEN (NEW.chest_cm IS NULL AND NEW.waist_cm IS NULL AND NEW.abdomen_cm IS NULL
|
|
142
|
+
AND NEW.hip_cm IS NULL AND NEW.left_thigh_cm IS NULL AND NEW.right_thigh_cm IS NULL
|
|
143
|
+
AND NEW.left_calf_cm IS NULL AND NEW.right_calf_cm IS NULL
|
|
144
|
+
AND NEW.left_arm_cm IS NULL AND NEW.right_arm_cm IS NULL
|
|
145
|
+
AND NEW.left_forearm_cm IS NULL AND NEW.right_forearm_cm IS NULL
|
|
146
|
+
AND NEW.shoulder_cm IS NULL)
|
|
147
|
+
BEGIN SELECT RAISE(ABORT, 'body_measurements 需要 date + 至少 1 个围度'); END`,
|
|
148
|
+
];
|
|
149
|
+
function tableColumns(db, table) {
|
|
150
|
+
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
151
|
+
return new Set(rows.map((r) => r.name));
|
|
152
|
+
}
|
|
153
|
+
function tableSql(db, table) {
|
|
154
|
+
const row = db
|
|
155
|
+
.prepare("SELECT sql FROM sqlite_master WHERE type='table' AND name=?")
|
|
156
|
+
.get(table);
|
|
157
|
+
return row?.sql ?? '';
|
|
158
|
+
}
|
|
159
|
+
function tableExists(db, table) {
|
|
160
|
+
return tableSql(db, table) !== '';
|
|
161
|
+
}
|
|
162
|
+
const CALIPERS = [
|
|
163
|
+
'caliper_chest_mm', 'caliper_abdominal_mm', 'caliper_thigh_mm', 'caliper_tricep_mm',
|
|
164
|
+
'caliper_subscapular_mm', 'caliper_suprailiac_mm', 'caliper_midaxillary_mm',
|
|
165
|
+
];
|
|
166
|
+
/** 收敛单线:有序幂等迁移。老库(py 建)与新库统一走同一入口。 */
|
|
167
|
+
export function applyMigrations(db) {
|
|
168
|
+
// M1 遗留表清理:entries 合并 → food_log;sleep_records / fitness_goals 删除。
|
|
169
|
+
const tables = new Set(db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all().map((r) => r.name));
|
|
170
|
+
if (tables.has('entries') && !tables.has('food_log')) {
|
|
171
|
+
db.exec('ALTER TABLE entries RENAME TO food_log');
|
|
172
|
+
}
|
|
173
|
+
else if (tables.has('entries') && tables.has('food_log')) {
|
|
174
|
+
db.exec('INSERT OR IGNORE INTO food_log (date, time, food_name, grams, calories, protein, carbs, fat, note, created_at) ' +
|
|
175
|
+
'SELECT date, time, food_name, grams, calories, protein, carbs, fat, note, created_at FROM entries');
|
|
176
|
+
db.exec('DROP TABLE entries');
|
|
177
|
+
}
|
|
178
|
+
for (const dead of ['sleep_records', 'fitness_goals', 'body_composition_new', 'body_composition_mig']) {
|
|
179
|
+
db.exec(`DROP TABLE IF EXISTS ${dead}`);
|
|
180
|
+
}
|
|
181
|
+
// M2 food_log 钠糖纤维列 + 回填(老家 2026-08-02 ticket #10)。
|
|
182
|
+
const foodCols = tableColumns(db, 'food_log');
|
|
183
|
+
for (const [col, type] of [['sodium_mg', 'REAL'], ['sugar_g', 'REAL'], ['fiber_g', 'REAL']]) {
|
|
184
|
+
if (!foodCols.has(col))
|
|
185
|
+
db.exec(`ALTER TABLE food_log ADD COLUMN ${col} ${type}`);
|
|
186
|
+
}
|
|
187
|
+
db.exec(`UPDATE food_log SET
|
|
188
|
+
sodium_mg = ROUND((SELECT n.sodium FROM nutrition_products n
|
|
189
|
+
WHERE n.product_name = food_log.food_name AND n.is_deprecated = 0
|
|
190
|
+
ORDER BY n.id DESC LIMIT 1) * food_log.grams / 100.0, 1),
|
|
191
|
+
sugar_g = ROUND((SELECT n.sugar FROM nutrition_products n
|
|
192
|
+
WHERE n.product_name = food_log.food_name AND n.is_deprecated = 0
|
|
193
|
+
ORDER BY n.id DESC LIMIT 1) * food_log.grams / 100.0, 1),
|
|
194
|
+
fiber_g = ROUND((SELECT n.dietary_fiber FROM nutrition_products n
|
|
195
|
+
WHERE n.product_name = food_log.food_name AND n.is_deprecated = 0
|
|
196
|
+
ORDER BY n.id DESC LIMIT 1) * food_log.grams / 100.0, 1)
|
|
197
|
+
WHERE food_log.sodium_mg IS NULL OR food_log.sugar_g IS NULL OR food_log.fiber_g IS NULL`);
|
|
198
|
+
// M3 daily_goal 增量列(PRAGMA 守卫,老家 try/except 语义)。
|
|
199
|
+
const goalCols = tableColumns(db, 'daily_goal');
|
|
200
|
+
for (const [col, type] of [
|
|
201
|
+
['weight_goal', 'REAL'], ['goal_deadline', 'TEXT'], ['water_goal', 'INTEGER DEFAULT 2000'],
|
|
202
|
+
['goal_paused', 'INTEGER DEFAULT 0'], ['exercise_goal', 'INTEGER'],
|
|
203
|
+
['start_weight', 'REAL'], ['start_date', 'TEXT'],
|
|
204
|
+
]) {
|
|
205
|
+
if (!goalCols.has(col))
|
|
206
|
+
db.exec(`ALTER TABLE daily_goal ADD COLUMN ${col} ${type}`);
|
|
207
|
+
}
|
|
208
|
+
// M4 nutrition_products 扩展列 + [已废弃] 回填。
|
|
209
|
+
const prodCols = tableColumns(db, 'nutrition_products');
|
|
210
|
+
for (const [col, type] of [
|
|
211
|
+
['source', "TEXT DEFAULT '未知'"], ['is_deprecated', 'INTEGER DEFAULT 0'],
|
|
212
|
+
['category', "TEXT DEFAULT ''"],
|
|
213
|
+
]) {
|
|
214
|
+
if (!prodCols.has(col))
|
|
215
|
+
db.exec(`ALTER TABLE nutrition_products ADD COLUMN ${col} ${type}`);
|
|
216
|
+
}
|
|
217
|
+
db.exec(`UPDATE nutrition_products SET is_deprecated = 1 WHERE is_deprecated = 0 AND (
|
|
218
|
+
note LIKE '%[已废弃]%' OR product_name LIKE '%[已废弃]%' OR brand LIKE '%[已废弃]%')`);
|
|
219
|
+
// M5 exercise_log 扩展列 + intensity→difficulty 数据迁移 + xunji 关联列。
|
|
220
|
+
const exCols = tableColumns(db, 'exercise_log');
|
|
221
|
+
for (const [col, type] of [
|
|
222
|
+
['category', 'TEXT'], ['difficulty', 'TEXT'], ['distance_km', 'REAL'],
|
|
223
|
+
['avg_heart_rate', 'INTEGER'], ['set_index', 'INTEGER'], ['load_kg', 'REAL'],
|
|
224
|
+
['reps', 'INTEGER'], ['updated_at', 'TEXT'], ['steps', 'INTEGER'],
|
|
225
|
+
['max_heart_rate', 'INTEGER'], ['is_deleted', 'INTEGER DEFAULT 0'],
|
|
226
|
+
['is_backfill', 'INTEGER DEFAULT 0'],
|
|
227
|
+
['xunji_localid', 'TEXT'], ['xunji_title', 'TEXT'],
|
|
228
|
+
]) {
|
|
229
|
+
if (!exCols.has(col))
|
|
230
|
+
db.exec(`ALTER TABLE exercise_log ADD COLUMN ${col} ${type}`);
|
|
231
|
+
}
|
|
232
|
+
if (exCols.has('intensity')) {
|
|
233
|
+
db.exec(`UPDATE exercise_log SET difficulty = CASE intensity
|
|
234
|
+
WHEN '低' THEN 'easy' WHEN '中' THEN 'normal' WHEN '高' THEN 'hard' ELSE NULL END
|
|
235
|
+
WHERE difficulty IS NULL AND intensity IS NOT NULL`);
|
|
236
|
+
}
|
|
237
|
+
// M6 user_profile.activity_level + 回填。
|
|
238
|
+
if (!tableColumns(db, 'user_profile').has('activity_level')) {
|
|
239
|
+
db.exec("ALTER TABLE user_profile ADD COLUMN activity_level TEXT DEFAULT 'moderate'");
|
|
240
|
+
db.exec("UPDATE user_profile SET activity_level = 'moderate' WHERE activity_level IS NULL");
|
|
241
|
+
}
|
|
242
|
+
// M7 body_composition 重建收敛:旧 CHECK(无 gym)或皮褶 NOT NULL → 一次重建为终态。
|
|
243
|
+
if (tableExists(db, 'body_composition')) {
|
|
244
|
+
const sql = tableSql(db, 'body_composition');
|
|
245
|
+
const info = db.prepare('PRAGMA table_info(body_composition)').all();
|
|
246
|
+
const notnullBy = new Map(info.map((c) => [c.name, c.notnull]));
|
|
247
|
+
const needsRebuild = !SOURCE_CHOICES.every((s) => sql.includes(`'${s}'`)) ||
|
|
248
|
+
CALIPERS.some((c) => (notnullBy.get(c) ?? 0) === 1);
|
|
249
|
+
if (needsRebuild) {
|
|
250
|
+
const cols = info.map((c) => c.name);
|
|
251
|
+
const colList = cols.map((c) => `"${c}"`).join(', ');
|
|
252
|
+
db.exec(TABLE_DDLS.body_composition.replace('body_composition (', 'body_composition_ts ('));
|
|
253
|
+
db.exec(`INSERT INTO body_composition_ts (${colList}) SELECT ${colList} FROM body_composition`);
|
|
254
|
+
db.exec('DROP TABLE body_composition');
|
|
255
|
+
db.exec('ALTER TABLE body_composition_ts RENAME TO body_composition');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
for (const sql of INDEX_SQLS)
|
|
259
|
+
db.exec(sql);
|
|
260
|
+
for (const sql of TRIGGER_SQLS)
|
|
261
|
+
db.exec(sql);
|
|
262
|
+
}
|
|
263
|
+
/** 建库入口:终态 DDL + 收敛迁移(幂等,可重入)。 */
|
|
264
|
+
export function initDb(db) {
|
|
265
|
+
for (const ddl of Object.values(TABLE_DDLS))
|
|
266
|
+
db.exec(ddl);
|
|
267
|
+
applyMigrations(db);
|
|
268
|
+
}
|
|
269
|
+
/** 开库:仅显式路径(测试传 tmp;生产见 paths.resolveDbPath)。 */
|
|
270
|
+
export function openDb(dbPath) {
|
|
271
|
+
const db = new DatabaseSync(dbPath);
|
|
272
|
+
initDb(db);
|
|
273
|
+
return db;
|
|
274
|
+
}
|
|
275
|
+
export function listUserTables(db) {
|
|
276
|
+
const rows = db
|
|
277
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name")
|
|
278
|
+
.all();
|
|
279
|
+
return rows.map((r) => r.name);
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEjE,0CAA0C;AAC1C,MAAM,CAAC,MAAM,UAAU,GAA2B;IAChD,QAAQ,EAAE;;;;;;qEAMyD;IACnE,UAAU,EAAE;;;;;;;+CAOiC;IAC7C,YAAY,EAAE;;;;;;;;;qEASqD;IACnE,UAAU,EAAE;;;;+CAIiC;IAC7C,kBAAkB,EAAE;;;;;;;;0FAQoE;IACxF,mBAAmB,EAAE;;;;0FAImE;IACxF,aAAa,EAAE;;;;;;;qDAOoC;IACnD,WAAW,EAAE;;;;+CAIgC;IAC7C,YAAY,EAAE;;;;0FAI0E;IACxF,gBAAgB,EAAE;;iEAE6C,SAAS;;;;;;;;;;;0FAWgB;IACxF,iBAAiB,EAAE;;;;;;;;;;;;;;;;0FAgBqE;CACzF,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAa;IAClC,gEAAgE;IAChE,gEAAgE;IAChE,oEAAoE;IACpE,4EAA4E;IAC5E,6EAA6E;IAC7E,sFAAsF;IACtF,iFAAiF;IACjF,6EAA6E;IAC7E,uFAAuF;IACvF,sEAAsE;IACtE,oEAAoE;IACpE,gFAAgF;IAChF,oFAAoF;IACpF,kFAAkF;CACnF,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAa;IACpC;;;;uGAIqG;IACrG;;;;uGAIqG;IACrG;;;;;;;;0EAQwE;CACzE,CAAC;AAEF,SAAS,YAAY,CAAC,EAAgB,EAAE,KAAa;IACnD,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,qBAAqB,KAAK,GAAG,CAAC,CAAC,GAAG,EAAwB,CAAC;IACnF,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,QAAQ,CAAC,EAAgB,EAAE,KAAa;IAC/C,MAAM,GAAG,GAAG,EAAE;SACX,OAAO,CAAC,6DAA6D,CAAC;SACtE,GAAG,CAAC,KAAK,CAAgC,CAAC;IAC7C,OAAO,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,SAAS,WAAW,CAAC,EAAgB,EAAE,KAAa;IAClD,OAAO,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,QAAQ,GAAG;IACf,kBAAkB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,mBAAmB;IACnF,wBAAwB,EAAE,uBAAuB,EAAE,wBAAwB;CAC5E,CAAC;AAEF,sCAAsC;AACtC,MAAM,UAAU,eAAe,CAAC,EAAgB;IAC9C,mEAAmE;IACnE,MAAM,MAAM,GAAG,IAAI,GAAG,CACnB,EAAE,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC,GAAG,EAAyB,CAAC,GAAG,CAC/F,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CACd,CACF,CAAC;IACF,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QACrD,EAAE,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IACpD,CAAC;SAAM,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3D,EAAE,CAAC,IAAI,CACL,iHAAiH;YAC/G,mGAAmG,CACtG,CAAC;QACF,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAChC,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,CAAC,eAAe,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,CAAC,EAAE,CAAC;QACtG,EAAE,CAAC,IAAI,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,oDAAoD;IACpD,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IAC9C,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,CAAU,EAAE,CAAC;QACrG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,EAAE,CAAC,IAAI,CAAC,mCAAmC,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;IACpF,CAAC;IACD,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;6FAUmF,CAAC,CAAC;IAE7F,iDAAiD;IACjD,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;IAChD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI;QACxB,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,sBAAsB,CAAC;QAC1F,CAAC,aAAa,EAAE,mBAAmB,CAAC,EAAE,CAAC,eAAe,EAAE,SAAS,CAAC;QAClE,CAAC,cAAc,EAAE,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;KACxC,EAAE,CAAC;QACX,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,EAAE,CAAC,IAAI,CAAC,qCAAqC,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,wCAAwC;IACxC,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,EAAE,oBAAoB,CAAC,CAAC;IACxD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI;QACxB,CAAC,QAAQ,EAAE,mBAAmB,CAAC,EAAE,CAAC,eAAe,EAAE,mBAAmB,CAAC;QACvE,CAAC,UAAU,EAAE,iBAAiB,CAAC;KACvB,EAAE,CAAC;QACX,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,EAAE,CAAC,IAAI,CAAC,6CAA6C,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;IAC9F,CAAC;IACD,EAAE,CAAC,IAAI,CAAC;gFACsE,CAAC,CAAC;IAEhF,+DAA+D;IAC/D,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;IAChD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI;QACxB,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,CAAC;QACrE,CAAC,gBAAgB,EAAE,SAAS,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC;QAC5E,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;QACjE,CAAC,gBAAgB,EAAE,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,mBAAmB,CAAC;QAClE,CAAC,aAAa,EAAE,mBAAmB,CAAC;QACpC,CAAC,eAAe,EAAE,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,CAAC;KAC1C,EAAE,CAAC;QACX,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,EAAE,CAAC,IAAI,CAAC,uCAAuC,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,EAAE,CAAC,IAAI,CAAC;;yDAE6C,CAAC,CAAC;IACzD,CAAC;IAED,uCAAuC;IACvC,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC5D,EAAE,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;QACtF,EAAE,CAAC,IAAI,CAAC,kFAAkF,CAAC,CAAC;IAC9F,CAAC;IAED,iEAAiE;IACjE,IAAI,WAAW,CAAC,EAAE,EAAE,kBAAkB,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAC,GAAG,EAG/D,CAAC;QACJ,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAChE,MAAM,YAAY,GAChB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACtD,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrD,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,OAAO,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,CAAC,CAAC;YAC5F,EAAE,CAAC,IAAI,CAAC,oCAAoC,OAAO,YAAY,OAAO,wBAAwB,CAAC,CAAC;YAChG,EAAE,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;YACvC,EAAE,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,UAAU;QAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,YAAY;QAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,MAAM,CAAC,EAAgB;IACrC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;QAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1D,eAAe,CAAC,EAAE,CAAC,CAAC;AACtB,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,MAAM,CAAC,MAAc;IACnC,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,CAAC,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAgB;IAC7C,MAAM,IAAI,GAAG,EAAE;SACZ,OAAO,CAAC,8FAA8F,CAAC;SACvG,GAAG,EAAwB,CAAC;IAC/B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** HELP 唤醒词速查台:wake_word/alias → 命中(公共组件 help_template 注入上游口径)。
|
|
2
|
+
* C2 #43 · 记早餐/记午餐/记晚餐别名同走 calorie.diet.add(SoT 零改动,别名唯一上游为本文件 WAKE_TABLE;buildHelpLookup/searchHelp 双注入)。
|
|
3
|
+
* C3 #43 · 去legacy首命中:可执行键(calorie-cmd-read calorie.*)排前,legacy python/mmx 排后;知名高频词用 HELP_EXEC_OVERRIDES + 合成首条保可执行。
|
|
4
|
+
*/
|
|
5
|
+
import type { HelpHit, Trigger } from './types.js';
|
|
6
|
+
/** 分类 → 场景编号(复盘并入 10-分析;食品库/综合在 SoT 中为空) */
|
|
7
|
+
export declare const CATEGORY_SCENE: Record<string, string>;
|
|
8
|
+
/** 全量速查表:主唤醒词与其 aliases 同指同一命中;记身材照一词三命中(按 key 区分)。 */
|
|
9
|
+
export declare function buildHelpLookup(triggers: Trigger[]): Record<string, HelpHit[]>;
|
|
10
|
+
export declare function lookupWake(map: Record<string, HelpHit[]>, word: string): HelpHit[];
|
|
11
|
+
/** C2 #43 · 餐别别名 WAKE_TABLE(SoT 不动:TRIGGERS 原文零改动,别名唯一上游为本表;buildHelpLookup/searchHelp 双注入)。 */
|
|
12
|
+
export declare const WAKE_TABLE: Array<{
|
|
13
|
+
phrase: string;
|
|
14
|
+
key: string;
|
|
15
|
+
cli: string;
|
|
16
|
+
}>;
|
|
17
|
+
export declare function routeWakeword(phrase: string): {
|
|
18
|
+
key: string;
|
|
19
|
+
cli: string;
|
|
20
|
+
} | null;
|
|
21
|
+
/** C3 #43 · cli 是否可执行(唯一出口 calorie-cmd-read)。 */
|
|
22
|
+
export declare function isExecCli(cli: string): boolean;
|
|
23
|
+
/** C3 #43 · legacy 内部 key → 可执行 cli 映射(SoT 原文不动,呈现层替换首命中)。 */
|
|
24
|
+
export declare const HELP_EXEC_OVERRIDES: Record<string, string>;
|
|
25
|
+
export declare function execCliFor(internalKey: string | null, fallbackCli: string): string;
|
|
26
|
+
/** C3 #43 · 别名感知 + 可执行排前 + 知名高频词合成首条(唯一搜索入口,cmd_read 同逻辑)。 */
|
|
27
|
+
export declare function searchHelp(triggers: Trigger[], q: string): HelpHit[];
|
|
28
|
+
//# sourceMappingURL=help-lookup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help-lookup.d.ts","sourceRoot":"","sources":["../../src/triggers/help-lookup.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEnD,4CAA4C;AAC5C,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAYjD,CAAC;AAUF,uDAAuD;AACvD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAmB9E;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAElF;AAED,gGAAgG;AAChG,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAI1E,CAAC;AAEF,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAGjF;AAED,iDAAiD;AACjD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED,8DAA8D;AAC9D,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAwBtD,CAAC;AAEF,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAIlF;AAOD,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE,CAgEpE"}
|