AI slop cleanup
This commit is contained in:
parent
3a50722f4c
commit
d63aa0aa4e
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
agent:
|
agent:
|
||||||
character : hendrik # Directory name in agent/characters/<character>/
|
character : hendrik # Directory name in agent/characters/<character>/
|
||||||
max_iterations : 40 # step(s)
|
max_iterations : 80 # step(s)
|
||||||
max_history_chat : 0 # message(s) - 0 for unlimited (Dead Config)
|
max_history_chat : 0 # message(s) - 0 for unlimited (Dead Config)
|
||||||
max_tool_output : 0 # character(s) - 0 for unlimited (Connected to AGENT_MAX_TOOL_OUTPUT but Dead Config)
|
max_tool_output : 0 # character(s) - 0 for unlimited
|
||||||
|
|
||||||
user:
|
user:
|
||||||
id: # Fill your user UUID here, empty = TUI/MUC guest
|
id: # Fill your user UUID here, empty = TUI/MUC guest
|
||||||
@ -15,26 +15,23 @@ llm:
|
|||||||
moop: # Model Option
|
moop: # Model Option
|
||||||
db_path: "~/.config/hendrik/moop.sqlite3"
|
db_path: "~/.config/hendrik/moop.sqlite3"
|
||||||
|
|
||||||
asr: # Speech-to-Text (push-to-talk TUI). Model dikelola via moop tipe 'asr'.
|
asr:
|
||||||
record_dir : "~/.config/hendrik/recordings" # lokasi file hasil rekaman
|
record_dir : "~/.config/hendrik/recordings"
|
||||||
record_key : f9 # tombol push-to-talk (f1..f12 / ctrl-<huruf>)
|
record_backend : pulse # ffmpeg input: pulse | alsa | oss | windows
|
||||||
record_backend : pulse # ffmpeg input: pulse | alsa | oss | windows
|
device : default
|
||||||
device : default # nama device input
|
windows_mic : "" # if backend==windows: device dshow name, example: "Microphone Array (Realtek(R) Audio)"
|
||||||
windows_mic : "" # backend=windows: nama device dshow,
|
format : wav # wav | ogg (opus)
|
||||||
# contoh "Microphone Array (Realtek(R) Audio)"
|
sample_rate : 16000 # Hz
|
||||||
format : wav # wav | ogg (opus)
|
channels : 1
|
||||||
sample_rate : 16000 # Hz
|
max_seconds : 120 # second
|
||||||
channels : 1
|
transcribe_timeout : 60 # second
|
||||||
max_seconds : 60 # auto-stop pengaman
|
keep_recordings : false
|
||||||
transcribe_timeout: 60 # detik timeout request ASR
|
auto_submit : true
|
||||||
keep_recordings : true # false = hapus file setelah ditranskrip
|
|
||||||
auto_submit : false # true = hasil transkrip langsung dikirim
|
|
||||||
# false = hanya mengisi form (Ctrl+Enter)
|
|
||||||
|
|
||||||
session: # Chat session
|
session:
|
||||||
db_path: "~/.config/hendrik/sessions.json"
|
db_path: "~/.config/hendrik/sessions.json"
|
||||||
|
|
||||||
ragroleplay: # Use nomic-embed-text
|
ragroleplay:
|
||||||
db_path : "~/.config/hendrik/ragroleplay"
|
db_path : "~/.config/hendrik/ragroleplay"
|
||||||
vector_size : 768 # used on table create only
|
vector_size : 768 # used on table create only
|
||||||
|
|
||||||
@ -53,7 +50,7 @@ xmpp:
|
|||||||
# - "room2@conference.server"
|
# - "room2@conference.server"
|
||||||
nickname: "" # custom MUC nickname (empty = use username)
|
nickname: "" # custom MUC nickname (empty = use username)
|
||||||
selective_response: true # true = only response if mentioned/relevant
|
selective_response: true # true = only response if mentioned/relevant
|
||||||
debug: false # true = tampilkan log debug menyeluruh (semua stanza XML, lifecycle, dll)
|
debug: false # true = display debug log (stanza XML, lifecycle, etc)
|
||||||
mute_session_end: false # true = tidak kirim pesan saat sesi berakhir (timeout)
|
mute_session_end: false # true = tidak kirim pesan saat sesi berakhir (timeout)
|
||||||
|
|
||||||
telegram:
|
telegram:
|
||||||
|
|||||||
@ -58,8 +58,8 @@ ASR_MAX_SECONDS = int(_yaml_get("asr", "max_seconds", default=60))
|
|||||||
ASR_TIMEOUT = int(_yaml_get("asr", "transcribe_timeout", default=60))
|
ASR_TIMEOUT = int(_yaml_get("asr", "transcribe_timeout", default=60))
|
||||||
ASR_KEEP_RECORDINGS = _as_bool(_yaml_get("asr", "keep_recordings", default=True), default=True)
|
ASR_KEEP_RECORDINGS = _as_bool(_yaml_get("asr", "keep_recordings", default=True), default=True)
|
||||||
|
|
||||||
# Tombol push-to-talk: "f1".."f12" atau "ctrl-<huruf>". Default F9.
|
# Tombol push-to-talk dipatok tetap ke F9 (tidak bisa dikonfigurasi).
|
||||||
ASR_RECORD_KEY = str(_yaml_get("asr", "record_key", default="f9")).strip().lower()
|
# Lihat interfaces/tui/actions.py -> ACTIONS["push_to_talk"].
|
||||||
|
|
||||||
# true = hasil transkripsi langsung dikirim sebagai pesan,
|
# true = hasil transkripsi langsung dikirim sebagai pesan,
|
||||||
# false = hasil hanya disisipkan ke form input (user kirim sendiri via Ctrl+Enter).
|
# false = hasil hanya disisipkan ke form input (user kirim sendiri via Ctrl+Enter).
|
||||||
|
|||||||
2
hendrik
2
hendrik
@ -1,5 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# wrapper to run the TUI agent from anywhere
|
# wrapper to run the hendrik agent from anywhere
|
||||||
|
|
||||||
# Set HENDRIK_DIR env var to override, or update the default below
|
# Set HENDRIK_DIR env var to override, or update the default below
|
||||||
DEFAULT_DIR="/opt/hendrik"
|
DEFAULT_DIR="/opt/hendrik"
|
||||||
|
|||||||
22
hendrik.py
22
hendrik.py
@ -14,20 +14,20 @@ from interfaces.tui import HendrikTUI
|
|||||||
|
|
||||||
tools_definition = [
|
tools_definition = [
|
||||||
# Coder Tools
|
# Coder Tools
|
||||||
gadget.tools_mapping( schema = coder.schema_read_file, handler = coder.read_file ),
|
gadget.tools_mapping( schema = coder.schema_read_file, handler = coder.read_file ),
|
||||||
gadget.tools_mapping( schema = coder.schema_write_file, handler = coder.write_file ),
|
gadget.tools_mapping( schema = coder.schema_write_file, handler = coder.write_file ),
|
||||||
gadget.tools_mapping( schema = coder.schema_edit_file, handler = coder.edit_file ),
|
gadget.tools_mapping( schema = coder.schema_edit_file, handler = coder.edit_file ),
|
||||||
gadget.tools_mapping( schema = coder.schema_run_bash, handler = coder.run_bash ),
|
gadget.tools_mapping( schema = coder.schema_run_bash, handler = coder.run_bash ),
|
||||||
gadget.tools_mapping( schema = coder.schema_search_code, handler = coder.search_code ),
|
gadget.tools_mapping( schema = coder.schema_search_code, handler = coder.search_code ),
|
||||||
gadget.tools_mapping( schema = coder.schema_git_operation, handler = coder.git_operation ),
|
gadget.tools_mapping( schema = coder.schema_git_operation, handler = coder.git_operation ),
|
||||||
gadget.tools_mapping( schema = coder.schema_search_grep, handler = coder.search_grep ),
|
gadget.tools_mapping( schema = coder.schema_search_grep, handler = coder.search_grep ),
|
||||||
gadget.tools_mapping( schema = coder.schema_search_glob, handler = coder.search_glob ),
|
gadget.tools_mapping( schema = coder.schema_search_glob, handler = coder.search_glob ),
|
||||||
# Carrack Tools
|
# Carrack Tools
|
||||||
gadget.tools_mapping( schema = carrack.schema_sendhttprequest, handler = carrack.sendhttprequest ),
|
gadget.tools_mapping( schema = carrack.schema_sendhttprequest, handler = carrack.sendhttprequest ),
|
||||||
# Vision Tools
|
# Vision Tools
|
||||||
gadget.tools_mapping( schema = vision.schema_describe_image, handler = vision.describe_image ),
|
gadget.tools_mapping( schema = vision.schema_describe_image, handler = vision.describe_image ),
|
||||||
# Image Generation Tools
|
# Image Generation Tools
|
||||||
gadget.tools_mapping( schema = imagegen.schema_generate_image, handler = imagegen.generate_image ),
|
gadget.tools_mapping( schema = imagegen.schema_generate_image, handler = imagegen.generate_image ),
|
||||||
# Instruction Tools
|
# Instruction Tools
|
||||||
gadget.tools_mapping( schema = smart.schema_instruction_use, handler = smart.instruction_use ), # snippet (global)
|
gadget.tools_mapping( schema = smart.schema_instruction_use, handler = smart.instruction_use ), # snippet (global)
|
||||||
gadget.tools_mapping( schema = smart.schema_instruction_char_use, handler = smart.instruction_char_use ), # snippet (private per character)
|
gadget.tools_mapping( schema = smart.schema_instruction_char_use, handler = smart.instruction_char_use ), # snippet (private per character)
|
||||||
|
|||||||
@ -16,6 +16,7 @@ from .keycodes import (
|
|||||||
KEY_F2,
|
KEY_F2,
|
||||||
KEY_F4,
|
KEY_F4,
|
||||||
KEY_F6,
|
KEY_F6,
|
||||||
|
KEY_F9,
|
||||||
)
|
)
|
||||||
from .input import (
|
from .input import (
|
||||||
new_session_popup,
|
new_session_popup,
|
||||||
@ -29,11 +30,8 @@ from .moopui import (
|
|||||||
providers_manage_popup,
|
providers_manage_popup,
|
||||||
)
|
)
|
||||||
from .agent import submit, log
|
from .agent import submit, log
|
||||||
from .keycodes import resolve_key
|
|
||||||
from . import talk as talk_mod
|
from . import talk as talk_mod
|
||||||
|
|
||||||
import config as _config
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------- handlers ---
|
# ---------------------------------------------------------------- handlers ---
|
||||||
def _exit_app(app, stdscr):
|
def _exit_app(app, stdscr):
|
||||||
@ -55,8 +53,8 @@ def _record_talk(app, stdscr):
|
|||||||
|
|
||||||
|
|
||||||
def _talk_configured(app):
|
def _talk_configured(app):
|
||||||
# Tombol rekam valid (di-resolve dari config). Ketersediaan chain 'asr'
|
# Tombol rekam dipatok tetap (F9) sehingga selalu valid. Ketersediaan
|
||||||
# divalidasi di handler supaya bisa memberi pesan panduan, bukan diam.
|
# chain 'asr' divalidasi di handler supaya bisa memberi pesan panduan.
|
||||||
return getattr(app, "talk_key", None) is not None
|
return getattr(app, "talk_key", None) is not None
|
||||||
|
|
||||||
|
|
||||||
@ -118,12 +116,12 @@ ACTIONS = {
|
|||||||
"label": "Change Workspace", "mnemonic": "C", "shortcut": "F6",
|
"label": "Change Workspace", "mnemonic": "C", "shortcut": "F6",
|
||||||
"handler": workspace_popup, "enabled": _ready,
|
"handler": workspace_popup, "enabled": _ready,
|
||||||
},
|
},
|
||||||
# Push-to-Talk (ASR): tombol berasal dari config.asr.record_key (default F9).
|
# Push-to-Talk (ASR): tombol dipatok tetap F9 (tidak dikonfigurasi).
|
||||||
# Handler talk_toggle memvalidasi chain moop 'asr' + ketersediaan mic.
|
# Handler talk_toggle memvalidasi chain moop 'asr' + ketersediaan mic.
|
||||||
"push_to_talk": {
|
"push_to_talk": {
|
||||||
"key": resolve_key(getattr(_config, "ASR_RECORD_KEY", "f9")),
|
"key": KEY_F9,
|
||||||
"label": "Push-to-Talk", "mnemonic": "T",
|
"label": "Push-to-Talk", "mnemonic": "T",
|
||||||
"shortcut": (getattr(_config, "ASR_RECORD_KEY", "f9") or "").upper(),
|
"shortcut": "F9",
|
||||||
"handler": _record_talk,
|
"handler": _record_talk,
|
||||||
"enabled": lambda app: _ready(app) and _talk_configured(app),
|
"enabled": lambda app: _ready(app) and _talk_configured(app),
|
||||||
},
|
},
|
||||||
|
|||||||
@ -60,7 +60,7 @@ class HendrikTUI:
|
|||||||
self.talk_done = threading.Event()
|
self.talk_done = threading.Event()
|
||||||
self._talk_thread: threading.Thread | None = None
|
self._talk_thread: threading.Thread | None = None
|
||||||
self._talk_result: dict | None = None
|
self._talk_result: dict | None = None
|
||||||
# Kode tombol rekam dari config (None = tombol tidak valid/fitur mati)
|
# Kode tombol rekam: dipatok tetap F9 (lihat ACTIONS["push_to_talk"])
|
||||||
from .actions import ACTIONS as _ACTIONS
|
from .actions import ACTIONS as _ACTIONS
|
||||||
self.talk_key = _ACTIONS["push_to_talk"]["key"]
|
self.talk_key = _ACTIONS["push_to_talk"]["key"]
|
||||||
self.talk_label = _ACTIONS["push_to_talk"]["shortcut"]
|
self.talk_label = _ACTIONS["push_to_talk"]["shortcut"]
|
||||||
|
|||||||
@ -263,30 +263,6 @@ def read_key(stdscr, timeout_ms: int = -1) -> int:
|
|||||||
return KEY_ESC
|
return KEY_ESC
|
||||||
|
|
||||||
|
|
||||||
def resolve_key(name) -> int | None:
|
|
||||||
"""Petakan nama tombol dari config menjadi kode kunci.
|
|
||||||
|
|
||||||
Format: "f1".."f12", "ctrl-<huruf>", atau "esc"/"enter".
|
|
||||||
Mengembalikan None jika tidak dikenal."""
|
|
||||||
n = str(name or "").strip().lower().replace("+", "-").replace(" ", "")
|
|
||||||
if not n:
|
|
||||||
return None
|
|
||||||
_F_KEYS = {f"f{i}": k for i, k in enumerate(
|
|
||||||
[KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6,
|
|
||||||
KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12], start=1)}
|
|
||||||
if n in _F_KEYS:
|
|
||||||
return _F_KEYS[n]
|
|
||||||
if n == "esc":
|
|
||||||
return KEY_ESC
|
|
||||||
if n == "enter":
|
|
||||||
return 13
|
|
||||||
if n.startswith("ctrl-") and len(n) == 6:
|
|
||||||
ch = n[-1]
|
|
||||||
if "a" <= ch <= "z":
|
|
||||||
return ord(ch) & 0x1F
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def is_alt_key(key: int) -> bool:
|
def is_alt_key(key: int) -> bool:
|
||||||
return _KEY_ALT_BASE <= key <= _KEY_ALT_BASE + 126
|
return _KEY_ALT_BASE <= key <= _KEY_ALT_BASE + 126
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# talk.py — Push-to-Talk (ASR/STT) untuk TUI.
|
# talk.py — Push-to-Talk (ASR/STT) untuk TUI.
|
||||||
#
|
#
|
||||||
# Alur:
|
# Alur:
|
||||||
# * F9 (configurable) → mulai rekam (ffmpeg subprocess, non-blocking).
|
# * F9 (dipatok, tidak configurable) → mulai rekam (ffmpeg subprocess, non-blocking).
|
||||||
# * F9 lagi / Enter → stop rekam → transkrip (thread) → hasil
|
# * F9 lagi / Enter → stop rekam → transkrip (thread) → hasil
|
||||||
# disisipkan ke form input pada posisi kursor,
|
# disisipkan ke form input pada posisi kursor,
|
||||||
# TIDAK submit (default).
|
# TIDAK submit (default).
|
||||||
@ -25,12 +25,13 @@ from tools import asr as asr_mod
|
|||||||
from .agent import log, submit
|
from .agent import log, submit
|
||||||
|
|
||||||
|
|
||||||
|
# Tombol push-to-talk dipatok tetap ke F9 (lihat actions.py & keycodes.py).
|
||||||
|
TALK_SHORTCUT_LABEL = "F9"
|
||||||
|
|
||||||
|
|
||||||
def _shortcut_label():
|
def _shortcut_label():
|
||||||
"""Label tombol rekam untuk pesan UI (dari config.asr.record_key)."""
|
"""Label tombol rekam untuk pesan UI (selalu 'F9')."""
|
||||||
n = (config.ASR_RECORD_KEY or "f9").strip().lower()
|
return TALK_SHORTCUT_LABEL
|
||||||
if n.startswith("ctrl-") and len(n) == 6:
|
|
||||||
return f"Ctrl+{n[5].upper()}"
|
|
||||||
return n.upper()
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------ helpers ---
|
# ------------------------------------------------------------------ helpers ---
|
||||||
|
|||||||
@ -13,7 +13,6 @@ tekan tombol → bicara → stop → teks hasil transkripsi masuk ke form input
|
|||||||
## Konfigurasi (config.yaml, blok `asr:`)
|
## Konfigurasi (config.yaml, blok `asr:`)
|
||||||
asr:
|
asr:
|
||||||
record_dir : "~/.config/hendrik/recordings" # lokasi file rekaman
|
record_dir : "~/.config/hendrik/recordings" # lokasi file rekaman
|
||||||
record_key : f9 # f1..f12 / ctrl-<huruf>
|
|
||||||
record_backend : pulse # pulse | alsa | oss | windows (dshow)
|
record_backend : pulse # pulse | alsa | oss | windows (dshow)
|
||||||
device : default
|
device : default
|
||||||
windows_mic : "" # backend=windows: nama device dshow
|
windows_mic : "" # backend=windows: nama device dshow
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 19 KiB |
@ -28,12 +28,10 @@ mindmapDiagram {
|
|||||||
;top to bottom direction
|
;top to bottom direction
|
||||||
|
|
||||||
* root <<done>>
|
* root <<done>>
|
||||||
** .env <<done>>
|
|
||||||
** .env.example <<done>>
|
|
||||||
** .gitignore <<done>>
|
** .gitignore <<done>>
|
||||||
|
** LICENSE <<done>>
|
||||||
|
** config.default.yaml <<done>>
|
||||||
** config.py
|
** config.py
|
||||||
** config.yaml <<done>>
|
|
||||||
** config.default.yaml
|
|
||||||
** hendrik <<done>>
|
** hendrik <<done>>
|
||||||
** hendrik.py <<done>>
|
** hendrik.py <<done>>
|
||||||
** requirements.txt <<done>>
|
** requirements.txt <<done>>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user