aboutsummaryrefslogtreecommitdiff
path: root/gptel-tools/read_text_file.el
diff options
context:
space:
mode:
Diffstat (limited to 'gptel-tools/read_text_file.el')
-rw-r--r--gptel-tools/read_text_file.el146
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.