branch: externals/ellama
commit c6cdb86950fafcf9902da067f2314997fd1f7b94
Merge: c491bf4c5b 1fd26a56e5
Author: Sergey Kostyaev <[email protected]>
Commit: GitHub <[email protected]>

    Merge pull request #370 from s-kostyaev/file-based-blueprints
    
    File based blueprints
---
 NEWS.org                              | 10 ++++
 README.org                            | 11 +++++
 blueprints/changelog.ellama-blueprint | 21 ++++++++
 docs/changelog.org                    |  3 --
 ellama-blueprint.el                   | 82 ++++++++++++++++++++++++++-----
 ellama-tools.el                       | 28 +++++++++++
 ellama.el                             |  2 +-
 ellama.info                           | 92 +++++++++++++++++++++--------------
 8 files changed, 197 insertions(+), 52 deletions(-)

diff --git a/NEWS.org b/NEWS.org
index 830120061d..710e9bd0ff 100644
--- a/NEWS.org
+++ b/NEWS.org
@@ -1,3 +1,13 @@
+* Version 1.10.12
+- Added prepend_file tool that allows prepending content to files. This expands
+  the set of file manipulation utilities available through the ellama tools.
+- Introduced customizable global and local directories for storing blueprint
+  files. Added support for configurable file extensions and utility functions 
to
+  locate, read, and load blueprints from files. This provides a flexible,
+  project-aware mechanism for discovering and loading blueprint resources.
+- Switched to backquote quoting for ellama-blueprint font-lock. This adjustment
+  ensures the regex is evaluated correctly and the font-lock face is applied as
+  intended.
 * Version 1.10.11
 - Remove explicit handling of numeric arguments in ellama-tools.
 - Add argument processing and type wrapping to tool definitions.
diff --git a/README.org b/README.org
index c51399e195..1c46bc2672 100644
--- a/README.org
+++ b/README.org
@@ -379,6 +379,11 @@ argument generated text string.
   will work without user confirmation.
 - ~ellama-tools-argument-max-length~: Max length of function argument in the
   confirmation prompt. Default value 50.
+- ~ellama-blueprint-global-dir~: Global directory for storing blueprint files.
+- ~ellama-blueprint-local-dir~: Local directory name for project-specific
+  blueprints.
+- ~ellama-blueprint-file-extensions~: File extensions recognized as blueprint
+  files.
 
 * Context Management
 
@@ -623,6 +628,12 @@ Ellama provides several functions to create, select, and 
manage blueprints:
    from the collection of blueprints. It filters prompts based on whether they
    are for developers and their source (user-defined, community, or all).
 
+** Blueprints files
+
+You can also store blueprints as plain text files. You can store it globally
+inside ~ellama-blueprint-global-dir~ or locally in the project local directory
+~ellama-blueprint-local-dir~ with ~ellama-blueprint-file-extensions~.
+
 ** Variable Management
 
 Blueprints can include variables that need to be filled before running the chat
diff --git a/blueprints/changelog.ellama-blueprint 
b/blueprints/changelog.ellama-blueprint
new file mode 100644
index 0000000000..a99656cb60
--- /dev/null
+++ b/blueprints/changelog.ellama-blueprint
@@ -0,0 +1,21 @@
+Call shell_command tool with "git log --reverse main..HEAD" argument. Based on
+the output write short changelog in org-mode list format. Use "~tildas~" 
quoting
+instead of "`backticks`" quoting. Do not add any anknowledgements. Every
+changelog element should be ended with full stop. Changelog shouldn't be too
+short or too long, use detailed description for major changes and concise
+description for minor changes. Write it to ./NEWS.org using prepend_file tool
+with header:
+
+* Version {version}
+
+After header should be changelog content. Content should ends with single
+newline.
+Example:
+ ```text
+* Version {version}
+- Some change description. Some additional information.
+- Major change detailed description. This change improves ~ellama-something~.
+  Some additional information.
+- Third change description.
+- Some fix in ~ellama-example-command~ description.
+```
diff --git a/docs/changelog.org b/docs/changelog.org
deleted file mode 100644
index 9cfaa62fb4..0000000000
--- a/docs/changelog.org
+++ /dev/null
@@ -1,3 +0,0 @@
-Based on shell_command "git log --reverse main..HEAD" output write short
-changelog in markdown list format. Do not add any headings or anknowledgements.
-Every changelog element should be ended with full stop.
diff --git a/ellama-blueprint.el b/ellama-blueprint.el
index 685ab534a5..79afea10da 100644
--- a/ellama-blueprint.el
+++ b/ellama-blueprint.el
@@ -37,6 +37,70 @@
   :group 'ellama
   :type '(repeat plist))
 
