From 0a41ebe0e999693481ad909a2e99b9fd310f2e2d Mon Sep 17 00:00:00 2001 From: Bruce Hauman Date: Fri, 10 Oct 2025 20:33:07 -0600 Subject: [PATCH 1/6] Add dry-run parameter to file_edit tool - Add optional dry-run parameter that accepts 'diff' or 'new-source' - When dry-run is set, skip file save, timestamp update, and Emacs highlight - With 'diff' mode: returns diff of proposed changes - With 'new-source' mode: returns complete new source code - Parameter is not exposed in tool schema (internal use for clients) - Addresses issue #115 --- src/clojure_mcp/tools/file_edit/pipeline.clj | 42 ++++++++++++++------ src/clojure_mcp/tools/file_edit/tool.clj | 8 ++-- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/clojure_mcp/tools/file_edit/pipeline.clj b/src/clojure_mcp/tools/file_edit/pipeline.clj index 64b8a079..2ff9244b 100644 --- a/src/clojure_mcp/tools/file_edit/pipeline.clj +++ b/src/clojure_mcp/tools/file_edit/pipeline.clj @@ -23,6 +23,8 @@ (s/def ::old-string string?) (s/def ::new-string string?) (s/def ::nrepl-client-atom (s/nilable #(instance? clojure.lang.Atom %))) + +(s/def ::dry-run (s/nilable #{"diff" "new-source"})) ;; Pipeline specific steps ;; Using check-file-modified from form-edit/pipeline instead @@ -117,15 +119,16 @@ - file-path: Path to the file to edit - old-string: String to replace - new-string: New string to insert - - nrepl-client-atom: Atom containing the nREPL client (optional) - - config: Optional tool configuration map + - dry-run: Optional string, either \"diff\" or \"new-source\" to skip actual file write + - config: Optional tool configuration map with :nrepl-client-atom Returns: - A context map with the result of the operation" - [file-path old-string new-string {:keys [nrepl-client-atom] :as config}] + [file-path old-string new-string dry-run {:keys [nrepl-client-atom] :as config}] (let [initial-ctx {::form-pipeline/file-path file-path ::old-string old-string ::new-string new-string + ::dry-run dry-run ::form-pipeline/nrepl-client-atom nrepl-client-atom ::form-pipeline/config config}] ;; Pipeline for existing file edit @@ -147,9 +150,14 @@ format-clojure-content ;; Format Clojure files automatically form-pipeline/determine-file-type ;; This will mark as "update" form-pipeline/generate-diff ;; Generate diff between old and new - form-pipeline/save-file ;; Save the file - form-pipeline/update-file-timestamp ;; Update the timestamp after save - form-pipeline/highlight-form))) ;; Update the timestamp after save ;; Update the timestamp after save + ;; Skip file operations if dry-run is set + (fn [ctx] + (if (::dry-run ctx) + ctx + (-> ctx + form-pipeline/save-file + form-pipeline/update-file-timestamp + form-pipeline/highlight-form)))))) ;; Update the timestamp after save ;; Update the timestamp after save ;; Format result for tool consumption (defn format-result @@ -159,17 +167,25 @@ - ctx: The final context map from the pipeline Returns: - - A map with :error, :message, and :diff keys, and potentially :repaired" + - A map with :error, :message, and :diff or :new-source keys, and potentially :repaired" [ctx] (if (::form-pipeline/error ctx) {:error true :message (::form-pipeline/message ctx)} - (cond-> {:error false - :diff (::form-pipeline/diff ctx) - :type (::form-pipeline/type ctx)} - ;; Include repaired flag if present - (::form-pipeline/repaired ctx) - (assoc :repaired true)))) + (let [dry-run (::dry-run ctx)] + (cond-> {:error false + :type (::form-pipeline/type ctx)} + ;; Include repaired flag if present + (::form-pipeline/repaired ctx) + (assoc :repaired true) + + ;; Return new-source if dry-run is "new-source" + (= dry-run "new-source") + (assoc :new-source (::form-pipeline/output-source ctx)) + + ;; Otherwise return diff (default behavior and for "diff" dry-run) + (not= dry-run "new-source") + (assoc :diff (::form-pipeline/diff ctx)))))) (comment ;; === Examples of using the file-edit pipeline directly === diff --git a/src/clojure_mcp/tools/file_edit/tool.clj b/src/clojure_mcp/tools/file_edit/tool.clj index 68a0a405..cefab06c 100644 --- a/src/clojure_mcp/tools/file_edit/tool.clj +++ b/src/clojure_mcp/tools/file_edit/tool.clj @@ -81,16 +81,16 @@ To make a file edit, provide the file_path, old_string (the text to replace), an :new_string new_string)))) (defmethod tool-system/execute-tool :file-edit [{:keys [nrepl-client-atom] :as tool} inputs] - (let [{:keys [file_path old_string new_string]} inputs - result (pipeline/file-edit-pipeline file_path old_string new_string tool)] + (let [{:keys [file_path old_string new_string dry-run]} inputs + result (pipeline/file-edit-pipeline file_path old_string new_string dry-run tool)] (pipeline/format-result result))) -(defmethod tool-system/format-results :file-edit [_ {:keys [error message diff type repaired]}] +(defmethod tool-system/format-results :file-edit [_ {:keys [error message diff new-source type repaired]}] (if error {:error true :result [message]} (cond-> {:error false - :result [diff] + :result [(or new-source diff)] :type type} ;; Include repaired flag if present repaired (assoc :repaired true)))) From a84a8f136bd00490c04f63c1de887b9f1f337329 Mon Sep 17 00:00:00 2001 From: Bruce Hauman Date: Tue, 14 Oct 2025 10:19:40 -0600 Subject: [PATCH 2/6] WIP: the dry run is not working on the clojure_edit yet --- .../tools/form_edit/combined_edit_tool.clj | 8 ++-- src/clojure_mcp/tools/form_edit/pipeline.clj | 43 +++++++++++++------ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/clojure_mcp/tools/form_edit/combined_edit_tool.clj b/src/clojure_mcp/tools/form_edit/combined_edit_tool.clj index 6f326c1f..fc877b32 100644 --- a/src/clojure_mcp/tools/form_edit/combined_edit_tool.clj +++ b/src/clojure_mcp/tools/form_edit/combined_edit_tool.clj @@ -154,21 +154,21 @@ Note: For `defmethod` forms, be sure to include the dispatch value (`area :recta ;; Execute tool implementation (defmethod tool-system/execute-tool :clojure-edit-form [{:keys [nrepl-client-atom] :as tool} inputs] - (let [{:keys [file_path form_name form_type operation content]} inputs + (let [{:keys [file_path form_name form_type operation content dry-run]} inputs edit-type (case operation "replace" :replace "insert_before" :before "insert_after" :after) - result (pipeline/edit-form-pipeline file_path form_name form_type content edit-type tool) + result (pipeline/edit-form-pipeline file_path form_name form_type content edit-type dry-run tool) formatted-result (pipeline/format-result result)] formatted-result)) ;; Format results implementation -(defmethod tool-system/format-results :clojure-edit-form [_ {:keys [error message diff]}] +(defmethod tool-system/format-results :clojure-edit-form [_ {:keys [error message diff new-source]}] (if error {:result [message] :error true} - {:result [diff] + {:result [(or new-source diff)] :error false})) ;; Tool registration function diff --git a/src/clojure_mcp/tools/form_edit/pipeline.clj b/src/clojure_mcp/tools/form_edit/pipeline.clj index 4d7030bd..03a711c7 100644 --- a/src/clojure_mcp/tools/form_edit/pipeline.clj +++ b/src/clojure_mcp/tools/form_edit/pipeline.clj @@ -43,14 +43,15 @@ (s/def ::nrepl-client-atom (s/nilable #(instance? clojure.lang.Atom %))) -;; Context map that flows through the pipeline +(s/def ::dry-run (s/nilable #{"diff" "new-source"})) + (s/def ::context (s/keys :req [::file-path] :opt [::source ::old-content ::new-source-code ::top-level-def-name ::top-level-def-type ::edit-type ::error ::message ::zloc ::offsets ::lint-result ::docstring ::comment-substring ::new-content ::expand-symbols - ::diff ::type ::output-source ::nrepl-client-atom])) + ::diff ::type ::output-source ::nrepl-client-atom ::dry-run])) ;; Pipeline helper functions @@ -536,16 +537,27 @@ - ctx: The final context map from the pipeline Returns: - - A map with :error, :message, and possibly :offsets and :result keys" + - A map with :error, :message, and possibly :diff or :new-source, and :offsets keys" [ctx] (if (::error ctx) {:error true :message (::message ctx)} - (let [result-map {:error false}] + (let [dry-run (::dry-run ctx) + result-map {:error false}] (cond-> result-map (::offsets ctx) (assoc :offsets (::offsets ctx)) - (::output-source ctx) (assoc :result [(::output-source ctx)]) - (::diff ctx) (assoc :diff (::diff ctx)))))) + + ;; Return new-source if dry-run is "new-source" + (= dry-run "new-source") + (assoc :new-source (::output-source ctx)) + + ;; Otherwise return diff (default behavior and for "diff" dry-run) + (and (::diff ctx) (not= dry-run "new-source")) + (assoc :diff (::diff ctx)) + + ;; Legacy: include :result if output-source exists + (and (::output-source ctx) (not dry-run)) + (assoc :result [(::output-source ctx)]))))) ;; Pipeline function definitions @@ -558,16 +570,17 @@ - form-type: Type of form (e.g., 'defn', 'defmethod') - content-str: New content to insert - edit-type: Type of edit (:replace, :before, :after) - - nrepl-client-atom: Atom containing the nREPL client (optional) - - config: Optional tool configuration map + - dry-run: Optional string, either \"diff\" or \"new-source\" to skip actual file write + - config: Optional tool configuration map with :nrepl-client-atom Returns a context map with the result of the operation" - [file-path form-name form-type content-str edit-type {:keys [nrepl-client-atom] :as config}] + [file-path form-name form-type content-str edit-type dry-run {:keys [nrepl-client-atom] :as config}] (let [ctx {::file-path file-path ::top-level-def-name form-name ::top-level-def-type form-type ::new-source-code content-str ::edit-type edit-type + ::dry-run dry-run ::nrepl-client-atom nrepl-client-atom ::config config}] (thread-ctx @@ -587,9 +600,15 @@ format-source determine-file-type generate-diff - save-file - update-file-timestamp - highlight-form))) + ;; Skip file operations if dry-run is set + (fn [ctx] + (log/info [:CONTEXT (pr-str (keys ctx))]) + (if (::dry-run ctx) + ctx + (-> ctx + save-file + update-file-timestamp + highlight-form)))))) (defn docstring-edit-pipeline "Pipeline for editing a docstring in a file. From 00738aa53baddb346265ae8bbe1e9947ce80db26 Mon Sep 17 00:00:00 2001 From: Bruce Hauman Date: Wed, 22 Oct 2025 16:05:51 -0600 Subject: [PATCH 3/6] Complete dry-run parameter implementation for clojure_edit tool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Extract and pass dry-run parameter through validate-inputs - Enable dry-run modes: "diff" (returns diff) and "new-source" (returns complete source) - Both modes skip file write operations while preserving all other pipeline steps - Clean up debug logging 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/clojure_mcp/tools/form_edit/combined_edit_tool.clj | 7 +++---- src/clojure_mcp/tools/form_edit/pipeline.clj | 2 -- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/clojure_mcp/tools/form_edit/combined_edit_tool.clj b/src/clojure_mcp/tools/form_edit/combined_edit_tool.clj index fc877b32..44c5aa37 100644 --- a/src/clojure_mcp/tools/form_edit/combined_edit_tool.clj +++ b/src/clojure_mcp/tools/form_edit/combined_edit_tool.clj @@ -126,8 +126,7 @@ Note: For `defmethod` forms, be sure to include the dispatch value (`area :recta ;; Validate inputs implementation (defmethod tool-system/validate-inputs :clojure-edit-form [{:keys [nrepl-client-atom]} inputs] (let [file-path (validate-file-path inputs nrepl-client-atom) - ;; Accept form_identifier but map it to form_name internally for compatibility - {:keys [form_identifier form_type operation content]} inputs + {:keys [form_identifier form_type operation content dry-run]} inputs form_name form_identifier] (when-not form_identifier (throw (ex-info "Missing required parameter: form_identifier" @@ -145,12 +144,12 @@ Note: For `defmethod` forms, be sure to include the dispatch value (`area :recta (when-not content (throw (ex-info "Missing required parameter: content" {:inputs inputs}))) - ;; Return validated inputs with form_name for backward compatibility {:file_path file-path :form_name form_name :form_type form_type :operation operation - :content content})) + :content content + :dry-run dry-run})) ;; Execute tool implementation (defmethod tool-system/execute-tool :clojure-edit-form [{:keys [nrepl-client-atom] :as tool} inputs] diff --git a/src/clojure_mcp/tools/form_edit/pipeline.clj b/src/clojure_mcp/tools/form_edit/pipeline.clj index 03a711c7..6204fb5d 100644 --- a/src/clojure_mcp/tools/form_edit/pipeline.clj +++ b/src/clojure_mcp/tools/form_edit/pipeline.clj @@ -600,9 +600,7 @@ format-source determine-file-type generate-diff - ;; Skip file operations if dry-run is set (fn [ctx] - (log/info [:CONTEXT (pr-str (keys ctx))]) (if (::dry-run ctx) ctx (-> ctx From 77656faf763cc011c52c4acf59eefe74eb853b90 Mon Sep 17 00:00:00 2001 From: Bruce Hauman Date: Wed, 22 Oct 2025 16:12:57 -0600 Subject: [PATCH 4/6] Rename dry-run parameter to dry_run for consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change parameter name from dry-run to dry_run (with underscore) - Update all references in file_edit and form_edit tools - Fix key mismatch in validate-inputs return map 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/clojure_mcp/tools/file_edit/pipeline.clj | 10 +++++----- src/clojure_mcp/tools/file_edit/tool.clj | 4 ++-- .../tools/form_edit/combined_edit_tool.clj | 8 ++++---- src/clojure_mcp/tools/form_edit/pipeline.clj | 12 ++++++------ 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/clojure_mcp/tools/file_edit/pipeline.clj b/src/clojure_mcp/tools/file_edit/pipeline.clj index 2ff9244b..9a3578b9 100644 --- a/src/clojure_mcp/tools/file_edit/pipeline.clj +++ b/src/clojure_mcp/tools/file_edit/pipeline.clj @@ -124,11 +124,11 @@ Returns: - A context map with the result of the operation" - [file-path old-string new-string dry-run {:keys [nrepl-client-atom] :as config}] + [file-path old-string new-string dry_run {:keys [nrepl-client-atom] :as config}] (let [initial-ctx {::form-pipeline/file-path file-path ::old-string old-string ::new-string new-string - ::dry-run dry-run + ::dry-run dry_run ::form-pipeline/nrepl-client-atom nrepl-client-atom ::form-pipeline/config config}] ;; Pipeline for existing file edit @@ -172,7 +172,7 @@ (if (::form-pipeline/error ctx) {:error true :message (::form-pipeline/message ctx)} - (let [dry-run (::dry-run ctx)] + (let [dry_run (::dry-run ctx)] (cond-> {:error false :type (::form-pipeline/type ctx)} ;; Include repaired flag if present @@ -180,11 +180,11 @@ (assoc :repaired true) ;; Return new-source if dry-run is "new-source" - (= dry-run "new-source") + (= dry_run "new-source") (assoc :new-source (::form-pipeline/output-source ctx)) ;; Otherwise return diff (default behavior and for "diff" dry-run) - (not= dry-run "new-source") + (not= dry_run "new-source") (assoc :diff (::form-pipeline/diff ctx)))))) (comment diff --git a/src/clojure_mcp/tools/file_edit/tool.clj b/src/clojure_mcp/tools/file_edit/tool.clj index cefab06c..93488b40 100644 --- a/src/clojure_mcp/tools/file_edit/tool.clj +++ b/src/clojure_mcp/tools/file_edit/tool.clj @@ -81,8 +81,8 @@ To make a file edit, provide the file_path, old_string (the text to replace), an :new_string new_string)))) (defmethod tool-system/execute-tool :file-edit [{:keys [nrepl-client-atom] :as tool} inputs] - (let [{:keys [file_path old_string new_string dry-run]} inputs - result (pipeline/file-edit-pipeline file_path old_string new_string dry-run tool)] + (let [{:keys [file_path old_string new_string dry_run]} inputs + result (pipeline/file-edit-pipeline file_path old_string new_string dry_run tool)] (pipeline/format-result result))) (defmethod tool-system/format-results :file-edit [_ {:keys [error message diff new-source type repaired]}] diff --git a/src/clojure_mcp/tools/form_edit/combined_edit_tool.clj b/src/clojure_mcp/tools/form_edit/combined_edit_tool.clj index 44c5aa37..aa69b298 100644 --- a/src/clojure_mcp/tools/form_edit/combined_edit_tool.clj +++ b/src/clojure_mcp/tools/form_edit/combined_edit_tool.clj @@ -126,7 +126,7 @@ Note: For `defmethod` forms, be sure to include the dispatch value (`area :recta ;; Validate inputs implementation (defmethod tool-system/validate-inputs :clojure-edit-form [{:keys [nrepl-client-atom]} inputs] (let [file-path (validate-file-path inputs nrepl-client-atom) - {:keys [form_identifier form_type operation content dry-run]} inputs + {:keys [form_identifier form_type operation content dry_run]} inputs form_name form_identifier] (when-not form_identifier (throw (ex-info "Missing required parameter: form_identifier" @@ -149,16 +149,16 @@ Note: For `defmethod` forms, be sure to include the dispatch value (`area :recta :form_type form_type :operation operation :content content - :dry-run dry-run})) + :dry_run dry_run})) ;; Execute tool implementation (defmethod tool-system/execute-tool :clojure-edit-form [{:keys [nrepl-client-atom] :as tool} inputs] - (let [{:keys [file_path form_name form_type operation content dry-run]} inputs + (let [{:keys [file_path form_name form_type operation content dry_run]} inputs edit-type (case operation "replace" :replace "insert_before" :before "insert_after" :after) - result (pipeline/edit-form-pipeline file_path form_name form_type content edit-type dry-run tool) + result (pipeline/edit-form-pipeline file_path form_name form_type content edit-type dry_run tool) formatted-result (pipeline/format-result result)] formatted-result)) diff --git a/src/clojure_mcp/tools/form_edit/pipeline.clj b/src/clojure_mcp/tools/form_edit/pipeline.clj index 6204fb5d..2c155a4c 100644 --- a/src/clojure_mcp/tools/form_edit/pipeline.clj +++ b/src/clojure_mcp/tools/form_edit/pipeline.clj @@ -542,21 +542,21 @@ (if (::error ctx) {:error true :message (::message ctx)} - (let [dry-run (::dry-run ctx) + (let [dry_run (::dry-run ctx) result-map {:error false}] (cond-> result-map (::offsets ctx) (assoc :offsets (::offsets ctx)) ;; Return new-source if dry-run is "new-source" - (= dry-run "new-source") + (= dry_run "new-source") (assoc :new-source (::output-source ctx)) ;; Otherwise return diff (default behavior and for "diff" dry-run) - (and (::diff ctx) (not= dry-run "new-source")) + (and (::diff ctx) (not= dry_run "new-source")) (assoc :diff (::diff ctx)) ;; Legacy: include :result if output-source exists - (and (::output-source ctx) (not dry-run)) + (and (::output-source ctx) (not dry_run)) (assoc :result [(::output-source ctx)]))))) ;; Pipeline function definitions @@ -574,13 +574,13 @@ - config: Optional tool configuration map with :nrepl-client-atom Returns a context map with the result of the operation" - [file-path form-name form-type content-str edit-type dry-run {:keys [nrepl-client-atom] :as config}] + [file-path form-name form-type content-str edit-type dry_run {:keys [nrepl-client-atom] :as config}] (let [ctx {::file-path file-path ::top-level-def-name form-name ::top-level-def-type form-type ::new-source-code content-str ::edit-type edit-type - ::dry-run dry-run + ::dry-run dry_run ::nrepl-client-atom nrepl-client-atom ::config config}] (thread-ctx From dfca0da59dc14a21a3a27fc9d46502f57d90f5fc Mon Sep 17 00:00:00 2001 From: Bruce Hauman Date: Wed, 22 Oct 2025 16:22:25 -0600 Subject: [PATCH 5/6] Add dry_run parameter support to clojure_edit_replace_sexp tool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add dry_run parameter to sexp-edit-pipeline - Extract and pass dry_run through validate-inputs and execute-tool - Update format-results to handle new-source output - Skip file write operations when dry_run is set 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/clojure_mcp/tools/form_edit/pipeline.clj | 14 ++++++++---- src/clojure_mcp/tools/form_edit/tool.clj | 23 ++++++-------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/clojure_mcp/tools/form_edit/pipeline.clj b/src/clojure_mcp/tools/form_edit/pipeline.clj index 2c155a4c..ea30158f 100644 --- a/src/clojure_mcp/tools/form_edit/pipeline.clj +++ b/src/clojure_mcp/tools/form_edit/pipeline.clj @@ -786,17 +786,19 @@ - operation: The operation to perform (:replace, :insert-before, :insert-after) - replace-all: Whether to apply the operation to all occurrences - whitespace-sensitive: Whether to match forms exactly as written + - dry_run: Optional string, either \"diff\" or \"new-source\" to skip actual file write - config: Optional tool configuration map with nrepl-client-atom Returns: - A context map with the result of the operation" - [file-path match-form new-form operation replace-all whitespace-sensitive {:keys [nrepl-client-atom] :as config}] + [file-path match-form new-form operation replace-all whitespace-sensitive dry_run {:keys [nrepl-client-atom] :as config}] (let [ctx {::file-path file-path ::match-form match-form ::new-form new-form ::operation operation ::replace-all replace-all ::whitespace-sensitive whitespace-sensitive + ::dry-run dry_run ::nrepl-client-atom nrepl-client-atom ::config config}] (thread-ctx @@ -814,9 +816,13 @@ format-source determine-file-type generate-diff - save-file - update-file-timestamp - highlight-form))) + (fn [ctx] + (if (::dry-run ctx) + ctx + (-> ctx + save-file + update-file-timestamp + highlight-form)))))) (comment ;; Example usage of the pipelines diff --git a/src/clojure_mcp/tools/form_edit/tool.clj b/src/clojure_mcp/tools/form_edit/tool.clj index b7a9ff21..58c52c19 100644 --- a/src/clojure_mcp/tools/form_edit/tool.clj +++ b/src/clojure_mcp/tools/form_edit/tool.clj @@ -545,7 +545,7 @@ For reliable results, use a unique substring that appears in only one comment bl (defmethod tool-system/validate-inputs :clojure-update-sexp [{:keys [nrepl-client-atom multi-op]} inputs] (let [file-path (validate-file-path inputs nrepl-client-atom) - {:keys [match_form new_form operation replace_all whitespace_sensitive]} inputs] + {:keys [match_form new_form operation replace_all whitespace_sensitive dry_run]} inputs] (when-not match_form (throw (ex-info "Missing required parameter: match_form" {:inputs inputs}))) @@ -567,16 +567,9 @@ For reliable results, use a unique substring that appears in only one comment bl (throw (ex-info "Bad parameter: match-form can not be a blank string." {:inputs inputs}))) - ;; TODO we can get more sophisticated here... we are handling - ;; code repairs deeper inside the actually tools evaluation and - ;; this prevents it. Also I think we can actually do comment - ;; replacement now but we might need special handling for that. - - ;; Special handling for empty string (when-not (str/blank? match_form) (try (let [parsed (p/parse-string-all match_form)] - ;; Check if there's at least one non-whitespace, non-comment node (when (zero? (count (n/child-sexprs parsed))) (throw (ex-info "match_form must contain at least one S-expression (not just comments or whitespace)" {:inputs inputs})))) @@ -587,13 +580,11 @@ For reliable results, use a unique substring that appears in only one comment bl {:inputs inputs})))))) (when-not (str/blank? new_form) - ;; Validate that new_form is valid Clojure code (try (p/parse-string-all new_form) (catch Exception e (throw (ex-info (str "Invalid Clojure code in new_form: " (.getMessage e)) {:inputs inputs}))))) - ;; Return validated inputs {:file_path file-path :match_form match_form :new_form new_form @@ -601,11 +592,11 @@ For reliable results, use a unique substring that appears in only one comment bl :replace_all (boolean (if (#{"insert_before" "insert_after"} operation) false (or replace_all false))) - :whitespace_sensitive (boolean (or whitespace_sensitive false))})) + :whitespace_sensitive (boolean (or whitespace_sensitive false)) + :dry_run dry_run})) (defmethod tool-system/execute-tool :clojure-update-sexp [{:keys [multi-op nrepl-client-atom] :as tool} inputs] - (let [{:keys [file_path match_form new_form operation replace_all whitespace_sensitive]} inputs - ;; Convert operation string to keyword for the pipeline + (let [{:keys [file_path match_form new_form operation replace_all whitespace_sensitive dry_run]} inputs operation-kw (if-not multi-op :replace (condp = operation @@ -613,15 +604,15 @@ For reliable results, use a unique substring that appears in only one comment bl "insert_before" :insert-before "insert_after" :insert-after)) result (pipeline/sexp-edit-pipeline - file_path match_form new_form operation-kw replace_all whitespace_sensitive tool) + file_path match_form new_form operation-kw replace_all whitespace_sensitive dry_run tool) formatted-result (pipeline/format-result result)] formatted-result)) -(defmethod tool-system/format-results :clojure-update-sexp [_ {:keys [error message diff]}] +(defmethod tool-system/format-results :clojure-update-sexp [_ {:keys [error message diff new-source]}] (if error {:result [message] :error true} - {:result [diff] + {:result [(or new-source diff)] :error false})) ;; Function to register the tool From 905170bc8d1230ca0555158cc9dbbc9eac109573 Mon Sep 17 00:00:00 2001 From: Bruce Hauman Date: Wed, 22 Oct 2025 16:37:23 -0600 Subject: [PATCH 6/6] Fix test failures by adding dry_run parameter to pipeline calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated three execute-tool methods in tool.clj and two test methods in pipeline_test.clj to pass the new dry_run parameter (as nil) to edit-form-pipeline, which now requires 7 arguments instead of 6. All 365 tests now pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/clojure_mcp/tools/form_edit/tool.clj | 6 +++--- test/clojure_mcp/tools/form_edit/pipeline_test.clj | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/clojure_mcp/tools/form_edit/tool.clj b/src/clojure_mcp/tools/form_edit/tool.clj index 58c52c19..05f3a1b4 100644 --- a/src/clojure_mcp/tools/form_edit/tool.clj +++ b/src/clojure_mcp/tools/form_edit/tool.clj @@ -164,7 +164,7 @@ Note: For `defmethod` forms, be sure to include the dispatch value (`area :recta (defmethod tool-system/execute-tool :clojure-edit-replace-form [{:keys [nrepl-client-atom] :as tool} inputs] (let [{:keys [file_path form_name form_type content]} inputs - result (pipeline/edit-form-pipeline file_path form_name form_type content :replace tool) + result (pipeline/edit-form-pipeline file_path form_name form_type content :replace nil tool) formatted-result (pipeline/format-result result)] formatted-result)) @@ -256,7 +256,7 @@ Note: For `defmethod` forms, be sure to include the dispatch value (`area :recta (defmethod tool-system/execute-tool :clojure-edit-insert-before-form [{:keys [nrepl-client-atom] :as tool} inputs] (let [{:keys [file_path form_name form_type content]} inputs - result (pipeline/edit-form-pipeline file_path form_name form_type content :before tool) + result (pipeline/edit-form-pipeline file_path form_name form_type content :before nil tool) formatted-result (pipeline/format-result result)] formatted-result)) @@ -348,7 +348,7 @@ Note: For `defmethod` forms, be sure to include the dispatch value (`area :recta (defmethod tool-system/execute-tool :clojure-edit-insert-after-form [{:keys [nrepl-client-atom] :as tool} inputs] (let [{:keys [file_path form_name form_type content]} inputs - result (pipeline/edit-form-pipeline file_path form_name form_type content :after tool) + result (pipeline/edit-form-pipeline file_path form_name form_type content :after nil tool) formatted-result (pipeline/format-result result)] formatted-result)) diff --git a/test/clojure_mcp/tools/form_edit/pipeline_test.clj b/test/clojure_mcp/tools/form_edit/pipeline_test.clj index 0ca6d16c..f04650d6 100644 --- a/test/clojure_mcp/tools/form_edit/pipeline_test.clj +++ b/test/clojure_mcp/tools/form_edit/pipeline_test.clj @@ -294,6 +294,7 @@ "defn" "(defn example-fn [x y]\n (* x y))" :replace + nil *nrepl-client-atom*) result (sut/format-result pipeline-result) file-content (slurp file-path)] @@ -316,6 +317,7 @@ "comment" "(comment some test comment)" :replace + nil *nrepl-client-atom*)] (is (true? (::sut/error pipeline-result))) (is (string? (::sut/message pipeline-result)))