Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/staged/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1855,6 +1855,7 @@ pub fn run() {
note_commands::delete_note,
note_commands::create_project_note,
note_commands::list_project_notes,
note_commands::get_project_note_by_session,
note_commands::delete_project_note,
// Images
image_commands::create_image,
Expand Down
26 changes: 22 additions & 4 deletions apps/staged/src-tauri/src/note_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,34 @@ pub fn list_project_notes(
project_id: String,
) -> Result<Vec<crate::store::ProjectNote>, String> {
crate::get_store(&store)?
.list_project_notes(&project_id)
.list_project_notes_with_status(&project_id)
.map_err(|e| e.to_string())
}

#[tauri::command]
/// Get a single project note by its linked session ID, with resolved session status.
#[tauri::command(rename_all = "camelCase")]
pub fn get_project_note_by_session(
store: tauri::State<'_, Mutex<Option<Arc<Store>>>>,
session_id: String,
) -> Result<Option<crate::store::ProjectNote>, String> {
crate::get_store(&store)?
.get_project_note_by_session_with_status(&session_id)
.map_err(|e| e.to_string())
}

/// Delete a project note and its linked session (if any).
#[tauri::command(rename_all = "camelCase")]
pub fn delete_project_note(
store: tauri::State<'_, Mutex<Option<Arc<Store>>>>,
note_id: String,
) -> Result<(), String> {
crate::get_store(&store)?
let store = crate::get_store(&store)?;
let session_id = store
.delete_project_note(&note_id)
.map_err(|e| e.to_string())
.map_err(|e| e.to_string())?;

if let Some(sid) = session_id {
let _ = store.delete_session(&sid);
}
Ok(())
}
29 changes: 22 additions & 7 deletions apps/staged/src-tauri/src/prs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,14 @@ fn start_pipeline_for_branch(
// Emit "running" event *before* returning so the global session listener
// registers this session atomically — avoiding the race where the session
// completes before the frontend `.then()` callback fires.
let branch_id = ctx.branch.id.clone();
let project_id = ctx.branch.project_id.clone();

session_runner::emit_session_running(
app_handle,
&session.id,
&ctx.branch.id,
&ctx.branch.project_id,
&branch_id,
&project_id,
session_type,
);

Expand All @@ -172,6 +175,8 @@ fn start_pipeline_for_branch(
provider,
workspace_name: ctx.workspace_name,
remote_working_dir: ctx.remote_working_dir,
branch_id: Some(branch_id),
project_id: Some(project_id),
},
store,
app_handle.clone(),
Expand Down Expand Up @@ -313,14 +318,17 @@ async fn start_running_commit_pipeline_for_branch(
session.pipeline = Some(pipeline.clone());
store.create_session(&session).map_err(|e| e.to_string())?;

let commit = store::Commit::new_pending(&ctx.branch.id).with_session(&session.id);
let branch_id = ctx.branch.id.clone();
let project_id = ctx.branch.project_id.clone();

let commit = store::Commit::new_pending(&branch_id).with_session(&session.id);
store.create_commit(&commit).map_err(|e| e.to_string())?;

session_runner::emit_session_running(
app_handle,
&session.id,
&ctx.branch.id,
&ctx.branch.project_id,
&branch_id,
&project_id,
"commit",
);

Expand All @@ -335,6 +343,8 @@ async fn start_running_commit_pipeline_for_branch(
provider,
workspace_name: ctx.workspace_name,
remote_working_dir: ctx.remote_working_dir,
branch_id: Some(branch_id),
project_id: Some(project_id),
},
store,
app_handle.clone(),
Expand Down Expand Up @@ -440,11 +450,14 @@ pub(crate) async fn start_queued_commit_pipeline_for_branch(
.update_session_pipeline(&session.id, &pipeline)
.map_err(|e| e.to_string())?;

let branch_id = ctx.branch.id.clone();
let project_id = ctx.branch.project_id.clone();

session_runner::emit_session_running(
&app_handle,
&session.id,
&ctx.branch.id,
&ctx.branch.project_id,
&branch_id,
&project_id,
"commit",
);

Expand All @@ -459,6 +472,8 @@ pub(crate) async fn start_queued_commit_pipeline_for_branch(
provider: effective_provider,
workspace_name: ctx.workspace_name,
remote_working_dir: ctx.remote_working_dir,
branch_id: Some(branch_id),
project_id: Some(project_id),
},
store,
app_handle,
Expand Down
25 changes: 21 additions & 4 deletions apps/staged/src-tauri/src/session_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ pub async fn start_session(
action_registry: None,
remote_working_dir: None,
image_ids: vec![],
branch_id: None,
project_id: None,
},
store,
app_handle,
Expand Down Expand Up @@ -321,6 +323,9 @@ pub async fn resume_session(
return Err("Session is already running".to_string());
}

let config_branch_id = event_branch_id.clone();
let config_project_id = event_project_id.clone().or(mcp_project_id.clone());

crate::web_server::emit_to_all(
&app_handle,
"session-status-changed",
Expand Down Expand Up @@ -363,6 +368,8 @@ pub async fn resume_session(
},
remote_working_dir,
image_ids: image_ids.unwrap_or_default(),
branch_id: config_branch_id,
project_id: config_project_id,
},
store,
app_handle,
Expand Down Expand Up @@ -407,6 +414,8 @@ pub fn cancel_session(
None,
Some(&store::CompletionReason::Interrupted),
);
let branch_id = store.get_branch_id_for_session(&session_id).ok().flatten();
let project_id = store.get_project_id_for_session(&session_id).ok().flatten();
crate::web_server::emit_to_all(
&app_handle,
"session-status-changed",
Expand All @@ -415,8 +424,8 @@ pub fn cancel_session(
status: "cancelled".to_string(),
error_message: None,
completion_reason: Some("interrupted".to_string()),
branch_id: None,
project_id: None,
branch_id,
project_id,
session_type: None,
is_auto_review: false,
},
Expand Down Expand Up @@ -602,8 +611,8 @@ Begin the note with a markdown H1 heading as the title.\n\n"
}
store.create_session(&session).map_err(|e| e.to_string())?;

// Always create a project note stub with empty title and content so that the
// frontend can detect it as "generating" via the !title && !content check.
// Create a project note stub linked to the session. The frontend uses the
// backend-resolved sessionStatus to determine whether the note is generating.
let note = store::ProjectNote::new(&project_id, "", "").with_session(&session.id);
store
.create_project_note(&note)
Expand All @@ -625,6 +634,8 @@ Begin the note with a markdown H1 heading as the title.\n\n"
action_registry: Some(Arc::clone(&action_registry)),
remote_working_dir: None,
image_ids: image_ids.unwrap_or_default(),
branch_id: None,
project_id: Some(project_id),
},
store,
app_handle,
Expand Down Expand Up @@ -876,6 +887,8 @@ pub async fn start_branch_session(
action_registry: None,
remote_working_dir,
image_ids: image_ids.unwrap_or_default(),
branch_id: Some(branch_id),
project_id: Some(branch.project_id.clone()),
},
store,
app_handle,
Expand Down Expand Up @@ -1283,6 +1296,8 @@ pub async fn drain_queued_sessions_for_branch(
action_registry: None,
remote_working_dir,
image_ids,
branch_id: Some(branch_id),
project_id: Some(branch.project_id.clone()),
},
store,
app_handle,
Expand Down Expand Up @@ -1567,6 +1582,8 @@ pub async fn trigger_auto_review(
action_registry: None,
remote_working_dir,
image_ids: vec![],
branch_id: Some(branch_id.clone()),
project_id: Some(branch.project_id.clone()),
},
store,
app_handle,
Expand Down
Loading