agentic_core/executor/
persist.rs1use crate::executor::error::{ExecutorError, ExecutorResult};
7use crate::executor::modes::{ConversationHandler, ResponseHandler};
8use crate::executor::request::RequestContext;
9use crate::types::event::ResponseStatus;
10use crate::types::io::OutputItem;
11use crate::types::request_response::ResponsePayload;
12use tracing::error;
13
14#[must_use]
15pub(crate) fn should_persist(ctx: &RequestContext) -> bool {
16 ctx.original_request.store
17 || ctx.original_request.previous_response_id.is_some()
18 || ctx.original_request.conversation_id.is_some()
19}
20
21pub(crate) async fn persist_if_needed(
22 payload: ResponsePayload,
23 ctx: RequestContext,
24 conv_handler: ConversationHandler,
25 resp_handler: ResponseHandler,
26) -> ExecutorResult<()> {
27 if should_persist(&ctx) {
28 persist_response(payload, ctx, conv_handler, resp_handler)
29 .await
30 .map_err(|source| {
31 error!(error = ?source, "failed to persist response");
32 ExecutorError::Persistence(Box::new(source))
33 })
34 } else {
35 Ok(())
36 }
37}
38
39pub async fn persist_response(
48 payload: ResponsePayload,
49 ctx: RequestContext,
50 conv_handler: ConversationHandler,
51 resp_handler: ResponseHandler,
52) -> ExecutorResult<()> {
53 if !matches!(
55 payload.status.parse::<ResponseStatus>().unwrap_or_default(),
56 ResponseStatus::Completed | ResponseStatus::Incomplete
57 ) || payload.id.is_empty()
58 {
59 return Ok(());
60 }
61
62 persist_turn(ctx, payload.output, &conv_handler, &resp_handler).await
63}
64
65pub async fn persist_turn(
70 ctx: RequestContext,
71 output_items: Vec<OutputItem>,
72 conv_handler: &ConversationHandler,
73 resp_handler: &ResponseHandler,
74) -> ExecutorResult<()> {
75 if ctx.original_request.conversation_id.is_some() {
76 conv_handler.execute_turn(ctx, output_items).await
77 } else {
78 resp_handler.execute_turn(ctx, output_items).await
79 }
80}