aboutsummaryrefslogtreecommitdiff
path: root/gptel-tools
Commit message (Collapse)AuthorAgeFilesLines
* feat(gptel-tools): harden path validation with file-truename realpathCraig Jennings2026-05-169-36/+82
| | | | | | | | | | | | | | | | | | | | | | | | Resolves PATH through file-truename before applying home-directory and read/write checks across the path-handling tools (git_status, git_log, git_diff, move_to_trash, read_text_file, update_text_file, write_text_file, list_directory_files, read_buffer, web_fetch). Without the resolve step, a symlink under HOME pointing outside HOME would pass the prefix check but the tool would act on the real target -- a symlink-escape. move_to_trash also tightens the trash-bin construction (treats empty file extensions correctly) and switches the "critical directories" list to truename-resolved canonical forms so a symlinked ~/.config can't be trashed via an aliased path. update_text_file fixes an off-by-one in the line-count derivation when the source content is empty. Each source change pairs with tests in tests/test-gptel-tools-*.el and tests/test-update-text-file.el covering the realpath escape paths, the empty-extension trash case, and the empty-content line- count edge. Combined coverage is now 100% across all ten gptel-tools source files: 516 / 516 executable lines, 217 tests.
* feat(gptel-tools): wire web_fetch as a local toolCraig Jennings2026-05-161-0/+150
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Fourth ADOPT entry from `docs/design/gptel-tools-shortlist.org'. Lets gptel pull a URL into the conversation so the model can read docs / current API shapes / etc. without me copy-pasting. Shape: - URL must be `http://' or `https://' (file://, ftp://, javascript:, scheme-less, etc. are rejected at the validator). - HTML responses go through `pandoc -f html -t plain' so the model gets a reading shape that isn't full of markup; falls back to `w3m -dump -T text/html' if pandoc isn't on PATH; signals `user-error' if neither is. Pass `raw=t' to skip stripping. - Output capped at 200KB by default, hard cap 1MB; `max_bytes' argument lets the caller pick a lower cap. Truncation reported inline. - 4xx / 5xx response codes signal `error' with the code -- the alternative is returning an error page body, which the model would treat as content. `:confirm t' on the tool because every call is a real outbound network request. The tool's description warns that URLs go wherever the user-agent points, including internal networks if that's what the URL names. `tests/test-gptel-tools-web-fetch.el' -- 20 tests across Normal / Boundary / Error. URL validator covers http / https / non-string / empty / non-http schemes. `--effective-max-bytes' covers default / low-clamp / hard-cap / passthrough. Truncate helper covers under-cap / at-cap / over-cap with the marker. HTML stripper runs against real pandoc / w3m (both installed in dev env, neither should mangle simple markup). Orchestrator stubs `cj/gptel-web-fetch--retrieve' via `cl-letf' to cover normal / raw / 4xx / 5xx / oversize / bad-scheme paths. Wired into `cj/gptel-local-tool-features' so gptel exposes the tool on next restart. Note: `call-process-region' invocation flattened to a single `with-temp-buffer' with DELETE=t -- the initial draft nested a second temp buffer and routed output to the inner one, which got killed before `buffer-string' on the outer ran. Test caught it.
* feat(gptel-tools): wire git_status / git_log / git_diff as local toolsCraig Jennings2026-05-163-0/+277
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Three read-only git context tools so gptel can see what's changed without me pasting `git status` / `git log` / `git diff` output into every chat turn. Builds the first batch from the ADOPT bucket in `docs/design/gptel-tools-shortlist.org`. Shape per tool: - `gptel-tools/git_status.el` — `git status --short --branch` for a directory inside a git working tree under HOME. Returns the porcelain output, or a "Clean working tree" marker when only the branch line is present. - `gptel-tools/git_log.el` — `git log --oneline -nN` with an optional `--since` filter. N defaults to 20, capped at 100; nil / non- integer / out-of-range N falls back to the default. - `gptel-tools/git_diff.el` — `git diff [REF1 [REF2]] [-- FILE]`. Output capped at ~500KB so a runaway diff can't blow up context; truncation is reported inline. Validation is uniform: path must resolve under HOME, must be a directory, must be inside a git working tree (verified via `git rev-parse --is-inside-work-tree`). Color is disabled via `-c color.ui=false` at the git level (`git status` doesn't accept `--no-color` directly). Tests run against real temp git repos created via `process-file`, not mocked — there's nothing in gptel-tools/git_*.el that's process-mockable in a meaningful way, and a real `git init` + a couple of commits is cheaper than building a fake. 31 tests total: 7 for git_status, 11 for git_log, 13 for git_diff. Wired into `cj/gptel-local-tool-features` so gptel exposes the three tools on next restart.
* test(gptel-tools): cover the helpers across the five remaining toolsCraig Jennings2026-05-162-77/+81
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The gptel-tools files had zero direct coverage outside of `update_text_file`, which landed with its rewrite earlier this session. This commit adds 52 tests across the five other tools. For three of the tools the helpers were already top-level defuns (`read_text_file`, `list_directory_files`, `move_to_trash`). The other two had their main bodies inlined into the `gptel-make-tool` lambda -- I extracted them so the work is testable without mocking gptel itself: read_buffer.el -> `cj/read-buffer--get-content` write_text_file.el -> `cj/write-text-file--run` plus `--validate-path`, `--backup-name`, `--ensure-parent` Test files, by tool: - read_buffer.el (5 tests): normal, empty, buffer-object, text-property-stripping, missing buffer. - write_text_file.el (10 tests): validate-path, backup-name shape, ensure-parent (creates missing / rejects unwritable), run with normal / overwrite / existing-no-overwrite / empty content / outside-home. - read_text_file.el (12 tests): validate-file-path (normal + three error shapes), metadata plist shape, size limits (no-op / hard cap / warning bypass with no-confirm), binary detection (text vs null-byte), special-type EPUB and generic-binary paths. - list_directory_files.el (15 tests): mode-to-permissions (file / dir / executable), get-file-info (file / directory), extension filter (keep / drop / always-dir / nil-extension), format-file- entry, list-directory flat / recursive / error, format-output with and without files. - move_to_trash.el (10 tests): unique-name (no conflict / conflict with timestamp / no-extension), validate-path (HOME / /tmp / outside / critical-dir / missing), perform on file and directory. Each test file uses the same load-path / gptel-stub idiom (`eval-and-compile` block, gptel stub when the real package isn't available) so the byte-compile hook is happy.
* feat(gptel-tools): wire update_text_file as a local tool with testsCraig Jennings2026-05-161-124/+206
| | | | | | | | | | | | | | | | | | | | | I rewrote `update_text_file.el` in pure Elisp. The previous version shelled out to sed for everything, had a stray quote terminator at EOF (line 149) that broke loading, produced literal backslash-n where actual newlines were expected, and prompted via `y-or-n-p` redundantly with gptel's own `:confirm t` flag. The five operations -- replace, append, prepend, insert-at-line, delete-lines -- split into pure string transforms that test without touching the disk. The file-level wrapper validates the path, enforces a 10MB size limit, takes a timestamped backup, and writes atomically. No backup is created when the operation is a no-op. Patterns are literal substrings (not regex) so the model can't trip over metacharacter quoting. `tests/test-update-text-file.el` covers Normal / Boundary / Error per operation plus the file-level wrapper. 48 tests green. Added `update_text_file` to `cj/gptel-local-tool-features` so gptel exposes the tool after restart.
* perf: Merge performance branch - org-agenda cache, tests, and inbox zeroCraig Jennings2025-11-121-475/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This squash merge combines 4 commits from the performance branch: ## Performance Improvements - **org-agenda cache**: Cache org-agenda file list to reduce rebuild time - Eliminates redundant file system scans on each agenda view - Added tests for cache invalidation and updates - **org-refile cache**: Optimize org-refile target building (15-20s → instant) - Cache eliminates bottleneck when capturing tasks ## Test Suite Improvements - Fixed all 18 failing tests → 0 failures (107 test files passing) - Deleted 9 orphaned test files (filesystem lib, dwim-shell-security, org-gcal-mock) - Fixed missing dependencies (cj/custom-keymap, user-constants) - Fixed duplicate test definitions and wrong variable names - Adjusted benchmark timing thresholds for environment variance - Added comprehensive tests for org-agenda cache functionality ## Documentation & Organization - **todo.org recovery**: Restored 1,176 lines lost in truncation - Recovered Methods 4, 5, 6 + Resolved + Inbox sections - Removed 3 duplicate TODO entries - **Inbox zero**: Triaged 12 inbox items → 0 items - Completed: 3 tasks marked DONE (tests, transcription) - Relocated: 4 tasks to appropriate V2MOM Methods - Deleted: 4 duplicates/vague tasks - Merged: 1 task as subtask ## Files Changed - 58 files changed, 29,316 insertions(+), 2,104 deletions(-) - Tests: All 107 test files passing - Codebase: Cleaner, better organized, fully tested
* maint: gptel: fetch_page: needs major work so disabling for nowCraig Jennings2025-10-202-399/+475
|
* changing repositoriesCraig Jennings2025-10-127-0/+1155