zaloha vseho zbyvajiciho

This commit is contained in:
lachtan
2026-06-10 07:12:11 +02:00
parent b2d367e6a4
commit 0b80827d4b
7 changed files with 848 additions and 17 deletions

26
.gitignore vendored
View File

@@ -1,17 +1,9 @@
/* db/
!memory/ sessions/
!SOUL.md log/
!USER.md __pycache__/
!memory/MEMORY.md tmp/
!.gitignore backup/
tasks/
!skills/ .nanobot/
!scripts/ *.bak
!plans/
!results/
!keep/
!HEARTBEAT.md
!develop/
!knowledge/
!notes/
!projects/

34
AGENTS.md Normal file
View File

@@ -0,0 +1,34 @@
# Agent Instructions
## Scheduled Reminders
**Personal reminders for the user** (notifications about tasks they need to do) → use the `/remind` skill → stored in `reminder.yaml`. Never use the `cron` tool for these.
**Background agent tasks** (run a script, check something, autonomous action) → use the built-in `cron` tool directly.
Test: *Who is the recipient?* User gets notified → `reminder.yaml` via `/remind` skill. Agent executes something → `cron` tool.
**Do NOT just write reminders to MEMORY.md** — that won't trigger actual notifications.
## Heartbeat Tasks
`HEARTBEAT.md` is checked on the configured heartbeat interval. Use file tools to manage periodic tasks:
- **Add**: `edit_file` to append new tasks
- **Remove**: `edit_file` to delete completed tasks
- **Rewrite**: `write_file` to replace all tasks
When the user asks for a recurring/periodic task, update `HEARTBEAT.md` instead of creating a one-time cron reminder.
## Databases (SQLite)
Always store SQLite databases under `db/*.sqlite` (relative to the workspace root).
Never use `/tmp/`, hardcoded absolute paths, or in-memory databases for persistent data.
## How you were extended & tuned
`develop/` records how this instance was extended and tuned — skills, config, service work — with verified facts and a change log you can learn from (not the upstream code). See `develop/README.md`; read on demand.
## Knowledge base
`knowledge/` holds verified facts and measured values you can draw on when answering (e.g. notes on the models available to you). See `knowledge/README.md` for what's there; read on demand.

59
TOOLS.md Normal file
View File

@@ -0,0 +1,59 @@
# Tool Usage Notes
Tool signatures are provided automatically via function calling.
This file documents non-obvious constraints and usage patterns.
## exec — Safety Limits
- Commands have a configurable timeout (default 60s)
- Dangerous commands are blocked (rm -rf, format, dd, shutdown, etc.)
- Output is truncated at 10,000 characters
- `restrictToWorkspace` config can limit file access to the workspace
## grep — Content Search
- Use `grep` to search file contents inside the workspace
- Default behavior returns only matching file paths (`output_mode="files_with_matches"`)
- Supports optional `glob` filtering (e.g. `glob="*.py"`) plus `context_before` / `context_after`
- Supports `type="py"`, `type="ts"`, `type="md"` and similar shorthand filters
- Use `fixed_strings=true` for literal keywords containing regex characters
- Use `output_mode="files_with_matches"` to get only matching file paths
- Use `output_mode="count"` to size a search before reading full matches
- Use `head_limit` and `offset` to page across results
- Prefer this over `exec` for code and history searches
- Binary or oversized files may be skipped to keep results readable
## cron — Background Agent Tasks
- Use `cron` only for **background agent tasks** (scripts, checks, autonomous actions).
- For **personal reminders to the user**, use the `/remind` skill instead (`reminder.yaml`).
- Do not call `nanobot cron` via `exec` — use the built-in `cron` tool.
## python — use uv
For all Python code (scripts, snippets, one-liners, tools) use `uv`,
not `python` / `python3` / `pip` directly.
- Run a script: `uv run script.py` (not `python script.py`)
- One-liner / snippet: `uv run --with <pkg> python -c '...'`
- Script with declared dependencies: `uv run --script script.py`
(PEP 723 header inside the file)
- Add a project dependency: `uv add <pkg>` (not `pip install`)
- Remove: `uv remove <pkg>`
- Sync environment: `uv sync`
- Run a tool: `uv run pytest`, `uv run ruff`, `uv run mypy`, …
- REPL: `uv run python`
Do not use `pip`, `pip-tools`, `poetry`, `conda`, or the system `python`.
Reason: isolated, reproducible environments with no system-level side
effects, faster resolves, no "works on my machine" surprises.
## log/reminder.log — doručené připomínky
Odeslané připomínky se logují do `log/reminder.log` (append-only, formát
`YYYY-MM-DDTHH:MM:SS <text>`, Prague time, bez timezone suffixu). Posílá je
**systémový cron uživatele nanobot** (`skills/remind/scripts/remind_send.py`)
přímo přes Telegram, mimo agenta. Když se uživatel ptá na minulé/dnešní
připomínky („připomněl jsi mi…?", „co dnes přišlo?"), přečti tento soubor.
Vedle něj v `log/reminder_cron.log` se zachytává stdout/stderr crontabu —
za normálního běhu prázdný, plní se jen při pádech skriptu.

423
cron/jobs.json Normal file
View File

@@ -0,0 +1,423 @@
{
"version": 1,
"jobs": [
{
"id": "42a84295",
"name": "nanobot-version-check",
"enabled": true,
"schedule": {
"kind": "cron",
"atMs": null,
"everyMs": null,
"expr": "0 8 * * *",
"tz": "Europe/Prague"
},
"payload": {
"kind": "agent_turn",
"message": "Run the nanobot version check script at /home/nanobot/.nanobot/workspace/scripts/check_nanobot_version.sh, then check if any of PyPI/GitHub/Docker Hub versions differ from current 0.2.0. If a newer version is found, send a Telegram notification to the user: \"New nanobot version available: X.Y.Z (current: 0.2.0). Update with: docker pull smanx/nanobot:X.Y.Z or pip install nanobot-ai==X.Y.Z\"",
"deliver": true,
"channel": "telegram",
"to": "8826147089",
"channelMeta": {
"message_id": 30,
"user_id": 8826147089,
"username": null,
"first_name": "Martin",
"is_group": false,
"message_thread_id": null,
"is_forum": false,
"reply_to_message_id": null,
"_wants_stream": true
},
"sessionKey": "telegram:8826147089"
},
"state": {
"nextRunAtMs": 1781071200000,
"lastRunAtMs": 1780984800002,
"lastStatus": "ok",
"lastError": null,
"runHistory": [
{
"runAtMs": 1779948000001,
"status": "ok",
"durationMs": 37408,
"error": null
},
{
"runAtMs": 1780120800001,
"status": "ok",
"durationMs": 14277,
"error": null
},
{
"runAtMs": 1780207200002,
"status": "ok",
"durationMs": 9226,
"error": null
},
{
"runAtMs": 1780293600002,
"status": "ok",
"durationMs": 18462,
"error": null
},
{
"runAtMs": 1780380000001,
"status": "ok",
"durationMs": 17065,
"error": null
},
{
"runAtMs": 1780466400002,
"status": "ok",
"durationMs": 12513,
"error": null
},
{
"runAtMs": 1780552800002,
"status": "ok",
"durationMs": 14408,
"error": null
},
{
"runAtMs": 1780639200002,
"status": "ok",
"durationMs": 8434,
"error": null
},
{
"runAtMs": 1780725600001,
"status": "ok",
"durationMs": 20082,
"error": null
},
{
"runAtMs": 1780812000002,
"status": "ok",
"durationMs": 15949,
"error": null
},
{
"runAtMs": 1780898400002,
"status": "ok",
"durationMs": 13551,
"error": null
},
{
"runAtMs": 1780984800002,
"status": "ok",
"durationMs": 13813,
"error": null
}
]
},
"createdAtMs": 1779872578080,
"updatedAtMs": 1780984813815,
"deleteAfterRun": false
},
{
"id": "dream",
"name": "dream",
"enabled": true,
"schedule": {
"kind": "every",
"atMs": null,
"everyMs": 7200000,
"expr": null,
"tz": null
},
"payload": {
"kind": "system_event",
"message": "",
"deliver": false,
"channel": null,
"to": null,
"channelMeta": {},
"sessionKey": null
},
"state": {
"nextRunAtMs": 1781073212281,
"lastRunAtMs": 1781066012279,
"lastStatus": "ok",
"lastError": null,
"runHistory": [
{
"runAtMs": 1780928715855,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1780935915858,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1780943115862,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1780950315865,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1780957515869,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1780964715872,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1780971915875,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1780979115879,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1780986315884,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1780993515887,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1781000715891,
"status": "ok",
"durationMs": 1,
"error": null
},
{
"runAtMs": 1781007915894,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1781015115897,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1781022315900,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1781029515903,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1781036715907,
"status": "ok",
"durationMs": 496360,
"error": null
},
{
"runAtMs": 1781044412268,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1781051612271,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1781058812275,
"status": "ok",
"durationMs": 2,
"error": null
},
{
"runAtMs": 1781066012279,
"status": "ok",
"durationMs": 2,
"error": null
}
]
},
"createdAtMs": 1780892715821,
"updatedAtMs": 1781066012281,
"deleteAfterRun": false
},
{
"id": "heartbeat",
"name": "heartbeat",
"enabled": true,
"schedule": {
"kind": "every",
"atMs": null,
"everyMs": 1800000,
"expr": null,
"tz": "Europe/Prague"
},
"payload": {
"kind": "system_event",
"message": "",
"deliver": false,
"channel": null,
"to": null,
"channelMeta": {},
"sessionKey": null
},
"state": {
"nextRunAtMs": 1781069612302,
"lastRunAtMs": 1781067812302,
"lastStatus": "ok",
"lastError": null,
"runHistory": [
{
"runAtMs": 1781033115995,
"status": "ok",
"durationMs": 0,
"error": null
},
{
"runAtMs": 1781034915997,
"status": "ok",
"durationMs": 1,
"error": null
},
{
"runAtMs": 1781037212270,
"status": "ok",
"durationMs": 1,
"error": null
},
{
"runAtMs": 1781039012273,
"status": "ok",
"durationMs": 0,
"error": null
},
{
"runAtMs": 1781040812275,
"status": "ok",
"durationMs": 0,
"error": null
},
{
"runAtMs": 1781042612276,
"status": "ok",
"durationMs": 0,
"error": null
},
{
"runAtMs": 1781044412277,
"status": "ok",
"durationMs": 0,
"error": null
},
{
"runAtMs": 1781046212279,
"status": "ok",
"durationMs": 1,
"error": null
},
{
"runAtMs": 1781048012282,
"status": "ok",
"durationMs": 0,
"error": null
},
{
"runAtMs": 1781049812285,
"status": "ok",
"durationMs": 0,
"error": null
},
{
"runAtMs": 1781051612286,
"status": "ok",
"durationMs": 0,
"error": null
},
{
"runAtMs": 1781053412287,
"status": "ok",
"durationMs": 1,
"error": null
},
{
"runAtMs": 1781055212291,
"status": "ok",
"durationMs": 0,
"error": null
},
{
"runAtMs": 1781057012293,
"status": "ok",
"durationMs": 0,
"error": null
},
{
"runAtMs": 1781058812293,
"status": "ok",
"durationMs": 1,
"error": null
},
{
"runAtMs": 1781060612296,
"status": "ok",
"durationMs": 1,
"error": null
},
{
"runAtMs": 1781062412298,
"status": "ok",
"durationMs": 1,
"error": null
},
{
"runAtMs": 1781064212299,
"status": "ok",
"durationMs": 1,
"error": null
},
{
"runAtMs": 1781066012300,
"status": "ok",
"durationMs": 0,
"error": null
},
{
"runAtMs": 1781067812302,
"status": "ok",
"durationMs": 0,
"error": null
}
]
},
"createdAtMs": 1780892715832,
"updatedAtMs": 1781067812302,
"deleteAfterRun": false
}
]
}

View File

@@ -0,0 +1,236 @@
{
"version": 1,
"jobs": [
{
"id": "42a84295",
"name": "nanobot-version-check",
"enabled": true,
"schedule": {
"kind": "cron",
"atMs": null,
"everyMs": null,
"expr": "0 8 * * *",
"tz": "Europe/Prague"
},
"payload": {
"kind": "agent_turn",
"message": "Run the nanobot version check script at /home/nanobot/.nanobot/workspace/scripts/check_nanobot_version.sh, then check if any of PyPI/GitHub/Docker Hub versions differ from current 0.2.0. If a newer version is found, send a Telegram notification to the user: \"New nanobot version available: X.Y.Z (current: 0.2.0). Update with: docker pull smanx/nanobot:X.Y.Z or pip install nanobot-ai==X.Y.Z\"",
"deliver": true,
"channel": "telegram",
"to": "8826147089",
"channelMeta": {
"message_id": 30,
"user_id": 8826147089,
"username": null,
"first_name": "Martin",
"is_group": false,
"message_thread_id": null,
"is_forum": false,
"reply_to_message_id": null,
"_wants_stream": true
},
"sessionKey": "telegram:8826147089"
},
"state": {
"nextRunAtMs": 1779948000000,
"lastRunAtMs": null,
"lastStatus": null,
"lastError": null,
"runHistory": []
},
"createdAtMs": 1779872578080,
"updatedAtMs": 1779872578080,
"deleteAfterRun": false
},
{
"id": "1a7bb634",
"name": "remind-check",
"enabled": true,
"schedule": {
"kind": "cron",
"atMs": null,
"everyMs": null,
"expr": "* * * * *",
"tz": "Europe/Prague"
},
"payload": {
"kind": "agent_turn",
"message": "Run /home/nanobot/.nanobot/workspace/skills/remind/scripts/remind_check.py via exec tool (/home/nanobot/.local/bin/uv run). If the output is EMPTY (no lines printed), do NOT send any message — exit silently. Only if there is non-empty output, forward each line as a Telegram notification to the user.",
"deliver": true,
"channel": "telegram",
"to": "8826147089",
"channelMeta": {},
"sessionKey": "telegram:8826147089"
},
"state": {
"nextRunAtMs": 1779911340000,
"lastRunAtMs": 1779910800001,
"lastStatus": "ok",
"lastError": null,
"runHistory": [
{
"runAtMs": 1779906120001,
"status": "ok",
"durationMs": 102857,
"error": null
},
{
"runAtMs": 1779906240001,
"status": "ok",
"durationMs": 510361,
"error": null
},
{
"runAtMs": 1779906780003,
"status": "ok",
"durationMs": 17453,
"error": null
},
{
"runAtMs": 1779907022917,
"status": "ok",
"durationMs": 122021,
"error": null
},
{
"runAtMs": 1779907200001,
"status": "ok",
"durationMs": 434016,
"error": null
},
{
"runAtMs": 1779907680003,
"status": "ok",
"durationMs": 425365,
"error": null
},
{
"runAtMs": 1779908160002,
"status": "ok",
"durationMs": 23054,
"error": null
},
{
"runAtMs": 1779908220001,
"status": "ok",
"durationMs": 386611,
"error": null
},
{
"runAtMs": 1779908640002,
"status": "ok",
"durationMs": 453205,
"error": null
},
{
"runAtMs": 1779909120002,
"status": "ok",
"durationMs": 102348,
"error": null
},
{
"runAtMs": 1779909240002,
"status": "ok",
"durationMs": 49995,
"error": null
},
{
"runAtMs": 1779909300003,
"status": "ok",
"durationMs": 207256,
"error": null
},
{
"runAtMs": 1779909540002,
"status": "ok",
"durationMs": 136616,
"error": null
},
{
"runAtMs": 1779909720001,
"status": "ok",
"durationMs": 9602,
"error": null
},
{
"runAtMs": 1779909780002,
"status": "ok",
"durationMs": 129043,
"error": null
},
{
"runAtMs": 1779909960001,
"status": "ok",
"durationMs": 58836,
"error": null
},
{
"runAtMs": 1779910020001,
"status": "ok",
"durationMs": 172213,
"error": null
},
{
"runAtMs": 1779910200001,
"status": "ok",
"durationMs": 99259,
"error": null
},
{
"runAtMs": 1779910320002,
"status": "ok",
"durationMs": 467494,
"error": null
},
{
"runAtMs": 1779910800001,
"status": "ok",
"durationMs": 484056,
"error": null
}
]
},
"createdAtMs": 1779888543665,
"updatedAtMs": 1779911284057,
"deleteAfterRun": false
},
{
"id": "dream",
"name": "dream",
"enabled": true,
"schedule": {
"kind": "every",
"atMs": null,
"everyMs": 7200000,
"expr": null,
"tz": null
},
"payload": {
"kind": "system_event",
"message": "",
"deliver": false,
"channel": null,
"to": null,
"channelMeta": {},
"sessionKey": null
},
"state": {
"nextRunAtMs": 1779914222916,
"lastRunAtMs": 1779906806699,
"lastStatus": "ok",
"lastError": null,
"runHistory": [
{
"runAtMs": 1779906806699,
"status": "ok",
"durationMs": 216217,
"error": null
}
]
},
"createdAtMs": 1779899606686,
"updatedAtMs": 1779907022916,
"deleteAfterRun": false
}
]
}

2
keep.md Normal file
View File

@@ -0,0 +1,2 @@
- Podcast "Máš na míň" — moderátor Vašek Matějovský spolumoderuje s Radarem (Michal Vrátný, zakladatel Železné koule)
- Při studiu 3+ souborů z git repozitáře (typicky GitHub) naklonuj do tmp/ a zkoumej lokálně — ale jen pokud repo není obrovské (desítky MB OK, stovky MB+ už ne)

View File

@@ -0,0 +1,85 @@
# Plán: /todo skill a unifikace /note, /remind, /keep
## Cíl
Prozkoumat všechny možné architektonické přístupy k vytvoření `/todo` skillu a případné unifikaci s existujícími skilly `/note`, `/remind`, `/keep`. Žádná implementace dokud plán není schválen.
## Fáze 1: Brainstorming alternativních přístupů
### 1.1 Event-sourcing / append-only log
- Místo CRUD v SQLite: každá akce je immutable event (`TaskCreated`, `TaskCompleted`, `TaskDeleted`)
- Aktuální stav se materializuje z event logu
- Výhody: audit trail, undo/redo, distribuovaná synchronizace
- Nevýhody: komplexita, overkill pro osobní asistenta
### 1.2 File-based s Git history
- Každý úkol = jeden markdown file v `tasks/` directory
- Git commit = historie změn
- Výhody: lidsky čitelné, diff-friendly, Git jako audit trail
- Nevýhody: pomalé listování, race conditions při paralelním zápisu, složité vyhledávání
### 1.3 SQLite + JSONB flex schema
- Jedna tabulka `items` s `data JSONB` sloupcem
- Každý typ (note, todo, reminder, keep) má vlastní schema uvnitř JSON
- Výhody: extrémní flexibilita, žádné ALTER TABLE migrace
- Nevýhody: ztráta typové bezpečnosti, složité dotazy, SQLite JSONB je relativně nové
### 1.4 Graph-based (RDF / knowledge graph)
- Úkoly a poznámky jako uzly v grafu, vztahy jako hrany
- "úkol X souvisí s poznámkou Y", "úkol Z závisí na úkolu W"
- Výhody: bohaté vztahy mezi entitami
- Nevýhody: obrovská komplexita, žádný jednoduchý CLI
### 1.5 Hybrid: SQLite + Markdown export
- Primární storage SQLite (rychlé dotazy, fulltext search)
- Periodický export do markdown (čitelnost, Git backup)
- Výhody: kombinuje výhody obou světů
- Nevýhody: duplicitní data, synchronizační problém
### 1.6 Plugin architektura
- Jeden core skill `/item` s rozhraním
- `/note`, `/todo`, `/remind`, `/keep` jako pluginy registrující se do core
- Výhody: extensibility, čisté separation of concerns
- Nevýhody: potřebuje plugin API v nanobot frameworku (neexistuje)
### 1.7 CLI-first s TUI
- Místo chat-based: terminal UI (např. `taskwarrior`, `todo.txt`)
- Nanobot jen wrapper volající externí CLI
- Výhody: battle-tested tools, offline použití
- Nevýhody: závislost na externím toolu, méně integrace s LLM
## Fáze 2: Hlubší analýza 3 nejslibnějších variant
Z fáze 1 vybrat 3 varianty pro detailní pro/contra:
- Varianta C z předchozí analýzy (konvergence / thin wrapper)
- Varianta 1.3 (SQLite + JSONB flex schema)
- Varianta 1.5 (hybrid SQLite + Markdown)
Pro každou variantu:
- Datový model (ER diagram / schema)
- Příkazová struktura (všechny subcommands)
- Migrace z existujících skillů
- Testovací strategie
- Maintenance overhead
- User experience flow
## Fáze 3: Rozhodovací kritéria a scoring
Definovat vážená kritéria:
- Jednoduchost implementace (30%)
- Jednoduchost použití (25%)
- Extensibility (15%)
- Data integrity / reliability (15%)
- Performance (10%)
- Aesthetics / "feels right" (5%)
Každá varianta dostane skóre 1-5 v každém kritériu.
## Fáze 4: Finální doporučení
Na základě scoringu vybrat vítěznou variantu.
Popis: proč právě tato, co se stane s existujícími skilly, roadmap implementace.
## Omezení
- Žádná implementace dokud plán není explicitně schválen
- Analýza musí být kompletní — žádné "to se vyřeší později"
- Každá varianta musí mít konkrétní pro/contra, ne obecné fráze