### Complete UDIFFX File Changes Example Source: https://github.com/zcoder-run/rust-udiffx/blob/main/src/prompt/prompt-file-changes.md A comprehensive example demonstrating the use of FILE_NEW, FILE_PATCH, FILE_APPEND, FILE_COPY, FILE_RENAME, and FILE_DELETE directives within a UDIFFX_FILE_CHANGES block. ```text [[[UDIFFX_FILE_CHANGES]]] [[[FILE_NEW file_path="src/hello.rs"]]] pub fn hello() { println!("Hello from hello.rs"); } [[[/FILE_NEW]]] [[[FILE_PATCH file_path="src/main.rs"]]] @@ +mod hello; fn main() { - println!("Old message"); + hello::hello(); } @@ fn helper() { -old_logic(); +new_logic(); } [[[/FILE_PATCH]]] <<<--- IMPORTANT: Always end FILE_PATCH with this end backet tag [[[FILE_APPEND file_path="CHANGELOG.md"]]] ## Added - Hello module [[[/FILE_APPEND]]] [[[FILE_COPY from_path="docs/OLD_README.md" to_path="docs/README.backup.md" /]]] [[[FILE_RENAME from_path="docs/OLD_README.md" to_path="README.md" /]]] [[[FILE_DELETE file_path="temp_notes.txt" /]]] [[[/UDIFFX_FILE_CHANGES]]] ``` -------------------------------- ### Initialize Database Connection Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-14-removal-suffix/original.txt Initializes a database connection pool and executes setup queries using the provided configuration. ```rust pub fn initialize_database_connection(config: &DatabaseConfig) -> Result[[[Connection]]] { let pool = create_connection_pool(config)?; let conn = pool.get_connection()?; conn.execute_setup_queries()?; Ok(conn) } ``` -------------------------------- ### LLM File Changes Envelope Example Source: https://github.com/zcoder-run/rust-udiffx/blob/main/README.md An example of the text format returned by an LLM containing multiple file operations wrapped in a FILE_CHANGES tag. ```txt I fix the issue you reported. [[[UDIFFX_FILE_CHANGES]]] [[[FILE_NEW file_path="src/hello.rs"> pub fn hello() { println!("Hello from udiffx"); } [[[/FILE_NEW]]] [[[FILE_APPEND file_path="changelog.md"] ## Next - Add a hello module. [[[/FILE_APPEND]]] @@ +mod hello; fn main() { - println!("Hello"); + hello::hello(); } [[[/FILE_PATCH]]] [[[FILE_COPY from_path="docs/template.md" to_path="docs/getting-started.md" /]]] [[[FILE_RENAME from_path="src/old-name.rs" to_path="src/legacy-name.rs" /]]] [[[FILE_DELETE file_path="tmp/generated.txt" /]]] ``` -------------------------------- ### FILE_PATCH Large Removal Example Source: https://github.com/zcoder-run/rust-udiffx/blob/main/src/prompt/prompt-file-changes.md Demonstrates the use of the ~ character to compress large consecutive removals of more than 6 lines. ```text [[[FILE_PATCH file_path="path/to/file"]]] @@ -first removed line -second removed line ~ -second-to-last removed line -last removed line +replacement [[[/FILE_PATCH]]] ``` -------------------------------- ### Correct Large Removal Example Source: https://github.com/zcoder-run/rust-udiffx/blob/main/src/prompt/prompt-file-changes.md The correct way to handle large removals using the ~ character. ```text -old line 1 -old line 2 ~ -old line 8 -old line 9 +replacement ``` -------------------------------- ### Handle Mouse Drag Initialization Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-18-out-of-order/original.txt Initializes drag state variables when a mouse event occurs, capturing the starting world position and plane configurations. ```cpp m_dragButton = mouseEvent->button(); m_dragStartWorld = hitOnTogo; m_prevHitWorld = hitOnTogo; m_dragStartRedPlane = m_redPlane; m_dragStartGreenPlane = m_greenPlane; m_useFirstHitpointForDrag = true; // Capture stable line direction and original plane normal at drag start // to prevent sign oscillation from line recomputation during drag. ``` -------------------------------- ### Incorrect Large Removal Example Source: https://github.com/zcoder-run/rust-udiffx/blob/main/src/prompt/prompt-file-changes.md An example of an incorrect large removal that does not use the ~ character. ```text -old line 1 -old line 2 -old line 3 -old line 4 -old line 5 -old line 6 -old line 7 -old line 8 -old line 9 +replacement ``` -------------------------------- ### prompt Source: https://github.com/zcoder-run/rust-udiffx/blob/main/docs/for-llm/api-reference-for-llm.md Retrieves the recommended system instructions for an LLM to generate valid file change directives. ```APIDOC ## prompt ### Description Returns the recommended system instructions for an LLM to generate the `FILE_CHANGES` block format required by the library. ### Signature `pub fn prompt() -> &'static str` ### Returns - **&'static str** - The system prompt string. ``` -------------------------------- ### Create src/hello.rs Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/changes-simple.md Initial creation of the hello.rs module file. ```rust pub fn hello() { println!("Hello from hello.rs"); } ``` -------------------------------- ### Create src/main.rs Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/changes-simple.md Initial creation of the main.rs file with a basic print statement. ```rust fn main() { println!("Old Message"); } ``` -------------------------------- ### Update database connection initialization in original.txt Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-14-removal-suffix/changes.txt Replaces synchronous connection pool creation and connection retrieval with asynchronous equivalents. ```rust @@ initialize_database_connection(config: &DatabaseConfig) -> Result[[[Connection]]] { - let pool = create_connection_pool(config)?; - let conn = pool.get_connection()?; + let pool = create_async_connection_pool(config).await?; + let conn = pool.get_async_connection().await?; conn.execute_setup_queries()?; ``` -------------------------------- ### FILE_PATCH Directive Source: https://github.com/zcoder-run/rust-udiffx/blob/main/src/prompt/prompt-file-changes.md Use this directive to modify existing file content. It supports multiple hunks starting with @@ and requires the specific closing tag. ```text [[[FILE_PATCH file_path="path/to/file"]]] @@ -old content +new content @@ context line -old value +new value [[[/FILE_PATCH]]] ``` -------------------------------- ### Create src/hello.rs Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/changes-patch-mixed-actionable.md Defines a new hello function in the src/hello.rs file. ```rust pub fn hello() { println!("Hello"); } ``` -------------------------------- ### Applying File Changes in Rust Source: https://github.com/zcoder-run/rust-udiffx/blob/main/README.md Demonstrates how to extract file changes from an AI response string and apply them to a project directory using the udiffx crate. ```rust use simple_fs::SPath; use udiffx::{apply_file_changes, extract_file_changes, Result}; fn main() -> Result<()> { let ai_response = "..."; // the string above let base_dir = SPath::new("./my-project"); let (changes, _) = extract_file_changes(ai_response, false)?; let status = apply_file_changes(&base_dir, changes)?; for item in status.items { if item.success() { println!("OK {} {}", item.kind(), item.file_path()); } else { eprintln!( "FAIL {} {}: {}", item.kind(), item.file_path(), item.error_msg().unwrap_or("unknown") ); } } Ok(()) } ``` -------------------------------- ### FILE_NEW Directive Source: https://github.com/zcoder-run/rust-udiffx/blob/main/src/prompt/prompt-file-changes.md Use this directive to create a new file. Include the complete file content within the tags. ```text [[[FILE_NEW file_path="path/to/file"]]] _complete file content_ [[[/FILE_NEW]]] ``` -------------------------------- ### Update Formatting and UI Getters Documentation Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-08-missmatch/changes.txt Updates the documentation for formatting and UI getters to include new model state helpers. ```markdown -### formatting & UI Getters (impl_fmt.rs) +### Formatting & UI Getters (impl_fmt.rs & impl_model_state.rs) - `current_run_duration_txt()`, `current_run_cost_fmt()`. ``` ```markdown - `current_task_model_name()`, `current_task_cost_fmt()`, `current_task_duration_txt()`. - `current_task_prompt_tokens_fmt()`, `current_task_completion_tokens_fmt()`. - `current_task_cache_info_fmt()`. + +### Model State Helpers +- `current_run_has_prompt_parts()`, `current_run_has_task_stages()`, `current_run_has_skip()`. ``` -------------------------------- ### Pin Knowledge and Reasoning Information Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-10/original.txt Pins knowledge files, reasoning, and helper files to the run and task interfaces if the respective conditions are met. ```lua -- === Pin Knowledge Files if knowledge_done and auto_context_config.knowledge and new_knowledge_files then msg = "" for _, file in ipairs(new_knowledge_files) do msg = msg .. " - " .. file.path .. "\n" end msg = aip.text.trim_end(msg) local kfiles_pin = { label = LABEL_KFILES, content = msg } aip.run.pin("kfiles", 3, kfiles_pin) aip.task.pin("kfiles", 3, kfiles_pin) end -- === Pin Reason if ctx.reason then local reason_pin = { label = LABEL_REASON, content = aip.text.trim(ctx.reason) } aip.run.pin("reason", 5, reason_pin) aip.task.pin("reason", 5, reason_pin) end -- === Pin Knowledge Reason if ctx.knowledge_reason then local kreason_pin = { label = LABEL_KREASON, content = aip.text.trim(ctx.knowledge_reason) } aip.run.pin("kreason", 6, kreason_pin) aip.task.pin("kreason", 6, kreason_pin) end -- === Helper helper_files if ctx.helper_files then local content = "" for _, file in ipairs(ctx.helper_files) do content = content .. "- " .. file.path .. "\n" end content = aip.text.trim_end(content) -- poor man local helpers_pin = { label = LABEL_HFILES, content = content } aip.run.pin("helpers", 4, helpers_pin) aip.task.pin("helpers", 4, helpers_pin) end end ``` -------------------------------- ### Module Export Configuration Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-10/original.txt Exports the configuration and pinning functions for use in other modules. ```lua return { extract_auto_context_config = extract_auto_context_config, pin_status = pin_status, } ``` -------------------------------- ### Patch src/main.rs Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/changes-simple.md Updates main.rs to include the hello module and call the hello function. ```diff @@ -1,3 +1,5 @@ +mod hello; + fn main() { - println!("Old Message"); + hello::hello(); } ``` -------------------------------- ### Pin Status and File Contexts Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-10/original.txt Constructs a status message including context and knowledge file counts, then pins the status and file lists to the run and task interfaces. ```lua msg = msg .. string.format("%-30s", label .. " " .. ctx.context_files_count .. " context files") msg = msg .. " (" .. context_files_size_fmt .. ")" if ctx.new_context_globs then msg = msg .. '\n' .. " ➜" msg = msg .. string.format("%-30s", " Now " .. #new_context_files .. " context files") local new_context_files_size_fmt = aip.text.format_size(new_context_files_size) msg = msg .. " (" .. new_context_files_size_fmt .. ")" end -- Knowledge status line if auto_context_config.knowledge then local knowledge_files_size_fmt = aip.text.format_size(ctx.knowledge_files_size or 0) local k_status = knowledge_done and "✅" or ".." msg = msg .. '\n' .. k_status msg = msg .. string.format("%-30s", " Reducing " .. (ctx.knowledge_files_count or 0) .. " knowledge files") msg = msg .. " (" .. knowledge_files_size_fmt .. ")" if ctx.new_knowledge_globs then msg = msg .. '\n' .. " ➜" msg = msg .. string.format("%-30s", " Now " .. #new_knowledge_files .. " knowledge files") local new_knowledge_files_size_fmt = aip.text.format_size(new_knowledge_files_size) msg = msg .. " (" .. new_knowledge_files_size_fmt .. ")" end end -- Pins for status local status_pin = { label = LABEL_STATUS, content = msg } aip.run.pin("status", 1, status_pin) aip.task.pin("status", 1, status_pin) -- === Pin Context Files if done then msg = "" if new_context_files and #new_context_files > 0 then for _, file in ipairs(new_context_files) do msg = msg .. " - " .. file.path .. "\n" end msg = aip.text.trim_end(msg) -- poor man else msg = "(no context files)" end -- files it in both local files_pin = { label = LABEL_CFILES, content = msg } aip.run.pin("files", 2, files_pin) aip.task.pin("files", 2, files_pin) end ``` -------------------------------- ### Update Lifecycle and State Processing Documentation Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-08-missmatch/changes.txt Updates the documentation section for lifecycle and state processing. ```markdown -### Lifecycle & Timeouts +### Lifecycle & State Processing Time-based state transitions and expirations are primarily managed in `src/tui/core/app_state/state_processor.rs`. ``` -------------------------------- ### Patch for original.txt Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-03-no-matching-empty-line/changes.txt This patch adds the lazy_regex dependency and integrates the init_profiles_if_missing function into the toggle_profile logic. ```rs @@ use crate::support::jsons; use crate::{Error, Result}; +use lazy_regex::regex; use serde::{Deserialize, Serialize}; @@ pub fn toggle_profile() -> Result<()> { let home = home::home_dir().ok_or("Could not find home directory")?; + // -- Init if missing + init_profiles_if_missing()?; + let config_dir = SPath::from_std_path(&home)?.join(".config/jc-zed-tasks"); @@ println!("Switched to profile: {next_profile_name}"); touch_tasks_json()?; Ok(()) } + +// region: --- Support + ``` -------------------------------- ### ensure_dir Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-06-no-match/original.txt Ensures that all directory paths are created. ```APIDOC ## ensure_dir(dir_path) ### Description Creates the directory structure for the given path. ``` -------------------------------- ### Patch src/main.rs Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/changes-no-head-nums.md Applying a patch to src/main.rs to include the hello module and update the main function. ```diff @@ +mod hello; + fn main() { - println!("Old Message"); + hello::hello(); } ``` -------------------------------- ### Update README.md file iteration API signatures Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-06-no-match/changes.txt This patch updates the documentation for iter_files and list_files to return SPath types instead of SFile, and clarifies that SPath provides the path functions. ```md @@ - DDIt does not have any `\\?\` on Windows. -The SFile is a File struct that contains an SPath. - -By applying the above rules, path/file APIs can be drastically simplified, and both structs offer many Path functions, with &str as the return type. +By applying the above rules, path/file APIs can be drastically simplified, and `SPath` offers many Path functions, with `&str` as the return type. This crate also offers a simple and scalable way to list or iterate on files, given a glob: -- `iter_files(dir, include_globs: Option<&[&str]>, list_options: Option[[[ListOptions]]]) -> Result[[[impl Iter SFile]]]` -- `list_files(dir, include_globs: Option<&[&str]>, list_options: Option[[[ListOptions]]]) -> Result` +- `iter_files(dir, include_globs: Option<&[&str]>, list_options: Option[[[ListOptions]]]) -> Result[[[impl Iter SPath]]]` +- `list_files(dir, include_globs: Option<&[&str]>, list_options: Option[[[ListOptions]]]) -> Result` - `ensure_dir(dir_path)` makes sure all the directory paths are created. ``` -------------------------------- ### load_files_context Source: https://github.com/zcoder-run/rust-udiffx/blob/main/docs/for-llm/api-reference-for-llm.md Resolves globs relative to a base directory, reads matching files, and formats them into blocks. ```APIDOC ## load_files_context ### Signature `pub fn load_files_context(base_dir: impl Into, globs: &[&str]) -> Result>` ### Description Resolves globs relative to `base_dir`, reads matching files, and formats them into `...` blocks. Files are sorted by path for deterministic output. ### Returns - `Ok(Some(String))` if files were found - `Ok(None)` if no files matched ``` -------------------------------- ### Profiles Configuration Data Structures Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-03-no-matching-empty-line/original.txt Defines the Rust structs used to deserialize profile configurations and current profile state from JSON files. ```rust #[derive(Deserialize)] struct ProfilesConfig { order: Vec[[[String]]], #[serde(flatten)] profiles: HashMap, } #[derive(Deserialize)] struct Profile { zed_config: Vec[[[ZedConfigEntry]]], } #[derive(Deserialize)] struct ZedConfigEntry { config_path: Vec[[[String]]], value: serde_json::Value, } #[derive(Deserialize, Serialize)] struct CurrentProfile { current_profile: String, } ``` -------------------------------- ### list_files Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-06-no-match/original.txt Lists files in a directory matching optional glob patterns. ```APIDOC ## list_files(dir, include_globs, list_options) ### Description Returns a vector of SFile objects found in the directory matching the provided glob patterns. ### Signature `list_files(dir, include_globs: Option<&[&str]>, list_options: Option) -> Result>` ``` -------------------------------- ### Update LinkZone Functionality Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-08-missmatch/changes.txt Adds new methods to the LinkZone documentation for handling multi-line section-wide hover. ```markdown ### LinkZones (src/tui/core/types/link_zone.rs) Used to handle hover/click on specific text regions. +- `start_group() -> u32`: For multi-line section-wide hover. +- `push_group_zone(...)`: Registers a zone belonging to a group. - `is_mouse_over(area, scroll, mouse_evt, spans) -> Option<&mut [Span]>`. ``` -------------------------------- ### Define AppStage and RunTab Enums Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-08-missmatch/original.txt Defines the application lifecycle stages and navigation tabs for the TUI. ```rust pub enum AppStage { Normal, // Main run view Installing, // Dialog-style installation progress overlay Installed, // Success dialog overlay (auto-dismisses after 4s) } pub enum RunTab { Overview, Tasks } ``` -------------------------------- ### Configure TogoLineManipulator Properties Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-18-out-of-order/original.txt A collection of setter methods for configuring the manipulator's intersection lines, planes, modes, apex, callbacks, and hit thresholds. ```cpp void TogoLineManipulator::setIntersectionLines(GlTogoIntersectionLines* lines) { m_lines = lines; } void TogoLineManipulator::setTogoPlane(const vec3& center, const vec3& normal) { m_TogoCenter = center; m_TogoNormal = normal.normalized(); } void TogoLineManipulator::setPlaneMatrices(const mat4& redPlane, const mat4& greenPlane) { m_redPlane = redPlane; m_greenPlane = greenPlane; } void TogoLineManipulator::setMode(ManipulationMode mode) { m_mode = mode; } void TogoLineManipulator::setApex(const vec3& apex) { m_apex = apex; } void TogoLineManipulator::setPlaneChangedCallback(PlaneChangedCallback cb) { m_callback = std::move(cb); } void TogoLineManipulator::setBothPlanesChangedCallback(BothPlanesChangedCallback cb) { m_bothPlanesCallback = std::move(cb); } void TogoLineManipulator::setHitThreshold(double pixels) { m_hitThreshold = pixels; } void TogoLineManipulator::setWorldHitThreshold(double mm) { m_worldHitThreshold = mm; } ``` -------------------------------- ### Access session and cancellation channels Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-21-silent-noop-hunk/original.txt Methods to retrieve the current session and the optional cancellation transaction channels. ```rust pub fn session(&self) -> &Session { self.inner.session() } pub fn cancel_tx(&self) -> Option<&CancelTx> { self.inner.cancel_trx.as_ref().map(|trx| trx.tx()) } pub fn cancel_rx(&self) -> Option<&CancelRx> { self.inner.cancel_trx.as_ref().map(|trx| trx.rx()) } ``` -------------------------------- ### Implement process_app_state function Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-00-tmp/original.txt Updates the application core time using the current microsecond timestamp during a tick process. ```rust pub fn process_app_state(state: &mut AppState) { // -- Process tick state.core.time = now_micro(); ``` -------------------------------- ### Hunk Header Source: https://github.com/zcoder-run/rust-udiffx/blob/main/src/prompt/prompt-file-changes.md Every hunk within a FILE_PATCH must begin with this header. ```text @@ ``` -------------------------------- ### Dev Chat Implementation Plan for Patch Completer Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-04-no-end-line/changes.txt This markdown block outlines the plan to modify compute_hunk_bounds in src/patch_completer.rs to improve error reporting by formatting failed context matches. ```md @@ # Dev Chat For each user request, add a new `## Request: _user_ask_title_concise_` with the answer below (concise title). Preserve this instruction as is. + +## Request: Improve Patch Completer Error Message + +The instruction is clear. The requirement is to enhance the error reporting in `patch_completer.rs` when context matching fails. Instead of a generic message, the error will now list the specific lines it was searching for, stripped of their unified diff prefixes (space or `-`), and separated by `----`. + +### Implementation Plan + +- Modify `compute_hunk_bounds` in `src/patch_completer.rs`. +- When `found_idx` is `None` (match failed): + - Collect all lines from `hunk_lines` that do not start with `+`. + - For each collected line, remove the first character (the diff marker). + - Join these cleaned lines using `\n----\n` as the separator. + - Pass this formatted string into `Error::patch_completion`. + +This will allow developers to quickly copy segments of the failing patch and search for them in the target file to identify why the match failed (e.g., drift, whitespace issues, or incorrect context). ``` -------------------------------- ### Access file write manager Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-21-silent-noop-hunk/original.txt Method to retrieve the file write manager instance. ```rust pub fn file_write_manager(&self) -> &FileWriteManager { self.inner.file_write_manager() } ``` -------------------------------- ### Patch for src/main.rs Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/changes-patch-unactionable-only.md This patch updates the exports in src/main.rs to include applier, apply_changes_status, and error modules. ```diff @@ pub use applier::apply_file_changes; pub use apply_changes_status::*; pub use error::*; ``` -------------------------------- ### UDIFFX_FILE_CHANGES block structure Source: https://github.com/zcoder-run/rust-udiffx/blob/main/src/prompt/prompt-file-changes.md The required syntax for the UDIFFX_FILE_CHANGES block. All file directives must be placed between the opening and closing tags. ```text [[[UDIFFX_FILE_CHANGES]]] _file directives_ [[[/UDIFFX_FILE_CHANGES]]] ``` -------------------------------- ### Define AppEvent and AppActionEvent Enums Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-08-missmatch/original.txt Defines the system events and action events used for communication within the TUI loop. ```rust pub enum AppEvent { DoRedraw, Term(crossterm::event::Event), Action(AppActionEvent), Hub(HubEvent), Tick(i64), } pub enum AppActionEvent { Quit, Redo, CancelRun, Scroll(ScrollDir), ScrollPage(ScrollDir), ScrollToEnd(ScrollDir), } ``` -------------------------------- ### toggle_profile Function Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-03-no-matching-empty-line/original.txt Switches the current Zed profile by updating settings.json and saving the new profile state. It validates the existence of configuration files before applying changes. ```rust pub fn toggle_profile() -> Result<()> { let home = home::home_dir().ok_or("Could not find home directory")?; let config_dir = SPath::from_std_path(&home)?.join(".config/jc-zed-tasks"); let profiles_path = config_dir.join("profiles.json"); let current_path = config_dir.join("profile-current.json"); let settings_path = SPath::from_std_path(&home)?.join(".config/zed/settings.json"); if !profiles_path.exists() { return Err(Error::custom(format!("Profiles config not found at: {profiles_path}"))); } if !settings_path.exists() { return Err(Error::custom(format!("Zed settings file not found at: {settings_path}"))); } // -- Load configs let profiles_content = simple_fs::read_to_string(&profiles_path)?; let profiles_config: ProfilesConfig = serde_json::from_str(&profiles_content)?; if profiles_config.order.is_empty() { return Err(Error::custom("No profiles defined in 'order' array in profiles.json")); } let current_profile_name = if current_path.exists() { let current_content = simple_fs::read_to_string(¤t_path)?; let current_config: CurrentProfile = serde_json::from_str(¤t_content)?; current_config.current_profile } else { profiles_config.order[0].clone() }; // -- Determine next profile let current_idx = profiles_config.order.iter().position(|p| p == ¤t_profile_name); let next_idx = match current_idx { Some(idx) => (idx + 1) % profiles_config.order.len(), None => 0, }; let next_profile_name = &profiles_config.order[next_idx]; let next_profile = profiles_config .profiles .get(next_profile_name) .ok_or_else(|| Error::custom(format!("Profile '{next_profile_name}' not found in profiles.json")))?; // -- Update settings.json let mut settings_content = simple_fs::read_to_string(&settings_path)?; for entry in &next_profile.zed_config { let path_refs: Vec<&str> = entry.config_path.iter().map(|s| s.as_str()).collect(); settings_content = jsons::update_json_value_text_mode(&settings_content, &path_refs, &entry.value)?; } // -- Save changes fs::write(settings_path.std_path(), settings_content)?; let new_current = CurrentProfile { current_profile: next_profile_name.clone() }; fs::write(current_path.std_path(), serde_json::to_string_pretty(&new_current)?)?; println!("Switched to profile: {next_profile_name}"); touch_tasks_json()?; Ok(()) } ``` -------------------------------- ### apply_file_changes Source: https://github.com/zcoder-run/rust-udiffx/blob/main/docs/for-llm/api-reference-for-llm.md Applies a set of file changes to the file system relative to a base directory, enforcing security policies. ```APIDOC ## apply_file_changes ### Description Applies file changes (new files, patches, renames, deletions) to the file system. All operations are relative to the provided base directory and subject to the specified security policy. ### Signature `pub fn apply_file_changes(base_dir: impl Into, file_changes: FileChanges, security_policy: impl Into) -> Result` ### Parameters - **base_dir** (impl Into) - Required - The root directory for all file operations. - **file_changes** (FileChanges) - Required - The collection of file directives to apply. - **security_policy** (impl Into) - Required - Configuration for path-traversal restrictions. Pass `None` or `SecurityPolicy::default()` for strict containment. ### Returns - **Result** - Returns a status object containing the outcome of each directive. ``` -------------------------------- ### Add sort_files_by_mtime to pro/coder/lua/auto_context.lua Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-10/changes.txt Adds a helper function to sort file paths by modification time (mtime), with alphabetical fallback for identical timestamps, and exports it in the module return table. ```lua -- Helper to sort file paths by their modification time (mtime) -- Logic: Oldest first, alphabetical if same mtime local function sort_files_by_mtime(file_paths) if not file_paths or #file_paths <= 1 then return file_paths end local files = aip.file.list(file_paths) table.sort(files, function(a, b) local am = a.mtime or 0 local bm = b.mtime or 0 if am == bm then return a.path < b.path end return am < bm end) local sorted = {} for _, f in ipairs(files) do table.insert(sorted, f.path) end return sorted end return { extract_auto_context_config = extract_auto_context_config, pin_status = pin_status, sort_files_by_mtime = sort_files_by_mtime, } ``` -------------------------------- ### FILE_COPY Directive Source: https://github.com/zcoder-run/rust-udiffx/blob/main/src/prompt/prompt-file-changes.md Use this self-closing directive to copy a file from a source path to a destination path. ```text [[[FILE_COPY from_path="source" to_path="destination" /]]] ``` -------------------------------- ### apply_file_changes Source: https://github.com/zcoder-run/rust-udiffx/blob/main/dev/specs/spec-security.md The primary function for applying file changes, now accepting an optional SecurityPolicy. ```APIDOC ## apply_file_changes ### Signature `pub fn apply_file_changes(base_dir: impl Into, file_changes: FileChanges, security_policy: impl Into) -> Result` ### Description Applies file changes based on the provided base directory and security policy. If no policy is provided, the system defaults to strict mode. ``` -------------------------------- ### iter_files Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-06-no-match/original.txt Iterates over files in a directory matching optional glob patterns. ```APIDOC ## iter_files(dir, include_globs, list_options) ### Description Iterates over files in the specified directory, optionally filtering by glob patterns. ### Signature `iter_files(dir, include_globs: Option<&[&str]>, list_options: Option) -> Result>` ``` -------------------------------- ### Define UiAction Enum Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-08-missmatch/original.txt Defines the UI intents that represent deferred requests from the view layer. ```rust pub enum UiAction { Quit, Redo, CancelRun, ToggleRunsNav, CycleTasksOverviewMode, GoToTask { task_id: Id }, ToClipboardCopy(String), OpenFile(String), // Opens file at path using auto-editor } ``` -------------------------------- ### FILE_APPEND Directive Source: https://github.com/zcoder-run/rust-udiffx/blob/main/src/prompt/prompt-file-changes.md Use this directive to append content to the end of a file. It can also create a file if it does not exist. ```text [[[FILE_APPEND file_path="path/to/file"]]] _content to append_ [[[/FILE_APPEND]]] ``` -------------------------------- ### Add runtime_ctx method to src/runtime/runtime_impl.rs Source: https://github.com/zcoder-run/rust-udiffx/blob/main/tests/data/test-patches/test-21-silent-noop-hunk/changes.txt This patch introduces the runtime_ctx method to the runtime implementation, returning an optional reference to the RuntimeCtx. ```diff @@ pub fn cancel_rx(&self) -> Option<&tokio_util::sync::CancellationToken> { self.inner.cancel_trx.as_ref().map(|trx| trx.rx()) } + + pub fn runtime_ctx(&self) -> Option<&RuntimeCtx> { + self.inner.runtime_ctx.as_ref() + } } ```