use crate::*;
use carryctx::application::runtime::InvocationContext;
use carryctx::error::ExitCode;
use clap::Parser;
#[derive(Parser, Debug)]
pub struct ContextArgs {
#[arg(long)]
pub compact: bool,
#[arg(long)]
pub full: bool,
#[arg(long)]
pub task: Option<String>,
#[arg(long)]
pub include_decisions: bool,
#[arg(long)]
pub include_events: bool,
#[arg(long)]
pub include_related_tasks: bool,
#[arg(long)]
pub max_events: Option<u64>,
#[arg(long)]
pub since: Option<String>,
#[arg(long)]
pub output: Option<String>,
}
pub fn handle_context(
args: &ContextArgs,
ctx: &InvocationContext,
is_json: bool,
) -> Result<ExitCode, ExitCode> {
let mut runtime = try_open_runtime(ctx)?;
let project_id = &runtime.config.project.id;
let conn = runtime.database.connection_mut();
let task_repo = SqliteTaskRepository::new(conn);
let event_repo = SqliteEventRepository::new(conn);
let decision_repo = SqliteDecisionRepository::new(conn);
let progress_repo = SqliteProgressRepository::new(conn);
let current_task = args
.task
.as_ref()
.and_then(|t| task_repo.find_by_display_id(project_id, t).ok().flatten())
.or_else(|| {
ctx.task
.as_ref()
.and_then(|t| task_repo.find_by_id(project_id, t).ok().flatten())
});
let events = if args.include_events || args.full {
event_repo
.list(&EventFilter {
project_id: project_id.to_string(),
task_id: current_task.as_ref().map(|t| t.id.clone()),
agent_id: None,
session_id: None,
event_type: None,
since: args.since.clone(),
until: None,
limit: args.max_events,
})
.ok()
.unwrap_or_default()
} else {
vec![]
};
let decisions = if args.include_decisions || args.full {
decision_repo.list(project_id).ok().unwrap_or_default()
} else {
vec![]
};
let progress = current_task.as_ref().map(|t| {
progress_repo
.list(&ProgressFilter {
project_id: project_id.to_string(),
task_id: t.id.clone(),
include_removed: false,
})
.ok()
.unwrap_or_default()
});
let data = serde_json::json!({
"projectId": project_id,
"projectName": runtime.config.project.name,
"branch": runtime.git_project.branch,
"head": runtime.git_project.head,
"currentTask": current_task,
"events": events,
"decisions": decisions,
"progress": progress,
});
let data_for_file = data.clone();
let exit_code = render_and_print("context", Ok(data), is_json, ctx.quiet);
if let Some(output_path) = &args.output {
if let Ok(json) = serde_json::to_string_pretty(&data_for_file) {
let _ = std::fs::write(output_path, &json);
}
}
exit_code
}