forge-openclaw-plugin 0.2.110 → 0.2.112

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.
Files changed (103) hide show
  1. package/dist/assets/{activity-page-BdeoV3N4.js → activity-page-DPPiiyLO.js} +1 -1
  2. package/dist/assets/{ai-surface-workspace-BCbQUekv.js → ai-surface-workspace-B_fV9C4s.js} +1 -1
  3. package/dist/assets/{atlas-panel-DTnRBOZx.js → atlas-panel-BPTJyMcI.js} +1 -1
  4. package/dist/assets/{calendar-page-YDexXy_e.js → calendar-page-D4DcRQv7.js} +1 -1
  5. package/dist/assets/{calendar-rules-B_aOcMi3.js → calendar-rules-Cl_xMrBn.js} +1 -1
  6. package/dist/assets/{calendar-week-toolbar-BTbIzq3e.js → calendar-week-toolbar-BARSOEO9.js} +1 -1
  7. package/dist/assets/{companion-sync-lab-page-DKouMut9.js → companion-sync-lab-page-COFYDI3w.js} +1 -1
  8. package/dist/assets/{daily-metrics-dashboard-B3UCGG1t.js → daily-metrics-dashboard-BNGQlJkQ.js} +1 -1
  9. package/dist/assets/{entity-note-count-link-DUxobQUt.js → entity-note-count-link-BX93WYgh.js} +1 -1
  10. package/dist/assets/{entity-notes-surface-BdHBn8rx.js → entity-notes-surface-CBlKc-x-.js} +1 -1
  11. package/dist/assets/{execution-board-R5-oyf-Z.js → execution-board-Dh41UeKR.js} +1 -1
  12. package/dist/assets/{faceted-token-search-DtO6OUwQ.js → faceted-token-search-BgxYH_gW.js} +1 -1
  13. package/dist/assets/{flagship-signal-deck-B9k46sWA.js → flagship-signal-deck-bolzzK8q.js} +1 -1
  14. package/dist/assets/{floating-action-menu-DBzfnJOx.js → floating-action-menu-C5H-Wr2B.js} +1 -1
  15. package/dist/assets/{goal-detail-page-Mr_gnZ2l.js → goal-detail-page-CQeFnGDJ.js} +1 -1
  16. package/dist/assets/{goals-page-BG7FuqK1.js → goals-page-BTg9crEK.js} +1 -1
  17. package/dist/assets/{habits-page-CGdaOqL3.js → habits-page-C4vqk346.js} +1 -1
  18. package/dist/assets/{index-BP9__l6C.js → index-By3tQxiE.js} +2 -2
  19. package/dist/assets/{insight-flow-dialog-BUv06Vn-.js → insight-flow-dialog-JPYCsTKI.js} +1 -1
  20. package/dist/assets/{insights-page-BgD1_1we.js → insights-page-CFhVMlVL.js} +1 -1
  21. package/dist/assets/{kanban-page-DvZSN-Bi.js → kanban-page-DC3IDsnh.js} +1 -1
  22. package/dist/assets/{knowledge-graph-page-BXWXtPvo.js → knowledge-graph-page-DucyRYTZ.js} +1 -1
  23. package/dist/assets/{life-force-page-CwjHvpzu.js → life-force-page-UrXfxaSO.js} +1 -1
  24. package/dist/assets/{life-force-workspace-Ct70SsNQ.js → life-force-workspace-BhPNH7ad.js} +1 -1
  25. package/dist/assets/{metric-tile-DCxLxNli.js → metric-tile-DtRPjN4V.js} +1 -1
  26. package/dist/assets/{movement-page-C06ebiYk.js → movement-page-DCIdTQEN.js} +1 -1
  27. package/dist/assets/{note-markdown-3wB52NOn.js → note-markdown-CepDxj3v.js} +1 -1
  28. package/dist/assets/{note-tags-input-Blg5Gqz_.js → note-tags-input-BXYaDkOr.js} +1 -1
  29. package/dist/assets/{notes-page-CSkjizyK.js → notes-page-Bl1LlCLo.js} +1 -1
  30. package/dist/assets/{open-in-graph-button-CDHxzS8B.js → open-in-graph-button-C263zl5l.js} +1 -1
  31. package/dist/assets/{orbit-map-OV-GcUZl.js → orbit-map-Cb_AJyIj.js} +1 -1
  32. package/dist/assets/{overview-page-Cw3pI34n.js → overview-page-C2yLity7.js} +1 -1
  33. package/dist/assets/{page-hero-DgnhI5es.js → page-hero-5RTqAI88.js} +1 -1
  34. package/dist/assets/{pill-cluster-DIGkIvKN.js → pill-cluster-CBrrtZBm.js} +1 -1
  35. package/dist/assets/{preference-entity-handoff-button-LT_GBuqB.js → preference-entity-handoff-button-BQzg2J4k.js} +1 -1
  36. package/dist/assets/{preferences-page-Dkvz7nkU.js → preferences-page-DekYF-Yz.js} +1 -1
  37. package/dist/assets/{project-collections-BsAT8WYE.js → project-collections-BVXB8PPF.js} +1 -1
  38. package/dist/assets/{project-detail-page-DsJUWg8k.js → project-detail-page-CQlrLEn9.js} +1 -1
  39. package/dist/assets/{project-management-hierarchy-page-CIy0wAp8.js → project-management-hierarchy-page--mzM_zRE.js} +1 -1
  40. package/dist/assets/{project-management-section-nav-ClB2S1FW.js → project-management-section-nav-DQl0qRWy.js} +1 -1
  41. package/dist/assets/{projects-page-Da1bZLSH.js → projects-page-Dr_0NdVP.js} +1 -1
  42. package/dist/assets/{psyche-behaviors-page-D0uwf78o.js → psyche-behaviors-page-DOUaCWON.js} +1 -1
  43. package/dist/assets/{psyche-flashcards-page-e_qwwsOf.js → psyche-flashcards-page-BA84fO_X.js} +1 -1
  44. package/dist/assets/{psyche-goal-map-page-BIY028Wx.js → psyche-goal-map-page-DpXAg1Vf.js} +1 -1
  45. package/dist/assets/{psyche-graph-Y1UKALEm.js → psyche-graph-BxcbAbXt.js} +1 -1
  46. package/dist/assets/{psyche-metrics-page-DDkGJzo_.js → psyche-metrics-page-D8JQEoOl.js} +1 -1
  47. package/dist/assets/{psyche-mode-guide-page-C7mD9uiv.js → psyche-mode-guide-page-CBlIS5N_.js} +1 -1
  48. package/dist/assets/{psyche-modes-page-RUdaOQWr.js → psyche-modes-page-DE6KDK_1.js} +1 -1
  49. package/dist/assets/{psyche-page-D3FZy__c.js → psyche-page-Dkh7R2Dc.js} +1 -1
  50. package/dist/assets/{psyche-patterns-page-BSD35F41.js → psyche-patterns-page-DbCNRuww.js} +1 -1
  51. package/dist/assets/{psyche-questionnaire-builder-page-BpgUTMgj.js → psyche-questionnaire-builder-page-DnraDj1H.js} +1 -1
  52. package/dist/assets/{psyche-questionnaire-detail-page-DwjyjNhg.js → psyche-questionnaire-detail-page-DQ6zNQkk.js} +1 -1
  53. package/dist/assets/{psyche-questionnaire-run-detail-page-mJ-DgeB-.js → psyche-questionnaire-run-detail-page-BGrOIX0B.js} +1 -1
  54. package/dist/assets/{psyche-questionnaire-run-page-YuMBkH1G.js → psyche-questionnaire-run-page-Bg3BhBHb.js} +1 -1
  55. package/dist/assets/{psyche-questionnaires-page-CNglToKh.js → psyche-questionnaires-page-BEreTNjG.js} +1 -1
  56. package/dist/assets/{psyche-report-detail-page-CV6tbLxz.js → psyche-report-detail-page-Br9KlJBG.js} +1 -1
  57. package/dist/assets/{psyche-reports-page-BEOe8OPA.js → psyche-reports-page-Bk6QpAEF.js} +1 -1
  58. package/dist/assets/{psyche-schemas-beliefs-page-KIRqmO8C.js → psyche-schemas-beliefs-page-Db8d2ga7.js} +1 -1
  59. package/dist/assets/{psyche-screen-time-page-DvXuwgU1.js → psyche-screen-time-page-NazHUAkT.js} +1 -1
  60. package/dist/assets/{psyche-self-observation-page-E6yDPBm1.js → psyche-self-observation-page-H6FToucM.js} +1 -1
  61. package/dist/assets/{psyche-values-page-CSLG7C6a.js → psyche-values-page-DqM382-6.js} +1 -1
  62. package/dist/assets/{report-chain-fields-BYEp3tRr.js → report-chain-fields-nW4zndrM.js} +1 -1
  63. package/dist/assets/{rewards-page-pAa_MIte.js → rewards-page-C-tZVnIK.js} +1 -1
  64. package/dist/assets/{scheduling-rules-editor-BmGrjC9q.js → scheduling-rules-editor-DGF-044c.js} +1 -1
  65. package/dist/assets/{schema-badge-IVJ4SoeC.js → schema-badge-57AJ3FY-.js} +1 -1
  66. package/dist/assets/{select-menu-BE5AIdgO.js → select-menu-mfaklv7r.js} +1 -1
  67. package/dist/assets/{settings-agents-page-hqI0IaNx.js → settings-agents-page-CPJeeYg0.js} +1 -1
  68. package/dist/assets/{settings-bin-page-2bPjFtZ3.js → settings-bin-page-D3eX5aNf.js} +1 -1
  69. package/dist/assets/{settings-calendar-page-u_TfZJEh.js → settings-calendar-page-Bgx8NIsP.js} +1 -1
  70. package/dist/assets/{settings-data-page-DSQ14F2i.js → settings-data-page-BuMSUjpp.js} +1 -1
  71. package/dist/assets/{settings-logs-page-BU0CJhDM.js → settings-logs-page-CHb2GNUM.js} +1 -1
  72. package/dist/assets/{settings-mobile-page-B1fQ61BB.js → settings-mobile-page-ClUvXhJg.js} +1 -1
  73. package/dist/assets/{settings-models-page-B0Dis_c_.js → settings-models-page-njK6D7zc.js} +1 -1
  74. package/dist/assets/{settings-page-V4ibXIp9.js → settings-page-Dm--cx6B.js} +1 -1
  75. package/dist/assets/{settings-rewards-page-DeCGBNn5.js → settings-rewards-page-3aShLM3A.js} +1 -1
  76. package/dist/assets/{settings-section-nav-DV5umEkp.js → settings-section-nav-BWox23Qv.js} +1 -1
  77. package/dist/assets/{settings-users-page-BB8Dzd_P.js → settings-users-page-D-hEPpgQ.js} +1 -1
  78. package/dist/assets/{settings-wiki-page-B0k0KRsU.js → settings-wiki-page-CC-rOtDm.js} +1 -1
  79. package/dist/assets/{sleep-page-CPwUb-em.js → sleep-page-Cm_Ei2w1.js} +1 -1
  80. package/dist/assets/{sports-page-Cl4vZVwh.js → sports-page-CqSI-j-H.js} +1 -1
  81. package/dist/assets/{strategies-page-DhFXf-g3.js → strategies-page-BuJ4zLLv.js} +1 -1
  82. package/dist/assets/{strategy-detail-page-B2gotRKI.js → strategy-detail-page-CLmy0jbW.js} +1 -1
  83. package/dist/assets/{strategy-dialog-DD1bbrRB.js → strategy-dialog-DnJix1ys.js} +1 -1
  84. package/dist/assets/{surface-98myBzix.js → surface-DRNu5Fpz.js} +1 -1
  85. package/dist/assets/{task-detail-page-nx4eQbMW.js → task-detail-page-DTnNjW33.js} +1 -1
  86. package/dist/assets/{timebox-planning-dialog-DoZ9zUra.js → timebox-planning-dialog-DckIr1K4.js} +1 -1
  87. package/dist/assets/{today-page-7BH7Yne1.js → today-page-Cgk4HBPK.js} +1 -1
  88. package/dist/assets/{training-load-page-E82pNn1-.js → training-load-page-C-7iINaB.js} +1 -1
  89. package/dist/assets/{vitals-page-D64WlwVv.js → vitals-page-CqE4bYMf.js} +1 -1
  90. package/dist/assets/{weekly-review-page-BkRxxm7Q.js → weekly-review-page-DFmuzzig.js} +1 -1
  91. package/dist/assets/{weight-loss-page-DPbg7rTC.js → weight-loss-page-CWtgeuti.js} +3 -3
  92. package/dist/assets/{wiki-article-markdown-B0Q6082A.js → wiki-article-markdown-BkQg8Hne.js} +1 -1
  93. package/dist/assets/{wiki-editor-page-Tkb50wEA.js → wiki-editor-page-BYKcdX5I.js} +1 -1
  94. package/dist/assets/{wiki-ingest-history-page-CcQzkZRr.js → wiki-ingest-history-page-D_p4myw1.js} +1 -1
  95. package/dist/assets/{wiki-ingest-modal-D6yft0Qb.js → wiki-ingest-modal-C-CidueO.js} +1 -1
  96. package/dist/assets/{wiki-page-DEND1jmD.js → wiki-page-DYpg9ZEO.js} +1 -1
  97. package/dist/assets/{workbench-flow-page-CkNI03j_.js → workbench-flow-page-Q3r2IJty.js} +1 -1
  98. package/dist/assets/{workbench-page-W3zQpeWr.js → workbench-page-BFfWMGm6.js} +1 -1
  99. package/dist/assets/{workout-detail-page-BVSZv53z.js → workout-detail-page-DeDyz1Kk.js} +1 -1
  100. package/dist/index.html +1 -1
  101. package/dist/server/server/src/health-weight-loss.js +30 -11
  102. package/openclaw.plugin.json +1 -1
  103. package/package.json +1 -1
