use std::path::PathBuf;
use super::{
ContextFile, EVENT_SCHEMA_VERSION, Event, SkillSummary, Template, TemplateSummary,
WorkspaceContext,
};
#[derive(Debug, Clone)]
pub struct RunContext {
pub workspace: PathBuf,
pub prompt: String,
pub provider: String,
pub model: String,
pub context: WorkspaceContext,
pub skills_dirs: Vec<PathBuf>,
pub skills: Vec<LoadedSkill>,
pub templates_dirs: Vec<PathBuf>,
pub templates: Vec<Template>,
pub mcp_files: Vec<ContextFile>,
pub mcp_servers: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct LoadedSkill {
pub name: String,
pub description: String,
pub model_invocable: bool,
pub path: PathBuf,
}
pub(super) fn header_for(session_id: &str, run: &RunContext) -> Event {
Event::RunStarted {
schema: EVENT_SCHEMA_VERSION,
basis: env!("CARGO_PKG_VERSION").to_string(),
session_id: session_id.to_string(),
workspace: run.workspace.clone(),
model: run.model.clone(),
provider: run.provider.clone(),
context_files: run
.context
.documents()
.iter()
.map(|document| ContextFile {
path: document.path.clone(),
scope: document.scope.label(),
})
.collect(),
skills_dirs: run.skills_dirs.clone(),
skills: run
.skills
.iter()
.map(|skill| SkillSummary {
name: skill.name.clone(),
description: skill.description.clone(),
})
.collect(),
templates_dirs: run.templates_dirs.clone(),
templates: run
.templates
.iter()
.map(|template| TemplateSummary {
name: template.name.clone(),
description: template.description.clone(),
argument_hint: template.argument_hint.clone(),
})
.collect(),
mcp_files: run.mcp_files.clone(),
mcp_servers: run.mcp_servers.clone(),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::context::{ContextDocument, ContextScope};
#[test]
fn the_header_lists_context_files_weakest_first() {
let context = WorkspaceContext::from_documents(vec![
ContextDocument {
path: PathBuf::from("/AGENTS.md"),
scope: ContextScope::Ancestor { depth: 2 },
content: "outer".to_string(),
},
ContextDocument {
path: PathBuf::from("/repo/AGENTS.md"),
scope: ContextScope::Workspace,
content: "inner".to_string(),
},
]);
let files: Vec<ContextFile> = context
.documents()
.iter()
.map(|document| ContextFile {
path: document.path.clone(),
scope: document.scope.label(),
})
.collect();
assert_eq!(files[0].scope, "ancestor:2");
assert_eq!(files[1].scope, "workspace");
}
}