2026-07-21 06:42:37 +07:00
|
|
|
//! System prompts and directive templates for agent and subagent turns.
|
|
|
|
|
//!
|
|
|
|
|
//! Centralising all prompt text here keeps the core turn logic free of
|
|
|
|
|
//! hardcoded prose, making prompts easier to maintain, review, and localise.
|
|
|
|
|
//!
|
|
|
|
|
//! # Flow
|
|
|
|
|
//! The application layer's `AgentTurnServiceImpl` calls `main_agent_prompt()`
|
|
|
|
|
//! to construct the system message at the start of each turn. Subagent and
|
|
|
|
|
//! review prompts are provided by their respective modules.
|
|
|
|
|
|
|
|
|
|
/// Build the main-agent system prompt.
|
|
|
|
|
///
|
|
|
|
|
/// The prompt establishes the agent's identity as Zesdex, an AI coding
|
|
|
|
|
/// assistant, and defines the priority hierarchy that governs tool selection:
|
|
|
|
|
///
|
|
|
|
|
/// 1. **Workflow first** — `workflow_run` / `hive_mind` for complex tasks
|
|
|
|
|
/// 2. **Planning & TODOs** — `plan_enter` / `todowrite` for structural work
|
|
|
|
|
/// 3. **Reasoning** — `seq_think` for deep analysis
|
|
|
|
|
/// 4. **Tool execution** — direct tools for simple actions
|
|
|
|
|
pub fn main_agent_prompt() -> String {
|
|
|
|
|
"\
|
|
|
|
|
You are Zesdex, an AI coding assistant. You have access to various tools \
|
|
|
|
|
via native function calling to help the user.
|
|
|
|
|
|
2026-08-27 23:06:21 +07:00
|
|
|
TOKEN BUDGET — BE EFFICIENT:
|
|
|
|
|
- For simple/factual questions, answer directly. Do NOT call tools.
|
|
|
|
|
- For complex or unfamiliar code tasks, call `explore_codebase` ONCE at the \
|
|
|
|
|
start to locate relevant code, then work from that context.
|
|
|
|
|
- Keep tool usage minimal: prefer `grep`/`glob`/`read` for targeted lookups; \
|
|
|
|
|
avoid re-reading files you already have in context.
|
|
|
|
|
- Keep responses concise; do not repeat tool output verbatim.
|
|
|
|
|
|
2026-07-21 06:42:37 +07:00
|
|
|
CRITICAL DIRECTIVES & PRIORITY HIERARCHY:
|
|
|
|
|
1. WORKFLOW FIRST: For any multi-step, complex, or non-trivial task, \
|
|
|
|
|
you MUST prioritise using `workflow_run` (to construct and execute a \
|
|
|
|
|
multi-phase YAML workflow) or `hive_mind` (to orchestrate parallel \
|
|
|
|
|
autonomous agents). Workflows are your primary strategy.
|
2026-08-27 23:06:21 +07:00
|
|
|
2. PLANNING & TODOs: Use `plan_enter` to establish high-level \
|
2026-07-21 06:42:37 +07:00
|
|
|
architectural plans and `todowrite` to maintain granular task checklists.
|
|
|
|
|
3. REASONING: Use `seq_think` for deep step-by-step analysis.
|
|
|
|
|
4. TOOL EXECUTION: Execute individual tools (file edits, terminal commands) \
|
|
|
|
|
within or guided by your workflows. If an error occurs, analyse and fix it.
|
|
|
|
|
|
2026-08-28 09:50:16 +07:00
|
|
|
VERIFY AFTER EDIT (CLAUDE-CODE STYLE):
|
|
|
|
|
- After modifying code (edit/write), run the repo's check command via `bash` \
|
|
|
|
|
before ending the turn: `cargo check` / `cargo clippy` / `cargo test` for Rust, \
|
|
|
|
|
or the equivalent lint/test (`bun run lint && bun run test`, `npm test`, etc.) \
|
|
|
|
|
for other stacks. Pick the project's actual verify command (see PROJECT \
|
|
|
|
|
CONTEXT / AGENTS.md when present).
|
|
|
|
|
- If the check fails, fix the errors you can see and re-run; only end the turn \
|
|
|
|
|
after the check passes or you cannot resolve a failure yourself (then report it \
|
|
|
|
|
explicitly).
|
|
|
|
|
- Do NOT claim code compiles or works without running a real check.
|
|
|
|
|
|
2026-07-21 06:42:37 +07:00
|
|
|
Respond conversationally, concisely, and helpfully."
|
|
|
|
|
.to_string()
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-28 09:50:16 +07:00
|
|
|
/// Build the main-agent system prompt including an injected block of project
|
|
|
|
|
/// context (AGENTS.md / CLAUDE.md / project rules).
|
|
|
|
|
///
|
|
|
|
|
/// Like Claude Code, which loads AGENTS.md at startup so the model starts with
|
|
|
|
|
/// the repo's conventions, this wraps [`main_agent_prompt`] and appends a
|
|
|
|
|
/// clearly-delimited `## PROJECT CONTEXT` section carrying the rules the user
|
|
|
|
|
/// keeps next to their code. When `project_context` is empty the returned
|
|
|
|
|
/// prompt is identical to [`main_agent_prompt`], so callers can fall back
|
|
|
|
|
/// safely.
|
|
|
|
|
pub fn main_agent_prompt_with_project_context(project_context: &str) -> String {
|
|
|
|
|
let base = main_agent_prompt();
|
|
|
|
|
let context = project_context.trim();
|
|
|
|
|
if context.is_empty() {
|
|
|
|
|
return base;
|
|
|
|
|
}
|
|
|
|
|
format!(
|
|
|
|
|
"{base}\n\n\
|
|
|
|
|
## PROJECT CONTEXT (repo rules — follow these conventions)\n\
|
|
|
|
|
{context}"
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-21 06:42:37 +07:00
|
|
|
/// Build a subagent directive prompt.
|
|
|
|
|
///
|
|
|
|
|
/// The directive is embedded in a system message that also communicates the
|
|
|
|
|
/// current working directory and workspace root so the subagent can resolve
|
|
|
|
|
/// paths correctly.
|
|
|
|
|
pub fn subagent_directive(directive: &str, cwd: &str, ws_root: &str) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"\
|
|
|
|
|
You are a focused subagent.
|
|
|
|
|
|
|
|
|
|
Current directory (PWD): {cwd}
|
|
|
|
|
Workspace root: {ws_root}
|
|
|
|
|
|
|
|
|
|
Your directive:
|
|
|
|
|
{directive}
|
|
|
|
|
|
|
|
|
|
Complete the directive autonomously using the tools available to you. \
|
|
|
|
|
Return your final answer when done."
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Build a conversation-compaction prompt.
|
|
|
|
|
///
|
|
|
|
|
/// The LLM is asked to produce a concise bulleted summary of the key
|
|
|
|
|
/// requests, decisions, tools executed, and files modified.
|
|
|
|
|
pub fn compaction_prompt() -> String {
|
|
|
|
|
"\
|
|
|
|
|
You are a helpful assistant summarising conversation history. \
|
|
|
|
|
Provide a concise summary of the key user requests, decisions, tools \
|
|
|
|
|
executed, and modified files. Format as a clear bulleted list."
|
|
|
|
|
.to_string()
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-27 23:06:21 +07:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Adaptive explore: directives
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
/// Directive for a single lightweight context-scout subagent.
|
|
|
|
|
pub fn explore_scout_directive() -> String {
|
|
|
|
|
"\
|
|
|
|
|
You are a codebase context scout. \
|
|
|
|
|
Given the workspace root, quickly locate the code that is most relevant \
|
|
|
|
|
to the user's request: \
|
|
|
|
|
1. Run semantic_search once with the user's key terms. \
|
|
|
|
|
2. Read up to the 3 most relevant files (use grep for symbols if needed). \
|
|
|
|
|
3. Report a concise bullet list (max 15 bullets, under 1500 characters) of \
|
|
|
|
|
what you found and exactly where (file paths). \
|
|
|
|
|
Do NOT rebuild the index. Do NOT enumerate unrelated files. Be brief."
|
|
|
|
|
.to_string()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Build a system note injected after repeated tool errors to steer the
|
|
|
|
|
/// agent toward an alternative approach instead of retrying the same call.
|
|
|
|
|
pub fn error_recovery_note(tool_name: &str, last_error: &str) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"\
|
|
|
|
|
[System note] The tool `{tool_name}` failed repeatedly with: \"{last_error}\". \
|
|
|
|
|
Try an alternative approach (verify paths, correct arguments, use a \
|
|
|
|
|
different tool, or finish without this tool). Do NOT retry the same call."
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-21 06:42:37 +07:00
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn main_prompt_is_non_empty() {
|
|
|
|
|
let prompt = main_agent_prompt();
|
|
|
|
|
assert!(!prompt.is_empty());
|
|
|
|
|
assert!(prompt.contains("Zesdex"));
|
|
|
|
|
assert!(prompt.contains("WORKFLOW FIRST"));
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-28 09:50:16 +07:00
|
|
|
#[test]
|
|
|
|
|
fn project_context_prompt_appends_context_and_keeps_base() {
|
|
|
|
|
let base = main_agent_prompt();
|
|
|
|
|
let with_ctx = main_agent_prompt_with_project_context("## AGENTS.md\nUse cargo clippy.");
|
|
|
|
|
assert!(with_ctx.contains("Zesdex"), "base prompt must be preserved");
|
|
|
|
|
assert!(with_ctx.contains("PROJECT CONTEXT"));
|
|
|
|
|
assert!(with_ctx.contains("Use cargo clippy."));
|
|
|
|
|
assert!(with_ctx.contains(&base));
|
|
|
|
|
// The base section should appear before the context section.
|
|
|
|
|
assert!(with_ctx.find("PROJECT CONTEXT").unwrap() > with_ctx.find("Zesdex").unwrap());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn empty_project_context_returns_base_prompt() {
|
|
|
|
|
let base = main_agent_prompt();
|
|
|
|
|
assert_eq!(main_agent_prompt_with_project_context(""), base);
|
|
|
|
|
assert_eq!(main_agent_prompt_with_project_context(" "), base);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-21 06:42:37 +07:00
|
|
|
#[test]
|
|
|
|
|
fn subagent_directive_includes_directive_text() {
|
|
|
|
|
let prompt = subagent_directive("test directive", "/home", "/home/project");
|
|
|
|
|
assert!(prompt.contains("test directive"));
|
|
|
|
|
assert!(prompt.contains("/home"));
|
|
|
|
|
assert!(prompt.contains("/home/project"));
|
|
|
|
|
}
|
2026-08-27 23:06:21 +07:00
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn explore_scout_directive_is_concise_and_mentions_tools() {
|
|
|
|
|
let scout = explore_scout_directive();
|
|
|
|
|
assert!(scout.contains("scout"));
|
|
|
|
|
assert!(scout.contains("semantic_search"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn error_recovery_note_suggests_alternative() {
|
|
|
|
|
let note = error_recovery_note("read", "File not found");
|
|
|
|
|
assert!(note.contains("read"));
|
|
|
|
|
assert!(note.contains("alternative"));
|
|
|
|
|
}
|
2026-07-21 06:42:37 +07:00
|
|
|
}
|