zaloha vseho zbyvajiciho
This commit is contained in:
26
.gitignore
vendored
26
.gitignore
vendored
@@ -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
34
AGENTS.md
Normal 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
59
TOOLS.md
Normal 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
423
cron/jobs.json
Normal 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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
236
cron/jobs.json.bak-1779911421
Normal file
236
cron/jobs.json.bak-1779911421
Normal 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
2
keep.md
Normal 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)
|
||||||
85
plans/2026-06-07_todo-unification-plan.md
Normal file
85
plans/2026-06-07_todo-unification-plan.md
Normal 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
|
||||||
Reference in New Issue
Block a user