diff --git a/workspace/skills/self-improving/SKILL.md b/workspace/skills/self-improving/SKILL.md new file mode 100644 index 000000000..642998bbd --- /dev/null +++ b/workspace/skills/self-improving/SKILL.md @@ -0,0 +1,223 @@ +--- +name: self-improving +description: Catat kesalahan, koreksi, dan pelajaran agar agent terus belajar dari pengalaman. Otomatis aktif saat terjadi error atau user mengoreksi. +metadata: {"nanobot":{"emoji":"🧠"}} +--- + +# Self-Improving Agent + +Skill ini membuat agent belajar dari kesalahan dan koreksi. Setiap error, koreksi user, atau knowledge gap dicatat ke file log, dan pelajaran penting dipromosikan ke MEMORY.md agar persisten lintas sesi. + +> Diadaptasi dari [self-improving-agent di ClawHub](https://clawhub.ai/pskoett/self-improving-agent) untuk PicoClaw. + +## When to use (trigger phrases) + +Skill ini aktif **otomatis** saat agent mendeteksi situasi berikut: + +**Kesalahan:** +- Command gagal (non-zero exit code) +- Error, exception, atau stack trace +- Timeout atau connection failure + +**Koreksi user:** +- "Bukan, yang bener..." +- "Salah, seharusnya..." +- "Actually, it should be..." + +**Knowledge gap:** +- User kasih info yang agent belum tahu +- Dokumentasi ternyata outdated +- Perilaku API berbeda dari yang agent kira + +**Feature request:** +- "Bisa gak kamu..." +- "Bagaimana kalau..." +- "I wish you could..." + +## Storage + +Semua log disimpan di `skills/self-improving/data/`: + +``` +skills/self-improving/data/ +├── LEARNINGS.md # Koreksi, knowledge gaps, best practices +├── ERRORS.md # Command failures, exceptions +└── FEATURE_REQUESTS.md # User-requested capabilities +``` + +## Quick Reference + +| Situasi | Aksi | +|---------|------| +| Command/operasi gagal | Catat ke `ERRORS.md` | +| User mengoreksi agent | Catat ke `LEARNINGS.md` (kategori: `correction`) | +| User minta fitur baru | Catat ke `FEATURE_REQUESTS.md` | +| API/tool eksternal gagal | Catat ke `ERRORS.md` dengan detail integrasi | +| Pengetahuan agent outdated | Catat ke `LEARNINGS.md` (kategori: `knowledge_gap`) | +| Ditemukan cara yang lebih baik | Catat ke `LEARNINGS.md` (kategori: `best_practice`) | +| Pelajaran bisa diterapkan luas | Promote ke `MEMORY.md` | + +## Format Log + +### Learning Entry + +Append ke `skills/self-improving/data/LEARNINGS.md`: + +```markdown +## [LRN-YYYYMMDD-XXX] category + +**Logged**: ISO-8601 timestamp +**Priority**: low | medium | high | critical +**Status**: pending + +### Summary +Satu baris ringkasan pelajaran + +### Details +Konteks lengkap: apa yang terjadi, apa yang salah, apa yang benar + +### Suggested Action +Fix atau improvement spesifik + +### Metadata +- Source: conversation | error | user_feedback +- Related Files: path/to/file +- Tags: tag1, tag2 +--- +``` + +### Error Entry + +Append ke `skills/self-improving/data/ERRORS.md`: + +```markdown +## [ERR-YYYYMMDD-XXX] skill_or_command_name + +**Logged**: ISO-8601 timestamp +**Priority**: high +**Status**: pending + +### Summary +Ringkasan singkat apa yang gagal + +### Error +``` +Pesan error atau output aktual +``` + +### Context +- Command yang dijalankan +- Parameter yang dipakai +- Detail environment jika relevan + +### Suggested Fix +Jika teridentifikasi, apa yang bisa memperbaiki ini + +### Metadata +- Reproducible: yes | no | unknown +- Related Files: path/to/file +--- +``` + +### Feature Request Entry + +Append ke `skills/self-improving/data/FEATURE_REQUESTS.md`: + +```markdown +## [FEAT-YYYYMMDD-XXX] capability_name + +**Logged**: ISO-8601 timestamp +**Priority**: medium +**Status**: pending + +### Requested Capability +Apa yang user ingin lakukan + +### User Context +Kenapa mereka butuh ini, masalah apa yang ingin dipecahkan + +### Suggested Implementation +Bagaimana ini bisa dibangun + +### Metadata +- Frequency: first_time | recurring +--- +``` + +## ID Format + +Format: `TYPE-YYYYMMDD-XXX` + +- TYPE: `LRN` (learning), `ERR` (error), `FEAT` (feature) +- YYYYMMDD: Tanggal saat ini +- XXX: Nomor urut (001, 002, dst) + +## Resolve Entry + +Saat issue sudah diperbaiki, update entry: + +1. Ubah `**Status**: pending` → `**Status**: resolved` +2. Tambah blok resolusi: + +```markdown +### Resolution +- **Resolved**: 2026-02-24T12:00:00Z +- **Notes**: Penjelasan singkat apa yang dilakukan +``` + +## Promote ke MEMORY.md + +Saat pelajaran applicable secara luas (bukan one-off fix), promosikan ke `MEMORY.md`: + +### Kapan Promote + +- Pelajaran berlaku untuk banyak skill/fitur +- Pengetahuan penting yang harus diingat lintas sesi +- Mencegah kesalahan berulang +- Mendokumentasikan konvensi khusus user + +### Cara Promote + +1. **Ringkas** pelajaran jadi rule singkat +2. **Tambahkan** ke section yang tepat di `MEMORY.md` +3. **Update** entry original: ubah `**Status**` → `promoted` + +### Contoh + +**Learning entry (verbose):** +> PicoClaw exec tool memblokir pattern `${}` dan `> /dev/null`. Command cron harus ditulis sederhana tanpa shell metacharacters. + +**Di MEMORY.md (ringkas):** +```markdown +## PicoClaw Safety Guard +- Exec tool memblokir: `${}`, `$()`, `> /dev/null`, `source *.sh`, `sudo`, `eval` +- Command cron harus ditulis sederhana: `bash scripts/file.sh "arg"` +``` + +## Recurring Pattern + +Jika mencatat pelajaran yang mirip dengan entry yang sudah ada: + +1. **Cari dulu**: apakah sudah ada entry serupa +2. **Link**: tambah `See Also: ERR-YYYYMMDD-XXX` di Metadata +3. **Naikkan priority** jika issue terus berulang +4. **Promote** jika sudah 3x berulang → masukkan ke `MEMORY.md` + +## Periodic Review + +Review `skills/self-improving/data/` di saat-saat natural: + +- Sebelum mulai task besar baru +- Setelah menyelesaikan fitur +- Saat bekerja di area yang pernah ada masalah +- Mingguan selama development aktif + +## Rules + +1. **Log segera** — konteks paling segar tepat setelah masalah terjadi +2. **Spesifik** — agent di sesi berikutnya harus bisa memahami dengan cepat +3. **Sertakan langkah reproduksi** — terutama untuk error +4. **Sarankan fix konkret** — bukan sekadar "perlu investigasi" +5. **Promote agresif** — jika ragu, masukkan ke MEMORY.md +6. **Jangan log hal sepele** — hanya yang non-obvious dan bermanfaat +7. **Hindari menyimpan data sensitif** — jangan log API key, password, atau data pribadi diff --git a/workspace/skills/self-improving/data/ERRORS.md b/workspace/skills/self-improving/data/ERRORS.md new file mode 100644 index 000000000..048196aa3 --- /dev/null +++ b/workspace/skills/self-improving/data/ERRORS.md @@ -0,0 +1,5 @@ +# Errors + +Log command failures dan exceptions di sini. + +--- diff --git a/workspace/skills/self-improving/data/FEATURE_REQUESTS.md b/workspace/skills/self-improving/data/FEATURE_REQUESTS.md new file mode 100644 index 000000000..4184fe0cc --- /dev/null +++ b/workspace/skills/self-improving/data/FEATURE_REQUESTS.md @@ -0,0 +1,5 @@ +# Feature Requests + +Log permintaan fitur dari user di sini. + +--- diff --git a/workspace/skills/self-improving/data/LEARNINGS.md b/workspace/skills/self-improving/data/LEARNINGS.md new file mode 100644 index 000000000..cd9c559d8 --- /dev/null +++ b/workspace/skills/self-improving/data/LEARNINGS.md @@ -0,0 +1,5 @@ +# Learnings + +Log koreksi, knowledge gaps, dan best practices di sini. + +--- diff --git a/workspace/skills/system-monitor/SKILL.md b/workspace/skills/system-monitor/SKILL.md new file mode 100644 index 000000000..53e66b56f --- /dev/null +++ b/workspace/skills/system-monitor/SKILL.md @@ -0,0 +1,119 @@ +--- +name: system-monitor +description: Monitor kesehatan sistem — CPU, RAM, disk, suhu, dan uptime. Kirim alert via ntfy jika ada masalah. +metadata: {"nanobot":{"emoji":"📊"}} +--- + +# System Monitor + +Monitor kesehatan STB/server: CPU, RAM, disk, suhu, dan uptime. Bisa dijalankan manual atau dijadwalkan via cron tool. + +## When to use (trigger phrases) + +- "cek sistem" / "system status" +- "health check" / "kesehatan server" +- "berapa suhu CPU?" / "CPU temperature" +- "disk penuh?" / "free disk space" +- "RAM usage" / "memory usage" +- "uptime" / "sudah jalan berapa lama?" +- "monitor sistem setiap jam" + +## Perintah Manual + +### Health check lengkap (via exec tool) + +```bash +bash skills/system-monitor/scripts/health_check.sh +``` + +Output berupa ringkasan singkat yang mudah dibaca: + +``` +🖥️ SYSTEM HEALTH REPORT +======================== +📅 2026-02-24 12:00 WIB +⏱️ Uptime: 3 days, 2:15 +🔥 CPU Temp: 52°C ✅ +💻 CPU Load: 0.85 (1 core) +🧠 RAM: 412MB / 1024MB (40%) ✅ +💾 Disk: 4.2GB / 14.5GB (29%) ✅ +🌐 Network: ✅ connected +======================== +Status: ALL OK ✅ +``` + +### Cek komponen spesifik (via exec tool) + +```bash +bash skills/system-monitor/scripts/health_check.sh --cpu +bash skills/system-monitor/scripts/health_check.sh --memory +bash skills/system-monitor/scripts/health_check.sh --disk +bash skills/system-monitor/scripts/health_check.sh --temp +bash skills/system-monitor/scripts/health_check.sh --network +``` + +## Jadwal Otomatis (via cron tool) + +### Health report harian pagi + +```json +{"action": "add", "message": "📊 System Health Report", "command": "bash skills/system-monitor/scripts/health_check.sh", "cron_expr": "0 7 * * *"} +``` + +### Monitor suhu tiap 6 jam + +```json +{"action": "add", "message": "🌡️ Temp check", "command": "bash skills/system-monitor/scripts/health_check.sh --temp", "every_seconds": 21600} +``` + +### Health check + ntfy alert (pakai reminder skill) + +Jika ingin health report dikirim ke HP juga via ntfy, buat 2 job: + +**Job 1 — Report ke Telegram:** +```json +{"action": "add", "message": "📊 Daily health", "command": "bash skills/system-monitor/scripts/health_check.sh", "cron_expr": "0 7 * * *"} +``` + +**Job 2 — Alert ke ntfy (hanya jika ada masalah):** +```json +{"action": "add", "message": "ntfy: health alert", "command": "bash skills/system-monitor/scripts/health_alert.sh", "every_seconds": 3600} +``` + +Script `health_alert.sh` hanya mengirim notifikasi jika ada warning/critical. + +## Threshold (Default) + +| Metrik | Warning | Critical | +|--------|---------|----------| +| CPU Temp | > 70°C | > 80°C | +| RAM Usage | > 80% | > 90% | +| Disk Usage | > 80% | > 90% | +| CPU Load (1-min) | > 2.0 | > 4.0 | + +Threshold bisa dikustomisasi di `skills/system-monitor/data/config`. + +## Custom Config + +Buat `skills/system-monitor/data/config` jika ingin override default: + +```bash +mkdir -p skills/system-monitor/data +cat > skills/system-monitor/data/config << 'ENDCONF' +TEMP_WARN=65 +TEMP_CRIT=75 +RAM_WARN=85 +RAM_CRIT=95 +DISK_WARN=85 +DISK_CRIT=95 +LOAD_WARN=3.0 +LOAD_CRIT=5.0 +ENDCONF +``` + +## Rules + +1. **Prefer script** — selalu gunakan `health_check.sh`, jangan `top` atau `htop` (bisa hang). +2. **Jangan pakai `-f` flag** — streaming command tidak cocok untuk exec tool. +3. **Alert cukup summary** — jangan dump output panjang, cukup status singkat. +4. **Kombinasikan dengan ntfy** — gunakan `health_alert.sh` untuk push notification saat ada masalah. diff --git a/workspace/skills/system-monitor/scripts/health_alert.sh b/workspace/skills/system-monitor/scripts/health_alert.sh new file mode 100755 index 000000000..9aa9003b0 --- /dev/null +++ b/workspace/skills/system-monitor/scripts/health_alert.sh @@ -0,0 +1,112 @@ +#!/bin/bash +# health_alert.sh — Send ntfy alert ONLY if system has warning/critical issues +# Does nothing if everything is OK (silent success). +# Designed to be called from cron every hour. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +SKILL_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +CONF_FILE="$SKILL_DIR/data/config" + +# Defaults +TEMP_WARN=70 +TEMP_CRIT=80 +RAM_WARN=80 +RAM_CRIT=90 +DISK_WARN=80 +DISK_CRIT=90 + +if [ -f "$CONF_FILE" ]; then + . "$CONF_FILE" +fi + +# Detect issues +alerts="" +priority="default" +tags="computer" + +# Check CPU temp +if [ -f /sys/class/thermal/thermal_zone0/temp ]; then + raw=$(cat /sys/class/thermal/thermal_zone0/temp) + temp=$((raw / 1000)) + if [ "$temp" -ge "$TEMP_CRIT" ]; then + alerts="$alerts 🔥 CPU: ${temp}°C CRITICAL!" + priority="urgent" + tags="fire,$tags" + elif [ "$temp" -ge "$TEMP_WARN" ]; then + alerts="$alerts 🔥 CPU: ${temp}°C warning" + priority="high" + tags="warning,$tags" + fi +fi + +# Check RAM +mem_info=$(free -m 2>/dev/null | grep Mem) +if [ -n "$mem_info" ]; then + total=$(echo "$mem_info" | awk '{print $2}') + used=$(echo "$mem_info" | awk '{print $3}') + if [ "$total" -gt 0 ]; then + pct=$((used * 100 / total)) + if [ "$pct" -ge "$RAM_CRIT" ]; then + alerts="$alerts 🧠 RAM: ${pct}% CRITICAL!" + priority="urgent" + elif [ "$pct" -ge "$RAM_WARN" ]; then + alerts="$alerts 🧠 RAM: ${pct}% warning" + [ "$priority" = "default" ] && priority="high" + fi + fi +fi + +# Check disk +disk_pct=$(df / 2>/dev/null | tail -1 | awk '{print $5}' | tr -d '%') +if [ -n "$disk_pct" ]; then + if [ "$disk_pct" -ge "$DISK_CRIT" ]; then + alerts="$alerts 💾 Disk: ${disk_pct}% CRITICAL!" + priority="urgent" + elif [ "$disk_pct" -ge "$DISK_WARN" ]; then + alerts="$alerts 💾 Disk: ${disk_pct}% warning" + [ "$priority" = "default" ] && priority="high" + fi +fi + +# Check network +if ! ping -c 1 -W 3 8.8.8.8 > /dev/null 2>&1; then + alerts="$alerts 🌐 Network: disconnected!" + [ "$priority" = "default" ] && priority="high" +fi + +# Exit silently if no issues +if [ -z "$alerts" ]; then + exit 0 +fi + +# Find ntfy config (check reminder skill's config) +NTFY_TOPIC="" +REMINDER_CONF="$SKILL_DIR/../reminder/data/ntfy.conf" +if [ -f "$REMINDER_CONF" ]; then + . "$REMINDER_CONF" +fi + +# Also check own config +OWN_NTFY="$SKILL_DIR/data/ntfy.conf" +if [ -f "$OWN_NTFY" ]; then + . "$OWN_NTFY" +fi + +if [ -z "$NTFY_TOPIC" ]; then + # No ntfy configured — just print to stdout (goes to Telegram via cron) + echo "⚠️ SYSTEM ALERT:$alerts" + exit 0 +fi + +# Send via ntfy +HOSTNAME_STR=$(hostname 2>/dev/null || echo "STB") +eval curl -sf \ + -H "\"Title: System Alert - $HOSTNAME_STR\"" \ + -H "\"Priority: $priority\"" \ + -H "\"Tags: $tags\"" \ + -d "\"$alerts\"" \ + "\"$NTFY_TOPIC\"" || true + +echo "⚠️ SYSTEM ALERT (sent to ntfy):$alerts" diff --git a/workspace/skills/system-monitor/scripts/health_check.sh b/workspace/skills/system-monitor/scripts/health_check.sh new file mode 100755 index 000000000..9fb391d96 --- /dev/null +++ b/workspace/skills/system-monitor/scripts/health_check.sh @@ -0,0 +1,189 @@ +#!/bin/bash +# health_check.sh — System health check for PicoClaw STB/server +# Usage: +# bash skills/system-monitor/scripts/health_check.sh # Full report +# bash skills/system-monitor/scripts/health_check.sh --cpu # CPU only +# bash skills/system-monitor/scripts/health_check.sh --memory # RAM only +# bash skills/system-monitor/scripts/health_check.sh --disk # Disk only +# bash skills/system-monitor/scripts/health_check.sh --temp # Temperature only +# bash skills/system-monitor/scripts/health_check.sh --network # Network only + +set -euo pipefail + +# Load config if exists +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +SKILL_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +CONF_FILE="$SKILL_DIR/data/config" + +# Defaults +TEMP_WARN=70 +TEMP_CRIT=80 +RAM_WARN=80 +RAM_CRIT=90 +DISK_WARN=80 +DISK_CRIT=90 +LOAD_WARN=2.0 +LOAD_CRIT=4.0 + +if [ -f "$CONF_FILE" ]; then + . "$CONF_FILE" +fi + +# Helper: status icon +status_icon() { + local val=$1 warn=$2 crit=$3 + if [ "$(echo "$val >= $crit" | bc -l 2>/dev/null || echo 0)" = "1" ]; then + echo "🔴" + elif [ "$(echo "$val >= $warn" | bc -l 2>/dev/null || echo 0)" = "1" ]; then + echo "🟡" + else + echo "✅" + fi +} + +# Components +get_uptime() { + uptime_str=$(uptime -p 2>/dev/null || uptime | sed 's/.*up /up /' | sed 's/,.*load.*//') + echo "$uptime_str" +} + +get_cpu_temp() { + temp="" + if [ -f /sys/class/thermal/thermal_zone0/temp ]; then + raw=$(cat /sys/class/thermal/thermal_zone0/temp) + temp=$(echo "$raw / 1000" | bc 2>/dev/null || echo "$((raw / 1000))") + fi + if [ -z "$temp" ]; then + echo "N/A" + return + fi + icon=$(status_icon "$temp" "$TEMP_WARN" "$TEMP_CRIT") + echo "${temp}°C $icon" +} + +get_cpu_load() { + load=$(cat /proc/loadavg 2>/dev/null | awk '{print $1}') + if [ -z "$load" ]; then + load=$(uptime | grep -oP 'load average: \K[^,]+' 2>/dev/null || echo "N/A") + fi + cores=$(nproc 2>/dev/null || echo 1) + if [ "$load" != "N/A" ]; then + icon=$(status_icon "$load" "$LOAD_WARN" "$LOAD_CRIT") + echo "$load ($cores core) $icon" + else + echo "N/A" + fi +} + +get_memory() { + mem_info=$(free -m 2>/dev/null | grep Mem) + if [ -z "$mem_info" ]; then + echo "N/A" + return + fi + total=$(echo "$mem_info" | awk '{print $2}') + used=$(echo "$mem_info" | awk '{print $3}') + if [ "$total" -gt 0 ]; then + pct=$((used * 100 / total)) + else + pct=0 + fi + icon=$(status_icon "$pct" "$RAM_WARN" "$RAM_CRIT") + echo "${used}MB / ${total}MB (${pct}%) $icon" +} + +get_disk() { + disk_info=$(df -h / 2>/dev/null | tail -1) + if [ -z "$disk_info" ]; then + echo "N/A" + return + fi + used=$(echo "$disk_info" | awk '{print $3}') + total=$(echo "$disk_info" | awk '{print $2}') + pct_raw=$(echo "$disk_info" | awk '{print $5}' | tr -d '%') + icon=$(status_icon "$pct_raw" "$DISK_WARN" "$DISK_CRIT") + echo "${used} / ${total} (${pct_raw}%) $icon" +} + +get_network() { + if ping -c 1 -W 3 8.8.8.8 > /dev/null 2>&1; then + echo "✅ connected" + else + echo "🔴 disconnected" + fi +} + +# Get overall status +get_overall_status() { + local has_warning=false has_critical=false + + # Check temp + if [ -f /sys/class/thermal/thermal_zone0/temp ]; then + raw=$(cat /sys/class/thermal/thermal_zone0/temp) + temp=$((raw / 1000)) + [ "$temp" -ge "$TEMP_CRIT" ] && has_critical=true + [ "$temp" -ge "$TEMP_WARN" ] && has_warning=true + fi + + # Check RAM + mem_info=$(free -m 2>/dev/null | grep Mem) + if [ -n "$mem_info" ]; then + total=$(echo "$mem_info" | awk '{print $2}') + used=$(echo "$mem_info" | awk '{print $3}') + if [ "$total" -gt 0 ]; then + pct=$((used * 100 / total)) + [ "$pct" -ge "$RAM_CRIT" ] && has_critical=true + [ "$pct" -ge "$RAM_WARN" ] && has_warning=true + fi + fi + + # Check disk + disk_pct=$(df / 2>/dev/null | tail -1 | awk '{print $5}' | tr -d '%') + if [ -n "$disk_pct" ]; then + [ "$disk_pct" -ge "$DISK_CRIT" ] && has_critical=true + [ "$disk_pct" -ge "$DISK_WARN" ] && has_warning=true + fi + + if [ "$has_critical" = true ]; then + echo "CRITICAL 🔴" + elif [ "$has_warning" = true ]; then + echo "WARNING 🟡" + else + echo "ALL OK ✅" + fi +} + +# Main +MODE="${1:-full}" +DATE_STR=$(date '+%Y-%m-%d %H:%M %Z' 2>/dev/null || date) + +case "$MODE" in + --cpu) + echo "💻 CPU Load: $(get_cpu_load)" + ;; + --temp) + echo "🔥 CPU Temp: $(get_cpu_temp)" + ;; + --memory) + echo "🧠 RAM: $(get_memory)" + ;; + --disk) + echo "💾 Disk: $(get_disk)" + ;; + --network) + echo "🌐 Network: $(get_network)" + ;; + *) + echo "🖥️ SYSTEM HEALTH REPORT" + echo "========================" + echo "📅 $DATE_STR" + echo "⏱️ Uptime: $(get_uptime)" + echo "🔥 CPU Temp: $(get_cpu_temp)" + echo "💻 CPU Load: $(get_cpu_load)" + echo "🧠 RAM: $(get_memory)" + echo "💾 Disk: $(get_disk)" + echo "🌐 Network: $(get_network)" + echo "========================" + echo "Status: $(get_overall_status)" + ;; +esac