This commit is contained in:
Martin Sukany
2026-02-07 23:30:27 +01:00
parent 52d90e72d8
commit 3423b08606

159
config.el
View File

@@ -3,7 +3,7 @@
;; -------------------------------------------------- ;; --------------------------------------------------
;; Theme / UI ;; Theme / UI
;; -------------------------------------------------- ;; --------------------------------------------------
(setq doom-theme 'tango-dark (setq doom-theme 'doom-moonlight
display-line-numbers-type t display-line-numbers-type t
doom-font (font-spec :family "JetBrains Mono" :size 14) doom-font (font-spec :family "JetBrains Mono" :size 14)
doom-variable-pitch-font nil) 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") (setq org-babel-python-command "python3")
(require 'ob-python)) (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) (after! gptel
doom-variable-pitch-font (font-spec :family "SF Pro Text" :size 20)) (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) ;; performance
(setq which-key-idle-delay 0)
(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))