diff --git a/src/prediction.rs b/src/prediction.rs index 4022b4b..605cbfb 100644 --- a/src/prediction.rs +++ b/src/prediction.rs @@ -44,7 +44,8 @@ struct Session { scenery: Scenery, tokens_consumed: usize, activity_notify: watch::Sender, - scene_sink: watch::Sender + scene_sink: watch::Sender, + do_regen: bool } #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] @@ -83,10 +84,70 @@ impl Session { direction, tokens_consumed: 0, activity_notify, - scene_sink + scene_sink, + do_regen: false } } + async fn commit(&mut self) { + let save_data = SaveData { + direction: self.direction.clone(), + messages: self.messages.clone(), + scenery: self.scenery.clone() + }; + + save_data.save(); + + if self.do_regen { + self.regenerate_options().await; + } + } + + async fn on_event(&mut self, evt: PredictionAction) { + self.do_regen = match evt { + PredictionAction::ConversationAppend(msg) => { + let do_regen = match msg { + ConversationEntry::Eva(_) | ConversationEntry::ShipComputer(_) | ConversationEntry::User(_) => true, + _ => false + }; + self.insert_conversation(msg); + + do_regen + }, + PredictionAction::SetPlaylist(playlist_name) => { + let args = MixxxQuery { playlist_name }; + match MixxxDB.query(&args).await { + Err(err) => log::info!("Failed to load mixxx playlist: {:?}.", err), + Ok(playlist) => { + self.scenery.current_playlist = vec![]; + for item in playlist.clone() { + if let Contents::Track(as_track) = item.contents() { + self.scenery.current_playlist.push(as_track.clone()); + } + self.scenery.artifacts.insert(item); + } + self.scenery.artifacts.synchronize().await; + self.direction.playlist = args.playlist_name; + log::info!("Mixxx playlist reloaded."); + } + } + false + }, + PredictionAction::GeneratePredictions => { + true + }, + PredictionAction::SetNarrative(narrative) => { + self.direction.narrative = narrative; + log::info!("Updated stage direction narrative"); + true + }, + PredictionAction::SetShowEndTime(end_time) => { + self.direction.end_time = end_time; + false + } + }; + } + async fn tool_stage_event(&mut self, args: StageEventArgs) -> ToolResults { let msg = match args.event { StageEvent::ShipComputer(text) => ConversationEntry::ShipComputer(text), @@ -139,6 +200,7 @@ impl Session { } async fn regenerate_options(&mut self) { + self.do_regen = false; self.reply_options.responses.clear(); self.refresh(); self.activity_notify.send_if_modified(|x| { if !*x { *x = true; true } else { false }}); @@ -332,62 +394,10 @@ pub async fn start_prediction(saved_session: SaveData, mut messages: tokio::sync tokio::spawn(async move { loop { if let Some(evt) = action_src.recv().await { - let mut session = shared_session.write().await; - let do_regen = match evt { - PredictionAction::ConversationAppend(msg) => { - let do_regen = match msg { - ConversationEntry::Eva(_) | ConversationEntry::ShipComputer(_) | ConversationEntry::User(_) => true, - _ => false - }; - session.insert_conversation(msg); - - do_regen - }, - PredictionAction::SetPlaylist(playlist_name) => { - let args = MixxxQuery { playlist_name }; - match MixxxDB.query(&args).await { - Err(err) => log::info!("Failed to load mixxx playlist: {:?}.", err), - Ok(playlist) => { - session.scenery.current_playlist = vec![]; - for item in playlist.clone() { - if let Contents::Track(as_track) = item.contents() { - session.scenery.current_playlist.push(as_track.clone()); - } - session.scenery.artifacts.insert(item); - } - session.scenery.artifacts.synchronize().await; - session.direction.playlist = args.playlist_name; - log::info!("Mixxx playlist reloaded."); - } - } - false - }, - PredictionAction::GeneratePredictions => { - true - }, - PredictionAction::SetNarrative(narrative) => { - session.direction.narrative = narrative; - log::info!("Updated stage direction narrative"); - true - }, - PredictionAction::SetShowEndTime(end_time) => { - session.direction.end_time = end_time; - false - } - }; - - let save_data = SaveData { - direction: session.direction.clone(), - messages: session.messages.clone(), - scenery: session.scenery.clone() - }; - - save_data.save(); - - if do_regen { - drop(session); - shared_session.write().await.regenerate_options().await; - } + shared_session.write().await.on_event(evt).await; + // Commit in a separate unlock operation, so the logging task has time to write messages into the conversation + // FIXME: The conversation we see in the UI really needs to go to another task. + shared_session.write().await.commit().await; } } });