diff options
Diffstat (limited to 'gptel-tools/read_text_file.el')
| -rw-r--r-- | gptel-tools/read_text_file.el | 146 |
1 files changed, 0 insertions, 146 deletions
diff --git a/gptel-tools/read_text_file.el b/gptel-tools/read_text_file.el deleted file mode 100644 index f35c94941..000000000 --- a/gptel-tools/read_text_file.el +++ /dev/null @@ -1,146 +0,0 @@ -;;; read_text_file.el --- Read text files for GPTel -*- coding: utf-8; lexical-binding: t; -*- - -;; Copyright (C) 2025 - -;; Author: gptel-tool-writer -;; Keywords: convenience, tools -;; Package-Requires: ((emacs "27.1") (gptel "0.9.0")) - -;; This file is not part of GNU Emacs. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;;; Commentary: - -;;; Code: - -;; Helper functions for read_text_file tool -(defun cj/validate-file-path (path) - "Validate PATH is within home directory and exists." - (let* ((home (file-name-as-directory (file-truename (expand-file-name "~")))) - (full-path (expand-file-name path "~"))) - (unless (string-prefix-p (expand-file-name "~") full-path) - (error "Path must be within home directory")) - (unless (file-exists-p full-path) - (error "File not found: %s" full-path)) - (let ((resolved (file-truename full-path))) - (unless (or (string= resolved (directory-file-name home)) - (string-prefix-p home resolved)) - (error "Resolved path must be within home directory: %s" path)) - (when (file-directory-p resolved) - (error "Path is a directory, not a file: %s" resolved)) - (unless (file-readable-p resolved) - (error "No read permission for file: %s" resolved)) - resolved))) - -(defun cj/get-file-metadata (path) - "Return formatted metadata string for file at PATH." - (let* ((attributes (file-attributes path)) - (size (file-attribute-size attributes)) - (modes (file-attribute-modes attributes)) - (modtime (format-time-string "%Y-%m-%d" - (file-attribute-modification-time attributes)))) - (list :size size - :string (format "File: %s (%s, %s, modified %s)" - path modes - (file-size-human-readable size) - modtime)))) - -(defun cj/check-file-size-limits (size no-confirm) - "Check file SIZE against limits, prompting user unless NO-CONFIRM." - (let ((size-warning-limit (* 10 1024 1024)) ; 10MB - (size-hard-limit (* 100 1024 1024))) ; 100MB - (when (> size size-hard-limit) - (error "File too large (%s): exceeds 100MB limit" - (file-size-human-readable size))) - (when (and (> size size-warning-limit) - (not no-confirm)) - (unless (y-or-n-p (format "File is large (%s). Continue? " - (file-size-human-readable size))) - (error "File read cancelled: size exceeds 10MB"))))) - -(defun cj/detect-binary-file (path) - "Check if file at PATH appears to be binary." - (with-temp-buffer - (insert-file-contents path nil 0 1024) - (goto-char (point-min)) - (search-forward "\0" nil t))) - -(defun cj/handle-special-file-types (path no-confirm) - "Handle PDF, EPUB, and other binary files at PATH." - (cond - ((string-match-p "\\.pdf\\'" path) - (when (and (not no-confirm) - (not (y-or-n-p "This is a PDF file. Extract text for LLM (y) or cancel (n)? "))) - (error "PDF file read cancelled")) - ;; Extract text from PDF - (let ((text (shell-command-to-string - (format "pdftotext '%s' -" path)))) - (if (string-empty-p text) - (error "Could not extract text from PDF: %s" path) - text))) - ((string-match-p "\\.epub\\'" path) - (when (and (not no-confirm) - (not (y-or-n-p "This is an EPUB file. Extract text for LLM (y) or cancel (n)? "))) - (error "EPUB file read cancelled")) - (error "EPUB text extraction not yet implemented")) - (t - (when (and (not no-confirm) - (not (y-or-n-p "This appears to be a binary file. Read anyway? "))) - (error "Binary file read cancelled")) - nil))) ; Return nil to indicate normal read - -;; Main tool function using the helpers -(gptel-make-tool - :name "read_text_file" - :function (lambda (path &optional no-confirm) - (let* ((full-path (cj/validate-file-path path)) - (metadata (cj/get-file-metadata full-path)) - (size (plist-get metadata :size)) - (metadata-string (plist-get metadata :string))) - ;; Show metadata and confirm - (unless no-confirm - (unless (y-or-n-p (format "%s\nRead this file? " metadata-string)) - (error "File read cancelled by user"))) - ;; Check size limits - (cj/check-file-size-limits size no-confirm) - ;; Handle binary/special files - (let ((content - (if (cj/detect-binary-file full-path) - (or (cj/handle-special-file-types full-path no-confirm) - ;; If not a special type or user wants to read anyway - (with-temp-buffer - (insert-file-contents full-path) - (buffer-string))) - ;; Normal text file - (with-temp-buffer - (insert-file-contents full-path) - (buffer-string))))) - (format "Read %d bytes from %s\n\n%s" - (length content) full-path content)))) - :description "Read text content from a file within the user's home directory. Shows file metadata and requests confirmation before reading. Handles large files, binary detection, and PDF text extraction." - :args (list '(:name "path" - :type string - :description "File path relative to home directory, e.g., 'documents/myfile.txt' or '~/documents/myfile.txt'") - '(:name "no_confirm" - :type boolean - :description "If true, skip confirmation prompts and read immediately" - :optional t)) - :category "filesystem" - :confirm t - :include t) - -;; Automatically add to gptel-tools on load -(add-to-list 'gptel-tools (gptel-get-tool '("filesystem" "read_text_file"))) - - -(provide 'read_text_file) -;;; read_text_file.el ends here. |
