From 3423b086066d56e17540848ebb5c6f003cc6270c Mon Sep 17 00:00:00 2001 From: Martin Sukany Date: Sat, 7 Feb 2026 23:30:27 +0100 Subject: [PATCH] update --- config.el | 159 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 132 insertions(+), 27 deletions(-) diff --git a/config.el b/config.el index 3a98165..ca7eeb6 100644 --- a/config.el +++ b/config.el @@ -3,7 +3,7 @@ ;; -------------------------------------------------- ;; Theme / UI ;; -------------------------------------------------- -(setq doom-theme 'tango-dark +(setq doom-theme 'doom-moonlight display-line-numbers-type t doom-font (font-spec :family "JetBrains Mono" :size 14) doom-variable-pitch-font nil) @@ -190,33 +190,138 @@ Funguje v libovolném textu, včetně Markdown linků (např. [x](./...))." (setq org-babel-python-command "python3") (require 'ob-python)) + + +;;; GPTel + OpenWebUI (OpenRouter behind it) + +(use-package! gptel + :config + ;; 1) API key z env (bez klíčů v configu) + (defun my/openwebui-key () + (or (getenv "OPENWEBUI_API_KEY") + (user-error "Missing OPENWEBUI_API_KEY env var"))) + + ;; 2) Stáhnout seznam modelů z OpenWebUI /api/models + (defun my/openwebui-fetch-model-ids () + "Return list of model ids from OpenWebUI /api/models (field data[].id)." + (require 'url) + (require 'json) + (let* ((url-request-method "GET") + (url-request-extra-headers + `(("Authorization" . ,(concat "Bearer " (funcall #'my/openwebui-key)))))) + (with-current-buffer (url-retrieve-synchronously + "https://ai.apps.sukany.cz/api/models" t t 15) + (goto-char (point-min)) + (re-search-forward "\n\n" nil 'move) ;; přeskočit HTTP hlavičky + (let* ((json-object-type 'alist) + (json-array-type 'list) + (json-key-type 'symbol) + (obj (json-read)) + (data (alist-get 'data obj)) + (ids (delq nil (mapcar (lambda (it) (alist-get 'id it)) data)))) + (kill-buffer (current-buffer)) + ids)))) + + (defvar my/openwebui-models-cache nil) + + (defun my/openwebui-models () + "Cached list of model ids. Falls back to a minimal list if API fails." + (or my/openwebui-models-cache + (setq my/openwebui-models-cache + (condition-case err + (my/openwebui-fetch-model-ids) + (error + (message "OpenWebUI models fetch failed: %s" err) + ;; fallback – zkus běžné OpenRouter ids (může, ale nemusí být dostupné) + '("openai/gpt-4o-mini" "openai/gpt-4.1-mini")))))) + + (defun my/openwebui-refresh-models () + "Clear cache and refetch OpenWebUI model list." + (interactive) + (setq my/openwebui-models-cache nil) + (message "OpenWebUI models refreshed: %d" (length (my/openwebui-models)))) + + ;; 3) Backend pro OpenWebUI (OpenAI-compatible chat/completions) + (setq gptel-backend + (gptel-make-openai "OpenWebUI" + :host "ai.apps.sukany.cz" + :protocol "https" + :key #'my/openwebui-key + :endpoint "/api/chat/completions" + :stream t + ;; často stabilnější přes reverzní proxy/ingress: + :curl-args '("--http1.1") + :models (my/openwebui-models))) + + ;; 4) Default model: ekonomický a praktický + ;; Preferuj openai/gpt-4o-mini (levný, rychlý), jinak první dostupný model. + ;; (GPT-4o mini je běžně uváděn jako “fast, affordable” a na OpenRouter má id openai/gpt-4o-mini) :contentReference[oaicite:2]{index=2} + (let* ((models (my/openwebui-models)) + (preferred "openai/gpt-4o-mini")) + (setq gptel-model (if (member preferred models) + preferred + (car models)))) + + ;; 5) Presety (rychlé přepínání podle úlohy) :contentReference[oaicite:3]{index=3} + ;; Pozn.: Presety jen nastavují model/backend/system atd. – žádná magie navíc. + (gptel-make-preset 'fast + :description "Default (rychlý/levný) – běžná práce" + :backend "OpenWebUI" + :model "openai/gpt-4o-mini" + :system "Odpovídej česky. Buď konkrétní, krokový. Neomáčej to." + :temperature 0.2) + + (gptel-make-preset 'coding + :description "Kód / refaktor / review (silnější model, když je potřeba)" + :backend "OpenWebUI" + ;; nastav si sem model, který opravdu máš v /api/models: + :model "openai/gpt-4.1-mini" + :system "Jsi přísný code reviewer. Navrhuj konkrétní změny a rizika." + :temperature 0.1) + + (gptel-make-preset 'deep + :description "Náročná analýza / architektura" + :backend "OpenWebUI" + ;; nastav si sem něco silnějšího z tvého seznamu: + :model "openai/gpt-4.1" + :system "Postupuj systematicky. Dej varianty, tradeoffs a doporučení." + :temperature 0.2) + + ;; 6) (Volitelné) Debug log, když něco zlobí: + ;; (setq gptel-log-level 'debug) + ) + +;; 7) Mini CLI: volání z command line přes `emacs --batch` +;; Použití níže v příkladech +(defun my/gptel-cli (prompt &optional model system) + "Send PROMPT via gptel and print response to stdout." + (require 'gptel) + (let* ((done nil) + (result nil) + (gptel-model (or model gptel-model)) + (gptel--system-message (or system gptel--system-message))) + (gptel-request prompt + :callback (lambda (response _info) + (setq result response) + (setq done t))) + (while (not done) + (accept-process-output nil 0.05)) + (princ result))) + + + ;; -------------------------------------------------- -;; Low-vision základ +;; GPTel keybindings (safe in Doom) SPC o g ... ;; -------------------------------------------------- -(setq doom-font (font-spec :family "JetBrains Mono" :size 20) - doom-variable-pitch-font (font-spec :family "SF Pro Text" :size 20)) +(after! gptel + (map! :leader + (:prefix ("o g" . "GPTel") + :desc "GPTel send (region or buffer)" "s" #'gptel-send + :desc "GPTel menu (model/scope/preset)" "m" #'gptel-menu + :desc "GPTel chat buffer" "c" #'gptel + :desc "GPTel abort request" "x" #'gptel-abort + :desc "Refresh OpenWebUI models" "R" #'my/openwebui-refresh-models))) -(setq-default line-spacing 0.25) - -(map! :n "C-=" #'text-scale-increase - :n "C--" #'text-scale-decrease - :n "C-0" #'text-scale-set - :i "C-=" #'text-scale-increase - :i "C--" #'text-scale-decrease - :i "C-0" #'text-scale-set) - -(add-hook 'org-after-refile-insert-hook #'save-buffer) -(add-hook 'org-after-todo-state-change-hook #'save-buffer) -(add-hook 'org-capture-after-finalize-hook #'save-buffer) - -(run-with-idle-timer - 300 t - (lambda () - (save-some-buffers t (lambda () - (derived-mode-p 'org-mode))))) - -;; performance tweak -(after! projectile - (setq projectile-indexing-method 'alien - projectile-enable-caching t)) +;; performance +(setq which-key-idle-delay 0)