forge-openclaw-plugin 0.2.101 → 0.2.102
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/assets/{activity-page-CpjuNSHw.js → activity-page-CgF7K2ww.js} +1 -1
- package/dist/assets/ai-surface-workspace-xtB5RFQu.js +1 -0
- package/dist/assets/atlas-panel-B3dPHCmZ.js +1 -0
- package/dist/assets/{board-BkDRaMp6.js → board-DqHzdCPQ.js} +1 -1
- package/dist/assets/{calendar-page-DNNt6lfz.js → calendar-page-C1Wfd2Fy.js} +1 -1
- package/dist/assets/{calendar-rules-DNJFNsxi.js → calendar-rules-CaZXtlxt.js} +1 -1
- package/dist/assets/calendar-week-toolbar-BZ_-X3Wb.js +1 -0
- package/dist/assets/{charts-P7EVhIog.js → charts-FcU0F3XV.js} +8 -8
- package/dist/assets/{companion-sync-lab-page-KxEDigM6.js → companion-sync-lab-page-NgeK-O-P.js} +1 -1
- package/dist/assets/daily-metrics-dashboard-BMyL0Qr4.js +1 -0
- package/dist/assets/{entity-note-count-link-DrhjJZ4i.js → entity-note-count-link-BrS1-O0o.js} +1 -1
- package/dist/assets/entity-notes-surface-CBylYDwy.js +1 -0
- package/dist/assets/{execution-board-D07gOocB.js → execution-board-CpO2ch6v.js} +1 -1
- package/dist/assets/faceted-token-search-D7xPWfOl.js +1 -0
- package/dist/assets/flagship-signal-deck-BEFKOhvx.js +1 -0
- package/dist/assets/{floating-action-menu-Fs_ZiUMo.js → floating-action-menu-zzC2r0Ob.js} +1 -1
- package/dist/assets/{forms-BFlTgZ3W.js → forms-CmLAyGqz.js} +1 -1
- package/dist/assets/{goal-detail-page-CqLiNz4f.js → goal-detail-page-JK_Nva8e.js} +1 -1
- package/dist/assets/goals-page-yeoJ06Vw.js +1 -0
- package/dist/assets/{graph-D6JLqDbD.js → graph-BTa79qum.js} +14 -14
- package/dist/assets/{habits-page-BJxagdzx.js → habits-page-Dx5EhkJi.js} +1 -1
- package/dist/assets/index-BHIKoiZ6.js +19 -0
- package/dist/assets/index-H8R-ABM3.css +1 -0
- package/dist/assets/insight-flow-dialog-BtIQXXsS.js +1 -0
- package/dist/assets/{insights-page-D6rOa7uk.js → insights-page-CujrosD_.js} +1 -1
- package/dist/assets/{kanban-page-XQ7Se6dH.js → kanban-page-Q9NuIz5w.js} +1 -1
- package/dist/assets/knowledge-graph-page-DaJmlvvM.js +1 -0
- package/dist/assets/{life-force-page-Dy0JTS2G.js → life-force-page-BGDkKfbJ.js} +1 -1
- package/dist/assets/{life-force-workspace-OfyB9HJM.js → life-force-workspace-CLVexVnb.js} +1 -1
- package/dist/assets/{maps-ClgJoCjz.js → maps-CF1RagUX.js} +1 -1
- package/dist/assets/metric-tile-4iMd_WnJ.js +1 -0
- package/dist/assets/{motion-BeD44FeG.js → motion-CfdU2F35.js} +1 -1
- package/dist/assets/movement-page-ClaoTNuX.js +1 -0
- package/dist/assets/note-markdown-CsGQhQXF.js +3 -0
- package/dist/assets/note-tags-input-DdZi93tj.js +1 -0
- package/dist/assets/notes-page-DYI8s3NN.js +1 -0
- package/dist/assets/{open-in-graph-button-IXe9SGth.js → open-in-graph-button-C0TGev7c.js} +1 -1
- package/dist/assets/orbit-map-DVXkfQdd.js +1 -0
- package/dist/assets/overview-page-BwMlFQKX.js +1 -0
- package/dist/assets/page-hero-oFHaAjtL.js +1 -0
- package/dist/assets/pill-cluster-7UZd_lHp.js +1 -0
- package/dist/assets/{preference-entity-handoff-button-5PzUn42S.js → preference-entity-handoff-button-DOKV9bZc.js} +1 -1
- package/dist/assets/preferences-page-BrKEkmfD.js +1 -0
- package/dist/assets/{project-collections-xPz2mlRr.js → project-collections-CZagCmeH.js} +1 -1
- package/dist/assets/{project-detail-page-BXK5-4xW.js → project-detail-page-DogvVNEn.js} +1 -1
- package/dist/assets/{project-management-hierarchy-page-DtRpMABw.js → project-management-hierarchy-page-Dr7hW9PW.js} +1 -1
- package/dist/assets/{project-management-section-nav-P3ixzPa-.js → project-management-section-nav-BLdAgTge.js} +1 -1
- package/dist/assets/{projects-page-C5ViRuf4.js → projects-page-UKrby_5-.js} +1 -1
- package/dist/assets/psyche-behaviors-page-BeVlXvbj.js +5 -0
- package/dist/assets/psyche-flashcards-page-CqAWCO4E.js +1 -0
- package/dist/assets/psyche-goal-map-page-IyNnbk_W.js +1 -0
- package/dist/assets/psyche-graph-IkUQRaDK.js +1 -0
- package/dist/assets/{psyche-metrics-page-CuR9oqEy.js → psyche-metrics-page-uai0a7Lx.js} +1 -1
- package/dist/assets/psyche-mode-guide-page-C7p-ABiF.js +1 -0
- package/dist/assets/psyche-modes-page-CLQ5V3w0.js +1 -0
- package/dist/assets/psyche-page-NQBHkkpU.js +1 -0
- package/dist/assets/psyche-patterns-page-BkRiNpI_.js +5 -0
- package/dist/assets/psyche-questionnaire-builder-page-Du-7HwPC.js +1 -0
- package/dist/assets/psyche-questionnaire-detail-page-C5-yf8MF.js +1 -0
- package/dist/assets/psyche-questionnaire-run-detail-page-CoSH5O6R.js +1 -0
- package/dist/assets/psyche-questionnaire-run-page-ChI7c1wy.js +1 -0
- package/dist/assets/psyche-questionnaires-page-xUcJJzbI.js +1 -0
- package/dist/assets/psyche-report-detail-page-BPrZCFZS.js +3 -0
- package/dist/assets/psyche-reports-page-D2EXJmm6.js +1 -0
- package/dist/assets/{psyche-schemas-HFmg37Wj.js → psyche-schemas-RcZYaokx.js} +1 -1
- package/dist/assets/psyche-schemas-beliefs-page-h0ooZ1lp.js +9 -0
- package/dist/assets/psyche-screen-time-page-_3-4LikV.js +1 -0
- package/dist/assets/psyche-self-observation-page-BdbCsgR5.js +1 -0
- package/dist/assets/psyche-values-page-DuUVki5e.js +5 -0
- package/dist/assets/report-chain-fields-BBMz0sGI.js +1 -0
- package/dist/assets/{rewards-page-DmC4R_Ps.js → rewards-page-PZFPa6rR.js} +1 -1
- package/dist/assets/{scheduling-rules-editor-D02s70hr.js → scheduling-rules-editor-B9KNKsQz.js} +1 -1
- package/dist/assets/schema-badge-D93RcG36.js +1 -0
- package/dist/assets/schema-visuals-CvC9a3i6.js +1 -0
- package/dist/assets/select-menu-Cdq7foRu.js +1 -0
- package/dist/assets/{settings-agents-page-C_v_hMJF.js → settings-agents-page-DPx2F6wf.js} +3 -3
- package/dist/assets/{settings-bin-page-DY5bg81n.js → settings-bin-page-COwP3gjo.js} +1 -1
- package/dist/assets/settings-calendar-page-C-ghE0YT.js +5 -0
- package/dist/assets/{settings-data-page-CHRQFU9H.js → settings-data-page-CBubzKBw.js} +1 -1
- package/dist/assets/{settings-logs-page-B04pUwEv.js → settings-logs-page-uOuXMeBm.js} +1 -1
- package/dist/assets/{settings-mobile-page-D9kTlYDS.js → settings-mobile-page-C5rfj8_r.js} +1 -1
- package/dist/assets/settings-models-page-DijmUWdU.js +1 -0
- package/dist/assets/{settings-page-DYDTFlnv.js → settings-page-B4u5TR5g.js} +1 -1
- package/dist/assets/{settings-rewards-page-cl4vqqO_.js → settings-rewards-page-COiTwkMH.js} +1 -1
- package/dist/assets/{settings-section-nav-DSOuht_F.js → settings-section-nav-Dc4IeVBt.js} +1 -1
- package/dist/assets/{settings-users-page-BU79JB_T.js → settings-users-page-DEGa5DNn.js} +1 -1
- package/dist/assets/settings-wiki-page-Cvsiz5_e.js +1 -0
- package/dist/assets/{sleep-page-D8NbdhyS.js → sleep-page-BnSOwkEU.js} +1 -1
- package/dist/assets/{sports-page-CV4Cnzwn.js → sports-page-l1RqXzA_.js} +1 -1
- package/dist/assets/{state-B-4sS1xO.js → state-VYvD1QVP.js} +1 -1
- package/dist/assets/{strategies-page-C4qvXnql.js → strategies-page-DEnPlpAs.js} +1 -1
- package/dist/assets/{strategy-detail-page-DJLo5rfy.js → strategy-detail-page-Ls8bxKeH.js} +1 -1
- package/dist/assets/strategy-dialog-DMyRKrWf.js +1 -0
- package/dist/assets/surface-Bfz_sLX6.js +1 -0
- package/dist/assets/{table-WfAPUppN.js → table-C0VTeqw0.js} +1 -1
- package/dist/assets/task-detail-page-CgrYgQLD.js +1 -0
- package/dist/assets/{timebox-planning-dialog-DB6FLqmI.js → timebox-planning-dialog-Ww0NGLLo.js} +1 -1
- package/dist/assets/today-page-CIuFHMi1.js +1 -0
- package/dist/assets/training-load-page-BIwc648i.js +1 -0
- package/dist/assets/{ui-C13Nbgas.js → ui-CsEkP2V8.js} +4 -4
- package/dist/assets/use-psyche-focus-target-qxT5Oy_z.js +1 -0
- package/dist/assets/{vendor-DHkYh85p.js → vendor-kIz9EZnX.js} +237 -222
- package/dist/assets/{vitals-page-qre17Nw8.js → vitals-page-Dz1Jt5H8.js} +1 -1
- package/dist/assets/{weekly-review-page-Cz4vkRcx.js → weekly-review-page-BFpBe1kI.js} +1 -1
- package/dist/assets/weight-loss-page-BgMoBpBt.js +5 -0
- package/dist/assets/{wiki-article-markdown-DdiR2TJE.js → wiki-article-markdown-gsPTXTg1.js} +1 -1
- package/dist/assets/{wiki-editor-page-DqwoqVFb.js → wiki-editor-page-BpAZHooY.js} +7 -7
- package/dist/assets/{wiki-ingest-history-page--evBLbOw.js → wiki-ingest-history-page-C-ig8O22.js} +1 -1
- package/dist/assets/{wiki-ingest-modal--ohzFnj2.js → wiki-ingest-modal-BK4eQgqs.js} +1 -1
- package/dist/assets/{wiki-page-B_VJFBPA.js → wiki-page-CMTZ60Zt.js} +1 -1
- package/dist/assets/workbench-flow-page-BIpWUcLJ.js +5 -0
- package/dist/assets/workbench-page-CtCjYSRe.js +1 -0
- package/dist/assets/workout-detail-page-DD9IGN6l.js +2 -0
- package/dist/index.html +9 -9
- package/dist/openclaw/local-runtime.js +41 -14
- package/dist/server/server/migrations/067_weight_loss_daily_active_overrides.sql +13 -0
- package/dist/server/server/src/app.js +103 -30
- package/dist/server/server/src/health-weight-loss.js +457 -55
- package/dist/server/server/src/health.js +12 -4
- package/dist/server/server/src/movement.js +84 -1
- package/dist/server/server/src/openapi.js +123 -18
- package/dist/server/server/src/repositories/model-settings.js +12 -9
- package/dist/server/server/src/repositories/settings.js +19 -5
- package/dist/server/src/components/ui/info-tooltip.js +6 -6
- package/dist/server/src/lib/api.js +14 -4
- package/dist/server/src/lib/theme-system.js +8 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -3
- package/server/migrations/067_weight_loss_daily_active_overrides.sql +13 -0
- package/skills/forge-openclaw/SKILL.md +13 -0
- package/skills/forge-openclaw/entity_conversation_playbooks.md +7 -1
- package/dist/assets/ai-surface-workspace-DEAFZruS.js +0 -1
- package/dist/assets/atlas-panel-CdVNPotj.js +0 -1
- package/dist/assets/calendar-week-toolbar-BbPwYeN0.js +0 -1
- package/dist/assets/daily-metrics-dashboard-B3cqJgDt.js +0 -1
- package/dist/assets/entity-notes-surface-CkcRsKJQ.js +0 -1
- package/dist/assets/faceted-token-search-BxRRcM3q.js +0 -1
- package/dist/assets/flagship-signal-deck-cmy82b8_.js +0 -1
- package/dist/assets/goals-page-BTk7mg_T.js +0 -1
- package/dist/assets/index-CF4J4R9L.js +0 -19
- package/dist/assets/index-CZbuZQjw.css +0 -1
- package/dist/assets/insight-flow-dialog-8f3D0GuC.js +0 -1
- package/dist/assets/knowledge-graph-page-BtAg8iv3.js +0 -1
- package/dist/assets/metric-tile-DKpo-8xw.js +0 -1
- package/dist/assets/movement-page-Bg_T_Stx.js +0 -1
- package/dist/assets/note-markdown-N-uxD3Xt.js +0 -3
- package/dist/assets/note-tags-input-Cdu7wiw6.js +0 -1
- package/dist/assets/notes-page-CKXnF_KU.js +0 -1
- package/dist/assets/orbit-map-Dzi6KliQ.js +0 -1
- package/dist/assets/overview-page-1miYqaVS.js +0 -1
- package/dist/assets/page-hero-DRy5b2MU.js +0 -1
- package/dist/assets/pill-cluster-C9QczVJ2.js +0 -1
- package/dist/assets/preferences-page-DtNaF5Q3.js +0 -1
- package/dist/assets/psyche-behaviors-page-Dco46sC4.js +0 -5
- package/dist/assets/psyche-flashcards-page-ZcoEB8gV.js +0 -1
- package/dist/assets/psyche-goal-map-page-CLBAQOI0.js +0 -1
- package/dist/assets/psyche-graph-k4tX2tdp.js +0 -1
- package/dist/assets/psyche-mode-guide-page-hIVXcCnE.js +0 -1
- package/dist/assets/psyche-modes-page-0lYtBlhO.js +0 -1
- package/dist/assets/psyche-page-VZ9k9ISp.js +0 -1
- package/dist/assets/psyche-patterns-page-gx5nmdGq.js +0 -5
- package/dist/assets/psyche-questionnaire-builder-page-Bn0TOISd.js +0 -1
- package/dist/assets/psyche-questionnaire-detail-page-CmVzSd_s.js +0 -1
- package/dist/assets/psyche-questionnaire-run-detail-page-BsMbmXCG.js +0 -1
- package/dist/assets/psyche-questionnaire-run-page-CgkRL2vi.js +0 -1
- package/dist/assets/psyche-questionnaires-page-D7V8uLXM.js +0 -1
- package/dist/assets/psyche-report-detail-page-OlFq57eL.js +0 -3
- package/dist/assets/psyche-reports-page-dVUZjna1.js +0 -1
- package/dist/assets/psyche-schemas-beliefs-page-BCgc8FUd.js +0 -9
- package/dist/assets/psyche-screen-time-page-B_6BT_WN.js +0 -1
- package/dist/assets/psyche-self-observation-page-CEG5mluK.js +0 -1
- package/dist/assets/psyche-values-page-DRbRfEd6.js +0 -5
- package/dist/assets/report-chain-fields-CALCV3V5.js +0 -1
- package/dist/assets/schema-badge-BZO-qNhO.js +0 -1
- package/dist/assets/schema-visuals-D6nxjbYC.js +0 -1
- package/dist/assets/select-menu-fYyreSdQ.js +0 -1
- package/dist/assets/settings-calendar-page-D1CzE6cg.js +0 -5
- package/dist/assets/settings-models-page-D26270R2.js +0 -1
- package/dist/assets/settings-wiki-page-DwAUlyA3.js +0 -1
- package/dist/assets/strategy-dialog-D3AuUlVz.js +0 -1
- package/dist/assets/task-detail-page-z-9u9rF0.js +0 -1
- package/dist/assets/today-page-BKlu6gx5.js +0 -1
- package/dist/assets/training-load-page-CyJQqo_3.js +0 -1
- package/dist/assets/use-psyche-focus-target-C1C_XjYG.js +0 -1
- package/dist/assets/weight-loss-page-BQrnOI0y.js +0 -1
- package/dist/assets/workbench-flow-page-Du62mtJU.js +0 -5
- package/dist/assets/workbench-page-4MKr3iRm.js +0 -1
- package/dist/assets/workout-detail-page-DfUbYYw1.js +0 -2
|
@@ -2777,6 +2777,7 @@ function expectedWorkoutEvidenceCounts(derived) {
|
|
|
2777
2777
|
expectedTimeSeriesSamples,
|
|
2778
2778
|
expectedHeartRateSamples,
|
|
2779
2779
|
expectedRoutePoints,
|
|
2780
|
+
rawEvidenceVersion,
|
|
2780
2781
|
hasCurrentRawEvidenceVersion: rawEvidenceVersion === CURRENT_WORKOUT_RAW_EVIDENCE_VERSION,
|
|
2781
2782
|
hasEvidenceMetadata: syncTimeSeriesCount !== null ||
|
|
2782
2783
|
captureHeartRateCount !== null ||
|
|
@@ -2819,7 +2820,9 @@ function mobileHealthWorkoutImportState(userId) {
|
|
|
2819
2820
|
ORDER BY w.started_at DESC`)
|
|
2820
2821
|
.all(userId);
|
|
2821
2822
|
const alreadyUploadedWorkoutExternalUids = [];
|
|
2823
|
+
const incompleteWorkoutExternalUids = [];
|
|
2822
2824
|
let incompleteWorkoutCount = 0;
|
|
2825
|
+
let staleEvidenceVersionWorkoutCount = 0;
|
|
2823
2826
|
let timeSeriesSampleCount = 0;
|
|
2824
2827
|
let heartRateSampleCount = 0;
|
|
2825
2828
|
let routePointCount = 0;
|
|
@@ -2829,27 +2832,32 @@ function mobileHealthWorkoutImportState(userId) {
|
|
|
2829
2832
|
const actualTimeSeriesCount = Math.max(0, row.time_series_count ?? 0);
|
|
2830
2833
|
const actualHeartRateCount = Math.max(0, row.heart_rate_count ?? 0);
|
|
2831
2834
|
const actualRoutePointCount = Math.max(0, row.route_point_count ?? 0);
|
|
2832
|
-
const
|
|
2833
|
-
? evidenceCounts.
|
|
2834
|
-
actualTimeSeriesCount >= evidenceCounts.expectedTimeSeriesSamples &&
|
|
2835
|
+
const evidenceCountsComplete = evidenceCounts.hasEvidenceMetadata
|
|
2836
|
+
? actualTimeSeriesCount >= evidenceCounts.expectedTimeSeriesSamples &&
|
|
2835
2837
|
actualHeartRateCount >= evidenceCounts.expectedHeartRateSamples &&
|
|
2836
2838
|
actualRoutePointCount >= evidenceCounts.expectedRoutePoints
|
|
2837
2839
|
: false;
|
|
2838
|
-
if (
|
|
2840
|
+
if (evidenceCountsComplete) {
|
|
2839
2841
|
alreadyUploadedWorkoutExternalUids.push(row.external_uid.toLowerCase());
|
|
2840
2842
|
timeSeriesSampleCount += actualTimeSeriesCount;
|
|
2841
2843
|
heartRateSampleCount += actualHeartRateCount;
|
|
2842
2844
|
routePointCount += actualRoutePointCount;
|
|
2845
|
+
if (!evidenceCounts.hasCurrentRawEvidenceVersion) {
|
|
2846
|
+
staleEvidenceVersionWorkoutCount += 1;
|
|
2847
|
+
}
|
|
2843
2848
|
}
|
|
2844
2849
|
else {
|
|
2845
2850
|
incompleteWorkoutCount += 1;
|
|
2851
|
+
incompleteWorkoutExternalUids.push(row.external_uid.toLowerCase());
|
|
2846
2852
|
}
|
|
2847
2853
|
}
|
|
2848
2854
|
return {
|
|
2849
2855
|
alreadyUploadedWorkoutExternalUids,
|
|
2856
|
+
incompleteWorkoutExternalUids,
|
|
2850
2857
|
alreadyUploadedWorkoutCount: alreadyUploadedWorkoutExternalUids.length,
|
|
2851
2858
|
existingWorkoutCount: rows.length,
|
|
2852
2859
|
incompleteWorkoutCount,
|
|
2860
|
+
staleEvidenceVersionWorkoutCount,
|
|
2853
2861
|
timeSeriesSampleCount,
|
|
2854
2862
|
heartRateSampleCount,
|
|
2855
2863
|
routePointCount,
|
|
@@ -905,6 +905,69 @@ function decodeMovementTimelineCursor(rawValue) {
|
|
|
905
905
|
return null;
|
|
906
906
|
}
|
|
907
907
|
}
|
|
908
|
+
function metricNumber(metrics, key) {
|
|
909
|
+
const metric = metrics[key];
|
|
910
|
+
if (!metric || typeof metric !== "object") {
|
|
911
|
+
return null;
|
|
912
|
+
}
|
|
913
|
+
const record = metric;
|
|
914
|
+
for (const field of ["latest", "average", "total", "maximum"]) {
|
|
915
|
+
const value = record[field];
|
|
916
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
917
|
+
return value;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
922
|
+
function latestKnownBodyMassKg(userId) {
|
|
923
|
+
const nutritionRow = getDatabase()
|
|
924
|
+
.prepare(`SELECT weight_kg
|
|
925
|
+
FROM nutrition_body_checkins
|
|
926
|
+
WHERE user_id = ?
|
|
927
|
+
AND weight_kg IS NOT NULL
|
|
928
|
+
ORDER BY checked_at DESC
|
|
929
|
+
LIMIT 1`)
|
|
930
|
+
.get(userId);
|
|
931
|
+
if (nutritionRow?.weight_kg && nutritionRow.weight_kg > 0) {
|
|
932
|
+
return nutritionRow.weight_kg;
|
|
933
|
+
}
|
|
934
|
+
const summaryRows = getDatabase()
|
|
935
|
+
.prepare(`SELECT metrics_json
|
|
936
|
+
FROM health_daily_summaries
|
|
937
|
+
WHERE user_id = ?
|
|
938
|
+
AND summary_type = 'vitals'
|
|
939
|
+
ORDER BY date_key DESC, updated_at DESC
|
|
940
|
+
LIMIT 14`)
|
|
941
|
+
.all(userId);
|
|
942
|
+
for (const row of summaryRows) {
|
|
943
|
+
const metrics = safeJsonParse(row.metrics_json, {});
|
|
944
|
+
const bodyMass = metricNumber(metrics, "bodyMass");
|
|
945
|
+
if (bodyMass != null && bodyMass > 0) {
|
|
946
|
+
return bodyMass;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
return 80;
|
|
950
|
+
}
|
|
951
|
+
function estimateMovementActiveCalories(input) {
|
|
952
|
+
const met = input.expectedMet;
|
|
953
|
+
if (met == null || met <= 1) {
|
|
954
|
+
return null;
|
|
955
|
+
}
|
|
956
|
+
const seconds = input.movingSeconds > 0
|
|
957
|
+
? input.movingSeconds
|
|
958
|
+
: durationSeconds(input.startedAt, input.endedAt);
|
|
959
|
+
if (seconds <= 0) {
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
const bodyMassKg = latestKnownBodyMassKg(input.userId);
|
|
963
|
+
const activeMet = Math.max(0, met - 1);
|
|
964
|
+
const minutes = seconds / 60;
|
|
965
|
+
return {
|
|
966
|
+
caloriesKcal: round((activeMet * 3.5 * bodyMassKg * minutes) / 200, 0),
|
|
967
|
+
bodyMassKg,
|
|
968
|
+
model: "active_met_minus_one_v1"
|
|
969
|
+
};
|
|
970
|
+
}
|
|
908
971
|
function haversineDistanceMeters(left, right) {
|
|
909
972
|
const toRadians = (degrees) => (degrees * Math.PI) / 180;
|
|
910
973
|
const earthRadius = 6_371_000;
|
|
@@ -1912,6 +1975,26 @@ function upsertMovementTrip(pairing, settings, input) {
|
|
|
1912
1975
|
});
|
|
1913
1976
|
const effectiveExpectedMet = parsed.expectedMet ??
|
|
1914
1977
|
inferExpectedMet(parsed.activityType, derivedMetrics.averageSpeedMps ?? parsed.averageSpeedMps);
|
|
1978
|
+
const estimatedCalories = parsed.caloriesKcal == null
|
|
1979
|
+
? estimateMovementActiveCalories({
|
|
1980
|
+
userId: pairing.user_id,
|
|
1981
|
+
expectedMet: effectiveExpectedMet,
|
|
1982
|
+
movingSeconds: derivedMetrics.movingSeconds,
|
|
1983
|
+
startedAt: derivedMetrics.startedAt,
|
|
1984
|
+
endedAt: derivedMetrics.endedAt
|
|
1985
|
+
})
|
|
1986
|
+
: null;
|
|
1987
|
+
const effectiveCaloriesKcal = parsed.caloriesKcal ?? estimatedCalories?.caloriesKcal ?? null;
|
|
1988
|
+
const metadata = {
|
|
1989
|
+
...parsed.metadata,
|
|
1990
|
+
...(estimatedCalories
|
|
1991
|
+
? {
|
|
1992
|
+
calorieEstimateModel: estimatedCalories.model,
|
|
1993
|
+
calorieEstimateBodyMassKg: estimatedCalories.bodyMassKg,
|
|
1994
|
+
calorieEstimateSource: "forge_server_ingestion"
|
|
1995
|
+
}
|
|
1996
|
+
: {})
|
|
1997
|
+
};
|
|
1915
1998
|
const id = existing?.id ?? `mtr_${randomUUID().replaceAll("-", "").slice(0, 10)}`;
|
|
1916
1999
|
getDatabase()
|
|
1917
2000
|
.prepare(`INSERT INTO movement_trips (
|
|
@@ -1946,7 +2029,7 @@ function upsertMovementTrip(pairing, settings, input) {
|
|
|
1946
2029
|
linked_people_json = excluded.linked_people_json,
|
|
1947
2030
|
metadata_json = excluded.metadata_json,
|
|
1948
2031
|
updated_at = excluded.updated_at`)
|
|
1949
|
-
.run(id, parsed.externalUid, pairing.id, pairing.user_id, startPlace?.id ?? null, endPlace?.id ?? null, parsed.label, parsed.status, parsed.travelMode, parsed.activityType, derivedMetrics.startedAt, derivedMetrics.endedAt, derivedMetrics.distanceMeters, derivedMetrics.movingSeconds, derivedMetrics.idleSeconds, derivedMetrics.averageSpeedMps, derivedMetrics.maxSpeedMps,
|
|
2032
|
+
.run(id, parsed.externalUid, pairing.id, pairing.user_id, startPlace?.id ?? null, endPlace?.id ?? null, parsed.label, parsed.status, parsed.travelMode, parsed.activityType, derivedMetrics.startedAt, derivedMetrics.endedAt, derivedMetrics.distanceMeters, derivedMetrics.movingSeconds, derivedMetrics.idleSeconds, derivedMetrics.averageSpeedMps, derivedMetrics.maxSpeedMps, effectiveCaloriesKcal, effectiveExpectedMet, JSON.stringify({}), JSON.stringify(uniqStrings(parsed.tags)), JSON.stringify(parsed.linkedEntities), JSON.stringify(parsed.linkedPeople), JSON.stringify(metadata), existing?.published_note_id ?? null, existing?.created_at ?? now, now);
|
|
1950
2033
|
reconcileMovementOverlapValidation(pairing.user_id);
|
|
1951
2034
|
const fresh = getDatabase()
|
|
1952
2035
|
.prepare(`SELECT * FROM movement_trips WHERE user_id = ? AND external_uid = ?`)
|
|
@@ -30,16 +30,14 @@ const HTTP_METHODS = new Set([
|
|
|
30
30
|
]);
|
|
31
31
|
const mobileHealthSyncProgressSchema = {
|
|
32
32
|
type: "object",
|
|
33
|
-
required: [
|
|
34
|
-
"chunkCount",
|
|
35
|
-
"receivedBytes",
|
|
36
|
-
"receivedCounts",
|
|
37
|
-
"byteTotals"
|
|
38
|
-
],
|
|
33
|
+
required: ["chunkCount", "receivedBytes", "receivedCounts", "byteTotals"],
|
|
39
34
|
properties: {
|
|
40
35
|
chunkCount: { type: "number" },
|
|
41
36
|
receivedBytes: { type: "number" },
|
|
42
|
-
receivedCounts: {
|
|
37
|
+
receivedCounts: {
|
|
38
|
+
type: "object",
|
|
39
|
+
additionalProperties: { type: "number" }
|
|
40
|
+
},
|
|
43
41
|
byteTotals: { type: "object", additionalProperties: { type: "number" } }
|
|
44
42
|
}
|
|
45
43
|
};
|
|
@@ -3054,8 +3052,12 @@ export function buildOpenApiDocument() {
|
|
|
3054
3052
|
newestUnlock: nullable({
|
|
3055
3053
|
$ref: "#/components/schemas/GamificationCatalogEntry"
|
|
3056
3054
|
}),
|
|
3057
|
-
nextTargets: arrayOf({
|
|
3058
|
-
|
|
3055
|
+
nextTargets: arrayOf({
|
|
3056
|
+
$ref: "#/components/schemas/GamificationCatalogEntry"
|
|
3057
|
+
}),
|
|
3058
|
+
recentlyUnlocked: arrayOf({
|
|
3059
|
+
$ref: "#/components/schemas/GamificationCatalogEntry"
|
|
3060
|
+
})
|
|
3059
3061
|
}
|
|
3060
3062
|
};
|
|
3061
3063
|
const xpMetricsPayload = {
|
|
@@ -3100,7 +3102,9 @@ export function buildOpenApiDocument() {
|
|
|
3100
3102
|
newestUnlock: nullable({
|
|
3101
3103
|
$ref: "#/components/schemas/GamificationCatalogEntry"
|
|
3102
3104
|
}),
|
|
3103
|
-
nextTargets: arrayOf({
|
|
3105
|
+
nextTargets: arrayOf({
|
|
3106
|
+
$ref: "#/components/schemas/GamificationCatalogEntry"
|
|
3107
|
+
}),
|
|
3104
3108
|
equipment: { $ref: "#/components/schemas/GamificationEquipment" },
|
|
3105
3109
|
mascot: { $ref: "#/components/schemas/GamificationMascotState" },
|
|
3106
3110
|
celebrations: arrayOf({
|
|
@@ -3652,6 +3656,7 @@ export function buildOpenApiDocument() {
|
|
|
3652
3656
|
"movement",
|
|
3653
3657
|
"lifeForce",
|
|
3654
3658
|
"workbench",
|
|
3659
|
+
"weightLoss",
|
|
3655
3660
|
"psyche"
|
|
3656
3661
|
],
|
|
3657
3662
|
properties: {
|
|
@@ -3674,6 +3679,7 @@ export function buildOpenApiDocument() {
|
|
|
3674
3679
|
movement: { type: "string" },
|
|
3675
3680
|
lifeForce: { type: "string" },
|
|
3676
3681
|
workbench: { type: "string" },
|
|
3682
|
+
weightLoss: { type: "string" },
|
|
3677
3683
|
psyche: { type: "string" }
|
|
3678
3684
|
}
|
|
3679
3685
|
},
|
|
@@ -3967,6 +3973,22 @@ export function buildOpenApiDocument() {
|
|
|
3967
3973
|
"weeklyReview",
|
|
3968
3974
|
"sleepOverview",
|
|
3969
3975
|
"sportsOverview",
|
|
3976
|
+
"trainingLoad",
|
|
3977
|
+
"weightLoss",
|
|
3978
|
+
"weightLossTarget",
|
|
3979
|
+
"weightLossDailyActiveCalories",
|
|
3980
|
+
"weightLossFoodsSearch",
|
|
3981
|
+
"weightLossFoodsBarcode",
|
|
3982
|
+
"weightLossFoodLogs",
|
|
3983
|
+
"weightLossFoodLogDetail",
|
|
3984
|
+
"weightLossParse",
|
|
3985
|
+
"weightLossBodyCheckins",
|
|
3986
|
+
"weightLossAppearanceCheckins",
|
|
3987
|
+
"weightLossSubjectiveCheckins",
|
|
3988
|
+
"weightLossGutCheckins",
|
|
3989
|
+
"weightLossPatterns",
|
|
3990
|
+
"weightLossExperiments",
|
|
3991
|
+
"weightLossExperimentDetail",
|
|
3970
3992
|
"lifeForce",
|
|
3971
3993
|
"lifeForceProfile",
|
|
3972
3994
|
"lifeForceWeekdayTemplate",
|
|
@@ -4015,6 +4037,22 @@ export function buildOpenApiDocument() {
|
|
|
4015
4037
|
weeklyReview: { type: "string" },
|
|
4016
4038
|
sleepOverview: { type: "string" },
|
|
4017
4039
|
sportsOverview: { type: "string" },
|
|
4040
|
+
trainingLoad: { type: "string" },
|
|
4041
|
+
weightLoss: { type: "string" },
|
|
4042
|
+
weightLossTarget: { type: "string" },
|
|
4043
|
+
weightLossDailyActiveCalories: { type: "string" },
|
|
4044
|
+
weightLossFoodsSearch: { type: "string" },
|
|
4045
|
+
weightLossFoodsBarcode: { type: "string" },
|
|
4046
|
+
weightLossFoodLogs: { type: "string" },
|
|
4047
|
+
weightLossFoodLogDetail: { type: "string" },
|
|
4048
|
+
weightLossParse: { type: "string" },
|
|
4049
|
+
weightLossBodyCheckins: { type: "string" },
|
|
4050
|
+
weightLossAppearanceCheckins: { type: "string" },
|
|
4051
|
+
weightLossSubjectiveCheckins: { type: "string" },
|
|
4052
|
+
weightLossGutCheckins: { type: "string" },
|
|
4053
|
+
weightLossPatterns: { type: "string" },
|
|
4054
|
+
weightLossExperiments: { type: "string" },
|
|
4055
|
+
weightLossExperimentDetail: { type: "string" },
|
|
4018
4056
|
lifeForce: { type: "string" },
|
|
4019
4057
|
lifeForceProfile: { type: "string" },
|
|
4020
4058
|
lifeForceWeekdayTemplate: { type: "string" },
|
|
@@ -4786,9 +4824,16 @@ export function buildOpenApiDocument() {
|
|
|
4786
4824
|
sync: {
|
|
4787
4825
|
type: "object",
|
|
4788
4826
|
additionalProperties: false,
|
|
4789
|
-
required: [
|
|
4827
|
+
required: [
|
|
4828
|
+
"fullSyncCompletedAt",
|
|
4829
|
+
"lastDailySyncAt",
|
|
4830
|
+
"lastSyncedDateKey"
|
|
4831
|
+
],
|
|
4790
4832
|
properties: {
|
|
4791
|
-
fullSyncCompletedAt: nullable({
|
|
4833
|
+
fullSyncCompletedAt: nullable({
|
|
4834
|
+
type: "string",
|
|
4835
|
+
format: "date-time"
|
|
4836
|
+
}),
|
|
4792
4837
|
lastDailySyncAt: nullable({ type: "string", format: "date-time" }),
|
|
4793
4838
|
lastSyncedDateKey: nullable({ type: "string" })
|
|
4794
4839
|
}
|
|
@@ -4925,10 +4970,20 @@ export function buildOpenApiDocument() {
|
|
|
4925
4970
|
sync: {
|
|
4926
4971
|
type: "object",
|
|
4927
4972
|
additionalProperties: false,
|
|
4928
|
-
required: [
|
|
4973
|
+
required: [
|
|
4974
|
+
"fullSyncCompletedAt",
|
|
4975
|
+
"lastDailySyncAt",
|
|
4976
|
+
"lastSyncedDateKey"
|
|
4977
|
+
],
|
|
4929
4978
|
properties: {
|
|
4930
|
-
fullSyncCompletedAt: nullable({
|
|
4931
|
-
|
|
4979
|
+
fullSyncCompletedAt: nullable({
|
|
4980
|
+
type: "string",
|
|
4981
|
+
format: "date-time"
|
|
4982
|
+
}),
|
|
4983
|
+
lastDailySyncAt: nullable({
|
|
4984
|
+
type: "string",
|
|
4985
|
+
format: "date-time"
|
|
4986
|
+
}),
|
|
4932
4987
|
lastSyncedDateKey: nullable({ type: "string" })
|
|
4933
4988
|
}
|
|
4934
4989
|
}
|
|
@@ -5218,7 +5273,10 @@ export function buildOpenApiDocument() {
|
|
|
5218
5273
|
}
|
|
5219
5274
|
},
|
|
5220
5275
|
trainingIntelligence: { type: "object", additionalProperties: true },
|
|
5221
|
-
activityBreakdown: arrayOf({
|
|
5276
|
+
activityBreakdown: arrayOf({
|
|
5277
|
+
type: "object",
|
|
5278
|
+
additionalProperties: true
|
|
5279
|
+
}),
|
|
5222
5280
|
vitalsTrend: arrayOf({ type: "object", additionalProperties: true }),
|
|
5223
5281
|
sessionSignals: arrayOf({ type: "object", additionalProperties: true }),
|
|
5224
5282
|
targetModel: { type: "object", additionalProperties: true }
|
|
@@ -5345,7 +5403,10 @@ export function buildOpenApiDocument() {
|
|
|
5345
5403
|
todayLedger: { type: "object", additionalProperties: true },
|
|
5346
5404
|
recentMeals: arrayOf(nutritionFoodLog),
|
|
5347
5405
|
bodyCheckins: arrayOf({ type: "object", additionalProperties: true }),
|
|
5348
|
-
appearanceCheckins: arrayOf({
|
|
5406
|
+
appearanceCheckins: arrayOf({
|
|
5407
|
+
type: "object",
|
|
5408
|
+
additionalProperties: true
|
|
5409
|
+
}),
|
|
5349
5410
|
energyModel: { type: "object", additionalProperties: true },
|
|
5350
5411
|
weightTrend: { type: "object", additionalProperties: true },
|
|
5351
5412
|
foodQuality: { type: "object", additionalProperties: true },
|
|
@@ -5820,6 +5881,47 @@ export function buildOpenApiDocument() {
|
|
|
5820
5881
|
}
|
|
5821
5882
|
}
|
|
5822
5883
|
},
|
|
5884
|
+
"/api/v1/health/weight-loss/daily-active-calories": {
|
|
5885
|
+
patch: {
|
|
5886
|
+
tags: ["Health"],
|
|
5887
|
+
summary: "Set or clear the user-edited active calorie allowance for one weight-loss day",
|
|
5888
|
+
requestBody: {
|
|
5889
|
+
content: {
|
|
5890
|
+
"application/json": {
|
|
5891
|
+
schema: {
|
|
5892
|
+
type: "object",
|
|
5893
|
+
additionalProperties: false,
|
|
5894
|
+
properties: {
|
|
5895
|
+
userId: { type: "string" },
|
|
5896
|
+
dayKey: {
|
|
5897
|
+
type: "string",
|
|
5898
|
+
pattern: "^\\d{4}-\\d{2}-\\d{2}$"
|
|
5899
|
+
},
|
|
5900
|
+
activeCaloriesKcal: {
|
|
5901
|
+
type: ["number", "null"],
|
|
5902
|
+
minimum: 0
|
|
5903
|
+
},
|
|
5904
|
+
notes: { type: "string" }
|
|
5905
|
+
}
|
|
5906
|
+
}
|
|
5907
|
+
}
|
|
5908
|
+
}
|
|
5909
|
+
},
|
|
5910
|
+
responses: {
|
|
5911
|
+
"200": jsonResponse({
|
|
5912
|
+
type: "object",
|
|
5913
|
+
required: ["dayKey"],
|
|
5914
|
+
properties: {
|
|
5915
|
+
dayKey: { type: "string" },
|
|
5916
|
+
override: {
|
|
5917
|
+
type: ["object", "null"],
|
|
5918
|
+
additionalProperties: true
|
|
5919
|
+
}
|
|
5920
|
+
}
|
|
5921
|
+
}, "Updated daily active calorie override")
|
|
5922
|
+
}
|
|
5923
|
+
}
|
|
5924
|
+
},
|
|
5823
5925
|
"/api/v1/health/weight-loss/foods/search": {
|
|
5824
5926
|
post: {
|
|
5825
5927
|
tags: ["Health"],
|
|
@@ -8865,7 +8967,10 @@ export function buildOpenApiDocument() {
|
|
|
8865
8967
|
"connectionHelp"
|
|
8866
8968
|
],
|
|
8867
8969
|
properties: {
|
|
8868
|
-
provider: {
|
|
8970
|
+
provider: {
|
|
8971
|
+
type: "string",
|
|
8972
|
+
enum: CALENDAR_PROVIDER_VALUES
|
|
8973
|
+
},
|
|
8869
8974
|
label: { type: "string" },
|
|
8870
8975
|
supportsDedicatedForgeCalendar: { type: "boolean" },
|
|
8871
8976
|
connectionHelp: { type: "string" }
|
|
@@ -203,7 +203,12 @@ export function syncForgeManagedWikiProfile(secrets) {
|
|
|
203
203
|
.get();
|
|
204
204
|
const connectionId = settings?.forge_wiki_connection_id?.trim() ?? "";
|
|
205
205
|
const fallbackModel = settings?.forge_wiki_model?.trim() || "gpt-5.4-mini";
|
|
206
|
-
const
|
|
206
|
+
const requestedConnection = connectionId
|
|
207
|
+
? getAiModelConnectionById(connectionId)
|
|
208
|
+
: null;
|
|
209
|
+
const connection = requestedConnection?.provider === "openai-codex"
|
|
210
|
+
? requestedConnection
|
|
211
|
+
: null;
|
|
207
212
|
const row = connectionId
|
|
208
213
|
? getDatabase()
|
|
209
214
|
.prepare(`SELECT secret_id
|
|
@@ -214,18 +219,16 @@ export function syncForgeManagedWikiProfile(secrets) {
|
|
|
214
219
|
upsertWikiLlmProfile({
|
|
215
220
|
id: FORGE_MANAGED_WIKI_PROFILE_ID,
|
|
216
221
|
label: "Forge wiki ingest",
|
|
217
|
-
provider:
|
|
218
|
-
|
|
219
|
-
: connection?.provider === "openai-codex"
|
|
220
|
-
? "openai-codex"
|
|
221
|
-
: "openai-responses",
|
|
222
|
-
baseUrl: connection?.baseUrl ?? DEFAULT_OPENAI_BASE_URL,
|
|
222
|
+
provider: "openai-codex",
|
|
223
|
+
baseUrl: connection?.baseUrl ?? DEFAULT_OPENAI_CODEX_BASE_URL,
|
|
223
224
|
model: connection?.model ?? fallbackModel,
|
|
224
|
-
secretId: row?.secret_id ?? null,
|
|
225
|
+
secretId: connection ? (row?.secret_id ?? null) : null,
|
|
225
226
|
enabled: true,
|
|
226
227
|
metadata: {
|
|
227
228
|
managedBySettings: true,
|
|
228
|
-
connectionId: connection?.id ?? null
|
|
229
|
+
connectionId: connection?.id ?? null,
|
|
230
|
+
authMode: "oauth",
|
|
231
|
+
billing: "chatgpt-codex-oauth"
|
|
229
232
|
}
|
|
230
233
|
}, secrets);
|
|
231
234
|
}
|
|
@@ -6,7 +6,7 @@ import { logForgeDebug } from "../debug.js";
|
|
|
6
6
|
import { recordActivityEvent } from "./activity-events.js";
|
|
7
7
|
import { recordEventLog } from "./event-log.js";
|
|
8
8
|
import { resolveGoogleCalendarOauthPublicConfig } from "../services/google-calendar-oauth-config.js";
|
|
9
|
-
import { buildConnectionAgentIdentity, FORGE_DEFAULT_AGENT_ID, listAiModelConnections, syncForgeManagedWikiProfile } from "./model-settings.js";
|
|
9
|
+
import { buildConnectionAgentIdentity, FORGE_DEFAULT_AGENT_ID, getAiModelConnectionById, listAiModelConnections, syncForgeManagedWikiProfile } from "./model-settings.js";
|
|
10
10
|
import { listUsersByIds } from "./users.js";
|
|
11
11
|
import { agentBootstrapPolicySchema, agentScopePolicySchema, createAgentTokenSchema, legacyAgentBootstrapPolicy, defaultAgentScopePolicy, agentIdentitySchema, customThemeSchema, settingsPayloadSchema, updateSettingsSchema } from "../types.js";
|
|
12
12
|
const settingsFileSchema = settingsPayloadSchema.deepPartial();
|
|
@@ -591,7 +591,10 @@ function buildSettingsPayloadFromDatabase() {
|
|
|
591
591
|
const basicChatConnectionId = normalizeModelConnectionId(row.forge_basic_chat_connection_id);
|
|
592
592
|
const wikiConnectionId = normalizeModelConnectionId(row.forge_wiki_connection_id);
|
|
593
593
|
const basicChatConnection = connections.find((entry) => entry.id === basicChatConnectionId) ?? null;
|
|
594
|
-
const
|
|
594
|
+
const wikiConnectionCandidate = connections.find((entry) => entry.id === wikiConnectionId) ?? null;
|
|
595
|
+
const wikiConnection = wikiConnectionCandidate?.provider === "openai-codex"
|
|
596
|
+
? wikiConnectionCandidate
|
|
597
|
+
: null;
|
|
595
598
|
const customTheme = parseCustomThemeJson(row.custom_theme_json);
|
|
596
599
|
return settingsPayloadSchema.parse({
|
|
597
600
|
profile: {
|
|
@@ -832,9 +835,20 @@ function updateSettingsInternal(input, options = {}) {
|
|
|
832
835
|
current.modelSettings.forgeAgent.basicChat.model
|
|
833
836
|
},
|
|
834
837
|
wiki: {
|
|
835
|
-
connectionId:
|
|
836
|
-
|
|
837
|
-
|
|
838
|
+
connectionId: (() => {
|
|
839
|
+
const normalized = parsed.modelSettings?.forgeAgent?.wiki?.connectionId !==
|
|
840
|
+
undefined
|
|
841
|
+
? normalizeModelConnectionId(parsed.modelSettings.forgeAgent.wiki.connectionId)
|
|
842
|
+
: (current.modelSettings.forgeAgent.wiki.connectionId ?? "");
|
|
843
|
+
if (!normalized) {
|
|
844
|
+
return "";
|
|
845
|
+
}
|
|
846
|
+
const connection = getAiModelConnectionById(normalized);
|
|
847
|
+
if (connection?.provider !== "openai-codex") {
|
|
848
|
+
throw new Error("KarpaWiki ingest must use an OpenAI Codex OAuth model connection, not an OpenAI Platform API connection.");
|
|
849
|
+
}
|
|
850
|
+
return normalized;
|
|
851
|
+
})(),
|
|
838
852
|
model: parsed.modelSettings?.forgeAgent?.wiki?.model?.trim() ||
|
|
839
853
|
current.modelSettings.forgeAgent.wiki.model
|
|
840
854
|
}
|
|
@@ -8,9 +8,9 @@ const TOOLTIP_MAX_WIDTH_PX = 320;
|
|
|
8
8
|
const TOOLTIP_MIN_HEIGHT_BELOW_PX = 180;
|
|
9
9
|
const TOOLTIP_ESTIMATED_HEIGHT_PX = 220;
|
|
10
10
|
export function FieldHint({ children, className }) {
|
|
11
|
-
return (_jsx("div", { className: cn("text-sm leading-6 text-
|
|
11
|
+
return (_jsx("div", { className: cn("text-sm leading-6 text-[var(--ui-ink-soft)]", className), children: children }));
|
|
12
12
|
}
|
|
13
|
-
export function InfoTooltip({ content, title, label = "Explain this field", className, panelClassName }) {
|
|
13
|
+
export function InfoTooltip({ content, title, label = "Explain this field", className, panelClassName, maxWidthPx = TOOLTIP_MAX_WIDTH_PX }) {
|
|
14
14
|
const [open, setOpen] = useState(false);
|
|
15
15
|
const [panelStyle, setPanelStyle] = useState({});
|
|
16
16
|
const containerRef = useRef(null);
|
|
@@ -18,7 +18,7 @@ export function InfoTooltip({ content, title, label = "Explain this field", clas
|
|
|
18
18
|
const tooltipId = useId();
|
|
19
19
|
const tooltipPanel = typeof document === "undefined"
|
|
20
20
|
? null
|
|
21
|
-
: createPortal(_jsxs("span", { id: tooltipId, role: "tooltip", "aria-hidden": !open, "data-state": open ? "open" : "closed", style: panelStyle, className: cn("pointer-events-none fixed z-[9999] grid overflow-y-auto rounded-[8px] border border-
|
|
21
|
+
: createPortal(_jsxs("span", { id: tooltipId, role: "tooltip", "aria-hidden": !open, "data-state": open ? "open" : "closed", style: panelStyle, className: cn("pointer-events-none fixed z-[9999] grid overflow-y-auto rounded-[8px] border border-[var(--ui-border-subtle)] bg-[var(--surface-glass)] px-3 py-2.5 text-left font-sans text-sm normal-case leading-6 tracking-normal text-[var(--ui-ink-medium)] shadow-[var(--ui-shadow-floating)] backdrop-blur-xl transition", open ? "translate-y-0 opacity-100" : "translate-y-1 opacity-0", panelClassName), children: [title ? (_jsx("span", { className: "text-[11px] font-semibold uppercase tracking-[0.14em] text-[var(--ui-ink-soft)]", children: title })) : null, _jsx("span", { className: "block min-w-0 whitespace-normal break-words", children: content })] }), document.body);
|
|
22
22
|
useLayoutEffect(() => {
|
|
23
23
|
if (!open) {
|
|
24
24
|
return;
|
|
@@ -31,7 +31,7 @@ export function InfoTooltip({ content, title, label = "Explain this field", clas
|
|
|
31
31
|
const rect = trigger.getBoundingClientRect();
|
|
32
32
|
const width = window.innerWidth < 480
|
|
33
33
|
? window.innerWidth - TOOLTIP_GUTTER_PX * 2
|
|
34
|
-
: Math.min(
|
|
34
|
+
: Math.min(maxWidthPx, window.innerWidth - TOOLTIP_GUTTER_PX * 2);
|
|
35
35
|
const centeredLeft = rect.left + rect.width / 2 - width / 2;
|
|
36
36
|
const maxLeft = window.innerWidth - width - TOOLTIP_GUTTER_PX;
|
|
37
37
|
const left = Math.max(TOOLTIP_GUTTER_PX, Math.min(centeredLeft, maxLeft));
|
|
@@ -53,7 +53,7 @@ export function InfoTooltip({ content, title, label = "Explain this field", clas
|
|
|
53
53
|
window.removeEventListener("resize", positionTooltip);
|
|
54
54
|
window.removeEventListener("scroll", positionTooltip, true);
|
|
55
55
|
};
|
|
56
|
-
}, [open]);
|
|
56
|
+
}, [maxWidthPx, open]);
|
|
57
57
|
useEffect(() => {
|
|
58
58
|
if (!open) {
|
|
59
59
|
return;
|
|
@@ -66,7 +66,7 @@ export function InfoTooltip({ content, title, label = "Explain this field", clas
|
|
|
66
66
|
document.addEventListener("pointerdown", handlePointerDown);
|
|
67
67
|
return () => document.removeEventListener("pointerdown", handlePointerDown);
|
|
68
68
|
}, [open]);
|
|
69
|
-
return (_jsxs("span", { ref: containerRef, className: cn("relative inline-flex items-center", className), onMouseEnter: () => setOpen(true), onMouseLeave: () => setOpen(false), children: [_jsx("button", { ref: triggerRef, type: "button", "aria-label": label, "aria-describedby": open ? tooltipId : undefined, "aria-expanded": open, className: "inline-flex size-5 items-center justify-center rounded-full text-
|
|
69
|
+
return (_jsxs("span", { ref: containerRef, className: cn("relative inline-flex items-center", className), onMouseEnter: () => setOpen(true), onMouseLeave: () => setOpen(false), children: [_jsx("button", { ref: triggerRef, type: "button", "aria-label": label, "aria-describedby": open ? tooltipId : undefined, "aria-expanded": open, className: "inline-flex size-5 items-center justify-center rounded-full text-[var(--ui-ink-faint)] transition hover:bg-[var(--ui-surface-hover)] hover:text-[var(--ui-ink-medium)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--primary)]/35", onFocus: () => setOpen(true), onBlur: () => setOpen(false), onClick: () => setOpen((current) => !current), onKeyDown: (event) => {
|
|
70
70
|
if (event.key === "Escape") {
|
|
71
71
|
setOpen(false);
|
|
72
72
|
}
|
|
@@ -740,7 +740,7 @@ export async function listFlashcards(userIds) {
|
|
|
740
740
|
{
|
|
741
741
|
entityTypes: ["flashcard"],
|
|
742
742
|
userIds: coerceUserIds(userIds),
|
|
743
|
-
limit:
|
|
743
|
+
limit: 200
|
|
744
744
|
}
|
|
745
745
|
]
|
|
746
746
|
});
|
|
@@ -1771,6 +1771,15 @@ export function updateNutritionTarget(patch, userIds) {
|
|
|
1771
1771
|
body: JSON.stringify(patch)
|
|
1772
1772
|
});
|
|
1773
1773
|
}
|
|
1774
|
+
export function updateNutritionDailyActiveCalories(patch, userIds) {
|
|
1775
|
+
const search = new URLSearchParams();
|
|
1776
|
+
appendUserIds(search, coerceUserIds(userIds));
|
|
1777
|
+
const suffix = search.size > 0 ? `?${search.toString()}` : "";
|
|
1778
|
+
return request(`/api/v1/health/weight-loss/daily-active-calories${suffix}`, {
|
|
1779
|
+
method: "PATCH",
|
|
1780
|
+
body: JSON.stringify(patch)
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
1774
1783
|
export function searchNutritionFoods(input) {
|
|
1775
1784
|
const search = new URLSearchParams();
|
|
1776
1785
|
appendUserIds(search, coerceUserIds(input.userIds));
|
|
@@ -1821,9 +1830,10 @@ export function parseNutritionFoodLogWithChatGpt(input) {
|
|
|
1821
1830
|
method: "POST",
|
|
1822
1831
|
body: JSON.stringify({
|
|
1823
1832
|
text: input.text,
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1833
|
+
mealTime: input.mealTime,
|
|
1834
|
+
imageRefs: input.imageRefs,
|
|
1835
|
+
connectionId: input.connectionId,
|
|
1836
|
+
commitCandidate: input.commitCandidate
|
|
1827
1837
|
})
|
|
1828
1838
|
});
|
|
1829
1839
|
}
|
|
@@ -31,6 +31,7 @@ const CUSTOM_THEME_STORAGE_KEYS = [
|
|
|
31
31
|
"--secondary",
|
|
32
32
|
"--tertiary",
|
|
33
33
|
"--surface",
|
|
34
|
+
"--canvas",
|
|
34
35
|
"--surface-low",
|
|
35
36
|
"--surface-panel",
|
|
36
37
|
"--surface-high",
|
|
@@ -41,6 +42,9 @@ const CUSTOM_THEME_STORAGE_KEYS = [
|
|
|
41
42
|
"--card-gradient",
|
|
42
43
|
"--card-shadow",
|
|
43
44
|
"--card-shadow-hover",
|
|
45
|
+
"--ui-accent",
|
|
46
|
+
"--ui-ink",
|
|
47
|
+
"--ui-ink-muted",
|
|
44
48
|
"--forge-body-ambient-primary",
|
|
45
49
|
"--forge-body-ambient-secondary",
|
|
46
50
|
"--forge-body-gradient-start",
|
|
@@ -271,6 +275,7 @@ export function buildForgeThemeVariables(theme) {
|
|
|
271
275
|
"--secondary": theme.secondary,
|
|
272
276
|
"--tertiary": theme.tertiary,
|
|
273
277
|
"--surface": theme.canvas,
|
|
278
|
+
"--canvas": theme.canvas,
|
|
274
279
|
"--surface-low": theme.panelLow,
|
|
275
280
|
"--surface-panel": theme.panel,
|
|
276
281
|
"--surface-high": theme.panelHigh,
|
|
@@ -281,6 +286,9 @@ export function buildForgeThemeVariables(theme) {
|
|
|
281
286
|
"--card-gradient": `linear-gradient(180deg, ${alpha(cardTop, 0.96)}, ${alpha(theme.panelLow, 0.94)})`,
|
|
282
287
|
"--card-shadow": `0 24px 60px ${alpha(theme.canvas, 0.3)}`,
|
|
283
288
|
"--card-shadow-hover": `0 32px 80px ${alpha(theme.canvas, 0.38)}`,
|
|
289
|
+
"--ui-accent": theme.primary,
|
|
290
|
+
"--ui-ink": theme.ink,
|
|
291
|
+
"--ui-ink-muted": alpha(theme.ink, 0.58),
|
|
284
292
|
"--forge-body-ambient-primary": alpha(theme.primary, 0.2),
|
|
285
293
|
"--forge-body-ambient-secondary": alpha(theme.secondary, 0.14),
|
|
286
294
|
"--forge-body-gradient-start": mixHex(theme.panel, theme.primary, 0.08),
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "forge-openclaw-plugin",
|
|
3
3
|
"name": "Forge",
|
|
4
4
|
"description": "Curated OpenClaw adapter for the Forge collaboration API, UI entrypoint, and localhost auto-start runtime.",
|
|
5
|
-
"version": "0.2.
|
|
5
|
+
"version": "0.2.102",
|
|
6
6
|
"activation": {
|
|
7
7
|
"onStartup": true,
|
|
8
8
|
"onCapabilities": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forge-openclaw-plugin",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.102",
|
|
4
4
|
"description": "Curated OpenClaw adapter for the Forge collaboration API, UI entrypoint, and localhost auto-start runtime.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"openclaw": "2026.5.4"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
+
"@azure/msal-node": "^5.1.2",
|
|
50
51
|
"@dnd-kit/core": "^6.3.1",
|
|
51
52
|
"@dnd-kit/sortable": "^10.0.0",
|
|
52
53
|
"@dnd-kit/utilities": "^3.2.2",
|
|
53
|
-
"@azure/msal-node": "^5.1.2",
|
|
54
54
|
"@fastify/cors": "^10.0.1",
|
|
55
55
|
"@fastify/multipart": "^9.4.0",
|
|
56
56
|
"@fontsource-variable/plus-jakarta-sans": "^5.2.8",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"react-hook-form": "^7.57.0",
|
|
90
90
|
"react-is": "^19.2.5",
|
|
91
91
|
"react-redux": "^9.2.0",
|
|
92
|
-
"react-router-dom": "^7.
|
|
92
|
+
"react-router-dom": "^7.16.0",
|
|
93
93
|
"recharts": "^3.1.0",
|
|
94
94
|
"sigma": "^3.0.2",
|
|
95
95
|
"tailwind-merge": "^3.3.1",
|