Skip to content

Commit 19bc0b0

Browse files
fix: bugs around serialization (#1812)
1 parent 029f760 commit 19bc0b0

File tree

4 files changed

+56
-13
lines changed

4 files changed

+56
-13
lines changed

crates/chat-cli/src/cli/chat/context.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ pub struct ContextManager {
5959
/// Context configuration for the current profile.
6060
pub profile_config: ContextConfig,
6161

62+
#[serde(skip)]
6263
pub hook_executor: HookExecutor,
6364
}
6465

@@ -128,6 +129,13 @@ impl ContextManager {
128129
Ok(())
129130
}
130131

132+
/// Reloads the global and profile config from disk.
133+
pub async fn reload_config(&mut self) -> Result<()> {
134+
self.global_config = load_global_config(&self.ctx).await?;
135+
self.profile_config = load_profile_config(&self.ctx, &self.current_profile).await?;
136+
Ok(())
137+
}
138+
131139
/// Add paths to the context configuration.
132140
///
133141
/// # Arguments

crates/chat-cli/src/cli/chat/conversation_state.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,37 @@ impl ConversationState {
156156
}
157157
}
158158

159+
/// Reloads necessary fields after being deserialized. This should be called after
160+
/// deserialization.
161+
pub async fn reload_serialized_state(&mut self, ctx: Arc<Context>, updates: Option<SharedWriter>) {
162+
self.updates = updates;
163+
164+
// Try to reload ContextManager, but do not return an error if we fail.
165+
// TODO: Currently the failure modes around ContextManager is unclear, and we don't return
166+
// errors in most cases. Thus, we try to preserve the same behavior here and simply have
167+
// self.context_manager equal to None if any errors are encountered. This needs to be
168+
// refactored.
169+
let mut failed = false;
170+
if let Some(context_manager) = self.context_manager.as_mut() {
171+
match context_manager.reload_config().await {
172+
Ok(_) => (),
173+
Err(err) => {
174+
error!(?err, "failed to reload context config");
175+
match ContextManager::new(ctx, None).await {
176+
Ok(v) => *context_manager = v,
177+
Err(err) => {
178+
failed = true;
179+
error!(?err, "failed to construct context manager");
180+
},
181+
}
182+
},
183+
}
184+
}
185+
if failed {
186+
self.context_manager.take();
187+
}
188+
}
189+
159190
pub fn latest_summary(&self) -> Option<&str> {
160191
self.latest_summary.as_deref()
161192
}

crates/chat-cli/src/cli/chat/hooks.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,14 @@ pub enum HookTrigger {
119119
PerPrompt,
120120
}
121121

122-
#[derive(Debug, Clone, Serialize, Deserialize)]
122+
#[derive(Debug, Clone)]
123123
pub struct CachedHook {
124124
output: String,
125-
#[serde(skip)]
126125
expiry: Option<Instant>,
127126
}
128127

129128
/// Maps a hook name to a [`CachedHook`]
130-
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
129+
#[derive(Debug, Clone, Default)]
131130
pub struct HookExecutor {
132131
pub global_cache: HashMap<String, CachedHook>,
133132
pub profile_cache: HashMap<String, CachedHook>,

crates/chat-cli/src/cli/chat/mod.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,9 @@ impl ChatContext {
543543
{
544544
Some(mut prior) => {
545545
existing_conversation = true;
546+
prior
547+
.reload_serialized_state(Arc::clone(&ctx), Some(output.clone()))
548+
.await;
546549
input = Some(input.unwrap_or("In a few words, summarize our conversation so far.".to_owned()));
547550
prior.tool_manager = tool_manager;
548551
prior
@@ -1315,14 +1318,6 @@ impl ChatContext {
13151318
// Otherwise continue with normal chat on 'n' or other responses
13161319
self.tool_use_status = ToolUseStatus::Idle;
13171320

1318-
if self.interactive {
1319-
queue!(self.output, style::SetForegroundColor(Color::Magenta))?;
1320-
queue!(self.output, style::SetForegroundColor(Color::Reset))?;
1321-
queue!(self.output, cursor::Hide)?;
1322-
execute!(self.output, style::Print("\n"))?;
1323-
self.spinner = Some(Spinner::new(Spinners::Dots, "Thinking...".to_owned()));
1324-
}
1325-
13261321
if pending_tool_index.is_some() {
13271322
self.conversation_state.abandon_tool_use(tool_uses, user_input);
13281323
} else {
@@ -1332,6 +1327,14 @@ impl ChatContext {
13321327
let conv_state = self.conversation_state.as_sendable_conversation_state(true).await;
13331328
self.send_tool_use_telemetry(telemetry).await;
13341329

1330+
if self.interactive {
1331+
queue!(self.output, style::SetForegroundColor(Color::Magenta))?;
1332+
queue!(self.output, style::SetForegroundColor(Color::Reset))?;
1333+
queue!(self.output, cursor::Hide)?;
1334+
execute!(self.output, style::Print("\n"))?;
1335+
self.spinner = Some(Spinner::new(Spinners::Dots, "Thinking...".to_owned()));
1336+
}
1337+
13351338
ChatState::HandleResponseStream(self.client.send_message(conv_state).await?)
13361339
},
13371340
Command::Execute { command } => {
@@ -2808,9 +2811,11 @@ impl ChatContext {
28082811
}
28092812

28102813
let contents = tri!(self.ctx.fs().read_to_string(&path).await);
2811-
let new_state: ConversationState = tri!(serde_json::from_str(&contents));
2814+
let mut new_state: ConversationState = tri!(serde_json::from_str(&contents));
2815+
new_state
2816+
.reload_serialized_state(Arc::clone(&self.ctx), Some(self.output.clone()))
2817+
.await;
28122818
self.conversation_state = new_state;
2813-
self.conversation_state.updates = Some(self.output.clone());
28142819

28152820
execute!(
28162821
self.output,

0 commit comments

Comments
 (0)