use crate::{ FormatPromptArgs, PredictionProvider, example::{ActualCursor, Example, ExamplePrompt}, headless::EpAppState, progress::{ExampleProgress, Step}, retrieve_context::{ContextRetrievalType, run_context_retrieval},};use anyhow::{Context as _, Result, anyhow};use gpui::AsyncApp;use std::ops::Range;use std::sync::Arc;use zeta_prompt::{ Zeta2PromptInput, ZetaFormat, format_edit_history_within_budget, format_expected_output, format_zeta_prompt, hashed_regions::{self, SnippetMarkers}, max_edit_event_count_for_format, resolve_cursor_region,}; fn resolved_excerpt_ranges_for_format( input: &zeta_prompt::Zeta2PromptInput, format: ZetaFormat,) -> (Range<usize>, Range<usize>) { let (_, editable_range_in_context, context_range, _) = resolve_cursor_region(input, format); let editable_range = (context_range.start + editable_range_in_context.start) ..(context_range.start + editable_range_in_context.end); (editable_range, context_range)} pub async fn run_format_prompt( example: &mut Example, args: &FormatPromptArgs, app_state: Arc<EpAppState>, example_progress: &ExampleProgress, cx: AsyncApp,) -> Result<()> { run_context_retrieval( example, app_state.clone(), example_progress, vec![ContextRetrievalType::Lsp], false, cx.clone(), ) .await?; // Teacher-jumps addresses every edit through related-file excerpts and // hard-errors unless the cursor file is covered by one. Settled-data // samples carry a `cursor_excerpt` but were not run through current-file // context retrieval, so normalize the input to synthesize a current-file // excerpt from it when the cursor isn't already covered (a no-op for proper // `ep context --type=current-file` runs). if matches!( args.provider, PredictionProvider::TeacherJumps(_) | PredictionProvider::TeacherJumpsNonBatching(_) ) { if let Some(prompt_inputs) = example.prompt_inputs.as_mut() { hashed_regions::ensure_cursor_file_excerpt(prompt_inputs); } } let step_progress = example_progress.start(Step::FormatPrompt); let prompt_inputs = example .prompt_inputs .as_ref() .context("prompt_inputs must be set after context retrieval")?; match args.provider { PredictionProvider::Teacher(_, zeta_format) | PredictionProvider::TeacherNonBatching(_, zeta_format) => { step_progress.set_substatus("formatting teacher prompt"); let (editable_range, context_range) = resolved_excerpt_ranges_for_format(prompt_inputs, zeta_format); let include_diagnostics = matches!(zeta_format, ZetaFormat::V0420Diagnostics); let prompt = TeacherPrompt::format_prompt( example, editable_range, context_range, include_diagnostics, ); example.prompt = Some(ExamplePrompt { input: prompt, expected_output: None, rejected_output: None, prefill: None, provider: args.provider, }); } PredictionProvider::TeacherJumps(_) | PredictionProvider::TeacherJumpsNonBatching(_) => { step_progress.set_substatus("formatting teacher jumps prompt"); let prompt = TeacherJumpsPrompt::format_prompt(example, args.related_files_budget)?; example.prompt = Some(ExamplePrompt { input: prompt, expected_output: None, rejected_output: None, prefill: None, provider: args.provider, }); } PredictionProvider::Zeta2(zeta_format) => { step_progress.set_substatus("formatting zeta2 prompt"); let prompt = format_zeta_prompt(prompt_inputs, zeta_format); let prefill = zeta_prompt::get_prefill(prompt_inputs, zeta_format); let expected_output = example .spec .expected_patches_with_cursor_positions() .into_iter() .next() .and_then(|(expected_patch, expected_cursor_offset)| { format_expected_output( prompt_inputs, zeta_format, &expected_patch, expected_cursor_offset, ) .ok() }); let rejected_output = example.spec.rejected_patch.as_ref().and_then(|patch| { format_expected_output(prompt_inputs, zeta_format, patch, None).ok() }); example.prompt = prompt.map(|prompt| ExamplePrompt { input: prompt, expected_output, rejected_output, provider: args.provider, prefill: Some(prefill), }); } _ => { panic!("Cannot format prompt for {:?}", args.provider); } }; Ok(())} pub struct TeacherPrompt; impl TeacherPrompt { pub(crate) const EDITABLE_REGION_START: &str = "<|editable_region_start|>\n"; pub(crate) const EDITABLE_REGION_END: &str = "\n<|editable_region_end|>"; pub(crate) const USER_CURSOR_MARKER: &str = "<|user_cursor|>"; pub(crate) const NO_EDITS: &str = "NO_EDITS"; /// Truncate edit history to this number of last lines const MAX_HISTORY_LINES: usize = 128; pub fn format_prompt( example: &Example, editable_range: Range<usize>, context_range: Range<usize>, include_diagnostics: bool, ) -> String { let edit_history = Self::format_edit_history(&example.spec.edit_history); let context = Self::format_context(example); let cursor_excerpt = Self::format_cursor_excerpt(example, editable_range, context_range); let diagnostics = include_diagnostics .then(|| Self::format_diagnostics(example)) .map(|diagnostics| format!("# 4. Diagnostics\n\n{diagnostics}")); let prompt_template = crate::prompt_assets::get_prompt("teacher.md"); let prompt = prompt_template .replace("{{context}}", &context) .replace("{{edit_history}}", &edit_history) .replace("{{diagnostics}}", diagnostics.as_deref().unwrap_or("")) .replace("{{cursor_excerpt}}", &cursor_excerpt); prompt } pub fn parse(example: &Example, response: &str) -> Result<(String, Option<ActualCursor>)> { // Check if the model indicated no edits are needed let no_edits = (String::new(), None); if let Some(last_codeblock) = extract_last_codeblock(&response) { if last_codeblock.trim() == Self::NO_EDITS { return Ok(no_edits); } } if response .trim_end_matches(&[' ', '\n', '`']) .ends_with(Self::NO_EDITS) { return Ok(no_edits); } // Extract updated (new) editable region from the model response. let new_editable_region = Self::extract_editable_region(&response)?; let cursor_offset = new_editable_region.find(Self::USER_CURSOR_MARKER); let mut new_editable_region = new_editable_region.replace(Self::USER_CURSOR_MARKER, ""); let old_editable_region = Self::extract_editable_region( &example .prompt .as_ref() .context("example prompt missing")? .input, )? .replace(Self::USER_CURSOR_MARKER, ""); let prompt_inputs = example .prompt_inputs .as_ref() .context("example is missing prompt inputs")?; // Normalize leading newlines: if old starts with newline but new doesn't, // prepend newline to new to preserve whitespace structure. // This handles the case where the model drops the leading blank line. if old_editable_region.starts_with('\n') && !new_editable_region.starts_with('\n') { new_editable_region.insert(0, '\n'); } let excerpt = prompt_inputs.cursor_excerpt.as_ref(); let (editable_region_offset, _) = excerpt .match_indices(&old_editable_region) .min_by_key(|(index, _)| index.abs_diff(prompt_inputs.cursor_offset_in_excerpt)) .context("editable region not found in prompt content")?; let editable_region_start_line = excerpt[..editable_region_offset].matches('\n').count(); let editable_region_lines = old_editable_region.lines().count() as u32; let diff = language::unified_diff_with_context( &old_editable_region, &new_editable_region, editable_region_start_line as u32, editable_region_start_line as u32, editable_region_lines, ); let diff = indoc::formatdoc! {" --- a/{path} +++ b/{path} {diff}", path = example.spec.cursor_path.to_string_lossy(), diff = diff, }; let actual_cursor = cursor_offset.map(|editable_region_cursor_offset| { ActualCursor::from_editable_region( &example.spec.cursor_path, editable_region_cursor_offset, &new_editable_region, excerpt, editable_region_offset, editable_region_start_line, ) }); Ok((diff, actual_cursor)) } fn format_edit_history(edit_history: &str) -> String { let lines: Vec<&str> = edit_history.lines().collect(); if lines.is_empty() { return "(No edit history)".to_string(); } if lines.len() > Self::MAX_HISTORY_LINES { let truncated = lines[lines.len() - Self::MAX_HISTORY_LINES..].join("\n"); format!("{truncated}\n[...truncated...]") } else { lines.join("\n") } } pub fn format_context(example: &Example) -> String { let related_files = example .prompt_inputs .as_ref() .and_then(|pi| pi.related_files.as_deref()); let Some(related_files) = related_files else { return "(No context)".to_string(); }; if related_files.is_empty() { return "(No context)".to_string(); } let prefix = "`````"; let suffix = "`````\n\n"; let max_tokens = 1024; zeta_prompt::format_related_files_within_budget(related_files, &prefix, &suffix, max_tokens) } fn format_cursor_excerpt( example: &Example, editable_range: Range<usize>, context_range: Range<usize>, ) -> String { let mut result = String::new(); let prompt_inputs = example.prompt_inputs.as_ref().unwrap(); let excerpt = prompt_inputs.cursor_excerpt.as_ref(); let cursor_offset = prompt_inputs.cursor_offset_in_excerpt; let path_str = example.spec.cursor_path.to_string_lossy(); result.push_str(&format!("`````{path_str}\n")); result.push_str(&excerpt[context_range.start..editable_range.start]); result.push_str(Self::EDITABLE_REGION_START); result.push_str(&excerpt[editable_range.start..cursor_offset]); result.push_str(Self::USER_CURSOR_MARKER); result.push_str(&excerpt[cursor_offset..editable_range.end]); result.push_str(Self::EDITABLE_REGION_END); result.push_str(&excerpt[editable_range.end..context_range.end]); result.push_str("\n`````"); result } pub fn extract_editable_region(text: &str) -> Result<String> { let start = text .rfind(Self::EDITABLE_REGION_START) .map_or(0, |pos| pos + Self::EDITABLE_REGION_START.len()); let end = text.rfind(Self::EDITABLE_REGION_END).unwrap_or(text.len()); if start >= end { return Err(anyhow!("Invalid editable region markers")); } let region = &text[start..end]; Ok(region.strip_suffix('\n').unwrap_or(region).to_string()) } fn format_diagnostics(example: &Example) -> String { let Some(prompt_inputs) = example.prompt_inputs.as_ref() else { return "No Diagnostics".to_string(); }; let cursor_buffer_row = prompt_inputs.excerpt_start_row.map(|excerpt_start_row| { excerpt_start_row + prompt_inputs.cursor_excerpt[..prompt_inputs.cursor_offset_in_excerpt] .bytes() .filter(|byte| *byte == b'\n') .count() as u32 }); let diagnostics = zeta_prompt::format_active_buffer_diagnostics_with_budget( &prompt_inputs.active_buffer_diagnostics, cursor_buffer_row, 2_000, ); let diagnostics = diagnostics .strip_prefix("<filename>diagnostics\n") .unwrap_or(&diagnostics); if diagnostics.is_empty() { "No Diagnostics".to_string() } else { diagnostics.to_string() } }} /// Teacher prompt for long-range edit prediction ("jumps"). All prompt/// context — the cursor file and every related-file excerpt — is annotated/// with hashed region markers (V0609HashedRegions), and the teacher may/// output a sequence of marker-bounded edits targeting any of it.pub struct TeacherJumpsPrompt; impl TeacherJumpsPrompt { pub(crate) const USER_CURSOR_MARKER: &str = "<|user_cursor|>"; pub(crate) const NO_EDITS: &str = "NO_EDITS"; const MAX_HISTORY_TOKENS: usize = 4000; pub const DEFAULT_RELATED_FILES_BUDGET: usize = 8192; pub fn format_prompt(example: &Example, related_files_budget: usize) -> Result<String> { let prompt_inputs = example .prompt_inputs .as_ref() .context("example is missing prompt inputs")?; let marker_table = hashed_regions::build_marker_table(prompt_inputs); let cursor = hashed_regions::locate_cursor_in_related_files(prompt_inputs).context( "cursor position is not covered by any related-file excerpt of the cursor file; \ teacher-jumps requires current-file context retrieval (e.g. `ep context --type=current-file,...`)", )?; let edit_history = Self::format_edit_history(&prompt_inputs); let context = Self::format_context( prompt_inputs, &marker_table, related_files_budget, cursor.file_ix, ); let cursor_excerpt = Self::format_cursor_excerpt(example, prompt_inputs, &marker_table, &cursor)?; let prompt_template = crate::prompt_assets::get_prompt("teacher_jumps.md"); let prompt = prompt_template .replace("{{context}}", &context) .replace("{{edit_history}}", &edit_history) .replace("{{cursor_excerpt}}", &cursor_excerpt); Ok(prompt) } pub fn parse(example: &Example, response: &str) -> Result<(String, Option<ActualCursor>)> { let no_edits = (String::new(), None); if let Some(last_codeblock) = extract_last_codeblock(&response) { if last_codeblock.trim() == Self::NO_EDITS { return Ok(no_edits); } } if response.trim().ends_with(Self::NO_EDITS) { return Ok(no_edits); } let prompt_inputs = example .prompt_inputs .as_ref() .context("example is missing prompt inputs")?; // The teacher emits reasoning plus a sequence of markdown code fences, // one per edit, each a marker-bounded span. Extract the spans from the // fences, then hand off to the shared hash-region patch assembler that // the student parser also uses. let codeblocks: Vec<String> = extract_all_codeblocks(response) .into_iter() .filter(|block| block.contains(hashed_regions::MARKER_TAG_PREFIX)) .collect(); if codeblocks.is_empty() { return Err(anyhow!( "no marker-bounded edit codeblocks found in model response" )); } let mut spans = Vec::with_capacity(codeblocks.len()); for codeblock in &codeblocks { spans.push(hashed_regions::extract_marker_span(codeblock)?); } let (patch, cursor) = hashed_regions::build_patch_from_spans( prompt_inputs, &spans, Self::USER_CURSOR_MARKER, )?; let actual_cursor = cursor.map(|cursor| { ActualCursor::from_editable_region( &cursor.path, cursor.cursor_offset_in_new_text, &cursor.new_text, &cursor.old_text, 0, cursor.start_row as usize, ) }); Ok((patch, actual_cursor)) } fn format_edit_history(prompt_inputs: &Zeta2PromptInput) -> String { format_edit_history_within_budget( &prompt_inputs.events, "", "", Self::MAX_HISTORY_TOKENS, max_edit_event_count_for_format(&ZetaFormat::V0327SingleFile), ) } /// Render related files with hashed region markers, within a token /// budget. Mirrors `zeta_prompt::format_related_files_within_budget`, /// but inserts marker tags into every included excerpt. The cursor file /// is skipped: it renders in its own prompt section via /// `format_cursor_excerpt`, and including it here would duplicate it. fn format_context( prompt_inputs: &Zeta2PromptInput, marker_table: &[SnippetMarkers], max_tokens: usize, cursor_file_ix: usize, ) -> String { let Some(related_files) = prompt_inputs.related_files.as_deref() else { return "(No context)".to_string(); }; if related_files.is_empty() { return "(No context)".to_string(); } let estimate_tokens = |bytes: usize| bytes / 3; struct RenderedExcerpt { file_ix: usize, excerpt_ix: usize, order: usize, rendered: String, } let mut candidates = Vec::new(); for (file_ix, file) in related_files.iter().enumerate() { if file_ix == cursor_file_ix { continue;Lines 1–500 of 1678. Load more
use crate::{ FormatPromptArgs, PredictionProvider, example::{ActualCursor, Example, ExamplePrompt}, headless::EpAppState, progress::{ExampleProgress, Step}, retrieve_context::{ContextRetrievalType, run_context_retrieval}, }; use anyhow::{Context as _, Result, anyhow}; use gpui::AsyncApp; use std::ops::Range; use std::sync::Arc; use zeta_prompt::{ Zeta2PromptInput, ZetaFormat, format_edit_history_within_budget, format_expected_output, format_zeta_prompt, hashed_regions::{self, SnippetMarkers}, max_edit_event_count_for_format, resolve_cursor_region, }; fn resolved_excerpt_ranges_for_format( input: &zeta_prompt::Zeta2PromptInput, format: ZetaFormat, ) -> (Range<usize>, Range<usize>) { let (_, editable_range_in_context, context_range, _) = resolve_cursor_region(input, format); let editable_range = (context_range.start + editable_range_in_context.start) ..(context_range.start + editable_range_in_context.end); (editable_range, context_range) } pub async fn run_format_prompt( example: &mut Example, args: &FormatPromptArgs, app_state: Arc<EpAppState>, example_progress: &ExampleProgress, cx: AsyncApp, ) -> Result<()> { run_context_retrieval( example, app_state.clone(), example_progress, vec![ContextRetrievalType::Lsp], false, cx.clone(), ) .await?; // Teacher-jumps addresses every edit through related-file excerpts and // hard-errors unless the cursor file is covered by one. Settled-data // samples carry a `cursor_excerpt` but were not run through current-file // context retrieval, so normalize the input to synthesize a current-file // excerpt from it when the cursor isn't already covered (a no-op for proper // `ep context --type=current-file` runs). if matches!( args.provider, PredictionProvider::TeacherJumps(_) | PredictionProvider::TeacherJumpsNonBatching(_) ) { if let Some(prompt_inputs) = example.prompt_inputs.as_mut() { hashed_regions::ensure_cursor_file_excerpt(prompt_inputs); } } let step_progress = example_progress.start(Step::FormatPrompt); let prompt_inputs = example .prompt_inputs .as_ref() .context("prompt_inputs must be set after context retrieval")?; match args.provider { PredictionProvider::Teacher(_, zeta_format) | PredictionProvider::TeacherNonBatching(_, zeta_format) => { step_progress.set_substatus("formatting teacher prompt"); let (editable_range, context_range) = resolved_excerpt_ranges_for_format(prompt_inputs, zeta_format); let include_diagnostics = matches!(zeta_format, ZetaFormat::V0420Diagnostics); let prompt = TeacherPrompt::format_prompt( example, editable_range, context_range, include_diagnostics, ); example.prompt = Some(ExamplePrompt { input: prompt, expected_output: None, rejected_output: None, prefill: None, provider: args.provider, }); } PredictionProvider::TeacherJumps(_) | PredictionProvider::TeacherJumpsNonBatching(_) => { step_progress.set_substatus("formatting teacher jumps prompt"); let prompt = TeacherJumpsPrompt::format_prompt(example, args.related_files_budget)?; example.prompt = Some(ExamplePrompt { input: prompt, expected_output: None, rejected_output: None, prefill: None, provider: args.provider, }); } PredictionProvider::Zeta2(zeta_format) => { step_progress.set_substatus("formatting zeta2 prompt"); let prompt = format_zeta_prompt(prompt_inputs, zeta_format); let prefill = zeta_prompt::get_prefill(prompt_inputs, zeta_format); let expected_output = example .spec .expected_patches_with_cursor_positions() .into_iter() .next() .and_then(|(expected_patch, expected_cursor_offset)| { format_expected_output( prompt_inputs, zeta_format, &expected_patch, expected_cursor_offset, ) .ok() }); let rejected_output = example.spec.rejected_patch.as_ref().and_then(|patch| { format_expected_output(prompt_inputs, zeta_format, patch, None).ok() }); example.prompt = prompt.map(|prompt| ExamplePrompt { input: prompt, expected_output, rejected_output, provider: args.provider, prefill: Some(prefill), }); } _ => { panic!("Cannot format prompt for {:?}", args.provider); } }; Ok(()) } pub struct TeacherPrompt; impl TeacherPrompt { pub(crate) const EDITABLE_REGION_START: &str = "<|editable_region_start|>\n"; pub(crate) const EDITABLE_REGION_END: &str = "\n<|editable_region_end|>"; pub(crate) const USER_CURSOR_MARKER: &str = "<|user_cursor|>"; pub(crate) const NO_EDITS: &str = "NO_EDITS"; /// Truncate edit history to this number of last lines const MAX_HISTORY_LINES: usize = 128; pub fn format_prompt( example: &Example, editable_range: Range<usize>, context_range: Range<usize>, include_diagnostics: bool, ) -> String { let edit_history = Self::format_edit_history(&example.spec.edit_history); let context = Self::format_context(example); let cursor_excerpt = Self::format_cursor_excerpt(example, editable_range, context_range); let diagnostics = include_diagnostics .then(|| Self::format_diagnostics(example)) .map(|diagnostics| format!("# 4. Diagnostics\n\n{diagnostics}")); let prompt_template = crate::prompt_assets::get_prompt("teacher.md"); let prompt = prompt_template .replace("{{context}}", &context) .replace("{{edit_history}}", &edit_history) .replace("{{diagnostics}}", diagnostics.as_deref().unwrap_or("")) .replace("{{cursor_excerpt}}", &cursor_excerpt); prompt } pub fn parse(example: &Example, response: &str) -> Result<(String, Option<ActualCursor>)> { // Check if the model indicated no edits are needed let no_edits = (String::new(), None); if let Some(last_codeblock) = extract_last_codeblock(&response) { if last_codeblock.trim() == Self::NO_EDITS { return Ok(no_edits); } } if response .trim_end_matches(&[' ', '\n', '`']) .ends_with(Self::NO_EDITS) { return Ok(no_edits); } // Extract updated (new) editable region from the model response. let new_editable_region = Self::extract_editable_region(&response)?; let cursor_offset = new_editable_region.find(Self::USER_CURSOR_MARKER); let mut new_editable_region = new_editable_region.replace(Self::USER_CURSOR_MARKER, ""); let old_editable_region = Self::extract_editable_region( &example .prompt .as_ref() .context("example prompt missing")? .input, )? .replace(Self::USER_CURSOR_MARKER, ""); let prompt_inputs = example .prompt_inputs .as_ref() .context("example is missing prompt inputs")?; // Normalize leading newlines: if old starts with newline but new doesn't, // prepend newline to new to preserve whitespace structure. // This handles the case where the model drops the leading blank line. if old_editable_region.starts_with('\n') && !new_editable_region.starts_with('\n') { new_editable_region.insert(0, '\n'); } let excerpt = prompt_inputs.cursor_excerpt.as_ref(); let (editable_region_offset, _) = excerpt .match_indices(&old_editable_region) .min_by_key(|(index, _)| index.abs_diff(prompt_inputs.cursor_offset_in_excerpt)) .context("editable region not found in prompt content")?; let editable_region_start_line = excerpt[..editable_region_offset].matches('\n').count(); let editable_region_lines = old_editable_region.lines().count() as u32; let diff = language::unified_diff_with_context( &old_editable_region, &new_editable_region, editable_region_start_line as u32, editable_region_start_line as u32, editable_region_lines, ); let diff = indoc::formatdoc! {" --- a/{path} +++ b/{path} {diff}", path = example.spec.cursor_path.to_string_lossy(), diff = diff, }; let actual_cursor = cursor_offset.map(|editable_region_cursor_offset| { ActualCursor::from_editable_region( &example.spec.cursor_path, editable_region_cursor_offset, &new_editable_region, excerpt, editable_region_offset, editable_region_start_line, ) }); Ok((diff, actual_cursor)) } fn format_edit_history(edit_history: &str) -> String { let lines: Vec<&str> = edit_history.lines().collect(); if lines.is_empty() { return "(No edit history)".to_string(); } if lines.len() > Self::MAX_HISTORY_LINES { let truncated = lines[lines.len() - Self::MAX_HISTORY_LINES..].join("\n"); format!("{truncated}\n[...truncated...]") } else { lines.join("\n") } } pub fn format_context(example: &Example) -> String { let related_files = example .prompt_inputs .as_ref() .and_then(|pi| pi.related_files.as_deref()); let Some(related_files) = related_files else { return "(No context)".to_string(); }; if related_files.is_empty() { return "(No context)".to_string(); } let prefix = "`````"; let suffix = "`````\n\n"; let max_tokens = 1024; zeta_prompt::format_related_files_within_budget(related_files, &prefix, &suffix, max_tokens) } fn format_cursor_excerpt( example: &Example, editable_range: Range<usize>, context_range: Range<usize>, ) -> String { let mut result = String::new(); let prompt_inputs = example.prompt_inputs.as_ref().unwrap(); let excerpt = prompt_inputs.cursor_excerpt.as_ref(); let cursor_offset = prompt_inputs.cursor_offset_in_excerpt; let path_str = example.spec.cursor_path.to_string_lossy(); result.push_str(&format!("`````{path_str}\n")); result.push_str(&excerpt[context_range.start..editable_range.start]); result.push_str(Self::EDITABLE_REGION_START); result.push_str(&excerpt[editable_range.start..cursor_offset]); result.push_str(Self::USER_CURSOR_MARKER); result.push_str(&excerpt[cursor_offset..editable_range.end]); result.push_str(Self::EDITABLE_REGION_END); result.push_str(&excerpt[editable_range.end..context_range.end]); result.push_str("\n`````"); result } pub fn extract_editable_region(text: &str) -> Result<String> { let start = text .rfind(Self::EDITABLE_REGION_START) .map_or(0, |pos| pos + Self::EDITABLE_REGION_START.len()); let end = text.rfind(Self::EDITABLE_REGION_END).unwrap_or(text.len()); if start >= end { return Err(anyhow!("Invalid editable region markers")); } let region = &text[start..end]; Ok(region.strip_suffix('\n').unwrap_or(region).to_string()) } fn format_diagnostics(example: &Example) -> String { let Some(prompt_inputs) = example.prompt_inputs.as_ref() else { return "No Diagnostics".to_string(); }; let cursor_buffer_row = prompt_inputs.excerpt_start_row.map(|excerpt_start_row| { excerpt_start_row + prompt_inputs.cursor_excerpt[..prompt_inputs.cursor_offset_in_excerpt] .bytes() .filter(|byte| *byte == b'\n') .count() as u32 }); let diagnostics = zeta_prompt::format_active_buffer_diagnostics_with_budget( &prompt_inputs.active_buffer_diagnostics, cursor_buffer_row, 2_000, ); let diagnostics = diagnostics .strip_prefix("<filename>diagnostics\n") .unwrap_or(&diagnostics); if diagnostics.is_empty() { "No Diagnostics".to_string() } else { diagnostics.to_string() } } } /// Teacher prompt for long-range edit prediction ("jumps"). All prompt /// context — the cursor file and every related-file excerpt — is annotated /// with hashed region markers (V0609HashedRegions), and the teacher may /// output a sequence of marker-bounded edits targeting any of it. pub struct TeacherJumpsPrompt; impl TeacherJumpsPrompt { pub(crate) const USER_CURSOR_MARKER: &str = "<|user_cursor|>"; pub(crate) const NO_EDITS: &str = "NO_EDITS"; const MAX_HISTORY_TOKENS: usize = 4000; pub const DEFAULT_RELATED_FILES_BUDGET: usize = 8192; pub fn format_prompt(example: &Example, related_files_budget: usize) -> Result<String> { let prompt_inputs = example .prompt_inputs .as_ref() .context("example is missing prompt inputs")?; let marker_table = hashed_regions::build_marker_table(prompt_inputs); let cursor = hashed_regions::locate_cursor_in_related_files(prompt_inputs).context( "cursor position is not covered by any related-file excerpt of the cursor file; \ teacher-jumps requires current-file context retrieval (e.g. `ep context --type=current-file,...`)", )?; let edit_history = Self::format_edit_history(&prompt_inputs); let context = Self::format_context( prompt_inputs, &marker_table, related_files_budget, cursor.file_ix, ); let cursor_excerpt = Self::format_cursor_excerpt(example, prompt_inputs, &marker_table, &cursor)?; let prompt_template = crate::prompt_assets::get_prompt("teacher_jumps.md"); let prompt = prompt_template .replace("{{context}}", &context) .replace("{{edit_history}}", &edit_history) .replace("{{cursor_excerpt}}", &cursor_excerpt); Ok(prompt) } pub fn parse(example: &Example, response: &str) -> Result<(String, Option<ActualCursor>)> { let no_edits = (String::new(), None); if let Some(last_codeblock) = extract_last_codeblock(&response) { if last_codeblock.trim() == Self::NO_EDITS { return Ok(no_edits); } } if response.trim().ends_with(Self::NO_EDITS) { return Ok(no_edits); } let prompt_inputs = example .prompt_inputs .as_ref() .context("example is missing prompt inputs")?; // The teacher emits reasoning plus a sequence of markdown code fences, // one per edit, each a marker-bounded span. Extract the spans from the // fences, then hand off to the shared hash-region patch assembler that // the student parser also uses. let codeblocks: Vec<String> = extract_all_codeblocks(response) .into_iter() .filter(|block| block.contains(hashed_regions::MARKER_TAG_PREFIX)) .collect(); if codeblocks.is_empty() { return Err(anyhow!( "no marker-bounded edit codeblocks found in model response" )); } let mut spans = Vec::with_capacity(codeblocks.len()); for codeblock in &codeblocks { spans.push(hashed_regions::extract_marker_span(codeblock)?); } let (patch, cursor) = hashed_regions::build_patch_from_spans( prompt_inputs, &spans, Self::USER_CURSOR_MARKER, )?; let actual_cursor = cursor.map(|cursor| { ActualCursor::from_editable_region( &cursor.path, cursor.cursor_offset_in_new_text, &cursor.new_text, &cursor.old_text, 0, cursor.start_row as usize, ) }); Ok((patch, actual_cursor)) } fn format_edit_history(prompt_inputs: &Zeta2PromptInput) -> String { format_edit_history_within_budget( &prompt_inputs.events, "", "", Self::MAX_HISTORY_TOKENS, max_edit_event_count_for_format(&ZetaFormat::V0327SingleFile), ) } /// Render related files with hashed region markers, within a token /// budget. Mirrors `zeta_prompt::format_related_files_within_budget`, /// but inserts marker tags into every included excerpt. The cursor file /// is skipped: it renders in its own prompt section via /// `format_cursor_excerpt`, and including it here would duplicate it. fn format_context( prompt_inputs: &Zeta2PromptInput, marker_table: &[SnippetMarkers], max_tokens: usize, cursor_file_ix: usize, ) -> String { let Some(related_files) = prompt_inputs.related_files.as_deref() else { return "(No context)".to_string(); }; if related_files.is_empty() { return "(No context)".to_string(); } let estimate_tokens = |bytes: usize| bytes / 3; struct RenderedExcerpt { file_ix: usize, excerpt_ix: usize, order: usize, rendered: String, } let mut candidates = Vec::new(); for (file_ix, file) in related_files.iter().enumerate() { if file_ix == cursor_file_ix { continue;