;;; init-gptel.el --- ai -*- lexical-binding: t -*- ;;; Commentary: ;;; Code: (use-package gptel :config (setq gptel-default-mode 'org-mode) (defun my/org-auto-gptel () (when (derived-mode-p 'org-mode) (save-excursion (goto-char (point-min)) (when (re-search-forward "^#\\+GPTEL_MODEL:" nil t) (gptel-mode))))) (add-hook 'org-mode-hook #'my/org-auto-gptel) (add-hook 'gptel-post-response-functions 'gptel-end-of-response) (add-hook 'gptel-post-stream-hook 'gptel-auto-scroll) (setq gptel-prompt-prefix-alist '((markdown-mode . "### ") (org-mode . "** User: ") (text-mode . "### "))) ;; 读取文件 (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 '((:name "filepath" :type string :description "Path to the file")) :category "filesystem") ;; 创建文件 (gptel-make-tool :name "create_file" ; javascript-style snake_case name :function (lambda (path filename content) ; the function that runs (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))) :description "Create a new file with the specified content" :args (list '(:name "path" ; a list of argument specifications :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") ; An arbitrary label for grouping (gptel-make-tool :name "read_buffer" ; javascript-style snake_case name :function (lambda (buffer) ; the function that will run (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)))) :description "return the contents of an emacs buffer" :args (list '(:name "buffer" :type string ; :type value must be a symbol :description "the name of the buffer whose contents are to be retrieved")) :category "emacs") ; An arbitrary label for grouping (gptel-make-openai "Kimi-Code" :host "api.kimi.com" :endpoint "/coding/v1/chat/completions" :protocol "https" :key (lambda () (auth-source-pick-first-password :host "api.kimi.com" :user "apikey")) :stream t :models '(kimi-for-coding) :header (lambda (_) (when-let ((key (gptel--get-api-key))) `(("User-Agent" . "RooCode/3.30.3") ("HTTP-Referer" . "https://github.com/RooVetGit/Roo-Cline") ("X-Title" . "Roo Code") ("Authorization" . ,(concat "Bearer " key)))))) (with-eval-after-load 'gptel (setf gptel--system-message "You are a large language model living in Emacs and a helpful assistant. Respond concisely. - NEVER use unescaped org-mode headings. Lines MUST NOT begin with `* `, `** `, `*** `, etc. If you must start a line with asterisks, use the standard org escape format `,*` (e.g. `,* Heading`, `,** Sub-heading`)."))) (use-package gptel-agent :config (add-to-list 'gptel-agent-dirs "~/.emacs.d/lisp/" t) (gptel-agent-update)) (provide 'init-gptel) ;;; init-gptel.el ends here