@@ -1,2 +1,2 @@
1
1
  const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/maps-C-yOWiDN.js","assets/vendor-Dnkkx2co.js","assets/vendor-CRS-psbw.css","assets/maps-B-YMMjus.css"])))=>i.map(i=>d[i]);
2
- import{eH as D,S as H,E as B,c as j,C as c,T as E,I as P,B as I,eM as K,eN as W}from"./index-BP9__l6C.js";import{cc as Q,r as h,j as e,aC as O,bk as q,bG as Z,bL as G,dw as X,bX as Y}from"./vendor-Dnkkx2co.js";import{j as U,i as V,k as J}from"./state-vCcAT5Hq.js";import"./maps-C-yOWiDN.js";import{P as ee}from"./page-hero-DgnhI5es.js";import{R as C,A as te,C as ae,X as T,Y as _,T as z,a as se,e as ie,B as re}from"./charts-DFnEuIMB.js";import"./motion-Lt5B1XuE.js";import"./ui-C1iwpj2-.js";import"./forms-hB0SqEh-.js";import"./board-dIX6etHh.js";import"./graph-DDUZNRsO.js";const A={below_z1:"#94a3b8",zone_1:"#38bdf8",zone_2:"#22c55e",zone_3:"#eab308",zone_4:"#f97316",zone_5:"#ef4444"};function k(t){return t?`${Math.round(t/60)}m`:"0m"}function F(t,s){const o=new Intl.DateTimeFormat(void 0,{weekday:"short",day:"numeric",month:"short"}),n=new Intl.DateTimeFormat(void 0,{hour:"2-digit",minute:"2-digit"});return`${o.format(new Date(t))} · ${n.format(new Date(t))} - ${n.format(new Date(s))}`}function $(t){const s=typeof t=="number"?Math.floor(t):Number.parseFloat(String(t??""));return Number.isFinite(s)?new Date(s).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}):""}function ne(t,s){if(typeof t=="number"){const o=Number.isInteger(t)?String(t):t.toFixed(1);return s&&s!=="count"?`${o} ${s}`:o}return typeof t=="boolean"?t?"Yes":"No":t==null?"n/a":String(t)}function oe(t){return t.length===0?null:{minLat:Math.min(...t.map(s=>s.latitude)),maxLat:Math.max(...t.map(s=>s.latitude)),minLon:Math.min(...t.map(s=>s.longitude)),maxLon:Math.max(...t.map(s=>s.longitude))}}function le({points:t}){var g;const s=h.useRef(null),[o,n]=h.useState(!1),u=typeof window<"u"?((g=window.localStorage.getItem("forge.map.tile-url"))==null?void 0:g.trim())??"":"";h.useEffect(()=>{let x=!1,i=null;if(!u||!s.current||t.length<2){n(!1);return}return K(()=>import("./maps-C-yOWiDN.js").then(r=>r.m),__vite__mapDeps([0,1,2,3])).then(r=>{x||!s.current||(i=new r.Map({container:s.current,style:{version:8,sources:{tiles:{type:"raster",tiles:[u],tileSize:256}},layers:[{id:"tiles",type:"raster",source:"tiles"}]},center:[t[0].longitude,t[0].latitude],zoom:13,attributionControl:!1}),i.on("load",()=>{if(!i)return;const d=t.map(m=>[m.longitude,m.latitude]);i.addSource("route",{type:"geojson",data:{type:"Feature",properties:{},geometry:{type:"LineString",coordinates:d}}}),i.addLayer({id:"route",type:"line",source:"route",paint:{"line-color":"#f97316","line-width":4}});const f=d.reduce((m,p)=>m.extend(p),new r.LngLatBounds(d[0],d[0]));i.fitBounds(f,{padding:44,maxZoom:15}),n(!0)}))}),()=>{x=!0,i==null||i.remove()}},[t,u]);const l=oe(t),v=h.useMemo(()=>{if(!l||t.length<2)return"";const x=720,i=280,r=Math.max(1e-6,l.maxLon-l.minLon),d=Math.max(1e-6,l.maxLat-l.minLat);return t.map(f=>{const m=(f.longitude-l.minLon)/r*x,p=i-(f.latitude-l.minLat)/d*i;return`${m.toFixed(1)},${p.toFixed(1)}`}).join(" ")},[l,t]);return e.jsxs("div",{className:"relative min-h-[280px] overflow-hidden rounded-[8px] border border-[var(--ui-border-subtle)] bg-[var(--ui-surface-1)]",children:[e.jsx("div",{ref:s,className:"absolute inset-0"}),o?null:e.jsxs("svg",{viewBox:"0 0 720 280",className:"absolute inset-0 h-full w-full",children:[e.jsx("rect",{width:"720",height:"280",fill:"var(--ui-surface-1)"}),v?e.jsx("polyline",{points:v,fill:"none",stroke:"#f97316",strokeWidth:"5",strokeLinecap:"round",strokeLinejoin:"round"}):null]}),e.jsx("div",{className:"absolute left-3 top-3 max-w-[calc(100%-1.5rem)] rounded-[8px] border border-[var(--ui-border-subtle)] bg-[var(--surface-glass)] px-3 py-2 text-xs text-[var(--ui-ink-medium)] backdrop-blur",children:u?"Local-first map tiles configured":"No tile source configured; showing private route shape only"})]})}function de({zones:t}){return e.jsx("div",{className:"grid gap-3",children:t.map(s=>e.jsxs("div",{className:"grid gap-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 text-sm",children:[e.jsx("span",{className:"min-w-0 break-words text-[var(--ui-ink-medium)] [overflow-wrap:anywhere]",children:s.label}),e.jsxs("span",{className:"shrink-0 text-[var(--ui-ink-strong)]",children:[(s.percentage*100).toFixed(1),"% · ",k(s.seconds)]})]}),e.jsx("div",{className:"h-2 overflow-hidden rounded-full bg-[var(--ui-surface-2)]",children:e.jsx("div",{className:"h-full rounded-full",style:{width:`${Math.max(1,s.percentage*100)}%`,background:A[s.key]??"#f8fafc"}})})]},s.key))})}function ke(){var p,N,b,y,S,L,M,R;const{workoutId:t=""}=Q(),s=U(),o=V({queryKey:["workout-detail",t],queryFn:()=>W(t),enabled:t.length>0}),n=o.data,[u,l]=h.useState(""),[v,g]=h.useState("");h.useEffect(()=>{n!=null&&n.workout&&(l(n.workout.meaningText??""),g(n.workout.tags.join(", ")))},[n==null?void 0:n.workout]);const x=J({mutationFn:()=>D(t,{meaningText:u,tags:v.split(",").map(a=>a.trim()).filter(Boolean)}),onSuccess:async()=>{await s.invalidateQueries({queryKey:["workout-detail",t]}),await s.invalidateQueries({queryKey:["forge-fitness"]})}});if(o.isLoading)return e.jsx(H,{title:"Loading workout"});if(o.isError||!n)return e.jsx(B,{eyebrow:"Workout detail",error:o.error??new Error("Forge could not load this workout detail."),onRetry:()=>void o.refetch()});const{workout:i,analytics:r,evidence:d}=n,f=d.timeSeries.filter(a=>a.metricKey==="heart_rate").map((a,w)=>({time:Date.parse(a.startedAt)+w/1e3,bpm:a.value})),m=r.zoneDurations.map(a=>({zone:a.label,minutes:Math.round(a.seconds/60),fill:A[a.key]??"#f8fafc"}));return e.jsxs("div",{className:"grid gap-6",children:[e.jsxs(O,{to:"/sports",className:"inline-flex w-fit items-center gap-2 text-sm text-[var(--ui-ink-soft)] transition hover:text-[var(--ui-ink-strong)]",children:[e.jsx(q,{className:"size-4"}),"Back to sports"]}),e.jsx(ee,{eyebrow:"Workout evidence",title:i.workoutTypeLabel??i.workoutType,description:`${F(i.startedAt,i.endedAt)} · ${i.sourceDevice||"Apple Health"}`,actions:e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(j,{children:k(i.durationSeconds)}),e.jsxs(j,{tone:"meta",children:[r.confidence," HR zones"]}),(p=r.routeSummary)!=null&&p.hasRoute?e.jsxs(j,{tone:"meta",children:[r.routeSummary.pointCount," route points"]}):null]})}),e.jsxs("section",{className:"grid gap-4 lg:grid-cols-4",children:[e.jsxs(c,{children:[e.jsx("div",{className:"text-sm text-[var(--ui-ink-soft)]",children:"Avg HR"}),e.jsx("div",{className:"mt-3 font-display text-4xl text-[var(--ui-ink-strong)]",children:r.hrSummary.averageHr??i.averageHeartRate??"n/a"}),e.jsx("div",{className:"mt-1 text-sm text-[var(--ui-ink-faint)]",children:"bpm"})]}),e.jsxs(c,{children:[e.jsx("div",{className:"text-sm text-[var(--ui-ink-soft)]",children:"Max HR"}),e.jsx("div",{className:"mt-3 font-display text-4xl text-[var(--ui-ink-strong)]",children:r.hrSummary.maxHr??i.maxHeartRate??"n/a"}),e.jsx("div",{className:"mt-1 text-sm text-[var(--ui-ink-faint)]",children:"bpm"})]}),e.jsxs(c,{children:[e.jsx("div",{className:"text-sm text-[var(--ui-ink-soft)]",children:"Training load"}),e.jsx("div",{className:"mt-3 font-display text-4xl text-[var(--ui-ink-strong)]",children:r.load.trimp??"n/a"}),e.jsx("div",{className:"mt-1 text-sm text-[var(--ui-ink-faint)]",children:"Forge TRIMP"})]}),e.jsxs(c,{children:[e.jsx("div",{className:"text-sm text-[var(--ui-ink-soft)]",children:"HR coverage"}),e.jsxs("div",{className:"mt-3 font-display text-4xl text-[var(--ui-ink-strong)]",children:[Math.round((r.dataQuality.sampleCoverage??0)*100),"%"]}),e.jsxs("div",{className:"mt-1 text-sm text-[var(--ui-ink-faint)]",children:[r.dataQuality.heartRateSampleCount??0," samples"]})]})]}),e.jsxs("section",{className:"grid min-w-0 gap-4 xl:grid-cols-[minmax(0,1.25fr)_minmax(280px,0.75fr)]",children:[e.jsxs(c,{className:"min-h-[360px] min-w-0 overflow-hidden",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[var(--ui-ink-strong)]",children:[e.jsx(Z,{className:"size-4 text-[var(--primary)]"}),"Heart-rate timeline"]}),e.jsx("div",{className:"mt-4 h-[300px]",children:f.length>0?e.jsx(C,{width:"100%",height:"100%",children:e.jsxs(te,{data:f,children:[e.jsx("defs",{children:e.jsxs("linearGradient",{id:"hrFill",x1:"0",y1:"0",x2:"0",y2:"1",children:[e.jsx("stop",{offset:"0%",stopColor:"#ef4444",stopOpacity:.38}),e.jsx("stop",{offset:"100%",stopColor:"#ef4444",stopOpacity:.04})]})}),e.jsx(ae,{stroke:"var(--ui-border-subtle)",vertical:!1}),e.jsx(T,{dataKey:"time",interval:"preserveStartEnd",tick:{fill:"var(--ui-ink-soft)",fontSize:11},tickFormatter:$,type:"number",domain:["dataMin","dataMax"]}),e.jsx(_,{tick:{fill:"var(--ui-ink-soft)",fontSize:11},width:42}),e.jsx(z,{labelFormatter:$,contentStyle:{background:"var(--surface-glass)",border:"1px solid var(--ui-border-subtle)",borderRadius:8,color:"var(--ui-ink-strong)"}}),e.jsx(se,{type:"monotone",dataKey:"bpm",stroke:"#ef4444",fill:"url(#hrFill)",strokeWidth:2,dot:!1})]})}):e.jsx("div",{className:"grid h-full place-items-center rounded-[8px] bg-[var(--ui-surface-1)] text-sm text-[var(--ui-ink-soft)]",children:"No raw HR timeline has been synced for this workout yet."})})]}),e.jsxs(c,{className:"min-w-0 overflow-hidden",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[var(--ui-ink-strong)]",children:[e.jsx(G,{className:"size-4 text-[var(--primary)]"}),"Zone mix"]}),e.jsx("div",{className:"mt-4",children:e.jsx(de,{zones:r.zoneDurations})}),e.jsx("div",{className:"mt-5 h-[180px]",children:e.jsx(C,{width:"100%",height:"100%",children:e.jsxs(ie,{data:m,children:[e.jsx(T,{dataKey:"zone",tick:{fill:"var(--ui-ink-soft)",fontSize:10}}),e.jsx(_,{tick:{fill:"var(--ui-ink-soft)",fontSize:10},width:34}),e.jsx(z,{contentStyle:{background:"var(--surface-glass)",border:"1px solid var(--ui-border-subtle)",borderRadius:8,color:"var(--ui-ink-strong)"}}),e.jsx(re,{dataKey:"minutes",radius:[4,4,0,0]})]})})})]})]}),e.jsxs("section",{className:"grid min-w-0 gap-4 xl:grid-cols-[minmax(0,1fr)_360px]",children:[e.jsxs(c,{className:"min-w-0 overflow-hidden",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[var(--ui-ink-strong)]",children:[e.jsx(X,{className:"size-4 text-[var(--primary)]"}),"Route"]}),e.jsx("div",{className:"mt-4",children:d.routePoints.length>1?e.jsx(le,{points:d.routePoints}):e.jsx("div",{className:"grid min-h-[240px] place-items-center rounded-[8px] bg-[var(--ui-surface-1)] text-sm text-[var(--ui-ink-soft)]",children:"No route evidence is available for this workout."})})]}),e.jsxs(c,{className:"min-w-0 overflow-hidden",children:[e.jsx("div",{className:"text-[var(--ui-ink-strong)]",children:"Captured metrics"}),e.jsx("div",{className:"mt-4 grid gap-3",children:(((N=i.details)==null?void 0:N.metrics)??[]).slice(0,14).map(a=>e.jsxs("div",{className:"min-w-0 rounded-[8px] bg-[var(--ui-surface-1)] px-3 py-2",children:[e.jsx("div",{className:"break-words text-sm text-[var(--ui-ink-soft)] [overflow-wrap:anywhere]",children:a.label}),e.jsx("div",{className:"mt-1 break-words text-[var(--ui-ink-strong)] [overflow-wrap:anywhere]",children:ne(a.value,a.unit)})]},`${a.category}:${a.key}:${a.statistic}`))})]})]}),e.jsxs("section",{className:"grid min-w-0 gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(280px,0.7fr)]",children:[e.jsxs(c,{className:"min-w-0 overflow-hidden",children:[e.jsx("div",{className:"text-[var(--ui-ink-strong)]",children:"Events and phases"}),e.jsxs("div",{className:"mt-4 grid gap-3",children:[[...((b=i.details)==null?void 0:b.events)??[],...((y=i.details)==null?void 0:y.components)??[]].slice(0,18).map((a,w)=>e.jsxs("div",{className:"min-w-0 rounded-[8px] bg-[var(--ui-surface-1)] px-4 py-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsx("div",{className:"min-w-0 break-words text-[var(--ui-ink-strong)] [overflow-wrap:anywhere]",children:"label"in a?a.label:a.activity.canonicalLabel}),e.jsx(j,{tone:"meta",children:k(a.durationSeconds)})]}),e.jsx("div",{className:"mt-1 text-sm text-[var(--ui-ink-soft)]",children:F(a.startedAt,a.endedAt??a.startedAt)})]},`${"type"in a?a.type:a.externalUid}:${a.startedAt}:${w}`)),(((L=(S=i.details)==null?void 0:S.events)==null?void 0:L.length)??0)+(((R=(M=i.details)==null?void 0:M.components)==null?void 0:R.length)??0)===0?e.jsx("div",{className:"rounded-[8px] bg-[var(--ui-surface-1)] p-4 text-sm text-[var(--ui-ink-soft)]",children:"No provider events or phases were captured."}):null]})]}),e.jsxs(c,{className:"min-w-0 overflow-hidden",children:[e.jsx("div",{className:"text-[var(--ui-ink-strong)]",children:"Reflection"}),e.jsxs("div",{className:"mt-4 grid gap-4",children:[e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-[var(--ui-ink-soft)]",children:"Meaning and impact"}),e.jsx(E,{className:"min-h-[160px]",value:u,onChange:a=>l(a.target.value)})]}),e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-[var(--ui-ink-soft)]",children:"Tags"}),e.jsx(P,{value:v,onChange:a=>g(a.target.value)})]}),e.jsxs(I,{type:"button",pending:x.isPending,pendingLabel:"Saving",onClick:()=>x.mutate(),children:[e.jsx(Y,{className:"size-4"}),"Save reflection"]})]})]})]})]})}export{ke as WorkoutDetailPage};
2
+ import{eH as D,S as H,E as B,c as j,C as c,T as E,I as P,B as I,eM as K,eN as W}from"./index-By3tQxiE.js";import{cc as Q,r as h,j as e,aC as O,bk as q,bG as Z,bL as G,dw as X,bX as Y}from"./vendor-Dnkkx2co.js";import{j as U,i as V,k as J}from"./state-vCcAT5Hq.js";import"./maps-C-yOWiDN.js";import{P as ee}from"./page-hero-5RTqAI88.js";import{R as C,A as te,C as ae,X as T,Y as _,T as z,a as se,e as ie,B as re}from"./charts-DFnEuIMB.js";import"./motion-Lt5B1XuE.js";import"./ui-C1iwpj2-.js";import"./forms-hB0SqEh-.js";import"./board-dIX6etHh.js";import"./graph-DDUZNRsO.js";const A={below_z1:"#94a3b8",zone_1:"#38bdf8",zone_2:"#22c55e",zone_3:"#eab308",zone_4:"#f97316",zone_5:"#ef4444"};function k(t){return t?`${Math.round(t/60)}m`:"0m"}function F(t,s){const o=new Intl.DateTimeFormat(void 0,{weekday:"short",day:"numeric",month:"short"}),n=new Intl.DateTimeFormat(void 0,{hour:"2-digit",minute:"2-digit"});return`${o.format(new Date(t))} · ${n.format(new Date(t))} - ${n.format(new Date(s))}`}function $(t){const s=typeof t=="number"?Math.floor(t):Number.parseFloat(String(t??""));return Number.isFinite(s)?new Date(s).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}):""}function ne(t,s){if(typeof t=="number"){const o=Number.isInteger(t)?String(t):t.toFixed(1);return s&&s!=="count"?`${o} ${s}`:o}return typeof t=="boolean"?t?"Yes":"No":t==null?"n/a":String(t)}function oe(t){return t.length===0?null:{minLat:Math.min(...t.map(s=>s.latitude)),maxLat:Math.max(...t.map(s=>s.latitude)),minLon:Math.min(...t.map(s=>s.longitude)),maxLon:Math.max(...t.map(s=>s.longitude))}}function le({points:t}){var g;const s=h.useRef(null),[o,n]=h.useState(!1),u=typeof window<"u"?((g=window.localStorage.getItem("forge.map.tile-url"))==null?void 0:g.trim())??"":"";h.useEffect(()=>{let x=!1,i=null;if(!u||!s.current||t.length<2){n(!1);return}return K(()=>import("./maps-C-yOWiDN.js").then(r=>r.m),__vite__mapDeps([0,1,2,3])).then(r=>{x||!s.current||(i=new r.Map({container:s.current,style:{version:8,sources:{tiles:{type:"raster",tiles:[u],tileSize:256}},layers:[{id:"tiles",type:"raster",source:"tiles"}]},center:[t[0].longitude,t[0].latitude],zoom:13,attributionControl:!1}),i.on("load",()=>{if(!i)return;const d=t.map(m=>[m.longitude,m.latitude]);i.addSource("route",{type:"geojson",data:{type:"Feature",properties:{},geometry:{type:"LineString",coordinates:d}}}),i.addLayer({id:"route",type:"line",source:"route",paint:{"line-color":"#f97316","line-width":4}});const f=d.reduce((m,p)=>m.extend(p),new r.LngLatBounds(d[0],d[0]));i.fitBounds(f,{padding:44,maxZoom:15}),n(!0)}))}),()=>{x=!0,i==null||i.remove()}},[t,u]);const l=oe(t),v=h.useMemo(()=>{if(!l||t.length<2)return"";const x=720,i=280,r=Math.max(1e-6,l.maxLon-l.minLon),d=Math.max(1e-6,l.maxLat-l.minLat);return t.map(f=>{const m=(f.longitude-l.minLon)/r*x,p=i-(f.latitude-l.minLat)/d*i;return`${m.toFixed(1)},${p.toFixed(1)}`}).join(" ")},[l,t]);return e.jsxs("div",{className:"relative min-h-[280px] overflow-hidden rounded-[8px] border border-[var(--ui-border-subtle)] bg-[var(--ui-surface-1)]",children:[e.jsx("div",{ref:s,className:"absolute inset-0"}),o?null:e.jsxs("svg",{viewBox:"0 0 720 280",className:"absolute inset-0 h-full w-full",children:[e.jsx("rect",{width:"720",height:"280",fill:"var(--ui-surface-1)"}),v?e.jsx("polyline",{points:v,fill:"none",stroke:"#f97316",strokeWidth:"5",strokeLinecap:"round",strokeLinejoin:"round"}):null]}),e.jsx("div",{className:"absolute left-3 top-3 max-w-[calc(100%-1.5rem)] rounded-[8px] border border-[var(--ui-border-subtle)] bg-[var(--surface-glass)] px-3 py-2 text-xs text-[var(--ui-ink-medium)] backdrop-blur",children:u?"Local-first map tiles configured":"No tile source configured; showing private route shape only"})]})}function de({zones:t}){return e.jsx("div",{className:"grid gap-3",children:t.map(s=>e.jsxs("div",{className:"grid gap-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 text-sm",children:[e.jsx("span",{className:"min-w-0 break-words text-[var(--ui-ink-medium)] [overflow-wrap:anywhere]",children:s.label}),e.jsxs("span",{className:"shrink-0 text-[var(--ui-ink-strong)]",children:[(s.percentage*100).toFixed(1),"% · ",k(s.seconds)]})]}),e.jsx("div",{className:"h-2 overflow-hidden rounded-full bg-[var(--ui-surface-2)]",children:e.jsx("div",{className:"h-full rounded-full",style:{width:`${Math.max(1,s.percentage*100)}%`,background:A[s.key]??"#f8fafc"}})})]},s.key))})}function ke(){var p,N,b,y,S,L,M,R;const{workoutId:t=""}=Q(),s=U(),o=V({queryKey:["workout-detail",t],queryFn:()=>W(t),enabled:t.length>0}),n=o.data,[u,l]=h.useState(""),[v,g]=h.useState("");h.useEffect(()=>{n!=null&&n.workout&&(l(n.workout.meaningText??""),g(n.workout.tags.join(", ")))},[n==null?void 0:n.workout]);const x=J({mutationFn:()=>D(t,{meaningText:u,tags:v.split(",").map(a=>a.trim()).filter(Boolean)}),onSuccess:async()=>{await s.invalidateQueries({queryKey:["workout-detail",t]}),await s.invalidateQueries({queryKey:["forge-fitness"]})}});if(o.isLoading)return e.jsx(H,{title:"Loading workout"});if(o.isError||!n)return e.jsx(B,{eyebrow:"Workout detail",error:o.error??new Error("Forge could not load this workout detail."),onRetry:()=>void o.refetch()});const{workout:i,analytics:r,evidence:d}=n,f=d.timeSeries.filter(a=>a.metricKey==="heart_rate").map((a,w)=>({time:Date.parse(a.startedAt)+w/1e3,bpm:a.value})),m=r.zoneDurations.map(a=>({zone:a.label,minutes:Math.round(a.seconds/60),fill:A[a.key]??"#f8fafc"}));return e.jsxs("div",{className:"grid gap-6",children:[e.jsxs(O,{to:"/sports",className:"inline-flex w-fit items-center gap-2 text-sm text-[var(--ui-ink-soft)] transition hover:text-[var(--ui-ink-strong)]",children:[e.jsx(q,{className:"size-4"}),"Back to sports"]}),e.jsx(ee,{eyebrow:"Workout evidence",title:i.workoutTypeLabel??i.workoutType,description:`${F(i.startedAt,i.endedAt)} · ${i.sourceDevice||"Apple Health"}`,actions:e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(j,{children:k(i.durationSeconds)}),e.jsxs(j,{tone:"meta",children:[r.confidence," HR zones"]}),(p=r.routeSummary)!=null&&p.hasRoute?e.jsxs(j,{tone:"meta",children:[r.routeSummary.pointCount," route points"]}):null]})}),e.jsxs("section",{className:"grid gap-4 lg:grid-cols-4",children:[e.jsxs(c,{children:[e.jsx("div",{className:"text-sm text-[var(--ui-ink-soft)]",children:"Avg HR"}),e.jsx("div",{className:"mt-3 font-display text-4xl text-[var(--ui-ink-strong)]",children:r.hrSummary.averageHr??i.averageHeartRate??"n/a"}),e.jsx("div",{className:"mt-1 text-sm text-[var(--ui-ink-faint)]",children:"bpm"})]}),e.jsxs(c,{children:[e.jsx("div",{className:"text-sm text-[var(--ui-ink-soft)]",children:"Max HR"}),e.jsx("div",{className:"mt-3 font-display text-4xl text-[var(--ui-ink-strong)]",children:r.hrSummary.maxHr??i.maxHeartRate??"n/a"}),e.jsx("div",{className:"mt-1 text-sm text-[var(--ui-ink-faint)]",children:"bpm"})]}),e.jsxs(c,{children:[e.jsx("div",{className:"text-sm text-[var(--ui-ink-soft)]",children:"Training load"}),e.jsx("div",{className:"mt-3 font-display text-4xl text-[var(--ui-ink-strong)]",children:r.load.trimp??"n/a"}),e.jsx("div",{className:"mt-1 text-sm text-[var(--ui-ink-faint)]",children:"Forge TRIMP"})]}),e.jsxs(c,{children:[e.jsx("div",{className:"text-sm text-[var(--ui-ink-soft)]",children:"HR coverage"}),e.jsxs("div",{className:"mt-3 font-display text-4xl text-[var(--ui-ink-strong)]",children:[Math.round((r.dataQuality.sampleCoverage??0)*100),"%"]}),e.jsxs("div",{className:"mt-1 text-sm text-[var(--ui-ink-faint)]",children:[r.dataQuality.heartRateSampleCount??0," samples"]})]})]}),e.jsxs("section",{className:"grid min-w-0 gap-4 xl:grid-cols-[minmax(0,1.25fr)_minmax(280px,0.75fr)]",children:[e.jsxs(c,{className:"min-h-[360px] min-w-0 overflow-hidden",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[var(--ui-ink-strong)]",children:[e.jsx(Z,{className:"size-4 text-[var(--primary)]"}),"Heart-rate timeline"]}),e.jsx("div",{className:"mt-4 h-[300px]",children:f.length>0?e.jsx(C,{width:"100%",height:"100%",children:e.jsxs(te,{data:f,children:[e.jsx("defs",{children:e.jsxs("linearGradient",{id:"hrFill",x1:"0",y1:"0",x2:"0",y2:"1",children:[e.jsx("stop",{offset:"0%",stopColor:"#ef4444",stopOpacity:.38}),e.jsx("stop",{offset:"100%",stopColor:"#ef4444",stopOpacity:.04})]})}),e.jsx(ae,{stroke:"var(--ui-border-subtle)",vertical:!1}),e.jsx(T,{dataKey:"time",interval:"preserveStartEnd",tick:{fill:"var(--ui-ink-soft)",fontSize:11},tickFormatter:$,type:"number",domain:["dataMin","dataMax"]}),e.jsx(_,{tick:{fill:"var(--ui-ink-soft)",fontSize:11},width:42}),e.jsx(z,{labelFormatter:$,contentStyle:{background:"var(--surface-glass)",border:"1px solid var(--ui-border-subtle)",borderRadius:8,color:"var(--ui-ink-strong)"}}),e.jsx(se,{type:"monotone",dataKey:"bpm",stroke:"#ef4444",fill:"url(#hrFill)",strokeWidth:2,dot:!1})]})}):e.jsx("div",{className:"grid h-full place-items-center rounded-[8px] bg-[var(--ui-surface-1)] text-sm text-[var(--ui-ink-soft)]",children:"No raw HR timeline has been synced for this workout yet."})})]}),e.jsxs(c,{className:"min-w-0 overflow-hidden",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[var(--ui-ink-strong)]",children:[e.jsx(G,{className:"size-4 text-[var(--primary)]"}),"Zone mix"]}),e.jsx("div",{className:"mt-4",children:e.jsx(de,{zones:r.zoneDurations})}),e.jsx("div",{className:"mt-5 h-[180px]",children:e.jsx(C,{width:"100%",height:"100%",children:e.jsxs(ie,{data:m,children:[e.jsx(T,{dataKey:"zone",tick:{fill:"var(--ui-ink-soft)",fontSize:10}}),e.jsx(_,{tick:{fill:"var(--ui-ink-soft)",fontSize:10},width:34}),e.jsx(z,{contentStyle:{background:"var(--surface-glass)",border:"1px solid var(--ui-border-subtle)",borderRadius:8,color:"var(--ui-ink-strong)"}}),e.jsx(re,{dataKey:"minutes",radius:[4,4,0,0]})]})})})]})]}),e.jsxs("section",{className:"grid min-w-0 gap-4 xl:grid-cols-[minmax(0,1fr)_360px]",children:[e.jsxs(c,{className:"min-w-0 overflow-hidden",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[var(--ui-ink-strong)]",children:[e.jsx(X,{className:"size-4 text-[var(--primary)]"}),"Route"]}),e.jsx("div",{className:"mt-4",children:d.routePoints.length>1?e.jsx(le,{points:d.routePoints}):e.jsx("div",{className:"grid min-h-[240px] place-items-center rounded-[8px] bg-[var(--ui-surface-1)] text-sm text-[var(--ui-ink-soft)]",children:"No route evidence is available for this workout."})})]}),e.jsxs(c,{className:"min-w-0 overflow-hidden",children:[e.jsx("div",{className:"text-[var(--ui-ink-strong)]",children:"Captured metrics"}),e.jsx("div",{className:"mt-4 grid gap-3",children:(((N=i.details)==null?void 0:N.metrics)??[]).slice(0,14).map(a=>e.jsxs("div",{className:"min-w-0 rounded-[8px] bg-[var(--ui-surface-1)] px-3 py-2",children:[e.jsx("div",{className:"break-words text-sm text-[var(--ui-ink-soft)] [overflow-wrap:anywhere]",children:a.label}),e.jsx("div",{className:"mt-1 break-words text-[var(--ui-ink-strong)] [overflow-wrap:anywhere]",children:ne(a.value,a.unit)})]},`${a.category}:${a.key}:${a.statistic}`))})]})]}),e.jsxs("section",{className:"grid min-w-0 gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(280px,0.7fr)]",children:[e.jsxs(c,{className:"min-w-0 overflow-hidden",children:[e.jsx("div",{className:"text-[var(--ui-ink-strong)]",children:"Events and phases"}),e.jsxs("div",{className:"mt-4 grid gap-3",children:[[...((b=i.details)==null?void 0:b.events)??[],...((y=i.details)==null?void 0:y.components)??[]].slice(0,18).map((a,w)=>e.jsxs("div",{className:"min-w-0 rounded-[8px] bg-[var(--ui-surface-1)] px-4 py-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsx("div",{className:"min-w-0 break-words text-[var(--ui-ink-strong)] [overflow-wrap:anywhere]",children:"label"in a?a.label:a.activity.canonicalLabel}),e.jsx(j,{tone:"meta",children:k(a.durationSeconds)})]}),e.jsx("div",{className:"mt-1 text-sm text-[var(--ui-ink-soft)]",children:F(a.startedAt,a.endedAt??a.startedAt)})]},`${"type"in a?a.type:a.externalUid}:${a.startedAt}:${w}`)),(((L=(S=i.details)==null?void 0:S.events)==null?void 0:L.length)??0)+(((R=(M=i.details)==null?void 0:M.components)==null?void 0:R.length)??0)===0?e.jsx("div",{className:"rounded-[8px] bg-[var(--ui-surface-1)] p-4 text-sm text-[var(--ui-ink-soft)]",children:"No provider events or phases were captured."}):null]})]}),e.jsxs(c,{className:"min-w-0 overflow-hidden",children:[e.jsx("div",{className:"text-[var(--ui-ink-strong)]",children:"Reflection"}),e.jsxs("div",{className:"mt-4 grid gap-4",children:[e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-[var(--ui-ink-soft)]",children:"Meaning and impact"}),e.jsx(E,{className:"min-h-[160px]",value:u,onChange:a=>l(a.target.value)})]}),e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-[var(--ui-ink-soft)]",children:"Tags"}),e.jsx(P,{value:v,onChange:a=>g(a.target.value)})]}),e.jsxs(I,{type:"button",pending:x.isPending,pendingLabel:"Saving",onClick:()=>x.mutate(),children:[e.jsx(Y,{className:"size-4"}),"Save reflection"]})]})]})]})]})}export{ke as WorkoutDetailPage};
package/dist/index.html CHANGED
@@ -130,7 +130,7 @@
130
130
  }
131
131
  }
132
132
  </style>
133
- <script type="module" crossorigin src="/forge/assets/index-BP9__l6C.js"></script>
133
+ <script type="module" crossorigin src="/forge/assets/index-By3tQxiE.js"></script>
134
134
  <link rel="modulepreload" crossorigin href="/forge/assets/vendor-Dnkkx2co.js">
135
135
  <link rel="modulepreload" crossorigin href="/forge/assets/state-vCcAT5Hq.js">
136
136
  <link rel="modulepreload" crossorigin href="/forge/assets/motion-Lt5B1XuE.js">
@@ -5,6 +5,7 @@ import { getSettings } from "./repositories/settings.js";
5
5
  import { getDefaultUser, resolveUserForMutation } from "./repositories/users.js";
6
6
  import { readEncryptedSecret } from "./repositories/calendar.js";
7
7
  import { hallNiddkWeeklyRateKgToDailyEnergyAdjustment } from "../../src/lib/weight-loss-energy-model.js";
8
+ const ACTIVE_BASELINE_WINDOW_DAYS = 7;
8
9
  const optionalNumberSchema = z
9
10
  .union([z.coerce.number().finite(), z.null()])
10
11
  .optional();
@@ -397,7 +398,7 @@ function getDailyEnergyOverride(userId, dateKey) {
397
398
  function buildStoredEnergyModel(input) {
398
399
  const todayKey = input.dateKey;
399
400
  const start = new Date(`${todayKey}T00:00:00.000Z`);
400
- start.setUTCDate(start.getUTCDate() - 6);
401
+ start.setUTCDate(start.getUTCDate() - ACTIVE_BASELINE_WINDOW_DAYS);
401
402
  const startKey = start.toISOString().slice(0, 10);
402
403
  const dailySummaryRows = getDatabase()
403
404
  .prepare(`SELECT date_key, metrics_json
@@ -405,8 +406,9 @@ function buildStoredEnergyModel(input) {
405
406
  WHERE user_id = ?
406
407
  AND summary_type = 'vitals'
407
408
  AND date_key >= ?
409
+ AND date_key <= ?
408
410
  ORDER BY date_key DESC`)
409
- .all(input.userId, startKey);
411
+ .all(input.userId, startKey, todayKey);
410
412
  const dailyHealthKit = dailySummaryRows.map((row) => {
411
413
  const metrics = parseJson(row.metrics_json, {});
412
414
  return {
@@ -427,8 +429,9 @@ function buildStoredEnergyModel(input) {
427
429
  FROM health_workout_sessions
428
430
  WHERE user_id = ?
429
431
  AND date(started_at) >= ?
432
+ AND date(started_at) <= ?
430
433
  GROUP BY date(started_at)`)
431
- .all(input.userId, startKey);
434
+ .all(input.userId, startKey, todayKey);
432
435
  const movementRows = getDatabase()
433
436
  .prepare(`SELECT date(started_at) AS date_key,
434
437
  NULL AS active_energy_kcal,
@@ -437,8 +440,9 @@ function buildStoredEnergyModel(input) {
437
440
  FROM movement_trips
438
441
  WHERE user_id = ?
439
442
  AND date(started_at) >= ?
443
+ AND date(started_at) <= ?
440
444
  GROUP BY date(started_at)`)
441
- .all(input.userId, startKey);
445
+ .all(input.userId, startKey, todayKey);
442
446
  const workoutByDay = new Map(workoutRows.map((row) => [
443
447
  row.date_key,
444
448
  n(row.active_energy_kcal) || n(row.total_energy_kcal) || null
@@ -466,7 +470,8 @@ function buildStoredEnergyModel(input) {
466
470
  AND started_at < ?`)
467
471
  .get(input.userId, input.dayStartAt, input.dayEndAt)
468
472
  : null;
469
- const activeEnergyAverage = average(dailyHealthKit.map((day) => day.activeEnergyKcal));
473
+ const activeBaselineHealthKitDays = dailyHealthKit.filter((day) => day.dateKey < todayKey && day.activeEnergyKcal != null);
474
+ const activeEnergyAverage = average(activeBaselineHealthKitDays.map((day) => day.activeEnergyKcal));
470
475
  const restingEvidenceDays = dailyHealthKit.filter((day) => day.restingEnergyKcal != null);
471
476
  const restingExclusionReasons = [];
472
477
  const qualifiedRestingDays = restingEvidenceDays.filter((day) => {
@@ -520,13 +525,17 @@ function buildStoredEnergyModel(input) {
520
525
  }
521
526
  return qualifiedRestingDays.length > 0 ? "high" : "medium";
522
527
  })();
523
- const workoutEnergyAverage = average([...workoutByDay.values()]);
524
- const movementCaloriesAverage = average([...movementByDay.values()]);
528
+ const workoutBaselineEntries = [...workoutByDay.entries()].filter(([dateKey, value]) => dateKey < todayKey && value != null);
529
+ const movementBaselineEntries = [...movementByDay.entries()].filter(([dateKey, value]) => dateKey < todayKey && value != null);
530
+ const workoutBaselineValues = workoutBaselineEntries.map(([, value]) => value);
531
+ const movementBaselineValues = movementBaselineEntries.map(([, value]) => value);
532
+ const workoutEnergyAverage = average(workoutBaselineValues);
533
+ const movementCaloriesAverage = average(movementBaselineValues);
525
534
  const fallbackActiveBurn = workoutEnergyAverage != null || movementCaloriesAverage != null
526
535
  ? n(workoutEnergyAverage) + n(movementCaloriesAverage)
527
536
  : null;
528
- const activeBurnKcal = activeEnergyAverage ?? fallbackActiveBurn;
529
- const baselineActiveCalories = input.defaultActiveCalories ?? activeBurnKcal ?? 0;
537
+ const activeBurnKcal = activeEnergyAverage ?? fallbackActiveBurn ?? input.defaultActiveCalories;
538
+ const baselineActiveCalories = activeBurnKcal ?? 0;
530
539
  const todayHealthKitActive = dailyHealthKit.find((day) => day.dateKey === todayKey)?.activeEnergyKcal ??
531
540
  null;
532
541
  const todayStepCount = dailyHealthKit.find((day) => day.dateKey === todayKey)?.stepCount ?? null;
@@ -636,6 +645,12 @@ function buildStoredEnergyModel(input) {
636
645
  inferredTdee: input.inferredTdee,
637
646
  estimatedTdeeKcal,
638
647
  activeBurnKcal: activeBurnKcal != null ? round(activeBurnKcal, 0) : null,
648
+ activeBaselineWindowDays: ACTIVE_BASELINE_WINDOW_DAYS,
649
+ activeBaselineEvidenceDays: new Set([
650
+ ...activeBaselineHealthKitDays.map((day) => day.dateKey),
651
+ ...workoutBaselineEntries.map(([dateKey]) => dateKey),
652
+ ...movementBaselineEntries.map(([dateKey]) => dateKey)
653
+ ]).size,
639
654
  baselineActiveCaloriesKcal: round(baselineActiveCalories, 0),
640
655
  todayActiveCaloriesKcal: round(todayActiveCalories, 0),
641
656
  todayObservedActiveCaloriesKcal: todayObservedActiveCalories != null
@@ -673,8 +688,12 @@ function buildStoredEnergyModel(input) {
673
688
  ...workoutRows.map((row) => row.date_key),
674
689
  ...movementRows.map((row) => row.date_key)
675
690
  ]).size,
676
- exerciseMinutesAverage: average(dailyHealthKit.map((day) => day.exerciseMinutes)),
677
- stepCountAverage: average(dailyHealthKit.map((day) => day.stepCount)),
691
+ exerciseMinutesAverage: average(dailyHealthKit
692
+ .filter((day) => day.dateKey < todayKey)
693
+ .map((day) => day.exerciseMinutes)),
694
+ stepCountAverage: average(dailyHealthKit
695
+ .filter((day) => day.dateKey < todayKey)
696
+ .map((day) => day.stepCount)),
678
697
  sourceAvailability: {
679
698
  healthKitDailyEnergy: hasHealthKitDailyActiveEnergy,
680
699
  movementTripCalories: hasMovementEnergy,
@@ -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.110",
5
+ "version": "0.2.112",
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.110",
3
+ "version": "0.2.112",
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",