This commit is contained in:
2026-06-05 23:30:45 +02:00
parent bd4dbc3aa6
commit 6a73cb4bc4
5 changed files with 100 additions and 82 deletions
+74 -71
View File
@@ -312,6 +312,65 @@ impl App {
self.regenerate_responses();
}
async fn on_command(&mut self, command: &str) {
let mut parts = command.splitn(2, " ");
let command = parts.next().unwrap();
let arg = parts.next().unwrap_or("");
match command {
"/bandcamp" => {
self.add_bandcamp_artifact(arg).await;
self.sys_message_sink.send(format!("Added Bandcamp artifact from {}", arg)).await.unwrap();
self.next_actions.push(ConversationEntry::ShipComputer(format!("Incoming transmission from {}", arg)));
self.regenerate_responses();
},
"/episode" => {
if let Ok(episode_number) = arg.trim().parse::<u32>() {
self.direction.episode_number = episode_number;
self.sys_message_sink.send(format!("Updated episode number: {}", self.direction.episode_number)).await.unwrap();
self.reload_mixxx_playlist();
} else {
self.sys_message_sink.send("Invalid episode number format. Use /episode [number]".into()).await.unwrap();
return;
}
},
"/timer" => {
if let Ok(minutes) = arg.trim().parse::<i64>() {
self.end_time = Utc::now() + Duration::minutes(minutes);
self.sys_message_sink.send(format!("Set timer for {} minutes.", minutes)).await.unwrap();
} else {
self.sys_message_sink.send("Invalid timer format. Use /timer [minutes]".into()).await.unwrap();
}
},
"/clear" => {
match arg.trim() {
"artifacts" => {
self.direction.artifacts.clear();
self.sys_message_sink.send("Cleared artifacts.".into()).await.unwrap();
},
_ => {
self.sys_message_sink.send("Unknown clear command. Use /clear [artifacts]".into()).await.unwrap();
}
}
return;
},
"/narrative" => {
self.direction.narrative = arg.to_string();
self.sys_message_sink.send(format!("Updated stage direction: {}", self.direction.narrative)).await.unwrap();
},
"/event" => {
self.next_actions.push(ConversationEntry::StageDirection(arg.to_string()));
self.regenerate_responses();
},
"/computer" => {
self.next_actions.push(ConversationEntry::ShipComputer(arg.to_string()));
self.regenerate_responses();
},
_ => {
self.sys_message_sink.send("Unknown command. Available commands: /bandcamp [url], /episode [number], /narrative [text], /reset".into()).await.unwrap();
}
}
}
async fn on_event(&mut self, evt: event::Event) {
if let Some(key) = evt.as_key_press_event() {
match self.focus_state {
@@ -366,70 +425,7 @@ impl App {
self.insert_selected_prompt().await;
} else {
if next_msg.starts_with("/") {
let mut parts = next_msg.splitn(2, " ");
let command = parts.next().unwrap();
let arg = parts.next().unwrap_or("");
match command {
"/bandcamp" => {
self.add_bandcamp_artifact(arg).await;
self.sys_message_sink.send(format!("Added Bandcamp artifact from {}", arg)).await.unwrap();
self.next_actions.push(ConversationEntry::ShipComputer(format!("Incoming transmission from {}", arg)));
self.regenerate_responses();
},
"/episode" => {
if let Ok(episode_number) = arg.trim().parse::<u32>() {
self.direction.episode_number = episode_number;
self.sys_message_sink.send(format!("Updated episode number: {}", self.direction.episode_number)).await.unwrap();
self.reload_mixxx_playlist();
} else {
self.sys_message_sink.send("Invalid episode number format. Use /episode [number]".into()).await.unwrap();
return;
}
},
"/timer" => {
if let Ok(minutes) = arg.trim().parse::<i64>() {
self.end_time = Utc::now() + Duration::minutes(minutes);
self.sys_message_sink.send(format!("Set timer for {} minutes.", minutes)).await.unwrap();
} else {
self.sys_message_sink.send("Invalid timer format. Use /timer [minutes]".into()).await.unwrap();
}
},
"/clear" => {
match arg.trim() {
"playlist" => {
self.direction.current_playlist.clear();
self.sys_message_sink.send("Cleared current playlist.".into()).await.unwrap();
},
"artifacts" => {
self.direction.artifacts.clear();
self.sys_message_sink.send("Cleared artifacts.".into()).await.unwrap();
},
"all" => {
self.scene = Scene::default();
self.sys_message_sink.send("Cleared all data.".into()).await.unwrap();
},
_ => {
self.sys_message_sink.send("Unknown clear command. Use /clear [playlist|artifacts|all]".into()).await.unwrap();
}
}
return;
},
"/narrative" => {
self.direction.narrative = arg.to_string();
self.sys_message_sink.send(format!("Updated stage direction: {}", self.direction.narrative)).await.unwrap();
},
"/event" => {
self.next_actions.push(ConversationEntry::StageDirection(arg.to_string()));
self.regenerate_responses();
},
"/computer" => {
self.next_actions.push(ConversationEntry::ShipComputer(arg.to_string()));
self.regenerate_responses();
},
_ => {
self.sys_message_sink.send("Unknown command. Available commands: /bandcamp [url], /episode [number], /narrative [text], /reset".into()).await.unwrap();
}
}
self.on_command(&next_msg).await;
} else {
self.next_actions.push(ConversationEntry::User(next_msg));
self.regenerate_responses();
@@ -528,16 +524,23 @@ async fn main() {
return;
}
let saved_session = if let Ok(save_data) = std::fs::read_to_string("save.json") {
serde_json::from_str(&save_data).unwrap_or_default()
//FIXME: Re-add load messages to sys log
} else {
SaveData::default()
};
let mut terminal: Terminal<CrosstermBackend<std::io::Stdout>> = ratatui::init();
let (sys_message_sink, sys_message_src) = tokio::sync::mpsc::channel(32);
let saved_session = if let Ok(save_data) = std::fs::read_to_string("save.json") {
if let Ok(ret) = serde_json::from_str(&save_data) {
sys_message_sink.send("Loaded session from save.json".into()).await.unwrap();
ret
} else {
sys_message_sink.send("Could not load saved session!".into()).await.unwrap();
SaveData::default()
}
} else {
sys_message_sink.send("Creating new session in save.json".into()).await.unwrap();
SaveData::default()
};
let tts_request_sender = start_tts().await;
let (prediction_request_in, mut prediction_out) = prediction::start_prediction(sys_message_src, saved_session.messages).await;
let (mut audio_state_receiver, audio_control_in, mut transcription_out) = transcription::start_transcription(sys_message_sink.clone()).await;
-10
View File
@@ -56,16 +56,6 @@ pub struct StageDirection {
pub current_playlist: Vec<PlaylistEntry>
}
/*impl StageDirection {
pub fn insert_conversation(&mut self, entry: ConversationEntry) {
self.additions.push(entry);
}
pub fn take_actions(&mut self) -> StageActions {
StageActions { direction: self.clone(), additions: std::mem::take(&mut self.additions) }
}
}*/
#[derive(Debug, Default, Clone)]
pub struct StageActions {
pub direction: StageDirection,
+1 -1
View File
@@ -45,7 +45,7 @@ It will also report out ship conditions, such as incoming transmissions, status
# Constraints
In a subsequent system prompt, you will be given the currrent 'stage direction' of the show, which includes the current playtime, the number of the episode, and any particular extra information about this episode that you should be aware of.
The stage direction is provided as structured JSON. There may be additional data fields for semantic context that should be incorporated into the roleplaying setting.
A list of artifacts that will be encountered during the episode are provided as blobs of json+ld metadata.
A list of artifacts that will be encountered during the episode are provided as blobs of json metadata.
Additionally, the current playlist of the radio show can be found as an array of track data.
Your response will be used verbatim to generate speach using a text-to-speech engine, meaning you should not include any tone indicators or other formatting.
This also means that your responses must not refer to any "lore", or "show", these instructions, or anything else out of character.