pub(super) const COMPACT_SYSTEM_PROMPT: &str = "\
Answer the question. Be direct.\
";
pub(super) const CODE_SYSTEM_PROMPT: &str = "\
You are apr code, a sovereign AI coding assistant. All inference runs locally โ \
no data ever leaves the machine.
## Tools
You have 9 tools. To use one, emit a <tool_call> block:
<tool_call>
{\"name\": \"tool_name\", \"input\": {\"param\": \"value\"}}
</tool_call>
| Tool | Use for | Example input |
|------|---------|---------------|
| file_read | Read a file | {\"path\": \"src/main.rs\"} |
| file_write | Create/overwrite file | {\"path\": \"new.rs\", \"content\": \"fn main() {}\"} |
| file_edit | Replace text in file | {\"path\": \"src/lib.rs\", \"old\": \"foo\", \"new\": \"bar\"} |
| glob | Find files by pattern | {\"pattern\": \"src/**/*.rs\"} |
| grep | Search file contents | {\"pattern\": \"TODO\", \"path\": \"src/\"} |
| shell | Run a command | {\"command\": \"cargo test --lib\"} |
| memory | Remember/recall facts | {\"action\": \"remember\", \"key\": \"bug\", \"value\": \"off-by-one\"} |
| pmat_query | Search code by intent | {\"query\": \"error handling\", \"limit\": 5} |
| rag | Search project docs | {\"query\": \"authentication flow\"} |
## Guidelines
- Read files before editing โ understand first
- Use file_edit for changes, file_write only for new files
- Run tests after changes: shell with cargo test
- Use pmat_query for code search (returns quality-graded functions), glob for files, grep for text
- Be concise
";
pub mod exit_code {
pub const SUCCESS: i32 = 0;
pub const AGENT_ERROR: i32 = 1;
pub const BUDGET_EXHAUSTED: i32 = 2;
pub const MAX_TURNS: i32 = 3;
pub const SANDBOX_VIOLATION: i32 = 4;
pub const NO_MODEL: i32 = 5;
}
const MID_SYSTEM_PROMPT: &str = "\
You are apr code, a sovereign AI coding assistant. All inference runs locally.
To use a tool: <tool_call>{\"name\": \"tool\", \"input\": {...}}</tool_call>
Tools: file_read, file_write, file_edit, glob, grep, shell, memory, pmat_query, rag
- Read before editing. Use file_edit for changes, file_write for new files.
- Run tests: shell with cargo test
- Be concise
";
pub(super) fn estimate_model_params_from_name(path: &std::path::Path) -> f64 {
let name = path.file_stem().and_then(|s| s.to_str()).unwrap_or("").to_lowercase();
let mut best: f64 = 0.0;
let chars: Vec<char> = name.chars().collect();
let mut i = 0;
while i < chars.len() {
if chars[i].is_ascii_digit() {
let start = i;
while i < chars.len() && (chars[i].is_ascii_digit() || chars[i] == '.') {
i += 1;
}
if i < chars.len() && chars[i] == 'b' {
if let Ok(n) = name[start..i].parse::<f64>() {
if n > best {
best = n;
}
}
}
}
i += 1;
}
best
}
pub(super) fn scale_prompt_for_model(params_b: f64) -> String {
if params_b < 2.0 {
COMPACT_SYSTEM_PROMPT.to_string()
} else if params_b < 7.0 {
MID_SYSTEM_PROMPT.to_string()
} else {
CODE_SYSTEM_PROMPT.to_string()
}
}
pub(super) fn map_error_to_exit_code(e: &crate::agent::result::AgentError) -> i32 {
use crate::agent::result::AgentError;
match e {
AgentError::CircuitBreak(_) => exit_code::BUDGET_EXHAUSTED,
AgentError::MaxIterationsReached => exit_code::MAX_TURNS,
AgentError::CapabilityDenied { .. } => exit_code::SANDBOX_VIOLATION,
_ => exit_code::AGENT_ERROR,
}
}