From c0a3ae4a24994115caa2430cf31568ff6bea4c65 Mon Sep 17 00:00:00 2001 From: Peter Tillemans Date: Wed, 13 Aug 2025 12:10:40 +0200 Subject: [PATCH] add gregory grubbs ai stuff --- init.org | 478 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 249 insertions(+), 229 deletions(-) diff --git a/init.org b/init.org index 43a4ccf..34350d9 100644 --- a/init.org +++ b/init.org @@ -1,3 +1,4 @@ + #+TITLE: My Emacs Configuration #+PROPERTY: header-args :tangle yes #+PROPERTY: header-args:emacs-lisp :lexical yes :tangle yes :comments nil :padline yes @@ -1573,85 +1574,88 @@ importing and exporting confluence pages. ** Mu4e Configuration #+BEGIN_SRC emacs-lisp - (setq snm/mu4e-load-path (concat - (file-name-parent-directory - (file-name-directory - (executable-find "mu"))) - "share/emacs/site-lisp/mu4e")) + (defvar snm/mu4e-load-path nil) + (if (executable-find "mu") + (let ((snm/mu4e-load-path (concat + (file-name-parent-directory + (file-name-directory + (executable-find "mu"))) + "share/emacs/site-lisp/mu4e"))) - (use-package mu4e - :load-path snm/mu4e-load-path + (use-package mu4e + :load-path snm/mu4e-load-path ;"/usr/share/emacs/site-lisp/mu4e" - :config + :config - ;; use mu4e for e-mail in emacs - (setq mail-user-agent 'mu4e-user-agent) + ;; use mu4e for e-mail in emacs + (setq mail-user-agent 'mu4e-user-agent) - (setq mu4e-drafts-folder "/[Gmail].Drafts") - (setq mu4e-sent-folder "/[Gmail].Sent Mail") - (setq mu4e-trash-folder "/[Gmail].Trash") + (setq mu4e-drafts-folder "/[Gmail].Drafts") + (setq mu4e-sent-folder "/[Gmail].Sent Mail") + (setq mu4e-trash-folder "/[Gmail].Trash") - ;; don't save message to Sent Messages, Gmail/IMAP takes care of this - (setq mu4e-sent-messages-behavior 'delete) + ;; don't save message to Sent Messages, Gmail/IMAP takes care of this + (setq mu4e-sent-messages-behavior 'delete) - ;; (See the documentation for `mu4e-sent-messages-behavior' if you have - ;; additional non-Gmail addresses and want assign them different - ;; behavior.) + ;; (See the documentation for `mu4e-sent-messages-behavior' if you have + ;; additional non-Gmail addresses and want assign them different + ;; behavior.) - ;; setup some handy shortcuts - ;; you can quickly switch to your Inbox -- press ``ji'' - ;; then, when you want archive some messages, move them to - ;; the 'All Mail' folder by pressing ``ma''. + ;; setup some handy shortcuts + ;; you can quickly switch to your Inbox -- press ``ji'' + ;; then, when you want archive some messages, move them to + ;; the 'All Mail' folder by pressing ``ma''. - (setq mu4e-maildir-shortcuts - '( (:maildir "/INBOX" :key ?i) - (:maildir "/[Gmail].Sent Mail" :key ?s) - (:maildir "/[Gmail].Trash" :key ?t) - (:maildir "/[Gmail].All Mail" :key ?a))) + (setq mu4e-maildir-shortcuts + '( (:maildir "/INBOX" :key ?i) + (:maildir "/[Gmail].Sent Mail" :key ?s) + (:maildir "/[Gmail].Trash" :key ?t) + (:maildir "/[Gmail].All Mail" :key ?a))) - (add-to-list 'mu4e-bookmarks - ;; ':favorite t' i.e, use this one for the modeline - '(:query "maildir:/inbox" :name "Inbox" :key ?i :favorite t)) + (add-to-list 'mu4e-bookmarks + ;; ':favorite t' i.e, use this one for the modeline + '(:query "maildir:/inbox" :name "Inbox" :key ?i :favorite t)) - ;; allow for updating mail using 'U' in the main view: - (setq mu4e-get-mail-command "offlineimap") + ;; allow for updating mail using 'U' in the main view: + (setq mu4e-get-mail-command "offlineimap") - ;; something about ourselves - (setq - user-mail-address "pti@snamellit.com" - user-full-name "Peter Tillemans" - message-signature - (concat - "Peter Tillemans\n" - "Snamellit BV\n" - "http://www.smamellit.com\n")) + ;; something about ourselves + (setq + user-mail-address "pti@snamellit.com" + user-full-name "Peter Tillemans" + message-signature + (concat + "Peter Tillemans\n" + "Snamellit BV\n" + "http://www.smamellit.com\n")) - ;; sending mail -- replace USERNAME with your gmail username - ;; also, make sure the gnutls command line utils are installed - ;; package 'gnutls-bin' in Debian/Ubuntu + ;; sending mail -- replace USERNAME with your gmail username + ;; also, make sure the gnutls command line utils are installed + ;; package 'gnutls-bin' in Debian/Ubuntu - (require 'smtpmail) - (setq - message-send-mail-function 'smtpmail-send-it - starttls-use-gnutls t - smtpmail-starttls-credentials '(("smtp.gmail.com" 587 nil nil)) - smtpmail-auth-credentials - '(("smtp.gmail.com" 587 "pti@snamellit.com" (auth-source-pass-get 'secret "snamellit/imap.gmail.com"))) - smtpmail-default-smtp-server "smtp.gmail.com" - smtpmail-smtp-server "smtp.gmail.com" - smtpmail-smtp-service 587) + (require 'smtpmail) + (setq + message-send-mail-function 'smtpmail-send-it + starttls-use-gnutls t + smtpmail-starttls-credentials '(("smtp.gmail.com" 587 nil nil)) + smtpmail-auth-credentials + '(("smtp.gmail.com" 587 "pti@snamellit.com" (auth-source-pass-get 'secret "snamellit/imap.gmail.com"))) + smtpmail-default-smtp-server "smtp.gmail.com" + smtpmail-smtp-server "smtp.gmail.com" + smtpmail-smtp-service 587) - ;; alternatively, for emacs-24 you can use: - ;;(setq message-send-mail-function 'smtpmail-send-it - ;; smtpmail-stream-type 'starttls - ;; smtpmail-default-smtp-server "smtp.gmail.com" - ;; smtpmail-smtp-server "smtp.gmail.com" - ;; smtpmail-smtp-service 587) + ;; alternatively, for emacs-24 you can use: + ;;(setq message-send-mail-function 'smtpmail-send-it + ;; smtpmail-stream-type 'starttls + ;; smtpmail-default-smtp-server "smtp.gmail.com" + ;; smtpmail-smtp-server "smtp.gmail.com" + ;; smtpmail-smtp-service 587) - ;; don't keep message buffers around - (setq message-kill-buffer-on-exit t) + ;; don't keep message buffers around + (setq message-kill-buffer-on-exit t) - ) + ) + )) #+END_SRC #+RESULTS: @@ -3111,32 +3115,194 @@ integration in Emacs. *** Load and Configure Model #+BEGIN_SRC emacs-lisp - (use-package gptel - :ensure t - :commands (gptel) - :config - (setq gptel-default-mode 'org-mode - gptel-expert-commands t - gptel-track-media t - gptel-include-reasoning 'ignore - gptel-log-level 'info - gptel--debug nil) + (use-package gptel + :ensure t + ;:commands (gptel) + :demand t + :config + (setq gptel-default-mode 'org-mode + gptel-expert-commands t + gptel-track-media t + gptel-include-reasoning 'ignore + gptel-log-level 'info + gptel--debug nil) - (add-to-list 'gptel-prompt-prefix-alist `(org-mode . ,(concat "*** pti " (format-time-string "[%Y-%m-%d]") "\n"))) - - ;; follow output - (add-hook 'gptel-post-stream-hook 'gptel-auto-scroll) - ;; move to next prompt after response - (add-hook 'gptel-post-response-functions 'gptel-end-of-response) - ) + (add-to-list 'gptel-prompt-prefix-alist `(org-mode . ,(concat "*** pti " (format-time-string "[%Y-%m-%d]") "\n"))) + + ;; follow output + (add-hook 'gptel-post-stream-hook 'gptel-auto-scroll) + ;; move to next prompt after response + (add-hook 'gptel-post-response-functions 'gptel-end-of-response) - (use-package gptel-curl) - (use-package gptel-transient) - (use-package gptel-integrations) + (require 'gptel-curl) + (require 'gptel-transient) + (require 'gptel-integrations) + (setq gptel-api-key openai-api-key) + (gptel-make-gemini "Gemini" :key gemini-api-key :stream t) + (gptel-make-anthropic "Claude" :stream t :key anthropic-api-key) + (gptel-make-ollama "Qwen Coder" + :models '(qwen2.5-coder:14b + :description "QWen 2.5 Coder 14b")) + + + (gptel-make-tool + :function (lambda (url) + (with-current-buffer (url-retrieve-synchronously url) + (goto-char (point-min)) (forward-paragraph) + (let ((dom (libxml-parse-html-region (point) (point-max)))) + (run-at-time 0 nil #'kill-buffer (current-buffer)) + (with-temp-buffer + (shr-insert-document dom) + (buffer-substring-no-properties (point-min) (point-max)))))) + :name "read_url" + :description "Fetch and read the contents of a URL" + :args (list '(:name "url" + :type "string" + :description "The URL to read")) + :category "web") + + (gptel-make-tool + :function (lambda (buffer text) + (with-current-buffer (get-buffer-create buffer) + (save-excursion + (goto-char (point-max)) + (insert text))) + (format "Appended text to buffer %s" buffer)) + :name "append_to_buffer" + :description "Append text to the an Emacs buffer. If the buffer does not exist, it will be created." + :args (list '(:name "buffer" + :type "string" + :description "The name of the buffer to append text to.") + '(:name "text" + :type "string" + :description "The text to append to the buffer.")) + :category "emacs") + + ;; Message buffer logging tool + + (gptel-make-tool + :function (lambda (text) + (message "%s" text) + (format "Message sent: %s" text)) + :name "echo_message" + :description "Send a message to the *Messages* buffer" + :args (list '(:name "text" + :type "string" + :description "The text to send to the messages buffer")) + :category "emacs") + + ;; buffer retrieval tool + + (gptel-make-tool + :function (lambda (buffer) + (unless (buffer-live-p (get-buffer buffer)) + (error "Error: buffer %s is not live." buffer)) + (with-current-buffer buffer + (buffer-substring-no-properties (point-min) (point-max)))) + :name "read_buffer" + :description "Return the contents of an Emacs buffer" + :args (list '(:name "buffer" + :type "string" + :description "The name of the buffer whose contents are to be retrieved")) + :category "emacs") + + + (gptel-make-tool + :function (lambda (directory) + (mapconcat #'identity + (directory-files directory) + "\n")) + :name "list_directory" + :description "List the contents of a given directory" + :args (list '(:name "directory" + :type "string" + :description "The path to the directory to list")) + :category "filesystem") + + (gptel-make-tool + :function (lambda (parent name) + (condition-case nil + (progn + (make-directory (expand-file-name name parent) t) + (format "Directory %s created/verified in %s" name parent)) + (error (format "Error creating directory %s in %s" name parent)))) + :name "make_directory" + :description "Create a new directory with the given name in the specified parent directory" + :args (list '(:name "parent" + :type "string" + :description "The parent directory where the new directory should be created, e.g. /tmp") + '(:name "name" + :type "string" + :description "The name of the new directory to create, e.g. testdir")) + :category "filesystem") + + (gptel-make-tool + :function (lambda (path filename content) + (let ((full-path (expand-file-name filename path))) + (with-temp-buffer + (insert content) + (write-file full-path)) + (format "Created file %s in %s" filename path))) + :name "create_file" + :description "Create a new file with the specified content" + :args (list '(:name "path" + :type "string" + :description "The directory where to create the file") + '(:name "filename" + :type "string" + :description "The name of the file to create") + '(:name "content" + :type "string" + :description "The content to write to the file")) + :category "filesystem") + + (gptel-make-tool + :function (lambda (filepath) + (with-temp-buffer + (insert-file-contents (expand-file-name filepath)) + (buffer-string))) + :name "read_file" + :description "Read and display the contents of a file" + :args (list '(:name "filepath" + :type "string" + :description "Path to the file to read. Supports relative paths and ~.")) + :category "filesystem") + + + + ) #+END_SRC #+RESULTS: +*** TODO Load MCP.el + +placeholder + +check [[https://www.youtube.com/watch?v=Hkih7jaqOnE&t=544s][Agentic LLM use in Emacs using Model Context Protocol (MCP)]] of +Gregg Grubbs for examples what to put here. + +#+BEGIN_SRC emacs-lisp :tangle no + (use-package mcp + :ensure t + :after gptel + :custom (mcp-hub-servers + `(("filesystem" . (:command "npx" :args ("-y" "@modelcontextprotocol/server-filesystem" "/home/lizqwer/MyProject/"))) + ("fetch" . (:command "uvx" :args ("mcp-server-fetch"))) + ("qdrant" . (:url "http://localhost:8000/sse")) + ("graphlit" . ( + :command "npx" + :args ("-y" "graphlit-mcp-server") + :env ( + :GRAPHLIT_ORGANIZATION_ID "your-organization-id" + :GRAPHLIT_ENVIRONMENT_ID "your-environment-id" + :GRAPHLIT_JWT_SECRET "your-jwt-secret"))))) + :config (require 'mcp-hub) + :hook (after-init . mcp-hub-start-all-server)) + +#+END_SRC + + *** Load jwiegley/gptel-prompts for prompt composability This package offers an alternative way to manage your ~gptel-directives~ variable, using files rather than customizing the variable directly. @@ -3206,152 +3372,6 @@ file itself to use what is easiest to maintain in the editor. NOTE: If you wish to use the Prompt Poet format, you will need to install the Emacs dependencies yaml and templatel. -*** Models - -#+BEGIN_SRC emacs-lisp - (setq gptel-api-key openai-api-key) - (gptel-make-gemini "Gemini" :key gemini-api-key :stream t) - (gptel-make-anthropic "Claude" :stream t :key anthropic-api-key) - (gptel-make-ollama "Qwen Coder" - :models '(qwen2.5-coder:14b - :description "QWen 2.5 Coder 14b")) - - -#+END_SRC - -#+RESULTS: -: #s(gptel-ollama "Qwen Coder" "localhost:11434" nil "http" nil "/api/chat" nil (qwen2.5-coder:14b :description QWen\ 2.5\ Coder\ 14b) "http://localhost:11434/api/chat" nil nil nil) - - -*** Tools - -#+BEGIN_SRC emacs-lisp - ;; define some tools for gptel - (gptel-make-tool - :function (lambda (url) - (with-current-buffer (url-retrieve-synchronously url) - (goto-char (point-min)) (forward-paragraph) - (let ((dom (libxml-parse-html-region (point) (point-max)))) - (run-at-time 0 nil #'kill-buffer (current-buffer)) - (with-temp-buffer - (shr-insert-document dom) - (buffer-substring-no-properties (point-min) (point-max)))))) - :name "read_url" - :description "Fetch and read the contents of a URL" - :args (list '(:name "url" - :type "string" - :description "The URL to read")) - :category "web") - - (gptel-make-tool - :function (lambda (buffer text) - (with-current-buffer (get-buffer-create buffer) - (save-excursion - (goto-char (point-max)) - (insert text))) - (format "Appended text to buffer %s" buffer)) - :name "append_to_buffer" - :description "Append text to the an Emacs buffer. If the buffer does not exist, it will be created." - :args (list '(:name "buffer" - :type "string" - :description "The name of the buffer to append text to.") - '(:name "text" - :type "string" - :description "The text to append to the buffer.")) - :category "emacs") - - ;; Message buffer logging tool - (gptel-make-tool - :function (lambda (text) - (message "%s" text) - (format "Message sent: %s" text)) - :name "echo_message" - :description "Send a message to the *Messages* buffer" - :args (list '(:name "text" - :type "string" - :description "The text to send to the messages buffer")) - :category "emacs") - - ;; buffer retrieval tool - (gptel-make-tool - :function (lambda (buffer) - (unless (buffer-live-p (get-buffer buffer)) - (error "Error: buffer %s is not live." buffer)) - (with-current-buffer buffer - (buffer-substring-no-properties (point-min) (point-max)))) - :name "read_buffer" - :description "Return the contents of an Emacs buffer" - :args (list '(:name "buffer" - :type "string" - :description "The name of the buffer whose contents are to be retrieved")) - :category "emacs") - - - (gptel-make-tool - :function (lambda (directory) - (mapconcat #'identity - (directory-files directory) - "\n")) - :name "list_directory" - :description "List the contents of a given directory" - :args (list '(:name "directory" - :type "string" - :description "The path to the directory to list")) - :category "filesystem") - - (gptel-make-tool - :function (lambda (parent name) - (condition-case nil - (progn - (make-directory (expand-file-name name parent) t) - (format "Directory %s created/verified in %s" name parent)) - (error (format "Error creating directory %s in %s" name parent)))) - :name "make_directory" - :description "Create a new directory with the given name in the specified parent directory" - :args (list '(:name "parent" - :type "string" - :description "The parent directory where the new directory should be created, e.g. /tmp") - '(:name "name" - :type "string" - :description "The name of the new directory to create, e.g. testdir")) - :category "filesystem") - - (gptel-make-tool - :function (lambda (path filename content) - (let ((full-path (expand-file-name filename path))) - (with-temp-buffer - (insert content) - (write-file full-path)) - (format "Created file %s in %s" filename path))) - :name "create_file" - :description "Create a new file with the specified content" - :args (list '(:name "path" - :type "string" - :description "The directory where to create the file") - '(:name "filename" - :type "string" - :description "The name of the file to create") - '(:name "content" - :type "string" - :description "The content to write to the file")) - :category "filesystem") - - (gptel-make-tool - :function (lambda (filepath) - (with-temp-buffer - (insert-file-contents (expand-file-name filepath)) - (buffer-string))) - :name "read_file" - :description "Read and display the contents of a file" - :args (list '(:name "filepath" - :type "string" - :description "Path to the file to read. Supports relative paths and ~.")) - :category "filesystem") - - -#+END_SRC - - ** Copilot Support #+BEGIN_SRC emacs-lisp