From fe7054a346e92a8a11fbeffc5fa742d4588a33a2 Mon Sep 17 00:00:00 2001 From: Alex Kwiatkowski Date: Thu, 19 Feb 2026 13:29:26 -0800 Subject: [PATCH] fix(bazel): replace askama templates with include_str! in memories (#11778) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - The experimental Bazel CI builds fail on all platforms because askama resolves template paths relative to `CARGO_MANIFEST_DIR`, which points outside the Bazel sandbox. This produces errors like: ``` error: couldn't read `codex-rs/core/src/memories/../../../../../../../../../../../work/codex/codex/codex-rs/core/templates/memories/consolidation.md`: No such file or directory ``` - Replaced `#[derive(Template)]` + `#[template(path = "...")]` with `include_str!` + `str::replace()` for the three affected templates (`consolidation.md`, `stage_one_input.md`, `read_path.md`). `include_str!` resolves paths relative to the source file, which works correctly in both Cargo and Bazel builds. - The templates only use simple `{{ variable }}` substitution with no control flow or filters, so no askama functionality is lost. - Removes the `askama` dependency from `codex-core` since it was the only crate using it. The workspace-level dependency definition is left in place. - This matches the existing pattern used throughout the codebase — e.g. `codex-rs/core/src/memories/mod.rs` already uses `include_str!("../../templates/memories/stage_one_system.md")` for the fourth template file. ## Test plan - [ ] Verify Bazel (experimental) CI passes on all platforms - [ ] Verify rust-ci (Cargo) builds and tests continue to pass - [ ] Verify `cargo test -p codex-core` passes locally --- codex-rs/Cargo.lock | 53 --------------------------- codex-rs/Cargo.toml | 1 - codex-rs/core/Cargo.toml | 1 - codex-rs/core/src/memories/prompts.rs | 53 +++++++-------------------- 4 files changed, 13 insertions(+), 95 deletions(-) diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 189d9468d..4e3ec84e8 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -458,58 +458,6 @@ dependencies = [ "term", ] -[[package]] -name = "askama" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08e1676b346cadfec169374f949d7490fd80a24193d37d2afce0c047cf695e57" -dependencies = [ - "askama_macros", - "itoa", - "percent-encoding", - "serde", - "serde_json", -] - -[[package]] -name = "askama_derive" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7661ff56517787343f376f75db037426facd7c8d3049cef8911f1e75016f3a37" -dependencies = [ - "askama_parser", - "basic-toml", - "memchr", - "proc-macro2", - "quote", - "rustc-hash 2.1.1", - "serde", - "serde_derive", - "syn 2.0.114", -] - -[[package]] -name = "askama_macros" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713ee4dbfd1eb719c2dab859465b01fa1d21cb566684614a713a6b7a99a4e47b" -dependencies = [ - "askama_derive", -] - -[[package]] -name = "askama_parser" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d62d674238a526418b30c0def480d5beadb9d8964e7f38d635b03bf639c704c" -dependencies = [ - "rustc-hash 2.1.1", - "serde", - "serde_derive", - "unicode-ident", - "winnow", -] - [[package]] name = "asn1-rs" version = "0.7.1" @@ -1662,7 +1610,6 @@ version = "0.0.0" dependencies = [ "anyhow", "arc-swap", - "askama", "assert_cmd", "assert_matches", "async-channel", diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index 7ad0566ef..e27b08b7f 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -145,7 +145,6 @@ allocative = "0.3.3" ansi-to-tui = "7.0.0" anyhow = "1" arboard = { version = "3", features = ["wayland-data-control"] } -askama = "0.15.4" assert_cmd = "2" assert_matches = "1.5.0" async-channel = "2.3.1" diff --git a/codex-rs/core/Cargo.toml b/codex-rs/core/Cargo.toml index 64b7330c3..fe7c2b5aa 100644 --- a/codex-rs/core/Cargo.toml +++ b/codex-rs/core/Cargo.toml @@ -22,7 +22,6 @@ anyhow = { workspace = true } arc-swap = "1.8.2" async-channel = { workspace = true } async-trait = { workspace = true } -askama = { workspace = true } base64 = { workspace = true } bm25 = { workspace = true } chardetng = { workspace = true } diff --git a/codex-rs/core/src/memories/prompts.rs b/codex-rs/core/src/memories/prompts.rs index 9b341c1ff..9a3ea6a92 100644 --- a/codex-rs/core/src/memories/prompts.rs +++ b/codex-rs/core/src/memories/prompts.rs @@ -2,43 +2,18 @@ use crate::memories::memory_root; use crate::memories::phase_one; use crate::truncate::TruncationPolicy; use crate::truncate::truncate_text; -use askama::Template; use codex_protocol::openai_models::ModelInfo; use std::path::Path; use tokio::fs; -use tracing::warn; -#[derive(Template)] -#[template(path = "memories/consolidation.md", escape = "none")] -struct ConsolidationPromptTemplate<'a> { - memory_root: &'a str, -} - -#[derive(Template)] -#[template(path = "memories/stage_one_input.md", escape = "none")] -struct StageOneInputTemplate<'a> { - rollout_path: &'a str, - rollout_cwd: &'a str, - rollout_contents: &'a str, -} - -#[derive(Template)] -#[template(path = "memories/read_path.md", escape = "none")] -struct MemoryToolDeveloperInstructionsTemplate<'a> { - base_path: &'a str, - memory_summary: &'a str, -} +const CONSOLIDATION_TEMPLATE: &str = include_str!("../../templates/memories/consolidation.md"); +const STAGE_ONE_INPUT_TEMPLATE: &str = include_str!("../../templates/memories/stage_one_input.md"); +const READ_PATH_TEMPLATE: &str = include_str!("../../templates/memories/read_path.md"); /// Builds the consolidation subagent prompt for a specific memory root. pub(super) fn build_consolidation_prompt(memory_root: &Path) -> String { let memory_root = memory_root.display().to_string(); - let template = ConsolidationPromptTemplate { - memory_root: &memory_root, - }; - template.render().unwrap_or_else(|err| { - warn!("failed to render memories consolidation prompt template: {err}"); - format!("## Memory Phase 2 (Consolidation)\nConsolidate Codex memories in: {memory_root}") - }) + CONSOLIDATION_TEMPLATE.replace("{{ memory_root }}", &memory_root) } /// Builds the stage-1 user message containing rollout metadata and content. @@ -65,12 +40,10 @@ pub(super) fn build_stage_one_input_message( let rollout_path = rollout_path.display().to_string(); let rollout_cwd = rollout_cwd.display().to_string(); - Ok(StageOneInputTemplate { - rollout_path: &rollout_path, - rollout_cwd: &rollout_cwd, - rollout_contents: &truncated_rollout_contents, - } - .render()?) + Ok(STAGE_ONE_INPUT_TEMPLATE + .replace("{{ rollout_path }}", &rollout_path) + .replace("{{ rollout_cwd }}", &rollout_cwd) + .replace("{{ rollout_contents }}", &truncated_rollout_contents)) } /// Build prompt used for read path. This prompt must be added to the developer instructions. In @@ -92,11 +65,11 @@ pub(crate) async fn build_memory_tool_developer_instructions(codex_home: &Path) return None; } let base_path = base_path.display().to_string(); - let template = MemoryToolDeveloperInstructionsTemplate { - base_path: &base_path, - memory_summary: &memory_summary, - }; - template.render().ok() + Some( + READ_PATH_TEMPLATE + .replace("{{ base_path }}", &base_path) + .replace("{{ memory_summary }}", &memory_summary), + ) } #[cfg(test)]