agent-bober 0.17.0 → 0.18.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +25 -0
- package/README.md +169 -6
- package/dist/chat/answerer.d.ts +17 -0
- package/dist/chat/answerer.d.ts.map +1 -0
- package/dist/chat/answerer.js +52 -0
- package/dist/chat/answerer.js.map +1 -0
- package/dist/chat/approval-cursor.d.ts +25 -0
- package/dist/chat/approval-cursor.d.ts.map +1 -0
- package/dist/chat/approval-cursor.js +61 -0
- package/dist/chat/approval-cursor.js.map +1 -0
- package/dist/chat/approval-reader.d.ts +11 -0
- package/dist/chat/approval-reader.d.ts.map +1 -0
- package/dist/chat/approval-reader.js +20 -0
- package/dist/chat/approval-reader.js.map +1 -0
- package/dist/chat/careful-sidecar.d.ts +15 -0
- package/dist/chat/careful-sidecar.d.ts.map +1 -0
- package/dist/chat/careful-sidecar.js +39 -0
- package/dist/chat/careful-sidecar.js.map +1 -0
- package/dist/chat/chat-session.d.ts +129 -0
- package/dist/chat/chat-session.d.ts.map +1 -0
- package/dist/chat/chat-session.js +470 -0
- package/dist/chat/chat-session.js.map +1 -0
- package/dist/chat/completion-tailer.d.ts +27 -0
- package/dist/chat/completion-tailer.d.ts.map +1 -0
- package/dist/chat/completion-tailer.js +187 -0
- package/dist/chat/completion-tailer.js.map +1 -0
- package/dist/chat/conversation-store.d.ts +22 -0
- package/dist/chat/conversation-store.d.ts.map +1 -0
- package/dist/chat/conversation-store.js +66 -0
- package/dist/chat/conversation-store.js.map +1 -0
- package/dist/chat/cursor-store.d.ts +23 -0
- package/dist/chat/cursor-store.d.ts.map +1 -0
- package/dist/chat/cursor-store.js +42 -0
- package/dist/chat/cursor-store.js.map +1 -0
- package/dist/chat/pid-sidecar.d.ts +22 -0
- package/dist/chat/pid-sidecar.d.ts.map +1 -0
- package/dist/chat/pid-sidecar.js +42 -0
- package/dist/chat/pid-sidecar.js.map +1 -0
- package/dist/chat/roster-reader.d.ts +16 -0
- package/dist/chat/roster-reader.d.ts.map +1 -0
- package/dist/chat/roster-reader.js +39 -0
- package/dist/chat/roster-reader.js.map +1 -0
- package/dist/chat/run-spawner.d.ts +71 -0
- package/dist/chat/run-spawner.d.ts.map +1 -0
- package/dist/chat/run-spawner.js +121 -0
- package/dist/chat/run-spawner.js.map +1 -0
- package/dist/chat/slash-commands.d.ts +36 -0
- package/dist/chat/slash-commands.d.ts.map +1 -0
- package/dist/chat/slash-commands.js +133 -0
- package/dist/chat/slash-commands.js.map +1 -0
- package/dist/chat/steer-cleanup.d.ts +12 -0
- package/dist/chat/steer-cleanup.d.ts.map +1 -0
- package/dist/chat/steer-cleanup.js +60 -0
- package/dist/chat/steer-cleanup.js.map +1 -0
- package/dist/chat/turn-classifier.d.ts +43 -0
- package/dist/chat/turn-classifier.d.ts.map +1 -0
- package/dist/chat/turn-classifier.js +150 -0
- package/dist/chat/turn-classifier.js.map +1 -0
- package/dist/cli/commands/blackboard.d.ts +33 -0
- package/dist/cli/commands/blackboard.d.ts.map +1 -0
- package/dist/cli/commands/blackboard.js +114 -0
- package/dist/cli/commands/blackboard.js.map +1 -0
- package/dist/cli/commands/chat.d.ts +13 -0
- package/dist/cli/commands/chat.d.ts.map +1 -0
- package/dist/cli/commands/chat.js +43 -0
- package/dist/cli/commands/chat.js.map +1 -0
- package/dist/cli/commands/evolve.d.ts +18 -0
- package/dist/cli/commands/evolve.d.ts.map +1 -0
- package/dist/cli/commands/evolve.js +72 -0
- package/dist/cli/commands/evolve.js.map +1 -0
- package/dist/cli/commands/facts.d.ts +15 -0
- package/dist/cli/commands/facts.d.ts.map +1 -0
- package/dist/cli/commands/facts.js +213 -0
- package/dist/cli/commands/facts.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +1 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/medical.d.ts +24 -0
- package/dist/cli/commands/medical.d.ts.map +1 -0
- package/dist/cli/commands/medical.js +132 -0
- package/dist/cli/commands/medical.js.map +1 -0
- package/dist/cli/commands/memory.d.ts +2 -1
- package/dist/cli/commands/memory.d.ts.map +1 -1
- package/dist/cli/commands/memory.js +94 -7
- package/dist/cli/commands/memory.js.map +1 -1
- package/dist/cli/commands/plan.d.ts.map +1 -1
- package/dist/cli/commands/plan.js +29 -3
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/replay.d.ts +17 -0
- package/dist/cli/commands/replay.d.ts.map +1 -0
- package/dist/cli/commands/replay.js +261 -0
- package/dist/cli/commands/replay.js.map +1 -0
- package/dist/cli/commands/run.d.ts +9 -0
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +27 -1
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/sprint.d.ts.map +1 -1
- package/dist/cli/commands/sprint.js +17 -3
- package/dist/cli/commands/sprint.js.map +1 -1
- package/dist/cli/commands/update.d.ts +18 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +81 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/index.js +15 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +8 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/role-providers.d.ts +1 -1
- package/dist/config/role-providers.d.ts.map +1 -1
- package/dist/config/role-providers.js +6 -1
- package/dist/config/role-providers.js.map +1 -1
- package/dist/config/schema.d.ts +467 -222
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +25 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/contracts/eval-result.d.ts +84 -84
- package/dist/contracts/spec.d.ts +28 -28
- package/dist/contracts/sprint-contract.d.ts +4 -4
- package/dist/fleet/critic-deep.d.ts +53 -0
- package/dist/fleet/critic-deep.d.ts.map +1 -0
- package/dist/fleet/critic-deep.js +199 -0
- package/dist/fleet/critic-deep.js.map +1 -0
- package/dist/fleet/decomposer-deep-constants.d.ts +4 -0
- package/dist/fleet/decomposer-deep-constants.d.ts.map +1 -0
- package/dist/fleet/decomposer-deep-constants.js +14 -0
- package/dist/fleet/decomposer-deep-constants.js.map +1 -0
- package/dist/fleet/decomposer-deep-types.d.ts +8 -0
- package/dist/fleet/decomposer-deep-types.d.ts.map +1 -0
- package/dist/fleet/decomposer-deep-types.js +9 -0
- package/dist/fleet/decomposer-deep-types.js.map +1 -0
- package/dist/fleet/decomposer-deep.d.ts +51 -0
- package/dist/fleet/decomposer-deep.d.ts.map +1 -0
- package/dist/fleet/decomposer-deep.js +261 -0
- package/dist/fleet/decomposer-deep.js.map +1 -0
- package/dist/fleet/decomposer.d.ts +22 -0
- package/dist/fleet/decomposer.d.ts.map +1 -0
- package/dist/fleet/decomposer.js +144 -0
- package/dist/fleet/decomposer.js.map +1 -0
- package/dist/fleet/index.d.ts +93 -0
- package/dist/fleet/index.d.ts.map +1 -1
- package/dist/fleet/index.js +230 -2
- package/dist/fleet/index.js.map +1 -1
- package/dist/fleet/manifest-write.d.ts +30 -0
- package/dist/fleet/manifest-write.d.ts.map +1 -0
- package/dist/fleet/manifest-write.js +90 -0
- package/dist/fleet/manifest-write.js.map +1 -0
- package/dist/fleet/manifest.d.ts +6 -6
- package/dist/fleet/shared-blackboard.d.ts +51 -0
- package/dist/fleet/shared-blackboard.d.ts.map +1 -0
- package/dist/fleet/shared-blackboard.js +79 -0
- package/dist/fleet/shared-blackboard.js.map +1 -0
- package/dist/fleet/synthesis.d.ts +16 -0
- package/dist/fleet/synthesis.d.ts.map +1 -0
- package/dist/fleet/synthesis.js +22 -0
- package/dist/fleet/synthesis.js.map +1 -0
- package/dist/fleet/tier-policy.d.ts +18 -0
- package/dist/fleet/tier-policy.d.ts.map +1 -0
- package/dist/fleet/tier-policy.js +53 -0
- package/dist/fleet/tier-policy.js.map +1 -0
- package/dist/fleet/tool-role-guard.d.ts +24 -0
- package/dist/fleet/tool-role-guard.d.ts.map +1 -0
- package/dist/fleet/tool-role-guard.js +55 -0
- package/dist/fleet/tool-role-guard.js.map +1 -0
- package/dist/incident/resolution-verify.d.ts +4 -4
- package/dist/incident/types.d.ts +8 -8
- package/dist/mcp/run-manager.d.ts +9 -1
- package/dist/mcp/run-manager.d.ts.map +1 -1
- package/dist/mcp/run-manager.js.map +1 -1
- package/dist/medical/adapters/apple-health.d.ts +32 -0
- package/dist/medical/adapters/apple-health.d.ts.map +1 -0
- package/dist/medical/adapters/apple-health.js +100 -0
- package/dist/medical/adapters/apple-health.js.map +1 -0
- package/dist/medical/audit.d.ts +31 -0
- package/dist/medical/audit.d.ts.map +1 -0
- package/dist/medical/audit.js +56 -0
- package/dist/medical/audit.js.map +1 -0
- package/dist/medical/consent.d.ts +37 -0
- package/dist/medical/consent.d.ts.map +1 -0
- package/dist/medical/consent.js +73 -0
- package/dist/medical/consent.js.map +1 -0
- package/dist/medical/disclaimer.d.ts +11 -0
- package/dist/medical/disclaimer.d.ts.map +1 -0
- package/dist/medical/disclaimer.js +21 -0
- package/dist/medical/disclaimer.js.map +1 -0
- package/dist/medical/egress.d.ts +30 -0
- package/dist/medical/egress.d.ts.map +1 -0
- package/dist/medical/egress.js +50 -0
- package/dist/medical/egress.js.map +1 -0
- package/dist/medical/engine.d.ts +73 -0
- package/dist/medical/engine.d.ts.map +1 -0
- package/dist/medical/engine.js +333 -0
- package/dist/medical/engine.js.map +1 -0
- package/dist/medical/guardrails.d.ts +47 -0
- package/dist/medical/guardrails.d.ts.map +1 -0
- package/dist/medical/guardrails.js +92 -0
- package/dist/medical/guardrails.js.map +1 -0
- package/dist/medical/health-store.d.ts +80 -0
- package/dist/medical/health-store.d.ts.map +1 -0
- package/dist/medical/health-store.js +204 -0
- package/dist/medical/health-store.js.map +1 -0
- package/dist/medical/inference.d.ts +22 -0
- package/dist/medical/inference.d.ts.map +1 -0
- package/dist/medical/inference.js +39 -0
- package/dist/medical/inference.js.map +1 -0
- package/dist/medical/ingestion.d.ts +33 -0
- package/dist/medical/ingestion.d.ts.map +1 -0
- package/dist/medical/ingestion.js +52 -0
- package/dist/medical/ingestion.js.map +1 -0
- package/dist/medical/numerics.d.ts +66 -0
- package/dist/medical/numerics.d.ts.map +1 -0
- package/dist/medical/numerics.js +216 -0
- package/dist/medical/numerics.js.map +1 -0
- package/dist/medical/red-flag.d.ts +42 -0
- package/dist/medical/red-flag.d.ts.map +1 -0
- package/dist/medical/red-flag.js +161 -0
- package/dist/medical/red-flag.js.map +1 -0
- package/dist/medical/refusal.d.ts +46 -0
- package/dist/medical/refusal.d.ts.map +1 -0
- package/dist/medical/refusal.js +131 -0
- package/dist/medical/refusal.js.map +1 -0
- package/dist/medical/retrieval/grounding-critic.d.ts +34 -0
- package/dist/medical/retrieval/grounding-critic.d.ts.map +1 -0
- package/dist/medical/retrieval/grounding-critic.js +153 -0
- package/dist/medical/retrieval/grounding-critic.js.map +1 -0
- package/dist/medical/retrieval/literature.d.ts +78 -0
- package/dist/medical/retrieval/literature.d.ts.map +1 -0
- package/dist/medical/retrieval/literature.js +292 -0
- package/dist/medical/retrieval/literature.js.map +1 -0
- package/dist/medical/retrieval/medline-source.d.ts +72 -0
- package/dist/medical/retrieval/medline-source.d.ts.map +1 -0
- package/dist/medical/retrieval/medline-source.js +120 -0
- package/dist/medical/retrieval/medline-source.js.map +1 -0
- package/dist/medical/team.d.ts +15 -0
- package/dist/medical/team.d.ts.map +1 -0
- package/dist/medical/team.js +44 -0
- package/dist/medical/team.js.map +1 -0
- package/dist/medical/types.d.ts +175 -0
- package/dist/medical/types.d.ts.map +1 -0
- package/dist/medical/types.js +8 -0
- package/dist/medical/types.js.map +1 -0
- package/dist/medical/whoop/whoop-client.d.ts +114 -0
- package/dist/medical/whoop/whoop-client.d.ts.map +1 -0
- package/dist/medical/whoop/whoop-client.js +226 -0
- package/dist/medical/whoop/whoop-client.js.map +1 -0
- package/dist/medical/whoop/whoop-sync.d.ts +25 -0
- package/dist/medical/whoop/whoop-sync.d.ts.map +1 -0
- package/dist/medical/whoop/whoop-sync.js +97 -0
- package/dist/medical/whoop/whoop-sync.js.map +1 -0
- package/dist/medical/whoop/whoop-token.d.ts +44 -0
- package/dist/medical/whoop/whoop-token.d.ts.map +1 -0
- package/dist/medical/whoop/whoop-token.js +66 -0
- package/dist/medical/whoop/whoop-token.js.map +1 -0
- package/dist/orchestrator/context-handoff.d.ts +60 -60
- package/dist/orchestrator/contract-materialization.d.ts +33 -0
- package/dist/orchestrator/contract-materialization.d.ts.map +1 -0
- package/dist/orchestrator/contract-materialization.js +113 -0
- package/dist/orchestrator/contract-materialization.js.map +1 -0
- package/dist/orchestrator/memory/distill.d.ts +4 -1
- package/dist/orchestrator/memory/distill.d.ts.map +1 -1
- package/dist/orchestrator/memory/distill.js +41 -1
- package/dist/orchestrator/memory/distill.js.map +1 -1
- package/dist/orchestrator/memory/fact-detector.d.ts +61 -0
- package/dist/orchestrator/memory/fact-detector.d.ts.map +1 -0
- package/dist/orchestrator/memory/fact-detector.js +153 -0
- package/dist/orchestrator/memory/fact-detector.js.map +1 -0
- package/dist/orchestrator/memory/fact-judge.d.ts +19 -0
- package/dist/orchestrator/memory/fact-judge.d.ts.map +1 -0
- package/dist/orchestrator/memory/fact-judge.js +121 -0
- package/dist/orchestrator/memory/fact-judge.js.map +1 -0
- package/dist/orchestrator/memory/fact-retrieve.d.ts +52 -0
- package/dist/orchestrator/memory/fact-retrieve.d.ts.map +1 -0
- package/dist/orchestrator/memory/fact-retrieve.js +117 -0
- package/dist/orchestrator/memory/fact-retrieve.js.map +1 -0
- package/dist/orchestrator/memory/hygiene.d.ts +66 -0
- package/dist/orchestrator/memory/hygiene.d.ts.map +1 -0
- package/dist/orchestrator/memory/hygiene.js +153 -0
- package/dist/orchestrator/memory/hygiene.js.map +1 -0
- package/dist/orchestrator/memory/reconcile.d.ts +47 -0
- package/dist/orchestrator/memory/reconcile.d.ts.map +1 -0
- package/dist/orchestrator/memory/reconcile.js +116 -0
- package/dist/orchestrator/memory/reconcile.js.map +1 -0
- package/dist/orchestrator/memory/retrieve.d.ts +5 -3
- package/dist/orchestrator/memory/retrieve.d.ts.map +1 -1
- package/dist/orchestrator/memory/retrieve.js +9 -6
- package/dist/orchestrator/memory/retrieve.js.map +1 -1
- package/dist/orchestrator/pipeline.d.ts +19 -3
- package/dist/orchestrator/pipeline.d.ts.map +1 -1
- package/dist/orchestrator/pipeline.js +63 -52
- package/dist/orchestrator/pipeline.js.map +1 -1
- package/dist/orchestrator/planner-agent.d.ts.map +1 -1
- package/dist/orchestrator/planner-agent.js +16 -1
- package/dist/orchestrator/planner-agent.js.map +1 -1
- package/dist/orchestrator/selfimprove/eval-guards.d.ts +51 -0
- package/dist/orchestrator/selfimprove/eval-guards.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/eval-guards.js +120 -0
- package/dist/orchestrator/selfimprove/eval-guards.js.map +1 -0
- package/dist/orchestrator/selfimprove/gepa.d.ts +74 -0
- package/dist/orchestrator/selfimprove/gepa.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/gepa.js +227 -0
- package/dist/orchestrator/selfimprove/gepa.js.map +1 -0
- package/dist/orchestrator/selfimprove/replay-harness.d.ts +65 -0
- package/dist/orchestrator/selfimprove/replay-harness.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/replay-harness.js +134 -0
- package/dist/orchestrator/selfimprove/replay-harness.js.map +1 -0
- package/dist/orchestrator/selfimprove/replay-store.d.ts +45 -0
- package/dist/orchestrator/selfimprove/replay-store.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/replay-store.js +119 -0
- package/dist/orchestrator/selfimprove/replay-store.js.map +1 -0
- package/dist/orchestrator/selfimprove/replay-types.d.ts +32 -0
- package/dist/orchestrator/selfimprove/replay-types.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/replay-types.js +15 -0
- package/dist/orchestrator/selfimprove/replay-types.js.map +1 -0
- package/dist/orchestrator/workflow/engine.d.ts +3 -1
- package/dist/orchestrator/workflow/engine.d.ts.map +1 -1
- package/dist/orchestrator/workflow/selector.d.ts +18 -0
- package/dist/orchestrator/workflow/selector.d.ts.map +1 -1
- package/dist/orchestrator/workflow/selector.js +41 -0
- package/dist/orchestrator/workflow/selector.js.map +1 -1
- package/dist/orchestrator/workflow/ts-engine.d.ts +3 -1
- package/dist/orchestrator/workflow/ts-engine.d.ts.map +1 -1
- package/dist/orchestrator/workflow/ts-engine.js +2 -2
- package/dist/orchestrator/workflow/ts-engine.js.map +1 -1
- package/dist/orchestrator/workflow/workflow-engine.d.ts +3 -1
- package/dist/orchestrator/workflow/workflow-engine.d.ts.map +1 -1
- package/dist/orchestrator/workflow/workflow-engine.js +3 -3
- package/dist/orchestrator/workflow/workflow-engine.js.map +1 -1
- package/dist/state/facts.d.ts +110 -0
- package/dist/state/facts.d.ts.map +1 -0
- package/dist/state/facts.js +208 -0
- package/dist/state/facts.js.map +1 -0
- package/dist/state/guidance.d.ts +37 -0
- package/dist/state/guidance.d.ts.map +1 -0
- package/dist/state/guidance.js +144 -0
- package/dist/state/guidance.js.map +1 -0
- package/dist/state/history.d.ts +2 -2
- package/dist/state/index.d.ts +1 -1
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/index.js +1 -1
- package/dist/state/index.js.map +1 -1
- package/dist/state/memory.d.ts +43 -11
- package/dist/state/memory.d.ts.map +1 -1
- package/dist/state/memory.js +93 -15
- package/dist/state/memory.js.map +1 -1
- package/dist/state/pause.d.ts +47 -0
- package/dist/state/pause.d.ts.map +1 -0
- package/dist/state/pause.js +146 -0
- package/dist/state/pause.js.map +1 -0
- package/dist/state/sprint-state.d.ts +8 -0
- package/dist/state/sprint-state.d.ts.map +1 -1
- package/dist/state/sprint-state.js +32 -1
- package/dist/state/sprint-state.js.map +1 -1
- package/dist/teams/registry.d.ts +16 -0
- package/dist/teams/registry.d.ts.map +1 -0
- package/dist/teams/registry.js +53 -0
- package/dist/teams/registry.js.map +1 -0
- package/dist/teams/types.d.ts +25 -0
- package/dist/teams/types.d.ts.map +1 -0
- package/dist/teams/types.js +2 -0
- package/dist/teams/types.js.map +1 -0
- package/package.json +3 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// ── Mapping table ────────────────────────────────────────────────────
|
|
2
|
+
// Per-collection: WHOOP score-field name -> fixed (metric, unit). Unmapped fields are SKIPPED.
|
|
3
|
+
const WHOOP_FIELD_MAP = {
|
|
4
|
+
recovery: {
|
|
5
|
+
recovery_score: { metric: "whoop_recovery_score", unit: "%" },
|
|
6
|
+
resting_heart_rate: { metric: "whoop_resting_heart_rate", unit: "bpm" },
|
|
7
|
+
hrv_rmssd_milli: { metric: "whoop_hrv", unit: "ms" },
|
|
8
|
+
spo2_percentage: { metric: "whoop_spo2", unit: "%" },
|
|
9
|
+
skin_temp_celsius: { metric: "whoop_skin_temp", unit: "degC" },
|
|
10
|
+
},
|
|
11
|
+
sleep: {
|
|
12
|
+
sleep_performance_percentage: { metric: "whoop_sleep_performance", unit: "%" },
|
|
13
|
+
total_in_bed_time_milli: { metric: "whoop_sleep_in_bed", unit: "ms" },
|
|
14
|
+
respiratory_rate: { metric: "whoop_respiratory_rate", unit: "rpm" },
|
|
15
|
+
},
|
|
16
|
+
cycle: {
|
|
17
|
+
strain: { metric: "whoop_strain", unit: "score" },
|
|
18
|
+
average_heart_rate: { metric: "whoop_avg_heart_rate", unit: "bpm" },
|
|
19
|
+
kilojoule: { metric: "whoop_kilojoule", unit: "kJ" },
|
|
20
|
+
},
|
|
21
|
+
workout: {
|
|
22
|
+
strain: { metric: "whoop_workout_strain", unit: "score" },
|
|
23
|
+
average_heart_rate: { metric: "whoop_workout_avg_hr", unit: "bpm" },
|
|
24
|
+
kilojoule: { metric: "whoop_workout_kilojoule", unit: "kJ" },
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
const COLLECTIONS = ["recovery", "sleep", "cycle", "workout"];
|
|
28
|
+
// ── Record mapping ───────────────────────────────────────────────────
|
|
29
|
+
/**
|
|
30
|
+
* Map a list of WhoopRecords from one collection into HealthObservations.
|
|
31
|
+
* Only fields present in WHOOP_FIELD_MAP are emitted — unmapped fields are skipped.
|
|
32
|
+
* id is left UNSET so the store derives the content-derived SHA-256 dedup key.
|
|
33
|
+
*/
|
|
34
|
+
function mapWhoopRecords(collection, records) {
|
|
35
|
+
const table = WHOOP_FIELD_MAP[collection];
|
|
36
|
+
const out = [];
|
|
37
|
+
for (const rec of records) {
|
|
38
|
+
for (const [field, value] of Object.entries(rec.metrics)) {
|
|
39
|
+
const mapped = table[field];
|
|
40
|
+
if (!mapped)
|
|
41
|
+
continue; // unmapped fields skipped, never guessed
|
|
42
|
+
out.push({
|
|
43
|
+
// id left UNSET — store derives content-derived SHA-256 (do NOT use rec.id)
|
|
44
|
+
metric: mapped.metric,
|
|
45
|
+
value,
|
|
46
|
+
unit: mapped.unit,
|
|
47
|
+
tStart: rec.tStartIso,
|
|
48
|
+
tEnd: rec.tEndIso,
|
|
49
|
+
source: "whoop",
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
// ── WhoopSyncAdapter ─────────────────────────────────────────────────
|
|
56
|
+
/**
|
|
57
|
+
* Adapts WhoopClient pagination into the ObservationSink interface (ADR-1).
|
|
58
|
+
*
|
|
59
|
+
* NOT an IngestionAdapter — its entry point is sync(window, sink), not ingest(filePath, sink).
|
|
60
|
+
* All HTTP is confined to WhoopClient (injected dependency).
|
|
61
|
+
*
|
|
62
|
+
* On any fetchPage throw, the error PROPAGATES (fail-closed).
|
|
63
|
+
* Prior batches are already committed via per-batch better-sqlite3 transactions (ADR-4).
|
|
64
|
+
* A failed sync is recovered by re-running — idempotent dedup via INSERT OR IGNORE.
|
|
65
|
+
*/
|
|
66
|
+
export class WhoopSyncAdapter {
|
|
67
|
+
client;
|
|
68
|
+
source = "whoop";
|
|
69
|
+
constructor(client) {
|
|
70
|
+
this.client = client;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Sync all four WHOOP collections over the given window into the sink.
|
|
74
|
+
* Pages each collection following nextCursor until the last page (undefined cursor).
|
|
75
|
+
* Returns IngestionResult { recordsParsed, newRows }.
|
|
76
|
+
*/
|
|
77
|
+
async sync(window, sink) {
|
|
78
|
+
let recordsParsed = 0;
|
|
79
|
+
for (const collection of COLLECTIONS) {
|
|
80
|
+
let cursor;
|
|
81
|
+
do {
|
|
82
|
+
// Any throw PROPAGATES — fail-closed; committed batches already persisted (ADR-4)
|
|
83
|
+
const page = await this.client.fetchPage(collection, window, cursor);
|
|
84
|
+
const obs = mapWhoopRecords(collection, page.records);
|
|
85
|
+
recordsParsed += obs.length; // counts mapped observations only (not raw records)
|
|
86
|
+
if (obs.length > 0) {
|
|
87
|
+
await sink.writeBatch(obs, []); // per-batch txn commits here; await = backpressure
|
|
88
|
+
}
|
|
89
|
+
cursor = page.nextCursor;
|
|
90
|
+
} while (cursor !== undefined);
|
|
91
|
+
}
|
|
92
|
+
// Read newRows off the sink (mirrors apple-health.ts:115-117); writeBatch returns void.
|
|
93
|
+
const newRows = "newRows" in sink ? sink.newRows : 0;
|
|
94
|
+
return { recordsParsed, newRows };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=whoop-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whoop-sync.js","sourceRoot":"","sources":["../../../src/medical/whoop/whoop-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Persisted token bundle at .bober/medical/whoop-token.json. */
|
|
2
|
+
export interface WhoopTokens {
|
|
3
|
+
accessToken: string;
|
|
4
|
+
refreshToken: string;
|
|
5
|
+
expiresAtIso: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Manages WHOOP OAuth credentials and the 0600 refresh-token sidecar.
|
|
9
|
+
*
|
|
10
|
+
* clientCredentials() reads WHOOP_CLIENT_ID/WHOOP_CLIENT_SECRET from process.env —
|
|
11
|
+
* mirroring src/providers/factory.ts:96-136 for the clear-throw pattern.
|
|
12
|
+
*
|
|
13
|
+
* readRefreshToken() / writeTokens() persist {accessToken, refreshToken, expiresAtIso}
|
|
14
|
+
* at .bober/medical/whoop-token.json with mode 0600 — mirroring src/medical/consent.ts.
|
|
15
|
+
*
|
|
16
|
+
* NO network imports in this file (ADR-2); all HTTP lives in whoop-client.ts.
|
|
17
|
+
*
|
|
18
|
+
* bober: env-var creds + file sidecar; swap for OS keychain if per-user isolation
|
|
19
|
+
* is needed across multiple OS accounts (ADR-2 deferred).
|
|
20
|
+
*/
|
|
21
|
+
export declare class WhoopTokenStore {
|
|
22
|
+
private readonly projectRoot;
|
|
23
|
+
constructor(projectRoot: string);
|
|
24
|
+
private path;
|
|
25
|
+
/**
|
|
26
|
+
* Reads WHOOP_CLIENT_ID and WHOOP_CLIENT_SECRET from process.env.
|
|
27
|
+
* Throws clearly naming both env vars when either is unset.
|
|
28
|
+
*/
|
|
29
|
+
clientCredentials(): {
|
|
30
|
+
clientId: string;
|
|
31
|
+
clientSecret: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Returns the stored refresh token, or undefined when the sidecar is absent or corrupt.
|
|
35
|
+
* Fail-closed: any read/parse error => undefined (not yet authorised).
|
|
36
|
+
*/
|
|
37
|
+
readRefreshToken(): Promise<string | undefined>;
|
|
38
|
+
/**
|
|
39
|
+
* Persist token bundle at .bober/medical/whoop-token.json with mode 0600.
|
|
40
|
+
* Directory is created if absent (mirrors consent.ts:75-81).
|
|
41
|
+
*/
|
|
42
|
+
writeTokens(tokens: WhoopTokens): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=whoop-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whoop-token.d.ts","sourceRoot":"","sources":["../../../src/medical/whoop/whoop-token.ts"],"names":[],"mappings":"AAOA,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAID;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAAX,WAAW,EAAE,MAAM;IAIhD,OAAO,CAAC,IAAI;IAMZ;;;OAGG;IACH,iBAAiB,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;IAc/D;;;OAGG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAWrD;;;OAGG;IACG,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAQtD"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** WhoopTokenStore — WHOOP OAuth creds (env) + 0600 refresh-token sidecar. NO network (ADR-2). */
|
|
2
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { ensureDir } from "../../utils/fs.js";
|
|
5
|
+
// ── WhoopTokenStore ──────────────────────────────────────────────────
|
|
6
|
+
/**
|
|
7
|
+
* Manages WHOOP OAuth credentials and the 0600 refresh-token sidecar.
|
|
8
|
+
*
|
|
9
|
+
* clientCredentials() reads WHOOP_CLIENT_ID/WHOOP_CLIENT_SECRET from process.env —
|
|
10
|
+
* mirroring src/providers/factory.ts:96-136 for the clear-throw pattern.
|
|
11
|
+
*
|
|
12
|
+
* readRefreshToken() / writeTokens() persist {accessToken, refreshToken, expiresAtIso}
|
|
13
|
+
* at .bober/medical/whoop-token.json with mode 0600 — mirroring src/medical/consent.ts.
|
|
14
|
+
*
|
|
15
|
+
* NO network imports in this file (ADR-2); all HTTP lives in whoop-client.ts.
|
|
16
|
+
*
|
|
17
|
+
* bober: env-var creds + file sidecar; swap for OS keychain if per-user isolation
|
|
18
|
+
* is needed across multiple OS accounts (ADR-2 deferred).
|
|
19
|
+
*/
|
|
20
|
+
export class WhoopTokenStore {
|
|
21
|
+
projectRoot;
|
|
22
|
+
constructor(projectRoot) {
|
|
23
|
+
this.projectRoot = projectRoot;
|
|
24
|
+
}
|
|
25
|
+
// ── Path ──────────────────────────────────────────────────────────
|
|
26
|
+
path() {
|
|
27
|
+
return join(this.projectRoot, ".bober", "medical", "whoop-token.json");
|
|
28
|
+
}
|
|
29
|
+
// ── Credentials ───────────────────────────────────────────────────
|
|
30
|
+
/**
|
|
31
|
+
* Reads WHOOP_CLIENT_ID and WHOOP_CLIENT_SECRET from process.env.
|
|
32
|
+
* Throws clearly naming both env vars when either is unset.
|
|
33
|
+
*/
|
|
34
|
+
clientCredentials() {
|
|
35
|
+
const clientId = process.env["WHOOP_CLIENT_ID"];
|
|
36
|
+
const clientSecret = process.env["WHOOP_CLIENT_SECRET"];
|
|
37
|
+
if (!clientId || !clientSecret) {
|
|
38
|
+
throw new Error("WHOOP credentials missing — set WHOOP_CLIENT_ID and WHOOP_CLIENT_SECRET " +
|
|
39
|
+
"environment variables and try again.");
|
|
40
|
+
}
|
|
41
|
+
return { clientId, clientSecret };
|
|
42
|
+
}
|
|
43
|
+
// ── Token sidecar ─────────────────────────────────────────────────
|
|
44
|
+
/**
|
|
45
|
+
* Returns the stored refresh token, or undefined when the sidecar is absent or corrupt.
|
|
46
|
+
* Fail-closed: any read/parse error => undefined (not yet authorised).
|
|
47
|
+
*/
|
|
48
|
+
async readRefreshToken() {
|
|
49
|
+
try {
|
|
50
|
+
const data = JSON.parse(await readFile(this.path(), "utf-8"));
|
|
51
|
+
return typeof data.refreshToken === "string" ? data.refreshToken : undefined;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return undefined; // absent or corrupt => not yet authorised
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Persist token bundle at .bober/medical/whoop-token.json with mode 0600.
|
|
59
|
+
* Directory is created if absent (mirrors consent.ts:75-81).
|
|
60
|
+
*/
|
|
61
|
+
async writeTokens(tokens) {
|
|
62
|
+
await ensureDir(join(this.projectRoot, ".bober", "medical"));
|
|
63
|
+
await writeFile(this.path(), JSON.stringify(tokens, null, 2) + "\n", { encoding: "utf-8", mode: 0o600 });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=whoop-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whoop-token.js","sourceRoot":"","sources":["../../../src/medical/whoop/whoop-token.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAW9C,wEAAwE;AAExE;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,eAAe;IACG;IAA7B,YAA6B,WAAmB;QAAnB,gBAAW,GAAX,WAAW,CAAQ;IAAG,CAAC;IAEpD,qEAAqE;IAE7D,IAAI;QACV,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;IACzE,CAAC;IAED,qEAAqE;IAErE;;;OAGG;IACH,iBAAiB;QACf,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAChD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,0EAA0E;gBACxE,sCAAsC,CACzC,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;IACpC,CAAC;IAED,qEAAqE;IAErE;;;OAGG;IACH,KAAK,CAAC,gBAAgB;QACpB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CACrB,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CACb,CAAC;YAC1B,OAAO,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC,CAAC,0CAA0C;QAC9D,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAC,MAAmB;QACnC,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;QAC7D,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,EAAE,EACX,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EACtC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CACnC,CAAC;IACJ,CAAC;CACF"}
|