feat: enhance workspace management and history tracking in application state

This commit is contained in:
asepharyana
2026-07-12 18:09:03 +07:00
parent a59feb23c4
commit 8a11a469f9
12 changed files with 112 additions and 20 deletions
+23 -5
View File
@@ -84,6 +84,8 @@ fn spawn_single_agent(
prompt: &str,
findings_snapshot: Vec<String>,
live: Option<&LiveStateFn>,
session_dir: &std::path::Path,
workspaces: &[std::path::PathBuf],
) -> anyhow::Result<String> {
use crate::app::subagent::context::build_subagent_context;
use crate::app::subagent::engine::run_subagent;
@@ -104,6 +106,8 @@ fn spawn_single_agent(
let def = AgentDefinition::new(agent_name.to_string(), "coder".to_string())
.with_max_steps(50);
let mut ctx = build_subagent_context(def);
ctx.session_dir = session_dir.to_path_buf();
ctx.workspaces = workspaces.to_vec();
let findings_section = if findings_snapshot.is_empty() {
String::new()
@@ -182,6 +186,8 @@ pub fn execute_primitive(
concurrency_cap: usize,
continue_on_error: bool,
live: Option<&LiveStateFn>,
session_dir: &std::path::Path,
workspaces: &[std::path::PathBuf],
) -> anyhow::Result<Vec<String>> {
match primitive {
ScriptPrimitive::Agent(prompt) => {
@@ -189,7 +195,7 @@ pub fn execute_primitive(
let findings_snapshot = FINDINGS.lock().map(|f| f.clone()).unwrap_or_default();
let agent_id = uuid::Uuid::new_v4().to_string();
let agent_name = resolved.chars().take(40).collect::<String>();
match spawn_single_agent(&agent_id, &agent_name, &resolved, findings_snapshot, live) {
match spawn_single_agent(&agent_id, &agent_name, &resolved, findings_snapshot, live, session_dir, workspaces) {
Ok(text) => Ok(vec![text]),
Err(e) => {
if continue_on_error {
@@ -219,12 +225,16 @@ pub fn execute_primitive(
let results = Arc::clone(&results);
let cap = concurrency_cap;
let live_clone = live.cloned();
let session_dir = session_dir.to_path_buf();
let workspaces = workspaces.to_vec();
std::thread::spawn(move || {
let _permit = sem.acquire();
let result = execute_primitive(
&script, &args, cap, continue_on_error,
live_clone.as_ref(),
&session_dir,
&workspaces,
);
if let Ok(mut locked) = results.lock() {
locked.push((idx, result));
@@ -258,7 +268,7 @@ pub fn execute_primitive(
// the global FINDINGS mutex.
let mut all = Vec::new();
for (idx, script) in scripts.iter().enumerate() {
match execute_primitive(script, args, concurrency_cap, continue_on_error, live) {
match execute_primitive(script, args, concurrency_cap, continue_on_error, live, session_dir, workspaces) {
Ok(outputs) => all.extend(outputs),
Err(e) => {
if continue_on_error {
@@ -273,7 +283,7 @@ pub fn execute_primitive(
}
ScriptPrimitive::Phase { name: _name, script } => {
execute_primitive(script, args, concurrency_cap, continue_on_error, live)
execute_primitive(script, args, concurrency_cap, continue_on_error, live, session_dir, workspaces)
}
}
}
@@ -282,8 +292,13 @@ pub fn execute_primitive(
/// summary string. Uses no live-state callback.
///
/// Return: a human-readable summary string.
pub fn run_workflow(script: &WorkflowScript, args: &HashMap<String, String>) -> anyhow::Result<String> {
run_workflow_tracked(script, args, None)
pub fn run_workflow(
script: &WorkflowScript,
args: &HashMap<String, String>,
session_dir: &std::path::Path,
workspaces: &[std::path::PathBuf],
) -> anyhow::Result<String> {
run_workflow_tracked(script, args, None, session_dir, workspaces)
}
/// Run a `WorkflowScript` with real-time live-state callbacks so the TUI
@@ -297,6 +312,8 @@ pub fn run_workflow_tracked(
script: &WorkflowScript,
args: &HashMap<String, String>,
live: Option<LiveStateFn>,
session_dir: &std::path::Path,
workspaces: &[std::path::PathBuf],
) -> anyhow::Result<String> {
if let Ok(mut findings) = FINDINGS.lock() {
findings.clear();
@@ -312,6 +329,7 @@ pub fn run_workflow_tracked(
let results = execute_primitive(
&script.script, args, concurrency_cap,
script.options.continue_on_error, live_ref,
session_dir, workspaces,
)?;
let summary = if results.is_empty() {