135 lines
6.6 KiB
Markdown
135 lines
6.6 KiB
Markdown
---
|
|
name: datastore
|
|
description: Structured personal data layer for OpenClaw powered by in-memory DuckDB and JSONL in git. Provides deterministic math, macro calculations, baby sleep interval tracking, and spatial radius search. Use whenever logging food, baby sleep, checking daily caloric balances, or querying places.
|
|
---
|
|
|
|
# 📦 Datastore: Structured Personal Data Layer
|
|
|
|
The `datastore` skill is the source of truth for all structured, repetitive, and mathematical data in OpenClaw. It stores data in git-versioned JSONL files in the Knowledge Wiki (`knowledge-wiki/data/`) and executes all calculations, aggregations, validations, and geospatial queries via in-memory **DuckDB**.
|
|
|
|
---
|
|
|
|
## 🎯 When to Use
|
|
|
|
1. **Personal Nutrition (`nutrition.intake`):**
|
|
- Logging meals, snacks, drinks, and ingredients.
|
|
- Computes macros and calories deterministically (zero LLM math).
|
|
- If a `food_id` from the food catalog is provided, macros are multiplied automatically from packaging reference values (`per_100 * qty / 100`).
|
|
2. **Baby Sleep (`sleep.session`):**
|
|
- Starting open sleep sessions when Mila falls asleep (`end=None`).
|
|
- Closing sleep sessions when Mila wakes up (`datastore_stop_event`).
|
|
- Logging completed nap or night intervals retroactively.
|
|
- Querying average night durations, wake windows, and daily sleep totals.
|
|
3. **Daily Caloric Balances:**
|
|
- Summarizing daily protein, carbs, calories, and deficit against Garmin expenditures.
|
|
4. **Points of Interest (`places`):**
|
|
- Searching for beer gardens, playgrounds, stores, or farm stands within a given radius (e.g. 500m or 1km around Grabengasse 7) using native DuckDB spatial distance.
|
|
5. **Catalogs & Entities (`foods`, `recipes`, `places`, `people`):**
|
|
- Upserting and reading reference data.
|
|
|
|
---
|
|
|
|
## ⛔ Core Guardrails & Protocol (MANDATORY)
|
|
|
|
- **NEVER compute arithmetic sums by hand:** Always let DuckDB calculate daily totals, durations, and macronutrient sums via `datastore_add_event`, `datastore_stop_event`, or `datastore_get_summary`.
|
|
- **NEVER write structured log tables directly into Markdown files:** Data goes into the datastore. Markdown view pages in `knowledge-wiki/entities/` are read-only views generated from the datastore.
|
|
- **Always provide feedback from the datastore response:** When logging an item, echo the DuckDB-calculated running day total (e.g. *"Tag bisher: 85.5 g Eiweiß · 970 kcal"*) provided in the tool response.
|
|
|
|
---
|
|
|
|
## 🛠️ MCP Tools
|
|
|
|
### 1. `datastore_add_event`
|
|
Logs a point or interval event.
|
|
- **Parameters:**
|
|
- `kind` (string, required): e.g. `'nutrition.intake'`, `'sleep.session'`, `'feeding.bottle'`.
|
|
- `subject` (string, required): `'moritz'`, `'mila'`, or `'amelie'`.
|
|
- `actor` (string, required): e.g. `'agent:koch'`, `'agent:hebamme'`, `'moritz'`.
|
|
- `payload` (object, required):
|
|
- For `nutrition.intake`: `{"item": "...", "qty": 200, "unit": "g"|"ml", "protein_g": ..., "kcal": ...}` (or `{"food_id": "oatly-haferdrink", "qty": 200, "unit": "ml"}`).
|
|
- For `sleep.session`: `{"type": "nap"|"night", "location": "bett"|"auto"|"kinderwagen"}`.
|
|
- `start` (string, optional): ISO 8601 timestamp (defaults to current time).
|
|
- `since` (string, optional): Relative start offset backwards from now (e.g. `'5m'`, `'15m'`, `'1h'`). Use for "schläft seit X Min" to avoid LLM mental math!
|
|
- `end` (string, optional): ISO 8601 timestamp. Leave empty for open sleep intervals!
|
|
- `meal` (string, optional): e.g. `'Frühstück'`, `'Mittagessen'`, `'Snack'`.
|
|
- `estimated` (boolean, optional): Set to `true` if portions or nutrients are estimated.
|
|
- `note` (string, optional): Context or notes.
|
|
|
|
### 2. `datastore_stop_event`
|
|
Closes the currently active open interval event (e.g. when Mila wakes up).
|
|
- **Parameters:**
|
|
- `kind` (string, required): `'sleep.session'`.
|
|
- `subject` (string, required): `'mila'`.
|
|
- `end_time` (string, optional): ISO timestamp (defaults to current time).
|
|
|
|
### 3. `datastore_get_summary`
|
|
Retrieves daily nutrition, sleep, and active status totals computed by DuckDB.
|
|
- **Parameters:**
|
|
- `subject` (string, required): `'moritz'` or `'mila'`.
|
|
- `date` (string, optional): `YYYY-MM-DD` (defaults to today).
|
|
|
|
### 4. `datastore_query`
|
|
Executes a read-only DuckDB SQL query for custom analysis.
|
|
- **Parameters:**
|
|
- `sql` (string, required): e.g. `"SELECT * FROM v_sleep_daily WHERE subject = 'mila' LIMIT 14"`.
|
|
|
|
### 5. `datastore_find_places_near`
|
|
Searches for points of interest within a radius in meters.
|
|
- **Parameters:**
|
|
- `lat` (number, required): e.g. `49.0205` (Grabengasse 7).
|
|
- `lon` (number, required): e.g. `12.0975`.
|
|
- `radius_m` (number, optional, default: 1000).
|
|
- `category` (string, optional): e.g. `'biergarten'`, `'spielplatz'`.
|
|
|
|
### 6. `datastore_put_entity`
|
|
Upserts a reference entity into `foods`, `recipes`, `places`, or `people`.
|
|
- **Parameters:**
|
|
- `collection` (string, required): `'foods'`, `'recipes'`, `'places'`, or `'people'`.
|
|
- `record` (object, required): Full entity record with an `'id'` field.
|
|
|
|
---
|
|
|
|
## 💻 CLI Usage
|
|
|
|
From the shell or scripts:
|
|
```bash
|
|
# Add food
|
|
uv run /home/node/mop-skills/mop-skills/skills/datastore/scripts/datastore.py add nutrition.intake \
|
|
--subject moritz \
|
|
--actor agent:koch \
|
|
--meal Frühstück \
|
|
--payload '{"item": "Haferflocken mit Skyr", "qty": 250, "unit": "g", "protein_g": 30.0, "kcal": 350.0}'
|
|
|
|
# Start Mila's nap (open interval)
|
|
uv run /home/node/mop-skills/mop-skills/skills/datastore/scripts/datastore.py add sleep.session \
|
|
--subject mila \
|
|
--actor agent:hebamme \
|
|
--payload '{"type": "nap", "location": "kinderwagen"}'
|
|
|
|
# Start Mila's nap with relative time offset (e.g. asleep since 15 minutes)
|
|
uv run /home/node/mop-skills/mop-skills/skills/datastore/scripts/datastore.py add sleep.session \
|
|
--subject mila \
|
|
--actor agent:hebamme \
|
|
--since "15m" \
|
|
--payload '{"type": "nap", "location": "bett"}'
|
|
|
|
# Stop Mila's nap (closes open interval)
|
|
uv run /home/node/mop-skills/mop-skills/skills/datastore/scripts/datastore.py stop sleep.session \
|
|
--subject mila
|
|
|
|
# Query daily summary
|
|
uv run /home/node/mop-skills/mop-skills/skills/datastore/scripts/datastore.py summary --subject moritz
|
|
|
|
# Radius search for beer gardens within 500m of Grabengasse 7
|
|
uv run /home/node/mop-skills/mop-skills/skills/datastore/scripts/datastore.py places \
|
|
--lat 49.0205 --lon 12.0975 --radius 500 --category biergarten
|
|
|
|
# Nightly Garmin mirror sync
|
|
uv run /home/node/mop-skills/mop-skills/skills/datastore/scripts/garmin_sync.py --days 2
|
|
|
|
# Render Markdown views & HTML dashboards
|
|
PYTHONPATH=/home/node/mop-skills/mop-skills/skills/datastore/scripts \
|
|
uv run /home/node/mop-skills/mop-skills/skills/datastore/scripts/render_views.py
|
|
```
|
|
|