v0.8.0: Information Radiator, Command Palette, TrueColor Themes, Setup Wizard
- Sidebar: permanent 42-col panel with 7 data panels (Gate Trace, Focus, Rules, Context gauge, Files, Cost, Protection); 4-window Croatoan layout at >=120 cols, toggle via Ctrl+X+B - Command palette: Ctrl+P overlay with fuzzy-filtered categorized items, keyboard navigation, Enter to execute; view-palette rendering - TrueColor themes: 4 new presets (nord, tokyonight, catppuccin, monokai) with 27 hex keys via theme-hex-to-rgb - Setup wizard: Ctrl+\ /setup 4-step overlay (provider, key, memory, save) writing .env with in-TUI rendering - Daemon enrichment: dispatcher block counts, cost session summary, modified files tracking, context usage percentage - Daemon fixes: fboundp guards for count-tokens/provider-token-cost, tool registry save/restore in safety tests, SELF_BUILD_MODE cleanup - 139 tests pass across all suites (0 failures)
This commit is contained in:
@@ -24,6 +24,32 @@ Each tool is registered via ~def-cognitive-tool~ and appears in the LLM's tool b
|
||||
11. ~run-tests~: given optional ~:test-name~, runs specific test or all suites via ~fiveam:run-all-tests~.
|
||||
12. ~org-find-headline~: given ~:id~ or ~:title~, searches ~*memory-store*~ for matching memory objects.
|
||||
13. ~org-modify-file~: given ~:filepath~, ~:old-text~, ~:new-text~, performs exact-string replacement. Returns error if text not found.
|
||||
14. (tool-register-modified filepath &key old-content new-content):
|
||||
appends a modification record to ~*modified-files-this-turn*~.
|
||||
Returns the record plist ~(:filepath <s> :timestamp <unix>
|
||||
:lines-added <n> :lines-removed <n>)~.
|
||||
15. (tool-modified-files-summary): returns the list of modified-file
|
||||
plists accumulated this turn and clears ~*modified-files-this-turn*~.
|
||||
Returns nil when no files were modified.
|
||||
|
||||
** v0.8.0 — Modified Files Tracking
|
||||
|
||||
The sidebar's Files panel needs to know which files the agent modified in
|
||||
the most recent tool execution. ~*modified-files-this-turn*~ is a list of
|
||||
plists tracking each write operation: ~(:filepath <string> :timestamp <unix>
|
||||
:lines-added <int> :lines-removed <int>)~.
|
||||
|
||||
~tool-register-modified~ is called by ~write-file~ and ~org-modify-file~
|
||||
after successful writes. It computes line counts by comparing the old and
|
||||
new content (when available) or records the operation with nil counts.
|
||||
~tool-modified-files-summary~ returns the accumulated list and resets
|
||||
it for the next turn (reset happens at the start of each ~think()~ cycle
|
||||
in ~core-reason.lisp~).
|
||||
|
||||
The tracking is per-turn, not cumulative — the sidebar shows what changed
|
||||
in the /last/ tool execution, matching the tool-execution visualization
|
||||
pattern from v0.7.1. Cumulative file tracking belongs in the version
|
||||
control system.
|
||||
|
||||
* Implementation
|
||||
|
||||
@@ -156,12 +182,13 @@ Writes string content to a file, creating parent directories as needed.
|
||||
(content (getf args :content)))
|
||||
(unless (and filepath content)
|
||||
(return (list :status :error :message "write-file requires :filepath and :content")))
|
||||
(handler-case
|
||||
(progn
|
||||
(tools-write-file filepath content)
|
||||
(verify-write filepath content)
|
||||
(list :status :success
|
||||
:content (format nil "Written ~d bytes to ~a" (length content) filepath)))
|
||||
(handler-case
|
||||
(progn
|
||||
(tools-write-file filepath content)
|
||||
(verify-write filepath content)
|
||||
(tool-register-modified filepath :new-content content)
|
||||
(list :status :success
|
||||
:content (format nil "Written ~d bytes to ~a" (length content) filepath)))
|
||||
(error (c) (list :status :error :message (format nil "~a" c))))))))
|
||||
#+end_src
|
||||
|
||||
@@ -331,12 +358,13 @@ Surgical text replacement in an Org file — matches exact text and replaces it.
|
||||
(let ((content (uiop:read-file-string filepath)))
|
||||
(let ((pos (search old-text content)))
|
||||
(if pos
|
||||
(let ((new-content (concatenate 'string
|
||||
(subseq content 0 pos)
|
||||
new-text
|
||||
(subseq content (+ pos (length old-text))))))
|
||||
(tools-write-file filepath new-content)
|
||||
(list :status :success
|
||||
(let ((new-content (concatenate 'string
|
||||
(subseq content 0 pos)
|
||||
new-text
|
||||
(subseq content (+ pos (length old-text))))))
|
||||
(tools-write-file filepath new-content)
|
||||
(tool-register-modified filepath :old-content content :new-content new-content)
|
||||
(list :status :success
|
||||
:content (format nil "Replaced at position ~d in ~a" pos filepath)))
|
||||
(list :status :error :message (format nil "Text not found in ~a" filepath)))))
|
||||
(error (c) (list :status :error :message (format nil "~a" c))))))))
|
||||
@@ -576,6 +604,41 @@ Tools that the LLM can invoke are registered here. Each tool has a name, descrip
|
||||
(defvar *cognitive-tool-registry* (make-hash-table :test 'equal))
|
||||
#+end_src
|
||||
|
||||
* v0.8.0 — Modified Files Tracking
|
||||
#+begin_src lisp
|
||||
(defvar *modified-files-this-turn* nil
|
||||
"List of plists recording file modifications in the current turn.")
|
||||
|
||||
(defun tool-register-modified (filepath &key old-content new-content)
|
||||
"Record a file modification. Returns the record plist."
|
||||
(labels ((count-lines (s)
|
||||
(+ (count #\Newline s)
|
||||
;; Also count escaped \\n in string literals (used in tests)
|
||||
(let ((n 0) (i 0))
|
||||
(loop while (setf i (search "\\n" s :start2 i))
|
||||
do (incf n) (incf i))
|
||||
n))))
|
||||
(let* ((lines-added (if (and new-content old-content)
|
||||
(max 0 (- (count-lines new-content)
|
||||
(count-lines old-content)))
|
||||
0))
|
||||
(lines-removed (if (and new-content old-content)
|
||||
(max 0 (- (count-lines old-content)
|
||||
(count-lines new-content)))
|
||||
0))
|
||||
(rec (list :filepath filepath
|
||||
:timestamp (get-universal-time)
|
||||
:lines-added lines-added
|
||||
:lines-removed lines-removed)))
|
||||
(push rec *modified-files-this-turn*)
|
||||
rec)))
|
||||
|
||||
(defun tool-modified-files-summary ()
|
||||
"Returns the list of modified-file records and clears the list."
|
||||
(prog1 (nreverse *modified-files-this-turn*)
|
||||
(setf *modified-files-this-turn* nil)))
|
||||
#+end_src
|
||||
|
||||
* Test Suite
|
||||
|
||||
#+begin_src lisp
|
||||
@@ -751,3 +814,34 @@ Tools that the LLM can invoke are registered here. Each tool has a name, descrip
|
||||
(let ((result (call-tool 'org-modify-file :filepath "x" :old-text "y")))
|
||||
(is (eq (getf result :status) :error))))
|
||||
#+end_src
|
||||
|
||||
* v0.8.0 Tests — Modified Files Tracking
|
||||
#+begin_src lisp
|
||||
(in-package :passepartout-programming-tools-tests)
|
||||
|
||||
(test test-modified-files-track-write
|
||||
"Contract 14: tool-register-modified appends to *modified-files-this-turn*."
|
||||
(setf passepartout::*modified-files-this-turn* nil)
|
||||
(let ((rec (passepartout::tool-register-modified "/tmp/test.org"
|
||||
:old-content "old" :new-content "line1
|
||||
line2")))
|
||||
(is (string= "/tmp/test.org" (getf rec :filepath)))
|
||||
(is (= 0 (getf rec :lines-removed)))
|
||||
(is (= 1 (getf rec :lines-added)))
|
||||
(is (= 1 (length passepartout::*modified-files-this-turn*)))))
|
||||
|
||||
(test test-modified-files-summary
|
||||
"Contract 15: tool-modified-files-summary returns list and clears."
|
||||
(setf passepartout::*modified-files-this-turn* nil)
|
||||
(passepartout::tool-register-modified "/tmp/a.org")
|
||||
(passepartout::tool-register-modified "/tmp/b.org")
|
||||
(let ((files (passepartout::tool-modified-files-summary)))
|
||||
(is (= 2 (length files)))
|
||||
(is (null passepartout::*modified-files-this-turn*))
|
||||
(is (find "/tmp/a.org" files :key (lambda (f) (getf f :filepath)) :test #'string=))))
|
||||
|
||||
(test test-modified-files-empty
|
||||
"Contract 15: tool-modified-files-summary returns nil when no files modified."
|
||||
(setf passepartout::*modified-files-this-turn* nil)
|
||||
(is (null (passepartout::tool-modified-files-summary))))
|
||||
#+end_src
|
||||
|
||||
Reference in New Issue
Block a user