+(defcustom ellama-blueprint-global-dir
+  (expand-file-name "ellama/blueprints" user-emacs-directory)
+  "Global directory for storing blueprint files."
+  :group 'ellama
+  :type 'directory)
+
+(defcustom ellama-blueprint-local-dir "blueprints"
+  "Local directory name for project-specific blueprints.
+When set to a string like \"blueprints\", it will look for this
+directory in the current project root."
+  :group 'ellama
+  :type 'string)
+
+(defcustom ellama-blueprint-file-extensions '("ellama-blueprint" "blueprint")
+  "File extensions recognized as blueprint files."
+  :group 'ellama
+  :type '(repeat string))
+
+(defun ellama-blueprint-get-local-dir ()
+  "Get local blueprint directory for current project."
+  (let ((project-root (ellama-tools-project-root-tool)))
+    (expand-file-name ellama-blueprint-local-dir project-root)))
+
+(defun ellama-blueprint-find-files (&optional dir extensions)
+  "Find blueprint files in DIR with given EXTENSIONS."
+  (let* ((search-dir (or dir ellama-blueprint-global-dir))
+         (exts (or extensions ellama-blueprint-file-extensions))
+         (files '()))
+    (when (file-exists-p search-dir)
+      (dolist (ext exts)
+        (setq files (append files
+                           (directory-files-recursively
+                            search-dir (concat "\\." ext "\\'"))))))
+    files))
+
+(defun ellama-blueprint-load-from-files ()
+  "Load blueprints from files."
+  (let ((global-files (ellama-blueprint-find-files 
ellama-blueprint-global-dir))
+        (local-files (ellama-blueprint-find-files 
(ellama-blueprint-get-local-dir)))
+        blueprints)
+    (dolist (file (append global-files local-files))
+      (when-let ((content (ellama-blueprint-read-file file))
+                 (name (file-name-sans-extension (file-name-nondirectory 
file)))
+                 (prompt (string-trim content)))
+        (push `(:act ,name :prompt ,prompt :file ,file) blueprints)))
+    blueprints))
+
+(defun ellama-blueprint-read-file (file)
+  "Read blueprint content from FILE."
+  (when (file-exists-p file)
+    (with-temp-buffer
+      (insert-file-contents file)
+      (buffer-string))))
+
+(defun ellama-blueprint-get-all-sources ()
+  "Get blueprints from all sources."
+  (let ((file-blueprints (ellama-blueprint-load-from-files))
+        (variable-blueprints ellama-blueprints)
+        (community-blueprints (ellama-community-prompts-ensure)))
+    (seq-uniq
+     (append file-blueprints variable-blueprints community-blueprints)
+     (lambda (b1 b2)
+       (string= (plist-get b1 :act) (plist-get b2 :act))))))
+
 ;;;###autoload
 (defun ellama-blueprint-set-system-kill-buffer ()
   "Set system message from current buffer and kill it."
@@ -62,10 +126,6 @@
   "{\\([[:alnum:]_-]+\\)}"
   "Regular expression to match blueprint variables like {var_name}.")
 
-(defvar ellama-blueprint-font-lock-keywords
-  '((,ellama-blueprint-variable-regexp 1 'font-lock-keyword-face))
-  "Highlight variables in curly braces for Ellama Blueprint Mode.")
-
 ;;;###autoload
 (define-derived-mode ellama-blueprint-mode
   text-mode
@@ -73,7 +133,7 @@
   "Toggle Ellama Blueprint mode."
   :keymap ellama-blueprint-mode-map
   :group 'ellama
-  (setq font-lock-defaults '(((,ellama-blueprint-variable-regexp 1 
font-lock-keyword-face t))))
+  (setq font-lock-defaults `(((,ellama-blueprint-variable-regexp 1 
font-lock-keyword-face t))))
   (setq header-line-format
        (concat
         (propertize
@@ -102,6 +162,9 @@
                    (define-key m [mode-line mouse-1] 
#'ellama-kill-current-buffer)
                    m)))))
 
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.ellama-blueprint\\'" . 
ellama-blueprint-mode))
+
 (defvar ellama-blueprint-buffer "*ellama-blueprint-buffer*"
   "Buffer for prompt blueprint.")
 
@@ -151,13 +214,8 @@ ARGS contains keys for fine control.
         (collection (pcase source
                       ('user ellama-blueprints)
                       ('community (ellama-community-prompts-ensure))
-                      (_ (seq-union
-                          ellama-blueprints
-                          (ellama-community-prompts-ensure)
-                          (lambda (blueprint1 blueprint2)
-                            (string=
-                             (plist-get blueprint1 :act)
-                             (plist-get blueprint2 :act)))))))
+                      ('files (ellama-blueprint-load-from-files))
+                      (_ (ellama-blueprint-get-all-sources))))
         selected-act
         selected-prompt)
     ;; Collect unique acts from the filtered collection
diff --git a/ellama-tools.el b/ellama-tools.el
index 47db0e700a..a2b6b63e59 100644
--- a/ellama-tools.el
+++ b/ellama-tools.el
@@ -303,6 +303,34 @@ TOOL-PLIST is a property list in the format expected by 
`llm-make-tool'."
    :description
    "Append CONTENT to the file located at the specified PATH."))
 
+(defun ellama-tools-prepend-file-tool (path content)
+  "Prepend CONTENT to the file located at the specified PATH."
+  (with-current-buffer (find-file-noselect path)
+    (goto-char (point-min))
+    (insert content)
+    (save-buffer)))
+
+(ellama-tools-define-tool
+ '(:function
+   ellama-tools-prepend-file-tool
+   :name
+   "prepend_file"
+   :args
+   ((:name
+     "path"
+     :type
+     string
+     :description
+     "Path to the file.")
+    (:name
+     "content"
+     :type
+     string
+     :description
+     "Content to prepend to the file."))
+   :description
+   "Prepend CONTENT to the file located at the specified PATH."))
+
 (defun ellama-tools-directory-tree-tool (dir &optional depth)
   "Return a string representing the directory tree under DIR.
 DEPTH is the current recursion depth, used internally."
diff --git a/ellama.el b/ellama.el
index b02659d5f4..23f41ece93 100644
--- a/ellama.el
+++ b/ellama.el
@@ -6,7 +6,7 @@
 ;; URL: http://github.com/s-kostyaev/ellama
 ;; Keywords: help local tools
 ;; Package-Requires: ((emacs "28.1") (llm "0.24.0") (plz "0.8") (transient 
"0.7") (compat "29.1"))
-;; Version: 1.10.11
+;; Version: 1.10.12
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;; Created: 8th Oct 2023
 
diff --git a/ellama.info b/ellama.info
index 31d09b1732..ec605322b7 100644
--- a/ellama.info
+++ b/ellama.info
@@ -101,6 +101,7 @@ Using Blueprints
 
 * Key Components of Ellama Blueprints::
 * Creating and Managing Blueprints::
+* Blueprints files::
 * Variable Management::
 * Keymap and Mode::
 * Transient Menus::
@@ -503,6 +504,12 @@ argument generated text string.
      this list will work without user confirmation.
    • ‘ellama-tools-argument-max-length’: Max length of function argument
      in the confirmation prompt.  Default value 50.
+   • ‘ellama-blueprint-global-dir’: Global directory for storing
+     blueprint files.
+   • ‘ellama-blueprint-local-dir’: Local directory name for
+     project-specific blueprints.
+   • ‘ellama-blueprint-file-extensions’: File extensions recognized as
+     blueprint files.
 
 
 File: ellama.info,  Node: Context Management,  Next: Minor modes,  Prev: 
Configuration,  Up: Top
@@ -813,6 +820,7 @@ for interactions.
 
 * Key Components of Ellama Blueprints::
 * Creating and Managing Blueprints::
+* Blueprints files::
 * Variable Management::
 * Keymap and Mode::
 * Transient Menus::
@@ -836,7 +844,7 @@ needed to guide the conversation.
 developers.
 
 
-File: ellama.info,  Node: Creating and Managing Blueprints,  Next: Variable 
Management,  Prev: Key Components of Ellama Blueprints,  Up: Using Blueprints
+File: ellama.info,  Node: Creating and Managing Blueprints,  Next: Blueprints 
files,  Prev: Key Components of Ellama Blueprints,  Up: Using Blueprints
 
 7.2 Creating and Managing Blueprints
 ====================================
@@ -859,9 +867,20 @@ blueprints:
      community, or all).
 
 
-File: ellama.info,  Node: Variable Management,  Next: Keymap and Mode,  Prev: 
Creating and Managing Blueprints,  Up: Using Blueprints
+File: ellama.info,  Node: Blueprints files,  Next: Variable Management,  Prev: 
Creating and Managing Blueprints,  Up: Using Blueprints
 
-7.3 Variable Management
+7.3 Blueprints files
+====================
+
+You can also store blueprints as plain text files.  You can store it
+globally inside ‘ellama-blueprint-global-dir’ or locally in the project
+local directory ‘ellama-blueprint-local-dir’ with
+‘ellama-blueprint-file-extensions’.
+
+
+File: ellama.info,  Node: Variable Management,  Next: Keymap and Mode,  Prev: 
Blueprints files,  Up: Using Blueprints
+
+7.4 Variable Management
 =======================
 
 Blueprints can include variables that need to be filled before running
@@ -873,7 +892,7 @@ the chat session.  Ellama provides command to fill these 
variables:
 
 File: ellama.info,  Node: Keymap and Mode,  Next: Transient Menus,  Prev: 
Variable Management,  Up: Using Blueprints
 
-7.4 Keymap and Mode
+7.5 Keymap and Mode
 ===================
 
 Ellama provides a local keymap ‘ellama-blueprint-mode-map’ for managing
@@ -897,7 +916,7 @@ available:
 
 File: ellama.info,  Node: Transient Menus,  Next: Running Blueprints 
programmatically,  Prev: Keymap and Mode,  Up: Using Blueprints
 
-7.5 Transient Menus
+7.6 Transient Menus
 ===================
 
 Ellama includes transient menus for easy access to blueprint commands.
@@ -910,7 +929,7 @@ main menu, providing a comprehensive interface for all 
Ellama commands.
 
 File: ellama.info,  Node: Running Blueprints programmatically,  Prev: 
Transient Menus,  Up: Using Blueprints
 
-7.6 Running Blueprints programmatically
+7.7 Running Blueprints programmatically
 =======================================
 
 The ‘ellama-blueprint-run’ function initiates a chat session using a
@@ -1471,36 +1490,37 @@ their use in free software.
 
 Tag Table:
 Node: Top1379
-Node: Installation3633
-Node: Commands8641
-Node: Keymap16080
-Node: Configuration18913
-Node: Context Management24921
-Node: Transient Menus for Context Management25829
-Node: Managing the Context27443
-Node: Considerations28218
-Node: Minor modes28811
-Node: ellama-context-header-line-mode30799
-Node: ellama-context-header-line-global-mode31624
-Node: ellama-context-mode-line-mode32344
-Node: ellama-context-mode-line-global-mode33192
-Node: Ellama Session Header Line Mode33896
-Node: Enabling and Disabling34465
-Node: Customization34912
-Node: Ellama Session Mode Line Mode35200
-Node: Enabling and Disabling (1)35785
-Node: Customization (1)36232
-Node: Using Blueprints36526
-Node: Key Components of Ellama Blueprints37145
-Node: Creating and Managing Blueprints37752
-Node: Variable Management38733
-Node: Keymap and Mode39202
-Node: Transient Menus40138
-Node: Running Blueprints programmatically40684
-Node: MCP Integration41271
-Node: Acknowledgments42296
-Node: Contributions43008
-Node: GNU Free Documentation License43394
+Node: Installation3654
+Node: Commands8662
+Node: Keymap16101
+Node: Configuration18934
+Node: Context Management25234
+Node: Transient Menus for Context Management26142
+Node: Managing the Context27756
+Node: Considerations28531
+Node: Minor modes29124
+Node: ellama-context-header-line-mode31112
+Node: ellama-context-header-line-global-mode31937
+Node: ellama-context-mode-line-mode32657
+Node: ellama-context-mode-line-global-mode33505
+Node: Ellama Session Header Line Mode34209
+Node: Enabling and Disabling34778
+Node: Customization35225
+Node: Ellama Session Mode Line Mode35513
+Node: Enabling and Disabling (1)36098
+Node: Customization (1)36545
+Node: Using Blueprints36839
+Node: Key Components of Ellama Blueprints37479
+Node: Creating and Managing Blueprints38086
+Node: Blueprints files39064
+Node: Variable Management39485
+Node: Keymap and Mode39938
+Node: Transient Menus40874
+Node: Running Blueprints programmatically41420
+Node: MCP Integration42007
+Node: Acknowledgments43032
+Node: Contributions43744
+Node: GNU Free Documentation License44130
 
 End Tag Table
 

Reply via email to