Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: corteza
Title: AI Agent Runtime
Version: 0.6.6.1
Version: 0.6.6.2
Authors@R: c(
person("Troy", "Hernandez", role = c("aut", "cre"),
email = "troy@cornball.ai",
Expand Down
27 changes: 27 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
# corteza 0.6.6.2

## Inline diffs on file edits

* `replace_in_file` and `write_file` now attach a unified-diff payload
to their MCP result. The CLI and `corteza::chat()` render it inline
in the tool-call output as `⎿ Added N, removed M` followed by one
row per kept line (`NNNN +|-| content` with red/green color) instead
of the prior `N lines in Xms` summary. The LLM-facing result text is
unchanged — the diff is for the human reading the terminal.
* Tool labels renamed for clarity: `replace_in_file` → "Update",
`write_file` → "Write" (matches the inline-diff phrasing).
* Diff generation shells out to the system `diff -u`. If `diff` isn't
on `PATH` the tool degrades to a one-line size summary rather than
failing. Diff payload is capped at 200 lines / 20000 chars with a
`[diff truncated: N more lines]` marker so big writes don't dump
thousands of lines into chat scrollback.
* The `/diff` slash command's output is also ANSI-colored.

## Console color policy is shared

* `ansi_supported()` / `ansi_colors()` in the package are now the
single source of truth for both `corteza::chat()` and the
`~/bin/corteza` CLI. RStudio's R console (which is not a tty) is now
correctly detected as ANSI-capable, and `NO_COLOR` / `FORCE_COLOR`
overrides work in both surfaces.

# corteza 0.6.6.1

## Interrupt key
Expand Down
58 changes: 58 additions & 0 deletions R/cli-colors.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@
#' @return Single logical.
#' @noRd
ansi_supported <- function() {
# NO_COLOR / FORCE_COLOR are the conventional overrides; they win
# over auto-detection so users can force either side. RStudio's R
# console pane is not a tty (isatty(stdout()) is FALSE) but it
# does render ANSI escape sequences — without the RSTUDIO check,
# corteza::chat() would emit plain text in RStudio while the
# terminal CLI gets colored output.
if (nzchar(Sys.getenv("NO_COLOR"))) {
return(FALSE)
}
if (nzchar(Sys.getenv("FORCE_COLOR"))) {
return(TRUE)
}
if (identical(Sys.getenv("RSTUDIO"), "1")) {
return(TRUE)
}
if (.Platform$OS.type == "windows") {
return(any(nzchar(Sys.getenv(c("WT_SESSION", "ConEmuANSI",
"TERM_PROGRAM")))))
Expand Down Expand Up @@ -46,3 +61,46 @@ ansi_colors <- function() {
bright_magenta = "\033[95m", bright_cyan = "\033[96m")
}

#' Colorize a unified-diff string for terminal display.
#'
#' Matches `git diff` / `git --color=always`'s palette: green additions,
#' red deletions, cyan hunk headers, bold file headers, dim metadata
#' lines. The `+++ ` / `--- ` file-header check has to run before the
#' bare `+` / `-` check or the file-header lines would be colored as
#' add/delete rows.
#'
#' Returns `text` unchanged when the terminal doesn't support ANSI.
#' @param text Character scalar, raw diff output.
#' @param palette Optional palette from \code{ansi_colors()}; tests pass
#' a forced palette to assert escape sequences are emitted.
#' @return Character scalar with ANSI escapes interleaved.
#' @noRd
colorize_diff <- function(text, palette = ansi_colors()) {
if (!is.character(text) || length(text) != 1L || !nzchar(text)) {
return(text)
}
if (!nzchar(palette$reset)) {
return(text)
}
lines <- strsplit(text, "\n", fixed = TRUE)[[1]]
paint <- function(ln) {
if (startsWith(ln, "diff --git ") || startsWith(ln, "index ") ||
startsWith(ln, "similarity ") || startsWith(ln, "rename ") ||
startsWith(ln, "new file") || startsWith(ln, "deleted file")) {
paste0(palette$dim, ln, palette$reset)
} else if (startsWith(ln, "+++ ") || startsWith(ln, "--- ")) {
paste0(palette$bold, ln, palette$reset)
} else if (startsWith(ln, "@@")) {
paste0(palette$cyan, ln, palette$reset)
} else if (startsWith(ln, "+")) {
paste0(palette$green, ln, palette$reset)
} else if (startsWith(ln, "-")) {
paste0(palette$red, ln, palette$reset)
} else {
ln
}
}
paste(vapply(lines, paint, character(1L), USE.NAMES = FALSE),
collapse = "\n")
}

8 changes: 4 additions & 4 deletions R/cli-ui.R
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ cli_tool_label <- function(tool_name, long = FALSE) {
run_r_script = "Run R Script",
read_file = "Read File",
"base::readLines" = "Read File",
write_file = "Write File",
"base::writeLines" = "Write File",
replace_in_file = "Replace in File",
write_file = "Write",
"base::writeLines" = "Write",
replace_in_file = "Update",
list_files = "List Files",
"base::list.files" = "List Files",
grep_files = "Grep Files",
Expand All @@ -144,7 +144,7 @@ cli_tool_label <- function(tool_name, long = FALSE) {
run_r = "Run R code", run_r_script = "Run R script",
read_file = "Read file", "base::readLines" = "Read file",
write_file = "Write file", "base::writeLines" = "Write file",
replace_in_file = "Replace in file", list_files = "List files",
replace_in_file = "Update file", list_files = "List files",
"base::list.files" = "List files", grep_files = "Search files",
web_search = "Web search", fetch_url = "Fetch URL",
git_status = "Git status", git_diff = "Git diff",
Expand Down
Loading