develop: sync knowledge.md (ollama usage API shape, no per-session tokens)
This commit is contained in:
@@ -292,7 +292,7 @@ Nanobot defaultně **vypíná vlastní logy** (`logger.disable("nanobot")`), pro
|
||||
|
||||
Žádná env proměnná ani config klíč pro log level mimo tyhle flagy neexistuje.
|
||||
|
||||
**Nasazení u nás:** `-v` přidáno do `ExecStart` v `~/.config/systemd/user/nanobot.service` na `nanobot.hell`. Logy živě: `ssh nanobot@nanobot.hell 'journalctl --user -u nanobot.service -f --no-pager'`.
|
||||
**Nasazení u nás:** `-v` bylo v `ExecStart` v `~/.config/systemd/user/nanobot.service` na `nanobot.hell`, ale **už tam není** (ověřeno 2026-09-15: `ExecStart=/home/nanobot/.local/bin/nanobot gateway`, poslední `LLM usage` řádek v journalu je z 2026-05-27). Bez `-v` tedy **tokeny nikde nejsou** — `Processing message`/`Response to` jsou INFO a logují se dál, `LLM usage` je DEBUG a ne. Logy živě: `ssh nanobot@nanobot.hell 'journalctl --user -u nanobot.service -f --no-pager'`.
|
||||
|
||||
**Co `-v` ukáže v jednom tahu** (ověřeno na WebUI zprávě):
|
||||
|
||||
@@ -570,6 +570,28 @@ Daemon notifikuje **jen Telegram** (přes Bot API, deterministicky). Když task
|
||||
|
||||
---
|
||||
|
||||
## Exec safety guard shazuje český text — diakritika + dvojtečka = „windowsová cesta"
|
||||
|
||||
**Problém → příčina → pravidlo.** `exec` vrátí `Command blocked by safety guard (path outside working dir)` u příkazu, který obsahuje běžnou českou prózu. Příčina: `ExecTool._extract_absolute_paths()` (`agent/tools/shell.py`) hledá windowsové cesty regexem `(?<![A-Za-z])(?:[A-Za-z]:[^\s"'|><;]*|…)`. Lookbehind je **ASCII-only**, takže znak s diakritikou před ASCII písmenem ho neutne — `Cíl:` dá token `l:`, `Závěr:`/`směr:` dají `r:`. `Path("r:").resolve()` to rozvine vůči cwd démona (`/home/nanobot`, ne vůči workdiru příkazu) na `/home/nanobot/r:` → mimo workspace → blok. Ověřeno 2026-09-11 spuštěním nainstalovaného guardu na reálných příkazech.
|
||||
|
||||
**Guard jede nad raw command stringem, bez shell parseru** (`_split_shell_segments` se používá jen na allow/deny patterns). Nerozliší tedy argument od obsahu heredocu — heredoc, `--text` i `printf | pipe` s týmž textem padnou identicky. Citování a quoted heredoc **nepomáhají**.
|
||||
|
||||
**Pravidlo pro psaní skillů: český text nikdy nedávej do command stringu.** Vždy `write_file` do `tmp/` + předání **cesty** (`--file <path>`, nebo `< tmp/soubor`). Cesta v příkazu je neškodná; relativní cesty žádný z regexů nechytá.
|
||||
|
||||
**Pravidlo je od 2026-09-11 zapsané globálně** v `workspace/AGENTS.md`, sekce `## exec Tool` — tedy v system promptu při každém tahu, nezávisle na tom, jaký skill se triggerne. `AGENTS.md` je jediný z `BOOTSTRAP_FILES` (`agent/context.py:57`), který je user-ownovaný; `SOUL.md`, `USER.md` i `memory/MEMORY.md` přepisuje Dream a bundled `templates/` přepíše upgrade balíčku. **Dvě omezení:** (1) `AGENTS.md` se bere z `project_root` aktuálního tahu (`context.py:163`), takže v session scoped do `tmp/<x>` se root verze nenačte — pro běžný chat platí; (2) kdyby byl obsah identický s `templates/AGENTS.md`, soubor se do promptu tiše nedá (`context.py:179–182`). Tentýž guard byl v `AGENTS.md` předtím zdokumentovaný **dvakrát izolovaně** (sekce `## Git commit timestamps` o `date '+%H:%M:%S'` → token `H:%M:%S`, a původní věta o chybějícím workspace path), aniž by se pojmenovala společná příčina.
|
||||
|
||||
Co blokuje a co ne (ASCII písmeno + `:`, kde znak **před** písmenem není ASCII písmeno):
|
||||
|
||||
| Blokuje | Projde |
|
||||
|---|---|
|
||||
| `Cíl:`, `Závěr:`, `směr:`, `díl:` | `Úkol:`, `Stav:`, `Řešení:`, `Otázky:`, `Poznámka:` |
|
||||
|
||||
Pozor i na druhý guard nad raw stringem: `if "..\\" in cmd or "../" in cmd` → jakákoli **prozaická** zmínka `../` shodí příkaz na `path traversal detected`.
|
||||
|
||||
**Stav skillů.** Opraveno na `--file`: `project` (`log --file`) a `note` (`note_capture.py --file`, 2026-09-11 — byl nejrizikovější, protože bere vstup uživatele doslova, takže poznámka „Cíl: …" tiše selhala). **Zbývá dluh:** `bookmark` (český článek v heredocu) a `remind` (`edit --text "…"`). Upstream regex zůstává rozbitý — fix by chtěl unicode-aware lookbehind.
|
||||
|
||||
---
|
||||
|
||||
## Prostředí `exec` toolu — PATH z procesu tam nedosáhne
|
||||
|
||||
`ExecTool._build_env()` (`agent/tools/shell.py`) staví prostředí subprocessu **od nuly**. Na Unixu předá jen `HOME`, `LANG`, `TERM`, `PYTHONUNBUFFERED` (+ cokoli v `tools.exec.allowedEnvKeys`). **`PATH` se z `os.environ` nekopíruje** — na Windows ano, na Unixu ne. Cokoli nastavíš v systemd unitu, `~/.profile` nebo wrapperu, `exec` neuvidí.
|
||||
@@ -723,7 +745,7 @@ Substituce Claude.ai "Projects". Adresář na projekt, ne jeden soubor: `workspa
|
||||
|
||||
**Nahradil netrackovaný server-side skill** (existoval na serveru mimo tento repo, žádná zmínka v history/knowledge/decisions před tímto datem): plochý soubor `projects/<slug>.md` s frontmatterem `status`/`priority`/`created`, CLI backend (`scripts/project.py`: add/list/show/status), `switch` ukládal aktivní projekt do `my` scratchpad nástroje (viz níže). Reálná data (`projects/radio-1.md`, projekt na stříhání audio streamu Radia 1, 2026-06-09) přemigrována do nového formátu jako `projects/radio1/`. Plná historie: history.md 2026-07-22.
|
||||
|
||||
**Zápis do `memory.md` jde výhradně přes `skills/project/scripts/project_cli.py log`** (od 2026-09-02). Subcommandy `activate` / `log` / `list` / `new`; volat workspace-relativně `uv run skills/project/scripts/project_cli.py …`. Skript vlastní datum (systémové hodiny, Europe/Prague) a koncový newline — obojí model prokazatelně kazil: `chata/memory.md` měl dva záznamy s vymyšleným datem `2026-09-14` (zapsané 09-01) a `proxmox/memory.md` slepený append na předchozím řádku, protože `edit_file` kotva se hádala bez přečtení souboru. Text se předává **stdin quoted heredocem** (`<<'NOTE'`), ne `--text` — shell obsah neinterpretuje, takže `„"`, `'` i `"` projdou doslova (v `log/note.log` je doložený případ, kdy model `--text` argument zmršil na `...`). Stav skriptu přepisuje env `PROJECTS_DIR` (testy). Plný kontext: history.md 2026-09-02.
|
||||
**Zápis do `memory.md` jde výhradně přes `skills/project/scripts/project_cli.py log`** (od 2026-09-02). Subcommandy `activate` / `log` / `list` / `new`; volat workspace-relativně `uv run skills/project/scripts/project_cli.py …`. Skript vlastní datum (systémové hodiny, Europe/Prague) a koncový newline — obojí model prokazatelně kazil: `chata/memory.md` měl dva záznamy s vymyšleným datem `2026-09-14` (zapsané 09-01) a `proxmox/memory.md` slepený append na předchozím řádku, protože `edit_file` kotva se hádala bez přečtení souboru. Text se předává **výhradně souborem**: `write_file` do `tmp/` + `log <slug> --file tmp/…` (od 2026-09-11). Dřív to byl stdin quoted heredoc (`<<'NOTE'`), protože `--text` model prokazatelně mrzačil (v `log/note.log` je doložený případ, kdy argument zmršil na `...`) — jenže heredoc padl na exec safety guardu, který sejme jakýkoli český text v command stringu bez ohledu na citování (viz sekce „Exec safety guard shazuje český text" výše; doloženo session `002f2196`, kdy tři varianty po sobě selhaly na `Diagnóza/směr:`). `--text` je proto z CLI **odstraněn**, stdin zůstal jako fallback. Stav skriptu přepisuje env `PROJECTS_DIR` (testy). Plný kontext: history.md 2026-09-02.
|
||||
|
||||
**Projektová data nemají strop ani konsolidaci** — `memory.md` roste neomezeně a nikdy se nekomprimuje ani nearchivuje. Velikost se řeší **výhradně na straně čtení**: `activate` nad limitem tool výsledku vypustí z výstupu nejstarší záznamy a ukáže cestu k plnému logu, soubor na disku nechá beze změny. Zamítnutá varianta: prahy 8 000 / 12 000 znaků s nabídkou konsolidace — ztráta zadaného obsahu je horší failure mode než jakákoli úspora kontextu (a čísla stála na špatném okně, viz níže).
|
||||
|
||||
@@ -1256,3 +1278,27 @@ dostávaly `store` z `remind`). Proto všechny skilly kromě `remind` prefixují
|
||||
skillu (`note_capture.py`, `wiki_sync.py`) — je to nutnost, ne estetika. U kolize, které se
|
||||
nelze vyhnout (`wiki_search.py` je i v retired `llm-wiki`), rozhoduje **pořadí** v
|
||||
`extra-paths`. Zdroj: history 2026-09-09.
|
||||
|
||||
## Ollama usage API: co v odpovědi je a co ne
|
||||
|
||||
`GET https://ollama.com/api/usage` (Bearer klíč z `workspace/.env`) vrací
|
||||
`limits.session` (hodinové okno) a `limits.weekly`, každé s `usage` (zlomek limitu)
|
||||
a `models: [{name, request_count}]` — **pole, ne slovník**. `activity.cost` je na Pro
|
||||
plánu rozbité (vždy `0.00000`). Žádné reset timestampy, žádné tokeny, žádný cost split.
|
||||
|
||||
**`usage` má 3 desetinná místa** (`0.072`, `0.156`) → rozlišení 0,1 % limitu.
|
||||
Delta za minutu je proto skoro vždy 0 — jediná přesná veličina je `request_count`
|
||||
per model. Ověřeno 2026-09-15.
|
||||
|
||||
## Nanobot nemá nikde per-session spotřebu tokenů
|
||||
|
||||
- `memory/history.jsonl` = destilát paměti z Dream procesoru (`cursor`, `timestamp`,
|
||||
`content`, u části `session_key`) — **není** to účtovací log, žádné tokeny.
|
||||
- `sessions/*.jsonl` = per-turn zprávy (`role`, `content`, `timestamp`, `tool_calls`,
|
||||
`reasoning_content`, `latency_ms`) — **taky bez tokenů a bez názvu modelu**.
|
||||
- Jediný zdroj tokenů je `LLM usage: prompt=… completion=… cached=…` v journalu, což je
|
||||
**DEBUG** (vyžaduje `-v` v `ExecStart`, viz sekce o log levelu) a navíc nenese session id.
|
||||
|
||||
→ Atribuce spotřeby na session jde jen **časovou korelací** (timestampy v `sessions/*.jsonl`
|
||||
a `Processing message from …` v journalu) proti řadě vzorků z `db/ollama_usage.sqlite`.
|
||||
Ověřeno 2026-09-15, zdroj: [[plans/ollama-usage-poller.md]] sekce Revize.
|
||||
|
||||
Reference in New Issue
Block a user